diff --git a/.agents/notes/archived/bug-fix/2026-08-12-collapsed-sidebar-shared-entry-motion.i18n.yaml b/.agents/notes/archived/bug-fix/2026-08-12-collapsed-sidebar-shared-entry-motion.i18n.yaml new file mode 100644 index 0000000000..971bc98a0c --- /dev/null +++ b/.agents/notes/archived/bug-fix/2026-08-12-collapsed-sidebar-shared-entry-motion.i18n.yaml @@ -0,0 +1,6 @@ +# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each +# 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 .agents/notes/implemented/bug-fix/2026-08-12-collapsed-sidebar-shared-entry-motion.md +2026-08-12-collapsed-sidebar-shared-entry-motion.md: c5bc18973db693cf9ba60800fbcf7720593dbad5 +2026-08-12-collapsed-sidebar-shared-entry-motion.zh.md: b87ef6322d548061cc2e29c0e8f9896098c09041 diff --git a/.agents/notes/archived/bug-fix/2026-08-12-collapsed-sidebar-shared-entry-motion.md b/.agents/notes/archived/bug-fix/2026-08-12-collapsed-sidebar-shared-entry-motion.md new file mode 100644 index 0000000000..c5bc18973d --- /dev/null +++ b/.agents/notes/archived/bug-fix/2026-08-12-collapsed-sidebar-shared-entry-motion.md @@ -0,0 +1,33 @@ +# Agent Note: Collapsed sidebar upper controls share one entry motion + +Status: implemented +Archived: 2026-08-12 + +English | [中文](2026-08-12-collapsed-sidebar-shared-entry-motion.zh.md) + +## Problem + +The collapsed sidebar rail renders four upper controls owned by two packages: the shell owns the toggle and New Session, while the workspace region owns add and search. Their opacity timing matched, but their geometry did not. Right-aligned controls moved with the narrowing column while left-aligned controls stayed fixed, so add appeared slower than search even under the same fade. + +The bottom settings control has a different role. It is pinned to the rail foot and must not join the upper controls' horizontal entry. + +## Decision + +At the rail settle point, the four upper 36px controls start from one left-anchored layout and share one `150ms` animation from `translateX(49px)` to their final 10px inset. The shell applies the translation to its toggle and New Session seats and once to the workspace region, so add and search inherit the same path without nested transforms. Opacity uses the same animation timeline. + +The settings seat uses a separate opacity-only keyframe with the same duration and easing. A page that starts collapsed renders the rail without an entry animation, and reduced-motion mode disables both keyframes. + +## Alternatives considered + +**Keep every rail control fixed at its final inset.** This removes the mismatch, but it also removes the requested horizontal entry from the four upper controls. + +**Animate each workspace button independently.** This would duplicate shell timing inside `ui-workspace` and could apply both a region and child transform. Translating the registered region once keeps animation ownership in the sidebar shell. + +**Translate the settings control with the upper controls.** Rejected because settings is a bottom-pinned foot action, not part of the upper control sequence. + +## Consequences + +- Toggle, New Session, add, and search follow the same horizontal coordinates throughout collapse. +- Settings fades at its final horizontal coordinate. +- Static collapsed renders retain their final geometry without startup motion. +- Style tests pin the shared animation assignments, translation distance, base anchors, and settings exception. diff --git a/.agents/notes/archived/bug-fix/2026-08-12-collapsed-sidebar-shared-entry-motion.zh.md b/.agents/notes/archived/bug-fix/2026-08-12-collapsed-sidebar-shared-entry-motion.zh.md new file mode 100644 index 0000000000..b87ef6322d --- /dev/null +++ b/.agents/notes/archived/bug-fix/2026-08-12-collapsed-sidebar-shared-entry-motion.zh.md @@ -0,0 +1,33 @@ +# Agent Note: 收起侧栏的上方控件共用同一进入动画 + +Status: implemented +Archived: 2026-08-12 + +[English](2026-08-12-collapsed-sidebar-shared-entry-motion.md) | 中文 + +## Problem + +收起侧栏轨道的四个上方控件由两个包渲染:外壳持有侧栏切换与新建会话,Workspace 区域持有添加和搜索。它们的透明度时序相同,但几何行为不同。右对齐控件会随栏变窄而移动,左对齐控件则保持不动,因此添加即使使用相同淡入,视觉上仍比搜索慢。 + +底部设置控件承担不同角色。它固定在轨道页脚,不能参与上方控件的横向进入。 + +## Decision + +轨道落位时,四个 36px 上方控件从同一个左对齐布局开始,共用一段 `150ms` 动画,从 `translateX(49px)` 移动到最终 10px 内边距。外壳把位移分别应用于侧栏切换、新建会话,并只对 Workspace 区域应用一次,因此添加与搜索会继承同一路径,不产生嵌套变换。透明度使用同一条动画时间线。 + +设置控件使用时长与缓动相同、但只改变透明度的独立关键帧。页面初始即为收起状态时不会播放进入动画;减少动态效果模式会禁用两段关键帧。 + +## Alternatives considered + +**把每个轨道控件固定在最终内边距。** 这能消除不一致,但也会移除四个上方控件所需的横向进入效果。 + +**分别为每个 Workspace 按钮添加动画。** 这会在 `ui-workspace` 中重复外壳时序,还可能同时应用区域与子控件变换。只移动一次已注册区域,可以让动画继续由侧栏外壳持有。 + +**让设置控件随上方控件一起移动。** 不予采纳,因为设置是固定在底部的页脚操作,不属于上方控件序列。 + +## Consequences + +- 侧栏切换、新建会话、添加与搜索在整个收起过程中使用相同横坐标。 +- 设置在最终横坐标上淡入。 +- 静态收起渲染保持最终几何,不播放启动动画。 +- 样式测试固定共用动画分配、位移距离、基础锚点与设置例外。 diff --git a/.agents/notes/archived/manifest.json b/.agents/notes/archived/manifest.json index a8377c346f..f8786470c7 100644 --- a/.agents/notes/archived/manifest.json +++ b/.agents/notes/archived/manifest.json @@ -97,6 +97,9 @@ "bug-fix/2026-08-10-web-favicon-dark-mode.i18n.yaml": "sha256:859c4399f9a017a68ba89552fdafa05e73c0599d94cee9551c84ea5b749a14f3", "bug-fix/2026-08-10-web-favicon-dark-mode.md": "sha256:4d17e247abd76ae3aed5fb4e075fd66a2838292f89f7021c82a79fe37ed905e6", "bug-fix/2026-08-10-web-favicon-dark-mode.zh.md": "sha256:7bbff8a3b7061c127afcc75cd2a8043b02a999b78c0180edd8f7e4807fcfe71d", + "bug-fix/2026-08-12-collapsed-sidebar-shared-entry-motion.i18n.yaml": "sha256:3ce4f6e39e173fc304bf64deca9c95bcddc1dbb492e065ca8c267a7a40788588", + "bug-fix/2026-08-12-collapsed-sidebar-shared-entry-motion.md": "sha256:7b169aa4543edfc965de5a8b7b9e60aa9d9d5218693cd0b57908e2d482280723", + "bug-fix/2026-08-12-collapsed-sidebar-shared-entry-motion.zh.md": "sha256:88db36c698800bf55c3c7531d6f92665576d978c29c15ff7d74215fb93376cb1", "feature/2026-06-14-acp-agent-client-protocol.i18n.yaml": "sha256:006795baa43ae962a8d125cc0f1e9f134bc2ee9fb758b6e7669e3fa0126e1918", "feature/2026-06-14-acp-agent-client-protocol.md": "sha256:6828c0af74bb3fb96206ca6b21c0e56a000b50e4744aad4bc2c05092f3a5a31b", "feature/2026-06-14-acp-agent-client-protocol.zh.md": "sha256:ba104e841a1fb84edbd3b6c8119d50445b7785255a7a8d13bb9ac8a2cb4d2e69", diff --git a/.agents/notes/implemented/architecture/2026-06-13-capability-seams.i18n.yaml b/.agents/notes/implemented/architecture/2026-06-13-capability-seams.i18n.yaml index f07afccac7..106164a71c 100644 --- a/.agents/notes/implemented/architecture/2026-06-13-capability-seams.i18n.yaml +++ b/.agents/notes/implemented/architecture/2026-06-13-capability-seams.i18n.yaml @@ -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 .agents/notes/implemented/architecture/2026-06-13-capability-seams.md -2026-06-13-capability-seams.md: efb000631c6dfe91ab648b102a14a27c30d790b4 -2026-06-13-capability-seams.zh.md: bf6571dfa5c3a90f856480bc22c6560ed65b3e77 +2026-06-13-capability-seams.md: 2a166278ea454895177fa12b58f5493276f19cd1 +2026-06-13-capability-seams.zh.md: 0874af5826960ab9e718eb07b00c12b446edfd78 diff --git a/.agents/notes/implemented/architecture/2026-06-13-capability-seams.md b/.agents/notes/implemented/architecture/2026-06-13-capability-seams.md index efb000631c..2a166278ea 100644 --- a/.agents/notes/implemented/architecture/2026-06-13-capability-seams.md +++ b/.agents/notes/implemented/architecture/2026-06-13-capability-seams.md @@ -1,4 +1,4 @@ -# Agent Note: Capability seams — Service Definition / Service provider / Consumer roles +# Agent Note: Capability seams — Service Definition / Service Provider / Consumer roles Status: implemented @@ -15,16 +15,18 @@ This is distinct from "who provides vs. needs a capability at runtime", which Co A swappable capability has **three roles**: 1. **Service Definition** — the Cordis `Service` and vocabulary types owning `ctx.` and depending only on the vocabulary the contract needs (e.g. `dsh-shell`: `ShellExecutor`, `ShellRunResult`, `ShellProcess`). A definition may be an abstract class or a concrete registry service; it is never a TypeScript `interface`. -2. **Service provider** — a plugin that supplies or registers an implementation (e.g. `dsh-bash-local`: subprocesses, process-group kills, spill-file truncation). Sandboxed and remote providers are sibling packages implementing or registering against the same Service Definition. +2. **Service Provider** — a plugin that supplies or registers an implementation (e.g. `dsh-bash-local`: subprocesses, process-group kills, spill-file truncation). Sandboxed and remote providers are sibling packages implementing or registering against the same Service Definition. 3. **Consumer** — what the model and plugins program against (e.g. `dsh-tool-bash`: the `bash` schema, with background handles registered into the generic job runtime). Consumers inject the service key and never import provider-specific types. -Service providers and Consumers then evolve independently: a sandboxed executor replaces `dsh-bash-local` without touching a tool schema. +The role names use title case: **Service Definition**, **Service Provider**, and **Consumer**. Generic uses of `provider` and `consumer` remain lowercase. -Roles normally use separate packages when they evolve independently, but the split is not mandatory when the roles are genuinely one concern: the LLM seam folds Service Definition and Consumer into `dsh-llm` (the Consumer is the loop itself, not a swappable schema surface) with adapters as Service provider packages. Don't split preemptively — a capability with one conceivable provider and one Consumer stays one package until a second appears. +Service Providers and Consumers then evolve independently: a sandboxed executor replaces `dsh-bash-local` without touching a tool schema. + +Roles normally use separate packages when they evolve independently, but the split is not mandatory when the roles are genuinely one concern: the LLM seam folds Service Definition and Consumer into `dsh-llm` (the Consumer is the loop itself, not a swappable schema surface) with adapters as Service Provider packages. Don't split preemptively — a capability with one conceivable provider and one Consumer stays one package until a second appears. ## Terminology: "seam" names the trio, not the interface -A **seam** is the whole capability — the three roles together: a **Service Definition** (the Cordis `Service` that owns `ctx.` and the vocabulary), one or more **Service providers**, and one or more **Consumers**. `packages/shell` is the canonical example — `dsh-shell` / `dsh-bash-local`+`dsh-bash-sandbox` / `dsh-tool-bash`. A package may own multiple roles, but one role alone is not the seam. The term "seam" is reserved for this complete capability; name a constituent by its role, class, service, contract, or extension point. The [glossary](../../../../docs/glossary.md#capability-seam) is the canonical entry. +A **seam** is the whole capability — the three roles together: a **Service Definition** (the Cordis `Service` that owns `ctx.` and the vocabulary), one or more **Service Providers**, and one or more **Consumers**. `packages/shell` is the canonical example — `dsh-shell` / `dsh-bash-local`+`dsh-bash-sandbox` / `dsh-tool-bash`. A package may own multiple roles, but one role alone is not the seam. The term "seam" is reserved for this complete capability; name a constituent by its role, class, service, contract, or extension point. The [glossary](../../../../docs/glossary.md#capability-seam) is the canonical entry. ## Alternatives considered @@ -33,4 +35,4 @@ A **seam** is the whole capability — the three roles together: a **Service Def ## Consequences -Separating roles adds packages and boilerplate (`package.json`, `tsconfig`, README, and injection wiring). In return, Service providers and Consumers ship and version independently, and a new backend never risks the model-facing contract. [AGENTS.md](../../../../AGENTS.md) and [architecture.md](../../../../docs/architecture.md) carry the rule; the bash trio is the reference template. This Agent Note records why independently changing roles normally split while genuinely shared concerns may remain folded. +Separating roles adds packages and boilerplate (`package.json`, `tsconfig`, README, and injection wiring). In return, Service Providers and Consumers ship and version independently, and a new backend never risks the model-facing contract. [AGENTS.md](../../../../AGENTS.md) and [architecture.md](../../../../docs/architecture.md) carry the rule; the bash trio is the reference template. This Agent Note records why independently changing roles normally split while genuinely shared concerns may remain folded. diff --git a/.agents/notes/implemented/architecture/2026-06-13-capability-seams.zh.md b/.agents/notes/implemented/architecture/2026-06-13-capability-seams.zh.md index bf6571dfa5..0874af5826 100644 --- a/.agents/notes/implemented/architecture/2026-06-13-capability-seams.zh.md +++ b/.agents/notes/implemented/architecture/2026-06-13-capability-seams.zh.md @@ -1,4 +1,4 @@ -# Agent Note: 能力 seam——Service Definition / Service provider / Consumer 角色 +# Agent Note: 能力 seam——Service Definition / Service Provider / Consumer 角色 Status: implemented @@ -15,22 +15,24 @@ harness 具有可替换的能力:当前是 bash 执行,未来会有沙箱化 一项可替换的能力包含**三个角色**: 1. **Service Definition**——拥有 `ctx.` 的 Cordis `Service` 和词汇类型,仅依赖约定所需的词汇(例如 `dsh-shell`:`ShellExecutor`、`ShellRunResult`、`ShellProcess`)。Service Definition 可以是抽象类,也可以是具体的注册表服务;绝不是 TypeScript `interface`。 -2. **Service provider**——提供或注册实现的插件(例如 `dsh-bash-local`:子进程、进程组 kill、spill 文件截断)。沙箱化和远程 Service provider 是依据同一 Service Definition 实现或注册的兄弟包。 -3. **Consumer**——模型和插件编程所面向的内容(例如 `dsh-tool-bash`:`bash` schema,后台句柄注册到通用任务运行时)。Consumer 注入服务键,从不导入 Service provider 特有的类型。 +2. **Service Provider**——提供或注册实现的插件(例如 `dsh-bash-local`:子进程、进程组 kill、spill 文件截断)。沙箱化和远程 Service Provider 是依据同一 Service Definition 实现或注册的兄弟包。 +3. **Consumer**——模型和插件编程所面向的内容(例如 `dsh-tool-bash`:`bash` schema,后台句柄注册到通用任务运行时)。Consumer 注入服务键,从不导入 Service Provider 特有的类型。 -Service provider 与 Consumer 由此独立演进:沙箱化执行器替换 `dsh-bash-local` 时无需触碰任何工具 schema。 +角色名使用标题式大小写:**Service Definition**、**Service Provider** 和 **Consumer**。泛指的 `provider` 和 `consumer` 仍使用小写。 -当角色独立演进时,通常使用不同的包;但当各角色确实属于同一个关注点时,并非必须拆分:LLM(大语言模型) seam 将 Service Definition 和 Consumer 合并为 `dsh-llm`(Consumer 是 agent loop(智能体循环)本身,而非可替换的 schema 接口),适配器作为 Service provider 包。不要预防性地拆分——如果一项能力只有一种可设想的 Service provider 和一个 Consumer,就保持为一个包,直到出现第二个。 +Service Provider 与 Consumer 由此独立演进:沙箱化执行器替换 `dsh-bash-local` 时无需触碰任何工具 schema。 + +当角色独立演进时,通常使用不同的包;但当各角色确实属于同一个关注点时,并非必须拆分:LLM(大语言模型) seam 将 Service Definition 和 Consumer 合并为 `dsh-llm`(Consumer 是 agent loop(智能体循环)本身,而非可替换的 schema 接口),适配器作为 Service Provider 包。不要预防性地拆分——如果一项能力只有一种可设想的 Service Provider 和一个 Consumer,就保持为一个包,直到出现第二个。 ## 术语:seam 指三者组合,而非接口 -一个 **seam** 是完整的能力——三个角色合在一起:**Service Definition**(拥有 `ctx.` 和词汇的 Cordis `Service`)、一个或多个 **Service provider**,以及一个或多个 **Consumer**。`packages/shell` 是规范范例——`dsh-shell` / `dsh-bash-local`+`dsh-bash-sandbox` / `dsh-tool-bash`。一个包可以承担多个角色,但单个角色本身不是 seam。「seam」一词严格保留给这种完整能力;命名其中一个组成部分时,应使用其角色、类、服务、约定或扩展点。[术语表](../../../../docs/glossary.md#capability-seam)是规范条目。 +一个 **seam** 是完整的能力——三个角色合在一起:**Service Definition**(拥有 `ctx.` 和词汇的 Cordis `Service`)、一个或多个 **Service Provider**,以及一个或多个 **Consumer**。`packages/shell` 是规范范例——`dsh-shell` / `dsh-bash-local`+`dsh-bash-sandbox` / `dsh-tool-bash`。一个包可以承担多个角色,但单个角色本身不是 seam。「seam」一词严格保留给这种完整能力;命名其中一个组成部分时,应使用其角色、类、服务、约定或扩展点。[术语表](../../../../docs/glossary.md#capability-seam)是规范条目。 ## 曾考虑的替代方案 -- **始终合并各角色**:否决。因为它会重新耦合独立变化的 Service Definition、Service provider 和 Consumer。 +- **始终合并各角色**:否决。因为它会重新耦合独立变化的 Service Definition、Service Provider 和 Consumer。 - **`@cordisjs/plugin-capability`**:这是完全不同的维度。它是一个权限/能力*安全*服务(具名权限加继承,通过 `ctx.capability.test` 针对会话检测这些权限),是延后的权限/沙箱工作(`tools/pre-execute` deny/ask 门)的候选方案,不是替换实现的机制。混淆这两个「能力」概念正是本 Agent Note 所指出的陷阱。 ## 后果 -分离角色会增加包和样板代码(`package.json`、`tsconfig`、README 和注入接线)。换来的是:Service provider 与 Consumer 独立发布和版本管理,新后端永远不会波及面向模型的约定。[AGENTS.md](../../../../AGENTS.md) 和 [architecture.md](../../../../docs/architecture.md) 载有这项规则;bash 三件套是参考模板。本 Agent Note 记录为什么独立变化的角色通常需要拆分,而确实共享的关注点可以保持合并。 +分离角色会增加包和样板代码(`package.json`、`tsconfig`、README 和注入接线)。换来的是:Service Provider 与 Consumer 独立发布和版本管理,新后端永远不会波及面向模型的约定。[AGENTS.md](../../../../AGENTS.md) 和 [architecture.md](../../../../docs/architecture.md) 载有这项规则;bash 三件套是参考模板。本 Agent Note 记录为什么独立变化的角色通常需要拆分,而确实共享的关注点可以保持合并。 diff --git a/.agents/notes/implemented/architecture/2026-06-17-filesystem-capability-seam.i18n.yaml b/.agents/notes/implemented/architecture/2026-06-17-filesystem-capability-seam.i18n.yaml index fc070d7c3a..9898684b9e 100644 --- a/.agents/notes/implemented/architecture/2026-06-17-filesystem-capability-seam.i18n.yaml +++ b/.agents/notes/implemented/architecture/2026-06-17-filesystem-capability-seam.i18n.yaml @@ -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 .agents/notes/implemented/architecture/2026-06-17-filesystem-capability-seam.md -2026-06-17-filesystem-capability-seam.md: 953ef0eaafe8f654bf55c3e5c4208560243c3d0b -2026-06-17-filesystem-capability-seam.zh.md: 1073226594acbe8c1c596bb4b2dcc959b20c0769 +2026-06-17-filesystem-capability-seam.md: 6265aebf5e7ffdd4ec4dc0083aa55adb34ee78a1 +2026-06-17-filesystem-capability-seam.zh.md: 024421ed59fa1e6c29bcc12ab51f69ac19a0c231 diff --git a/.agents/notes/implemented/architecture/2026-06-17-filesystem-capability-seam.md b/.agents/notes/implemented/architecture/2026-06-17-filesystem-capability-seam.md index 953ef0eaaf..6265aebf5e 100644 --- a/.agents/notes/implemented/architecture/2026-06-17-filesystem-capability-seam.md +++ b/.agents/notes/implemented/architecture/2026-06-17-filesystem-capability-seam.md @@ -53,7 +53,7 @@ The filesystem seam uses the same dependency direction as the bash trio: `@deepseek-ai/dsh-tool-fs` depends on `@deepseek-ai/dsh-fs`, `@deepseek-ai/dsh-tools`, `@deepseek-ai/dsh-system-prompt`, and `cordis`. It registers model-facing tools and prompt sections. It must not import `node:fs`, `node:path`, or `@deepseek-ai/dsh-fs-local`; filesystem execution always goes through `ctx.fs`. If the implementation needs concrete agent or session helper types, those dependencies belong in `tool-fs`; they must not leak back into `dsh-fs`. -The root `tool-fs` plugin registers the full filesystem tool suite (`read`, `write`, and `edit`) by composing the per-tool registration helpers. It injects `fs` and never imports a Service provider package. +The root `tool-fs` plugin registers the full filesystem tool suite (`read`, `write`, and `edit`) by composing the per-tool registration helpers. It injects `fs` and never imports a Service Provider package. ## `ctx.fs` contract @@ -139,7 +139,7 @@ The defensive-pattern classes this repo has been bitten by are pinned directly: ## Alternatives considered - **Model-facing tools directly over `node:fs`** — the tool package would own execution policy, path resolution, atomic writes, text decoding, and edit semantics at once, coupling the three independently-changing concerns the Problem names and churning schemas on any backend swap. -- **One combined `dsh-fs-tools` package** — the pre-seam shape; rejected for the same Service Definition / Service provider / Consumer split as bash, and the combined name never became public API. +- **One combined `dsh-fs-tools` package** — the pre-seam shape; rejected for the same Service Definition / Service Provider / Consumer split as bash, and the combined name never became public API. - **Observed-state on `ctx.fs`** — the shape this Agent Note first landed; superseded by [the split-fs-seam Agent Note](../simplification/2026-06-26-fsspec-style-fs-seam.md) and [the event-gate Agent Note](2026-06-26-file-context-as-event-gate.md): a sandboxed/remote backend must not inherit model-facing observation policy, so the provider keeps only the version token and the optional version-guarded mutation. ## Consequences diff --git a/.agents/notes/implemented/architecture/2026-06-17-filesystem-capability-seam.zh.md b/.agents/notes/implemented/architecture/2026-06-17-filesystem-capability-seam.zh.md index 1073226594..024421ed59 100644 --- a/.agents/notes/implemented/architecture/2026-06-17-filesystem-capability-seam.zh.md +++ b/.agents/notes/implemented/architecture/2026-06-17-filesystem-capability-seam.zh.md @@ -53,7 +53,7 @@ Consumer 包仅依赖 Service Definition 包,从不依赖 `dsh-fs-local`。需 `@deepseek-ai/dsh-tool-fs` 依赖 `@deepseek-ai/dsh-fs`、`@deepseek-ai/dsh-tools`、`@deepseek-ai/dsh-system-prompt` 和 `cordis`。它注册面向模型的工具和提示词段落。它禁止导入 `node:fs`、`node:path` 或 `@deepseek-ai/dsh-fs-local`;文件系统执行始终通过 `ctx.fs`。如果实现需要具体的 agent(智能体)或会话辅助类型,这些依赖属于 `tool-fs`;它们禁止回漏到 `dsh-fs` 中。 -根 `tool-fs` 插件通过组合各工具的注册辅助函数来注册完整的文件系统工具套件(`read`、`write` 和 `edit`)。它注入 `fs`,从不导入 Service provider 包。 +根 `tool-fs` 插件通过组合各工具的注册辅助函数来注册完整的文件系统工具套件(`read`、`write` 和 `edit`)。它注入 `fs`,从不导入 Service Provider 包。 ## `ctx.fs` 约定 @@ -139,7 +139,7 @@ Consumer 包仅依赖 Service Definition 包,从不依赖 `dsh-fs-local`。需 ## 曾考虑的替代方案 - **面向模型的工具直接基于 `node:fs`**:工具包将同时承担执行策略、路径解析、原子写入、文本解码和编辑语义,耦合问题部分所列的三个独立变化的关注点,且任何后端替换都会搅动 schema。 -- **单一合并包 `dsh-fs-tools`**:seam 之前的形态;以与 bash 相同的 Service Definition / Service provider / Consumer 拆分理由否决,且合并名称从未成为公开 API。 +- **单一合并包 `dsh-fs-tools`**:seam 之前的形态;以与 bash 相同的 Service Definition / Service Provider / Consumer 拆分理由否决,且合并名称从未成为公开 API。 - **观测状态放在 `ctx.fs` 上**:本 Agent Note 最初落地的形态;被 [拆分文件系统 seam Agent Note](../simplification/2026-06-26-fsspec-style-fs-seam.md) 和 [事件门控 Agent Note](2026-06-26-file-context-as-event-gate.md) 取代:沙箱/远程后端不应继承面向模型的观测策略,因此提供方只保留版本令牌和可选的版本守护变更。 ## 后果 diff --git a/.agents/notes/implemented/architecture/2026-06-18-agent-lifecycle-and-ownership-contracts.i18n.yaml b/.agents/notes/implemented/architecture/2026-06-18-agent-lifecycle-and-ownership-contracts.i18n.yaml index d3c3a774bd..0ecda2484f 100644 --- a/.agents/notes/implemented/architecture/2026-06-18-agent-lifecycle-and-ownership-contracts.i18n.yaml +++ b/.agents/notes/implemented/architecture/2026-06-18-agent-lifecycle-and-ownership-contracts.i18n.yaml @@ -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 .agents/notes/implemented/architecture/2026-06-18-agent-lifecycle-and-ownership-contracts.md -2026-06-18-agent-lifecycle-and-ownership-contracts.md: f0f9f90b15dee9155cfb1e8c772503642ff34be3 -2026-06-18-agent-lifecycle-and-ownership-contracts.zh.md: a5f6ca10dbe7c71281cccdaf83fff95139ad2d79 +2026-06-18-agent-lifecycle-and-ownership-contracts.md: 9bc558bfce75892b0ebdb80e9f8735d440cabaf4 +2026-06-18-agent-lifecycle-and-ownership-contracts.zh.md: 65e0018c3f2ba56043898050c8e0b49929f8e7e7 diff --git a/.agents/notes/implemented/architecture/2026-06-18-agent-lifecycle-and-ownership-contracts.md b/.agents/notes/implemented/architecture/2026-06-18-agent-lifecycle-and-ownership-contracts.md index f0f9f90b15..9bc558bfce 100644 --- a/.agents/notes/implemented/architecture/2026-06-18-agent-lifecycle-and-ownership-contracts.md +++ b/.agents/notes/implemented/architecture/2026-06-18-agent-lifecycle-and-ownership-contracts.md @@ -37,7 +37,7 @@ These invariants hold and are pinned by tests: ## Session owner tokens are unique among live agents -The bash owner-token comparison relies on the shared `Agent.id`/`SessionId` being unique among live agents. Concurrent same-ID operations may both prepare privately, but publication enters the session and agent in order; `SessionStore.enter()` rejects a duplicate live session id, and every losing transaction rolls its private state back. A programmatic caller therefore cannot publish two live agents with one session token. The access *policy* (token comparison) stays in `tool-bash` (the Consumer); the bash capability keeps `owner` opaque and never interprets it — the correct Service Definition / Service provider / Consumer split. +The bash owner-token comparison relies on the shared `Agent.id`/`SessionId` being unique among live agents. Concurrent same-ID operations may both prepare privately, but publication enters the session and agent in order; `SessionStore.enter()` rejects a duplicate live session id, and every losing transaction rolls its private state back. A programmatic caller therefore cannot publish two live agents with one session token. The access *policy* (token comparison) stays in `tool-bash` (the Consumer); the bash capability keeps `owner` opaque and never interprets it — the correct Service Definition / Service Provider / Consumer split. ## Alternatives considered diff --git a/.agents/notes/implemented/architecture/2026-06-18-agent-lifecycle-and-ownership-contracts.zh.md b/.agents/notes/implemented/architecture/2026-06-18-agent-lifecycle-and-ownership-contracts.zh.md index a5f6ca10db..65e0018c3f 100644 --- a/.agents/notes/implemented/architecture/2026-06-18-agent-lifecycle-and-ownership-contracts.zh.md +++ b/.agents/notes/implemented/architecture/2026-06-18-agent-lifecycle-and-ownership-contracts.zh.md @@ -37,7 +37,7 @@ ACP(Agent Client Protocol)与 tool-bash 的若干限制是同一个所有权 ## 会话所有者令牌在存活 agent 中唯一 -bash 所有者 token 比较依赖共享的 `Agent.id`/`SessionId` 在存活 agent 中唯一。并发的同 ID 操作可以都私下准备,但发布时会依次登记会话和 agent;`SessionStore.enter()` 拒绝重复的存活会话 id,每个失败事务都回滚自己的私有状态。因此程序化调用方无法发布两个共享同一会话 token 的存活 agent。访问*策略*(token 比较)留在 Consumer `tool-bash`;bash 能力只存储不透明的 `owner` 字符串且从不解释它——这是正确的 Service Definition / Service provider / Consumer 拆分。 +bash 所有者 token 比较依赖共享的 `Agent.id`/`SessionId` 在存活 agent 中唯一。并发的同 ID 操作可以都私下准备,但发布时会依次登记会话和 agent;`SessionStore.enter()` 拒绝重复的存活会话 id,每个失败事务都回滚自己的私有状态。因此程序化调用方无法发布两个共享同一会话 token 的存活 agent。访问*策略*(token 比较)留在 Consumer `tool-bash`;bash 能力只存储不透明的 `owner` 字符串且从不解释它——这是正确的 Service Definition / Service Provider / Consumer 拆分。 ## 曾考虑的替代方案 diff --git a/.agents/notes/implemented/architecture/2026-06-20-branded-ids.i18n.yaml b/.agents/notes/implemented/architecture/2026-06-20-branded-ids.i18n.yaml index 877a53e0ac..b7e2678928 100644 --- a/.agents/notes/implemented/architecture/2026-06-20-branded-ids.i18n.yaml +++ b/.agents/notes/implemented/architecture/2026-06-20-branded-ids.i18n.yaml @@ -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 .agents/notes/implemented/architecture/2026-06-20-branded-ids.md -2026-06-20-branded-ids.md: 6bf68c9b6b6dea8317992bcb6f694a8ee141f048 -2026-06-20-branded-ids.zh.md: 11a78df609888fdf917246940c12463373ff2de3 +2026-06-20-branded-ids.md: 29b258b21240c92e74051339f0939a8e70933099 +2026-06-20-branded-ids.zh.md: 288125764d4b279c79b7469080bb0c9f2efdc709 diff --git a/.agents/notes/implemented/architecture/2026-06-20-branded-ids.md b/.agents/notes/implemented/architecture/2026-06-20-branded-ids.md index 6bf68c9b6b..29b258b212 100644 --- a/.agents/notes/implemented/architecture/2026-06-20-branded-ids.md +++ b/.agents/notes/implemented/architecture/2026-06-20-branded-ids.md @@ -46,7 +46,7 @@ export function OwnerToken(id: string): OwnerToken { ### Why not typing `owner` as `SessionId`? -The obvious shortcut is to type `owner` as `SessionId` directly — it always *is* one. We reject that. The bash executor seam is a capability seam (Service Definition `dsh-shell`, Service provider `dsh-bash-local`, Consumer `dsh-tool-bash`) and its owner token is *documented as deliberately opaque*: the executor "never interprets it (no access policy lives in the seam — that is the consumer's job)" (`packages/shell/shell/src/types.ts`). Typing the Service Definition's field as `SessionId` would import `dsh-session`'s vocabulary into a package that must not know what an owner token *means* — it would couple a generic execution backend to the session model and contradict the opaque-token design. A sandboxed or remote executor that replaces `dsh-bash-local` should not inherit a session dependency. The distinct `OwnerToken` brand keeps the seam decoupled: `dsh-shell` knows only "an owner is some opaque branded token," and the `dsh-tool-bash` consumer — which already decides the access policy — is the single boundary that casts its `SessionId` into an `OwnerToken`. The brand still delivers the safety win (you cannot pass a `BashTaskId` or a raw string where an owner is expected) without the coupling. +The obvious shortcut is to type `owner` as `SessionId` directly — it always *is* one. We reject that. The bash executor seam is a capability seam (Service Definition `dsh-shell`, Service Provider `dsh-bash-local`, Consumer `dsh-tool-bash`) and its owner token is *documented as deliberately opaque*: the executor "never interprets it (no access policy lives in the seam — that is the consumer's job)" (`packages/shell/shell/src/types.ts`). Typing the Service Definition's field as `SessionId` would import `dsh-session`'s vocabulary into a package that must not know what an owner token *means* — it would couple a generic execution backend to the session model and contradict the opaque-token design. A sandboxed or remote executor that replaces `dsh-bash-local` should not inherit a session dependency. The distinct `OwnerToken` brand keeps the seam decoupled: `dsh-shell` knows only "an owner is some opaque branded token," and the `dsh-tool-bash` consumer — which already decides the access policy — is the single boundary that casts its `SessionId` into an `OwnerToken`. The brand still delivers the safety win (you cannot pass a `BashTaskId` or a raw string where an owner is expected) without the coupling. ## Out of scope / possible extensions @@ -64,6 +64,6 @@ The landed invariants: `BashTaskId` and `OwnerToken` are defined in `dsh-shell` ## Consequences -- **Mechanical churn across two surfaces.** Propagating brands touches the bash seam (Service Definition + Service provider + Consumer) and the ACP session-id surface plus the persistence coordinator. The churn is broad but low-severity: a missed site is a compile error, not a silent bug. The change is observably type-only — no snapshot or e2e behavioral diff. It sits next to the [unified agent/session identity decision](../simplification/2026-06-20-unify-agent-and-session-id.md) because both touch the session-id / owner-token boundary; `OwnerToken` stays distinct from the unified id for the decoupling reason above. +- **Mechanical churn across two surfaces.** Propagating brands touches the bash seam (Service Definition + Service Provider + Consumer) and the ACP session-id surface plus the persistence coordinator. The churn is broad but low-severity: a missed site is a compile error, not a silent bug. The change is observably type-only — no snapshot or e2e behavioral diff. It sits next to the [unified agent/session identity decision](../simplification/2026-06-20-unify-agent-and-session-id.md) because both touch the session-id / owner-token boundary; `OwnerToken` stays distinct from the unified id for the decoupling reason above. - **Brands do not validate.** A brand is a confusability guard, not a correctness proof: a *wrong* session id that is still a well-formed string passes the type checker exactly as before. This decision does not close that gap (see Out of scope) — it only stops the *category* error of passing the wrong *kind* of id. - **The "where to stop" line stays a judgment call.** Branding `BashTaskId` but not `ToolName`, `OwnerToken` but not `ModelId`, is a taste call about which strings "could plausibly be confused." Reasonable reviewers may want more or fewer; the policy in `brand.ts` is the tie-breaker, and this decision errs toward the ids that are model-facing or used for access control. diff --git a/.agents/notes/implemented/architecture/2026-06-20-branded-ids.zh.md b/.agents/notes/implemented/architecture/2026-06-20-branded-ids.zh.md index 11a78df609..288125764d 100644 --- a/.agents/notes/implemented/architecture/2026-06-20-branded-ids.zh.md +++ b/.agents/notes/implemented/architecture/2026-06-20-branded-ids.zh.md @@ -46,7 +46,7 @@ export function OwnerToken(id: string): OwnerToken { ### 为什么不把 `owner` 类型标注为 `SessionId`? -显而易见的捷径是直接把 `owner` 类型标注为 `SessionId`——它确实*总是*一个会话 id。我们否决这个方案。bash 执行器 seam 是能力 seam(Service Definition `dsh-shell`、Service provider `dsh-bash-local`、Consumer `dsh-tool-bash`),其 owner token 被*明确记录为刻意不透明*:执行器「从不解释它(seam 中没有访问策略——那是消费方的职责)」(`packages/shell/shell/src/types.ts`)。把 Service Definition 的字段类型标注为 `SessionId`,会把 `dsh-session` 的词汇引入一个不应知道 owner token *含义*的包——这会让通用执行后端耦合会话模型,并违背不透明 token 的设计。取代 `dsh-bash-local` 的沙箱化执行器或远程执行器不应继承会话依赖。独立的 `OwnerToken` brand 使 seam 保持解耦:`dsh-shell` 只知道「owner 是某种带 brand 的不透明 token」,而已经决定访问策略的 `dsh-tool-bash` 消费方,是把其 `SessionId` cast 为 `OwnerToken` 的唯一边界。该 brand 仍带来安全收益(不能把 `BashTaskId` 或裸 string 传到 owner 位置),且不引入耦合。 +显而易见的捷径是直接把 `owner` 类型标注为 `SessionId`——它确实*总是*一个会话 id。我们否决这个方案。bash 执行器 seam 是能力 seam(Service Definition `dsh-shell`、Service Provider `dsh-bash-local`、Consumer `dsh-tool-bash`),其 owner token 被*明确记录为刻意不透明*:执行器「从不解释它(seam 中没有访问策略——那是消费方的职责)」(`packages/shell/shell/src/types.ts`)。把 Service Definition 的字段类型标注为 `SessionId`,会把 `dsh-session` 的词汇引入一个不应知道 owner token *含义*的包——这会让通用执行后端耦合会话模型,并违背不透明 token 的设计。取代 `dsh-bash-local` 的沙箱化执行器或远程执行器不应继承会话依赖。独立的 `OwnerToken` brand 使 seam 保持解耦:`dsh-shell` 只知道「owner 是某种带 brand 的不透明 token」,而已经决定访问策略的 `dsh-tool-bash` 消费方,是把其 `SessionId` cast 为 `OwnerToken` 的唯一边界。该 brand 仍带来安全收益(不能把 `BashTaskId` 或裸 string 传到 owner 位置),且不引入耦合。 ## 不在范围内 / 可能的扩展 @@ -64,6 +64,6 @@ export function OwnerToken(id: string): OwnerToken { ## 后果 -- **两个接口面的机械性改动。** 传播 brand 涉及 bash seam(Service Definition + Service provider + Consumer)以及 ACP 会话 id 接口和持久化协调器。改动面广但严重度低:遗漏的位置是编译错误而非静默 bug。从可观察行为看,这是一项纯类型变更——无快照或 e2e 行为差异。它与[统一 agent/会话标识决策](../simplification/2026-06-20-unify-agent-and-session-id.md)相邻,因为二者都触及会话 id / owner-token 边界;`OwnerToken` 出于上述解耦理由仍与统一后的 id 保持独立。 +- **两个接口面的机械性改动。** 传播 brand 涉及 bash seam(Service Definition + Service Provider + Consumer)以及 ACP 会话 id 接口和持久化协调器。改动面广但严重度低:遗漏的位置是编译错误而非静默 bug。从可观察行为看,这是一项纯类型变更——无快照或 e2e 行为差异。它与[统一 agent/会话标识决策](../simplification/2026-06-20-unify-agent-and-session-id.md)相邻,因为二者都触及会话 id / owner-token 边界;`OwnerToken` 出于上述解耦理由仍与统一后的 id 保持独立。 - **Brand 不做校验。** Brand 是混淆防护,不是正确性证明:一个*错误的*会话 id 只要仍是格式正确的 string,就和以前一样能通过类型检查器。本决策不关闭这个缺口(见「不在范围内」)——它只阻止这类*类别*错误:传入错误*种类*的 id。 - **「在哪里停下」仍是判断题。** 为 `BashTaskId` 加 brand 但不为 `ToolName` 加,为 `OwnerToken` 加但不为 `ModelId` 加,是对哪些 string「可能被混淆」的品味判断。合理的评审者可能想要更多或更少;`brand.ts` 中的策略是裁决依据,本决策倾向于面向模型或用于访问控制的 id。 diff --git a/.agents/notes/implemented/architecture/2026-06-20-generic-long-running-tool-runtime.i18n.yaml b/.agents/notes/implemented/architecture/2026-06-20-generic-long-running-tool-runtime.i18n.yaml index 3480f0b231..477c6df3ae 100644 --- a/.agents/notes/implemented/architecture/2026-06-20-generic-long-running-tool-runtime.i18n.yaml +++ b/.agents/notes/implemented/architecture/2026-06-20-generic-long-running-tool-runtime.i18n.yaml @@ -3,4 +3,4 @@ # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-20-generic-long-running-tool-runtime.md 2026-06-20-generic-long-running-tool-runtime.md: 7db43323dd83f8e99698a7163412c9b33a607dfb -2026-06-20-generic-long-running-tool-runtime.zh.md: fe12ef264d294224fcfaf503ba958fa90c782347 +2026-06-20-generic-long-running-tool-runtime.zh.md: efd306cc8d3b82749635dde302af45235c27b431 diff --git a/.agents/notes/implemented/architecture/2026-06-20-generic-long-running-tool-runtime.zh.md b/.agents/notes/implemented/architecture/2026-06-20-generic-long-running-tool-runtime.zh.md index fe12ef264d..efd306cc8d 100644 --- a/.agents/notes/implemented/architecture/2026-06-20-generic-long-running-tool-runtime.zh.md +++ b/.agents/notes/implemented/architecture/2026-06-20-generic-long-running-tool-runtime.zh.md @@ -19,13 +19,13 @@ Status: implemented 长时间运行工具是生产方。`dsh-tool-bash` 将 `ShellProcess` 适配为增量输出与进程取消;`dsh-tool-subagent` 将子运行适配为最终输出与子运行释放。bash 与 subagent 能力 seam 保持独立,不依赖会话或任务注册表。 -`JobRegistry` 是 `@deepseek-ai/dsh-jobs` 中的 Service Definition;进程内 Service provider 是 `@deepseek-ai/dsh-jobs-local` 中的 `LocalJobRegistry`(该拆分记录在[任务注册表约定 Agent Note](2026-07-26-job-registry-seam.md)中)。 +`JobRegistry` 是 `@deepseek-ai/dsh-jobs` 中的 Service Definition;进程内 Service Provider 是 `@deepseek-ai/dsh-jobs-local` 中的 `LocalJobRegistry`(该拆分记录在[任务注册表约定 Agent Note](2026-07-26-job-registry-seam.md)中)。 ## 运行时约定 字面类型见[任务子系统页面](../../../../docs/subsystems/jobs.md)。生产方调用 `ctx.jobs.start()`,传入 kind、label、可选的所属 `Agent`、可选的正数 `outputLimitBytes` 与一个 `run()` 函数。运行时会在调用 `run()` 前完成所有可能失败的预检工作,并且只调用一次。`run()` 返回钩子后,注册过程不会再执行可能失败的步骤而直接提交;生产方无法启动没有可收集 job id 的工作。 -进程内 Service provider 还拥有有界准入,其理由记录在[有界后台任务准入决策](../bug-fix/2026-08-11-bounded-background-job-admission.md)中。它的 `maxConcurrentJobsPerOwner` 配置必须是正的安全整数,默认值为 `10`;`start()` 从 `running` 与 `stopping` 记录派生每个确切 `Agent` 对象的活动数量,而全部无 owner 任务共享一个服务级桶。容量拒绝发生在 `run()` 与 id 分配之前,处于 stopping 的任务只有在生产方 `done` 结算时才释放名额。Service provider 不排队或抢占任务,也不保留第二份可变计数。 +进程内 Service Provider 还拥有有界准入,其理由记录在[有界后台任务准入决策](../bug-fix/2026-08-11-bounded-background-job-admission.md)中。它的 `maxConcurrentJobsPerOwner` 配置必须是正的安全整数,默认值为 `10`;`start()` 从 `running` 与 `stopping` 记录派生每个确切 `Agent` 对象的活动数量,而全部无 owner 任务共享一个服务级桶。容量拒绝发生在 `run()` 与 id 分配之前,处于 stopping 的任务只有在生产方 `done` 结算时才释放名额。Service Provider 不排队或抢占任务,也不保留第二份可变计数。 `outputLimitBytes` 是生产方拥有的呈现策略,而非注册表缓冲区。注册表校验该值,并将其原样投影到 `JobSnapshot`;通用任务控制器添加自身的状态或通知元数据后,再将该上限应用于完整的面向模型输出。省略该值时保持现有控制器行为,因此运行时不会向无关的生产方类别施加隐式默认值。 @@ -57,7 +57,7 @@ job id 在运行时全局可见且可预测,因此注册表会授权每次访 `JobRegistry` 提供: -- `start(spec)`:经过预检与 Service provider 准入的原子注册。 +- `start(spec)`:经过预检与 Service Provider 准入的原子注册。 - `get(id, caller?)` 和 `list(caller?)`:非消费式快照。 - `read(id, caller?)`:消费式流增量或幂等的最终结果。 - `kill(id, caller?, reason?)`:取消。 diff --git a/.agents/notes/implemented/architecture/2026-06-24-web-capability-seam.i18n.yaml b/.agents/notes/implemented/architecture/2026-06-24-web-capability-seam.i18n.yaml index 03dd8d5694..bc92549f44 100644 --- a/.agents/notes/implemented/architecture/2026-06-24-web-capability-seam.i18n.yaml +++ b/.agents/notes/implemented/architecture/2026-06-24-web-capability-seam.i18n.yaml @@ -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 .agents/notes/implemented/architecture/2026-06-24-web-capability-seam.md -2026-06-24-web-capability-seam.md: 6e81650e2d7286fc3c9df1e740ba9ccbf30118df -2026-06-24-web-capability-seam.zh.md: b91a4470999fd66ec7178326fcfb5247ff83a2e0 +2026-06-24-web-capability-seam.md: 7e7b09f19864bd2ad8ad9d69579c1d5c79600cde +2026-06-24-web-capability-seam.zh.md: d6051eec498edb640773ba367038581cebd1f654 diff --git a/.agents/notes/implemented/architecture/2026-06-24-web-capability-seam.md b/.agents/notes/implemented/architecture/2026-06-24-web-capability-seam.md index 6e81650e2d..7e7b09f198 100644 --- a/.agents/notes/implemented/architecture/2026-06-24-web-capability-seam.md +++ b/.agents/notes/implemented/architecture/2026-06-24-web-capability-seam.md @@ -38,7 +38,7 @@ The seam deliberately exposes no observation surface — no registry-change even ## Package topology -The three-package Service Definition / Service provider / Consumer split follows bash and filesystem, but the *interface* package is closer to the LLM seam. `LlmRuntime` (`packages/llm/llm/src/index.ts`) is a name-keyed provider registry: `registerAdapter(models, adapter)` stores adapters in a `Map`, returns a disposer, throws `DUPLICATE_ADAPTER` on duplicate keys, and throws `NO_ADAPTER` at resolution time. `ctx.web` follows that registry shape, but has two capability kinds and a richer selection policy (a configured provider id, or auto-select when exactly one usable provider is registered), so the `WebError` an execution throws can explain why a search or fetch capability cannot run. +The three-package Service Definition / Service Provider / Consumer split follows bash and filesystem, but the *interface* package is closer to the LLM seam. `LlmRuntime` (`packages/llm/llm/src/index.ts`) is a name-keyed provider registry: `registerAdapter(models, adapter)` stores adapters in a `Map`, returns a disposer, throws `DUPLICATE_ADAPTER` on duplicate keys, and throws `NO_ADAPTER` at resolution time. `ctx.web` follows that registry shape, but has two capability kinds and a richer selection policy (a configured provider id, or auto-select when exactly one usable provider is registered), so the `WebError` an execution throws can explain why a search or fetch capability cannot run. The dependency direction mirrors bash and filesystem: diff --git a/.agents/notes/implemented/architecture/2026-06-24-web-capability-seam.zh.md b/.agents/notes/implemented/architecture/2026-06-24-web-capability-seam.zh.md index b91a447099..d6051eec49 100644 --- a/.agents/notes/implemented/architecture/2026-06-24-web-capability-seam.zh.md +++ b/.agents/notes/implemented/architecture/2026-06-24-web-capability-seam.zh.md @@ -38,7 +38,7 @@ Web 访问是一个一等能力 seam,遵循[能力 seam Agent Note](2026-06-13 ## 包拓扑 -由三个包构成的 Service Definition / Service provider / Consumer 拆分沿用 bash 和 filesystem 的模式,但*接口*包更接近 LLM(大语言模型) seam。`LlmRuntime`(`packages/llm/llm/src/index.ts`)是一个按名称键控的提供方注册表:`registerAdapter(models, adapter)` 将适配器存入 `Map`、返回 disposer、对重复键抛出 `DUPLICATE_ADAPTER`、在解析时抛出 `NO_ADAPTER`。`ctx.web` 沿用该注册表形状,但有两种能力类别和更丰富的选择策略(配置的提供方 id,或在恰好只有一个可用提供方注册时自动选择),因此执行时抛出的 `WebError` 能解释搜索或 fetch 能力为何无法运行。 +由三个包构成的 Service Definition / Service Provider / Consumer 拆分沿用 bash 和 filesystem 的模式,但*接口*包更接近 LLM(大语言模型) seam。`LlmRuntime`(`packages/llm/llm/src/index.ts`)是一个按名称键控的提供方注册表:`registerAdapter(models, adapter)` 将适配器存入 `Map`、返回 disposer、对重复键抛出 `DUPLICATE_ADAPTER`、在解析时抛出 `NO_ADAPTER`。`ctx.web` 沿用该注册表形状,但有两种能力类别和更丰富的选择策略(配置的提供方 id,或在恰好只有一个可用提供方注册时自动选择),因此执行时抛出的 `WebError` 能解释搜索或 fetch 能力为何无法运行。 依赖方向与 bash 和 filesystem 一致: diff --git a/.agents/notes/implemented/architecture/2026-07-07-tool-call-timeout-policy.i18n.yaml b/.agents/notes/implemented/architecture/2026-07-07-tool-call-timeout-policy.i18n.yaml index 384a870dd0..aad3aa26f0 100644 --- a/.agents/notes/implemented/architecture/2026-07-07-tool-call-timeout-policy.i18n.yaml +++ b/.agents/notes/implemented/architecture/2026-07-07-tool-call-timeout-policy.i18n.yaml @@ -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 .agents/notes/implemented/architecture/2026-07-07-tool-call-timeout-policy.md -2026-07-07-tool-call-timeout-policy.md: 20ca57cee4cd3ae51e7bfb8af1d2a1f8c7edd743 -2026-07-07-tool-call-timeout-policy.zh.md: 5b91c29f5492a36bbd023a892f0f2f8dd857ae53 +2026-07-07-tool-call-timeout-policy.md: ce414e541f8e374dd48e46d68cb00121e0004247 +2026-07-07-tool-call-timeout-policy.zh.md: 6fe3c979a3c4e7b7a6ed803a47af45ad32d52cce diff --git a/.agents/notes/implemented/architecture/2026-07-07-tool-call-timeout-policy.md b/.agents/notes/implemented/architecture/2026-07-07-tool-call-timeout-policy.md index 20ca57cee4..ce414e541f 100644 --- a/.agents/notes/implemented/architecture/2026-07-07-tool-call-timeout-policy.md +++ b/.agents/notes/implemented/architecture/2026-07-07-tool-call-timeout-policy.md @@ -16,7 +16,7 @@ Tool-call timeout is a policy that applies only to model-facing tool execution, - `@deepseek-ai/dsh-timeout` remains the shared library that owns `deadline()` and `timeoutOf()`. - `@deepseek-ai/dsh-tools` has an around-dispatch waterfall, `tools/execute`, between `tools/pre-execute` and `tools/post-execute`. -- The [repository naming contract](../../proposed/architecture/2026-08-11-repository-naming-contract-and-rename-ledger.md) names `@deepseek-ai/dsh-tool-call-timeout-policy` for the exact operation it limits. The plugin reads each tool's declared `timeoutMs` from the runtime and wraps a call that has one by deriving a new `exec.signal`. +- The [repository naming contract](2026-08-11-repository-naming-contract-and-rename-ledger.md) names `@deepseek-ai/dsh-tool-call-timeout-policy` for the exact operation it limits. The plugin reads each tool's declared `timeoutMs` from the runtime and wraps a call that has one by deriving a new `exec.signal`. The execution pipeline is: diff --git a/.agents/notes/implemented/architecture/2026-07-07-tool-call-timeout-policy.zh.md b/.agents/notes/implemented/architecture/2026-07-07-tool-call-timeout-policy.zh.md index 5b91c29f54..6fe3c979a3 100644 --- a/.agents/notes/implemented/architecture/2026-07-07-tool-call-timeout-policy.zh.md +++ b/.agents/notes/implemented/architecture/2026-07-07-tool-call-timeout-policy.zh.md @@ -16,7 +16,7 @@ Status: implemented - `@deepseek-ai/dsh-timeout` 仍是拥有 `deadline()` 和 `timeoutOf()` 的共享库。 - `@deepseek-ai/dsh-tools` 在 `tools/pre-execute` 和 `tools/post-execute` 之间有一个环绕分发的 waterfall(瀑布式事件)`tools/execute`。 -- [仓库命名约定](../../proposed/architecture/2026-08-11-repository-naming-contract-and-rename-ledger.md)使用 `@deepseek-ai/dsh-tool-call-timeout-policy`,准确说明该策略所限制的操作。插件从 runtime 读取每个工具声明的 `timeoutMs`,并通过派生新的 `exec.signal` 来包装有此声明的调用。 +- [仓库命名约定](2026-08-11-repository-naming-contract-and-rename-ledger.md)使用 `@deepseek-ai/dsh-tool-call-timeout-policy`,准确说明该策略所限制的操作。插件从 runtime 读取每个工具声明的 `timeoutMs`,并通过派生新的 `exec.signal` 来包装有此声明的调用。 执行流水线如下: diff --git a/.agents/notes/implemented/architecture/2026-07-14-provider-routed-llm-adapters.i18n.yaml b/.agents/notes/implemented/architecture/2026-07-14-provider-routed-llm-adapters.i18n.yaml index a79104468c..3f4683f480 100644 --- a/.agents/notes/implemented/architecture/2026-07-14-provider-routed-llm-adapters.i18n.yaml +++ b/.agents/notes/implemented/architecture/2026-07-14-provider-routed-llm-adapters.i18n.yaml @@ -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 .agents/notes/implemented/architecture/2026-07-14-provider-routed-llm-adapters.md -2026-07-14-provider-routed-llm-adapters.md: e1eaf52f21481a7c65e85effb7607b16f9b0ffdd -2026-07-14-provider-routed-llm-adapters.zh.md: 4e620408dabffc8368293635613afb5778b6e822 +2026-07-14-provider-routed-llm-adapters.md: 78c8d6788006c503b532ff2bbddd30342415f0a4 +2026-07-14-provider-routed-llm-adapters.zh.md: 5e73cab5f1f2b1296c9a486d1c833e95bb5674a0 diff --git a/.agents/notes/implemented/architecture/2026-07-14-provider-routed-llm-adapters.md b/.agents/notes/implemented/architecture/2026-07-14-provider-routed-llm-adapters.md index e1eaf52f21..78c8d67880 100644 --- a/.agents/notes/implemented/architecture/2026-07-14-provider-routed-llm-adapters.md +++ b/.agents/notes/implemented/architecture/2026-07-14-provider-routed-llm-adapters.md @@ -40,9 +40,9 @@ pi-ai's common stream options do not expose stop sequences. `dsh-llm-pi-ai` reje Assistant messages carry the request's `provider` and `model`, plus an optional JSON-serializable adapter replay state. A successful `assistant/message` session event records those fields and `deriveMessages()` returns them with the assistant message. User, system, context, and tool-result messages carry no assistant route fields. The provider/model fields are authoritative loop data; an adapter owns only its opaque replay-state payload. -A terminal successful `finish` chunk may carry replay state, and `BlockAssembler` retains it alongside usage and finish reason. The loop attaches that state to the assembled assistant message's model source without exposing a response-rewrite hook. Error and aborted responses do not produce a normal assistant message and therefore do not enter future model history. +A terminal successful `finish` chunk may carry replay state as a `ReplayEnvelope`: opaque response-level metadata plus optional per-block entries aligned with the emitted block sequence. `BlockAssembler` makes one keep/drop decision for content and metadata — when max-token assembly drops a tool call, the envelope loses the entry at the same position — so the state the loop attaches to the assembled assistant message's model source always describes the stored blocks, per the [max-token replay-state alignment decision](../bug-fix/2026-08-15-max-token-replay-state-alignment.md). The loop exposes no response-rewrite hook. Error and aborted responses do not produce a normal assistant message and therefore do not enter future model history. -The pi-ai replay state is a versioned, minimal projection of its successful `AssistantMessage`: source API/provider/model, response id/model, stop reason, and index-aligned text, thinking, and tool-call signatures. It does not duplicate text or tool arguments already carried by Harness content blocks, and it omits diagnostics, timestamps, usage, and errors. On a later request, `LlmRuntime` gives replay state to the target adapter only when the historical provider and target provider are currently owned by the same adapter instance. That adapter combines the logged Harness content with replay state when it can restore the historical response, and owns any required cross-model or cross-provider conversion. An adapter receiving replay state with an unknown version or mismatched block shape fails explicitly; a different adapter receives only provider-neutral content plus provider/model fields. +The pi-ai replay state fills that envelope with a versioned, minimal projection of its successful `AssistantMessage`: a response half (source API/provider/model, response id/model, stop reason) and per-block text, thinking, and tool-call signatures. It does not duplicate text or tool arguments already carried by Harness content blocks, and it omits diagnostics, timestamps, usage, and errors. On a later request, `LlmRuntime` gives replay state to the target adapter only when the historical provider and target provider are currently owned by the same adapter instance. That adapter combines the logged Harness content with replay state when it can restore the historical response, and owns any required cross-model or cross-provider conversion. Durable content stays authoritative: an adapter receiving replay state it cannot use — an unknown kind or version, malformed metadata, or a block shape that no longer matches the content — degrades that message to provider-neutral conversion with a diagnostic; a different adapter receives only provider-neutral content plus provider/model fields. This state is model-visible replay input and therefore follows the existing [reconstructable-request rule](2026-07-05-reconstructable-requests.md): it is present in both the terminal `finish` chunk and the assembled `assistant/message` model source that drives derivation. Resume and fork preserve it verbatim. Compaction that shadows the assistant message also removes its replay state from the active surface; the summary is ordinary provider-neutral content. diff --git a/.agents/notes/implemented/architecture/2026-07-14-provider-routed-llm-adapters.zh.md b/.agents/notes/implemented/architecture/2026-07-14-provider-routed-llm-adapters.zh.md index 4e620408da..5e73cab5f1 100644 --- a/.agents/notes/implemented/architecture/2026-07-14-provider-routed-llm-adapters.zh.md +++ b/.agents/notes/implemented/architecture/2026-07-14-provider-routed-llm-adapters.zh.md @@ -40,9 +40,9 @@ pi-ai 的通用流选项不支持停止序列。若 Harness `stop` 选项已定 助手消息携带请求的 `provider` 和 `model`,以及可选的 JSON 可序列化适配器回放状态。成功的 `assistant/message` 会话事件记录这些字段,`deriveMessages()` 返回助手消息时也会包含它们。用户、系统、上下文与工具结果消息不携带助手路由字段。提供方/模型字段是 agent loop 的权威数据;适配器仅拥有其不透明回放状态 payload。 -成功的终止 `finish` 分片可以携带回放状态,`BlockAssembler` 会将其与 token 用量和结束原因一起保留。agent loop 会把该状态附加到已组装助手消息的模型来源中,但不公开响应改写钩子。错误或中止响应不会生成正常助手消息,因此不会进入后续模型历史。 +成功的终止 `finish` 分片可以以 `ReplayEnvelope` 形式携带回放状态:不透明的响应级元数据,加上与发射块序列对齐的可选逐块条目。`BlockAssembler` 对内容与元数据只做一次保留/丢弃决定——max-token 组装丢弃工具调用时,数据同一位置的条目一并丢弃——因此 agent loop 附加到已组装助手消息模型来源中的状态始终描述存储的块,见 [max-token 回放状态对齐决定](../bug-fix/2026-08-15-max-token-replay-state-alignment.md)。agent loop 不公开响应改写钩子。错误或中止响应不会生成正常助手消息,因此不会进入后续模型历史。 -pi-ai 回放状态是其成功 `AssistantMessage` 的带版本最小投影,包含源 API/提供方/模型、响应 ID/模型、停止原因,以及按索引对齐的文本签名、thinking 签名和工具调用签名。它不会重复 Harness 内容块中已有的文本或工具参数,也不包含诊断信息、时间戳、用量或错误。后续请求中,只有历史提供方和目标提供方当前归同一个适配器实例所有时,`LlmRuntime` 才会把回放状态交给目标适配器。适配器在能够恢复历史响应时,将 Harness 记录的内容与回放状态组合,并负责所需的跨模型或跨提供方转换。适配器收到未知版本或块形状不匹配的回放状态时会显式失败;其他适配器只能收到提供方无关的内容以及提供方/模型字段。 +pi-ai 回放状态用其成功 `AssistantMessage` 的带版本最小投影填充该结构:一个响应半区(源 API/提供方/模型、响应 ID/模型、停止原因),以及逐块的文本签名、thinking 签名和工具调用签名。它不会重复 Harness 内容块中已有的文本或工具参数,也不包含诊断信息、时间戳、用量或错误。后续请求中,只有历史提供方和目标提供方当前归同一个适配器实例所有时,`LlmRuntime` 才会把回放状态交给目标适配器。适配器在能够恢复历史响应时,将 Harness 记录的内容与回放状态组合,并负责所需的跨模型或跨提供方转换。持久化内容保持权威:适配器收到无法使用的回放状态——未知 kind 或版本、格式错误的元数据、或与内容不再匹配的块结构——会把该消息降级为提供方无关转换并带出诊断;其他适配器只能收到提供方无关的内容以及提供方/模型字段。 该状态属于模型可见的回放输入,因此遵循现有的[请求可重建规则](2026-07-05-reconstructable-requests.md):它同时存在于终止 `finish` 分片和驱动派生的已组装 `assistant/message` 模型来源中。恢复和 fork 会原样保留该状态。压缩(compaction)遮蔽助手消息时,也会从活动 surface 中移除其回放状态;摘要属于普通的提供方无关内容。 diff --git a/.agents/notes/implemented/architecture/2026-07-24-adapter-owned-reasoning-effort-capabilities.i18n.yaml b/.agents/notes/implemented/architecture/2026-07-24-adapter-owned-reasoning-effort-capabilities.i18n.yaml index 7e8eb5c17d..48967a6faa 100644 --- a/.agents/notes/implemented/architecture/2026-07-24-adapter-owned-reasoning-effort-capabilities.i18n.yaml +++ b/.agents/notes/implemented/architecture/2026-07-24-adapter-owned-reasoning-effort-capabilities.i18n.yaml @@ -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 .agents/notes/implemented/architecture/2026-07-24-adapter-owned-reasoning-effort-capabilities.md -2026-07-24-adapter-owned-reasoning-effort-capabilities.md: f71a15626b97090a89f071e552a12b1f89173620 -2026-07-24-adapter-owned-reasoning-effort-capabilities.zh.md: 6e8c99f98107e2855aa7cb7ea759544013d0ea8a +2026-07-24-adapter-owned-reasoning-effort-capabilities.md: f59e5d351970e785e6ade32797f1c1a5dd9e2591 +2026-07-24-adapter-owned-reasoning-effort-capabilities.zh.md: 6e657a90e8ef3cd400a3e252f728bb1aadd9f4f2 diff --git a/.agents/notes/implemented/architecture/2026-07-24-adapter-owned-reasoning-effort-capabilities.md b/.agents/notes/implemented/architecture/2026-07-24-adapter-owned-reasoning-effort-capabilities.md index f71a15626b..f59e5d3519 100644 --- a/.agents/notes/implemented/architecture/2026-07-24-adapter-owned-reasoning-effort-capabilities.md +++ b/.agents/notes/implemented/architecture/2026-07-24-adapter-owned-reasoning-effort-capabilities.md @@ -14,7 +14,7 @@ Reasoning strength was adapter configuration only, so a conversation could not d `LlmCallConfig` and `GenerateOptions` carry the optional effort. The agent loop prepares the post-`agent/request` config under the active turn signal before writing `request/header`, so defaults and dynamic changes are model-visible only after becoming durable facts. The prepared call retains the exact adapter registration across asynchronous exact-model resolution, durable header logging, and dispatch; direct `LlmRuntime.stream()` calls likewise capture their final registration before awaiting resolution. A route with no registered adapter retains its proposed config so an `llm/stream` middleware can own and short-circuit it; terminal dispatch still rejects an unhandled route. A resumed loop retains the logged effort only when its initial provider/model route is unchanged; a route change discards the previous model's opaque id. -The native DeepSeek adapter advertises `off`, `high`, and `max` when deployment policy permits thinking, and defaults to the configured effort or `high`. Its adapter-owned `off` maps to `thinking.type: disabled` with no `reasoning_effort`; `high` and `max` enable thinking and carry their official wire effort. A `thinking: disabled` deployment publishes only `off` and rejects attempts to enable thinking before provider I/O. The pi-ai adapter publishes each exact model's `getSupportedThinkingLevels()` result unchanged, including `off`, preserves an absent profile default as a provider default, and leaves provider wire-value mapping inside pi-ai. Its common stream options represent `off` by omitting `reasoning`, as required by pi-ai's own API. +The native DeepSeek adapter advertises `off`, `low`, `high`, and `max` when deployment policy permits thinking, and defaults to the configured effort or `high`. Its adapter-owned `off` maps to `thinking.type: disabled` with no `reasoning_effort`; `low`, `high`, and `max` enable thinking and carry their same-named official wire effort. A `thinking: disabled` deployment publishes only `off` and rejects attempts to enable thinking before provider I/O. The pi-ai adapter publishes each exact model's `getSupportedThinkingLevels()` result unchanged, including `off`, preserves an absent profile default as a provider default, and leaves provider wire-value mapping inside pi-ai. Its common stream options represent `off` by omitting `reasoning`, as required by pi-ai's own API. ## Alternatives considered diff --git a/.agents/notes/implemented/architecture/2026-07-24-adapter-owned-reasoning-effort-capabilities.zh.md b/.agents/notes/implemented/architecture/2026-07-24-adapter-owned-reasoning-effort-capabilities.zh.md index 6e8c99f981..6e657a90e8 100644 --- a/.agents/notes/implemented/architecture/2026-07-24-adapter-owned-reasoning-effort-capabilities.zh.md +++ b/.agents/notes/implemented/architecture/2026-07-24-adapter-owned-reasoning-effort-capabilities.zh.md @@ -14,7 +14,7 @@ Status: implemented `LlmCallConfig` 和 `GenerateOptions` 携带可选的推理强度。agent loop 在活跃轮次信号的控制下准备 `agent/request` 处理完成后的配置,再写入 `request/header`,因此默认值和动态变更只有成为持久化事实后才对模型可见。准备完成的调用在异步确切模型解析、请求头持久记录和分派全程保留同一项确切的适配器注册;直接调用 `LlmRuntime.stream()` 时,也会在等待解析前捕获最终的适配器注册。没有已注册适配器的路由会保留原定配置,使 `llm/stream` 中间件可以接管并短路该请求;若仍未得到处理,最终分发会拒绝该路由。恢复后的 agent loop 仅在初始提供方/模型路由未变时保留日志中记录的推理强度;如果路由发生变化,则丢弃上一模型的不透明 ID。 -当部署策略允许思考时,原生 DeepSeek 适配器声明 `off`、`high` 和 `max`,默认使用配置指定的推理强度,若未配置则使用 `high`。由适配器持有的 `off` 映射为 `thinking.type: disabled`,且不带 `reasoning_effort`;`high` 和 `max` 会启用思考并携带各自的官方协议强度值。配置为 `thinking: disabled` 的部署仅声明 `off`,并会在提供方 I/O 前拒绝启用思考的尝试。pi-ai 适配器原样发布每个确切模型的 `getSupportedThinkingLevels()` 结果,其中包括 `off`;profile 未指定默认值时保留提供方默认行为,并将提供方协议值的映射留在 pi-ai 内部。按照 pi-ai 自身 API 的要求,其通用流选项通过省略 `reasoning` 来表示 `off`。 +当部署策略允许思考时,原生 DeepSeek 适配器声明 `off`、`low`、`high` 和 `max`,默认使用配置指定的推理强度,若未配置则使用 `high`。由适配器持有的 `off` 映射为 `thinking.type: disabled`,且不带 `reasoning_effort`;`low`、`high` 和 `max` 会启用思考并携带各自的同名官方协议强度值。配置为 `thinking: disabled` 的部署仅声明 `off`,并会在提供方 I/O 前拒绝启用思考的尝试。pi-ai 适配器原样发布每个确切模型的 `getSupportedThinkingLevels()` 结果,其中包括 `off`;profile 未指定默认值时保留提供方默认行为,并将提供方协议值的映射留在 pi-ai 内部。按照 pi-ai 自身 API 的要求,其通用流选项通过省略 `reasoning` 来表示 `off`。 ## 备选方案 diff --git a/.agents/notes/implemented/architecture/2026-07-26-job-registry-seam.i18n.yaml b/.agents/notes/implemented/architecture/2026-07-26-job-registry-seam.i18n.yaml index dfc3a79832..5d60dee0d3 100644 --- a/.agents/notes/implemented/architecture/2026-07-26-job-registry-seam.i18n.yaml +++ b/.agents/notes/implemented/architecture/2026-07-26-job-registry-seam.i18n.yaml @@ -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 .agents/notes/implemented/architecture/2026-07-26-job-registry-seam.md -2026-07-26-job-registry-seam.md: 5a77e8e8098a135dd25abeb11c68127fd9f1b4e9 -2026-07-26-job-registry-seam.zh.md: fdc0912eca0b7ba01241137020e8e028c5480e2f +2026-07-26-job-registry-seam.md: b4a8a66ef63f1a4955e2497cad2d0d0b1ef138ec +2026-07-26-job-registry-seam.zh.md: ebab92029ddb9edd4c7085eef0d8cc83e9289bd9 diff --git a/.agents/notes/implemented/architecture/2026-07-26-job-registry-seam.md b/.agents/notes/implemented/architecture/2026-07-26-job-registry-seam.md index 5a77e8e809..b4a8a66ef6 100644 --- a/.agents/notes/implemented/architecture/2026-07-26-job-registry-seam.md +++ b/.agents/notes/implemented/architecture/2026-07-26-job-registry-seam.md @@ -6,17 +6,17 @@ English | [中文](2026-07-26-job-registry-seam.zh.md) ## Problem -The [background-job runtime](2026-06-20-generic-long-running-tool-runtime.md) shipped `JobRegistry` as one concrete package: `@deepseek-ai/dsh-jobs` owned both the `ctx.jobs` contract every producer and controller programs against and the process-local provider (the in-memory store, settlement bookkeeping, owner-cleanup effects, teardown). That bundling recouples the two rates of change the repository's [capability-seam rule](2026-06-13-capability-seams.md) separates: swapping the registry's storage or lifecycle backend would churn the same package whose types and `ctx.jobs` API producers (`dsh-tool-bash`, `dsh-tool-terminal`, `dsh-tool-subagent`), the controller (`dsh-tool-jobs`), and `JobKindMap` extenders import. Every other swappable capability in the harness — bash, pty, fs, skill, subagent, web, session persistence — already carries the Service Definition / Service provider / Consumer split; the job registry was the remaining `core`-mode exception, guarded only by a `TODO(job-service-backend)` comment. +The [background-job runtime](2026-06-20-generic-long-running-tool-runtime.md) shipped `JobRegistry` as one concrete package: `@deepseek-ai/dsh-jobs` owned both the `ctx.jobs` contract every producer and controller programs against and the process-local provider (the in-memory store, settlement bookkeeping, owner-cleanup effects, teardown). That bundling recouples the two rates of change the repository's [capability-seam rule](2026-06-13-capability-seams.md) separates: swapping the registry's storage or lifecycle backend would churn the same package whose types and `ctx.jobs` API producers (`dsh-tool-bash`, `dsh-tool-terminal`, `dsh-tool-subagent`), the controller (`dsh-tool-jobs`), and `JobKindMap` extenders import. Every other swappable capability in the harness — bash, pty, fs, skill, subagent, web, session persistence — already carries the Service Definition / Service Provider / Consumer split; the job registry was the remaining `core`-mode exception, guarded only by a `TODO(job-service-backend)` comment. ## Decision `jobs/` is now a three-package capability family in the bash-trio shape: -- **`@deepseek-ai/dsh-jobs` (Service Definition)** — the abstract `JobRegistry extends Service` owning `ctx.jobs`, the nine-method contract (`start`, `list`, `get`, `read`, `kill`, `wait`, `onJobDone`, `onJobsChanged`, `attachController`), all vocabulary types (`JobId`, `JobKindMap`, `JobStart`, `JobHooks`, `JobOutcome`, `JobSnapshot`, `JobRead`, `JobDoneListener`), and the snapshot invariant companion. The class-level JSDoc states the semantics every Service provider owes: registrations outlive producer and controller fibers, owned access is session-fenced, settlement is first-wins with contained listeners, and `start` refuses work while no attached job controller serves the spec's owner (controllers and listeners are scope-layered, so one process-wide registry answers both questions per owner). -- **`@deepseek-ai/dsh-jobs-local` (Service provider)** — `LocalJobRegistry`, the process-local registry: the in-memory store, per-kind id counters, waiter bookkeeping, `TASK_WAIT_TIMEOUT` deadline code, owner-cleanup effects, force-fail teardown, and the default-10 configurable admission policy. Admission derives `running` plus `stopping` capacity from the same records per exact owner, with one unowned bucket; it adds no public count or second state owner. The `dsh-timeout` dependency and Schemastery-owned provider config live here; the Service Definition package has no provider dependencies. +- **`@deepseek-ai/dsh-jobs` (Service Definition)** — the abstract `JobRegistry extends Service` owning `ctx.jobs`, the nine-method contract (`start`, `list`, `get`, `read`, `kill`, `wait`, `onJobDone`, `onJobsChanged`, `attachController`), all vocabulary types (`JobId`, `JobKindMap`, `JobStart`, `JobHooks`, `JobOutcome`, `JobSnapshot`, `JobRead`, `JobDoneListener`), and the snapshot invariant companion. The class-level JSDoc states the semantics every Service Provider owes: registrations outlive producer and controller fibers, owned access is session-fenced, settlement is first-wins with contained listeners, and `start` refuses work while no attached job controller serves the spec's owner (controllers and listeners are scope-layered, so one process-wide registry answers both questions per owner). +- **`@deepseek-ai/dsh-jobs-local` (Service Provider)** — `LocalJobRegistry`, the process-local registry: the in-memory store, per-kind id counters, waiter bookkeeping, `TASK_WAIT_TIMEOUT` deadline code, owner-cleanup effects, force-fail teardown, and the default-10 configurable admission policy. Admission derives `running` plus `stopping` capacity from the same records per exact owner, with one unowned bucket; it adds no public count or second state owner. The `dsh-timeout` dependency and Schemastery-owned provider config live here; the Service Definition package has no provider dependencies. - **`@deepseek-ai/dsh-tool-jobs` (Consumer)** — unchanged; it injects `'jobs'` and never imports provider types. -Compositions load `dsh-jobs-local` where they previously loaded `dsh-jobs` (the CLI cordis.yml row, `agent-spine-demo`, test harnesses, the tool-catalog generator boot). Producer misconfiguration diagnostics ("background jobs unavailable: load …") name `dsh-jobs` — the Service Definition package that declares the absent `ctx.jobs` service — and the Service Definition package's own APIs (its README and the direct-mount fence) point at Service providers, so the producer message stays correct when another backend becomes the recommended default. Producers, `JobKindMap` declaration merges, and the controller keep importing `@deepseek-ai/dsh-jobs` only. +Compositions load `dsh-jobs-local` where they previously loaded `dsh-jobs` (the CLI cordis.yml row, `agent-spine-demo`, test harnesses, the tool-catalog generator boot). Producer misconfiguration diagnostics ("background jobs unavailable: load …") name `dsh-jobs` — the Service Definition package that declares the absent `ctx.jobs` service — and the Service Definition package's own APIs (its README and the direct-mount fence) point at Service Providers, so the producer message stays correct when another backend becomes the recommended default. Producers, `JobKindMap` declaration merges, and the controller keep importing `@deepseek-ai/dsh-jobs` only. The seam keeps the in-process contract semantics unchanged: `JobStart.run()` still passes callbacks and exact `Agent` objects, so a durable or cross-process backend still has design work to do before it can satisfy this Service Definition (identity, restart, ownership, observation). The split moves that future work out of every Consumer's dependency graph; it does not pre-design the backend. @@ -30,6 +30,6 @@ The seam keeps the in-process contract semantics unchanged: `JobStart.run()` sti ## Consequences -Bought: the job registry now matches the repository-wide seam shape; a durable, remote, or instrumented registry is a sibling Service provider implementing nine abstract methods, and no producer, controller, or `JobKindMap` extender changes when one lands. The Service Definition README states the contract; the provider README owns the lifecycle bookkeeping facts. The registry behavior suite (owner cleanup, settlement, waits, teardown) lives with `dsh-jobs-local`; the Service Definition package keeps a stub-subclass test pinning registration under `ctx.jobs` and single-service duplication behavior, plus the probe-based invariant suite. +Bought: the job registry now matches the repository-wide seam shape; a durable, remote, or instrumented registry is a sibling Service Provider implementing nine abstract methods, and no producer, controller, or `JobKindMap` extender changes when one lands. The Service Definition README states the contract; the provider README owns the lifecycle bookkeeping facts. The registry behavior suite (owner cleanup, settlement, waits, teardown) lives with `dsh-jobs-local`; the Service Definition package keeps a stub-subclass test pinning registration under `ctx.jobs` and single-service duplication behavior, plus the probe-based invariant suite. -Cost: one more package (manifest, tsconfig, README, invariant companion), and compositions must name the Service provider package. `abstract` erases at runtime and this package name used to be the mountable registry, so the Service Definition constructor fails loudly when mounted directly — a stale composition row gets "load a Service provider such as @deepseek-ai/dsh-jobs-local" at load time instead of a half-registered `ctx.jobs` failing far from the misconfiguration. +Cost: one more package (manifest, tsconfig, README, invariant companion), and compositions must name the Service Provider package. `abstract` erases at runtime and this package name used to be the mountable registry, so the Service Definition constructor fails loudly when mounted directly — a stale composition row gets "load a Service Provider such as @deepseek-ai/dsh-jobs-local" at load time instead of a half-registered `ctx.jobs` failing far from the misconfiguration. diff --git a/.agents/notes/implemented/architecture/2026-07-26-job-registry-seam.zh.md b/.agents/notes/implemented/architecture/2026-07-26-job-registry-seam.zh.md index fdc0912eca..ebab92029d 100644 --- a/.agents/notes/implemented/architecture/2026-07-26-job-registry-seam.zh.md +++ b/.agents/notes/implemented/architecture/2026-07-26-job-registry-seam.zh.md @@ -6,30 +6,30 @@ Status: implemented ## 问题 -[后台任务运行时](2026-06-20-generic-long-running-tool-runtime.md)交付时把 `JobRegistry` 做成了单个具体包:`@deepseek-ai/dsh-jobs` 既拥有每个生产方和控制器面向编程的 `ctx.jobs` 约定,也拥有进程内 Service provider(内存存储、结算簿记、所有者清理 effect、拆除)。这种捆绑重新耦合了仓库[能力 seam 规则](2026-06-13-capability-seams.md)本要分离的两种变化速率:一旦替换注册表的存储或生命周期后端,被搅动的就是同一个包,而生产方(`dsh-tool-bash`、`dsh-tool-terminal`、`dsh-tool-subagent`)、控制器(`dsh-tool-jobs`)和 `JobKindMap` 扩展方正是从这个包导入类型与 `ctx.jobs` API。harness 中其余每项可替换能力——bash、pty、fs、skill(技能)、subagent、web、会话持久化——都已具备 Service Definition / Service provider / Consumer 三分;任务注册表曾是仅剩的 `core` 模式例外,仅由一条 `TODO(job-service-backend)` 注释把守。 +[后台任务运行时](2026-06-20-generic-long-running-tool-runtime.md)交付时把 `JobRegistry` 做成了单个具体包:`@deepseek-ai/dsh-jobs` 既拥有每个生产方和控制器面向编程的 `ctx.jobs` 约定,也拥有进程内 Service Provider(内存存储、结算簿记、所有者清理 effect、拆除)。这种捆绑重新耦合了仓库[能力 seam 规则](2026-06-13-capability-seams.md)本要分离的两种变化速率:一旦替换注册表的存储或生命周期后端,被搅动的就是同一个包,而生产方(`dsh-tool-bash`、`dsh-tool-terminal`、`dsh-tool-subagent`)、控制器(`dsh-tool-jobs`)和 `JobKindMap` 扩展方正是从这个包导入类型与 `ctx.jobs` API。harness 中其余每项可替换能力——bash、pty、fs、skill(技能)、subagent、web、会话持久化——都已具备 Service Definition / Service Provider / Consumer 三分;任务注册表曾是仅剩的 `core` 模式例外,仅由一条 `TODO(job-service-backend)` 注释把守。 ## 决策 `jobs/` 如今是一个 bash 三件套形态的三包能力家族: -- **`@deepseek-ai/dsh-jobs`(Service Definition)**——抽象的 `JobRegistry extends Service`,拥有 `ctx.jobs`、九个方法的约定(`start`、`list`、`get`、`read`、`kill`、`wait`、`onJobDone`、`onJobsChanged`、`attachController`)、全部词汇类型(`JobId`、`JobKindMap`、`JobStart`、`JobHooks`、`JobOutcome`、`JobSnapshot`、`JobRead`、`JobDoneListener`),以及快照不变式配套插件。类级 JSDoc 陈述了每个 Service provider 都必须兑现的语义:注册的存续期长于生产方与控制器的 fiber,有所有者的访问以会话为界,结算遵循首次结果优先且监听器错误被隔离,并且当没有任何已附加的任务控制器服务于 spec 的所有者时 `start` 拒绝启动工作(控制器与监听器按 scope 分层,因此一个进程级注册表能逐所有者地回答这两个问题)。 -- **`@deepseek-ai/dsh-jobs-local`(Service provider)**——`LocalJobRegistry`,即进程内注册表:内存存储、按 kind 划分的 id 计数器、等待方簿记、`TASK_WAIT_TIMEOUT` deadline 代码、所有者清理 effect、强制失败的拆除,以及默认值为 10 且可配置的准入策略。准入从同一组记录中按确切 owner 派生 `running` 加 `stopping` 容量,并为无 owner 任务使用一个共享桶;它不新增公开计数或第二个状态 owner。`dsh-timeout` 依赖与由 Schemastery 管理的 Service provider 配置都位于此包;Service Definition 包不含任何提供方依赖。 +- **`@deepseek-ai/dsh-jobs`(Service Definition)**——抽象的 `JobRegistry extends Service`,拥有 `ctx.jobs`、九个方法的约定(`start`、`list`、`get`、`read`、`kill`、`wait`、`onJobDone`、`onJobsChanged`、`attachController`)、全部词汇类型(`JobId`、`JobKindMap`、`JobStart`、`JobHooks`、`JobOutcome`、`JobSnapshot`、`JobRead`、`JobDoneListener`),以及快照不变式配套插件。类级 JSDoc 陈述了每个 Service Provider 都必须兑现的语义:注册的存续期长于生产方与控制器的 fiber,有所有者的访问以会话为界,结算遵循首次结果优先且监听器错误被隔离,并且当没有任何已附加的任务控制器服务于 spec 的所有者时 `start` 拒绝启动工作(控制器与监听器按 scope 分层,因此一个进程级注册表能逐所有者地回答这两个问题)。 +- **`@deepseek-ai/dsh-jobs-local`(Service Provider)**——`LocalJobRegistry`,即进程内注册表:内存存储、按 kind 划分的 id 计数器、等待方簿记、`TASK_WAIT_TIMEOUT` deadline 代码、所有者清理 effect、强制失败的拆除,以及默认值为 10 且可配置的准入策略。准入从同一组记录中按确切 owner 派生 `running` 加 `stopping` 容量,并为无 owner 任务使用一个共享桶;它不新增公开计数或第二个状态 owner。`dsh-timeout` 依赖与由 Schemastery 管理的 Service Provider 配置都位于此包;Service Definition 包不含任何提供方依赖。 - **`@deepseek-ai/dsh-tool-jobs`(Consumer)**——保持不变;它注入 `'jobs'`,从不导入提供方类型。 -各组合在原先加载 `dsh-jobs` 的位置改为加载 `dsh-jobs-local`:CLI(命令行界面)的 cordis.yml 配置项、`agent-spine-demo`、各测试 harness,以及工具目录生成器的启动流程。生产方的配置错误诊断信息(「background jobs unavailable: load …」)点名 `dsh-jobs`——即声明缺失的 `ctx.jobs` 服务的 Service Definition 包;Service Definition 包自身的 API(其 README 与直接挂载防线)会指向各 Service provider,因此当另一个后端日后成为推荐默认时,生产方的消息依旧正确。生产方、`JobKindMap` 声明合并和控制器仍然只导入 `@deepseek-ai/dsh-jobs`。 +各组合在原先加载 `dsh-jobs` 的位置改为加载 `dsh-jobs-local`:CLI(命令行界面)的 cordis.yml 配置项、`agent-spine-demo`、各测试 harness,以及工具目录生成器的启动流程。生产方的配置错误诊断信息(「background jobs unavailable: load …」)点名 `dsh-jobs`——即声明缺失的 `ctx.jobs` 服务的 Service Definition 包;Service Definition 包自身的 API(其 README 与直接挂载防线)会指向各 Service Provider,因此当另一个后端日后成为推荐默认时,生产方的消息依旧正确。生产方、`JobKindMap` 声明合并和控制器仍然只导入 `@deepseek-ai/dsh-jobs`。 该 seam 保持进程内约定语义不变:`JobStart.run()` 仍然传入回调和确切的 `Agent` 对象,因此持久化或跨进程后端在能满足此 Service Definition 之前仍有设计工作要做(身份、重启、所有权、观察)。这次拆分把该项未来工作移出了每个 Consumer 的依赖图;它并不预先设计后端。 ## 曾考虑的替代方案 -**在第二个后端出现之前保持具体服务(维持现状)。**这正是运行时 Agent Note 当初的立场:在第二个 Service provider 出现前抽取 Service Definition,可能固化错误的边界。该方案落选,因为这条边界已不再是臆测:九个服务方法及其语义自引入以来在每一次生产方集成中都保持稳定,它们正是 `dsh-tool-jobs` 与各生产方已经面向编程的那套接口,而且仓库约定默认将可替换能力拆成三个包。剩余风险(持久化后端可能需要变更约定)不因这次拆分而改变:无论拆分与否,这类变更都会落在 Service Definition 包里;而若维持现状,它们今天还会连带搅动每个 Consumer 的提供方依赖。 +**在第二个后端出现之前保持具体服务(维持现状)。**这正是运行时 Agent Note 当初的立场:在第二个 Service Provider 出现前抽取 Service Definition,可能固化错误的边界。该方案落选,因为这条边界已不再是臆测:九个服务方法及其语义自引入以来在每一次生产方集成中都保持稳定,它们正是 `dsh-tool-jobs` 与各生产方已经面向编程的那套接口,而且仓库约定默认将可替换能力拆成三个包。剩余风险(持久化后端可能需要变更约定)不因这次拆分而改变:无论拆分与否,这类变更都会落在 Service Definition 包里;而若维持现状,它们今天还会连带搅动每个 Consumer 的提供方依赖。 -**在单个包内仅抽取 Service Definition(在具体类旁导出一个抽象类)。**否决,因为它在运作层面并未分离任何东西:Consumer 依然依赖携带 Service provider 及其依赖项的那个包,而替换后端若不把本地 Service provider 纳入自身依赖图,就仍然无法发布。在这里,包边界才是独立演进的单位。 +**在单个包内仅抽取 Service Definition(在具体类旁导出一个抽象类)。**否决,因为它在运作层面并未分离任何东西:Consumer 依然依赖携带 Service Provider 及其依赖项的那个包,而替换后端若不把本地 Service Provider 纳入自身依赖图,就仍然无法发布。在这里,包边界才是独立演进的单位。 **拆出 `types.ts` 但让服务保持具体。**基于同样的理由否决:类型并不是完整能力,`ctx.jobs` Service Definition 及其方法约定才是。生产方需要的是服务键和语义,而不只是类型形状。 ## 后果 -换来的是:任务注册表如今与全仓库通行的 seam 形态一致;持久化、远程或带插桩的注册表将是一个实现九个抽象方法的同级 Service provider,这样的注册表落地时,任何生产方、控制器或 `JobKindMap` 扩展方都无需改动。Service Definition 的 README 陈述约定;生命周期簿记方面的事实归 Service provider 的 README 所有。注册表行为测试套件(所有者清理、结算、等待、拆除)随 `dsh-jobs-local` 存放;Service Definition 包保留一个桩子类(stub subclass)测试,固定 `ctx.jobs` 下的注册行为与单一服务的重复注册行为,外加基于探针的不变式测试套件。 +换来的是:任务注册表如今与全仓库通行的 seam 形态一致;持久化、远程或带插桩的注册表将是一个实现九个抽象方法的同级 Service Provider,这样的注册表落地时,任何生产方、控制器或 `JobKindMap` 扩展方都无需改动。Service Definition 的 README 陈述约定;生命周期簿记方面的事实归 Service Provider 的 README 所有。注册表行为测试套件(所有者清理、结算、等待、拆除)随 `dsh-jobs-local` 存放;Service Definition 包保留一个桩子类(stub subclass)测试,固定 `ctx.jobs` 下的注册行为与单一服务的重复注册行为,外加基于探针的不变式测试套件。 -代价是:多出一个包,即多一份 manifest(元数据清单)、tsconfig、README 与不变式配套插件;同时各组合必须点名 Service provider 包。`abstract` 在运行时会被擦除,而这个包名过去正是可挂载的具体注册表,因此直接挂载 Service Definition 时,其构造函数会明确报错——一条陈旧的组合配置行会在加载时得到「load a Service provider such as @deepseek-ai/dsh-jobs-local」,而不是一个未完整注册的 `ctx.jobs` 在远离错误配置处才失败。 +代价是:多出一个包,即多一份 manifest(元数据清单)、tsconfig、README 与不变式配套插件;同时各组合必须点名 Service Provider 包。`abstract` 在运行时会被擦除,而这个包名过去正是可挂载的具体注册表,因此直接挂载 Service Definition 时,其构造函数会明确报错——一条陈旧的组合配置行会在加载时得到「load a Service Provider such as @deepseek-ai/dsh-jobs-local」,而不是一个未完整注册的 `ctx.jobs` 在远离错误配置处才失败。 diff --git a/.agents/notes/implemented/architecture/2026-07-26-subprocess-seam.i18n.yaml b/.agents/notes/implemented/architecture/2026-07-26-subprocess-seam.i18n.yaml index 03c1e1092e..8422759a46 100644 --- a/.agents/notes/implemented/architecture/2026-07-26-subprocess-seam.i18n.yaml +++ b/.agents/notes/implemented/architecture/2026-07-26-subprocess-seam.i18n.yaml @@ -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 .agents/notes/implemented/architecture/2026-07-26-subprocess-seam.md -2026-07-26-subprocess-seam.md: f738c5be517d7f915cf5cb0f42506339259c62a2 -2026-07-26-subprocess-seam.zh.md: 078648d1d676f2d5889df4ec5793de687713cbb9 +2026-07-26-subprocess-seam.md: aa7a989a0321760c9bc278df8356a57f4dd0d459 +2026-07-26-subprocess-seam.zh.md: 22de6774b866b9b7a0248dc7b06587f7f3235fdc diff --git a/.agents/notes/implemented/architecture/2026-07-26-subprocess-seam.md b/.agents/notes/implemented/architecture/2026-07-26-subprocess-seam.md index f738c5be51..aa7a989a03 100644 --- a/.agents/notes/implemented/architecture/2026-07-26-subprocess-seam.md +++ b/.agents/notes/implemented/architecture/2026-07-26-subprocess-seam.md @@ -13,7 +13,7 @@ English | [中文](2026-07-26-subprocess-seam.zh.md) A new `subprocess/` capability family owns "run and manage a process"; the bash family keeps "run a bash command" and consumes it: - **`@deepseek-ai/dsh-subprocess` (Service Definition)** — the abstract `SubprocessRuntime` owning `ctx.subprocess`: executable lookup, fully explicit ordinary spawns, and the terminal primitive added by the [portable execution-world decision](2026-07-28-portable-execution-world-consumers.md). Each stdio stream independently selects `'pipe'`, `'inherit'`, or bounded collection `{ maxBytes, spill? }`; stdin selects `'ignore'`, `'pipe'`, or `{ data }`. `SubprocessOutcome` carries exit facts with deliberately no timeout/cancel classification, while collected output remains on the handle after settlement. The Service Definition also owns process and terminal handles, the shared scrub, and `DSH_ENV_PREFIX`/`DshEnvironment`/`CollectedOutput`; `argv` is never shell-interpreted. -- **`@deepseek-ai/dsh-subprocess-local` (Service provider)** — `LocalSubprocessRuntime` over the former `run.ts` plumbing (`spawn.ts`) plus `node-pty`: detached groups, bounded collection and private spill files, executable lookup, foreground/session inspection, and disposal that terminates and joins every managed process. `terminate()` owns TERM→grace→KILL for the tree, `waitForExit()` observes tree liveness, and injected `taskkill /T` covers Windows. Ordinary and terminal spawns apply the Service Definition's case-insensitive `KEY`/`PASSWORD`/`SECRET`/`TOKEN` scrub before explicit env. The provider has no config; every limit arrives on the spec, while Bash and PTY presentation environment overrides stay in their Consumers. +- **`@deepseek-ai/dsh-subprocess-local` (Service Provider)** — `LocalSubprocessRuntime` over the former `run.ts` plumbing (`spawn.ts`) plus `node-pty`: detached groups, bounded collection and private spill files, executable lookup, foreground/session inspection, and disposal that terminates and joins every managed process. `terminate()` owns TERM→grace→KILL for the tree, `waitForExit()` observes tree liveness, and injected `taskkill /T` covers Windows. Ordinary and terminal spawns apply the Service Definition's case-insensitive `KEY`/`PASSWORD`/`SECRET`/`TOKEN` scrub before explicit env. The provider has no config; every limit arrives on the spec, while Bash and PTY presentation environment overrides stay in their Consumers. - **`dsh-bash-local` (Consumer)** — `inject: ['subprocess']`; maps each resolved `ShellExecSpec` onto a `SubprocessSpawnSpec` (`['bash', '-c', command]`), keeps its config, `resolve()` defaulting, fused-deadline `timedOut`/`aborted` classification, the `[stderr]`-marked background read merge with its consuming cursor, and the `onProcessDone` subclass hook. `dsh-bash-sandbox` is unchanged apart from redeclaring the inherited inject; it still wraps at the command-string level and re-enters the inherited spawn path. - **`dsh-shell` (Service Definition)** — re-exports the moved vocabulary from `dsh-subprocess`, so no bash Consumer changes an import; `ShellExecRequest`/`ShellExecSpec`/`ShellProcess` and the sandbox facts remain bash-owned. diff --git a/.agents/notes/implemented/architecture/2026-07-26-subprocess-seam.zh.md b/.agents/notes/implemented/architecture/2026-07-26-subprocess-seam.zh.md index 078648d1d6..22de6774b8 100644 --- a/.agents/notes/implemented/architecture/2026-07-26-subprocess-seam.zh.md +++ b/.agents/notes/implemented/architecture/2026-07-26-subprocess-seam.zh.md @@ -13,7 +13,7 @@ Status: implemented 新的 `subprocess/` 能力家族拥有「运行并管理一个进程」;bash 家族保留「运行一条 bash 命令」,并成为前者的消费方: - **`@deepseek-ai/dsh-subprocess`(Service Definition)**——拥有 `ctx.subprocess` 的抽象 `SubprocessRuntime`:可执行文件查找、完全显式的普通 spawn,以及[可移植执行环境决策](2026-07-28-portable-execution-world-consumers.md)新增的终端原语。每条 stdio 流独立选择 `'pipe'`、`'inherit'` 或有界收集 `{ maxBytes, spill? }`;stdin 选择 `'ignore'`、`'pipe'` 或 `{ data }`。`SubprocessOutcome` 只承载刻意不含超时/取消分类的退出事实,收集输出在结算后仍留在句柄上。该 Service Definition 还拥有进程与终端句柄、共享凭据清除,以及 `DSH_ENV_PREFIX`/`DshEnvironment`/`CollectedOutput`;`argv` 绝不经过 shell 解释。 -- **`@deepseek-ai/dsh-subprocess-local`(Service provider)**——`LocalSubprocessRuntime` 构建在原 `run.ts` 管道(现为 `spawn.ts`)与 `node-pty` 之上:detached 进程组、有界收集与私有 spill 文件、可执行文件查找、前台/会话检查,以及终止每个受管进程并等待其退出的 dispose。`terminate()` 拥有面向进程树的 TERM→宽限→KILL,`waitForExit()` 观察进程树存活性,可注入的 `taskkill /T` 覆盖 Windows。普通与终端 spawn 都先应用 Service Definition 对 `KEY`/`PASSWORD`/`SECRET`/`TOKEN` 不区分大小写的清除,再合并显式 env。该 Service provider 没有配置;每项限制都随 spec 到达,Bash 与 PTY 的呈现环境覆盖仍归各自 Consumer 所有。 +- **`@deepseek-ai/dsh-subprocess-local`(Service Provider)**——`LocalSubprocessRuntime` 构建在原 `run.ts` 管道(现为 `spawn.ts`)与 `node-pty` 之上:detached 进程组、有界收集与私有 spill 文件、可执行文件查找、前台/会话检查,以及终止每个受管进程并等待其退出的 dispose。`terminate()` 拥有面向进程树的 TERM→宽限→KILL,`waitForExit()` 观察进程树存活性,可注入的 `taskkill /T` 覆盖 Windows。普通与终端 spawn 都先应用 Service Definition 对 `KEY`/`PASSWORD`/`SECRET`/`TOKEN` 不区分大小写的清除,再合并显式 env。该 Service Provider 没有配置;每项限制都随 spec 到达,Bash 与 PTY 的呈现环境覆盖仍归各自 Consumer 所有。 - **`dsh-bash-local`(Consumer)**——`inject: ['subprocess']`;把每个解析后的 `ShellExecSpec` 映射为一个 `SubprocessSpawnSpec`(`['bash', '-c', command]`),并保留自身配置、`resolve()` 默认值补全、基于融合 deadline 的 `timedOut`/`aborted` 分类、带 `[stderr]` 标记的后台读取合并及其消费游标,以及 `onProcessDone` 子类钩子。`dsh-bash-sandbox` 除了重新声明继承来的 inject 之外没有变化;它仍在命令字符串层面做包装,并重新进入继承的 spawn 路径。 - **`dsh-shell`(Service Definition)**——把迁走的词汇从 `dsh-subprocess` 重导出,因此没有任何 bash Consumer 需要改动导入;`ShellExecRequest`/`ShellExecSpec`/`ShellProcess` 与沙箱事实仍归 bash 所有。 diff --git a/.agents/notes/implemented/architecture/2026-07-27-dispose-ladder-to-consumer.i18n.yaml b/.agents/notes/implemented/architecture/2026-07-27-dispose-ladder-to-consumer.i18n.yaml index 10e1fbef20..a81c4706e7 100644 --- a/.agents/notes/implemented/architecture/2026-07-27-dispose-ladder-to-consumer.i18n.yaml +++ b/.agents/notes/implemented/architecture/2026-07-27-dispose-ladder-to-consumer.i18n.yaml @@ -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 .agents/notes/implemented/architecture/2026-07-27-dispose-ladder-to-consumer.md -2026-07-27-dispose-ladder-to-consumer.md: ab2afd313448438752e15e0f89230124cb95232f -2026-07-27-dispose-ladder-to-consumer.zh.md: b181b2c3286c42d85eb91ca9ac5acf624e5c7a28 +2026-07-27-dispose-ladder-to-consumer.md: 58d835864d2f6544152fdf09cf6e93380793a2ae +2026-07-27-dispose-ladder-to-consumer.zh.md: dc7413e85fa6e52de14f51fd175c7b37b43029a4 diff --git a/.agents/notes/implemented/architecture/2026-07-27-dispose-ladder-to-consumer.md b/.agents/notes/implemented/architecture/2026-07-27-dispose-ladder-to-consumer.md index ab2afd3134..58d835864d 100644 --- a/.agents/notes/implemented/architecture/2026-07-27-dispose-ladder-to-consumer.md +++ b/.agents/notes/implemented/architecture/2026-07-27-dispose-ladder-to-consumer.md @@ -14,10 +14,10 @@ The ladder moves to its one consumer. `dsh-subagent-acp` owns `disposeAcpChild(c ## Alternatives considered -**Keep the ladder on the handle as a convenience.** Rejected: a Service Definition method every Service provider must implement is not a convenience, it is contract surface — and this one encodes one consumer's cooperation shape (stdin-EOF-first) as if it were process vocabulary. The seam's own README already had to caveat that children quiescing on other signals need "their own tier-1", which is the admission that the ladder is policy. +**Keep the ladder on the handle as a convenience.** Rejected: a Service Definition method every Service Provider must implement is not a convenience, it is contract surface — and this one encodes one consumer's cooperation shape (stdin-EOF-first) as if it were process vocabulary. The seam's own README already had to caveat that children quiescing on other signals need "their own tier-1", which is the admission that the ladder is policy. **Move the ladder to a shared helper package.** Rejected: one consumer. A second out-of-process backend with the same stdin-EOF cooperation shape can lift `disposeAcpChild` to shared code when it exists; extracting now would recreate `dsh-subagent-subprocess`, the single-purpose library this change deleted. ## Consequences -Bought: the Service Definition is one method and one type smaller; Service providers owe four verbs and no teardown policy; the cooperative EOF window lives beside the ACP config field that tunes it, while the subprocess owner alone owns the termination window and final join. Cost: a future backend wanting EOF-first teardown writes ~20 lines against the verbs (or lifts the ACP helper); the ladder's tier tests live in the ACP suite, and the Service Definition suite pins the verbs the ladder composes (bounded `waitForExit` false before escalation and an unbounded whole-tree join after it) instead of the composed policy. +Bought: the Service Definition is one method and one type smaller; Service Providers owe four verbs and no teardown policy; the cooperative EOF window lives beside the ACP config field that tunes it, while the subprocess owner alone owns the termination window and final join. Cost: a future backend wanting EOF-first teardown writes ~20 lines against the verbs (or lifts the ACP helper); the ladder's tier tests live in the ACP suite, and the Service Definition suite pins the verbs the ladder composes (bounded `waitForExit` false before escalation and an unbounded whole-tree join after it) instead of the composed policy. diff --git a/.agents/notes/implemented/architecture/2026-07-27-dispose-ladder-to-consumer.zh.md b/.agents/notes/implemented/architecture/2026-07-27-dispose-ladder-to-consumer.zh.md index b181b2c328..dc7413e85f 100644 --- a/.agents/notes/implemented/architecture/2026-07-27-dispose-ladder-to-consumer.zh.md +++ b/.agents/notes/implemented/architecture/2026-07-27-dispose-ladder-to-consumer.zh.md @@ -14,10 +14,10 @@ Status: implemented ## 曾考虑的替代方案 -**把阶梯作为便利方法留在句柄上。**否决:一个每个 Service provider 都必须实现的 Service Definition 方法不是便利,而是约定的一部分——而这一个把某一消费方的协作模式(stdin EOF 打头)当作进程词汇来编码。seam 自己的 README 早已不得不加注「依赖其他信号才能完全停稳的子进程需要自己的第一阶」,这本身就是承认该阶梯是策略。 +**把阶梯作为便利方法留在句柄上。**否决:一个每个 Service Provider 都必须实现的 Service Definition 方法不是便利,而是约定的一部分——而这一个把某一消费方的协作模式(stdin EOF 打头)当作进程词汇来编码。seam 自己的 README 早已不得不加注「依赖其他信号才能完全停稳的子进程需要自己的第一阶」,这本身就是承认该阶梯是策略。 **把阶梯移到共享辅助包。**否决:只有一个消费方。当第二个具有相同 stdin EOF 协作模式的进程外后端出现时,可以再把 `disposeAcpChild` 提升为共享代码;现在抽取只会重造 `dsh-subagent-subprocess`——本次变更删掉的那个单一用途库。 ## 后果 -买到的:Service Definition 少了一个方法和一个类型;Service provider 只欠四个动词,不欠拆卸策略;协作式 EOF 时间窗与调节它的 ACP 配置字段住在一起,而终止时间窗与最终的整树退出等待仅由子进程责任方拥有。代价:未来想要 EOF 打头拆卸的后端需针对这些动词写约 20 行(或直接搬 ACP 的辅助函数);阶梯的层级测试位于 ACP 套件,Service Definition 套件转而钉住阶梯所组合的动词(升级前有界 `waitForExit` 返回假,升级后无界等待整棵进程树退出),而非组合后的策略。 +买到的:Service Definition 少了一个方法和一个类型;Service Provider 只欠四个动词,不欠拆卸策略;协作式 EOF 时间窗与调节它的 ACP 配置字段住在一起,而终止时间窗与最终的整树退出等待仅由子进程责任方拥有。代价:未来想要 EOF 打头拆卸的后端需针对这些动词写约 20 行(或直接搬 ACP 的辅助函数);阶梯的层级测试位于 ACP 套件,Service Definition 套件转而钉住阶梯所组合的动词(升级前有界 `waitForExit` 返回假,升级后无界等待整棵进程树退出),而非组合后的策略。 diff --git a/.agents/notes/implemented/architecture/2026-07-29-package-regrouping.i18n.yaml b/.agents/notes/implemented/architecture/2026-07-29-package-regrouping.i18n.yaml index 69bcf2af17..77bca2bb85 100644 --- a/.agents/notes/implemented/architecture/2026-07-29-package-regrouping.i18n.yaml +++ b/.agents/notes/implemented/architecture/2026-07-29-package-regrouping.i18n.yaml @@ -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 .agents/notes/implemented/architecture/2026-07-29-package-regrouping.md -2026-07-29-package-regrouping.md: 35042086503167d01edc1b3bfafdef92ba4781c5 -2026-07-29-package-regrouping.zh.md: 2dfd7ba85484008138f799ff60c406807a9ecf7f +2026-07-29-package-regrouping.md: 52a1fa28e4826daa7b0bb84a37be3c094fddb68c +2026-07-29-package-regrouping.zh.md: bef55544664f6e6daf391b33ef7224c00507a908 diff --git a/.agents/notes/implemented/architecture/2026-07-29-package-regrouping.md b/.agents/notes/implemented/architecture/2026-07-29-package-regrouping.md index 3504208650..52a1fa28e4 100644 --- a/.agents/notes/implemented/architecture/2026-07-29-package-regrouping.md +++ b/.agents/notes/implemented/architecture/2026-07-29-package-regrouping.md @@ -17,7 +17,7 @@ The north star for the regrouping: **closely clustered packages share a group.** ## Decision -Five regrouping decisions remain current; every other group keeps its prior boundary and contents (the dependency analysis confirmed the capability families — `shell/`, `terminal/`, `code-runtime/`, `sandbox/`, `subprocess/`, `fs/`, `lsp/`, `web/`, `skill/`, and the rest — were already drawn correctly). The original sixth decision collected the SDK project initializer, launcher tooling, and runtime JSON-RPC packages under `scaffold/`; [removing that unreleased toolchain](../simplification/2026-08-11-remove-sdk-project-toolchain.md) deleted the project tooling and moved the surviving runtime trio to `sdk/`. The later [repository naming contract](../../proposed/architecture/2026-08-11-repository-naming-contract-and-rename-ledger.md) owns the `shell/`, `terminal/`, and `extensions/` group names and the two package names that this decision deferred. +Five regrouping decisions remain current; every other group keeps its prior boundary and contents (the dependency analysis confirmed the capability families — `shell/`, `terminal/`, `code-runtime/`, `sandbox/`, `subprocess/`, `fs/`, `lsp/`, `web/`, `skill/`, and the rest — were already drawn correctly). The original sixth decision collected the SDK project initializer, launcher tooling, and runtime JSON-RPC packages under `scaffold/`; [removing that unreleased toolchain](../simplification/2026-08-11-remove-sdk-project-toolchain.md) deleted the project tooling and moved the surviving runtime trio to `sdk/`. The later [repository naming contract](2026-08-11-repository-naming-contract-and-rename-ledger.md) owns the `shell/`, `terminal/`, and `extensions/` group names and the two package names that this decision deferred. | Group | Members (folder names) | From | |---|---|---| @@ -37,7 +37,7 @@ Five regrouping decisions remain current; every other group keeps its prior boun ## Later naming decisions -The [repository naming contract](../../proposed/architecture/2026-08-11-repository-naming-contract-and-rename-ledger.md) resolves the two names that this move deliberately deferred. `@deepseek-ai/dsh-sdk-jsonrpc-server` names the JSON-RPC server half of the runtime SDK protocol. `@deepseek-ai/dsh-tool-call-timeout-policy` names the exact operation limited by the policy while keeping its `guard/timeout-policy/` home. Their release-blocking `FIXME` markers are removed with those renames. +The [repository naming contract](2026-08-11-repository-naming-contract-and-rename-ledger.md) resolves the two names that this move deliberately deferred. `@deepseek-ai/dsh-sdk-jsonrpc-server` names the JSON-RPC server half of the runtime SDK protocol. `@deepseek-ai/dsh-tool-call-timeout-policy` names the exact operation limited by the policy while keeping its `guard/timeout-policy/` home. Their release-blocking `FIXME` markers are removed with those renames. ## What the move touched diff --git a/.agents/notes/implemented/architecture/2026-07-29-package-regrouping.zh.md b/.agents/notes/implemented/architecture/2026-07-29-package-regrouping.zh.md index 2dfd7ba854..bef5554466 100644 --- a/.agents/notes/implemented/architecture/2026-07-29-package-regrouping.zh.md +++ b/.agents/notes/implemented/architecture/2026-07-29-package-regrouping.zh.md @@ -17,7 +17,7 @@ Status: implemented ## 决策 -五项重组决策仍然有效;其余每个组都保持先前的边界与内容不变(依赖分析确认各能力家族——`shell/`、`terminal/`、`code-runtime/`、`sandbox/`、`subprocess/`、`fs/`、`lsp/`、`web/`、`skill/` 及其余——本来就划得正确)。原本的第六项决策把 SDK 项目初始化器、启动器工具与运行时 JSON-RPC 包汇集到 `scaffold/`;[移除这套未发布工具链](../simplification/2026-08-11-remove-sdk-project-toolchain.md)的决策删除了项目工具,并将存留的运行时三包移到 `sdk/`。后续的[仓库命名约定](../../proposed/architecture/2026-08-11-repository-naming-contract-and-rename-ledger.md)负责 `shell/`、`terminal/` 与 `extensions/` 组名,以及本决策曾推迟的两个包名。 +五项重组决策仍然有效;其余每个组都保持先前的边界与内容不变(依赖分析确认各能力家族——`shell/`、`terminal/`、`code-runtime/`、`sandbox/`、`subprocess/`、`fs/`、`lsp/`、`web/`、`skill/` 及其余——本来就划得正确)。原本的第六项决策把 SDK 项目初始化器、启动器工具与运行时 JSON-RPC 包汇集到 `scaffold/`;[移除这套未发布工具链](../simplification/2026-08-11-remove-sdk-project-toolchain.md)的决策删除了项目工具,并将存留的运行时三包移到 `sdk/`。后续的[仓库命名约定](2026-08-11-repository-naming-contract-and-rename-ledger.md)负责 `shell/`、`terminal/` 与 `extensions/` 组名,以及本决策曾推迟的两个包名。 | 组 | 成员(目录名) | 来源 | |---|---|---| @@ -37,7 +37,7 @@ Status: implemented ## 后续命名决策 -[仓库命名约定](../../proposed/architecture/2026-08-11-repository-naming-contract-and-rename-ledger.md)解决了本次移动有意推迟的两个名称。`@deepseek-ai/dsh-sdk-jsonrpc-server` 表示运行时 SDK 协议的 JSON-RPC 服务器一侧。`@deepseek-ai/dsh-tool-call-timeout-policy` 准确表示策略所限制的操作,同时保留其 `guard/timeout-policy/` 归属。这些重命名会一并移除阻塞发布的 `FIXME` 标记。 +[仓库命名约定](2026-08-11-repository-naming-contract-and-rename-ledger.md)解决了本次移动有意推迟的两个名称。`@deepseek-ai/dsh-sdk-jsonrpc-server` 表示运行时 SDK 协议的 JSON-RPC 服务器一侧。`@deepseek-ai/dsh-tool-call-timeout-policy` 准确表示策略所限制的操作,同时保留其 `guard/timeout-policy/` 归属。这些重命名会一并移除阻塞发布的 `FIXME` 标记。 ## 移动触及了什么 diff --git a/.agents/notes/implemented/architecture/2026-07-30-config-plane-boundaries.i18n.yaml b/.agents/notes/implemented/architecture/2026-07-30-config-plane-boundaries.i18n.yaml index f11d779582..674bd5bd51 100644 --- a/.agents/notes/implemented/architecture/2026-07-30-config-plane-boundaries.i18n.yaml +++ b/.agents/notes/implemented/architecture/2026-07-30-config-plane-boundaries.i18n.yaml @@ -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 .agents/notes/implemented/architecture/2026-07-30-config-plane-boundaries.md -2026-07-30-config-plane-boundaries.md: 2dfb527749e8dea54e037abc602af1611c3f9794 -2026-07-30-config-plane-boundaries.zh.md: 8b1ec3206237b7c2deafb743b62e697b3c452ffc +2026-07-30-config-plane-boundaries.md: aab0d7a80c2732b33637ec721a9ab7c1b50fce3f +2026-07-30-config-plane-boundaries.zh.md: fb069e6dd9f276c7cc0069695b388ef37a081ab4 diff --git a/.agents/notes/implemented/architecture/2026-07-30-config-plane-boundaries.md b/.agents/notes/implemented/architecture/2026-07-30-config-plane-boundaries.md index 2dfb527749..aab0d7a80c 100644 --- a/.agents/notes/implemented/architecture/2026-07-30-config-plane-boundaries.md +++ b/.agents/notes/implemented/architecture/2026-07-30-config-plane-boundaries.md @@ -6,6 +6,8 @@ English | [中文](2026-07-30-config-plane-boundaries.zh.md) > Scope: boundary hardening of the [web configuration plane](2026-07-30-web-config-plane.md) — which namespaces reach the wire, which callers reach them, and how an editor holding a partial, possibly stale view writes without destroying what it cannot see. +> The caller boundary, the redaction, and the revision fencing remain current. Restricting which namespaces reach the wire to the configurable-provider directory is superseded by the [plugin-owned settings surface](2026-08-12-plugin-owned-settings-surface.md), which serves every registered namespace. + ## Problem The plane worked and was reachable by more callers, and with more authority, than its design claimed. diff --git a/.agents/notes/implemented/architecture/2026-07-30-config-plane-boundaries.zh.md b/.agents/notes/implemented/architecture/2026-07-30-config-plane-boundaries.zh.md index 8b1ec32062..fb069e6dd9 100644 --- a/.agents/notes/implemented/architecture/2026-07-30-config-plane-boundaries.zh.md +++ b/.agents/notes/implemented/architecture/2026-07-30-config-plane-boundaries.zh.md @@ -6,6 +6,8 @@ Status: implemented > 范围:对 [Web 配置面](2026-07-30-web-config-plane.md)的边界加固——哪些 namespace 能抵达协议、哪些调用方能抵达它们,以及一个只持有局部且可能陈旧的视图的编辑器该如何写入,才不会毁掉它看不见的东西。 +> 调用方边界、脱敏与 revision 设栅依然有效。把「哪些 namespace 能抵达协议」限制为可配置提供方目录这一条,已被[由插件自己拥有的设置表层](2026-08-12-plugin-owned-settings-surface.md)取代——后者服务每一个已注册的 namespace。 + ## 问题 这个面能用,但能触达它的调用方、以及它们所拥有的权限,都比设计声称的更多。 diff --git a/.agents/notes/implemented/architecture/2026-07-31-code-runtime-portable-identifier-seam.i18n.yaml b/.agents/notes/implemented/architecture/2026-07-31-code-runtime-portable-identifier-seam.i18n.yaml index 32746bd58f..bcb20fd6c8 100644 --- a/.agents/notes/implemented/architecture/2026-07-31-code-runtime-portable-identifier-seam.i18n.yaml +++ b/.agents/notes/implemented/architecture/2026-07-31-code-runtime-portable-identifier-seam.i18n.yaml @@ -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 .agents/notes/implemented/architecture/2026-07-31-code-runtime-portable-identifier-seam.md -2026-07-31-code-runtime-portable-identifier-seam.md: 7692660c5577a9d647e8c55c8e808c1293d03e4f -2026-07-31-code-runtime-portable-identifier-seam.zh.md: 668fb46a80737d0cbf0ea79e820f1baeb17c4a5c +2026-07-31-code-runtime-portable-identifier-seam.md: 6d75f0b0872a5d4b92403f597f5551276e2d7c9f +2026-07-31-code-runtime-portable-identifier-seam.zh.md: 68515d7a4d9d26d6c510654255d36b615afc2b7d diff --git a/.agents/notes/implemented/architecture/2026-07-31-code-runtime-portable-identifier-seam.md b/.agents/notes/implemented/architecture/2026-07-31-code-runtime-portable-identifier-seam.md index 7692660c55..6d75f0b087 100644 --- a/.agents/notes/implemented/architecture/2026-07-31-code-runtime-portable-identifier-seam.md +++ b/.agents/notes/implemented/architecture/2026-07-31-code-runtime-portable-identifier-seam.md @@ -8,11 +8,11 @@ English | [中文](2026-07-31-code-runtime-portable-identifier-seam.zh.md) The code-runtime seam promises that a binding-namespace list valid on one backend is valid on every backend, so a Code Mode consumer can hand the same bindings to any registered runtime without knowing its language. The first backend, `dsh-code-runtime-worker-thread`, privately owned the identifier rules that enforce part of that promise: an `IDENTIFIER` regex that allowed the JS-only `$`, a `RESERVED_WORDS` set holding only ECMAScript keywords, and a `RESERVED_ERROR_PROPERTIES` set of three JS `Error` slots. Those rules described the worker's own language, not the seam's portability contract. -A second backend written against a different language (CPython) would either re-declare its own rules — letting `lambda` pass the worker and fail Python, or `$tools` pass the worker and fail every non-JS backend — or import the worker's, inverting the dependency so a Service provider reached into a sibling Service provider. Neither keeps the portability promise real: it would hold only for the backend a caller happened to test against. +A second backend written against a different language (CPython) would either re-declare its own rules — letting `lambda` pass the worker and fail Python, or `$tools` pass the worker and fail every non-JS backend — or import the worker's, inverting the dependency so a Service Provider reached into a sibling Service Provider. Neither keeps the portability promise real: it would hold only for the backend a caller happened to test against. ## Decision -The Service Definition package (`@deepseek-ai/dsh-code-runtime`) exports the portable-identifier exclusion contract as four named constants, and every Service provider imports them rather than re-declaring: +The Service Definition package (`@deepseek-ai/dsh-code-runtime`) exports the portable-identifier exclusion contract as four named constants, and every Service Provider imports them rather than re-declaring: - `PORTABLE_RESERVED_WORDS` — the union of ECMAScript and Python reserved words. A namespace global or error-class name matching any is refused on all backends, so `lambda` is refused even though it is a legal JS parameter name. Adding a language widens this union, which is a deliberate breaking review of existing binding names. - `RESERVED_BINDING_GLOBALS` — globals some backend owns in the program's namespace: `console` (the worker's log capture), `__dsh_main__`/`__builtins__`/`__name__` (the Python bootstrap's wrapper and seeded module globals), and `__debug__` (not a seeded slot but a CPython compile-time constant that rejects assignment, so an injected global under that name is unreachable — the same portability split by a different mechanism). Refused everywhere so a namespace list cannot pick a name that works on one backend and collides on another. @@ -21,7 +21,7 @@ The Service Definition package (`@deepseek-ai/dsh-code-runtime`) exports the por The Service Definition also narrows the portable identifier subset to `[A-Za-z_][A-Za-z0-9_]*` (documented on `CodeBindingNamespace.global` and `CodeBindingErrorClass`), dropping the JS-only `$`. The worker consumes the shared constants directly under their exported names — `PORTABLE_RESERVED_WORDS` for both binding-global and error-class names, `RESERVED_BINDING_GLOBALS` for backend-owned slots, `RESERVED_ERROR_MEMBERS` plus `DUNDER_MEMBER` for error members — with no local re-alias; its `IDENTIFIER` regex loses `$`. -The constants live in the Service Definition even though the worker is the only shipped backend: the whole point is that the contract is language-agnostic and owned above any single language. A Service provider that violated it would be the bug, and the shared set is where a reviewer looks to see what "portable" means. +The constants live in the Service Definition even though the worker is the only shipped backend: the whole point is that the contract is language-agnostic and owned above any single language. A Service Provider that violated it would be the bug, and the shared set is where a reviewer looks to see what "portable" means. ## Scope @@ -33,7 +33,7 @@ This decision delivers only the Service Definition extension and the worker's ad **Each backend declares its own exclusions.** Rejected: it makes the portability promise per-backend. A binding list the caller tested on the worker could be refused by Python, which is exactly the split the seam exists to prevent. -**The Python backend imports the worker's constants.** Rejected: it inverts the dependency — the seam's Service providers would reach into a sibling implementation for a contract neither owns. The contract belongs above both, at the seam. +**The Python backend imports the worker's constants.** Rejected: it inverts the dependency — the seam's Service Providers would reach into a sibling implementation for a contract neither owns. The contract belongs above both, at the seam. **Keep `$` in the portable identifier subset.** Rejected: `$` is JS-only spelling. Allowing it would let `$tools` pass the worker and fail every non-JS backend, breaking portability for a purely cosmetic gain. diff --git a/.agents/notes/implemented/architecture/2026-07-31-code-runtime-portable-identifier-seam.zh.md b/.agents/notes/implemented/architecture/2026-07-31-code-runtime-portable-identifier-seam.zh.md index 668fb46a80..68515d7a4d 100644 --- a/.agents/notes/implemented/architecture/2026-07-31-code-runtime-portable-identifier-seam.zh.md +++ b/.agents/notes/implemented/architecture/2026-07-31-code-runtime-portable-identifier-seam.zh.md @@ -8,11 +8,11 @@ Status: implemented code-runtime seam 承诺:在一个后端上有效的绑定命名空间列表,在每个后端上都有效,因此 Code Mode 消费方可以把同一组绑定交给任何已注册的运行时,而不必知道它的语言。首个后端 `dsh-code-runtime-worker-thread` 私自拥有了执行这项承诺一部分的标识符规则:一个允许 JS 专有 `$` 的 `IDENTIFIER` 正则、一个只含 ECMAScript 关键字的 `RESERVED_WORDS` 集合,以及一个含三个 JS `Error` 槽位的 `RESERVED_ERROR_PROPERTIES` 集合。这些规则描述的是 worker 自身的语言,而非 seam 的可移植性约定。 -一个针对不同语言(CPython)编写的第二后端,要么重新声明自己的规则——让 `lambda` 通过 worker 却在 Python 上失败,或让 `$tools` 通过 worker 却在每个非 JS 后端上失败——要么导入 worker 的规则,从而反转依赖,使一个 Service provider 伸手进入另一个兄弟 Service provider。二者都无法让可移植承诺成真:它只对调用方恰好测试过的那个后端成立。 +一个针对不同语言(CPython)编写的第二后端,要么重新声明自己的规则——让 `lambda` 通过 worker 却在 Python 上失败,或让 `$tools` 通过 worker 却在每个非 JS 后端上失败——要么导入 worker 的规则,从而反转依赖,使一个 Service Provider 伸手进入另一个兄弟 Service Provider。二者都无法让可移植承诺成真:它只对调用方恰好测试过的那个后端成立。 ## Decision -Service Definition 包(`@deepseek-ai/dsh-code-runtime`)以四个具名常量导出可移植标识符排除约定,每个 Service provider 导入它们而非重新声明: +Service Definition 包(`@deepseek-ai/dsh-code-runtime`)以四个具名常量导出可移植标识符排除约定,每个 Service Provider 导入它们而非重新声明: - `PORTABLE_RESERVED_WORDS`——ECMAScript 与 Python 保留字的联集。任何命名空间 global 或 error-class 名称匹配其中之一,都在所有后端上被拒绝,因此 `lambda` 即便是合法的 JS 参数名也被拒绝。新增一门语言即扩宽此联集,这是对现有绑定名称的一次有意的破坏性复审。 - `RESERVED_BINDING_GLOBALS`——某个后端在程序命名空间中拥有的 global:`console`(worker 的日志捕获)、`__dsh_main__`/`__builtins__`/`__name__`(Python bootstrap 的包装器与预置模块 global),以及 `__debug__`(不是 seed 的槽位,而是 CPython 编译期常量,赋值会被拒,故以该名注入的 global 不可达——同一种可移植性分裂,只是机制不同)。在所有后端上被拒绝,使命名空间列表无法选到一个在某后端能用、在另一后端冲突的名称。 @@ -21,7 +21,7 @@ Service Definition 包(`@deepseek-ai/dsh-code-runtime`)以四个具名常量 Service Definition 同时把可移植标识符子集收窄为 `[A-Za-z_][A-Za-z0-9_]*`(记录在 `CodeBindingNamespace.global` 与 `CodeBindingErrorClass` 上),去掉 JS 专有的 `$`。worker 直接以这些常量的导出名称消费它们——binding-global 与 error-class 名称用 `PORTABLE_RESERVED_WORDS`、后端拥有槽位用 `RESERVED_BINDING_GLOBALS`、error member 用 `RESERVED_ERROR_MEMBERS` 加 `DUNDER_MEMBER`——不再本地起别名;其 `IDENTIFIER` 正则去掉 `$`。 -尽管 worker 是唯一已交付的后端,这些常量仍置于 Service Definition:要点正是该约定与语言无关,且由高于任何单一语言的层级拥有。违反它的 Service provider 才是 bug,而共享集合正是复审者查看「可移植」含义的地方。 +尽管 worker 是唯一已交付的后端,这些常量仍置于 Service Definition:要点正是该约定与语言无关,且由高于任何单一语言的层级拥有。违反它的 Service Provider 才是 bug,而共享集合正是复审者查看「可移植」含义的地方。 ## Scope @@ -33,7 +33,7 @@ Service Definition 同时把可移植标识符子集收窄为 `[A-Za-z_][A-Za-z0 **每个后端声明自己的排除集。** 拒绝:这让可移植承诺变成逐后端成立。调用方在 worker 上测过的绑定列表可能被 Python 拒绝,而这正是 seam 存在要防止的分裂。 -**Python 后端导入 worker 的常量。** 拒绝:这反转依赖——seam 的 Service provider 会为一个二者都不拥有的约定伸手进入兄弟实现。约定属于二者之上,即 seam。 +**Python 后端导入 worker 的常量。** 拒绝:这反转依赖——seam 的 Service Provider 会为一个二者都不拥有的约定伸手进入兄弟实现。约定属于二者之上,即 seam。 **在可移植标识符子集中保留 `$`。** 拒绝:`$` 是 JS 专有拼写。允许它会让 `$tools` 通过 worker 却在每个非 JS 后端上失败,为纯粹表面的好处破坏可移植性。 diff --git a/.agents/notes/implemented/architecture/2026-08-10-product-subagent-providers-in-shared-host.i18n.yaml b/.agents/notes/implemented/architecture/2026-08-10-product-subagent-providers-in-shared-host.i18n.yaml index b696b46749..205757eacc 100644 --- a/.agents/notes/implemented/architecture/2026-08-10-product-subagent-providers-in-shared-host.i18n.yaml +++ b/.agents/notes/implemented/architecture/2026-08-10-product-subagent-providers-in-shared-host.i18n.yaml @@ -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 .agents/notes/implemented/architecture/2026-08-10-product-subagent-providers-in-shared-host.md -2026-08-10-product-subagent-providers-in-shared-host.md: 33b6eb6cf7a6c19e9ea71cdb7dc8881e8052ef24 -2026-08-10-product-subagent-providers-in-shared-host.zh.md: fd78c7a3fee4e4ee30d27d87c752e1a23576fd85 +2026-08-10-product-subagent-providers-in-shared-host.md: a747d641ae112d114912958c289fe00b592e6ea5 +2026-08-10-product-subagent-providers-in-shared-host.zh.md: fef69e8a2d18135cbc9d5f0d80134fa5701bbbd0 diff --git a/.agents/notes/implemented/architecture/2026-08-10-product-subagent-providers-in-shared-host.md b/.agents/notes/implemented/architecture/2026-08-10-product-subagent-providers-in-shared-host.md index 33b6eb6cf7..a747d641ae 100644 --- a/.agents/notes/implemented/architecture/2026-08-10-product-subagent-providers-in-shared-host.md +++ b/.agents/notes/implemented/architecture/2026-08-10-product-subagent-providers-in-shared-host.md @@ -12,21 +12,21 @@ The placement decision must preserve two independent facts. Loading a provider m ## Decision -Every shipped Profile loads the fixed `codex` and `claude-code` providers once through the base bundle's host plane. Loading either plugin only registers a dormant backend; the corresponding Codex or Claude process starts on the first actual delegation call. Agent Presets independently contribute ordinary `dsh-tool-subagent` rows for `subagent_codex` and `subagent_claude_code`, so a preset can expose neither tool, either one, or both without changing the provider registry. +Product providers remain process-scoped host-plane registrations. The [production-install exclusion decision](../simplification/2026-08-12-production-dsh-excludes-product-subagent-providers.md) supersedes only this note's former base-bundle installation choice: production `dsh-base` neither depends on nor mounts them. A Profile that opts in installs the selected provider package and mounts it once on the host plane. Loading either plugin only registers a dormant backend; the corresponding Codex or Claude process starts on the first actual delegation call. Agent Presets independently contribute ordinary `dsh-tool-subagent` rows for `subagent_codex` and `subagent_claude_code`, so a preset can expose neither tool, either one, or both without changing the provider registry. -This decision supersedes only the opt-in composition placement recorded by the provider-contract note. That note continues to own each product protocol, result mapping, cancellation, process-tree lifecycle, and evidence tiers. The [Agent Preset architecture](2026-08-03-per-session-agent-presets.md) continues to own the Host/Agent split, preset authoring, and the rule that edits affect only newly composed sessions. +This note continues to own why a mounted product provider belongs on the host plane while its model-facing tool belongs to an Agent Preset. The production-install exclusion decision owns which Profiles install those optional packages. The provider-contract note continues to own each product protocol, result mapping, cancellation, process-tree lifecycle, and evidence tiers. The [Agent Preset architecture](2026-08-03-per-session-agent-presets.md) continues to own the Host/Agent split, preset authoring, and the rule that edits affect only newly composed sessions. The providers use products already selected by the host environment. Codex starts `codex` from `PATH`; Claude Code resolves `claude` through the shared subprocess execution world and passes the exact path to the official SDK. Profile loading does not install a product, create product state, probe a version, test authentication, or add product-specific settings. Missing commands and product failures remain local to the attempted delegation. -The current base dependency closure still includes the Claude Agent SDK's optional platform CLI payload even though production resolves the host `claude`. Removing that unused payload belongs to the separate product installation-closure follow-up; this placement decision neither installs it dynamically nor treats it as the production executable. +Only a Profile that selects the Claude Code provider carries the Claude Agent SDK's optional platform CLI payload. Production still resolves the host `claude`; the SDK payload remains provider-package installation cost rather than the production executable. ## Verification -The base Loader test proves both provider names register exactly once and no product process starts during Profile boot. Real Agent Preset composition covers none, Codex-only, Claude-only, and both tool sets, including generation isolation after an authored preset changes. Keyless ACP snapshots pin the model-visible tool schemas for one and both products, while provider tests separately prove native executable resolution, failure, cancellation, and process-tree quiescence. +The base bundle test proves production `dsh-base` contains neither product provider dependency nor provider row. The Web composition explicitly mounts both optional providers and covers none, Codex-only, Claude-only, and both tool sets, including generation isolation after an authored preset changes. Package-owned Loader compositions prove the Codex-only and dual-provider opt-in paths register the selected providers without starting a product process. Keyless ACP snapshots pin the model-visible tool schemas for one and both products, while provider tests separately prove native executable resolution, failure, cancellation, and process-tree quiescence. ## Alternatives considered -**Keep product providers opt-in at the Profile layer.** This preserves a smaller default dependency closure, but a copied or agent-authored Preset row is not usable unless the person also discovers and edits a second composition layer. It leaves the general Preset entry incomplete for these otherwise ordinary tools. +**Keep product providers opt-in at the Profile layer.** This preserves a smaller default dependency closure but requires the user to edit both a Profile and a Preset. The production-install exclusion decision accepts that installation trade-off; this note retains the requirement that any selected provider is mounted once on the host plane rather than inside the preset. **Store global or per-Profile product enable switches.** A process switch competes with the Preset as owner of model-visible tools and cannot express two sessions using different combinations. Availability and authentication are deployment facts, not another persisted product state. @@ -36,6 +36,6 @@ The base Loader test proves both provider names register exactly once and no pro ## Consequences -A user manages both products through the same Agent Preset authoring path as other plugins, and each new session receives exactly the tools its chosen preset contributes. Every Profile carries two dormant provider registrations, so unused products consume package and module-loading footprint but no product process, login, model call, or product home. +A user installs each selected product provider in a Profile and exposes its tool through the same Agent Preset authoring path as other plugins. Each new session receives exactly the tools its chosen preset contributes. Profiles that do not select a product provider carry no corresponding package or module-loading footprint; loading a selected provider still starts no product process, login, model call, or product home. -The Host registry remains the single provider authority and each Preset remains the single model-tool authority. The trade-off is the current Claude SDK optional-payload installation cost, which stays explicitly deferred rather than being hidden behind another enable state or installer lifecycle. +The Host registry remains the single provider authority and each Preset remains the single model-tool authority. The trade-off is a two-layer opt-in: the Profile owns installation and host-plane registration, while the Preset owns per-agent exposure. Selecting the Claude provider also accepts its current SDK optional-payload installation cost. diff --git a/.agents/notes/implemented/architecture/2026-08-10-product-subagent-providers-in-shared-host.zh.md b/.agents/notes/implemented/architecture/2026-08-10-product-subagent-providers-in-shared-host.zh.md index fd78c7a3fe..fef69e8a2d 100644 --- a/.agents/notes/implemented/architecture/2026-08-10-product-subagent-providers-in-shared-host.zh.md +++ b/.agents/notes/implemented/architecture/2026-08-10-product-subagent-providers-in-shared-host.zh.md @@ -12,21 +12,21 @@ Status: implemented ## 决策 -每个随发行版交付的 Profile 都会通过 base 组合包的宿主平面,把固定的 `codex` 与 `claude-code` 提供方各加载一次。加载任一插件只会注册一个休眠后端;对应的 Codex 或 Claude 进程直到第一次实际委派调用时才启动。Agent Preset 分别通过普通的 `dsh-tool-subagent` 行贡献 `subagent_codex` 与 `subagent_claude_code`,因此一个 preset 可以不暴露任何工具、只暴露其中一个或同时暴露两者,而无需更改提供方注册表。 +产品提供方仍是进程级的 host plane(宿主平面)注册。[生产安装排除决策](../simplification/2026-08-12-production-dsh-excludes-product-subagent-providers.md)只取代本说明原先由 base bundle 安装提供方的选择:生产 `dsh-base` 既不依赖也不挂载它们。选择产品集成的 Profile 会安装目标提供方包,并在 host plane 挂载一次。加载任一插件只会注册一个休眠后端;对应的 Codex 或 Claude 进程直到第一次实际委派调用时才启动。Agent Preset 分别通过普通的 `dsh-tool-subagent` 行贡献 `subagent_codex` 与 `subagent_claude_code`,因此一个 preset 可以不暴露任何工具、只暴露其中一个或同时暴露两者,而无需更改提供方注册表。 -本决策仅取代提供方约定说明所记录的、原先由用户选择启用的组装位置。该说明仍负责每个产品的协议、结果映射、取消、进程树生命周期与证据层级。[Agent Preset 架构](2026-08-03-per-session-agent-presets.md)仍负责宿主与 agent 的划分、preset 创作,以及改动只影响新组装会话的规则。 +本说明继续负责解释为什么已经挂载的产品提供方属于 host plane,而面向模型的工具属于 Agent Preset。生产安装排除决策负责哪些 Profile 安装这些可选包。提供方约定说明继续负责每个产品的协议、结果映射、取消、进程树生命周期与证据层级。[Agent Preset 架构](2026-08-03-per-session-agent-presets.md)仍负责宿主与 agent 的划分、preset 创作,以及改动只影响新组装会话的规则。 这些提供方使用宿主环境已经选定的产品。Codex 启动 `codex`,该命令从 `PATH` 解析;Claude Code 通过共享的子进程执行世界解析 `claude`,并把确切路径交给官方 SDK。加载 Profile 不会安装产品、创建产品状态、探测版本、测试身份验证,也不会新增产品专属设置。命令缺失和产品故障仍局限于发生问题的那次委派。 -当前 base 依赖闭包仍包含 Claude Agent SDK 的可选平台 CLI(命令行界面)载荷,尽管生产环境解析的是宿主提供的 `claude`。移除这份未使用载荷属于独立的产品安装闭包后续项;本归属决策既不会动态安装它,也不会将它当作生产可执行文件。 +只有选择 Claude Code 提供方的 Profile 才会携带 Claude Agent SDK 的可选平台 CLI(命令行界面)载荷。生产环境仍解析宿主提供的 `claude`;这份 SDK 载荷是提供方包的安装成本,而不是生产可执行文件。 ## 验证 -base Loader 测试证明两个提供方名称都恰好注册一次,而且 Profile 启动期间不会启动产品进程。真实 Agent Preset 组装覆盖不暴露任何工具、仅暴露 Codex、仅暴露 Claude 和同时暴露两者这四种工具集合,也覆盖自行创作的 preset 发生改动后的代际隔离。无密钥 ACP(Agent Client Protocol)快照固定单个产品与两个产品同时启用时的模型可见工具 schema,提供方测试则另行证明原生可执行文件解析、失败、取消和进程树完全停稳。 +base bundle 测试证明生产 `dsh-base` 既不包含产品提供方依赖,也不包含提供方配置行。Web 组装显式挂载两个可选提供方,并覆盖不暴露任何工具、仅暴露 Codex、仅暴露 Claude 和同时暴露两者这四种工具集合,也覆盖自行创作的 preset 发生改动后的代际隔离。由包负责的 Loader 组装证明 Codex-only 与双提供方按需启用路径会注册选中的提供方,而不会启动产品进程。无密钥 ACP(Agent Client Protocol)快照固定单个产品与两个产品同时启用时的模型可见工具 schema,提供方测试则另行证明原生可执行文件解析、失败、取消和进程树完全停稳。 ## 考虑过的替代方案 -**将产品提供方保留为 Profile 层的按需启用项。** 这样可缩小默认依赖闭包,但复制或由 agent 创作的 Preset 行无法直接使用,除非用户还发现并编辑第二个组装层。对于这些本来与其他工具无异的工具,通用 Preset 入口仍不完整。 +**将产品提供方保留为 Profile 层的按需启用项。** 这样可缩小默认依赖闭包,但要求用户同时编辑 Profile 与 Preset。生产安装排除决策接受这项安装取舍;本说明保留的要求是,任何被选中的提供方都在 host plane 挂载一次,而不是放入 preset。 **存储全局或按 Profile 配置的产品启用开关。** 进程级开关会与 Preset 争夺模型可见工具的责任归属,也无法表示两个会话使用不同组合。可用性与身份验证属于部署事实,并非另一份需要持久化的产品状态。 @@ -36,6 +36,6 @@ base Loader 测试证明两个提供方名称都恰好注册一次,而且 Prof ## 后果 -用户通过与其他插件相同的 Agent Preset 创作路径管理两个产品,每个新会话只会获得其所选 preset 所贡献的工具。每个 Profile 都携带两个休眠的提供方注册,因此未使用的产品会产生包和模块加载开销,但不会启动产品进程、登录、调用模型或创建产品主目录。 +用户在 Profile 中安装每个被选中的产品提供方,再通过与其他插件相同的 Agent Preset 创作路径暴露它的工具。每个新会话只会获得其所选 preset 所贡献的工具。没有选择产品提供方的 Profile 不承担对应包或模块的加载开销;加载已选择的提供方仍不会启动产品进程、登录、调用模型或创建产品主目录。 -宿主注册表仍是提供方的唯一权威,每个 Preset 仍是模型工具的唯一权威。代价是当前 Claude SDK 可选载荷的安装成本继续被明确延期处理,而不会隐藏在另一种启用状态或安装程序生命周期之后。 +宿主注册表仍是提供方的唯一权威,每个 Preset 仍是模型工具的唯一权威。代价是两层按需启用:Profile 负责安装与 host plane 注册,Preset 负责按 agent 暴露。选择 Claude 提供方还会接受当前 SDK 可选载荷的安装成本。 diff --git a/.agents/notes/proposed/architecture/2026-08-11-repository-naming-contract-and-rename-ledger.i18n.yaml b/.agents/notes/implemented/architecture/2026-08-11-repository-naming-contract-and-rename-ledger.i18n.yaml similarity index 51% rename from .agents/notes/proposed/architecture/2026-08-11-repository-naming-contract-and-rename-ledger.i18n.yaml rename to .agents/notes/implemented/architecture/2026-08-11-repository-naming-contract-and-rename-ledger.i18n.yaml index 36e8bb9536..d683f9cea6 100644 --- a/.agents/notes/proposed/architecture/2026-08-11-repository-naming-contract-and-rename-ledger.i18n.yaml +++ b/.agents/notes/implemented/architecture/2026-08-11-repository-naming-contract-and-rename-ledger.i18n.yaml @@ -1,6 +1,6 @@ # Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each # 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 .agents/notes/proposed/architecture/2026-08-11-repository-naming-contract-and-rename-ledger.md -2026-08-11-repository-naming-contract-and-rename-ledger.md: ad5a2061c40011b3f8c32ecbb62a0b545f82f9f6 -2026-08-11-repository-naming-contract-and-rename-ledger.zh.md: 8f1b3505f0cc16a6e3e6429b5924cabda231f00f +# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-08-11-repository-naming-contract-and-rename-ledger.md +2026-08-11-repository-naming-contract-and-rename-ledger.md: 895a202256504690b0451e6c09f3fc4ea8e7f4db +2026-08-11-repository-naming-contract-and-rename-ledger.zh.md: 897d06d95b3a05fb53d36146fe1ac1f0e1330a7a diff --git a/.agents/notes/proposed/architecture/2026-08-11-repository-naming-contract-and-rename-ledger.md b/.agents/notes/implemented/architecture/2026-08-11-repository-naming-contract-and-rename-ledger.md similarity index 87% rename from .agents/notes/proposed/architecture/2026-08-11-repository-naming-contract-and-rename-ledger.md rename to .agents/notes/implemented/architecture/2026-08-11-repository-naming-contract-and-rename-ledger.md index ad5a2061c4..895a202256 100644 --- a/.agents/notes/proposed/architecture/2026-08-11-repository-naming-contract-and-rename-ledger.md +++ b/.agents/notes/implemented/architecture/2026-08-11-repository-naming-contract-and-rename-ledger.md @@ -1,34 +1,34 @@ # Agent Note: Repository naming contract and pre-release rename ledger -Status: proposed +Status: implemented English | [中文](2026-08-11-repository-naming-contract-and-rename-ledger.zh.md) ## Problem -The repository has grown faster than some names. Several package names still describe the first implementation instead of the capability. Several classes use `Service` even when they are registries, runtimes, engines, controllers, or resolvers. Some `ctx` keys are singular for registries and plural for one engine. Some provider names say `local` when they use replaceable filesystem or subprocess services and can run in another execution world. +The repository had grown faster than some names. Several package names described the first implementation instead of the capability. Several classes used `Service` even when they were registries, runtimes, engines, controllers, or resolvers. Some `ctx` keys were singular for registries and plural for one engine. Some provider names said `local` even though they used replaceable filesystem or subprocess services and could run in another execution world. These names are not harmless. A name tells a contributor where a responsibility starts and stops. `Store` suggests data access. `Registry` suggests registrations and lookup. `Runtime` suggests live execution and lifecycle. When one word is used for all three, callers cannot tell which object owns policy, work, or state without reading the implementation. -The repository also uses `SDK` in two meanings. The supported Python and TypeScript clients use the JSON-RPC SDK protocol. The project as a whole is DeepSeek Harness, not an SDK project. The removed SDK project toolchain made the broad meaning obsolete, but current prose and names still preserve parts of it. +The repository also used `SDK` in two meanings. The supported Python and TypeScript clients use the JSON-RPC SDK protocol. The project as a whole is DeepSeek Harness, not an SDK project. The removed SDK project toolchain made the broad meaning obsolete, but prose and names preserved parts of it. -This is the last pre-release point at which repository-wide renames are cheap. Keeping weak names would turn accidental vocabulary into a compatibility contract. +The last pre-release window made repository-wide renames cheap. Keeping weak names would have turned accidental vocabulary into a compatibility contract. -## Proposal +## Decision -Apply the rename ledger in this note before the first tagged release. Change names only. Do not change package responsibilities, service boundaries, behavior, defaults, or data models in a rename change. If a name exposes a bad boundary, write a separate proposed Agent Note for that boundary change. +The repository uses every current name in this ledger. This decision changes names only; package responsibilities, service boundaries, behavior, defaults, and data models stay the same. A name that exposes a bad boundary requires a separate proposed Agent Note for that boundary change. -Each accepted family rename is atomic. Update its directory, npm package name, imports, Cordis plugin name, `ctx` key, public types, directly coupled event or tool identifiers, configuration, tests, fixtures, examples, generated references, and current documentation where the ledger names those surfaces. Do not leave an alias, compatibility package, duplicate service key, dual event name, or fallback parser. The repository is pre-release and rejects the old name. +Each renamed family has one vocabulary. Its directory, npm package name, imports, Cordis plugin name, `ctx` key, public types, directly coupled event or tool identifiers, configuration, tests, fixtures, examples, generated references, and current documentation use the current name where the ledger names those interfaces. No alias, compatibility package, duplicate service key, dual event name, or fallback parser remains. The repository rejects the old name. -Implementation can use more than one PR to keep review practical. One PR must not leave one family with two public vocabularies. The final state must satisfy the complete ledger. +No family exposes two public vocabularies. ### Use `SDK` for one thing -`SDK` means the JSON-RPC-based client/server protocol used by the supported Python and TypeScript SDKs. Keep `@deepseek-ai/dsh-sdk-client`, `@deepseek-ai/dsh-sdk-protocol`, and the wire identity `deepseek-harness-sdk-runtime`. Rename the JSON-RPC server into that family. Do not call DeepSeek Harness itself an SDK, and do not restore the removed project generator, launcher, helper, or launcher telemetry packages. +`SDK` means the JSON-RPC-based client/server protocol used by the supported Python and TypeScript SDKs. The repository keeps `@deepseek-ai/dsh-sdk-client`, `@deepseek-ai/dsh-sdk-protocol`, and the wire identity `deepseek-harness-sdk-runtime`; the JSON-RPC server belongs to the same family. DeepSeek Harness itself is not an SDK, and the removed project generator, launcher, helper, and launcher telemetry packages stay absent. -If accepted, this proposal will partially supersede three active decisions. It replaces the retained `bash/`, `pty/`, and `self-modification/` group names and both deferred package targets in the [package-regrouping decision](../../implemented/architecture/2026-07-29-package-regrouping.md). It replaces only the repository-wide SDK claim in the [SDK project toolchain removal](../../implemented/simplification/2026-08-11-remove-sdk-project-toolchain.md), which remains the owner of the deletion and the surviving runtime SDK. It replaces only the package-name rationale in the [tool-call timeout policy](../../implemented/architecture/2026-07-07-tool-call-timeout-policy.md); the timeout mechanism and its `guard/timeout-policy/` home remain unchanged. +This decision partially supersedes three active decisions. It replaces the retained `bash/`, `pty/`, and `self-modification/` group names and both deferred package targets in the [package-regrouping decision](2026-07-29-package-regrouping.md). It replaces only the repository-wide SDK claim in the [SDK project toolchain removal](../simplification/2026-08-11-remove-sdk-project-toolchain.md), which remains the owner of the deletion and the surviving runtime SDK. It replaces only the package-name rationale in the [tool-call timeout policy](2026-07-07-tool-call-timeout-policy.md); the timeout mechanism and its `guard/timeout-policy/` home remain unchanged. -Other implemented notes that use a renamed package, path, or type are not superseded when their boundary and rationale remain intact. The implementation updates those factual names. It adds reciprocal links only where this proposal changes a decision; a proposal does not make current implemented notes describe unshipped names. +Other implemented notes that use a renamed package, path, or type are not superseded when their boundary and rationale remain intact. They carry the current factual names. The three partially superseded decisions link back to this decision. ### Name the role that exists @@ -68,7 +68,7 @@ The practical tests are direct. If callers mainly call `register()` and receive Keep a protocol or dialect name when it distinguishes implementations. Keep `Bash`, `Pwsh`, `JSON-RPC`, `SQLite`, `JSONL`, `OpenTelemetry`, `Claude Code`, and `E2B` where the implementation depends on that mechanism. Do not put `LLM` into a compaction backend name when every current backend already uses the LLM seam; `basic` is the honest neutral name until a more specific algorithm name exists. -Do not invent a `process sandbox` concept. The current `sandbox` family already names its product responsibility, and the accepted sweep does not change that boundary. +Do not invent a `process sandbox` concept. The current `sandbox` family already names its product responsibility. This decision does not change that responsibility. Use title case for initialisms inside PascalCase identifiers: `Ui`, `Llm`, `JsonRpc`, and `ApiProxy`. Use the conventional uppercase form in prose and package names where applicable: UI, LLM, JSON-RPC, and API. `Typert` is the exact product spelling in identifiers and prose; do not write `TypeRT`, `TypeRt`, or `Typert` with another internal split. @@ -76,15 +76,15 @@ Do not remove an intentional vendor qualifier to avoid repetition. `dsh-subagent ### Put the rule in project documentation -When the rename implementation lands, add the full role-word contract to the paired package-creation guide at `docs/cookbook/adding-a-package.md`. Add a short linked rule to `packages/AGENTS.md`. Update the terminology table and the root project description so `SDK` and `Typert` have one meaning. The Agent Note owns the rationale and rejected alternatives; the guide owns the rule contributors follow. +The paired package-creation guide at `docs/cookbook/adding-a-package.md` contains the full role-word contract, and `packages/AGENTS.md` links to it. The terminology table and root project description give `SDK` and `Typert` one meaning. This Agent Note owns the rationale and rejected alternatives; the guide owns the rule contributors follow. ## Rename ledger -The tables list public and repository-wide names. Private local variables follow the new vocabulary when they refer to the same role. A retained low-level or product-visible name is stated where a broad replacement would be wrong. +The tables record public and repository-wide renames. The `Current` column holds the current name. Private local variables use the same vocabulary when they refer to the same role. A retained low-level or product-visible name is stated where a broad replacement would be wrong. ### Runtime SDK -| Current | Proposed | Reason | +| Former | Current | Reason | |---|---|---| | `@deepseek-ai/dsh-jsonrpc` | `@deepseek-ai/dsh-sdk-jsonrpc-server` | It is the server half of the SDK protocol. `jsonrpc` alone names an encoding; `sdk-jsonrpc-server` gives the family, mechanism, and role. | | `HarnessSdkServer` | `HarnessSdkJsonRpcServer` | The class is one JSON-RPC server implementation, not every possible SDK server. | @@ -93,7 +93,7 @@ Keep `@deepseek-ai/dsh-sdk-client`, `@deepseek-ai/dsh-sdk-protocol`, and `deepse ### Shell and terminal -| Current | Proposed | Reason | +| Former | Current | Reason | |---|---|---| | `packages/bash/` | `packages/shell/` | The group contains the dialect-neutral executor seam, Bash and PowerShell implementations, environment support, and shell tools. | | `@deepseek-ai/dsh-bash`, `ctx.bash` | `@deepseek-ai/dsh-shell`, `ctx.shell` | PowerShell already implements this seam. The capability is shell execution, not Bash. | @@ -113,7 +113,7 @@ Keep the Bash- and PowerShell-specific leaf packages, plugin ids, types, and too ### Language server and jobs -| Current | Proposed | Reason | +| Former | Current | Reason | |---|---|---| | `@deepseek-ai/dsh-lsp-local` | `@deepseek-ai/dsh-lsp-stdio` | The provider speaks LSP over stdio through replaceable filesystem and subprocess services. It is not necessarily local. | | `packages/tasks/` | `packages/jobs/` | The family owns detached tool jobs. `jobs` is short and avoids collision with user task or todo concepts. | @@ -131,7 +131,7 @@ Keep the base LSP package, `ctx.lsp`, LSP protocol types, and the LSP tool. The ### Input triggers, tool presentation, permission presets, and user questions -| Current | Proposed | Reason | +| Former | Current | Reason | |---|---|---| | `@deepseek-ai/dsh-client-ui-slash`, `ui-slash/` | `@deepseek-ai/dsh-client-ui-input-trigger`, `ui-input-trigger/` | The client handles `/`, `@`, keyboard arbitration, candidate menus, and programmatic launch. It is not only slash commands. | | `ctx.slash`, `SlashService`, `SlashController`, `SlashSource` | `ctx.inputTriggers`, `InputTriggerService`, `InputTriggerController`, `InputTriggerSource` | The names cover every supported trigger and keep the existing service, controller, and source roles. Coupled locale and public type names follow `InputTrigger`. | @@ -144,11 +144,11 @@ Keep the base LSP package, `ctx.lsp`, LSP protocol types, and the LSP tool. The | `ctx.userInteraction`, `UserInteractionService`, `UserInteractionProvider`, `UserInteractionError` | `ctx.userQuestions`, `UserQuestionService`, `UserQuestionProvider`, `UserQuestionError` | These names state the one supported interaction form. Keep `AskUserQuestion*`, the `ask_user_question` tool, and `@deepseek-ai/dsh-tool-ask-user`. | | `docs/subsystems/user-interaction.md` | `docs/subsystems/user-questions.md` | The page documents questions and answers only. | -Keep `/permission`, the `permissions` projection, the `permission` settings namespace, and `permission/preset`; they are accurate product or durable vocabulary. Keep the full `PermissionPresetSettingsController` name. Dropping `Preset` would remove the word that limits its authority. Plan a separate proposal to remove the `both` tool-presentation mode; this rename does not remove behavior. +Keep `/permission`, the `permissions` projection, the `permission` settings namespace, and `permission/preset`; they are accurate product or durable vocabulary. Keep the full `PermissionPresetSettingsController` name. Dropping `Preset` would remove the word that limits its authority. Removal of the `both` tool-presentation mode remains deferred to a separate proposal; this rename does not remove behavior. ### Typert, API gateway, and tools -| Current | Proposed | Reason | +| Former | Current | Reason | |---|---|---| | `packages/typert/type-meta/`, `@deepseek-ai/dsh-type-meta` | `typert/protocol/`, `@deepseek-ai/dsh-typert-protocol` | The package owns the Typert Remote protocol, decorators, bindings, codecs, lookups, and context contracts. It is not generic type metadata. | | `GatewayService` in the protocol package | `TypertRemoteService` | The base class marks a same-process service for Remote export. It is not the API gateway. | @@ -162,7 +162,7 @@ Keep `@deepseek-ai/dsh-tools` and `ctx.tools`. Keep `@deepseek-ai/dsh-api-gatewa ### Workspace instructions, telemetry, identity, and launch environment -| Current | Proposed | Reason | +| Former | Current | Reason | |---|---|---| | Host `ctx.workspace` | Host `ctx.workspaceRegistry` | `WorkspaceRegistry` owns multiple workspaces, but Client `ctx.workspaces` already has an incompatible type. Both declarations merge into the same Cordis `Context` interface at compile time even though their runtime contexts are separate. The role suffix states the host service and avoids that collision. Keep `@deepseek-ai/dsh-workspace`, `WorkspaceRegistry`, `Workspace`, and `workspace.*` wire names. | | `@deepseek-ai/dsh-workspace-context`, `context/workspace-context/` | `@deepseek-ai/dsh-agent-instructions`, `context/agent-instructions/` | The package loads hierarchical `AGENTS.md` and `CLAUDE.md` files for the agent. It is not general workspace context. | @@ -181,7 +181,7 @@ Keep `@deepseek-ai/dsh-tools` and `ctx.tools`. Keep `@deepseek-ai/dsh-api-gatewa ### Schedule, workflow, goals, and compaction -| Current | Proposed | Reason | +| Former | Current | Reason | |---|---|---| | `@deepseek-ai/dsh-tool-schedule`, `schedule/tool-schedule/`, plugin `tool-schedule` | `@deepseek-ai/dsh-schedule`, `schedule/schedule/`, plugin `schedule` | The package owns the durable Schedule domain, persistence barriers, management tools, timers, follow-ups, and runtime lifecycle. `tool-` describes only one part. | | `ScheduleOwner` | `ScheduleRuntime` | The per-agent object runs live timers, durable projection, dispatch, idle waits, and disposal. `Owner` does not state that execution role. Coupled private `owner*` names follow `runtime*`. | @@ -194,11 +194,11 @@ Keep `@deepseek-ai/dsh-tools` and `ctx.tools`. Keep `@deepseek-ai/dsh-api-gatewa | `@deepseek-ai/dsh-compact-basic`, `BasicCompactService`, public `BasicCompact*` | `@deepseek-ai/dsh-compaction-basic`, `BasicCompactionEngine`, corresponding `BasicCompaction*` | `basic` is plain but honest. `compaction-llm` adds no information because LLM use is already part of the current implementation family. | | `@deepseek-ai/dsh-compact-tool-result-prune`, `ToolResultPruneService`, `ctx.toolResultPrune` | `@deepseek-ai/dsh-compaction-tool-result-pruner`, `ToolResultPruner`, `ctx.toolResultPruner` | The plugin is an actor that prunes tool results. The noun `pruner` names that role. | -Keep `/compact`, the command package, and the rejected decision to preserve separate compaction definition and provider packages. The rename changes vocabulary, not that package boundary. +Keep `/compact`, the command package, and the separate compaction definition and provider packages. Merging those packages remains rejected. The rename changes vocabulary, not that package boundary. ### Settings, credentials, client modules, and small core roles -| Current | Proposed | Reason | +| Former | Current | Reason | |---|---|---| | Abstract `Settings` | `SettingsProvider` | The class supplies settings through a replaceable capability. Keep the package, key, and events. | | `@deepseek-ai/dsh-settings-local`, `SettingsLocal` | `@deepseek-ai/dsh-settings-file`, `FileSettingsProvider` | The implementation is file-backed through the filesystem seam. `file` states the mechanism; `local` does not. | @@ -216,7 +216,7 @@ Keep `/compact`, the command package, and the rejected decision to preserve sepa ### Host web server, session data, and code execution -| Current | Proposed | Reason | +| Former | Current | Reason | |---|---|---| | `HttpServerService`, `ctx.httpServer` | `WebServer`, `ctx.webServer` | The server owns HTTP routes and WebSocket upgrade routes. `Web` leaves room for both; `Http` is too narrow here. Keep `packages/host/webserver`, `@deepseek-ai/dsh-host-webserver`, `WebRoute`, and `WebUpgradeRoute`. | | Documentation subsystem label `http-server` | `web-server` | The subsystem must use the same scope as the service. | @@ -233,7 +233,7 @@ Keep the complete session projection family and `SessionProjection*` vocabulary. ### Filesystem, skill, subagent, and web providers -| Current | Proposed | Reason | +| Former | Current | Reason | |---|---|---| | `@deepseek-ai/dsh-fs-policy` | `@deepseek-ai/dsh-fs-observation-policy` | The package defines which filesystem observations authorize later effects. It is not the complete filesystem or sandbox policy. | | `FsPolicyExec` | `FsObservationActor` | The value names the actor whose observations and effects the policy relates. It does not execute the policy itself. | @@ -251,7 +251,7 @@ Keep `@deepseek-ai/dsh-subagent-dsh-sdk`, its provider id `dsh-sdk`, external AC ### Hooks, guards, plan mode, extensions, and diagnostics -| Current | Proposed | Reason | +| Former | Current | Reason | |---|---|---| | `@deepseek-ai/dsh-hooks-claude`, `ClaudeHookConfig`, `parseClaudeConfig`, dialect `claude` | `@deepseek-ai/dsh-hooks-claude-code`, `ClaudeCodeHookConfig`, `parseClaudeCodeConfig`, dialect `claude-code` | The hook bridge targets Claude Code, not every Anthropic or Claude product. | | `@deepseek-ai/dsh-repeat-tool-guard`, plugin/source `repeat-tool-guard` | `@deepseek-ai/dsh-repeat-tool-reminder`, plugin/source `repeat-tool-reminder` | The plugin adds a model reminder. It does not block or enforce a guard decision. | @@ -263,11 +263,11 @@ Keep `@deepseek-ai/dsh-subagent-dsh-sdk`, its provider id `dsh-sdk`, external AC | `InvariantService` | `InvariantRegistry` | The object owns registered invariant checks. Keep `@deepseek-ai/dsh-invariants` and `ctx.invariants`. | | `packages/client/test-runtime/` | `packages/test-support/client-runtime/` | The package is client test infrastructure. Keep its npm name if it already states that contract. | -Keep MCP, Todo, and the Plan Mode package, key, events, and tool names. The accepted change concerns the controller class, not the product feature. +Keep MCP, Todo, and the Plan Mode package, key, events, and tool names. This decision renames the controller class, not the product feature. ### Utilities, E2B, host, bundles, examples, and applications -| Current | Proposed | Reason | +| Former | Current | Reason | |---|---|---| | `util/paths/`, `@deepseek-ai/dsh-paths` | `util/home-paths/`, `@deepseek-ai/dsh-home-paths` | The helpers resolve paths under the Harness home. They are not a general path library. Keep the individual function names when they already state the returned path. | | `util/retention/`, `@deepseek-ai/dsh-retention` | `util/output-retention/`, `@deepseek-ai/dsh-output-retention` | The policy retains command and tool output. It is not a general data-retention framework. | @@ -281,7 +281,7 @@ Keep atomic-write, brand, native-command, timeout utility, directory-picker, `ds ### Client runtime and UI -| Current | Proposed | Reason | +| Former | Current | Reason | |---|---|---| | `SlotsService` | `SlotRegistry` | The object owns named slot declarations and registrations. | | `SessionsService` | `SessionRuntime` | The object owns live client session coordination, not a passive session list. | @@ -365,26 +365,22 @@ The following debated names stay unchanged because the current scope is accurate **Keep aliases for old names.** Rejected. No released consumer needs them. Aliases would preserve two vocabularies and make the first release carry a migration that never had a user. -## Acceptance criteria +## Verification -- Every mapping in the ledger is applied, or this proposal is amended before implementation to explain a changed decision. -- Each family has one public vocabulary. No compatibility package, re-export alias, duplicate `ctx` key within one Cordis context, dual plugin id, dual event id, old tool alias, or fallback parser remains. -- The change is rename-only. Runtime behavior, package boundaries, defaults, policy, durable semantics, and model behavior stay equivalent except where an identifier is itself visible. -- Package directories, npm names, imports, manifests, TypeScript references and paths, Cordis config, plugin ids, service keys, events, tools, RPC names, persisted names named by the ledger, fixtures, snapshots, examples, generated catalogs, and current prose agree with the new vocabulary. -- Current implemented Agent Notes are updated with factual name and path changes when the implementation lands. The package-regrouping note records the new group inventory and package targets, the SDK removal note does not call the repository an SDK, and the timeout-policy note records the new package-name rationale. Notes whose architectural decision remains current are not rewritten into new decisions. +- Every mapping in the ledger appears in the repository. Each family has one public vocabulary; no compatibility package, re-export alias, duplicate `ctx` key within one Cordis context, dual plugin id, dual event id, old tool alias, or fallback parser remains. +- Runtime behavior, package boundaries, defaults, policy, durable semantics, and model behavior remain equivalent except where an identifier is itself visible. +- Package directories, npm names, imports, manifests, TypeScript references and paths, Cordis config, plugin ids, service keys, events, tools, RPC names, persisted names named by the ledger, fixtures, snapshots, examples, generated catalogs, and current prose use the current vocabulary. +- Current implemented Agent Notes carry the factual name and path changes. The package-regrouping note records the group inventory and package targets, the SDK removal note reserves `SDK` for the runtime protocol, and the timeout-policy note records the package-name rationale. - The paired package-creation guide contains the role-word contract, `packages/AGENTS.md` links to it, the terminology table records the chosen words and `Typert` spelling, and root project prose calls the product DeepSeek Harness rather than DeepSeek Harness SDK. - The removed SDK project toolchain stays absent. -- Focused tests cover each renamed family; source-plane typecheck, build, package hygiene, generated-reference gates, snapshots affected by visible identifiers, translation pairing, `doc-sync`, and lint pass on the complete implementation. -- The proposed note moves to `implemented/` only after the full ledger and documentation contract are true. Its implementation form describes the final state, not a migration checklist. +- `pnpm run check:ci` covers source-plane typecheck, build, package hygiene, generated-reference checks, affected snapshots, translation pairing, `doc-sync`, and lint. Release-shaped Python runtime smokes and required CI cover packaged-runtime and platform paths. -## Risks +## Consequences -The sweep changes many imports, paths, configuration strings, generated references, and model-visible names. A missed string can compile but fail at load or replay time. Implementation must use both type-directed edits and exact old-name searches across source, config, tests, fixtures, docs, and generated inputs. +The repository has one vocabulary for each renamed family. Old on-disk names, wire values, tool names, and configuration entries named in the ledger do not work. An owning parser that can identify stale configuration fails clearly instead of accepting both forms. -Concurrent work will conflict with moved paths and renamed symbols. This is temporary pre-release cost. Splitting the implementation by coherent family can reduce review and merge conflicts, but each family must remain atomic. +Some names are longer. The extra word is intentional when it prevents a false claim about authority or mechanism. A long name remains wrong when every word does not constrain the role. -Some names will become longer. The extra word is intentional when it prevents a false claim about authority or mechanism. Long names are still a failure when every word does not constrain the role. +Role suffixes do not replace inspection of behavior. The package guide keeps the direct tests from this decision: inspect what callers do, what lifetime the object owns, and what failure or policy it controls. -The role words can be applied mechanically if reviewers check suffixes without checking behavior. The guide must keep the direct tests in this note: inspect what callers do, what lifetime the object owns, and what failure or policy it controls. - -Old on-disk names, wire values, tool names, and configuration entries named in the ledger will stop working. This is accepted before release. The implementation must fail clearly on stale configuration where the owning parser can identify it; it must not silently accept both forms. +Branches based on the former paths and symbols require conflict repair. This is a one-time pre-release cost of removing the old vocabulary without compatibility aliases. diff --git a/.agents/notes/proposed/architecture/2026-08-11-repository-naming-contract-and-rename-ledger.zh.md b/.agents/notes/implemented/architecture/2026-08-11-repository-naming-contract-and-rename-ledger.zh.md similarity index 87% rename from .agents/notes/proposed/architecture/2026-08-11-repository-naming-contract-and-rename-ledger.zh.md rename to .agents/notes/implemented/architecture/2026-08-11-repository-naming-contract-and-rename-ledger.zh.md index 8f1b3505f0..897d06d95b 100644 --- a/.agents/notes/proposed/architecture/2026-08-11-repository-naming-contract-and-rename-ledger.zh.md +++ b/.agents/notes/implemented/architecture/2026-08-11-repository-naming-contract-and-rename-ledger.zh.md @@ -1,34 +1,34 @@ # Agent Note: 仓库命名约定与预发布重命名清单 -Status: proposed +Status: implemented [English](2026-08-11-repository-naming-contract-and-rename-ledger.md) | 中文 ## 问题 -仓库的发展速度超过了部分名称的演进速度。一些包名仍在描述最初的实现,而非所提供的能力。若干类即使实际承担注册表、运行时、引擎、控制器或解析器的职责,名称仍使用 `Service`。部分 `ctx` 键以单数命名注册表,却以复数命名单个引擎。还有一些提供方明明通过可替换的文件系统或子进程服务工作,可以在另一执行环境中运行,名称却使用 `local`。 +仓库的发展速度曾超过部分名称的演进速度。一些包名描述的是最初的实现,而非所提供的能力。若干类即使实际承担注册表、运行时、引擎、控制器或解析器的职责,名称仍使用 `Service`。部分 `ctx` 键以单数命名注册表,却以复数命名单个引擎。还有一些提供方明明通过可替换的文件系统或子进程服务工作,可以在另一执行环境中运行,名称却使用 `local`。 这些名称并非无关紧要。名称会告诉贡献者一项职责从哪里开始、到哪里结束。`Store` 表示数据访问。`Registry` 表示注册与查找。`Runtime` 表示实时执行和生命周期。如果同一个词同时表示这三者,调用方就必须阅读实现,才能判断哪个对象拥有策略、工作或状态。 -仓库还在两种含义下使用 `SDK`。受支持的 Python 和 TypeScript 客户端使用 JSON-RPC SDK 协议。项目整体是 DeepSeek Harness,而不是 SDK 项目。已移除的 SDK 项目工具链使宽泛的含义失去依据,但现有文案和名称仍保留了部分旧用法。 +仓库还曾在两种含义下使用 `SDK`。受支持的 Python 和 TypeScript 客户端使用 JSON-RPC SDK 协议。项目整体是 DeepSeek Harness,而不是 SDK 项目。已移除的 SDK 项目工具链使宽泛的含义失去依据,但文案和名称仍保留了部分旧用法。 -这是首次发布带标签版本之前,最后一个能够低成本完成仓库级重命名的时点。保留含义不清的名称,会让偶然形成的词汇变成兼容性约定。 +首次发布带标签版本之前的最后一个窗口,使仓库级重命名仍可低成本完成。若继续保留含义不清的名称,偶然形成的词汇就会变成兼容性约定。 -## 提案 +## 决策 -在首次发布带标签版本之前,应用本说明中的重命名清单。只更改名称,不得在重命名变更中改变包职责、服务边界、行为、默认值或数据模型。如果某个名称暴露出不合理的边界,应另写一份 proposed Agent Note,专门提议边界变更。 +仓库使用本清单中的全部当前名称。本决策只更改名称;包职责、服务边界、行为、默认值和数据模型保持不变。如果某个名称暴露出不合理的边界,需要另写一份 proposed Agent Note,专门提议边界变更。 -每组获准的系列重命名都必须原子完成。清单点名某一表面时,应一并更新其目录、NPM 包名、导入、Cordis 插件名称、`ctx` 键、公开类型、直接耦合的事件或工具标识符、配置、测试、fixture(测试前置数据)、示例、生成的参考资料以及当前文档。不得留下别名、兼容包、重复的服务键、双重事件名称或回退解析器。仓库尚未发布,旧名称应被拒绝。 +每个已重命名系列只有一套词汇。清单点名某一接口时,其目录、NPM 包名、导入、Cordis 插件名称、`ctx` 键、公开类型、直接耦合的事件或工具标识符、配置、测试、fixture(测试前置数据)、示例、生成的参考资料以及当前文档都使用当前名称。仓库不保留别名、兼容包、重复的服务键、双重事件名称或回退解析器,并拒绝旧名称。 -实现可以拆分为多个 PR(Pull Request),以保持评审可行。任何一个 PR 都不得让同一系列同时存在两套公开词汇。最终状态必须满足完整清单。 +同一系列不会公开两套词汇。 ### `SDK` 只表示一件事 -`SDK` 表示受支持的 Python 和 TypeScript SDK 所使用、基于 JSON-RPC 的客户端/服务器协议。保留 `@deepseek-ai/dsh-sdk-client`、`@deepseek-ai/dsh-sdk-protocol` 和协议身份 `deepseek-harness-sdk-runtime`。将 JSON-RPC 服务器重命名并纳入该系列。不得将 DeepSeek Harness 本身称为 SDK,也不得恢复已移除的项目生成器、启动器、辅助工具或启动器遥测包。 +`SDK` 表示受支持的 Python 和 TypeScript SDK 所使用、基于 JSON-RPC 的客户端/服务器协议。仓库保留 `@deepseek-ai/dsh-sdk-client`、`@deepseek-ai/dsh-sdk-protocol` 和协议身份 `deepseek-harness-sdk-runtime`;JSON-RPC 服务器属于同一系列。DeepSeek Harness 本身不是 SDK,已移除的项目生成器、启动器、辅助工具和启动器遥测包继续保持不存在。 -如果本提案获准,它将部分取代三项现行决策。它会替换[包重新分组决策](../../implemented/architecture/2026-07-29-package-regrouping.md)中保留的 `bash/`、`pty/` 和 `self-modification/` 组名,以及两项暂定包名。它只替换[移除 SDK 项目工具链](../../implemented/simplification/2026-08-11-remove-sdk-project-toolchain.md)中将整个仓库称为 SDK 的说法;后者仍负责说明删除范围和保留的运行时 SDK。它只替换[工具调用超时策略](../../implemented/architecture/2026-07-07-tool-call-timeout-policy.md)中的包名理由;超时机制及其 `guard/timeout-policy/` 归属保持不变。 +本决策部分取代三项现行决策。它替换[包重新分组决策](2026-07-29-package-regrouping.md)中保留的 `bash/`、`pty/` 和 `self-modification/` 组名,以及两项暂定包名。它只替换[移除 SDK 项目工具链](../simplification/2026-08-11-remove-sdk-project-toolchain.md)中将整个仓库称为 SDK 的说法;后者仍负责说明删除范围和保留的运行时 SDK。它只替换[工具调用超时策略](2026-07-07-tool-call-timeout-policy.md)中的包名理由;超时机制及其 `guard/timeout-policy/` 归属保持不变。 -如果其他已实现说明中的包、路径或类型被重命名,而其边界和理由保持不变,则本提案不会取代这些说明。实现阶段只更新其中的事实名称。只有本提案改变既有决策时才添加双向链接;尚未获准的提案不会让现行的已实现说明提前描述未交付名称。 +如果其他已实现说明中的包、路径或类型被重命名,而其边界和理由保持不变,则本决策不会取代这些说明。这些说明使用已实现的事实名称。三项被部分取代的决策都链接回本决策。 ### 按实际职责命名 @@ -68,7 +68,7 @@ Status: proposed 如果协议或方言名称能够区分实现,就应保留。实现依赖相应机制时,保留 `Bash`、`Pwsh`、`JSON-RPC`、`SQLite`、`JSONL`、`OpenTelemetry`、`Claude Code` 和 `E2B`。每个当前后端都已使用 LLM(大语言模型)seam 时,不要在压缩后端名称中加入 `LLM`;在出现更具体的算法名称之前,`basic` 才是如实且中性的名称。 -不得虚构 `process sandbox` 概念。当前 `sandbox` 系列已经准确命名其产品职责,获准的整体重命名不会改变该边界。 +不得虚构 `process sandbox` 概念。当前 `sandbox` 系列已经准确命名其产品职责。本决策不改变该职责。 PascalCase 标识符中的首字母缩略词使用首字母大写格式:`Ui`、`Llm`、`JsonRpc` 和 `ApiProxy`。在文案和适用的包名中使用惯例规定的全大写形式:UI、LLM、JSON-RPC 和 API。`Typert` 是标识符和文案中的唯一准确产品拼写;不得写成 `TypeRT`、`TypeRt`,也不得对 `Typert` 作其他内部拆分。 @@ -76,15 +76,15 @@ PascalCase 标识符中的首字母缩略词使用首字母大写格式:`Ui` ### 将规则写入项目文档 -重命名实现合入时,应将完整的职责词约定加入配对的包创建指南 `docs/cookbook/adding-a-package.md`。在 `packages/AGENTS.md` 中添加一条简短规则并链接到该指南。更新术语表和根项目说明,使 `SDK` 和 `Typert` 各自只有一种含义。Agent Note 负责记录理由和被否决的替代方案;指南负责记录贡献者应遵循的规则。 +配对的包创建指南 `docs/cookbook/adding-a-package.md` 包含完整的职责词约定,`packages/AGENTS.md` 链接到该约定。术语表和根项目说明使 `SDK` 和 `Typert` 各自只有一种含义。本 Agent Note 负责记录理由和被否决的替代方案;指南负责记录贡献者应遵循的规则。 ## 重命名清单 -以下表格列出公开名称和仓库级名称。引用相同职责的私有局部变量也应采用新词汇。若宽泛替换并不正确,清单会明确指出保留的底层名称或产品可见名称。 +以下表格记录公开名称和仓库级名称的变更。`当前名称` 栏记录当前名称。引用相同职责的私有局部变量也使用相同词汇。若宽泛替换并不正确,清单会明确指出保留的底层名称或产品可见名称。 ### 运行时 SDK -| 当前名称 | 提议名称 | 理由 | +| 旧名称 | 当前名称 | 理由 | |---|---|---| | `@deepseek-ai/dsh-jsonrpc` | `@deepseek-ai/dsh-sdk-jsonrpc-server` | 它是 SDK 协议的服务器端。单独使用 `jsonrpc` 只说明编码;`sdk-jsonrpc-server` 则同时说明所属系列、机制和职责。 | | `HarnessSdkServer` | `HarnessSdkJsonRpcServer` | 该类是 JSON-RPC 服务器的一种实现,并不代表所有可能的 SDK 服务器。 | @@ -93,7 +93,7 @@ PascalCase 标识符中的首字母缩略词使用首字母大写格式:`Ui` ### Shell 与终端 -| 当前名称 | 提议名称 | 理由 | +| 旧名称 | 当前名称 | 理由 | |---|---|---| | `packages/bash/` | `packages/shell/` | 该组包含方言无关的执行器 seam、Bash 和 PowerShell 实现、环境支持以及 shell 工具。 | | `@deepseek-ai/dsh-bash`, `ctx.bash` | `@deepseek-ai/dsh-shell`, `ctx.shell` | PowerShell 已经实现该 seam。此项能力是 shell 执行,而不是 Bash。 | @@ -113,7 +113,7 @@ PascalCase 标识符中的首字母缩略词使用首字母大写格式:`Ui` ### 语言服务器与作业 -| 当前名称 | 提议名称 | 理由 | +| 旧名称 | 当前名称 | 理由 | |---|---|---| | `@deepseek-ai/dsh-lsp-local` | `@deepseek-ai/dsh-lsp-stdio` | 该提供方通过可替换的文件系统和子进程服务,以 stdio 传输 LSP。它不一定在本地运行。 | | `packages/tasks/` | `packages/jobs/` | 该系列负责脱离前台运行的工具作业。`jobs` 简短,并可避免与用户任务或 todo 概念冲突。 | @@ -131,7 +131,7 @@ PascalCase 标识符中的首字母缩略词使用首字母大写格式:`Ui` ### 输入触发器、工具呈现、权限预设和用户问题 -| 当前名称 | 提议名称 | 理由 | +| 旧名称 | 当前名称 | 理由 | |---|---|---| | `@deepseek-ai/dsh-client-ui-slash`, `ui-slash/` | `@deepseek-ai/dsh-client-ui-input-trigger`, `ui-input-trigger/` | 客户端处理 `/`、`@`、键盘仲裁、候选菜单和程序化启动,并非只处理斜杠命令。 | | `ctx.slash`、`SlashService`、`SlashController`、`SlashSource` | `ctx.inputTriggers`、`InputTriggerService`、`InputTriggerController`、`InputTriggerSource` | 这些名称覆盖所有受支持的触发器,并保留现有的服务、控制器和来源职责。耦合的区域设置和公开类型名称也改用 `InputTrigger`。 | @@ -144,11 +144,11 @@ PascalCase 标识符中的首字母缩略词使用首字母大写格式:`Ui` | `ctx.userInteraction`, `UserInteractionService`, `UserInteractionProvider`, `UserInteractionError` | `ctx.userQuestions`, `UserQuestionService`, `UserQuestionProvider`, `UserQuestionError` | 这些名称说明唯一受支持的交互形式。保留 `AskUserQuestion*`、`ask_user_question` 工具和 `@deepseek-ai/dsh-tool-ask-user`。 | | `docs/subsystems/user-interaction.md` | `docs/subsystems/user-questions.md` | 该页面只记录问题和答案。 | -保留 `/permission`、`permissions` 投影、`permission` 设置命名空间和 `permission/preset`;它们都是准确的产品词汇或持久化词汇。保留完整名称 `PermissionPresetSettingsController`。删除 `Preset` 会去掉限定其权限的词。另行制定提案以移除 `both` 工具呈现模式;本次重命名不移除行为。 +保留 `/permission`、`permissions` 投影、`permission` 设置命名空间和 `permission/preset`;它们都是准确的产品词汇或持久化词汇。保留完整名称 `PermissionPresetSettingsController`。删除 `Preset` 会去掉限定其权限的词。移除 `both` 工具呈现模式的工作仍推迟到另一份提案;本次重命名不移除行为。 ### Typert、API 网关与工具 -| 当前名称 | 提议名称 | 理由 | +| 旧名称 | 当前名称 | 理由 | |---|---|---| | `packages/typert/type-meta/`, `@deepseek-ai/dsh-type-meta` | `typert/protocol/`, `@deepseek-ai/dsh-typert-protocol` | 该包拥有 Typert Remote 协议、装饰器、绑定、编解码器、查找逻辑和上下文约定。它不是通用类型元数据。 | | 协议包中的 `GatewayService` | `TypertRemoteService` | 该基类标记要导出为 Remote 的同进程服务。它不是 API 网关。 | @@ -162,7 +162,7 @@ PascalCase 标识符中的首字母缩略词使用首字母大写格式:`Ui` ### 工作区指令、遥测、身份和启动环境 -| 当前名称 | 提议名称 | 理由 | +| 旧名称 | 当前名称 | 理由 | |---|---|---| | Host `ctx.workspace` | Host `ctx.workspaceRegistry` | `WorkspaceRegistry` 拥有多个工作区,但 Client `ctx.workspaces` 已经使用不兼容的类型。即使二者运行时上下文独立,两份声明仍会在编译时合并进同一个 Cordis `Context` 接口。职责后缀明确指出 host 服务,并避免该冲突。保留 `@deepseek-ai/dsh-workspace`、`WorkspaceRegistry`、`Workspace` 和 `workspace.*` 协议名称。 | | `@deepseek-ai/dsh-workspace-context`, `context/workspace-context/` | `@deepseek-ai/dsh-agent-instructions`, `context/agent-instructions/` | 该包为 agent(智能体)加载分层的 `AGENTS.md` 和 `CLAUDE.md` 文件。它并非通用工作区上下文。 | @@ -181,7 +181,7 @@ PascalCase 标识符中的首字母缩略词使用首字母大写格式:`Ui` ### 日程、工作流、目标与压缩 -| 当前名称 | 提议名称 | 理由 | +| 旧名称 | 当前名称 | 理由 | |---|---|---| | `@deepseek-ai/dsh-tool-schedule`、`schedule/tool-schedule/`、插件 `tool-schedule` | `@deepseek-ai/dsh-schedule`、`schedule/schedule/`、插件 `schedule` | 该包拥有持久 Schedule 领域、持久化屏障、管理工具、定时器、后续轮次和运行时生命周期。`tool-` 只描述其中一部分。 | | `ScheduleOwner` | `ScheduleRuntime` | 该逐 agent 对象运行实时定时器、持久化投影、分派、空闲等待和资源释放。`Owner` 没有说明这一执行职责。耦合的私有 `owner*` 名称也改用 `runtime*`。 | @@ -194,11 +194,11 @@ PascalCase 标识符中的首字母缩略词使用首字母大写格式:`Ui` | `@deepseek-ai/dsh-compact-basic`、`BasicCompactService`、公开的 `BasicCompact*` | `@deepseek-ai/dsh-compaction-basic`、`BasicCompactionEngine`、对应的 `BasicCompaction*` | `basic` 朴素但准确。`compaction-llm` 没有增加信息,因为当前实现系列已使用 LLM。 | | `@deepseek-ai/dsh-compact-tool-result-prune`, `ToolResultPruneService`, `ctx.toolResultPrune` | `@deepseek-ai/dsh-compaction-tool-result-pruner`, `ToolResultPruner`, `ctx.toolResultPruner` | 该插件是剪除工具结果的执行主体。名词 `pruner` 说明了这一职责。 | -保留 `/compact`、命令包,以及维持压缩定义包与提供方包分离的既有决策。本次重命名只改变词汇,不改变该包边界。 +保留 `/compact`、命令包,以及相互独立的压缩定义包和提供方包。合并这些包的提议仍被否决。本次重命名只改变词汇,不改变该包边界。 ### 设置、凭据、客户端模块和较小的核心职责 -| 当前名称 | 提议名称 | 理由 | +| 旧名称 | 当前名称 | 理由 | |---|---|---| | 抽象类 `Settings` | `SettingsProvider` | 该类通过可替换能力提供设置。保留包、键和事件。 | | `@deepseek-ai/dsh-settings-local`, `SettingsLocal` | `@deepseek-ai/dsh-settings-file`, `FileSettingsProvider` | 该实现通过文件系统 seam 以文件为后端。`file` 说明机制,`local` 则不能。 | @@ -216,7 +216,7 @@ PascalCase 标识符中的首字母缩略词使用首字母大写格式:`Ui` ### Host Web 服务器、会话数据与代码执行 -| 当前名称 | 提议名称 | 理由 | +| 旧名称 | 当前名称 | 理由 | |---|---|---| | `HttpServerService`, `ctx.httpServer` | `WebServer`, `ctx.webServer` | 该服务器拥有 HTTP 路由和 WebSocket 升级路由。`Web` 可以同时涵盖两者;此处的 `Http` 作用域过窄。保留 `packages/host/webserver`、`@deepseek-ai/dsh-host-webserver`、`WebRoute` 和 `WebUpgradeRoute`。 | | 文档子系统标签 `http-server` | `web-server` | 子系统标签必须与服务采用相同作用域。 | @@ -233,7 +233,7 @@ PascalCase 标识符中的首字母缩略词使用首字母大写格式:`Ui` ### 文件系统、skill、subagent 和 Web 提供方 -| 当前名称 | 提议名称 | 理由 | +| 旧名称 | 当前名称 | 理由 | |---|---|---| | `@deepseek-ai/dsh-fs-policy` | `@deepseek-ai/dsh-fs-observation-policy` | 该包定义哪些文件系统观察可以授权后续操作。它不是完整的文件系统策略或沙箱策略。 | | `FsPolicyExec` | `FsObservationActor` | 该值表示策略所关联的观察与操作的执行主体。它本身不执行策略。 | @@ -251,7 +251,7 @@ PascalCase 标识符中的首字母缩略词使用首字母大写格式:`Ui` ### 钩子、防护、Plan Mode、扩展与诊断 -| 当前名称 | 提议名称 | 理由 | +| 旧名称 | 当前名称 | 理由 | |---|---|---| | `@deepseek-ai/dsh-hooks-claude`、`ClaudeHookConfig`、`parseClaudeConfig`,方言 `claude` | `@deepseek-ai/dsh-hooks-claude-code`、`ClaudeCodeHookConfig`、`parseClaudeCodeConfig`,方言 `claude-code` | 该钩子桥接面向 Claude Code,而非所有 Anthropic 或 Claude 产品。 | | `@deepseek-ai/dsh-repeat-tool-guard`,插件/来源 `repeat-tool-guard` | `@deepseek-ai/dsh-repeat-tool-reminder`,插件/来源 `repeat-tool-reminder` | 该插件向模型添加提醒,并不阻止工具调用,也不执行防护决策。 | @@ -263,11 +263,11 @@ PascalCase 标识符中的首字母缩略词使用首字母大写格式:`Ui` | `InvariantService` | `InvariantRegistry` | 该对象拥有已注册的不变量检查。保留 `@deepseek-ai/dsh-invariants` 和 `ctx.invariants`。 | | `packages/client/test-runtime/` | `packages/test-support/client-runtime/` | 该包是客户端测试基础设施。如果现有 NPM 名称已经说明这一约定,则予以保留。 | -保留 MCP、Todo、Plan Mode 包、键、事件和工具名称。获准的变更针对控制器类,而不是产品功能。 +保留 MCP、Todo、Plan Mode 包、键、事件和工具名称。本决策重命名控制器类,而不是产品功能。 ### 实用工具、E2B、Host、组合包、示例与应用 -| 当前名称 | 提议名称 | 理由 | +| 旧名称 | 当前名称 | 理由 | |---|---|---| | `util/paths/`, `@deepseek-ai/dsh-paths` | `util/home-paths/`, `@deepseek-ai/dsh-home-paths` | 这些辅助函数解析 Harness 主目录下的路径,并非通用路径库。已准确说明返回路径的函数名保持不变。 | | `util/retention/`, `@deepseek-ai/dsh-retention` | `util/output-retention/`, `@deepseek-ai/dsh-output-retention` | 该策略保留命令和工具输出,而不是通用数据保留框架。 | @@ -281,7 +281,7 @@ PascalCase 标识符中的首字母缩略词使用首字母大写格式:`Ui` ### 客户端运行时与 UI -| 当前名称 | 提议名称 | 理由 | +| 旧名称 | 当前名称 | 理由 | |---|---|---| | `SlotsService` | `SlotRegistry` | 该对象拥有具名 slot 声明和注册项。 | | `SessionsService` | `SessionRuntime` | 该对象拥有实时客户端会话协调职责,而不是被动的会话列表。 | @@ -365,26 +365,22 @@ PascalCase 标识符内部使用 `Ui`,不要使用 `UI`。除非清单明确 **为旧名称保留别名。**不予采纳。没有已发布的消费方需要这些别名。别名会保留两套词汇,使首次发布携带一项从未有用户需要的迁移。 -## 验收标准 +## 验证 -- 应用清单中的每项映射;如果决策发生变化,则必须在实施前修订本提案并说明原因。 -- 每个系列只有一套公开词汇。同一个 Cordis 上下文中不得留下兼容包、重新导出别名、重复的 `ctx` 键、双重插件 id、双重事件 id、旧工具别名或回退解析器。 -- 变更只能重命名。运行时行为、包边界、默认值、策略、持久化语义和模型行为必须保持等价,只有标识符本身可见时除外。 -- 包目录、NPM 名称、导入、manifest(元数据清单)、TypeScript 引用和路径、Cordis 配置、插件 id、服务键、事件、工具、RPC 名称、清单点名的持久化名称、fixture、快照、示例、生成的目录和当前文案都采用新词汇。 -- 实现合入时,以事实性名称和路径变更更新当前处于 implemented 状态的 Agent Note。包重新分组说明应记录新的分组清单和包名目标,SDK 移除说明不得再将仓库称为 SDK,超时策略说明应记录新的包名理由。架构决策仍然有效的说明,不得被重写为新的决策。 -- 配对的包创建指南应包含职责词约定,`packages/AGENTS.md` 应链接到该约定,术语表应记录选定用词和 `Typert` 拼写,根项目文案应将产品称为 DeepSeek Harness,而不是 DeepSeek Harness SDK。 +- 清单中的每项映射都出现在仓库中。每个系列只有一套公开词汇;同一个 Cordis 上下文中没有兼容包、重新导出别名、重复的 `ctx` 键、双重插件 id、双重事件 id、旧工具别名或回退解析器。 +- 运行时行为、包边界、默认值、策略、持久化语义和模型行为保持等价,只有标识符本身可见时除外。 +- 包目录、NPM 名称、导入、manifest(元数据清单)、TypeScript 引用和路径、Cordis 配置、插件 id、服务键、事件、工具、RPC 名称、清单点名的持久化名称、fixture、快照、示例、生成的目录和当前文案都使用已实现词汇。 +- 当前处于 implemented 状态的 Agent Note 使用事实名称和路径。包重新分组说明记录分组清单和包名目标,SDK 移除说明将 `SDK` 限定为运行时协议,超时策略说明记录包名理由。 +- 配对的包创建指南包含职责词约定,`packages/AGENTS.md` 链接到该约定,术语表记录选定用词和 `Typert` 拼写,根项目文案将产品称为 DeepSeek Harness,而不是 DeepSeek Harness SDK。 - 已移除的 SDK 项目工具链继续保持不存在。 -- 聚焦测试覆盖每个重命名系列;在完整实现上,源代码平面的类型检查、构建、包卫生检查、生成参考资料门禁、受可见标识符影响的快照、翻译配对、`doc-sync` 和 lint 均应通过。 -- 只有完整清单和文档约定全部成为事实后,才能将该 proposed 说明移入 `implemented/`。其实现版应描述最终状态,而不是迁移检查清单。 +- `pnpm run check:ci` 覆盖源代码平面的类型检查、构建、包卫生检查、生成参考资料检查、受影响的快照、翻译配对、`doc-sync` 和 lint。发布形态的 Python 运行时冒烟测试和必需 CI 覆盖打包运行时与平台路径。 -## 风险 +## 后果 -这轮整体重命名会更改大量导入、路径、配置字符串、生成的参考资料和模型可见名称。遗漏的字符串可能通过编译,却在加载或回放时失败。实现时必须结合类型驱动的修改,并在源代码、配置、测试、fixture、文档和生成输入中精确搜索旧名称。 +仓库为每个重命名系列保留一套词汇。清单点名的旧磁盘名称、协议值、工具名称和配置项不再工作。能够识别陈旧配置的所属解析器会明确报错,而不是同时接受两种形式。 -并行工作会与路径移动和符号重命名产生冲突。这是发布前的临时成本。按职责一致的系列拆分实现,可以降低评审成本和合并冲突,但每个系列都必须保持原子性。 +一些名称更长。额外增加的词只有在防止误述权限或机制时才有意义。如果名称中的词不能全部限定职责,长名称仍然错误。 -一些名称会变得更长。额外增加的词只有在防止误述权限或机制时才有意义。如果名称中的词不能全部限定职责,长名称仍然是失败的命名。 +职责后缀不能替代对行为的检查。包创建指南保留本决策中的直接判断方式:检查调用方执行什么操作、对象拥有什么生命周期,以及对象控制什么失败或策略。 -如果评审人只检查后缀而不检查行为,职责词就会被机械套用。指南必须保留本说明中的直接判断方式:检查调用方执行什么操作、对象拥有什么生命周期,以及对象控制什么失败或策略。 - -清单点名的旧磁盘名称、协议值、工具名称和配置项将停止工作。发布前接受这一后果。如果负责解析的解析器能够识别陈旧配置,实现必须明确报错;不得静默接受两种形式。 +基于旧路径和旧符号的分支需要解决冲突。这是发布前移除旧词汇且不保留兼容别名的一次性成本。 diff --git a/.agents/notes/implemented/architecture/2026-08-12-plugin-owned-settings-surface.i18n.yaml b/.agents/notes/implemented/architecture/2026-08-12-plugin-owned-settings-surface.i18n.yaml new file mode 100644 index 0000000000..d77b2c75c7 --- /dev/null +++ b/.agents/notes/implemented/architecture/2026-08-12-plugin-owned-settings-surface.i18n.yaml @@ -0,0 +1,6 @@ +# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each +# 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 .agents/notes/implemented/architecture/2026-08-12-plugin-owned-settings-surface.md +2026-08-12-plugin-owned-settings-surface.md: 3137cfe81ef3cb78a940f085c559ab4a7b62cce3 +2026-08-12-plugin-owned-settings-surface.zh.md: 8dd5e5ccebf1cfb80b55a615f6049dd391943bd7 diff --git a/.agents/notes/implemented/architecture/2026-08-12-plugin-owned-settings-surface.md b/.agents/notes/implemented/architecture/2026-08-12-plugin-owned-settings-surface.md new file mode 100644 index 0000000000..3137cfe81e --- /dev/null +++ b/.agents/notes/implemented/architecture/2026-08-12-plugin-owned-settings-surface.md @@ -0,0 +1,61 @@ +# Agent Note: Plugin-owned settings surface + +Status: implemented + +English | [中文](2026-08-12-plugin-owned-settings-surface.zh.md) + +## Problem + +A plugin that registered a settings namespace could not reach the browser configuration page, and both gates that stopped it lived in this repository. + +`packages/host/apiproxy` held two hardcoded namespace lists. `settings.describe` filtered its answer through them and every write checked them first, so a namespace outside them answered `settings-not-exposed` even when its owner had registered it. Adding a plugin to the configuration page therefore meant editing a package the plugin author does not own. + +The plugin configuration section rendered an unordered list of whatever cards were registered into `settings.plugin.item`. A card carried an opaque `id`, never the namespace it edited, so the section could not tell which served namespaces already had a home. That left every question about "who renders this namespace" unanswerable from the ledger the section could see. + +Together the two meant a user-authored plugin was configurable only by hand-editing `settings.yaml`. The [web plugin configuration note](../feature/2026-08-10-web-plugin-configuration.md) recorded the allowlist as deliberate, and the [config-plane boundaries note](2026-07-30-config-plane-boundaries.md) tied web-configurability to membership in the configurable-provider directory. Both conclusions blocked exactly the plugin authors the general seam was built for. + +## Decision + +**Registering is exposing.** The api-proxy serves every namespace `ctx.settings.describe()` returns and gates no write. `WEB_SETTINGS_NAMESPACES`, `PRODUCT_SETTINGS_NAMESPACES`, the union with `ctx.llm.listConfigurableProviders()`, and the `settings-not-exposed` error code are gone. A name no registration answers — unknown, or malformed and therefore unable to address one — folds into the seam's own `settings-rejected`, so the proxy contributes no boundary and no vocabulary of its own. + +**The settings seam is untouched.** Which client may read a namespace, and which page renders it, are facts about consumers; a Service Definition that carried either would let one Consumer dictate its contract. `SettingsRegisterOptions` gains nothing. + +**`settings.plugin.item` is keyed on the settings namespace.** The slot moved from `list` to `keyed`, the key being the namespace the card edits, following the `tool.call.toolview` precedent where each tool plugin registers its renderer under the tool name. A card declares `key`, not `id`/`order`. The slot is declared by the Plugins section's `configurable` tab, which owns the card list. + +**The tab drives dispatch from the served namespaces.** It reads `settings.describe` once, subscribes to the settings-document invalidation and to connection resets, and dispatches one key per served namespace. What renders is the intersection of two ledgers — namespaces a live Host plugin registered, and cards registered under those keys — computed in the tab's controller from the slot ledger (`ctx.slots.entries`, `ctx.slots.subscribe`) and the wire answer. + +Keying makes absence the signal, and that is what removes the bookkeeping the previous shape needed. A namespace another surface owns (`ui-theme`, `permission`, `llm-*`, `agent-presets`) has no card under its key, so it renders nothing without declaring anything anywhere. A card whose namespace this deployment does not serve is never dispatched, which also fixes the old empty-state defect: the tab counted registered cards, including ones rendering nothing, so a deployment exposing none showed an empty list instead of its empty line. + +**Nothing renders a form it was not given.** The tab supplies no fallback card. A plugin's browser half owns its card completely — chrome, controls, and copy — which is what the slot's `fallback` option would have replaced with a schema-reverse-rendered form. + +## What the allowlist protected + +The gate did keep one thing off the wire, and this note states it plainly because the decision has to survive the accurate version: a registered namespace the list did not name never had its resolved, `base`, or `user` values reach the browser at all. The plugin inventory page is not a substitute — `PluginInventoryEntry` carries `entryId`, `moduleName`, `enabled`, and `fiberPhase`, and its "configuration" row renders an enabled/disabled tag, never a stored value. + +What the gate was not is the boundary its position suggested. Every `settings.*` method sits in `PRIVILEGED_METHODS` (`packages/client/connection`), so a non-loopback or cross-origin request is refused with 403 before reaching this code; `role('secret')` fields are structurally stripped from every layer of every response; and the document the plane edits is the user's own `settings.yaml`, which the same settings page offers to open. The writes it did not block were also the consequential ones: `permission` (which can widen the approval preset) and `agent-presets` (which decides what a session mounts) were both already served. + +So the exposure this change actually adds, in this repository, is one namespace: `agent-default-model`, whose two fields name a provider and a model and which no browser half renders. A future namespace whose values genuinely must not cross the wire is answered per field by `role('secret')` — finer than a namespace switch, and already enforced. + +## Alternatives considered + +**A declaration on `settings.register()`** (`client: { surface: 'plugin-config' | 'custom', title, description }`), which the removed `WEB_SETTINGS_NAMESPACES` comment named as the intended direction. It keeps registration from crossing the transport by default and lets a plugin author self-serve in one line. Rejected because `surface` is browser-page vocabulary and `title`/`description` are presentation: a Service Definition carrying them is a seam shaped by one Consumer. Its fail-closed property is also worth less than it reads — see what the allowlist protected, above. + +**A separate exposure catalog**, a registry of its own that plugins join beside their settings registration, generalizing `ctx.llm.registerConfigurableProviders()`. Rejected because it makes one fact require two registrations that can drift: registering a namespace and forgetting the catalog entry produces a section nothing can edit, with no gate able to see the mistake. + +**A deny-list `Config` field on the api-proxy**, so a deployment could withhold a namespace. Rejected for having no consumer: every currently registered namespace is one a user may edit, and a genuinely sensitive field is answered per-field by `role('secret')`, which is the finer instrument. A namespace-wide switch invented ahead of its first use is the speculative option the package rules forbid. + +**A schema-driven generic card as the slot's `fallback`**, so a plugin with no browser half still got a form from `schema.toJSON()` (schemastery already carries `description`, `role`, `min`/`max`/`step` and serializes them). Rejected because client plugins load at runtime from mounted Loader entries, so a plugin author can ship a real card, and a reverse-rendered form was already judged worse than a hand-written one for the Models page. The `fallback` option remains available without a contract change if that judgment changes. + +**A client-side claim registry**, where each surface owning a namespace declares it so a generic card knows what is already covered. Rejected with the generic card: keyed dispatch already makes an unclaimed key render nothing, so the registry would restate what the slot ledger says. + +**Keeping the list slot and adding a namespace field to its options.** Rejected because the section would still enumerate entries rather than namespaces, keeping the empty-state defect and leaving a card for an uncomposed plugin to suppress itself. + +## Consequences + +A plugin distributed outside this repository is configurable from the settings page with no change here: it registers its namespace on the Host and its card under that key in the browser, and the section pairs the two. Cards now appear in card registration order rather than by hand-assigned `order`. That is stable for the cards this package registers, which install from one generator, and **not** stable across plugins: apply order between packages is unconstrained (`packages/client/AGENTS.md`), so several external cards can still reorder between boots. Ordering them needs an explicit key the section can sort on, which the keyed registration does not carry today. + +Deferred, and larger than this change: the redactor returns a `role('secret')` reachable only through a union, intersection, or transform verbatim (its own `TODO(settings-wire-redaction)`), and `schema.toJSON()` carries a secret's default. That gap predates this change, but serving every registered namespace widens its blast radius from schemas audited in this repository to any third-party schema, so the wire should refuse a namespace it cannot prove it can redact. Also deferred: an assembled-composition test of the headline capability — an overlay-mounted fixture plugin whose Host half registers a namespace and whose `dsh.client` half registers a card, asserted end-to-end. The current coverage proves each half separately; the shipped cards' unchanged output cannot prove the new path. + +The wire read the section adds is one `settings.describe` beside the per-scope reads the cards already make. Its invalidation is imprecise in one direction: the wire announces document commits and connection resets, not registrations, so a namespace registered after the section's read joins on the next commit or reconnect. + +Two frictions remain for an author outside this repository, both recorded in the section's README. The browser half must be a `dsh.client` package built in the client module system's lazy-CJS factory format, and the `clientBundle` preset that emits it lives in `packages/client/tsdown.client.ts` rather than a published package. The bundle-purity gate forbids importing this package's card chrome or staged-form model as values, so such a card reimplements staging and revision fencing. Sharing them would mean either publishing the preset or declaring a child slot inside the card so the section supplies the chrome; neither is built. diff --git a/.agents/notes/implemented/architecture/2026-08-12-plugin-owned-settings-surface.zh.md b/.agents/notes/implemented/architecture/2026-08-12-plugin-owned-settings-surface.zh.md new file mode 100644 index 0000000000..8dd5e5cceb --- /dev/null +++ b/.agents/notes/implemented/architecture/2026-08-12-plugin-owned-settings-surface.zh.md @@ -0,0 +1,61 @@ +# Agent Note: 由插件自己拥有的设置表层 + +Status: implemented + +[English](2026-08-12-plugin-owned-settings-surface.md) | 中文 + +## Problem + +注册了 settings 命名空间的插件到不了浏览器配置页,而拦住它的两道门都在本仓库里。 + +`packages/host/apiproxy` 持有两份硬编码的命名空间清单。`settings.describe` 用它们过滤答复,每次写入也先对照它们,因此清单之外的命名空间即便其拥有方已注册,也只会得到 `settings-not-exposed`。于是把一个插件加进配置页,意味着要改一个插件作者并不拥有的包。 + +插件配置分区渲染的是注册进 `settings.plugin.item` 的卡片列表,无序。卡片携带的是不透明的 `id`,从不是它所编辑的命名空间,因此分区无从判断哪些被服务的命名空间已经有了归属。凡是"这个命名空间由谁渲染"的问题,都无法从分区看得见的账本里得到答案。 + +两者相加,用户自己写的插件就只能靠手改 `settings.yaml` 来配置。[web 插件配置 note](../feature/2026-08-10-web-plugin-configuration.md) 把白名单记为刻意为之,[配置面边界 note](2026-07-30-config-plane-boundaries.md) 则把「可在 Web 上配置」绑定到可配置提供方目录的成员资格。这两条结论恰恰挡住了那个通用 seam 本来要服务的插件作者。 + +## Decision + +**注册即暴露。** api-proxy 服务 `ctx.settings.describe()` 返回的每一个命名空间,写入不设门禁。`WEB_SETTINGS_NAMESPACES`、`PRODUCT_SETTINGS_NAMESPACES`、与 `ctx.llm.listConfigurableProviders()` 的并集,以及 `settings-not-exposed` 错误码,全部删除。没有任何注册应答的名字——未知的,或格式非法因而根本无法寻址到注册的——都折叠为 seam 自己的 `settings-rejected`,于是代理既不贡献边界,也不贡献自己的词汇。 + +**settings seam 不动。** 哪个客户端可以读某个命名空间、哪个页面渲染它,都是关于 Consumer 的事实;Service Definition 只要携带其中之一,就等于让一个 Consumer 决定它的契约。`SettingsRegisterOptions` 一个字段都没加。 + +**`settings.plugin.item` 以 settings 命名空间为键。** 该 slot 从 `list` 改为 `keyed`,键就是卡片所编辑的命名空间,沿用 `tool.call.toolview` 的先例——每个工具插件把自己的渲染器注册在工具名这个键上。卡片声明 `key`,不再声明 `id`/`order`。该 slot 由「插件」分区的 `configurable` 标签页声明,卡片列表归它所有。 + +**标签页以被服务的命名空间驱动派发。** 它读取一次 `settings.describe`,订阅 settings 文档失效通知与连接重置,并为每个被服务的命名空间派发一个键。渲染出来的是两份账本的交集——存活 Host 插件注册的命名空间,以及注册在这些键上的卡片——由标签页的 controller 从 slot 账本(`ctx.slots.entries`、`ctx.slots.subscribe`)与协议答复算出。 + +以命名空间为键,让「缺席」本身成为信号,而这正是它消掉旧形态所需簿记的原因。归别的界面所有的命名空间(`ui-theme`、`permission`、`llm-*`、`agent-presets`)在其键上没有卡片,于是什么都不渲染,且无需在任何地方声明任何东西。命名空间未被本部署服务的卡片根本不会被派发,这同时修掉了旧的空态缺陷:标签页数的是已注册卡片,其中包含那些什么都不渲染的,因此一个都不暴露的部署看到的是空列表,而不是它那行空态文案。 + +**不渲染任何未被交给它的表单。** 标签页不提供兜底卡片。插件的浏览器半侧完整拥有自己的卡片——外观、控件与文案——而这正是 slot 的 `fallback` 选项会用一份 schema 反向渲染的表单取代掉的东西。 + +## 白名单实际护住了什么 + +这道门确实挡住了一样东西,本 note 如实写出,因为这个决策必须在准确版本下也站得住:不在名单上的已注册命名空间,其 resolved、`base` 与 `user` 值根本不会抵达浏览器。插件清单页不能替代它——`PluginInventoryEntry` 携带的是 `entryId`、`moduleName`、`enabled` 与 `fiberPhase`,它那一行「configuration」渲染的是启用/停用标签,从不是任何已存值。 + +这道门不是的,是它所处位置暗示的那种边界。每个 `settings.*` 方法都在 `PRIVILEGED_METHODS` 里(`packages/client/connection`),非回环或跨源请求在到达这段代码之前就以 403 被拒;`role('secret')` 字段在每种响应的每一层都被结构性剥离;而这个面所编辑的文档,本就是用户自己的 `settings.yaml`,同一个设置页还提供了打开它的入口。它没有挡住的写入,恰恰是有分量的那些:`permission`(能放宽审批预设)与 `agent-presets`(决定一个会话挂载什么)本来就已被服务。 + +因此本次改动在本仓库实际新增的暴露面是一个命名空间:`agent-default-model`——它的两个字段指明一个提供方与一个模型,且没有任何浏览器半侧渲染它。将来若某个命名空间的值确实不该跨越协议,由 `role('secret')` 逐字段作答:比整命名空间开关更精细,而且已经在执行。 + +## Alternatives considered + +**在 `settings.register()` 上加声明**(`client: { surface: 'plugin-config' | 'custom', title, description }`),这也是被删掉的 `WEB_SETTINGS_NAMESPACES` 注释所点名的既定方向。它让注册默认不跨越传输边界,并让插件作者一行代码自助。否决的原因是 `surface` 是浏览器页面的词汇,而 `title`/`description` 属于呈现:Service Definition 一旦携带它们,就成了被单个 Consumer 塑形的 seam。它那条 fail-closed 性质的价值也不如读起来那么高——见上文「白名单实际护住了什么」。 + +**另设一份暴露目录**,插件在注册 settings 之外再加入这份自有注册表,即把 `ctx.llm.registerConfigurableProviders()` 一般化。否决的原因是它把一件事实拆成两处可能脱节的注册:注册了命名空间却忘了目录条目,产出的是一个谁都编辑不了的分节,而没有任何门禁看得见这个错误。 + +**给 api-proxy 加一个 deny-list `Config` 字段**,让部署方能扣下某个命名空间。因为没有消费者而否决:当前每一个已注册的命名空间都是用户可以编辑的,而真正敏感的字段由 `role('secret')` 逐字段作答,那是更精细的工具。在第一个用例出现之前就发明出来的整命名空间开关,正是包规则所禁止的投机选项。 + +**把 schema 驱动的通用卡片作为该 slot 的 `fallback`**,让没有浏览器半侧的插件也能从 `schema.toJSON()` 得到一份表单(schemastery 本就携带 `description`、`role`、`min`/`max`/`step` 并将其序列化)。否决的原因是客户端插件按已挂载的 Loader entries 在运行时加载,插件作者完全可以交付一张真正的卡片;而反向渲染的表单在模型页那次已被判定不如手写。若这个判断日后改变,`fallback` 选项无需改动契约即可启用。 + +**客户端认领注册表**,让每个拥有某命名空间的界面声明它,好让通用卡片知道哪些已经有人管。与通用卡片一并否决:keyed 派发本就让无人认领的键什么都不渲染,这份注册表只会把 slot 账本已经说过的话再说一遍。 + +**保留 list slot,只给它的 options 加一个命名空间字段。** 否决的原因是分区枚举的仍是 entry 而非命名空间,空态缺陷照旧,未组装插件的卡片也仍需自我抑制。 + +## Consequences + +在本仓库之外分发的插件无需改动这里即可从设置页配置:它在 Host 上注册自己的命名空间、在浏览器里把卡片注册在该键上,由分区把两者配对。卡片现在按卡片注册顺序出现,而不再依赖手工指定的 `order`。对本包注册的这几张卡它是稳定的——它们从同一个 generator 安装;对**跨插件**的卡片它并不稳定:包与包之间的 apply 顺序是无约束的(`packages/client/AGENTS.md`),因此多个外部卡片仍可能在不同次启动之间重排。要为它们定序,需要一个 section 可排序的显式键,而 keyed 注册今天并不携带。 + +以下延后,且都大于本次改动:脱敏器对只能经由 union、intersection 或 transform 抵达的 `role('secret')` 原样返回(其自身的 `TODO(settings-wire-redaction)`),而 `schema.toJSON()` 会携带 secret 的默认值。该缺口早于本次改动,但服务每一个已注册命名空间,把它的影响面从本仓库内经审计的 schema 扩大到任意第三方 schema,因此协议应当拒绝服务它无法证明可安全脱敏的命名空间。同样延后的还有:对本次头号能力的组装态测试——用 overlay 挂载一个 fixture 插件(Host 半注册命名空间、`dsh.client` 半注册卡片)并在端到端断言。当前覆盖分别证明了两个半侧;已发卡片输出未变这一点,证明不了新路径。 + +分区新增的协议读取是一次 `settings.describe`,与卡片各自已有的 per-scope 读取并列。它的失效通知在一个方向上不精确:协议通告的是文档提交与连接重置,而非注册行为,因此在分区读取之后才被注册的命名空间,要等下一次提交或重连才会加入。 + +对仓库之外的作者仍留有两处摩擦,均记在该分区的 README 里。浏览器半侧必须是按客户端模块系统的 lazy-CJS factory 格式构建的 `dsh.client` 包,而产出它的 `clientBundle` 预设位于 `packages/client/tsdown.client.ts`,并非已发布的包。bundle 纯净度门禁禁止以值的形式导入本包的卡片外观与暂存表单模型,因此这样的卡片要重新实现暂存与 revision 设栅。要共享它们,要么发布该预设,要么在卡片内部声明一层子 slot 让分区提供外观;两者都尚未构建。 diff --git a/.agents/notes/implemented/architecture/2026-08-13-session-content-search-opt-in.i18n.yaml b/.agents/notes/implemented/architecture/2026-08-13-session-content-search-opt-in.i18n.yaml new file mode 100644 index 0000000000..270d93300e --- /dev/null +++ b/.agents/notes/implemented/architecture/2026-08-13-session-content-search-opt-in.i18n.yaml @@ -0,0 +1,6 @@ +# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each +# 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 .agents/notes/implemented/architecture/2026-08-13-session-content-search-opt-in.md +2026-08-13-session-content-search-opt-in.md: 2d14b2def00186c2957dc03ae712fbcb63d2c820 +2026-08-13-session-content-search-opt-in.zh.md: dbde561c82cebdbf51ad31b1cd22c908c8d0f327 diff --git a/.agents/notes/implemented/architecture/2026-08-13-session-content-search-opt-in.md b/.agents/notes/implemented/architecture/2026-08-13-session-content-search-opt-in.md new file mode 100644 index 0000000000..2d14b2def0 --- /dev/null +++ b/.agents/notes/implemented/architecture/2026-08-13-session-content-search-opt-in.md @@ -0,0 +1,32 @@ +# Agent Note: Session content search ships opt-in through openAt never + +Status: implemented + +English | [中文](2026-08-13-session-content-search-opt-in.zh.md) + +## Problem + +The shipped bundles mounted the SQLite session-query provider with the full-text index live (`openAt: first-search`), so every default deployment carried a derived FTS index and the Web sidebar offered content search. Whether a deployment wants that index — its node:sqlite import, per-search source reconciliation, and derived storage — is a deployment choice, and the product default is to ship without it; the model-facing search tools were already opt-in and unmounted (the [not-shipped-default decision](../feature/2026-08-02-session-search-not-shipped-default.md)). + +Turning the capability off by unmounting the plugin row is not viable. `ApiProxyService` declares `sessionQuery` as a required injection, so without the provider the whole host API gateway stays unloaded and the Web GUI never boots. Session-log export traces subagent descendants through `ctx.sessionQuery.traceSession`, and a subagent fork resolves its Workspace through the same lineage trace — both would need optional-service guards plus a replacement lineage source, roughly tripling the change surface while losing exact reads everywhere. + +## Decision + +Content search is enforced off at the provider. `openAt: 'never'` is a third opening phase on `@deepseek-ai/dsh-session-query-sqlite`: `searchSessions` and `searchEvents` fail with the typed `SESSION_QUERY_SEARCH_DISABLED` code before any request normalization, node:sqlite is never imported or opened, and no source observation or reconciliation runs. Every inherited `ctx.sessionQuery` exact read, filter, and trace keeps working, so session export, fork Workspace inheritance, and title reads are unaffected. + +`SESSION_QUERY_SEARCH_DISABLED` joins the closed `SessionQueryErrorCode` taxonomy, and the `tool-session-query` service boundary maps it to the model-safe message `session search is disabled in this deployment`. + +The base bundle sets `openAt: never` on the `session-query-sqlite` row and the web bundle's restatement keeps it; enabling content search is a one-line `openAt` override (`first-search` or `startup`) in a later patch layer, typically with a durable `path`. The host `session.search` endpoint reports the provider failure through its existing error path, and the Web sidebar keeps its designed degradation: local title/workspace matching plus the content-search-unavailable notice. The CLI compat spec pins the shipped `openAt: never` rows, while the web e2e scaffold keeps content search enabled — its seeded-session scenarios navigate by content search, and those runs are the assembled coverage for the opt-in path. + +## Alternatives considered + +- **Unmount the plugin row** (`disabled: true` in the base patch): rejected — the api-gateway's required `sessionQuery` injection keeps the whole host API unloaded, and making that injection optional forces guards plus a header-walk lineage fallback in session export and fork resolution. +- **Disable at the consumers** (the host `session.search` endpoint or the sidebar): rejected — enforcement belongs to the operation that makes the decision; opt-in model tools or any other consumer would still reach the index. +- **A separate boolean beside `openAt`**: rejected — the opening phase already owns when SQLite starts; `never` extends the same axis instead of adding a second knob that can contradict it. + +## Consequences + +- Default deployments run no derived index: no node:sqlite import or experimental-SQLite startup warning, no reconciliation work, no derived database on disk. Sidebar search matches session titles and workspace names only. +- Search failures under the default are typed and stable rather than incidental, so callers distinguish a deployment choice from an index fault (`SESSION_QUERY_INDEX_FAILED`). +- Re-enabling content search is per-deployment configuration, not a code change, and restores the full FTS behavior unchanged. +- Compositions that mount the search tools without overriding `openAt` get the model-safe disabled message on every search call; enabling the tools implies enabling the index. diff --git a/.agents/notes/implemented/architecture/2026-08-13-session-content-search-opt-in.zh.md b/.agents/notes/implemented/architecture/2026-08-13-session-content-search-opt-in.zh.md new file mode 100644 index 0000000000..dbde561c82 --- /dev/null +++ b/.agents/notes/implemented/architecture/2026-08-13-session-content-search-opt-in.zh.md @@ -0,0 +1,32 @@ +# Agent Note: 会话内容搜索通过 openAt never 以 opt-in 方式交付 + +Status: implemented + +[English](2026-08-13-session-content-search-opt-in.md) | 中文 + +## 问题 + +交付的 bundle 之前以启用状态挂载 SQLite 会话查询提供方的全文索引(`openAt: first-search`),因此每个默认部署都携带一个派生 FTS 索引,Web 侧边栏提供内容搜索。一个部署是否需要该索引——它的 node:sqlite 导入、每次搜索的来源对账和派生存储——是部署自身的选择,产品默认不携带它交付;面向模型的搜索工具此前已经是 opt-in 且未挂载(见[非默认交付决策](../feature/2026-08-02-session-search-not-shipped-default.md))。 + +通过卸载插件行来关闭该能力不可行。`ApiProxyService` 将 `sessionQuery` 声明为必需注入,没有该提供方时整个宿主 API 网关保持未加载,Web GUI 无法启动。会话日志导出通过 `ctx.sessionQuery.traceSession` 追踪子代理后代,子代理分叉也通过同一血缘追踪解析其 Workspace——两者都需要可选服务守卫加一个替代血缘来源,改动面大约扩大三倍,同时使精确读取在所有地方消失。 + +## 决策 + +内容搜索在提供方处强制关闭。`openAt: 'never'` 是 `@deepseek-ai/dsh-session-query-sqlite` 的第三个打开阶段:`searchSessions` 和 `searchEvents` 在任何请求规范化之前就以类型化的 `SESSION_QUERY_SEARCH_DISABLED` 代码失败,node:sqlite 绝不会被导入或打开,也不运行任何来源观察或对账。`ctx.sessionQuery` 上继承的全部精确读取、过滤和跟踪保持可用,因此会话导出、分叉的 Workspace 继承和标题读取不受影响。 + +`SESSION_QUERY_SEARCH_DISABLED` 加入封闭的 `SessionQueryErrorCode` 分类,`tool-session-query` 的服务边界将它映射为模型安全消息 `session search is disabled in this deployment`。 + +base bundle 在 `session-query-sqlite` 行上设置 `openAt: never`,web bundle 的重述保持该值;启用内容搜索只需在后续 patch 层用一行覆盖 `openAt`(`first-search` 或 `startup`),通常同时配一个持久 `path`。宿主 `session.search` 端点沿现有错误路径报告提供方失败,Web 侧边栏保持其既有降级:本地标题/工作区匹配加内容搜索不可用提示。CLI 兼容性测试固定交付的 `openAt: never` 行,而 Web e2e 脚手架保持内容搜索启用——其种子会话场景通过内容搜索导航,这些运行也是 opt-in 路径的装配级覆盖。 + +## 曾考虑的替代方案 + +- **卸载插件行**(在 base patch 中 `disabled: true`)——否决:api-gateway 的必需 `sessionQuery` 注入会使整个宿主 API 保持未加载,而把该注入改为可选需要守卫加上会话导出与分叉解析中的 header 遍历血缘回退。 +- **在消费方处关闭**(宿主 `session.search` 端点或侧边栏)——否决:强制应由做出决定的操作执行;opt-in 的模型工具或任何其他消费方仍会触达索引。 +- **在 `openAt` 旁增加独立布尔开关**——否决:打开阶段已经拥有"SQLite 何时启动"这一轴;`never` 延伸同一根轴,而不是增加一个可能与之矛盾的第二个旋钮。 + +## 结果 + +- 默认部署不运行任何派生索引:没有 node:sqlite 导入或实验性 SQLite 启动警告,没有对账工作,磁盘上没有派生数据库。侧边栏搜索只匹配会话标题和工作区名称。 +- 默认状态下的搜索失败是类型化且稳定的,调用方可以把部署选择与索引故障(`SESSION_QUERY_INDEX_FAILED`)区分开。 +- 重新启用内容搜索是逐部署配置而非代码改动,并原样恢复完整的 FTS 行为。 +- 挂载搜索工具但未覆盖 `openAt` 的组合,每次搜索调用都会得到模型安全的已禁用消息;启用工具意味着同时启用索引。 diff --git a/.agents/notes/implemented/bug-fix/2026-07-31-composer-text-layers-share-one-scrollport.i18n.yaml b/.agents/notes/implemented/bug-fix/2026-07-31-composer-text-layers-share-one-scrollport.i18n.yaml index 92dcd28a7e..4c5e88d55e 100644 --- a/.agents/notes/implemented/bug-fix/2026-07-31-composer-text-layers-share-one-scrollport.i18n.yaml +++ b/.agents/notes/implemented/bug-fix/2026-07-31-composer-text-layers-share-one-scrollport.i18n.yaml @@ -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 .agents/notes/implemented/bug-fix/2026-07-31-composer-text-layers-share-one-scrollport.md -2026-07-31-composer-text-layers-share-one-scrollport.md: 6097779529f86e6d994296ae396f108c63f01abc -2026-07-31-composer-text-layers-share-one-scrollport.zh.md: 753d67d538d0c17512444639d60b7b5c8ff80e9a +2026-07-31-composer-text-layers-share-one-scrollport.md: d01231f706a7d3850ce1b3770ef351cb7e211384 +2026-07-31-composer-text-layers-share-one-scrollport.zh.md: 3ce8cc05dc57b05bb8c0bd903a0b64b12d4a6963 diff --git a/.agents/notes/implemented/bug-fix/2026-07-31-composer-text-layers-share-one-scrollport.md b/.agents/notes/implemented/bug-fix/2026-07-31-composer-text-layers-share-one-scrollport.md index 6097779529..d01231f706 100644 --- a/.agents/notes/implemented/bug-fix/2026-07-31-composer-text-layers-share-one-scrollport.md +++ b/.agents/notes/implemented/bug-fix/2026-07-31-composer-text-layers-share-one-scrollport.md @@ -24,6 +24,8 @@ One scrolling box, holding both layers. The browser then applies one offset to both layers, in the same frame, on the same compositor. The caret is bound to its glyphs by construction rather than by upkeep: there is no code to run, no event to wait for, and no state that can be one frame stale. The wheel-chaining handler stays, retargeted from the textarea to the scrollport, and remains the only listener on the box. +Safari's native text control has one engine exception: deleting across a soft-wrap threshold can retain the former line layout after the mirror shrinks. The [Safari soft-wrap recovery](2026-08-13-safari-textarea-soft-wrap-reflow.md) restores the zero-overflow invariant before paint without changing the one-scrollport design. + Two things the previous mechanism needed are gone with it: **The backdrop's trailing-line sentinel.** It existed to keep the two boxes' scroll extents equal — a textarea reserves a line box for the caret after a final newline while `white-space: pre-wrap` collapses a text node's trailing newline, so a draft ending in a newline made the backdrop one line shorter and clamped the mirrored offset a line above the caret. With one scrollport the backdrop's own extent decides nothing: the mirror div sizes the stack for both layers, both start at the same top, and a layer whose content ends earlier simply paints nothing on the last line. The shape is worth keeping in mind rather than the mechanism: it is the one that measured 628 against 652 when the two boxes had to agree on a height. diff --git a/.agents/notes/implemented/bug-fix/2026-07-31-composer-text-layers-share-one-scrollport.zh.md b/.agents/notes/implemented/bug-fix/2026-07-31-composer-text-layers-share-one-scrollport.zh.md index 753d67d538..3ce8cc05dc 100644 --- a/.agents/notes/implemented/bug-fix/2026-07-31-composer-text-layers-share-one-scrollport.zh.md +++ b/.agents/notes/implemented/bug-fix/2026-07-31-composer-text-layers-share-one-scrollport.zh.md @@ -24,6 +24,8 @@ composer 的文本由两层叠放绘制(见 [InputBar](../../../../packages/cl 于是浏览器在同一帧、同一个合成器上,把同一个偏移施加给两层。光标与字形的绑定来自结构本身,而不是来自持续维护:没有代码要跑,没有事件要等,也没有任何状态可能落后一帧。滚轮接力处理器保留,只是从 textarea 改挂到滚动容器上,并且仍是这个盒子上唯一的监听。 +Safari 的原生文本控件存在一个引擎例外:跨过软换行阈值的删除可能在镜像层收缩后仍保留原先的行布局。[Safari 软换行恢复](2026-08-13-safari-textarea-soft-wrap-reflow.md)会在绘制前恢复零溢出不变量,而不改变单滚动容器设计。 + 上一版机制所需要的两样东西随它一起消失: **backdrop 的尾行哨兵。** 它的存在只是为了让两个盒子的滚动范围相等——textarea 会在末尾换行之后为光标保留一个行盒,而 `white-space: pre-wrap` 会折叠文本节点的尾随换行,因此以换行结尾的草稿会让 backdrop 少一行,把镜像偏移钳制在光标上方一行。改为单一滚动容器后,backdrop 自身的范围不再决定任何事:镜像层为两层统一定高,两层顶端对齐,内容更早结束的那一层只是在最后一行什么都不画。值得记住的是这类草稿形状而不是那套机制:正是它在「两个盒子必须就高度达成一致」的时代量出了 628 对 652。 diff --git a/.agents/notes/implemented/bug-fix/2026-08-04-composer-tab-gutter-reservation.i18n.yaml b/.agents/notes/implemented/bug-fix/2026-08-04-composer-tab-gutter-reservation.i18n.yaml index 8a9b6236ae..ccae7043a7 100644 --- a/.agents/notes/implemented/bug-fix/2026-08-04-composer-tab-gutter-reservation.i18n.yaml +++ b/.agents/notes/implemented/bug-fix/2026-08-04-composer-tab-gutter-reservation.i18n.yaml @@ -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 .agents/notes/implemented/bug-fix/2026-08-04-composer-tab-gutter-reservation.md -2026-08-04-composer-tab-gutter-reservation.md: 3b28c35c1f11676e41cabde76d1b0d16c688f034 -2026-08-04-composer-tab-gutter-reservation.zh.md: c357dd06c52a834c18d2e8a25246d4ad003db548 +2026-08-04-composer-tab-gutter-reservation.md: 8bd9fb2d86982d82b44a82c55b7303fcd9a5bf4d +2026-08-04-composer-tab-gutter-reservation.zh.md: 4b70aeb1d3777384907c345968971fcf75b3e74d diff --git a/.agents/notes/implemented/bug-fix/2026-08-04-composer-tab-gutter-reservation.md b/.agents/notes/implemented/bug-fix/2026-08-04-composer-tab-gutter-reservation.md index 3b28c35c1f..8bd9fb2d86 100644 --- a/.agents/notes/implemented/bug-fix/2026-08-04-composer-tab-gutter-reservation.md +++ b/.agents/notes/implemented/bug-fix/2026-08-04-composer-tab-gutter-reservation.md @@ -14,13 +14,11 @@ So for as long as the transcript overflowed — the ordinary state of any sessio ## Decision -`.scrollBody` declares `scrollbar-gutter: stable` unconditionally, and the overlay branch declares the same box a scroll container on both axes — `overflow-x: hidden; overflow-y: auto` — instead of `overflow: hidden`. +`.scrollBody` declares `scrollbar-gutter: stable` for the Chat state, and the overlay branch overrides it with `scrollbar-gutter: auto` while staying a scroll container on both axes — `overflow-x: hidden; overflow-y: auto`. The reservation is Chat's alone: it holds the seat's content box at the same width whether or not the transcript overflows, so the card never jumps as a growing transcript starts to scroll, nor between the hero phase and the first scrolling turn. The overlay branch reserves nothing — the view owns its own scrollers, so a gutter there would only narrow the view's content — and its seat compensates for the bar instead ([the seat-width compensation](2026-08-12-composer-overlay-seat-width-compensation.md)). -The two halves are one change. The reservation is what makes both states measure against the same width; declaring the overlay branch a scroll container is what makes the reservation reach it. `stable` rather than `auto` because `auto` reserves only while the box actually overflows, and the difference between overflowing and not is precisely the difference between the two tabs — an `auto` gutter would state the bug rather than fix it. +`stable` rather than `auto` because `auto` reserves only while the box actually overflows, and the difference between overflowing and not is precisely the difference between Chat's two phases — an `auto` gutter would state the bug rather than fix it. -The overlay state is a scroll container that nothing scrolls: the view fills it (`flex: 1 1 0` with its own clip) and the seat is out of flow, so no gesture and no clipping behavior changes. What changes is which declarations the engine honours. WebKit applies `scrollbar-gutter` to an `overflow-y: auto` box and ignores it on a hidden one — measured on this app's own composer layers and recorded in [the composer scrollport note](2026-07-31-composer-text-layers-share-one-scrollport.md) — so a reservation left on a hidden box would hold in Chromium and silently not in Safari. - -The horizontal axis is declared rather than left to compute: a box that scrolls on one axis computes `visible` on the other to `auto`, and would grow a horizontal scrollbar of its own the first time a view's content reached past the column. +The reservation lives on an `overflow-y: auto` box, and that form is load-bearing: WebKit applies `scrollbar-gutter` to an `overflow-y: auto` box and ignores it on a hidden one — measured on this app's own composer layers and recorded in [the composer scrollport note](2026-07-31-composer-text-layers-share-one-scrollport.md) — so a reservation on a hidden box would hold in Chromium and silently not in Safari. The overlay branch keeps its `overflow-y: auto` form too, as a clipping box nothing scrolls out of: a single-axis scroller computes the other axis to `auto`, so the horizontal axis is declared `hidden` rather than left to compute, and would otherwise grow a horizontal scrollbar of its own the first time a view's content reached past the column. The reservation is worth what it costs only because the bar takes layout space here at all, which is not the browser's default behavior but this client's: `::-webkit-scrollbar` carries a width in ui-theme's sheet ([themed scrollbars](2026-07-28-themed-scrollbars-and-reserved-gutter.md)), and the sidebar's session list already reserves its own gutter for the same reason. @@ -37,7 +35,7 @@ The reservation is worth what it costs only because the bar takes layout space h ## Consequences - Chat's content column is permanently 8px narrower — in the hero phase and while the transcript is short as well, where no bar is drawn. That is the trade: one card position at every content height, instead of the widest possible column. -- The fix covers three transitions with one declaration, because all three are the same difference: Chat ↔ Trajectory, short ↔ scrolling transcript within Chat, and hero ↔ first scrolling turn. +- The card holds one position across three transitions, by two mechanisms: the reservation keeps Chat's seat at one width across its own phases (short ↔ scrolling transcript, hero ↔ first scrolling turn), and the overlay seat's compensation matches it on the Chat ↔ Trajectory transition ([the seat-width compensation](2026-08-12-composer-overlay-seat-width-compensation.md)). - The overlay state is now a scroll container. Nothing in it can overflow today; a future view that let its content exceed the column would scroll this box instead of clipping, and would need its own clip the way the Trajectory view already has one. - The committed golden records the reserved band, so a change to the sheet's `::-webkit-scrollbar` width — the value that decides how wide the reservation is — arrives as a reviewable diff in this scenario as well as in the sidebar's. @@ -45,6 +43,6 @@ The reservation is worth what it costs only because the bar takes layout space h `apps/web/tests/composer-tab-geometry.e2e.ts` measures the input card's rectangle in both tabs, at a viewport where the card sits at its width cap and one where it shrinks with the column, and asserts the two rectangles are the same rectangle. Only a real engine reports this: jsdom gives every element a zero-sized box and no scrollbar, so a unit spec could assert the declarations exist but not that the two states land in the same place. For the same reason no CSS-text spec accompanies it — it would restate the declarations without adding a fact the browser lane does not already establish. -The scenario launches chromium without Playwright's default `--hide-scrollbars`, which is load-bearing: under that argument a bar consumes no layout width, both tabs agree before this change as much as after it, and every comparison in the file holds vacuously. Measured, the pre-fix cascade leaves both bands at 0 under the argument, and at 8 and 0 with it dropped. +The scenario launches chromium without Playwright's default `--hide-scrollbars`, which is load-bearing: under that argument a bar consumes no layout width, so the tabs agree with and without the compensation and every comparison in the file holds vacuously. Measured, both bands sit at 0 under the argument and at 8 and 0 with it dropped. -The pre-fix cascade is then applied in the page — `scrollbar-gutter: auto` on the scroller, `overflow: hidden` on the overlay branch — and the same two tabs measured through it, which is what separates a card that does not move from a tab switch that never reached the layout. It reproduces the reported symptom as a number: 4px on each edge, half the 8px band. The golden records that control beside the fixed state, so the fixture carries the difference the change removes rather than only its absence. +The uncompensated cascade is then applied in the page — the overlay seat's `right` compensation dropped to 0 via `!important`, Chat's reservation untouched — and the same two tabs measured through it, which is what separates a card that does not move from a tab switch that never reached the layout. It reproduces the reported symptom as a number: 4px on each edge, half the 8px band. The golden records that control beside the fixed state, so the fixture carries the difference the change removes rather than only its absence. diff --git a/.agents/notes/implemented/bug-fix/2026-08-04-composer-tab-gutter-reservation.zh.md b/.agents/notes/implemented/bug-fix/2026-08-04-composer-tab-gutter-reservation.zh.md index c357dd06c5..4b70aeb1d3 100644 --- a/.agents/notes/implemented/bug-fix/2026-08-04-composer-tab-gutter-reservation.zh.md +++ b/.agents/notes/implemented/bug-fix/2026-08-04-composer-tab-gutter-reservation.zh.md @@ -14,13 +14,11 @@ composer 座位在组件树中只有一个节点、一个位置,但它究竟 ## 决策 -`.scrollBody` 无条件声明 `scrollbar-gutter: stable`,overlay 分支则把同一个盒子在两个轴向上都声明为滚动容器——`overflow-x: hidden; overflow-y: auto`——而不再是 `overflow: hidden`。 +`.scrollBody` 为 Chat 状态声明 `scrollbar-gutter: stable`,覆盖分支则将其覆盖为 `scrollbar-gutter: auto`,同时保持为双轴滚动容器——`overflow-x: hidden; overflow-y: auto`。这条预留只属于 Chat:它让座位的内容盒在 transcript 是否溢出时都保持同一宽度,因此卡片不会在 transcript 增长到开始滚动的那一刻跳动,也不会在 hero 态与第一个可滚动轮次之间跳动。覆盖分支不预留任何槽位——视图自己滚动,槽位只会白白收窄视图内容——它的座位改为补偿滚动条宽度([座位宽度补偿](2026-08-12-composer-overlay-seat-width-compensation.md))。 -这两半是同一处改动。预留使两种状态依附于同一个宽度;把 overlay 分支声明为滚动容器,才使这条预留真正抵达它。选 `stable` 而非 `auto`,是因为 `auto` 只在盒子确实溢出时才预留,而「溢出与否」恰恰就是两个标签页之间的那点差别——`auto` 的写法只是把缺陷重述一遍,并不能修掉它。 +选 `stable` 而非 `auto`,是因为 `auto` 只在盒子确实溢出时才预留,而「溢出与否」恰恰就是 Chat 两种相位之间的那点差别——`auto` 的写法只是把缺陷重述一遍,并不能修掉它。 -overlay 状态是一个没有任何东西会去滚动它的滚动容器:视图把它填满(`flex: 1 1 0`,且自带裁剪),座位不在常规流中,因此没有任何手势与裁剪行为发生变化。变化的是引擎会认哪些声明。WebKit 对 `overflow-y: auto` 的盒子应用 `scrollbar-gutter`,对 hidden 的盒子则忽略它——这是在本应用 composer 自身的图层上实测所得,并记录于 [composer 滚动视口记录](2026-07-31-composer-text-layers-share-one-scrollport.md)——所以把预留留在一个 hidden 盒子上,会在 Chromium 上成立,在 Safari 上悄无声息地不成立。 - -横向轴是显式声明的,而不是交给推导:单轴滚动的盒子会把另一轴的 `visible` 计算为 `auto`,于是只要某个视图的内容第一次伸出列外,它就会长出自己的横向滚动条。 +这条预留位于 `overflow-y: auto` 的盒子上,而这个形式是承重的:WebKit 对 `overflow-y: auto` 的盒子应用 `scrollbar-gutter`,对 hidden 的盒子则忽略它——这是在本应用 composer 自身的图层上实测所得,并记录于 [composer 滚动视口记录](2026-07-31-composer-text-layers-share-one-scrollport.md)——所以把预留放在 hidden 盒子上,会在 Chromium 上成立,在 Safari 上悄无声息地不成立。覆盖分支同样保留 `overflow-y: auto` 的形式,作为没有任何内容会滚出去的裁剪盒:单轴滚动的盒子会把另一轴的 `visible` 计算为 `auto`,因此横向轴显式声明为 `hidden` 而不是交给推导,否则某个视图的内容第一次伸出列外时,它就会长出自己的横向滚动条。 这条预留之所以值回它的代价,前提是滚动条在这里确实占布局空间——这并非浏览器的默认行为,而是本客户端的选择:ui-theme 的样式表给 `::-webkit-scrollbar` 声明了宽度([滚动条主题化](2026-07-28-themed-scrollbars-and-reserved-gutter.md)),侧边栏的会话列表也正是出于同一原因预留了自己的滚动条槽。 @@ -37,7 +35,7 @@ overlay 状态是一个没有任何东西会去滚动它的滚动容器:视图 ## 后果 - Chat 的内容列永久变窄 8px——hero 态与 transcript 尚短、根本不绘制滚动条时同样如此。这就是这笔交易:以最宽的列换取卡片在任何内容高度下都只有一个位置。 -- 一条声明覆盖三种切换,因为这三者本就是同一个差异:Chat ↔ Trajectory、Chat 内部 transcript 较短 ↔ transcript 可滚动,以及 hero ↔ 第一个可滚动轮次。 +- 卡片在三种切换下保持同一位置,由两种机制达成:预留让 Chat 的座位在自身各相位间保持同一宽度(transcript 较短 ↔ 可滚动、hero ↔ 第一个可滚动轮次),Chat ↔ Trajectory 的切换则由覆盖座位的补偿来对齐([座位宽度补偿](2026-08-12-composer-overlay-seat-width-compensation.md))。 - overlay 状态现在是一个滚动容器。今天其中没有任何内容会溢出;将来若有视图允许自身内容超出会话列,这个盒子会滚动而不是裁剪,那个视图就需要像 Trajectory 视图那样自带裁剪。 - 提交的 golden 记录了预留条带,因此样式表中 `::-webkit-scrollbar` 宽度的变化——决定这条预留有多宽的那个值——会在本场景中与在侧边栏场景中一样,以可评审的 diff 形式出现。 @@ -45,6 +43,6 @@ overlay 状态是一个没有任何东西会去滚动它的滚动容器:视图 `apps/web/tests/composer-tab-geometry.e2e.ts` 在两个标签页下测量输入卡片的矩形,分别取卡片处于宽度上限的视口与卡片随列收缩的视口,并断言这两个矩形是同一个矩形。只有真实引擎能报告这件事:jsdom 给每个元素的盒子尺寸都是零,也没有滚动条,因此单元测试只能断言那些声明存在,无法断言两种状态落在同一位置。出于同一原因,本次没有附带读取 CSS 文本的单元测试——它只会把声明复述一遍,并不会补上浏览器车道尚未确立的事实。 -该场景启动 chromium 时去掉了 Playwright 默认的 `--hide-scrollbars`,这一点是承重的:带上该参数时滚动条不占任何布局宽度,两个标签页在改动前后同样一致,文件中的每一处比较都会空洞地通过。实测:带上该参数时,改动前的层叠让两条预留带的宽度都是 0;去掉它则分别是 8 与 0。 +该场景启动 chromium 时去掉了 Playwright 默认的 `--hide-scrollbars`,这一点是承重的:带上该参数时滚动条不占任何布局宽度,因此两个标签页在有补偿与无补偿时同样一致,文件中的每一处比较都会空洞地通过。实测:带上该参数时两条预留带的宽度都是 0;去掉它则分别是 8 与 0。 -随后,改动前的层叠会被注入页面——滚动容器上 `scrollbar-gutter: auto`,overlay 分支上 `overflow: hidden`——并在其下测量同样的两个标签页,这正是把「卡片确实没动」与「标签页切换根本没到达布局」区分开的那一步。它把上报的症状复现为一个数字:每条边 4px,恰是 8px 带宽的一半。golden 把这份对照与修复后的状态并排记录,因此 fixture(测试前置数据)承载的是这次改动所消除的那个差值,而不仅仅是它的缺席。 +随后,未补偿的级联会被注入页面——通过 `!important` 把覆盖座位的 `right` 补偿降为 0,Chat 的预留保持不变——并在其下测量同样的两个标签页,这正是把「卡片确实没动」与「标签页切换根本没到达布局」区分开的那一步。它把上报的症状复现为一个数字:每条边 4px,恰是 8px 带宽的一半。golden 把这份对照与修复后的状态并排记录,因此 fixture(测试前置数据)承载的是这次改动所消除的那个差值,而不仅仅是它的缺席。 diff --git a/.agents/notes/implemented/bug-fix/2026-08-04-large-history-pagination-call-stack.i18n.yaml b/.agents/notes/implemented/bug-fix/2026-08-04-large-history-pagination-call-stack.i18n.yaml new file mode 100644 index 0000000000..96fb51ced0 --- /dev/null +++ b/.agents/notes/implemented/bug-fix/2026-08-04-large-history-pagination-call-stack.i18n.yaml @@ -0,0 +1,6 @@ +# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each +# 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 .agents/notes/implemented/bug-fix/2026-08-04-large-history-pagination-call-stack.md +2026-08-04-large-history-pagination-call-stack.md: 28c22121123a227c507c506683ae727d238d98bd +2026-08-04-large-history-pagination-call-stack.zh.md: 57dde9bdc0a4aa52e1af024eb606bf9258430fa7 diff --git a/.agents/notes/implemented/bug-fix/2026-08-04-large-history-pagination-call-stack.md b/.agents/notes/implemented/bug-fix/2026-08-04-large-history-pagination-call-stack.md new file mode 100644 index 0000000000..28c2212112 --- /dev/null +++ b/.agents/notes/implemented/bug-fix/2026-08-04-large-history-pagination-call-stack.md @@ -0,0 +1,27 @@ +# Agent Note: Large history provenance is scanned without argument expansion + +Status: implemented + +English | [中文](2026-08-04-large-history-pagination-call-stack.zh.md) + +## Problem + +A finalized assistant message can reference hundreds of thousands of streamed chunks through `sourceEventSeqs`. History pagination found the message group's first event with `Math.min(event.seq, ...sourceEventSeqs)`, so a valid session could exceed the JavaScript engine's function-argument limit and make `session.history` fail with HTTP 500. + +## Decision + +Pagination scans `sourceEventSeqs` and updates the earliest sequence number one element at a time. The algorithm remains linear in the provenance size and preserves the existing page boundary: a page starts before all recorded sources of its oldest included message. + +A regression test rejects multi-argument minimum calls and verifies that every provenance event remains on the page with its finalized message. This exercises the failure mechanism without making the default test suite allocate a production-sized chunk stream. + +## Alternatives considered + +- **Raise the JavaScript stack or argument limit** — rejected: the limit is engine- and deployment-dependent, and array expansion still makes valid history depend on an unrelated runtime ceiling. +- **Truncate `sourceEventSeqs` during pagination** — rejected: this could cut a page inside a message and violate replay grouping. +- **Cap streamed chunk count at the provider boundary** — rejected: providers may legitimately emit long streams, and pagination must handle every valid session representation. + +## Consequences + +- Large provenance arrays no longer make history pagination throw solely because of their length. +- Pagination semantics and wire responses are unchanged. +- This does not bound the byte size of a history page or the browser cost of replaying it; those performance concerns remain separate from the server-side call-stack failure. diff --git a/.agents/notes/implemented/bug-fix/2026-08-04-large-history-pagination-call-stack.zh.md b/.agents/notes/implemented/bug-fix/2026-08-04-large-history-pagination-call-stack.zh.md new file mode 100644 index 0000000000..57dde9bdc0 --- /dev/null +++ b/.agents/notes/implemented/bug-fix/2026-08-04-large-history-pagination-call-stack.zh.md @@ -0,0 +1,27 @@ +# Agent Note: 大规模历史记录的溯源信息通过扫描处理,不做参数展开 + +Status: implemented + +[English](2026-08-04-large-history-pagination-call-stack.md) | 中文 + +## 问题 + +一条已定稿的 assistant 消息可以通过 `sourceEventSeqs` 引用数十万个流式分片。历史记录分页使用 `Math.min(event.seq, ...sourceEventSeqs)` 查找消息组的首个事件,因此,有效会话可能超出 JavaScript 引擎的函数参数数量上限,导致 `session.history` 以 HTTP 500 失败。 + +## 决策 + +分页逻辑逐项扫描 `sourceEventSeqs`,每次使用一个元素更新最早的序号。该算法的复杂度相对溯源信息规模仍为线性,并保留现有的页面边界:页面起点位于其所含最早消息的所有已记录来源之前。 + +回归测试会拒绝以多个参数调用取最小值的做法,并验证每个溯源事件都会与其已定稿消息保留在同一页中。这既覆盖了故障机制,也避免默认测试套件分配生产规模的分片流。 + +## 考虑过的替代方案 + +- **提高 JavaScript 栈或参数上限**:不予采纳,因为该上限取决于引擎和部署环境,而且数组展开仍会让有效历史记录受制于无关的运行时上限。 +- **在分页时截断 `sourceEventSeqs`**:不予采纳,因为这可能会从消息中间切分页面,破坏回放分组。 +- **在提供方边界限制流式分片数量**:不予采纳,因为提供方可能会合理地产生长流,而分页必须处理每一种有效的会话表示。 + +## 后果 + +- 大型溯源数组不再仅因长度而使历史记录分页抛出异常。 +- 分页语义与协议响应保持不变。 +- 本决策不限制历史记录页面的字节大小,也不限制浏览器回放该页面的开销;这两项性能问题仍与服务端调用栈故障分开处理。 diff --git a/.agents/notes/implemented/bug-fix/2026-08-10-minimal-preset-owns-rl-composition.i18n.yaml b/.agents/notes/implemented/bug-fix/2026-08-10-minimal-preset-owns-rl-composition.i18n.yaml index cca3debb14..0b27ea5d9f 100644 --- a/.agents/notes/implemented/bug-fix/2026-08-10-minimal-preset-owns-rl-composition.i18n.yaml +++ b/.agents/notes/implemented/bug-fix/2026-08-10-minimal-preset-owns-rl-composition.i18n.yaml @@ -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 .agents/notes/implemented/bug-fix/2026-08-10-minimal-preset-owns-rl-composition.md -2026-08-10-minimal-preset-owns-rl-composition.md: d83083de74f1d3203822d82e4e04560819412b48 -2026-08-10-minimal-preset-owns-rl-composition.zh.md: 36aeea0d8af6e371eddd6f09e36bb48a0348959e +2026-08-10-minimal-preset-owns-rl-composition.md: 65d24f9a03eedffac34f0c0141a8e2f643a48b7b +2026-08-10-minimal-preset-owns-rl-composition.zh.md: 72eaa0e5bba46743abd336e64316c886fa58631a diff --git a/.agents/notes/implemented/bug-fix/2026-08-10-minimal-preset-owns-rl-composition.md b/.agents/notes/implemented/bug-fix/2026-08-10-minimal-preset-owns-rl-composition.md index d83083de74..65d24f9a03 100644 --- a/.agents/notes/implemented/bug-fix/2026-08-10-minimal-preset-owns-rl-composition.md +++ b/.agents/notes/implemented/bug-fix/2026-08-10-minimal-preset-owns-rl-composition.md @@ -14,13 +14,13 @@ The split also hid other drift. The preset mounted one-shot Bash rather than the The shipped Web `minimal` preset is the sole Web owner of the RL agent composition. It declares an entry-local PTY registry and local backend, persistent `bash` with the RL environment description and 300-second timeout, and `str_replace_editor`. Tool presentation remains a deployment choice. The later [bare two-tool runtime decision](../feature/2026-08-11-minimal-profiles-bare-two-tool-runtime.md) supersedes this note's original compaction and filesystem-provider choices: the current preset mounts an entry-local `fs-local` provider and no compaction backend. The editor accepts no `requireAbsolutePath` setting because absolute paths are its unconditional contract. -The preset persona is exactly `You are a helpful software engineer assistant.` and sets `complete: true`. A complete `PromptSection` participates in ordinary assembly so tools, contexts, variables, and cooperative listeners still resolve; after the `system-prompt/assemble` waterfall, the prompt registry restores a detached copy of that section as the sole system-prompt section. Multiple effective complete sections reject assembly. This final registry constraint prevents harness identity, Web orientation, tool guidance, or an assembly listener from appending prompt text. +The preset persona is exactly `You are a helpful software engineer assistant.`, sets `complete: true`, and suppresses runtime context for its agent scope. A complete `PromptSection` participates in ordinary assembly so tools, variables, and cooperative listeners still resolve; after the `system-prompt/assemble` waterfall, the prompt registry restores a detached copy of that section as the sole system-prompt section and discards every dynamic context contribution. Multiple effective complete sections reject assembly. These final registry constraints prevent harness identity, Web orientation, tool guidance, an assembly listener, sandbox policy, approval policy, delegation, or another dynamic context provider from adding model input. The process-wide `core-web.cordis.yml` patch is absent. Browser UI, workspace attachment, persistence, subprocess, sandbox, permission, model routing, and other cross-session services remain host-owned. Selecting `minimal` changes one agent's model-facing composition and shadows the host filesystem provider only for that agent, without changing other sessions in the Web process. ## Verification -System-prompt and persona package tests prove final complete-section enforcement, including waterfall mutation and duplicate rejection. The shipped-preset composition test asserts the exact prompt, Bash description, absolute editor schema, and two-tool catalog under the default native presentation. The keyless Web replay sends a real request through a `minimal` agent while global identity, Web-orientation text, and a test section are registered, asserts the entry-local filesystem is bare and compaction is absent, then executes two persistent Bash calls to prove environment and cwd state survive and executes the editor through an absolute path. +System-prompt and persona package tests prove final complete-section and runtime-context suppression, including waterfall mutation and duplicate rejection. The shipped-preset composition test asserts the exact prompt, Bash description, absolute editor schema, and two-tool catalog under the default native presentation. The keyless Web replay sends a real request through a `minimal` agent while global identity, Web-orientation text, dynamic policy contexts, and a test section are registered, asserts that no runtime-context snapshot exists, the entry-local filesystem is bare, and compaction is absent, then executes two persistent Bash calls to prove environment and cwd state survive and executes the editor through an absolute path. The standalone [`minimal.cordis.yml`](../../../../examples/jsonrpc-agent/minimal.cordis.yml) is the complete two-tool composition for the bundled JSON-RPC runtime. The [bare two-tool runtime decision](../feature/2026-08-11-minimal-profiles-bare-two-tool-runtime.md) owns its launch-specific environment configuration, bare filesystem, and absence of compaction. Its keyless SDK replay asserts the assembled system prompt and two-tool catalog, executes persistent Bash across calls, and exercises the editor; the Python SDK tutorial provides the runnable entry point. diff --git a/.agents/notes/implemented/bug-fix/2026-08-10-minimal-preset-owns-rl-composition.zh.md b/.agents/notes/implemented/bug-fix/2026-08-10-minimal-preset-owns-rl-composition.zh.md index 36aeea0d8a..72eaa0e5bb 100644 --- a/.agents/notes/implemented/bug-fix/2026-08-10-minimal-preset-owns-rl-composition.zh.md +++ b/.agents/notes/implemented/bug-fix/2026-08-10-minimal-preset-owns-rl-composition.zh.md @@ -14,13 +14,13 @@ Status: implemented 随附的 Web `minimal` preset 是 RL agent 组合在 Web 中的唯一所有者。它声明 entry 本地的 PTY 注册表与本地后端、带 RL 环境描述且超时为 300 秒的持久 `bash`,以及 `str_replace_editor`。工具呈现仍由部署选择。后续的[裸双工具运行时决策](../feature/2026-08-11-minimal-profiles-bare-two-tool-runtime.md)取代了本记录最初的压缩与文件系统提供方选择:当前 preset 挂载 entry 本地的 `fs-local` 提供方,不挂载压缩后端。编辑器不接受 `requireAbsolutePath` 设置,因为要求绝对路径是它的无条件约定。 -preset persona 恰好是 `You are a helpful software engineer assistant.`,并设置 `complete: true`。complete `PromptSection` 参与常规组装,因此工具、上下文、变量和协作式监听器仍会解析;`system-prompt/assemble` waterfall(瀑布式事件)结束后,提示词注册表会将该段落的独立副本恢复为唯一的系统提示词段落。存在多个有效 complete 段时,组装会被拒绝。这项最终注册表约束可防止 harness 身份、Web 定位、工具引导或组装监听器追加提示词文本。 +preset persona 恰好是 `You are a helpful software engineer assistant.`,它设置 `complete: true`,并为其 agent 作用域抑制 runtime context。complete `PromptSection` 参与常规组装,因此工具、变量和协作式监听器仍会解析;`system-prompt/assemble` waterfall(瀑布式事件)结束后,提示词注册表会将该段落的独立副本恢复为唯一的系统提示词段落,并丢弃每个动态上下文贡献。存在多个有效 complete 段时,组装会被拒绝。这些最终注册表约束可防止 harness 身份、Web 定位、工具引导、组装监听器、沙箱策略、批准策略、委派或其他动态上下文提供方添加模型输入。 进程级 `core-web.cordis.yml` patch 不再存在。浏览器 UI、workspace 附加、持久化、子进程、沙箱、权限、模型路由及其他跨会话服务仍由宿主持有。选择 `minimal` 会改变一个 agent 面向模型的组合,并且仅为该 agent 遮蔽宿主文件系统提供方,不会改变 Web 进程中的其他会话。 ## 验证 -系统提示词与 persona 包测试证明了 complete 段的最终约束,包括 waterfall 修改与重复项拒绝。交付 preset 组合测试在默认原生呈现下断言精确的提示词、Bash 描述、要求绝对路径的编辑器 schema 和双工具目录。无密钥 Web 回放通过 `minimal` agent 发送一个真实请求,同时注册全局身份、Web 定位文本和一个测试段落;它断言 entry 本地文件系统是裸后端且压缩不存在,随后执行两次持久 Bash 调用,证明环境与 cwd 状态能够保留,并通过绝对路径执行编辑器。 +系统提示词与 persona 包测试证明了 complete 段最终约束与 runtime-context 抑制,包括 waterfall 修改与重复项拒绝。交付 preset 组合测试在默认原生呈现下断言精确的提示词、Bash 描述、要求绝对路径的编辑器 schema 和双工具目录。无密钥 Web 回放通过 `minimal` agent 发送一个真实请求,同时注册全局身份、Web 定位文本、动态策略上下文和一个测试段落;它断言不存在 runtime-context 快照、entry 本地文件系统是裸后端且压缩不存在,随后执行两次持久 Bash 调用,证明环境与 cwd 状态能够保留,并通过绝对路径执行编辑器。 独立的 [`minimal.cordis.yml`](../../../../examples/jsonrpc-agent/minimal.cordis.yml) 是内置 JSON-RPC 运行时的完整双工具组合。[裸双工具运行时决策](../feature/2026-08-11-minimal-profiles-bare-two-tool-runtime.md)说明其启动方式专属的环境配置、裸文件系统和无压缩选择。其无密钥 SDK 回放会断言组装后的系统提示词与双工具目录,跨调用执行持久 Bash,并使用编辑器;Python SDK 教程提供可运行的入口。 diff --git a/.agents/notes/implemented/bug-fix/2026-08-11-bounded-background-job-admission.i18n.yaml b/.agents/notes/implemented/bug-fix/2026-08-11-bounded-background-job-admission.i18n.yaml index 61be0dddfb..290ede1714 100644 --- a/.agents/notes/implemented/bug-fix/2026-08-11-bounded-background-job-admission.i18n.yaml +++ b/.agents/notes/implemented/bug-fix/2026-08-11-bounded-background-job-admission.i18n.yaml @@ -3,4 +3,4 @@ # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write .agents/notes/implemented/bug-fix/2026-08-11-bounded-background-job-admission.md 2026-08-11-bounded-background-job-admission.md: 8fa5bec07647947b730c436284da71b83deedb48 -2026-08-11-bounded-background-job-admission.zh.md: d827e07aacc7bc933474577214d94bab9fe5f5c3 +2026-08-11-bounded-background-job-admission.zh.md: 79e759041cbf9d6e12b444f47e9d9ef0aa218532 diff --git a/.agents/notes/implemented/bug-fix/2026-08-11-bounded-background-job-admission.zh.md b/.agents/notes/implemented/bug-fix/2026-08-11-bounded-background-job-admission.zh.md index d827e07aac..79e759041c 100644 --- a/.agents/notes/implemented/bug-fix/2026-08-11-bounded-background-job-admission.zh.md +++ b/.agents/notes/implemented/bug-fix/2026-08-11-bounded-background-job-admission.zh.md @@ -12,7 +12,7 @@ Status: implemented ## 决策 -`LocalJobRegistry` 拥有 `maxConcurrentJobsPerOwner` 配置字段。它只接受正的安全整数,默认值为 `10`,并通过 Service provider 的 Cordis schema、typed `agent-spine-demo` 组合包与 ACP 应用配置提供。组合包只传输该值;其含义归进程内 Service provider 所有。 +`LocalJobRegistry` 拥有 `maxConcurrentJobsPerOwner` 配置字段。它只接受正的安全整数,默认值为 `10`,并通过 Service Provider 的 Cordis schema、typed `agent-spine-demo` 组合包与 ACP 应用配置提供。组合包只传输该值;其含义归进程内 Service Provider 所有。 [通用任务运行时决策](../architecture/2026-06-20-generic-long-running-tool-runtime.md)拥有共享 Task 生命周期与控制 API;本记录只拥有进程内准入策略。 @@ -34,7 +34,7 @@ owner 与服务释放保留现有顺序:请求取消,在生产方释放资 ## 验证 -任务 Service provider 测试覆盖默认与显式上限、生产方执行前拒绝、id 计数器不变、`stopping` 占位、每种终态释放、确切 owner 隔离、同会话替代对象、共享无 owner 桶、非法配置、owner 清理和服务拆除。spine 与 ACP 组合测试固定 typed 转发。一条 keyless ACP 回放以 1 为上限启动真实 Loader 组合,启动一个真实后台 Bash 进程,观察第二次启动返回可操作错误,按返回的 job id 停止第一个任务,并验证被拒绝生产方的标记文件从未生成。 +任务 Service Provider 测试覆盖默认与显式上限、生产方执行前拒绝、id 计数器不变、`stopping` 占位、每种终态释放、确切 owner 隔离、同会话替代对象、共享无 owner 桶、非法配置、owner 清理和服务拆除。spine 与 ACP 组合测试固定 typed 转发。一条 keyless ACP 回放以 1 为上限启动真实 Loader 组合,启动一个真实后台 Bash 进程,观察第二次启动返回可操作错误,按返回的 job id 停止第一个任务,并验证被拒绝生产方的标记文件从未生成。 ## 曾考虑的替代方案 diff --git a/.agents/notes/implemented/bug-fix/2026-08-12-composer-overlay-seat-width-compensation.i18n.yaml b/.agents/notes/implemented/bug-fix/2026-08-12-composer-overlay-seat-width-compensation.i18n.yaml new file mode 100644 index 0000000000..a1904a4b03 --- /dev/null +++ b/.agents/notes/implemented/bug-fix/2026-08-12-composer-overlay-seat-width-compensation.i18n.yaml @@ -0,0 +1,6 @@ +# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each +# 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 .agents/notes/implemented/bug-fix/2026-08-12-composer-overlay-seat-width-compensation.md +2026-08-12-composer-overlay-seat-width-compensation.md: 0ec4d1272ac1adab5b724dccf44f567e15cc3368 +2026-08-12-composer-overlay-seat-width-compensation.zh.md: 2f66771240fe62e15c481342d55a82dd09cfb864 diff --git a/.agents/notes/implemented/bug-fix/2026-08-12-composer-overlay-seat-width-compensation.md b/.agents/notes/implemented/bug-fix/2026-08-12-composer-overlay-seat-width-compensation.md new file mode 100644 index 0000000000..0ec4d1272a --- /dev/null +++ b/.agents/notes/implemented/bug-fix/2026-08-12-composer-overlay-seat-width-compensation.md @@ -0,0 +1,39 @@ +# Agent Note: The overlay composer seat compensates for the bar instead of reserving a gutter + +Status: implemented + +English | [中文](2026-08-12-composer-overlay-seat-width-compensation.zh.md) + +## Problem + +The [composer-tab gutter reservation](2026-08-04-composer-tab-gutter-reservation.md) made the column's scroller reserve a scrollbar gutter unconditionally, so the composer seat measured the same width in Chat and in a view with a composer overlay. The cost was paid by every overlay view: the view's content column ended 8px short of the column's right edge, because the scroller reserved a gutter for a bar it never draws — the trajectory ledger owns its own scrollers and the outer box never scrolls. + +The trajectory table made that cost visible: its full-width row divider lines stopped 8px short of the pane edge, leaving a strip of whitespace at the right of every line and of the whole content column. + +## Decision + +The reservation now belongs to Chat alone. The overlay branch declares `scrollbar-gutter: auto`, so the view's content spans the full column; the overlay composer seat (absolutely positioned against the padding box) gives back the bar's width with `right: var(--dsh-scrollbar-width)`, so the input card still measures the same width as Chat's seat and does not move between tabs. + +The compensation value is not a literal: ui-theme's scrollbar.css defines `--dsh-scrollbar-width` (8px on the WebKit path) beside the `::-webkit-scrollbar` rule it mirrors, and the seat reads that variable. The scrollbar-styles spec pairs the variable with the mirrored rule and with the compensation consumer, so a change to the sheet's bar width without the variable — or to the variable without the consumer — fails the gate, not just review. + +## Alternatives considered + +**Keep the unconditional reservation and shrink every overlay view.** The pre-fix behavior. It keeps one declaration for both tabs but taxes every overlay view with an 8px content column, which the trajectory ledger surfaced as visible whitespace. Rejected because the overlay views own their scrolling; they should not pay for Chat's bar. + +**Reserve on the overlay branch too and let the view bleed into the gutter.** More moving parts for the same result: the gutter would still exist on a box that never scrolls, and the view would have to break out of the content box to reclaim its width. + +**Accept the 4px card shift.** Dropping the reservation without compensating the seat would move the input card on every tab switch, which is exactly the symptom the earlier note fixed. Rejected: the card position is a deliberate cross-tab invariant. + +**Inset the overlay seat by the bar's width.** The [gutter-reservation note](2026-08-04-composer-tab-gutter-reservation.md) rejected exactly this, and this note adopts it; what changed is the rejection's premise. The number was the engine's, not ours — the WebKit path draws the sheet's 8px bar while the Firefox path draws whatever `scrollbar-width: thin` resolves to — so a hardcoded inset would line the two states up in Chromium and drift elsewhere. The overlay branch reserved an engine-resolved gutter of its own back then, so an inset had to match that width exactly. Today the overlay branch reserves nothing, so the compensation is the overlay side's only mechanism, and the literal half of the rejection is answered by making the 8px a variable that mirrors the `::-webkit-scrollbar` rule in the same diff. The Firefox half remains: Chat reserves the engine-resolved width while the compensation stays fixed, and the residual drift where the two differ is recorded as an accepted cost in Consequences. + +## Consequences + +- Chat keeps its reserved gutter and its stable card position; nothing changes on that tab. +- Overlay views (trajectory) span the full column; the trajectory ledger's divider lines reach the pane edge. +- The input card still holds one horizontal position across the Chat and Trajectory tabs, now by two mechanisms instead of one: Chat reserves, the overlay seat compensates. +- Chat reserves the engine-resolved width while the overlay seat compensates a fixed 8px. Where the two differ — the Firefox path resolves `scrollbar-width: thin` per platform, and the e2e runs only on Chromium — the card drifts by half the difference on tab switch. Accepted residual cost, recorded here rather than asserted away: no measurement of the Firefox thin width on the target platforms exists in this change. +- `--dsh-scrollbar-width` becomes a public ui-theme variable read outside ui-theme; the scrollbar-styles spec pairs it with the mirrored `::-webkit-scrollbar` width rule and with the compensation consumer, closing the indirection-gate gap the variable would otherwise leave. + +## Testing + +`apps/web/tests/composer-tab-geometry.e2e.ts` still asserts the card holds its position across tabs and now also asserts the split: Chat's scroller keeps `scrollbar-gutter: stable` and a nonzero band, while the overlay branch resolves `auto` with a zero band. The control cascade changed with the mechanism: it now drops the seat's `right` compensation (instead of dropping a gutter Chat never had on that branch) and measures the same 4px shift, proving the equal rectangles are not a tab switch that never reached layout. The committed golden records both states. diff --git a/.agents/notes/implemented/bug-fix/2026-08-12-composer-overlay-seat-width-compensation.zh.md b/.agents/notes/implemented/bug-fix/2026-08-12-composer-overlay-seat-width-compensation.zh.md new file mode 100644 index 0000000000..2f66771240 --- /dev/null +++ b/.agents/notes/implemented/bug-fix/2026-08-12-composer-overlay-seat-width-compensation.zh.md @@ -0,0 +1,39 @@ +# Agent Note: 覆盖视图的 composer 座位改为补偿滚动条宽度,不再预留滚动条槽 + +Status: implemented + +[English](2026-08-12-composer-overlay-seat-width-compensation.md) | 中文 + +## 问题 + +[composer 标签页滚动条槽预留](2026-08-04-composer-tab-gutter-reservation.md) 让会话列滚动容器无条件预留一条滚动条槽,使 composer 座位在 Chat 与带 composer 覆盖的视图中测得相同宽度。代价由每个覆盖视图承担:视图内容列比列右边缘窄 8px,因为滚动容器为一条它从不绘制的滚动条预留了槽——trajectory 台账由视图内部自己的滚动容器滚动,外层盒子从不滚动。 + +trajectory 表格让这个代价显形:整行分隔线在面板右边缘前 8px 处停止,每条线右侧以及整个内容列右侧都留下一条空白带。 + +## 决策 + +预留现在只属于 Chat。覆盖分支声明 `scrollbar-gutter: auto`,视图内容占满整列;覆盖分支的 composer 座位(相对 padding box 绝对定位)用 `right: var(--dsh-scrollbar-width)` 让出滚动条宽度,使输入卡仍与 Chat 座位测得相同宽度,切换标签页时不移动。 + +补偿值不是字面量:ui-theme 的 scrollbar.css 在它镜像的 `::-webkit-scrollbar` 规则旁定义 `--dsh-scrollbar-width`(WebKit 路径 8px),座位读取该变量。scrollbar-styles 规格把该变量与其镜像规则、以及补偿消费者配对检查,因此样式表滚动条宽度一变却不同步变量——或变量一变却不同步消费者——都会让门禁失败,而不只是评审时发现。 + +## 备选方案 + +**保留无条件预留,压缩每个覆盖视图。** 修复前行为。两个标签页一条声明,但每个覆盖视图都要付出 8px 内容列,trajectory 台账将其显现为可见空白。已拒绝:覆盖视图自己滚动,不应为 Chat 的滚动条买单。 + +**覆盖分支也预留,并让视图渗入滚动条槽。** 同样结果下更多活动部件:从不滚动的盒子上仍存在滚动条槽,视图还得突破内容盒才能取回宽度。 + +**接受 4px 卡片位移。** 去掉预留却不补偿座位,会在每次切换标签页时移动输入卡——正是前一份 note 修复的症状。已拒绝:卡片位置是刻意保持的跨标签页不变量。 + +**把 overlay 座位按滚动条宽度内缩。** [滚动条槽预留 note](2026-08-04-composer-tab-gutter-reservation.md) 当初否决的正是这个方案,本 note 采纳了它;变的是否决的前提。这个数字属于引擎而不属于我们——WebKit 路径绘制样式表里的 8px 滚动条,Firefox 路径绘制 `scrollbar-width: thin` 解析出的宽度——因此硬编码的内缩会让两种状态在 Chromium 上对齐、在别处继续漂移。当初 overlay 分支自己预留的是引擎解析出的槽宽,内缩必须精确匹配那个宽度。如今 overlay 分支不预留任何槽位,补偿成为覆盖侧唯一的机制;否决的字面量那一半,通过把 8px 变成与 `::-webkit-scrollbar` 规则同处一个 diff 的变量来回应。Firefox 那一半仍然存在:Chat 预留引擎解析宽度,补偿保持固定 8px,两者不等之处的残余漂移作为接受的代价记录在后果中。 + +## 后果 + +- Chat 保留滚动条槽与稳定的卡片位置;该标签页无任何变化。 +- 覆盖视图(trajectory)占满整列;trajectory 台账的分隔线到达面板右边缘。 +- 输入卡在 Chat 与 Trajectory 标签页间仍保持同一水平位置,现在由两种机制而非一种达成:Chat 预留,覆盖座位补偿。 +- Chat 预留引擎解析宽度,覆盖座位补偿固定的 8px。两者不等之处——Firefox 路径按平台解析 `scrollbar-width: thin`,而 e2e 只在 Chromium 上运行——卡片在切换标签页时会漂移半个差值。这是接受的残余代价,如实记录于此而不断言消除:本次改动并未提供目标平台 Firefox thin 宽度的实测。 +- `--dsh-scrollbar-width` 成为 ui-theme 对外、且被 ui-theme 之外读取的变量;scrollbar-styles 规格把它与镜像的 `::-webkit-scrollbar` 宽度规则、以及补偿消费者配对检查,补上了该变量本会留下的间接层门禁缺口。 + +## 测试 + +`apps/web/tests/composer-tab-geometry.e2e.ts` 仍断言输入卡在标签页间保持位置,并新增断言拆分:Chat 滚动容器保持 `scrollbar-gutter: stable` 与非零槽宽,覆盖分支解析为 `auto` 且槽宽为零。控制级联随机制改变:现在移除座位的 `right` 补偿(而非移除该分支上 Chat 从未有过的槽),测得同样的 4px 位移,证明相等的矩形并非从未到达布局的标签页切换。提交的 golden 记录两种状态。 diff --git a/.agents/notes/implemented/bug-fix/2026-08-12-fix-pwsh-terminal-overlay-dup.i18n.yaml b/.agents/notes/implemented/bug-fix/2026-08-12-fix-pwsh-terminal-overlay-dup.i18n.yaml new file mode 100644 index 0000000000..1c650cc79c --- /dev/null +++ b/.agents/notes/implemented/bug-fix/2026-08-12-fix-pwsh-terminal-overlay-dup.i18n.yaml @@ -0,0 +1,6 @@ +# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each +# 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 .agents/notes/implemented/bug-fix/2026-08-12-fix-pwsh-terminal-overlay-dup.md +2026-08-12-fix-pwsh-terminal-overlay-dup.md: 7a214ea093faf49141c66bfc2cbb065fbeb29825 +2026-08-12-fix-pwsh-terminal-overlay-dup.zh.md: 6d38ca58ad97e5ad04992e54a7938c9fea300863 diff --git a/.agents/notes/implemented/bug-fix/2026-08-12-fix-pwsh-terminal-overlay-dup.md b/.agents/notes/implemented/bug-fix/2026-08-12-fix-pwsh-terminal-overlay-dup.md new file mode 100644 index 0000000000..7a214ea093 --- /dev/null +++ b/.agents/notes/implemented/bug-fix/2026-08-12-fix-pwsh-terminal-overlay-dup.md @@ -0,0 +1,55 @@ +# Agent Note: fix the pwsh terminal overlay duplicate-loader collision + +Status: implemented + +English | [中文](2026-08-12-fix-pwsh-terminal-overlay-dup.zh.md) + +## Problem + +`apps/web/tests/pwsh-terminal.e2e.ts` fails on every platform with `TypeError: duplicate loader entry id: tool-pwsh`, thrown from `vendor/loader/src/config/group.ts:64` while applying the web composition. The failing seed lane boots the full shipped bundle plus a test overlay, so the E2E never reaches its rendering assertion and every `check:ci:snapshot`/`test:web` run reports a red web test even though the feature under test is unrelated to the change under review. + +The web E2E scaffold applies an `extraOverlayPath` after the shipped Web surface and base patches. `pwsh-terminal.overlay.yml` used an `insert` block to add a `tool-pwsh` row: + +```yaml +- insert: + - id: pwsh-local + name: '@deepseek-ai/dsh-pwsh-local' + - id: tool-pwsh + name: '@deepseek-ai/dsh-tool-pwsh' +``` + +`insert` is correct only while `tool-pwsh` is absent from the composition. The id exists because `86b6979bdc` (refactor(bundle): fold the Windows shell platform layer into the base rows) moved both shell stacks into the base bundle with inverted platform gates — `packages/bundle/base/cordis.patch.yml` declares `tool-pwsh` with `disabled: !!js process.platform !== 'win32'`, so the row is present in the composition on every platform. Later, `42fc7c5ffb` (refactor(preset): gate tool-pwsh by platform alongside tool-bash) added a web-app patch row that disables `tool-pwsh` for surfaces that use presets; a patch row cannot introduce an id, so it is not the source of the collision. The overlay's `insert` delivers a second row with the same id in the same loader group, and the loader rejects the pair at boot. + +## Decision + +Replace the overlay's `insert` of `tool-pwsh` with a top-level id-targeted override: + +```yaml +- id: tool-pwsh + name: '@deepseek-ai/dsh-tool-pwsh' + disabled: false +``` + +The effective `tool-pwsh` state is a three-layer stack: the base row gates `disabled` on `process.platform !== 'win32'`, the web-app overlay sets `disabled: true` unconditionally for preset surfaces, and this lane's override clears it back to `disabled: false` regardless of platform. An `id`-targeted top-level override replaces the composed row; only an `insert` would collide. + +The lane also now disables `pwsh-sandbox` by id, symmetric with the existing `bash-sandbox` disable: the base gates `pwsh-sandbox` with `disabled: !!js process.platform !== 'win32'`, so on Windows it would otherwise mount beside the inserted `pwsh-local` and both would register the same executor service. Disabling it keeps `pwsh-local` the lone executor on every platform. + +The overlay header comment was updated to describe the full selection and the `tool-pwsh` inline comment now names the base row as the source of the id. + +## Alternatives considered + +**Keep the `insert` and change the web composition instead.** Rejected, because the shipped web composition should keep the host `tool-pwsh` row disabled for every surface that uses presets; the overlay is the lane that deliberately needs it, so the by-id enable belongs there. The base row itself cannot be removed either: it is the platform-gated shell-stack declaration shared by every bundle. + +**Enable `tool-pwsh` in the `insert` block.** Not possible: an `insert` of an id that already exists is the very duplicate being fixed. The row must be targeted by id, which is the top-level override form, not `insert`. + +**Patch `tool-pwsh` by id without setting `disabled: false`.** Insufficient: the web-app overlay sets `disabled: true` unconditionally, and the base row's platform gate only applies where the web-app override is absent, so an override that only restates `name` leaves the row disabled and the lane renders no terminal card. The `disabled: false` is required. + +**Only disable `bash-sandbox` and rely on the platform gate to keep `pwsh-sandbox` off.** Rejected: that holds on POSIX but breaks on Windows, where the base row leaves `pwsh-sandbox` enabled and it would collide with the inserted `pwsh-local` on the shared executor service. The lane's `pwsh-sandbox` disable keeps one executor on every platform. + +## Verification + +Reverting the fix (restoring the `insert` of `tool-pwsh`) reproduces the exact `duplicate loader entry id: tool-pwsh` boot failure, confirming the override is load-bearing. With the fix in place `pwsh-terminal.e2e.ts` passes 2/2 on the same head — this exercises the POSIX seam, where the seeded pwsh call renders through the enabled `tool-pwsh` and the inserted `pwsh-local`. The seed lane requires a usable `pwsh`, so it skips on hosts without one; a `pwsh` binary is present on this machine and the test ran. The Windows path (base `pwsh-sandbox` mounted beside the inserted `pwsh-local`) is not exercised by any CI lane, whose `test:web` runs only on Linux; the overlay disables `pwsh-sandbox` to keep that path composable if it ever runs on a Windows dev machine. + +## Consequences + +The web E2E seed lane that exercises PowerShell boot now composes instead of colliding, so `check:ci:snapshot` and `test:web` stop failing on the duplicate independently of the change under test. The pattern is general: a `--patch`/`extraOverlayPath` overlay must probe whether a row already exists in the bundle it augments before choosing `insert` over an id-targeted override; `insert` of an id that the base or shipped Web surface already declares is a boot-time duplicate. diff --git a/.agents/notes/implemented/bug-fix/2026-08-12-fix-pwsh-terminal-overlay-dup.zh.md b/.agents/notes/implemented/bug-fix/2026-08-12-fix-pwsh-terminal-overlay-dup.zh.md new file mode 100644 index 0000000000..6d38ca58ad --- /dev/null +++ b/.agents/notes/implemented/bug-fix/2026-08-12-fix-pwsh-terminal-overlay-dup.zh.md @@ -0,0 +1,55 @@ +# Agent Note:修复 pwsh 终端 overlay 的重复 loader 冲突 + +Status: implemented + +[English](2026-08-12-fix-pwsh-terminal-overlay-dup.md) | 中文 + +## Problem + +`apps/web/tests/pwsh-terminal.e2e.ts` 在所有平台上都以 `TypeError: duplicate loader entry id: tool-pwsh` 失败,由 `vendor/loader/src/config/group.ts:64` 在应用 web 组合时抛出。该失败的 seed 通道会启动完整发布的 bundle 加一个测试 overlay,因此 E2E 永远到不了渲染断言,导致 `check:ci:snapshot` 与 `test:web` 每次运行都报一个红的 web 测试,即便被测功能与评审中的改动无关。 + +web E2E scaffold 在已发布的 Web 表面与 base patches 之后应用 `extraOverlayPath`。`pwsh-terminal.overlay.yml` 用 `insert` 块新增 `tool-pwsh` 行: + +```yaml +- insert: + - id: pwsh-local + name: '@deepseek-ai/dsh-pwsh-local' + - id: tool-pwsh + name: '@deepseek-ai/dsh-tool-pwsh' +``` + +`insert` 仅在组合中不存在 `tool-pwsh` 时才正确。该 id 存在是因为 `86b6979bdc`(refactor(bundle): fold the Windows shell platform layer into the base rows)把两套 shell 栈以互逆的平台门移进了 base bundle —— `packages/bundle/base/cordis.patch.yml` 声明 `tool-pwsh` 且 `disabled: !!js process.platform !== 'win32'`,于是该行在每个平台都存在于组合中。随后 `42fc7c5ffb`(refactor(preset): gate tool-pwsh by platform alongside tool-bash)往 web-app patch 里加了一行对使用 preset 的表面禁用 `tool-pwsh` 的行;patch 不能引入 id,因此它不是冲突来源。overlay 的 `insert` 于是在同一个 loader 组里再送一个同 id 的行,loader 在启动时拒绝这对重复。 + +## Decision + +把 overlay 对 `tool-pwsh` 的 `insert` 替换成顶层按 id override: + +```yaml +- id: tool-pwsh + name: '@deepseek-ai/dsh-tool-pwsh' + disabled: false +``` + +有效的 `tool-pwsh` 状态是三层栈:base 行把 `disabled` 门在 `process.platform !== 'win32'` 上,web-app overlay 对 preset 表面无条件设 `disabled: true`,本通道的 override 无论平台都把 `disabled: false` 还回去。`id` 定位的顶层 override 替换组合后的行;只有 `insert` 才会相撞。 + +该通道现在也按 id 禁用 `pwsh-sandbox`,与既有的 `bash-sandbox` 禁用对称:base 以 `disabled: !!js process.platform !== 'win32'` 门住 `pwsh-sandbox`,因此在 Windows 上它本会与插入的 `pwsh-local` 并存,两者会注册同一个 executor 服务。禁用它让 `pwsh-local` 在每个平台上都是唯一 executor。 + +overlay 头部注释已更新为完整描述选择,`tool-pwsh` 行内注释现在把 base 行标为该 id 的来源。 + +## Alternatives considered + +**保留 `insert`、改 web 组合。** 拒绝。已发布的 web 组合应在所有使用 preset 的表面上保持 host `tool-pwsh` 行禁用;overlay 才是那条刻意需要该行的通道,因此按 id 启用应放在那里。base 行本身也不能移除:它是所有 bundle 共享的平台门 shell 栈声明。 + +**在 `insert` 块里启用 `tool-pwsh`。** 不可行。对已存在的 id 做 `insert` 正是这里要修的重复。该行必须按 id 定位,即顶层 override 形式,而非 `insert`。 + +**只按 id 改 `tool-pwsh` 而不设 `disabled: false`。** 不充分。web-app 无条件设 `disabled: true`,base 行的平台门只在 web-app override 缺失处生效,因此只重申 `name` 的 override 会让行保持禁用,通道渲染不出终端卡。`disabled: false` 是必需的。 + +**只禁用 `bash-sandbox`、依赖平台门让 `pwsh-sandbox` 保持关闭。** 拒绝。在 POSIX 上成立,但在 Windows 上会失败:base 行让 `pwsh-sandbox` 启用,它会与插入的 `pwsh-local` 在共享 executor 服务上相撞。本通道禁用 `pwsh-sandbox` 让每个平台只有唯一 executor。 + +## Verification + +把修复还原(恢复对 `tool-pwsh` 的 `insert`)即复现同样的 `duplicate loader entry id: tool-pwsh` 启动失败,证实 override 是有效的。修复后同一 head 上 `pwsh-terminal.e2e.ts` 2/2 通过 —— 这作用于 POSIX seam,播种的 pwsh 调用经启用的 `tool-pwsh` 与插入的 `pwsh-local` 渲染出来。该 seed 通道需要可用的 `pwsh`,无此二进制的主机会跳过;本机有 `pwsh`,测试实际跑过。Windows 路径(base `pwsh-sandbox` 与插入的 `pwsh-local` 并存)没有任何 CI lane 覆盖,其 `test:web` 只在 Linux 上跑;overlay 禁用 `pwsh-sandbox` 让该路径在真到 Windows 开发机运行时可组合。 + +## Consequences + +用于执行 PowerShell 启动的 web E2E seed 通道现在能组合而非相撞,因此 `check:ci:snapshot` 与 `test:web` 不再与被测改动无关地在该 duplicate 上失败。该模式具有通用性:`--patch`/`extraOverlayPath` overlay 在决定用 `insert` 还是按 id override 之前,必须探测目标 bundle 是否已存在该行;对已由 base 或已发布 Web 表面声明的 id 做 `insert`,是启动期重复。 diff --git a/.agents/notes/implemented/bug-fix/2026-08-12-resolve-store-pwsh-aliases.i18n.yaml b/.agents/notes/implemented/bug-fix/2026-08-12-resolve-store-pwsh-aliases.i18n.yaml new file mode 100644 index 0000000000..140c7b9ae7 --- /dev/null +++ b/.agents/notes/implemented/bug-fix/2026-08-12-resolve-store-pwsh-aliases.i18n.yaml @@ -0,0 +1,6 @@ +# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each +# 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 .agents/notes/implemented/bug-fix/2026-08-12-resolve-store-pwsh-aliases.md +2026-08-12-resolve-store-pwsh-aliases.md: 20fe58e15e75462dc0a9ba76c7a1a94939f8a004 +2026-08-12-resolve-store-pwsh-aliases.zh.md: bbfa4616127a9dbdb6609fe2973283663de55b31 diff --git a/.agents/notes/implemented/bug-fix/2026-08-12-resolve-store-pwsh-aliases.md b/.agents/notes/implemented/bug-fix/2026-08-12-resolve-store-pwsh-aliases.md new file mode 100644 index 0000000000..20fe58e15e --- /dev/null +++ b/.agents/notes/implemented/bug-fix/2026-08-12-resolve-store-pwsh-aliases.md @@ -0,0 +1,23 @@ +# Agent Note: Resolve Microsoft Store pwsh aliases + +Status: implemented + +English | [中文](2026-08-12-resolve-store-pwsh-aliases.zh.md) + +## Problem + +`resolvePwshPath` documented that Microsoft Store installs resolve through PATH, but its existence probe was `existsSync`, which stats a candidate and therefore follows reparse points. The Store's `%LOCALAPPDATA%\Microsoft\WindowsApps\pwsh.exe` is an app execution alias whose target directory ACL refuses stat (EACCES), so `existsSync` missed it and resolution silently fell through to Windows PowerShell 5.1 on hosts whose only PowerShell 7 is a Store install. + +## Decision + +`candidateExists` accepts a candidate that stats as a file or that lstat sees as a link-shaped reparse point, and `resolvePwshPath` uses it. Spawning the alias path works because CreateProcess resolves app execution aliases. A dangling link-shaped candidate is accepted so a broken pwsh fails loudly at spawn instead of silently downgrading to 5.1. + +## Alternatives considered + +**Probe the WindowsApps package directory directly.** The Store package path is versioned and ACL-hidden; hard-coding it duplicates packaging knowledge that PATH plus the alias already owns. + +**Keep the 5.1 fallback for stat failures.** Rejected: it silently runs a different shell than the one installed, which is the defect this note fixes. + +## Consequences + +Store-installed PowerShell 7 now resolves ahead of the 5.1 fallback on Windows; real-file candidates and non-Windows behavior are unchanged. The dangling-symlink unit test pins the stat/lstat split on every platform. diff --git a/.agents/notes/implemented/bug-fix/2026-08-12-resolve-store-pwsh-aliases.zh.md b/.agents/notes/implemented/bug-fix/2026-08-12-resolve-store-pwsh-aliases.zh.md new file mode 100644 index 0000000000..bbfa461612 --- /dev/null +++ b/.agents/notes/implemented/bug-fix/2026-08-12-resolve-store-pwsh-aliases.zh.md @@ -0,0 +1,23 @@ +# Agent Note: 解析 Microsoft Store 的 pwsh 别名 + +Status: implemented + +[English](2026-08-12-resolve-store-pwsh-aliases.md) | 中文 + +## 问题 + +`resolvePwshPath` 声称 Store 安装经 PATH 解析,但它的存在性探测用的是 `existsSync`,会对候选做 stat、从而跟随重解析点。Store 的 `%LOCALAPPDATA%\Microsoft\WindowsApps\pwsh.exe` 是 app execution alias,其目标目录的 ACL 拒绝 stat(EACCES),于是 `existsSync` 看不到它,解析静默落到 Windows PowerShell 5.1——在这类「唯一的 PowerShell 7 是 Store 安装」的机器上就用了错误的 shell。 + +## 决策 + +`candidateExists` 接受「stat 为文件」或「lstat 为链接形态重解析点」的候选,`resolvePwshPath` 改用它。spawn 别名路径可以工作,因为 CreateProcess 会解析 app execution alias。悬空的链接形态候选同样被接受,让损坏的 pwsh 在 spawn 时响亮失败,而不是静默降级到 5.1。 + +## 考虑过的替代方案 + +**直接探测 WindowsApps 包目录。** Store 包路径带版本且被 ACL 隐藏;硬编码它只是重复了 PATH 加别名已经拥有的打包知识。 + +**对 stat 失败继续走 5.1 回退。** 否决:它静默运行了一个并非所装的 shell,这正是本 note 修复的缺陷。 + +## 后果 + +Windows 上 Store 安装的 PowerShell 7 现在先于 5.1 回退被解析;普通文件候选和非 Windows 平台行为不变。悬空 symlink 单元测试在全部平台上钉住 stat/lstat 的分裂行为。 diff --git a/.agents/notes/implemented/bug-fix/2026-08-12-unlink-fixture-junctions-before-delete.i18n.yaml b/.agents/notes/implemented/bug-fix/2026-08-12-unlink-fixture-junctions-before-delete.i18n.yaml new file mode 100644 index 0000000000..160f947daa --- /dev/null +++ b/.agents/notes/implemented/bug-fix/2026-08-12-unlink-fixture-junctions-before-delete.i18n.yaml @@ -0,0 +1,6 @@ +# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each +# 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 .agents/notes/implemented/bug-fix/2026-08-12-unlink-fixture-junctions-before-delete.md +2026-08-12-unlink-fixture-junctions-before-delete.md: 4514a33d728866b817f4e9c1393f16c07976ed45 +2026-08-12-unlink-fixture-junctions-before-delete.zh.md: 3c212c052ab0303ccb8d31d2b310a365a1d8cc99 diff --git a/.agents/notes/implemented/bug-fix/2026-08-12-unlink-fixture-junctions-before-delete.md b/.agents/notes/implemented/bug-fix/2026-08-12-unlink-fixture-junctions-before-delete.md new file mode 100644 index 0000000000..4514a33d72 --- /dev/null +++ b/.agents/notes/implemented/bug-fix/2026-08-12-unlink-fixture-junctions-before-delete.md @@ -0,0 +1,23 @@ +# Agent Note: Unlink fixture junctions before recursive deletion + +Status: implemented + +English | [中文](2026-08-12-unlink-fixture-junctions-before-delete.zh.md) + +## Problem + +The install-lefthook and translation-pairing fixtures junction the repository's real `scripts/`, `node_modules`, and tsx package directories into fixture trees so installer probes resolve through them. Windows recursive deletion can treat a junction (a MOUNT_POINT reparse point) as a directory and follow it into its target; Git's `worktree remove` did exactly that and deleted the repository's tracked `scripts/` and tsx package (the incident's instrumentation pinned the deletion to that step). A fixture cleanup that trusts its deleter therefore deletes the repository's own sources instead of the fixture. + +## Decision + +`scripts/test-fixture-cleanup.ts` owns junction-safe fixture teardown: `unlinkFixtureLinks` walks a tree and unlinks every reparse point before `removeFixtureSafely` removes the now link-free tree (with Windows async-handle retries). Every affected `afterEach` and the pre-`worktree remove` hook call it. The general rule lives in `docs/defensive-patterns.md`: remove link-shaped paths with unlink, reserve recursive `rmSync` for known real directories. + +## Alternatives considered + +**Trust recursive deletion alone.** Rejected: whether a given deleter follows junctions is tool- and version-dependent, and one path through `git worktree remove` already destroyed tracked files; no cleanup may bet the repository on that behavior. + +**Copy instead of junctioning the real directories.** Rejected: the fixtures exist to probe the real installer paths through their real contents, so copies would stop exercising the boundary under test. + +## Consequences + +Fixture teardown can no longer reach repository sources through junctions. The extra walk is one lstat/unlink pass over small fixture trees. The data-destroying defect now has its durable why beside the defensive-patterns rule, and the helper is the shared teardown path for future junction fixtures. diff --git a/.agents/notes/implemented/bug-fix/2026-08-12-unlink-fixture-junctions-before-delete.zh.md b/.agents/notes/implemented/bug-fix/2026-08-12-unlink-fixture-junctions-before-delete.zh.md new file mode 100644 index 0000000000..3c212c052a --- /dev/null +++ b/.agents/notes/implemented/bug-fix/2026-08-12-unlink-fixture-junctions-before-delete.zh.md @@ -0,0 +1,23 @@ +# Agent Note: 递归删除前先解链 fixture junction + +Status: implemented + +[English](2026-08-12-unlink-fixture-junctions-before-delete.md) | 中文 + +## 问题 + +install-lefthook 与 translation-pairing 的 fixture 把仓库真实的 `scripts/`、`node_modules` 和 tsx 包目录用 junction 链进 fixture 树,让 installer 探测能穿透解析。Windows 的递归删除可能把 junction(MOUNT_POINT 重解析点)当作目录并跟随进其目标;Git 的 `worktree remove` 正是这样删掉了仓库被跟踪的 `scripts/` 和 tsx 包(事故的插桩把删除定位到这一步)。因此,信任删除器的 fixture 清理删掉的是仓库自己的源码,而不是 fixture。 + +## 决策 + +`scripts/test-fixture-cleanup.ts` 拥有 junction 安全的 fixture 拆除:`unlinkFixtureLinks` 先遍历并解链所有重解析点,`removeFixtureSafely` 再删除已无链接的树(带 Windows 异步句柄重试)。所有受影响的 `afterEach` 和 `worktree remove` 前的钩子都调用它。通用规则记录在 `docs/defensive-patterns.md`:链接形态的路径用 unlink 删除,递归 `rmSync` 只留给确知为真实目录的路径。 + +## 考虑过的替代方案 + +**只信任递归删除。** 否决:特定删除器是否跟随 junction 随工具和版本而异,而 `git worktree remove` 这一条路径已经摧毁过被跟踪文件;任何清理都不该拿仓库去赌这个行为。 + +**复制而不是 junction 真实目录。** 否决:fixture 的意义就是用真实内容探测真实 installer 路径,复制品会失去被测边界。 + +## 后果 + +fixture 拆除不再能穿过 junction 触及仓库源码。额外开销只是对小型 fixture 树的一趟 lstat/unlink。这个摧毁数据的缺陷现在在 defensive-patterns 规则旁有了持久化的原因,helper 也是未来所有 junction fixture 共享的拆除路径。 diff --git a/.agents/notes/implemented/bug-fix/2026-08-12-unlink-stale-profile-fallback-links.i18n.yaml b/.agents/notes/implemented/bug-fix/2026-08-12-unlink-stale-profile-fallback-links.i18n.yaml new file mode 100644 index 0000000000..0e53f1c748 --- /dev/null +++ b/.agents/notes/implemented/bug-fix/2026-08-12-unlink-stale-profile-fallback-links.i18n.yaml @@ -0,0 +1,6 @@ +# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each +# 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 .agents/notes/implemented/bug-fix/2026-08-12-unlink-stale-profile-fallback-links.md +2026-08-12-unlink-stale-profile-fallback-links.md: 32959eb1b83bcc290d1daa4e4a020a2721be489b +2026-08-12-unlink-stale-profile-fallback-links.zh.md: 1f4da12748c9b57c12bf41a740001d5df770beb6 diff --git a/.agents/notes/implemented/bug-fix/2026-08-12-unlink-stale-profile-fallback-links.md b/.agents/notes/implemented/bug-fix/2026-08-12-unlink-stale-profile-fallback-links.md new file mode 100644 index 0000000000..32959eb1b8 --- /dev/null +++ b/.agents/notes/implemented/bug-fix/2026-08-12-unlink-stale-profile-fallback-links.md @@ -0,0 +1,25 @@ +# Agent Note: Unlink stale profile fallback links instead of rmSync + +Status: implemented + +English | [中文](2026-08-12-unlink-stale-profile-fallback-links.zh.md) + +## Problem + +`healProfilesModuleFallback` re-points `$DSH_HOME/profiles/node_modules` entries when an installation moves, and Windows hosts keep those entries as junctions. `ensureSymlink` deleted a stale entry with `rmSync(link)`, but Node treats a junction as a directory for removal: without `recursive`, `rmSync` throws `ERR_FS_EISDIR`, so every launch from a moved installation or a second worktree crashed before booting. The `replaces a wrong symlink` unit test reproduces that crash on Windows at the exact removal call. + +## Decision + +`ensureSymlink` removes a stale link with `unlinkSync(link)`. `unlink` deletes the reparse point or symlink itself on every platform and never descends into the target, which preserves the function's fail-loud guarantee that a real directory is never deleted. The [profile-plugin-bundles decision](../architecture/2026-08-05-profile-plugin-bundles.md) keeps owning the fallback's two-anchor resolution; this note owns only the removal primitive. + +## Alternatives considered + +**`rmSync(link, { recursive: true })`.** On Node 24 this deletes the junction without following its target, but `recursive` would silently delete a real directory that replaced the link between the `lstat` guard and the removal, weakening the fail-loud contract that motivates the guard. + +**`rmdirSync(link)`.** Removes a junction on Windows as well, but it reads as directory removal for a link, and `unlinkSync` is the repository's existing junction-cleanup idiom. + +**Delete and recreate every entry unconditionally.** Correct but churns unchanged links on every launch and widens the concurrent-heal race window. + +## Consequences + +Windows launches heal moved or second-checkout installations instead of crashing with `ERR_FS_EISDIR`; POSIX behavior is unchanged because `unlinkSync` also unlinks plain symlinks. The existing `replaces a wrong symlink` test now passes on Windows where it previously reproduced the crash. Two concurrent healers deleting the same stale link still surface the second deletion as `ENOENT`, unchanged from the previous `rmSync` implementation. diff --git a/.agents/notes/implemented/bug-fix/2026-08-12-unlink-stale-profile-fallback-links.zh.md b/.agents/notes/implemented/bug-fix/2026-08-12-unlink-stale-profile-fallback-links.zh.md new file mode 100644 index 0000000000..1f4da12748 --- /dev/null +++ b/.agents/notes/implemented/bug-fix/2026-08-12-unlink-stale-profile-fallback-links.zh.md @@ -0,0 +1,25 @@ +# Agent Note: 用 unlink 删除过期的 profile 回退链接而非 rmSync + +Status: implemented + +[English](2026-08-12-unlink-stale-profile-fallback-links.md) | 中文 + +## 问题 + +`healProfilesModuleFallback` 在安装位置迁移时会把 `$DSH_HOME/profiles/node_modules` 中的条目重新指向新目标,而 Windows 主机上这些条目是 junction。`ensureSymlink` 原先用 `rmSync(link)` 删除过期条目,但 Node 在删除时把 junction 当作目录处理:不带 `recursive` 的 `rmSync` 会抛 `ERR_FS_EISDIR`,于是从迁移后的安装或第二个 worktree 启动时,每次都会在应用引导前崩溃。`replaces a wrong symlink` 单元测试在 Windows 上正好在该删除调用处复现了这一崩溃。 + +## 决策 + +`ensureSymlink` 改用 `unlinkSync(link)` 删除过期链接。`unlink` 在所有平台上都只删除重解析点或符号链接本身、绝不进入目标目录,从而保住该函数“真实目录永远不会被删除”的大声失败保证。[profile-plugin-bundles 决策](../architecture/2026-08-05-profile-plugin-bundles.md)继续拥有回退目录的双锚点解析;本 note 只拥有“用哪个删除原语”这一决定。 + +## 考虑过的替代方案 + +**`rmSync(link, { recursive: true })`。** Node 24 上它只删 junction、不跟随目标,但 `recursive` 会在 `lstat` 守卫与删除之间链接被替换成真实目录时静默删除该目录,削弱守卫存在所依据的大声失败契约。 + +**`rmdirSync(link)`。** Windows 上同样能删 junction,但它读起来像“删目录”,而 `unlinkSync` 才是仓库现有的 junction 清理惯例。 + +**无条件删除并重建所有条目。** 正确,但每次启动都翻动未变化的链接,并扩大并发修复的竞态窗口。 + +## 后果 + +Windows 启动现在可以修复迁移后的安装或第二个 checkout,而不是以 `ERR_FS_EISDIR` 崩溃;POSIX 行为不变,因为 `unlinkSync` 同样能 unlink 普通符号链接。现有的 `replaces a wrong symlink` 测试在 Windows 上从复现崩溃变为通过。两个并发 healer 删除同一过期链接时,第二次删除仍会以 `ENOENT` 浮现,与原先的 `rmSync` 实现一致。 diff --git a/.agents/notes/implemented/bug-fix/2026-08-13-bounded-cold-blank-verification.i18n.yaml b/.agents/notes/implemented/bug-fix/2026-08-13-bounded-cold-blank-verification.i18n.yaml new file mode 100644 index 0000000000..2cd2577fc5 --- /dev/null +++ b/.agents/notes/implemented/bug-fix/2026-08-13-bounded-cold-blank-verification.i18n.yaml @@ -0,0 +1,6 @@ +# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each +# 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 .agents/notes/implemented/bug-fix/2026-08-13-bounded-cold-blank-verification.md +2026-08-13-bounded-cold-blank-verification.md: bf8d167d742001ce65b3e96713a9603adb19603e +2026-08-13-bounded-cold-blank-verification.zh.md: 7cfef77a02308a8e75281877f8a774b41bb9559d diff --git a/.agents/notes/implemented/bug-fix/2026-08-13-bounded-cold-blank-verification.md b/.agents/notes/implemented/bug-fix/2026-08-13-bounded-cold-blank-verification.md new file mode 100644 index 0000000000..bf8d167d74 --- /dev/null +++ b/.agents/notes/implemented/bug-fix/2026-08-13-bounded-cold-blank-verification.md @@ -0,0 +1,37 @@ +# Agent Note: Bound cold blank-session verification + +Status: implemented + +English | [中文](2026-08-13-bounded-cold-blank-verification.zh.md) + +## Problem + +The Web session tree hides blank Sessions and reuses the selected blank entry as New Session. Attached Sessions can derive blankness from their in-memory event log, but `session.list` normally avoids loading every cold log. Treating every materialized cold Session as non-blank exposes empty Sessions left by older versions. Treating a projection-cache `blank: true` as current can instead hide a real conversation after the log advances and the fail-soft cache remains stale. + +The same cold list used the JSONL artifact mtime for `updatedAt`. Opening a Session appends `session/end-seed`, so a pickup with no human prompt refreshed mtime and promoted that Session above recently used conversations. + +## Decision + +`dsh-host-apiproxy` registers `sessionListMetadata`, a projection containing `blank` and `lastPromptAt`. The attached summary folds the same functions directly over the live log. `blank` changes only from true to false on `turn/start`; `lastPromptAt` changes only on a `user/message` whose source kind is `user`. + +A cold summary trusts cached `blank: false`, because a checkpoint prefix containing `turn/start` remains non-blank. Cached `blank: true` and a cache miss do not prove the current log is blank. When persistence exposes a physical artifact through `locate()` and its observed size is at most the `coldBlankProbeMaxBytes` eligibility threshold (default 1 KiB per Session), the gateway calls `readFrom(id, 0)` and folds exact list metadata from the stored prefix. Files above the threshold, backends without a location, vanished artifacts, and failed reads all produce `blank: false`, keeping the Session visible. + +`updatedAt` is the later of `createdAt` and `lastPromptAt`. An eligible artifact read supplies exact `lastPromptAt` at no additional I/O cost; other cache misses or stale checkpoints order the Session too old rather than promoting it from an unrelated file write. After each asynchronous cold read, the gateway checks the live store again and replaces the cold result with an attached summary when another request resumed that Session meanwhile. + +## Alternatives considered + +**Trust cached `blank: true`.** Rejected because the projection cache deliberately permits a persisted log to advance beyond its checkpoint. A crash or fail-soft write failure after the first `turn/start` would hide a real conversation and could make the client reuse it as New Session. + +**Read every cold log.** Rejected because list latency and I/O would scale with total stored conversation bytes. The physical-size eligibility check targets small historical artifacts that can be checked cheaply and degrades larger unknowns toward visibility. It intentionally does not add a persistence operation solely to make the threshold atomic with the read: concurrent growth may increase one probe's read cost, but the additional events can only preserve visibility or change a blank result to non-blank. + +**Store blankness and recency in an authoritative persistence index.** Deferred because JSONL has an immutable first line and would require a second durable artifact with ordered updates, while SQLite would require a schema field. The broader exact-index design remains in the [last-activity proposal](../../proposed/architecture/2026-07-29-durable-last-activity-index.md). + +**Continue ordering JSONL by mtime.** Rejected because mtime records every artifact write, including pickup boundaries, rather than the latest human prompt. Its error direction promotes untouched Sessions to the front. + +## Consequences + +Existing small blank JSONL artifacts are hidden without depending on projection-cache availability, and a stale cache cannot hide a stored `turn/start`. A cold list may read each artifact whose observed physical size is within the configured threshold when its cache does not already prove non-blank. The default threshold compares compressed bytes for the shipped Zstandard JSONL backend. + +Blank artifacts above the threshold and blank Sessions on location-less backends remain visible. Missing or delayed recency cache entries for artifacts that are not read fall back to `createdAt`. These are conservative degradations: the UI may show an extra empty row or order a Session too low, but it does not hide a conversation or promote one because it was merely opened. + +The gateway-owned projection is an effect of the gateway fiber; unloading the gateway removes the key. Unit coverage pins exact-threshold eligibility, stale-true rejection, monotonic false reuse, exact small-log recency, live-attachment races, fallback direction, human-prompt recency, and fiber disposal. A keyless Web snapshot boots the shipped compressed JSONL composition, seeds a small cold blank artifact without a cache row, and verifies that the sidebar omits it. diff --git a/.agents/notes/implemented/bug-fix/2026-08-13-bounded-cold-blank-verification.zh.md b/.agents/notes/implemented/bug-fix/2026-08-13-bounded-cold-blank-verification.zh.md new file mode 100644 index 0000000000..7cfef77a02 --- /dev/null +++ b/.agents/notes/implemented/bug-fix/2026-08-13-bounded-cold-blank-verification.zh.md @@ -0,0 +1,37 @@ +# Agent Note: 有界验证冷空白会话 + +Status: implemented + +[English](2026-08-13-bounded-cold-blank-verification.md) | 中文 + +## Problem + +Web 会话树会隐藏空白 Session,并把当前选中的空白项复用为 New Session。已附加 Session 可以从内存事件日志派生空白状态,但 `session.list` 通常不会加载每一份冷日志。把所有已物化的冷 Session 都视为非空,会暴露旧版本留下的空 Session;反过来,把 projection cache 中的 `blank: true` 当成当前事实,则可能在日志已经前进而 fail-soft cache 仍然陈旧时隐藏真实对话。 + +同一份冷列表还曾用 JSONL 工件的 mtime 作为 `updatedAt`。打开 Session 会追加 `session/end-seed`,因此即使没有真人 prompt,单纯拾起也会刷新 mtime,并把该 Session 提升到最近使用的对话之前。 + +## Decision + +`dsh-host-apiproxy` 注册 `sessionListMetadata` 投影,其中包含 `blank` 与 `lastPromptAt`。已附加摘要直接用同一组函数折叠实时日志。`blank` 只在 `turn/start` 时从 true 单调变为 false;`lastPromptAt` 只在来源 kind 为 `user` 的 `user/message` 上更新。 + +冷摘要信任缓存的 `blank: false`,因为已包含 `turn/start` 的 checkpoint 前缀会始终保持非空。缓存的 `blank: true` 和 cache miss 都无法证明当前日志为空。当 persistence 通过 `locate()` 暴露物理工件,且其观测大小不超过 `coldBlankProbeMaxBytes` 资格阈值(默认每个 Session 1 KiB)时,网关调用 `readFrom(id, 0)`,从已存前缀折叠精确列表元数据。超过阈值的文件、不提供位置的后端、已消失的工件和读取失败都产生 `blank: false`,让 Session 保持可见。 + +`updatedAt` 取 `createdAt` 与 `lastPromptAt` 中较晚者。符合资格的工件读取无需额外 I/O 即可提供精确 `lastPromptAt`;其他 cache miss 或陈旧 checkpoint 只会让 Session 排得偏旧,而不会因无关的文件写入被提升。每次异步冷读取后,网关都会再次检查实时 store;若另一请求期间已恢复该 Session,则用已附加摘要替换冷结果。 + +## Alternatives considered + +**信任缓存的 `blank: true`。** 拒绝,因为 projection cache 有意允许持久日志前进到 checkpoint 之后。首个 `turn/start` 之后若发生崩溃或 fail-soft 写入失败,真实对话就会被隐藏,客户端还可能把它复用为 New Session。 + +**读取每一份冷日志。** 拒绝,因为列表延迟与 I/O 会随所有已存对话的总字节数增长。物理大小资格检查只针对能够低成本核验的小型历史工件,更大的未知项则向保持可见降级。该检查有意不为“让阈值与读取原子化”单独新增 persistence 操作:并发增长可能增加一次探测的读取成本,但新增事件只会保持可见,或把空白结果改为非空。 + +**把空白状态与最近时间存入权威 persistence index。** 暂缓,因为 JSONL 的首行不可变,需要增加带有顺序写入要求的第二份持久工件;SQLite 则需要 schema 字段。更广泛的精确索引设计仍由[最后活动提案](../../proposed/architecture/2026-07-29-durable-last-activity-index.md)负责。 + +**继续按 mtime 排序 JSONL。** 拒绝,因为 mtime 记录包括拾起边界在内的每一次工件写入,而非最近真人 prompt;其错误方向会把未经操作的 Session 提升到列表开头。 + +## Consequences + +既有的小型空白 JSONL 工件无需依赖 projection cache 是否存在即可被隐藏,陈旧 cache 也无法隐藏已存的 `turn/start`。对于 cache 尚不能证明非空,且观测物理大小在配置阈值内的每个 Session,冷列表可能读取其工件。对默认交付的 Zstandard JSONL 后端,该阈值比较压缩后的字节数。 + +超过阈值的空白工件,以及来自不提供位置的后端的空白 Session 会保持可见。对于未被读取的工件,缺失或延迟的最近时间 cache 会回退到 `createdAt`。这些都是保守降级:UI 可能多显示一条空记录,或把 Session 排得偏低,但不会隐藏真实对话,也不会因为单纯打开而把会话提升到前面。 + +网关自有投影是网关 fiber 的 effect;卸载网关会移除该 key。单元覆盖固定了临界大小资格、拒绝陈旧 true、复用单调 false、小日志精确最近时间、实时附加竞态、回退方向、真人 prompt 最近时间和 fiber 销毁。无密钥 Web snapshot 会启动发行版的压缩 JSONL 组合,在没有 cache row 的情况下播种一份小型冷空白工件,并验证侧栏不展示它。 diff --git a/.agents/notes/implemented/bug-fix/2026-08-13-oauth-only-providers-withheld.i18n.yaml b/.agents/notes/implemented/bug-fix/2026-08-13-oauth-only-providers-withheld.i18n.yaml new file mode 100644 index 0000000000..f5765160ac --- /dev/null +++ b/.agents/notes/implemented/bug-fix/2026-08-13-oauth-only-providers-withheld.i18n.yaml @@ -0,0 +1,6 @@ +# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each +# 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 .agents/notes/implemented/bug-fix/2026-08-13-oauth-only-providers-withheld.md +2026-08-13-oauth-only-providers-withheld.md: 8c85c2900fd0af7c97a3ac8f04d3c6a2f469f8b0 +2026-08-13-oauth-only-providers-withheld.zh.md: 8f05d096a5d474407585bcbd84bd47da8a1abb2e diff --git a/.agents/notes/implemented/bug-fix/2026-08-13-oauth-only-providers-withheld.md b/.agents/notes/implemented/bug-fix/2026-08-13-oauth-only-providers-withheld.md new file mode 100644 index 0000000000..8c85c2900f --- /dev/null +++ b/.agents/notes/implemented/bug-fix/2026-08-13-oauth-only-providers-withheld.md @@ -0,0 +1,43 @@ +# Agent Note: The configurable-provider directory withholds OAuth-only providers + +Status: implemented + +English | [中文](2026-08-13-oauth-only-providers-withheld.zh.md) + +## Problem + +The Models page offered `openai-codex` like any other pi-ai route, with the placeholder every pi-ai provider carries: enter a key, or leave it blank to authenticate from the environment. Configuring it that way and sending a message failed the turn with `Provider is not configured: openai-codex`, reported as the adapter's catch-all `PI_AI_ERROR`. + +The posture the placeholder invited could not work on that route. pi-ai's `resolveProviderAuth` reaches an OAuth provider through one path — a credential already in the collection's `CredentialStore` — and has no ambient fallback for it, while `openai-codex` is the one installed provider declaring `auth.oauth` with no `auth.apiKey` beside it. `PiAiAdapter.current()` constructs its collection with `createModels()` and no options, so the store is pi-ai's default `InMemoryCredentialStore`: empty at every boot, and rebuilt from scratch each time a configuration change produces a new snapshot. No code here runs `Models.login()`, and pi-ai's library half does not read Codex's own `~/.codex/auth.json` either — its OAuth module is a PKCE login flow whose credential the *host* application persists, which is what the pi CLI supplies and this adapter does not. + +So the page advertised, with the keyless posture its own placeholder describes, a provider that has no keyless posture — and the failure named the configuration key rather than the missing capability. The one thing that does authenticate the route is a ChatGPT OAuth token pasted into the key field, which is not what the offer describes and expires with nothing here to refresh it. + +## Decision + +The directory offers only what this adapter can authenticate. `catalogProviderTakesApiKey(provider)` answers whether pi-ai's installed provider for a route declares an api-key method — the one method the harness can feed, since it resolves a key through its own credential seam and hands it over as the request's `apiKey` override — and `directoryEntries()` skips the catalog routes that fail it. + +OAuth support is not attempted. It needs a persistent credential store, a login flow, and a surface to run it from; none of those is a release-blocking fix, and shipping the offer without them is what produced the report. + +Two boundaries keep the withholding narrow: + +- **Catalog membership is unchanged.** `catalogProviderIds()` still answers what pi-ai ships, so the `declared` flag on a directory entry keeps meaning "no installed provider answers for this route" rather than "this route is not offered". +- **The profile half of the union is unconditional.** A route a settings document already names keeps its entry, so a stored `openai-codex` profile stays visible, editable, and deletable instead of being stranded in the document with nothing on the page to remove it. + +Resolution is untouched. A profile naming `apiKeyEnv` on an OAuth-only route still builds a working provider — `routeAuth` adds the harness api-key method beside the catalog's OAuth, and pi-ai's Codex API derives the account id from the token itself — so a deployment that writes one into `settings.yaml` or `cordis.yml` keeps that path. Enforcing the withholding in `resolveProfiles` instead would have refused such a profile at registration, and because `validate` runs at boot as well as at write time, a document already naming a keyless OAuth route would fail the whole namespace's registration rather than one provider. + +## Alternatives considered + +- **Rejecting a keyless OAuth-only route in `resolveProfiles`.** This is where the repo normally enforces a decision, and the directory filter is a surface that a `cordis.yml` entry bypasses. It was refused for the boot behavior above: an existing stored profile would take down every other route in the namespace with it, which for a release trades a one-provider defect for a total one. The gap is that the offer, not the capability, is what got fixed — a deployment can still hand-write the route it can no longer add from the page. +- **Keeping the offer and correcting only the placeholder text.** The field would then have to say the provider needs a login this build cannot run, which is a card whose only honest content is that it does not work. +- **Mapping `Provider is not configured` to a named `LlmError`.** Worth doing, and reachable for reasons this change does not remove — any api-key route left blank whose provider finds nothing in the process environment produces the same message. Deferred as a separate change: it improves a diagnostic rather than removing a broken offer. +- **Reading `~/.codex/auth.json` into a pi-ai `CredentialStore`.** It makes Codex work without a login flow, and pi-ai owns the refresh. It also binds the harness to another tool's private file format for one provider, which is a decision for the OAuth work rather than a release fix. + +## Consequences + +`openai-codex` disappears from the provider picker and from the directory the Models page joins; every other installed provider is unaffected, including the six that offer OAuth *beside* an api-key method (`anthropic`, `github-copilot`, `kimi-coding`, `openrouter`, `radius`, `xai`), which keep their entries and their key path. A future provider that ships OAuth alone is withheld automatically rather than by name. + +Two adjacent gaps remain and are recorded in the package README: a route naming no credential still resolves through the catalog provider's own discovery, which reads process environment variables only — not `~/.aws/credentials`, and not the harness credential seam — and the resulting failure is still the catch-all `PI_AI_ERROR`. + +## Testing + +Package tests pin both halves of the union: the withheld route is absent from `listConfigurableProviders()` while `anthropic` and `openai` stay, and a stored `openai-codex` profile still produces a full entry with `declared: false`. The existing resolution tests are unchanged and still pass, which is what shows the withholding did not narrow what a hand-written profile can serve. The `models-settings` and `onboarding-usable-provider` web e2e goldens lost exactly the `openai-codex` option line, recorded against the real assembled application. diff --git a/.agents/notes/implemented/bug-fix/2026-08-13-oauth-only-providers-withheld.zh.md b/.agents/notes/implemented/bug-fix/2026-08-13-oauth-only-providers-withheld.zh.md new file mode 100644 index 0000000000..8f05d096a5 --- /dev/null +++ b/.agents/notes/implemented/bug-fix/2026-08-13-oauth-only-providers-withheld.zh.md @@ -0,0 +1,43 @@ +# Agent Note:可配置提供方目录不再提供仅以 OAuth 认证的提供方 + +Status: implemented + +[English](2026-08-13-oauth-only-providers-withheld.md) | 中文 + +## 问题 + +模型设置页把 `openai-codex` 当作普通 pi-ai 路由提供出来,配的还是每个 pi-ai 提供方共用的那句占位文案:填入 API 密钥,或留空使用环境认证。照此配置后发送消息,本轮以 `Provider is not configured: openai-codex` 失败,并被适配器归入兜底的 `PI_AI_ERROR`。 + +占位文案所邀请的那种配置姿态在这条路由上不可能工作。pi-ai 的 `resolveProviderAuth` 抵达 OAuth 提供方只有一条路径——集合的 `CredentialStore` 里已经存着的凭据——对它没有任何 ambient 回退;而 `openai-codex` 正是已安装 catalog 中唯一只声明 `auth.oauth`、没有 `auth.apiKey` 的提供方。`PiAiAdapter.current()` 以不带参数的 `createModels()` 构造集合,于是用的是 pi-ai 默认的 `InMemoryCredentialStore`:每次启动都是空的,每次配置变更产生新快照时又重建一份。本仓库没有任何位置调用 `Models.login()`;pi-ai 库这一半也不会去读 Codex 自己的 `~/.codex/auth.json`——它的 OAuth 模块是一套 PKCE 登录流程,凭据由*宿主*应用持久化,这正是 pi CLI 提供、而本适配器没有提供的东西。 + +于是页面用自己占位文案所描述的「留空」姿态,提供了一个根本没有「留空」姿态的提供方——而失败信息指向的是配置键,不是缺失的能力。唯一能让这条路由完成认证的,是把一个 ChatGPT OAuth token 粘进密钥框,那既不是这个提供所描述的用法,也会过期且这里没有任何环节会去刷新它。 + +## 决策 + +目录只提供本适配器认得的东西。`catalogProviderTakesApiKey(provider)` 回答 pi-ai 为某路由安装的提供方是否声明了 api-key 方法——这是 harness 唯一能供给的方法,因为它通过自己的凭据 seam 解析密钥,再作为请求的 `apiKey` 覆盖交给 pi-ai——`directoryEntries()` 跳过不满足它的 catalog 路由。 + +不尝试实现 OAuth。它需要持久化凭据存储、登录流程,以及运行登录的界面;这三样都不是发布阻塞项的修复,而在它们缺席时仍把提供方摆出来,正是这次报告的成因。 + +两条边界把「不提供」的范围收窄: + +- **catalog 成员身份不变。** `catalogProviderIds()` 仍回答 pi-ai 装了什么,因此目录条目上的 `declared` 标记仍然表示「没有已安装提供方对应这条路由」,而不是「这条路由不被提供」。 +- **联合的 profile 那一半无条件保留。** settings 文档已经写过的路由保留条目,因此已存储的 `openai-codex` profile 仍然可见、可编辑、可删除,而不会滞留在文档里、页面上却没有任何入口能移除它。 + +resolution 未被触动。在仅 OAuth 的路由上指定 `apiKeyEnv` 的 profile 仍会构造出可用的提供方——`routeAuth` 会在 catalog 的 OAuth 旁边补上 harness 的 api-key 方法,而 pi-ai 的 Codex API 从 token 本身推导 account id——因此把它写进 `settings.yaml` 或 `cordis.yml` 的部署保留这条路径。改为在 `resolveProfiles` 里强制拒绝会在注册时就否掉这类 profile;又因为 `validate` 在启动时与写入时同样运行,一份已经写有无密钥 OAuth 路由的文档会让整个 namespace 注册失败,而不只是一个提供方失败。 + +## 备选方案 + +- **在 `resolveProfiles` 里拒绝无密钥的仅 OAuth 路由。** 这才是本仓库通常强制决策的位置,而目录过滤是一层 `cordis.yml` entry 可以绕过的表面。因上述启动行为被否决:已存储的 profile 会连带拖垮该 namespace 中其他所有路由,对一次发布而言,这是拿一个提供方的缺陷换取全体的缺陷。留下的缺口是:被修的是「提供」而不是「能力」——部署仍可手写一条页面上已经无法添加的路由。 +- **保留提供,只修正占位文案。** 那么该输入框只能写「此提供方需要本构建无法运行的登录」,等于一张唯一诚实内容就是「它不能用」的卡片。 +- **把 `Provider is not configured` 映射成具名 `LlmError`。** 值得做,而且触发原因本次改动并未消除——任何留空密钥、其提供方又在进程环境里找不到东西的 api-key 路由,都会产生同一句话。作为独立改动暂缓:它改进的是诊断,而不是移除一个坏掉的提供。 +- **把 `~/.codex/auth.json` 读进 pi-ai 的 `CredentialStore`。** 这能让 Codex 在没有登录流程的情况下可用,刷新也由 pi-ai 负责。但它为一个提供方把 harness 绑定到另一个工具的私有文件格式上,这属于 OAuth 那项工作的决策,而不是发布期的修复。 + +## 影响 + +`openai-codex` 从提供方选择器、以及模型设置页所 join 的目录中消失;其余已安装提供方一概不受影响,包括在 api-key 方法*之外*另提供 OAuth 的那六个(`anthropic`、`github-copilot`、`kimi-coding`、`openrouter`、`radius`、`xai`),它们保留条目也保留密钥路径。将来若出现只带 OAuth 的提供方,会被自动排除,而不是靠列名。 + +两处相邻缺口仍在,并记录在包 README 中:不指定凭据的路由仍走 catalog 提供方自带的发现,而它只读进程环境变量——不读 `~/.aws/credentials`,也不读 harness 凭据 seam——且由此产生的失败仍是兜底的 `PI_AI_ERROR`。 + +## 测试 + +包测试钉住联合的两半:不予提供的路由不出现在 `listConfigurableProviders()` 中,而 `anthropic` 与 `openai` 仍在;已存储的 `openai-codex` profile 仍产出完整条目且 `declared: false`。既有的 resolution 测试未改动且依然通过,这正是「不提供」没有收窄手写 profile 可服务范围的证据。`models-settings` 与 `onboarding-usable-provider` 两条 web e2e golden 恰好各少了 `openai-codex` 这一行选项,录自真实装配的应用。 diff --git a/.agents/notes/implemented/bug-fix/2026-08-13-safari-textarea-soft-wrap-reflow.i18n.yaml b/.agents/notes/implemented/bug-fix/2026-08-13-safari-textarea-soft-wrap-reflow.i18n.yaml new file mode 100644 index 0000000000..f7fde5254a --- /dev/null +++ b/.agents/notes/implemented/bug-fix/2026-08-13-safari-textarea-soft-wrap-reflow.i18n.yaml @@ -0,0 +1,6 @@ +# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each +# 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 .agents/notes/implemented/bug-fix/2026-08-13-safari-textarea-soft-wrap-reflow.md +2026-08-13-safari-textarea-soft-wrap-reflow.md: fb264a8e6fbe24369584f2427bbb0c462b450ecf +2026-08-13-safari-textarea-soft-wrap-reflow.zh.md: 7f55a5260e825059e1f9a08db03f13e19484d14e diff --git a/.agents/notes/implemented/bug-fix/2026-08-13-safari-textarea-soft-wrap-reflow.md b/.agents/notes/implemented/bug-fix/2026-08-13-safari-textarea-soft-wrap-reflow.md new file mode 100644 index 0000000000..fb264a8e6f --- /dev/null +++ b/.agents/notes/implemented/bug-fix/2026-08-13-safari-textarea-soft-wrap-reflow.md @@ -0,0 +1,47 @@ +# Agent Note: Safari textarea soft-wrap shrink recovery + +Status: implemented + +English | [中文](2026-08-13-safari-textarea-soft-wrap-reflow.zh.md) + +## Problem + +The composer keeps the caret and selection in a transparent native textarea while the backdrop paints visible glyphs and the hidden mirror determines the full draft height. The [single-scrollport decision](2026-07-31-composer-text-layers-share-one-scrollport.md) therefore depends on the textarea owning no scrollable overflow: after every draft commit, its `scrollHeight` and `clientHeight` are equal and its `scrollTop` is zero. + +Safari 26.5.2 can retain the textarea's former native line layout when Backspace moves a draft across a soft-wrap threshold at the same time that React updates the mirror. In the reproduced two-line-to-one-line transition, the mirror, backdrop, grow stack, and textarea box all become 28px high, but the textarea still reports `scrollHeight=52` and `scrollTop=20`. The caret remains in the stale native line while the backdrop correctly paints one line. + +The `color` declaration is not a layout input. Changing its inline style changes the computed color but leaves the stale `52/28/20` state intact. Editing the stylesheet rule happens to trigger broader rule invalidation and clears the state to `28/28/0`, which explains why Web Inspector makes the declaration appear causal. + +## Decision + +`InputBar` detects Safari once from the Apple vendor and the `Version/... Safari/...` user-agent form, while rejecting known alternate iOS browser tokens such as `CriOS`, `FxiOS`, `EdgiOS`, and `OPiOS`. A browser shell indistinguishable through these identity fields still has to violate the textarea overflow invariant before the recovery mutates layout. + +The native textarea change handler records whether an edit shortens the controlled draft. After that draft commits, a layout effect returns without reading geometry unless both the cached Safari identity and the native-shrink signal are present. It then checks the single-scrollport invariant: equal `scrollHeight` and `clientHeight` are settled and trigger no forced layout. A mismatch first changes the textarea's real height by one pixel, forces layout, restores the owned height, and forces layout again. This rebuilds Safari's native text-control layout without changing the value, selection, IME state, or undo transaction. + +The temporary native overflow can leave the draft scrollport's auto height at the former line count even after the textarea is correct. The recovery therefore repeats the one-pixel invalidation on `[data-input-scroll]` after repairing the textarea. Both elements return to their owned styles before paint; the settled one-line state is `scrollHeight=clientHeight=28`, `scrollTop=0`, and a 28px scrollport. + +## Verification + +Component tests synthesize Safari's stale metrics, assert the textarea-then-scrollport invalidation order, preserve selection, and prove that a growing native draft reads no geometry. Browser-identity tests cover desktop and mobile Safari, desktop Chromium, Chrome, Edge, and Opera on iOS, and an Apple web view. + +The assembled package is also exercised in Safari 26.5.2 through the native 51-character-to-50-character Backspace path. Playwright WebKit 26.5 settles correctly without the workaround in both the assembled app and a reduced page, so the repository's Chromium browser lane cannot reproduce this Safari application defect; the focused component test pins the engine state until an automatable Safari lane exists. + +## Alternatives considered + +**Change `color` or use `-webkit-text-fill-color`.** Rejected because inline color changes and transparent text fill leave the stale native geometry unchanged. Stylesheet-rule editing works only because its invalidation scope is broader than the declaration's paint semantics. + +**Set `scrollTop=0`.** Rejected because it moves the stale native content without rebuilding its two-line `scrollHeight`; the caret can become clipped instead of aligned. + +**Rewrite the textarea value.** Clearing and restoring the value rebuilds Safari's text control, but it mutates the editing state that owns IME composition and selection. The height invalidation leaves the value untouched. + +**Use `field-sizing: content`.** Rejected because Safari reproduces the stale two-line intrinsic height after the same deletion, and the composer still needs the mirror as the caret ruler and backdrop metric peer. + +**Invalidate only the textarea or only the scrollport.** Rejected because the textarea-only recovery clears `52/28/20` but can leave the scrollport at 52px, while the scrollport-only recovery leaves the textarea's native overflow untouched. The ordered pair is the smallest complete recovery. + +**Check geometry after every Safari draft commit.** Rejected because reading `scrollHeight` or `clientHeight` after React changes the mirror can synchronously lay out even a healthy growing draft. A native shortening signal limits the invariant read to edits that can produce the observed shrink defect. + +**Run the recovery in every browser.** Rejected because Chromium, Playwright WebKit, and Firefox maintain the invariant without forced layouts. The Safari identity and observed mismatch jointly bound the synchronous work. + +## Consequences + +Non-Safari browsers, programmatic draft updates, and native edits that do not shorten the draft perform no geometry read. A native Safari shortening reads the overflow invariant and pays the four forced layouts only when the textarea violates it. The exceptional path accepts rare local work before paint to preserve caret alignment, native editing semantics, and the single scrolling box. An equivalent stale state caused only by resize or sidebar width changes has not been observed and is outside this recovery trigger. The browser test gap remains explicit: real Safari evidence owns the engine defect, while deterministic component coverage owns the recovery and its browser gate. diff --git a/.agents/notes/implemented/bug-fix/2026-08-13-safari-textarea-soft-wrap-reflow.zh.md b/.agents/notes/implemented/bug-fix/2026-08-13-safari-textarea-soft-wrap-reflow.zh.md new file mode 100644 index 0000000000..7f55a5260e --- /dev/null +++ b/.agents/notes/implemented/bug-fix/2026-08-13-safari-textarea-soft-wrap-reflow.zh.md @@ -0,0 +1,47 @@ +# Agent Note: Safari textarea 软换行收缩恢复 + +Status: implemented + +[English](2026-08-13-safari-textarea-soft-wrap-reflow.md) | 中文 + +## 问题 + +composer 把光标与选区留在透明的原生 textarea 中,由 backdrop 绘制可见字形,并由隐藏的镜像层决定完整草稿高度。因此,[单滚动容器决策](2026-07-31-composer-text-layers-share-one-scrollport.md)依赖 textarea 不持有可滚动溢出:每次草稿提交后,它的 `scrollHeight` 与 `clientHeight` 相等,`scrollTop` 为零。 + +当 Backspace 让草稿跨过软换行阈值,同时 React 更新镜像层时,Safari 26.5.2 可能保留 textarea 原先的原生行布局。在复现出的两行变一行转换中,镜像层、backdrop、自增高栈和 textarea 盒都变为 28px 高,但 textarea 仍报告 `scrollHeight=52` 与 `scrollTop=20`。光标留在陈旧的原生行中,而 backdrop 已正确绘制为一行。 + +`color` 声明不是布局输入。修改 inline style 会改变计算后的颜色,却让陈旧的 `52/28/20` 状态保持不变。编辑样式表规则会碰巧触发范围更广的规则失效,并把状态清为 `28/28/0`,这正是 Web Inspector 让该声明显得像成因的原因。 + +## 决策 + +`InputBar` 通过 Apple vendor 与 `Version/... Safari/...` 形式的 user agent 一次性识别 Safari,同时排除 `CriOS`、`FxiOS`、`EdgiOS`、`OPiOS` 等已知的 iOS 其他浏览器 token。仅凭这些 identity 字段无法区分的浏览器壳仍必须先违反 textarea 溢出不变量,恢复逻辑才会修改布局。 + +原生 textarea change handler 会记录本次编辑是否缩短受控草稿。草稿提交后,除非同时存在已缓存的 Safari identity 与原生缩短信号,否则 layout effect 会在读取几何前直接返回。随后它才检查单滚动容器不变量:`scrollHeight` 与 `clientHeight` 相等即为稳定态,不会触发强制布局。出现差异时,逻辑先把 textarea 的实际高度改变一个像素,强制布局,再恢复其自有高度并再次强制布局。这样无需改变值、选区、输入法组合状态或撤销事务,即可重建 Safari 的原生文本控件布局。 + +即使 textarea 已正确恢复,临时的原生溢出仍可能让草稿滚动容器的 auto 高度停在原行数。因此,恢复逻辑会在修复 textarea 后,对 `[data-input-scroll]` 重复一次单像素失效。两个元素都会在绘制前恢复各自拥有的样式;稳定的一行状态为 `scrollHeight=clientHeight=28`、`scrollTop=0`,滚动容器高度为 28px。 + +## 验证 + +组件测试会合成 Safari 的陈旧度量,断言先 textarea 后滚动容器的失效顺序,保留选区,并证明原生草稿增长不会读取几何。浏览器 identity 测试覆盖桌面与移动 Safari、桌面 Chromium、iOS Chrome/Edge/Opera 和 Apple web view。 + +组装后的包还会在 Safari 26.5.2 中通过原生的 51 字符到 50 字符 Backspace 路径验证。Playwright WebKit 26.5 在组装应用与最小化页面中都无需本绕法即可正确稳定,因此仓库的 Chromium 浏览器泳道无法复现这个 Safari 应用缺陷;在可自动化的 Safari 泳道出现之前,由聚焦组件测试固定该引擎状态。 + +## 备选方案 + +**修改 `color` 或使用 `-webkit-text-fill-color`。** 被否决,因为 inline color 修改与透明 text fill 都不会改变陈旧的原生几何。编辑样式表规则之所以有效,只是因为其失效范围比该声明的绘制语义更广。 + +**设置 `scrollTop=0`。** 被否决,因为这只会移动陈旧的原生内容,不会重建其两行 `scrollHeight`;光标可能从错位变为被裁剪。 + +**重写 textarea 的值。** 清空再恢复值能够重建 Safari 文本控件,但会改动拥有输入法组合与选区的编辑状态。高度失效不会触碰值。 + +**使用 `field-sizing: content`。** 被否决,因为相同删除后 Safari 的两行固有高度仍会陈旧,并且 composer 仍需要镜像层充当光标标尺与 backdrop 的度量对端。 + +**只让 textarea 或滚动容器失效。** 被否决,因为只恢复 textarea 虽能清除 `52/28/20`,却可能把滚动容器留在 52px;只恢复滚动容器则不会改变 textarea 的原生溢出。这个有序二元操作是最小的完整恢复。 + +**每次 Safari 草稿提交后都检查几何。** 被否决,因为 React 改变镜像层后读取 `scrollHeight` 或 `clientHeight`,即使草稿健康增长也可能同步执行布局。原生缩短信号把不变量读取限制在可能产生已观测收缩缺陷的编辑中。 + +**在所有浏览器中运行恢复逻辑。** 被否决,因为 Chromium、Playwright WebKit 与 Firefox 无需强制布局即可维持该不变量。Safari identity 与已观测到的差异共同限定同步工作范围。 + +## 影响 + +非 Safari 浏览器、程序化草稿更新,以及不会缩短草稿的原生编辑都不会读取几何。Safari 的原生缩短会读取溢出不变量,并且仅在 textarea 违反不变量时承担四次强制布局。例外路径以绘制前的罕见局部工作换取光标对齐、原生编辑语义与单一滚动盒。尚未观测到仅由 resize 或侧栏宽度变化引发的同类陈旧状态,本恢复触发器也不覆盖它。浏览器测试缺口保持显式:真实 Safari 证据负责引擎缺陷,确定性的组件覆盖负责恢复逻辑与浏览器门控。 diff --git a/.agents/notes/implemented/bug-fix/2026-08-15-max-token-replay-state-alignment.i18n.yaml b/.agents/notes/implemented/bug-fix/2026-08-15-max-token-replay-state-alignment.i18n.yaml new file mode 100644 index 0000000000..af691f1175 --- /dev/null +++ b/.agents/notes/implemented/bug-fix/2026-08-15-max-token-replay-state-alignment.i18n.yaml @@ -0,0 +1,6 @@ +# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each +# 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 .agents/notes/implemented/bug-fix/2026-08-15-max-token-replay-state-alignment.md +2026-08-15-max-token-replay-state-alignment.md: 256a64403a08377cf35ba645175698678eaa7f8b +2026-08-15-max-token-replay-state-alignment.zh.md: a24f3e194dca100d2ea0faf659b1868c605c26c1 diff --git a/.agents/notes/implemented/bug-fix/2026-08-15-max-token-replay-state-alignment.md b/.agents/notes/implemented/bug-fix/2026-08-15-max-token-replay-state-alignment.md new file mode 100644 index 0000000000..256a64403a --- /dev/null +++ b/.agents/notes/implemented/bug-fix/2026-08-15-max-token-replay-state-alignment.md @@ -0,0 +1,33 @@ +# Agent Note: Replay state aligns with assembled content by construction + +Status: implemented + +English | [中文](2026-08-15-max-token-replay-state-alignment.zh.md) + +## Problem + +pi-ai recorded one opaque replay blob per response, projected from the provider's native message, while `BlockAssembler.blocks()` separately dropped tool calls from a `max-tokens` response because a truncated call is unsafe to execute. The durable assistant message therefore stored transformed content next to metadata describing the untransformed native block list. The next request failed during history reconstruction with `INVALID_REPLAY_STATE: block count does not match assistant content`, and because the mismatch was already on disk, every later request on that session failed the same way — the session was permanently stuck. The root cause is structural: two representations of one response were snapshotted at different pipeline points, with their index alignment enforced only by a read-time hard error. + +## Decision + +Two changes, one per side of the durable boundary. + +**Write side — one keep/drop decision.** The finish chunk's `replayState` becomes a typed `ReplayEnvelope`: an opaque `response` half plus optional opaque per-block entries aligned with the emitted block sequence. `BlockAssembler` computes its keep/drop decision once and applies it to blocks and envelope entries together, so any transformation assembly performs — today's max-token tool-call drop or a future one — prunes the matching metadata by construction. Retained blocks keep their entries, so a truncated response keeps signatures for the reasoning and text it kept. An envelope whose entries do not match the emitted block count is discarded whole (a misemitting adapter must not publish misattributed metadata). pi-ai splits its former flat state into a version-2 response half and per-block signature entries. + +**Read side — durable content is authoritative.** `toPiAssistant` treats replay state as fidelity metadata, not as a load-bearing input: any state the reading build cannot use — another adapter's kind, another version (including the flat version-1 form already on disk), malformed metadata, or a block shape that no longer matches the content — degrades that one message to the existing foreign provider-neutral conversion and reports the `INVALID_REPLAY_STATE` diagnostic through the plugin's `onReplayDegrade` hook (a logger warning). The request proceeds. This is what lets sessions poisoned before this change continue instead of erroring forever, and it bounds every future divergence source to a fidelity loss on one message. + +## Verification + +Assembler unit tests prove pruning, misalignment discard, and pass-through for untransformed and per-block-free envelopes. pi-ai unit tests prove the version-2 envelope round-trip and that every formerly-throwing invalid-state case now degrades to foreign conversion with the diagnostic. An agent-loop regression drives a truncated text-plus-tool-call response through persistence and shows the follow-up request carrying the pruned envelope. Keyless real-composition tests boot `dsh-llm-pi-ai` through the Loader and prove a native continuation without `tool_calls` after truncation, and a successful continuation over a legacy flat-state message whose block count no longer matches. The authored keyless snapshot scenario `max-tokens-continue` pins the assembled application's durable log — truncated turn, pruned envelope on the stored message, continued turn — through the real ACP subprocess path. + +## Alternatives considered + +**Suppress the whole replay state when assembly drops a tool call.** Works for today's one transformation, but re-derives the drop condition beside `blocks()` (the two drift silently), discards valid signatures for the retained blocks, and leaves read-time divergence — legacy sessions on disk foremost — a hard error. + +**Keep the state and relax pi-ai's block-count validation to attach what fits.** Rejected: index-aligned signatures attached to a different block list would present false native history to the provider. Degrading attaches nothing. + +**Teach each adapter to rewrite its state after assembly.** Rejected as an adapter obligation with an opaque blob; the envelope moves exactly the needed structure — and nothing else — into shared vocabulary, and the assembler's single decision does the rewrite mechanically. + +## Consequences + +Continuing after a max-token response that included a tool call works, retains the kept blocks' native signatures, and replays as a native pi-ai message. Sessions recorded before this change replay their affected assistant messages as provider-neutral content (with a diagnostic) instead of failing the turn; on-disk `replayState` values changed shape under the pre-release no-compatibility stance, with the old flat form handled by the same degrade path. This supersedes the read-time hard-error rule in the [provider-routed adapter decision](../architecture/2026-07-14-provider-routed-llm-adapters.md) for unusable state; validation itself is unchanged and still precedes any native reconstruction. diff --git a/.agents/notes/implemented/bug-fix/2026-08-15-max-token-replay-state-alignment.zh.md b/.agents/notes/implemented/bug-fix/2026-08-15-max-token-replay-state-alignment.zh.md new file mode 100644 index 0000000000..a24f3e194d --- /dev/null +++ b/.agents/notes/implemented/bug-fix/2026-08-15-max-token-replay-state-alignment.zh.md @@ -0,0 +1,33 @@ +# Agent Note: 回放状态与组装内容按构造对齐 + +Status: implemented + +[English](2026-08-15-max-token-replay-state-alignment.md) | 中文 + +## 问题 + +pi-ai 为每个响应记录一个从提供方原生消息投影而来的不透明回放数据,而 `BlockAssembler.blocks()` 会另行从 `max-tokens` 响应中丢弃工具调用,因为被截断的调用不能安全执行。持久化的 assistant 消息因此把变换后的内容与描述未变换原生块清单的元数据存在一起。下一个请求在历史重建阶段以 `INVALID_REPLAY_STATE: block count does not match assistant content` 失败;由于不一致已经落盘,该会话之后的每个请求都以同样方式失败——会话被永久卡死。根因是结构性的:同一响应的两种表示在流水线的不同位置各自拍摄快照,其索引对齐只靠读取时的硬错误来维持。 + +## 决定 + +两处改动,各覆盖持久化边界的一侧。 + +**写侧——一次保留/丢弃决定。** finish 分片的 `replayState` 变为有类型的 `ReplayEnvelope`:一个不透明的 `response` 半区,加上与发射块序列对齐的可选不透明逐块条目。`BlockAssembler` 只计算一次保留/丢弃决定,并把它同时应用于块和逐块条目,因此组装执行的任何变换——今天的 max-token 工具调用丢弃或未来的其他变换——都按构造裁剪掉对应元数据。保留的块保留其条目,所以被截断的响应仍为其保留的推理(reasoning)与文本保有签名。条目数与发射块数不一致的数据整体丢弃(发射不当的适配器不得发布归属错误的元数据)。pi-ai 把原先的平铺状态拆为版本 2 的 response 半区和逐块签名条目。 + +**读侧——持久化内容是权威记录。** `toPiAssistant` 把回放状态当作保真度元数据,而非承重输入:读取方无法使用的任何状态——其他适配器的 kind、其他版本(包括已落盘的平铺版本 1 形式)、格式错误的元数据、或与内容不再匹配的块结构——都把这一条消息降级为既有的外来提供方无关转换,并通过插件的 `onReplayDegrade` 钩子(logger 警告)上报 `INVALID_REPLAY_STATE` 诊断。请求继续执行。正是这一点让本次改动之前已被毒化的会话得以继续而不是永远报错,也把未来一切分叉源约束为单条消息的保真度损失。 + +## 验证 + +组装器单元测试证明裁剪、错位丢弃、以及未变换与无逐块条目数据的透传。pi-ai 单元测试证明版本 2 数据的往返,以及先前每个抛错的无效状态用例现在都降级为外来转换并带出诊断。agent loop 回归用例驱动一个被截断的文本加工具调用响应穿过持久化,并证明后续请求携带裁剪后的数据。无密钥真实组合测试通过 loader 启动 `dsh-llm-pi-ai`,证明截断后不带 `tool_calls` 的原生续聊,以及在块数不再匹配的旧平铺状态消息之上成功续聊。手工编写的无密钥快照场景 `max-tokens-continue` 通过真实 ACP 子进程路径钉住组装应用的持久化日志——截断轮次、存储消息上裁剪后的数据、以及继续的轮次。 + +## 已考虑的替代方案 + +**组装丢弃工具调用时抑制整个回放状态。** 对今天唯一的变换有效,但在 `blocks()` 旁边重新推导丢弃条件(两处会无声漂移),丢掉保留块的有效签名,并让读取时的分叉——首当其冲是已落盘的旧会话——仍然是硬错误。 + +**保留状态并放宽 pi-ai 的块数校验、能贴多少贴多少。** 否决:索引对齐的签名贴到不同的块清单上,会向提供方呈现虚假的原生历史。降级则什么都不贴。 + +**让每个适配器在组装后改写自己的状态。** 否决:这把义务压给持有不透明数据的适配器;信封只把恰好需要的结构——不多一分——纳入共享词汇,组装器的单一决定即可机械完成改写。 + +## 影响 + +包含工具调用的 max-token 响应之后的续聊可以工作,保留块保有原生签名,并作为原生 pi-ai 消息回放。本次改动之前记录的会话,其受影响的 assistant 消息作为提供方无关内容回放(带诊断)而不是让轮次失败;`replayState` 落盘形状在预发布无兼容承诺立场下发生变化,旧平铺形式由同一降级路径处理。对不可用状态而言,这取代了[提供方路由适配器决定](../architecture/2026-07-14-provider-routed-llm-adapters.md)中读取时硬错误的规则;校验本身不变,仍先于任何原生重建执行。 diff --git a/.agents/notes/implemented/bug-fix/2026-08-15-persistent-bash-keeps-controlled-prompt.i18n.yaml b/.agents/notes/implemented/bug-fix/2026-08-15-persistent-bash-keeps-controlled-prompt.i18n.yaml new file mode 100644 index 0000000000..b981cd7c0b --- /dev/null +++ b/.agents/notes/implemented/bug-fix/2026-08-15-persistent-bash-keeps-controlled-prompt.i18n.yaml @@ -0,0 +1,6 @@ +# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each +# 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 .agents/notes/implemented/bug-fix/2026-08-15-persistent-bash-keeps-controlled-prompt.md +2026-08-15-persistent-bash-keeps-controlled-prompt.md: 9ee71f2adc0d473c5490dbe2b29ce55c8377e275 +2026-08-15-persistent-bash-keeps-controlled-prompt.zh.md: 48b2cc323e745a184cefc9603d461fe8fb27e15e diff --git a/.agents/notes/implemented/bug-fix/2026-08-15-persistent-bash-keeps-controlled-prompt.md b/.agents/notes/implemented/bug-fix/2026-08-15-persistent-bash-keeps-controlled-prompt.md new file mode 100644 index 0000000000..9ee71f2adc --- /dev/null +++ b/.agents/notes/implemented/bug-fix/2026-08-15-persistent-bash-keeps-controlled-prompt.md @@ -0,0 +1,35 @@ +# Agent Note: Persistent bash keeps the backend's controlled prompt + +Status: implemented + +English | [中文](2026-08-15-persistent-bash-keeps-controlled-prompt.zh.md) + +## Problem + +`dsh-tool-bash-persistent` initialized its shell with `stty -echo; PS1='__DSH_PERSISTENT_BASH_PROMPT__ '`, overwriting the `PS1` that `dsh-terminal-bash` sets in the spawn environment. The backend's prompt readiness requires the printable tail after the OSC `133;D` marker to exactly equal the controlled prompt ([design](../feature/2026-07-16-persistent-pty-sessions.md)), so after initialization no send could ever settle through it. `PROMPT_COMMAND` survived the override, so the marker kept arriving and every send paid the silence tier plus handoff grace — 3.5 s per tool call under production defaults, 7.2 s for the first call because the initialization send degraded too, and an extra 3.5 s tail after every long command. macOS has no exact stdin-wait tier, and on Linux the exact probe cannot observe a sub-poll-interval command leaving its stdin wait, so the degradation applied to effectively every call. Package tests masked it by configuring `idleSilenceMs: 100`. + +The override existed to give the tool a known prompt for two consumers: a viewport-suffix fallback that detected "shell at a prompt without the end marker", and cosmetic stripping of prompt text from partial output. + +## Decision + +The backend owns its prompt protocol and repairs it itself: the controlled `PROMPT_COMMAND` re-asserts `PS1` after printing the marker, so any in-shell prompt override — this tool's former initialization, a model command, a sourced script — lasts zero prompts. This also protects providers that cannot report foreground state, where the exact prompt text is the only readiness evidence. + +The tool stops overwriting `PS1` (initialization is `stty -echo` alone) and replaces its viewport-suffix fallback with the seam's existing signal: a send that settles as `stdin_read` without the end marker in scrollback returns the captured partial output. The private prompt constant and its stripping are deleted; partial output may now end with the backend's own prompt text, which the tool cannot and should not know. + +## Alternatives considered + +**Fix only the tool, leaving `PROMPT_COMMAND` unchanged.** Rejected because the seam would stay silently fragile: any later consumer or model command that touches `PS1` reintroduces the 3.5 s degradation with no failing signal, and providers without foreground inspection lose their only readiness factor. + +**Import the controlled prompt into the tool.** Rejected because the prompt is one provider's protocol constant; a Consumer matching it would couple the tool to `dsh-terminal-bash` specifically, and any other mounted backend would break it again. + +**Drop the prompt-text factor from backend readiness.** Rejected because for providers whose `inspectForeground` reports nothing, marker-plus-text is the defense against command output that embeds the raw OSC marker sequence; weakening it trades a fast path for a false-settle risk. + +**Widen `handoffGraceMs`/`idleSilenceMs` tuning instead.** Rejected because no silence value fixes a dead fast path; it only rebalances how much every call overpays. + +## Consequences + +Measured on darwin with production defaults: raw sends settle in ~86 ms with the controlled prompt intact versus ~3540 ms after an override; tool calls drop from 7180/3560/3566 ms to 355/88/91 ms for spawn+init+echo, echo, and pwd. + +The `stdin_read` fallback is behavior, not only cosmetics: after `exec`, an interrupt, or an interactive foreground child whose stdin wait the provider proves (the Linux exact tier), the call now returns captured partial output instead of spinning to the command deadline. Where no provider proves the wait (macOS), an interactive child still runs to `timeoutMs` — recorded as a known limitation in the tool README. Partial output can carry the backend's trailing prompt; complete marker-delimited output is byte-identical to before, which the keyless jsonrpc-agent snapshots confirm. + +The loader-composition suite now sets `idleSilenceMs` above the send bound, so silence can settle nothing and every case fails if prompt readiness regresses; a real-PTY case overrides `PS1` in-shell and requires the next send to settle as `stdin_read` with the healed prompt. The self-repair cannot survive a command that overwrites `PROMPT_COMMAND` itself; the silence tier remains the bound there, unchanged from the prior design. diff --git a/.agents/notes/implemented/bug-fix/2026-08-15-persistent-bash-keeps-controlled-prompt.zh.md b/.agents/notes/implemented/bug-fix/2026-08-15-persistent-bash-keeps-controlled-prompt.zh.md new file mode 100644 index 0000000000..48b2cc323e --- /dev/null +++ b/.agents/notes/implemented/bug-fix/2026-08-15-persistent-bash-keeps-controlled-prompt.zh.md @@ -0,0 +1,35 @@ +# Agent Note: 持久 bash 保留后端的受控提示符 + +Status: implemented + +[English](2026-08-15-persistent-bash-keeps-controlled-prompt.md) | 中文 + +## Problem + +`dsh-tool-bash-persistent` 用 `stty -echo; PS1='__DSH_PERSISTENT_BASH_PROMPT__ '` 初始化其 shell,覆盖了 `dsh-terminal-bash` 在 spawn 环境中设定的 `PS1`。后端的提示符就绪检测要求 OSC `133;D` 标记之后的可打印尾部与受控提示符完全相等([设计](../feature/2026-07-16-persistent-pty-sessions.md)),因此初始化之后任何 send 都无法经由该路径结算。`PROMPT_COMMAND` 未被覆盖,标记仍持续到达,于是每次 send 都要支付静默层加交接宽限——生产默认值下每次工具调用 3.5 秒;首次调用 7.2 秒,因为初始化 send 同样退化;每条长命令结束后还要多等 3.5 秒。macOS 没有精确 stdin 等待层,而 Linux 的精确探测无法观察到在一个轮询周期内完成的命令脱离其 stdin 等待,因此退化实际覆盖了几乎每次调用。包测试把 `idleSilenceMs` 配成 100 毫秒,掩盖了该问题。 + +这个覆盖存在的目的是给工具一个已知提示符,服务两个消费点:用视口后缀检测「shell 已回到提示符但没有结束标记」的回退判定,以及从部分输出中剥离提示符文本的美化。 + +## Decision + +后端拥有自己的提示符协议并自行修复:受控 `PROMPT_COMMAND` 在打印标记后重新设定 `PS1`,因此任何 shell 内的提示符覆盖——本工具从前的初始化、模型命令、被 source 的脚本——都存活不到下一个提示符。这同时保护了无法报告前台状态的提供方:在那里,确切的提示符文本是唯一的就绪证据。 + +工具不再覆盖 `PS1`(初始化只剩 `stty -echo`),并用 seam 已有的信号替换其视口后缀回退:一次以 `stdin_read` 结算而 scrollback 中没有结束标记的 send,返回已捕获的部分输出。私有提示符常量及其剥离逻辑删除;部分输出现在可能以后端自己的提示符文本结尾,工具无法也不应知道该文本。 + +## Alternatives considered + +**只改工具,不动 `PROMPT_COMMAND`。** 被拒绝:seam 仍然静默脆弱——之后任何触碰 `PS1` 的消费方或模型命令都会在没有失败信号的情况下重新引入 3.5 秒退化,且无前台检查的提供方失去唯一的就绪因子。 + +**把受控提示符导入工具。** 被拒绝:提示符是单个提供方的协议常量;Consumer 匹配它就把工具与 `dsh-terminal-bash` 具体耦合,换任何其他后端都会再次损坏。 + +**从后端就绪检测中去掉提示符文本因子。** 被拒绝:对 `inspectForeground` 无法报告任何信息的提供方而言,标记加文本是对抗「命令输出中嵌入原始 OSC 标记序列」的防御;削弱它是拿误结算风险换快速路径。 + +**改为调大 `handoffGraceMs`/`idleSilenceMs`。** 被拒绝:任何静默值都修不好已死的快速路径,只是重新分配每次调用多付多少。 + +## Consequences + +darwin 上以生产默认值实测:受控提示符完好时裸 send 约 86 毫秒结算,覆盖后约 3540 毫秒;工具调用从 7180/3560/3566 毫秒(spawn+init+echo、echo、pwd)降至 355/88/91 毫秒。 + +`stdin_read` 回退是行为而不只是美化:在 `exec`、中断,或提供方能证明其 stdin 等待的交互式前台子进程(Linux 精确层)之后,调用现在返回已捕获的部分输出,而不是空转到命令期限。没有提供方证明该等待时(macOS),交互式子进程仍会运行到 `timeoutMs`——已记入工具 README 的已知限制。部分输出可能带有后端的尾部提示符;由标记界定的完整输出与之前逐字节相同,无密钥 jsonrpc-agent 快照确认了这一点。 + +loader 组合套件现在把 `idleSilenceMs` 设在 send 上限之上,静默无法结算任何 send,提示符就绪一旦回归,每个用例都会失败;一个真实 PTY 用例在 shell 内覆盖 `PS1`,并要求下一次 send 以 `stdin_read` 结算且提示符已修复。自我修复无法在 `PROMPT_COMMAND` 本身被覆盖的命令后存活;那里静默层仍是边界,与先前设计一致。 diff --git a/.agents/notes/implemented/feature/2026-06-15-code-mode.i18n.yaml b/.agents/notes/implemented/feature/2026-06-15-code-mode.i18n.yaml index 701a26bf10..7b213dc96f 100644 --- a/.agents/notes/implemented/feature/2026-06-15-code-mode.i18n.yaml +++ b/.agents/notes/implemented/feature/2026-06-15-code-mode.i18n.yaml @@ -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 .agents/notes/implemented/feature/2026-06-15-code-mode.md -2026-06-15-code-mode.md: bc019c0b9acc6d834da41ceff2b1d1930fb34027 -2026-06-15-code-mode.zh.md: c19562b828089b6deeb048d30a08ce8681f150da +2026-06-15-code-mode.md: dbf77557c9f1aa59deed443b74ca3ef83137d773 +2026-06-15-code-mode.zh.md: 6f263d946cf7632a0747dcb61f3dd22105e21e0c diff --git a/.agents/notes/implemented/feature/2026-06-15-code-mode.md b/.agents/notes/implemented/feature/2026-06-15-code-mode.md index bc019c0b9a..dbf77557c9 100644 --- a/.agents/notes/implemented/feature/2026-06-15-code-mode.md +++ b/.agents/notes/implemented/feature/2026-06-15-code-mode.md @@ -19,7 +19,7 @@ Tool presentation belongs to the registry that owns tool visibility: implementin Three decisions, each elaborated in its own section below: 1. **Code Mode is a first-class presentation mode of `ToolRuntime`** (`dsh-tools`), selected by a validated `mode` config: `'native'` (the default, contributing the visible capability schemas), `'code'` (the registry contributes only its reserved `run_code` transport plus a generated SDK `.d.ts` in the system prompt), or `'both'` (native schemas and the transport + SDK). The registry constructs its canonical contribution at the source; the cooperative prompt-assembly result remains authoritative, and the logged request header records exactly that returned presentation. -2. **Code execution is a capability seam** — `packages/code-runtime/` contains the Service Definition package `@deepseek-ai/dsh-code-runtime`, which owns `ctx.codeRuntime` ([capability seams](../architecture/2026-06-13-capability-seams.md); Consumer = `dsh-tools`, with core-consumes-a-seam precedent in `agent-loop` → `dsh-llm`). The runtime knows nothing about tools: it is handed a program and named async bindings, runs the program, and reports `{ value, logs, error? }`. Language and substrate are backend properties, so a future Python or container backend is another Service provider package, not a redesign. +2. **Code execution is a capability seam** — `packages/code-runtime/` contains the Service Definition package `@deepseek-ai/dsh-code-runtime`, which owns `ctx.codeRuntime` ([capability seams](../architecture/2026-06-13-capability-seams.md); Consumer = `dsh-tools`, with core-consumes-a-seam precedent in `agent-loop` → `dsh-llm`). The runtime knows nothing about tools: it is handed a program and named async bindings, runs the program, and reports `{ value, logs, error? }`. Language and substrate are backend properties, so a future Python or container backend is another Service Provider package, not a redesign. 3. **The shipped implementation is `@deepseek-ai/dsh-code-runtime-worker-thread`**: one fresh Node worker thread per run, executing the model's TypeScript after type-strip, with bindings bridged over the message port, an empty environment, configurable heap/output/time caps, and hard termination. Its trust posture is bash-equivalent by design — no unsafe-acknowledgement flags — because the harness already ships `dsh-bash-local`, which executes arbitrary model-written shell commands with strictly *more* ambient authority. This note owns Code Mode's presentation, composition, isolation, and settlement foundation. The later [typed tool-return Agent Note](2026-07-20-code-mode-typed-tool-returns.md) owns the generated output map, canonical binding values, `ToolCallError`, and the lossless outer-output boundary. @@ -87,6 +87,8 @@ The worker runtime provides containment, not a security boundary: model code can The SDK instructs the model to write an async body in the loaded runtime's language (an erasable-TypeScript body by default; a Python `async` body under a Python runtime — see the [language-dispatch note](2026-07-31-code-mode-language-dispatch.md)), call tools through `await tools.name(args)`, catch rejected tool calls when needed, and return or log only the output that should re-enter context. Both flavors state the same contract in their own primitive: independent read-only calls MAY overlap under `Promise.all` (TypeScript) or `asyncio.gather` (Python), mutating calls run alone in submission order, and dependent work sequences with `await`. The declaration prefix can be as large as native schemas, especially in `'both'`, but remains stable for provider caching. +The transport's own `description` and both SDK instruction flavors open by naming `code` and `description` as the call's two required arguments. Prose that describes the call as passing a program leaves the second argument discoverable only through the parameter schema, and a model that emits `{code}` alone loses the whole written program to an `INVALID_ARGS` rejection. + ## Consequences Deployments switching to `'code'` must update any native-only `toolOrder`. Assembly listeners own the integrity of any rewritten protocol messages. Sub-dispatch starts in submission order under a bounded overlap pool, while per-call contexts retain their source, envelope, and metadata through the outer result. diff --git a/.agents/notes/implemented/feature/2026-06-15-code-mode.zh.md b/.agents/notes/implemented/feature/2026-06-15-code-mode.zh.md index c19562b828..6f263d946c 100644 --- a/.agents/notes/implemented/feature/2026-06-15-code-mode.zh.md +++ b/.agents/notes/implemented/feature/2026-06-15-code-mode.zh.md @@ -19,7 +19,7 @@ Cloudflare 的 [Code Mode](https://blog.cloudflare.com/code-mode/) 提出了一 三项决策,各自在下方独立小节中展开: 1. **Code Mode 是 `ToolRuntime`(`dsh-tools`)的一等呈现模式**,通过经校验的 `mode` 配置选择:`'native'`(默认,贡献可见能力 schema)、`'code'`(注册表仅贡献其保留的 `run_code` 传输通道加一份生成的 SDK `.d.ts` 到系统提示词中)或 `'both'`(原生 schema 加传输通道 + SDK)。注册表在源头构建其规范贡献;协作式提示词组装的结果仍具权威性,记录在日志中的请求头精确反映该返回的呈现。 -2. **代码执行是一个能力 seam**——`packages/code-runtime/` 包含 Service Definition 包 `@deepseek-ai/dsh-code-runtime`,拥有 `ctx.codeRuntime`([能力 seam](../architecture/2026-06-13-capability-seams.md);消费方 = `dsh-tools`,core 消费 seam 的先例见 `agent-loop` → `dsh-llm`)。运行时对工具一无所知:它接收一段程序和命名的异步绑定,执行程序,报告 `{ value, logs, error? }`。语言和基底是后端属性,因此未来的 Python 或容器后端只是另一个 Service 提供方包,而非重新设计。 +2. **代码执行是一个能力 seam**——`packages/code-runtime/` 包含 Service Definition 包 `@deepseek-ai/dsh-code-runtime`,拥有 `ctx.codeRuntime`([能力 seam](../architecture/2026-06-13-capability-seams.md);消费方 = `dsh-tools`,core 消费 seam 的先例见 `agent-loop` → `dsh-llm`)。运行时对工具一无所知:它接收一段程序和命名的异步绑定,执行程序,报告 `{ value, logs, error? }`。语言和基底是后端属性,因此未来的 Python 或容器后端只是另一个 Service Provider 包,而非重新设计。 3. **交付的实现是 `@deepseek-ai/dsh-code-runtime-worker-thread`**:每次运行 spawn 一个全新的 Node worker 线程,对模型的 TypeScript 进行 type-strip 后执行,绑定通过消息端口桥接,环境为空,堆/输出/时间上限可配置,并支持硬终止。其信任姿态在设计上等同于 bash——无需 unsafe-acknowledgement flag——因为 harness 已经交付了 `dsh-bash-local`,后者以严格*更高*的环境权限执行模型编写的任意 shell 命令。 本说明负责定义 Code Mode 的呈现、组合、隔离与结算基础。后续的[类型化工具返回值 Agent Note](2026-07-20-code-mode-typed-tool-returns.md)负责定义生成的输出映射、规范绑定值、`ToolCallError` 和无损外层输出边界。 @@ -87,6 +87,8 @@ worker 运行时只能约束程序的运行,而不构成安全边界:模型 SDK 指示模型编写一个所加载运行时语言的异步函数体(默认可擦除 TypeScript;Python 运行时下为 Python `async` 函数体——见[语言分发 note](2026-07-31-code-mode-language-dispatch.md)),通过 `await tools.name(args)` 调用工具,在需要时捕获被拒绝的工具调用,并仅 return 或 log 应重新进入上下文的输出。两种 flavor 用各自的原语陈述同一约定:相互独立的只读调用可以(MAY)在 `Promise.all`(TypeScript)或 `asyncio.gather`(Python)下重叠,有副作用的调用按提交顺序单独运行,有依赖的工作用 `await` 排序。声明前缀可能与原生 schema 一样大,尤其在 `'both'` 下,但对提供方缓存保持稳定。 +传输自身的 `description` 与两种 flavor 的 SDK 说明都以点名 `code` 和 `description` 这两个必填参数开头。把该调用描述成「传入一个程序」的散文会让第二个参数只能从参数 schema 中发现,而只发出 `{code}` 的模型会因 `INVALID_ARGS` 被拒,连同已写好的整个程序一起丢失。 + ## 后果 切换到 `'code'` 的部署必须更新任何仅限 native 的 `toolOrder`。组装监听器有责任维护任何被重写的协议消息的完整性。子分发在有界的重叠池下按提交顺序启动,而每次调用的上下文会通过外层结果保留其 source、信封与元数据。 diff --git a/.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.i18n.yaml b/.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.i18n.yaml index dcb4d5e33a..1870906b95 100644 --- a/.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.i18n.yaml +++ b/.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.i18n.yaml @@ -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 .agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.md -2026-06-18-compaction-capability-seam.md: 77ccd615a20524fad2a1ee47130ba2837d83c663 -2026-06-18-compaction-capability-seam.zh.md: a18e7593a5b654685a2e033dd2f0a721da74502e +2026-06-18-compaction-capability-seam.md: 71ea7144cd843364fd77db0dd2c8a0d1e8bab1ac +2026-06-18-compaction-capability-seam.zh.md: bd7ab06b3a012d83d3f918a3ebd5a553624780e9 diff --git a/.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.md b/.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.md index 77ccd615a2..71ea7144cd 100644 --- a/.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.md +++ b/.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.md @@ -14,7 +14,7 @@ Two forces shape the design. First, compaction policy and reusable token measure ## Decision -### Compaction is a capability seam with separate Service Definition and Service provider roles +### Compaction is a capability seam with separate Service Definition and Service Provider roles Per the [capability-seams Agent Note](../architecture/2026-06-13-capability-seams.md), compaction ships as separate packages so the contract, the algorithm, and (later) the consumer API evolve independently: diff --git a/.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.zh.md b/.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.zh.md index a18e7593a5..bd7ab06b3a 100644 --- a/.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.zh.md +++ b/.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.zh.md @@ -14,7 +14,7 @@ Status: implemented ## 决策 -### 压缩是一个能力 seam,Service Definition 与 Service 提供方角色分离 +### 压缩是一个能力 seam,Service Definition 与 Service Provider 角色分离 遵循[能力 seam Agent Note](../architecture/2026-06-13-capability-seams.md),压缩以独立包发布,使约定、算法和(后续的)消费方 API 各自独立演进: diff --git a/.agents/notes/implemented/feature/2026-06-21-subagent-capability-seam.i18n.yaml b/.agents/notes/implemented/feature/2026-06-21-subagent-capability-seam.i18n.yaml index 431665bbb7..e8ece4d624 100644 --- a/.agents/notes/implemented/feature/2026-06-21-subagent-capability-seam.i18n.yaml +++ b/.agents/notes/implemented/feature/2026-06-21-subagent-capability-seam.i18n.yaml @@ -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 .agents/notes/implemented/feature/2026-06-21-subagent-capability-seam.md -2026-06-21-subagent-capability-seam.md: 337e1f8aaf8db8b9d41bbf0ad02f7f8a9468e4fb -2026-06-21-subagent-capability-seam.zh.md: f88ad5cfba5b7f364064ad6b82fc918bdf5d7ef3 +2026-06-21-subagent-capability-seam.md: fa3b4f570bfccdc849a38b3eda16c1c8dd7b1827 +2026-06-21-subagent-capability-seam.zh.md: b25fe64377f98af92dbccb87f755627926975ef2 diff --git a/.agents/notes/implemented/feature/2026-06-21-subagent-capability-seam.md b/.agents/notes/implemented/feature/2026-06-21-subagent-capability-seam.md index 337e1f8aaf..fa3b4f570b 100644 --- a/.agents/notes/implemented/feature/2026-06-21-subagent-capability-seam.md +++ b/.agents/notes/implemented/feature/2026-06-21-subagent-capability-seam.md @@ -21,7 +21,7 @@ The harness has a long-deferred seam for **subagents** — an agent delegating w ### Why not the bash seam shape -The bash seam ([capability seams](../architecture/2026-06-13-capability-seams.md)) registers exactly one `ShellExecutor` per context; loading a second throws. That is correct for bash (one machine, one way to run a command) but wrong here: coexistence is the requirement. So the subagent service is a **named-provider registry** — each implementation registers under a unique name and a caller picks one by name — mirroring the **LLM adapter registry** (`LlmRuntime.registerAdapter`), not the single-service bash executor. The seam is still three-package (Service Definition / Service provider / Consumer); only the "one vs. many implementations" axis differs. +The bash seam ([capability seams](../architecture/2026-06-13-capability-seams.md)) registers exactly one `ShellExecutor` per context; loading a second throws. That is correct for bash (one machine, one way to run a command) but wrong here: coexistence is the requirement. So the subagent service is a **named-provider registry** — each implementation registers under a unique name and a caller picks one by name — mirroring the **LLM adapter registry** (`LlmRuntime.registerAdapter`), not the single-service bash executor. The seam is still three-package (Service Definition / Service Provider / Consumer); only the "one vs. many implementations" axis differs. ## Decision diff --git a/.agents/notes/implemented/feature/2026-06-21-subagent-capability-seam.zh.md b/.agents/notes/implemented/feature/2026-06-21-subagent-capability-seam.zh.md index f88ad5cfba..b25fe64377 100644 --- a/.agents/notes/implemented/feature/2026-06-21-subagent-capability-seam.zh.md +++ b/.agents/notes/implemented/feature/2026-06-21-subagent-capability-seam.zh.md @@ -21,7 +21,7 @@ harness 有一个长期搁置的 seam 用于 **subagent**:一个 agent 将工 ### 为何不采用 bash seam 的形状 -bash seam([能力 seam](../architecture/2026-06-13-capability-seams.md))在每个上下文中只注册恰好一个 `ShellExecutor`;加载第二个会抛异常。这对 bash 是正确的(一台机器、一种执行命令的方式),但对这里是错误的:共存才是需求。因此 subagent 服务是一个**命名提供方注册表**——每个实现以唯一名称注册,调用方按名称选择——镜像 **LLM(大语言模型)适配器注册表**(`LlmRuntime.registerAdapter`),而非单服务的 bash 执行器。seam 仍然是由三类包构成的结构(Service Definition / Service provider / Consumer);只是「一个 vs. 多个实现」这个维度不同。 +bash seam([能力 seam](../architecture/2026-06-13-capability-seams.md))在每个上下文中只注册恰好一个 `ShellExecutor`;加载第二个会抛异常。这对 bash 是正确的(一台机器、一种执行命令的方式),但对这里是错误的:共存才是需求。因此 subagent 服务是一个**命名提供方注册表**——每个实现以唯一名称注册,调用方按名称选择——镜像 **LLM(大语言模型)适配器注册表**(`LlmRuntime.registerAdapter`),而非单服务的 bash 执行器。seam 仍然是由三类包构成的结构(Service Definition / Service Provider / Consumer);只是「一个 vs. 多个实现」这个维度不同。 ## 决策 diff --git a/.agents/notes/implemented/feature/2026-07-05-dynamic-workflows.i18n.yaml b/.agents/notes/implemented/feature/2026-07-05-dynamic-workflows.i18n.yaml index 948301ca44..d066d73db4 100644 --- a/.agents/notes/implemented/feature/2026-07-05-dynamic-workflows.i18n.yaml +++ b/.agents/notes/implemented/feature/2026-07-05-dynamic-workflows.i18n.yaml @@ -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 .agents/notes/implemented/feature/2026-07-05-dynamic-workflows.md -2026-07-05-dynamic-workflows.md: bf7b98891d19c31be7e1ca2763f98bb3668ab659 -2026-07-05-dynamic-workflows.zh.md: f3c06ae17e7cf185865d03e261e4e6bbabcabd1f +2026-07-05-dynamic-workflows.md: eff37365534cd41e46c98e20a5e763a233330647 +2026-07-05-dynamic-workflows.zh.md: 15aa8326958faebb53d33153b1c1537af199a4c5 diff --git a/.agents/notes/implemented/feature/2026-07-05-dynamic-workflows.md b/.agents/notes/implemented/feature/2026-07-05-dynamic-workflows.md index bf7b98891d..eff3736553 100644 --- a/.agents/notes/implemented/feature/2026-07-05-dynamic-workflows.md +++ b/.agents/notes/implemented/feature/2026-07-05-dynamic-workflows.md @@ -10,7 +10,7 @@ The harness can delegate ONE task to ONE child (`dsh-tool-subagent`), but work t ## Decision -A workflow capability family at `packages/workflow/` in the bash seam shape (Service Definition / Service provider / Consumer), plus the structured-output foundation it needs on the subagent seam. +A workflow capability family at `packages/workflow/` in the bash seam shape (Service Definition / Service Provider / Consumer), plus the structured-output foundation it needs on the subagent seam. ### The script contract (Claude Code-compatible) diff --git a/.agents/notes/implemented/feature/2026-07-05-dynamic-workflows.zh.md b/.agents/notes/implemented/feature/2026-07-05-dynamic-workflows.zh.md index f3c06ae17e..15aa832695 100644 --- a/.agents/notes/implemented/feature/2026-07-05-dynamic-workflows.zh.md +++ b/.agents/notes/implemented/feature/2026-07-05-dynamic-workflows.zh.md @@ -10,7 +10,7 @@ harness 可以通过 `dsh-tool-subagent` 将一个任务委派给一个子 agent ## 决策 -在 `packages/workflow/` 下以 bash seam 的形态(Service Definition/Service provider/Consumer)提供一组工作流能力,以及它在 subagent seam 上所需的结构化输出基础。 +在 `packages/workflow/` 下以 bash seam 的形态(Service Definition/Service Provider/Consumer)提供一组工作流能力,以及它在 subagent seam 上所需的结构化输出基础。 ### 脚本约定(兼容 Claude Code) diff --git a/.agents/notes/implemented/feature/2026-07-06-approval-seam.i18n.yaml b/.agents/notes/implemented/feature/2026-07-06-approval-seam.i18n.yaml index 1033d13843..b04c952748 100644 --- a/.agents/notes/implemented/feature/2026-07-06-approval-seam.i18n.yaml +++ b/.agents/notes/implemented/feature/2026-07-06-approval-seam.i18n.yaml @@ -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 .agents/notes/implemented/feature/2026-07-06-approval-seam.md -2026-07-06-approval-seam.md: 5c62a175b0a96ecc8dd3f5b09b618b8e4d5e7612 -2026-07-06-approval-seam.zh.md: 091db8347e0a5bd5ee475809dde6b90d183d3112 +2026-07-06-approval-seam.md: ace41ebbb94cc24c2fdd3e7ae2d3a69b28b169af +2026-07-06-approval-seam.zh.md: 3e06c3ba26dd6d85555727dc0c62cbffe0a2a1da diff --git a/.agents/notes/implemented/feature/2026-07-06-approval-seam.md b/.agents/notes/implemented/feature/2026-07-06-approval-seam.md index 5c62a175b0..ace41ebbb9 100644 --- a/.agents/notes/implemented/feature/2026-07-06-approval-seam.md +++ b/.agents/notes/implemented/feature/2026-07-06-approval-seam.md @@ -97,7 +97,7 @@ Snapshots record allowed and rejected sandbox escalation through `session/reques - **An inline `tools/pre-execute` permission gate in the ACP bridge** — rejected: prompting for every bridge-owned call hardwires the asking policy into the transport, cannot serve a second asker (sandbox escalation happens after execution starts, with no pre-execute moment), and leaves hook-produced `ask` decisions without a shared mechanism. - **The generic user-questions seam (`ctx.userQuestions`)** — rejected as the approval mechanism: the two share a skeleton (route by agent, block for a human, handle absence), but approval's contract is narrower in every dimension that matters: a closed outcome vocabulary instead of free text, a protocol-native prompt attached to a tool call instead of a generic form, mandatory fail-closed absence, and audit events. Approval therefore does not ride the shipped `packages/interaction/user-questions` / `ask_user_question` elicitation path — an elicitation form is not a permission prompt, and a free-text answer is not a closed outcome; sharing provider plumbing stays open if the two ever converge. - **Static optional injection in `dsh-tools`** — rejected: the vendored cordis `Inject` type has no optional flag — the object form maps service names to intercept config, and a declared inject gates the fiber. `ctx.get('approval')` is the documented opportunistic-consumption pattern (the `tool-bash` owner-token lookup, the loop's persistence probe), reads presence per call, and degrades correctly across HMR without extra machinery. -- **The capability-seam three-package split** — rejected: Service Definition / Service provider / Consumer fits a seam whose Service provider is swappable (bash-local vs bash-sandbox). Here the service body is fixed mechanism and the variable part is listeners that live with their owners — splitting would manufacture a Service provider package with nothing in it ("don't split preemptively"). +- **The capability-seam three-package split** — rejected: Service Definition / Service Provider / Consumer fits a seam whose Service Provider is swappable (bash-local vs bash-sandbox). Here the service body is fixed mechanism and the variable part is listeners that live with their owners — splitting would manufacture a Service Provider package with nothing in it ("don't split preemptively"). - **Offering `allow_always` now** — rejected: the protocol can express it, but honoring it means designing grant storage, scope identity, and revocation (§ Deferred). Advertising an option the harness cannot honor manufactures doomed grants. ## Consequences diff --git a/.agents/notes/implemented/feature/2026-07-06-approval-seam.zh.md b/.agents/notes/implemented/feature/2026-07-06-approval-seam.zh.md index 091db8347e..3e06c3ba26 100644 --- a/.agents/notes/implemented/feature/2026-07-06-approval-seam.zh.md +++ b/.agents/notes/implemented/feature/2026-07-06-approval-seam.zh.md @@ -97,7 +97,7 @@ ACP 桥只应答其会话映射所拥有的精确 agent 对象。它携带既有 - **在 ACP 桥中内联 `tools/pre-execute` 权限门禁**:否决。对桥拥有的每次调用都弹出提示,会将请求策略硬编码进传输层,无法服务第二个发起方(沙箱升级发生在执行开始之后,没有 pre-execute 时刻),且钩子产生的 `ask` 决策没有共享机制。 - **通用用户交互 seam(`ctx.userQuestions`)**:否决作为审批机制。二者骨架相似(按 agent 路由、阻塞等待人类、处理缺失),但审批的约定在每个关键维度上都更窄:封闭的结果词汇而非自由文本、附着在工具调用上的协议原生提示而非通用表单、强制的缺失时失败关闭、以及审计事件。因此审批不走已交付的 `packages/interaction/user-questions` / `ask_user_question` 信息征集路径——信息征集表单不是权限提示,自由文本应答不是封闭结果;如果二者将来趋同,共享提供方管道仍然开放。 - **`dsh-tools` 中的静态可选注入**:否决。vendor 的 Cordis `Inject` 类型没有 optional 标志——对象形式将服务名映射到拦截配置,声明的 inject 会阻塞 fiber。`ctx.get('approval')` 是文档化的机会性消费模式(`tool-bash` 的 owner-token 查找、loop 的持久化探测),按调用读取存在性,跨 HMR 正确降级,无需额外机制。 -- **能力 seam 的三包拆分**:否决。Service Definition/Service provider/Consumer 适合 Service provider 可替换的 seam(bash-local vs bash-sandbox)。此处服务体是固定机制,可变部分是留在各自通道拥有者插件中的监听器——拆分只会制造一个空的 Service provider 包(「不要预防性拆分」)。 +- **能力 seam 的三包拆分**:否决。Service Definition/Service Provider/Consumer 适合 Service Provider 可替换的 seam(bash-local vs bash-sandbox)。此处服务体是固定机制,可变部分是留在各自通道拥有者插件中的监听器——拆分只会制造一个空的 Service Provider 包(「不要预防性拆分」)。 - **现在就提供 `allow_always`**:否决。协议能表达它,但兑现它意味着设计授权存储、作用域标识和撤销(§ 延后)。展示 harness 无法兑现的选项只会制造注定失败的授权。 ## 后果 diff --git a/.agents/notes/implemented/feature/2026-07-06-sandbox.i18n.yaml b/.agents/notes/implemented/feature/2026-07-06-sandbox.i18n.yaml index b3cba4dcb8..3cf7133534 100644 --- a/.agents/notes/implemented/feature/2026-07-06-sandbox.i18n.yaml +++ b/.agents/notes/implemented/feature/2026-07-06-sandbox.i18n.yaml @@ -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 .agents/notes/implemented/feature/2026-07-06-sandbox.md -2026-07-06-sandbox.md: 76733c619e3e34a6ee49c80aaf5c3bd4d48d82f7 -2026-07-06-sandbox.zh.md: 36ecbadd0589b4859389961aa52181de3f034dcc +2026-07-06-sandbox.md: 62c46c99a2283b03cf75d8823783367dd6b3473a +2026-07-06-sandbox.zh.md: 82c2e7962800c007a207f0204bf47cef01f79a36 diff --git a/.agents/notes/implemented/feature/2026-07-06-sandbox.md b/.agents/notes/implemented/feature/2026-07-06-sandbox.md index 76733c619e..62c46c99a2 100644 --- a/.agents/notes/implemented/feature/2026-07-06-sandbox.md +++ b/.agents/notes/implemented/feature/2026-07-06-sandbox.md @@ -54,7 +54,7 @@ OS subprocess confinement applies to the bash executor, including hook commands, Policy rides each CALL, not the provider: two consumers may confine under different policies at the same instant (bash under `read-only` while a confined child agent keeps its state directory writable), and an approved escalated retry is a new call with a wider policy — inexpressible under a config-fixed provider mode. -The seam confines SAME-WORLD subprocesses only: a backend shares the host's filesystem and kernel. Containers, microVMs, and remote executors are NOT backends of this seam — they replace the Service providers for whole capability seams (`ctx.shell`, `ctx.fs`) as environment-coherent groups, because an agent whose bash runs in a container while its fs tools write the host lives in two split worlds. +The seam confines SAME-WORLD subprocesses only: a backend shares the host's filesystem and kernel. Containers, microVMs, and remote executors are NOT backends of this seam — they replace the Service Providers for whole capability seams (`ctx.shell`, `ctx.fs`) as environment-coherent groups, because an agent whose bash runs in a container while its fs tools write the host lives in two split worlds. Left open, for the phase that needs them: whether network restriction arrives as a separate `network_mode` or merges into `sandbox_mode` once a runner enforces both, and whether `SandboxPolicy` grows extra writable-root grants now (the launcher already speaks `--rw `) or only when escalation needs them. @@ -199,7 +199,7 @@ Costs and accepted limits: In-repo precedents this design copies or contrasts with: -- [The capability-seams Agent Note](../architecture/2026-06-13-capability-seams.md) — the Service Definition / Service provider / Consumer split and the "don't split preemptively" timing rule the second consumer satisfied. +- [The capability-seams Agent Note](../architecture/2026-06-13-capability-seams.md) — the Service Definition / Service Provider / Consumer split and the "don't split preemptively" timing rule the second consumer satisfied. - The `dsh-shell` request/spec split ([the bash vocabulary catalog](../../../../docs/subsystems/shell.md)) — the complete `sandboxPolicy` rides its per-call carrier, and the explicit-`resolve()` defaulting convention. - [The approval seam Agent Note](2026-07-06-approval-seam.md) — the channel escalation asks through; its answerer waterfall, audit pair, and one-package rationale are recorded there. - [Event-sourced sessions](../architecture/2026-06-11-event-sourced-sessions.md) and [standalone log-only events](../simplification/2026-07-28-remove-synthetic-log-only-turns.md) — the log-as-store foundation the per-session modes fold over, and the explicit durability boundary the anchoring design obeys. diff --git a/.agents/notes/implemented/feature/2026-07-06-sandbox.zh.md b/.agents/notes/implemented/feature/2026-07-06-sandbox.zh.md index 36ecbadd05..82c2e79628 100644 --- a/.agents/notes/implemented/feature/2026-07-06-sandbox.zh.md +++ b/.agents/notes/implemented/feature/2026-07-06-sandbox.zh.md @@ -54,7 +54,7 @@ OS 子进程约束适用于 bash 执行器(包括钩子命令),后续还 策略随每次调用而非提供方携带:两个消费方可以在同一时刻以不同策略约束(bash 在 `read-only` 下运行,而一个受约束的子 agent 保持其状态目录可写),且经批准的升级重试是一次带有更宽策略的新调用——在配置固定的提供方模式下无法表达。 -该 seam 仅约束与宿主共享文件系统和内核的子进程。容器、microVM 和远程执行器不是此 seam 的后端——它们以环境一致的组替换整个能力 seam(`ctx.shell`、`ctx.fs`)的 Service provider,因为一个 bash 在容器中运行而 fs 工具写主机的 agent 生活在两个割裂的世界中。 +该 seam 仅约束与宿主共享文件系统和内核的子进程。容器、microVM 和远程执行器不是此 seam 的后端——它们以环境一致的组替换整个能力 seam(`ctx.shell`、`ctx.fs`)的 Service Provider,因为一个 bash 在容器中运行而 fs 工具写主机的 agent 生活在两个割裂的世界中。 留待需要时再决定:网络限制是作为独立的 `network_mode` 到来,还是在某个 runner 同时强制两者后合并进 `sandbox_mode`;以及 `SandboxPolicy` 是现在就增加额外的可写根授权(launcher 已支持 `--rw `),还是等到升级机制需要时再加。 @@ -199,7 +199,7 @@ fs/web/todo 在进程内执行,因此它们的沙箱语义是各自能力边 本设计复制或对比的仓库内先例: -- [能力 seam Agent Note](../architecture/2026-06-13-capability-seams.md)——Service Definition/Service provider/Consumer 拆分与「不要过早拆分」的时机规则(第二个消费方满足了该规则)。 +- [能力 seam Agent Note](../architecture/2026-06-13-capability-seams.md)——Service Definition/Service Provider/Consumer 拆分与「不要过早拆分」的时机规则(第二个消费方满足了该规则)。 - `dsh-shell` 的 request/spec 拆分([bash 词汇目录](../../../../docs/subsystems/shell.md))——完整的 `sandboxPolicy` 搭载其按调用载体,以及显式 `resolve()` 默认约定。 - [批准 seam Agent Note](2026-07-06-approval-seam.md)——升级请求通过的通道;其应答器 waterfall(瀑布式事件)、审计对和单包理由记录在那里。 - [事件溯源会话](../architecture/2026-06-11-event-sourced-sessions.md)与[独立纯日志事件](../simplification/2026-07-28-remove-synthetic-log-only-turns.md)——按会话模式 fold 所依赖的日志即存储基础,以及锚定设计遵守的显式持久性边界。 diff --git a/.agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.i18n.yaml b/.agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.i18n.yaml index 40e2c6dd19..674176e65a 100644 --- a/.agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.i18n.yaml +++ b/.agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.i18n.yaml @@ -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 .agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.md -2026-07-27-trajectory-inspection-ledger.md: 74ed1f8ec6f6efcbf77e9caec7e254cb114efbd9 -2026-07-27-trajectory-inspection-ledger.zh.md: be648cb73478037979fd941753129b7c68be5085 +2026-07-27-trajectory-inspection-ledger.md: 7f97bc395ed694a0a750d3b744cc9887834ef32f +2026-07-27-trajectory-inspection-ledger.zh.md: 34bb8741124c410fe06ec18bdde801caa987f4fb diff --git a/.agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.md b/.agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.md index 74ed1f8ec6..7f97bc395e 100644 --- a/.agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.md +++ b/.agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.md @@ -21,7 +21,7 @@ Trajectory has to make prose, machine payloads, token usage, timing, and nested - Call schemas come from the active recorded Request header. Keyless snapshot fixtures deliberately replace that catalog with the non-array `{{tools}}` token, which the durable inspection boundary treats as unavailable instead of attempting to project or fabricate schemas. - Selecting a record or Request opens an inspector inside Trajectory. Tabs and Summary sections follow the selected entity: Markdown messages expose rendered content, source fields, provider/model fields, and hierarchy views; tools add JSON payload/result and schema views; Requests add options, usage, timing, and result navigation. Scrollable Summary regions keep their scrollbar thumbs transparent until hover or `focus-within`, while retaining the scrollbar reservation and scroll behavior. Images render as media rather than serialized data. - Turn folding removes all rows after its first record and replaces them with a compact step/tool-call count; Assistant folding applies the same interaction to its tool-call descendants. Global controls fold or expand both levels. -- A long ledger initially positions the loaded tail at the bottom and mounts only the viewport's row window plus bounded overscan. Request-only separators join the next measurable virtual item, with a terminal separator retaining its own fixed clearance, so the virtualizer never owns a zero-height item. Semantic DOM-safe row keys and ARIA indexes expose identity independently from mount position. A tail with known older history virtualizes immediately even when its loaded projection is below the ordinary row threshold. Stable-key virtualizer anchoring preserves the visible item across prepends and appends; the manual scroll-height fallback applies only when completing pagination disables virtualization. Selection, timeline focus, folding, search, and bottom following address records by stable event or tool-call identity rather than requiring their DOM rows to exist. An explicit loading row covers records until initial positioning finishes and while an older Session page is pending. +- A long ledger initially positions the loaded tail at the bottom and mounts only the viewport's row window plus bounded overscan. Request-only separators join the next measurable virtual item, with a terminal separator retaining its own fixed clearance, so the virtualizer never owns a zero-height item. Semantic DOM-safe row keys and ARIA indexes expose identity independently from mount position. A tail with known older history virtualizes immediately even when its loaded projection is below the ordinary row threshold. Stable-key virtualizer anchoring preserves the visible item across prepends and appends; the manual scroll-height fallback applies only when completing pagination disables virtualization. Selection, timeline focus, folding, search, and bottom following address records by stable event or tool-call identity rather than requiring their DOM rows to exist. An explicit loading row covers records until initial positioning finishes. While an older Session prefix remains unloaded, an interactive first row precedes the loaded records and requests one older page; the same row becomes a disabled loading status for a pending page and disappears only when paging completes. - The separate Waterfall tab is removed. A fixed Overview above the ledger projects every loaded record with known `startedAt` onto three semantic timing lanes using its own duration. While an older prefix remains unloaded and the viewport includes the loaded domain's start, a neutral ellipsis control covers the truncated edge and loads one earlier page without assigning unknown history a fabricated duration; hovering that control suppresses the ordinary timeline cursor. Finalized Assistant spans divide the recorded interval at the first non-empty token delta, so distinct TTFT and decoding colors retain their actual ratio; incomplete timing falls back to one Assistant color. Hovering for 500 ms exposes exact start/end, total duration, TTFT, and decoding time without relying on the browser's native tooltip delay. Dragging left or right commits an inclusive interval filter: any record whose active interval overlaps either boundary remains visible, records without known timing leave the focused ledger, and clearing the selection restores the full loaded ledger. Wheel gestures zoom the time domain. A right-button click clears the interval selection; dragging instead pans an already zoomed viewport without mutating it. The Overview keeps the full time domain while focused so the selection can be resized or cleared without losing orientation. - Live history updates retain the ledger's bottom position only while the user is already following its tail. Scrolling upward clears that follow state, so streamed chunks and newly appended records do not interrupt inspection of earlier rows. Tail following and virtualizer measurement react to row keys and heights rather than content identity, so text-only stream frames neither discard the measurement cache nor repeat a DOM scroll write. - Token streaming updates only the matching Trajectory Assistant Context, while publication is coalesced to at most once per animation frame. The target snapshot preserves the existing stage, layout, Request numbering, Overview, and search inputs; completed Assistant State retains assembled blocks, timing, and usage rather than every raw chunk payload, while Session keeps the raw Event window. diff --git a/.agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.zh.md b/.agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.zh.md index be648cb734..34bb874112 100644 --- a/.agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.zh.md +++ b/.agents/notes/implemented/feature/2026-07-27-trajectory-inspection-ledger.zh.md @@ -21,7 +21,7 @@ Status: implemented - 调用 schema 来自当前生效且已记录的请求头。无密钥快照 fixture(测试前置数据)有意将该目录替换为非数组 token `{{tools}}`,持久化检查边界会将其视为不可用,而不是尝试投影或虚构 schema。 - 选择记录或请求后,Trajectory 内部会打开检查器,其标签页和概述区域随实体类型变化:Markdown 消息提供渲染内容、来源字段、提供方/模型字段和层级视图;工具提供 JSON 载荷/结果和 schema 视图;请求提供选项、用量、计时和结果跳转。可滚动的概述区域默认保持滚动条滑块透明,直到悬停或 `focus-within` 时才显示,同时保留滚动条预留空间和滚动行为。图片以媒体形式渲染,而不是显示为序列化数据。 - 折叠轮次时保留其第一条记录,并用紧凑的步骤数和工具调用数替换后续所有行;折叠助手时对其工具调用后代应用相同操作。全局控件会折叠或展开这两个层级。 -- 长记录表初始时将已加载尾部置于底部,只挂载视口对应的行窗口及有界的额外缓冲行。仅含请求的分隔行并入下一个具备可测高度的虚拟项,末尾分隔行则保留固定留白,因此虚拟化器不会管理零高度项。可安全用于 DOM 的语义行键与 ARIA 索引使标识不依赖挂载位置。只要已知尾部之前仍有更早历史,即使当前已加载投影低于常规行数阈值,也会立即启用虚拟化。基于稳定键的虚拟化器锚定会在向前补页和尾部追加时保留当前可见项;只有分页完成导致虚拟化停用时,才使用手动滚动高度兜底。选择、时间线聚焦、折叠、搜索和末尾跟随均按稳定的事件或工具调用标识定位,不要求对应 DOM 行已存在。初始定位完成前以及更早 Session 页面仍在等待时,明确的加载行会遮住真实记录。 +- 长记录表初始时将已加载尾部置于底部,只挂载视口对应的行窗口及有界的额外缓冲行。仅含请求的分隔行并入下一个具备可测高度的虚拟项,末尾分隔行则保留固定留白,因此虚拟化器不会管理零高度项。可安全用于 DOM 的语义行键与 ARIA 索引使标识不依赖挂载位置。只要已知尾部之前仍有更早历史,即使当前已加载投影低于常规行数阈值,也会立即启用虚拟化。基于稳定键的虚拟化器锚定会在向前补页和尾部追加时保留当前可见项;只有分页完成导致虚拟化停用时,才使用手动滚动高度兜底。选择、时间线聚焦、折叠、搜索和末尾跟随均按稳定的事件或工具调用标识定位,不要求对应 DOM 行已存在。初始定位完成前,明确的加载行会遮住真实记录。更早的 Session 前缀仍未加载时,交互式首行位于已加载记录之前,可请求一页更早历史;页面加载期间,同一行会变为禁用的加载状态,仅在分页完成时消失。 - 移除独立的 waterfall(瀑布式事件)标签页。固定在记录表上方的 Overview 区域将所有 `startedAt` 已知的已加载记录按各自耗时投影到三条语义计时轨道。仍有更早前缀尚未加载且 viewport 包含已加载时间域起点时,中性的省略号控件会遮住截断边缘并加载一页更早历史,而不会为未知历史虚构耗时;悬停在该控件上会隐藏普通的时间线光标。已完成的助手时间条以首个非空 token 增量为分界,用不同颜色按真实比例表示 TTFT 与解码时间;计时不完整时退化为单一助手色。悬停 500 ms 后会显示精确起止时刻、总耗时、TTFT 和解码时间,而不依赖浏览器原生 tooltip 的延迟。向左或向右拖动会提交包含边界的区间筛选:任何活动区间与所选区间任一边界重叠的记录都会保留,计时未知的记录会从聚焦后的记录表中移除,清除选择则恢复完整的已加载记录表。滚轮手势用于缩放时间域。右键单击会清除区间选择;右键拖动则只会平移已放大的 viewport,不会改变该选区。聚焦后,Overview 区域仍保留完整时间范围,以便在不失去方位的情况下调整或清除选择。 - 实时历史更新仅在用户已经跟随记录表末尾时保留底部位置。向上滚动会清除跟随状态,因此流式分块和新追加的记录不会打断对旧记录的检查。末尾跟随与虚拟化器测量仅响应行键和高度,而非内容标识,因此仅含文本的流式帧既不会丢弃测量缓存,也不会重复执行 DOM 滚动写入。 - token 流式输出只更新命中的 Trajectory Assistant Context,发布则合并为每个 animation frame 最多一次。target snapshot 继续提供既有 stage、layout、请求编号、Overview 与搜索输入;已完成的 Assistant State 只保留组装后的 blocks、计时与 usage,不保留每条原始 chunk payload,而 Session 继续保存原始 Event 窗口。 diff --git a/.agents/notes/implemented/feature/2026-07-27-typescript-sdk-and-sdk-subagent-backend.i18n.yaml b/.agents/notes/implemented/feature/2026-07-27-typescript-sdk-and-sdk-subagent-backend.i18n.yaml index 354bc66050..7357dd353d 100644 --- a/.agents/notes/implemented/feature/2026-07-27-typescript-sdk-and-sdk-subagent-backend.i18n.yaml +++ b/.agents/notes/implemented/feature/2026-07-27-typescript-sdk-and-sdk-subagent-backend.i18n.yaml @@ -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 .agents/notes/implemented/feature/2026-07-27-typescript-sdk-and-sdk-subagent-backend.md -2026-07-27-typescript-sdk-and-sdk-subagent-backend.md: 8b17603e5c90941778835befd84d114a3f3cd78b -2026-07-27-typescript-sdk-and-sdk-subagent-backend.zh.md: fe5026871778bfcdcb85b71704d79e6fa678188d +2026-07-27-typescript-sdk-and-sdk-subagent-backend.md: 84314eaf5827464767666b1b9c65e105ea4e869a +2026-07-27-typescript-sdk-and-sdk-subagent-backend.zh.md: 48f292514844d59d2084731b30bcb5ba7fb563d5 diff --git a/.agents/notes/implemented/feature/2026-07-27-typescript-sdk-and-sdk-subagent-backend.md b/.agents/notes/implemented/feature/2026-07-27-typescript-sdk-and-sdk-subagent-backend.md index 8b17603e5c..84314eaf58 100644 --- a/.agents/notes/implemented/feature/2026-07-27-typescript-sdk-and-sdk-subagent-backend.md +++ b/.agents/notes/implemented/feature/2026-07-27-typescript-sdk-and-sdk-subagent-backend.md @@ -10,7 +10,7 @@ The stdio JSON-RPC serving surface (`@deepseek-ai/dsh-sdk-jsonrpc-server`, the [ ## Decision -Three packages, layered exactly like the existing Python stack, plus one Service provider registration: +Three packages, layered exactly like the existing Python stack, plus one Service Provider registration: - **`@deepseek-ai/dsh-sdk-protocol`** (`packages/sdk/protocol/`) — the wire made shared and nominal. `JsonRpcLineTransport` moves here verbatim from `dsh-sdk-jsonrpc-server` (which now imports it), and `types.ts` names every payload the server speaks: `InitializeParams/Result`, `SessionPromptParams/Result`, the four notification payloads, and the `HarnessSdkRequestMap`/`HarnessSdkNotificationMap` indexes. The package root explicitly exports that complete interface and provides no source-module deep imports. The server's `notify()` call sites are typed against these named payloads, so server drift breaks compilation, not clients. One behavioral change: an error response now rejects with `JsonRpcResponseError` carrying the wire `code`/`data` (the Python client already preserved these; the old transport threw a bare `Error` with only the message). - **`@deepseek-ai/dsh-sdk-client`** (`packages/sdk/client/`) — the TypeScript twin of `python/sdk`: `HarnessClient` (spawn, frame, fan out notifications, typed error surfaces, close-to-quiescence via the shared dispose ladder) under `DeepSeekHarness`/`HarnessSession` (lazy start, memoized `initialize`, `run()` pairing one `session/prompt` with its `session.finished`). Its package-root consumer interface explicitly exports both client layers, caller-facing types, and the protocol-owned `JsonRpcResponseError`; source modules, normalization helpers, and the notification producer stay internal. `TurnResult.events` contains only the root session's typed events, while `notifications` retains session ids across the root and descendants discovered from `subagent.started`; session-tree scoping is client-side, mirroring `client.py`. Deliberate asymmetries with Python: the launch spec is explicit `command`/`args` (no bundled-runtime resolution — that is a distribution concern with no TS consumer yet); `env` replaces rather than merges (callers own credential policy; `scrubbedParentEnv` from the subprocess seam is one import away); `TurnResult` carries the structured `reason` (Python exposes only `status`); teardown walks a private stdin-EOF → SIGTERM → SIGKILL ladder to actual exit (the client runs outside any harness context, so it cannot ride `ctx.subprocess`). @@ -30,7 +30,7 @@ Four tiers, per [testing policy](../../../../docs/testing.md): ## Alternatives considered -**Import wire types from `dsh-sdk-jsonrpc-server` instead of extracting a protocol package.** Makes every SDK consumer (including `subagent-dsh-sdk`, which must not serve JSON-RPC) depend on the server plugin and its `dsh-agent`/`dsh-llm-deepseek` peer set, and leaves the notification payloads anonymous. The capability-seam rule (Service Definition / Service provider / Consumer as separate packages) already names this shape; the transport is genuinely two-sided. +**Import wire types from `dsh-sdk-jsonrpc-server` instead of extracting a protocol package.** Makes every SDK consumer (including `subagent-dsh-sdk`, which must not serve JSON-RPC) depend on the server plugin and its `dsh-agent`/`dsh-llm-deepseek` peer set, and leaves the notification payloads anonymous. The capability-seam rule (Service Definition / Service Provider / Consumer as separate packages) already names this shape; the transport is genuinely two-sided. **Have `subagent-dsh-sdk` speak raw JSON-RPC without the client SDK.** Duplicates the request/notification pairing, subscription fan-out, timeout, and teardown logic the SDK exists to own; the user's ask was explicitly a backend that *uses* the SDK, and the layering earns its keep by making the backend ~200 lines of policy over a reusable client. diff --git a/.agents/notes/implemented/feature/2026-07-27-typescript-sdk-and-sdk-subagent-backend.zh.md b/.agents/notes/implemented/feature/2026-07-27-typescript-sdk-and-sdk-subagent-backend.zh.md index fe50268717..48f2925148 100644 --- a/.agents/notes/implemented/feature/2026-07-27-typescript-sdk-and-sdk-subagent-backend.zh.md +++ b/.agents/notes/implemented/feature/2026-07-27-typescript-sdk-and-sdk-subagent-backend.zh.md @@ -10,7 +10,7 @@ stdio JSON-RPC 对外服务接口(`@deepseek-ai/dsh-sdk-jsonrpc-server`,见[ ## 决策 -三个包,分层与既有 Python 栈完全一致,外加一个 Service provider 注册: +三个包,分层与既有 Python 栈完全一致,外加一个 Service Provider 注册: - **`@deepseek-ai/dsh-sdk-protocol`**(`packages/sdk/protocol/`)—— 把线协议做成共享且具名。`JsonRpcLineTransport` 从 `dsh-sdk-jsonrpc-server` 原样移入(后者现在导入它),`types.ts` 为服务器所说的每个载荷命名:`InitializeParams/Result`、`SessionPromptParams/Result`、四个通知载荷,以及 `HarnessSdkRequestMap`/`HarnessSdkNotificationMap` 索引。该包根显式导出这一完整接口,且不提供指向源模块的深层导入。服务器的 `notify()` 调用点以这些具名载荷标注类型,服务器漂移会先破坏编译而不是破坏客户端。一处行为变化:错误响应现在以携带线上 `code`/`data` 的 `JsonRpcResponseError` 拒绝(Python 客户端本就保留这些;旧传输只抛携带消息的裸 `Error`)。 - **`@deepseek-ai/dsh-sdk-client`**(`packages/sdk/client/`)—— `python/sdk` 的 TypeScript 孪生:`HarnessClient`(spawn、分帧、通知扇出、有类型的错误表面、经共享 dispose(资源释放)阶梯关闭至完全停稳)之上是 `DeepSeekHarness`/`HarnessSession`(惰性启动、记忆化 `initialize`、`run()` 把一个 `session/prompt` 与其 `session.finished` 配对)。其包根消费方接口显式导出两层客户端、面向调用方的类型,以及协议包所拥有的 `JsonRpcResponseError`;源模块、规范化辅助函数和通知投递端都保留为内部实现。`TurnResult.events` 只包含根会话的类型化事件,而 `notifications` 则保留根会话及从 `subagent.started` 发现的后代各自的会话 id;基于 `subagent.started` 血缘边的会话树范围限定在客户端完成,镜像 `client.py`。与 Python 的刻意不对称:启动规格是显式 `command`/`args`(无捆绑运行时解析——那是尚无 TS 消费方的发行问题);`env` 整体替换而非合并(凭据策略归调用方;subprocess seam 的 `scrubbedParentEnv` 一个 import 即得);`TurnResult` 携带结构化 `reason`(Python 只暴露 `status`);拆除走私有的 stdin-EOF → SIGTERM → SIGKILL 阶梯直到真正退出(客户端运行在任何 harness 上下文之外,无法搭乘 `ctx.subprocess`)。 @@ -30,7 +30,7 @@ stdio JSON-RPC 对外服务接口(`@deepseek-ai/dsh-sdk-jsonrpc-server`,见[ ## 考虑过的替代方案 -**从 `dsh-sdk-jsonrpc-server` 导入协议类型而不是提取协议包。** 会让每个 SDK 消费方(包括绝不能提供 JSON-RPC 服务的 `subagent-dsh-sdk`)依赖服务器插件及其 `dsh-agent`/`dsh-llm-deepseek` peer 集合,且通知载荷仍然匿名。能力 seam 规则(Service Definition/Service provider/Consumer 三个包分立)已经点名了这种形态;这个传输是货真价实的双边物。 +**从 `dsh-sdk-jsonrpc-server` 导入协议类型而不是提取协议包。** 会让每个 SDK 消费方(包括绝不能提供 JSON-RPC 服务的 `subagent-dsh-sdk`)依赖服务器插件及其 `dsh-agent`/`dsh-llm-deepseek` peer 集合,且通知载荷仍然匿名。能力 seam 规则(Service Definition/Service Provider/Consumer 三个包分立)已经点名了这种形态;这个传输是货真价实的双边物。 **让 `subagent-dsh-sdk` 直说裸 JSON-RPC、绕开客户端 SDK。** 会复制 SDK 存在意义所在的请求/通知配对、订阅扇出、超时与拆除逻辑;用户的要求明确是一个*使用* SDK 的后端,分层的回报是后端成为可复用客户端之上约 200 行的纯策略。 diff --git a/.agents/notes/implemented/feature/2026-07-30-current-sandbox-policy-context.i18n.yaml b/.agents/notes/implemented/feature/2026-07-30-current-sandbox-policy-context.i18n.yaml index 5455415389..695a161749 100644 --- a/.agents/notes/implemented/feature/2026-07-30-current-sandbox-policy-context.i18n.yaml +++ b/.agents/notes/implemented/feature/2026-07-30-current-sandbox-policy-context.i18n.yaml @@ -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 .agents/notes/implemented/feature/2026-07-30-current-sandbox-policy-context.md -2026-07-30-current-sandbox-policy-context.md: ab231d19aec4852369c0f1a13fc50c69ab8128f1 -2026-07-30-current-sandbox-policy-context.zh.md: 4ac493dcfff5c286d569a46c34686dc4b8746618 +2026-07-30-current-sandbox-policy-context.md: b4c657ba52ff26e2e295e3635201424a155738d0 +2026-07-30-current-sandbox-policy-context.zh.md: bd32b021ef8622dc6843a163b21714a263bc8bed diff --git a/.agents/notes/implemented/feature/2026-07-30-current-sandbox-policy-context.md b/.agents/notes/implemented/feature/2026-07-30-current-sandbox-policy-context.md index ab231d19ae..b4c657ba52 100644 --- a/.agents/notes/implemented/feature/2026-07-30-current-sandbox-policy-context.md +++ b/.agents/notes/implemented/feature/2026-07-30-current-sandbox-policy-context.md @@ -12,7 +12,7 @@ The sandbox policy already enforced and logged each session's file-effect mode, `dsh-sandbox-policy`, the owner of mode and workspace-root resolution, registers one `sandbox:policy` cache-safe context contribution. Every agent request resolves the active session directly through `ctx.sandboxPolicy.resolve({ session })`; there is no denial-history scan or process-local “last told” state. -The policy contribution is capability-neutral and present for every agent session. It does not maintain a second inventory of mounted backends or tools; model-visible schemas remain the authority for available operations, while the context conditions its claims on any available operation that the DSH file sandbox enforces. The [capability-neutral policy context decision](../simplification/2026-07-31-capability-neutral-sandbox-policy-context.md) supersedes the earlier family-registration mechanism while retaining this note's cache-safe delivery and durable snapshot design. +The policy contribution is capability-neutral and available to every agent session by default. A composition may suppress the complete runtime-context channel when its model interface intentionally excludes dynamic context; this does not disable policy enforcement. The contribution does not maintain a second inventory of mounted backends or tools; model-visible schemas remain the authority for available operations, while the context conditions its claims on any available operation that the DSH file sandbox enforces. The [capability-neutral policy context decision](../simplification/2026-07-31-capability-neutral-sandbox-policy-context.md) supersedes the earlier family-registration mechanism while retaining this note's cache-safe delivery and durable snapshot design. The contribution states only facts shared by every enforcement dialect. `read-only` says an available sandbox-enforced operation cannot modify files in the standing mode and directs the model to try an available tool normally, then follow any denial and escalation guidance that tool returns. `workspace-write` states the canonical session workspace with non-exclusive wording and summarizes, without enumerating, that some platform temporary areas may also be writable. `danger-full-access` says the DSH file sandbox does not restrict file modifications by available operations. Backend-selected temporary paths, `/dev/null`, runner readiness, exact tool availability, and other policy domains are absent because `resolve()` cannot establish them at request assembly. diff --git a/.agents/notes/implemented/feature/2026-07-30-current-sandbox-policy-context.zh.md b/.agents/notes/implemented/feature/2026-07-30-current-sandbox-policy-context.zh.md index 4ac493dcff..bd32b021ef 100644 --- a/.agents/notes/implemented/feature/2026-07-30-current-sandbox-policy-context.zh.md +++ b/.agents/notes/implemented/feature/2026-07-30-current-sandbox-policy-context.zh.md @@ -12,7 +12,7 @@ Status: implemented `dsh-sandbox-policy` 负责解析模式与工作区根目录,并注册一项缓存安全的 `sandbox:policy` 上下文贡献。每次 agent(智能体)请求都通过 `ctx.sandboxPolicy.resolve({ session })` 直接解析当前会话;不存在拒绝历史扫描或进程本地的「上次告知」状态。 -该策略贡献不依赖具体能力,并存在于每个 agent 会话中。它不会另行维护一份已挂载后端或工具清单;模型可见的 schema 仍是可用操作的权威来源,而上下文会将其声明限定在 DSH 文件沙箱所强制执行的任何可用操作上。[不依赖具体能力的策略上下文决策](../simplification/2026-07-31-capability-neutral-sandbox-policy-context.md)取代了较早的家族注册机制,同时保留本 Agent Note 的缓存安全交付与持久快照设计。 +该策略贡献不依赖具体能力,并默认可用于每个 agent 会话。当模型接口有意排除动态上下文时,组合可以抑制完整的 runtime-context 通道;这不会禁用策略强制机制。该贡献不会另行维护一份已挂载后端或工具清单;模型可见的 schema 仍是可用操作的权威来源,而上下文会将其声明限定在 DSH 文件沙箱所强制执行的任何可用操作上。[不依赖具体能力的策略上下文决策](../simplification/2026-07-31-capability-neutral-sandbox-policy-context.md)取代了较早的家族注册机制,同时保留本 Agent Note 的缓存安全交付与持久快照设计。 该贡献只说明所有强制执行方言所共有的事实。`read-only` 表明受沙箱强制执行的可用操作在常驻模式下无法修改文件,并指示模型正常尝试可用工具,随后遵循该工具返回的任何拒绝与升权引导。`workspace-write` 用非排他措辞说明规范化的会话工作区,并概述某些平台临时区域可能也可写,而不逐一列举。`danger-full-access` 表明 DSH 文件沙箱不会限制可用操作修改文件。后端选择的临时路径、`/dev/null`、runner 就绪状态、确切的工具可用情况和其他策略领域都不会出现,因为 `resolve()` 无法在请求组装时确定它们。 diff --git a/.agents/notes/implemented/feature/2026-07-30-deepseek-onboarding-credential-setup.i18n.yaml b/.agents/notes/implemented/feature/2026-07-30-deepseek-onboarding-credential-setup.i18n.yaml index 4f037737ff..5ef2099535 100644 --- a/.agents/notes/implemented/feature/2026-07-30-deepseek-onboarding-credential-setup.i18n.yaml +++ b/.agents/notes/implemented/feature/2026-07-30-deepseek-onboarding-credential-setup.i18n.yaml @@ -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 .agents/notes/implemented/feature/2026-07-30-deepseek-onboarding-credential-setup.md -2026-07-30-deepseek-onboarding-credential-setup.md: ebf5c66cffa8a7db90328dfcdd04e4134a78e3b1 -2026-07-30-deepseek-onboarding-credential-setup.zh.md: 3df63c59fd23acf32c16dac8f4ca373409ab2968 +2026-07-30-deepseek-onboarding-credential-setup.md: 823d10a723af70ec4ff51018b8b86198db0f5c29 +2026-07-30-deepseek-onboarding-credential-setup.zh.md: 7e8d79c23c4b1489bfd818c90558f36509635486 diff --git a/.agents/notes/implemented/feature/2026-07-30-deepseek-onboarding-credential-setup.md b/.agents/notes/implemented/feature/2026-07-30-deepseek-onboarding-credential-setup.md index ebf5c66cff..823d10a723 100644 --- a/.agents/notes/implemented/feature/2026-07-30-deepseek-onboarding-credential-setup.md +++ b/.agents/notes/implemented/feature/2026-07-30-deepseek-onboarding-credential-setup.md @@ -12,9 +12,9 @@ The [web configuration plane](../architecture/2026-07-30-web-config-plane.md) ma **One readiness projection owns both Models and onboarding facts.** `ui-settings-models` keeps a single store that joins `llm.providers({})`, redacted `settings.describe({})`, and batched `credentials.describe({refs})`. The onboarding projection selects the `deepseek-official` configurable-provider entry owned by the `llm-deepseek` namespace and empty settings path, reads the effective `apiKeyEnv`, and evaluates the matching credential descriptor. A live route with the same provider id but no matching configurable-provider declaration is adapter-absent for onboarding. A configured process-environment credential is ready and remains read-only. -**The settings shell contributes ordering and navigation, not provider policy.** `ui-settings` declares a root-scoped `settings.onboarding` list slot and mounts one ordered step at a time while the current surface is the empty Hero. The active registrant receives `complete()` and a private `openSection(id)` callback; completion transfers ownership to the next entry. `ui-settings-models` registers the DeepSeek step and its Models section through `slots.inject()`, so each contribution follows its declaration lifetime without making plugin load order a contract, and independently contributed dialogs cannot stack. The product-wide welcome step that precedes it is owned separately by [the versioned welcome decision](2026-07-30-versioned-gui-welcome-onboarding.md). +**The settings shell contributes ordering, not provider policy.** `ui-settings` declares a root-scoped `settings.onboarding` list slot and mounts one ordered step at a time while the current surface is the empty Hero. The active registrant receives `complete()` and a private `openSection(id)` callback; completion transfers ownership to the next entry. `ui-settings-models` registers the DeepSeek step, the preceding welcome notice, and its Models section through `slots.inject()`, so every contribution follows one client Cordis plugin's lifecycle and the dialogs cannot stack. Their common presentation is owned by the [shared-modal onboarding decision](2026-08-13-shared-modal-product-onboarding.md). -**The prompt routes to the one credential editor.** A mounted, active adapter with a resolved, writable, unconfigured reference presents one action that opens Settings on Models. The existing DeepSeek setup card there exclusively owns the password input, `credentials.set({ref, value})`, write failures, and post-write refresh; the onboarding overlay never holds or submits a secret. An unavailable settings or credential capability keeps its deployment diagnostic and routes to the same page, while an absent adapter remains skipped because navigation cannot mount a Cordis plugin. +**The prompt renders the existing credential editor inline.** A mounted, active adapter with a resolved, writable, unconfigured reference renders `ProviderEditor` in credential-only mode inside the shared onboarding modal. The same component owns the password input, validation, `credentials.set({ref, value})`, write failures, and post-write refresh; credential-only mode emits no provider-settings mutation. Configure later completes only this coordinator pass. An absent adapter remains skipped because the browser cannot mount a missing Cordis plugin. **Unavailable states do not capture the product.** An absent configurable-provider entry, inactive route, failed initial join, read-only deployment, or unresolved settings or credential capability completes the step without rendering because the onboarding action cannot repair that state. The Models page remains the deployment diagnostic and retry surface. Configure later completes a missing-credential step for the current mounted coordinator pass and writes no completion fact. Settings, credential, provider-topology, and connection invalidations all refresh the shared join, so an external credential update completes an open step without a reload. @@ -22,7 +22,7 @@ The [web configuration plane](../architecture/2026-07-30-web-config-plane.md) ma **A separate onboarding store and readiness RPC sequence** — rejected because it would create a second client-side interpretation of provider identity, settings paths, secret sidecars, credential references, and invalidation ordering beside the Models page. -**A second API-key editor inside onboarding** — rejected because the Models page already renders its DeepSeek setup card for exactly this state. Duplicating its secret draft, write errors, and configured-state convergence would add a second security-sensitive UI without another user capability. +**A standalone API-key implementation inside onboarding** — rejected because it would duplicate the Models editor's secret draft, validation, errors, and configured-state convergence. The modal renders the existing `ProviderEditor` in a constrained mode instead. **Writing the API key into provider settings** — rejected because a literal secret would enter the settings mutation path and whole-section replacement cannot safely reconstruct redacted values. Credential storage is already the product seam and supplies immediate invalidation. @@ -30,4 +30,4 @@ The [web configuration plane](../architecture/2026-07-30-web-config-plane.md) ma ## Consequences -The ordered flow leads from the product notice to the shipped adapter's existing editor without restarting: a keyless browser test boots the real Web composition under an isolated harness home, acknowledges the notice, follows the DeepSeek page to Models, stores a generated key through that page into the home's `.credentials.yaml`, verifies no key reaches DOM, ARIA, or browser console output, and confirms the running page reports configured. The full keyless Web replay lane also pins that a non-configurable replay route with the same provider id does not block unrelated journeys. Pure readiness and React tests pin managed-file and process-environment credentials, missing providers and capabilities, navigation, cancellation, external invalidation, and coordinator transfer. The flow deliberately inherits the configuration plane's documented base limitations rather than adding local secret storage, redaction, or settings replacement workarounds. +The ordered flow leads from the product notice to an inline key form without restarting: a keyless browser test boots the real Web composition under an isolated harness home, acknowledges the notice, stores a generated key from the shared modal into the home's `.credentials.yaml`, verifies no key reaches DOM, ARIA, or browser console output, and confirms the ordinary Models page reports configured. The full keyless Web replay lane also pins that a non-configurable replay route with the same provider id does not block unrelated journeys. Pure readiness and React tests pin managed-file and process-environment credentials, missing providers and capabilities, cancellation, external invalidation, and coordinator transfer. The flow deliberately inherits the configuration plane's documented base limitations rather than adding local secret storage, redaction, or settings replacement workarounds. diff --git a/.agents/notes/implemented/feature/2026-07-30-deepseek-onboarding-credential-setup.zh.md b/.agents/notes/implemented/feature/2026-07-30-deepseek-onboarding-credential-setup.zh.md index 3df63c59fd..7e8d79c23c 100644 --- a/.agents/notes/implemented/feature/2026-07-30-deepseek-onboarding-credential-setup.zh.md +++ b/.agents/notes/implemented/feature/2026-07-30-deepseek-onboarding-credential-setup.zh.md @@ -12,9 +12,9 @@ Status: implemented **Models 与首次使用引导共享同一个就绪状态投影。**`ui-settings-models` 维护一个 store,把 `llm.providers({})`、脱敏后的 `settings.describe({})` 和批量调用的 `credentials.describe({refs})` 联接为同一份状态。首次使用投影选取由 `llm-deepseek` namespace 与空 settings path 持有的 `deepseek-official` 可配置提供方条目,读取生效的 `apiKeyEnv`,并检查对应的凭据描述符。同 provider id 但没有匹配可配置提供方声明的存活路由,在首次使用引导中视为适配器缺失。通过进程环境提供的凭据若已配置,则判定为就绪并保持只读。 -**设置外壳只贡献排序与导航,不持有提供方策略。** `ui-settings` 声明一个根作用域的 `settings.onboarding` list slot,并在当前界面为空白 Hero 时,每次只挂载一个有序步骤。当前注册方会收到 `complete()` 和私有 `openSection(id)` 回调;完成当前步骤后,所有权转交给下一项。`ui-settings-models` 通过 `slots.inject()` 注册 DeepSeek 步骤及其 Models 分区,使每项贡献都跟随自身的声明生命周期,不让插件加载顺序成为约定;独立贡献的对话框也无法堆叠。排在它之前的产品级欢迎步骤由[版本化欢迎决策](2026-07-30-versioned-gui-welcome-onboarding.md)单独持有。 +**设置外壳只贡献排序,不持有提供方策略。** `ui-settings` 声明一个根作用域的 `settings.onboarding` list slot,并在当前界面为空白 Hero 时,每次只挂载一个有序步骤。当前注册方会收到 `complete()` 和私有 `openSection(id)` 回调;完成当前步骤后,所有权转交给下一项。`ui-settings-models` 通过 `slots.inject()` 注册 DeepSeek 步骤、排在它之前的欢迎声明及 Models 分区,因此所有贡献都跟随同一个 client Cordis 插件的生命周期,两个弹窗也无法堆叠。它们的共用展示由[共用弹窗引导决策](2026-08-13-shared-modal-product-onboarding.md)持有。 -**首次使用页面只负责跳转到唯一的凭据编辑器。**适配器已挂载且处于活跃状态,其引用可解析、可写但尚未配置时,界面会显示一个操作按钮,用于打开「设置」的 Models 分区。该分区已有的 DeepSeek 设置卡片全权负责密码输入框、`credentials.set({ref, value})`、写入失败处理和写入后刷新;首次使用页面绝不持有或提交 secret。 +**首次使用弹窗行内渲染既有凭据编辑器。** 适配器已挂载且处于活跃状态,其引用可解析、可写但尚未配置时,`ProviderEditor` 会以仅凭据模式渲染在共用引导弹窗中。同一个组件全权负责密码输入框、校验、`credentials.set({ref, value})`、写入失败处理和写入后刷新;仅凭据模式不会发出提供方 settings 变更。「稍后配置」只完成协调器当前这一轮。适配器缺失时仍跳过,因为浏览器不能挂载缺失的 Cordis 插件。 **不可用状态不会占住产品。** 可配置提供方条目缺失、路由不活跃、初始联接失败、部署只读或设置/凭据能力无法解析时,都会直接完成而不渲染该步骤,因为首次使用引导无法修复这些状态。Models 页仍是部署诊断与重试界面。「稍后配置」只会完成协调器当前这一次缺少凭据的步骤,不写入任何完成状态。设置、凭据、提供方拓扑和连接失效事件都会刷新共享联接,因此外部凭据更新无需重新加载页面即可完成已打开的步骤。 @@ -22,7 +22,7 @@ Status: implemented **为首次使用引导单设 store 与就绪状态 RPC 调用序列**:不予采用,因为这会在 Models 页之外,再建立一套客户端解释,用于判定提供方身份、设置路径、secret 槽位的伴随信息、凭据引用及失效事件顺序。 -**在首次使用引导中增设第二个 API key 编辑器**:不予采用,因为 Models 页已为这一状态渲染 DeepSeek 设置卡片。复制其中的 secret 草稿、写入错误处理和已配置状态收敛会增加第二个安全敏感的 UI,却不会带来新的用户能力。 +**在首次使用引导中单独实现 API key 表单**:不予采用,因为这会复制 Models 编辑器的 secret 草稿、校验、错误和已配置状态收敛。弹窗改为以受限模式渲染既有 `ProviderEditor`。 **把 API key 写入提供方设置**:不予采用,因为字面量 secret 会进入设置变更路径,而整个分节替换无法安全重建脱敏值。凭据存储已经是产品 seam,并能立即发出失效事件。 @@ -30,4 +30,4 @@ Status: implemented ## 后果 -有序流程从产品声明页开始,无需重启即可引导用户前往随产品提供的适配器已有的编辑器:无密钥浏览器测试在隔离的 harness 家目录下启动真实 Web 组合,确认声明后依照 DeepSeek 页面前往 Models,通过该页面把生成的密钥存入该目录的 `.credentials.yaml`,验证密钥未进入 DOM、ARIA 或浏览器控制台输出,并确认运行中的页面报告已配置。完整的无密钥 Web 回放也固定了同 id 的不可配置回放路由不会阻塞无关流程。纯就绪状态测试与 React 测试固化了受管文件凭据与进程环境凭据、提供方与能力缺失、导航、取消、外部失效和协调器移交。该流程直接继承配置平面已记录的基础限制,不会另加局部的机密存储、脱敏或设置替换变通方案。 +有序流程从产品声明页开始,无需重启即可进入行内密钥表单:无密钥浏览器测试在隔离的 harness 家目录下启动真实 Web 组合,确认声明后从共用弹窗把生成的密钥存入该目录的 `.credentials.yaml`,验证密钥未进入 DOM、ARIA 或浏览器控制台输出,并确认普通 Models 页面报告已配置。完整的无密钥 Web 回放也固定了同 id 的不可配置回放路由不会阻塞无关流程。纯就绪状态测试与 React 测试固化了受管文件凭据与进程环境凭据、提供方与能力缺失、取消、外部失效和协调器移交。该流程直接继承配置平面已记录的基础限制,不会另加局部的机密存储、脱敏或设置替换变通方案。 diff --git a/.agents/notes/implemented/feature/2026-07-30-versioned-gui-welcome-onboarding.i18n.yaml b/.agents/notes/implemented/feature/2026-07-30-versioned-gui-welcome-onboarding.i18n.yaml index abe1f687fb..630898f12a 100644 --- a/.agents/notes/implemented/feature/2026-07-30-versioned-gui-welcome-onboarding.i18n.yaml +++ b/.agents/notes/implemented/feature/2026-07-30-versioned-gui-welcome-onboarding.i18n.yaml @@ -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 .agents/notes/implemented/feature/2026-07-30-versioned-gui-welcome-onboarding.md -2026-07-30-versioned-gui-welcome-onboarding.md: 8897e28413df77d127a4d846f2a3e42789454490 -2026-07-30-versioned-gui-welcome-onboarding.zh.md: 9f5eb99033cd62154937808f26b0e1aa40966c9f +2026-07-30-versioned-gui-welcome-onboarding.md: 9c8684c0510c50c28e8ece53fd794844c771e496 +2026-07-30-versioned-gui-welcome-onboarding.zh.md: 52c35bf46e40afca1248bcbb94f38d7154f138a4 diff --git a/.agents/notes/implemented/feature/2026-07-30-versioned-gui-welcome-onboarding.md b/.agents/notes/implemented/feature/2026-07-30-versioned-gui-welcome-onboarding.md index 8897e28413..9c8684c051 100644 --- a/.agents/notes/implemented/feature/2026-07-30-versioned-gui-welcome-onboarding.md +++ b/.agents/notes/implemented/feature/2026-07-30-versioned-gui-welcome-onboarding.md @@ -10,15 +10,13 @@ The GUI's credential onboarding begins with a DeepSeek-specific readiness check, ## Decision -**The Settings shell coordinates ordered steps.** `settings.onboarding` remains a root-scoped list, but `ui-settings` projects its entry ids and order into one coordinator and mounts only the first incomplete step. The active registrant receives `complete()` and `openSection(id)`; no later step mounts until ownership transfers. The product welcome registers at order `-100`, while `ui-settings-models` retains only the conditional DeepSeek readiness and credential-routing step at order `0`. +**The Settings shell coordinates ordered steps.** `settings.onboarding` remains a root-scoped list, but `ui-settings` projects its entry ids and order into one coordinator and mounts only the first incomplete step. The active registrant receives `complete()` and `openSection(id)`; no later step mounts until ownership transfers. `ui-settings-models` now registers the restored welcome notice at order `-100` and the conditional DeepSeek credential step at order `0`; their current shared presentation is owned by the [shared-modal onboarding decision](2026-08-13-shared-modal-product-onboarding.md). -**Ownerless product onboarding belongs to `ui-settings-general`.** `src/onboarding-copy.ts` is the single editable source for the complete notice, the Continue label, and `WELCOME_NOTICE_VERSION`; both supported GUI locales intentionally render the same Chinese owner copy. Runtime locale dictionaries derive their welcome values from that file, and tests import the same owner instead of repeating paragraph text. The notice is browser UI only: it creates no Session event and contributes no model-visible content. The notice states that session telemetry is [disabled by default](2026-08-10-telemetry-default-off.md) and names the `FEEDBACK_ONLY` and `FULL` opt-in modes. +**The product welcome step is versioned and feature-owned.** The notice was historically removed by the [first-run beta notice removal](../simplification/2026-08-13-remove-first-run-beta-notice.md) and is now restored in `ui-settings-models` with new testing-stage copy. `ui-settings-general` still seats no onboarding step; the plugin that owns both current steps also owns the copy, store, and shared modal. -**Loopback acknowledgement is durable per Harness profile.** The Host half registers a `ui-onboarding` section in the user-settings seam, stored under the active `$DSH_HOME/settings.yaml`. The connection plugin publishes whether the current page uses a loopback authority as `ctx.connection.isLoopback`; hostname classification remains internal to the connection package, and other client plugins consume the service state instead of importing its implementation. A loopback browser shows the notice unless `welcomeNoticeVersion` equals the owner constant exactly. Continue applies one path mutation with the current version and calls `complete()` only after the Host commits it; a failed write leaves the notice open, and closing the page or process writes nothing. Bumping the constant intentionally makes every profile acknowledge the revised copy once. A non-loopback browser must not call the loopback-only settings API. It presents the same notice, but explicit Continue completes the step only in the current browser process; reload or a new process presents it again. +**The durable `ui-onboarding` section owns acknowledgement.** The Host half registers it in the user-settings seam under the active `$DSH_HOME/settings.yaml`; the current welcome store reads and writes `welcomeNoticeVersion` through the existing public settings API. The connection plugin publishes whether the current page uses a loopback authority as `ctx.connection.isLoopback`; hostname classification remains internal to the connection package, and other client plugins consume the service state instead of importing its implementation. The API proxy exposes this one product namespace through a closed allowlist beside configurable-provider namespaces, without treating its changes as model-catalog invalidations. -**Concurrent loopback views converge without stale replacement.** The acknowledgement write omits `expectedRevision` deliberately: every loopback tab writes the same version to one path, so the operation is idempotent and preserves sibling fields instead of rebuilding the section. `settings/document-updated` reaches the client as an invalidation — through `host/settings-changed` then, and forwarded verbatim now ([forwarded Remote events](../architecture/2026-08-10-remote-event-delivery.md)); an already mounted loopback tab refetches and advances when another tab or an external editor commits the current version. The API proxy exposes this one product namespace through a closed allowlist beside configurable-provider namespaces, without treating its changes as model-catalog invalidations. - -**Onboarding temporarily owns the viewport as one continuous stage.** A solid product surface replaces the complete application view through a body-level portal and marks the underlying app root inert; the exact required mask remains mounted behind that surface with `position:absolute`, zero left/right/bottom offsets, `top:80px`, `rgba(0, 0, 0, 0.24)`, and `backdrop-filter: blur(2px)`. Welcome and conditional credential setup render as successive pages in this stage instead of independent modals. Both pages reuse the Web UI's black `BrandWordmark`. The welcome page preserves the four authored paragraphs verbatim under the `内测声明` title; every paragraph uses one 16/28 body scale, and only the requested action clause inside the final paragraph receives a subtle 500 weight. A short staggered opacity/vertical entrance supplies pacing without blocking interaction and disappears under reduced motion. The title receives initial focus, Continue is the sole button, and no close, Escape, or mask-click path exists. +**Visible onboarding uses one shared modal contract.** Both current steps render through the same body-portaled `OnboardingModal`, and the underlying app root stays inert only while a dialog is visible. The shell renders no wrapper while a step loads its private facts. Explicit actions transfer coordinator ownership; Escape and mask clicks do not acknowledge or skip a step. ## Alternatives considered @@ -32,4 +30,4 @@ The GUI's credential onboarding begins with a DeepSeek-specific readiness check, ## Consequences -A fresh profile always sees the welcome notice before provider-specific onboarding; an already configured credential skips only the later DeepSeek step. On loopback, reloading after Continue stays past the acknowledged version, changing the owner version presents it again, and closing before Continue leaves the next launch unchanged. On non-loopback, Continue advances the live process without a privileged settings request and reload presents the notice again. Focused store and React tests pin both persistence modes, exact-version comparison, write failure, sole-action behavior, no-dismiss paths, coordinator ordering, conditional DeepSeek transfer, and HMR cleanup. The real Chromium scenario boots the shipped Web composition with an isolated harness home, verifies the exact mask geometry and computed styles, reloads before and after acknowledgement, continues into missing-credential setup, confirms an acknowledged-version mismatch returns while the credential is configured, and checks the browser console. +A fresh profile sees the current testing-stage notice, then the conditional DeepSeek key dialog when no provider is usable. Focused store and React tests pin exact-version acknowledgement, coordinator ordering, conditional transfer, shared modal behavior, and HMR cleanup. The real Chromium scenario boots the shipped Web composition with an isolated harness home, verifies both dialogs, writes the key through the existing credential boundary, and checks that no secret reaches the DOM, ARIA, or browser console. diff --git a/.agents/notes/implemented/feature/2026-07-30-versioned-gui-welcome-onboarding.zh.md b/.agents/notes/implemented/feature/2026-07-30-versioned-gui-welcome-onboarding.zh.md index 9f5eb99033..52c35bf46e 100644 --- a/.agents/notes/implemented/feature/2026-07-30-versioned-gui-welcome-onboarding.zh.md +++ b/.agents/notes/implemented/feature/2026-07-30-versioned-gui-welcome-onboarding.zh.md @@ -10,15 +10,13 @@ GUI 的凭据引导从 DeepSeek 专用的就绪状态检查开始,但内部测 ## 决策 -**设置外壳协调有序步骤。** `settings.onboarding` 仍是根作用域 list,但 `ui-settings` 会把其中各条目的 id 和顺序投影到一个协调器中,并且只挂载第一个未完成的步骤。当前注册方会收到 `complete()` 和 `openSection(id)`;所有权转移前,不会挂载后续步骤。产品欢迎步骤的顺序为 `-100`,`ui-settings-models` 则只保留顺序为 `0` 的 DeepSeek 条件式就绪状态与凭据跳转步骤。 +**设置外壳协调有序步骤。** `settings.onboarding` 仍是根作用域 list,但 `ui-settings` 会把其中各条目的 id 和顺序投影到一个协调器中,并且只挂载第一个未完成的步骤。当前注册方会收到 `complete()` 和 `openSection(id)`;所有权转移前,不会挂载后续步骤。`ui-settings-models` 现在以顺序 `-100` 注册恢复后的欢迎声明,以顺序 `0` 注册 DeepSeek 条件式凭据步骤;两者当前的共用展示由[共用弹窗引导决策](2026-08-13-shared-modal-product-onboarding.md)持有。 -**不属于单一功能的产品引导由 `ui-settings-general` 持有。** `src/onboarding-copy.ts` 是完整通知、「继续」按钮文案和 `WELCOME_NOTICE_VERSION` 的唯一可编辑来源;GUI 支持的两种 locale 都有意渲染同一份中文所有者文案。运行时 locale 字典从该文件派生欢迎文案,测试也导入同一个所有者,而不重复段落文本。该通知只存在于浏览器 UI:它不会创建会话事件,也不会贡献任何模型可见内容。通知说明会话遥测[默认禁用](2026-08-10-telemetry-default-off.md),并列出 `FEEDBACK_ONLY` 和 `FULL` 两种显式启用模式。 +**产品欢迎步骤按版本管理并归功能插件所有。** 该声明曾由[移除首次启动内测声明](../simplification/2026-08-13-remove-first-run-beta-notice.md)历史决策移除,现在以新的测试阶段文案恢复在 `ui-settings-models` 中。`ui-settings-general` 仍不注册任何引导步骤;持有当前两个步骤的插件也持有文案、store 和共用弹窗。 -**loopback 确认状态按 Harness profile 持久化。** 宿主端在 user-settings seam 中注册 `ui-onboarding` 分节,并存入当前 `$DSH_HOME/settings.yaml`。connection 插件通过 `ctx.connection.isLoopback` 统一发布当前页面是否使用 loopback authority;hostname 判定留在 connection 包内,其他客户端插件只消费服务状态,而不导入其实现。除非 `welcomeNoticeVersion` 与文案所有者文件中的常量精确相等,否则 loopback 浏览器会显示通知。「继续」会以当前版本执行一次路径变更,并且仅在宿主端提交成功后调用 `complete()`;写入失败时通知保持打开,关闭页面或进程则不会写入任何内容。更新该常量会有意要求每个 profile 对修订后的文案重新确认一次。非 loopback 浏览器不能调用仅限 loopback 的 settings API;它仍显示同一通知,但显式点击「继续」只会在当前浏览器进程中完成该步骤,重新加载或新进程会再次显示通知。 +**持久化的 `ui-onboarding` 分节持有确认状态。** 宿主端在 user-settings seam 中注册它,存入当前 `$DSH_HOME/settings.yaml`;当前欢迎 store 通过既有公开 settings API 读写其中的 `welcomeNoticeVersion`。connection 插件通过 `ctx.connection.isLoopback` 统一发布当前页面是否使用 loopback authority;hostname 判定留在 connection 包内,其他客户端插件只消费服务状态,而不导入其实现。API Proxy 在可配置提供方 namespace 之外,通过封闭的允许列表暴露这一个产品 namespace,同时不会把它的变更视为模型目录失效事件。 -**并发 loopback 视图无需陈旧的整体替换即可收敛。** 确认写入有意省略 `expectedRevision`:每个 loopback 标签页都向同一路径写入相同版本,因此该操作是幂等的,并会保留同级字段,而不是重建整个分节。`settings/document-updated` 以失效通知形式到达客户端——当时经 `host/settings-changed`,现在则是原样转发([转发的 Remote 事件](../architecture/2026-08-10-remote-event-delivery.md));另一个标签页或外部编辑器提交当前版本后,已挂载的 loopback 标签页会重新拉取状态并推进。API Proxy(`@deepseek-ai/dsh-host-apiproxy`)在可配置提供方 namespace 之外,通过封闭的允许列表暴露这一个产品 namespace,同时不会把它的变更视为模型目录失效事件。 - -**引导流程会暂时接管视口,形成一个连续阶段。** 纯色产品界面通过挂载到 `body` 的 portal 取代完整的应用视图,并将底层应用根节点标记为 inert;严格符合要求的遮罩仍挂载在该界面后方,并保留 `position:absolute`、left/right/bottom 偏移量为零、`top:80px`、`rgba(0, 0, 0, 0.24)` 和 `backdrop-filter: blur(2px)`。欢迎页和按条件显示的凭据设置页在这一阶段中依次呈现,而不是各自作为独立的模态窗口。两个页面都复用 Web UI 的黑色 `BrandWordmark`。欢迎页在 `内测声明` 标题下逐字保留既定的四段文案;所有段落统一采用 16/28 的正文字号与行高,只有最后一段中指定的行动语句使用较为克制的 500 字重。短暂的错落式透明度与纵向位移动画营造出节奏感,但不会阻碍交互,并会在用户启用减少动态效果时禁用。初始焦点落在标题上,「继续」是唯一按钮,且不存在关闭、Escape 或点击遮罩的退出路径。 +**可见引导使用同一个弹窗契约。** 当前两个步骤都通过 body portal 的同一个 `OnboardingModal` 渲染,且只在弹窗可见期间把下层应用根节点设为 inert。步骤加载私有事实时,外壳不渲染任何包装。明确操作会移交协调器所有权;Escape 和点击遮罩都不会确认或跳过步骤。 ## 曾考虑的替代方案 @@ -32,4 +30,4 @@ GUI 的凭据引导从 DeepSeek 专用的就绪状态检查开始,但内部测 ## 后果 -全新 profile 始终会在提供方专用引导之前看到欢迎通知;凭据已经配置时,只会跳过后续 DeepSeek 步骤。在 loopback 上,点击「继续」后重新加载不会再次显示已确认版本,更改文案所有者文件中的版本值会让通知重新出现,而确认前关闭窗口不会改变下次启动。在非 loopback 上,「继续」会在不发起受保护 settings 请求的情况下推进当前进程,重新加载则再次显示通知。针对性的 store 与 React 测试固化了两种持久化模式、精确版本比较、写入失败、单一操作、不可关闭路径、协调器顺序、按条件移交 DeepSeek 步骤和 HMR(热模块替换)清理行为。真实 Chromium 场景会使用隔离的 harness 家目录启动随产品提供的 Web 组合,验证遮罩的精确几何尺寸和计算样式,在确认前后分别重新加载,继续进入凭据缺失设置流程,确认凭据已配置时确认版本不匹配仍会使通知重新出现,并检查浏览器控制台。 +全新 profile 会先看到当前测试阶段声明;当没有任何可用提供方时,再看到条件式 DeepSeek 密钥弹窗。定向 store 与 React 测试固定精确版本确认、协调器顺序、条件式移交、共用弹窗行为与 HMR 清理。真实 Chromium 场景会在隔离的 harness 家目录下启动已发布 Web 组合,验证两个弹窗,通过既有凭据边界写入密钥,并检查 secret 未进入 DOM、ARIA 或浏览器控制台。 diff --git a/.agents/notes/implemented/feature/2026-08-02-session-search-not-shipped-default.i18n.yaml b/.agents/notes/implemented/feature/2026-08-02-session-search-not-shipped-default.i18n.yaml index 1a4d923540..b9a8b2e9c8 100644 --- a/.agents/notes/implemented/feature/2026-08-02-session-search-not-shipped-default.i18n.yaml +++ b/.agents/notes/implemented/feature/2026-08-02-session-search-not-shipped-default.i18n.yaml @@ -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 .agents/notes/implemented/feature/2026-08-02-session-search-not-shipped-default.md -2026-08-02-session-search-not-shipped-default.md: c1bfd7f8e354a4480c5635619514fe782ea71d2c -2026-08-02-session-search-not-shipped-default.zh.md: 9b80c549425c26055700480dd57f1a0a7d01e4a8 +2026-08-02-session-search-not-shipped-default.md: 60d1f424d5a9029a00b3f195d1f6e6baf2790d1e +2026-08-02-session-search-not-shipped-default.zh.md: 221613ae1aef93cd72734e4c328d822a88b64227 diff --git a/.agents/notes/implemented/feature/2026-08-02-session-search-not-shipped-default.md b/.agents/notes/implemented/feature/2026-08-02-session-search-not-shipped-default.md index c1bfd7f8e3..60d1f424d5 100644 --- a/.agents/notes/implemented/feature/2026-08-02-session-search-not-shipped-default.md +++ b/.agents/notes/implemented/feature/2026-08-02-session-search-not-shipped-default.md @@ -12,7 +12,7 @@ The [shipped-roster decision](2026-07-31-even-out-shipped-tool-rosters.md) made The shipped TUI, Web, and headless surfaces do not mount `@deepseek-ai/dsh-tool-session-query`, and no shipped agent preset carries it. The consumer stays opt-in exactly as the model-facing-session-query-tools note describes: the ACP example's [`session-query.cordis.yml`](../../../../examples/acp-agent/session-query.cordis.yml) and its snapshot counterpart remain the mounted reference, and a custom composition can mount the package with the timeout and spill policies. -The `ctx.sessionQuery` service itself stays mounted. `session-query-sqlite` remains a base row — the TUI's `session-reference` consumes it for `/resume` — and the Web overlay keeps patching it to an in-memory index for the browser content search. Only the model-facing consumer is removed. +The `ctx.sessionQuery` service itself stays mounted. `session-query-sqlite` remains a base row — the TUI's `session-reference` consumes it for `/resume` — with its full-text index off by default (`openAt: never`; the [content-search opt-in decision](../architecture/2026-08-13-session-content-search-opt-in.md)), and the Web overlay keeps its in-memory values for deployments that enable content search. Only the model-facing consumer is removed. ## Alternatives considered diff --git a/.agents/notes/implemented/feature/2026-08-02-session-search-not-shipped-default.zh.md b/.agents/notes/implemented/feature/2026-08-02-session-search-not-shipped-default.zh.md index 9b80c54942..221613ae1a 100644 --- a/.agents/notes/implemented/feature/2026-08-02-session-search-not-shipped-default.zh.md +++ b/.agents/notes/implemented/feature/2026-08-02-session-search-not-shipped-default.zh.md @@ -12,7 +12,7 @@ Status: implemented 交付的 TUI、Web 与无头 surface 均不挂载 `@deepseek-ai/dsh-tool-session-query`,交付的 agent preset 也都不包含它。该消费方仍保持 opt-in,与面向模型的会话查询工具决策所述完全一致:ACP(Agent Client Protocol)示例的 [`session-query.cordis.yml`](../../../../examples/acp-agent/session-query.cordis.yml) 及其快照对侧文件仍是挂载参考,自定义组合也可以连同超时与 spill 策略一起挂载该包。 -`ctx.sessionQuery` 服务本身保持挂载。`session-query-sqlite` 仍是 base 的一行,TUI 的 `session-reference` 消费它来实现 `/resume`,Web overlay 也继续把它 patch 成内存索引,供浏览器内容搜索使用。被移除的只有面向模型的消费方。 +`ctx.sessionQuery` 服务本身保持挂载。`session-query-sqlite` 仍是 base 的一行,TUI 的 `session-reference` 消费它来实现 `/resume`;其全文索引默认关闭(`openAt: never`,见[内容搜索 opt-in 决策](../architecture/2026-08-13-session-content-search-opt-in.md)),Web overlay 保留内存索引取值,供启用内容搜索的部署使用。被移除的只有面向模型的消费方。 ## 曾考虑的替代方案 diff --git a/.agents/notes/implemented/feature/2026-08-04-claude-code-and-codex-subagent-backends.i18n.yaml b/.agents/notes/implemented/feature/2026-08-04-claude-code-and-codex-subagent-backends.i18n.yaml index c390d514a3..48773ba819 100644 --- a/.agents/notes/implemented/feature/2026-08-04-claude-code-and-codex-subagent-backends.i18n.yaml +++ b/.agents/notes/implemented/feature/2026-08-04-claude-code-and-codex-subagent-backends.i18n.yaml @@ -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 .agents/notes/implemented/feature/2026-08-04-claude-code-and-codex-subagent-backends.md -2026-08-04-claude-code-and-codex-subagent-backends.md: ccc96d6c998c4ab958a7eea1e502d036d16ec90d -2026-08-04-claude-code-and-codex-subagent-backends.zh.md: 5facbe79e7afccd9eccddac046cd97a60b50d25a +2026-08-04-claude-code-and-codex-subagent-backends.md: 666945c4d8039874729a7f9da34d9cf82bfd479d +2026-08-04-claude-code-and-codex-subagent-backends.zh.md: 35b8dd51f1c45200a495c68f19f055a224123263 diff --git a/.agents/notes/implemented/feature/2026-08-04-claude-code-and-codex-subagent-backends.md b/.agents/notes/implemented/feature/2026-08-04-claude-code-and-codex-subagent-backends.md index ccc96d6c99..666945c4d8 100644 --- a/.agents/notes/implemented/feature/2026-08-04-claude-code-and-codex-subagent-backends.md +++ b/.agents/notes/implemented/feature/2026-08-04-claude-code-and-codex-subagent-backends.md @@ -12,24 +12,25 @@ The product integrations must not become second owners for task text, cwd, cance ## Decision -The harness publishes two sibling one-shot provider packages: `codex` and `claude-code`. This note owns their product protocols, result mapping, and process lifecycle; the [shared-profile-host placement decision](../architecture/2026-08-10-product-subagent-providers-in-shared-host.md) supersedes the original opt-in composition placement. Loading either provider starts no product process, and each tool accepts only a standalone text task; product selection and background execution are not model arguments. +The harness publishes two sibling one-shot provider packages: `codex` and `claude-code`. This note owns their product protocols, result mapping, and process lifecycle; the [production-install exclusion decision](../simplification/2026-08-12-production-dsh-excludes-product-subagent-providers.md) owns their explicit Profile installation and host-plane placement, and the [product one-shot background decision](2026-08-12-product-subagent-one-shot-background-tasks.md) owns the model-visible scheduling choice. Loading either provider starts no product process, and each tool accepts only a standalone text task; product selection remains deployment configuration. -Both providers report `inheritsParentContext: false`, advertise no optional start capabilities, and pass the parent Session cwd without copying the parent conversation. Their documented tools disable background execution and use `maxDepth: 'provider-managed'`, leaving recursion policy with the out-of-process product instead of sending a limit the provider cannot enforce. Every call creates a fresh product process and a non-resumable product conversation. The shared subagent service continues to own request resolution, lifecycle events, result settlement, and foreground collection; the shared subprocess service owns credential scrubbing, process-tree termination, and whole-tree exit observation. +Both providers report `inheritsParentContext: false`, advertise no optional start capabilities, and pass the parent Session cwd without copying the parent conversation. Their documented tools use `backgroundMode: 'one-shot'` and `maxDepth: 'provider-managed'`: the consumer keeps foreground collection as the default and may place the same run in the generic Job runtime, while recursion policy stays with the out-of-process product. Every call creates a fresh product process and a non-resumable product conversation. `ctx.subagents` owns named-request resolution and paired lifecycle events; `dsh-tool-subagent` owns model-visible scheduling and foreground-versus-Job adaptation; `ctx.jobs` and `dsh-tool-jobs` own Job ids, state, output, controls, notices, and parent-owner cancellation; each product provider owns native result mapping, while `dsh-subprocess` owns credential scrubbing, process-tree termination, and whole-tree exit observation. ```text -fixed tool → shared subagent service → product provider → official product process - ← final answer / explicit error / cancellation ← terminal product fact - → foreground disposal → shared process-tree termination → whole-tree exit +fixed tool -> dsh-tool-subagent -> ctx.subagents -> product provider -> product process + foreground <- final product outcome + background -> ctx.jobs / dsh-tool-jobs -> Job id / state / notice / controls + both -> provider disposal -> dsh-subprocess -> whole-tree exit ``` ### Ownership and lifecycle -| Phase | Shared owner | Product-specific responsibility | Observable result | +| Layer | Owner | Responsibility | Observable result | | --- | --- | --- | --- | -| Resolve | `dsh-tool-subagent` and `ctx.subagents` | Validate the product's text-only input and derive native startup parameters | Unsupported context or malformed input fails before a run is published | -| Start | `dsh-subprocess` owns every acquired process tree | Reach the smallest native point at which the product conversation and process can both be controlled | `start()` publishes one existing `SubagentRun`, or cleans up and rejects | -| Run | The product owns its native protocol facts; the holder owns their mapping | Submit exactly one task and derive an existing shared stop reason; Codex uses `max-tokens` only for explicit context exhaustion | The parent receives only a final answer or an explicit failure | -| Dispose | The foreground consumer requests release; `dsh-subprocess` proves exit | Close the native protocol and express any best-effort native cancellation | Disposal is idempotent and returns only after the whole process tree exits | +| Delegation lifecycle | `ctx.subagents` | Resolve the named provider request and pair lifecycle events around the published `SubagentRun` | Unsupported context or malformed input fails before a run is published; start and terminal events remain paired | +| Scheduling and adaptation | `dsh-tool-subagent` | Interpret `run_in_background`, choose foreground collection or one-shot Job registration, and map the shared stop reason | Foreground returns the product outcome; background returns a Job id after registration | +| Job state and control | `ctx.jobs` and `dsh-tool-jobs` | Own Job state, output, cancellation, owner cleanup, completion notices, and model-facing controls | The exact parent can collect, list, or stop background work and receives its completion notice | +| Native run and teardown | Product provider and `dsh-subprocess` | Produce one native result, close the product protocol, request best-effort native cancellation, and prove process-tree exit | Foreground return and Job settlement both wait for idempotent disposal and whole-tree exit | ## Codex provider @@ -59,7 +60,7 @@ The credentialed Claude Code e2e uses the official DeepSeek Claude Code contract ## Distribution and evidence -Each product owns branch-complete package tests, a required keyless real-product spec, a Loader composition e2e, and a credentialed DeepSeek e2e. The keyless product tier uses the exact official distribution under test, a non-empty fake product key, an isolated temporary workspace and product home, and a loopback fixed-answer model. Missing product requests, wrong authentication, altered task text, a non-exact answer, a skipped real product, or a surviving managed handle fails the required test. The Loader tier boots the README-shaped user configuration, verifies both fixed foreground-only tools in one context, and starts neither product process. The credentialed tier starts the same production provider and real product with a runtime-only key, requires a unique nonce from the fixed official DeepSeek service, and proves quiescence again; it self-skips only when a local operator supplied no key, while trusted CI preflights the secret. +Each product owns branch-complete package tests, a required keyless real-product spec, a Loader composition e2e, and a credentialed DeepSeek e2e. The keyless product tier uses the exact official distribution under test, a non-empty fake product key, an isolated temporary workspace and product home, and a loopback fixed-answer model. Missing product requests, wrong authentication, altered task text, a non-exact answer, a skipped real product, or a surviving managed handle fails the required test. The Loader tier boots the README-shaped explicit Profile configuration, verifies both fixed one-shot tools expose optional background scheduling alongside generic Job controls, and starts neither product process. The credentialed tier starts the same production provider and real product with a runtime-only key, requires a unique nonce from the fixed official DeepSeek service, and proves quiescence again; it self-skips only when a local operator supplied no key, while trusted CI preflights the secret. The Codex evidence pins `@openai/codex@0.147.0` and `codex-cli 0.147.0`. Its real-product spec observes the exact Bearer key, original task, byte-exact final answer, unattended command rejection with no file side effect, local cancellation, and whole-tree exit. Production still supplies `codex` on `PATH`. @@ -83,12 +84,12 @@ The project owner's distribution authorization is scoped to the official `@anthr **Plugin-managed login, product home, models, settings, or permissions.** Those choices would create another authority beside each product's native configuration and enlarge a one-shot provider into account management. The providers expose only an explicit environment overlay and teardown grace; unattended interaction fails closed. -**Continuation, progress, background collection, and shared parent context.** The delivered user result is one self-contained task and one final answer. Product sessions, resume, follow-up, intermediate messages, parent transcript transfer, structured output, and background collection need separate user contracts and are not prebuilt. +**Continuation, progress, product-native background state, and shared parent context.** The provider payload remains one final answer for one self-contained task. The generic Job layer may add its id, status, notice, collection, and cancellation results, but product sessions, resume, follow-up, intermediate messages, parent transcript transfer, structured output, and provider-specific background state need separate user contracts and are not prebuilt. ## Consequences -Users delegate through two stable foreground tools backed by the official product integrations. Their Profile placement and per-Preset exposure are owned by the [shared-host placement decision](../architecture/2026-08-10-product-subagent-providers-in-shared-host.md); this note's provider lifecycle keeps native settings and behavior while shared services retain the sole ownership of task settlement and process-tree quiescence. +Users delegate through two stable one-shot tools backed by the official product integrations. Explicit Profile installation and host-plane provider placement are owned by the [production-install exclusion decision](../simplification/2026-08-12-production-dsh-excludes-product-subagent-providers.md); per-Preset tool exposure and foreground-default optional Job scheduling are owned by the [product one-shot background decision](2026-08-12-product-subagent-one-shot-background-tasks.md). This note's provider lifecycle keeps native settings and behavior while shared services retain the sole ownership of job settlement and process-tree quiescence. -Every delegation pays for a fresh product process and independent model context, and only final text reaches the parent. Product-native configuration makes behavior depend on the deployment's installed product, account state, and workspace settings. Credentialed e2e runs also spend external API quota and depend on the official DeepSeek endpoint; deterministic protocol, failure, cancellation, and approval coverage remains in the keyless tier. The providers do not resume sessions, stream progress, accept new human interaction, roll back tool or file side effects, or impose a wall-clock timeout. +Every delegation pays for a fresh product process and independent model context. The product payload reaching the parent is final text only; background scheduling additionally exposes generic Job ids, status, completion notices, and collection or cancellation results. Product-native configuration makes behavior depend on the deployment's installed product, account state, and workspace settings. Credentialed e2e runs also spend external API quota and depend on the official DeepSeek endpoint; deterministic protocol, failure, cancellation, and approval coverage remains in the keyless tier. The providers do not resume sessions, stream progress, accept new human interaction, roll back tool or file side effects, or impose a wall-clock timeout. Compatibility is pinned by package-level unit coverage, keyless real-product loopback tests, credentialed DeepSeek nonce tests, public Loader composition, built-package and NodeNext consumer checks, generated documentation and notices, and the repository CI matrix. A supported product or DeepSeek endpoint/model baseline change must refresh those facts; production performs no separate runtime version probe. diff --git a/.agents/notes/implemented/feature/2026-08-04-claude-code-and-codex-subagent-backends.zh.md b/.agents/notes/implemented/feature/2026-08-04-claude-code-and-codex-subagent-backends.zh.md index 5facbe79e7..35b8dd51f1 100644 --- a/.agents/notes/implemented/feature/2026-08-04-claude-code-and-codex-subagent-backends.zh.md +++ b/.agents/notes/implemented/feature/2026-08-04-claude-code-and-codex-subagent-backends.zh.md @@ -12,24 +12,25 @@ Status: implemented ## 决策 -harness 交付两个同级的一次性提供方包:`codex` 与 `claude-code`。本说明负责它们的产品协议、结果映射和进程生命周期;[共享 profile 宿主归属决策](../architecture/2026-08-10-product-subagent-providers-in-shared-host.md)取代原先由用户选择启用的组装位置。加载任一提供方都不会启动产品进程,而且每个工具只接受独立文本任务;产品选择与后台执行都不作为模型参数。 +harness 交付两个同级的一次性提供方包:`codex` 与 `claude-code`。本说明负责它们的产品协议、结果映射和进程生命周期;[生产安装排除决策](../simplification/2026-08-12-production-dsh-excludes-product-subagent-providers.md)负责显式 Profile 安装与 host plane(宿主平面)放置,[产品一次性后台任务决策](2026-08-12-product-subagent-one-shot-background-tasks.md)负责模型可见的调度选择。加载任一提供方都不会启动产品进程,而且每个工具只接受独立文本任务;产品选择仍属于部署配置。 -这两个提供方都报告 `inheritsParentContext: false`,不声明任何可选的启动能力,并传递父会话 cwd,但不会复制父级对话。文档所示的工具会禁用后台执行,并使用 `maxDepth: 'provider-managed'`,将递归策略留给进程外产品,而不是发送提供方无法强制执行的限制。每次调用都会创建一个全新的产品进程和一次不可续接的产品对话。共享 subagent 服务继续负责请求解析、生命周期事件、结果结算和前台收集;共享子进程服务负责凭证清洗、进程树终止以及整棵进程树的退出观测。 +这两个提供方都报告 `inheritsParentContext: false`,不声明任何可选的启动能力,并传递父会话 cwd,但不会复制父级对话。文档所示的工具使用 `backgroundMode: 'one-shot'` 与 `maxDepth: 'provider-managed'`:消费方默认在前台收集结果,也可把同一次运行放入通用 Job 运行时,而递归策略仍由进程外产品负责。每次调用都会创建一个全新的产品进程和一次不可续接的产品对话。`ctx.subagents` 负责具名请求解析与成对生命周期事件;`dsh-tool-subagent` 负责模型可见的调度以及前台与 Job 适配;`ctx.jobs` 和 `dsh-tool-jobs` 负责 Job id、状态、输出、控制、通知与父级 owner 取消;各产品提供方负责原生结果映射,`dsh-subprocess` 则负责凭证清洗、进程树终止以及整棵进程树的退出观测。 ```text -fixed tool → shared subagent service → product provider → official product process - ← final answer / explicit error / cancellation ← terminal product fact - → foreground disposal → shared process-tree termination → whole-tree exit +fixed tool -> dsh-tool-subagent -> ctx.subagents -> product provider -> product process + foreground <- final product outcome + background -> ctx.jobs / dsh-tool-jobs -> Job id / state / notice / controls + both -> provider disposal -> dsh-subprocess -> whole-tree exit ``` ### 归属与生命周期 -| 阶段 | 共享责任方 | 产品特定职责 | 可观察结果 | +| 层级 | 责任方 | 职责 | 可观察结果 | | --- | --- | --- | --- | -| 解析 | `dsh-tool-subagent` 与 `ctx.subagents` | 验证产品的纯文本输入并推导原生启动参数 | 不受支持的上下文或格式错误的输入会在发布运行前报错 | -| 启动 | `dsh-subprocess` 负责每棵已获取的进程树 | 到达能够同时控制产品对话与进程的最小原生控制点 | `start()` 发布一个已存在的 `SubagentRun`,否则清理后拒绝调用 | -| 运行 | 产品负责其原生协议事实;持有方负责映射这些事实 | 只提交一项任务,并推导出一种现有的共享停止原因;Codex 仅在明确发生上下文耗尽时使用 `max-tokens` | 父级只会收到最终回答或明确失败 | -| dispose(资源释放) | 前台消费方请求释放;`dsh-subprocess` 证明进程已退出 | 关闭原生协议,并发出尽力而为的原生取消请求 | 释放操作具有幂等性,且仅在整棵进程树退出后才返回 | +| 委派生命周期 | `ctx.subagents` | 解析具名提供方请求,并为已发布的 `SubagentRun` 配对生命周期事件 | 不受支持的上下文或格式错误的输入会在发布运行前报错;启动与终态事件保持成对 | +| 调度与适配 | `dsh-tool-subagent` | 解释 `run_in_background`,选择前台收集或 one-shot Job 登记,并映射共享停止原因 | 前台返回产品结果;后台在登记完成后返回 Job id | +| Job 状态与控制 | `ctx.jobs` 与 `dsh-tool-jobs` | 负责 Job 状态、输出、取消、owner 清理、完成通知与面向模型的控制工具 | 准确父级可以收集、列出或停止后台工作,并收到完成通知 | +| 原生运行与清理 | 产品提供方与 `dsh-subprocess` | 产生一个原生结果、关闭产品协议、请求尽力而为的原生取消,并证明进程树退出 | 前台返回与 Job 结算都会等待幂等资源释放和整棵进程树退出 | ## Codex 提供方 @@ -59,7 +60,7 @@ Codex 0.147.0 使用 Responses 协议,而 DeepSeek 的公开 OpenAI 兼容端 ## 分发与证据 -每个产品都负责覆盖所有分支的包测试、一项必跑的无密钥真实产品测试、一项 Loader 组合 e2e 和一项带密钥 DeepSeek e2e。无密钥产品层级使用被测的确切官方发行版、非空的伪产品密钥、隔离的临时工作区与产品主目录,以及能返回固定答案的回环模型。产品请求缺失、身份验证错误、任务文本被改动、答案不完全一致、真实产品被跳过或受管句柄仍存活,都会使这项必跑测试失败。Loader 层级会启动 README 所示形态的用户配置,在同一个上下文中验证两个固定且只支持前台执行的工具,并且不会启动任何产品进程。带密钥层级会使用仅在运行时提供的密钥启动同一生产提供方与真实产品,要求从固定的 DeepSeek 官方服务取得唯一随机数,并再次证明完全停稳;仅当本地操作者未提供密钥时才会自行跳过,而受信任的 CI 会预检该 secret。 +每个产品都负责覆盖所有分支的包测试、一项必跑的无密钥真实产品测试、一项 Loader 组合 e2e 和一项带密钥 DeepSeek e2e。无密钥产品层级使用被测的确切官方发行版、非空的伪产品密钥、隔离的临时工作区与产品主目录,以及能返回固定答案的回环模型。产品请求缺失、身份验证错误、任务文本被改动、答案不完全一致、真实产品被跳过或受管句柄仍存活,都会使这项必跑测试失败。Loader 层级会启动 README 所示的显式 Profile 配置,在同一个上下文中验证两个固定一次性工具会与通用 Job 控制工具一起公开可选后台调度,而且不会启动任何产品进程。带密钥层级会使用仅在运行时提供的密钥启动同一生产提供方与真实产品,要求从固定的 DeepSeek 官方服务取得唯一随机数,并再次证明完全停稳;仅当本地操作者未提供密钥时才会自行跳过,而受信任的 CI 会预检该 secret。 Codex 证据锁定 `@openai/codex@0.147.0` 与 `codex-cli 0.147.0`。其真实产品测试会观测确切的 Bearer 密钥、原始任务、逐字节完全一致的最终回答、不会产生文件副作用的无人值守命令拒绝、本地取消以及整棵进程树退出。生产环境仍提供 `codex`,并通过 `PATH` 解析。 @@ -83,12 +84,12 @@ Claude Code 证据锁定 Agent SDK 0.3.220,并使用 SDK 按平台分发的 Cl **由插件管理登录、产品主目录、模型、设置或权限。** 这些选择会在每个产品的原生配置之外建立另一套权威来源,并将一次性提供方扩张为账户管理功能。提供方只公开显式环境覆盖项和清理宽限期;无人值守交互会以默认拒绝方式失败。 -**续接、进度、后台收集和共享父级上下文。** 已交付的用户结果是一项自包含任务和一个最终回答。产品会话、恢复、后续交互、中间消息、父级 transcript(文本记录)传递、结构化输出和后台收集都需要独立的用户约定,当前实现不会预先构建这些功能。 +**续接、进度、产品原生后台状态和共享父级上下文。** 提供方载荷仍是一项自包含任务的一个最终回答。通用 Job 层可以额外提供 id、状态、通知、收集与取消结果,但产品会话、恢复、后续交互、中间消息、父级 transcript(文本记录)传递、结构化输出和提供方专属后台状态都需要独立的用户约定,当前实现不会预先构建这些功能。 ## 后果 -用户通过官方产品集成支持的两个稳定前台工具进行委派。它们在 Profile 中的归属和按 Preset 暴露方式由[共享宿主归属决策](../architecture/2026-08-10-product-subagent-providers-in-shared-host.md)负责;本说明规定的提供方生命周期会保留原生设置与行为,而共享服务继续独占任务结算与进程树完全停稳的责任。 +用户通过官方产品集成支持的两个稳定一次性工具进行委派。显式 Profile 安装与 host plane 提供方放置由[生产安装排除决策](../simplification/2026-08-12-production-dsh-excludes-product-subagent-providers.md)负责;按 Preset 暴露工具以及默认前台且可选通用 Job 的调度方式由[产品一次性后台任务决策](2026-08-12-product-subagent-one-shot-background-tasks.md)负责。本说明规定的提供方生命周期会保留原生设置与行为,而共享服务继续独占作业结算与进程树完全停稳的责任。 -每次委派都要承担新建产品进程和独立模型上下文的开销,且只有最终文本会到达父级。产品原生配置使行为取决于部署环境中安装的产品、账户状态和工作区设置。带密钥 e2e 运行还会消耗外部 API 配额,并依赖 DeepSeek 官方端点;对协议、失败、取消与审批的确定性覆盖仍由无密钥层级承担。提供方不会恢复会话、以流式方式传送进度、接受新的人工交互、回滚工具或文件副作用,也不会施加按实际经过时间触发的超时。 +每次委派都要承担新建产品进程和独立模型上下文的开销。到达父级的产品载荷仍只有最终文本;后台调度还会额外公开通用 Job id、状态、完成通知以及收集或取消结果。产品原生配置使行为取决于部署环境中安装的产品、账户状态和工作区设置。带密钥 e2e 运行还会消耗外部 API 配额,并依赖 DeepSeek 官方端点;对协议、失败、取消与审批的确定性覆盖仍由无密钥层级承担。提供方不会恢复会话、以流式方式传送进度、接受新的人工交互、回滚工具或文件副作用,也不会施加按实际经过时间触发的超时。 兼容性由包级单元测试覆盖率、无密钥真实产品回环测试、带密钥 DeepSeek 随机数测试、公开 Loader 组合、已构建包与 NodeNext 消费方检查、生成的文档与声明以及仓库 CI 矩阵共同锁定。更改受支持的产品基线或 DeepSeek 端点/模型基线时必须刷新这些事实;生产环境不会另行执行运行时版本探测。 diff --git a/.agents/notes/implemented/feature/2026-08-10-telemetry-default-off.i18n.yaml b/.agents/notes/implemented/feature/2026-08-10-telemetry-default-off.i18n.yaml index be70f91180..5a4552f5d0 100644 --- a/.agents/notes/implemented/feature/2026-08-10-telemetry-default-off.i18n.yaml +++ b/.agents/notes/implemented/feature/2026-08-10-telemetry-default-off.i18n.yaml @@ -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 .agents/notes/implemented/feature/2026-08-10-telemetry-default-off.md -2026-08-10-telemetry-default-off.md: a4f0099565bb240cf62774fab2d5ad5f7de90e95 -2026-08-10-telemetry-default-off.zh.md: 8e2544eb7dee8b9bd6b8a4c81a28a8a03d3404d4 +2026-08-10-telemetry-default-off.md: 3f56817c9c23ec55f2173b66fa915ab05646b2a7 +2026-08-10-telemetry-default-off.zh.md: aa7b640f292713aa4e598f5ea1194f806dd6ae0d diff --git a/.agents/notes/implemented/feature/2026-08-10-telemetry-default-off.md b/.agents/notes/implemented/feature/2026-08-10-telemetry-default-off.md index a4f0099565..3f56817c9c 100644 --- a/.agents/notes/implemented/feature/2026-08-10-telemetry-default-off.md +++ b/.agents/notes/implemented/feature/2026-08-10-telemetry-default-off.md @@ -14,7 +14,7 @@ Both feeds use `DSH_TELEMETRY_MODE` as their positive consent setting. Unset and The dsh-sdk launcher reads the same variable without parsing `cordis.yml` or booting Cordis. `FULL` permits reporting; `FEEDBACK_ONLY`, `DISABLED`, unset, and empty values deny it. Consent is frozen from the launching environment before the command runs, because `dsh-sdk start` loads a project `.env` and project code can mutate `process.env`: resolving afterwards would let a project grant reporting of its own configuration, which the [configuration source ownership decision](../architecture/2026-08-04-configuration-source-ownership.md) denies for the whole `DSH_*` namespace. An unsupported mode denies rather than throwing at that boundary, since telemetry may never change a command's result. This rule superseded the default-on launcher consent before the launcher and its proposal were deleted by the [SDK project toolchain removal](../simplification/2026-08-11-remove-sdk-project-toolchain.md). -The versioned Web welcome notice states that Session Log upload is off by default, names `DSH_TELEMETRY_MODE=FEEDBACK_ONLY` and `DSH_TELEMETRY_MODE=FULL` as the two opt-in choices, and discloses that `FULL` also enables dsh-sdk command telemetry. Its version changes with that material privacy statement so every profile acknowledges the current copy. +The [CLI reference README](../../../../apps/cli/reference/README.md) documents the deployment stance: Session Log upload is off by default, `DSH_TELEMETRY_MODE=FEEDBACK_ONLY` and `DSH_TELEMETRY_MODE=FULL` are the two opt-in choices, and explicitly enabled exports can contain complete session content. The restored [testing-stage onboarding notice](2026-08-13-shared-modal-product-onboarding.md) contains no telemetry copy, so the product still presents no prompt about enabling upload. ## Alternatives considered diff --git a/.agents/notes/implemented/feature/2026-08-10-telemetry-default-off.zh.md b/.agents/notes/implemented/feature/2026-08-10-telemetry-default-off.zh.md index 8e2544eb7d..aa7b640f29 100644 --- a/.agents/notes/implemented/feature/2026-08-10-telemetry-default-off.zh.md +++ b/.agents/notes/implemented/feature/2026-08-10-telemetry-default-off.zh.md @@ -14,7 +14,7 @@ DeepSeek Harness 有两路出站遥测数据流。在内测阶段,共享基础 dsh-sdk 启动器读取同一变量,不解析 `cordis.yml`,也不启动 Cordis。`FULL` 允许上报;`FEEDBACK_ONLY`、`DISABLED`、未设置和空值都会拒绝。授权在命令执行前从启动环境冻结:`dsh-sdk start` 会加载项目 `.env`,项目代码也能修改 `process.env`,若在执行后解析,项目便能自行授权上报其自身配置,而[配置来源所有权决策](../architecture/2026-08-04-configuration-source-ownership.md)对整个 `DSH_*` 命名空间禁止这种行为。在该边界上,不受支持的模式按拒绝处理而非抛出,因为遥测不得改变命令结果。此规则在启动器及其提案被[SDK 项目工具链移除决策](../simplification/2026-08-11-remove-sdk-project-toolchain.md)删除之前,仅取代了启动器默认允许上报的规则。 -带版本的 Web 欢迎通知说明会话日志上传默认关闭,将 `DSH_TELEMETRY_MODE=FEEDBACK_ONLY` 和 `DSH_TELEMETRY_MODE=FULL` 列为两种显式启用选项,并披露 `FULL` 同时会启用 dsh-sdk 命令遥测。其版本随这项重要的隐私声明一同变更,使每个 profile 都确认当前文案。 +[CLI reference README](../../../../apps/cli/reference/README.md) 记录了这一部署口径:会话日志上传默认关闭,`DSH_TELEMETRY_MODE=FEEDBACK_ONLY` 和 `DSH_TELEMETRY_MODE=FULL` 是两种显式启用选项,显式开启后的导出可能包含完整会话内容。恢复后的[测试阶段引导声明](2026-08-13-shared-modal-product-onboarding.md)不包含遥测文案,因此产品仍不提供任何关于开启上传的提示。 ## 考虑过的替代方案 diff --git a/.agents/notes/implemented/feature/2026-08-10-web-plugin-configuration.i18n.yaml b/.agents/notes/implemented/feature/2026-08-10-web-plugin-configuration.i18n.yaml index 8a9e7a0bda..6b4b469aba 100644 --- a/.agents/notes/implemented/feature/2026-08-10-web-plugin-configuration.i18n.yaml +++ b/.agents/notes/implemented/feature/2026-08-10-web-plugin-configuration.i18n.yaml @@ -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 .agents/notes/implemented/feature/2026-08-10-web-plugin-configuration.md -2026-08-10-web-plugin-configuration.md: bdb5a3cbddabb516a0921abc00f1be97be4d17d7 -2026-08-10-web-plugin-configuration.zh.md: ed8ced71ed50063f9b1702ff2a6601271712f910 +2026-08-10-web-plugin-configuration.md: 218d5ed4536c489f89cb53c62c457a988e451b7e +2026-08-10-web-plugin-configuration.zh.md: 999e785699741084e1e230c4a240a0605491cb04 diff --git a/.agents/notes/implemented/feature/2026-08-10-web-plugin-configuration.md b/.agents/notes/implemented/feature/2026-08-10-web-plugin-configuration.md index bdb5a3cbdd..218d5ed453 100644 --- a/.agents/notes/implemented/feature/2026-08-10-web-plugin-configuration.md +++ b/.agents/notes/implemented/feature/2026-08-10-web-plugin-configuration.md @@ -4,6 +4,8 @@ Status: implemented English | [中文](2026-08-10-web-plugin-configuration.zh.md) +> The three sections, the layering, and the staged-save form remain current. The Host allowlist and the unkeyed card list are superseded by the [plugin-owned settings surface](../architecture/2026-08-12-plugin-owned-settings-surface.md): every registered namespace is served, and cards are keyed on the namespace they edit. + ## Problem Everything a plugin can be configured with lived in `cordis.yml`. A user who wanted a longer shell timeout, a different search endpoint, or fewer parallel tool calls had to find the composition file, know its shape, and restart — while the Models page had shown for months that a settings namespace can be edited from the browser and take effect immediately. diff --git a/.agents/notes/implemented/feature/2026-08-10-web-plugin-configuration.zh.md b/.agents/notes/implemented/feature/2026-08-10-web-plugin-configuration.zh.md index ed8ced71ed..999e785699 100644 --- a/.agents/notes/implemented/feature/2026-08-10-web-plugin-configuration.zh.md +++ b/.agents/notes/implemented/feature/2026-08-10-web-plugin-configuration.zh.md @@ -4,6 +4,8 @@ Status: implemented [English](2026-08-10-web-plugin-configuration.md) | 中文 +> 三个分节、分层解析与暂存保存表单依然有效。Host 白名单与无键卡片列表已被[由插件自己拥有的设置表层](../architecture/2026-08-12-plugin-owned-settings-surface.md)取代:每一个已注册的命名空间都被服务,卡片以它所编辑的命名空间为键。 + ## 问题 插件的一切可配置项都只存在于 `cordis.yml`。想要更长的 shell 超时、不同的搜索端点或更少的并行工具调用,用户必须找到组装文件、了解它的形状,然后重启——而 Models 页几个月来一直在证明:settings 命名空间可以在浏览器里编辑并立即生效。 diff --git a/.agents/notes/implemented/feature/2026-08-11-collapsible-ask-user-question-card.i18n.yaml b/.agents/notes/implemented/feature/2026-08-11-collapsible-ask-user-question-card.i18n.yaml new file mode 100644 index 0000000000..e403530fec --- /dev/null +++ b/.agents/notes/implemented/feature/2026-08-11-collapsible-ask-user-question-card.i18n.yaml @@ -0,0 +1,6 @@ +# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each +# 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 .agents/notes/implemented/feature/2026-08-11-collapsible-ask-user-question-card.md +2026-08-11-collapsible-ask-user-question-card.md: 5c7e62749e63a6042285b79751c400ba09038b49 +2026-08-11-collapsible-ask-user-question-card.zh.md: 5f4b5851e4b595e634841bf87827db70fe928afb diff --git a/.agents/notes/implemented/feature/2026-08-11-collapsible-ask-user-question-card.md b/.agents/notes/implemented/feature/2026-08-11-collapsible-ask-user-question-card.md new file mode 100644 index 0000000000..5c7e62749e --- /dev/null +++ b/.agents/notes/implemented/feature/2026-08-11-collapsible-ask-user-question-card.md @@ -0,0 +1,32 @@ +# Agent Note: Collapsible Ask-User Question Card + +Status: implemented + +English | [中文](2026-08-11-collapsible-ask-user-question-card.zh.md) + +## Problem + +`dsh`'s ask-user takeover renders the pending question set as a bottom card capped at `min(60vh, 520px)`, so a long batch or a user who wants to re-read the conversation above before deciding has no way to reduce the card — the conversation above becomes hard to read because only a few lines peek out at the top. + +## Decision + +Add a minimize/maximize toggle to the question card header, next to the existing dismiss action. Collapsing hides the option body and the footer actions, leaving a header strip (eyebrow, title, both icon buttons) so the user still sees that a question is pending; expanding restores the full card. + +- State lives in `QuestionFlow` local state (`minimized`), so drafts and the current question index survive collapse/expand — nothing is re-derived or reset, and the answers already picked remain submit-ready. +- The toggle is a plain `IconChevronDownOutline14` / `IconChevronUpOutline14` pair on the existing 24px icon-button grid; `aria-expanded` reflects the card state and the label flips between `nav.minimize` / `nav.maximize` (the collapsed button reads "expand" for screen readers). +- While minimized the option body and footer are unmounted (`{!minimized && ...}`), so no hidden interactive surface remains in the a11y tree. +- The collapse button is disabled while a submit/cancel is in flight (`busy !== null`), matching the dismiss button's existing guard. +- CSS: `.cardMinimized` drops the `max-height` cap and hides `.body` / `.footer`; `.header` gains bottom padding so the strip is not cramped. +- Scope: only the generic question flow (`QuestionFlow`) gets the toggle. The plan-review card (`PlanReviewPanel`) is a different shape (one decision over one plan) and keeps its current layout. + +## Consequences + +- Users can shrink the question card to read the conversation, then expand to answer — drafts and position are preserved because the state lives in the flow component, not in the DOM. +- The minimize action is visually adjacent to dismiss; both share the icon button style, so the header stays balanced. +- Product copy additions are confined to the `question` locale namespace (`nav.minimize` / `nav.maximize`), paired zh/en per the dictionary contract. + +## Alternatives considered + +- **Auto-collapse on scroll**: collapsing the card when the user scrolls the conversation would reclaim space without a button, but it fights the user mid-interaction and hides the pending-question signal unexpectedly; an explicit toggle keeps the decision with the user. +- **Resizable card**: a drag handle would let users size the card freely, but it is more machinery than the ask needs and does not address "I want the card out of the way entirely". +- **Persisting the collapsed state per session**: nice-to-have, but the ask is per-interaction; persisting adds storage and sync complexity without a clear win for this surface. diff --git a/.agents/notes/implemented/feature/2026-08-11-collapsible-ask-user-question-card.zh.md b/.agents/notes/implemented/feature/2026-08-11-collapsible-ask-user-question-card.zh.md new file mode 100644 index 0000000000..5f4b5851e4 --- /dev/null +++ b/.agents/notes/implemented/feature/2026-08-11-collapsible-ask-user-question-card.zh.md @@ -0,0 +1,32 @@ +# Agent Note: 可收起的提问卡片 + +Status: implemented + +[English](2026-08-11-collapsible-ask-user-question-card.md) | 中文 + +## Problem + +`dsh` 的 ask-user 接管界面把待回答的问题组渲染为底部卡片,高度上限为 `min(60vh, 520px)`;当问题批次较长、或用户想先阅读上方的会话记录再决定时,卡片会占满大部分视口且无法缩小——上方会话几乎被遮住,只能看到顶部几行。 + +## Decision + +在提问卡片头部(现有的"放弃整组问题"按钮旁)增加收起/展开切换按钮。收起时隐藏选项主体和底部操作区,只保留一条头部(eyebrow、标题、两个图标按钮),用户仍能看到"有未答问题"的信号;展开后恢复完整卡片。 + +- 状态存放在 `QuestionFlow` 的本地 state(`minimized`),因此收起/展开不会丢失草稿和当前题目索引——已选答案仍可直接提交。 +- 切换按钮使用 `IconChevronDownOutline14` / `IconChevronUpOutline14`,复用现有 24px 图标按钮网格;`aria-expanded` 反映卡片状态,文案在 `nav.minimize` / `nav.maximize` 之间切换(收起后按钮对读屏器显示为"展开")。 +- 收起时选项主体和底部通过 `{!minimized && ...}` 卸载,a11y 树中不残留隐藏的可交互面。 +- 提交/取消进行中(`busy !== null`)时收起按钮禁用,与现有放弃按钮的守卫一致。 +- CSS:`.cardMinimized` 去掉 `max-height` 上限并隐藏 `.body` / `.footer`;`.header` 增加底部 padding,避免折叠后过于局促。 +- 范围:只有通用提问流(`QuestionFlow`)获得该切换。计划评审卡片(`PlanReviewPanel`)是另一种形态(对一个计划做一次决策),保持现有布局。 + +## Consequences + +- 用户可以缩小提问卡片以阅读会话,再展开作答——草稿和位置因状态存放在流程组件中而得以保留。 +- 收起动作紧邻放弃按钮,二者共用图标按钮样式,头部保持平衡。 +- 新增产品文案仅落在 `question` locale 命名空间(`nav.minimize` / `nav.maximize`),按字典契约中英成对。 + +## Alternatives considered + +- **滚动时自动收起**:用户滚动会话时自动折叠卡片可以省空间,但会在交互中途与用户对抗,并意外隐藏"待答问题"信号;显式切换把决定权交给用户。 +- **可拖拽调整大小**:拖拽手柄让用户自由调整卡片大小,但比需求所需的机制更复杂,也没有解决"让卡片完全让开"的诉求。 +- **按会话持久化折叠状态**:锦上添花,但提问是单次交互;持久化引入存储与同步复杂度,对这个界面没有明确收益。 diff --git a/.agents/notes/implemented/feature/2026-08-11-minimal-profiles-bare-two-tool-runtime.i18n.yaml b/.agents/notes/implemented/feature/2026-08-11-minimal-profiles-bare-two-tool-runtime.i18n.yaml index 8133a3f08a..2907d9c241 100644 --- a/.agents/notes/implemented/feature/2026-08-11-minimal-profiles-bare-two-tool-runtime.i18n.yaml +++ b/.agents/notes/implemented/feature/2026-08-11-minimal-profiles-bare-two-tool-runtime.i18n.yaml @@ -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 .agents/notes/implemented/feature/2026-08-11-minimal-profiles-bare-two-tool-runtime.md -2026-08-11-minimal-profiles-bare-two-tool-runtime.md: 92d00a77de3e378abccc2ea67ba38a0cc76e0eca -2026-08-11-minimal-profiles-bare-two-tool-runtime.zh.md: 1528b241436171145839240c7415ef18acab337f +2026-08-11-minimal-profiles-bare-two-tool-runtime.md: 2f26dda5ddc905076dbc2f6c681f462973bde793 +2026-08-11-minimal-profiles-bare-two-tool-runtime.zh.md: ffdd8f0ddb86535468dbcb4384a6ba18c97b7124 diff --git a/.agents/notes/implemented/feature/2026-08-11-minimal-profiles-bare-two-tool-runtime.md b/.agents/notes/implemented/feature/2026-08-11-minimal-profiles-bare-two-tool-runtime.md index 92d00a77de..2f26dda5dd 100644 --- a/.agents/notes/implemented/feature/2026-08-11-minimal-profiles-bare-two-tool-runtime.md +++ b/.agents/notes/implemented/feature/2026-08-11-minimal-profiles-bare-two-tool-runtime.md @@ -12,7 +12,7 @@ The two launch paths also have different configuration owners. Web mounts a per- ## Decision -Both shipped minimal profiles expose exactly persistent `bash` and `str_replace_editor`, mount no context-compaction provider, and run the editor against `@deepseek-ai/dsh-fs-local`. The Web preset isolates `ctx.fs` inside the agent entry and mounts `fs-local` beside the editor, so other Web agents retain the host filesystem provider. Its persona remains the fixed complete prompt owned by the earlier [minimal-preset composition decision](../bug-fix/2026-08-10-minimal-preset-owns-rl-composition.md). +Both shipped minimal profiles expose exactly persistent `bash` and `str_replace_editor`, mount no context-compaction provider, suppress every `dsh-system-prompt` runtime-context contribution for fresh sessions, and run the editor against `@deepseek-ai/dsh-fs-local`. The Web preset isolates `ctx.fs` inside the agent entry and mounts `fs-local` beside the editor, so other Web agents retain the host filesystem provider. Its persona remains the fixed complete prompt owned by the earlier [minimal-preset composition decision](../bug-fix/2026-08-10-minimal-preset-owns-rl-composition.md) and applies runtime-context suppression only to that agent scope. The standalone spine forwards the same setting to its process-owned system-prompt service. Sandbox and approval services remain mounted and enforce their policies; only their model-facing dynamic context is absent. The standalone [`minimal.cordis.yml`](../../../../examples/jsonrpc-agent/minimal.cordis.yml) remains a complete JSON-RPC process composition. It mounts `dsh-sdk-jsonrpc-server`, the local PTY and subprocess services required by persistent Bash, `fs-local`, the two tool consumers, and uncompressed JSONL persistence. It does not mount `token-meter`, `compaction-basic`, `fs-sandbox`, or `fs-observation-policy`. Persistent Bash still consumes the deployment's danger-full-access sandbox policy; the editor is not confined by that policy. @@ -20,9 +20,9 @@ The standalone [`minimal.cordis.yml`](../../../../examples/jsonrpc-agent/minimal ## Verification -The Web replay boots the complete Web host, creates the agent through the preset service, and asserts that the scoped filesystem is bare, no scoped compaction service exists, and the assembled request contains exactly the fixed prompt and two tools. It then executes persistent Bash and the editor against the real scoped services. +The Web replay boots the complete Web host, creates the agent through the preset service, and asserts that the scoped filesystem is bare, no scoped compaction service exists, no system-prompt-owned runtime-context message was appended, and the assembled request contains exactly the fixed prompt and two tools. It then executes persistent Bash and the editor against the real scoped services. -The SDK replay boots the real JSON-RPC agent process through the SDK client, injects an environment-selected prompt, asserts the assembled prompt and exact two-tool catalog, and executes both tools. Python SDK bundled-runtime coverage initializes the standalone configuration through each available packaged carrier with environment-selected model, model capacity, and prompt values. Cordis validation checks that both configurations resolve their declared plugins and configuration fields. +The SDK replay boots the real JSON-RPC agent process through the SDK client, injects an environment-selected prompt, asserts the assembled prompt, exact two-tool catalog, and absence of every system-prompt-owned runtime-context message, and executes both tools. Python SDK bundled-runtime coverage initializes the standalone configuration through each available packaged carrier with environment-selected model, model capacity, and prompt values. Cordis validation checks that both configurations resolve their declared plugins and configuration fields. ## Alternatives considered @@ -36,4 +36,4 @@ The SDK replay boots the real JSON-RPC agent process through the SDK client, inj ## Consequences -Minimal sessions never summarize or replace earlier history; callers must keep turns within the selected model's context capacity. The editor can address any absolute path visible to the runtime process, independently of the persistent shell's sandbox policy. The two launch paths share their model-facing tool and no-compaction guarantees while retaining different prompt and model configuration appropriate to their owners. The Python SDK path continues to communicate only through the bundled stdio JSON-RPC runtime. +Minimal sessions never summarize or replace earlier history and never add a runtime-context snapshot; callers must keep turns within the selected model's context capacity and must not rely on model-visible narration of standing sandbox or approval policy. The editor can address any absolute path visible to the runtime process, independently of the persistent shell's sandbox policy. The two launch paths share their model-facing tool, no-context, and no-compaction guarantees while retaining different prompt and model configuration appropriate to their owners. The Python SDK path continues to communicate only through the bundled stdio JSON-RPC runtime. diff --git a/.agents/notes/implemented/feature/2026-08-11-minimal-profiles-bare-two-tool-runtime.zh.md b/.agents/notes/implemented/feature/2026-08-11-minimal-profiles-bare-two-tool-runtime.zh.md index 1528b24143..ffdd8f0ddb 100644 --- a/.agents/notes/implemented/feature/2026-08-11-minimal-profiles-bare-two-tool-runtime.zh.md +++ b/.agents/notes/implemented/feature/2026-08-11-minimal-profiles-bare-two-tool-runtime.zh.md @@ -12,7 +12,7 @@ Web `minimal` preset 与独立 JSON-RPC minimal 组合对外提供持久 `bash` ## 决策 -两种随附 minimal profile 都只对外提供持久 `bash` 与 `str_replace_editor`,不挂载上下文压缩提供方,并让编辑器使用 `@deepseek-ai/dsh-fs-local`。Web preset 在 agent entry 内隔离 `ctx.fs`,将 `fs-local` 与编辑器一起挂载,因此其他 Web agent 仍使用宿主文件系统提供方。其 persona 继续采用较早的 [minimal preset 组合决策](../bug-fix/2026-08-10-minimal-preset-owns-rl-composition.md)所拥有的固定 complete 提示词。 +两种随附 minimal profile 都只对外提供持久 `bash` 与 `str_replace_editor`,不挂载上下文压缩提供方,为新建会话抑制每个 `dsh-system-prompt` runtime-context 贡献,并让编辑器使用 `@deepseek-ai/dsh-fs-local`。Web preset 在 agent entry 内隔离 `ctx.fs`,将 `fs-local` 与编辑器一起挂载,因此其他 Web agent 仍使用宿主文件系统提供方。其 persona 继续采用较早的 [minimal preset 组合决策](../bug-fix/2026-08-10-minimal-preset-owns-rl-composition.md)所拥有的固定 complete 提示词,并仅为该 agent 作用域实施 runtime-context 抑制。独立 spine 将同一设置转发给其进程拥有的 system-prompt 服务。沙箱与批准服务仍保持挂载并强制其策略;只有它们面向模型的动态上下文缺席。 独立的 [`minimal.cordis.yml`](../../../../examples/jsonrpc-agent/minimal.cordis.yml) 仍是完整的 JSON-RPC 进程组合。它挂载 `dsh-sdk-jsonrpc-server`、持久 Bash 所需的本地 PTY 和子进程服务、`fs-local`、两个工具消费方,以及未压缩的 JSONL 持久化。它不挂载 `token-meter`、`compaction-basic`、`fs-sandbox` 或 `fs-observation-policy`。持久 Bash 仍消费部署的 danger-full-access 沙箱策略;编辑器不受该策略限制。 @@ -20,9 +20,9 @@ Web `minimal` preset 与独立 JSON-RPC minimal 组合对外提供持久 `bash` ## 验证 -Web 回放会启动完整 Web 宿主,通过 preset 服务创建 agent,并断言作用域文件系统为裸后端、不存在作用域压缩服务,而且组装请求只包含固定提示词与两个工具。随后,它通过真实作用域服务执行持久 Bash 和编辑器。 +Web 回放会启动完整 Web 宿主,通过 preset 服务创建 agent,并断言作用域文件系统为裸后端、不存在作用域压缩服务、没有追加 system-prompt 拥有的 runtime-context 消息,而且组装请求只包含固定提示词与两个工具。随后,它通过真实作用域服务执行持久 Bash 和编辑器。 -SDK 回放通过 SDK 客户端启动真实 JSON-RPC agent 进程,注入由环境选择的提示词,断言组装提示词与精确双工具目录,并执行两个工具。Python SDK 内置运行时覆盖会通过每种可用的打包载体,使用环境选择的模型、模型容量和提示词值初始化独立配置。Cordis 校验会检查两份配置能否解析声明的插件和配置字段。 +SDK 回放通过 SDK 客户端启动真实 JSON-RPC agent 进程,注入由环境选择的提示词,断言组装提示词与精确双工具目录,另外断言不存在任何 system-prompt 拥有的 runtime-context 消息,并执行两个工具。Python SDK 内置运行时覆盖会通过每种可用的打包载体,使用环境选择的模型、模型容量和提示词值初始化独立配置。Cordis 校验会检查两份配置能否解析声明的插件和配置字段。 ## 考虑过的替代方案 @@ -36,4 +36,4 @@ SDK 回放通过 SDK 客户端启动真实 JSON-RPC agent 进程,注入由环 ## 后果 -Minimal 会话不会摘要或替换较早历史;调用方必须让会话轮次保持在所选模型的上下文容量内。编辑器可以访问运行时进程可见的任何绝对路径,且不受持久 shell 沙箱策略影响。两条启动路径共享面向模型的工具与无压缩保证,同时保留适合各自所有者的不同提示词和模型配置。Python SDK 路径继续仅通过内置 stdio JSON-RPC 运行时通信。 +Minimal 会话不会摘要或替换较早历史,也不会添加 runtime-context 快照;调用方必须让会话轮次保持在所选模型的上下文容量内,且不得依赖模型可见的常驻沙箱或批准策略说明。编辑器可以访问运行时进程可见的任何绝对路径,且不受持久 shell 沙箱策略影响。两条启动路径共享面向模型的工具、无上下文与无压缩保证,同时保留适合各自所有者的不同提示词和模型配置。Python SDK 路径继续仅通过内置 stdio JSON-RPC 运行时通信。 diff --git a/.agents/notes/implemented/feature/2026-08-12-product-subagent-one-shot-background-tasks.i18n.yaml b/.agents/notes/implemented/feature/2026-08-12-product-subagent-one-shot-background-tasks.i18n.yaml new file mode 100644 index 0000000000..2310e148a0 --- /dev/null +++ b/.agents/notes/implemented/feature/2026-08-12-product-subagent-one-shot-background-tasks.i18n.yaml @@ -0,0 +1,6 @@ +# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each +# 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 .agents/notes/implemented/feature/2026-08-12-product-subagent-one-shot-background-tasks.md +2026-08-12-product-subagent-one-shot-background-tasks.md: b8865cf94852396c32dd6da996bc9f5c2c7d806b +2026-08-12-product-subagent-one-shot-background-tasks.zh.md: bbc18ebb6cf0de1b04f0c2a10ddf51cea282c24e diff --git a/.agents/notes/implemented/feature/2026-08-12-product-subagent-one-shot-background-tasks.md b/.agents/notes/implemented/feature/2026-08-12-product-subagent-one-shot-background-tasks.md new file mode 100644 index 0000000000..b8865cf948 --- /dev/null +++ b/.agents/notes/implemented/feature/2026-08-12-product-subagent-one-shot-background-tasks.md @@ -0,0 +1,70 @@ +# Agent Note: Product one-shot subagents use generic background Jobs + +Status: implemented + +English | [中文](2026-08-12-product-subagent-one-shot-background-tasks.zh.md) + +## Problem + +The Codex and Claude Code providers already run one self-contained task and return one final answer, while `dsh-tool-subagent` already adapts any one-shot provider to the generic background Job runtime. The shipped product-tool rows disabled that route, so an agent could only wait for the product answer even when the delegation was independent of its next action. + +Exposing background execution must not add a product session, product-specific job state, another cancellation owner, or another result protocol. The same provider run must remain responsible for one native process or query and one final answer, while the existing Job registry remains responsible for ids, collection, cancellation, owner cleanup, and completion notices. + +## Decision + +Production `dsh` does not install the optional product providers. A Profile that opts in installs and mounts `dsh-subagent-codex`, `dsh-subagent-claude-code`, or both once on the host plane. The `standard`, `code`, and `cordis` Agent Presets configure the corresponding dormant tool rows with `backgroundMode: one-shot`; removing a row's `disabled` field exposes the existing optional `run_in_background` argument to agents composed from that preset. Omission or `false` waits in the foreground; explicit `true` returns a parent-owned Job id after synchronous Job preflight and registration, without waiting for provider startup or completion. + +The [generic one-shot background adapter](2026-07-08-background-subagent-tasks.md) owns background registration and settlement. It starts the same [`SubagentRun`](2026-06-21-subagent-capability-seam.md), uses a Job-owned cancellation signal across provider startup and execution, waits for `run.result` and `run.dispose()`, maps the terminal result into the Job, and lets `job_output`, `job_list`, `job_kill`, and the existing completion notice expose that state. The [product provider decision](2026-08-04-claude-code-and-codex-subagent-backends.md) continues to own native protocols, answer selection, local cancellation, and process-tree quiescence. + +No provider configuration, service interface, event, wire field, persistence format, or product identifier is added. Foreground and background differ only in which existing consumer waits for the same one-shot run. + +### Ownership and lifecycle + +```text +product tool call + -> omitted / false: tool call waits -> final answer or error -> run disposal + -> true: Job preflight + owner cleanup + -> starter begins provider startup under Job-owned signal + -> Job record/id published and returned (startup remains pending) + -> provider result + run disposal -> Job settlement + notice + -> job_output reads / job_kill cancels + -> parent disposal: Job owner cleanup cancels -> run disposal -> process exit +``` + +| Fact or resource | Owner | Product-tool responsibility | Observable result | +| --- | --- | --- | --- | +| Product provider installation and registration | Explicit Profile | Install the optional provider package and mount it once on the host plane | The provider name is available without adding its package to every production `dsh` install | +| Product selection and exposure | Agent Preset | Bind one fixed tool name to one fixed provider | Enabling one row exposes only that product tool | +| Foreground or background choice | `dsh-tool-subagent` | Resolve `run_in_background` under `one-shot` policy | Omission is foreground; explicit `true` returns a Job id | +| Job id, state, output, cancellation, and notice | `ctx.jobs` and `dsh-tool-jobs` | Register and present the existing one-shot run | Generic job tools collect or stop the run for the exact parent | +| Native answer and process quiescence | Product provider and `dsh-subprocess` | Produce one final result and release one process tree | Job settlement and foreground return both wait for disposal | + +## Published composition + +The production base keeps both optional product providers out of its dependency closure. An opting-in Profile installs and mounts either or both providers once on the host plane. Each full preset keeps both product-tool rows disabled and contributes the generic Job controls to its own agent scope, while the base host owns the shared Job registry. A user copies a preset and removes `disabled` from the matching product rows after the Profile provider is present; no product process starts during composition. + +A standalone custom composition that enables one-shot background execution must provide the product provider plus the complete generic Job capability: `dsh-jobs-local` as the Job provider and `dsh-tool-jobs` as the model-facing consumer. A Profile based on `dsh-base` already has the Job capability and adds only the optional product provider before enabling the preset tool row. A product tool without the Job runtime can still execute in the foreground, but an explicit background request fails the existing Job preflight instead of publishing an uncollectable id. + +The ACP product compositions use the same fixed product rows and generic job controls. Their keyless schema snapshots expose `description`, `prompt`, and optional `run_in_background` for each enabled product tool without invoking Codex, Claude Code, or an external model. + +## Verification + +The Web composition test explicitly mounts both optional providers from the repository examples dependency anchor, then boots four user-preset variants—neither product, Codex, Claude Code, and both—and checks that each enabled product tool exposes `run_in_background` alongside `job_output`, `job_list`, and `job_kill`. The two package-owned Loader compositions run with an empty `PATH`, inspect the same schemas and controls, and prove that explicit provider loading starts no product process. ACP keyless snapshots pin the assembled explicit product schemas, while the existing `dsh-tool-subagent` and job suites pin foreground defaulting, Job registration, final-output collection, cancellation, completion notices, owner disposal, and provider disposal. + +## Alternatives considered + +**Keep the product tools foreground-only.** This preserves the smallest schema but prevents agents from scheduling independent product work even though the generic one-shot Job adapter already owns the required lifecycle. + +**Make product delegations background by default.** A one-shot Job requires later collection, unlike a continuable child with its own durable conversation id and settlement delivery. Foreground remains the compatible default, and background remains an explicit scheduling choice. + +**Use Codex or Claude Code native session state as the background owner.** That would create provider-specific ids, status, cancellation, and recovery semantics beside the generic Job registry. The providers remain one-shot result producers and keep native ids private. + +**Add product-specific output, wait, or kill tools.** Separate controls would duplicate the generic job protocol and teach a different collection workflow for each provider. The existing `job_*` tools already cover the required operations. + +**Add continuable product sessions at the same time.** Resume, follow-up, progress, and persisted product sessions require new product contracts and lifecycle ownership. This decision exposes only the already implemented one-shot background route. + +## Consequences + +Agents can continue useful work while Codex or Claude Code handles an independent one-shot task, then collect the final answer or cancel it through the same Job controls used by other background producers. Foreground callers retain their existing result and error behavior. + +Every product delegation still starts a fresh native process or query, produces final text as its only product payload, and ends with provider disposal and whole-tree exit. A background call additionally exposes the generic Job id, status, completion notice, and collection or cancellation results. Background Jobs are process-local and parent-owned: they do not survive parent disposal, do not expose intermediate product activity, and do not make a product conversation resumable. Production installs do not pay for either product integration unless a Profile explicitly installs it; any composition that exposes the background argument must also keep the generic Job provider and controls available. diff --git a/.agents/notes/implemented/feature/2026-08-12-product-subagent-one-shot-background-tasks.zh.md b/.agents/notes/implemented/feature/2026-08-12-product-subagent-one-shot-background-tasks.zh.md new file mode 100644 index 0000000000..bbc18ebb6c --- /dev/null +++ b/.agents/notes/implemented/feature/2026-08-12-product-subagent-one-shot-background-tasks.zh.md @@ -0,0 +1,70 @@ +# Agent Note: 产品 one-shot subagent 使用通用后台 Job + +Status: implemented + +[English](2026-08-12-product-subagent-one-shot-background-tasks.md) | 中文 + +## 问题 + +Codex 与 Claude Code 提供方已经能够运行一项自包含任务并返回一个最终回答,而 `dsh-tool-subagent` 也已经能够把任意 one-shot 提供方接入通用后台 Job 运行时。随附产品工具行禁用了这条路径,因此即使委托与 agent 的下一步操作彼此独立,agent 也只能等待产品回答。 + +公开后台执行不得增加产品会话、产品专属作业状态、另一取消责任方或另一结果协议。同一个提供方运行必须继续负责一个原生进程或 query 和一个最终回答,而现有作业注册表继续负责 id、收集、取消、owner 清理与完成通知。 + +## 决策 + +生产 `dsh` 不安装可选产品提供方。选择启用产品集成的 Profile 会安装 `dsh-subagent-codex`、`dsh-subagent-claude-code` 或两者,并在 host plane(宿主平面)各挂载一次。`standard`、`code` 与 `cordis` Agent Preset 使用 `backgroundMode: one-shot` 配置相应的休眠工具行;删除某一行的 `disabled` 字段后,现有可选参数 `run_in_background` 会向由该 preset 组装的 agent 公开。省略该参数或传入 `false` 时会在前台等待;显式传入 `true` 时会在同步完成 Job 预检与登记后返回由父级拥有的 Job id,而不会等待提供方启动或完成。 + +[通用 one-shot 后台适配器](2026-07-08-background-subagent-tasks.md)负责后台登记与结算。它会启动同一个 [`SubagentRun`](2026-06-21-subagent-capability-seam.md),让 Job 自有的取消信号覆盖提供方启动与执行,等待 `run.result` 和 `run.dispose()`,把终态结果映射进 Job,并由 `job_output`、`job_list`、`job_kill` 与现有完成通知公开该状态。[产品提供方决策](2026-08-04-claude-code-and-codex-subagent-backends.md)继续负责原生协议、答案选择、本地取消与进程树完全停稳。 + +本决策不新增提供方配置、服务接口、事件、协议字段、持久化格式或产品标识符。前台与后台的区别仅在于由哪个现有消费方等待同一个 one-shot 运行。 + +### 归属与生命周期 + +```text +product tool call + -> omitted / false: tool call waits -> final answer or error -> run disposal + -> true: Job preflight + owner cleanup + -> starter begins provider startup under Job-owned signal + -> Job record/id published and returned (startup remains pending) + -> provider result + run disposal -> Job settlement + notice + -> job_output reads / job_kill cancels + -> parent disposal: Job owner cleanup cancels -> run disposal -> process exit +``` + +| 事实或资源 | 责任方 | 产品工具职责 | 可观察结果 | +| --- | --- | --- | --- | +| 产品提供方安装与登记 | 显式 Profile | 安装可选提供方包,并在 host plane 挂载一次 | 提供方名称可用,但不会让每次生产 `dsh` 安装都包含该包 | +| 产品选择与公开 | Agent Preset | 把一个固定工具名绑定到一个固定提供方 | 启用一行只会公开对应产品工具 | +| 前台或后台选择 | `dsh-tool-subagent` | 按 `one-shot` 策略解析 `run_in_background` | 省略参数时在前台运行;显式传入 `true` 时返回 Job id | +| Job id、状态、输出、取消与通知 | `ctx.jobs` 与 `dsh-tool-jobs` | 登记并展示现有 one-shot 运行 | 通用作业工具为准确父级收集或停止运行 | +| 原生答案与进程完全停稳 | 产品提供方与 `dsh-subprocess` | 产生一个最终结果并释放一棵进程树 | Job 结算与前台返回都会等待资源释放 | + +## 发布组装 + +生产 base 不让两个可选产品提供方进入依赖闭包。选择启用产品集成的 Profile 会在 host plane 安装并挂载任一或两个提供方。每个完整 preset 让两个产品工具行保持禁用,并把通用 Job 控制工具贡献到自身 agent 作用域;base host 负责共享 Job 注册表。Profile 提供方存在后,用户复制一个 preset,再从对应产品行删除 `disabled`;组装期间不会启动产品进程。 + +独立自定义组装若启用 one-shot 后台执行,就必须同时提供产品提供方与完整通用 Job 能力:由 `dsh-jobs-local` 充当 Job 提供方,由 `dsh-tool-jobs` 充当面向模型的消费方。基于 `dsh-base` 的 Profile 已具备 Job 能力,只需在启用 preset 工具行前新增可选产品提供方。没有 Job 运行时的产品工具仍可在前台执行,但显式后台请求会在现有 Job 预检中失败,不会发布无法收集的 id。 + +ACP 产品组装使用相同的固定产品行与通用作业控制工具。其无密钥 schema 快照会为每个已启用产品工具公开 `description`、`prompt` 和可选的 `run_in_background`,而不会调用 Codex、Claude Code 或外部模型。 + +## 验证 + +Web 组装测试会从仓库 examples 依赖锚点显式挂载两个可选提供方,再启动四种用户 preset 变体——不启用产品、只启用 Codex、只启用 Claude Code,以及同时启用两者——并检查每个已启用产品工具都会与 `job_output`、`job_list` 和 `job_kill` 一起公开 `run_in_background`。两个由包负责的 Loader 组装会在空 `PATH` 下运行,检查相同 schema 与控制工具,并证明显式加载提供方不会启动产品进程。ACP 无密钥快照会固定显式组装后的产品 schema,而现有 `dsh-tool-subagent` 与作业测试套件会固定前台默认值、Job 登记、最终输出收集、取消、完成通知、owner 资源释放与提供方资源释放。 + +## 曾考虑的替代方案 + +**让产品工具继续只支持前台运行。** 这种方案保留最小 schema,却会阻止 agent 调度独立产品工作,即使通用 one-shot Job 适配器已经负责所需生命周期。 + +**让产品委托默认在后台运行。** one-shot Job 需要后续收集,这不同于拥有自身持久会话 id 与结算交付的可续接子级。前台继续作为兼容默认值,后台继续作为显式调度选择。 + +**让 Codex 或 Claude Code 原生会话状态负责后台生命周期。** 这会在通用作业注册表之外建立提供方专属 id、状态、取消与恢复语义。提供方继续只产生 one-shot 结果,并把原生 id 保持为私有事实。 + +**增加产品专属 output、wait 或 kill 工具。** 独立控制工具会复制通用作业协议,并为每个提供方教授不同的收集工作流。现有 `job_*` 工具已经覆盖所需操作。 + +**同时增加可续接产品会话。** 恢复、后续交互、进度与持久化产品会话需要新的产品约定和生命周期归属。本决策只公开已经实现的 one-shot 后台路径。 + +## 后果 + +agent 可以在 Codex 或 Claude Code 处理独立 one-shot 任务时继续推进其他工作,随后通过其他后台 producer 共用的 Job 控制工具收集最终回答或取消运行。前台调用方继续获得既有结果与错误行为。 + +每次产品委托仍会启动一个全新的原生进程或 query,把最终文本作为唯一产品载荷,并以提供方资源释放和整棵进程树退出结束。后台调用还会额外公开通用 Job id、状态、完成通知以及收集或取消结果。后台 Job 仅存在于当前进程且由父级拥有:它不会在父级资源释放后继续存活,不会公开产品中间活动,也不会让产品对话变得可恢复。只有 Profile 显式安装产品集成时,生产安装才承担对应成本;公开后台参数的任何组装还必须让通用 Job 提供方与控制工具保持可用。 diff --git a/.agents/notes/implemented/feature/2026-08-13-shared-modal-product-onboarding.i18n.yaml b/.agents/notes/implemented/feature/2026-08-13-shared-modal-product-onboarding.i18n.yaml new file mode 100644 index 0000000000..abf480f6b2 --- /dev/null +++ b/.agents/notes/implemented/feature/2026-08-13-shared-modal-product-onboarding.i18n.yaml @@ -0,0 +1,6 @@ +# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each +# 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 .agents/notes/implemented/feature/2026-08-13-shared-modal-product-onboarding.md +2026-08-13-shared-modal-product-onboarding.md: 771b6675ea170c5001fca7c880f6c246e19fe7f1 +2026-08-13-shared-modal-product-onboarding.zh.md: ebbcb73344b531e90a6d27641f25fa9961d572ac diff --git a/.agents/notes/implemented/feature/2026-08-13-shared-modal-product-onboarding.md b/.agents/notes/implemented/feature/2026-08-13-shared-modal-product-onboarding.md new file mode 100644 index 0000000000..771b6675ea --- /dev/null +++ b/.agents/notes/implemented/feature/2026-08-13-shared-modal-product-onboarding.md @@ -0,0 +1,33 @@ +# Agent Note: Shared-modal product onboarding + +Status: implemented + +English | [中文](2026-08-13-shared-modal-product-onboarding.zh.md) + +## Problem + +First-run onboarding mixed two interaction models: a viewport takeover for product context and a credential prompt that redirected users into Settings before they could enter a key. That made a short, ordered flow feel like two unrelated surfaces and left onboarding UI ownership split across packages. The product still needs a versioned testing-stage notice before provider setup, but restoring it must not add a second independent overlay or change the Host settings and credential boundaries. + +## Decision + +**One existing client Cordis plugin owns both shipped steps.** `ui-settings-models` registers `welcome-notice` at order `-100` and `deepseek-official` at order `0` in `settings.onboarding`. The shell continues to mount only the first incomplete entry, so the dialogs cannot stack. No additional client package or plugin row is introduced. + +**Both steps share one modal component.** `OnboardingModal` wraps the existing ui-primitives `Modal`, supplies the common title and content geometry, and owns `#root` inert for exactly the visible lifetime. Escape and mask clicks do not silently complete mandatory onboarding; each step exposes only its explicit actions. A step still loading private facts returns `null`, so it paints and blocks nothing. + +**The welcome notice reuses the existing durable field.** Its exact copy and version live in `onboarding-copy.ts`. Loopback clients compare and write `ui-onboarding.welcomeNoticeVersion` through the existing settings API, and only Continue acknowledges the current version. Remote clients retain the existing process-local fallback because the settings namespace is loopback-only. No Host schema, API-proxy allowlist, or persistence implementation changes. + +**The credential dialog reuses the existing editor and write boundary.** The Models join still decides whether any provider is usable. When the official DeepSeek reference is writable and missing, `ProviderEditor` renders in credential-only mode inside the shared modal. It validates the key and calls the existing `credentials.set`; it does not mutate provider settings. Save and continue waits for the write and refreshed readiness, while Configure later completes only the current coordinator pass. + +## Alternatives considered + +**Separate client plugins for the notice and credential steps.** Rejected because the product asks for one client Cordis plugin and the two surfaces share copy, ordering, modal chrome, and invalidation ownership. + +**Move acknowledgement or credential logic into a new Host API.** Rejected because both backend contracts already express the required state and writes. A new endpoint would widen scope without changing user capability. + +**Keep the credential step as navigation into Models.** Rejected because the key is the only required first-run field, and the existing editor can expose that write safely without sending the user through a second dialog. + +**Keep the former full-viewport stage.** Rejected because the requested onboarding is a pair of dialogs over the current app, and the common ui-primitives modal already provides the appropriate portal, mask, and accessibility contract. + +## Consequences + +A fresh loopback profile sees the specified internal-testing notice, then an inline DeepSeek key dialog only when no provider is usable. Acknowledgement remains versioned in `settings.yaml`, secrets remain write-only in `.credentials.yaml`, and already-ready or unsupported deployments render no onboarding chrome while readiness loads. The Models package now owns product-onboarding presentation as well as provider configuration; its README and browser coverage make that broader responsibility explicit. This decision restores a concise testing-stage notice after the historical [full-viewport beta notice removal](../simplification/2026-08-13-remove-first-run-beta-notice.md) without restoring that notice's telemetry copy or takeover layout. diff --git a/.agents/notes/implemented/feature/2026-08-13-shared-modal-product-onboarding.zh.md b/.agents/notes/implemented/feature/2026-08-13-shared-modal-product-onboarding.zh.md new file mode 100644 index 0000000000..ebbcb73344 --- /dev/null +++ b/.agents/notes/implemented/feature/2026-08-13-shared-modal-product-onboarding.zh.md @@ -0,0 +1,33 @@ +# Agent Note: 共用弹窗的产品引导 + +Status: implemented + +[English](2026-08-13-shared-modal-product-onboarding.md) | 中文 + +## 问题 + +首次使用引导混用了两种交互:产品背景说明占满整个视口,凭据提示则先把用户带进「设置」,之后才能输入密钥。一个很短的有序流程因此像两个互不相关的界面,引导 UI 的归属也分散在多个包中。产品仍需要在提供方配置之前显示版本化的测试阶段声明,但恢复它不能增加第二个独立浮层,也不能改变 Host 的设置与凭据边界。 + +## 决策 + +**由同一个既有 client Cordis 插件持有两个已发布步骤。** `ui-settings-models` 在 `settings.onboarding` 中以顺序 `-100` 注册 `welcome-notice`,以顺序 `0` 注册 `deepseek-official`。外壳仍然只挂载第一个未完成条目,因此两个弹窗不会堆叠。不新增 client 包或插件配置行。 + +**两个步骤共用同一个弹窗组件。** `OnboardingModal` 包装既有 ui-primitives `Modal`,提供统一的标题和内容布局,并只在可见期间持有 `#root` 的 inert 状态。Escape 和遮罩点击不会静默完成强制引导;每个步骤只暴露自己的明确操作。步骤仍在加载私有事实时返回 `null`,因此不会绘制或阻塞界面。 + +**欢迎声明复用既有持久化字段。** 完整文案与版本由 `onboarding-copy.ts` 持有。回环客户端通过既有 settings API 比较和写入 `ui-onboarding.welcomeNoticeVersion`,且只有点击「继续」才确认当前版本。远程客户端继续使用既有的进程内回退,因为该 settings namespace 仅限回环访问。不改变 Host schema、API Proxy 允许列表或持久化实现。 + +**凭据弹窗复用既有编辑器与写入边界。** Models 联接仍负责判断是否已有任意可用提供方。当 DeepSeek 官方引用可写但缺失时,`ProviderEditor` 以仅凭据模式渲染在共用弹窗中。它校验密钥并调用既有 `credentials.set`,不会修改提供方设置。「保存并继续」会等待写入与就绪状态刷新;「稍后配置」只完成协调器当前这一轮。 + +## 曾考虑的替代方案 + +**让声明与凭据步骤分别成为 client 插件。** 不采用:产品要求只使用一个 client Cordis 插件,且两个界面共享文案、顺序、弹窗框架与失效刷新归属。 + +**把确认或凭据逻辑移入新的 Host API。** 不采用:两个既有后端契约已经能表达所需状态与写入;新增 endpoint 只会扩大范围,不会增加用户能力。 + +**继续从凭据步骤跳转到 Models。** 不采用:首次使用唯一必填的是密钥,既有编辑器可以安全暴露这项写入,无需再把用户送进第二个对话框。 + +**保留此前占满视口的展示层。** 不采用:本次需要的是叠加在当前应用上的两个弹窗,既有 ui-primitives modal 已提供合适的 portal、遮罩与无障碍契约。 + +## 后果 + +新的回环 profile 会先看到指定的内测声明;仅当没有任何可用提供方时,之后才会出现行内 DeepSeek 密钥弹窗。确认仍按版本写入 `settings.yaml`,secret 仍以只写方式存入 `.credentials.yaml`,已就绪或无法修复的部署在加载判定期间不会渲染任何引导框架。Models 包现在同时持有产品引导展示与提供方配置;README 和浏览器覆盖明确记录了这项扩展后的职责。本决策在历史上的[全屏内测声明移除](../simplification/2026-08-13-remove-first-run-beta-notice.md)之后恢复简洁的测试阶段声明,但不会恢复那份声明中的遥测文案或接管式布局。 diff --git a/.agents/notes/implemented/process/2026-06-11-vendor-cordis-as-source.i18n.yaml b/.agents/notes/implemented/process/2026-06-11-vendor-cordis-as-source.i18n.yaml index b75b7f8ac5..9dd1c72ec5 100644 --- a/.agents/notes/implemented/process/2026-06-11-vendor-cordis-as-source.i18n.yaml +++ b/.agents/notes/implemented/process/2026-06-11-vendor-cordis-as-source.i18n.yaml @@ -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 .agents/notes/implemented/process/2026-06-11-vendor-cordis-as-source.md -2026-06-11-vendor-cordis-as-source.md: ccc1289c8a0feadc08d80a3b6e8dc674c1b87bc4 -2026-06-11-vendor-cordis-as-source.zh.md: 4b30ba7684c75bf5eadc0d7c58990ced5355e8f0 +2026-06-11-vendor-cordis-as-source.md: 265966ad0a28900f511efb3091889081d56db2b4 +2026-06-11-vendor-cordis-as-source.zh.md: af8c640e2164c2f14183b29f371e234e59035180 diff --git a/.agents/notes/implemented/process/2026-06-11-vendor-cordis-as-source.md b/.agents/notes/implemented/process/2026-06-11-vendor-cordis-as-source.md index ccc1289c8a..265966ad0a 100644 --- a/.agents/notes/implemented/process/2026-06-11-vendor-cordis-as-source.md +++ b/.agents/notes/implemented/process/2026-06-11-vendor-cordis-as-source.md @@ -6,7 +6,7 @@ English | [中文](2026-06-11-vendor-cordis-as-source.zh.md) ## Problem -DeepSeek Harness SDK is built on the Cordis framework. Cordis core was at 4.0.0-rc.6 (a release candidate) when this repo started; the harness depends on framework internals (fiber lifecycle, effect disposal, waterfall dispatch) whose exact behavior matters to the agent loop's correctness guarantees. +DeepSeek Harness is built on the Cordis framework. Cordis core was at 4.0.0-rc.6 (a release candidate) when this repo started; the harness depends on framework internals (fiber lifecycle, effect disposal, waterfall dispatch) whose exact behavior matters to the agent loop's correctness guarantees. ## Decision diff --git a/.agents/notes/implemented/process/2026-06-11-vendor-cordis-as-source.zh.md b/.agents/notes/implemented/process/2026-06-11-vendor-cordis-as-source.zh.md index 4b30ba7684..af8c640e21 100644 --- a/.agents/notes/implemented/process/2026-06-11-vendor-cordis-as-source.zh.md +++ b/.agents/notes/implemented/process/2026-06-11-vendor-cordis-as-source.zh.md @@ -6,7 +6,7 @@ Status: implemented ## 问题 -DeepSeek Harness SDK 构建于 Cordis 框架之上。本仓库启动时,Cordis core 处于 4.0.0-rc.6(一个候选发布版本);harness 依赖框架内部实现(fiber 生命周期、dispose(资源释放)、waterfall(瀑布式事件)分发),其确切行为直接关系到 agent loop(智能体循环)的正确性保证。 +DeepSeek Harness 构建于 Cordis 框架之上。本仓库启动时,Cordis core 处于 4.0.0-rc.6(一个候选发布版本);harness 依赖框架内部实现(fiber 生命周期、dispose(资源释放)、waterfall(瀑布式事件)分发),其确切行为直接关系到 agent loop(智能体循环)的正确性保证。 ## 决策 diff --git a/.agents/notes/implemented/process/2026-07-02-tool-schema-catalog.i18n.yaml b/.agents/notes/implemented/process/2026-07-02-tool-schema-catalog.i18n.yaml index df27661306..8d2b2035b0 100644 --- a/.agents/notes/implemented/process/2026-07-02-tool-schema-catalog.i18n.yaml +++ b/.agents/notes/implemented/process/2026-07-02-tool-schema-catalog.i18n.yaml @@ -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 .agents/notes/implemented/process/2026-07-02-tool-schema-catalog.md -2026-07-02-tool-schema-catalog.md: 5ae396d0942379f625b6e0ccb89030d8a34c2283 -2026-07-02-tool-schema-catalog.zh.md: 278a9e17dc9f8462ea70694f67ae7944a43765aa +2026-07-02-tool-schema-catalog.md: 21192b8caff386058008eed1417ef78c678190f7 +2026-07-02-tool-schema-catalog.zh.md: 66c01a5ea9f233cf22ef7ebc467c031692bde002 diff --git a/.agents/notes/implemented/process/2026-07-02-tool-schema-catalog.md b/.agents/notes/implemented/process/2026-07-02-tool-schema-catalog.md index 5ae396d094..21192b8caf 100644 --- a/.agents/notes/implemented/process/2026-07-02-tool-schema-catalog.md +++ b/.agents/notes/implemented/process/2026-07-02-tool-schema-catalog.md @@ -29,7 +29,7 @@ Booting has a cost the AST pass did not: there is no source declaration set to e ### A hand-maintained boot manifest is the irreducible policy -The filesystem discovers the tool-package inventory and the completeness guard rejects omissions. `TOOL_PACKAGES` still owns an explicit boot recipe for each package because required Service providers and config are policy, not facts that can be inferred safely from layout or injection names. +The filesystem discovers the tool-package inventory and the completeness guard rejects omissions. `TOOL_PACKAGES` still owns an explicit boot recipe for each package because required Service Providers and config are policy, not facts that can be inferred safely from layout or injection names. ### Scope diff --git a/.agents/notes/implemented/process/2026-07-02-tool-schema-catalog.zh.md b/.agents/notes/implemented/process/2026-07-02-tool-schema-catalog.zh.md index 278a9e17dc..66c01a5ea9 100644 --- a/.agents/notes/implemented/process/2026-07-02-tool-schema-catalog.zh.md +++ b/.agents/notes/implemented/process/2026-07-02-tool-schema-catalog.zh.md @@ -29,7 +29,7 @@ Cordis 目录是纯 TypeScript AST 遍历,因为每个事件/服务名都是 ### 手动维护的启动 manifest 是无法省去的策略 -文件系统负责发现工具包清单,完整性守卫负责拒绝遗漏。`TOOL_PACKAGES` 仍然为每个包持有一份显式的启动配方,因为所需的服务提供方和配置属于策略,不是能从目录布局或注入名称安全推断的事实。 +文件系统负责发现工具包清单,完整性守卫负责拒绝遗漏。`TOOL_PACKAGES` 仍然为每个包持有一份显式的启动配方,因为所需的 Service Provider 和配置属于策略,不是能从目录布局或注入名称安全推断的事实。 ### 范围 diff --git a/.agents/notes/implemented/process/2026-07-22-evidence-based-larger-hosted-runners.i18n.yaml b/.agents/notes/implemented/process/2026-07-22-evidence-based-larger-hosted-runners.i18n.yaml index 314705f776..4580a534c5 100644 --- a/.agents/notes/implemented/process/2026-07-22-evidence-based-larger-hosted-runners.i18n.yaml +++ b/.agents/notes/implemented/process/2026-07-22-evidence-based-larger-hosted-runners.i18n.yaml @@ -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 .agents/notes/implemented/process/2026-07-22-evidence-based-larger-hosted-runners.md -2026-07-22-evidence-based-larger-hosted-runners.md: 84c951809891b4936549a2f429dc7efc99833c1b -2026-07-22-evidence-based-larger-hosted-runners.zh.md: bb5b585da26ffd15b5a1096cd40293f64fb69c79 +2026-07-22-evidence-based-larger-hosted-runners.md: e0d919851d99eac6539a25c63c9baeb49f76335f +2026-07-22-evidence-based-larger-hosted-runners.zh.md: 673bd7643506f022b640d14918dd7c883fb60e36 diff --git a/.agents/notes/implemented/process/2026-07-22-evidence-based-larger-hosted-runners.md b/.agents/notes/implemented/process/2026-07-22-evidence-based-larger-hosted-runners.md index 84c9518098..e0d919851d 100644 --- a/.agents/notes/implemented/process/2026-07-22-evidence-based-larger-hosted-runners.md +++ b/.agents/notes/implemented/process/2026-07-22-evidence-based-larger-hosted-runners.md @@ -52,7 +52,7 @@ The process-bound coverage project contains exactly five suite files. Thirty-two Complete serial Linux, macOS, and Windows references run only when `master` moves. Pull requests use the enterprise required path plus standard-hosted compatibility jobs, while other larger-runner sizes run only by manual dispatch. -An additional serial Linux reference runs on the in-house self-hosted pool (`vm-backup` label: a 64-core VM with six always-on systemd-managed runner instances) on every `master` push. It is a hot-standby drill, not a required check: each run re-proves that the persistent VM can execute the complete unsharded aggregate. The actual switch is pre-wired: the three required Linux jobs resolve their pool through the writer-manageable `DSH_CI_FAILOVER` repository variable, so an outage response is setting one variable and re-running — no merge, which would be deadlocked behind the failing checks themselves ([runbook](2026-07-26-ci-failover-runbook.md)). The standby lane is push-triggered, so it always executes the base branch's workflow definition. Under failover, however, `pull_request` jobs do reach these runners with the PR merge ref's own workflow definition — the trust boundary is repository membership (the repository is private with forking disabled, and the selectors exclude Dependabot), as the [failover runbook](2026-07-26-ci-failover-runbook.md) records. +An additional serial Linux reference runs on the in-house self-hosted pool (`vm-backup` label: a 64-core VM with six always-on systemd-managed runner instances) on every `master` push. It is a hot-standby drill, not a required check: each run re-proves that the persistent VM can execute the complete unsharded aggregate. The actual switch is pre-wired: the three required Linux jobs resolve their pool through the writer-manageable `DSH_CI_FAILOVER_LINUX` repository variable, so an outage response is setting one variable and re-running — no merge, which would be deadlocked behind the failing checks themselves ([runbook](2026-07-26-ci-failover-runbook.md)). The standby lane is push-triggered, so it always executes the base branch's workflow definition. Under failover, however, `pull_request` jobs do reach these runners with the PR merge ref's own workflow definition — the trust boundary is repository membership (the repository is private with forking disabled, and the selectors exclude Dependabot), as the [failover runbook](2026-07-26-ci-failover-runbook.md) records. ## Alternatives considered diff --git a/.agents/notes/implemented/process/2026-07-22-evidence-based-larger-hosted-runners.zh.md b/.agents/notes/implemented/process/2026-07-22-evidence-based-larger-hosted-runners.zh.md index bb5b585da2..673bd76435 100644 --- a/.agents/notes/implemented/process/2026-07-22-evidence-based-larger-hosted-runners.zh.md +++ b/.agents/notes/implemented/process/2026-07-22-evidence-based-larger-hosted-runners.zh.md @@ -52,7 +52,7 @@ Windows 仓库工作在超过 16 核后收益很小,但 32 核池可以让完 只有在 `master` 移动时,才运行完整的 Linux、macOS 和 Windows 串行参考。拉取请求使用企业级运行器必需路径和标准托管兼容性作业,其他大型运行器规格仅通过手动触发运行。 -另有一条串行 Linux 参考在每次 `master` 推送时运行于公司自有的自托管池(`vm-backup` 标签:一台 64 核虚拟机,运行 6 个常驻的 systemd 管理运行器实例)。它是热备演练而非必需检查:每次运行都重新证明这台持久化虚拟机能够执行完整的未分片聚合流程。实际切换机制已预先布线:三个必需 Linux 作业通过写入权限持有者可管理的仓库变量 `DSH_CI_FAILOVER` 解析运行器池,因此故障响应就是设置一个变量并重跑——无需合并(合并本身会被正在失败的检查阻塞,形成死锁)([切换手册](2026-07-26-ci-failover-runbook.md))。该热备通道由 push 触发,执行的始终是基础分支自身的工作流定义。但需要注意:故障切换期间,`pull_request` 作业确实会带着 PR merge 引用自带的工作流定义到达这些运行器——信任边界是仓库成员资格(仓库为私有且禁用 fork,选择器排除 Dependabot),详见[故障切换手册](2026-07-26-ci-failover-runbook.md)的记录。 +另有一条串行 Linux 参考在每次 `master` 推送时运行于公司自有的自托管池(`vm-backup` 标签:一台 64 核虚拟机,运行 6 个常驻的 systemd 管理运行器实例)。它是热备演练而非必需检查:每次运行都重新证明这台持久化虚拟机能够执行完整的未分片聚合流程。实际切换机制已预先布线:三个必需 Linux 作业通过写入权限持有者可管理的仓库变量 `DSH_CI_FAILOVER_LINUX` 解析运行器池,因此故障响应就是设置一个变量并重跑——无需合并(合并本身会被正在失败的检查阻塞,形成死锁)([切换手册](2026-07-26-ci-failover-runbook.md))。该热备通道由 push 触发,执行的始终是基础分支自身的工作流定义。但需要注意:故障切换期间,`pull_request` 作业确实会带着 PR merge 引用自带的工作流定义到达这些运行器——信任边界是仓库成员资格(仓库为私有且禁用 fork,选择器排除 Dependabot),详见[故障切换手册](2026-07-26-ci-failover-runbook.md)的记录。 ## 曾考虑的替代方案 diff --git a/.agents/notes/implemented/process/2026-07-26-ci-failover-runbook.i18n.yaml b/.agents/notes/implemented/process/2026-07-26-ci-failover-runbook.i18n.yaml index ed819bc19e..2dd42d87db 100644 --- a/.agents/notes/implemented/process/2026-07-26-ci-failover-runbook.i18n.yaml +++ b/.agents/notes/implemented/process/2026-07-26-ci-failover-runbook.i18n.yaml @@ -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 .agents/notes/implemented/process/2026-07-26-ci-failover-runbook.md -2026-07-26-ci-failover-runbook.md: 90ef2905bec86911697e552c0c1eac96ea0d3a18 -2026-07-26-ci-failover-runbook.zh.md: 5c8fd0e90ae31e3622ae6b49217591a54b84c351 +2026-07-26-ci-failover-runbook.md: b4522e623ffb76f3fd33d242b21c2d1d9ff2eadf +2026-07-26-ci-failover-runbook.zh.md: 58ba7ffee013d38f06afe097362f5c23f04b8121 diff --git a/.agents/notes/implemented/process/2026-07-26-ci-failover-runbook.md b/.agents/notes/implemented/process/2026-07-26-ci-failover-runbook.md index 90ef2905be..b4522e623f 100644 --- a/.agents/notes/implemented/process/2026-07-26-ci-failover-runbook.md +++ b/.agents/notes/implemented/process/2026-07-26-ci-failover-runbook.md @@ -6,11 +6,11 @@ English | [中文](2026-07-26-ci-failover-runbook.zh.md) ## Problem -The three required Linux worker jobs in [CI](../../../../.github/workflows/ci.yml) (`node 24 / static`, `node 24 / coverage`, `node 24 / snapshots and artifacts`) run on the hosted enterprise 32-core pools; the required verdict job that aggregates them (`all checks passed`) runs on standard `ubuntu-latest`; the independent native Windows job (`windows node 24 / native complete`) runs on the hosted `dsh-windows-2025-16core` larger runner. When the enterprise pools degrade — jobs queue indefinitely or the enterprise labels vanish — every open pull request becomes unmergeable, and the ordinary recovery of merging a fix is itself deadlocked behind the very required checks that cannot run. **Scope: this switch recovers an enterprise Linux-pool outage AND a hosted Windows-pool outage.** The verdict's other required dependencies (`node-compat`, `python-sdk`, `windows`) stay on standard hosted runners by design (the portable boundary); in a broader GitHub-hosted capacity failure that also takes out the standard pools, those dependencies still block `all checks passed`. An outage therefore needs a switch any responder with repository write access can throw without merging anything. +The three required Linux worker jobs in [CI](../../../../.github/workflows/ci.yml) (`node 24 / static`, `node 24 / coverage`, `node 24 / snapshots and artifacts`) run on the hosted enterprise 32-core pools; the required verdict job that aggregates them (`all checks passed`) runs on standard `ubuntu-latest`; the independent native Windows job (`windows node 24 / native complete`) runs on the hosted `dsh-windows-2025-16core` larger runner. When the enterprise pools degrade — jobs queue indefinitely or the enterprise labels vanish — every open pull request becomes unmergeable, and the ordinary recovery of merging a fix is itself deadlocked behind the very required checks that cannot run. **Scope: two independent switches, one per platform.** `DSH_CI_FAILOVER_LINUX` recovers an enterprise Linux-pool outage (the three required Linux workers plus the `all checks passed` verdict); `DSH_CI_FAILOVER_WINDOWS` recovers a hosted Windows-pool outage (the native Windows job). A Linux-pool outage need not retarget the native Windows job and vice versa. The verdict's other required dependencies (`node-compat`, `python-sdk`, `windows`) stay on standard hosted runners by design (the portable boundary); in a broader GitHub-hosted capacity failure that also takes out the standard pools, those dependencies still block `all checks passed`. An outage therefore needs a switch any responder with repository write access can throw without merging anything. ## Decision -Each of the three required Linux worker jobs, the independent native Windows job, and the `all checks passed` verdict job — which would otherwise stay queued on the failed pool even after every worker passed — resolves its runner pool through the `DSH_CI_FAILOVER` repository variable. Unset (normal), they run on the hosted enterprise pools. Set to `selfhosted` by any repository writer, all five retarget onto the in-house self-hosted pools: the Linux jobs and verdict onto the `vm-backup` pool, coverage and snapshot concurrency drop to shared-VM bounds, and the hosted-path pnpm cache restores are skipped; the native Windows job onto the `dsh-win-ci` pool. The switch is writer-manageable repository state, not a merge, so it works while every check is red. The in-house pools' readiness is continuously re-proven by the `serial / linux (self-hosted standby)` and `serial / windows (self-hosted standby)` lanes, which run the complete unsharded aggregates on every master push. +Each of the three required Linux worker jobs, the independent native Windows job, and the `all checks passed` verdict job — which would otherwise stay queued on the failed pool even after every worker passed — resolves its runner pool through a repository variable, and the switch is split by platform so an outage on one platform does not retarget the other. The three Linux workers and the `all checks passed` verdict (whose `needs` are the required Linux workers and which runs on the `vm-backup` pool) resolve through `DSH_CI_FAILOVER_LINUX`; the native Windows job resolves through `DSH_CI_FAILOVER_WINDOWS`. Unset (normal), they run on the hosted enterprise pools. Set to `selfhosted` by any repository writer, the corresponding jobs retarget onto the in-house self-hosted pool: under `DSH_CI_FAILOVER_LINUX`, the Linux jobs and verdict move onto the `vm-backup` pool, coverage and snapshot concurrency drop to shared-VM bounds, and the hosted-path pnpm cache restores are skipped; under `DSH_CI_FAILOVER_WINDOWS`, the native Windows job moves onto the `dsh-win-ci` pool. Each switch is writer-manageable repository state, not a merge, so it works while every check is red. The in-house pools' readiness is continuously re-proven by the `serial / linux (self-hosted standby)` and `serial / windows (self-hosted standby)` lanes, which run the complete unsharded aggregates on every master push. `ci.yml` exempts exactly one event from `cancel-in-progress` (`${{ github.event_name != 'push' }}`), so one master push does not cancel the drill still running from the previous one. Each drill runs its complete unsharded aggregate with one gate worker, which takes longer than the interval between master merges; under unconditional cancellation a drill is superseded before reaching a verdict and the lane yields no readiness evidence for a responder to check. @@ -28,13 +28,15 @@ The decision belongs at workflow level because cancellation applies to the whole ### Switch (any repository writer, ~1 minute, no merge) -1. Repository **Settings → Secrets and variables → Actions → Variables → New repository variable**: name `DSH_CI_FAILOVER`, value `selfhosted`. +The two switches are independent: flip only the one whose platform is degraded. + +1. Repository **Settings → Secrets and variables → Actions → Variables → New repository variable**: name `DSH_CI_FAILOVER_LINUX` (Linux pool outage) or `DSH_CI_FAILOVER_WINDOWS` (Windows pool outage), value `selfhosted`. 2. Retrigger the required jobs so they re-resolve their pool. Jobs already **queued** for the hosted labels do not retarget and cannot be re-run in place, so for the documented indefinite-queue outage, cancel the stuck run and re-run all jobs, or push a new commit; "Re-run failed jobs" only helps once a job has actually failed rather than queued. -3. That is the entire switch. Under failover the workflow also, automatically: drops `DSH_COVERAGE_MAX_WORKERS` to 8 and `DSH_SNAPSHOT_MAX_CONCURRENCY` to 12 (sized for six always-on instances: worst case 6 × 8 = 48 coverage workers on the 64-core VM) (shared-VM contention bounds), and skips the hosted-path pnpm cache restores (the VM's persistent store serves warm installs). +3. That is the entire switch. Under Linux failover the workflow also, automatically: drops `DSH_COVERAGE_MAX_WORKERS` to 8 and `DSH_SNAPSHOT_MAX_CONCURRENCY` to 12 (sized for six always-on instances: worst case 6 × 8 = 48 coverage workers on the 64-core VM) (shared-VM contention bounds), and skips the hosted-path pnpm cache restores (the VM's persistent store serves warm installs). The Windows switch has no such concurrency or cache branches; it only retargets the native Windows job's pool. -#**Dependabot exception.** All five selectors deliberately exclude `dependabot[bot]`: under failover, Dependabot PRs stay queued for the hosted pool rather than executing dependency-supplied code on the persistent VMs. A Dependabot PR that remains queued during an outage is expected behavior, not a failed switch; it completes when the hosted pool recovers. +#**Dependabot exception.** Both switches' selectors deliberately exclude `dependabot[bot]`: under failover, Dependabot PRs stay queued for the hosted pool rather than executing dependency-supplied code on the persistent VMs. A Dependabot PR that remains queued during an outage is expected behavior, not a failed switch; it completes when the hosted pool recovers. -**Who can flip the variable.** GitHub's API lets any collaborator with write access manage repository variables, so the switch is writer-level, not strictly admin-only. In this repository's trust model that is not an escalation: the runner groups admit all workflows of this private, fork-disabled repository (a deliberate trade to make PR-ref failover possible at all), so any writer could already reach the VMs by pushing a branch workflow. The boundary against untrusted code is repository membership; the variable only routes work for members. +**Who can flip the variable.** GitHub's API lets any collaborator with write access manage repository variables, so each switch is writer-level, not strictly admin-only. In this repository's trust model that is not an escalation: the runner groups admit all workflows of this private, fork-disabled repository (a deliberate trade to make PR-ref failover possible at all), so any writer could already reach the VMs by pushing a branch workflow. The boundary against untrusted code is repository membership; the variables only route work for members. ## Capacity during failover @@ -43,18 +45,18 @@ Six always-on instances absorb normal PR traffic (the pool's steady-state load i ### Switch back -Delete the `DSH_CI_FAILOVER` variable (or set it to anything other than `selfhosted`). New runs resolve back to the hosted enterprise pools. Remove any extra instances that were registered during the incident. +Delete the `DSH_CI_FAILOVER_LINUX` or `DSH_CI_FAILOVER_WINDOWS` variable (or set it to anything other than `selfhosted`). New runs resolve back to the hosted enterprise pools. Remove any extra instances that were registered during the incident. ### Trust boundary -The variable is writer-manageable repository state; a pull request event itself can neither set it nor read a different value into effect, and the selector expressions live in workflow definitions. Note that under failover, `pull_request` runs execute the PR merge ref's own workflow definition — the boundary against untrusted code is repository membership (private, forking disabled, Dependabot excluded by the selectors), not the variable. Note on runner-group policy: pinning the runner group to the master-ref workflow is **incompatible** with this failover — the four failover jobs are `pull_request` runs evaluated from PR merge refs, and a master-pinned group leaves them queued (observed live on 2026-07-27; the group was widened to all workflows of this repository to unblock the switch). A stricter runner-side policy therefore costs PR failover; the shipped posture accepts repository-scoped, all-workflow group access. +The variables are writer-manageable repository state; a pull request event itself can neither set them nor read a different value into effect, and the selector expressions live in workflow definitions. Note that under failover, `pull_request` runs execute the PR merge ref's own workflow definition — the boundary against untrusted code is repository membership (private, forking disabled, Dependabot excluded by the selectors), not the variable. Note on runner-group policy: pinning the runner group to the master-ref workflow is **incompatible** with this failover — the five failover jobs are `pull_request` runs evaluated from PR merge refs, and a master-pinned group leaves them queued (observed live on 2026-07-27; the group was widened to all workflows of this repository to unblock the switch). A stricter runner-side policy therefore costs PR failover; the shipped posture accepts repository-scoped, all-workflow group access. ## Alternatives considered **Merge a workflow change to switch pools.** Rejected because the outage that motivates the switch is exactly the state in which no PR can merge: the required checks are the ones failing. A repository variable is writer-manageable state that takes effect on re-run without a merge. -**Keep the self-hosted pool always in the required path.** Rejected because it trades hosted-pool availability for the in-house VM's, moving a single point of failure rather than adding a fallback. The variable keeps the hosted pools primary and the self-hosted pool a proven, one-action standby. +**Keep the self-hosted pool always in the required path.** Rejected because it trades hosted-pool availability for the in-house VM's, moving a single point of failure rather than adding a fallback. The variables keep the hosted pools primary and the self-hosted pools proven, one-action standbys; splitting them by platform means an outage on one platform does not retarget the other. ## Consequences -Recovering from a hosted-pool outage is a single variable (any writer) plus a re-run, with no merge on the critical path. The cost is a second runner topology to keep working: the standby lane exercises it on every master push so the failover target never goes stale, and the concurrency and cache-restore branches in `ci.yml` carry a `selfhosted` leg that must stay in step with the hosted leg. +Recovering from a hosted-pool outage is flipping the affected platform's variable (any writer) plus a re-run, with no merge on the critical path. The cost is a second runner topology per platform to keep working: the standby lanes exercise them on every master push so the failover targets never go stale, and the concurrency and cache-restore branches in `ci.yml` carry a `selfhosted` leg (Linux only) that must stay in step with the hosted leg. Splitting the switch by platform adds one more variable to manage but bounds the blast radius of each switch to the jobs of a single platform. diff --git a/.agents/notes/implemented/process/2026-07-26-ci-failover-runbook.zh.md b/.agents/notes/implemented/process/2026-07-26-ci-failover-runbook.zh.md index 5c8fd0e90a..58ba7ffee0 100644 --- a/.agents/notes/implemented/process/2026-07-26-ci-failover-runbook.zh.md +++ b/.agents/notes/implemented/process/2026-07-26-ci-failover-runbook.zh.md @@ -6,11 +6,11 @@ Status: implemented ## 问题 -[CI](../../../../.github/workflows/ci.yml) 中三个必需的 Linux 工作作业(`node 24 / static`、`node 24 / coverage`、`node 24 / snapshots and artifacts`)运行在托管的企业级 32 核池上;聚合它们的必需判定作业(`all checks passed`)运行在标准 `ubuntu-latest` 上;独立的原生 Windows 作业(`windows node 24 / native complete`)运行在托管的 `dsh-windows-2025-16core` 大型运行器上。当企业池发生故障——作业无限排队或企业标签消失——所有开启的拉取请求都无法合并,而"合并一个修复"这一常规恢复手段本身正被那些无法运行的必需检查死锁。**适用范围:本切换恢复的是企业级 Linux 池故障与托管 Windows 池故障。**判定作业的其余必需依赖(`node-compat`、`python-sdk`、`windows`)按设计留在标准托管运行器上(可移植边界);若更大范围的 GitHub 托管容量故障连标准池一并击倒,这些依赖仍会阻塞 `all checks passed`。因此故障需要一个任何具备仓库写权限的响应者都能在不合并任何代码的情况下触发的开关。 +[CI](../../../../.github/workflows/ci.yml) 中三个必需的 Linux 工作作业(`node 24 / static`、`node 24 / coverage`、`node 24 / snapshots and artifacts`)运行在托管的企业级 32 核池上;聚合它们的必需判定作业(`all checks passed`)运行在标准 `ubuntu-latest` 上;独立的原生 Windows 作业(`windows node 24 / native complete`)运行在托管的 `dsh-windows-2025-16core` 大型运行器上。当企业池发生故障——作业无限排队或企业标签消失——所有开启的拉取请求都无法合并,而"合并一个修复"这一常规恢复手段本身正被那些无法运行的必需检查死锁。**适用范围:两个独立开关,每个平台一个。**`DSH_CI_FAILOVER_LINUX` 恢复企业级 Linux 池故障(三个必需的 Linux 工作作业加 `all checks passed` 判定作业);`DSH_CI_FAILOVER_WINDOWS` 恢复托管 Windows 池故障(原生 Windows 作业)。Linux 池故障无需重定向原生 Windows 作业,反之亦然。判定作业的其余必需依赖(`node-compat`、`python-sdk`、`windows`)按设计留在标准托管运行器上(可移植边界);若更大范围的 GitHub 托管容量故障连标准池一并击倒,这些依赖仍会阻塞 `all checks passed`。因此故障需要一个任何具备仓库写权限的响应者都能在不合并任何代码的情况下触发的开关。 ## 决策 -三个必需的 Linux 工作作业、独立的原生 Windows 作业,以及 `all checks passed` 判定作业(若不随切换,即使全部工作作业通过,它仍会滞留在故障池的队列中)——各自通过仓库变量 `DSH_CI_FAILOVER` 解析运行器池。变量不存在(正常)时它们运行在托管企业池上;由任何具备写权限的协作者设为 `selfhosted` 时,五个作业全部切换到公司自有的自托管池:Linux 作业与判定作业切到 `vm-backup` 池,覆盖率与快照的并发降到共享虚拟机上限,并跳过托管路径的 pnpm 缓存恢复;原生 Windows 作业切到 `dsh-win-ci` 池。这个开关是写者可管理的仓库状态而非一次合并,因此在所有检查都是红色时仍然有效。自有池的就绪状态由 `serial / linux (self-hosted standby)` 与 `serial / windows (self-hosted standby)` 通道持续验证——每次 master 推送都在其上运行完整的未分片聚合流程。 +三个必需的 Linux 工作作业、独立的原生 Windows 作业,以及 `all checks passed` 判定作业(若不随切换,即使全部工作作业通过,它仍会滞留在故障池的队列中)——各自通过仓库变量解析运行器池,且开关按平台拆分,使一个平台的故障不会重定向另一个平台。三个 Linux 工作作业与 `all checks passed` 判定作业(其 `needs` 是必需的 Linux 工作作业,且运行在 `vm-backup` 池上)通过 `DSH_CI_FAILOVER_LINUX` 解析;原生 Windows 作业通过 `DSH_CI_FAILOVER_WINDOWS` 解析。变量不存在(正常)时它们运行在托管企业池上;由任何具备写权限的协作者设为 `selfhosted` 时,对应作业切换到公司自有的自托管池:`DSH_CI_FAILOVER_LINUX` 下,Linux 作业与判定作业切到 `vm-backup` 池,覆盖率与快照的并发降到共享虚拟机上限,并跳过托管路径的 pnpm 缓存恢复;`DSH_CI_FAILOVER_WINDOWS` 下,原生 Windows 作业切到 `dsh-win-ci` 池。每个开关都是写者可管理的仓库状态而非一次合并,因此在所有检查都是红色时仍然有效。自有池的就绪状态由 `serial / linux (self-hosted standby)` 与 `serial / windows (self-hosted standby)` 通道持续验证——每次 master 推送都在其上运行完整的未分片聚合流程。 `ci.yml` 只豁免一个事件不做取消(`${{ github.event_name != 'push' }}`),因此一次 master 推送不会取消上一次推送留下的、仍在运行的演练。每次演练以单门禁工作进程执行完整的未分片聚合流程,耗时长于 master 合并的间隔;在无条件取消下,演练会在得出结论前被后续运行取代,该通道无法产出供响应者查看的就绪证据。 @@ -28,13 +28,15 @@ Status: implemented ### 切换步骤(任何具备写权限的协作者,约 1 分钟,无需合并) -1. 仓库 **Settings → Secrets and variables → Actions → Variables → New repository variable**:名称 `DSH_CI_FAILOVER`,值 `selfhosted`。 +两个开关相互独立:只切换发生故障的那个平台。 + +1. 仓库 **Settings → Secrets and variables → Actions → Variables → New repository variable**:名称 `DSH_CI_FAILOVER_LINUX`(Linux 池故障)或 `DSH_CI_FAILOVER_WINDOWS`(Windows 池故障),值 `selfhosted`。 2. 重新触发必需作业,使其重新解析运行器池。已经为托管标签**排队**的作业不会重定向,也无法原地 re-run,因此对于本手册所述的无限排队故障,应取消卡住的运行并 re-run all jobs,或推送一个新提交;“Re-run failed jobs”只有在作业真正失败(而非仍在排队)时才有用。 -3. 切换到此完成。故障切换状态下工作流还会自动:把 `DSH_COVERAGE_MAX_WORKERS` 降为 8、`DSH_SNAPSHOT_MAX_CONCURRENCY` 降为 12(按 6 个常驻实例定容:最坏情况下,6 × 8 = 48 个覆盖率工作进程运行在 64 核虚拟机上)(共享虚拟机的争抢上限),并跳过托管路径的 pnpm 缓存恢复(虚拟机的持久 store 直接提供热安装)。 +3. 切换到此完成。Linux 故障切换状态下工作流还会自动:把 `DSH_COVERAGE_MAX_WORKERS` 降为 8、`DSH_SNAPSHOT_MAX_CONCURRENCY` 降为 12(按 6 个常驻实例定容:最坏情况下,6 × 8 = 48 个覆盖率工作进程运行在 64 核虚拟机上)(共享虚拟机的争抢上限),并跳过托管路径的 pnpm 缓存恢复(虚拟机的持久 store 直接提供热安装)。Windows 开关没有这类并发或缓存分支;它只重定向原生 Windows 作业的运行器池。 -#**Dependabot 例外。**五个选择器都刻意排除了 `dependabot[bot]`:故障切换期间,Dependabot 拉取请求继续在托管池排队,而不是把依赖项提供的代码放到持久化虚拟机上执行。故障期间 Dependabot PR 持续排队是预期行为而非切换失败;托管池恢复后它会自行完成。 +#**Dependabot 例外。**两个开关的选择器都刻意排除了 `dependabot[bot]`:故障切换期间,Dependabot 拉取请求继续在托管池排队,而不是把依赖项提供的代码放到持久化虚拟机上执行。故障期间 Dependabot PR 持续排队是预期行为而非切换失败;托管池恢复后它会自行完成。 -**谁能扳动这个变量。**GitHub 的 API 允许任何具有写权限的协作者管理仓库变量,因此该开关实际是写者级而非严格的管理员级。在本仓库的信任模型下这并不构成升权:runner group 接纳本私有、禁 fork 仓库的全部工作流(这是让 PR 引用的故障切换得以成立的刻意取舍),因此任何写者本就可以通过推送分支工作流触达这台虚拟机。抵御不可信代码的边界是仓库成员资格;变量只是为成员路由工作。 +**谁能扳动这个变量。**GitHub 的 API 允许任何具有写权限的协作者管理仓库变量,因此每个开关实际是写者级而非严格的管理员级。在本仓库的信任模型下这并不构成升权:runner group 接纳本私有、禁 fork 仓库的全部工作流(这是让 PR 引用的故障切换得以成立的刻意取舍),因此任何写者本就可以通过推送分支工作流触达这台虚拟机。抵御不可信代码的边界是仓库成员资格;变量只是为成员路由工作。 ## 切换期间的容量 @@ -43,18 +45,18 @@ Status: implemented ### 切回 -删除 `DSH_CI_FAILOVER` 变量(或改为 `selfhosted` 以外的任何值),新的运行即解析回托管企业池。若故障期间追加注册过实例,将其移除。 +删除 `DSH_CI_FAILOVER_LINUX` 或 `DSH_CI_FAILOVER_WINDOWS` 变量(或改为 `selfhosted` 以外的任何值),新的运行即解析回托管企业池。若故障期间追加注册过实例,将其移除。 ### 信任边界 -该变量是写者可管理的仓库状态;`pull_request` 事件本身既不能设置它,也不能让不同的值生效,选择器表达式存在于工作流定义中。需要注意:故障切换期间,`pull_request` 运行执行的是 PR merge 引用自带的工作流定义——抵御不可信代码的边界是仓库成员资格(私有、禁 fork、选择器排除 Dependabot),而非该变量。关于 runner group 策略的说明:把 runner group 绑定到 master 引用的工作流与本故障切换机制**不兼容**——四个故障切换作业是从 PR merge 引用求值的 `pull_request` 运行,master 绑定的组会让它们持续排队(2026-07-27 实际故障中亲历;当时将组放宽为本仓库全部工作流才疏通了切换)。更严格的运行器侧策略以牺牲 PR 故障切换为代价;当前采用的形态是仓库范围、全工作流的组访问。 +这些变量是写者可管理的仓库状态;`pull_request` 事件本身既不能设置它们,也不能让不同的值生效,选择器表达式存在于工作流定义中。需要注意:故障切换期间,`pull_request` 运行执行的是 PR merge 引用自带的工作流定义——抵御不可信代码的边界是仓库成员资格(私有、禁 fork、选择器排除 Dependabot),而非该变量。关于 runner group 策略的说明:把 runner group 绑定到 master 引用的工作流与本故障切换机制**不兼容**——五个故障切换作业是从 PR merge 引用求值的 `pull_request` 运行,master 绑定的组会让它们持续排队(2026-07-27 实际故障中亲历;当时将组放宽为本仓库全部工作流才疏通了切换)。更严格的运行器侧策略以牺牲 PR 故障切换为代价;当前采用的形态是仓库范围、全工作流的组访问。 ## 曾考虑的替代方案 **通过合并一次工作流改动来切换池。** 否决,因为触发切换的故障状态恰恰是任何 PR 都无法合并的状态:必需检查正是失败的那些。仓库变量是写者可管理的状态,重跑即生效,无需合并。 -**让自托管池长期处于必需路径中。** 否决,因为这是拿托管池的可用性去换自有虚拟机的可用性,只是搬移了单点故障而非增加回退。该变量让托管池保持主路径,自托管池作为一个经过验证、一步即可启用的热备。 +**让自托管池长期处于必需路径中。** 否决,因为这是拿托管池的可用性去换自有虚拟机的可用性,只是搬移了单点故障而非增加回退。这些变量让托管池保持主路径,自托管池作为一个经过验证、一步即可启用的热备;按平台拆分意味着一个平台的故障不会重定向另一个平台。 ## 后果 -从托管池故障中恢复只需一个变量(任何写者可设)加一次重跑,关键路径上没有合并。代价是要维护第二套运行器拓扑:热备通道在每次 master 推送时都运行它,避免故障切换目标变得陈旧;而 `ci.yml` 中的并发与缓存恢复分支带有一条 `selfhosted` 支路,必须与托管支路保持同步。 +从托管池故障中恢复只需切换受影响平台的变量(任何写者可设)加一次重跑,关键路径上没有合并。代价是每个平台都要维护第二套运行器拓扑:热备通道在每次 master 推送时都运行它们,避免故障切换目标变得陈旧;而 `ci.yml` 中的并发与缓存恢复分支带有一条 `selfhosted` 支路(仅 Linux),必须与托管支路保持同步。按平台拆分开关多了一个需要管理的变量,但把每个开关的影响范围限定在单个平台的作业上。 diff --git a/.agents/notes/implemented/process/2026-08-06-in-repository-landlock-release.i18n.yaml b/.agents/notes/implemented/process/2026-08-06-in-repository-landlock-release.i18n.yaml index 91ddfe4f6c..2c58cd8d43 100644 --- a/.agents/notes/implemented/process/2026-08-06-in-repository-landlock-release.i18n.yaml +++ b/.agents/notes/implemented/process/2026-08-06-in-repository-landlock-release.i18n.yaml @@ -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 .agents/notes/implemented/process/2026-08-06-in-repository-landlock-release.md -2026-08-06-in-repository-landlock-release.md: 1540cebbf5a3dffa20003c70ffcec426aeca104b -2026-08-06-in-repository-landlock-release.zh.md: 5defa5f3ca83e5a420d0c11857ad4cf46555450b +2026-08-06-in-repository-landlock-release.md: 82b21cc0c30338ad11583797f011794b8dbcc90c +2026-08-06-in-repository-landlock-release.zh.md: 7ebd69f505c3b071216eb23f5eed35c392e6f844 diff --git a/.agents/notes/implemented/process/2026-08-06-in-repository-landlock-release.md b/.agents/notes/implemented/process/2026-08-06-in-repository-landlock-release.md index 1540cebbf5..82b21cc0c3 100644 --- a/.agents/notes/implemented/process/2026-08-06-in-repository-landlock-release.md +++ b/.agents/notes/implemented/process/2026-08-06-in-repository-landlock-release.md @@ -18,7 +18,7 @@ The consolidation must preserve platform selection. The public distribution is d `native/landlock-run` and `native/landlock-run/packages/*` belong to the repository's root pnpm workspace and use the root `pnpm-lock.yaml`. Harness consumers declare `@deepseek-ai/node-addon-landlock-run` with `workspace:*`, so development, type checking, builds, and pull-request tests resolve the entry package from the same checkout. The root TypeScript project graph builds that entry package before consumers, and the repository cleaner owns its direct `lib/` output. -The public npm boundary is three organization-owned packages with one launcher-family version: `@deepseek-ai/node-addon-landlock-run`, `@deepseek-ai/node-addon-landlock-run-linux-x64`, and `@deepseek-ai/node-addon-landlock-run-linux-arm64`. The entry package retains both platform packages as `optionalDependencies`; their `os` and `cpu` manifest fields let npm install only the compatible package. Repository constraints allow public publication only for those three names, require `publishConfig.access: public`, and require their versions to match the private launcher workspace root. The former unscoped names are not release targets of this repository; other repository workspaces remain private under the existing constraint. +The public npm boundary is three organization-owned packages with one launcher-family version: `@deepseek-ai/node-addon-landlock-run`, `@deepseek-ai/node-addon-landlock-run-linux-x64`, and `@deepseek-ai/node-addon-landlock-run-linux-arm64`. The entry package retains both platform packages as `optionalDependencies`; their `os` and `cpu` manifest fields let npm install only the compatible package. Repository constraints require `publishConfig.access: public` for those three names and require their versions to match the private launcher workspace root. The former unscoped names are not release targets of this repository. These three are no longer the only public packages: the [per-sequence access decision](2026-08-13-public-vendor-and-native-sequences.md) publishes the nine vendored framework packages publicly as well, while the dsh family stays restricted. The main repository owns both native CI and publication. `Landlock Run` runs for relevant pull requests and `master` pushes and builds each platform on its matching native runner. The manually dispatched `Landlock Run Release` workflow builds both platform binaries, transfers them as workflow artifacts, assembles and verifies the complete package family, packs immutable npm tarballs, installs and exercises those tarballs, and only then permits the protected publish job. Platform tarballs publish before the entry tarball that optionally depends on them. Publication uses `landlock-run-vX.Y.Z` tags so launcher releases cannot collide with other release families in the monorepo; prereleases use the npm `next` dist-tag. diff --git a/.agents/notes/implemented/process/2026-08-06-in-repository-landlock-release.zh.md b/.agents/notes/implemented/process/2026-08-06-in-repository-landlock-release.zh.md index 5defa5f3ca..7ebd69f505 100644 --- a/.agents/notes/implemented/process/2026-08-06-in-repository-landlock-release.zh.md +++ b/.agents/notes/implemented/process/2026-08-06-in-repository-landlock-release.zh.md @@ -18,7 +18,7 @@ Status: implemented `native/landlock-run` 和 `native/landlock-run/packages/*` 属于仓库根 pnpm workspace,并使用根 `pnpm-lock.yaml`。Harness 消费方将 `@deepseek-ai/node-addon-landlock-run` 声明为 `workspace:*`,因此开发、类型检查、构建和 PR 测试都会从同一个 checkout 解析入口包。根 TypeScript 项目图会先构建该入口包,再构建消费方;仓库清理器负责清理其直接生成的 `lib/` 输出目录。 -公开 npm 分发边界由 3 个归组织所有的包组成,它们共用一个启动器包家族版本:`@deepseek-ai/node-addon-landlock-run`、`@deepseek-ai/node-addon-landlock-run-linux-x64` 和 `@deepseek-ai/node-addon-landlock-run-linux-arm64`。入口包继续通过 `optionalDependencies` 声明两个平台包;它们在 manifest(元数据清单)中的 `os` 和 `cpu` 字段让 npm 只安装兼容的包。仓库约束只允许公开发布这 3 个包名,要求设置 `publishConfig.access: public`,并要求其版本与私有启动器 workspace 根包一致。原先的非 scoped 包名不属于本仓库的发布目标;仓库中的其他 workspace 仍受现有约束保护,保持私有状态。 +公开 npm 分发边界由 3 个归组织所有的包组成,它们共用一个启动器包家族版本:`@deepseek-ai/node-addon-landlock-run`、`@deepseek-ai/node-addon-landlock-run-linux-x64` 和 `@deepseek-ai/node-addon-landlock-run-linux-arm64`。入口包继续通过 `optionalDependencies` 声明两个平台包;它们在 manifest(元数据清单)中的 `os` 和 `cpu` 字段让 npm 只安装兼容的包。仓库约束要求这 3 个包名设置 `publishConfig.access: public`,并要求其版本与私有启动器 workspace 根包一致。原先的非 scoped 包名不属于本仓库的发布目标。这 3 个已不再是唯一的公开包:[按序列区分 access 的决策](2026-08-13-public-vendor-and-native-sequences.md)让 vendored 框架九包也公开发布,而 dsh 族保持受限。 主仓库同时负责原生 CI 和发布。`Landlock Run` 会为相关 PR 和 `master` 推送运行,并在各自匹配的原生 runner 上构建每个平台包。手动触发的 `Landlock Run Release` 工作流会构建两个平台的二进制文件,将其作为工作流产物传递,组装并验证完整的包家族,打包出内容不可变的 npm tarball,安装并实际运行这些 tarball,之后才允许受保护的发布作业执行。发布顺序是平台 tarball 在前,最后发布将它们列为可选依赖的入口 tarball。发布使用 `landlock-run-vX.Y.Z` tag,避免启动器版本与 monorepo 中其他发布家族发生冲突;预发布版本使用 npm 的 `next` dist-tag。 diff --git a/.agents/notes/implemented/process/2026-08-08-native-windows-pull-request-ci.i18n.yaml b/.agents/notes/implemented/process/2026-08-08-native-windows-pull-request-ci.i18n.yaml index dcdbff1208..311f39f0ff 100644 --- a/.agents/notes/implemented/process/2026-08-08-native-windows-pull-request-ci.i18n.yaml +++ b/.agents/notes/implemented/process/2026-08-08-native-windows-pull-request-ci.i18n.yaml @@ -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 .agents/notes/implemented/process/2026-08-08-native-windows-pull-request-ci.md -2026-08-08-native-windows-pull-request-ci.md: 33fbf1ae378112b4fd82633a77afa52056d93d98 -2026-08-08-native-windows-pull-request-ci.zh.md: 552e5cd3129011198fe442ba747cf2fdb7d97365 +2026-08-08-native-windows-pull-request-ci.md: d7db73b2049ae2d08f8996bcfd5b54fa15901478 +2026-08-08-native-windows-pull-request-ci.zh.md: 474b7f71aca8fbb5e0082fd2e4faf8e462bf0c0f diff --git a/.agents/notes/implemented/process/2026-08-08-native-windows-pull-request-ci.md b/.agents/notes/implemented/process/2026-08-08-native-windows-pull-request-ci.md index 33fbf1ae37..d7db73b204 100644 --- a/.agents/notes/implemented/process/2026-08-08-native-windows-pull-request-ci.md +++ b/.agents/notes/implemented/process/2026-08-08-native-windows-pull-request-ci.md @@ -14,7 +14,7 @@ A coverage audit found that stale branch state had restored temporary exclusions The required `windows` job in [ci.yml](../../../../.github/workflows/ci.yml) remains `windows node 24 / wine blocking` on `ubuntu-latest`. It retains the checksum-verified Windows Node, Wine apt and pnpm caches, a hoisted install confined to a workspace snapshot, and the [shared Wine gate script](../../../../scripts/wine-windows-gates.sh) that runs the workspace build and production site. Node distribution transfers use bounded retries; when nodejs.org stalls on the large archive, a range-capable transport mirror resumes the same bytes, but nodejs.org remains the version and SHA-256 authority and the archive is never promoted before that checksum passes. The stable `windows` job id remains a dependency of `all checks passed`. The [archived Wine experiment](../../archived/process/2026-07-27-wine-windows-gates-experiment.md) preserves its measured trade-offs, while this note owns the current dual topology. -Every pull request also starts an ordinary independent `windows-native` job named `windows node 24 / native complete` on the organization-owned `dsh-windows-2025-16core` runner. It enables Developer Mode for workspace symlinks, provisions the repository-pinned pnpm through `pnpm/action-setup`, performs an immutable install without a transferred store archive, and runs `pnpm run check:ci:windows-complete` under native PowerShell. A 60-minute timeout bounds a stuck gate without treating the measured performance target as a correctness deadline. +Every pull request also starts an ordinary independent `windows-native` job named `windows node 24 / native complete` on the organization-owned `dsh-windows-2025-16core` runner. It enables Developer Mode for workspace symlinks, provisions the repository-pinned pnpm through `pnpm/action-setup`, performs an immutable install without a transferred store archive, and runs `pnpm run check:ci:windows-complete` under native PowerShell. A 120-minute timeout bounds a stuck gate without treating the measured performance target as a correctness deadline. The native job is deliberately absent from `all-checks-passed.needs` and does not use `continue-on-error`: the aggregate neither waits for it nor changes conclusion because of it, while the job retains its own unmasked result. Workspace build, production-site, and 100%-per-file coverage failures make the native job fail. The broader static, documentation, package, and built-artifact portability inventory remains observational. Linux remains the owner of duplicate lint and snapshot enforcement, while native Windows independently enforces supported-source coverage. diff --git a/.agents/notes/implemented/process/2026-08-08-native-windows-pull-request-ci.zh.md b/.agents/notes/implemented/process/2026-08-08-native-windows-pull-request-ci.zh.md index 552e5cd312..474b7f71ac 100644 --- a/.agents/notes/implemented/process/2026-08-08-native-windows-pull-request-ci.zh.md +++ b/.agents/notes/implemented/process/2026-08-08-native-windows-pull-request-ci.zh.md @@ -14,7 +14,7 @@ Status: implemented [ci.yml](../../../../.github/workflows/ci.yml) 中必需的 `windows` 作业仍是在 `ubuntu-latest` 上运行的 `windows node 24 / wine blocking`。它保留经过校验和验证的 Windows Node、Wine apt 与 pnpm 缓存、仅限工作区快照的 hoisted 安装,以及运行工作区构建与生产网站的[共享 Wine 门禁脚本](../../../../scripts/wine-windows-gates.sh)。Node 分发文件传输采用有界重试;nodejs.org 的大文件传输停滞时,由支持范围请求的传输镜像续传相同字节,但版本和 SHA-256 权威仍属于 nodejs.org,归档通过该校验前绝不会投入使用。稳定的 `windows` 作业 ID 仍是 `all checks passed` 的依赖项。[已归档的 Wine 实验](../../archived/process/2026-07-27-wine-windows-gates-experiment.md)保留其实测取舍,而本文负责当前双通道拓扑。 -每个拉取请求还会在组织自有的 `dsh-windows-2025-16core` 运行器上启动一个常规且独立的 `windows-native` 作业,名称为 `windows node 24 / native complete`。该作业为工作区符号链接启用开发人员模式,通过 `pnpm/action-setup` 提供仓库固定版本的 pnpm,在不传输 store 归档的情况下执行不可变安装,并在原生 PowerShell 下运行 `pnpm run check:ci:windows-complete`。门禁卡住时,60 分钟超时会为其设定上限,同时不把实测性能目标当作正确性截止时间。 +每个拉取请求还会在组织自有的 `dsh-windows-2025-16core` 运行器上启动一个常规且独立的 `windows-native` 作业,名称为 `windows node 24 / native complete`。该作业为工作区符号链接启用开发人员模式,通过 `pnpm/action-setup` 提供仓库固定版本的 pnpm,在不传输 store 归档的情况下执行不可变安装,并在原生 PowerShell 下运行 `pnpm run check:ci:windows-complete`。门禁卡住时,120 分钟超时会为其设定上限,同时不把实测性能目标当作正确性截止时间。 原生作业被刻意排除在 `all-checks-passed.needs` 之外,且不使用 `continue-on-error`:聚合流程既不等待它,也不会因它改变结论;该作业则保留自身未被掩盖的结果。工作区构建、生产网站和逐文件 100% 覆盖率检查失败会使原生作业失败。更广泛的静态检查、文档、包和构建产物可移植性清单仍作为观测项报告。重复的 lint 与快照强制检查仍由 Linux 负责,原生 Windows 则独立强制执行受支持源码覆盖率。 diff --git a/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.i18n.yaml b/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.i18n.yaml index 9f147f34bb..851f0e9d2d 100644 --- a/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.i18n.yaml +++ b/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.i18n.yaml @@ -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 .agents/notes/implemented/process/2026-08-10-npm-release-sequences.md -2026-08-10-npm-release-sequences.md: 13f343911b6d684ec8738b2245ceae8d848e2f0c -2026-08-10-npm-release-sequences.zh.md: 4116b74b54e84d33df29fd0ab9169f8d38d5514d +2026-08-10-npm-release-sequences.md: d8495f158482d5d6e06a1752a096d1e9200b6070 +2026-08-10-npm-release-sequences.zh.md: 24b466f6b7b10d31ac2e025da6e12ec3c91c7548 diff --git a/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.md b/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.md index 13f343911b..d8495f1584 100644 --- a/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.md +++ b/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.md @@ -26,7 +26,7 @@ Two hard blockers sat in the way. All 217 workspace manifests set `private: true | vendored framework | the nine `vendor/*` packages | each package on its own version line | `vendor--v` (one per package) | `release-vendor.yml` | | native | `native/landlock-run/packages/*` | its own `0.0.x` | `landlock-run-v` | `landlock-run-release.yml` | -All three publish privately to the `@deepseek-ai` scope on npmjs.com. `publishConfig.access` in each manifest is `restricted` and no workflow passes `--access`, because a command-line flag overrides the manifest. +All three publish to the `@deepseek-ai` scope on npmjs.com, and access is per sequence rather than per scope: the vendored framework and the native packages are `public`, the dsh family is `restricted` ([rationale](2026-08-13-public-vendor-and-native-sequences.md)). No publish path passes `--access`, because one flag cannot serve sequences that disagree and would override the manifest that owns the level. ### Versions land in the repository from a local command; CI only checks and uploads @@ -70,12 +70,24 @@ Publication runs only from GitHub Actions; there is no local publication path. P The third state catches code that changed without a version bump. The first two provide idempotence — re-running publish over one artifact republishes nothing and needs no manual selection of packages. The same rule resolves the tension between one vendor release carrying several tags and a workflow that can only run from one ref: the workflow never infers which packages to publish from the tag it ran from. +All three sequences decide this way, including the native one: it publishes through its own script rather than a shell loop, because a loop of bare `npm publish` calls cannot be retried — the registry answers a repeat of an existing version permanently, so one failure partway through left no way forward. + +Two registry behaviours shape how a publish is attempted. Writes are spaced by at least two seconds and retried with a backoff, because publishing several packages back to back outruns the registry's own processing and earns `E409 Failed to save packument`. And every retry re-reads the registry first: a reported failure can answer a write that landed anyway, so a version that now exists with this tarball's integrity counts as published rather than as a version to place again. + ### Workspace-internal references use the `workspace:` protocol Every reference to a workspace member uses `workspace:^`, so `pnpm pack` substitutes a range matching the target version: sibling `peerDependencies` follow the family version, and a reference to a vendored package follows that package's own line. The Landlock platform packages keep `workspace:*`, which publishes the exact version, because a platform package and its entry must agree exactly. `scripts/check-workspace-constraints.ts` requires the protocol, so a new package cannot reintroduce a hand-written range; the invariant-companion rule requires `workspace:^` for `@deepseek-ai/dsh-invariants` for the same reason. +### An optional dependency is never loaded at module scope + +A dependency in `optionalDependencies`, or a peer carrying `peerDependenciesMeta..optional`, may be absent from an installed tree — that absence is the whole promise of "optional". A static import is evaluated when the importing module loads, so one absent package stops being "this capability is unavailable" and becomes a load failure for everything that reaches the importing module. The failure appears only in an installed tree missing that package, and no test here constructs one: a workspace install always has every package, so the unit tests, the snapshots, and the packed-install probe all pass while the published package is broken for the consumer who declined the optional peer. + +[`verify-optional-dependency-imports`](../../../../scripts/verify-optional-dependency-imports.ts) closes that hole. It reads each package's own manifest for what that package allows to be absent, then scans the files that ship — `packages/*/*/src/` and `apps/*/src/` — across both compiler faces. `vendor/` is out of scope, as pinned upstream source under the [vendoring policy](../../../../vendor/README.md). Value-versus-type is decided against a bound Program rather than the import syntax, because `verbatimModuleSyntax` is off: the compiler already erases an import whose bindings resolve to types, so `import type {}`, `import {}`, an inline `type` specifier, and a named binding that resolves to a type all emit nothing and are allowed, while a bare import, a value binding, and a star re-export are kept and rejected. Only the type phase erases an import: `import defer` still resolves and links its module, deferring evaluation alone, so the gate counts it as a load. + +A violation names the package, the declaration that made it optional, and the way out in order — import it as a type, which is all that declaration merging needs, or restructure so module scope does not need the package. A dynamic `import()` only moves the failure to first use, so it belongs to a caller that genuinely requires the package and handles its absence; reaching for it is a sign the dependency is not optional, and the gate does not offer it as the remedy. + ### Release family objects The entity in this domain is a **release family**: a set of packages sharing one version baseline and tag naming that publishes as a unit. Adding a family means adding a subclass and a workflow lane, not changing the core. @@ -84,9 +96,9 @@ The entity in this domain is a **release family**: a set of packages sharing one |---|---| | `ReleaseFamily` | a family's identity: member discovery, version baseline, tag prefix, packed-payload rule, installed entry | | `ReleaseMember` | one publishable package: directory, name, version, manifest | -| `publishOrder` | topological order over runtime dependencies, ties broken by package name; a cycle is reported rather than resolved arbitrarily | +| `publishOrder` | topological order over the sections npm installs plus peer declarations, ties broken by package name; a cycle among installed dependencies is reported rather than resolved arbitrarily, and a peer edge no order can honour is dropped and named | | `pack` | packs a whole family into one directory and records the upload order | -| `verify` | the family's version baseline, and — when publishing — that the run comes from that family's tag and its members are publishable | +| `verify` | the family's version baseline, the publish order it prints in full, and — when publishing — that the run comes from that family's tag and its members are publishable | | `verify-packed-install` | installs the tarballs of one or more pack directories into a throwaway consumer and drives the installed executable | | `publish` | the three registry states above | | `process` / `tarball` | the one home for spawning commands and for reading a packed tarball, including the entry guard that keeps every script importable | @@ -107,12 +119,12 @@ The verification also packs the Landlock entry, which `dsh-sandbox-local` declar | Item | Content | |---|---| -| release-set manifests | `private: true` removed; `publishConfig.access: restricted` and `repository` with each package's `directory` added | +| release-set manifests | `private: true` removed; `publishConfig.access` per sequence and `repository` with each package's `directory` added | | release-set boundary | every member of `packages/*/*`, `apps/*`, and `vendor/*` | | dependency protocol | workspace-internal references are `workspace:^`, with `check-workspace-constraints.ts` and the invariant-companion rule requiring it | | root `AGENTS.md` | the convention that vendored packages are `private: true` no longer holds | | `vendor/README.md` | records `src` joining `cordis`'s `files` as a local modification | -| the three native packages | `publishConfig.access: restricted`, and their workflow no longer passes `--access` | +| the three native packages | `publishConfig.access: public`, and their workflow passes no `--access` | ### Relationship to the earlier proposal diff --git a/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.zh.md b/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.zh.md index 4116b74b54..24b466f6b7 100644 --- a/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.zh.md +++ b/.agents/notes/implemented/process/2026-08-10-npm-release-sequences.zh.md @@ -26,7 +26,7 @@ Status: implemented | vendored framework | `vendor/*` 九个包 | 每包各自一条版本线 | `vendor-<包名>-v<版本>`(每包一个) | `release-vendor.yml` | | native | `native/landlock-run/packages/*` | 自己的 `0.0.x` | `landlock-run-v<版本>` | `landlock-run-release.yml` | -三组一律发到 npmjs.com 的 `@deepseek-ai` scope 下的私有包。每个 manifest 的 `publishConfig.access` 都是 `restricted`,且没有任何 workflow 传 `--access`——命令行选项会覆盖 manifest。 +三组一律发到 npmjs.com 的 `@deepseek-ai` scope,且 access 按序列而非按 scope 区分:vendored 框架与 native 包是 `public`,dsh 族是 `restricted`([理由](2026-08-13-public-vendor-and-native-sequences.md))。没有任何发布路径传 `--access`——一个选项无法服务级别互不相同的序列,且会覆盖真正拥有该级别的 manifest。 ### 版本由本地命令写进仓库,CI 只核对与上传 @@ -70,12 +70,24 @@ tag 只是 commit 指针,不是发布成功的证明。bump 会向 registry 第三态拦住「改了代码却没 bump 版本」。前两态给出幂等——同一个 artifact 重跑 publish 不会重复发布,也不需要人工挑拣包。同一条规则还解决了「一次 vendor 发布携带多个 tag,而 workflow 只能从一个 ref 触发」的矛盾:workflow 从不从触发它的 tag 去推断该发哪些包。 +三条序列都按这套判定,native 也在内:它通过自己的脚本发布,而不是 shell 循环——一串裸 `npm publish` 无法重试,registry 对「重发已存在的版本」的回答是永久失败,因此中途失败一次就没有前路了。 + +registry 的两个行为决定了「怎么尝试一次发布」。写入之间至少间隔两秒并带退避重试,因为连续背靠背发多个包会超出 registry 自身的处理速度,换来 `E409 Failed to save packument`。而每次重试都先重查 registry:报出来的失败可能对应一次其实已经落地的写入,所以「该版本现在存在且 integrity 与本 tarball 相同」算作已发布,而不是又一个待放置的版本。 + ### workspace 内部引用走 `workspace:` 协议 所有指向 workspace 成员的引用都用 `workspace:^`,由 `pnpm pack` 替换成匹配目标版本的范围:兄弟包的 `peerDependencies` 跟随族版本,指向 vendored 包的引用跟随那个包自己的版本线。Landlock 平台包保留 `workspace:*`(发布成精确版本),因为平台包与它的入口必须版本完全一致。 `scripts/check-workspace-constraints.ts` 要求这个协议,所以新包无法再引入硬写的范围;同理,invariant companion 规则要求 `@deepseek-ai/dsh-invariants` 用 `workspace:^`。 +### optional 依赖绝不在模块作用域被加载 + +`optionalDependencies` 里的依赖,或带 `peerDependenciesMeta..optional` 的 peer,在安装出来的树里可以不存在——这份「可以不存在」正是 optional 的全部承诺。而静态 import 在引入方模块加载时就求值,于是一个缺失的包不再表现为「这个能力不可用」,而是变成所有能走到该模块的代码的加载失败。这种失败只在「缺了该包的安装树」里出现,而本仓没有任何测试构造这种树:workspace 安装总是把每个包都装上,所以单测、快照、打包安装探针全都会过,而那个拒绝了这个 optional peer 的消费者拿到的却是坏的包。 + +[`verify-optional-dependency-imports`](../../../../scripts/verify-optional-dependency-imports.ts) 堵掉这个洞。它从每个包自己的 manifest 读取「这个包允许谁缺失」,再扫描会发布出去的文件——`packages/*/*/src/` 与 `apps/*/src/`——且两个编译门面各扫一遍。`vendor/` 不在范围内,那是[受 vendoring 政策管辖](../../../../vendor/README.md)的固定上游源码。值与类型的判定对着绑定好的 Program 做,而不是看 import 写法,因为 `verbatimModuleSyntax` 是关的:编译器本来就会消除绑定解析为类型的 import,所以 `import type {}`、`import {}`、内联 `type` 说明符、以及解析为类型的具名绑定都不产生产物、一律放行,而裸 import、值绑定、星号 re-export 会被保留、一律报错。只有 type 相位会消除 import:`import defer` 仍然解析并链接它的模块,只推迟求值,所以门禁把它算作一次加载。 + +报错会点名这个包、点名是哪条声明把它标成 optional 的,并按顺序给出出路——把它作为类型引入(声明合并需要的仅此而已),或者调整写法让模块作用域不再需要这个包。动态 `import()` 只是把失败推迟到首次使用,它属于那种确实需要这个包、并且自己处理缺失的调用方;会想到它,往往说明这个依赖并不 optional,所以门禁不把它作为解法给出。 + ### 发布族对象 这个领域里的实体是**发布族**:一组共享版本基线与 tag 命名、可整体发布的包。新增一族等于加一个子类和一条 workflow lane,不改核心。 @@ -84,9 +96,9 @@ tag 只是 commit 指针,不是发布成功的证明。bump 会向 registry |---|---| | `ReleaseFamily` | 一族的身份:成员发现、版本基线、tag 前缀、打包 payload 规则、已安装入口 | | `ReleaseMember` | 一个可发布包:目录、包名、版本、manifest | -| `publishOrder` | 按运行时依赖的拓扑序,同层按包名排;遇到环是报错而不是随意定序 | +| `publishOrder` | 按 npm 会安装的依赖段加 peer 声明做拓扑序,同层按包名排;安装依赖成环是报错而不是随意定序,任何排不进去的 peer 边被丢弃并点名 | | `pack` | 把整族打进一个目录并记录上传顺序 | -| `verify` | 族的版本基线;发布时还要求本次运行来自该族的 tag、且成员可发布 | +| `verify` | 族的版本基线、完整打印出来的发布顺序;发布时还要求本次运行来自该族的 tag、且成员可发布 | | `verify-packed-install` | 把一个或多个 pack 目录的 tarball 装进一次性 consumer,并驱动已安装的可执行入口 | | `publish` | 上面那三态 | | `process` / `tarball` | 启动命令、读取打包 tarball 的唯一正家,其中的入口守卫让每个脚本都可被 import | @@ -107,12 +119,12 @@ dsh 的验证会一并安装 vendored 族的 pack 产物。harness 的包把 ven | 项 | 内容 | |---|---| -| 发布集 manifest | 去掉 `private: true`;补 `publishConfig.access: restricted` 与带各自 `directory` 的 `repository` | +| 发布集 manifest | 去掉 `private: true`;按序列补 `publishConfig.access` 与带各自 `directory` 的 `repository` | | 发布集边界 | `packages/*/*`、`apps/*`、`vendor/*` 的全部成员 | | 依赖协议 | workspace 内部引用为 `workspace:^`,由 `check-workspace-constraints.ts` 与 invariant companion 规则强制 | | 根 `AGENTS.md` | 「vendored 包是 `private: true`」这条约定不再成立 | | `vendor/README.md` | 记录「`src` 加入 `cordis` 的 `files`」这条本地修改 | -| native 三包 | `publishConfig.access: restricted`,且其 workflow 不再传 `--access` | +| native 三包 | `publishConfig.access: public`,且其 workflow 不传 `--access` | ### 与先前提案的关系 diff --git a/.agents/notes/implemented/process/2026-08-13-public-vendor-and-native-sequences.i18n.yaml b/.agents/notes/implemented/process/2026-08-13-public-vendor-and-native-sequences.i18n.yaml new file mode 100644 index 0000000000..07a3e279de --- /dev/null +++ b/.agents/notes/implemented/process/2026-08-13-public-vendor-and-native-sequences.i18n.yaml @@ -0,0 +1,6 @@ +# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each +# 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 .agents/notes/implemented/process/2026-08-13-public-vendor-and-native-sequences.md +2026-08-13-public-vendor-and-native-sequences.md: ada7c3bcbe5feb288d67fe8e7ee7204dda6b4597 +2026-08-13-public-vendor-and-native-sequences.zh.md: 1f687d1134baf58c59f5cf6014e265b24a38042f diff --git a/.agents/notes/implemented/process/2026-08-13-public-vendor-and-native-sequences.md b/.agents/notes/implemented/process/2026-08-13-public-vendor-and-native-sequences.md new file mode 100644 index 0000000000..ada7c3bcbe --- /dev/null +++ b/.agents/notes/implemented/process/2026-08-13-public-vendor-and-native-sequences.md @@ -0,0 +1,45 @@ +# Agent Note: npm access per release sequence: the vendored framework and the native packages publish publicly + +Status: implemented + +English | [中文](2026-08-13-public-vendor-and-native-sequences.zh.md) + +## Problem + +The [three release sequences](2026-08-10-npm-release-sequences.md) shipped with `publishConfig.access: restricted`, so every package published to the `@deepseek-ai` scope was visible only inside the organization. Five rehearsal publications ran that way, through `dsh@0.0.1-rc.5`, `vendor *-rc.4`, and `landlock-run@0.0.1`. + +A restricted dependency is what actually blocks a public consumer. Every harness package declares the vendored framework as a `peerDependency`, and `dsh-sandbox-local` declares the Landlock entry as a `dependency`. A public package that requires a restricted one cannot be installed by anyone outside the organization, so those two sequences have to be public before the dsh family can be — and while the dsh family is still restricted, they are the only two whose artifacts an outside consumer would need to resolve. + +## Decision + +Access is a property of each release sequence, not of the scope: + +| Sequence | Members | `publishConfig.access` | +|---|---|---| +| vendored framework | the nine `vendor/*` packages | `public` | +| native | the three `native/landlock-run/packages/*` packages | `public` | +| dsh | `packages/*/*` + `apps/*` (221 members) | `restricted` | + +`check-workspace-constraints.ts` holds every manifest to its own sequence's level, which is what stops the scope from drifting: a new `vendor/*` package left at `restricted`, or a dsh member flipped to `public`, fails the workspace constraints. + +**No publish path passes `--access`.** A single flag cannot serve sequences that disagree, and a flag overrides the manifest that owns the fact — so `publish.ts` passes none, and the native workflow continues to pass none. Each packed manifest decides. + +Harness consumers reference the Landlock entry as `workspace:^` rather than `workspace:*`, so a published harness package accepts the entry's patch and minor releases instead of pinning one exact version. The entry keeps `workspace:*` for its two platform packages, where the binary must match the entry version exactly. + +Access is a property of the package, not of a version: the twelve packages already published as restricted — `landlock-run@0.0.1` and the vendored `*-rc.*` versions — become world-readable at their next publication. + +## Alternatives considered + +**Flip the whole scope public at once.** Rejected for now: it would make the next dsh release public as a side effect of a manifest change rather than a deliberate release decision. Opening the two dependency sequences first is the order that keeps every published package installable at each step, and it is the precondition for opening dsh whenever that is decided. + +**Keep everything restricted and grant a read-only team instead.** `npm access grant read-only ` is per-package with no scope wildcard, so covering the set means one grant per package plus a standing reconciliation job for every package added afterwards. It also only reaches organization members, which does not serve an installable public artifact. + +**Publish public from the publish path instead of the manifests.** Impossible for a mixed scope — one `--access` flag cannot express two levels — and it would override the manifest that the workspace constraint already checks. + +## Consequences + +- **The twelve packages are public from their next publication onward, and that is not cleanly reversible.** Returning to a restricted scope requires a paid plan plus per-package `npm access set status=private`, and anything already downloaded or mirrored stays out. +- **`@deepseek-ai/dsh` is still not installable from outside the organization.** Its manifests stay `restricted`; what changed is that its published dependencies no longer would be, so opening it later is a version decision rather than a dependency problem. +- **What ships from the two public sequences is now world-readable, so their payload policy carries more weight.** `vendor/cordis` publishes `src` deliberately, because its export map declares `./src/*`; the Landlock entry publishes `src/main.c` as a documented audit surface. +- **The private-packages plan is no longer required for these two sequences.** The `402 Payment Required` failure that blocked the first native publication cannot recur for a public package. +- **An unauthenticated `npm view` becomes a usable check for the public sequences.** While every package was restricted, a machine without credentials received `E404` for a package that existed, which is indistinguishable from an absent version. diff --git a/.agents/notes/implemented/process/2026-08-13-public-vendor-and-native-sequences.zh.md b/.agents/notes/implemented/process/2026-08-13-public-vendor-and-native-sequences.zh.md new file mode 100644 index 0000000000..1f687d1134 --- /dev/null +++ b/.agents/notes/implemented/process/2026-08-13-public-vendor-and-native-sequences.zh.md @@ -0,0 +1,45 @@ +# Agent Note: 按发布序列区分 npm access:vendored 框架与 native 包公开发布 + +Status: implemented + +[English](2026-08-13-public-vendor-and-native-sequences.md) | 中文 + +## Problem + +[三条发布序列](2026-08-10-npm-release-sequences.md)交付时带的是 `publishConfig.access: restricted`,因此发到 `@deepseek-ai` scope 的每个包只在组织内可见。五次排练发布都是这样跑的:`dsh@0.0.1-rc.5`、vendor 的 `*-rc.4`、`landlock-run@0.0.1`。 + +真正卡住公开消费者的是**受限的依赖**。每个 harness 包都把 vendored 框架声明成 `peerDependency`,`dsh-sandbox-local` 把 Landlock 入口声明成 `dependency`。一个公开包若要求一个受限包,组织外的人根本装不上;所以这两条序列必须先公开,dsh 族才可能公开 —— 而在 dsh 族仍受限期间,它们也正是外部消费者唯一需要解析到的两条。 + +## Decision + +access 是每条发布序列的属性,不是整个 scope 的属性: + +| 序列 | 成员 | `publishConfig.access` | +|---|---|---| +| vendored 框架 | `vendor/*` 九包 | `public` | +| native | `native/landlock-run/packages/*` 三包 | `public` | +| dsh | `packages/*/*` + `apps/*`(221 个成员) | `restricted` | + +`check-workspace-constraints.ts` 按各自序列的级别校验每个 manifest,这是阻止 scope 漂移的那道闸:新增的 `vendor/*` 包留在 `restricted`、或某个 dsh 成员被改成 `public`,都会让 workspace 约束失败。 + +**没有任何发布路径传 `--access`。** 一个选项无法服务级别互不相同的序列,而且选项会覆盖真正拥有这个事实的 manifest —— 所以 `publish.ts` 不传,native 的 workflow 也照旧不传,由各 packed manifest 决定。 + +harness 消费方引用 Landlock 入口改用 `workspace:^` 而非 `workspace:*`,于是发布出去的 harness 包接受该入口的 patch 与 minor 版本,而不是钉死一个精确版本。入口对它那两个平台包仍保持 `workspace:*` —— 那里二进制必须与入口版本完全一致。 + +access 是包的属性、不是版本的属性:已经以 restricted 发布的这十二个包(`landlock-run@0.0.1` 与 vendored 的 `*-rc.*`)会在**下一次发布**时变为全网可读。 + +## Alternatives considered + +**一次性把整个 scope 改成 public。** 暂不采用:那会让下一次 dsh 发布因为一次 manifest 改动而顺带变成公开,而不是出自一个刻意的发布决定。先公开这两条依赖序列,是能让每一步的已发布包都保持可安装的顺序,也是将来决定公开 dsh 时的前置条件。 + +**全部保持受限,改为授予一个只读 team。** `npm access grant read-only <包>` 是逐包的、没有 scope 通配,覆盖全集意味着每个包一次 grant,外加一个为后续新增包长期补齐的对账任务。它也只能覆盖组织成员,无法服务一个可安装的公开产物。 + +**在发布路径而不是 manifest 里指定公开。** 混合 scope 下不可能 —— 一个 `--access` 选项表达不了两种级别 —— 而且它会覆盖 workspace 约束正在校验的那个 manifest。 + +## Consequences + +- **这十二个包从下一次发布起就是公开的,而且不能干净地回退。** 回到受限 scope 需要付费套餐加逐包 `npm access set status=private`,且已经被下载或镜像的内容收不回来。 +- **`@deepseek-ai/dsh` 仍然装不了(组织外)。** 它的 manifest 保持 `restricted`;变化的是它已发布的依赖不再受限,所以将来公开它是一个版本决定,而不再是依赖问题。 +- **两条公开序列交付的内容成为全网可读,它们的 payload 策略分量因此变重。** `vendor/cordis` 有意发布 `src`,因为其导出映射声明了 `./src/*`;Landlock 入口按既有约定发布 `src/main.c` 作为审计面。 +- **这两条序列不再需要私有包套餐。** 阻塞过首次 native 发布的 `402 Payment Required` 失败形态对公开包不会再出现。 +- **对公开序列,无凭据的 `npm view` 成为一个可用的检查手段。** 在所有包都受限的时期,没有凭据的机器对一个确实存在的包会收到 `E404`,与「版本不存在」无法区分。 diff --git a/.agents/notes/implemented/process/2026-08-13-published-document-fragments.i18n.yaml b/.agents/notes/implemented/process/2026-08-13-published-document-fragments.i18n.yaml new file mode 100644 index 0000000000..d90edf5075 --- /dev/null +++ b/.agents/notes/implemented/process/2026-08-13-published-document-fragments.i18n.yaml @@ -0,0 +1,6 @@ +# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each +# 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 .agents/notes/implemented/process/2026-08-13-published-document-fragments.md +2026-08-13-published-document-fragments.md: 4146a592a97b5d8b4e1d3fbabd0f035074cc8001 +2026-08-13-published-document-fragments.zh.md: 6cf76dfa349bbd61d1dd51cb683b696e4c405435 diff --git a/.agents/notes/implemented/process/2026-08-13-published-document-fragments.md b/.agents/notes/implemented/process/2026-08-13-published-document-fragments.md new file mode 100644 index 0000000000..4146a592a9 --- /dev/null +++ b/.agents/notes/implemented/process/2026-08-13-published-document-fragments.md @@ -0,0 +1,27 @@ +# Agent Note: Validate published document fragments + +Status: implemented + +English | [中文](2026-08-13-published-document-fragments.zh.md) + +## Problem + +`verify-md-links` validates fragments with GitHub's Markdown heading ids, while the documentation website renders headings with VitePress. Punctuation-heavy headings and translated headings can therefore pass source validation but produce links to ids absent from the published HTML. A successful VitePress build validates target pages, not fragment ids. + +## Decision + +`docs:build` and its MPA variant run `verify-doc-site-fragments` after VitePress emits `website/.dist`. The verifier parses every emitted HTML page, resolves each internal fragment link against VitePress clean URLs, and fails when the output is absent, routes are ambiguous, an href is malformed, or either the target page or requested id is missing. Unit tests cover those failures plus clean URLs, `.html` aliases, same-page links, encoded and literal ids, and external-link exclusion. + +Any fragment target heading whose GitHub id differs from its VitePress id carries an explicit GitHub-compatible alias. Authored English and translated pages place the alias before the heading; translated pages use the English id shared by the bilingual pair. Generated config, tool, and persistence catalogs emit the alias from their owning generator. Source Markdown validation remains independent and continues to reject links that do not resolve under repository rendering. + +## Alternatives considered + +**Use locale-specific fragments.** Bilingual pairs intentionally preserve identical link targets. Locale-specific fragments would make the two sources disagree and would require every link producer to know the target locale's translated heading. + +**Rely on VitePress heading ids.** Those ids depend on rendered punctuation and localized heading text. They do not preserve the GitHub ids already used by repository links and generated references. + +**Check source Markdown only.** This leaves the published artifact unverified and cannot detect differences between the GitHub and VitePress slug algorithms. + +## Consequences + +Every production documentation build reads its emitted HTML once, adding a bounded post-build check to the existing site build. Cross-page fragment links now require an id that survives publication. Explicit aliases become part of the published reference and let headings change language or punctuation without invalidating established fragments. diff --git a/.agents/notes/implemented/process/2026-08-13-published-document-fragments.zh.md b/.agents/notes/implemented/process/2026-08-13-published-document-fragments.zh.md new file mode 100644 index 0000000000..6cf76dfa34 --- /dev/null +++ b/.agents/notes/implemented/process/2026-08-13-published-document-fragments.zh.md @@ -0,0 +1,27 @@ +# Agent Note: 校验已发布文档的 fragment + +Status: implemented + +[English](2026-08-13-published-document-fragments.md) | 中文 + +## Problem + +`verify-md-links` 使用 GitHub 的 Markdown 标题 id 校验 fragment,而文档网站使用 VitePress 渲染标题。包含较多标点的标题与翻译后的标题可能通过源码校验,却在已发布 HTML 中没有对应 id。VitePress 构建成功只会校验目标页面,不会校验 fragment id。 + +## Decision + +`docs:build` 及其 MPA 变体会在 VitePress 生成 `website/.dist` 后运行 `verify-doc-site-fragments`。该校验器解析每个生成的 HTML 页面,按照 VitePress clean URL 解析每个内部 fragment 链接,并在构建产物不存在、路由有歧义、href 格式错误、目标页面不存在或请求的 id 缺失时失败。单元测试覆盖这些失败,以及 clean URL、`.html` 别名、同页链接、编码和字面 id 与外部链接排除。 + +任何 GitHub id 与 VitePress id 不同的 fragment 目标标题都会带有与 GitHub 兼容的显式别名。英文手写页面和翻译页面会在标题前添加别名;翻译页面使用双语对侧文件共享的英文 id。生成的配置、工具和持久化目录由所属生成器输出别名。源码 Markdown 校验保持独立,仍会拒绝在仓库渲染规则下无法解析的链接。 + +## Alternatives considered + +**使用各语言专属的 fragment。** 双语对侧文件会刻意保留相同的链接目标。语言专属 fragment 会使两侧源码不一致,还会要求每个链接生成方都了解目标语言翻译后的标题。 + +**依赖 VitePress 标题 id。** 这些 id 取决于渲染后的标点与本地化标题文本,无法保留仓库链接和生成引用已经使用的 GitHub id。 + +**只检查 Markdown 源码。** 这种做法不会校验发布产物,也无法发现 GitHub 与 VitePress slug 算法之间的差异。 + +## Consequences + +每次生产文档构建都会读取一次生成的 HTML,在现有网站构建后增加一个有界检查。跨页面 fragment 链接必须指向发布后仍存在的 id。显式别名成为已发布参考的一部分,使标题更换语言或标点后仍能保留既有 fragment。 diff --git a/.agents/notes/implemented/simplification/2026-06-26-fsspec-style-fs-seam.i18n.yaml b/.agents/notes/implemented/simplification/2026-06-26-fsspec-style-fs-seam.i18n.yaml index e2ff001696..9c09464d87 100644 --- a/.agents/notes/implemented/simplification/2026-06-26-fsspec-style-fs-seam.i18n.yaml +++ b/.agents/notes/implemented/simplification/2026-06-26-fsspec-style-fs-seam.i18n.yaml @@ -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 .agents/notes/implemented/simplification/2026-06-26-fsspec-style-fs-seam.md -2026-06-26-fsspec-style-fs-seam.md: ec3ee9bd0781b64b804f58c32cb59afc7f05e0d4 -2026-06-26-fsspec-style-fs-seam.zh.md: a4e50c401e56854933bcaebd24cf9955949b3c31 +2026-06-26-fsspec-style-fs-seam.md: 927220a4042a47aa1a76926161427613f3a2b809 +2026-06-26-fsspec-style-fs-seam.zh.md: 52c55f82f77d4101f1e659d4642689e5aa3a804f diff --git a/.agents/notes/implemented/simplification/2026-06-26-fsspec-style-fs-seam.md b/.agents/notes/implemented/simplification/2026-06-26-fsspec-style-fs-seam.md index ec3ee9bd07..927220a404 100644 --- a/.agents/notes/implemented/simplification/2026-06-26-fsspec-style-fs-seam.md +++ b/.agents/notes/implemented/simplification/2026-06-26-fsspec-style-fs-seam.md @@ -105,7 +105,7 @@ This Agent Note reverses two decisions from [filesystem-capability-seam](../arch - Text reads no longer return backend-numbered line records or `full`/`partial` views; authorization is based on version freshness, so a windowed read can authorize edit when the file is unchanged. - Literal edit no longer sits behind the old `applyEdit` API that mixed backend mutation with seam-owned observation policy. It remains a provider primitive as `editText`, because version guard + literal match + atomic rewrite must stay inside the provider's mutation critical section. -It keeps the Service Definition / Service provider / Consumer discipline, consumer-never-imports-backend rule, backend-defined target/version/display metadata, atomic local writes, and the shared `FsError` taxonomy. +It keeps the Service Definition / Service Provider / Consumer discipline, consumer-never-imports-backend rule, backend-defined target/version/display metadata, atomic local writes, and the shared `FsError` taxonomy. ## Verification diff --git a/.agents/notes/implemented/simplification/2026-06-26-fsspec-style-fs-seam.zh.md b/.agents/notes/implemented/simplification/2026-06-26-fsspec-style-fs-seam.zh.md index a4e50c401e..52c55f82f7 100644 --- a/.agents/notes/implemented/simplification/2026-06-26-fsspec-style-fs-seam.zh.md +++ b/.agents/notes/implemented/simplification/2026-06-26-fsspec-style-fs-seam.zh.md @@ -105,7 +105,7 @@ type FsWriteIntent = - 文本读取不再返回后端编号的行记录或 `full`/`partial` 视图;授权基于版本新鲜度,因此窗口化读取在文件未变时即可授权编辑。 - 字面编辑不再位于旧的 `applyEdit` API 之后(该 API 混合了后端变更与 seam 拥有的观测策略)。它作为 `editText` 保留为提供方原语,因为版本守卫 + 字面匹配 + 原子重写必须留在提供方的变更临界区内。 -保留的内容:Service Definition / Service provider / Consumer 纪律、消费方不导入后端规则、后端定义的 target/version/display 元数据、原子本地写入,以及共享的 `FsError` 分类体系。 +保留的内容:Service Definition / Service Provider / Consumer 纪律、消费方不导入后端规则、后端定义的 target/version/display 元数据、原子本地写入,以及共享的 `FsError` 分类体系。 ## 验证 diff --git a/.agents/notes/implemented/simplification/2026-08-11-remove-sdk-project-toolchain.i18n.yaml b/.agents/notes/implemented/simplification/2026-08-11-remove-sdk-project-toolchain.i18n.yaml index c24200f8be..29dd78cab1 100644 --- a/.agents/notes/implemented/simplification/2026-08-11-remove-sdk-project-toolchain.i18n.yaml +++ b/.agents/notes/implemented/simplification/2026-08-11-remove-sdk-project-toolchain.i18n.yaml @@ -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 .agents/notes/implemented/simplification/2026-08-11-remove-sdk-project-toolchain.md -2026-08-11-remove-sdk-project-toolchain.md: cfaf0df46e34d419f5d0b2d5a2a25580675fdc31 -2026-08-11-remove-sdk-project-toolchain.zh.md: 3b563007bf92f94adab6c68eeaa9c6c1522815e4 +2026-08-11-remove-sdk-project-toolchain.md: fc896c2823a1ccddf06c8dce788c4ffe72a9367a +2026-08-11-remove-sdk-project-toolchain.zh.md: a258ca39bc824fbf9f1717c10e6b123d52689af5 diff --git a/.agents/notes/implemented/simplification/2026-08-11-remove-sdk-project-toolchain.md b/.agents/notes/implemented/simplification/2026-08-11-remove-sdk-project-toolchain.md index cfaf0df46e..fc896c2823 100644 --- a/.agents/notes/implemented/simplification/2026-08-11-remove-sdk-project-toolchain.md +++ b/.agents/notes/implemented/simplification/2026-08-11-remove-sdk-project-toolchain.md @@ -16,7 +16,7 @@ The same `scaffold/` group also contained the independently used SDK protocol, T The SDK project toolchain is deleted. The `@deepseek-ai/create-sdk`, `@deepseek-ai/dsh-scripts`, `@deepseek-ai/dsh-helper`, and `@deepseek-ai/dsh-telemetry` packages, their binaries, tests, templates, feature catalog, project-editing model, package-manager support, launcher telemetry, and repository creation skill have no replacement or compatibility layer. Their workspace, build, test, packaging, documentation-generator, vendoring-rescope, and dependency records are removed with them. -The runtime SDK remains. `@deepseek-ai/dsh-sdk-client`, `@deepseek-ai/dsh-sdk-protocol`, and `@deepseek-ai/dsh-sdk-jsonrpc-server` move unchanged from `packages/scaffold/` to `packages/sdk/`; their npm names and wire behavior do not change. Consumers continue to provide an executable plus an external `cordis.yml`, and the JSON-RPC server remains an ordinary plugin selected by that configuration. +The runtime SDK remains. `@deepseek-ai/dsh-sdk-client`, `@deepseek-ai/dsh-sdk-protocol`, and `@deepseek-ai/dsh-sdk-jsonrpc-server` move unchanged from `packages/scaffold/` to `packages/sdk/`; their npm names and wire behavior do not change. Consumers continue to provide an executable plus an external `cordis.yml`, and the JSON-RPC server remains an ordinary plugin selected by that configuration. The [repository naming contract](../architecture/2026-08-11-repository-naming-contract-and-rename-ledger.md) owns this one repository meaning of `SDK` and the surviving package names; this note owns the deleted toolchain. The canceled developer-project, project-editing, and follow-up-capabilities proposals are deleted rather than retained as active or rejected records. This note preserves the motivation they shared, the decision not to ship that product, the capability given up, and the condition for reconsideration. Frozen archived Agent Notes remain historical snapshots and are not edited. diff --git a/.agents/notes/implemented/simplification/2026-08-11-remove-sdk-project-toolchain.zh.md b/.agents/notes/implemented/simplification/2026-08-11-remove-sdk-project-toolchain.zh.md index 3b563007bf..a258ca39bc 100644 --- a/.agents/notes/implemented/simplification/2026-08-11-remove-sdk-project-toolchain.zh.md +++ b/.agents/notes/implemented/simplification/2026-08-11-remove-sdk-project-toolchain.zh.md @@ -16,7 +16,7 @@ Status: implemented 删除 SDK 项目工具链。`@deepseek-ai/create-sdk`、`@deepseek-ai/dsh-scripts`、`@deepseek-ai/dsh-helper` 和 `@deepseek-ai/dsh-telemetry` 包及其二进制文件、测试、模板、功能目录、项目编辑模型、包管理器支持、启动器遥测和仓库项目创建 skill 均不提供替代实现或兼容层。与其对应的 workspace、构建、测试、打包、文档生成器、vendor scope 重写和依赖记录也一并移除。 -保留运行时 SDK。`@deepseek-ai/dsh-sdk-client`、`@deepseek-ai/dsh-sdk-protocol` 和 `@deepseek-ai/dsh-sdk-jsonrpc-server` 保持原样,从 `packages/scaffold/` 移至 `packages/sdk/`;其 npm 名称和协议交互行为保持不变。消费方继续提供一个可执行文件和一份外置 `cordis.yml`,JSON-RPC 服务器仍是由该配置选择的普通插件。 +保留运行时 SDK。`@deepseek-ai/dsh-sdk-client`、`@deepseek-ai/dsh-sdk-protocol` 和 `@deepseek-ai/dsh-sdk-jsonrpc-server` 保持原样,从 `packages/scaffold/` 移至 `packages/sdk/`;其 npm 名称和协议交互行为保持不变。消费方继续提供一个可执行文件和一份外置 `cordis.yml`,JSON-RPC 服务器仍是由该配置选择的普通插件。[仓库命名约定](../architecture/2026-08-11-repository-naming-contract-and-rename-ledger.md)负责规定 `SDK` 在仓库中的唯一含义和保留的包名;本说明负责记录已删除的工具链。 被取消的开发者项目、项目编辑和后续能力提案予以删除,而不是保留为活跃或已否决记录。本 Agent Note 保留这些提案共有的动机、不交付该产品的决策、放弃的能力,以及重新考虑这一决定的条件。已冻结的归档 Agent Note 仍是历史快照,不作修改。 diff --git a/.agents/notes/implemented/simplification/2026-08-12-production-dsh-excludes-product-subagent-providers.i18n.yaml b/.agents/notes/implemented/simplification/2026-08-12-production-dsh-excludes-product-subagent-providers.i18n.yaml new file mode 100644 index 0000000000..44f197e39d --- /dev/null +++ b/.agents/notes/implemented/simplification/2026-08-12-production-dsh-excludes-product-subagent-providers.i18n.yaml @@ -0,0 +1,6 @@ +# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each +# 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 .agents/notes/implemented/simplification/2026-08-12-production-dsh-excludes-product-subagent-providers.md +2026-08-12-production-dsh-excludes-product-subagent-providers.md: 3e3e4fbefb31932a637bfe05ff0d90916e202a79 +2026-08-12-production-dsh-excludes-product-subagent-providers.zh.md: 166964675bf7084b62f5500969e5756c9bd9f644 diff --git a/.agents/notes/implemented/simplification/2026-08-12-production-dsh-excludes-product-subagent-providers.md b/.agents/notes/implemented/simplification/2026-08-12-production-dsh-excludes-product-subagent-providers.md new file mode 100644 index 0000000000..3e3e4fbefb --- /dev/null +++ b/.agents/notes/implemented/simplification/2026-08-12-production-dsh-excludes-product-subagent-providers.md @@ -0,0 +1,25 @@ +# Agent Note: Production dsh excludes product subagent providers + +Status: implemented + +English | [中文](2026-08-12-production-dsh-excludes-product-subagent-providers.zh.md) + +## Problem + +`@deepseek-ai/dsh` receives the `@deepseek-ai/dsh-base` dependency closure. Including the Codex and Claude Code subagent providers there makes every production install download optional product integration code, including the Claude Agent SDK, even when neither integration is used. + +## Decision + +This decision supersedes the [shared-host placement](../architecture/2026-08-10-product-subagent-providers-in-shared-host.md): `@deepseek-ai/dsh-base` does not depend on or mount the Codex and Claude Code subagent providers. Their packages remain available for Profiles that install and mount them explicitly. Repository examples keep direct development dependencies so their explicit provider configurations continue to resolve. + +## Verification + +The base bundle test rejects both provider dependencies and configuration rows. Cordis configuration validation requires explicit examples to declare the provider packages they name. + +## Alternatives considered + +**Keep dormant providers in the base bundle.** Dormant providers start no product processes, but their packages still enter every production npm install. + +## Consequences + +Installing `@deepseek-ai/dsh` does not download either product provider through the base bundle. Using either integration requires explicit Profile configuration. diff --git a/.agents/notes/implemented/simplification/2026-08-12-production-dsh-excludes-product-subagent-providers.zh.md b/.agents/notes/implemented/simplification/2026-08-12-production-dsh-excludes-product-subagent-providers.zh.md new file mode 100644 index 0000000000..166964675b --- /dev/null +++ b/.agents/notes/implemented/simplification/2026-08-12-production-dsh-excludes-product-subagent-providers.zh.md @@ -0,0 +1,25 @@ +# Agent Note: 生产 dsh 排除产品 subagent 提供方 + +Status: implemented + +[English](2026-08-12-production-dsh-excludes-product-subagent-providers.md) | 中文 + +## 问题 + +`@deepseek-ai/dsh` 会获得 `@deepseek-ai/dsh-base` 的依赖闭包。如果 base 包含 Codex 与 Claude Code subagent 提供方,每次生产安装都会下载可选的产品集成代码,包括 Claude Agent SDK,即使用户并未使用任一集成。 + +## 决策 + +本决策取代[共享 host 放置决策](../architecture/2026-08-10-product-subagent-providers-in-shared-host.md):`@deepseek-ai/dsh-base` 不依赖也不挂载 Codex 与 Claude Code subagent 提供方。需要这些集成的 Profile 仍可显式安装并挂载对应包。仓库 examples 保留直接开发依赖,使其显式提供方配置可以继续解析。 + +## 验证 + +base 组合包测试会拒绝这两个提供方依赖与配置行。Cordis 配置验证要求显式 examples 声明其引用的提供方包。 + +## 考虑过的替代方案 + +**在 base 组合包中保留休眠提供方。** 休眠提供方不会启动产品进程,但其包仍会进入每次生产 NPM 安装。 + +## 后果 + +安装 `@deepseek-ai/dsh` 时,不会通过 base 组合包下载任一产品提供方。使用任一集成都需要显式 Profile 配置。 diff --git a/.agents/notes/implemented/simplification/2026-08-13-remove-first-run-beta-notice.i18n.yaml b/.agents/notes/implemented/simplification/2026-08-13-remove-first-run-beta-notice.i18n.yaml new file mode 100644 index 0000000000..e48ec3de3b --- /dev/null +++ b/.agents/notes/implemented/simplification/2026-08-13-remove-first-run-beta-notice.i18n.yaml @@ -0,0 +1,6 @@ +# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each +# 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 .agents/notes/implemented/simplification/2026-08-13-remove-first-run-beta-notice.md +2026-08-13-remove-first-run-beta-notice.md: 21396eb9cc3e0e766238115967e354abe1032bd2 +2026-08-13-remove-first-run-beta-notice.zh.md: 2818343804e88e7114f5a6298393780b0fdcaf24 diff --git a/.agents/notes/implemented/simplification/2026-08-13-remove-first-run-beta-notice.md b/.agents/notes/implemented/simplification/2026-08-13-remove-first-run-beta-notice.md new file mode 100644 index 0000000000..21396eb9cc --- /dev/null +++ b/.agents/notes/implemented/simplification/2026-08-13-remove-first-run-beta-notice.md @@ -0,0 +1,25 @@ +# Agent Note: Remove the first-run beta notice + +Status: implemented + +English | [中文](2026-08-13-remove-first-run-beta-notice.zh.md) + +## Problem + +Every GUI first launch opened with a full-viewport internal-test statement (内测声明): internal-beta framing plus instructions for enabling Session Log upload through `DSH_TELEMETRY_MODE`. Session telemetry already resolves to `DISABLED` when its mode is unset ([telemetry default-off](../feature/2026-08-10-telemetry-default-off.md)), so the only onboarding content about telemetry was a prompt explaining how to turn it on, and the internal-test framing itself must not ship in a release build. + +## Decision + +This decision removed the first-run notice from the assembled product rather than rewording it. `ui-settings-general` seated no `settings.onboarding` step; the notice component, acknowledgement store, copy owner, and locale keys were deleted, while the Host kept the `ui-onboarding` namespace so stored documents remained valid. The later [shared-modal product onboarding](../feature/2026-08-13-shared-modal-product-onboarding.md) restores a new concise testing-stage notice in `ui-settings-models`, reusing that field and backend contract without restoring the removed takeover layout or telemetry instructions. Telemetry opt-in remains an explicit deployment environment choice documented in the [CLI reference README](../../../../apps/cli/reference/README.md); the restored notice says nothing about enabling it. + +## Alternatives considered + +**Keep the notice and only drop its telemetry paragraph.** Rejected: the internal-test framing is what a release must not present, and a mandatory first-run interstitial with no material statement left is pure friction. + +**Ask for upload consent instead (a versioned consent step).** Rejected for this release: a first-run question about enabling upload is still a telemetry prompt. A future consent flow can register through the unchanged `settings.onboarding` seam and use a fresh versioned field for re-acknowledgement. + +**Deregister the `ui-onboarding` namespace as well.** Rejected: existing settings documents already carry the section, and the settings seam validates stored documents against registered namespaces; keeping the registration keeps those documents valid at no cost. + +## Consequences + +This removal eliminated the full-viewport notice and its telemetry copy. The later restoration is intentionally a different presentation and copy revision: a shared modal precedes the inline credential dialog, the remote scenario again covers process-local acknowledgement, and the existing `welcomeNoticeVersion` field records the new copy version. The historical telemetry prompt remains absent. diff --git a/.agents/notes/implemented/simplification/2026-08-13-remove-first-run-beta-notice.zh.md b/.agents/notes/implemented/simplification/2026-08-13-remove-first-run-beta-notice.zh.md new file mode 100644 index 0000000000..2818343804 --- /dev/null +++ b/.agents/notes/implemented/simplification/2026-08-13-remove-first-run-beta-notice.zh.md @@ -0,0 +1,25 @@ +# Agent Note: 移除首次启动内测声明 + +Status: implemented + +[English](2026-08-13-remove-first-run-beta-notice.md) | 中文 + +## 问题 + +GUI 每次首启都会先显示占满视口的内测声明:内部测试的定位表述,加上通过 `DSH_TELEMETRY_MODE` 开启 Session Log 上传的说明。会话遥测在 mode 未设置时已解析为 `DISABLED`([遥测默认关闭](../feature/2026-08-10-telemetry-default-off.md)),因此引导流程中关于遥测的全部内容就是一段教用户如何开启的提示,而内部测试的定位表述本身也不应出现在发布版本里。 + +## 决策 + +本决策当时把首启声明从组装后的产品中整体移除,而不是改写。`ui-settings-general` 不再注册任何 `settings.onboarding` 步骤;声明组件、确认 store、文案所有者文件和 locale 键均被删除,Host 则保留 `ui-onboarding` namespace,使既有设置文档继续有效。后续的[共用弹窗产品引导](../feature/2026-08-13-shared-modal-product-onboarding.md)在 `ui-settings-models` 中恢复了一份新的简洁测试阶段声明,复用该字段与后端契约,但不会恢复已移除的接管式布局或遥测说明。遥测的开启仍是显式的部署环境变量选择,记录在 [CLI reference README](../../../../apps/cli/reference/README.md) 中;恢复后的声明不涉及如何开启遥测。 + +## 曾考虑的替代方案 + +**保留声明,只删除其中的遥测段落。** 不予采用:发布版本不应呈现的正是内部测试的定位表述本身,而一个没有实质内容的强制首启插页只剩下打扰。 + +**改为询问上传同意(版本化的同意步骤)。** 本次发布不予采用:首启询问是否开启上传仍然是一个遥测提示。未来的同意流程可以通过保持不变的 `settings.onboarding` seam 注册,并使用新的版本化字段做重新确认。 + +**连 `ui-onboarding` namespace 一起注销。** 不予采用:既有设置文档已经包含该分节,而设置 seam 会用已注册的 namespace 校验存储文档;保留注册就能让这些文档继续有效,且没有额外成本。 + +## 后果 + +这次移除消除了占满视口的声明及其遥测文案。后续恢复有意采用不同的展示与文案版本:共用弹窗先于行内凭据弹窗出现,远程场景重新覆盖进程内确认,既有 `welcomeNoticeVersion` 字段记录新的文案版本。历史上的遥测提示仍未恢复。 diff --git a/.agents/notes/proposed/architecture/2026-07-19-required-cancellation-through-tool-capability-seams.i18n.yaml b/.agents/notes/proposed/architecture/2026-07-19-required-cancellation-through-tool-capability-seams.i18n.yaml index 75270e6a39..56bc51e639 100644 --- a/.agents/notes/proposed/architecture/2026-07-19-required-cancellation-through-tool-capability-seams.i18n.yaml +++ b/.agents/notes/proposed/architecture/2026-07-19-required-cancellation-through-tool-capability-seams.i18n.yaml @@ -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 .agents/notes/proposed/architecture/2026-07-19-required-cancellation-through-tool-capability-seams.md -2026-07-19-required-cancellation-through-tool-capability-seams.md: 380204200711158fcda640fe25551293515fc49a -2026-07-19-required-cancellation-through-tool-capability-seams.zh.md: 631abfaa1cd21578437458cc194e277dc7883792 +2026-07-19-required-cancellation-through-tool-capability-seams.md: 478cd887d84ceae8a5a0cd455fb7cf4b4d562950 +2026-07-19-required-cancellation-through-tool-capability-seams.zh.md: f3afdc953b50751798b412d24ecd7a9efd7d9af2 diff --git a/.agents/notes/proposed/architecture/2026-07-19-required-cancellation-through-tool-capability-seams.md b/.agents/notes/proposed/architecture/2026-07-19-required-cancellation-through-tool-capability-seams.md index 3802042007..478cd887d8 100644 --- a/.agents/notes/proposed/architecture/2026-07-19-required-cancellation-through-tool-capability-seams.md +++ b/.agents/notes/proposed/architecture/2026-07-19-required-cancellation-through-tool-capability-seams.md @@ -18,7 +18,7 @@ Require an `AbortSignal` on every asynchronous same-process capability operation Each direct caller supplies a signal it owns or propagates from its own required operation context. Implementations may derive a child deadline or cancellation scope, but the derived signal remains linked to the upstream signal for the delegated lifetime. Capability implementations do not synthesize never-abort signals, use ambient async-local cancellation, or validate `AbortSignal` at runtime solely to repeat the typed same-process contract. -The migration begins with an inventory from every first-party `ToolDefinition.execute()` through the capability calls it awaits. It then changes each coherent Service Definition / Service provider / Consumer seam together, including tests and generated API documentation. Separate PRs may migrate filesystem, shell/task, web/provider, workflow/subagent, code-runtime, and similar families so each change remains reviewable, but no migrated interface keeps an optional compatibility overload under the repository's pre-release policy. +The migration begins with an inventory from every first-party `ToolDefinition.execute()` through the capability calls it awaits. It then changes each coherent Service Definition / Service Provider / Consumer seam together, including tests and generated API documentation. Separate PRs may migrate filesystem, shell/task, web/provider, workflow/subagent, code-runtime, and similar families so each change remains reviewable, but no migrated interface keeps an optional compatibility overload under the repository's pre-release policy. ### Scope boundary diff --git a/.agents/notes/proposed/architecture/2026-07-19-required-cancellation-through-tool-capability-seams.zh.md b/.agents/notes/proposed/architecture/2026-07-19-required-cancellation-through-tool-capability-seams.zh.md index 631abfaa1c..f3afdc953b 100644 --- a/.agents/notes/proposed/architecture/2026-07-19-required-cancellation-through-tool-capability-seams.zh.md +++ b/.agents/notes/proposed/architecture/2026-07-19-required-cancellation-through-tool-capability-seams.zh.md @@ -18,7 +18,7 @@ Status: proposed 每个直接调用方提供自己持有的信号,或从自身必填的操作上下文继续传递信号。实现可以派生子截止时间或取消作用域,但派生信号在委托期间仍须与上游信号关联。能力实现不得生成永不中止信号、使用环境式异步本地取消,也不得仅为重复类型化同进程约定而在运行时校验 `AbortSignal`。 -迁移首先从每个第一方 `ToolDefinition.execute()` 出发,沿其等待的能力调用进行清点;随后按内聚的 Service Definition/Service provider/Consumer seam,将测试与生成的 API 文档一并修改。文件系统、Bash 与任务、Web 与提供方、工作流与 subagent、代码运行时等能力族可以通过独立 PR(Pull Request)迁移,以保持每项变更可审查;但根据仓库的预发布原则,已经迁移的接口不得保留可选兼容重载。 +迁移首先从每个第一方 `ToolDefinition.execute()` 出发,沿其等待的能力调用进行清点;随后按内聚的 Service Definition/Service Provider/Consumer seam,将测试与生成的 API 文档一并修改。文件系统、Bash 与任务、Web 与提供方、工作流与 subagent、代码运行时等能力族可以通过独立 PR(Pull Request)迁移,以保持每项变更可审查;但根据仓库的预发布原则,已经迁移的接口不得保留可选兼容重载。 ### 范围边界 diff --git a/.agents/notes/proposed/architecture/2026-07-29-durable-last-activity-index.i18n.yaml b/.agents/notes/proposed/architecture/2026-07-29-durable-last-activity-index.i18n.yaml index af319b51a7..e8355305ed 100644 --- a/.agents/notes/proposed/architecture/2026-07-29-durable-last-activity-index.i18n.yaml +++ b/.agents/notes/proposed/architecture/2026-07-29-durable-last-activity-index.i18n.yaml @@ -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 .agents/notes/proposed/architecture/2026-07-29-durable-last-activity-index.md -2026-07-29-durable-last-activity-index.md: 0e441f54a719b29a1a450c133e08cdf7d2c82e9e -2026-07-29-durable-last-activity-index.zh.md: ebc2e2167d7743eafc5a4600fe9a0f687349e1a3 +2026-07-29-durable-last-activity-index.md: 99e50dd40b789db5d896cb7f9e25fa8893b02ae2 +2026-07-29-durable-last-activity-index.zh.md: e317fb192d53353295e6b52f631707ba6b400b66 diff --git a/.agents/notes/proposed/architecture/2026-07-29-durable-last-activity-index.md b/.agents/notes/proposed/architecture/2026-07-29-durable-last-activity-index.md index 0e441f54a7..99e50dd40b 100644 --- a/.agents/notes/proposed/architecture/2026-07-29-durable-last-activity-index.md +++ b/.agents/notes/proposed/architecture/2026-07-29-durable-last-activity-index.md @@ -6,17 +6,17 @@ English | [中文](2026-07-29-durable-last-activity-index.zh.md) ## Problem -A cold (persisted, unattached) session has no stored answer to "when was this last worked in". `dsh-host-apiproxy`'s `summarizeCold()` therefore approximates it with the log file's mtime where one exists — `locate()` resolves a per-session artifact for JSONL and `undefined` for SQLite, whose cold sessions fall back to `createdAt` — and the web client sorts its session tree by the resulting `updatedAt`. The two backends are wrong in opposite directions: JSONL reads too new, SQLite too old. +A cold (persisted, unattached) session has no authoritative stored answer to "when did the user last prompt here". `dsh-host-apiproxy` serves `updatedAt` from the optional projection cache's `lastPromptAt`, falling back to `createdAt`, and the Web client sorts its Session tree by that value. The cache is fail-soft and checkpointed asynchronously, so a missing or delayed row makes a recently prompted Session sort too old. -mtime answers a different question: when the artifact was last written. Every durable write refreshes it, including writes that are not activity — a truncate-repair of a torn tail, the synthetic closers that balance an interrupted turn, and the [`session/end-seed` boundary](../../implemented/architecture/2026-07-30-session-end-seed-log-boundary.md) a seeded session appends. (A `flush` with nothing pending is not among them: the coordinator returns without reaching the backend.) The visible consequence is stable and wrong in one direction: a session touched without being worked in promotes itself above sessions the user actually worked in afterwards, and each touch re-promotes it. `dsh-host-apiproxy` keeps `session.history` inspection-only, but any Agent-bound ordinary-session control resumes through `agentFor()` and is enough to promote the cold artifact. +The gateway previously used JSONL artifact mtime when available. mtime answers a different question: when the artifact was last written. Every durable write refreshes it, including a truncate-repair of a torn tail, synthetic closers that balance an interrupted turn, and the [`session/end-seed` boundary](../../implemented/architecture/2026-07-30-session-end-seed-log-boundary.md) appended during pickup. That approximation promoted a Session merely because it was opened. The [bounded cold blank verification](../../implemented/bug-fix/2026-08-13-bounded-cold-blank-verification.md) removed mtime ordering and accepted the cache's conservative "too old" failure direction as an interim tradeoff. -The attached projection has a real fix — `lastActivityTime()` skips boundaries — but it needs the event log, and the cold path deliberately does not read one. Reading the log to compute `updatedAt` would defeat the header-only listing that keeps `list()` scaling with session count rather than log size. +An attached summary can fold the live event log and select the latest human-authored `user/message`, but the cold path deliberately does not read large logs. Reading every log to compute `updatedAt` would make `list()` scale with total conversation bytes rather than Session count. The 1 KiB cold read used for metadata verification makes eligible small-artifact recency exact, but it does not make large-log ordering exact. -The [boundary change](../../implemented/architecture/2026-07-30-session-end-seed-log-boundary.md) raised the frequency of this defect, because a pickup now writes where nothing was written before; `dsh-host-apiproxy`'s README records it under Known Limitations. It did not introduce the approximation, and removing the approximation is a durable-format decision, which is why it is scoped here rather than there. +Making cold ordering exact remains a durable-format decision, which is why it is scoped here rather than in the gateway workaround. ## Proposal -Store last-activity time where a listing already reads — the session index — so `summarizeCold()` can serve it without opening the log. The coordinator computes the value, because it sees every append and already owns per-id state; backends persist it. That makes it a new `PersistenceBackend` contract element rather than backend-local bookkeeping, and keeps one definition of "activity" shared with the in-log `lastActivityTime()`. +Store the latest human-prompt time where a listing already reads — the Session index — so `summarizeCold()` can serve it without opening the log or depending on a cache checkpoint. The coordinator computes the value because it sees every append and already owns per-id state; backends persist it. That makes it a new `PersistenceBackend` contract element rather than backend-local bookkeeping, with the same event predicate as the attached projection: `user/message` whose `source.kind` is `user`. The two shipped backends have opposite constraints, and the proposal is deliberately asymmetric about them: @@ -25,7 +25,7 @@ The two shipped backends have opposite constraints, and the proposal is delibera Three questions must be answered before implementation, and none of them is settled here: -**Which events count as activity?** `lastActivityTime()` answers this for the log by excluding `session/end-seed`. A stored field encodes the rule at write time, where the writer sees one batch rather than the whole log. The two must not drift, or the attached and cold surfaces will disagree about the same session. +**How is the shared predicate owned?** A stored field encodes the rule at write time, where the writer sees one batch, while the attached summary folds a whole log. Both must use one exported event predicate or reducer so new message-source variants cannot make attached and cold ordering disagree. **How do pre-field logs behave?** Existing artifacts have no value. Falling back to mtime keeps them at today's accuracy; falling back to `createdAt` is honest but reorders every existing session in the picker and the tree. @@ -39,28 +39,29 @@ Three questions must be answered before implementation, and none of them is sett **Write the boundary only when repair occurred.** Would reduce the frequency, and the [boundary note](../../implemented/architecture/2026-07-30-session-end-seed-log-boundary.md) already rejected it: the predicate must hold for an orderly restart too. Trading a correctness invariant for timestamp accuracy is the wrong direction. -**Derive activity from a projection cache.** `session-projection-cache` already folds tails past a watermark, so a last-activity unit would ride existing machinery. Rejected as the primary shape because the cache is an optional composition entry; a listing served only when a cache plugin is mounted makes ordering depend on composition. +**Derive activity from a projection cache.** This is the current interim implementation. `session-projection-cache` folds tails past a watermark without changing the persistence format, but it is optional and fail-soft. Its absence or checkpoint delay makes ordering depend on cache availability and freshness, so it cannot provide the authoritative value proposed here. ## Acceptance criteria - `SessionSummary.updatedAt` for a cold session equals the same value the attached projection reports for that session, verified by resuming, quitting without a turn, and asserting the order is unchanged across both paths. - A resumed-then-abandoned session does not sort above a session worked in afterwards, in the web session tree and the TUI resume picker, pinned by an assembled snapshot rather than unit tests alone. -- The activity rule has one definition: a test proves the stored field and `lastActivityTime()` agree over a log containing boundaries, closers, and a plain turn. +- The prompt-time rule has one definition: a test proves the stored field and attached fold agree over a log containing human prompts, injected user messages, boundaries, and closers. - Pre-field artifacts load and list without error under the chosen fallback, with the fallback's ordering consequence asserted. - SQLite's `SCHEMA_VERSION` bump rejects the old on-disk version per the repo's no-migration stance. ## Risks -**Two definitions of activity drift.** The stored field is computed per batch, the projection over a whole log. A new event type classified one way at write time and the other at read time yields a session whose cold and attached orderings disagree — a bug that only appears after a restart, which is where it is hardest to notice. +**Two definitions of prompt time drift.** The stored field is computed per batch, the projection over a whole log. A new message source classified one way at write time and the other at read time yields a Session whose cold and attached orderings disagree — a bug that only appears after restart. **A JSONL sidecar can disagree with its log.** A crash between the log append and the sidecar write leaves a stale value with no torn-tail marker to repair it. Every consumer would need to treat the sidecar as a hint, which is close to what mtime already is. **The fallback reorders existing sessions.** Whichever fallback is chosen, users with existing logs see their picker and tree reorder once on upgrade. `createdAt` makes that reordering large. -**Cost may exceed the defect.** The defect is a misordering of abandoned sessions. If the honest answer for JSONL is "keep the approximation", this note's outcome may be documenting that decision rather than implementing a field — and that is an acceptable outcome. +**Cost may exceed the defect.** The remaining defect is conservative misordering when projection metadata is missing or delayed. If the honest answer for JSONL is "keep the cache fallback", this note's outcome may be documenting that decision rather than implementing a field. ## Related -- [The end-seed log boundary](../../implemented/architecture/2026-07-30-session-end-seed-log-boundary.md) — one of the non-activity writes mtime counts; `dsh-session` owns `lastActivityTime()`, the in-log projection a stored field must agree with. +- [Bounded cold blank verification](../../implemented/bug-fix/2026-08-13-bounded-cold-blank-verification.md) — removes mtime ordering, defines the interim projection-cache fallback, and limits direct cold reads to small-artifact metadata verification. +- [The end-seed log boundary](../../implemented/architecture/2026-07-30-session-end-seed-log-boundary.md) — one of the non-prompt writes that made mtime unsuitable. - [Session persistence](../../implemented/architecture/2026-06-14-session-persistence.md) — the append-only and never-rewrite invariants that rule out a mutable JSONL header field. - [Shared persistence write coordinator](../../implemented/architecture/2026-06-18-shared-persistence-write-coordinator.md) — the append path a stored field would hook into. diff --git a/.agents/notes/proposed/architecture/2026-07-29-durable-last-activity-index.zh.md b/.agents/notes/proposed/architecture/2026-07-29-durable-last-activity-index.zh.md index ebc2e2167d..e317fb192d 100644 --- a/.agents/notes/proposed/architecture/2026-07-29-durable-last-activity-index.zh.md +++ b/.agents/notes/proposed/architecture/2026-07-29-durable-last-activity-index.zh.md @@ -6,17 +6,17 @@ Status: proposed ## 问题 -一个冷会话(已持久化、未附加)对「上次是什么时候在这里面工作过」没有任何已存储的答案。因此 `dsh-host-apiproxy` 的 `summarizeCold()` 在存在日志文件时用它的 mtime 来近似它——`locate()` 为 JSONL 解析出一个逐会话产物,为 SQLite 解析出 `undefined`,而 SQLite 的冷会话会回退到 `createdAt`——而 web 客户端就按由此得到的 `updatedAt` 为自己的会话树排序。这两个后端错的方向正好相反:JSONL 读出来偏新,SQLite 偏旧。 +一个冷会话(已持久化、未附加)对「用户上次是什么时候在这里发出 prompt」没有权威的已存储答案。`dsh-host-apiproxy` 从可选 projection cache 的 `lastPromptAt` 提供 `updatedAt`,缺失时回退到 `createdAt`,Web 客户端按该值为 Session 树排序。cache 采用 fail-soft 并异步写入 checkpoint,因此缺失或延迟的记录会让最近收到 prompt 的 Session 排得过旧。 -mtime 回答的是另一个问题:这份产物上次是什么时候被写入的。每一次持久写入都会刷新它,包括那些并不是活动的写入:一次对撕裂尾部的截断修复、用来平衡被中断的轮次的那些合成 closer,以及带种子的会话会追加的 [`session/end-seed` 边界](../../implemented/architecture/2026-07-30-session-end-seed-log-boundary.md)。(没有待处理内容的 `flush` 不在其中:协调器在到达后端之前就返回了。)用户可见的后果是稳定的,而且只朝一个方向错:一个被触碰过却没有在里面工作过的会话,会把自己排到用户此后真正工作过的那些会话之前,而且每次触碰都会重新把它排上去一次。`dsh-host-apiproxy` 让 `session.history` 保持只执行检查,但任何绑定到 Agent 的普通会话控件都会通过 `agentFor()` 恢复会话,足以把冷态产物排到前面。 +网关以前会在可用时采用 JSONL 产物的 mtime。mtime 回答的是另一件事:这份产物上次是什么时候被写入。每一次持久写入都会刷新它,包括对撕裂尾部的截断修复、平衡中断轮次的合成 closer,以及拾起时追加的 [`session/end-seed` 边界](../../implemented/architecture/2026-07-30-session-end-seed-log-boundary.md)。这套近似会让 Session 仅仅因为被打开就提升排序。[有界冷空白验证](../../implemented/bug-fix/2026-08-13-bounded-cold-blank-verification.md)移除了 mtime 排序,并把 cache 保守的「过旧」错误方向作为现阶段取舍。 -已附加会话的那个投影有真正的修复办法(`lastActivityTime()` 会跳过边界),但它需要事件日志,而冷路径有意不去读日志。为计算 `updatedAt` 而读取日志,会让只读 header 的列举失去意义,而正是它让 `list()` 的开销随会话数量而非日志体量增长。 +已附加摘要可以折叠实时事件日志并选择最新的真人 `user/message`,但冷路径有意不读取大日志。为计算 `updatedAt` 而读取每一份日志,会让 `list()` 的开销随对话总字节数而非 Session 数量增长。用于 metadata 验证的 1 KiB 冷读取可以让符合条件的小产物得到精确的最近时间,但不能让大日志的排序精确。 -[边界那次变更](../../implemented/architecture/2026-07-30-session-end-seed-log-boundary.md)提高了这个缺陷的出现频率,因为一次拾起如今会在此前完全无写入的路径上产生写入;`dsh-host-apiproxy` 的 README 已在 Known Limitations 中记录该项。它并没有引入这套近似做法,而移除这套近似是一项持久格式决策,因此它的范围划在本文,而不是那里。 +让冷排序变得精确仍是一项持久格式决策,因此其范围留在本文,而不是网关 workaround 中。 ## 提案 -把最后活动时间存到列举本就会读取的地方,也就是会话索引,这样 `summarizeCold()` 无需打开日志就能给出答案。该值由协调器计算,因为它看得到每一次追加,而且本就拥有每 id 状态;由后端负责持久化。这样它就成为 `PersistenceBackend` 约定中新增的一个要素,而不是各后端本地的账目,同时让「活动」只保留一个定义,与日志内的 `lastActivityTime()` 共用。 +把最新真人 prompt 时间存到列举本就会读取的 Session 索引,这样 `summarizeCold()` 无需打开日志或依赖 cache checkpoint 就能给出答案。该值由协调器计算,因为它看得到每一次追加,而且本就拥有每 id 状态;由后端负责持久化。这样它就成为 `PersistenceBackend` 约定中新增的一个要素,而不是各后端本地账目,并与已附加投影使用同一个事件谓词:`source.kind` 为 `user` 的 `user/message`。 两个已交付的后端受到的约束正好相反,本提案对它们有意采取不对称的处理: @@ -25,7 +25,7 @@ mtime 回答的是另一个问题:这份产物上次是什么时候被写入 实现之前必须回答三个问题,本文对它们都没有定论: -**哪些事件算作活动?** 对日志而言,`lastActivityTime()` 通过排除 `session/end-seed` 回答了这个问题。一个已存储字段是在写入时编码这条规则的,而写入方在那里只看到一个批次,不是整份日志。两者不得发生漂移,否则已附加表层与冷表层会对同一个会话给出彼此矛盾的答案。 +**共享谓词由谁拥有?** 已存储字段在写入时编码规则,写入方只看到一个批次,而已附加摘要折叠整份日志。两者必须使用同一个导出的事件谓词或 reducer,避免新的消息来源变体让已附加排序与冷排序发生分歧。 **该字段引入之前的日志表现如何?** 既有产物里没有这个值。回退到 mtime 能让它们保持今天的准确度;回退到 `createdAt` 是诚实的,但会把选择器和会话树里每一个既有会话都重新排一次序。 @@ -39,28 +39,29 @@ mtime 回答的是另一个问题:这份产物上次是什么时候被写入 **仅在确实发生了修复时才写入边界。** 这能降低出现频率,而[边界 Agent Note](../../implemented/architecture/2026-07-30-session-end-seed-log-boundary.md)已经否决过它:谓词对有序重启同样必须成立。用一条正确性不变式去换时间戳的准确度,方向是错的。 -**从投影缓存派生活动时间。** `session-projection-cache` 本就会折叠水位线之后的尾部,因此一个最后活动单元可以搭乘既有机制。它作为主形态被否决,因为该缓存是一个可选的组合项;只有挂载了缓存插件才提供的列举,会让排序取决于如何组合。 +**从投影缓存派生活动时间。** 这是当前的过渡实现。`session-projection-cache` 会折叠水位线之后的尾部,无需改变持久格式,但它是可选且 fail-soft 的。缺失或 checkpoint 延迟会让排序取决于 cache 是否存在以及是否新鲜,因此无法提供本文所提议的权威值。 ## 验收标准 - 冷会话的 `SessionSummary.updatedAt` 等于已附加会话的投影为同一个会话报告的那个值;验证方式是恢复、不跑轮次就退出,并断言两条路径上的顺序都没有变化。 - 在 web 会话树和 TUI 恢复选择器中,一个恢复后即被弃置的会话不会排到此后工作过的会话之前;由一份组装后的快照钉住,而不是只靠单元测试。 -- 活动规则只有一个定义:一个测试证明,在一份同时包含边界、closer 和一个普通轮次的日志上,已存储字段与 `lastActivityTime()` 的结果一致。 +- prompt 时间规则只有一个定义:一个测试证明,在包含真人 prompt、注入式 user message、边界和 closer 的日志上,已存储字段与已附加折叠结果一致。 - 在选定的回退方案下,该字段引入之前的产物能够无错误地加载和列举,并且该回退在排序上的后果有断言覆盖。 - 按本仓库不做迁移的立场,SQLite 的 `SCHEMA_VERSION` 递增会拒绝旧的磁盘版本。 ## 风险 -**「活动」的两个定义发生漂移。** 已存储字段按批次计算,而投影在整份日志上计算。一种新事件类型若在写入时按一种方式归类、在读取时按另一种方式归类,就会产生一个冷排序与已附加排序彼此矛盾的会话;这个缺陷只在重启之后才显现,而那正是最难被注意到的地方。 +**prompt 时间的两个定义发生漂移。** 已存储字段按批次计算,而投影在整份日志上计算。一种新消息来源若在写入时按一种方式归类、在读取时按另一种方式归类,就会产生冷排序与已附加排序彼此矛盾的 Session;该缺陷只会在重启后显现。 **JSONL 的伴随文件可能与它的日志不一致。** 在日志追加与伴随文件写入之间发生崩溃,会留下一个陈旧的值,而且没有撕裂尾部标记可用来修复它。每个消费方都得把伴随文件当作一条提示来对待,而这与 mtime 今天的地位已经很接近了。 **回退方案会让既有会话重新排序。** 无论选定哪种回退,持有既有日志的用户都会在升级时看到自己的选择器和会话树重新排一次序。选 `createdAt` 会让这次重排的幅度很大。 -**代价可能超过这个缺陷本身。** 该缺陷是被弃置会话的排序出错。如果对 JSONL 来说诚实的答案是「保留这套近似」,那么本文的结局可能是记录下这个决定,而不是实现一个字段,而这也是一个可以接受的结局。 +**代价可能超过这个缺陷本身。** 剩余缺陷是 projection metadata 缺失或延迟时的保守错序。如果对 JSONL 来说诚实的答案是「保留 cache 回退」,那么本文的结局可能是记录该决定,而不是实现一个字段。 ## 相关 -- [种子结束日志边界](../../implemented/architecture/2026-07-30-session-end-seed-log-boundary.md)——mtime 会计入的非活动写入之一;`dsh-session` 拥有 `lastActivityTime()`,也就是一个已存储字段必须与之保持一致的那个日志内投影。 +- [有界冷空白验证](../../implemented/bug-fix/2026-08-13-bounded-cold-blank-verification.md)——移除 mtime 排序,定义 projection cache 的过渡回退,并把直接冷读取限制为小产物 metadata 验证。 +- [种子结束日志边界](../../implemented/architecture/2026-07-30-session-end-seed-log-boundary.md)——让 mtime 不适用的非 prompt 写入之一。 - [会话持久化](../../implemented/architecture/2026-06-14-session-persistence.md)——仅追加与绝不重写这两条不变式,正是它们排除了可变的 JSONL header 字段。 - [共享持久化写入协调器](../../implemented/architecture/2026-06-18-shared-persistence-write-coordinator.md)——一个已存储字段将挂入的那条追加路径。 diff --git a/.agents/skills/dsh-doc-site-sync/SKILL.md b/.agents/skills/dsh-doc-site-sync/SKILL.md index 5d39470d72..91dd42ae8a 100644 --- a/.agents/skills/dsh-doc-site-sync/SKILL.md +++ b/.agents/skills/dsh-doc-site-sync/SKILL.md @@ -49,6 +49,7 @@ Write normal repository-relative Markdown links in canonical docs. The projector - An image is the exception: its file is copied into the generated tree and referenced from there, so the site serves it regardless of repository visibility. It must be a regular file inside the repository. - External URLs, site-absolute URLs, email links, and fragment-only links remain unchanged. - A missing repository-relative target fails projection instead of silently producing a broken link. +- Cross-page fragments use the English GitHub heading id as their canonical id. If an authored heading emits a different VitePress id, place an explicit `` immediately before it; add generated aliases in the owning generator. Do not write website-specific routes into canonical Markdown just to satisfy VitePress. Use `sourceAliases` for directory-style repository links that should resolve to a mapped index page. @@ -68,6 +69,8 @@ Run the focused website gate before treating the mapping as valid: pnpm docs:check ``` +If Markdown link checks pass but the site build reports a missing fragment, follow the `verify-doc-site-fragments` source and target paths. Preserve the English GitHub id with an explicit alias in authored Markdown or in the owning generator. + Before committing a documentation-site change, run: ```sh diff --git a/.github/AGENTS.md b/.github/AGENTS.md index 3e879db8ae..0c1f0dc780 100644 --- a/.github/AGENTS.md +++ b/.github/AGENTS.md @@ -1,3 +1,3 @@ # AGENTS.md — GitHub Actions -Run jobs on Windows runners (`windows-*` labels) under native `pwsh`. The pull-request `windows` job is the deliberate exception: it runs Windows Node under Wine on hosted Linux and blocks `all checks passed`; `windows-native` runs automatically on `windows-2025` (or the self-hosted `[self-hosted, dsh-win-ci, windows]` pool under `DSH_CI_FAILOVER=selfhosted`) but reports independently. The master `serial-windows` standby continuously validates the self-hosted failover target — see the [failover runbook](../.agents/notes/implemented/process/2026-07-26-ci-failover-runbook.md). +Run jobs on Windows runners (`windows-*` labels) under native `pwsh`. The pull-request `windows` job is the deliberate exception: it runs Windows Node under Wine on hosted Linux and blocks `all checks passed`; `windows-native` runs automatically on `windows-2025` (or the self-hosted `[self-hosted, dsh-win-ci, windows]` pool under `DSH_CI_FAILOVER_WINDOWS=selfhosted`) but reports independently. The master `serial-windows` standby continuously validates the self-hosted failover target — see the [failover runbook](../.agents/notes/implemented/process/2026-07-26-ci-failover-runbook.md). diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7bb2bc1518..5e0c006355 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,8 +49,8 @@ jobs: # build-backed consumer tail. The consumer job owns the only Linux build so # all three jobs enter runner allocation independently. # - # FAILOVER: each Linux enterprise job resolves its pool through the - # DSH_CI_FAILOVER repository variable. Unset (normal), the expressions + # FAILOVER (Linux): each Linux enterprise job resolves its pool through the + # DSH_CI_FAILOVER_LINUX repository variable. Unset (normal), the expressions # pick the hosted enterprise pools below. Setting the variable to # 'selfhosted' (repo Settings → Actions → Variables; writer-manageable # repository state — not PR-editable, no merge required) retargets all @@ -58,11 +58,12 @@ jobs: # vm-backup pool and re-running the failed jobs is the entire switch — # see .agents/notes/implemented/process/2026-07-26-ci-failover-runbook.md. The # in-house pool's readiness is re-proven on every master push by the - # serial-linux-selfhosted standby lane below. + # serial-linux-selfhosted standby lane below. The Windows failover switch is + # the separate DSH_CI_FAILOVER_WINDOWS variable on the windows-native job below. node-24: if: github.event_name == 'pull_request' runs-on: >- - ${{ vars.DSH_CI_FAILOVER == 'selfhosted' + ${{ vars.DSH_CI_FAILOVER_LINUX == 'selfhosted' && github.event.pull_request.user.login != 'dependabot[bot]' && fromJSON('["self-hosted", "linux", "x64", "vm-backup"]') || 'dsh-ubuntu-24-04-16core' }} @@ -96,7 +97,7 @@ jobs: # compression and upload on the paid latency-critical path. Skipped # under failover — see the coverage lane's identical rationale. - uses: actions/cache/restore@v4 - if: vars.DSH_CI_FAILOVER != 'selfhosted' || github.event.pull_request.user.login == 'dependabot[bot]' + if: vars.DSH_CI_FAILOVER_LINUX != 'selfhosted' || github.event.pull_request.user.login == 'dependabot[bot]' with: path: ${{ steps.pnpm-store.outputs.path }} key: ${{ runner.os }}-node-${{ env.PRIMARY_NODE_VERSION }}-pnpm-${{ hashFiles('pnpm-lock.yaml') }} @@ -114,7 +115,7 @@ jobs: node-24-coverage: if: github.event_name == 'pull_request' runs-on: >- - ${{ vars.DSH_CI_FAILOVER == 'selfhosted' + ${{ vars.DSH_CI_FAILOVER_LINUX == 'selfhosted' && github.event.pull_request.user.login != 'dependabot[bot]' && fromJSON('["self-hosted", "linux", "x64", "vm-backup"]') || 'dsh-ubuntu-24-04-16core' }} @@ -124,7 +125,7 @@ jobs: # shares one 64-core VM across six always-on runner instances, so each # instance may use eight while keeping the worst case at 8 × 6 = 48 # workers; process-bound suites remain isolated in forks. - DSH_COVERAGE_MAX_WORKERS: ${{ vars.DSH_CI_FAILOVER == 'selfhosted' && github.event.pull_request.user.login != 'dependabot[bot]' && '8' || '6' }} + DSH_COVERAGE_MAX_WORKERS: ${{ vars.DSH_CI_FAILOVER_LINUX == 'selfhosted' && github.event.pull_request.user.login != 'dependabot[bot]' && '8' || '6' }} DSH_GATE_CONCURRENCY: '3' steps: - uses: actions/checkout@v6 @@ -151,7 +152,7 @@ jobs: # already serves warm installs, while restoring the hosted archive # would spend ~52 s pulling ~180 MB into that populated store. - uses: actions/cache/restore@v4 - if: vars.DSH_CI_FAILOVER != 'selfhosted' || github.event.pull_request.user.login == 'dependabot[bot]' + if: vars.DSH_CI_FAILOVER_LINUX != 'selfhosted' || github.event.pull_request.user.login == 'dependabot[bot]' with: path: ${{ steps.pnpm-store.outputs.path }} key: ${{ runner.os }}-node-${{ env.PRIMARY_NODE_VERSION }}-pnpm-${{ hashFiles('pnpm-lock.yaml') }} @@ -177,7 +178,7 @@ jobs: node-24-consumers: if: github.event_name == 'pull_request' runs-on: >- - ${{ vars.DSH_CI_FAILOVER == 'selfhosted' + ${{ vars.DSH_CI_FAILOVER_LINUX == 'selfhosted' && github.event.pull_request.user.login != 'dependabot[bot]' && fromJSON('["self-hosted", "linux", "x64", "vm-backup"]') || 'dsh-ubuntu-24-04-16core' }} @@ -188,7 +189,7 @@ jobs: DSH_OXLINT_THREADS: '8' DSH_PUBLINT_CONCURRENCY: '8' # Failover halves snapshot concurrency for the shared 64-core VM. - DSH_SNAPSHOT_MAX_CONCURRENCY: ${{ vars.DSH_CI_FAILOVER == 'selfhosted' && github.event.pull_request.user.login != 'dependabot[bot]' && '12' || '32' }} + DSH_SNAPSHOT_MAX_CONCURRENCY: ${{ vars.DSH_CI_FAILOVER_LINUX == 'selfhosted' && github.event.pull_request.user.login != 'dependabot[bot]' && '12' || '32' }} steps: - uses: actions/checkout@v6 with: @@ -212,7 +213,7 @@ jobs: # Skipped under failover — see the coverage lane's identical rationale. - uses: actions/cache/restore@v4 - if: vars.DSH_CI_FAILOVER != 'selfhosted' || github.event.pull_request.user.login == 'dependabot[bot]' + if: vars.DSH_CI_FAILOVER_LINUX != 'selfhosted' || github.event.pull_request.user.login == 'dependabot[bot]' with: path: ${{ steps.pnpm-store.outputs.path }} key: ${{ runner.os }}-node-${{ env.PRIMARY_NODE_VERSION }}-pnpm-${{ hashFiles('pnpm-lock.yaml') }} @@ -222,7 +223,7 @@ jobs: # Pull requests restore the cache normally produced by serial-linux on # master; they do not pay compression and upload on the required path. - uses: actions/cache/restore@v4 - if: vars.DSH_CI_FAILOVER != 'selfhosted' || github.event.pull_request.user.login == 'dependabot[bot]' + if: vars.DSH_CI_FAILOVER_LINUX != 'selfhosted' || github.event.pull_request.user.login == 'dependabot[bot]' with: path: ~/.cache/ms-playwright key: ${{ runner.os }}-playwright-${{ hashFiles('pnpm-lock.yaml') }} @@ -243,13 +244,13 @@ jobs: exit "$sandbox_status" - name: Install Playwright Chromium and hosted dependencies - if: vars.DSH_CI_FAILOVER != 'selfhosted' || github.event.pull_request.user.login == 'dependabot[bot]' + if: vars.DSH_CI_FAILOVER_LINUX != 'selfhosted' || github.event.pull_request.user.login == 'dependabot[bot]' run: pnpm --filter @deepseek-ai/dsh-web-frontend exec playwright install --with-deps chromium # The persistent VM image owns Playwright's Linux system packages; do # not mutate the shared host with apt on every failover run. - name: Install Playwright Chromium on the failover VM - if: vars.DSH_CI_FAILOVER == 'selfhosted' && github.event.pull_request.user.login != 'dependabot[bot]' + if: vars.DSH_CI_FAILOVER_LINUX == 'selfhosted' && github.event.pull_request.user.login != 'dependabot[bot]' run: pnpm --filter @deepseek-ai/dsh-web-frontend exec playwright install chromium - name: Run compatibility, snapshot, and artifact gates @@ -437,18 +438,21 @@ jobs: # its own unmasked conclusion but is deliberately absent from # all-checks-passed.needs, so it never delays or changes that required # verdict. Under normal operation it runs on the hosted larger runner; under - # failover (DSH_CI_FAILOVER=selfhosted) it retargets onto the in-house - # self-hosted Windows pool. Dependabot PRs are excluded from the self-hosted - # pool and stay queued for the hosted runner — see the failover runbook. + # Windows failover (DSH_CI_FAILOVER_WINDOWS=selfhosted) it retargets onto the + # in-house self-hosted Windows pool. Dependabot PRs are excluded from the + # self-hosted pool and stay queued for the hosted runner — see the failover + # runbook. This Windows switch is independent of the Linux + # DSH_CI_FAILOVER_LINUX variable that retargets the three required Linux jobs + # and the all-checks-passed verdict above. windows-native: if: github.event_name == 'pull_request' runs-on: >- - ${{ vars.DSH_CI_FAILOVER == 'selfhosted' + ${{ vars.DSH_CI_FAILOVER_WINDOWS == 'selfhosted' && github.event.pull_request.user.login != 'dependabot[bot]' && fromJSON('["self-hosted", "dsh-win-ci", "windows"]') || 'dsh-windows-2025-16core' }} name: windows node 24 / native complete - timeout-minutes: 60 + timeout-minutes: 120 env: DSH_COVERAGE_MAX_WORKERS: '2' DSH_GATE_CONCURRENCY: '2' @@ -558,7 +562,7 @@ jobs: # re-runs the complete unsharded aggregate on the persistent 64-core VM, # continuously proving that environment can take over a required lane if # the hosted pools degrade (the switch is then setting the writer-manageable - # DSH_CI_FAILOVER variable — see the failover runbook, no merge required). + # DSH_CI_FAILOVER_LINUX variable — see the failover runbook, no merge required). # Push-triggered, so this lane always executes the base branch's own # workflow definition. (Under failover, pull_request jobs do reach these # runners with the PR merge ref's workflow — the boundary there is @@ -644,18 +648,18 @@ jobs: # move re-runs the complete unsharded Windows gate inventory on the persistent # VM, continuously proving that environment can take over the required # `windows` lane if the hosted pool degrades (the switch is setting the - # writer-manageable DSH_CI_FAILOVER variable — see the failover runbook, no - # merge required). Push-triggered, so this lane always executes the base - # branch's own workflow definition. Non-blocking for pull requests; absent - # from all-checks-passed.needs by design — the required `windows` job owns - # the PR verdict. No cache steps because the VM's persistent pnpm store + # writer-manageable DSH_CI_FAILOVER_WINDOWS variable — see the failover + # runbook, no merge required). Push-triggered, so this lane always executes + # the base branch's own workflow definition. Non-blocking for pull requests; + # absent from all-checks-passed.needs by design — the required `windows` job + # owns the PR verdict. No cache steps because the VM's persistent pnpm store # and tool caches make them redundant (and saving here would poison the # hosted cache namespace with self-hosted paths). serial-windows: if: github.event_name == 'push' && github.ref == 'refs/heads/master' name: serial / windows (self-hosted standby) runs-on: [self-hosted, dsh-win-ci, windows] - timeout-minutes: 60 + timeout-minutes: 120 steps: - uses: actions/checkout@v6 @@ -911,11 +915,13 @@ jobs: all-checks-passed: name: all checks passed # This bookkeeping-only verdict must not depend on custom-pool - # provisioning — and under failover it follows the same selector as the - # worker jobs it aggregates, so a standard-hosted outage cannot strand - # the branch-protection verdict either. + # provisioning — and under Linux failover it follows the same selector as + # the worker jobs it aggregates, so a standard-hosted outage cannot strand + # the branch-protection verdict either. It retargets with the Linux switch + # (DSH_CI_FAILOVER_LINUX), not the Windows one, because it aggregates the + # required Linux workers and runs on the vm-backup pool. runs-on: >- - ${{ vars.DSH_CI_FAILOVER == 'selfhosted' + ${{ vars.DSH_CI_FAILOVER_LINUX == 'selfhosted' && github.event.pull_request.user.login != 'dependabot[bot]' && fromJSON('["self-hosted", "linux", "x64", "vm-backup"]') || 'ubuntu-latest' }} diff --git a/.github/workflows/docs-pages.yml b/.github/workflows/docs-pages.yml index 6336089a41..78bdafdf5b 100644 --- a/.github/workflows/docs-pages.yml +++ b/.github/workflows/docs-pages.yml @@ -23,6 +23,9 @@ permissions: env: PRIMARY_NODE_VERSION: '24' + # Projected source links target the public repository, whose history can + # differ from this workflow's source repository. + DOCS_REPOSITORY_REF: master # CI runs must never report to the production telemetry endpoint baked # into apps/cli/cordis.yml (AppCLIEntry disables the row when set). DSH_TELEMETRY_DISABLED: '1' diff --git a/.github/workflows/landlock-run-release.yml b/.github/workflows/landlock-run-release.yml index 8448af1ad1..76d08e9e4c 100644 --- a/.github/workflows/landlock-run-release.yml +++ b/.github/workflows/landlock-run-release.yml @@ -147,6 +147,12 @@ jobs: contents: read id-token: write steps: + # The publish script is the only repository file this job needs, and it + # imports nothing outside Node's builtins, so there is no install step. + - uses: actions/checkout@v4 + with: + persist-credentials: false + - uses: actions/setup-node@v4 with: node-version: 24 @@ -167,12 +173,8 @@ jobs: fi - name: Publish tarballs - run: | - version="${GITHUB_REF#refs/tags/landlock-run-v}" - tag_args=() - case "$version" in *-*) tag_args=(--tag next);; esac - while IFS= read -r tarball; do - # No --access: publishConfig.access in each manifest decides, and a - # command-line flag would override it. - npm publish "dist/npm/${tarball}" "${tag_args[@]}" - done < dist/npm/publish-order.txt + # Publication is decided per package against the registry, so re-running + # this job over the same artifact skips what already landed instead of + # failing on it. A bare `npm publish` loop could not be retried: the + # registry answers a repeat of an existing version permanently. + run: node ./scripts/publish-release.mjs dist/npm diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index cab178a3d2..2e20c215fd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -81,8 +81,10 @@ jobs: run: pnpm run release:pack --family dsh --out dist/npm # The harness packages declare the vendored framework as a peer, and this - # job has no credentials for the private registry, so the verification - # installs that family's pack output too. Only dist/npm is published. + # verification must not depend on the registry already carrying matching + # versions — one pull request may bump both families before either + # publishes — so it installs that family's pack output too. Only dist/npm + # is published. - name: Pack the vendored framework for verification run: pnpm run release:pack --family vendor --out dist/npm-vendor diff --git a/AGENTS.md b/AGENTS.md index d6e3b6cfc0..53f4d17bdb 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -106,7 +106,7 @@ Real-API tests and demos read `DEEPSEEK_API_KEY`, optional `DEEPSEEK_BASE_URL`, - **Waterfall listeners MUST call `next()`** to delegate; returning without it short-circuits the chain ([semantics](docs/cordis-primer.md#cordis-waterfall-semantics)). - **Model-visible ⟺ logged**: anything that reaches a model request must be reconstructable from the session log; a new model-visible input requires a session event. - **Plugins, not loop changes**: new behavior goes on documented extension points; changing `agent-loop` requires updating docs/architecture.md. -- **A capability seam comprises Service Definition / Service provider / Consumer roles.** It is complete, never one role; split only when roles evolve independently ([glossary](docs/glossary.md#capability-seam)). +- **A capability seam comprises Service Definition / Service Provider / Consumer roles.** It is complete, never one role; split only when roles evolve independently ([glossary](docs/glossary.md#capability-seam)). - **Prefer maintained dependencies over hand-rolling** when they genuinely delete owned code and tests ([policy](.agents/notes/implemented/process/2026-07-26-dependencies-over-hand-rolling.md)). - **Explicit > implicit at package boundaries**: defaulting is an explicit `resolve(request): Spec` step in the owning implementation, never a hidden `?? default` inside `run()` (the `dsh-shell` request/spec split is the template). - **No hardcoded tunables in plugins**: deployment-varying choices are validated `Config` fields changeable from cordis.yml; a `DEFAULT_*` constant or test hook is not configurability. Protocol constants, external specs, and security invariants stay fixed. diff --git a/LICENSE b/LICENSE index d03c77437e..c1f7a78e89 100644 --- a/LICENSE +++ b/LICENSE @@ -1,28 +1,21 @@ -BSD 3-Clause License +MIT License -Copyright (c) 2026, DeepSeek +Copyright (c) 2026 DeepSeek -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.i18n.yaml b/README.i18n.yaml index a71b0b8ade..47ae1591e8 100644 --- a/README.i18n.yaml +++ b/README.i18n.yaml @@ -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 README.md -README.md: 891098974433535fa65863c80c512d3818e75955 -README.zh.md: 7a5b1a9219c8442fca7deabdff45ee4323bba840 +README.md: 8a4bd01332a23ce4144c661784bc549e0ba72d21 +README.zh.md: b7bc214bfb1fd8a76a47de3f0aa242122aeb7603 diff --git a/README.md b/README.md index 8910989744..8a4bd01332 100644 --- a/README.md +++ b/README.md @@ -2,31 +2,29 @@ English | [中文](README.zh.md) -DeepSeek Harness (`dsh`) is an open-source coding agent and plugin-based agent harness. +DeepSeek Harness (`dsh`) is an open-source agent harness developed by [DeepSeek AI](https://deepseek.com). -It uses an architecture where **everything is a plugin**. +It uses an architecture where **everything is a plugin**, and is powered by [Cordis](https://github.com/cordiverse/cordis), whose design is described in [_A Programming Paradigm for Spatiotemporal Composability_](https://github.com/cordiverse/paper). -## Internal testing notice +## Developer preview -DeepSeek Harness is under internal testing. Features and interfaces may change. - -Session Logs stay local by default. Set `DSH_TELEMETRY_MODE=FEEDBACK_ONLY` to share a Session Log only when submitting feedback, or `DSH_TELEMETRY_MODE=FULL` to upload continuously; `FULL` also enables dsh-sdk command telemetry reporting an anonymous ID, the command result, and redacted project configuration. Send feedback through the internal WeChat group. +DeepSeek Harness is currently in _developer preview_ and is iterating rapidly. **THERE WILL BE COMPATIBILITY-BREAKING CHANGES.** ## Run -Install Node.js ^22.19 or >= 24 and pnpm 11, then run the published package: +### Run from `npm` + +Install `Node.js`, then run: ```sh npx @deepseek-ai/dsh web ``` -The command initializes the Web profile and prints the Web UI URL, which is `http://127.0.0.1:3080` by default. Open it, add a DeepSeek API key under **Settings → Models**, then start a session. The invoking directory is the default workspace; try `Summarize this repository and identify its main packages.` - -Continue with the [Web UI guide](docs/user/guide/index.md). +The command starts the Web UI, served at `http://127.0.0.1:3080` by default. See [Web UI guide](docs/user/guide/index.md). ### Run from source -To run a repository checkout instead: +To run from a repository checkout: ```sh git clone https://github.com/deepseek-ai/deepseek-harness.git @@ -36,37 +34,24 @@ pnpm run build pnpm dsh web ``` -`pnpm run build` prepares the repository artifacts. `pnpm dsh web` starts the Web UI without rebuilding and opens the same path. +## Community and support -## Profiles and plugins +- Feel free to submit feedback or bug reports through [GitHub Discussions](https://github.com/deepseek-ai/deepseek-harness/discussions). +- Add the [`dsh-plugin`](https://github.com/topics/dsh-plugin) topic to your plugin repository for discoverability. +- Join DeepSeek Harness Discord community. -A profile is an ordered list of plugin bundles. The shipped `web` profile powers `dsh web`. Manage a profile with `dsh plugin --profile `, which forwards the remaining arguments to pnpm in that profile's directory: +## Contributing -```sh -npx -p @deepseek-ai/dsh dsh plugin --profile web add -npx -p @deepseek-ai/dsh dsh plugin --profile web remove -``` - -`add`, `remove`, `update`, `why`, and other pnpm commands work unchanged. The command initializes a missing profile before changing its packages and updates its bundle list from installed packages that declare `dsh.bundle`. See the [CLI reference](apps/cli/reference/README.md#plugin-management) for the exact behavior. - -The [CLI reference](apps/cli/README.md) covers headless execution and custom profiles. The [Python SDK](python/README.md) and [examples](examples/README.md) cover programmatic and custom compositions. - -## Community - -Follow DeepSeek Harness on Twitter for project updates. +See [CONTRIBUTING.md](CONTRIBUTING.md). ## Development -Start with the [development guide](docs/development.md) and read the [architecture](docs/architecture.md) before changing packages. +Start with the [development guide](docs/development.md) and [architecture documentation](docs/architecture.md). For agents, follow [AGENTS.md](AGENTS.md). ## License -[BSD 3-Clause](LICENSE) +[MIT](LICENSE) Third-party dependencies and their licenses are disclosed in [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md). - -## Contributing - -Read [CONTRIBUTING.md](CONTRIBUTING.md) before contributing to this repository. diff --git a/README.zh.md b/README.zh.md index 7a5b1a9219..b7bc214bfb 100644 --- a/README.zh.md +++ b/README.zh.md @@ -2,28 +2,25 @@ [English](README.md) | 中文 -DeepSeek Harness(`dsh`)是一款开源 coding agent(编程智能体),也是一个基于插件的 agent harness(智能体框架)。 +DeepSeek Harness(`dsh`)是由 [DeepSeek AI](https://deepseek.com) 开发的开源 agent harness(智能体框架)。 -它采用了**一切皆插件**的架构。 +它采用**一切皆插件**的架构,并由 [Cordis](https://github.com/cordiverse/cordis) 驱动,其设计参见论文 [_A Programming Paradigm for Spatiotemporal Composability_](https://github.com/cordiverse/paper)。 -## 内测说明 - -DeepSeek Harness 正处于内部测试阶段,功能和接口可能发生变化。 - -Session Log 默认留在本地。设置 `DSH_TELEMETRY_MODE=FEEDBACK_ONLY` 可仅在提交反馈时共享 Session Log,设置 `DSH_TELEMETRY_MODE=FULL` 可持续上传;`FULL` 同时会启用 dsh-sdk 命令遥测,上报匿名 ID、命令结果以及脱敏后的项目配置。请通过内部企业微信群反馈问题和建议。 +## 开发者预览 +DeepSeek Harness 目前处于 _开发者预览_ 阶段,正在快速迭代。**未来将出现破坏兼容性的变更。** ## 运行 -请先安装 Node.js(版本要求:`^22.19` 或 `>=24`)和 pnpm 11,然后运行已发布的包: +### 通过 `npm` 运行 + +安装 `Node.js`,然后运行: ```sh npx @deepseek-ai/dsh web ``` -该命令会初始化 Web profile 并打印 Web UI 地址,默认地址为 `http://127.0.0.1:3080`。打开该地址,在**设置 → 模型**中添加 DeepSeek API 密钥,然后启动一个会话。运行命令时所在的目录将作为默认工作区;你可以尝试输入 `Summarize this repository and identify its main packages.`。 - -下一步请阅读 [Web UI 指南](docs/user/guide/index.md)。 +该命令会启动 Web UI,默认地址为 `http://127.0.0.1:3080`。详见 [Web UI 指南](docs/user/guide/index.md)。 ### 从源码运行 @@ -37,41 +34,41 @@ pnpm run build pnpm dsh web ``` -`pnpm run build` 会准备仓库产物。`pnpm dsh web` 不会重新构建,而是直接启动同一个 Web UI。 +## 社区与支持 -## Profile 与插件 +- 欢迎通过 [GitHub Discussions](https://github.com/deepseek-ai/deepseek-harness/discussions) 提交反馈或 bug 报告。 +- 为你的插件仓库添加 [`dsh-plugin`](https://github.com/topics/dsh-plugin) 话题,便于被发现。 +- 欢迎加入 DeepSeek Harness 企微群:扫码添加企微小助手并填写入群问卷,完成后小助手会邀请你入群。 -profile 由一组按顺序排列的插件组合包构成。随附的 `web` profile 用于运行 `dsh web`。使用 `dsh plugin --profile ` 管理 profile;该命令会在对应 profile 目录中将剩余参数转发给 pnpm: - -```sh -npx -p @deepseek-ai/dsh dsh plugin --profile web add -npx -p @deepseek-ai/dsh dsh plugin --profile web remove -``` - -`add`、`remove`、`update`、`why` 等 pnpm 命令均可直接使用。该命令会先初始化不存在的 profile,再修改其中的包,并根据声明了 `dsh.bundle` 的已安装包更新 bundle 列表。具体行为见 [CLI 参考](apps/cli/reference/README.md#plugin-management)。 - -[CLI(命令行界面)参考](apps/cli/README.md)介绍 headless 执行与自定义 profile。[Python SDK](python/README.md) 和[示例](examples/README.md)介绍程序化组合与自定义组合。 - -## 社区 - -扫描二维码,或打开 DeepSeek Harness 微信社区申请页面 申请加入。 - -

- DeepSeek Harness 微信社区二维码 -

- -## 开发 - -请先阅读[开发指南](docs/development.md);修改包之前,请阅读[架构文档](docs/architecture.md)。 - -面向 agent:遵循 [AGENTS.md](AGENTS.md)。 - -## 许可证 - -[BSD 3-Clause](LICENSE) - -第三方依赖及其许可证见 [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md)。 + + + + + + + + + + + + + + + +
企微小助手入群问卷微信公众号
DeepSeek Harness 企微小助手二维码DeepSeek Harness 入群问卷二维码DeepSeek Harness 团队微信公众号二维码
## 参与贡献 -向本仓库贡献前,请阅读 [CONTRIBUTING.md](CONTRIBUTING.md)。 +参见 [CONTRIBUTING.md](CONTRIBUTING.md)。 + +## 开发 + +请先阅读[开发指南](docs/development.md)与[架构文档](docs/architecture.md)。 + +面向 agent:请遵循 [AGENTS.md](AGENTS.md)。 + +## 许可证 + +[MIT](LICENSE) + +第三方依赖及其许可证见 [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md)。 diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md index 49d5e15b47..92b218ff33 100644 --- a/THIRD_PARTY_NOTICES.md +++ b/THIRD_PARTY_NOTICES.md @@ -3,7 +3,7 @@ # Third-Party Notices -DeepSeek Harness is licensed under [BSD 3-Clause](LICENSE). It depends on the third-party software listed below. Each project remains under its own license; nothing in this file changes those terms. +DeepSeek Harness is licensed under [MIT](LICENSE). It depends on the third-party software listed below. Each project remains under its own license; nothing in this file changes those terms. This file lists **direct** dependencies declared by the workspace and the explicitly disclosed official Claude platform payload closure. It is generated from the workspace manifests by `scripts/gen-third-party-notices.ts`: a pre-commit hook regenerates it whenever a staged file changes one of its inputs, and `scripts/gen-third-party-notices.spec.ts` asserts in the test lane that the committed bytes match. Deleting a manifest runs no hook, so that case is caught by the assertion instead. Run `pnpm run verify-third-party-notices` for the standalone check. diff --git a/apps/cli/README.i18n.yaml b/apps/cli/README.i18n.yaml index 9285fa6c1d..f270fdf882 100644 --- a/apps/cli/README.i18n.yaml +++ b/apps/cli/README.i18n.yaml @@ -3,4 +3,4 @@ # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write apps/cli/README.md README.md: 9a8d722b044ed5d8e31e3c27e54f8c9ef0839f82 -README.zh.md: dc40a4a6f54f99507bccb6b989aee0015e9604b3 +README.zh.md: 7889b4180b5ce2f65550f98708d498f324ac349d diff --git a/apps/cli/README.zh.md b/apps/cli/README.zh.md index dc40a4a6f5..7889b4180b 100644 --- a/apps/cli/README.zh.md +++ b/apps/cli/README.zh.md @@ -2,22 +2,22 @@ [English](README.md) | 中文 -`dsh` 命令是 profile 的产品启动器:profile 是按序叠放的插件组合包 patch 层,之上再叠加用户自己的覆盖层。[`src/args.ts`](src/args.ts) 负责命令语法,[`src/bin.ts`](src/bin.ts) 只加载选中的运行器。无效命令、来自其他模式的选项、配置错误和启动失败都会以非零状态退出。 +`dsh` 是 DeepSeek Harness 中用于启动 profile 的命令;profile 由多个插件组合包 patch 层按顺序叠加而成,其上再应用用户自己的覆盖配置。[`src/args.ts`](src/args.ts) 负责命令语法,[`src/bin.ts`](src/bin.ts) 只加载选中的运行器。无效命令、来自其他模式的选项、配置错误和启动失败都会以非零状态退出。 ## 入口模式 | 命令 | 用途 | |---|---| | `dsh --profile ` | 启动位于 `$DSH_HOME/profiles/` 的指定 profile。 | -| `dsh --profile headless "job"` | 运行一个新的持久化会话,打印最终答案并退出。 | +| `dsh --profile headless "job"` | 运行一个全新的持久化会话,打印最终答案并退出。 | | `dsh web` | `--profile web` 的别名。 | | `dsh plugin --profile ` | 通过在 profile 目录中转发给 pnpm 来管理该 profile 的插件。 | -调用目录是默认 workspace 根目录。`web` 和 `headless` profile 在首次使用时会从随附模板自动初始化;其他任何 profile 都必须通过 `dsh plugin` 创建。 +运行命令时所在的目录将作为默认 workspace 根目录。`web` 和 `headless` profile 在首次使用时会从随附模板自动初始化;其他任何 profile 都必须通过 `dsh plugin` 创建。 ## 应用参数 -启动器只解析属于自己的 flag,并把其后的一切交给启动起来的 profile,任何注入它的应用插件都可以解析这份共享的不可变快照([`dsh-cmdline`](../../packages/boot/cmdline/README.md))。因此启动器的 flag 必须写在前面,而启动器不认识的第一个 token 就是应用参数的起点: +启动器只解析自身的 flag,并将其后的所有内容交给已启动的 profile;注入该 profile 的任意应用插件都可以解析这份共享的不可变快照([`dsh-cmdline`](../../packages/boot/cmdline/README.md))。因此,启动器的 flag 必须写在最前面;启动器无法识别的第一个 token 标志着应用参数的开始: ```sh dsh --profile web --port 8080 # --port belongs to the web app @@ -29,19 +29,19 @@ dsh --help # the launcher's own help ## Profile -profile 目录包含一个 `package.json`(树外插件依赖,加上 profile manifest(元数据清单)`dsh.profile` 及其有序的 `bundles` 列表)和一个 `cordis.patch.yml`(用户自己的 patch 层)。 +profile 目录包含一个 `package.json`,其中记录树外插件依赖,以及 profile manifest(元数据清单)`dsh.profile` 和其中按顺序排列的 `bundles` 列表;还包含一个 `cordis.patch.yml`,其中保存用户自己的 patch 层。 -配置树在空根之上组合: -- 先按 `dsh.profile.bundles` 顺序应用各组合包的 patch -- 然后是 profile 的 `cordis.patch.yml`,然后是 home 级的 `$DSH_HOME/cordis.patch.yml` -- 最后是 `--patch` overlay +配置树以空根为起点,依次叠加以下配置层: +- `dsh.profile.bundles` 中各组合包的 patch +- profile 自身的 `cordis.patch.yml`,然后是 home 级的 `$DSH_HOME/cordis.patch.yml` +- `--patch` 指定的覆盖层 -`dsh.profile.bundles` 中列出的组合包先从 dsh 安装目录解析(`@deepseek-ai/dsh-base`、`@deepseek-ai/dsh-web-app`、`@deepseek-ai/dsh-headless`),再从 profile 自己的 `node_modules` 解析;pnpm 把树外插件安装在后者。 +`dsh.profile.bundles` 中列出的组合包先从 dsh 安装目录解析(`@deepseek-ai/dsh-base`、`@deepseek-ai/dsh-web-app`、`@deepseek-ai/dsh-headless`),再从 profile 自身的 `node_modules` 解析;pnpm 会将树外插件安装到该目录。 使用 `--dump-default-config` 和 `--dump-config` 可在不启动的情况下检查组合后的配置树。 -[CLI(命令行界面)行为参考](reference/README.md)负责确切的层优先级、flag、关闭行为、部署默认值和源码执行。 +层的确切优先级、flag、关闭行为、部署默认值和源码执行方式,以 [CLI(命令行界面)行为参考](reference/README.md)为准。 ## 开发 -生产运行需要已构建的包与前端产物。请在仓库根目录单独运行 `pnpm run build`,然后使用 `pnpm dsh ` 运行 TypeScript 入口并转发所有参数;模块解析约定由[源码执行参考](reference/README.md#source-execution)负责。 +生产运行需要已构建的包与前端产物。请在仓库根目录单独运行 `pnpm run build`,然后使用 `pnpm dsh ` 运行 TypeScript 入口并转发所有参数;模块解析约定以[源码执行参考](reference/README.md#source-execution)为准。 diff --git a/apps/cli/composition.md b/apps/cli/composition.md index 0d56813430..4d37b9186a 100644 --- a/apps/cli/composition.md +++ b/apps/cli/composition.md @@ -114,10 +114,6 @@ flowchart LR cfg --> plugin_dsh_base_subagent_spawn_in_process plugin_dsh_base_subagent_fork_in_process["subagent-fork-in-process
@deepseek-ai/dsh-subagent-fork-in-process"] cfg --> plugin_dsh_base_subagent_fork_in_process - plugin_dsh_base_subagent_codex["subagent-codex
@deepseek-ai/dsh-subagent-codex"] - cfg --> plugin_dsh_base_subagent_codex - plugin_dsh_base_subagent_claude_code["subagent-claude-code
@deepseek-ai/dsh-subagent-claude-code"] - cfg --> plugin_dsh_base_subagent_claude_code plugin_dsh_base_tool_subagent_control["tool-subagent-control
@deepseek-ai/dsh-tool-subagent-control"] cfg --> plugin_dsh_base_tool_subagent_control plugin_dsh_base_tool_subagent_list_agents["tool-subagent-list-agents
@deepseek-ai/dsh-tool-subagent-control/list-agents"] @@ -225,8 +221,6 @@ flowchart LR | `subagent` | `@deepseek-ai/dsh-subagent` | | `subagent-spawn-in-process` | `@deepseek-ai/dsh-subagent-spawn-in-process` | | `subagent-fork-in-process` | `@deepseek-ai/dsh-subagent-fork-in-process` | -| `subagent-codex` | `@deepseek-ai/dsh-subagent-codex` | -| `subagent-claude-code` | `@deepseek-ai/dsh-subagent-claude-code` | | `tool-subagent-control` | `@deepseek-ai/dsh-tool-subagent-control` | | `tool-subagent-list-agents` | `@deepseek-ai/dsh-tool-subagent-control/list-agents` | | `tool-subagent` | `@deepseek-ai/dsh-tool-subagent` | diff --git a/apps/cli/config/agent-presets/code/agent.cordis.yml b/apps/cli/config/agent-presets/code/agent.cordis.yml index fb21c21185..407938e5c8 100644 --- a/apps/cli/config/agent-presets/code/agent.cordis.yml +++ b/apps/cli/config/agent-presets/code/agent.cordis.yml @@ -198,16 +198,16 @@ toolName: subagent_fork backgroundMode: continuable - # Product providers are host-plane singletons. Copy this preset, then - # remove `disabled` from either ordinary tool row to expose that product - # only to agents composed from the copy. + # Production dsh does not install these optional providers. An opting-in + # Profile mounts each provider once on the host plane; copy this preset, + # then remove `disabled` from the matching tool row. - id: tool-subagent-codex name: '@deepseek-ai/dsh-tool-subagent' disabled: true config: provider: codex toolName: subagent_codex - enableRunInBackground: false + backgroundMode: one-shot maxDepth: provider-managed - id: tool-subagent-claude-code @@ -216,7 +216,7 @@ config: provider: claude-code toolName: subagent_claude_code - enableRunInBackground: false + backgroundMode: one-shot maxDepth: provider-managed - id: workflow-worker-thread diff --git a/apps/cli/config/agent-presets/cordis/agent.cordis.yml b/apps/cli/config/agent-presets/cordis/agent.cordis.yml index 598418c3b6..e808250c00 100644 --- a/apps/cli/config/agent-presets/cordis/agent.cordis.yml +++ b/apps/cli/config/agent-presets/cordis/agent.cordis.yml @@ -185,16 +185,16 @@ toolName: subagent_fork backgroundMode: continuable - # Product providers are host-plane singletons. Copy this preset, then - # remove `disabled` from either ordinary tool row to expose that product - # only to agents composed from the copy. + # Production dsh does not install these optional providers. An opting-in + # Profile mounts each provider once on the host plane; copy this preset, + # then remove `disabled` from the matching tool row. - id: tool-subagent-codex name: '@deepseek-ai/dsh-tool-subagent' disabled: true config: provider: codex toolName: subagent_codex - enableRunInBackground: false + backgroundMode: one-shot maxDepth: provider-managed - id: tool-subagent-claude-code @@ -203,7 +203,7 @@ config: provider: claude-code toolName: subagent_claude_code - enableRunInBackground: false + backgroundMode: one-shot maxDepth: provider-managed - id: workflow-worker-thread diff --git a/apps/cli/config/agent-presets/cordis/skills/editing-cordis-compositions/SKILL.md b/apps/cli/config/agent-presets/cordis/skills/editing-cordis-compositions/SKILL.md index 72a3ce35ea..8214e88654 100644 --- a/apps/cli/config/agent-presets/cordis/skills/editing-cordis-compositions/SKILL.md +++ b/apps/cli/config/agent-presets/cordis/skills/editing-cordis-compositions/SKILL.md @@ -123,7 +123,7 @@ After a clean mount-validation, ask the user to start a session on the new prese ## Native product subagents -Codex and Claude Code providers already live in the host composition. A preset chooses either product by contributing the same ordinary delegation-tool row used for spawn and fork; never move a product provider into the preset and never add a product-specific settings field. +Codex and Claude Code providers belong on the host plane but are not installed by production `dsh`. The active Profile must install and mount the selected provider before a preset can expose its ordinary delegation-tool row; never move a product provider into the preset and never add a product-specific settings field. Copy these disabled templates from a shipped full preset and remove `disabled` only for the products the user requested: @@ -134,7 +134,7 @@ Copy these disabled templates from a shipped full preset and remove `disabled` o config: provider: codex toolName: subagent_codex - enableRunInBackground: false + backgroundMode: one-shot maxDepth: provider-managed - id: tool-subagent-claude-code @@ -143,11 +143,11 @@ Copy these disabled templates from a shipped full preset and remove `disabled` o config: provider: claude-code toolName: subagent_claude_code - enableRunInBackground: false + backgroundMode: one-shot maxDepth: provider-managed ``` -The two rows are independent. Leaving both disabled preserves the copied preset, enabling one exposes only that product tool, and enabling both exposes both. The host must provide `codex` or `claude` on `PATH`; the preset does not install, authenticate, select a model for, or probe either product. +The two rows are independent. Leaving both disabled preserves the copied preset, enabling one exposes only that product tool, and enabling both exposes both. Production `dsh` does not install or mount either optional provider: before enabling a row, the Profile must install the matching `@deepseek-ai/dsh-subagent-codex` or `@deepseek-ai/dsh-subagent-claude-code` package and mount it once on the host plane. A preset cannot provide that host dependency. `backgroundMode: one-shot` keeps omitted or `false` calls in the foreground and lets explicit `run_in_background: true` return a generic Job id. Full presets already carry `tool-jobs`, while the base host carries the job registry; retain both so `job_output`, `job_list`, `job_kill`, cancellation, and completion notices stay available. The host must also provide `codex` or `claude` on `PATH`; the preset does not install, authenticate, select a model for, or probe either product. ## What not to move into a preset diff --git a/apps/cli/config/agent-presets/minimal/agent.cordis.yml b/apps/cli/config/agent-presets/minimal/agent.cordis.yml index 1a2336b222..b6ed406f54 100644 --- a/apps/cli/config/agent-presets/minimal/agent.cordis.yml +++ b/apps/cli/config/agent-presets/minimal/agent.cordis.yml @@ -1,15 +1,16 @@ # The `minimal` agent preset: a fixed-prompt, two-tool coding-agent composition. # # The persona is the complete system prompt, so global identity, Web orientation, -# tool guidance, and later assembly listeners cannot add prompt text. The model -# composes only the persistent `bash` and `str_replace_editor` tools. Context -# compaction is deliberately absent. +# tool guidance, and later assembly listeners cannot add prompt text. Runtime +# context snapshots are suppressed for this preset, and the model composes only +# persistent `bash` and `str_replace_editor`. Context compaction is absent. - id: persona name: '@deepseek-ai/dsh-persona' config: text: You are a helpful software engineer assistant. complete: true + includeRuntimeContext: false # The PTY registry is an agent-owned service, so it lives in an entry-local # realm. The backend still consumes the host sandbox policy and subprocess diff --git a/apps/cli/config/agent-presets/standard/agent.cordis.yml b/apps/cli/config/agent-presets/standard/agent.cordis.yml index f0916d9992..b8559cfd74 100644 --- a/apps/cli/config/agent-presets/standard/agent.cordis.yml +++ b/apps/cli/config/agent-presets/standard/agent.cordis.yml @@ -197,16 +197,16 @@ toolName: subagent_fork backgroundMode: continuable - # Product providers are host-plane singletons. Copy this preset, then - # remove `disabled` from either ordinary tool row to expose that product - # only to agents composed from the copy. + # Production dsh does not install these optional providers. An opting-in + # Profile mounts each provider once on the host plane; copy this preset, + # then remove `disabled` from the matching tool row. - id: tool-subagent-codex name: '@deepseek-ai/dsh-tool-subagent' disabled: true config: provider: codex toolName: subagent_codex - enableRunInBackground: false + backgroundMode: one-shot maxDepth: provider-managed - id: tool-subagent-claude-code @@ -215,7 +215,7 @@ config: provider: claude-code toolName: subagent_claude_code - enableRunInBackground: false + backgroundMode: one-shot maxDepth: provider-managed - id: workflow-worker-thread diff --git a/apps/cli/package.json b/apps/cli/package.json index 50251dbc9a..a5f7913c2f 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh", "description": "dsh CLI: profile boot, plugin management, and the browser UI alias", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -18,7 +18,7 @@ "lib/*.js", "config" ], - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "@deepseek-ai/cordis-plugin-hmr": "workspace:^", "@deepseek-ai/cordis-plugin-include": "workspace:^", diff --git a/apps/cli/reference/README.i18n.yaml b/apps/cli/reference/README.i18n.yaml index 89fb45feb7..b62de584e2 100644 --- a/apps/cli/reference/README.i18n.yaml +++ b/apps/cli/reference/README.i18n.yaml @@ -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 apps/cli/reference/README.md -README.md: 0b23db293c304807b5959f5eae9a2faf868caa62 -README.zh.md: 1ca91fb69c3ed34d925f6b8a6454866e82c8dcf7 +README.md: 0be64fdfc0ad4e81d23f25a26881fa89f37565b0 +README.zh.md: 649bf15df814abf4875fed794c2e76c494bfcc25 diff --git a/apps/cli/reference/README.md b/apps/cli/reference/README.md index 0b23db293c..0be64fdfc0 100644 --- a/apps/cli/reference/README.md +++ b/apps/cli/reference/README.md @@ -61,7 +61,7 @@ dsh web --dump-config dsh web --help ``` -The production Web runner needs built package and frontend artifacts (`pnpm run build`). It serves `http://127.0.0.1:3080` by default. Binding all interfaces also trusts the machine's discovered LAN IP literals; `--trusted-host` adds named authorities accepted by the `/api` browser-trust fence. +The production Web runner needs built package and frontend artifacts (`pnpm run build`). It serves `http://127.0.0.1:3080` by default. The CLI intentionally does not support `--host 0.0.0.0` yet and exits with a usage error; `--trusted-host` adds named authorities accepted by the `/api` browser-trust fence. Process shutdown gives the plugin tree up to five seconds to dispose. The first `SIGINT`/`SIGTERM` starts that graceful drain — `SIGTERM` is a supervisor's ordinary stop request and exits 0 on every surface, `SIGINT` reports 130; a second signal forces immediate exit. If one-shot normal completion is already stuck in disposal, the first `Ctrl+C` is the escalation and exits immediately instead of being swallowed. diff --git a/apps/cli/reference/README.zh.md b/apps/cli/reference/README.zh.md index 1ca91fb69c..649bf15df8 100644 --- a/apps/cli/reference/README.zh.md +++ b/apps/cli/reference/README.zh.md @@ -2,25 +2,25 @@ [English](README.md) | 中文 -本参考定义 profile、web 别名、插件管理和配置 dump 命令模式。参数由 [`src/args.ts`](../src/args.ts) 统一解析,[`src/bin.ts`](../src/bin.ts) 只动态导入选中的运行器。 +本参考定义 profile 启动、web 别名、插件管理和配置 dump 等命令模式。argv 由 [`src/args.ts`](../src/args.ts) 统一解析一次,[`src/bin.ts`](../src/bin.ts) 只会动态导入选中的运行器。 ## Profile 启动 -`dsh --profile ` 启动位于 `$DSH_HOME/profiles/` 的 profile。生效配置树在空根节点之上按以下顺序逐层组合:profile manifest(元数据清单)的 `dsh.profile.bundles` 列表所列的各个组合包 patch、profile 自身的 `cordis.patch.yml`、home 级的 `$DSH_HOME/cordis.patch.yml`(各 profile 共享的机器本地偏好,因此优先级高于逐 profile 的层)、以及按 argv 顺序的各个 `--patch ` overlay。后应用的层按行胜出;patch 替换目标行完整的 `config` 值,而不是深度合并各键,并且可以插入新行。配置解析、schema 校验、模块解析或插件启动失败会得到报告并以非零状态退出。收到 SIGINT 或 SIGTERM 时,挂载的根节点会先 dispose(资源释放)再退出。 +`dsh --profile ` 启动位于 `$DSH_HOME/profiles/` 的 profile。生效配置树以空根节点为起点,依次叠加 profile manifest(元数据清单)的 `dsh.profile.bundles` 列表中指定的各组合包 patch、profile 自身的 `cordis.patch.yml`、home 级的 `$DSH_HOME/cordis.patch.yml`(这是各 profile 共享的机器本地偏好,因此优先于逐 profile 配置层),以及按 argv 顺序指定的各个 `--patch ` 覆盖层。对同一配置行,后应用的层优先。patch 会替换目标行的整个 `config` 值,而不是深度合并其中的键;patch 也可以插入新行。配置解析、schema 校验、模块解析或插件启动失败时,系统会报告错误并以非零状态退出。收到 SIGINT 或 SIGTERM 时,挂载的根节点会先 dispose(资源释放)再退出。 -组合包名称先从 dsh 安装解析,再从 profile 目录解析。因此内置组合包(`@deepseek-ai/dsh-base`、`@deepseek-ai/dsh-web-app`、`@deepseek-ai/dsh-headless`)总是来自与正在运行的 `dsh` 相同的安装;树外组合包来自 profile 由 pnpm 管理的 `node_modules`。任何 patch 行中的裸插件 `name` 通过 profile 目录的 Node 父目录逐级查找解析,该查找可达到持续维护的安装后备目录 `$DSH_HOME/profiles/node_modules`(安装的应用和组合包所依赖的每个包对应一个符号链接,每次启动时修复)。 +组合包名称先从 dsh 安装目录解析,再从 profile 目录解析。因此,内置组合包(`@deepseek-ai/dsh-base`、`@deepseek-ai/dsh-web-app`、`@deepseek-ai/dsh-headless`)始终来自当前运行的 `dsh` 所属的安装;树外组合包则来自 profile 中由 pnpm 管理的 `node_modules`。patch 行中的裸插件 `name` 会从 profile 目录开始,按照 Node 的模块解析规则逐级向父目录查找,直至由 dsh 维护的安装后备目录 `$DSH_HOME/profiles/node_modules`。该目录为 dsh 安装中的应用和组合包所依赖的每个包各维护一个符号链接,并在每次启动时修复这些链接。 `web` 和 `headless` profile 首次使用时会从随附模板自动初始化(`web`:base + web-app;`headless`:base + headless)。其他缺失的 profile 会显式报错,并提示运行 `dsh plugin --profile add `。 ### 应用参数 -启动器自己的 flag 写在最前面,并在它不认识的第一个 token 处结束;从那里开始的一切都通过 `ctx.cmdlineArgs` 原样交给启动起来的 profile,任何注入它的应用插件都可以解析([`dsh-cmdline`](../../../packages/boot/cmdline/README.md))。因此 `dsh --profile web --port 8080` 到达的是 web 应用的 `--port`,`dsh --profile web --help` 打印的是该应用的 help 且什么也不启动,而 `dsh --help`(没有可以交付的 profile)打印的是启动器自己的 help。`-V`/`--version` 写在应用参数边界之前时会打印启动器的版本。 +启动器自身的 flag 必须写在最前面,并在遇到第一个无法识别的 token 时结束;从该 token 开始的所有内容都会通过 `ctx.cmdlineArgs` 原样交给已启动的 profile,注入该 profile 的任意应用插件都可以解析这些内容([`dsh-cmdline`](../../../packages/boot/cmdline/README.md))。因此,`dsh --profile web --port 8080` 会将 `--port` 交给 web 应用;`dsh --profile web --help` 只打印该应用的帮助信息,不启动应用;`dsh --help` 没有可供交付参数的 profile,因此会打印启动器自身的帮助信息。`-V`/`--version` 位于应用参数边界之前时,会打印启动器的版本。 -一套组合只挂载一次。普通插件注入 `cmdlineArgs`、解析本应用参数,并把结果作为服务提供出去;由 flag 配置的每一行都会注入该服务,Loader 会等服务激活后再求值该行配置(`port: !!js ctx.webStartup.port ?? 3080`),因此 flag 胜过写在它旁边的值。该优先级要求配置行保留这一表达式;若用户 patch 用字面量替换整份 `config`,运行时读取也会随之消失。help 和被拒绝的参数会请求退出——拒绝时以非零状态,help 时以 0——且不会激活依赖提供方服务的行。在线编辑 `cordis.patch.yml` 会针对仍然在线的服务重新求值表达式,因此不会重置已在服务的端口。 +每套组合只会挂载一次。普通插件注入 `cmdlineArgs`,解析所属应用的参数,并将解析结果作为服务提供。每个从 flag 取值的配置行都会注入该服务;Loader 会等到服务激活后,再对该行的配置求值(`port: !!js ctx.webStartup.port ?? 3080`),因此 flag 的优先级高于配置行中写明的值。要维持这一优先级,配置行必须保留该表达式;如果用户 patch 用字面量替换整个 `config`,也会随之移除运行时读取。帮助参数和被拒绝的参数都会请求退出:参数被拒绝时以非零状态退出,显示帮助时以 0 退出;依赖该提供方服务的配置行不会激活。在线编辑 `cordis.patch.yml` 时,系统会根据仍在运行的服务重新计算表达式,因此不会重置当前正在使用的端口。 启动器的 flag 必须写在应用参数之前,且启动器的解析器会消耗掉一个 `--`:必须以字面量 `--` 送达应用的参数需要写成 `-- --`。如果应用的第一个参数恰好等于 `web` 或 `plugin`,会选择对应的子命令。`ctx.cmdlineArgs.get()` 是共享的不可变读取:多个插件可以解析同一份快照,没有读取方的 profile 则会忽略自己的应用参数。 -随附的各应用持有这些命令行: +随附的应用接受以下命令行参数: | Profile | 参数 | |---|---| @@ -36,11 +36,11 @@ dsh --profile web --dump-default-config dsh --profile web --patch ./extra.yml --dump-config ``` -`--dump-default-config` 只打印组合包各层;`--dump-config` 额外加上 profile 的 `cordis.patch.yml`、home 级的 `$DSH_HOME/cordis.patch.yml` 和 `--patch` overlay。两者都会打印注释,标明每行由哪个文件提供,以及哪些 overlay 修改过它;`!!js` 表达式保持未求值,找不到目标的 patch 会报告到 stderr。dump 从不运行应用命令行提供方,因此它展示的是任何应用参数被解析之前的组合配置树,并拒绝携带应用参数的调用。 +`--dump-default-config` 只打印组合包各层;`--dump-config` 额外加上 profile 的 `cordis.patch.yml`、home 级的 `$DSH_HOME/cordis.patch.yml` 和 `--patch` overlay。两者都会打印注释,标明每行由哪个文件提供,以及哪些 overlay 修改过它;`!!js` 表达式保持未求值,找不到目标的 patch 会报告到 stderr。dump 操作不会运行应用的命令行参数提供方,因此展示的是解析任何应用参数之前的组合配置树;如果调用中包含应用参数,dump 会拒绝该调用。 ## 插件管理 -`dsh plugin --profile ` 在 profile 缺失时先初始化它(有随附模板的用模板,其他名称只装 `@deepseek-ai/dsh-base`),然后以 profile 目录为工作目录,把 `` 转发给 `pnpm`:`add`、`remove`、`why`、`update` 及其他所有 pnpm 子命令都照常可用;pnpm 必须在 PATH 上。相对路径 spec(`.`、`../plugin` 及其 `file:`/`link:` 形式)会先锚定到调用目录,因此在插件 checkout 中执行 `add .` 安装的是该 checkout,而不是 profile。每次成功运行后,`dsh.profile.bundles` 都会与已安装状态对齐:每个解析到 manifest 中声明了 `"dsh": { "bundle": { "patch": "./cordis.patch.yml" } }` 的包的依赖加入层栈(因此让包获得该声明的 `update` 会将其激活),没有组合包声明的依赖保持为普通依赖并给出一次性警告,已移除的依赖则退出层栈。 +`dsh plugin --profile ` 在 profile 缺失时先初始化它(有随附模板的用模板,其他名称只装 `@deepseek-ai/dsh-base`),然后以 profile 目录为工作目录,把 `` 转发给 `pnpm`:`add`、`remove`、`why`、`update` 及其他所有 pnpm 子命令都照常可用;pnpm 必须在 PATH 上。相对路径 spec(`.`、`../plugin` 及其 `file:`/`link:` 形式)会先锚定到调用目录,因此在插件 checkout 中执行 `add .` 安装的是该 checkout,而不是 profile。每次成功运行后,系统都会根据当前安装状态更新 `dsh.profile.bundles`:如果某项依赖解析到的包在 manifest 中声明了 `"dsh": { "bundle": { "patch": "./cordis.patch.yml" } }`,该依赖就会加入配置层栈;如果某项依赖在 `update` 后获得该声明,也会随即激活。没有组合包声明的依赖仍作为普通依赖保留,并显示一次性警告;已移除的依赖则从配置层栈中删除。 ```sh dsh plugin --profile tui add github:deepseek-harness/turtle-ui @@ -48,7 +48,7 @@ dsh plugin --profile tui remove turtle-ui dsh --profile tui ``` -Git 托管、随附源码的插件在安装期间通过其 `prepare` 脚本构建,而 pnpm ≥10 在消费方允许之前会阻止该脚本:首次 `add` 会失败并给出 pnpm 的 `allowBuilds` 提示(以及 dsh 指向该 profile 的 `pnpm-workspace.yaml` 的指引);把打印出的键复制到那里并重新运行即可。安装已构建的 tarball 或本地 checkout 不需要任何允许。 +随源码发布的 Git 托管插件会在安装期间通过 `prepare` 脚本构建,而 pnpm ≥10 默认会阻止该脚本,直到使用方明确允许。首次运行 `add` 会失败,并显示 pnpm 的 `allowBuilds` 提示;dsh 还会提示应修改该 profile 的 `pnpm-workspace.yaml`。将输出的键复制到该文件后,重新运行命令即可。安装已经构建好的 tarball 或本地 checkout 时,无需加入 `allowBuilds`。 ## Web 别名 @@ -61,11 +61,11 @@ dsh web --dump-config dsh web --help ``` -生产 Web 运行器需要已构建的包和前端产物(`pnpm run build`)。默认服务地址是 `http://127.0.0.1:3080`。绑定所有网络接口时,还会信任机器自动发现的 LAN IP 字面量;`--trusted-host` 可添加 `/api` 浏览器信任围栏接受的具名 authority。 +生产 Web 运行器需要已构建的包和前端产物(`pnpm run build`)。默认服务地址是 `http://127.0.0.1:3080`。CLI 目前有意不支持 `--host 0.0.0.0`,并会以用法错误退出;`--trusted-host` 可添加 `/api` 浏览器信任围栏接受的具名 authority。 -进程关闭时会给插件树最多 5 秒完成 dispose。第一次 `SIGINT`/`SIGTERM` 启动该优雅排空——`SIGTERM` 是监督进程的普通停止请求,在所有 surface 上以 0 退出,`SIGINT` 报告 130;第二次信号强制立即退出。如果一次性运行正常结束时已经卡在 dispose 中,第一次 `Ctrl+C` 就会升格并立即退出,而不会被吞掉。 +进程关闭时,插件树最多有 5 秒完成 dispose。首次收到 `SIGINT` 或 `SIGTERM` 时会开始优雅排空:`SIGTERM` 是监督进程发出的常规停止请求,在所有运行模式下都以 0 退出;`SIGINT` 则报告 130。第二次收到信号时会立即强制退出。如果一次性运行在正常结束时已经卡在 dispose 阶段,第一次按下 `Ctrl+C` 就会直接升级为强制退出,而不会被忽略。 -所有模式都将调用目录作为默认 workspace 根目录,以 65,536 字节渲染预算加载适用的 `AGENTS.md` 或 `CLAUDE.md` 指令,并使用内存 SQLite 会话内容索引。每次 profile 启动都监视两个 `cordis.patch.yml` 层(profile 与 home)的有效编辑并以事务方式重新应用;一次性 surface 经由有界关闭退出,关闭会先 dispose 监视器。 +所有模式都将运行命令时所在的目录作为默认 workspace 根目录,以 65,536 字节渲染预算加载适用的 `AGENTS.md` 或 `CLAUDE.md` 指令,并使用内存 SQLite 会话内容索引。每次启动 profile 时,系统都会监视 profile 与 home 两个 `cordis.patch.yml` 配置层的有效变更,并以事务方式重新应用;一次性运行模式通过有界关闭流程退出,该流程会先 dispose 监视器。 新会话默认使用 `workspace-write` 权限预设。Bash 和文件系统修改仅限于会话 workspace 与平台临时根目录;读取、网络访问和进程可见性不受限制。`DSH_PERMISSION_MODE` 更改进程后备值。General settings 中存储的权限影响后续 Web 会话,不改变已打开的会话。 @@ -75,8 +75,7 @@ dsh web --help 基础组合包挂载原生 DeepSeek 适配器、settings 与凭据提供方、稳定的 `web_search` 和已禁用的会话遥测。提供方凭据依次从继承环境、`$DSH_HOME/.credentials.yaml`、调用目录的 `.env` 和 `$DSH_HOME/.env` 解析;受管文档从不物化进 `process.env`,而两个 `.env` 文件都是普通启动环境层。搜索使用 `DEEPSEEK_API_KEY` 并接受 `DEEPSEEK_SEARCH_BASE_URL`;只有 patch 层插入提供方并启用 `web_fetch` 后,该工具才可用。 -会话遥测默认留在本地。`DSH_TELEMETRY_MODE=FULL` 将每条已投影会话事件作为 OTLP/HTTP 日志流式发送,`DSH_TELEMETRY_MODE=FEEDBACK_ONLY` 则仅在记录反馈时上传会话日志后缀。`DSH_TELEMETRY_OTLP_URL` 选择其他 collector,任何非空 `DSH_TELEMETRY_DISABLED` 仍是具有最高优先级的硬性退出开关。随附基础配置没有遥测脱敏规则,因此显式启用的导出可能包含消息文本、工具参数与结果以及 workspace 路径;该部署决策由[默认关闭 Agent Note](../../../.agents/notes/implemented/feature/2026-08-10-telemetry-default-off.md)负责。 - +会话遥测默认留在本地。`DSH_TELEMETRY_MODE=FULL` 将每条已投影会话事件作为 OTLP/HTTP 日志流式发送,`DSH_TELEMETRY_MODE=FEEDBACK_ONLY` 则仅在记录反馈时上传会话日志后缀。`DSH_TELEMETRY_OTLP_URL` 选择其他 collector。任何非空的 `DSH_TELEMETRY_DISABLED` 都是具有最终效力的遥测强制关闭开关。随附基础配置没有遥测脱敏规则,因此显式启用的导出可能包含消息文本、工具参数和结果,以及 workspace 路径;相关部署决策见[默认关闭 Agent Note](../../../.agents/notes/implemented/feature/2026-08-10-telemetry-default-off.md)。 通过 `dsh plugin --profile add ` 安装外部插件组合包。安装的包拥有其依赖,并贡献其声明的 `cordis.patch.yml` 层。CLI 还随附 `@deepseek-ai/dsh-mcp-client` 作为供 patch 层使用的依赖,但默认不启用 MCP 服务器,因为每条服务器命令都是 agent(智能体)沙箱之外的受信任可执行代码。 diff --git a/apps/cli/tests/args.spec.ts b/apps/cli/tests/args.spec.ts index 89a16921b2..611a098b6f 100644 --- a/apps/cli/tests/args.spec.ts +++ b/apps/cli/tests/args.spec.ts @@ -36,8 +36,8 @@ describe('parseDshArgs', () => { .toEqual({ mode: 'profile', profile: 'tui', patches: [], args: ['--resume', 'abc'] }) expect(parse(['--profile', 'web', '-h'])) .toEqual({ mode: 'profile', profile: 'web', patches: [], args: ['-h'] }) - expect(parse(['web', '--host', '0.0.0.0', '--port', '8080', '--dev'])) - .toEqual({ mode: 'profile', profile: 'web', patches: [], args: ['--host', '0.0.0.0', '--port', '8080', '--dev'] }) + expect(parse(['web', '--host', '127.0.0.1', '--port', '8080', '--dev'])) + .toEqual({ mode: 'profile', profile: 'web', patches: [], args: ['--host', '127.0.0.1', '--port', '8080', '--dev'] }) expect(parse(['--profile', 'headless', 'run', 'the', 'tests'])) .toEqual({ mode: 'profile', profile: 'headless', patches: [], args: ['run', 'the', 'tests'] }) // Launcher flags placed after that boundary belong to the app too. diff --git a/apps/cli/tests/built-bin.e2e.ts b/apps/cli/tests/built-bin.e2e.ts index c989d9ce3e..f887c170d3 100644 --- a/apps/cli/tests/built-bin.e2e.ts +++ b/apps/cli/tests/built-bin.e2e.ts @@ -339,6 +339,15 @@ describe.skipIf(!existsSync(dshBin))('dsh BUILT bin (node lib/bin.js, no tsx)', expect(web.stdout).toContain('--port ') expect(web.stdout).not.toContain('dsh web: http://') + const wildcardHost = await runBuiltBin(['web', '--host', '0.0.0.0'], { + DSH_HOME: home, + DSH_TELEMETRY_DISABLED: '1', + }) + expect(wildcardHost.code).toBe(1) + expect(wildcardHost.stdout).toBe('') + expect(wildcardHost.stderr).toContain('--host 0.0.0.0 is intentionally not supported yet for safety: it would expose remote code execution to the network; use 127.0.0.1 instead') + expect(wildcardHost.stderr).not.toContain('dsh web: http://') + const headlessHelp = await runBuiltBin(['--profile', 'headless', '--help'], { DSH_HOME: home, DSH_TELEMETRY_DISABLED: '1', diff --git a/apps/cli/tests/lazy-search-startup.compat.spec.ts b/apps/cli/tests/lazy-search-startup.compat.spec.ts index b1477a63d0..c563c850e6 100644 --- a/apps/cli/tests/lazy-search-startup.compat.spec.ts +++ b/apps/cli/tests/lazy-search-startup.compat.spec.ts @@ -21,15 +21,22 @@ import { describe, expect, it } from 'vitest' const repoRoot = fileURLToPath(new URL('../../../', import.meta.url)) const builtBin = join(repoRoot, 'apps/cli/lib/bin.js') const webDist = join(repoRoot, 'apps/web/dist/index.html') -// The web bundle's patch owns the session-query-sqlite lazy-open row. -const configPath = join(repoRoot, 'packages/bundle/web-app/cordis.patch.yml') +// Full-text session search ships off (`openAt: never` on both layers): the +// base patch carries the default, and the web restatement must not re-enable it. +const baseConfigPath = join(repoRoot, 'packages/bundle/base/cordis.patch.yml') +const webConfigPath = join(repoRoot, 'packages/bundle/web-app/cordis.patch.yml') const requireBuiltArtifacts = process.env.DSH_REQUIRE_BUILT_CLI_SMOKE === '1' interface ConfigRow { id?: string + disabled?: unknown config?: { openAt?: unknown } } +interface PatchEntry extends ConfigRow { + insert?: ConfigRow[] +} + const jsExprType = new yaml.Type('tag:yaml.org,2002:js', { kind: 'scalar', construct: value => String(value), @@ -92,12 +99,20 @@ function runBuiltWeb(cwd: string): Promise<{ stdout: string; stderr: string; cod } describe.skipIf(!requireBuiltArtifacts)('built CLI lazy-search startup', () => { - it('boots and disposes the shipped composition without a SQLite startup warning', async () => { + it('boots and disposes the shipped composition with full-text search off by default', async () => { expect(existsSync(builtBin), `missing built CLI ${resolve(builtBin)}; run pnpm build`).toBe(true) expect(existsSync(webDist), `missing Web dist ${resolve(webDist)}; run pnpm run build:web`).toBe(true) - const rows = yaml.load(await readFile(configPath, 'utf8'), { schema: configSchema }) as ConfigRow[] - const searchRow = rows.find(row => row.id === 'session-query-sqlite') - expect(searchRow?.config?.openAt).toBe('first-search') + const baseRows = (yaml.load(await readFile(baseConfigPath, 'utf8'), { schema: configSchema }) as PatchEntry[]) + .flatMap(entry => entry.insert ?? [entry]) + const webRows = (yaml.load(await readFile(webConfigPath, 'utf8'), { schema: configSchema }) as PatchEntry[]) + .flatMap(entry => entry.insert ?? [entry]) + const baseRow = baseRows.find(row => row.id === 'session-query-sqlite') + const webRow = webRows.find(row => row.id === 'session-query-sqlite') + expect(baseRow?.config?.openAt).toBe('never') + expect(baseRow?.disabled).toBeUndefined() + // The web restatement keeps the shipped default; opting in is a later layer's override. + expect(webRow?.config?.openAt).toBe('never') + expect(webRow?.disabled).toBeUndefined() const cwd = await mkdtemp(join(tmpdir(), 'dsh-cli-lazy-search-')) try { diff --git a/apps/cli/tests/web-agent-presets.e2e.ts b/apps/cli/tests/web-agent-presets.e2e.ts index ca0f5ece78..7b347353fd 100644 --- a/apps/cli/tests/web-agent-presets.e2e.ts +++ b/apps/cli/tests/web-agent-presets.e2e.ts @@ -28,6 +28,7 @@ const BASE_PATCH = join(REPO_ROOT, 'packages/bundle/base/cordis.patch.yml') const WEB_PATCH = join(REPO_ROOT, 'packages/bundle/web-app/cordis.patch.yml') /** The installation anchor whose dependency surface the preset module fallback mirrors. */ const INSTALL_ANCHOR = join(REPO_ROOT, 'apps/cli/package.json') +const EXAMPLES_INSTALL_ANCHOR = join(REPO_ROOT, 'examples/package.json') const MINIMAL_PROMPT = 'You are a helpful software engineer assistant.' const MINIMAL_BASH_DESCRIPTION = `Run commands in a bash shell * When invoking this tool, the contents of the "command" parameter does NOT need to be XML-escaped. @@ -43,7 +44,11 @@ const MINIMAL_BASH_DESCRIPTION = `Run commands in a bash shell * touch the network, or write outside the test. Everything that decides an * agent's capabilities is the real thing, including both shipped presets. */ -async function bootWeb(settingsFile: string, extra: PatchOptions[] = []): Promise { +async function bootWeb( + settingsFile: string, + extra: PatchOptions[] = [], + extraInstallAnchor?: string, +): Promise { const storageRoot = join(dirname(settingsFile), 'storages') const patches: PatchOptions[] = [ ...loadOverlayPatches('dsh-test', BASE_PATCH), @@ -110,6 +115,7 @@ async function bootWeb(settingsFile: string, extra: PatchOptions[] = []): Promis // them resolvable — the same mechanism, not a test-only shim. const home = dirname(settingsFile) healProfilesModuleFallback(INSTALL_ANCHOR, home) + if (extraInstallAnchor !== undefined) healProfilesModuleFallback(extraInstallAnchor, home) const profileDir = join(home, 'profiles', 'spec') await mkdir(profileDir, { recursive: true }) const rootConfig = join(profileDir, 'cordis.yml') @@ -122,6 +128,16 @@ async function bootWeb(settingsFile: string, extra: PatchOptions[] = []): Promis const toolNames = (ctx: Context, agent?: Agent): string[] => ctx.tools.schemas(agent).map(schema => schema.name).sort() +function toolParameterNames(ctx: Context, agent: Agent, toolName: string): string[] { + const schema = ctx.tools.schemas(agent).find(tool => tool.name === toolName) + if (schema === undefined) throw new Error(`missing tool schema ${toolName}`) + const properties = schema.parameters.properties + if (typeof properties !== 'object' || properties === null || Array.isArray(properties)) { + throw new Error(`${toolName} has invalid parameter properties`) + } + return Object.keys(properties).sort() +} + function enablePresetTool(composition: string, id: string): string { const row = ` - id: ${id}\n` const start = composition.indexOf(row) @@ -440,17 +456,23 @@ describe('product subagent rows in user presets', () => { await mkdir(directory, { recursive: true }) await writeFile(join(directory, 'agent.cordis.yml'), composition) } - productCtx = await bootWeb(settingsFile, [{ - id: 'agent-presets', - config: { - default: 'standard', - roots: [ - { path: join(CONFIG_DIR, 'agent-presets'), trust: 'system' }, - { path: userRoot, trust: 'user' }, - ], - includeUserRoot: false, + productCtx = await bootWeb(settingsFile, [ + { insert: [ + { id: 'subagent-codex', name: '@deepseek-ai/dsh-subagent-codex' }, + { id: 'subagent-claude-code', name: '@deepseek-ai/dsh-subagent-claude-code' }, + ] }, + { + id: 'agent-presets', + config: { + default: 'standard', + roots: [ + { path: join(CONFIG_DIR, 'agent-presets'), trust: 'system' }, + { path: userRoot, trust: 'user' }, + ], + includeUserRoot: false, + }, }, - }]) + ], EXAMPLES_INSTALL_ANCHOR) }, 120_000) afterAll(async () => { @@ -477,6 +499,12 @@ describe('product subagent rows in user presets', () => { const tools = toolNames(productCtx, handle.agent) expect(tools.filter(name => name === 'subagent_codex' || name === 'subagent_claude_code')) .toEqual(productTools) + expect(tools).toEqual(expect.arrayContaining(['job_kill', 'job_list', 'job_output'])) + for (const productTool of productTools) { + expect(toolParameterNames(productCtx, handle.agent, productTool)).toEqual([ + 'description', 'prompt', 'run_in_background', + ]) + } } finally { await handle.dispose() } diff --git a/apps/web/package.json b/apps/web/package.json index f6dd190d91..fc990f684c 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-web-frontend", "description": "Web application entry: vite build over the @deepseek-ai/dsh-client-web shell library; dist/ served by apps/cli's dsh web", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -24,7 +24,7 @@ "dev": "vite", "watch": "vite build --watch" }, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "@deepseek-ai/dsh-client-web": "workspace:^", "react": "^18.2.0", diff --git a/apps/web/tests/README.i18n.yaml b/apps/web/tests/README.i18n.yaml index a6005ade32..b366a7ff52 100644 --- a/apps/web/tests/README.i18n.yaml +++ b/apps/web/tests/README.i18n.yaml @@ -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 apps/web/tests/README.md -README.md: 68e5db5af5f816cc982bacb7989d996c859be204 -README.zh.md: f366c28024dab89d0243a60d93a706f220fa8fb8 +README.md: acb0c300bafe221f6a92f0168908bebf965377b9 +README.zh.md: fd3d950a106375bb038b205415407b4a31bd2b32 diff --git a/apps/web/tests/README.md b/apps/web/tests/README.md index 68e5db5af5..acb0c300ba 100644 --- a/apps/web/tests/README.md +++ b/apps/web/tests/README.md @@ -29,9 +29,9 @@ artifact it produces itself. When a scenario needs a Client-owned constant or pure function, mirror it here instead, next to the commented-out import that names the source module. A drift -then surfaces as a missed selector or an unsuppressed notice — a loud failure, -never a silent pass. `scaffold.ts` holds the mirrored welcome-notice values and -exports them for the scenarios that assert on them. +then surfaces as a missed selector or a stale mirrored value — a loud failure, +never a silent pass. `scaffold.ts` follows this rule for the welcome-notice +namespace, acknowledgement field, version, and asserted Chinese copy. Two kinds of Client import stand. `assembled-boot.ts` drives the shell itself, so it imports `AppWebEntry` from `@deepseek-ai/dsh-client-web` and the boot-manifest diff --git a/apps/web/tests/README.zh.md b/apps/web/tests/README.zh.md index f366c28024..fd3d950a10 100644 --- a/apps/web/tests/README.zh.md +++ b/apps/web/tests/README.zh.md @@ -23,8 +23,8 @@ Client face,而该 face 必须等 Host tsdown 生成 `@deepseek-ai/dsh-goal/re 于是 Host 构建阶段变成在等一个由它自己产出的产物。 当某个场景需要 Client 持有的常量或纯函数时,改为在此处镜像一份,并紧挨着一条注释掉的 -import 点明源模块。这样漂移会表现为选择器未命中或提示未被抑制——是响亮的失败,绝不会是静默 -通过。`scaffold.ts` 持有镜像的 welcome-notice 取值,并导出给断言它们的场景使用。 +import 点明源模块。这样漂移会表现为选择器未命中或镜像值过期——是响亮的失败,绝不会是静默 +通过。`scaffold.ts` 按此规则镜像欢迎声明的 namespace、确认字段、版本和被断言的中文文案。 有两类 Client import 是长期成立的。`assembled-boot.ts` 驱动 shell 本身,因此它从 `@deepseek-ai/dsh-client-web` import `AppWebEntry`、从 diff --git a/apps/web/tests/cold-blank-session.e2e.ts b/apps/web/tests/cold-blank-session.e2e.ts new file mode 100644 index 0000000000..dd79c4e8b1 --- /dev/null +++ b/apps/web/tests/cold-blank-session.e2e.ts @@ -0,0 +1,60 @@ +/** Cold Session list visibility through the shipped compressed JSONL backend. */ + +import { mkdir, stat } from 'node:fs/promises' +import { fileURLToPath } from 'node:url' +import { join } from 'node:path' +import type { Browser, Page } from 'playwright' +import { chromium } from 'playwright' +import { afterAll, beforeAll, describe, expect, it, onTestFailed } from 'vitest' +import { + captureStableAria, compareOrRefreshGolden, launchWebScaffold, seedBlankSession, + watchConsole, webSnapshotMode, type WebScaffold, +} from './scaffold.ts' +import { newEnglishPage, saveFailureShot } from './support.ts' + +const SNAPSHOT_DIR = fileURLToPath(new URL('./snapshots/cold-blank-session', import.meta.url)) +const SIDEBAR_EXPECTED = join(SNAPSHOT_DIR, 'sidebar.expected.md') +const MODE = webSnapshotMode() +const SESSION_ID = 'cold-blank-session-web-e2e' +const WORKSPACE_NAME = 'cold-blank-workspace' + +describe('web e2e: cold blank Session visibility', () => { + let scaffold: WebScaffold + let browser: Browser + let page: Page + let tripwire: ReturnType + + beforeAll(async () => { + scaffold = await launchWebScaffold({}) + const cwd = join(scaffold.workspaceCwd, WORKSPACE_NAME) + await mkdir(cwd, { recursive: true }) + await seedBlankSession(scaffold, SESSION_ID, cwd) + const header = (await scaffold.ctx.sessionPersistence.list()) + .find(candidate => candidate.id === SESSION_ID) + if (header === undefined) throw new Error('blank Session fixture did not materialize') + const location = scaffold.ctx.sessionPersistence.locate(header) + if (location === undefined) throw new Error('JSONL fixture has no physical artifact') + expect((await stat(location.path)).size).toBeLessThanOrEqual(1024) + + browser = await chromium.launch() + page = await newEnglishPage(browser) + tripwire = watchConsole(page) + await page.goto(scaffold.baseUrl, { waitUntil: 'load' }) + await page.waitForSelector('[class*="frame"]', { timeout: 30_000 }) + }, 120_000) + + afterAll(async () => { + await browser?.close() + await scaffold?.close() + }) + + it('keeps the verified cold blank Session out of the sidebar', async () => { + onTestFailed(() => saveFailureShot(page, 'web-e2e-cold-blank-session')) + const tree = page.getByRole('tree', { name: 'Sessions' }) + await tree.waitFor({ timeout: 30_000 }) + expect(await tree.getByText(WORKSPACE_NAME, { exact: true }).count()).toBe(0) + const sidebar = await captureStableAria(page, '[role="tree"][aria-label="Sessions"]', scaffold.workspaceCwd) + await compareOrRefreshGolden(SIDEBAR_EXPECTED, sidebar, MODE) + expect(tripwire.pageErrors).toEqual([]) + }) +}) diff --git a/apps/web/tests/composer-tab-geometry.e2e.ts b/apps/web/tests/composer-tab-geometry.e2e.ts index bb43e20406..0f7b01c7ff 100644 --- a/apps/web/tests/composer-tab-geometry.e2e.ts +++ b/apps/web/tests/composer-tab-geometry.e2e.ts @@ -11,12 +11,13 @@ // gets an absolutely positioned seat instead, laid out against the padding box, // which the scrollbar never reduces. // -// Without a shared reservation the two tabs disagree by exactly the bar's -// width for as long as the transcript overflows: the card jumps sideways on -// every tab switch, and inside Chat alone at the moment a growing transcript -// starts to scroll. The column reserves the gutter unconditionally -// (`scrollbar-gutter: stable`) and states the overlay branch as a scroll -// container on the same axes, so both edges are the same edge. +// The column handles the two edges without reserving the gutter on both: Chat +// keeps `scrollbar-gutter: stable` so its seat's content box never jumps as the +// transcript starts to scroll; the overlay branch does NOT reserve (the view +// owns its own scrollers, so a reserved gutter would only narrow the view's +// content by the bar's width), and the overlay seat instead gives back the +// bar's width (`right: var(--dsh-scrollbar-width)`) so both seats measure the +// same width and the card does not move. // // Only a real engine can show this. The seat's geometry is layout: jsdom gives // every element a zero-sized box and reports no scrollbar at all, so a unit spec @@ -27,18 +28,17 @@ // The browser is launched WITHOUT Playwright's default `--hide-scrollbars`, // which is load-bearing rather than incidental. Under that argument a scroll // container's bar consumes no layout width at all, so the two tabs agree with -// and without the reservation and every comparison below holds vacuously — -// measured: the unreserved cascade leaves both tabs' bands at 0 there, against -// 8 and 0 with the argument dropped. Dropping it is also the faithful +// and without the compensation and every comparison below holds vacuously — +// measured: the uncompensated cascade leaves both tabs' bands at 0 there, +// against 8 and 0 with the argument dropped. Dropping it is also the faithful // configuration: ui-theme's scrollbar.css gives `::-webkit-scrollbar` a width, // and a bar that occupies layout space is what the product actually draws. // -// The scenario runs that unreserved cascade in the page — `scrollbar-gutter: auto` -// on the scroller, `overflow: hidden` on the overlay branch — and measures the -// same two tabs through it, which is what keeps the equal rectangles above from -// being explained by a tab switch that never reached the layout. It is the -// reported symptom as a number: the card moves 4px, half the 8px band, on each -// edge. +// The scenario runs that uncompensated cascade in the page — the overlay seat's +// `right` compensation dropped to 0 — and measures the same two tabs through +// it, which is what keeps the equal rectangles above from being explained by a +// tab switch that never reached the layout. It is the reported symptom as a +// number: the card moves 4px, half the 8px band, on each edge. // // Zero model calls: a seeded cold session renders from its log, and switching // tabs asks the host for nothing. A stray stream would fail loud with NO_ADAPTER. @@ -62,9 +62,9 @@ const SNAPSHOT_DIR = fileURLToPath(new URL('./snapshots/composer-tab-geometry', * Absolute coordinates are deliberately absent: they depend on the sidebar's * laid-out width and on font metrics, so committing them would produce a fixture * that has to be re-recorded per platform. What is recorded is the distance - * between the two tabs' rectangles, which is zero when the reservation holds and + * between the two tabs' rectangles, which is zero when the compensation holds and * the bar's width when it does not — including under the control, so the golden - * carries the shift the unreserved cascade produces rather than only its absence. + * carries the shift the uncompensated cascade produces rather than only its absence. */ const GEOMETRY_EXPECTED = join(SNAPSHOT_DIR, 'geometry.expected.md') const MODE = webSnapshotMode() @@ -114,15 +114,15 @@ async function setMeasuredViewport( } /** - * The unreserved cascade, injected into the page: the reservation dropped and - * the overlay branch forced to a hidden box. `!important` beats the module + * The uncompensated cascade, injected into the page: the overlay seat's `right` + * compensation dropped to 0, so it measures the full padding box while Chat's + * seat still rides the reserved content box. `!important` beats the module * rules without a rebuild, and the id lets the control be lifted again in the * same session. */ const CONTROL_STYLE_ID = 'composer-tab-geometry-control' const CONTROL_CSS = ` -[data-conversation-scroll] { scrollbar-gutter: auto !important; } -[data-conversation-scroll]:has([data-conversation-composer-overlay]) { overflow: hidden !important; } +[data-conversation-scroll]:has([data-conversation-composer-overlay]) > [data-composer-seat] { right: 0 !important; } ` /** The column scroller and the input card as the browser lays them out, in one tab. */ @@ -221,11 +221,13 @@ async function compareTabs(page: Page): Promise { } /** - * Run the unreserved cascade in the page for one measurement, then lift it. + * Run the uncompensated cascade in the page for one measurement, then lift it: + * the overlay seat's `right` compensation dropped to 0, so it measures the + * full padding box while Chat's seat still rides the reserved content box. * @param page - the page under test. - * @returns the comparison as the column lays out without the reservation. + * @returns the comparison as the column lays out without the compensation. */ -async function compareTabsWithoutReservation(page: Page): Promise { +async function compareTabsWithoutCompensation(page: Page): Promise { await page.evaluate(({ id, css }) => { const style = document.createElement('style') style.id = id @@ -268,7 +270,7 @@ async function openSeededSession(page: Page): Promise { * Render the golden body. * @param wide - comparison at the viewport where the card sits at its width cap. * @param narrow - comparison at the viewport where the card shrinks with the column. - * @param control - comparison at the wide viewport with the reservation removed. + * @param control - comparison at the wide viewport with the compensation removed. * @returns the golden body, without a trailing newline. */ function renderGeometry(wide: TabComparison, narrow: TabComparison, control: TabComparison): string { @@ -291,7 +293,7 @@ function renderGeometry(wide: TabComparison, narrow: TabComparison, control: Tab '', ...section(`Wide viewport (${String(WIDE_VIEWPORT.width)}px, card at its cap)`, wide), ...section(`Narrow viewport (${String(NARROW_VIEWPORT.width)}px, card shrinking with the column)`, narrow), - ...section('Wide viewport, reservation removed in the page (control)', control), + ...section('Wide viewport, seat compensation removed in the page (control)', control), ].join('\n').trimEnd() } @@ -322,22 +324,29 @@ describe('web e2e: input card position across view tabs', () => { await scaffold?.close() }) - it('reserves the same gutter in both tabs while the transcript scrolls', async () => { + it('reserves the gutter in Chat and lets Trajectory own its width', async () => { onTestFailed(() => saveFailureShot(page, 'web-e2e-composer-tab-geometry-band')) await setMeasuredViewport(page, WIDE_VIEWPORT, false) - // Vacuity guard, in two parts. A transcript that does not overflow gives - // Chat no scrollbar, and a hidden or overlaid bar gives it no width; either - // would make the tabs agree without the reservation doing anything. + // Vacuity guard. The scenario must be able to fail: on an engine that + // does not implement `scrollbar-gutter`, Chat reserves nothing and the + // overlay seat's fixed compensation stands alone, manufacturing an 8px + // deviation the equal-rectangle assertions would catch. `stable` reserves + // even without overflow, so a short transcript is not a vacuous case; the + // poll still pins the measurement to the overflowing state the product + // ships. await expect.poll(async () => (await measureTab(page)).scrolls, { timeout: 10_000 }).toBe(true) const comparison = await compareTabs(page) expect(comparison.chat.band).toBeGreaterThan(0) - // The reservation reaches both states, which is the whole point: the same - // band, on a box that scrolls and on one that only holds a view. + // Chat keeps the unconditional reservation so its seat's content box never + // jumps as the transcript starts to scroll. expect(comparison.chat.gutter).toBe('stable') - expect(comparison.trajectory.gutter).toBe('stable') - expect(comparison.trajectory.band).toBe(comparison.chat.band) + // The overlay branch does NOT reserve: the view owns its own scrollers, so + // a reserved gutter would only narrow the view's content by the bar's + // width. The seat compensates instead, which the next test asserts. + expect(comparison.trajectory.gutter).toBe('auto') + expect(comparison.trajectory.band).toBe(0) // Declared as a scroll container on both axes rather than left to compute: - // `overflow: hidden` would drop the reservation in WebKit, and a `visible` + // `overflow: hidden` would drop any reservation in WebKit, and a `visible` // horizontal axis computes to `auto` beside a scrolling one. expect(comparison.trajectory.overflowY).toBe('auto') expect(comparison.trajectory.overflowX).toBe('hidden') @@ -351,7 +360,7 @@ describe('web e2e: input card position across view tabs', () => { await setMeasuredViewport(page, WIDE_VIEWPORT, false) const comparison = await compareTabs(page) // The reported symptom as a number. At this viewport the card sits at its - // width cap, so the unreserved cascade's shift shows up as a centring + // width cap, so the uncompensated cascade's shift shows up as a centring // difference — half the band on each edge — rather than as a width change. expect(comparison.leftShift).toBe(0) expect(comparison.rightShift).toBe(0) @@ -378,20 +387,21 @@ describe('web e2e: input card position across view tabs', () => { expect(tripwire.pageErrors).toEqual([]) }, 60_000) - it('moves the card again once the reservation is removed in the page', async () => { + it('moves the card again once the seat compensation is removed in the page', async () => { onTestFailed(() => saveFailureShot(page, 'web-e2e-composer-tab-geometry-control')) await setMeasuredViewport(page, WIDE_VIEWPORT, false) // The control: without it, equal rectangles could also mean the tab switch - // never reached the layout. Under the unreserved cascade the Chat scroller - // keeps its bar and the Trajectory branch becomes a hidden box with none, - // and the card moves by half the band on each edge. - const comparison = await compareTabsWithoutReservation(page) - expect(comparison.chat.gutter).toBe('auto') + // never reached the layout. Under the uncompensated cascade the overlay seat + // loses its `right` compensation and measures the full padding box, so the + // card moves by half the band on each edge. Chat's own reservation is + // untouched — that is the side that must not change. + const comparison = await compareTabsWithoutCompensation(page) + expect(comparison.chat.gutter).toBe('stable') expect(comparison.chat.band).toBeGreaterThan(0) expect(comparison.trajectory.band).toBe(0) expect(comparison.leftShift).toBe(comparison.chat.band / 2) expect(comparison.rightShift).toBe(comparison.chat.band / 2) - // Restoring the sheet restores the reservation, so the control cannot leak + // Restoring the sheet restores the compensation, so the control cannot leak // into the remaining measurements. const restored = await compareTabs(page) expect(restored.leftShift).toBe(0) @@ -405,7 +415,7 @@ describe('web e2e: input card position across view tabs', () => { await setMeasuredViewport(page, NARROW_VIEWPORT, true) const narrow = await compareTabs(page) await setMeasuredViewport(page, WIDE_VIEWPORT, false) - const control = await compareTabsWithoutReservation(page) + const control = await compareTabsWithoutCompensation(page) await compareOrRefreshGolden(GEOMETRY_EXPECTED, renderGeometry(wide, narrow, control), MODE) expect(tripwire.pageErrors).toEqual([]) }, 60_000) diff --git a/apps/web/tests/cordis-tool-round.e2e.ts b/apps/web/tests/cordis-tool-round.e2e.ts index a702a7f1ea..7d1d6ab3b5 100644 --- a/apps/web/tests/cordis-tool-round.e2e.ts +++ b/apps/web/tests/cordis-tool-round.e2e.ts @@ -47,8 +47,7 @@ function assertCompleteCordisLifecycle(events: readonly SessionEvent[]): void { (event): event is Extract => event.type === 'turn/end', ) const reason = turnEnd?.data.reason - const reasonSummary = { kind: reason?.kind } - expect(reasonSummary).toEqual({ kind: 'completed' }) + expect(reason).toEqual({ kind: 'completed' }) const calls = events.filter( (event): event is Extract => event.type === 'tool/call', diff --git a/apps/web/tests/goal-bar.overlay.yml b/apps/web/tests/goal-bar.overlay.yml index 2594d6a3e9..4e9e382bb8 100644 --- a/apps/web/tests/goal-bar.overlay.yml +++ b/apps/web/tests/goal-bar.overlay.yml @@ -1,5 +1,5 @@ -# The client-side FixtureApiClient intentionally rejects settings writes, so -# this goal-only scenario omits the durable welcome step that would otherwise -# cover the page. Onboarding owns separate assembled-browser coverage. +# The client-side FixtureApiClient intentionally rejects settings traffic, so +# this goal-only scenario omits the settings shell and the onboarding steps it +# would mount. Onboarding owns separate assembled-browser coverage. - id: ui-settings-general disabled: true diff --git a/apps/web/tests/minimal-preset.snapshot.ts b/apps/web/tests/minimal-preset.snapshot.ts index 4a402077a3..011f71ea8d 100644 --- a/apps/web/tests/minimal-preset.snapshot.ts +++ b/apps/web/tests/minimal-preset.snapshot.ts @@ -55,6 +55,9 @@ describe('minimal agent preset', () => { const requestHeader = agentHandle.agent.session.requestHeader() if (requestHeader === undefined) throw new Error('the minimal agent issued no model request') + expect(agentHandle.agent.session.events.some(event => event.type === 'user/message' + && event.data.source.kind === 'plugin' + && event.data.source.plugin === '@deepseek-ai/dsh-system-prompt')).toBe(false) const presetFileSystem = scaffold.ctx.agentPresets.serviceFor(agentHandle.agent, 'fs') expect(presetFileSystem).toBeDefined() expect(presetFileSystem?.sandboxMode).toBeUndefined() diff --git a/apps/web/tests/onboarding-deepseek-config.e2e.ts b/apps/web/tests/onboarding-deepseek-config.e2e.ts index 5572e834ad..ad9bc0903f 100644 --- a/apps/web/tests/onboarding-deepseek-config.e2e.ts +++ b/apps/web/tests/onboarding-deepseek-config.e2e.ts @@ -1,6 +1,7 @@ // Keyless browser e2e: the shipped DeepSeek adapter stays mounted while its -// credential is absent, onboarding routes to the real Models editor, and its -// write lands in an isolated harness home without a reload or model call. +// credential is absent, both ordered steps share the shipped modal chrome, +// and the inline key write lands in an isolated harness home without a reload +// or model call. import { randomBytes } from 'node:crypto' import { readFile } from 'node:fs/promises' import { fileURLToPath } from 'node:url' @@ -8,14 +9,14 @@ import { join } from 'node:path' import type { Browser, Page } from 'playwright' import { chromium } from 'playwright' import { afterAll, beforeAll, describe, expect, it, onTestFailed } from 'vitest' +import { settingsNamespace } from '@deepseek-ai/dsh-settings' import { acknowledgeReloadConnectionLoss, assertFixtureInventory, captureStableAria, compareOrRefreshGolden, - WELCOME_NOTICE_SETTINGS_NAMESPACE, WELCOME_NOTICE_ACK_FIELD, - WELCOME_NOTICE_VERSION, WELCOME_NOTICE_COPY, launchWebScaffold, watchConsole, webSnapshotMode, type WebScaffold, + WELCOME_NOTICE_ACK_FIELD, WELCOME_NOTICE_COPY, WELCOME_NOTICE_SETTINGS_NAMESPACE, + WELCOME_NOTICE_VERSION, } from './scaffold.ts' import { ZH_BROWSER_LOCALE, connectFreshWorkspaceZh, saveFailureShot } from './support.ts' -import { settingsNamespace } from '@deepseek-ai/dsh-settings' const SNAPSHOT_DIR = fileURLToPath(new URL('./snapshots/onboarding-deepseek-config', import.meta.url)) const WELCOME_EXPECTED = join(SNAPSHOT_DIR, 'welcome.expected.md') @@ -48,43 +49,20 @@ describe.skipIf(MODE === 'record')('web e2e: first-run DeepSeek credential setup it('stores a key write-only and observes configured state without restarting', async () => { onTestFailed(() => saveFailureShot(page, 'web-e2e-onboarding-deepseek-config')) - const welcome = page.getByRole('region', { name: WELCOME_NOTICE_COPY.zh.title }) + const welcome = page.getByRole('dialog', { name: WELCOME_NOTICE_COPY.zh.title }) await welcome.waitFor({ timeout: 15_000 }) expect(await page.locator('#root').evaluate(root => (root as HTMLElement).inert)).toBe(true) - const welcomeAria = await captureStableAria(page, '[role="region"]', scaffold.workspaceCwd) + for (const paragraph of WELCOME_NOTICE_COPY.zh.body.split('\n\n')) { + expect(await welcome.getByText(paragraph, { exact: true }).count()).toBe(1) + } + expect(await welcome.getByRole('button').allTextContents()).toEqual([ + WELCOME_NOTICE_COPY.zh.continueLabel, + ]) + const welcomeAria = await captureStableAria(page, '[role="dialog"]', scaffold.workspaceCwd) await compareOrRefreshGolden(WELCOME_EXPECTED, welcomeAria, MODE) - expect(await welcome.getByRole('button').allTextContents()).toEqual([WELCOME_NOTICE_COPY.zh.continueLabel]) - expect(await welcome.locator('button').count()).toBe(1) - const mask = page.locator('[class*="onboardingMask"]') - expect(await mask.count()).toBe(1) - const maskStyles = await mask.evaluate((mask) => { - const style = getComputedStyle(mask) - const rect = mask.getBoundingClientRect() - return { - position: style.position, - left: style.left, - right: style.right, - top: style.top, - bottom: style.bottom, - background: style.backgroundColor, - backdropFilter: style.backdropFilter, - rect: { left: rect.left, top: rect.top, right: rect.right, bottom: rect.bottom }, - } - }) - expect(maskStyles).toEqual({ - position: 'absolute', - left: '0px', - right: '0px', - top: '80px', - bottom: '0px', - background: 'rgba(0, 0, 0, 0.24)', - backdropFilter: 'blur(2px)', - rect: { left: 0, top: 80, right: 1440, bottom: 960 }, - }) - - // Closing the process/page before acknowledgement writes nothing, so the - // same durable profile presents the notice again after reload. + // Observation is not acknowledgement: the exact version is persisted + // only by the explicit action, so a reload still presents this dialog. const firstReloadWarnings = tripwire.warnings.length await page.reload({ waitUntil: 'load' }) acknowledgeReloadConnectionLoss(tripwire, firstReloadWarnings) @@ -92,24 +70,19 @@ describe.skipIf(MODE === 'record')('web e2e: first-run DeepSeek credential setup await welcome.getByRole('button', { name: WELCOME_NOTICE_COPY.zh.continueLabel }).click() await welcome.waitFor({ state: 'detached', timeout: 15_000 }) - const credentialStep = page.getByRole('region', { name: '添加一个 API Key 开始使用' }) - await credentialStep.waitFor({ timeout: 15_000 }) - expect(await credentialStep.getByRole('textbox').count()).toBe(0) - const initial = await captureStableAria(page, '[role="region"]', scaffold.workspaceCwd) - await compareOrRefreshGolden(MISSING_EXPECTED, initial, MODE) - await credentialStep.getByRole('button', { name: '前往配置' }).click() - await credentialStep.waitFor({ state: 'detached', timeout: 15_000 }) - const settings = page.getByRole('dialog', { name: '设置' }) - await settings.waitFor({ timeout: 10_000 }) - expect(await page.locator('#root').evaluate(root => (root as HTMLElement).inert)).toBe(false) - const keyInput = settings.getByLabel('API 密钥', { exact: true }) + const credentialStep = page.getByRole('dialog', { name: '添加一个 API Key 开始使用' }) + await credentialStep.waitFor({ timeout: 15_000 }) + const keyInput = credentialStep.getByLabel('API 密钥', { exact: true }) await keyInput.waitFor({ timeout: 10_000 }) + const initial = await captureStableAria(page, '[role="dialog"]', scaffold.workspaceCwd) + await compareOrRefreshGolden(MISSING_EXPECTED, initial, MODE) const secret = `dsh_onboarding_${randomBytes(12).toString('hex')}` await keyInput.fill(secret) - await settings.getByRole('button', { name: '保存', exact: true }).click() - await keyInput.waitFor({ state: 'detached', timeout: 15_000 }) + await credentialStep.getByRole('button', { name: '保存并继续' }).click() + await credentialStep.waitFor({ state: 'detached', timeout: 15_000 }) + expect(await page.locator('#root').evaluate(root => (root as HTMLElement).inert)).toBe(false) const stored = await readFile(join(scaffold.harnessHome, '.credentials.yaml'), 'utf8') expect(stored.includes(`DEEPSEEK_API_KEY: ${secret}`)).toBe(true) @@ -117,8 +90,15 @@ describe.skipIf(MODE === 'record')('web e2e: first-run DeepSeek credential setup expect((await page.locator('body').ariaSnapshot()).includes(secret)).toBe(false) expect(browserConsole.some(line => line.includes(secret))).toBe(false) - // The same open Models surface reuses the refreshed join and exposes the + const acknowledgedSettings = await readFile(join(scaffold.harnessHome, 'settings.yaml'), 'utf8') + expect(acknowledgedSettings).toContain(`${WELCOME_NOTICE_ACK_FIELD}: ${WELCOME_NOTICE_VERSION}`) + + // The ordinary Models surface reuses the refreshed join and exposes the // configured write-only placeholder without a reload. + await page.getByRole('button', { name: '设置', exact: true }).click() + const settings = page.getByRole('dialog', { name: '设置' }) + await settings.waitFor({ timeout: 10_000 }) + await settings.getByRole('button', { name: '模型' }).click() const deepSeekRow = settings.getByText('DeepSeek', { exact: true }).first() await deepSeekRow.waitFor({ timeout: 10_000 }) await deepSeekRow.locator('xpath=ancestor::li').getByRole('button', { name: '编辑' }).click() @@ -129,18 +109,15 @@ describe.skipIf(MODE === 'record')('web e2e: first-run DeepSeek credential setup { timeout: 10_000 }, ).toBe('已配置——输入新值可替换') - const acknowledgedSettings = await readFile(join(scaffold.harnessHome, 'settings.yaml'), 'utf8') - expect(acknowledgedSettings).toContain(`${WELCOME_NOTICE_ACK_FIELD}: ${WELCOME_NOTICE_VERSION}`) - const secondReloadWarnings = tripwire.warnings.length await page.reload({ waitUntil: 'load' }) acknowledgeReloadConnectionLoss(tripwire, secondReloadWarnings) await page.waitForSelector('[class*="frame"]', { timeout: 15_000 }) - expect(await page.getByRole('region', { name: WELCOME_NOTICE_COPY.zh.title }).count()).toBe(0) - expect(await page.getByRole('region', { name: '添加一个 API Key 开始使用' }).count()).toBe(0) + expect(await page.getByRole('dialog', { name: WELCOME_NOTICE_COPY.zh.title }).count()).toBe(0) + expect(await page.getByRole('dialog', { name: '添加一个 API Key 开始使用' }).count()).toBe(0) - // A different stored copy version represents an intentional version bump: - // the welcome step returns even though the credential is already ready. + // An old acknowledgement means materially revised copy: welcome returns, + // while the already-configured provider step remains complete. await scaffold.ctx.settings.mutate(settingsNamespace(WELCOME_NOTICE_SETTINGS_NAMESPACE), [{ op: 'set', path: [WELCOME_NOTICE_ACK_FIELD], value: 'previous-copy-version', }]) @@ -150,7 +127,7 @@ describe.skipIf(MODE === 'record')('web e2e: first-run DeepSeek credential setup await welcome.waitFor({ timeout: 15_000 }) await welcome.getByRole('button', { name: WELCOME_NOTICE_COPY.zh.continueLabel }).click() await welcome.waitFor({ state: 'detached', timeout: 15_000 }) - expect(await page.getByRole('region', { name: '添加一个 API Key 开始使用' }).count()).toBe(0) + expect(await page.getByRole('dialog', { name: '添加一个 API Key 开始使用' }).count()).toBe(0) expect((await page.content()).includes(secret)).toBe(false) expect((await page.locator('body').ariaSnapshot()).includes(secret)).toBe(false) @@ -161,10 +138,9 @@ describe.skipIf(MODE === 'record')('web e2e: first-run DeepSeek credential setup it('never paints the takeover chrome on a configured reload, even with the settings join held open', async () => { onTestFailed(() => saveFailureShot(page, 'web-e2e-onboarding-configured-reload')) - // Regression pin for the reload white flash: both steps are satisfied - // (welcome acknowledged, credential configured), yet each must LOAD its - // private join before it can decide not to show. The chrome lives inside - // the step (OnboardingSurface), so the deciding window paints and blocks + // Regression pin for the reload flash: both steps are satisfied, yet each + // must load private facts before deciding not to show. Dialog chrome lives + // inside each visible branch, so the deciding window paints and blocks // nothing. Holding settings.describe widens that window from loopback // RTT scale to a deterministic hundreds of milliseconds, removing all // timing dependence from the sampler assertions below. @@ -177,7 +153,10 @@ describe.skipIf(MODE === 'record')('web e2e: first-run DeepSeek credential setup const sightings: string[] = [] ;(window as unknown as { __takeoverSightings: string[] }).__takeoverSightings = sightings setInterval(() => { - if (document.querySelector('[class*="onboardingStage"], [class*="onboardingMask"]') !== null) { + if (document.querySelector( + '[role="dialog"][aria-label="内测声明"], ' + + '[role="dialog"][aria-label="添加一个 API Key 开始使用"]', + ) !== null) { sightings.push('chrome') } if (document.getElementById('root')?.inert === true) sightings.push('inert') @@ -207,14 +186,15 @@ describe.skipIf(MODE === 'record')('web e2e: first-run DeepSeek credential setup acknowledgeReloadConnectionLoss(tripwire, warningsBefore) expect(await page.evaluate(() => (window as unknown as { __takeoverSightings: string[] }).__takeoverSightings)).toEqual([]) - expect(await page.locator('[class*="onboardingStage"]').count()).toBe(0) + expect(await page.getByRole('dialog', { name: WELCOME_NOTICE_COPY.zh.title }).count()).toBe(0) + expect(await page.getByRole('dialog', { name: '添加一个 API Key 开始使用' }).count()).toBe(0) expect(tripwire.pageErrors).toEqual([]) }, 60_000) it('configures arbitrary DeepSeek models and prompts after the selected model is removed', async () => { onTestFailed(() => saveFailureShot(page, 'web-e2e-onboarding-deepseek-models')) // Opened here rather than inherited: the credential test reloads the page - // to exercise the welcome step, so nothing carries an open dialog across. + // after configuring the key, so nothing carries an open dialog across. await page.getByRole('button', { name: '设置', exact: true }).click() const settings = page.getByRole('dialog', { name: '设置' }) await settings.waitFor({ timeout: 10_000 }) @@ -264,7 +244,7 @@ describe.skipIf(MODE === 'record')('web e2e: first-run DeepSeek credential setup it('keeps the fixture inventory closed', async () => { await assertFixtureInventory( SNAPSHOT_DIR, - ['missing.expected.md', 'models.expected.md', 'welcome.expected.md'], + ['welcome.expected.md', 'missing.expected.md', 'models.expected.md'], ) }) }) diff --git a/apps/web/tests/onboarding-usable-provider.e2e.ts b/apps/web/tests/onboarding-usable-provider.e2e.ts index 09e3923064..5638668705 100644 --- a/apps/web/tests/onboarding-usable-provider.e2e.ts +++ b/apps/web/tests/onboarding-usable-provider.e2e.ts @@ -44,14 +44,17 @@ describe.skipIf(MODE === 'record')('web e2e: another usable provider ends first- it('closes the setup card without discarding the add card beside it', async () => { onTestFailed(() => saveFailureShot(page, 'web-e2e-onboarding-setup-card-cancel')) - const credentialStep = page.getByRole('region', { name: CREDENTIAL_STEP }) + const credentialStep = page.getByRole('dialog', { name: CREDENTIAL_STEP }) await credentialStep.waitFor({ timeout: 15_000 }) - await credentialStep.getByRole('button', { name: '前往配置' }).click() + await credentialStep.getByRole('button', { name: '稍后配置' }).click() await credentialStep.waitFor({ state: 'detached', timeout: 15_000 }) + await page.getByRole('button', { name: '设置', exact: true }).click() const settings = page.getByRole('dialog', { name: '设置' }) await settings.waitFor({ timeout: 10_000 }) - // Nothing is reachable yet, so DeepSeek presents itself as its open card. + // The onboarding step no longer navigates into Settings on dismissal, so + // enter the Models section explicitly before exercising its normal cards. + await settings.getByRole('button', { name: '模型' }).click() const setupKey = settings.getByRole('textbox', { name: 'API 密钥', exact: true }) await setupKey.waitFor({ timeout: 10_000 }) @@ -66,15 +69,14 @@ describe.skipIf(MODE === 'record')('web e2e: another usable provider ends first- { timeout: 10_000 }, ).toBe(2) - // Cancelling the setup card is the regression: it used to leave itself open - // and close the add card, discarding that draft. + // Cancelling the setup card must not close the independent add-provider + // draft beside it. await settings.getByRole('button', { name: '取消', exact: true }).first().click() expect(await settings.getByLabel('提供方').count()).toBe(1) await expect.poll( async () => settings.getByRole('textbox', { name: 'API 密钥', exact: true }).count(), { timeout: 10_000 }, ).toBe(1) - // DeepSeek is now an ordinary row: a missing-key dot and an Edit button. await settings.getByRole('button', { name: '编辑 DeepSeek (deepseek-official)' }).waitFor({ timeout: 10_000 }) const dismissed = await captureStableAria(page, '[role="dialog"]', scaffold.workspaceCwd) await compareOrRefreshGolden(DISMISSED_EXPECTED, dismissed, MODE) @@ -104,10 +106,9 @@ describe.skipIf(MODE === 'record')('web e2e: another usable provider ends first- // The regression: the step read only the official route's credential, so a // fully configured user was taken over on every blank session. await expect.poll( - async () => page.getByRole('region', { name: CREDENTIAL_STEP }).count(), + async () => page.getByRole('dialog', { name: CREDENTIAL_STEP }).count(), { timeout: 10_000 }, ).toBe(0) - expect(await page.locator('[class*="onboardingStage"]').count()).toBe(0) expect(await page.locator('#root').evaluate(root => (root as HTMLElement).inert)).toBe(false) // The Models page agrees: DeepSeek stays a row rather than reopening its diff --git a/apps/web/tests/pwsh-terminal.overlay.yml b/apps/web/tests/pwsh-terminal.overlay.yml index 43afe77e51..23b917c080 100644 --- a/apps/web/tests/pwsh-terminal.overlay.yml +++ b/apps/web/tests/pwsh-terminal.overlay.yml @@ -1,20 +1,30 @@ # The pwsh terminal-card lane swaps the shipped bash stack for the PowerShell -# twin: the bash executor row is disabled (patches cannot rename a row — `name` -# is a guard) and the pwsh executor + tool are inserted. The permission service -# refuses an unconfined executor by design (presets bundle a sandbox mode), so -# its row is disabled too — this lane renders a seeded session, never a -# permission decision. The seeded scenario renders the logged pwsh call/result -# through the real tools on replay; no command executes, but the composition -# must boot the pwsh executor, so the lane skips on hosts without a usable -# `pwsh`. +# twin: the bash executor row is disabled, the pwsh executor is inserted, and +# the host tool-pwsh row is enabled by id. The pwsh-sandbox row is disabled +# too so the inserted pwsh-local is the lone executor on every platform. The +# permission service refuses an unconfined executor by design (presets bundle +# a sandbox mode), so its row is disabled as well — this lane renders a seeded +# session, never a permission decision. The seeded scenario renders the logged +# pwsh call/result through the real tools on replay; no command executes, but +# the composition must boot the pwsh executor, so the lane skips on hosts +# without a usable `pwsh`. - id: bash-sandbox name: '@deepseek-ai/dsh-bash-sandbox' disabled: true +- id: pwsh-sandbox + name: '@deepseek-ai/dsh-pwsh-sandbox' + disabled: true - id: permission name: '@deepseek-ai/dsh-permission-presets' disabled: true - insert: - id: pwsh-local name: '@deepseek-ai/dsh-pwsh-local' - - id: tool-pwsh - name: '@deepseek-ai/dsh-tool-pwsh' + +# tool-pwsh already exists in the shipped composition: the base bundle declares +# it platform-gated on every platform, and the web-app overlay disables it for +# surfaces that use presets. So this lane enables it by id rather than +# inserting a second row to the same id. +- id: tool-pwsh + name: '@deepseek-ai/dsh-tool-pwsh' + disabled: false diff --git a/apps/web/tests/remote-welcome.e2e.ts b/apps/web/tests/remote-welcome.e2e.ts index 7187936ae9..256afaeede 100644 --- a/apps/web/tests/remote-welcome.e2e.ts +++ b/apps/web/tests/remote-welcome.e2e.ts @@ -1,5 +1,5 @@ -// Trusted non-loopback Web access must not wedge on the loopback-only -// settings API while the mandatory product notice owns the viewport. +// Trusted non-loopback Web access cannot call the loopback-only settings API; +// the notice therefore advances for this browser process and returns on reload. import type { Browser, Page } from 'playwright' import { chromium } from 'playwright' import { afterAll, beforeAll, describe, expect, it } from 'vitest' @@ -19,9 +19,15 @@ describe.skipIf(MODE === 'record')('web e2e: remote welcome notice', () => { let tripwire: ReturnType beforeAll(async () => { - scaffold = await launchWebScaffold({ remoteAuthority: 'remote.localhost', welcomeNoticePending: true }) + scaffold = await launchWebScaffold({ + remoteAuthority: 'remote.localhost', + welcomeNoticePending: true, + }) browser = await chromium.launch() - page = await browser.newPage({ viewport: { width: 1440, height: 960 }, locale: ZH_BROWSER_LOCALE }) + page = await browser.newPage({ + viewport: { width: 1440, height: 960 }, + locale: ZH_BROWSER_LOCALE, + }) tripwire = watchConsole(page) await page.goto(scaffold.baseUrl, { waitUntil: 'load' }) await page.waitForSelector('#root', { timeout: 30_000 }) @@ -33,7 +39,7 @@ describe.skipIf(MODE === 'record')('web e2e: remote welcome notice', () => { }) it('advances process-locally and presents the notice again after reload', async () => { - const welcome = page.getByRole('region', { name: WELCOME_NOTICE_COPY.zh.title }) + const welcome = page.getByRole('dialog', { name: WELCOME_NOTICE_COPY.zh.title }) await welcome.waitFor({ timeout: 15_000 }) expect(await page.locator('#root').evaluate(root => (root as HTMLElement).inert)).toBe(true) @@ -43,6 +49,7 @@ describe.skipIf(MODE === 'record')('web e2e: remote welcome notice', () => { () => page.locator('#root').evaluate(root => (root as HTMLElement).inert), { timeout: 15_000 }, ).toBe(false) + const reloadWarnings = tripwire.warnings.length await page.reload({ waitUntil: 'load' }) acknowledgeReloadConnectionLoss(tripwire, reloadWarnings) diff --git a/apps/web/tests/scaffold.ts b/apps/web/tests/scaffold.ts index 1c3fb67e85..f1ba62d881 100644 --- a/apps/web/tests/scaffold.ts +++ b/apps/web/tests/scaffold.ts @@ -23,7 +23,7 @@ // (the plugin-row path discards the ReplayHandle; the direct install keeps // assertConsumed for the teardown fixture-consumption check). import { existsSync } from 'node:fs' -import { mkdir, mkdtemp, readFile, readdir, realpath, rm, utimes, writeFile } from 'node:fs/promises' +import { mkdir, mkdtemp, readFile, readdir, realpath, rm, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' import { pathToFileURL } from 'node:url' @@ -41,19 +41,6 @@ import { loadOverlayPatches, } from '@deepseek-ai/dsh-app-boot' import { dshHomePath } from '@deepseek-ai/dsh-home-paths' -// Client packages must not be imported here: these e2e type-check in the Host -// aggregate, so a Client import pulls that package's whole project — and every -// project it references — into the Host build graph. Mirrored from -// packages/client/ui-settings-general/src/onboarding-copy.ts; a drift makes the -// pre-acknowledgement stop suppressing the notice, which fails loudly. -// import { -// WELCOME_NOTICE_ACK_FIELD, WELCOME_NOTICE_SETTINGS_NAMESPACE, WELCOME_NOTICE_VERSION, WELCOME_NOTICE_COPY, -// } from '@deepseek-ai/dsh-client-ui-settings-general' -export const WELCOME_NOTICE_SETTINGS_NAMESPACE = 'ui-onboarding' -export const WELCOME_NOTICE_ACK_FIELD = 'welcomeNoticeVersion' -export const WELCOME_NOTICE_VERSION = '2026-08-11.1' -export const WELCOME_NOTICE_COPY = { zh: { title: '内测声明', continueLabel: '继续' } } as const - import { settingsNamespace } from '@deepseek-ai/dsh-settings' import { LlmAdapter } from '@deepseek-ai/dsh-llm' import type { @@ -76,6 +63,25 @@ import type {} from '@deepseek-ai/dsh-agent' import { provideCmdline } from '@deepseek-ai/dsh-cmdline' import { REPO_ROOT, requireDist } from './support.ts' +// Host-side web e2e cannot import a browser package: doing so would pull that +// package's complete TS project into this graph. Mirrored from +// packages/client/ui-settings-models/src/onboarding-copy.ts; drift makes the +// default pre-acknowledgement stop suppressing the notice and fails loudly. +// import { +// WELCOME_NOTICE_ACK_FIELD, WELCOME_NOTICE_SETTINGS_NAMESPACE, +// WELCOME_NOTICE_VERSION, WELCOME_NOTICE_COPY, +// } from '@deepseek-ai/dsh-client-ui-settings-models' +export const WELCOME_NOTICE_SETTINGS_NAMESPACE = 'ui-onboarding' +export const WELCOME_NOTICE_ACK_FIELD = 'welcomeNoticeVersion' +export const WELCOME_NOTICE_VERSION = '2026-08-13.1' +export const WELCOME_NOTICE_COPY = { + zh: { + title: '内测声明', + body: 'DeepSeek Harness 目前的 0.1 版本仍处在面向 Harness 开发者进行测试的阶段,还有许多地方需要持续改进和打磨,希望听取广大开发者的反馈建议。预计 DeepSeek Harness 的核心插件以及基础 API 都会在接下来的一段时间内快速迭代、持续演化。\n\n我们期待与全球开发者一起,在开源、开放、可复用、可组合的基础设施之上,共同探索智能上限。欢迎全球 Harness 开发者加入 DSH 插件生态。', + continueLabel: '继续', + }, +} as const + /** Snapshot mode for the lane, from $DSH_SNAPSHOT (same vocabulary as the other snapshot suites). */ export type WebSnapshotMode = 'replay' | 'record' | 'refresh' @@ -227,6 +233,8 @@ export interface LaunchOptions { * keyless first-run configuration lane; the default disables the adapter. */ deepSeekMissingCredential?: boolean + /** Leave the current welcome notice pending; ordinary scenarios pre-acknowledge it before browser boot. */ + welcomeNoticePending?: boolean /** * Patch the shipped DeepSeek search row to a deterministic endpoint and * credential reference. Browser search scenarios keep the real provider and @@ -252,8 +260,6 @@ export interface LaunchOptions { /** The preset a session that names none is composed from. */ default: string } - /** Leave the current welcome notice unacknowledged; ordinary scenarios publish it as complete before browser boot. */ - welcomeNoticePending?: boolean /** * Mount the shipped telemetry row in FULL mode against this exporter URL * instead of disabling it. Used to pin a real backend disclosure in @@ -391,6 +397,10 @@ export async function launchWebScaffold(options: LaunchOptions = {}): Promise { + const meta: SessionHeader = { + version: SESSION_FORMAT_VERSION, + id: SessionId(id), + createdAt: Date.now() - 60_000, + cwd, + delegationDepth: 0, + } + await persistSeedSession(scaffold, meta, [{ + type: 'session/end-seed', + seq: 0, + time: meta.createdAt, + data: {}, + }]) + return meta.id +} + +/** Materialize one detached Session fixture through the shipped JSONL provider. */ +async function persistSeedSession( + scaffold: WebScaffold, + meta: SessionHeader, + events: readonly SessionEvent[], +): Promise { const seeder = new Context() try { await seeder.plugin(SessionStore) @@ -728,16 +770,9 @@ export async function seedSession( await seeder.plugin(JsonlSessionPersistence, { root: scaffold.persistenceRoot }) await seeder.sessionPersistence.create(meta) await seeder.sessionPersistence.append(meta.id, events) - // Deterministic sidebar order: cold summaries take updatedAt from mtime. - const located = seeder.sessionPersistence.locate(meta) - if (located !== undefined) { - const backdated = new Date(meta.createdAt) - await utimes(located.path, backdated, backdated) - } } finally { await seeder.fiber.dispose() } - return meta.id } /** diff --git a/apps/web/tests/smoke-real.e2e.ts b/apps/web/tests/smoke-real.e2e.ts index 2784b66d07..5d479e9552 100644 --- a/apps/web/tests/smoke-real.e2e.ts +++ b/apps/web/tests/smoke-real.e2e.ts @@ -533,16 +533,9 @@ describe.skipIf(!process.env.DEEPSEEK_API_KEY || notReady.length > 0)('web smoke it('empty-state first send completes a real model round', async () => { onTestFailed(() => saveFailureShot(page, 'w5-first-round')) - // This scenario spawns its own server against a fresh $DSH_HOME, so the - // first-run welcome notice is unacknowledged and its overlay owns pointer - // events (the shared scaffold acknowledges it before boot instead). The - // notice is anchored structurally, not by its copy: this spec sits in the - // client TypeScript program, which does not reference the package that - // owns the strings. - const welcome = page.locator('[class*="onboardingOverlay"]') - await welcome.waitFor({ timeout: 15_000 }) - await welcome.getByRole('button').click() - await welcome.waitFor({ state: 'detached', timeout: 15_000 }) + // This scenario spawns its own server against a fresh $DSH_HOME with the + // DeepSeek credential inherited from the environment, so no onboarding + // step mounts and the page is immediately interactive. // Fresh world: connect a Workspace so the composer starts live. await connectFreshWorkspace(page, sessionsDir) const input = page.locator('textarea').first() diff --git a/apps/web/tests/snapshots/agent-preset-selection/menu.expected.md b/apps/web/tests/snapshots/agent-preset-selection/menu.expected.md index 7e0d1ae032..9e3116d353 100644 --- a/apps/web/tests/snapshots/agent-preset-selection/menu.expected.md +++ b/apps/web/tests/snapshots/agent-preset-selection/menu.expected.md @@ -2,6 +2,6 @@ - menuitem "Standard mode Full coding agent with file editing, shell, file and web search, skills, planning, goals, subagents, and workflows.": - text: Standard mode Full coding agent with file editing, shell, file and web search, skills, planning, goals, subagents, and workflows. - img - - menuitem "Code mode All Standard mode capabilities, with tools exposed through the Code Mode SDK so the model can combine multi-step operations in one TypeScript program." + - menuitem "PTC mode All Standard mode capabilities, with tools exposed through the Code Mode SDK so the model can combine multi-step operations in one TypeScript program." - menuitem "Minimal mode Two-tool coding agent with persistent bash and str_replace_editor." - menuitem "Creator mode Built for creating custom agent presets, with all Standard mode capabilities plus runtime inspection, plugin experiments, and preset-authoring guidance." diff --git a/apps/web/tests/snapshots/cold-blank-session/sidebar.expected.md b/apps/web/tests/snapshots/cold-blank-session/sidebar.expected.md new file mode 100644 index 0000000000..d4d370892e --- /dev/null +++ b/apps/web/tests/snapshots/cold-blank-session/sidebar.expected.md @@ -0,0 +1 @@ +- tree "Sessions": No sessions yet diff --git a/apps/web/tests/snapshots/composer-tab-geometry/geometry.expected.md b/apps/web/tests/snapshots/composer-tab-geometry/geometry.expected.md index 9735019508..e95adaaa6f 100644 --- a/apps/web/tests/snapshots/composer-tab-geometry/geometry.expected.md +++ b/apps/web/tests/snapshots/composer-tab-geometry/geometry.expected.md @@ -5,9 +5,9 @@ - Chat: scrollbar-gutter stable, overflow hidden/auto - Chat scroller scrolls: true - Chat reserved band: 8px -- Trajectory: scrollbar-gutter stable, overflow hidden/auto +- Trajectory: scrollbar-gutter auto, overflow hidden/auto - Trajectory scroller scrolls: false -- Trajectory reserved band: 8px +- Trajectory reserved band: 0px - input card left edge moves between tabs: 0px - input card right edge moves between tabs: 0px - input card width changes between tabs: 0px @@ -17,19 +17,19 @@ - Chat: scrollbar-gutter stable, overflow hidden/auto - Chat scroller scrolls: true - Chat reserved band: 8px -- Trajectory: scrollbar-gutter stable, overflow hidden/auto +- Trajectory: scrollbar-gutter auto, overflow hidden/auto - Trajectory scroller scrolls: false -- Trajectory reserved band: 8px +- Trajectory reserved band: 0px - input card left edge moves between tabs: 0px - input card right edge moves between tabs: 0px - input card width changes between tabs: 0px -## Wide viewport, reservation removed in the page (control) +## Wide viewport, seat compensation removed in the page (control) -- Chat: scrollbar-gutter auto, overflow hidden/auto +- Chat: scrollbar-gutter stable, overflow hidden/auto - Chat scroller scrolls: true - Chat reserved band: 8px -- Trajectory: scrollbar-gutter auto, overflow hidden/hidden +- Trajectory: scrollbar-gutter auto, overflow hidden/auto - Trajectory scroller scrolls: false - Trajectory reserved band: 0px - input card left edge moves between tabs: 4px diff --git a/apps/web/tests/snapshots/message-actions/fork.expected.md b/apps/web/tests/snapshots/message-actions/fork.expected.md index 2487b6c374..f7f9efb3ab 100644 --- a/apps/web/tests/snapshots/message-actions/fork.expected.md +++ b/apps/web/tests/snapshots/message-actions/fork.expected.md @@ -2,6 +2,6 @@ - treeitem "Ungrouped" [expanded]: - img - text: Ungrouped - - treeitem "Use the read tool twice 1min" - - treeitem "Use the read tool twice (1) now" - treeitem "Use the read tool twice (2) now" [selected] + - treeitem "Use the read tool twice (1) now" + - treeitem "Use the read tool twice 1min" diff --git a/apps/web/tests/snapshots/models-settings/empty.expected.md b/apps/web/tests/snapshots/models-settings/empty.expected.md index cea14113ac..2c928e2f0d 100644 --- a/apps/web/tests/snapshots/models-settings/empty.expected.md +++ b/apps/web/tests/snapshots/models-settings/empty.expected.md @@ -44,7 +44,6 @@ - option "moonshotai-cn" - option "nvidia" - option "openai" - - option "openai-codex" - option "opencode" - option "opencode-go" - option "openrouter" diff --git a/apps/web/tests/snapshots/onboarding-deepseek-config/missing.expected.md b/apps/web/tests/snapshots/onboarding-deepseek-config/missing.expected.md index ed37b0fe4d..d42cf40681 100644 --- a/apps/web/tests/snapshots/onboarding-deepseek-config/missing.expected.md +++ b/apps/web/tests/snapshots/onboarding-deepseek-config/missing.expected.md @@ -1,5 +1,8 @@ -- region "添加一个 API Key 开始使用": +- dialog "添加一个 API Key 开始使用": - heading "添加一个 API Key 开始使用" [level=2] - paragraph: 配置 DeepSeek 官方模型,即可开始使用。 + - text: API 密钥 + - textbox "API 密钥": + - /placeholder: 输入 API 密钥 - button "稍后配置" - - button "前往配置" + - button "保存并继续" [disabled] diff --git a/apps/web/tests/snapshots/onboarding-deepseek-config/welcome.expected.md b/apps/web/tests/snapshots/onboarding-deepseek-config/welcome.expected.md index 8332305eed..de65e02fc7 100644 --- a/apps/web/tests/snapshots/onboarding-deepseek-config/welcome.expected.md +++ b/apps/web/tests/snapshots/onboarding-deepseek-config/welcome.expected.md @@ -1,9 +1,5 @@ -- region "内测声明": +- dialog "内测声明": - heading "内测声明" [level=2] - - paragraph: 感谢您愿意拨冗试用 DeepSeek Harness。当前版本仍处于内部测试阶段,功能仍待完善,体验难免有些粗糙。 - - blockquote: “如切如磋,如琢如磨。” 产品的成长,离不开一次次真实的碰撞与坦诚的反馈。您在真实使用中发现的问题,也可能促使我们重新审视,甚至推翻已有的设计。 - - paragraph: - - text: 内测版本默认不会上传 Session Log。如需在提交反馈时共享会话日志,可以设置环境变量 DSH_TELEMETRY_MODE=FEEDBACK_ONLY;如需持续上传,可以设置 DSH_TELEMETRY_MODE=FULL,但该模式同时会启用 dsh-sdk 命令遥测,上报匿名 ID、命令结果以及脱敏后的项目配置。另外, - - strong: 如果您有任何反馈与建议,请在企业微信群中留言告诉我们 - - text: 。每一条反馈,都会帮助我们把它打磨得更好。 + - paragraph: DeepSeek Harness 目前的 0.1 版本仍处在面向 Harness 开发者进行测试的阶段,还有许多地方需要持续改进和打磨,希望听取广大开发者的反馈建议。预计 DeepSeek Harness 的核心插件以及基础 API 都会在接下来的一段时间内快速迭代、持续演化。 + - paragraph: 我们期待与全球开发者一起,在开源、开放、可复用、可组合的基础设施之上,共同探索智能上限。欢迎全球 Harness 开发者加入 DSH 插件生态。 - button "继续" diff --git a/apps/web/tests/snapshots/onboarding-usable-provider/dismissed.expected.md b/apps/web/tests/snapshots/onboarding-usable-provider/dismissed.expected.md index 84c7358b54..809e7880ff 100644 --- a/apps/web/tests/snapshots/onboarding-usable-provider/dismissed.expected.md +++ b/apps/web/tests/snapshots/onboarding-usable-provider/dismissed.expected.md @@ -48,7 +48,6 @@ - option "moonshotai-cn" - option "nvidia" - option "openai" - - option "openai-codex" - option "opencode" - option "opencode-go" - option "openrouter" diff --git a/apps/web/tests/snapshots/question-composer/composed.expected.md b/apps/web/tests/snapshots/question-composer/composed.expected.md index c18e6225c6..66f3706af5 100644 --- a/apps/web/tests/snapshots/question-composer/composed.expected.md +++ b/apps/web/tests/snapshots/question-composer/composed.expected.md @@ -1,6 +1,8 @@ - region "Which color do you prefer?": - text: Pick one - heading "Which color do you prefer?" [level=2] + - button "Collapse the question card" [expanded]: + - img - button "Dismiss all questions": - img - group: diff --git a/apps/web/tests/snapshots/question-composer/ui.expected.md b/apps/web/tests/snapshots/question-composer/ui.expected.md index c2ee767319..1c7109702d 100644 --- a/apps/web/tests/snapshots/question-composer/ui.expected.md +++ b/apps/web/tests/snapshots/question-composer/ui.expected.md @@ -1,6 +1,8 @@ - region "Which color do you prefer?": - text: Pick one - heading "Which color do you prefer?" [level=2] + - button "Collapse the question card" [expanded]: + - img - button "Dismiss all questions": - img - group: diff --git a/apps/web/tests/snapshots/sidebar-subagent-activity/owner-running.expected.md b/apps/web/tests/snapshots/sidebar-subagent-activity/owner-running.expected.md index 62671cbb8b..7e1864ff58 100644 --- a/apps/web/tests/snapshots/sidebar-subagent-activity/owner-running.expected.md +++ b/apps/web/tests/snapshots/sidebar-subagent-activity/owner-running.expected.md @@ -2,5 +2,5 @@ - treeitem "workspace" [expanded]: - img - text: workspace - - treeitem "New Session" [selected] - treeitem "1 subagent running Delegate a background job. now" + - treeitem "New Session" [selected] diff --git a/apps/web/tests/snapshots/steering/mid-steer.expected.md b/apps/web/tests/snapshots/steering/mid-steer.expected.md index e3b82f0964..9a713be0e5 100644 --- a/apps/web/tests/snapshots/steering/mid-steer.expected.md +++ b/apps/web/tests/snapshots/steering/mid-steer.expected.md @@ -32,6 +32,8 @@ - region "Ready to continue?": - text: Checkpoint - heading "Ready to continue?" [level=2] + - button "Collapse the question card" [expanded]: + - img - button "Dismiss all questions": - img - radiogroup: diff --git a/apps/web/tests/snapshots/subagent-conversation/fork.expected.md b/apps/web/tests/snapshots/subagent-conversation/fork.expected.md index 398c3ceddd..c60eb2d064 100644 --- a/apps/web/tests/snapshots/subagent-conversation/fork.expected.md +++ b/apps/web/tests/snapshots/subagent-conversation/fork.expected.md @@ -2,5 +2,5 @@ - treeitem "workspace" [expanded]: - img - text: workspace - - treeitem "Ask a research subagent to now" - treeitem "Explain event sourcing in one (1) now" [selected] + - treeitem "Ask a research subagent to now" diff --git a/apps/web/tests/snapshots/trajectory-virtualization/load-more.expected.md b/apps/web/tests/snapshots/trajectory-virtualization/load-more.expected.md new file mode 100644 index 0000000000..c3c1302000 --- /dev/null +++ b/apps/web/tests/snapshots/trajectory-virtualization/load-more.expected.md @@ -0,0 +1,4 @@ +- row "Load earlier history": + - cell "Load earlier history": + - button "Load earlier history": + - status diff --git a/apps/web/tests/trajectory-virtualization.e2e.ts b/apps/web/tests/trajectory-virtualization.e2e.ts index 64f149646b..16880295fd 100644 --- a/apps/web/tests/trajectory-virtualization.e2e.ts +++ b/apps/web/tests/trajectory-virtualization.e2e.ts @@ -3,6 +3,7 @@ // DOM mounting stays bounded, and every scroll range remains reachable. import { mkdtemp, rm, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' +import { fileURLToPath } from 'node:url' import { join } from 'node:path' import type { Browser, Page } from 'playwright' import { chromium } from 'playwright' @@ -11,6 +12,8 @@ import type { StreamChunk } from '@deepseek-ai/dsh-llm' import type { ReplayEntry } from '@deepseek-ai/dsh-llm-replay' import { createChatScrollFixture } from './chat-scroll-fixture.ts' import { + captureStableAria, + compareOrRefreshGolden, launchWebScaffold, seedSession, watchConsole, @@ -20,6 +23,10 @@ import { import { newEnglishPage, saveFailureShot } from './support.ts' const MODE = webSnapshotMode() +const LOAD_MORE_EXPECTED = fileURLToPath(new URL( + './snapshots/trajectory-virtualization/load-more.expected.md', + import.meta.url, +)) const SESSION_ID = 'trajectory-virtualization-e2e' const FIXTURE = createChatScrollFixture({ markerPrefix: 'TRAJECTORY_VIRTUAL', @@ -150,10 +157,16 @@ async function loadToFirstTurn(page: Page): Promise { await scrollToRatio(page, 0) if (await page.getByText(marker, { exact: false }).count() > 0) return const before = await logicalRows(page) + const anchor = await firstVisibleRow(page) await expect.poll(async () => ({ marker: await page.getByText(marker, { exact: false }).count() > 0, rows: await logicalRows(page), }), { timeout: 30_000 }).not.toEqual({ marker: false, rows: before }) + await nextPaint(page) + await expect.poll(async () => { + const top = await rowTop(page, anchor.key) + return top === null ? Number.POSITIVE_INFINITY : Math.abs(top - anchor.top) + }, { timeout: 15_000 }).toBeLessThanOrEqual(GEOMETRY_TOLERANCE) } throw new Error('trajectory did not reach the first turn after twelve older-page requests') } @@ -230,8 +243,27 @@ describe('web e2e: Trajectory virtualization over tail-paged history', () => { expect(await page.getByText('Initial System Prompt', { exact: true }).count()).toBe(0) expect(await mountedRows(page)).toBeLessThanOrEqual(MAX_MOUNTED_ROWS) - await scrollToRatio(page, 0) + const loadMore = page.locator('[data-history-load] button') + await loadMore.waitFor({ timeout: 15_000 }) + expect(await loadMore.textContent()).toBe('Load earlier history') + const loadMoreSnapshot = await captureStableAria( + page, + '[data-history-load]', + scaffold.workspaceCwd, + ) + await compareOrRefreshGolden(LOAD_MORE_EXPECTED, loadMoreSnapshot, MODE) + // Avoid Playwright scrolling the offscreen first row into the automatic-load threshold. + await loadMore.evaluate((button: HTMLButtonElement) => { button.click() }) await expect.poll(() => held, { timeout: 15_000 }).toBe(true) + await expect.poll(async () => ({ + disabled: await loadMore.isDisabled(), + label: await loadMore.getAttribute('aria-label'), + }), { timeout: 15_000 }).toEqual({ + disabled: true, + label: 'Loading earlier history…', + }) + + await scrollToRatio(page, 0) const anchor = await firstVisibleRow(page) const selectedRow = page.locator( `[data-trajectory-scroll] tr[data-trajectory-row-key=${JSON.stringify(anchor.key)}]`, diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json index e087543cf9..6e706c7123 100644 --- a/apps/web/tsconfig.json +++ b/apps/web/tsconfig.json @@ -48,6 +48,7 @@ "tests/replay-round-trip.e2e.ts", "tests/hmr-live.e2e.ts", "tests/seeded-history.e2e.ts", + "tests/cold-blank-session.e2e.ts", "tests/stats-paged-history.e2e.ts", "tests/sidebar-scrollbar.e2e.ts", "tests/conversation-column-overflow.e2e.ts", diff --git a/assets/community-wechat-official-account.png b/assets/community-wechat-official-account.png new file mode 100644 index 0000000000..222a051dc8 Binary files /dev/null and b/assets/community-wechat-official-account.png differ diff --git a/assets/community-wecom-assistant.png b/assets/community-wecom-assistant.png new file mode 100644 index 0000000000..b735f2ccc7 Binary files /dev/null and b/assets/community-wecom-assistant.png differ diff --git a/assets/community-wecom-survey.png b/assets/community-wecom-survey.png index d6f6040ba7..800865f785 100644 Binary files a/assets/community-wecom-survey.png and b/assets/community-wecom-survey.png differ diff --git a/docs/architecture.i18n.yaml b/docs/architecture.i18n.yaml index 482e683aa9..ab7a7558b8 100644 --- a/docs/architecture.i18n.yaml +++ b/docs/architecture.i18n.yaml @@ -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 docs/architecture.md -architecture.md: ad5b9072d2731b0b68c5f6035dafe37bc6229de8 -architecture.zh.md: 24ccd3bfbbd86213134201e49c8e768037eecd38 +architecture.md: a1507fa5e54f6703e89f09a5d387e6c9afc81ade +architecture.zh.md: 4642a1e7691bccf4d52d9a84c92c8237c3c6658b diff --git a/docs/architecture.md b/docs/architecture.md index ad5b9072d2..a1507fa5e5 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -97,7 +97,7 @@ The session log is the source of the context the model sees. `deriveMessages()` ## Capability seams -A **seam** is a swappable capability with three roles: a **Service Definition** declaring the interface, a **Service provider** implementing it, and a **Consumer** using it, commonly a model-facing tool. A package may combine roles, but one role alone is not a seam; adding a capability means designing all three ([capability graph](capability-seams.md)). +A **seam** is a swappable capability with three roles: a **Service Definition** declaring the interface, a **Service Provider** implementing it, and a **Consumer** using it, commonly a model-facing tool. A package may combine roles, but one role alone is not a seam; adding a capability means designing all three ([capability graph](capability-seams.md)). Seams are why one provider swap changes the whole product. Filesystem and subprocess providers share one execution world, so pointing them at a remote sandbox moves Bash, PTY, and LSP with them, with no provider forks. [Subagent providers](subsystems/subagent.md) vary just as widely behind one interface, from a fresh child agent to a delegated turn in another product. @@ -126,4 +126,4 @@ New behavior attaches to a documented extension point. Changing the loop itself | Fork a live session | `ctx.sessions.fork(source, boundary?, childSessionId?)` | | Scope a registration to one agent | use that agent's `agent.ctx` | -The [extension cookbook](cookbook/extension-cookbook.md) maps features to capabilities and indexes the step-by-step guides for [packages](cookbook/adding-a-package.md), [tools](cookbook/adding-a-tool.md), [LLM adapters](cookbook/adding-an-llm-adapter.md), and [Chat nodes](cookbook/adding-a-conversation-node.md). +The [extension cookbook](cookbook/extension-cookbook.md) maps features to capabilities and indexes the step-by-step guides for [packages](cookbook/adding-a-package.md), [tools](cookbook/adding-a-tool.md), [LLM adapters](cookbook/adding-an-llm-adapter.md), [Chat nodes](cookbook/adding-a-conversation-node.md), and [settings cards](cookbook/adding-a-settings-card.md). diff --git a/docs/architecture.zh.md b/docs/architecture.zh.md index 24ccd3bfbb..4642a1e769 100644 --- a/docs/architecture.zh.md +++ b/docs/architecture.zh.md @@ -50,6 +50,8 @@ dsh --profile web --dump-config | [`core/scope`](subsystems/scope.md) | 按 agent 划分作用域的注册原语 | 库,无 ctx 键 | | [`llm/llm`](subsystems/llm-streaming.md) | 消息与流式词汇表,以及适配器 seam | `ctx.llm` | + + ## 事件 事件就是扩展点,而选对事件域是大多数改动的第一个决定。 @@ -60,6 +62,8 @@ dsh --profile web --dump-config [事件映射](event-producer-consumer.md)列出每个事件的生产方与消费方。 + + ## 轮次流程 一个**步骤**是一次模型请求加上它调用的工具。一个**轮次**包含零个或多个步骤:它在领取首条输入之前打开,并在不再欠下任何工作时关闭。 @@ -97,7 +101,7 @@ turn/end ## 能力 seam -一个 **seam** 是一项可替换能力,包含三种角色:声明接口的 **Service Definition**、实现它的 **Service provider**,以及使用它的 **Consumer**(通常是面向模型的工具)。一个包可以合并承担多个角色,但单一角色本身不是 seam;添加一项能力意味着把三者一并设计([能力图](capability-seams.md))。 +一个 **seam** 是一项可替换能力,包含三种角色:声明接口的 **Service Definition**、实现它的 **Service Provider**,以及使用它的 **Consumer**(通常是面向模型的工具)。一个包可以合并承担多个角色,但单一角色本身不是 seam;添加一项能力意味着把三者一并设计([能力图](capability-seams.md))。 seam 正是替换一个提供方就能改变整个产品的原因。文件系统与进程提供方共享同一个执行世界,因此把它们指向远程沙箱,也就把 Bash、PTY 和 LSP 一并搬了过去,无需提供方专用 fork。[subagent 提供方](subsystems/subagent.md)在同一个接口之后同样千差万别,从新建一个子 agent,到把一个轮次委派给另一个产品。 @@ -126,4 +130,4 @@ seam 正是替换一个提供方就能改变整个产品的原因。文件系统 | fork 活跃会话 | `ctx.sessions.fork(source, boundary?, childSessionId?)` | | 将注册项限定到单个 agent | 使用该 agent 的 `agent.ctx` | -[扩展实操手册](cookbook/extension-cookbook.md)将功能映射到能力,并索引[包](cookbook/adding-a-package.md)、[工具](cookbook/adding-a-tool.md)、[LLM(大语言模型)适配器](cookbook/adding-an-llm-adapter.md)和 [Chat 节点](cookbook/adding-a-conversation-node.md)的分步指南。 +[扩展实操手册](cookbook/extension-cookbook.md)将功能映射到能力,并索引[包](cookbook/adding-a-package.md)、[工具](cookbook/adding-a-tool.md)、[LLM(大语言模型)适配器](cookbook/adding-an-llm-adapter.md)、[Chat 节点](cookbook/adding-a-conversation-node.md)和[设置卡片](cookbook/adding-a-settings-card.md)的分步指南。 diff --git a/docs/config-catalog.i18n.yaml b/docs/config-catalog.i18n.yaml index 96397ace10..10cae6e914 100644 --- a/docs/config-catalog.i18n.yaml +++ b/docs/config-catalog.i18n.yaml @@ -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 docs/config-catalog.md -config-catalog.md: 09c6064c2c6bb3c1da6283a885db33a5b4a674df -config-catalog.zh.md: 0bd95a5ab24b7acf85ba7ca00125ea9135e7dd82 +config-catalog.md: 4f22ed3da7de81f94d6fc5ee55a305d117c126e7 +config-catalog.zh.md: 7054ec8b52a8c46bc1ace97112f086119a61cfec diff --git a/docs/config-catalog.md b/docs/config-catalog.md index 09c6064c2c..4f22ed3da7 100644 --- a/docs/config-catalog.md +++ b/docs/config-catalog.md @@ -9,6 +9,8 @@ This file is GENERATED from source (`scripts/gen-config-catalog.ts`) and verifie A `Requires:` line lists the service keys the plugin `inject`s: its `cordis.yml` tree must also load providers for those services. Scope is the harness tier (`packages/`); the vendored cordis plugins a config tree may also load (`hmr`, the console logger, …) are pinned upstream source ([vendoring policy](../vendor/README.md)) and not catalogued here. + + ## `@deepseek-ai/dsh-acp` Requires: `agents` @@ -29,6 +31,8 @@ Depends on: `Stream` (`@agentclientprotocol/sdk`) Source: [`packages/acp/acp/src/index.ts:70`](../packages/acp/acp/src/index.ts) + + ## `@deepseek-ai/dsh-acp-demo` ```ts config-catalog @@ -82,6 +86,8 @@ Depends on: [`agentCore`](../packages/examples/agent-spine-demo/src/index.ts) · Source: [`packages/examples/acp-demo/src/index.ts:39`](../packages/examples/acp-demo/src/index.ts) + + ## `@deepseek-ai/dsh-agent-default-model` ```ts config-catalog @@ -96,6 +102,8 @@ export interface Config { Source: [`packages/core/agent-default-model/src/index.ts:41`](../packages/core/agent-default-model/src/index.ts) + + ## `@deepseek-ai/dsh-agent-instructions` ```ts config-catalog @@ -124,6 +132,8 @@ export interface Config { Source: [`packages/context/agent-instructions/src/config.ts:18`](../packages/context/agent-instructions/src/config.ts) + + ## `@deepseek-ai/dsh-agent-loop` Requires: `agents` · `sessions` · `llm` · `tools` · `systemPrompt` @@ -154,6 +164,8 @@ Depends on: [`AgentOptions`](subsystems/core.md) · [`SessionId`](subsystems/cor Source: [`packages/core/agent-loop/src/index.ts:255`](../packages/core/agent-loop/src/index.ts) + + ## `@deepseek-ai/dsh-agent-presets` Requires: `loader` @@ -190,15 +202,18 @@ export type PresetTrust = 'system' | 'user' Source: [`packages/preset/agent-presets/src/preset.ts:52`](../packages/preset/agent-presets/src/preset.ts) + + ## `@deepseek-ai/dsh-agent-spine-demo` ```ts config-catalog /** * Bundle config: each field forwarded verbatim to the child that owns it — * `agents` to the agent loop (an app that pre-creates no agents, like the ACP - * bridge, simply omits it), `includeHarnessIdentity`, `persona`, and `toolOrder` - * to the system-prompt plugin (the fixed opener, deployment persona, and explicit - * model-facing tool order), the `tools` object to the tool registry (its presentation `mode`), + * bridge, simply omits it), `includeHarnessIdentity`, `includeRuntimeContext`, + * `persona`, and `toolOrder` to the system-prompt plugin (the fixed opener, + * dynamic-context policy, deployment persona, and explicit model-facing tool + * order), the `tools` object to the tool registry (its presentation `mode`), * `dshHome` to bash environment and local skill discovery, `sessionTitle` to * the fallback title service, `skills` to the * skill registry/local provider/tool consumer, `workspaceContext` to the @@ -222,6 +237,8 @@ export interface Config { maxParallelToolCalls?: AgentLoopConfig['maxParallelToolCalls'] /** Whether the system prompt includes the fixed Harness identity (default true). */ includeHarnessIdentity?: SystemPromptConfig['includeHarnessIdentity'] + /** Whether model history includes dynamic runtime-context snapshots (default true). */ + includeRuntimeContext?: SystemPromptConfig['includeRuntimeContext'] /** The deployment persona (see dsh-system-prompt's `Config`). */ persona?: SystemPromptConfig['persona'] /** The explicit model-facing tool order (see dsh-system-prompt's `Config`). */ @@ -275,7 +292,9 @@ export interface GoalConfig { Depends on: [`AgentLoopConfig`](#deepseek-aidsh-agent-loop) · [`GoalDomainConfig`](#deepseek-aidsh-goal) · [`InvariantConfig`](#deepseek-aidsh-invariants) · [`JobsConfig`](#deepseek-aidsh-jobs-local) · [`SessionTitleConfig`](#deepseek-aidsh-session-title) · [`SkillFileSystem`](../packages/skill/skill-filesystem/src/index.ts) · [`SkillRegistryConfig`](#deepseek-aidsh-skill) · [`SystemPromptConfig`](#deepseek-aidsh-system-prompt) · [`toolBash`](../packages/shell/tool-bash/src/index.ts) · [`toolGoal`](../packages/goal/tool-goal/src/index.ts) · [`toolJobs`](../packages/jobs/tool-jobs/src/index.ts) · [`ToolsConfig`](#deepseek-aidsh-tools) · [`toolSkill`](../packages/skill/tool-skill/src/index.ts) · [`workspaceContext`](../packages/context/agent-instructions/src/index.ts) -Source: [`packages/examples/agent-spine-demo/src/index.ts:91`](../packages/examples/agent-spine-demo/src/index.ts) +Source: [`packages/examples/agent-spine-demo/src/index.ts:92`](../packages/examples/agent-spine-demo/src/index.ts) + + ## `@deepseek-ai/dsh-agent-tool-presentation` @@ -299,6 +318,8 @@ Depends on: [`ToolPresentationMode`](subsystems/tools.md) Source: [`packages/core/agent-tool-presentation/src/index.ts:38`](../packages/core/agent-tool-presentation/src/index.ts) + + ## `@deepseek-ai/dsh-attachment-local` ```ts config-catalog @@ -319,6 +340,8 @@ export interface Config { Source: [`packages/attachment/attachment-local/src/index.ts:24`](../packages/attachment/attachment-local/src/index.ts) + + ## `@deepseek-ai/dsh-bash-local` Requires: `subprocess` @@ -343,6 +366,8 @@ export interface Config { Source: [`packages/shell/bash-local/src/index.ts:41`](../packages/shell/bash-local/src/index.ts) + + ## `@deepseek-ai/dsh-bash-sandbox` Requires: `subprocess` · `sandbox` · `sandboxPolicy` @@ -362,6 +387,8 @@ Depends on: [`LocalConfig`](#deepseek-aidsh-bash-local) Source: [`packages/shell/bash-sandbox/src/index.ts:35`](../packages/shell/bash-sandbox/src/index.ts) + + ## `@deepseek-ai/dsh-client-connection` Requires: `webServer` @@ -385,6 +412,8 @@ export interface ConnectionConfig { Source: [`packages/client/connection/src/index.ts:50`](../packages/client/connection/src/index.ts) + + ## `@deepseek-ai/dsh-client-hmr` Requires: `clientModules` · `webServer` @@ -399,6 +428,8 @@ export interface Config { Source: [`packages/client/hmr/src/index.ts:31`](../packages/client/hmr/src/index.ts) + + ## `@deepseek-ai/dsh-code-runtime-worker-thread` ```ts config-catalog @@ -434,6 +465,8 @@ export interface Config { Source: [`packages/code-runtime/code-runtime-worker-thread/src/index.ts:25`](../packages/code-runtime/code-runtime-worker-thread/src/index.ts) + + ## `@deepseek-ai/dsh-compaction-basic` Requires: `llm` · `tokenMeter` · `sessions` @@ -478,6 +511,8 @@ export interface ModelCompactPolicyConfig extends CompactionPolicyConfig { Source: [`packages/compaction/compaction-basic/src/types.ts:38`](../packages/compaction/compaction-basic/src/types.ts) + + ## `@deepseek-ai/dsh-compaction-tool-result-pruner` Requires: `tokenMeter` @@ -496,6 +531,8 @@ export interface ToolResultPruneConfig { Source: [`packages/compaction/compaction-tool-result-pruner/src/types.ts:4`](../packages/compaction/compaction-tool-result-pruner/src/types.ts) + + ## `@deepseek-ai/dsh-cordis-host-runner` Requires: `tools` @@ -510,6 +547,8 @@ export interface Config { Source: [`packages/extensions/cordis-host-runner/src/index.ts:88`](../packages/extensions/cordis-host-runner/src/index.ts) + + ## `@deepseek-ai/dsh-credentials-local` ```ts config-catalog @@ -528,6 +567,8 @@ export interface Config { Source: [`packages/credentials/credentials-local/src/index.ts:55`](../packages/credentials/credentials-local/src/index.ts) + + ## `@deepseek-ai/dsh-e2b` ```ts config-catalog @@ -544,6 +585,8 @@ export interface Config { Source: [`packages/e2b/e2b/src/index.ts:43`](../packages/e2b/e2b/src/index.ts) + + ## `@deepseek-ai/dsh-fs-local` ```ts config-catalog @@ -561,6 +604,8 @@ export interface Config { Source: [`packages/fs/fs-local/src/index.ts:41`](../packages/fs/fs-local/src/index.ts) + + ## `@deepseek-ai/dsh-fs-sandbox` Requires: `sandboxPolicy` @@ -579,6 +624,8 @@ Depends on: [`LocalConfig`](#deepseek-aidsh-fs-local) Source: [`packages/fs/fs-sandbox/src/index.ts:49`](../packages/fs/fs-sandbox/src/index.ts) + + ## `@deepseek-ai/dsh-goal` Requires: `agents` @@ -593,6 +640,8 @@ export interface Config { Source: [`packages/goal/goal/src/index.ts:116`](../packages/goal/goal/src/index.ts) + + ## `@deepseek-ai/dsh-headless` Requires: `agentDefaultModel` · `agents` · `sessions` @@ -607,6 +656,8 @@ export interface Config { Source: [`packages/bundle/headless/src/index.ts:31`](../packages/bundle/headless/src/index.ts) + + ## `@deepseek-ai/dsh-hooks-claude-code` Requires: `shell` @@ -643,6 +694,8 @@ export interface Config { Source: [`packages/hooks/hooks-claude-code/src/index.ts:45`](../packages/hooks/hooks-claude-code/src/index.ts) + + ## `@deepseek-ai/dsh-hooks-codex` Requires: `shell` @@ -668,6 +721,8 @@ export interface Config { Source: [`packages/hooks/hooks-codex/src/index.ts:44`](../packages/hooks/hooks-codex/src/index.ts) + + ## `@deepseek-ai/dsh-host-apiproxy` Requires: `agentDefaultModel` · `agents` · `attachments` · `directoryPicker` · `llm` · `sessions` · `subagents` · `sessionQuery` · `tools` · `userQuestions` · `workspaceRegistry` @@ -689,11 +744,19 @@ export interface Config { * @default 6 */ sessionExportCompressionLevel?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 + /** + * Maximum physical size of a cold Session artifact eligible for blankness + * verification. Zero disables probes. + * @default 1024 + */ + coldBlankProbeMaxBytes?: number } ``` Source: [`packages/host/apiproxy/src/index.ts:41`](../packages/host/apiproxy/src/index.ts) + + ## `@deepseek-ai/dsh-host-directory-picker-browse` ```ts config-catalog @@ -706,6 +769,8 @@ export interface Config { Source: [`packages/host/directory-picker-browse/src/index.ts:181`](../packages/host/directory-picker-browse/src/index.ts) + + ## `@deepseek-ai/dsh-host-frontend-static` Requires: `webServer` @@ -720,6 +785,8 @@ export interface Config { Source: [`packages/host/frontend-static/src/index.ts:28`](../packages/host/frontend-static/src/index.ts) + + ## `@deepseek-ai/dsh-host-webserver` ```ts config-catalog @@ -734,6 +801,8 @@ export interface Config { Source: [`packages/host/webserver/src/index.ts:45`](../packages/host/webserver/src/index.ts) + + ## `@deepseek-ai/dsh-invariants` ```ts config-catalog @@ -750,6 +819,8 @@ export interface Config { Source: [`packages/runtime-diagnostics/invariants/src/index.ts:15`](../packages/runtime-diagnostics/invariants/src/index.ts) + + ## `@deepseek-ai/dsh-jobs-local` ```ts config-catalog @@ -765,6 +836,8 @@ export interface Config { Source: [`packages/jobs/jobs-local/src/index.ts:31`](../packages/jobs/jobs-local/src/index.ts) + + ## `@deepseek-ai/dsh-llm-deepseek` Requires: `llm` @@ -786,7 +859,7 @@ export interface Config { /** Deployment thinking policy; `disabled` limits every conversation request to `off`. */ thinking?: 'enabled' | 'disabled' /** Default thinking effort (default `high`); `off` disables thinking per request. */ - reasoningEffort?: 'off' | 'high' | 'max' + reasoningEffort?: 'off' | 'low' | 'high' | 'max' /** Default per-request output cap (default 256,000); a model's own cap and explicit request values win. */ maxTokens?: number /** Positive context capacity used when the selected model has no exact value (default 1,000,000). */ @@ -818,6 +891,8 @@ Depends on: [`RetryPolicyConfig`](../packages/llm/llm/src/index.ts) Source: [`packages/llm/llm-deepseek/src/index.ts:62`](../packages/llm/llm-deepseek/src/index.ts) + + ## `@deepseek-ai/dsh-llm-pi-ai` Requires: `llm` @@ -1006,6 +1081,8 @@ Depends on: `Api` (`@earendil-works/pi-ai`) · `CacheRetention` (`@earendil-work Source: [`packages/llm/llm-pi-ai/src/config.ts:172`](../packages/llm/llm-pi-ai/src/config.ts) + + ## `@deepseek-ai/dsh-llm-replay` Requires: `llm` @@ -1072,6 +1149,8 @@ Depends on: [`ModelModality`](../packages/llm/llm/src/index.ts) · [`RetryPolicy Source: [`packages/test-support/llm-replay/src/index.ts:776`](../packages/test-support/llm-replay/src/index.ts) + + ## `@deepseek-ai/dsh-llm-retry` Requires: `agents` @@ -1083,6 +1162,8 @@ export type Config = Readonly> Source: [`packages/llm/llm-retry/src/index.ts:24`](../packages/llm/llm-retry/src/index.ts) + + ## `@deepseek-ai/dsh-lsp-stdio` Requires: `fs` · `lsp` · `subprocess` @@ -1123,6 +1204,8 @@ export interface LspLocalServerConfig { Source: [`packages/lsp/lsp-stdio/src/index.ts:82`](../packages/lsp/lsp-stdio/src/index.ts) + + ## `@deepseek-ai/dsh-mcp-client` Requires: `tools` @@ -1194,6 +1277,8 @@ export interface ReconnectConfig { Source: [`packages/mcp/mcp-client/src/index.ts:98`](../packages/mcp/mcp-client/src/index.ts) + + ## `@deepseek-ai/dsh-message-feedback` Requires: `storageDomain` · `sessionPersistence` · `sessions` @@ -1208,6 +1293,8 @@ export interface Config { Source: [`packages/feedback/message-feedback/src/index.ts:49`](../packages/feedback/message-feedback/src/index.ts) + + ## `@deepseek-ai/dsh-permission-presets` Requires: `shell` · `approval` · `sessions` @@ -1245,6 +1332,8 @@ Depends on: [`ApprovalPolicy`](subsystems/approval.md) · [`SandboxMode`](subsys Source: [`packages/interaction/permission-presets/src/index.ts:140`](../packages/interaction/permission-presets/src/index.ts) + + ## `@deepseek-ai/dsh-persona` Requires: `systemPrompt` @@ -1260,11 +1349,15 @@ export interface Config { text: string /** Make this persona the complete system prompt, suppressing every other section. */ complete?: boolean + /** Suppress dynamic runtime-context snapshots for this persona's agent scope. */ + includeRuntimeContext?: boolean } ``` Source: [`packages/preset/persona/src/index.ts:34`](../packages/preset/persona/src/index.ts) + + ## `@deepseek-ai/dsh-plan-mode` Requires: `tools` · `systemPrompt` @@ -1279,6 +1372,8 @@ export interface PlanModeConfig { Source: [`packages/plan/plan-mode/src/index.ts:70`](../packages/plan/plan-mode/src/index.ts) + + ## `@deepseek-ai/dsh-pwsh-local` Requires: `subprocess` @@ -1310,6 +1405,8 @@ export interface Config { Source: [`packages/shell/pwsh-local/src/index.ts:58`](../packages/shell/pwsh-local/src/index.ts) + + ## `@deepseek-ai/dsh-pwsh-sandbox` Requires: `subprocess` · `sandbox` · `sandboxPolicy` @@ -1330,6 +1427,8 @@ Depends on: [`LocalConfig`](#deepseek-aidsh-pwsh-local) Source: [`packages/shell/pwsh-sandbox/src/index.ts:40`](../packages/shell/pwsh-sandbox/src/index.ts) + + ## `@deepseek-ai/dsh-repeat-tool-reminder` ```ts config-catalog @@ -1362,6 +1461,8 @@ export interface Config { Source: [`packages/guard/repeat-tool-reminder/src/index.ts:28`](../packages/guard/repeat-tool-reminder/src/index.ts) + + ## `@deepseek-ai/dsh-sandbox-local` ```ts config-catalog @@ -1392,6 +1493,8 @@ export interface Config { Source: [`packages/sandbox/sandbox-local/src/index.ts:44`](../packages/sandbox/sandbox-local/src/index.ts) + + ## `@deepseek-ai/dsh-sandbox-policy` ```ts config-catalog @@ -1417,6 +1520,8 @@ Depends on: [`SandboxMode`](subsystems/sandbox.md) Source: [`packages/sandbox/sandbox-policy/src/index.ts:67`](../packages/sandbox/sandbox-policy/src/index.ts) + + ## `@deepseek-ai/dsh-sdk-jsonrpc-server` Requires: `agents` @@ -1439,6 +1544,8 @@ Depends on: `Readable` (`node:stream`) · `Writable` (`node:stream`) Source: [`packages/sdk/server/src/index.ts:25`](../packages/sdk/server/src/index.ts) + + ## `@deepseek-ai/dsh-session-persistence-jsonl` Requires: `sessions` @@ -1476,6 +1583,8 @@ export type JsonlCompression = 'zstd' | 'none' Source: [`packages/session/session-persistence-jsonl/src/index.ts:60`](../packages/session/session-persistence-jsonl/src/index.ts) + + ## `@deepseek-ai/dsh-session-persistence-sqlite` Requires: `sessions` @@ -1519,6 +1628,8 @@ export type JournalMode = 'wal' | 'delete' | 'truncate' | 'persist' Source: [`packages/session/session-persistence-sqlite/src/index.ts:70`](../packages/session/session-persistence-sqlite/src/index.ts) + + ## `@deepseek-ai/dsh-session-projection-cache` Requires: `storageDomain` · `sessionProjections` · `sessionPersistence` · `sessions` @@ -1540,6 +1651,8 @@ export interface Config { Source: [`packages/session/session-projection-cache/src/index.ts:42`](../packages/session/session-projection-cache/src/index.ts) + + ## `@deepseek-ai/dsh-session-query-sqlite` Requires: `sessions` @@ -1553,7 +1666,13 @@ export interface Config extends SessionQueryConfig { * POSIX filesystems; existing modes are preserved. */ path: string - /** Open the SQLite module and handle at service activation or the first search. Defaults to `startup`. */ + /** + * Open the SQLite module and handle at service activation or the first + * search, or `never` to disable full-text search: the inherited exact + * reads, filters, and traces stay available, while `searchSessions` and + * `searchEvents` fail with `SESSION_QUERY_SEARCH_DISABLED` and SQLite is + * never imported or opened. Defaults to `startup`. + */ openAt?: OpenAt /** SQLite journal mode. Defaults to `wal`. */ journalMode?: JournalMode @@ -1567,8 +1686,8 @@ export interface Config extends SessionQueryConfig { persistedInspectConcurrency?: number } -/** SQLite module/handle opening phase. */ -export type OpenAt = 'startup' | 'first-search' +/** SQLite module/handle opening phase; `never` disables full-text search entirely. */ +export type OpenAt = 'startup' | 'first-search' | 'never' /** Supported SQLite journal modes. */ export type JournalMode = 'wal' | 'delete' | 'truncate' | 'persist' @@ -1578,6 +1697,8 @@ Depends on: [`SessionQueryConfig`](../packages/session-query/session-query/src/i Source: [`packages/session-query/session-query-sqlite/src/index.ts:89`](../packages/session-query/session-query-sqlite/src/index.ts) + + ## `@deepseek-ai/dsh-session-reference` Requires: `sessionQuery` @@ -1596,6 +1717,8 @@ export interface Config { Source: [`packages/context/session-reference/src/config.ts:11`](../packages/context/session-reference/src/config.ts) + + ## `@deepseek-ai/dsh-session-telemetry-otel` Requires: `sessions` @@ -1640,6 +1763,8 @@ Depends on: `BatchLogRecordProcessorOptions` (`@opentelemetry/sdk-logs`) · `OTL Source: [`packages/session/session-telemetry-otel/src/index.ts:91`](../packages/session/session-telemetry-otel/src/index.ts) + + ## `@deepseek-ai/dsh-session-title` Requires: `sessions` @@ -1658,6 +1783,8 @@ export interface Config { Source: [`packages/session/session-title/src/index.ts:79`](../packages/session/session-title/src/index.ts) + + ## `@deepseek-ai/dsh-session-title-all-prompts-llm` Requires: `sessionTitle` · `llm` · `sessions` @@ -1671,6 +1798,8 @@ Depends on: [`SessionTitleLlmConfig`](../packages/session/session-title-llm/src/ Source: [`packages/session/session-title-all-prompts-llm/src/index.ts:15`](../packages/session/session-title-all-prompts-llm/src/index.ts) + + ## `@deepseek-ai/dsh-session-title-first-prompt-llm` Requires: `sessionTitle` · `llm` · `sessions` @@ -1684,6 +1813,8 @@ Depends on: [`SessionTitleLlmConfig`](../packages/session/session-title-llm/src/ Source: [`packages/session/session-title-first-prompt-llm/src/index.ts:15`](../packages/session/session-title-first-prompt-llm/src/index.ts) + + ## `@deepseek-ai/dsh-settings-file` ```ts config-catalog @@ -1702,6 +1833,8 @@ export interface Config { Source: [`packages/settings/settings-file/src/index.ts:21`](../packages/settings/settings-file/src/index.ts) + + ## `@deepseek-ai/dsh-shell-env` ```ts config-catalog @@ -1714,6 +1847,8 @@ export interface Config { Source: [`packages/shell/shell-env/src/index.ts:29`](../packages/shell/shell-env/src/index.ts) + + ## `@deepseek-ai/dsh-skill` ```ts config-catalog @@ -1726,6 +1861,8 @@ export interface Config { Source: [`packages/skill/skill/src/index.ts:279`](../packages/skill/skill/src/index.ts) + + ## `@deepseek-ai/dsh-skill-filesystem` Requires: `skills` @@ -1762,6 +1899,8 @@ export interface Config { Source: [`packages/skill/skill-filesystem/src/index.ts:49`](../packages/skill/skill-filesystem/src/index.ts) + + ## `@deepseek-ai/dsh-spill-local` ```ts config-catalog @@ -1778,6 +1917,8 @@ export interface Config { Source: [`packages/spill/spill-local/src/index.ts:22`](../packages/spill/spill-local/src/index.ts) + + ## `@deepseek-ai/dsh-spill-policy` Requires: `tools` @@ -1796,6 +1937,8 @@ export interface Config { Source: [`packages/spill/spill-policy/src/index.ts:60`](../packages/spill/spill-policy/src/index.ts) + + ## `@deepseek-ai/dsh-storage-domain` Requires: `storage` @@ -1817,6 +1960,8 @@ export interface Config { Source: [`packages/storage/storage-domain/src/index.ts:52`](../packages/storage/storage-domain/src/index.ts) + + ## `@deepseek-ai/dsh-storage-json` Requires: `storage` @@ -1836,6 +1981,8 @@ export interface Config { Source: [`packages/storage/storage-json/src/index.ts:27`](../packages/storage/storage-json/src/index.ts) + + ## `@deepseek-ai/dsh-storage-sqlite` Requires: `storage` @@ -1874,6 +2021,8 @@ export type JournalMode = 'wal' | 'delete' | 'truncate' | 'persist' Source: [`packages/storage/storage-sqlite/src/index.ts:24`](../packages/storage/storage-sqlite/src/index.ts) + + ## `@deepseek-ai/dsh-subagent-acp` Requires: `subagents` · `subprocess` @@ -1925,6 +2074,8 @@ export type PermissionPolicy = 'allow' | 'reject' Source: [`packages/subagent/subagent-acp/src/index.ts:27`](../packages/subagent/subagent-acp/src/index.ts) + + ## `@deepseek-ai/dsh-subagent-claude-code` Requires: `subagents` · `subprocess` @@ -1944,6 +2095,8 @@ export interface Config { Source: [`packages/subagent/subagent-claude-code/src/index.ts:32`](../packages/subagent/subagent-claude-code/src/index.ts) + + ## `@deepseek-ai/dsh-subagent-codex` Requires: `subagents` · `subprocess` @@ -1963,6 +2116,8 @@ export interface Config { Source: [`packages/subagent/subagent-codex/src/index.ts:30`](../packages/subagent/subagent-codex/src/index.ts) + + ## `@deepseek-ai/dsh-subagent-dsh-sdk` Requires: `subagents` @@ -2014,6 +2169,8 @@ export interface Config { Source: [`packages/subagent/subagent-dsh-sdk/src/index.ts:29`](../packages/subagent/subagent-dsh-sdk/src/index.ts) + + ## `@deepseek-ai/dsh-subagent-fork-in-process` Requires: `subagents` @@ -2028,6 +2185,8 @@ export interface Config { Source: [`packages/subagent/subagent-fork-in-process/src/index.ts:31`](../packages/subagent/subagent-fork-in-process/src/index.ts) + + ## `@deepseek-ai/dsh-subagent-spawn-in-process` Requires: `subagents` @@ -2042,6 +2201,8 @@ export interface Config { Source: [`packages/subagent/subagent-spawn-in-process/src/index.ts:25`](../packages/subagent/subagent-spawn-in-process/src/index.ts) + + ## `@deepseek-ai/dsh-subprocess-e2b` Requires: `e2b` @@ -2056,6 +2217,8 @@ export interface Config { Source: [`packages/e2b/subprocess-e2b/src/index.ts:25`](../packages/e2b/subprocess-e2b/src/index.ts) + + ## `@deepseek-ai/dsh-system-prompt` ```ts config-catalog @@ -2063,6 +2226,8 @@ Source: [`packages/e2b/subprocess-e2b/src/index.ts:25`](../packages/e2b/subproce export interface Config { /** Include the fixed DeepSeek Harness identity before the deployment persona (default true). */ includeHarnessIdentity?: boolean + /** Include dynamic runtime-context snapshots in model history (default true). */ + includeRuntimeContext?: boolean /** * Deployment-wide order-0 persona template. A scoped section named * `deployment:persona` shadows it; `{{variable}}` references are strict. @@ -2079,6 +2244,8 @@ export interface Config { Source: [`packages/core/system-prompt/src/index.ts:186`](../packages/core/system-prompt/src/index.ts) + + ## `@deepseek-ai/dsh-terminal-bash` Requires: `terminals` · `sandboxPolicy` · `subprocess` @@ -2122,6 +2289,8 @@ export interface Config { Source: [`packages/terminal/terminal-bash/src/config.ts:6`](../packages/terminal/terminal-bash/src/config.ts) + + ## `@deepseek-ai/dsh-time-context` Requires: `agents` @@ -2138,6 +2307,8 @@ export interface Config { Source: [`packages/context/time-context/src/index.ts:27`](../packages/context/time-context/src/index.ts) + + ## `@deepseek-ai/dsh-tmux-context` Requires: `agents` @@ -2152,6 +2323,8 @@ export interface Config { Source: [`packages/context/tmux-context/src/index.ts:34`](../packages/context/tmux-context/src/index.ts) + + ## `@deepseek-ai/dsh-token-meter` ```ts config-catalog @@ -2161,6 +2334,8 @@ export type TokenMeterConfig = Record Source: [`packages/llm/token-meter/src/types.ts:12`](../packages/llm/token-meter/src/types.ts) + + ## `@deepseek-ai/dsh-tool-bash` Requires: `tools` · `shell` · `systemPrompt` · `shellEnv` @@ -2175,6 +2350,8 @@ export interface Config { Source: [`packages/shell/tool-bash/src/index.ts:34`](../packages/shell/tool-bash/src/index.ts) + + ## `@deepseek-ai/dsh-tool-bash-persistent` Requires: `tools` · `terminals` @@ -2193,7 +2370,9 @@ export interface Config { } ``` -Source: [`packages/shell/tool-bash-persistent/src/index.ts:405`](../packages/shell/tool-bash-persistent/src/index.ts) +Source: [`packages/shell/tool-bash-persistent/src/index.ts:400`](../packages/shell/tool-bash-persistent/src/index.ts) + + ## `@deepseek-ai/dsh-tool-fs` @@ -2215,6 +2394,8 @@ export interface Config { Source: [`packages/fs/tool-fs/src/index.ts:25`](../packages/fs/tool-fs/src/index.ts) + + ## `@deepseek-ai/dsh-tool-fs-search` Requires: `tools` · `systemPrompt` · `subprocess` @@ -2248,6 +2429,8 @@ export interface Config { Source: [`packages/fs/tool-fs-search/src/index.ts:73`](../packages/fs/tool-fs-search/src/index.ts) + + ## `@deepseek-ai/dsh-tool-goal` Requires: `agents` · `goals` · `tools` · `systemPrompt` @@ -2262,6 +2445,8 @@ export interface Config { Source: [`packages/goal/tool-goal/src/index.ts:26`](../packages/goal/tool-goal/src/index.ts) + + ## `@deepseek-ai/dsh-tool-jobs` Requires: `tools` · `jobs` · `systemPrompt` @@ -2294,6 +2479,8 @@ export type CompletionDelivery = 'quiet' | 'wakeup' Source: [`packages/jobs/tool-jobs/src/index.ts:32`](../packages/jobs/tool-jobs/src/index.ts) + + ## `@deepseek-ai/dsh-tool-lsp` Requires: `tools` · `lsp` · `systemPrompt` @@ -2312,6 +2499,8 @@ export interface Config { Source: [`packages/lsp/tool-lsp/src/index.ts:58`](../packages/lsp/tool-lsp/src/index.ts) + + ## `@deepseek-ai/dsh-tool-pwsh` Requires: `tools` · `shell` · `systemPrompt` · `shellEnv` @@ -2326,6 +2515,8 @@ export interface Config { Source: [`packages/shell/tool-pwsh/src/index.ts:52`](../packages/shell/tool-pwsh/src/index.ts) + + ## `@deepseek-ai/dsh-tool-ralph` Requires: `tools` · `workflowEngine` · `subagents` · `systemPrompt` @@ -2346,6 +2537,8 @@ export interface Config { Source: [`packages/workflow/tool-ralph/src/index.ts:23`](../packages/workflow/tool-ralph/src/index.ts) + + ## `@deepseek-ai/dsh-tool-session-query` Requires: `tools` · `systemPrompt` · `sessionQuery` @@ -2362,6 +2555,8 @@ export interface Config { Source: [`packages/session-query/tool-session-query/src/index.ts:29`](../packages/session-query/tool-session-query/src/index.ts) + + ## `@deepseek-ai/dsh-tool-skill` Requires: `agents` · `tools` · `skills` @@ -2376,6 +2571,8 @@ export interface Config { Source: [`packages/skill/tool-skill/src/index.ts:61`](../packages/skill/tool-skill/src/index.ts) + + ## `@deepseek-ai/dsh-tool-str-replace-editor` Requires: `tools` · `fs` @@ -2392,6 +2589,8 @@ export interface Config { Source: [`packages/fs/tool-str-replace-editor/src/index.ts:497`](../packages/fs/tool-str-replace-editor/src/index.ts) + + ## `@deepseek-ai/dsh-tool-subagent` Requires: `tools` · `subagents` · `systemPrompt` @@ -2455,6 +2654,8 @@ Depends on: [`AgentOptions`](subsystems/core.md) Source: [`packages/subagent/tool-subagent/src/index.ts:29`](../packages/subagent/tool-subagent/src/index.ts) + + ## `@deepseek-ai/dsh-tool-subagent-report` Requires: `subagents` · `tools` · `systemPrompt` @@ -2475,6 +2676,8 @@ Depends on: [`SubagentReportDelivery`](subsystems/subagent.md) Source: [`packages/subagent/tool-subagent-report/src/index.ts:27`](../packages/subagent/tool-subagent-report/src/index.ts) + + ## `@deepseek-ai/dsh-tool-terminal` Requires: `terminals` · `tools` · `systemPrompt` @@ -2491,6 +2694,8 @@ export interface Config { Source: [`packages/terminal/tool-terminal/src/index.ts:35`](../packages/terminal/tool-terminal/src/index.ts) + + ## `@deepseek-ai/dsh-tool-todo` Requires: `tools` @@ -2511,6 +2716,8 @@ export interface Config { Source: [`packages/todo/tool-todo/src/index.ts:29`](../packages/todo/tool-todo/src/index.ts) + + ## `@deepseek-ai/dsh-tool-web` Requires: `tools` · `web` · `systemPrompt` @@ -2535,6 +2742,8 @@ export interface Config { Source: [`packages/web/tool-web/src/index.ts:37`](../packages/web/tool-web/src/index.ts) + + ## `@deepseek-ai/dsh-tool-workflow` Requires: `tools` · `workflowEngine` · `systemPrompt` @@ -2551,6 +2760,8 @@ export interface Config { Source: [`packages/workflow/tool-workflow/src/index.ts:33`](../packages/workflow/tool-workflow/src/index.ts) + + ## `@deepseek-ai/dsh-tools` Requires: `systemPrompt` @@ -2585,6 +2796,8 @@ export type ToolPresentationMode = 'native' | 'code' | 'both' Source: [`packages/core/tools/src/index.ts:654`](../packages/core/tools/src/index.ts) + + ## `@deepseek-ai/dsh-typert-loader` Requires: `typert` · `loader` @@ -2599,6 +2812,8 @@ export interface Config { Source: [`packages/typert/loader/src/index.ts:47`](../packages/typert/loader/src/index.ts) + + ## `@deepseek-ai/dsh-user-approval` ```ts config-catalog @@ -2628,6 +2843,8 @@ export type ApprovalPolicy = 'ask' | 'never' Source: [`packages/interaction/user-approval/src/index.ts:177`](../packages/interaction/user-approval/src/index.ts) + + ## `@deepseek-ai/dsh-web` ```ts config-catalog @@ -2647,6 +2864,8 @@ export interface WebRuntimeConfig { Source: [`packages/web/web/src/index.ts:55`](../packages/web/web/src/index.ts) + + ## `@deepseek-ai/dsh-web-app` Requires: `webServer` @@ -2670,6 +2889,8 @@ export interface Config { Source: [`packages/bundle/web-app/src/index.ts:38`](../packages/bundle/web-app/src/index.ts) + + ## `@deepseek-ai/dsh-web-fetch-http` Requires: `web` @@ -2694,6 +2915,8 @@ export interface Config { Source: [`packages/web/web-fetch-http/src/index.ts:34`](../packages/web/web-fetch-http/src/index.ts) + + ## `@deepseek-ai/dsh-web-search-deepseek` Requires: `web` @@ -2720,6 +2943,8 @@ export interface Config { Source: [`packages/web/web-search-deepseek/src/index.ts:46`](../packages/web/web-search-deepseek/src/index.ts) + + ## `@deepseek-ai/dsh-web-search-exa` Requires: `web` @@ -2742,6 +2967,8 @@ export interface Config { Source: [`packages/web/web-search-exa/src/index.ts:38`](../packages/web/web-search-exa/src/index.ts) + + ## `@deepseek-ai/dsh-web-search-perplexity` Requires: `web` @@ -2764,6 +2991,8 @@ export interface Config { Source: [`packages/web/web-search-perplexity/src/index.ts:32`](../packages/web/web-search-perplexity/src/index.ts) + + ## `@deepseek-ai/dsh-workflow-worker-thread` Requires: `subagents` diff --git a/docs/config-catalog.zh.md b/docs/config-catalog.zh.md index 0bd95a5ab2..7054ec8b52 100644 --- a/docs/config-catalog.zh.md +++ b/docs/config-catalog.zh.md @@ -11,6 +11,8 @@ `Requires:` 行列出插件通过 `inject` 注入的服务键:其 `cordis.yml` 树还必须加载这些服务的提供者。范围限定为 harness 层级(`packages/`);配置树还可能加载的 vendored cordis 插件(`hmr`、控制台日志记录器等)固定为上游源代码(参见 [vendoring policy](../vendor/README.md)),未收录于此目录。 + + ## `@deepseek-ai/dsh-acp` 需要:`agents` @@ -31,6 +33,8 @@ export interface AcpConfig { 来源:[`packages/acp/acp/src/index.ts:70`](../packages/acp/acp/src/index.ts) + + ## `@deepseek-ai/dsh-acp-demo` ```ts config-catalog @@ -84,6 +88,8 @@ export interface Config { 来源:[`packages/examples/acp-demo/src/index.ts:39`](../packages/examples/acp-demo/src/index.ts) + + ## `@deepseek-ai/dsh-agent-default-model` ```ts config-catalog @@ -98,6 +104,8 @@ export interface Config { 来源:[`packages/core/agent-default-model/src/index.ts:41`](../packages/core/agent-default-model/src/index.ts) + + ## `@deepseek-ai/dsh-agent-instructions` ```ts config-catalog @@ -126,6 +134,8 @@ export interface Config { 来源:[`packages/context/agent-instructions/src/config.ts:18`](../packages/context/agent-instructions/src/config.ts) + + ## `@deepseek-ai/dsh-agent-loop` 需要:`agents` · `sessions` · `llm` · `tools` · `systemPrompt` @@ -156,6 +166,8 @@ export interface Config { 来源:[`packages/core/agent-loop/src/index.ts:255`](../packages/core/agent-loop/src/index.ts) + + ## `@deepseek-ai/dsh-agent-presets` 需要:`loader` @@ -192,15 +204,18 @@ export type PresetTrust = 'system' | 'user' 来源:[`packages/preset/agent-presets/src/preset.ts:52`](../packages/preset/agent-presets/src/preset.ts) + + ## `@deepseek-ai/dsh-agent-spine-demo` ```ts config-catalog /** * Bundle config: each field forwarded verbatim to the child that owns it — * `agents` to the agent loop (an app that pre-creates no agents, like the ACP - * bridge, simply omits it), `includeHarnessIdentity`, `persona`, and `toolOrder` - * to the system-prompt plugin (the fixed opener, deployment persona, and explicit - * model-facing tool order), the `tools` object to the tool registry (its presentation `mode`), + * bridge, simply omits it), `includeHarnessIdentity`, `includeRuntimeContext`, + * `persona`, and `toolOrder` to the system-prompt plugin (the fixed opener, + * dynamic-context policy, deployment persona, and explicit model-facing tool + * order), the `tools` object to the tool registry (its presentation `mode`), * `dshHome` to bash environment and local skill discovery, `sessionTitle` to * the fallback title service, `skills` to the * skill registry/local provider/tool consumer, `workspaceContext` to the @@ -224,6 +239,8 @@ export interface Config { maxParallelToolCalls?: AgentLoopConfig['maxParallelToolCalls'] /** Whether the system prompt includes the fixed Harness identity (default true). */ includeHarnessIdentity?: SystemPromptConfig['includeHarnessIdentity'] + /** Whether model history includes dynamic runtime-context snapshots (default true). */ + includeRuntimeContext?: SystemPromptConfig['includeRuntimeContext'] /** The deployment persona (see dsh-system-prompt's `Config`). */ persona?: SystemPromptConfig['persona'] /** The explicit model-facing tool order (see dsh-system-prompt's `Config`). */ @@ -277,7 +294,9 @@ export interface GoalConfig { 依赖:[`AgentLoopConfig`](#deepseek-aidsh-agent-loop) · [`GoalDomainConfig`](#deepseek-aidsh-goal) · [`InvariantConfig`](#deepseek-aidsh-invariants) · [`JobsConfig`](#deepseek-aidsh-jobs-local) · [`SessionTitleConfig`](#deepseek-aidsh-session-title) · [`SkillFileSystem`](../packages/skill/skill-filesystem/src/index.ts) · [`SkillRegistryConfig`](#deepseek-aidsh-skill) · [`SystemPromptConfig`](#deepseek-aidsh-system-prompt) · [`toolBash`](../packages/shell/tool-bash/src/index.ts) · [`toolGoal`](../packages/goal/tool-goal/src/index.ts) · [`toolJobs`](../packages/jobs/tool-jobs/src/index.ts) · [`ToolsConfig`](#deepseek-aidsh-tools) · [`toolSkill`](../packages/skill/tool-skill/src/index.ts) · [`workspaceContext`](../packages/context/agent-instructions/src/index.ts) -来源:[`packages/examples/agent-spine-demo/src/index.ts:91`](../packages/examples/agent-spine-demo/src/index.ts) +来源:[`packages/examples/agent-spine-demo/src/index.ts:92`](../packages/examples/agent-spine-demo/src/index.ts) + + ## `@deepseek-ai/dsh-agent-tool-presentation` @@ -301,6 +320,8 @@ export interface Config { 来源:[`packages/core/agent-tool-presentation/src/index.ts:38`](../packages/core/agent-tool-presentation/src/index.ts) + + ## `@deepseek-ai/dsh-attachment-local` ```ts config-catalog @@ -321,6 +342,8 @@ export interface Config { 来源:[`packages/attachment/attachment-local/src/index.ts:24`](../packages/attachment/attachment-local/src/index.ts) + + ## `@deepseek-ai/dsh-bash-local` 需要:`subprocess` @@ -345,6 +368,8 @@ export interface Config { 来源:[`packages/shell/bash-local/src/index.ts:41`](../packages/shell/bash-local/src/index.ts) + + ## `@deepseek-ai/dsh-bash-sandbox` 需要:`subprocess` · `sandbox` · `sandboxPolicy` @@ -364,6 +389,8 @@ export type Config = LocalConfig 来源:[`packages/shell/bash-sandbox/src/index.ts:35`](../packages/shell/bash-sandbox/src/index.ts) + + ## `@deepseek-ai/dsh-client-connection` 需要:`webServer` @@ -387,6 +414,8 @@ export interface ConnectionConfig { 来源:[`packages/client/connection/src/index.ts:50`](../packages/client/connection/src/index.ts) + + ## `@deepseek-ai/dsh-client-hmr` 需要:`clientModuleHost` · `webServer` @@ -401,6 +430,8 @@ export interface Config { 来源:[`packages/client/hmr/src/index.ts:31`](../packages/client/hmr/src/index.ts) + + ## `@deepseek-ai/dsh-code-runtime-worker-thread` ```ts config-catalog @@ -436,6 +467,8 @@ export interface Config { 来源:[`packages/code-runtime/code-runtime-worker-thread/src/index.ts:25`](../packages/code-runtime/code-runtime-worker-thread/src/index.ts) + + ## `@deepseek-ai/dsh-compaction-basic` 需要:`llm` · `tokenMeter` · `sessions` @@ -480,6 +513,8 @@ export interface ModelCompactPolicyConfig extends CompactionPolicyConfig { 来源:[`packages/compaction/compaction-basic/src/types.ts:38`](../packages/compaction/compaction-basic/src/types.ts) + + ## `@deepseek-ai/dsh-compaction-tool-result-pruner` 需要:`tokenMeter` @@ -498,6 +533,8 @@ export interface ToolResultPruneConfig { 来源:[`packages/compaction/compaction-tool-result-pruner/src/types.ts:4`](../packages/compaction/compaction-tool-result-pruner/src/types.ts) + + ## `@deepseek-ai/dsh-cordis-host-runner` 需要:`tools` @@ -512,6 +549,8 @@ export interface Config { 来源:[`packages/extensions/cordis-host-runner/src/index.ts:88`](../packages/extensions/cordis-host-runner/src/index.ts) + + ## `@deepseek-ai/dsh-credentials-local` ```ts config-catalog @@ -530,6 +569,8 @@ export interface Config { 来源:[`packages/credentials/credentials-local/src/index.ts:55`](../packages/credentials/credentials-local/src/index.ts) + + ## `@deepseek-ai/dsh-e2b` ```ts config-catalog @@ -546,6 +587,8 @@ export interface Config { 来源:[`packages/e2b/e2b/src/index.ts:43`](../packages/e2b/e2b/src/index.ts) + + ## `@deepseek-ai/dsh-fs-local` ```ts config-catalog @@ -563,6 +606,8 @@ export interface Config { 来源:[`packages/fs/fs-local/src/index.ts:41`](../packages/fs/fs-local/src/index.ts) + + ## `@deepseek-ai/dsh-fs-sandbox` 需要:`sandboxPolicy` @@ -581,6 +626,8 @@ export type Config = LocalConfig 来源:[`packages/fs/fs-sandbox/src/index.ts:49`](../packages/fs/fs-sandbox/src/index.ts) + + ## `@deepseek-ai/dsh-goal` 需要:`agents` @@ -595,6 +642,8 @@ export interface Config { 来源:[`packages/goal/goal/src/index.ts:116`](../packages/goal/goal/src/index.ts) + + ## `@deepseek-ai/dsh-headless` 需要:`agentDefaultModel` · `agents` · `sessions` @@ -609,6 +658,8 @@ export interface Config { 来源:[`packages/bundle/headless/src/index.ts:31`](../packages/bundle/headless/src/index.ts) + + ## `@deepseek-ai/dsh-hooks-claude-code` 需要:`bash` @@ -645,6 +696,8 @@ export interface Config { 来源:[`packages/hooks/hooks-claude-code/src/index.ts:45`](../packages/hooks/hooks-claude-code/src/index.ts) + + ## `@deepseek-ai/dsh-hooks-codex` 需要:`bash` @@ -670,6 +723,8 @@ export interface Config { 来源:[`packages/hooks/hooks-codex/src/index.ts:44`](../packages/hooks/hooks-codex/src/index.ts) + + ## `@deepseek-ai/dsh-host-apiproxy` 需要:`agentDefaultModel` · `agents` · `attachments` · `directoryPicker` · `llm` · `sessions` · `subagents` · `sessionQuery` · `tools` · `userInteraction` · `workspace` @@ -691,11 +746,19 @@ export interface Config { * @default 6 */ sessionExportCompressionLevel?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 + /** + * Maximum physical size of a cold Session artifact eligible for blankness + * verification. Zero disables probes. + * @default 1024 + */ + coldBlankProbeMaxBytes?: number } ``` 来源:[`packages/host/apiproxy/src/index.ts:41`](../packages/host/apiproxy/src/index.ts) + + ## `@deepseek-ai/dsh-host-directory-picker-browse` ```ts config-catalog @@ -708,6 +771,8 @@ export interface Config { 来源:[`packages/host/directory-picker-browse/src/index.ts:181`](../packages/host/directory-picker-browse/src/index.ts) + + ## `@deepseek-ai/dsh-host-frontend-static` 需要:`webServer` @@ -722,6 +787,8 @@ export interface Config { 来源:[`packages/host/frontend-static/src/index.ts:28`](../packages/host/frontend-static/src/index.ts) + + ## `@deepseek-ai/dsh-host-webserver` ```ts config-catalog @@ -736,6 +803,8 @@ export interface Config { 来源:[`packages/host/webserver/src/index.ts:45`](../packages/host/webserver/src/index.ts) + + ## `@deepseek-ai/dsh-invariants` ```ts config-catalog @@ -752,6 +821,8 @@ export interface Config { 来源:[`packages/runtime-diagnostics/invariants/src/index.ts:15`](../packages/runtime-diagnostics/invariants/src/index.ts) + + ## `@deepseek-ai/dsh-jobs-local` ```ts config-catalog @@ -767,6 +838,8 @@ export interface Config { 来源:[`packages/jobs/jobs-local/src/index.ts:31`](../packages/jobs/jobs-local/src/index.ts) + + ## `@deepseek-ai/dsh-llm-deepseek` 需要:`llm` @@ -788,7 +861,7 @@ export interface Config { /** Deployment thinking policy; `disabled` limits every conversation request to `off`. */ thinking?: 'enabled' | 'disabled' /** Default thinking effort (default `high`); `off` disables thinking per request. */ - reasoningEffort?: 'off' | 'high' | 'max' + reasoningEffort?: 'off' | 'low' | 'high' | 'max' /** Default per-request output cap (default 256,000); a model's own cap and explicit request values win. */ maxTokens?: number /** Positive context capacity used when the selected model has no exact value (default 1,000,000). */ @@ -820,6 +893,8 @@ export interface DeepSeekCatalogModel { 来源:[`packages/llm/llm-deepseek/src/index.ts:62`](../packages/llm/llm-deepseek/src/index.ts) + + ## `@deepseek-ai/dsh-llm-pi-ai` 需要:`llm` @@ -1008,6 +1083,8 @@ type WithheldThinkingFormat = 'chat-template' | 'qwen-chat-template' 来源:[`packages/llm/llm-pi-ai/src/config.ts:172`](../packages/llm/llm-pi-ai/src/config.ts) + + ## `@deepseek-ai/dsh-llm-replay` 需要:`llm` @@ -1074,6 +1151,8 @@ export interface ReplayModelConfig { 来源:[`packages/test-support/llm-replay/src/index.ts:776`](../packages/test-support/llm-replay/src/index.ts) + + ## `@deepseek-ai/dsh-llm-retry` 需要:`agents` @@ -1085,6 +1164,8 @@ export type Config = Readonly> 来源:[`packages/llm/llm-retry/src/index.ts:24`](../packages/llm/llm-retry/src/index.ts) + + ## `@deepseek-ai/dsh-lsp-stdio` 需要:`fs` · `lsp` · `subprocess` @@ -1125,6 +1206,8 @@ export interface LspLocalServerConfig { 来源:[`packages/lsp/lsp-stdio/src/index.ts:82`](../packages/lsp/lsp-stdio/src/index.ts) + + ## `@deepseek-ai/dsh-mcp-client` 需要:`tools` @@ -1196,6 +1279,8 @@ export interface ReconnectConfig { 来源:[`packages/mcp/mcp-client/src/index.ts:98`](../packages/mcp/mcp-client/src/index.ts) + + ## `@deepseek-ai/dsh-message-feedback` 需要:`storageDomain` · `sessionPersistence` · `sessions` @@ -1210,6 +1295,8 @@ export interface Config { 来源:[`packages/feedback/message-feedback/src/index.ts:49`](../packages/feedback/message-feedback/src/index.ts) + + ## `@deepseek-ai/dsh-permission-presets` 需要:`bash` · `approval` · `sessions` @@ -1247,6 +1334,8 @@ export interface PresetSpec { 来源:[`packages/interaction/permission-presets/src/index.ts:140`](../packages/interaction/permission-presets/src/index.ts) + + ## `@deepseek-ai/dsh-persona` 需要:`systemPrompt` @@ -1262,11 +1351,15 @@ export interface Config { text: string /** Make this persona the complete system prompt, suppressing every other section. */ complete?: boolean + /** Suppress dynamic runtime-context snapshots for this persona's agent scope. */ + includeRuntimeContext?: boolean } ``` 来源:[`packages/preset/persona/src/index.ts:34`](../packages/preset/persona/src/index.ts) + + ## `@deepseek-ai/dsh-plan-mode` 需要:`tools` · `systemPrompt` @@ -1281,6 +1374,8 @@ export interface PlanModeConfig { 来源:[`packages/plan/plan-mode/src/index.ts:70`](../packages/plan/plan-mode/src/index.ts) + + ## `@deepseek-ai/dsh-pwsh-local` 需要:`subprocess` @@ -1312,6 +1407,8 @@ export interface Config { 来源:[`packages/shell/pwsh-local/src/index.ts:58`](../packages/shell/pwsh-local/src/index.ts) + + ## `@deepseek-ai/dsh-pwsh-sandbox` 需要:`subprocess` · `sandbox` · `sandboxPolicy` @@ -1332,6 +1429,8 @@ export type Config = LocalConfig 来源:[`packages/shell/pwsh-sandbox/src/index.ts:40`](../packages/shell/pwsh-sandbox/src/index.ts) + + ## `@deepseek-ai/dsh-repeat-tool-reminder` ```ts config-catalog @@ -1364,6 +1463,8 @@ export interface Config { 来源:[`packages/guard/repeat-tool-reminder/src/index.ts:28`](../packages/guard/repeat-tool-reminder/src/index.ts) + + ## `@deepseek-ai/dsh-sandbox-local` ```ts config-catalog @@ -1394,6 +1495,8 @@ export interface Config { 来源:[`packages/sandbox/sandbox-local/src/index.ts:44`](../packages/sandbox/sandbox-local/src/index.ts) + + ## `@deepseek-ai/dsh-sandbox-policy` ```ts config-catalog @@ -1419,6 +1522,8 @@ export interface Config { 来源:[`packages/sandbox/sandbox-policy/src/index.ts:67`](../packages/sandbox/sandbox-policy/src/index.ts) + + ## `@deepseek-ai/dsh-sdk-jsonrpc-server` 需要:`agents` @@ -1441,6 +1546,8 @@ export interface JsonRpcConfig { 来源:[`packages/sdk/server/src/index.ts:29`](../packages/sdk/server/src/index.ts) + + ## `@deepseek-ai/dsh-session-persistence-jsonl` 需要:`sessions` @@ -1478,6 +1585,8 @@ export type JsonlCompression = 'zstd' | 'none' 来源:[`packages/session/session-persistence-jsonl/src/index.ts:60`](../packages/session/session-persistence-jsonl/src/index.ts) + + ## `@deepseek-ai/dsh-session-persistence-sqlite` 需要:`sessions` @@ -1521,6 +1630,8 @@ export type JournalMode = 'wal' | 'delete' | 'truncate' | 'persist' 来源:[`packages/session/session-persistence-sqlite/src/index.ts:70`](../packages/session/session-persistence-sqlite/src/index.ts) + + ## `@deepseek-ai/dsh-session-projection-cache` 需要:`storageDomain` · `sessionProjections` · `sessionPersistence` · `sessions` @@ -1542,6 +1653,8 @@ export interface Config { 来源:[`packages/session/session-projection-cache/src/index.ts:42`](../packages/session/session-projection-cache/src/index.ts) + + ## `@deepseek-ai/dsh-session-query-sqlite` 需要:`sessions` @@ -1555,7 +1668,13 @@ export interface Config extends SessionQueryConfig { * POSIX filesystems; existing modes are preserved. */ path: string - /** Open the SQLite module and handle at service activation or the first search. Defaults to `startup`. */ + /** + * Open the SQLite module and handle at service activation or the first + * search, or `never` to disable full-text search: the inherited exact + * reads, filters, and traces stay available, while `searchSessions` and + * `searchEvents` fail with `SESSION_QUERY_SEARCH_DISABLED` and SQLite is + * never imported or opened. Defaults to `startup`. + */ openAt?: OpenAt /** SQLite journal mode. Defaults to `wal`. */ journalMode?: JournalMode @@ -1569,8 +1688,8 @@ export interface Config extends SessionQueryConfig { persistedInspectConcurrency?: number } -/** SQLite module/handle opening phase. */ -export type OpenAt = 'startup' | 'first-search' +/** SQLite module/handle opening phase; `never` disables full-text search entirely. */ +export type OpenAt = 'startup' | 'first-search' | 'never' /** Supported SQLite journal modes. */ export type JournalMode = 'wal' | 'delete' | 'truncate' | 'persist' @@ -1580,6 +1699,8 @@ export type JournalMode = 'wal' | 'delete' | 'truncate' | 'persist' 来源:[`packages/session-query/session-query-sqlite/src/index.ts:89`](../packages/session-query/session-query-sqlite/src/index.ts) + + ## `@deepseek-ai/dsh-session-reference` 需要:`sessionQuery` @@ -1598,6 +1719,8 @@ export interface Config { 来源:[`packages/context/session-reference/src/config.ts:11`](../packages/context/session-reference/src/config.ts) + + ## `@deepseek-ai/dsh-session-telemetry-otel` 需要:`sessions` @@ -1642,6 +1765,8 @@ export enum SessionTelemetryMode { 来源:[`packages/session/session-telemetry-otel/src/index.ts:91`](../packages/session/session-telemetry-otel/src/index.ts) + + ## `@deepseek-ai/dsh-session-title` 需要:`sessions` @@ -1660,6 +1785,8 @@ export interface Config { 来源:[`packages/session/session-title/src/index.ts:79`](../packages/session/session-title/src/index.ts) + + ## `@deepseek-ai/dsh-session-title-all-prompts-llm` 需要:`sessionTitle` · `llm` · `sessions` @@ -1673,6 +1800,8 @@ export type Config = SessionTitleLlmConfig 来源:[`packages/session/session-title-all-prompts-llm/src/index.ts:15`](../packages/session/session-title-all-prompts-llm/src/index.ts) + + ## `@deepseek-ai/dsh-session-title-first-prompt-llm` 需要:`sessionTitle` · `llm` · `sessions` @@ -1686,6 +1815,8 @@ export type Config = SessionTitleLlmConfig 来源:[`packages/session/session-title-first-prompt-llm/src/index.ts:15`](../packages/session/session-title-first-prompt-llm/src/index.ts) + + ## `@deepseek-ai/dsh-settings-file` ```ts config-catalog @@ -1704,6 +1835,8 @@ export interface Config { 来源:[`packages/settings/settings-file/src/index.ts:21`](../packages/settings/settings-file/src/index.ts) + + ## `@deepseek-ai/dsh-shell-env` ```ts config-catalog @@ -1716,6 +1849,8 @@ export interface Config { 来源:[`packages/shell/shell-env/src/index.ts:29`](../packages/shell/shell-env/src/index.ts) + + ## `@deepseek-ai/dsh-skill` ```ts config-catalog @@ -1728,6 +1863,8 @@ export interface Config { 来源:[`packages/skill/skill/src/index.ts:279`](../packages/skill/skill/src/index.ts) + + ## `@deepseek-ai/dsh-skill-filesystem` 需要:`skills` @@ -1764,6 +1901,8 @@ export interface Config { 来源:[`packages/skill/skill-filesystem/src/index.ts:49`](../packages/skill/skill-filesystem/src/index.ts) + + ## `@deepseek-ai/dsh-spill-local` ```ts config-catalog @@ -1780,6 +1919,8 @@ export interface Config { 来源:[`packages/spill/spill-local/src/index.ts:22`](../packages/spill/spill-local/src/index.ts) + + ## `@deepseek-ai/dsh-spill-policy` 需要:`tools` @@ -1798,6 +1939,8 @@ export interface Config { 来源:[`packages/spill/spill-policy/src/index.ts:60`](../packages/spill/spill-policy/src/index.ts) + + ## `@deepseek-ai/dsh-storage-domain` 需要:`storage` @@ -1819,6 +1962,8 @@ export interface Config { 来源:[`packages/storage/storage-domain/src/index.ts:52`](../packages/storage/storage-domain/src/index.ts) + + ## `@deepseek-ai/dsh-storage-json` 需要:`storage` @@ -1838,6 +1983,8 @@ export interface Config { 来源:[`packages/storage/storage-json/src/index.ts:27`](../packages/storage/storage-json/src/index.ts) + + ## `@deepseek-ai/dsh-storage-sqlite` 需要:`storage` @@ -1876,6 +2023,8 @@ export type JournalMode = 'wal' | 'delete' | 'truncate' | 'persist' 来源:[`packages/storage/storage-sqlite/src/index.ts:24`](../packages/storage/storage-sqlite/src/index.ts) + + ## `@deepseek-ai/dsh-subagent-acp` 需要:`subagents` · `subprocess` @@ -1927,6 +2076,8 @@ export type PermissionPolicy = 'allow' | 'reject' 来源:[`packages/subagent/subagent-acp/src/index.ts:27`](../packages/subagent/subagent-acp/src/index.ts) + + ## `@deepseek-ai/dsh-subagent-claude-code` 需要:`subagents` · `subprocess` @@ -1946,6 +2097,8 @@ export interface Config { 来源:[`packages/subagent/subagent-claude-code/src/index.ts:32`](../packages/subagent/subagent-claude-code/src/index.ts) + + ## `@deepseek-ai/dsh-subagent-codex` 需要:`subagents` · `subprocess` @@ -1965,6 +2118,8 @@ export interface Config { 来源:[`packages/subagent/subagent-codex/src/index.ts:30`](../packages/subagent/subagent-codex/src/index.ts) + + ## `@deepseek-ai/dsh-subagent-dsh-sdk` 需要:`subagents` @@ -2016,6 +2171,8 @@ export interface Config { 来源:[`packages/subagent/subagent-dsh-sdk/src/index.ts:29`](../packages/subagent/subagent-dsh-sdk/src/index.ts) + + ## `@deepseek-ai/dsh-subagent-fork-in-process` 需要:`subagents` @@ -2030,6 +2187,8 @@ export interface Config { 来源:[`packages/subagent/subagent-fork-in-process/src/index.ts:31`](../packages/subagent/subagent-fork-in-process/src/index.ts) + + ## `@deepseek-ai/dsh-subagent-spawn-in-process` 需要:`subagents` @@ -2044,6 +2203,8 @@ export interface Config { 来源:[`packages/subagent/subagent-spawn-in-process/src/index.ts:25`](../packages/subagent/subagent-spawn-in-process/src/index.ts) + + ## `@deepseek-ai/dsh-subprocess-e2b` 需要:`e2b` @@ -2058,6 +2219,8 @@ export interface Config { 来源:[`packages/e2b/subprocess-e2b/src/index.ts:25`](../packages/e2b/subprocess-e2b/src/index.ts) + + ## `@deepseek-ai/dsh-system-prompt` ```ts config-catalog @@ -2065,6 +2228,8 @@ export interface Config { export interface Config { /** Include the fixed DeepSeek Harness identity before the deployment persona (default true). */ includeHarnessIdentity?: boolean + /** Include dynamic runtime-context snapshots in model history (default true). */ + includeRuntimeContext?: boolean /** * Deployment-wide order-0 persona template. A scoped section named * `deployment:persona` shadows it; `{{variable}}` references are strict. @@ -2081,6 +2246,8 @@ export interface Config { 来源:[`packages/core/system-prompt/src/index.ts:186`](../packages/core/system-prompt/src/index.ts) + + ## `@deepseek-ai/dsh-terminal-bash` 需要:`pty` · `sandboxPolicy` · `subprocess` @@ -2124,6 +2291,8 @@ export interface Config { 来源:[`packages/terminal/terminal-bash/src/config.ts:6`](../packages/terminal/terminal-bash/src/config.ts) + + ## `@deepseek-ai/dsh-time-context` 需要:`agents` @@ -2140,6 +2309,8 @@ export interface Config { 来源:[`packages/context/time-context/src/index.ts:27`](../packages/context/time-context/src/index.ts) + + ## `@deepseek-ai/dsh-tmux-context` 需要:`agents` @@ -2154,6 +2325,8 @@ export interface Config { 来源:[`packages/context/tmux-context/src/index.ts:34`](../packages/context/tmux-context/src/index.ts) + + ## `@deepseek-ai/dsh-token-meter` ```ts config-catalog @@ -2163,6 +2336,8 @@ export type TokenMeterConfig = Record 来源:[`packages/llm/token-meter/src/types.ts:12`](../packages/llm/token-meter/src/types.ts) + + ## `@deepseek-ai/dsh-tool-bash` 需要:`tools` · `bash` · `systemPrompt` · `bashEnv` @@ -2177,6 +2352,8 @@ export interface Config { 来源:[`packages/shell/tool-bash/src/index.ts:34`](../packages/shell/tool-bash/src/index.ts) + + ## `@deepseek-ai/dsh-tool-bash-persistent` 需要:`tools` · `pty` @@ -2195,7 +2372,9 @@ export interface Config { } ``` -来源:[`packages/shell/tool-bash-persistent/src/index.ts:405`](../packages/shell/tool-bash-persistent/src/index.ts) +来源:[`packages/shell/tool-bash-persistent/src/index.ts:400`](../packages/shell/tool-bash-persistent/src/index.ts) + + ## `@deepseek-ai/dsh-tool-fs` @@ -2217,6 +2396,8 @@ export interface Config { 来源:[`packages/fs/tool-fs/src/index.ts:25`](../packages/fs/tool-fs/src/index.ts) + + ## `@deepseek-ai/dsh-tool-fs-search` 需要:`tools` · `systemPrompt` · `subprocess` @@ -2250,6 +2431,8 @@ export interface Config { 来源:[`packages/fs/tool-fs-search/src/index.ts:73`](../packages/fs/tool-fs-search/src/index.ts) + + ## `@deepseek-ai/dsh-tool-goal` 需要:`agents` · `goals` · `tools` · `systemPrompt` @@ -2264,6 +2447,8 @@ export interface Config { 来源:[`packages/goal/tool-goal/src/index.ts:26`](../packages/goal/tool-goal/src/index.ts) + + ## `@deepseek-ai/dsh-tool-jobs` 需要:`tools` · `tasks` · `systemPrompt` @@ -2296,6 +2481,8 @@ export type CompletionDelivery = 'quiet' | 'wakeup' 来源:[`packages/jobs/tool-jobs/src/index.ts:32`](../packages/jobs/tool-jobs/src/index.ts) + + ## `@deepseek-ai/dsh-tool-lsp` 需要:`tools` · `lsp` · `systemPrompt` @@ -2314,6 +2501,8 @@ export interface Config { 来源:[`packages/lsp/tool-lsp/src/index.ts:58`](../packages/lsp/tool-lsp/src/index.ts) + + ## `@deepseek-ai/dsh-tool-pwsh` 需要:`tools` · `bash` · `systemPrompt` · `bashEnv` @@ -2328,6 +2517,8 @@ export interface Config { 来源:[`packages/shell/tool-pwsh/src/index.ts:52`](../packages/shell/tool-pwsh/src/index.ts) + + ## `@deepseek-ai/dsh-tool-ralph` 需要:`tools` · `workflows` · `subagents` · `systemPrompt` @@ -2348,6 +2539,8 @@ export interface Config { 来源:[`packages/workflow/tool-ralph/src/index.ts:23`](../packages/workflow/tool-ralph/src/index.ts) + + ## `@deepseek-ai/dsh-tool-session-query` 需要:`tools` · `systemPrompt` · `sessionQuery` @@ -2364,6 +2557,8 @@ export interface Config { 来源:[`packages/session-query/tool-session-query/src/index.ts:29`](../packages/session-query/tool-session-query/src/index.ts) + + ## `@deepseek-ai/dsh-tool-skill` 需要:`agents` · `tools` · `skills` @@ -2378,6 +2573,8 @@ export interface Config { 来源:[`packages/skill/tool-skill/src/index.ts:61`](../packages/skill/tool-skill/src/index.ts) + + ## `@deepseek-ai/dsh-tool-str-replace-editor` 需要:`tools` · `fs` @@ -2394,6 +2591,8 @@ export interface Config { 来源:[`packages/fs/tool-str-replace-editor/src/index.ts:497`](../packages/fs/tool-str-replace-editor/src/index.ts) + + ## `@deepseek-ai/dsh-tool-subagent` 需要:`tools` · `subagents` · `systemPrompt` @@ -2457,6 +2656,8 @@ export interface Config { 来源:[`packages/subagent/tool-subagent/src/index.ts:29`](../packages/subagent/tool-subagent/src/index.ts) + + ## `@deepseek-ai/dsh-tool-subagent-report` 需要:`subagents` · `tools` · `systemPrompt` @@ -2477,6 +2678,8 @@ export interface Config { 来源:[`packages/subagent/tool-subagent-report/src/index.ts:27`](../packages/subagent/tool-subagent-report/src/index.ts) + + ## `@deepseek-ai/dsh-tool-terminal` 需要:`pty` · `tools` · `systemPrompt` @@ -2493,6 +2696,8 @@ export interface Config { 来源:[`packages/terminal/tool-terminal/src/index.ts:35`](../packages/terminal/tool-terminal/src/index.ts) + + ## `@deepseek-ai/dsh-tool-todo` 需要:`tools` @@ -2513,6 +2718,8 @@ export interface Config { 来源:[`packages/todo/tool-todo/src/index.ts:29`](../packages/todo/tool-todo/src/index.ts) + + ## `@deepseek-ai/dsh-tool-web` 需要:`tools` · `web` · `systemPrompt` @@ -2537,6 +2744,8 @@ export interface Config { 来源:[`packages/web/tool-web/src/index.ts:37`](../packages/web/tool-web/src/index.ts) + + ## `@deepseek-ai/dsh-tool-workflow` 需要:`tools` · `workflows` · `systemPrompt` @@ -2553,6 +2762,8 @@ export interface Config { 来源:[`packages/workflow/tool-workflow/src/index.ts:33`](../packages/workflow/tool-workflow/src/index.ts) + + ## `@deepseek-ai/dsh-tools` 需要:`systemPrompt` @@ -2587,6 +2798,8 @@ export type ToolPresentationMode = 'native' | 'code' | 'both' 来源:[`packages/core/tools/src/index.ts:654`](../packages/core/tools/src/index.ts) + + ## `@deepseek-ai/dsh-typert-loader` 需要:`typert` · `loader` @@ -2601,6 +2814,8 @@ export interface Config { 来源:[`packages/typert/loader/src/index.ts:47`](../packages/typert/loader/src/index.ts) + + ## `@deepseek-ai/dsh-user-approval` ```ts config-catalog @@ -2630,6 +2845,8 @@ export type ApprovalPolicy = 'ask' | 'never' 来源:[`packages/interaction/user-approval/src/index.ts:177`](../packages/interaction/user-approval/src/index.ts) + + ## `@deepseek-ai/dsh-web` ```ts config-catalog @@ -2649,6 +2866,8 @@ export interface WebRuntimeConfig { 来源:[`packages/web/web/src/index.ts:55`](../packages/web/web/src/index.ts) + + ## `@deepseek-ai/dsh-web-app` 需要:`webServer` @@ -2672,6 +2891,8 @@ export interface Config { 来源:[`packages/bundle/web-app/src/index.ts:38`](../packages/bundle/web-app/src/index.ts) + + ## `@deepseek-ai/dsh-web-fetch-http` 需要:`web` @@ -2696,6 +2917,8 @@ export interface Config { 来源:[`packages/web/web-fetch-http/src/index.ts:34`](../packages/web/web-fetch-http/src/index.ts) + + ## `@deepseek-ai/dsh-web-search-deepseek` 需要:`web` @@ -2722,6 +2945,8 @@ export interface Config { 来源:[`packages/web/web-search-deepseek/src/index.ts:46`](../packages/web/web-search-deepseek/src/index.ts) + + ## `@deepseek-ai/dsh-web-search-exa` 需要:`web` @@ -2744,6 +2969,8 @@ export interface Config { 来源:[`packages/web/web-search-exa/src/index.ts:38`](../packages/web/web-search-exa/src/index.ts) + + ## `@deepseek-ai/dsh-web-search-perplexity` 需要:`web` @@ -2766,6 +2993,8 @@ export interface Config { 来源:[`packages/web/web-search-perplexity/src/index.ts:32`](../packages/web/web-search-perplexity/src/index.ts) + + ## `@deepseek-ai/dsh-workflow-worker-thread` 需要:`subagents` diff --git a/docs/cookbook/adding-a-package.i18n.yaml b/docs/cookbook/adding-a-package.i18n.yaml index d9cf8eb3a4..5cdb1404f8 100644 --- a/docs/cookbook/adding-a-package.i18n.yaml +++ b/docs/cookbook/adding-a-package.i18n.yaml @@ -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 docs/cookbook/adding-a-package.md -adding-a-package.md: 26a380fd3ec6b8b0447ad27d7ef79d3e58433cbe -adding-a-package.zh.md: 49a9fba820698d0c82c9700c31a28039fbc030c8 +adding-a-package.md: a78695735957395c5c900c3294b6778904557f85 +adding-a-package.zh.md: b7a749220fdc1581875851e2e4a7189ba7642b2d diff --git a/docs/cookbook/adding-a-package.md b/docs/cookbook/adding-a-package.md index 26a380fd3e..a786957359 100644 --- a/docs/cookbook/adding-a-package.md +++ b/docs/cookbook/adding-a-package.md @@ -40,7 +40,7 @@ Covered automatically by globs or package-manifest discovery — no edits needed ## 3. Decide the package topology -For a swappable capability, separate Service Definition / Service provider / Consumer roles into packages when they evolve independently (see docs/architecture.md § "Capability seams" — the shell trio is the template). A single-purpose plugin stays one package. +For a swappable capability, separate Service Definition / Service Provider / Consumer roles into packages when they evolve independently (see docs/architecture.md § "Capability seams" — the shell trio is the template). A single-purpose plugin stays one package. ### Name the role that exists diff --git a/docs/cookbook/adding-a-package.zh.md b/docs/cookbook/adding-a-package.zh.md index 49a9fba820..b7a749220f 100644 --- a/docs/cookbook/adding-a-package.zh.md +++ b/docs/cookbook/adding-a-package.zh.md @@ -40,7 +40,7 @@ package.json 不变式(由 `pnpm run constraints` / `scripts/check-workspace-c ## 3. 确定包拓扑 -对于可替换的能力,当 Service Definition/Service provider/Consumer 角色需要独立演进时,将它们拆分到不同包中(见 docs/architecture.md § "Capability seams"——shell 三组件是模板)。单一用途的插件保持为一个包。 +对于可替换的能力,当 Service Definition/Service Provider/Consumer 角色需要独立演进时,将它们拆分到不同包中(见 docs/architecture.md § "Capability seams"——shell 三组件是模板)。单一用途的插件保持为一个包。 ### 使用符合实际的角色名称 diff --git a/docs/cookbook/adding-a-settings-card.i18n.yaml b/docs/cookbook/adding-a-settings-card.i18n.yaml new file mode 100644 index 0000000000..acaa9a598b --- /dev/null +++ b/docs/cookbook/adding-a-settings-card.i18n.yaml @@ -0,0 +1,6 @@ +# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each +# 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 docs/cookbook/adding-a-settings-card.md +adding-a-settings-card.md: 56ec3be578bbc489bbb979a50bcaed063a35ace5 +adding-a-settings-card.zh.md: 4643303bfd76ba77676b7e508424f46082627b62 diff --git a/docs/cookbook/adding-a-settings-card.md b/docs/cookbook/adding-a-settings-card.md new file mode 100644 index 0000000000..56ec3be578 --- /dev/null +++ b/docs/cookbook/adding-a-settings-card.md @@ -0,0 +1,100 @@ +# Cookbook: adding a settings card + +English | [中文](adding-a-settings-card.zh.md) + +How a plugin puts its own configuration on the web settings page. Nothing in this path needs a change inside this repository: the Host serves every registered settings namespace, and the **Plugins** section keys its cards on the namespace they edit, so a plugin that registers both halves is paired up automatically. + +The two halves live in one package — the Host half under `src/`, the browser half under `src/client/`, exported as `./client` and declared with `dsh.client`. [`packages/client/ui-theme`](../../packages/client/ui-theme) is a worked example of that packaging; the cards this section ships live in [`packages/client/ui-settings-plugins`](../../packages/client/ui-settings-plugins). + +## 1. Register the namespace (Host half) + +The namespace is the join key, so pick it once and spell it in both halves. A consumer that already has a `cordis.yml` entry should register through `installSettingsSection`, which layers the entry under the user document and keeps working when no settings provider is mounted: + +```ts +import type { Context } from '@deepseek-ai/cordis' +import { installSettingsSection, settingsNamespace } from '@deepseek-ai/dsh-settings' +import z from '@deepseek-ai/schemastery' + +declare function assertReachable(endpoint: string | undefined): void +declare function rebuildFromSettings(config: Config): void + +export const MY_PLUGIN_NS = settingsNamespace('my-plugin') + +export interface Config { + endpoint?: string + retries?: number +} + +export const Config: z = z.object({ + endpoint: z.string(), + retries: z.number().step(1).min(0).default(3), +}) + +export function apply(ctx: Context, config: Config) { + let source = () => config + installSettingsSection(ctx, MY_PLUGIN_NS, Config, config, { + // Constraints the schema cannot express refuse the write, not the next use. + validate: value => void assertReachable(value.endpoint), + setSource: (current) => { source = current }, + onChange: () => { rebuildFromSettings(source()) }, + }) +} +``` + +`role('secret')` on a field keeps its value off every response; the card writes such a field into an `update`/`mutate` payload, or addresses a credential reference through the `credentials` domain instead. `applies: 'restart'` tells a configuration surface the owner acts on a change only at the next start. + +## 2. Register the card (browser half) + +The card registers into `settings.plugin.item` under its namespace and owns everything inside it — chrome, controls, and copy. It reads and writes through `ctx.settingsScope`, which fences each write with the revision it read: + +```ts ignore-check +import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client' +// Type-only: the keyed slot's declaration. Cross-plugin collaboration goes +// through cordis services; a value import fails the client bundle-purity gate. +import type {} from '@deepseek-ai/dsh-client-ui-settings-plugins/client' + +export const inject = ['slots', 'locale', 'connection', 'remote', 'settingsScope'] + +export function apply(ctx: ClientContext): void { + const card = new MyPluginCardController(ctx.settingsScope.bind({ namespace: 'my-plugin' })) + ctx.slots.inject('settings.plugin.item', () => ctx.slots.register({ + name: 'settings.plugin.item', + key: 'my-plugin', + locale: 'settings.myPlugin', + inject: () => card.inject(), + }, MyPluginCard), + ) +} +``` + +The scope snapshot carries what a form needs: the resolved `value`, the composition `base`, and the raw `user` layer, whose key **presence** — not its value — is what marks a field overridden. `scope.set(field, value)` stores one field and `scope.unset(field)` clears it back to the composition layer. + +## 3. What the tab does with it + +The **Plugin configuration** tab reads which namespaces the Host serves and dispatches one slot key per namespace. A card is rendered when the Host serves its key and skipped when it does not, so a deployment that never composed the Host half shows no trace of the card. A served namespace no card claims renders nothing — that is how the namespaces owned by other pages (`ui-theme`, `permission`, `llm-*`) stay off this tab. + +Cards appear in the order they registered into the slot; a keyed entry declares no `order` of its own. + +## Packaging + +The browser half is served to the page by the [client module system](../../packages/client/modules), which scans the enabled Loader entries for packages declaring `dsh.client` and serves each one's built `./client` export. So the plugin appears on the page as soon as a `cordis.yml` mounts it — no rebuild of the web application. + +```jsonc +{ + "exports": { + ".": { "types": "./lib/types/index.d.ts", "default": "./lib/index.js" }, + "./client": { "types": "./lib/types/client/index.d.ts", "default": "./lib/client.js" } + }, + "dsh": { "client": { "platform": "web", "inject": ["@deepseek-ai/dsh-client-ui-settings-plugins"] } } +} +``` + +The bundle must be the loader's lazy-CJS factory artifact. Inside this repository `tsdown.config.ts` is three lines over the shared preset: + +```ts ignore-check +import { clientBundle } from '../tsdown.client.ts' + +export default clientBundle('@deepseek-ai/dsh-client-my-plugin', ['lib/types/index.js', 'lib/types/invariant.js']) +``` + +That preset is not published today, so a package outside this repository has to reproduce the same output format itself. The bundle-purity gate also rejects value imports across plugins, so a card cannot import this section's card chrome or its staged-form model — it renders its own, and owns its own staging and revision fencing. Both limits are recorded under [the section's known limitations](../../packages/client/ui-settings-plugins/README.md#known-limitations-and-deferred-work). diff --git a/docs/cookbook/adding-a-settings-card.zh.md b/docs/cookbook/adding-a-settings-card.zh.md new file mode 100644 index 0000000000..4643303bfd --- /dev/null +++ b/docs/cookbook/adding-a-settings-card.zh.md @@ -0,0 +1,100 @@ +# Cookbook: 新增设置卡片 + +[English](adding-a-settings-card.md) | 中文 + +插件如何把自己的配置放上 Web 设置页。这条路径上没有任何一步需要改动本仓库:Host 服务每一个已注册的 settings 命名空间,而**插件配置**分区以卡片所编辑的命名空间为键,因此同时注册了两个半侧的插件会被自动配对。 + +两个半侧住在同一个包里——Host 半侧在 `src/`,浏览器半侧在 `src/client/`,以 `./client` 导出并用 `dsh.client` 声明。[`packages/client/ui-theme`](../../packages/client/ui-theme) 是这种打包方式的现成例子;本分区自带的卡片在 [`packages/client/ui-settings-plugins`](../../packages/client/ui-settings-plugins)。 + +## 1. 注册命名空间(Host 半侧) + +命名空间就是配对用的键,所以只挑一次,并在两个半侧都写出它。已经有 `cordis.yml` entry 的消费方应通过 `installSettingsSection` 注册——它把 entry 层叠在用户文档之下,并在没有挂载 settings provider 时照常工作: + +```ts +import type { Context } from '@deepseek-ai/cordis' +import { installSettingsSection, settingsNamespace } from '@deepseek-ai/dsh-settings' +import z from '@deepseek-ai/schemastery' + +declare function assertReachable(endpoint: string | undefined): void +declare function rebuildFromSettings(config: Config): void + +export const MY_PLUGIN_NS = settingsNamespace('my-plugin') + +export interface Config { + endpoint?: string + retries?: number +} + +export const Config: z = z.object({ + endpoint: z.string(), + retries: z.number().step(1).min(0).default(3), +}) + +export function apply(ctx: Context, config: Config) { + let source = () => config + installSettingsSection(ctx, MY_PLUGIN_NS, Config, config, { + // Constraints the schema cannot express refuse the write, not the next use. + validate: value => void assertReachable(value.endpoint), + setSource: (current) => { source = current }, + onChange: () => { rebuildFromSettings(source()) }, + }) +} +``` + +字段上的 `role('secret')` 让它的值不出现在任何响应里;卡片把这类字段写进 `update`/`mutate` 载荷,或改为经 `credentials` 领域寻址一个凭据引用。`applies: 'restart'` 告诉配置表层:拥有方要到下次启动才会对变更生效。 + +## 2. 注册卡片(浏览器半侧) + +卡片以自己的命名空间为键注册进 `settings.plugin.item`,并拥有其中的一切——外观、控件与文案。它通过 `ctx.settingsScope` 读写,后者用读取时的 revision 为每次写入设栅: + +```ts ignore-check +import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client' +// Type-only: the keyed slot's declaration. Cross-plugin collaboration goes +// through cordis services; a value import fails the client bundle-purity gate. +import type {} from '@deepseek-ai/dsh-client-ui-settings-plugins/client' + +export const inject = ['slots', 'locale', 'connection', 'remote', 'settingsScope'] + +export function apply(ctx: ClientContext): void { + const card = new MyPluginCardController(ctx.settingsScope.bind({ namespace: 'my-plugin' })) + ctx.slots.inject('settings.plugin.item', () => ctx.slots.register({ + name: 'settings.plugin.item', + key: 'my-plugin', + locale: 'settings.myPlugin', + inject: () => card.inject(), + }, MyPluginCard), + ) +} +``` + +scope 快照携带表单所需的一切:解析后的 `value`、组装层 `base`,以及原始的 `user` 层——字段是否被覆盖,取决于它在 `user` 层中是否**出现**,而非它的值。`scope.set(field, value)` 存一个字段,`scope.unset(field)` 把它清回组装层。 + +## 3. 标签页拿它做什么 + +**插件配置**标签页读取 Host 服务了哪些命名空间,并为每个命名空间派发一个 slot 键。当 Host 服务了某卡片的键时它被渲染,否则被跳过,因此从未组装过 Host 半侧的部署不会留下这张卡片的任何痕迹。被服务却无人认领的命名空间什么都不渲染——归其他页面所有的那些命名空间(`ui-theme`、`permission`、`llm-*`)正是这样留在本标签页之外的。 + +卡片按其注册进该 slot 的顺序出现;keyed entry 不声明自己的 `order`。 + +## 打包 + +浏览器半侧由[客户端模块系统](../../packages/client/modules)提供给页面:它扫描已启用的 Loader entries 中声明了 `dsh.client` 的包,并提供每个包构建出的 `./client` 导出。因此只要 `cordis.yml` 挂载了该插件,它就会出现在页面上——无需重新构建 Web 应用。 + +```jsonc +{ + "exports": { + ".": { "types": "./lib/types/index.d.ts", "default": "./lib/index.js" }, + "./client": { "types": "./lib/types/client/index.d.ts", "default": "./lib/client.js" } + }, + "dsh": { "client": { "platform": "web", "inject": ["@deepseek-ai/dsh-client-ui-settings-plugins"] } } +} +``` + +bundle 必须是 loader 的 lazy-CJS factory 产物。在本仓库内,`tsdown.config.ts` 就是基于共享预设的三行: + +```ts ignore-check +import { clientBundle } from '../tsdown.client.ts' + +export default clientBundle('@deepseek-ai/dsh-client-my-plugin', ['lib/types/index.js', 'lib/types/invariant.js']) +``` + +该预设目前未发布,因此本仓库之外的包得自行复刻同样的输出格式。bundle 纯净度门禁同时拒绝跨插件的值导入,所以卡片无法导入本分区的卡片外观或其暂存表单模型——它渲染自己的那一份,并自行拥有暂存与 revision 设栅。这两条限制都记在[本分区的已知限制](../../packages/client/ui-settings-plugins/README.md#known-limitations-and-deferred-work)里。 diff --git a/docs/cookbook/adding-a-tool.i18n.yaml b/docs/cookbook/adding-a-tool.i18n.yaml index d7f08cc5af..b39b907128 100644 --- a/docs/cookbook/adding-a-tool.i18n.yaml +++ b/docs/cookbook/adding-a-tool.i18n.yaml @@ -3,4 +3,4 @@ # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write docs/cookbook/adding-a-tool.md adding-a-tool.md: 37516521de4d00de964003fd6f877831774fdcd3 -adding-a-tool.zh.md: 9455fa3b8d8b87632724ad4b035f184cb0c17993 +adding-a-tool.zh.md: 27a90ce19653333a0a6afd989115e614a1c8f9f4 diff --git a/docs/cookbook/adding-a-tool.zh.md b/docs/cookbook/adding-a-tool.zh.md index 9455fa3b8d..27a90ce196 100644 --- a/docs/cookbook/adding-a-tool.zh.md +++ b/docs/cookbook/adding-a-tool.zh.md @@ -54,6 +54,8 @@ export function apply(ctx: Context) { producer 提供同步的 `cancel`、在资源清理后 settle 且不 reject 的 `done`,以及可选的消费式 `readOutput`(负责有界输出的格式化)。预先中止的调用属于失败,因为此时没有任务,其 id 无法满足成功输出 schema。`ctx.jobs.start()` 发布 id 后,应使用任务自有的取消信号,而不是 `exec.signal`:之后取消外层调用只会停止等待本次调用,不会终止已经发布的工作;该生命周期归 `job_kill`、owner dispose 和服务 teardown 所有。前台工作仍与 `exec.signal` 耦合。流式 producer 的示例和完整约定见[后台任务运行时 Agent Note](../../.agents/notes/implemented/architecture/2026-06-20-generic-long-running-tool-runtime.md)与 `dsh-tool-bash`。 + + ## 执行策略与观测 尽量不要把部署策略内建到工具中。使用 `tools/pre-execute` 实现可扩展的允许/拒绝/询问策略(见[权限门禁示例](extension-cookbook.md#a-hook-plugin-permission-gate-example));使用 `ctx.tools.guard()` 设置最终的单调拒绝,后续监听器无法撤销;使用 `tools/execute` 为分发添加截止时间、重试或指标收集;使用 `tools/post-execute` 替换展示内容或返回值、阻止结果,或附加模型可见上下文;使用 `tools/result` 观测不可变的归一化结果而不改变它。替换内容不会阻止程序化访问 `value`;保密策略会屏蔽或替换该值。沙箱实现也可以在工具的执行器实现中运行;[`dsh-tools` README](../../packages/core/tools/README.md#extension-points) 定义每个扩展点的输入、顺序、返回值和失败行为。 diff --git a/docs/cookbook/extension-cookbook.i18n.yaml b/docs/cookbook/extension-cookbook.i18n.yaml index a496c31981..d55871fa50 100644 --- a/docs/cookbook/extension-cookbook.i18n.yaml +++ b/docs/cookbook/extension-cookbook.i18n.yaml @@ -3,4 +3,4 @@ # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write docs/cookbook/extension-cookbook.md extension-cookbook.md: 9618a3522c5566636fe3e49f7eca93d1e113d51a -extension-cookbook.zh.md: 7b82d7d1ff239cc2139ee424613e818669f3e2e8 +extension-cookbook.zh.md: 540bc6867016d095ccae0fb0fdc79bc1b1c26290 diff --git a/docs/cookbook/extension-cookbook.zh.md b/docs/cookbook/extension-cookbook.zh.md index 7b82d7d1ff..540bc68670 100644 --- a/docs/cookbook/extension-cookbook.zh.md +++ b/docs/cookbook/extension-cookbook.zh.md @@ -8,6 +8,8 @@ harness 扩展的参考模式。代码片段省略了 import 和辅助实现, 工具在 `ctx.tools` 上注册。带注解的 `defineTool` 示例(类型化的 `execute` 参数、结果构造、`run_in_background` 模式)见 [adding-a-tool.md](adding-a-tool.md)——该指南是工具定义的真源。`ctx.tools.register()` 也直接接受原始 JSON Schema `ToolDefinition`(MCP 来源的工具就是这样到达的);`defineTool` 是第一方工具使用的类型化辅助函数。 + + ## 钩子插件(以权限门禁为例) 这个权限门禁是钩子插件的一个示例。它从 `tools/pre-execute` 门禁返回一个类型化的决策,用于允许或拒绝一次调用;沙箱、权限和 plan-mode 插件都可以使用该扩展点。钩子插件也可以拦截其他扩展点,本身并不等同于权限门禁。「原生钩子」是在拦截点上运行的普通 Cordis 插件,不需要外部协议。 diff --git a/docs/cordis-paper.pdf b/docs/cordis-paper.pdf deleted file mode 100644 index 9d722738d7..0000000000 --- a/docs/cordis-paper.pdf +++ /dev/null @@ -1,65905 +0,0 @@ -%PDF-1.7 -% - -1 0 obj -<< - /Type /Pages - /Count 48 - /Kids [4681 0 R 4715 0 R 4736 0 R 4743 0 R 4756 0 R 4769 0 R 4787 0 R 4799 0 R 4803 0 R 4806 0 R 4808 0 R 4812 0 R 4817 0 R 4820 0 R 4822 0 R 4829 0 R 4836 0 R 4840 0 R 4844 0 R 4848 0 R 4852 0 R 4864 0 R 4874 0 R 4884 0 R 4899 0 R 4905 0 R 4917 0 R 4921 0 R 4925 0 R 4929 0 R 4941 0 R 4947 0 R 4956 0 R 4973 0 R 4976 0 R 4985 0 R 4998 0 R 5009 0 R 5029 0 R 5053 0 R 5066 0 R 5095 0 R 5127 0 R 5155 0 R 5189 0 R 5221 0 R 5251 0 R 5270 0 R] ->> -endobj - -2 0 obj -<< - /Type /Outlines - /First 3 0 R - /Last 52 0 R - /Count 8 ->> -endobj - -3 0 obj -<< - /Parent 2 0 R - /Next 10 0 R - /First 4 0 R - /Last 9 0 R - /Count -3 - /Title (1. Introduction) - /Dest 4412 0 R ->> -endobj - -4 0 obj -<< - /Parent 3 0 R - /Next 5 0 R - /Title (1.1. Dimensions of Composability) - /Dest 4406 0 R ->> -endobj - -5 0 obj -<< - /Parent 3 0 R - /Next 9 0 R - /Prev 4 0 R - /First 6 0 R - /Last 8 0 R - /Count -3 - /Title (1.2. Motivating Examples) - /Dest 4410 0 R ->> -endobj - -6 0 obj -<< - /Parent 5 0 R - /Next 7 0 R - /Title (1.2.1. Plugin Systems) - /Dest 4407 0 R ->> -endobj - -7 0 obj -<< - /Parent 5 0 R - /Next 8 0 R - /Prev 6 0 R - /Title (1.2.2. Self-Evolving Agent Harnesses) - /Dest 4408 0 R ->> -endobj - -8 0 obj -<< - /Parent 5 0 R - /Prev 7 0 R - /Title (1.2.3. The Coarse-Grained Workaround) - /Dest 4409 0 R ->> -endobj - -9 0 obj -<< - /Parent 3 0 R - /Prev 5 0 R - /Title (1.3. Contributions) - /Dest 4411 0 R ->> -endobj - -10 0 obj -<< - /Parent 2 0 R - /Next 14 0 R - /Prev 3 0 R - /First 11 0 R - /Last 13 0 R - /Count -3 - /Title (2. Preliminaries) - /Dest 4416 0 R ->> -endobj - -11 0 obj -<< - /Parent 10 0 R - /Next 12 0 R - /Title (2.1. Effects) - /Dest 4413 0 R ->> -endobj - -12 0 obj -<< - /Parent 10 0 R - /Next 13 0 R - /Prev 11 0 R - /Title (2.2. Coeffects) - /Dest 4414 0 R ->> -endobj - -13 0 obj -<< - /Parent 10 0 R - /Prev 12 0 R - /Title (2.3. Relationship to Dynamic Composability) - /Dest 4415 0 R ->> -endobj - -14 0 obj -<< - /Parent 2 0 R - /Next 30 0 R - /Prev 10 0 R - /First 15 0 R - /Last 27 0 R - /Count -4 - /Title (3. Revertible Effects and Reactive Coeffects) - /Dest 4432 0 R ->> -endobj - -15 0 obj -<< - /Parent 14 0 R - /Next 18 0 R - /First 16 0 R - /Last 17 0 R - /Count -2 - /Title (3.1. Revertible Effects) - /Dest 4419 0 R ->> -endobj - -16 0 obj -<< - /Parent 15 0 R - /Next 17 0 R - /Title (3.1.1. Effect Context) - /Dest 4417 0 R ->> -endobj - -17 0 obj -<< - /Parent 15 0 R - /Prev 16 0 R - /Title (3.1.2. Revertible Effect Functions) - /Dest 4418 0 R ->> -endobj - -18 0 obj -<< - /Parent 14 0 R - /Next 22 0 R - /Prev 15 0 R - /First 19 0 R - /Last 21 0 R - /Count -3 - /Title (3.2. Reactive Coeffects) - /Dest 4423 0 R ->> -endobj - -19 0 obj -<< - /Parent 18 0 R - /Next 20 0 R - /Title (3.2.1. Coeffect Context) - /Dest 4420 0 R ->> -endobj - -20 0 obj -<< - /Parent 18 0 R - /Next 21 0 R - /Prev 19 0 R - /Title (3.2.2. Specification and Notification) - /Dest 4421 0 R ->> -endobj - -21 0 obj -<< - /Parent 18 0 R - /Prev 20 0 R - /Title (3.2.3. Isolation and Interception) - /Dest 4422 0 R ->> -endobj - -22 0 obj -<< - /Parent 14 0 R - /Next 27 0 R - /Prev 18 0 R - /First 23 0 R - /Last 26 0 R - /Count -4 - /Title (3.3. Component Lifecycle) - /Dest 4428 0 R ->> -endobj - -23 0 obj -<< - /Parent 22 0 R - /Next 24 0 R - /Title (3.3.1. Idempotent Recovery) - /Dest 4424 0 R ->> -endobj - -24 0 obj -<< - /Parent 22 0 R - /Next 25 0 R - /Prev 23 0 R - /Title (3.3.2. Iteration) - /Dest 4425 0 R ->> -endobj - -25 0 obj -<< - /Parent 22 0 R - /Next 26 0 R - /Prev 24 0 R - /Title (3.3.3. Coherence) - /Dest 4426 0 R ->> -endobj - -26 0 obj -<< - /Parent 22 0 R - /Prev 25 0 R - /Title (3.3.4. Asynchrony) - /Dest 4427 0 R ->> -endobj - -27 0 obj -<< - /Parent 14 0 R - /Prev 22 0 R - /First 28 0 R - /Last 29 0 R - /Count -2 - /Title (3.4. The Context Paradigm) - /Dest 4431 0 R ->> -endobj - -28 0 obj -<< - /Parent 27 0 R - /Next 29 0 R - /Title (3.4.1. Unified Context) - /Dest 4429 0 R ->> -endobj - -29 0 obj -<< - /Parent 27 0 R - /Prev 28 0 R - /Title (3.4.2. Situating the Context Paradigm) - /Dest 4430 0 R ->> -endobj - -30 0 obj -<< - /Parent 2 0 R - /Next 40 0 R - /Prev 14 0 R - /First 31 0 R - /Last 39 0 R - /Count -3 - /Title (4. Implementation and Case Study) - /Dest 4442 0 R ->> -endobj - -31 0 obj -<< - /Parent 30 0 R - /Next 36 0 R - /First 32 0 R - /Last 35 0 R - /Count -4 - /Title (4.1. Core Library) - /Dest 4437 0 R ->> -endobj - -32 0 obj -<< - /Parent 31 0 R - /Next 33 0 R - /Title (4.1.1. Effect Tracking) - /Dest 4433 0 R ->> -endobj - -33 0 obj -<< - /Parent 31 0 R - /Next 34 0 R - /Prev 32 0 R - /Title (4.1.2. Coeffect Operations) - /Dest 4434 0 R ->> -endobj - -34 0 obj -<< - /Parent 31 0 R - /Next 35 0 R - /Prev 33 0 R - /Title (4.1.3. Component Lifecycle) - /Dest 4435 0 R ->> -endobj - -35 0 obj -<< - /Parent 31 0 R - /Prev 34 0 R - /Title (4.1.4. Context Access) - /Dest 4436 0 R ->> -endobj - -36 0 obj -<< - /Parent 30 0 R - /Next 39 0 R - /Prev 31 0 R - /First 37 0 R - /Last 38 0 R - /Count -2 - /Title (4.2. Component Loader) - /Dest 4440 0 R ->> -endobj - -37 0 obj -<< - /Parent 36 0 R - /Next 38 0 R - /Title (4.2.1. Declarative Configuration Layer) - /Dest 4438 0 R ->> -endobj - -38 0 obj -<< - /Parent 36 0 R - /Prev 37 0 R - /Title (4.2.2. Hot Module Replacement) - /Dest 4439 0 R ->> -endobj - -39 0 obj -<< - /Parent 30 0 R - /Prev 36 0 R - /Title (4.3. Case Study: Koishi) - /Dest 4441 0 R ->> -endobj - -40 0 obj -<< - /Parent 2 0 R - /Next 46 0 R - /Prev 30 0 R - /First 41 0 R - /Last 45 0 R - /Count -5 - /Title (5. Discussion) - /Dest 4448 0 R ->> -endobj - -41 0 obj -<< - /Parent 40 0 R - /Next 42 0 R - /Title (5.1. Service Multiplexing) - /Dest 4443 0 R ->> -endobj - -42 0 obj -<< - /Parent 40 0 R - /Next 43 0 R - /Prev 41 0 R - /Title (5.2. Access Control and Sandboxing) - /Dest 4444 0 R ->> -endobj - -43 0 obj -<< - /Parent 40 0 R - /Next 44 0 R - /Prev 42 0 R - /Title (5.3. Language Independence and Selection) - /Dest 4445 0 R ->> -endobj - -44 0 obj -<< - /Parent 40 0 R - /Next 45 0 R - /Prev 43 0 R - /Title (5.4. Mutual Dependencies and Component Granularity) - /Dest 4446 0 R ->> -endobj - -45 0 obj -<< - /Parent 40 0 R - /Prev 44 0 R - /Title (5.5. Dependency Typing and Versioning) - /Dest 4447 0 R ->> -endobj - -46 0 obj -<< - /Parent 2 0 R - /Next 51 0 R - /Prev 40 0 R - /First 47 0 R - /Last 50 0 R - /Count -4 - /Title (6. Related Work) - /Dest 4453 0 R ->> -endobj - -47 0 obj -<< - /Parent 46 0 R - /Next 48 0 R - /Title (6.1. Effect and Coeffect Systems) - /Dest 4449 0 R ->> -endobj - -48 0 obj -<< - /Parent 46 0 R - /Next 49 0 R - /Prev 47 0 R - /Title (6.2. Programming Paradigms) - /Dest 4450 0 R ->> -endobj - -49 0 obj -<< - /Parent 46 0 R - /Next 50 0 R - /Prev 48 0 R - /Title (6.3. Temporal Composability) - /Dest 4451 0 R ->> -endobj - -50 0 obj -<< - /Parent 46 0 R - /Prev 49 0 R - /Title (6.4. Spatial Composability) - /Dest 4452 0 R ->> -endobj - -51 0 obj -<< - /Parent 2 0 R - /Next 52 0 R - /Prev 46 0 R - /Title (7. Conclusion) - /Dest 4454 0 R ->> -endobj - -52 0 obj -<< - /Parent 2 0 R - /Prev 51 0 R - /Title (References) - /Dest 4455 0 R ->> -endobj - -53 0 obj -<< - /Nums [0 4306 0 R 1 4307 0 R 2 4308 0 R 3 4309 0 R 4 4310 0 R 5 4311 0 R 6 4312 0 R 7 4313 0 R 8 4314 0 R 9 4315 0 R 10 4316 0 R 11 4317 0 R 12 4318 0 R 13 4319 0 R 14 4320 0 R 15 4321 0 R 16 4322 0 R 17 4323 0 R 18 4324 0 R 19 4325 0 R 20 4326 0 R 21 4327 0 R 22 4328 0 R 23 4329 0 R 24 4330 0 R 25 4331 0 R 26 4332 0 R 27 4333 0 R 28 4334 0 R 29 4335 0 R 30 4336 0 R 31 4337 0 R 32 4338 0 R 33 4339 0 R 34 4340 0 R 35 4341 0 R 36 4342 0 R 37 4343 0 R 38 4344 0 R 39 4345 0 R 40 4346 0 R 41 4347 0 R 42 4348 0 R 43 4349 0 R 44 4350 0 R 45 4351 0 R 46 4352 0 R 47 4353 0 R] ->> -endobj - -54 0 obj -<< - /Type /StructTreeRoot - /RoleMap << - /Datetime /Span - /Terms /Part - /Title /P - /Strong /Span - /Em /Span - >> - /K [103 0 R] - /ParentTree << - /Nums [0 55 0 R 1 4287 0 R 2 4283 0 R 3 4279 0 R 4 4275 0 R 5 4271 0 R 6 4267 0 R 7 4262 0 R 8 4257 0 R 9 4253 0 R 10 4249 0 R 11 4245 0 R 12 4240 0 R 13 4236 0 R 14 4232 0 R 15 4228 0 R 16 4223 0 R 17 4219 0 R 18 4215 0 R 19 4211 0 R 20 4206 0 R 21 4202 0 R 22 4198 0 R 23 4194 0 R 24 4190 0 R 25 4185 0 R 26 4181 0 R 27 4177 0 R 28 4171 0 R 29 4167 0 R 30 4163 0 R 31 4159 0 R 32 4155 0 R 33 56 0 R 34 4155 0 R 35 4151 0 R 36 4146 0 R 37 4142 0 R 38 4138 0 R 39 4133 0 R 40 4128 0 R 41 4124 0 R 42 4120 0 R 43 4116 0 R 44 4112 0 R 45 4108 0 R 46 4103 0 R 47 4099 0 R 48 4095 0 R 49 4091 0 R 50 4087 0 R 51 4082 0 R 52 4079 0 R 53 57 0 R 54 4074 0 R 55 4071 0 R 56 4070 0 R 57 4055 0 R 58 4054 0 R 59 58 0 R 60 4046 0 R 61 4033 0 R 62 4028 0 R 63 4027 0 R 64 4024 0 R 65 4023 0 R 66 4022 0 R 67 4021 0 R 68 4020 0 R 69 4019 0 R 70 4043 0 R 71 59 0 R 72 4015 0 R 73 4013 0 R 74 4007 0 R 75 4006 0 R 76 4004 0 R 77 4003 0 R 78 3999 0 R 79 3993 0 R 80 3988 0 R 81 3986 0 R 82 3981 0 R 83 60 0 R 84 3976 0 R 85 3973 0 R 86 3972 0 R 87 3964 0 R 88 3961 0 R 89 3960 0 R 90 3952 0 R 91 3951 0 R 92 3947 0 R 93 3941 0 R 94 3940 0 R 95 3939 0 R 96 3938 0 R 97 3937 0 R 98 3933 0 R 99 3932 0 R 100 61 0 R 101 3927 0 R 102 3926 0 R 103 3915 0 R 104 3914 0 R 105 3906 0 R 106 3905 0 R 107 3904 0 R 108 3903 0 R 109 3898 0 R 110 3886 0 R 111 62 0 R 112 3883 0 R 113 3841 0 R 114 63 0 R 115 3768 0 R 116 64 0 R 117 65 0 R 118 3508 0 R 119 3507 0 R 120 66 0 R 121 3500 0 R 122 3499 0 R 123 3391 0 R 124 67 0 R 125 3361 0 R 126 68 0 R 127 69 0 R 128 3096 0 R 129 3091 0 R 130 3063 0 R 131 3049 0 R 132 3049 0 R 133 70 0 R 134 3049 0 R 135 3042 0 R 136 3035 0 R 137 3015 0 R 138 2978 0 R 139 71 0 R 140 2892 0 R 141 2890 0 R 142 72 0 R 143 2835 0 R 144 2804 0 R 145 73 0 R 146 2767 0 R 147 2761 0 R 148 74 0 R 149 2694 0 R 150 2687 0 R 151 75 0 R 152 2679 0 R 153 2678 0 R 154 2674 0 R 155 2671 0 R 156 2669 0 R 157 2667 0 R 158 2664 0 R 159 2659 0 R 160 2652 0 R 161 2644 0 R 162 76 0 R 163 2635 0 R 164 2552 0 R 165 2551 0 R 166 2550 0 R 167 2549 0 R 168 2546 0 R 169 2541 0 R 170 2535 0 R 171 77 0 R 172 2385 0 R 173 2383 0 R 174 2374 0 R 175 2367 0 R 176 2362 0 R 177 2342 0 R 178 2329 0 R 179 2327 0 R 180 78 0 R 181 2216 0 R 182 2213 0 R 183 2212 0 R 184 2209 0 R 185 2135 0 R 186 2130 0 R 187 2124 0 R 188 2123 0 R 189 2119 0 R 190 2116 0 R 191 2109 0 R 192 2106 0 R 193 2103 0 R 194 79 0 R 195 2009 0 R 196 2008 0 R 197 2001 0 R 198 1998 0 R 199 80 0 R 200 1785 0 R 201 1783 0 R 202 1777 0 R 203 1776 0 R 204 1773 0 R 205 1765 0 R 206 1763 0 R 207 1705 0 R 208 1701 0 R 209 1695 0 R 210 81 0 R 211 1689 0 R 212 1678 0 R 213 82 0 R 214 1610 0 R 215 1609 0 R 216 83 0 R 217 1216 0 R 218 1213 0 R 219 84 0 R 220 1107 0 R 221 1100 0 R 222 1090 0 R 223 1089 0 R 224 1086 0 R 225 1085 0 R 226 1084 0 R 227 1081 0 R 228 1104 0 R 229 1097 0 R 230 85 0 R 231 1080 0 R 232 1073 0 R 233 1060 0 R 234 1059 0 R 235 86 0 R 236 1055 0 R 237 1050 0 R 238 1049 0 R 239 1048 0 R 240 1045 0 R 241 1042 0 R 242 1041 0 R 243 87 0 R 244 1040 0 R 245 1032 0 R 246 1021 0 R 247 1018 0 R 248 1014 0 R 249 1013 0 R 250 1012 0 R 251 1009 0 R 252 1008 0 R 253 1005 0 R 254 1003 0 R 255 1002 0 R 256 1001 0 R 257 999 0 R 258 1029 0 R 259 88 0 R 260 998 0 R 261 89 0 R 262 974 0 R 263 966 0 R 264 958 0 R 265 953 0 R 266 952 0 R 267 951 0 R 268 950 0 R 269 90 0 R 270 944 0 R 271 941 0 R 272 939 0 R 273 938 0 R 274 937 0 R 275 932 0 R 276 929 0 R 277 926 0 R 278 924 0 R 279 923 0 R 280 922 0 R 281 91 0 R 282 919 0 R 283 916 0 R 284 915 0 R 285 913 0 R 286 911 0 R 287 908 0 R 288 907 0 R 289 900 0 R 290 899 0 R 291 92 0 R 292 893 0 R 293 891 0 R 294 890 0 R 295 889 0 R 296 888 0 R 297 887 0 R 298 886 0 R 299 885 0 R 300 883 0 R 301 882 0 R 302 879 0 R 303 876 0 R 304 875 0 R 305 873 0 R 306 872 0 R 307 871 0 R 308 870 0 R 309 868 0 R 310 93 0 R 311 865 0 R 312 864 0 R 313 863 0 R 314 862 0 R 315 861 0 R 316 860 0 R 317 859 0 R 318 858 0 R 319 857 0 R 320 852 0 R 321 851 0 R 322 848 0 R 323 845 0 R 324 844 0 R 325 843 0 R 326 840 0 R 327 839 0 R 328 837 0 R 329 834 0 R 330 833 0 R 331 832 0 R 332 830 0 R 333 94 0 R 334 820 0 R 335 817 0 R 336 814 0 R 337 810 0 R 338 807 0 R 339 803 0 R 340 800 0 R 341 796 0 R 342 790 0 R 343 787 0 R 344 783 0 R 345 95 0 R 346 777 0 R 347 775 0 R 348 771 0 R 349 769 0 R 350 769 0 R 351 765 0 R 352 761 0 R 353 757 0 R 354 753 0 R 355 749 0 R 356 743 0 R 357 739 0 R 358 735 0 R 359 729 0 R 360 724 0 R 361 721 0 R 362 717 0 R 363 711 0 R 364 708 0 R 365 704 0 R 366 701 0 R 367 697 0 R 368 694 0 R 369 690 0 R 370 684 0 R 371 681 0 R 372 677 0 R 373 96 0 R 374 671 0 R 375 668 0 R 376 664 0 R 377 661 0 R 378 657 0 R 379 654 0 R 380 654 0 R 381 650 0 R 382 647 0 R 383 647 0 R 384 643 0 R 385 640 0 R 386 636 0 R 387 633 0 R 388 629 0 R 389 625 0 R 390 621 0 R 391 618 0 R 392 614 0 R 393 611 0 R 394 607 0 R 395 604 0 R 396 600 0 R 397 597 0 R 398 593 0 R 399 590 0 R 400 586 0 R 401 583 0 R 402 579 0 R 403 576 0 R 404 97 0 R 405 572 0 R 406 569 0 R 407 565 0 R 408 559 0 R 409 557 0 R 410 553 0 R 411 550 0 R 412 546 0 R 413 540 0 R 414 538 0 R 415 538 0 R 416 534 0 R 417 532 0 R 418 528 0 R 419 522 0 R 420 519 0 R 421 515 0 R 422 512 0 R 423 508 0 R 424 505 0 R 425 501 0 R 426 495 0 R 427 489 0 R 428 483 0 R 429 480 0 R 430 476 0 R 431 98 0 R 432 470 0 R 433 467 0 R 434 463 0 R 435 460 0 R 436 456 0 R 437 450 0 R 438 447 0 R 439 443 0 R 440 441 0 R 441 441 0 R 442 437 0 R 443 434 0 R 444 430 0 R 445 428 0 R 446 428 0 R 447 424 0 R 448 421 0 R 449 417 0 R 450 414 0 R 451 410 0 R 452 407 0 R 453 407 0 R 454 403 0 R 455 400 0 R 456 396 0 R 457 393 0 R 458 389 0 R 459 386 0 R 460 382 0 R 461 379 0 R 462 375 0 R 463 372 0 R 464 99 0 R 465 368 0 R 466 365 0 R 467 361 0 R 468 358 0 R 469 354 0 R 470 351 0 R 471 347 0 R 472 344 0 R 473 340 0 R 474 338 0 R 475 334 0 R 476 331 0 R 477 327 0 R 478 324 0 R 479 320 0 R 480 317 0 R 481 313 0 R 482 310 0 R 483 310 0 R 484 306 0 R 485 303 0 R 486 299 0 R 487 296 0 R 488 292 0 R 489 289 0 R 490 285 0 R 491 282 0 R 492 278 0 R 493 274 0 R 494 270 0 R 495 100 0 R 496 267 0 R 497 263 0 R 498 260 0 R 499 256 0 R 500 253 0 R 501 249 0 R 502 246 0 R 503 242 0 R 504 239 0 R 505 235 0 R 506 232 0 R 507 228 0 R 508 225 0 R 509 221 0 R 510 215 0 R 511 210 0 R 512 205 0 R 513 202 0 R 514 198 0 R 515 195 0 R 516 191 0 R 517 188 0 R 518 184 0 R 519 181 0 R 520 177 0 R 521 174 0 R 522 170 0 R 523 167 0 R 524 101 0 R 525 163 0 R 526 160 0 R 527 156 0 R 528 151 0 R 529 145 0 R 530 142 0 R 531 138 0 R 532 135 0 R 533 131 0 R 534 128 0 R 535 124 0 R 536 121 0 R 537 117 0 R 538 115 0 R 539 115 0 R 540 111 0 R 541 108 0 R 542 102 0 R] - >> - /IDTree << - /Names [(Note 1) 4041 0 R (Note 2) 1994 0 R (Note 3) 1211 0 R (Note 4) 1102 0 R (Note 5) 1093 0 R (Note 6) 1026 0 R (U1x0y1) 2633 0 R (U1x1y1) 2631 0 R] - >> - /ParentTreeNextKey 543 ->> -endobj - -55 0 obj -[4305 0 R 4301 0 R 4304 0 R 4301 0 R 4303 0 R 4301 0 R 4302 0 R 4300 0 R 4298 0 R 4299 0 R 4298 0 R 4297 0 R 4290 0 R 4290 0 R 4296 0 R 4290 0 R 4290 0 R 4295 0 R 4290 0 R 4290 0 R 4294 0 R 4290 0 R 4290 0 R 4290 0 R 4293 0 R 4290 0 R 4290 0 R 4290 0 R 4292 0 R 4290 0 R 4290 0 R 4290 0 R 4290 0 R 4290 0 R 4290 0 R 4290 0 R 4291 0 R 4290 0 R 4290 0 R 4290 0 R] -endobj - -56 0 obj -[4289 0 R 4288 0 R 4287 0 R 4287 0 R 4284 0 R 4283 0 R 4283 0 R 4280 0 R 4279 0 R 4279 0 R 4276 0 R 4275 0 R 4275 0 R 4272 0 R 4271 0 R 4271 0 R 4268 0 R 4267 0 R 4267 0 R 4263 0 R 4262 0 R 4262 0 R 4258 0 R 4257 0 R 4257 0 R 4254 0 R 4253 0 R 4253 0 R 4250 0 R 4249 0 R 4249 0 R 4246 0 R 4245 0 R 4245 0 R 4241 0 R 4240 0 R 4240 0 R 4237 0 R 4236 0 R 4236 0 R 4233 0 R 4232 0 R 4232 0 R 4229 0 R 4228 0 R 4228 0 R 4224 0 R 4223 0 R 4223 0 R 4220 0 R 4219 0 R 4219 0 R 4216 0 R 4215 0 R 4215 0 R 4212 0 R 4211 0 R 4211 0 R 4207 0 R 4206 0 R 4206 0 R 4203 0 R 4202 0 R 4202 0 R 4199 0 R 4198 0 R 4198 0 R 4195 0 R 4194 0 R 4194 0 R 4191 0 R 4190 0 R 4190 0 R 4186 0 R 4185 0 R 4185 0 R 4182 0 R 4181 0 R 4181 0 R 4178 0 R 4177 0 R 4177 0 R 4172 0 R 4171 0 R 4171 0 R 4168 0 R 4167 0 R 4167 0 R 4164 0 R 4163 0 R 4163 0 R 4160 0 R 4159 0 R 4159 0 R] -endobj - -57 0 obj -[4156 0 R 4155 0 R 4155 0 R 4152 0 R 4151 0 R 4151 0 R 4147 0 R 4146 0 R 4146 0 R 4143 0 R 4142 0 R 4142 0 R 4139 0 R 4138 0 R 4138 0 R 4134 0 R 4133 0 R 4133 0 R 4129 0 R 4128 0 R 4128 0 R 4125 0 R 4124 0 R 4124 0 R 4121 0 R 4120 0 R 4120 0 R 4117 0 R 4116 0 R 4116 0 R 4113 0 R 4112 0 R 4112 0 R 4109 0 R 4108 0 R 4108 0 R 4104 0 R 4103 0 R 4103 0 R 4100 0 R 4099 0 R 4099 0 R 4096 0 R 4095 0 R 4095 0 R 4092 0 R 4091 0 R 4091 0 R 4088 0 R 4087 0 R 4087 0 R 4083 0 R 4082 0 R 4082 0 R 4079 0 R 4079 0 R] -endobj - -58 0 obj -[4075 0 R 4075 0 R 4069 0 R 4069 0 R 4069 0 R 4074 0 R 4069 0 R 4069 0 R 4073 0 R 4069 0 R 4069 0 R 4069 0 R 4072 0 R 4069 0 R 4069 0 R 4069 0 R 4071 0 R 4069 0 R 4069 0 R 4069 0 R 4069 0 R 4069 0 R 4070 0 R 4069 0 R 4069 0 R 4069 0 R 4069 0 R 4069 0 R 4068 0 R 4068 0 R 4067 0 R 4067 0 R 4067 0 R 4066 0 R 4065 0 R 4063 0 R 4064 0 R 4063 0 R 4063 0 R 4063 0 R 4063 0 R 4063 0 R 4061 0 R 4060 0 R 4058 0 R 4059 0 R 4058 0 R 4058 0 R 4058 0 R 4058 0 R 4058 0 R 4053 0 R 4053 0 R 4055 0 R 4053 0 R 4053 0 R 4053 0 R 4053 0 R 4054 0 R 4053 0 R 4053 0 R 4053 0 R 4053 0 R 4053 0 R 4053 0 R 4052 0 R 4052 0 R 4051 0 R 4051 0 R 4050 0 R 4050 0 R 4049 0 R 4038 0 R 4038 0 R 4038 0 R 4048 0 R 4038 0 R 4038 0 R 4038 0 R] -endobj - -59 0 obj -[4038 0 R 4038 0 R 4047 0 R 4038 0 R 4038 0 R 4040 0 R 4038 0 R 4038 0 R 4038 0 R 4039 0 R 4038 0 R 4038 0 R 4037 0 R 4029 0 R 4036 0 R 4029 0 R 4029 0 R 4029 0 R 4029 0 R 4035 0 R 4029 0 R 4034 0 R 4029 0 R 4029 0 R 4029 0 R 4029 0 R 4029 0 R 4029 0 R 4029 0 R 4031 0 R 4029 0 R 4029 0 R 4030 0 R 4029 0 R 4029 0 R 4029 0 R 4026 0 R 4026 0 R 4028 0 R 4026 0 R 4027 0 R 4026 0 R 4026 0 R 4025 0 R 4025 0 R 4018 0 R 4018 0 R 4024 0 R 4018 0 R 4023 0 R 4018 0 R 4018 0 R 4018 0 R 4018 0 R 4022 0 R 4018 0 R 4018 0 R 4018 0 R 4018 0 R 4021 0 R 4018 0 R 4018 0 R 4018 0 R 4018 0 R 4018 0 R 4020 0 R 4018 0 R 4018 0 R 4018 0 R 4018 0 R 4018 0 R 4018 0 R 4018 0 R 4019 0 R 4018 0 R 4018 0 R 4018 0 R 4017 0 R 4017 0 R 4017 0 R 4017 0 R 4017 0 R 4017 0 R 4017 0 R 4017 0 R 4017 0 R 4016 0 R 4016 0 R 4014 0 R 4014 0 R 4014 0 R 4014 0 R 4044 0 R 4041 0 R] -endobj - -60 0 obj -[4014 0 R 4014 0 R 4015 0 R 4014 0 R 4014 0 R 4014 0 R 4014 0 R 4014 0 R 4012 0 R 4012 0 R 4012 0 R 4012 0 R 4012 0 R 4013 0 R 4012 0 R 4012 0 R 4012 0 R 4012 0 R 4012 0 R 4012 0 R 4012 0 R 4012 0 R 4012 0 R 4012 0 R 4011 0 R 4011 0 R 4002 0 R 4010 0 R 4002 0 R 4002 0 R 4009 0 R 4002 0 R 4008 0 R 4008 0 R 4002 0 R 4002 0 R 4007 0 R 4002 0 R 4006 0 R 4002 0 R 4002 0 R 4005 0 R 4002 0 R 4002 0 R 4004 0 R 4002 0 R 4003 0 R 4002 0 R 4002 0 R 4002 0 R 4002 0 R 4002 0 R 4002 0 R 4002 0 R 4002 0 R 4002 0 R 4002 0 R 4001 0 R 3997 0 R 4000 0 R 3997 0 R 3999 0 R 3997 0 R 3997 0 R 3997 0 R 3998 0 R 3997 0 R 3997 0 R 3997 0 R 3997 0 R 3995 0 R 3992 0 R 3994 0 R 3992 0 R 3993 0 R 3992 0 R 3992 0 R 3992 0 R 3992 0 R 3992 0 R 3990 0 R 3985 0 R 3989 0 R 3985 0 R 3988 0 R 3985 0 R 3985 0 R 3985 0 R 3985 0 R 3987 0 R 3985 0 R 3986 0 R 3985 0 R 3985 0 R 3983 0 R 3980 0 R 3982 0 R 3980 0 R 3981 0 R 3980 0 R 3980 0 R 3980 0 R 3980 0 R 3980 0 R 3980 0 R] -endobj - -61 0 obj -[3977 0 R 3977 0 R 3975 0 R 3975 0 R 3975 0 R 3976 0 R 3975 0 R 3975 0 R 3974 0 R 3974 0 R 3966 0 R 3966 0 R 3973 0 R 3966 0 R 3972 0 R 3966 0 R 3966 0 R 3971 0 R 3971 0 R 3971 0 R 3971 0 R 3971 0 R 3966 0 R 3966 0 R 3970 0 R 3966 0 R 3969 0 R 3966 0 R 3968 0 R 3966 0 R 3967 0 R 3966 0 R 3966 0 R 3965 0 R 3965 0 R 3965 0 R 3965 0 R 3965 0 R 3965 0 R 3965 0 R 3963 0 R 3963 0 R 3963 0 R 3963 0 R 3964 0 R 3963 0 R 3963 0 R 3963 0 R 3963 0 R 3962 0 R 3954 0 R 3954 0 R 3961 0 R 3954 0 R 3954 0 R 3954 0 R 3954 0 R 3960 0 R 3954 0 R 3954 0 R 3959 0 R 3959 0 R 3959 0 R 3959 0 R 3959 0 R 3959 0 R 3959 0 R 3954 0 R 3958 0 R 3954 0 R 3954 0 R 3954 0 R 3957 0 R 3957 0 R 3957 0 R 3957 0 R 3954 0 R 3956 0 R 3956 0 R 3956 0 R 3956 0 R 3956 0 R 3956 0 R 3956 0 R 3956 0 R 3954 0 R 3954 0 R 3955 0 R 3955 0 R 3955 0 R 3955 0 R 3955 0 R 3955 0 R 3955 0 R 3955 0 R 3955 0 R 3955 0 R 3955 0 R 3955 0 R 3955 0 R 3955 0 R 3954 0 R 3954 0 R 3953 0 R 3945 0 R 3945 0 R 3952 0 R 3945 0 R 3951 0 R 3945 0 R 3945 0 R 3945 0 R 3945 0 R 3945 0 R 3950 0 R 3945 0 R 3949 0 R 3949 0 R 3949 0 R 3949 0 R 3949 0 R 3949 0 R 3945 0 R 3948 0 R 3948 0 R 3948 0 R 3948 0 R 3948 0 R 3948 0 R 3945 0 R 3945 0 R 3945 0 R 3945 0 R 3947 0 R 3945 0 R 3945 0 R 3946 0 R 3945 0 R 3945 0 R 3944 0 R 3944 0 R 3944 0 R 3944 0 R 3944 0 R 3944 0 R 3944 0 R 3944 0 R 3944 0 R 3944 0 R 3944 0 R 3944 0 R 3944 0 R 3944 0 R 3936 0 R 3943 0 R 3936 0 R 3942 0 R 3936 0 R 3936 0 R 3936 0 R 3936 0 R 3941 0 R 3936 0 R 3936 0 R 3936 0 R 3940 0 R 3936 0 R 3939 0 R 3936 0 R 3936 0 R 3936 0 R 3938 0 R 3936 0 R 3936 0 R 3936 0 R 3937 0 R 3936 0 R 3936 0 R 3936 0 R 3935 0 R 3935 0 R 3931 0 R 3934 0 R 3931 0 R 3931 0 R 3933 0 R 3931 0 R 3932 0 R 3931 0 R 3931 0 R 3931 0 R 3930 0 R 3930 0 R 3930 0 R 3930 0 R 3930 0 R 3930 0 R 3930 0 R 3929 0 R 3929 0 R] -endobj - -62 0 obj -[3929 0 R 3929 0 R 3928 0 R 3919 0 R 3919 0 R 3919 0 R 3927 0 R 3919 0 R 3919 0 R 3919 0 R 3919 0 R 3919 0 R 3926 0 R 3919 0 R 3919 0 R 3919 0 R 3925 0 R 3925 0 R 3925 0 R 3925 0 R 3925 0 R 3925 0 R 3925 0 R 3919 0 R 3919 0 R 3924 0 R 3924 0 R 3924 0 R 3924 0 R 3924 0 R 3924 0 R 3924 0 R 3924 0 R 3919 0 R 3919 0 R 3919 0 R 3923 0 R 3923 0 R 3923 0 R 3923 0 R 3923 0 R 3923 0 R 3923 0 R 3923 0 R 3923 0 R 3923 0 R 3923 0 R 3923 0 R 3923 0 R 3923 0 R 3919 0 R 3922 0 R 3922 0 R 3922 0 R 3922 0 R 3922 0 R 3922 0 R 3922 0 R 3922 0 R 3919 0 R 3921 0 R 3919 0 R 3920 0 R 3920 0 R 3920 0 R 3920 0 R 3920 0 R 3920 0 R 3920 0 R 3920 0 R 3919 0 R 3918 0 R 3902 0 R 3917 0 R 3902 0 R 3902 0 R 3916 0 R 3916 0 R 3916 0 R 3916 0 R 3916 0 R 3916 0 R 3916 0 R 3916 0 R 3916 0 R 3916 0 R 3916 0 R 3916 0 R 3916 0 R 3916 0 R 3916 0 R 3902 0 R 3902 0 R 3915 0 R 3902 0 R 3902 0 R 3902 0 R 3902 0 R 3914 0 R 3902 0 R 3902 0 R 3913 0 R 3902 0 R 3902 0 R 3912 0 R 3902 0 R 3911 0 R 3902 0 R 3910 0 R 3902 0 R 3909 0 R 3902 0 R 3902 0 R 3908 0 R 3902 0 R 3907 0 R 3902 0 R 3902 0 R 3902 0 R 3906 0 R 3902 0 R 3902 0 R 3902 0 R 3905 0 R 3902 0 R 3904 0 R 3902 0 R 3902 0 R 3902 0 R 3902 0 R 3902 0 R 3903 0 R 3902 0 R 3902 0 R 3901 0 R 3901 0 R 3897 0 R 3897 0 R 3900 0 R 3897 0 R 3897 0 R 3899 0 R 3897 0 R 3897 0 R 3897 0 R 3898 0 R 3897 0 R 3896 0 R 3895 0 R 3894 0 R 3894 0 R 3894 0 R 3894 0 R 3894 0 R 3892 0 R 3891 0 R 3890 0 R 3890 0 R 3890 0 R 3890 0 R 3887 0 R 3887 0 R 3887 0 R 3887 0 R 3887 0 R 3887 0 R 3887 0 R 3885 0 R 3885 0 R 3885 0 R 3885 0 R 3885 0 R 3886 0 R 3885 0 R] -endobj - -63 0 obj -[3884 0 R 3884 0 R 3880 0 R 3883 0 R 3880 0 R 3880 0 R 3880 0 R 3882 0 R 3880 0 R 3880 0 R 3881 0 R 3880 0 R 3880 0 R 3880 0 R 3880 0 R 3880 0 R 3880 0 R 3880 0 R 3880 0 R 3879 0 R 3879 0 R 3878 0 R 3875 0 R 3875 0 R 3875 0 R 3875 0 R 3877 0 R 3877 0 R 3877 0 R 3877 0 R 3877 0 R 3877 0 R 3877 0 R 3877 0 R 3877 0 R 3875 0 R 3875 0 R 3875 0 R 3875 0 R 3876 0 R 3875 0 R 3875 0 R 3874 0 R 3874 0 R 3863 0 R 3873 0 R 3873 0 R 3873 0 R 3873 0 R 3873 0 R 3873 0 R 3863 0 R 3872 0 R 3872 0 R 3872 0 R 3872 0 R 3872 0 R 3872 0 R 3872 0 R 3872 0 R 3872 0 R 3863 0 R 3871 0 R 3863 0 R 3863 0 R 3870 0 R 3863 0 R 3869 0 R 3869 0 R 3869 0 R 3863 0 R 3868 0 R 3868 0 R 3868 0 R 3868 0 R 3868 0 R 3868 0 R 3868 0 R 3868 0 R 3868 0 R 3868 0 R 3868 0 R 3868 0 R 3863 0 R 3867 0 R 3863 0 R 3863 0 R 3866 0 R 3863 0 R 3865 0 R 3865 0 R 3865 0 R 3865 0 R 3865 0 R 3865 0 R 3865 0 R 3863 0 R 3863 0 R 3864 0 R 3863 0 R 3862 0 R 3861 0 R 3860 0 R 3858 0 R 3857 0 R 3854 0 R 3856 0 R 3856 0 R 3854 0 R 3855 0 R 3854 0 R 3852 0 R 3851 0 R 3848 0 R 3850 0 R 3850 0 R 3850 0 R 3850 0 R 3848 0 R 3849 0 R 3849 0 R 3849 0 R 3849 0 R 3849 0 R 3849 0 R 3848 0 R 3848 0 R 3848 0 R 3840 0 R 3845 0 R 3840 0 R 3840 0 R 3840 0 R 3840 0 R 3844 0 R 3840 0 R 3843 0 R 3843 0 R 3840 0 R 3842 0 R 3842 0 R 3840 0 R 3840 0 R 3840 0 R 3841 0 R 3840 0 R 3840 0 R 3839 0 R 3838 0 R 3838 0 R 3838 0 R 3835 0 R 3837 0 R 3835 0 R 3836 0 R 3835 0 R 3834 0 R 3834 0 R 3834 0 R 3834 0 R 3834 0 R 3834 0 R 3834 0 R 3834 0 R 3832 0 R 3833 0 R 3833 0 R 3833 0 R 3833 0 R 3833 0 R 3832 0 R] -endobj - -64 0 obj -[3831 0 R 3830 0 R 3830 0 R 3830 0 R 3829 0 R 3827 0 R 3826 0 R 3826 0 R 3826 0 R 3826 0 R 3825 0 R 3821 0 R 3822 0 R 3822 0 R 3822 0 R 3822 0 R 3822 0 R 3822 0 R 3822 0 R 3821 0 R 3817 0 R 3819 0 R 3817 0 R 3818 0 R 3818 0 R 3817 0 R 3817 0 R 3816 0 R 3816 0 R 3816 0 R 3812 0 R 3815 0 R 3815 0 R 3812 0 R 3814 0 R 3814 0 R 3812 0 R 3813 0 R 3813 0 R 3813 0 R 3812 0 R 3811 0 R 3811 0 R 3809 0 R 3807 0 R 3807 0 R 3807 0 R 3807 0 R 3807 0 R 3805 0 R 3803 0 R 3803 0 R 3801 0 R 3799 0 R 3799 0 R 3797 0 R 3797 0 R 3795 0 R 3793 0 R 3791 0 R 3789 0 R 3789 0 R 3789 0 R 3789 0 R 3789 0 R 3787 0 R 3785 0 R 3785 0 R 3785 0 R 3785 0 R 3785 0 R 3785 0 R 3785 0 R 3785 0 R 3785 0 R 3785 0 R 3785 0 R 3785 0 R 3765 0 R 3781 0 R 3781 0 R 3781 0 R 3781 0 R 3765 0 R 3780 0 R 3765 0 R 3765 0 R 3779 0 R 3779 0 R 3765 0 R 3778 0 R 3778 0 R 3778 0 R 3778 0 R 3778 0 R 3765 0 R 3777 0 R 3777 0 R 3777 0 R 3777 0 R 3777 0 R 3765 0 R 3776 0 R 3765 0 R 3775 0 R 3765 0 R 3774 0 R 3765 0 R 3773 0 R 3773 0 R 3773 0 R 3773 0 R 3773 0 R 3765 0 R 3772 0 R 3772 0 R 3765 0 R 3765 0 R 3771 0 R 3771 0 R 3771 0 R 3771 0 R 3771 0 R 3771 0 R 3771 0 R 3771 0 R 3771 0 R 3771 0 R 3771 0 R 3771 0 R 3771 0 R 3771 0 R 3771 0 R 3771 0 R 3771 0 R 3771 0 R 3771 0 R 3771 0 R 3771 0 R 3771 0 R 3765 0 R 3770 0 R 3770 0 R 3765 0 R 3765 0 R 3769 0 R 3769 0 R 3769 0 R 3769 0 R 3769 0 R 3769 0 R 3769 0 R 3769 0 R 3769 0 R 3769 0 R 3765 0 R 3768 0 R 3765 0 R 3767 0 R 3767 0 R 3767 0 R 3767 0 R 3767 0 R 3765 0 R 3766 0 R 3766 0 R 3765 0 R 3764 0 R 3764 0 R 3764 0 R 3763 0 R 3762 0 R 3762 0 R 3762 0 R 3762 0 R 3762 0 R 3762 0 R 3762 0 R 3762 0 R 3762 0 R 3762 0 R 3762 0 R 3762 0 R 3762 0 R 3762 0 R 3762 0 R 3762 0 R 3762 0 R 3762 0 R 3762 0 R 3761 0 R 3759 0 R 3758 0 R 3758 0 R 3757 0 R 3757 0 R 3756 0 R 3756 0 R 3755 0 R 3754 0 R 3753 0 R 3752 0 R 3752 0 R 3751 0 R 3751 0 R 3749 0 R 3749 0 R 3749 0 R 3745 0 R 3748 0 R 3745 0 R 3747 0 R 3745 0 R 3746 0 R 3746 0 R 3746 0 R 3746 0 R 3746 0 R 3746 0 R 3746 0 R 3745 0 R 3744 0 R 3744 0 R 3744 0 R 3744 0 R 3744 0 R 3744 0 R 3744 0 R 3744 0 R 3744 0 R 3744 0 R 3744 0 R 3744 0 R 3744 0 R 3744 0 R 3744 0 R 3744 0 R 3744 0 R 3744 0 R 3744 0 R 3744 0 R 3739 0 R 3742 0 R 3742 0 R 3739 0 R 3741 0 R 3739 0 R 3739 0 R 3740 0 R 3740 0 R 3739 0 R 3738 0 R 3738 0 R 3738 0 R 3735 0 R 3737 0 R 3737 0 R 3735 0 R 3736 0 R 3736 0 R 3735 0 R 3734 0 R 3734 0 R 3732 0 R 3730 0 R 3730 0 R 3728 0 R 3726 0 R 3726 0 R 3724 0 R 3724 0 R 3722 0 R 3720 0 R 3720 0 R 3720 0 R 3720 0 R 3720 0 R 3718 0 R 3716 0 R 3716 0 R 3716 0 R 3716 0 R 3716 0 R 3716 0 R 3716 0 R 3716 0 R 3716 0 R 3705 0 R 3712 0 R 3705 0 R 3711 0 R 3705 0 R 3710 0 R 3705 0 R 3705 0 R 3709 0 R 3705 0 R 3708 0 R 3705 0 R 3705 0 R 3707 0 R 3707 0 R 3707 0 R 3707 0 R 3707 0 R 3707 0 R 3707 0 R 3707 0 R 3707 0 R 3707 0 R 3707 0 R 3707 0 R 3707 0 R 3705 0 R 3705 0 R 3706 0 R 3706 0 R 3705 0 R 3704 0 R 3704 0 R 3703 0 R 3703 0 R 3702 0 R 3702 0 R 3702 0 R 3701 0 R 3701 0 R 3701 0 R 3700 0 R 3699 0 R 3698 0 R 3697 0 R 3696 0 R 3695 0 R 3694 0 R 3693 0 R 3692 0 R 3692 0 R 3691 0 R 3691 0 R 3690 0 R 3690 0 R 3689 0 R 3689 0 R] -endobj - -65 0 obj -[3687 0 R 3687 0 R 3683 0 R 3686 0 R 3683 0 R 3685 0 R 3683 0 R 3683 0 R 3683 0 R 3684 0 R 3683 0 R 3683 0 R 3683 0 R 3682 0 R 3678 0 R 3681 0 R 3678 0 R 3678 0 R 3680 0 R 3680 0 R 3680 0 R 3680 0 R 3680 0 R 3680 0 R 3680 0 R 3680 0 R 3680 0 R 3678 0 R 3679 0 R 3679 0 R 3679 0 R 3679 0 R 3678 0 R 3676 0 R 3672 0 R 3675 0 R 3675 0 R 3672 0 R 3672 0 R 3674 0 R 3674 0 R 3674 0 R 3674 0 R 3674 0 R 3674 0 R 3674 0 R 3674 0 R 3674 0 R 3674 0 R 3674 0 R 3674 0 R 3674 0 R 3672 0 R 3673 0 R 3673 0 R 3673 0 R 3673 0 R 3673 0 R 3673 0 R 3672 0 R 3666 0 R 3666 0 R 3666 0 R 3669 0 R 3669 0 R 3666 0 R 3668 0 R 3668 0 R 3666 0 R 3667 0 R 3667 0 R 3667 0 R 3666 0 R 3665 0 R 3665 0 R 3665 0 R 3662 0 R 3664 0 R 3664 0 R 3662 0 R 3663 0 R 3663 0 R 3663 0 R 3662 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3661 0 R 3658 0 R 3660 0 R 3660 0 R 3660 0 R 3660 0 R 3658 0 R 3659 0 R 3659 0 R 3659 0 R 3659 0 R 3659 0 R 3658 0 R 3657 0 R 3656 0 R 3656 0 R 3656 0 R 3655 0 R 3653 0 R 3652 0 R 3652 0 R 3652 0 R 3652 0 R 3652 0 R 3651 0 R 3646 0 R 3647 0 R 3647 0 R 3647 0 R 3647 0 R 3647 0 R 3647 0 R 3646 0 R 3646 0 R 3646 0 R 3646 0 R 3645 0 R 3644 0 R 3644 0 R 3644 0 R 3643 0 R 3642 0 R 3642 0 R 3641 0 R 3641 0 R 3640 0 R 3639 0 R 3638 0 R 3638 0 R 3632 0 R 3636 0 R 3636 0 R 3632 0 R 3635 0 R 3635 0 R 3635 0 R 3632 0 R 3634 0 R 3634 0 R 3632 0 R 3633 0 R 3633 0 R 3633 0 R 3632 0 R 3631 0 R 3631 0 R 3631 0 R 3629 0 R 3630 0 R 3630 0 R 3629 0 R 3628 0 R 3628 0 R 3626 0 R 3624 0 R 3624 0 R 3622 0 R 3620 0 R 3620 0 R 3618 0 R 3616 0 R 3616 0 R 3616 0 R 3614 0 R 3614 0 R 3612 0 R 3610 0 R 3608 0 R 3606 0 R 3606 0 R 3606 0 R 3606 0 R 3606 0 R 3604 0 R 3602 0 R 3602 0 R 3602 0 R 3602 0 R 3602 0 R 3602 0 R 3602 0 R 3602 0 R 3602 0 R 3602 0 R 3602 0 R 3602 0 R 3601 0 R 3601 0 R 3601 0 R 3601 0 R 3601 0 R 3601 0 R 3601 0 R 3601 0 R 3601 0 R 3601 0 R 3601 0 R 3601 0 R 3601 0 R 3601 0 R 3601 0 R 3595 0 R 3597 0 R 3597 0 R 3595 0 R 3596 0 R 3596 0 R 3596 0 R 3595 0 R 3595 0 R] -endobj - -66 0 obj -[3594 0 R 3593 0 R 3593 0 R 3592 0 R 3592 0 R 3592 0 R 3591 0 R 3591 0 R 3591 0 R 3591 0 R 3590 0 R 3589 0 R 3589 0 R 3588 0 R 3588 0 R 3587 0 R 3587 0 R 3586 0 R 3586 0 R 3585 0 R 3585 0 R 3584 0 R 3584 0 R 3578 0 R 3583 0 R 3582 0 R 3581 0 R 3581 0 R 3580 0 R 3580 0 R 3579 0 R 3579 0 R 3579 0 R 3577 0 R 3577 0 R 3577 0 R 3576 0 R 3575 0 R 3574 0 R 3573 0 R 3573 0 R 3572 0 R 3571 0 R 3571 0 R 3571 0 R 3571 0 R 3571 0 R 3571 0 R 3571 0 R 3571 0 R 3571 0 R 3571 0 R 3571 0 R 3571 0 R 3571 0 R 3571 0 R 3571 0 R 3571 0 R 3571 0 R 3570 0 R 3567 0 R 3568 0 R 3568 0 R 3567 0 R 3567 0 R 3566 0 R 3566 0 R 3566 0 R 3563 0 R 3565 0 R 3565 0 R 3565 0 R 3565 0 R 3565 0 R 3565 0 R 3563 0 R 3564 0 R 3564 0 R 3564 0 R 3563 0 R 3562 0 R 3562 0 R 3562 0 R 3560 0 R 3558 0 R 3556 0 R 3554 0 R 3554 0 R 3552 0 R 3552 0 R 3552 0 R 3550 0 R 3548 0 R 3546 0 R 3544 0 R 3544 0 R 3544 0 R 3544 0 R 3544 0 R 3544 0 R 3544 0 R 3544 0 R 3544 0 R 3544 0 R 3544 0 R 3544 0 R 3543 0 R 3543 0 R 3543 0 R 3543 0 R 3543 0 R 3543 0 R 3543 0 R 3543 0 R 3543 0 R 3543 0 R 3543 0 R 3543 0 R 3542 0 R 3542 0 R 3542 0 R 3542 0 R 3542 0 R 3542 0 R 3542 0 R 3538 0 R 3538 0 R 3538 0 R 3537 0 R 3536 0 R 3535 0 R 3534 0 R 3534 0 R 3533 0 R 3532 0 R 3532 0 R 3532 0 R 3532 0 R 3532 0 R 3532 0 R 3532 0 R 3532 0 R 3532 0 R 3532 0 R 3532 0 R 3532 0 R 3532 0 R 3532 0 R 3532 0 R 3532 0 R 3531 0 R 3528 0 R 3529 0 R 3528 0 R 3527 0 R 3527 0 R 3527 0 R 3523 0 R 3526 0 R 3523 0 R 3525 0 R 3523 0 R 3524 0 R 3524 0 R 3524 0 R 3524 0 R 3524 0 R 3524 0 R 3524 0 R 3523 0 R 3522 0 R 3522 0 R 3522 0 R 3522 0 R 3522 0 R 3522 0 R 3522 0 R 3522 0 R 3522 0 R 3522 0 R 3522 0 R 3522 0 R 3522 0 R 3522 0 R 3522 0 R 3522 0 R 3522 0 R 3522 0 R 3522 0 R 3522 0 R 3513 0 R 3520 0 R 3513 0 R 3519 0 R 3519 0 R 3519 0 R 3513 0 R 3513 0 R 3518 0 R 3513 0 R 3517 0 R 3517 0 R 3513 0 R 3516 0 R 3513 0 R 3513 0 R 3513 0 R 3513 0 R 3515 0 R 3513 0 R 3514 0 R 3513 0 R 3513 0 R 3506 0 R 3512 0 R 3506 0 R 3511 0 R 3511 0 R 3511 0 R 3511 0 R 3511 0 R 3511 0 R 3511 0 R 3506 0 R 3510 0 R 3506 0 R 3509 0 R 3506 0 R 3506 0 R 3506 0 R 3506 0 R 3508 0 R 3506 0 R 3506 0 R 3507 0 R 3506 0 R 3505 0 R 3505 0 R 3504 0 R 3502 0 R 3502 0 R 3502 0 R] -endobj - -67 0 obj -[3502 0 R 3502 0 R 3502 0 R 3502 0 R 3502 0 R 3502 0 R 3503 0 R 3502 0 R 3502 0 R 3502 0 R 3502 0 R 3501 0 R 3501 0 R 3498 0 R 3498 0 R 3500 0 R 3498 0 R 3499 0 R 3498 0 R 3498 0 R 3498 0 R 3498 0 R 3497 0 R 3497 0 R 3497 0 R 3494 0 R 3496 0 R 3496 0 R 3496 0 R 3496 0 R 3496 0 R 3494 0 R 3495 0 R 3494 0 R 3494 0 R 3493 0 R 3493 0 R 3493 0 R 3493 0 R 3493 0 R 3493 0 R 3493 0 R 3493 0 R 3493 0 R 3493 0 R 3493 0 R 3489 0 R 3492 0 R 3492 0 R 3492 0 R 3489 0 R 3491 0 R 3491 0 R 3491 0 R 3491 0 R 3491 0 R 3491 0 R 3491 0 R 3491 0 R 3489 0 R 3490 0 R 3490 0 R 3489 0 R 3489 0 R 3488 0 R 3487 0 R 3487 0 R 3487 0 R 3487 0 R 3485 0 R 3486 0 R 3486 0 R 3486 0 R 3486 0 R 3486 0 R 3486 0 R 3485 0 R 3483 0 R 3482 0 R 3482 0 R 3482 0 R 3482 0 R 3482 0 R 3482 0 R 3480 0 R 3481 0 R 3481 0 R 3481 0 R 3481 0 R 3481 0 R 3481 0 R 3480 0 R 3478 0 R 3477 0 R 3477 0 R 3477 0 R 3475 0 R 3476 0 R 3476 0 R 3476 0 R 3476 0 R 3476 0 R 3476 0 R 3475 0 R 3473 0 R 3472 0 R 3472 0 R 3472 0 R 3472 0 R 3472 0 R 3472 0 R 3471 0 R 3462 0 R 3467 0 R 3462 0 R 3466 0 R 3462 0 R 3462 0 R 3465 0 R 3465 0 R 3462 0 R 3462 0 R 3462 0 R 3464 0 R 3464 0 R 3464 0 R 3464 0 R 3464 0 R 3464 0 R 3462 0 R 3463 0 R 3463 0 R 3463 0 R 3463 0 R 3463 0 R 3463 0 R 3462 0 R 3461 0 R 3461 0 R 3461 0 R 3457 0 R 3460 0 R 3457 0 R 3459 0 R 3457 0 R 3458 0 R 3457 0 R 3456 0 R 3454 0 R 3452 0 R 3452 0 R 3452 0 R 3452 0 R 3452 0 R 3450 0 R 3448 0 R 3446 0 R 3444 0 R 3444 0 R 3442 0 R 3440 0 R 3438 0 R 3436 0 R 3434 0 R 3432 0 R 3430 0 R 3430 0 R 3430 0 R 3430 0 R 3428 0 R 3426 0 R 3424 0 R 3424 0 R 3424 0 R 3424 0 R 3424 0 R 3424 0 R 3424 0 R 3424 0 R 3422 0 R 3420 0 R 3418 0 R 3416 0 R 3416 0 R 3416 0 R 3416 0 R 3416 0 R 3416 0 R 3416 0 R 3414 0 R 3412 0 R 3410 0 R 3410 0 R 3410 0 R 3410 0 R 3410 0 R 3408 0 R 3406 0 R 3404 0 R 3402 0 R 3402 0 R 3402 0 R 3402 0 R 3402 0 R 3402 0 R 3402 0 R 3402 0 R 3402 0 R 3402 0 R 3402 0 R 3402 0 R 3402 0 R 3402 0 R 3402 0 R 3402 0 R 3402 0 R 3395 0 R 3399 0 R 3399 0 R 3399 0 R 3399 0 R 3395 0 R 3398 0 R 3398 0 R 3398 0 R 3398 0 R 3398 0 R 3398 0 R 3395 0 R 3397 0 R 3397 0 R 3397 0 R 3397 0 R 3397 0 R 3397 0 R 3395 0 R 3396 0 R 3396 0 R 3396 0 R 3396 0 R 3396 0 R 3396 0 R 3395 0 R 3389 0 R 3393 0 R 3393 0 R 3393 0 R 3393 0 R 3393 0 R 3393 0 R 3389 0 R 3392 0 R 3392 0 R 3389 0 R 3389 0 R 3391 0 R 3389 0 R 3390 0 R 3390 0 R 3389 0 R 3389 0 R 3389 0 R 3389 0 R 3388 0 R 3388 0 R 3384 0 R 3384 0 R] -endobj - -68 0 obj -[3384 0 R 3384 0 R 3384 0 R 3384 0 R 3384 0 R 3387 0 R 3384 0 R 3384 0 R 3386 0 R 3386 0 R 3386 0 R 3384 0 R 3385 0 R 3384 0 R 3383 0 R 3383 0 R 3383 0 R 3383 0 R 3383 0 R 3383 0 R 3383 0 R 3383 0 R 3383 0 R 3383 0 R 3383 0 R 3383 0 R 3383 0 R 3383 0 R 3383 0 R 3383 0 R 3380 0 R 3382 0 R 3382 0 R 3382 0 R 3382 0 R 3380 0 R 3381 0 R 3380 0 R 3380 0 R 3380 0 R 3380 0 R 3379 0 R 3379 0 R 3379 0 R 3377 0 R 3378 0 R 3377 0 R 3376 0 R 3376 0 R 3376 0 R 3376 0 R 3376 0 R 3376 0 R 3376 0 R 3376 0 R 3375 0 R 3369 0 R 3369 0 R 3373 0 R 3369 0 R 3372 0 R 3372 0 R 3369 0 R 3371 0 R 3371 0 R 3371 0 R 3371 0 R 3369 0 R 3370 0 R 3369 0 R 3369 0 R 3369 0 R 3368 0 R 3368 0 R 3368 0 R 3365 0 R 3367 0 R 3367 0 R 3367 0 R 3365 0 R 3366 0 R 3366 0 R 3366 0 R 3366 0 R 3366 0 R 3366 0 R 3365 0 R 3364 0 R 3364 0 R 3364 0 R 3364 0 R 3364 0 R 3364 0 R 3364 0 R 3364 0 R 3364 0 R 3364 0 R 3364 0 R 3364 0 R 3364 0 R 3364 0 R 3364 0 R 3364 0 R 3364 0 R 3364 0 R 3364 0 R 3364 0 R 3364 0 R 3364 0 R 3364 0 R 3364 0 R 3364 0 R 3364 0 R 3364 0 R 3364 0 R 3364 0 R 3364 0 R 3364 0 R 3364 0 R 3364 0 R 3360 0 R 3362 0 R 3362 0 R 3362 0 R 3360 0 R 3360 0 R 3360 0 R 3360 0 R 3360 0 R 3361 0 R 3360 0 R 3341 0 R 3359 0 R 3341 0 R 3358 0 R 3341 0 R 3357 0 R 3341 0 R 3341 0 R 3356 0 R 3341 0 R 3355 0 R 3355 0 R 3355 0 R 3355 0 R 3355 0 R 3355 0 R 3341 0 R 3354 0 R 3341 0 R 3353 0 R 3353 0 R 3353 0 R 3353 0 R 3341 0 R 3352 0 R 3341 0 R 3351 0 R 3341 0 R 3350 0 R 3341 0 R 3349 0 R 3349 0 R 3349 0 R 3349 0 R 3341 0 R 3348 0 R 3348 0 R 3348 0 R 3348 0 R 3348 0 R 3348 0 R 3341 0 R 3347 0 R 3341 0 R 3346 0 R 3341 0 R 3345 0 R 3345 0 R 3345 0 R 3345 0 R 3341 0 R 3344 0 R 3341 0 R 3343 0 R 3341 0 R 3341 0 R 3342 0 R 3341 0 R 3341 0 R 3341 0 R 3340 0 R 3340 0 R 3336 0 R 3339 0 R 3336 0 R 3336 0 R 3336 0 R 3338 0 R 3336 0 R 3336 0 R 3337 0 R 3336 0 R 3336 0 R] -endobj - -69 0 obj -[3335 0 R 3333 0 R 3334 0 R 3333 0 R 3333 0 R 3333 0 R 3333 0 R 3332 0 R 3332 0 R 3332 0 R 3331 0 R 3330 0 R 3330 0 R 3330 0 R 3330 0 R 3330 0 R 3330 0 R 3330 0 R 3330 0 R 3330 0 R 3330 0 R 3330 0 R 3330 0 R 3330 0 R 3330 0 R 3330 0 R 3330 0 R 3330 0 R 3330 0 R 3330 0 R 3330 0 R 3330 0 R 3328 0 R 3329 0 R 3329 0 R 3329 0 R 3329 0 R 3329 0 R 3328 0 R 3327 0 R 3326 0 R 3326 0 R 3326 0 R 3326 0 R 3326 0 R 3326 0 R 3326 0 R 3326 0 R 3325 0 R 3323 0 R 3322 0 R 3322 0 R 3322 0 R 3322 0 R 3322 0 R 3322 0 R 3322 0 R 3322 0 R 3322 0 R 3322 0 R 3321 0 R 3321 0 R 3321 0 R 3313 0 R 3313 0 R 3317 0 R 3313 0 R 3316 0 R 3316 0 R 3316 0 R 3316 0 R 3313 0 R 3313 0 R 3315 0 R 3313 0 R 3314 0 R 3314 0 R 3314 0 R 3314 0 R 3313 0 R 3312 0 R 3312 0 R 3312 0 R 3307 0 R 3311 0 R 3307 0 R 3310 0 R 3307 0 R 3309 0 R 3307 0 R 3308 0 R 3308 0 R 3307 0 R 3306 0 R 3304 0 R 3302 0 R 3302 0 R 3302 0 R 3302 0 R 3302 0 R 3300 0 R 3298 0 R 3298 0 R 3296 0 R 3294 0 R 3294 0 R 3294 0 R 3294 0 R 3294 0 R 3292 0 R 3290 0 R 3288 0 R 3286 0 R 3284 0 R 3284 0 R 3284 0 R 3284 0 R 3284 0 R 3282 0 R 3280 0 R 3280 0 R 3280 0 R 3280 0 R 3280 0 R 3280 0 R 3280 0 R 3278 0 R 3276 0 R 3274 0 R 3274 0 R 3274 0 R 3274 0 R 3274 0 R 3274 0 R 3274 0 R 3274 0 R 3274 0 R 3274 0 R 3274 0 R 3272 0 R 3270 0 R 3270 0 R 3268 0 R 3266 0 R 3266 0 R 3266 0 R 3266 0 R 3266 0 R 3266 0 R 3266 0 R 3266 0 R 3266 0 R 3266 0 R 3264 0 R 3262 0 R 3260 0 R 3260 0 R 3260 0 R 3260 0 R 3260 0 R 3258 0 R 3256 0 R 3256 0 R 3256 0 R 3256 0 R 3256 0 R 3254 0 R 3252 0 R 3252 0 R 3252 0 R 3252 0 R 3252 0 R 3252 0 R 3252 0 R 3252 0 R 3252 0 R 3252 0 R 3252 0 R 3252 0 R 3252 0 R 3252 0 R 3252 0 R 3252 0 R 3252 0 R 3252 0 R 3252 0 R 3252 0 R 3252 0 R 3252 0 R 3252 0 R 3252 0 R 3252 0 R 3252 0 R 3252 0 R 3252 0 R 3252 0 R 3252 0 R 3252 0 R 3252 0 R 3252 0 R 3252 0 R 3252 0 R 3252 0 R 3252 0 R 3252 0 R 3250 0 R 3248 0 R 3246 0 R 3246 0 R 3246 0 R 3244 0 R 3242 0 R 3242 0 R 3240 0 R 3238 0 R 3238 0 R 3238 0 R 3238 0 R 3238 0 R 3238 0 R 3238 0 R 3238 0 R 3238 0 R 3238 0 R 3236 0 R 3234 0 R 3232 0 R 3232 0 R 3232 0 R 3232 0 R 3232 0 R 3230 0 R 3228 0 R 3228 0 R 3228 0 R 3228 0 R 3228 0 R 3226 0 R 3224 0 R 3224 0 R 3224 0 R 3224 0 R 3224 0 R 3224 0 R 3224 0 R 3224 0 R 3224 0 R 3224 0 R 3224 0 R 3224 0 R 3224 0 R 3224 0 R 3224 0 R 3224 0 R 3224 0 R 3224 0 R 3224 0 R 3224 0 R 3224 0 R 3224 0 R 3224 0 R 3224 0 R 3224 0 R 3224 0 R 3224 0 R 3224 0 R 3224 0 R 3224 0 R 3224 0 R 3219 0 R 3219 0 R 3219 0 R 3219 0 R 3219 0 R 3219 0 R 3220 0 R 3220 0 R 3220 0 R 3219 0 R 3218 0 R 3216 0 R 3217 0 R 3216 0 R 3216 0 R 3216 0 R 3216 0 R 3215 0 R 3215 0 R 3215 0 R 3214 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3213 0 R 3195 0 R 3212 0 R 3212 0 R 3195 0 R 3211 0 R 3211 0 R 3211 0 R 3211 0 R 3211 0 R 3195 0 R 3210 0 R 3195 0 R 3209 0 R 3195 0 R 3195 0 R 3208 0 R 3208 0 R 3195 0 R 3207 0 R 3195 0 R 3206 0 R 3195 0 R 3205 0 R 3195 0 R 3204 0 R 3204 0 R 3195 0 R 3203 0 R 3203 0 R 3195 0 R 3202 0 R 3202 0 R 3202 0 R 3202 0 R 3195 0 R 3201 0 R 3195 0 R 3195 0 R 3200 0 R 3200 0 R 3200 0 R 3200 0 R 3195 0 R 3199 0 R 3199 0 R 3199 0 R 3199 0 R 3195 0 R 3195 0 R 3198 0 R 3198 0 R 3198 0 R 3198 0 R 3198 0 R 3198 0 R 3198 0 R 3198 0 R 3198 0 R 3198 0 R 3195 0 R 3197 0 R 3197 0 R 3195 0 R 3196 0 R 3196 0 R 3195 0 R 3193 0 R 3193 0 R 3193 0 R 3188 0 R 3192 0 R 3188 0 R 3191 0 R 3188 0 R 3190 0 R 3188 0 R 3189 0 R 3189 0 R 3188 0 R] -endobj - -70 0 obj -[3187 0 R 3185 0 R 3183 0 R 3183 0 R 3183 0 R 3183 0 R 3183 0 R 3183 0 R 3183 0 R 3183 0 R 3181 0 R 3179 0 R 3179 0 R 3177 0 R 3175 0 R 3175 0 R 3173 0 R 3171 0 R 3169 0 R 3169 0 R 3169 0 R 3169 0 R 3169 0 R 3167 0 R 3165 0 R 3165 0 R 3165 0 R 3165 0 R 3165 0 R 3163 0 R 3161 0 R 3161 0 R 3161 0 R 3161 0 R 3161 0 R 3161 0 R 3161 0 R 3161 0 R 3161 0 R 3161 0 R 3161 0 R 3161 0 R 3161 0 R 3159 0 R 3157 0 R 3155 0 R 3155 0 R 3155 0 R 3155 0 R 3155 0 R 3155 0 R 3155 0 R 3155 0 R 3155 0 R 3155 0 R 3155 0 R 3155 0 R 3155 0 R 3153 0 R 3151 0 R 3151 0 R 3149 0 R 3147 0 R 3147 0 R 3147 0 R 3147 0 R 3147 0 R 3147 0 R 3147 0 R 3147 0 R 3147 0 R 3147 0 R 3145 0 R 3143 0 R 3141 0 R 3141 0 R 3141 0 R 3141 0 R 3141 0 R 3139 0 R 3137 0 R 3137 0 R 3137 0 R 3137 0 R 3137 0 R 3135 0 R 3133 0 R 3133 0 R 3133 0 R 3133 0 R 3133 0 R 3133 0 R 3133 0 R 3133 0 R 3133 0 R 3133 0 R 3133 0 R 3133 0 R 3133 0 R 3133 0 R 3133 0 R 3133 0 R 3133 0 R 3133 0 R 3133 0 R 3133 0 R 3133 0 R 3133 0 R 3133 0 R 3133 0 R 3133 0 R 3133 0 R 3133 0 R 3133 0 R 3133 0 R 3133 0 R 3133 0 R 3131 0 R 3129 0 R 3127 0 R 3127 0 R 3127 0 R 3127 0 R 3127 0 R 3127 0 R 3127 0 R 3127 0 R 3125 0 R 3123 0 R 3123 0 R 3121 0 R 3119 0 R 3119 0 R 3119 0 R 3119 0 R 3119 0 R 3119 0 R 3119 0 R 3119 0 R 3119 0 R 3119 0 R 3117 0 R 3115 0 R 3113 0 R 3113 0 R 3113 0 R 3113 0 R 3113 0 R 3111 0 R 3109 0 R 3109 0 R 3109 0 R 3109 0 R 3109 0 R 3107 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3105 0 R 3095 0 R 3101 0 R 3095 0 R 3100 0 R 3095 0 R 3099 0 R 3099 0 R 3099 0 R 3099 0 R 3099 0 R 3099 0 R 3099 0 R 3099 0 R 3099 0 R 3099 0 R 3099 0 R 3099 0 R 3099 0 R 3099 0 R 3099 0 R 3099 0 R 3095 0 R 3098 0 R 3095 0 R 3095 0 R 3095 0 R 3097 0 R 3097 0 R 3097 0 R 3097 0 R 3095 0 R 3095 0 R 3095 0 R 3095 0 R 3096 0 R 3095 0 R 3094 0 R 3094 0 R 3090 0 R 3090 0 R 3090 0 R 3093 0 R 3090 0 R 3092 0 R 3090 0 R 3090 0 R 3091 0 R 3090 0 R 3089 0 R 3089 0 R 3089 0 R 3086 0 R 3088 0 R 3086 0 R 3087 0 R 3086 0 R 3085 0 R 3085 0 R 3085 0 R 3085 0 R 3085 0 R 3085 0 R 3085 0 R 3085 0 R 3085 0 R 3083 0 R 3084 0 R 3084 0 R 3084 0 R 3084 0 R 3084 0 R 3083 0 R 3082 0 R 3081 0 R 3081 0 R 3081 0 R 3081 0 R 3080 0 R 3080 0 R 3080 0 R 3078 0 R 3077 0 R 3077 0 R 3077 0 R 3077 0 R 3076 0 R 3062 0 R 3072 0 R 3062 0 R 3062 0 R 3062 0 R 3071 0 R 3062 0 R 3062 0 R 3062 0 R 3070 0 R 3070 0 R 3070 0 R 3062 0 R 3069 0 R 3062 0 R 3068 0 R 3062 0 R 3062 0 R 3067 0 R 3062 0 R 3066 0 R 3062 0 R 3062 0 R 3065 0 R 3062 0 R 3064 0 R 3062 0 R 3062 0 R 3062 0 R 3063 0 R 3062 0 R 3062 0 R 3059 0 R 3058 0 R 3057 0 R 3056 0 R 3061 0 R 3052 0 R 3052 0 R 3039 0 R 3051 0 R 3039 0 R 3039 0 R 3050 0 R 3039 0 R 3049 0 R 3049 0 R] -endobj - -71 0 obj -[3049 0 R 3039 0 R 3048 0 R 3039 0 R 3047 0 R 3047 0 R 3039 0 R 3046 0 R 3039 0 R 3045 0 R 3039 0 R 3039 0 R 3044 0 R 3039 0 R 3043 0 R 3043 0 R 3043 0 R 3043 0 R 3043 0 R 3043 0 R 3039 0 R 3042 0 R 3039 0 R 3039 0 R 3041 0 R 3039 0 R 3039 0 R 3040 0 R 3039 0 R 3032 0 R 3038 0 R 3032 0 R 3032 0 R 3037 0 R 3032 0 R 3032 0 R 3036 0 R 3032 0 R 3032 0 R 3035 0 R 3032 0 R 3032 0 R 3032 0 R 3032 0 R 3034 0 R 3032 0 R 3033 0 R 3032 0 R 3031 0 R 3031 0 R 3031 0 R 3024 0 R 3030 0 R 3024 0 R 3029 0 R 3029 0 R 3029 0 R 3029 0 R 3029 0 R 3029 0 R 3029 0 R 3029 0 R 3029 0 R 3029 0 R 3029 0 R 3029 0 R 3029 0 R 3024 0 R 3028 0 R 3028 0 R 3024 0 R 3024 0 R 3024 0 R 3027 0 R 3024 0 R 3026 0 R 3024 0 R 3024 0 R 3025 0 R 3024 0 R 3023 0 R 3023 0 R 3023 0 R 3023 0 R 3023 0 R 3023 0 R 3023 0 R 3023 0 R 3023 0 R 3023 0 R 3023 0 R 3023 0 R 3023 0 R 3023 0 R 3023 0 R 3023 0 R 3023 0 R 3023 0 R 3023 0 R 3023 0 R 3023 0 R 3023 0 R 3023 0 R 3023 0 R 3023 0 R 3023 0 R 3023 0 R 3023 0 R 3023 0 R 3023 0 R 3023 0 R 3023 0 R 3023 0 R 3023 0 R 3023 0 R 3023 0 R 3023 0 R 3023 0 R 3018 0 R 3022 0 R 3018 0 R 3018 0 R 3021 0 R 3021 0 R 3018 0 R 3020 0 R 3020 0 R 3020 0 R 3018 0 R 3019 0 R 3019 0 R 3018 0 R 3010 0 R 3016 0 R 3016 0 R 3010 0 R 3015 0 R 3010 0 R 3010 0 R 3014 0 R 3014 0 R 3014 0 R 3014 0 R 3014 0 R 3010 0 R 3013 0 R 3010 0 R 3010 0 R 3012 0 R 3012 0 R 3012 0 R 3010 0 R 3011 0 R 3010 0 R 3009 0 R 3009 0 R 3009 0 R 3007 0 R 3005 0 R 3005 0 R 3003 0 R 3001 0 R 3001 0 R 2999 0 R 2997 0 R 2997 0 R 2997 0 R 2995 0 R 2995 0 R 2995 0 R 2993 0 R 2991 0 R 2989 0 R 2987 0 R 2987 0 R 2987 0 R 2987 0 R 2987 0 R 2985 0 R 2983 0 R 2983 0 R 2983 0 R 2983 0 R 2983 0 R 2983 0 R 2983 0 R 2983 0 R 2983 0 R 2983 0 R 2983 0 R 2983 0 R 2982 0 R 2982 0 R 2982 0 R 2982 0 R 2982 0 R 2982 0 R 2982 0 R 2982 0 R 2982 0 R 2982 0 R 2982 0 R 2982 0 R 2982 0 R 2982 0 R 2982 0 R 2982 0 R 2982 0 R 2982 0 R 2977 0 R 2979 0 R 2977 0 R 2977 0 R 2978 0 R 2977 0 R 2976 0 R 2976 0 R 2972 0 R 2975 0 R 2972 0 R 2974 0 R 2972 0 R 2972 0 R 2973 0 R 2972 0 R 2972 0 R 2971 0 R 2971 0 R 2971 0 R 2968 0 R 2970 0 R 2970 0 R 2970 0 R 2968 0 R 2969 0 R 2969 0 R 2969 0 R 2969 0 R 2968 0 R 2968 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2967 0 R 2964 0 R 2966 0 R 2966 0 R 2966 0 R 2966 0 R 2964 0 R 2965 0 R 2965 0 R 2965 0 R 2965 0 R 2965 0 R 2965 0 R 2965 0 R 2964 0 R 2963 0 R 2962 0 R 2961 0 R 2959 0 R 2958 0 R 2957 0 R 2955 0 R 2954 0 R 2953 0 R] -endobj - -72 0 obj -[2950 0 R 2949 0 R 2948 0 R 2946 0 R 2945 0 R 2945 0 R 2945 0 R 2945 0 R 2944 0 R 2937 0 R 2939 0 R 2939 0 R 2939 0 R 2937 0 R 2938 0 R 2938 0 R 2937 0 R 2937 0 R 2936 0 R 2936 0 R 2936 0 R 2934 0 R 2935 0 R 2935 0 R 2935 0 R 2934 0 R 2933 0 R 2933 0 R 2933 0 R 2931 0 R 2929 0 R 2929 0 R 2929 0 R 2927 0 R 2925 0 R 2925 0 R 2923 0 R 2921 0 R 2921 0 R 2921 0 R 2919 0 R 2919 0 R 2919 0 R 2917 0 R 2915 0 R 2913 0 R 2911 0 R 2911 0 R 2911 0 R 2911 0 R 2911 0 R 2909 0 R 2907 0 R 2907 0 R 2907 0 R 2907 0 R 2907 0 R 2907 0 R 2907 0 R 2907 0 R 2907 0 R 2907 0 R 2907 0 R 2907 0 R 2907 0 R 2907 0 R 2906 0 R 2906 0 R 2905 0 R 2905 0 R 2905 0 R 2905 0 R 2905 0 R 2905 0 R 2905 0 R 2905 0 R 2905 0 R 2905 0 R 2905 0 R 2905 0 R 2905 0 R 2905 0 R 2905 0 R 2905 0 R 2905 0 R 2905 0 R 2904 0 R 2904 0 R 2904 0 R 2904 0 R 2904 0 R 2904 0 R 2904 0 R 2904 0 R 2904 0 R 2904 0 R 2904 0 R 2904 0 R 2904 0 R 2904 0 R 2904 0 R 2904 0 R 2904 0 R 2904 0 R 2904 0 R 2904 0 R 2904 0 R 2904 0 R 2904 0 R 2904 0 R 2904 0 R 2904 0 R 2904 0 R 2903 0 R 2903 0 R 2903 0 R 2903 0 R 2903 0 R 2903 0 R 2903 0 R 2903 0 R 2903 0 R 2903 0 R 2903 0 R 2896 0 R 2899 0 R 2896 0 R 2898 0 R 2896 0 R 2896 0 R 2896 0 R 2897 0 R 2897 0 R 2897 0 R 2897 0 R 2897 0 R 2897 0 R 2897 0 R 2897 0 R 2897 0 R 2896 0 R 2889 0 R 2895 0 R 2889 0 R 2889 0 R 2889 0 R 2894 0 R 2893 0 R 2893 0 R 2893 0 R 2893 0 R 2889 0 R 2889 0 R 2892 0 R 2889 0 R 2889 0 R 2889 0 R 2891 0 R 2889 0 R 2889 0 R 2890 0 R 2889 0 R 2889 0 R 2889 0 R 2889 0 R 2886 0 R 2885 0 R 2884 0 R 2883 0 R 2888 0 R 2877 0 R 2879 0 R 2879 0 R 2877 0 R 2878 0 R 2877 0 R 2877 0 R 2877 0 R 2868 0 R 2876 0 R 2876 0 R 2876 0 R 2868 0 R 2868 0 R 2875 0 R 2868 0 R 2874 0 R 2874 0 R 2874 0 R 2874 0 R 2874 0 R 2874 0 R 2874 0 R 2874 0 R 2874 0 R 2874 0 R 2874 0 R 2874 0 R 2874 0 R 2874 0 R 2874 0 R 2874 0 R 2874 0 R 2868 0 R 2868 0 R 2873 0 R 2873 0 R 2873 0 R 2873 0 R 2873 0 R 2873 0 R 2873 0 R 2868 0 R 2872 0 R 2868 0 R 2871 0 R 2868 0 R 2870 0 R 2868 0 R 2869 0 R 2868 0 R 2868 0 R 2868 0 R 2868 0 R 2867 0 R 2867 0 R 2854 0 R 2866 0 R 2854 0 R 2865 0 R 2854 0 R 2864 0 R 2854 0 R 2863 0 R 2854 0 R 2862 0 R 2854 0 R 2861 0 R 2854 0 R 2860 0 R 2854 0 R 2854 0 R 2859 0 R 2854 0 R 2858 0 R 2854 0 R 2857 0 R 2854 0 R 2856 0 R 2854 0 R 2855 0 R 2854 0 R] -endobj - -73 0 obj -[2850 0 R 2853 0 R 2850 0 R 2850 0 R 2852 0 R 2852 0 R 2852 0 R 2852 0 R 2852 0 R 2852 0 R 2850 0 R 2851 0 R 2850 0 R 2849 0 R 2849 0 R 2849 0 R 2849 0 R 2849 0 R 2849 0 R 2849 0 R 2849 0 R 2849 0 R 2849 0 R 2849 0 R 2849 0 R 2849 0 R 2849 0 R 2849 0 R 2849 0 R 2849 0 R 2845 0 R 2848 0 R 2848 0 R 2848 0 R 2848 0 R 2848 0 R 2848 0 R 2848 0 R 2848 0 R 2848 0 R 2848 0 R 2848 0 R 2848 0 R 2848 0 R 2848 0 R 2848 0 R 2848 0 R 2848 0 R 2848 0 R 2848 0 R 2848 0 R 2848 0 R 2848 0 R 2848 0 R 2848 0 R 2848 0 R 2848 0 R 2848 0 R 2848 0 R 2845 0 R 2847 0 R 2845 0 R 2846 0 R 2846 0 R 2845 0 R 2840 0 R 2844 0 R 2844 0 R 2840 0 R 2843 0 R 2843 0 R 2840 0 R 2840 0 R 2842 0 R 2842 0 R 2840 0 R 2841 0 R 2841 0 R 2840 0 R 2840 0 R 2840 0 R 2834 0 R 2839 0 R 2834 0 R 2838 0 R 2834 0 R 2834 0 R 2834 0 R 2837 0 R 2834 0 R 2836 0 R 2834 0 R 2835 0 R 2834 0 R 2831 0 R 2830 0 R 2829 0 R 2828 0 R 2828 0 R 2828 0 R 2828 0 R 2828 0 R 2828 0 R 2828 0 R 2828 0 R 2828 0 R 2827 0 R 2826 0 R 2826 0 R 2826 0 R 2826 0 R 2826 0 R 2826 0 R 2826 0 R 2826 0 R 2826 0 R 2825 0 R 2824 0 R 2824 0 R 2824 0 R 2824 0 R 2824 0 R 2824 0 R 2824 0 R 2824 0 R 2824 0 R 2823 0 R 2822 0 R 2822 0 R 2822 0 R 2822 0 R 2822 0 R 2822 0 R 2822 0 R 2822 0 R 2822 0 R 2821 0 R 2820 0 R 2820 0 R 2820 0 R 2820 0 R 2820 0 R 2820 0 R 2820 0 R 2820 0 R 2820 0 R 2819 0 R 2818 0 R 2818 0 R 2818 0 R 2818 0 R 2818 0 R 2818 0 R 2818 0 R 2818 0 R 2818 0 R 2833 0 R 2814 0 R 2814 0 R 2811 0 R 2811 0 R 2811 0 R 2813 0 R 2813 0 R 2813 0 R 2813 0 R 2811 0 R 2811 0 R 2812 0 R 2811 0 R 2811 0 R 2811 0 R 2803 0 R 2810 0 R 2803 0 R 2809 0 R 2803 0 R 2803 0 R 2808 0 R 2803 0 R 2803 0 R 2803 0 R 2807 0 R 2803 0 R 2806 0 R 2803 0 R 2803 0 R 2803 0 R 2805 0 R 2803 0 R 2803 0 R 2804 0 R 2803 0 R] -endobj - -74 0 obj -[2800 0 R 2799 0 R 2798 0 R 2797 0 R 2802 0 R 2793 0 R 2792 0 R 2784 0 R 2791 0 R 2784 0 R 2790 0 R 2784 0 R 2789 0 R 2784 0 R 2784 0 R 2788 0 R 2784 0 R 2787 0 R 2784 0 R 2786 0 R 2784 0 R 2784 0 R 2785 0 R 2784 0 R 2782 0 R 2775 0 R 2781 0 R 2775 0 R 2780 0 R 2775 0 R 2779 0 R 2775 0 R 2775 0 R 2775 0 R 2778 0 R 2775 0 R 2777 0 R 2775 0 R 2775 0 R 2776 0 R 2775 0 R 2773 0 R 2772 0 R 2772 0 R 2769 0 R 2769 0 R 2769 0 R 2769 0 R 2768 0 R 2768 0 R 2765 0 R 2767 0 R 2765 0 R 2766 0 R 2765 0 R 2765 0 R 2765 0 R 2765 0 R 2764 0 R 2764 0 R 2759 0 R 2763 0 R 2759 0 R 2762 0 R 2762 0 R 2759 0 R 2761 0 R 2759 0 R 2759 0 R 2759 0 R 2760 0 R 2759 0 R 2758 0 R 2758 0 R 2758 0 R 2756 0 R 2757 0 R 2757 0 R 2756 0 R 2755 0 R 2755 0 R 2755 0 R 2755 0 R 2755 0 R 2755 0 R 2755 0 R 2755 0 R 2755 0 R 2755 0 R 2755 0 R 2755 0 R 2755 0 R 2755 0 R 2755 0 R 2755 0 R 2754 0 R 2753 0 R 2752 0 R 2751 0 R 2749 0 R 2748 0 R 2748 0 R 2748 0 R 2747 0 R 2745 0 R 2744 0 R 2743 0 R 2729 0 R 2739 0 R 2729 0 R 2738 0 R 2738 0 R 2729 0 R 2737 0 R 2729 0 R 2729 0 R 2736 0 R 2729 0 R 2729 0 R 2729 0 R 2735 0 R 2729 0 R 2734 0 R 2729 0 R 2733 0 R 2729 0 R 2729 0 R 2732 0 R 2729 0 R 2731 0 R 2729 0 R 2729 0 R 2729 0 R 2730 0 R 2729 0 R] -endobj - -75 0 obj -[2729 0 R 2729 0 R 2728 0 R 2725 0 R 2727 0 R 2727 0 R 2725 0 R 2725 0 R 2725 0 R 2726 0 R 2725 0 R 2725 0 R 2725 0 R 2724 0 R 2723 0 R 2721 0 R 2720 0 R 2720 0 R 2718 0 R 2717 0 R 2717 0 R 2717 0 R 2717 0 R 2714 0 R 2710 0 R 2713 0 R 2713 0 R 2710 0 R 2712 0 R 2710 0 R 2710 0 R 2711 0 R 2710 0 R 2710 0 R 2709 0 R 2709 0 R 2709 0 R 2706 0 R 2708 0 R 2708 0 R 2708 0 R 2708 0 R 2708 0 R 2706 0 R 2707 0 R 2706 0 R 2705 0 R 2704 0 R 2703 0 R 2703 0 R 2701 0 R 2700 0 R 2698 0 R 2698 0 R 2699 0 R 2699 0 R 2698 0 R 2693 0 R 2693 0 R 2694 0 R 2693 0 R 2692 0 R 2692 0 R 2691 0 R 2691 0 R 2690 0 R 2686 0 R 2686 0 R 2686 0 R 2689 0 R 2686 0 R 2688 0 R 2688 0 R 2688 0 R 2688 0 R 2688 0 R 2688 0 R 2688 0 R 2686 0 R 2686 0 R 2687 0 R 2686 0 R 2686 0 R 2686 0 R 2686 0 R 2686 0 R 2686 0 R 2686 0 R 2685 0 R 2681 0 R 2681 0 R 2681 0 R 2681 0 R 2684 0 R 2681 0 R 2681 0 R 2681 0 R 2681 0 R 2681 0 R 2683 0 R 2681 0 R 2681 0 R 2681 0 R 2682 0 R 2681 0 R] -endobj - -76 0 obj -[2681 0 R 2681 0 R 2680 0 R 2680 0 R 2680 0 R 2680 0 R 2677 0 R 2677 0 R 2677 0 R 2677 0 R 2677 0 R 2679 0 R 2677 0 R 2677 0 R 2677 0 R 2678 0 R 2677 0 R 2677 0 R 2677 0 R 2677 0 R 2676 0 R 2676 0 R 2666 0 R 2675 0 R 2666 0 R 2674 0 R 2666 0 R 2666 0 R 2673 0 R 2666 0 R 2666 0 R 2666 0 R 2666 0 R 2666 0 R 2672 0 R 2666 0 R 2671 0 R 2666 0 R 2666 0 R 2670 0 R 2666 0 R 2669 0 R 2666 0 R 2666 0 R 2666 0 R 2668 0 R 2666 0 R 2667 0 R 2666 0 R 2666 0 R 2665 0 R 2665 0 R 2664 0 R 2661 0 R 2661 0 R 2661 0 R 2663 0 R 2661 0 R 2661 0 R 2662 0 R 2661 0 R 2661 0 R 2643 0 R 2660 0 R 2643 0 R 2643 0 R 2659 0 R 2643 0 R 2643 0 R 2643 0 R 2658 0 R 2643 0 R 2657 0 R 2643 0 R 2656 0 R 2643 0 R 2655 0 R 2643 0 R 2643 0 R 2654 0 R 2643 0 R 2653 0 R 2643 0 R 2643 0 R 2652 0 R 2643 0 R 2643 0 R 2643 0 R 2651 0 R 2643 0 R 2650 0 R 2643 0 R 2649 0 R 2643 0 R 2643 0 R 2648 0 R 2648 0 R 2648 0 R 2648 0 R 2648 0 R 2643 0 R 2647 0 R 2643 0 R 2646 0 R 2643 0 R 2645 0 R 2643 0 R 2644 0 R 2643 0 R 2643 0 R] -endobj - -77 0 obj -[2637 0 R 2636 0 R 2634 0 R 2632 0 R 2624 0 R 2624 0 R 2622 0 R 2621 0 R 2619 0 R 2619 0 R 2617 0 R 2618 0 R 2618 0 R 2618 0 R 2616 0 R 2614 0 R 2614 0 R 2614 0 R 2614 0 R 2614 0 R 2612 0 R 2609 0 R 2606 0 R 2608 0 R 2608 0 R 2606 0 R 2607 0 R 2607 0 R 2605 0 R 2602 0 R 2604 0 R 2602 0 R 2603 0 R 2600 0 R 2600 0 R 2600 0 R 2600 0 R 2598 0 R 2599 0 R 2599 0 R 2599 0 R 2599 0 R 2599 0 R 2599 0 R 2597 0 R 2595 0 R 2596 0 R 2593 0 R 2593 0 R 2593 0 R 2593 0 R 2593 0 R 2593 0 R 2591 0 R 2588 0 R 2588 0 R 2588 0 R 2588 0 R 2588 0 R 2588 0 R 2586 0 R 2583 0 R 2583 0 R 2581 0 R 2580 0 R 2578 0 R 2578 0 R 2578 0 R 2578 0 R 2576 0 R 2573 0 R 2573 0 R 2573 0 R 2573 0 R 2571 0 R 2568 0 R 2568 0 R 2568 0 R 2568 0 R 2568 0 R 2566 0 R 2563 0 R 2561 0 R 2560 0 R 2642 0 R 2548 0 R 2552 0 R 2548 0 R 2548 0 R 2551 0 R 2548 0 R 2548 0 R 2550 0 R 2548 0 R 2549 0 R 2548 0 R 2547 0 R 2547 0 R 2536 0 R 2546 0 R 2536 0 R 2536 0 R 2545 0 R 2536 0 R 2536 0 R 2544 0 R 2536 0 R 2536 0 R 2536 0 R 2543 0 R 2536 0 R 2542 0 R 2542 0 R 2542 0 R 2536 0 R 2541 0 R 2536 0 R 2536 0 R 2540 0 R 2540 0 R 2540 0 R 2536 0 R 2539 0 R 2539 0 R 2539 0 R 2539 0 R 2536 0 R 2536 0 R 2538 0 R 2538 0 R 2536 0 R 2537 0 R 2537 0 R 2537 0 R 2536 0 R 2536 0 R 2536 0 R 2535 0 R 2529 0 R 2534 0 R 2529 0 R 2533 0 R 2533 0 R 2533 0 R 2529 0 R 2532 0 R 2529 0 R 2531 0 R 2529 0 R 2530 0 R 2529 0 R 2528 0 R 2527 0 R 2525 0 R 2523 0 R 2522 0 R 2520 0 R 2516 0 R 2515 0 R 2514 0 R 2512 0 R 2509 0 R 2508 0 R 2507 0 R 2505 0 R 2502 0 R 2501 0 R 2499 0 R 2494 0 R 2493 0 R 2491 0 R 2492 0 R 2491 0 R 2489 0 R 2485 0 R 2483 0 R 2484 0 R 2483 0 R 2482 0 R 2481 0 R 2479 0 R 2475 0 R 2472 0 R 2474 0 R 2472 0 R 2473 0 R 2470 0 R 2467 0 R 2466 0 R 2464 0 R 2462 0 R 2461 0 R 2459 0 R 2455 0 R 2454 0 R 2453 0 R] -endobj - -78 0 obj -[2451 0 R 2448 0 R 2447 0 R 2446 0 R 2445 0 R 2444 0 R 2442 0 R 2439 0 R 2438 0 R 2436 0 R 2431 0 R 2428 0 R 2430 0 R 2428 0 R 2429 0 R 2426 0 R 2422 0 R 2421 0 R 2420 0 R 2418 0 R 2414 0 R 2413 0 R 2411 0 R 2412 0 R 2411 0 R 2409 0 R 2405 0 R 2403 0 R 2400 0 R 2399 0 R 2398 0 R 2396 0 R 2393 0 R 2392 0 R 2378 0 R 2387 0 R 2378 0 R 2386 0 R 2386 0 R 2386 0 R 2378 0 R 2385 0 R 2378 0 R 2378 0 R 2378 0 R 2384 0 R 2378 0 R 2378 0 R 2383 0 R 2378 0 R 2382 0 R 2381 0 R 2381 0 R 2381 0 R 2381 0 R 2378 0 R 2378 0 R 2380 0 R 2378 0 R 2379 0 R 2378 0 R 2377 0 R 2364 0 R 2376 0 R 2364 0 R 2364 0 R 2375 0 R 2364 0 R 2374 0 R 2364 0 R 2373 0 R 2364 0 R 2372 0 R 2364 0 R 2371 0 R 2364 0 R 2364 0 R 2370 0 R 2364 0 R 2364 0 R 2369 0 R 2364 0 R 2364 0 R 2368 0 R 2368 0 R 2368 0 R 2364 0 R 2367 0 R 2364 0 R 2364 0 R 2366 0 R 2364 0 R 2365 0 R 2364 0 R 2363 0 R 2363 0 R 2361 0 R 2362 0 R 2361 0 R 2361 0 R 2360 0 R 2359 0 R 2357 0 R 2358 0 R 2358 0 R 2358 0 R 2358 0 R 2358 0 R 2358 0 R 2358 0 R 2358 0 R 2358 0 R 2358 0 R 2357 0 R 2355 0 R 2354 0 R 2352 0 R 2353 0 R 2353 0 R 2353 0 R 2353 0 R 2353 0 R 2353 0 R 2353 0 R 2353 0 R 2352 0 R 2350 0 R 2349 0 R 2347 0 R 2348 0 R 2348 0 R 2348 0 R 2348 0 R 2348 0 R 2348 0 R 2348 0 R 2348 0 R 2348 0 R 2348 0 R 2347 0 R 2333 0 R 2344 0 R 2344 0 R 2344 0 R 2344 0 R 2344 0 R 2344 0 R 2344 0 R 2344 0 R 2344 0 R 2344 0 R 2344 0 R 2344 0 R 2344 0 R 2344 0 R 2333 0 R 2343 0 R 2333 0 R 2333 0 R 2342 0 R 2333 0 R 2341 0 R 2341 0 R 2341 0 R 2341 0 R 2333 0 R 2340 0 R 2333 0 R 2339 0 R 2339 0 R 2339 0 R 2339 0 R 2339 0 R 2339 0 R 2339 0 R 2333 0 R 2338 0 R 2333 0 R 2337 0 R 2333 0 R 2336 0 R 2333 0 R 2333 0 R 2335 0 R 2333 0 R 2333 0 R 2334 0 R 2334 0 R 2333 0 R 2332 0 R 2322 0 R 2331 0 R 2331 0 R 2331 0 R 2331 0 R 2331 0 R 2331 0 R 2322 0 R 2330 0 R 2330 0 R 2322 0 R 2329 0 R 2322 0 R 2322 0 R 2328 0 R 2322 0 R 2327 0 R 2322 0 R 2326 0 R 2322 0 R 2325 0 R 2325 0 R 2325 0 R 2325 0 R 2325 0 R 2325 0 R 2322 0 R 2322 0 R 2324 0 R 2324 0 R 2324 0 R 2324 0 R 2322 0 R 2322 0 R 2323 0 R 2322 0 R 2321 0 R 2320 0 R 2318 0 R 2316 0 R 2315 0 R 2313 0 R 2309 0 R 2308 0 R 2307 0 R 2306 0 R 2305 0 R 2305 0 R 2304 0 R 2304 0 R 2304 0 R 2304 0 R 2302 0 R 2299 0 R 2298 0 R 2297 0 R 2296 0 R 2296 0 R 2295 0 R 2295 0 R 2295 0 R 2295 0 R 2295 0 R 2295 0 R 2295 0 R] -endobj - -79 0 obj -[2293 0 R 2291 0 R 2290 0 R 2288 0 R 2284 0 R 2283 0 R 2281 0 R 2276 0 R 2275 0 R 2274 0 R 2273 0 R 2272 0 R 2272 0 R 2271 0 R 2271 0 R 2271 0 R 2271 0 R 2269 0 R 2265 0 R 2264 0 R 2263 0 R 2262 0 R 2261 0 R 2261 0 R 2260 0 R 2260 0 R 2260 0 R 2260 0 R 2260 0 R 2260 0 R 2260 0 R 2260 0 R 2260 0 R 2258 0 R 2254 0 R 2252 0 R 2248 0 R 2246 0 R 2247 0 R 2246 0 R 2244 0 R 2238 0 R 2237 0 R 2236 0 R 2235 0 R 2235 0 R 2234 0 R 2234 0 R 2234 0 R 2234 0 R 2234 0 R 2234 0 R 2232 0 R 2227 0 R 2225 0 R 2222 0 R 2221 0 R 2216 0 R 2208 0 R 2208 0 R 2215 0 R 2208 0 R 2208 0 R 2214 0 R 2208 0 R 2213 0 R 2208 0 R 2208 0 R 2212 0 R 2208 0 R 2211 0 R 2211 0 R 2211 0 R 2208 0 R 2210 0 R 2208 0 R 2208 0 R 2209 0 R 2208 0 R 2207 0 R 2206 0 R 2204 0 R 2202 0 R 2201 0 R 2199 0 R 2195 0 R 2192 0 R 2194 0 R 2192 0 R 2193 0 R 2190 0 R 2185 0 R 2182 0 R 2184 0 R 2182 0 R 2183 0 R 2180 0 R 2174 0 R 2173 0 R 2172 0 R 2170 0 R 2171 0 R 2170 0 R 2169 0 R 2168 0 R 2167 0 R 2166 0 R 2165 0 R 2163 0 R 2164 0 R 2161 0 R 2154 0 R 2152 0 R 2146 0 R 2141 0 R 2128 0 R 2128 0 R 2140 0 R 2128 0 R 2128 0 R 2139 0 R 2128 0 R 2138 0 R 2128 0 R 2137 0 R 2128 0 R 2128 0 R 2136 0 R 2128 0 R 2135 0 R 2128 0 R 2128 0 R 2134 0 R 2128 0 R 2128 0 R 2133 0 R 2128 0 R 2132 0 R 2128 0 R 2131 0 R 2128 0 R 2130 0 R 2128 0 R 2128 0 R 2129 0 R 2128 0 R 2128 0 R 2127 0 R 2127 0 R 2117 0 R 2126 0 R 2117 0 R 2125 0 R 2117 0 R 2124 0 R 2117 0 R 2123 0 R 2117 0 R 2117 0 R 2122 0 R 2117 0 R 2121 0 R 2117 0 R 2117 0 R 2120 0 R 2120 0 R 2117 0 R 2119 0 R 2117 0 R 2118 0 R 2117 0 R 2117 0 R 2116 0 R 2099 0 R 2115 0 R 2099 0 R 2114 0 R 2099 0 R 2113 0 R 2099 0 R 2112 0 R 2099 0 R 2099 0 R 2111 0 R 2099 0 R 2110 0 R 2099 0 R 2109 0 R 2099 0 R 2108 0 R 2099 0 R 2099 0 R 2107 0 R 2099 0 R 2106 0 R 2099 0 R 2105 0 R 2099 0 R 2099 0 R 2104 0 R 2099 0 R 2103 0 R 2099 0 R] -endobj - -80 0 obj -[2099 0 R 2102 0 R 2099 0 R 2101 0 R 2099 0 R 2099 0 R 2100 0 R 2099 0 R 2098 0 R 2097 0 R 2095 0 R 2093 0 R 2092 0 R 2089 0 R 2085 0 R 2084 0 R 2082 0 R 2077 0 R 2075 0 R 2071 0 R 2069 0 R 2070 0 R 2069 0 R 2067 0 R 2061 0 R 2060 0 R 2059 0 R 2058 0 R 2056 0 R 2051 0 R 2049 0 R 2046 0 R 2045 0 R 2044 0 R 2042 0 R 2039 0 R 2038 0 R 2037 0 R 2036 0 R 2035 0 R 2032 0 R 2029 0 R 2028 0 R 2027 0 R 2026 0 R 2025 0 R 2023 0 R 2020 0 R 2018 0 R 2015 0 R 2014 0 R 2009 0 R 1985 0 R 2008 0 R 1985 0 R 2007 0 R 1985 0 R 2006 0 R 1985 0 R 1985 0 R 1985 0 R 2005 0 R 1985 0 R 1985 0 R 2004 0 R 1985 0 R 2003 0 R 1985 0 R 2002 0 R 1985 0 R 1993 0 R 1985 0 R 1985 0 R 1992 0 R 1985 0 R 1985 0 R 1991 0 R 1985 0 R 1985 0 R 1990 0 R 1985 0 R 1989 0 R 1985 0 R 1988 0 R 1985 0 R 1985 0 R 1987 0 R 1985 0 R 1986 0 R 1985 0 R 1985 0 R 1984 0 R 1983 0 R 1981 0 R 1979 0 R 1978 0 R 1976 0 R 1972 0 R 1971 0 R 1970 0 R 1969 0 R 1969 0 R 1969 0 R 1969 0 R 1969 0 R 1967 0 R 1964 0 R 1963 0 R 1962 0 R 1959 0 R 1961 0 R 1959 0 R 1960 0 R 1957 0 R 1954 0 R 1953 0 R 1952 0 R 1950 0 R 1947 0 R 1944 0 R 1946 0 R 1944 0 R 1945 0 R 1942 0 R 1939 0 R 1938 0 R 1937 0 R 1936 0 R 1935 0 R 1933 0 R 1934 0 R 1931 0 R 1926 0 R 1925 0 R 1924 0 R 1922 0 R 1919 0 R 1917 0 R 1912 0 R 1911 0 R 1910 0 R 1908 0 R 1906 0 R 1905 0 R 1903 0 R 1898 0 R 1899 0 R 1898 0 R 1897 0 R 1896 0 R 1894 0 R 1891 0 R 1890 0 R 1888 0 R 1889 0 R 1888 0 R 1887 0 R 1886 0 R 1885 0 R 1883 0 R 1884 0 R 1883 0 R 1881 0 R 1878 0 R 1877 0 R 1876 0 R 1874 0 R 1871 0 R 1870 0 R 1869 0 R 1866 0 R 1868 0 R 1866 0 R 1867 0 R 1864 0 R 1859 0 R 1858 0 R 1857 0 R 1999 0 R 1996 0 R 1994 0 R 1995 0 R 1994 0 R 1994 0 R 1994 0 R 1994 0 R] -endobj - -81 0 obj -[1855 0 R 1852 0 R 1850 0 R 1845 0 R 1844 0 R 1843 0 R 1841 0 R 1839 0 R 1838 0 R 1836 0 R 1832 0 R 1831 0 R 1829 0 R 1826 0 R 1825 0 R 1824 0 R 1822 0 R 1819 0 R 1818 0 R 1817 0 R 1816 0 R 1815 0 R 1813 0 R 1814 0 R 1811 0 R 1806 0 R 1805 0 R 1804 0 R 1802 0 R 1799 0 R 1797 0 R 1792 0 R 1791 0 R 1790 0 R 1782 0 R 1782 0 R 1785 0 R 1782 0 R 1784 0 R 1782 0 R 1783 0 R 1782 0 R 1782 0 R 1775 0 R 1781 0 R 1775 0 R 1780 0 R 1775 0 R 1779 0 R 1775 0 R 1778 0 R 1775 0 R 1775 0 R 1777 0 R 1775 0 R 1775 0 R 1775 0 R 1776 0 R 1775 0 R 1774 0 R 1774 0 R 1762 0 R 1773 0 R 1762 0 R 1772 0 R 1762 0 R 1771 0 R 1762 0 R 1770 0 R 1762 0 R 1762 0 R 1769 0 R 1762 0 R 1762 0 R 1768 0 R 1762 0 R 1762 0 R 1767 0 R 1762 0 R 1762 0 R 1766 0 R 1762 0 R 1765 0 R 1762 0 R 1762 0 R 1764 0 R 1762 0 R 1763 0 R 1762 0 R 1761 0 R 1760 0 R 1758 0 R 1756 0 R 1755 0 R 1753 0 R 1749 0 R 1748 0 R 1747 0 R 1745 0 R 1742 0 R 1740 0 R 1735 0 R 1734 0 R 1733 0 R 1730 0 R 1732 0 R 1730 0 R 1731 0 R 1730 0 R 1728 0 R 1724 0 R 1723 0 R 1722 0 R 1719 0 R 1721 0 R 1719 0 R 1720 0 R 1719 0 R 1718 0 R 1716 0 R 1712 0 R 1711 0 R 1710 0 R 1705 0 R 1694 0 R 1694 0 R 1704 0 R 1694 0 R 1703 0 R 1694 0 R 1702 0 R 1694 0 R 1701 0 R 1694 0 R 1694 0 R 1694 0 R 1700 0 R 1694 0 R 1699 0 R 1694 0 R 1694 0 R 1698 0 R 1694 0 R 1694 0 R 1697 0 R 1694 0 R 1694 0 R 1696 0 R 1694 0 R 1694 0 R 1695 0 R 1694 0 R 1688 0 R 1693 0 R 1688 0 R 1688 0 R 1692 0 R 1688 0 R] -endobj - -82 0 obj -[1688 0 R 1691 0 R 1688 0 R 1690 0 R 1688 0 R 1689 0 R 1688 0 R 1688 0 R 1688 0 R 1687 0 R 1687 0 R 1680 0 R 1686 0 R 1680 0 R 1680 0 R 1680 0 R 1685 0 R 1680 0 R 1684 0 R 1680 0 R 1683 0 R 1680 0 R 1682 0 R 1682 0 R 1680 0 R 1680 0 R 1681 0 R 1680 0 R 1680 0 R 1680 0 R 1680 0 R 1680 0 R 1679 0 R 1679 0 R 1676 0 R 1676 0 R 1678 0 R 1676 0 R 1677 0 R 1676 0 R 1676 0 R 1676 0 R 1675 0 R 1675 0 R 1675 0 R 1673 0 R 1674 0 R 1673 0 R 1672 0 R 1671 0 R 1670 0 R 1668 0 R 1667 0 R 1666 0 R 1664 0 R 1663 0 R 1662 0 R 1660 0 R 1659 0 R 1658 0 R 1656 0 R 1655 0 R 1653 0 R 1654 0 R 1653 0 R 1651 0 R 1650 0 R 1649 0 R 1646 0 R 1646 0 R 1641 0 R 1644 0 R 1641 0 R 1641 0 R 1641 0 R 1641 0 R 1643 0 R 1641 0 R 1641 0 R 1642 0 R 1641 0 R 1641 0 R 1640 0 R 1640 0 R 1640 0 R 1639 0 R 1638 0 R 1636 0 R 1637 0 R 1636 0 R 1634 0 R 1633 0 R 1632 0 R 1632 0 R 1630 0 R 1629 0 R 1628 0 R 1628 0 R 1626 0 R 1625 0 R 1621 0 R 1621 0 R 1621 0 R 1624 0 R 1621 0 R 1623 0 R 1621 0 R] -endobj - -83 0 obj -[1621 0 R 1622 0 R 1621 0 R 1621 0 R 1621 0 R 1619 0 R 1618 0 R 1617 0 R 1613 0 R 1614 0 R 1613 0 R 1613 0 R 1613 0 R 1612 0 R 1612 0 R 1608 0 R 1611 0 R 1608 0 R 1608 0 R 1608 0 R 1608 0 R 1608 0 R 1608 0 R 1608 0 R 1608 0 R 1608 0 R 1610 0 R 1608 0 R 1608 0 R 1608 0 R 1609 0 R 1608 0 R 1608 0 R 1605 0 R 1607 0 R 1605 0 R 1606 0 R 1605 0 R 1604 0 R 1597 0 R 1603 0 R 1597 0 R 1597 0 R 1602 0 R 1597 0 R 1597 0 R 1601 0 R 1597 0 R 1597 0 R 1600 0 R 1597 0 R 1599 0 R 1597 0 R 1598 0 R 1597 0 R 1596 0 R 1595 0 R 1593 0 R 1591 0 R 1590 0 R 1588 0 R 1584 0 R 1583 0 R 1582 0 R 1580 0 R 1577 0 R 1576 0 R 1575 0 R 1573 0 R 1570 0 R 1569 0 R 1568 0 R 1567 0 R 1565 0 R 1562 0 R 1559 0 R 1561 0 R 1559 0 R 1560 0 R 1557 0 R 1552 0 R 1551 0 R 1550 0 R 1549 0 R 1548 0 R 1547 0 R 1546 0 R 1545 0 R 1544 0 R 1542 0 R 1539 0 R 1537 0 R 1532 0 R 1531 0 R 1530 0 R 1528 0 R 1524 0 R 1521 0 R 1523 0 R 1521 0 R 1522 0 R 1519 0 R 1513 0 R 1512 0 R 1511 0 R 1510 0 R 1509 0 R 1508 0 R 1507 0 R 1505 0 R 1506 0 R 1503 0 R 1496 0 R 1495 0 R 1494 0 R 1493 0 R 1492 0 R 1490 0 R 1484 0 R 1483 0 R 1482 0 R 1481 0 R 1480 0 R 1478 0 R 1472 0 R 1471 0 R 1470 0 R 1468 0 R 1463 0 R 1462 0 R 1461 0 R 1459 0 R 1460 0 R 1457 0 R 1450 0 R 1449 0 R 1448 0 R 1447 0 R 1446 0 R 1444 0 R 1438 0 R 1437 0 R 1436 0 R 1435 0 R 1434 0 R 1432 0 R 1426 0 R 1425 0 R 1424 0 R 1422 0 R 1417 0 R 1415 0 R 1408 0 R 1407 0 R 1406 0 R 1405 0 R 1404 0 R 1403 0 R 1402 0 R 1401 0 R 1400 0 R 1398 0 R 1395 0 R 1394 0 R 1392 0 R 1389 0 R 1388 0 R 1387 0 R 1386 0 R 1385 0 R] -endobj - -84 0 obj -[1383 0 R 1380 0 R 1379 0 R 1374 0 R 1374 0 R 1374 0 R 1373 0 R 1367 0 R 1372 0 R 1367 0 R 1371 0 R 1367 0 R 1367 0 R 1370 0 R 1367 0 R 1367 0 R 1369 0 R 1367 0 R 1367 0 R 1368 0 R 1367 0 R 1366 0 R 1365 0 R 1363 0 R 1361 0 R 1360 0 R 1358 0 R 1354 0 R 1353 0 R 1352 0 R 1351 0 R 1349 0 R 1346 0 R 1345 0 R 1343 0 R 1338 0 R 1337 0 R 1336 0 R 1334 0 R 1335 0 R 1334 0 R 1333 0 R 1330 0 R 1332 0 R 1330 0 R 1331 0 R 1328 0 R 1324 0 R 1323 0 R 1322 0 R 1321 0 R 1320 0 R 1318 0 R 1314 0 R 1311 0 R 1313 0 R 1311 0 R 1312 0 R 1311 0 R 1309 0 R 1306 0 R 1304 0 R 1301 0 R 1300 0 R 1298 0 R 1296 0 R 1295 0 R 1293 0 R 1289 0 R 1288 0 R 1287 0 R 1286 0 R 1284 0 R 1281 0 R 1278 0 R 1280 0 R 1278 0 R 1279 0 R 1276 0 R 1271 0 R 1270 0 R 1269 0 R 1267 0 R 1263 0 R 1262 0 R 1261 0 R 1260 0 R 1259 0 R 1258 0 R 1257 0 R 1255 0 R 1256 0 R 1253 0 R 1247 0 R 1246 0 R 1245 0 R 1244 0 R 1243 0 R 1241 0 R 1236 0 R 1235 0 R 1234 0 R 1233 0 R 1232 0 R 1230 0 R 1227 0 R 1226 0 R 1219 0 R 1221 0 R 1219 0 R 1220 0 R 1219 0 R 1218 0 R 1209 0 R 1209 0 R 1217 0 R 1209 0 R 1209 0 R 1210 0 R 1209 0 R 1208 0 R 1207 0 R 1205 0 R 1203 0 R 1202 0 R 1200 0 R 1196 0 R 1195 0 R 1194 0 R 1192 0 R 1189 0 R 1187 0 R 1182 0 R 1179 0 R 1181 0 R 1179 0 R 1180 0 R 1177 0 R 1171 0 R 1169 0 R 1164 0 R 1163 0 R 1162 0 R 1160 0 R 1157 0 R 1156 0 R 1154 0 R 1149 0 R 1214 0 R 1211 0 R 1211 0 R] -endobj - -85 0 obj -[1147 0 R 1143 0 R 1140 0 R 1142 0 R 1140 0 R 1141 0 R 1138 0 R 1132 0 R 1130 0 R 1125 0 R 1124 0 R 1123 0 R 1121 0 R 1117 0 R 1116 0 R 1110 0 R 1110 0 R 1110 0 R 1111 0 R 1110 0 R 1110 0 R 1109 0 R 1109 0 R 1092 0 R 1108 0 R 1092 0 R 1092 0 R 1101 0 R 1092 0 R 1092 0 R 1092 0 R 1092 0 R 1091 0 R 1088 0 R 1088 0 R 1090 0 R 1088 0 R 1088 0 R 1088 0 R 1088 0 R 1088 0 R 1089 0 R 1088 0 R 1088 0 R 1088 0 R 1088 0 R 1088 0 R 1087 0 R 1083 0 R 1086 0 R 1083 0 R 1083 0 R 1083 0 R 1083 0 R 1083 0 R 1083 0 R 1083 0 R 1083 0 R 1085 0 R 1083 0 R 1083 0 R 1083 0 R 1084 0 R 1083 0 R 1083 0 R 1082 0 R 1079 0 R 1081 0 R 1079 0 R 1079 0 R 1079 0 R 1079 0 R 1105 0 R 1102 0 R 1102 0 R 1098 0 R 1093 0 R 1095 0 R 1093 0 R 1094 0 R 1093 0 R] -endobj - -86 0 obj -[1079 0 R 1079 0 R 1080 0 R 1079 0 R 1079 0 R 1079 0 R 1079 0 R 1079 0 R 1078 0 R 1077 0 R 1077 0 R 1077 0 R 1077 0 R 1077 0 R 1077 0 R 1077 0 R 1076 0 R 1076 0 R 1075 0 R 1075 0 R 1075 0 R 1075 0 R 1075 0 R 1074 0 R 1074 0 R 1065 0 R 1065 0 R 1073 0 R 1065 0 R 1065 0 R 1072 0 R 1065 0 R 1065 0 R 1065 0 R 1065 0 R 1071 0 R 1065 0 R 1070 0 R 1065 0 R 1069 0 R 1065 0 R 1065 0 R 1068 0 R 1065 0 R 1065 0 R 1067 0 R 1065 0 R 1065 0 R 1065 0 R 1065 0 R 1066 0 R 1065 0 R 1065 0 R 1065 0 R 1065 0 R 1065 0 R 1064 0 R 1064 0 R 1063 0 R 1062 0 R 1062 0 R 1062 0 R 1062 0 R 1062 0 R 1062 0 R 1061 0 R 1057 0 R 1057 0 R 1057 0 R 1060 0 R 1057 0 R 1059 0 R 1057 0 R 1057 0 R] -endobj - -87 0 obj -[1057 0 R 1058 0 R 1057 0 R 1057 0 R 1057 0 R 1057 0 R 1057 0 R 1056 0 R 1054 0 R 1054 0 R 1055 0 R 1054 0 R 1054 0 R 1054 0 R 1054 0 R 1054 0 R 1054 0 R 1054 0 R 1054 0 R 1053 0 R 1053 0 R 1052 0 R 1052 0 R 1052 0 R 1052 0 R 1052 0 R 1051 0 R 1046 0 R 1050 0 R 1046 0 R 1046 0 R 1046 0 R 1046 0 R 1046 0 R 1049 0 R 1046 0 R 1048 0 R 1046 0 R 1046 0 R 1046 0 R 1047 0 R 1046 0 R 1046 0 R 1046 0 R 1046 0 R 1046 0 R 1044 0 R 1044 0 R 1045 0 R 1044 0 R 1044 0 R 1044 0 R 1044 0 R 1044 0 R 1044 0 R 1044 0 R 1044 0 R 1044 0 R 1044 0 R 1043 0 R 1039 0 R 1039 0 R 1039 0 R 1039 0 R 1039 0 R 1039 0 R 1039 0 R 1042 0 R 1039 0 R 1039 0 R 1039 0 R 1039 0 R 1041 0 R 1039 0 R 1039 0 R 1039 0 R] -endobj - -88 0 obj -[1039 0 R 1040 0 R 1039 0 R 1039 0 R 1039 0 R 1038 0 R 1038 0 R 1037 0 R 1037 0 R 1037 0 R 1037 0 R 1036 0 R 1034 0 R 1035 0 R 1034 0 R 1034 0 R 1034 0 R 1034 0 R 1020 0 R 1020 0 R 1020 0 R 1020 0 R 1033 0 R 1020 0 R 1020 0 R 1025 0 R 1020 0 R 1024 0 R 1020 0 R 1020 0 R 1023 0 R 1020 0 R 1022 0 R 1020 0 R 1020 0 R 1021 0 R 1020 0 R 1020 0 R 1020 0 R 1020 0 R 1020 0 R 1020 0 R 1020 0 R 1019 0 R 1015 0 R 1015 0 R 1015 0 R 1015 0 R 1018 0 R 1015 0 R 1015 0 R 1015 0 R 1017 0 R 1015 0 R 1016 0 R 1015 0 R 1007 0 R 1007 0 R 1007 0 R 1014 0 R 1007 0 R 1007 0 R 1013 0 R 1007 0 R 1007 0 R 1007 0 R 1007 0 R 1012 0 R 1007 0 R 1007 0 R 1007 0 R 1011 0 R 1007 0 R 1010 0 R 1007 0 R 1007 0 R 1009 0 R 1007 0 R 1007 0 R 1007 0 R 1008 0 R 1007 0 R 1007 0 R 1007 0 R 1000 0 R 1000 0 R 1000 0 R 1000 0 R 1006 0 R 1000 0 R 1000 0 R 1005 0 R 1000 0 R 1000 0 R 1000 0 R 1004 0 R 1000 0 R 1000 0 R 1003 0 R 1000 0 R 1000 0 R 1000 0 R 1002 0 R 1000 0 R 1001 0 R 1000 0 R 1000 0 R 1000 0 R 997 0 R 997 0 R 997 0 R 999 0 R 997 0 R 997 0 R 1030 0 R 1026 0 R 1027 0 R 1026 0 R 1026 0 R] -endobj - -89 0 obj -[997 0 R 997 0 R 997 0 R 998 0 R 997 0 R 997 0 R 997 0 R 997 0 R 996 0 R 996 0 R 989 0 R 989 0 R 995 0 R 989 0 R 994 0 R 989 0 R 993 0 R 989 0 R 992 0 R 989 0 R 991 0 R 989 0 R 990 0 R 989 0 R 989 0 R 989 0 R 988 0 R 988 0 R 988 0 R 988 0 R 988 0 R 988 0 R 988 0 R 988 0 R 988 0 R 988 0 R 988 0 R 988 0 R 985 0 R 985 0 R 985 0 R 987 0 R 985 0 R 985 0 R 986 0 R 985 0 R 985 0 R 985 0 R 985 0 R 985 0 R 985 0 R 985 0 R 985 0 R 984 0 R 984 0 R 984 0 R 984 0 R 984 0 R 984 0 R 984 0 R 984 0 R 983 0 R 983 0 R 979 0 R 979 0 R 982 0 R 979 0 R 981 0 R 979 0 R 980 0 R 980 0 R 979 0 R] -endobj - -90 0 obj -[979 0 R 979 0 R 978 0 R 973 0 R 977 0 R 973 0 R 973 0 R 973 0 R 973 0 R 976 0 R 973 0 R 973 0 R 975 0 R 975 0 R 975 0 R 975 0 R 975 0 R 975 0 R 973 0 R 973 0 R 973 0 R 973 0 R 974 0 R 973 0 R 973 0 R 972 0 R 970 0 R 971 0 R 970 0 R 970 0 R 970 0 R 970 0 R 970 0 R 970 0 R 965 0 R 969 0 R 965 0 R 965 0 R 968 0 R 965 0 R 967 0 R 965 0 R 965 0 R 966 0 R 965 0 R 965 0 R 965 0 R 964 0 R 960 0 R 963 0 R 960 0 R 962 0 R 962 0 R 962 0 R 960 0 R 961 0 R 960 0 R 960 0 R 960 0 R 960 0 R 960 0 R 959 0 R 956 0 R 956 0 R 956 0 R 958 0 R 956 0 R 956 0 R 956 0 R 957 0 R 956 0 R 956 0 R 956 0 R 956 0 R 956 0 R 956 0 R 956 0 R 956 0 R 956 0 R 956 0 R 955 0 R 949 0 R 949 0 R 949 0 R 954 0 R 954 0 R 954 0 R 954 0 R 954 0 R 954 0 R 949 0 R 949 0 R 949 0 R 949 0 R 953 0 R 949 0 R 949 0 R 949 0 R 949 0 R 949 0 R 949 0 R 949 0 R 952 0 R 949 0 R 949 0 R 949 0 R 951 0 R 949 0 R 949 0 R 949 0 R 949 0 R 950 0 R 949 0 R 949 0 R 948 0 R 948 0 R 948 0 R] -endobj - -91 0 obj -[947 0 R 947 0 R 946 0 R 946 0 R 945 0 R 945 0 R 944 0 R 943 0 R 943 0 R 943 0 R 943 0 R 942 0 R 934 0 R 941 0 R 934 0 R 934 0 R 934 0 R 940 0 R 934 0 R 934 0 R 939 0 R 934 0 R 938 0 R 934 0 R 934 0 R 934 0 R 934 0 R 934 0 R 937 0 R 934 0 R 934 0 R 934 0 R 934 0 R 934 0 R 934 0 R 934 0 R 936 0 R 934 0 R 934 0 R 935 0 R 934 0 R 934 0 R 934 0 R 934 0 R 934 0 R 934 0 R 933 0 R 928 0 R 928 0 R 928 0 R 932 0 R 928 0 R 928 0 R 928 0 R 931 0 R 928 0 R 930 0 R 928 0 R 928 0 R 928 0 R 928 0 R 928 0 R 928 0 R 928 0 R 928 0 R 928 0 R 929 0 R 928 0 R 927 0 R 921 0 R 921 0 R 926 0 R 921 0 R 921 0 R 925 0 R 925 0 R 921 0 R 921 0 R 921 0 R 921 0 R 921 0 R 921 0 R 924 0 R 921 0 R 923 0 R 921 0 R 921 0 R 921 0 R 922 0 R 921 0 R 921 0 R 921 0 R 921 0 R] -endobj - -92 0 obj -[921 0 R 921 0 R 920 0 R 920 0 R 919 0 R 918 0 R 918 0 R 918 0 R 917 0 R 910 0 R 910 0 R 916 0 R 910 0 R 915 0 R 910 0 R 910 0 R 914 0 R 910 0 R 910 0 R 910 0 R 910 0 R 910 0 R 910 0 R 913 0 R 910 0 R 910 0 R 910 0 R 910 0 R 910 0 R 910 0 R 910 0 R 912 0 R 912 0 R 910 0 R 910 0 R 911 0 R 910 0 R 910 0 R 910 0 R 910 0 R 910 0 R 910 0 R 910 0 R 910 0 R 909 0 R 898 0 R 898 0 R 908 0 R 898 0 R 907 0 R 898 0 R 898 0 R 906 0 R 898 0 R 905 0 R 898 0 R 904 0 R 898 0 R 903 0 R 898 0 R 898 0 R 898 0 R 898 0 R 898 0 R 898 0 R 902 0 R 902 0 R 898 0 R 898 0 R 898 0 R 898 0 R 898 0 R 898 0 R 901 0 R 898 0 R 898 0 R 898 0 R 898 0 R 898 0 R 900 0 R 898 0 R 899 0 R 898 0 R 898 0 R 898 0 R 898 0 R 898 0 R 897 0 R 897 0 R 896 0 R 896 0 R] -endobj - -93 0 obj -[896 0 R 896 0 R 896 0 R 895 0 R 878 0 R 878 0 R 878 0 R 878 0 R 894 0 R 878 0 R 878 0 R 893 0 R 878 0 R 878 0 R 878 0 R 892 0 R 878 0 R 878 0 R 891 0 R 878 0 R 878 0 R 890 0 R 878 0 R 878 0 R 878 0 R 878 0 R 878 0 R 878 0 R 889 0 R 878 0 R 878 0 R 878 0 R 878 0 R 888 0 R 878 0 R 878 0 R 878 0 R 887 0 R 878 0 R 878 0 R 878 0 R 878 0 R 878 0 R 878 0 R 886 0 R 878 0 R 878 0 R 878 0 R 878 0 R 878 0 R 885 0 R 878 0 R 878 0 R 878 0 R 884 0 R 878 0 R 878 0 R 878 0 R 878 0 R 883 0 R 878 0 R 878 0 R 878 0 R 882 0 R 878 0 R 878 0 R 878 0 R 881 0 R 878 0 R 880 0 R 878 0 R 878 0 R 879 0 R 878 0 R 878 0 R 878 0 R 878 0 R 878 0 R 878 0 R 878 0 R 877 0 R 867 0 R 867 0 R 867 0 R 867 0 R 876 0 R 867 0 R 867 0 R 867 0 R 867 0 R 875 0 R 867 0 R 867 0 R 867 0 R 874 0 R 867 0 R 867 0 R 873 0 R 867 0 R 867 0 R 867 0 R 867 0 R 867 0 R 872 0 R 867 0 R 867 0 R 867 0 R 871 0 R 867 0 R 867 0 R 867 0 R 867 0 R 867 0 R 870 0 R 867 0 R 869 0 R 867 0 R 867 0 R 868 0 R 867 0 R 867 0 R 867 0 R 867 0 R 867 0 R 867 0 R 867 0 R 867 0 R 867 0 R 867 0 R 867 0 R 867 0 R 867 0 R] -endobj - -94 0 obj -[866 0 R 856 0 R 856 0 R 856 0 R 865 0 R 856 0 R 864 0 R 856 0 R 856 0 R 856 0 R 856 0 R 863 0 R 856 0 R 856 0 R 856 0 R 856 0 R 856 0 R 862 0 R 856 0 R 861 0 R 856 0 R 856 0 R 856 0 R 856 0 R 860 0 R 856 0 R 856 0 R 856 0 R 856 0 R 859 0 R 856 0 R 856 0 R 856 0 R 858 0 R 856 0 R 856 0 R 856 0 R 857 0 R 856 0 R 856 0 R 856 0 R 856 0 R 856 0 R 856 0 R 855 0 R 855 0 R 854 0 R 854 0 R 854 0 R 854 0 R 853 0 R 847 0 R 847 0 R 847 0 R 852 0 R 847 0 R 847 0 R 847 0 R 851 0 R 847 0 R 847 0 R 847 0 R 847 0 R 850 0 R 847 0 R 849 0 R 847 0 R 847 0 R 847 0 R 847 0 R 847 0 R 847 0 R 848 0 R 847 0 R 847 0 R 847 0 R 846 0 R 836 0 R 836 0 R 836 0 R 845 0 R 836 0 R 844 0 R 836 0 R 836 0 R 836 0 R 836 0 R 836 0 R 836 0 R 843 0 R 836 0 R 836 0 R 836 0 R 836 0 R 842 0 R 836 0 R 841 0 R 836 0 R 836 0 R 840 0 R 836 0 R 836 0 R 836 0 R 836 0 R 839 0 R 836 0 R 836 0 R 836 0 R 836 0 R 836 0 R 836 0 R 836 0 R 838 0 R 836 0 R 836 0 R 837 0 R 836 0 R 835 0 R 827 0 R 827 0 R 834 0 R 827 0 R 827 0 R 827 0 R 827 0 R 827 0 R 833 0 R 827 0 R 832 0 R 827 0 R 827 0 R 827 0 R 831 0 R 827 0 R 827 0 R 827 0 R 827 0 R 830 0 R 827 0 R 827 0 R 829 0 R] -endobj - -95 0 obj -[828 0 R 827 0 R 827 0 R 827 0 R 827 0 R 826 0 R 826 0 R 821 0 R 821 0 R 825 0 R 821 0 R 821 0 R 821 0 R 821 0 R 824 0 R 821 0 R 821 0 R 821 0 R 823 0 R 821 0 R 821 0 R 822 0 R 822 0 R 821 0 R 821 0 R 821 0 R 821 0 R 821 0 R 819 0 R 819 0 R 820 0 R 819 0 R 819 0 R 819 0 R 819 0 R 819 0 R 819 0 R 819 0 R 818 0 R 817 0 R 813 0 R 815 0 R 815 0 R 815 0 R 813 0 R 814 0 R 813 0 R 810 0 R 806 0 R 808 0 R 806 0 R 806 0 R 807 0 R 806 0 R 803 0 R 799 0 R 799 0 R 799 0 R 801 0 R 799 0 R 800 0 R 799 0 R 796 0 R 793 0 R 794 0 R 793 0 R 790 0 R 786 0 R 786 0 R 788 0 R 788 0 R 786 0 R 786 0 R 787 0 R 786 0 R 783 0 R 780 0 R 781 0 R 780 0 R 780 0 R] -endobj - -96 0 obj -[777 0 R 774 0 R 774 0 R 774 0 R 775 0 R 771 0 R 768 0 R 768 0 R 768 0 R 769 0 R 769 0 R 765 0 R 760 0 R 763 0 R 760 0 R 762 0 R 762 0 R 762 0 R 760 0 R 761 0 R 760 0 R 757 0 R 752 0 R 755 0 R 752 0 R 754 0 R 752 0 R 752 0 R 753 0 R 752 0 R 749 0 R 746 0 R 746 0 R 747 0 R 746 0 R 743 0 R 738 0 R 741 0 R 738 0 R 738 0 R 740 0 R 740 0 R 738 0 R 739 0 R 738 0 R 735 0 R 732 0 R 732 0 R 733 0 R 732 0 R 732 0 R 729 0 R 727 0 R 727 0 R 724 0 R 720 0 R 722 0 R 720 0 R 720 0 R 721 0 R 720 0 R 717 0 R 714 0 R 715 0 R 715 0 R 714 0 R 714 0 R 711 0 R 707 0 R 707 0 R 709 0 R 709 0 R 707 0 R 707 0 R 708 0 R 707 0 R 704 0 R 700 0 R 700 0 R 702 0 R 702 0 R 700 0 R 700 0 R 700 0 R 701 0 R 700 0 R 697 0 R 693 0 R 695 0 R 693 0 R 693 0 R 694 0 R 693 0 R 690 0 R 687 0 R 688 0 R 687 0 R 684 0 R 680 0 R 682 0 R 682 0 R 680 0 R 680 0 R 680 0 R 681 0 R 680 0 R 677 0 R 674 0 R 675 0 R 674 0 R 674 0 R] -endobj - -97 0 obj -[671 0 R 667 0 R 669 0 R 669 0 R 667 0 R 667 0 R 667 0 R 668 0 R 667 0 R 664 0 R 660 0 R 662 0 R 662 0 R 660 0 R 660 0 R 661 0 R 660 0 R 657 0 R 653 0 R 655 0 R 653 0 R 654 0 R 654 0 R 653 0 R 650 0 R 646 0 R 648 0 R 648 0 R 648 0 R 646 0 R 647 0 R 647 0 R 646 0 R 643 0 R 639 0 R 641 0 R 641 0 R 639 0 R 639 0 R 640 0 R 639 0 R 636 0 R 632 0 R 634 0 R 634 0 R 632 0 R 633 0 R 632 0 R 629 0 R 624 0 R 627 0 R 624 0 R 626 0 R 626 0 R 624 0 R 625 0 R 624 0 R 621 0 R 617 0 R 617 0 R 619 0 R 619 0 R 617 0 R 617 0 R 618 0 R 617 0 R 614 0 R 610 0 R 612 0 R 612 0 R 612 0 R 610 0 R 611 0 R 610 0 R 607 0 R 603 0 R 603 0 R 605 0 R 605 0 R 603 0 R 604 0 R 603 0 R 600 0 R 596 0 R 596 0 R 598 0 R 596 0 R 597 0 R 596 0 R 593 0 R 589 0 R 591 0 R 591 0 R 589 0 R 589 0 R 590 0 R 589 0 R 586 0 R 582 0 R 584 0 R 582 0 R 582 0 R 583 0 R 582 0 R 579 0 R 575 0 R 577 0 R 577 0 R 575 0 R 576 0 R 575 0 R] -endobj - -98 0 obj -[572 0 R 568 0 R 570 0 R 570 0 R 568 0 R 569 0 R 568 0 R 565 0 R 562 0 R 563 0 R 563 0 R 563 0 R 562 0 R 559 0 R 556 0 R 556 0 R 556 0 R 557 0 R 553 0 R 549 0 R 549 0 R 551 0 R 551 0 R 549 0 R 549 0 R 550 0 R 549 0 R 546 0 R 543 0 R 544 0 R 544 0 R 544 0 R 543 0 R 543 0 R 540 0 R 537 0 R 538 0 R 538 0 R 534 0 R 531 0 R 532 0 R 528 0 R 525 0 R 526 0 R 525 0 R 522 0 R 518 0 R 518 0 R 518 0 R 520 0 R 518 0 R 518 0 R 519 0 R 518 0 R 515 0 R 511 0 R 511 0 R 513 0 R 513 0 R 511 0 R 512 0 R 511 0 R 508 0 R 504 0 R 504 0 R 506 0 R 506 0 R 504 0 R 505 0 R 504 0 R 501 0 R 498 0 R 498 0 R 499 0 R 498 0 R 495 0 R 492 0 R 493 0 R 493 0 R 492 0 R 489 0 R 486 0 R 486 0 R 486 0 R 487 0 R 486 0 R 483 0 R 479 0 R 479 0 R 481 0 R 479 0 R 479 0 R 480 0 R 479 0 R 476 0 R 473 0 R 473 0 R 474 0 R 474 0 R 473 0 R] -endobj - -99 0 obj -[470 0 R 466 0 R 468 0 R 468 0 R 466 0 R 467 0 R 466 0 R 463 0 R 459 0 R 461 0 R 461 0 R 459 0 R 460 0 R 459 0 R 456 0 R 453 0 R 454 0 R 454 0 R 453 0 R 450 0 R 446 0 R 448 0 R 448 0 R 446 0 R 447 0 R 446 0 R 443 0 R 440 0 R 441 0 R 441 0 R 437 0 R 433 0 R 433 0 R 435 0 R 433 0 R 433 0 R 434 0 R 433 0 R 430 0 R 427 0 R 428 0 R 428 0 R 424 0 R 420 0 R 422 0 R 422 0 R 420 0 R 420 0 R 421 0 R 420 0 R 417 0 R 413 0 R 413 0 R 415 0 R 415 0 R 415 0 R 415 0 R 413 0 R 414 0 R 413 0 R 410 0 R 406 0 R 406 0 R 408 0 R 406 0 R 407 0 R 407 0 R 406 0 R 403 0 R 399 0 R 401 0 R 401 0 R 399 0 R 400 0 R 399 0 R 396 0 R 392 0 R 392 0 R 394 0 R 392 0 R 392 0 R 393 0 R 392 0 R 389 0 R 385 0 R 385 0 R 387 0 R 387 0 R 385 0 R 385 0 R 386 0 R 385 0 R 382 0 R 378 0 R 378 0 R 380 0 R 378 0 R 378 0 R 379 0 R 378 0 R 375 0 R 371 0 R 373 0 R 373 0 R 371 0 R 371 0 R 372 0 R 371 0 R] -endobj - -100 0 obj -[368 0 R 364 0 R 366 0 R 364 0 R 364 0 R 365 0 R 364 0 R 361 0 R 357 0 R 359 0 R 357 0 R 357 0 R 358 0 R 357 0 R 354 0 R 350 0 R 350 0 R 352 0 R 350 0 R 350 0 R 351 0 R 350 0 R 347 0 R 343 0 R 343 0 R 345 0 R 345 0 R 343 0 R 344 0 R 343 0 R 340 0 R 337 0 R 337 0 R 337 0 R 338 0 R 334 0 R 330 0 R 332 0 R 332 0 R 330 0 R 330 0 R 331 0 R 330 0 R 327 0 R 323 0 R 323 0 R 325 0 R 323 0 R 324 0 R 323 0 R 320 0 R 316 0 R 316 0 R 318 0 R 316 0 R 317 0 R 316 0 R 313 0 R 309 0 R 309 0 R 309 0 R 311 0 R 309 0 R 310 0 R 310 0 R 309 0 R 306 0 R 302 0 R 302 0 R 304 0 R 302 0 R 302 0 R 303 0 R 302 0 R 299 0 R 295 0 R 297 0 R 297 0 R 295 0 R 296 0 R 295 0 R 292 0 R 288 0 R 288 0 R 290 0 R 290 0 R 288 0 R 289 0 R 288 0 R 285 0 R 281 0 R 281 0 R 283 0 R 281 0 R 281 0 R 282 0 R 281 0 R 278 0 R 273 0 R 276 0 R 273 0 R 275 0 R 275 0 R 273 0 R 273 0 R 274 0 R 273 0 R 270 0 R 266 0 R 266 0 R 268 0 R] -endobj - -101 0 obj -[268 0 R 266 0 R 266 0 R 267 0 R 266 0 R 263 0 R 259 0 R 259 0 R 259 0 R 261 0 R 261 0 R 259 0 R 260 0 R 259 0 R 256 0 R 252 0 R 252 0 R 254 0 R 254 0 R 252 0 R 253 0 R 252 0 R 249 0 R 245 0 R 247 0 R 247 0 R 245 0 R 245 0 R 246 0 R 245 0 R 242 0 R 238 0 R 238 0 R 240 0 R 240 0 R 238 0 R 238 0 R 239 0 R 238 0 R 235 0 R 231 0 R 231 0 R 233 0 R 231 0 R 231 0 R 232 0 R 231 0 R 228 0 R 224 0 R 224 0 R 226 0 R 226 0 R 224 0 R 225 0 R 224 0 R 221 0 R 218 0 R 219 0 R 219 0 R 218 0 R 215 0 R 213 0 R 213 0 R 210 0 R 208 0 R 205 0 R 201 0 R 203 0 R 201 0 R 202 0 R 201 0 R 198 0 R 194 0 R 196 0 R 196 0 R 196 0 R 194 0 R 194 0 R 195 0 R 194 0 R 191 0 R 187 0 R 187 0 R 187 0 R 189 0 R 189 0 R 187 0 R 188 0 R 187 0 R 184 0 R 180 0 R 180 0 R 182 0 R 182 0 R 180 0 R 181 0 R 180 0 R 177 0 R 173 0 R 175 0 R 175 0 R 175 0 R 173 0 R 174 0 R 173 0 R 170 0 R 166 0 R 168 0 R 168 0 R 168 0 R 166 0 R 167 0 R 166 0 R] -endobj - -102 0 obj -[163 0 R 159 0 R 159 0 R 161 0 R 161 0 R 161 0 R 159 0 R 160 0 R 159 0 R 156 0 R 154 0 R 151 0 R 148 0 R 149 0 R 148 0 R 145 0 R 141 0 R 141 0 R 141 0 R 143 0 R 141 0 R 141 0 R 142 0 R 141 0 R 138 0 R 134 0 R 134 0 R 136 0 R 136 0 R 134 0 R 135 0 R 134 0 R 131 0 R 127 0 R 129 0 R 129 0 R 127 0 R 127 0 R 128 0 R 127 0 R 124 0 R 120 0 R 120 0 R 122 0 R 120 0 R 120 0 R 121 0 R 120 0 R 117 0 R 114 0 R 114 0 R 115 0 R 115 0 R 111 0 R 107 0 R 107 0 R 109 0 R 107 0 R 108 0 R 107 0 R] -endobj - -103 0 obj -<< - /Type /StructElem - /S /Document - /P 54 0 R - /K [4305 0 R 4301 0 R 4298 0 R 4297 0 R 4290 0 R 4289 0 R 4076 0 R 4075 0 R 4069 0 R 4068 0 R 4067 0 R 4056 0 R 4053 0 R 4052 0 R 4051 0 R 4050 0 R 4038 0 R 4029 0 R 4026 0 R 4025 0 R 4018 0 R 4017 0 R 4016 0 R 4014 0 R 4012 0 R 4011 0 R 4002 0 R 3978 0 R 3977 0 R 3975 0 R 3974 0 R 3966 0 R 3965 0 R 3963 0 R 3954 0 R 3945 0 R 3944 0 R 3936 0 R 3935 0 R 3931 0 R 3930 0 R 3929 0 R 3919 0 R 3902 0 R 3901 0 R 3897 0 R 3888 0 R 3887 0 R 3885 0 R 3884 0 R 3880 0 R 3879 0 R 3875 0 R 3874 0 R 3863 0 R 3846 0 R 3840 0 R 3839 0 R 3820 0 R 3817 0 R 3782 0 R 3765 0 R 3760 0 R 3750 0 R 3743 0 R 3739 0 R 3713 0 R 3705 0 R 3688 0 R 3687 0 R 3683 0 R 3670 0 R 3666 0 R 3648 0 R 3646 0 R 3637 0 R 3632 0 R 3598 0 R 3595 0 R 3578 0 R 3569 0 R 3567 0 R 3539 0 R 3530 0 R 3528 0 R 3521 0 R 3513 0 R 3506 0 R 3505 0 R 3502 0 R 3501 0 R 3498 0 R 3468 0 R 3462 0 R 3394 0 R 3389 0 R 3388 0 R 3384 0 R 3383 0 R 3380 0 R 3374 0 R 3369 0 R 3363 0 R 3360 0 R 3341 0 R 3340 0 R 3336 0 R 3333 0 R 3318 0 R 3313 0 R 3221 0 R 3219 0 R 3216 0 R 3194 0 R 3102 0 R 3095 0 R 3094 0 R 3090 0 R 3073 0 R 3062 0 R 3053 0 R 3052 0 R 3039 0 R 3032 0 R 3017 0 R 3010 0 R 2980 0 R 2977 0 R 2976 0 R 2972 0 R 2940 0 R 2937 0 R 2900 0 R 2896 0 R 2889 0 R 2880 0 R 2877 0 R 2868 0 R 2867 0 R 2854 0 R 2850 0 R 2849 0 R 2845 0 R 2840 0 R 2834 0 R 2815 0 R 2814 0 R 2811 0 R 2803 0 R 2794 0 R 2793 0 R 2770 0 R 2769 0 R 2768 0 R 2765 0 R 2764 0 R 2759 0 R 2740 0 R 2729 0 R 2725 0 R 2715 0 R 2710 0 R 2695 0 R 2693 0 R 2692 0 R 2691 0 R 2686 0 R 2681 0 R 2680 0 R 2677 0 R 2676 0 R 2666 0 R 2665 0 R 2661 0 R 2643 0 R 2553 0 R 2548 0 R 2547 0 R 2536 0 R 2529 0 R 2388 0 R 2378 0 R 2364 0 R 2363 0 R 2361 0 R 2345 0 R 2333 0 R 2322 0 R 2217 0 R 2208 0 R 2142 0 R 2128 0 R 2127 0 R 2117 0 R 2099 0 R 2010 0 R 1985 0 R 1786 0 R 1782 0 R 1775 0 R 1774 0 R 1762 0 R 1706 0 R 1694 0 R 1688 0 R 1687 0 R 1680 0 R 1679 0 R 1676 0 R 1645 0 R 1641 0 R 1640 0 R 1615 0 R 1613 0 R 1612 0 R 1608 0 R 1605 0 R 1597 0 R 1375 0 R 1374 0 R 1367 0 R 1222 0 R 1219 0 R 1209 0 R 1112 0 R 1110 0 R 1109 0 R 1092 0 R 1088 0 R 1083 0 R 1079 0 R 1077 0 R 1076 0 R 1075 0 R 1074 0 R 1065 0 R 1064 0 R 1062 0 R 1057 0 R 1054 0 R 1053 0 R 1052 0 R 1046 0 R 1044 0 R 1039 0 R 1038 0 R 1037 0 R 1034 0 R 1020 0 R 1015 0 R 1007 0 R 1000 0 R 997 0 R 996 0 R 989 0 R 988 0 R 985 0 R 984 0 R 983 0 R 979 0 R 973 0 R 970 0 R 965 0 R 960 0 R 956 0 R 949 0 R 948 0 R 947 0 R 946 0 R 945 0 R 943 0 R 934 0 R 928 0 R 921 0 R 920 0 R 918 0 R 910 0 R 898 0 R 897 0 R 896 0 R 878 0 R 867 0 R 856 0 R 855 0 R 854 0 R 847 0 R 836 0 R 827 0 R 826 0 R 821 0 R 819 0 R 818 0 R 104 0 R] ->> -endobj - -104 0 obj -<< - /Type /StructElem - /S /L - /P 103 0 R - /A [<< - /O /List - /ListNumbering /Decimal - >>] - /K [811 0 R 804 0 R 797 0 R 791 0 R 784 0 R 778 0 R 772 0 R 766 0 R 758 0 R 750 0 R 744 0 R 736 0 R 730 0 R 725 0 R 718 0 R 712 0 R 705 0 R 698 0 R 691 0 R 685 0 R 678 0 R 672 0 R 665 0 R 658 0 R 651 0 R 644 0 R 637 0 R 630 0 R 622 0 R 615 0 R 608 0 R 601 0 R 594 0 R 587 0 R 580 0 R 573 0 R 566 0 R 560 0 R 554 0 R 547 0 R 541 0 R 535 0 R 529 0 R 523 0 R 516 0 R 509 0 R 502 0 R 496 0 R 490 0 R 484 0 R 477 0 R 471 0 R 464 0 R 457 0 R 451 0 R 444 0 R 438 0 R 431 0 R 425 0 R 418 0 R 411 0 R 404 0 R 397 0 R 390 0 R 383 0 R 376 0 R 369 0 R 362 0 R 355 0 R 348 0 R 341 0 R 335 0 R 328 0 R 321 0 R 314 0 R 307 0 R 300 0 R 293 0 R 286 0 R 279 0 R 271 0 R 264 0 R 257 0 R 250 0 R 243 0 R 236 0 R 229 0 R 222 0 R 216 0 R 211 0 R 206 0 R 199 0 R 192 0 R 185 0 R 178 0 R 171 0 R 164 0 R 157 0 R 152 0 R 146 0 R 139 0 R 132 0 R 125 0 R 118 0 R 112 0 R 105 0 R] ->> -endobj - -105 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [110 0 R 106 0 R] ->> -endobj - -106 0 obj -<< - /Type /StructElem - /S /LBody - /P 105 0 R - /K [107 0 R] ->> -endobj - -107 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 106 0 R - /K [54 55 109 0 R 57 108 0 R 59] - /Pg 5270 0 R ->> -endobj - -108 0 obj -<< - /Type /StructElem - /S /Link - /P 107 0 R - /K [58 << - /Type /OBJR - /Pg 5270 0 R - /Obj 5269 0 R - >>] - /Pg 5270 0 R ->> -endobj - -109 0 obj -<< - /Type /StructElem - /S /Em - /P 107 0 R - /K [56] - /Pg 5270 0 R ->> -endobj - -110 0 obj -<< - /Type /StructElem - /S /Lbl - /P 105 0 R - /K [111 0 R] ->> -endobj - -111 0 obj -<< - /Type /StructElem - /S /Link - /P 110 0 R - /K [53 << - /Type /OBJR - /Pg 5270 0 R - /Obj 5268 0 R - >>] - /Pg 5270 0 R ->> -endobj - -112 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [116 0 R 113 0 R] ->> -endobj - -113 0 obj -<< - /Type /StructElem - /S /LBody - /P 112 0 R - /K [114 0 R] ->> -endobj - -114 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 113 0 R - /K [49 50 115 0 R] - /Pg 5270 0 R ->> -endobj - -115 0 obj -<< - /Type /StructElem - /S /Link - /P 114 0 R - /K [51 << - /Type /OBJR - /Pg 5270 0 R - /Obj 5266 0 R - >> 52 << - /Type /OBJR - /Pg 5270 0 R - /Obj 5267 0 R - >>] - /Pg 5270 0 R ->> -endobj - -116 0 obj -<< - /Type /StructElem - /S /Lbl - /P 112 0 R - /K [117 0 R] ->> -endobj - -117 0 obj -<< - /Type /StructElem - /S /Link - /P 116 0 R - /K [48 << - /Type /OBJR - /Pg 5270 0 R - /Obj 5265 0 R - >>] - /Pg 5270 0 R ->> -endobj - -118 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [123 0 R 119 0 R] ->> -endobj - -119 0 obj -<< - /Type /StructElem - /S /LBody - /P 118 0 R - /K [120 0 R] ->> -endobj - -120 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 119 0 R - /K [41 42 122 0 R 44 45 121 0 R 47] - /Pg 5270 0 R ->> -endobj - -121 0 obj -<< - /Type /StructElem - /S /Link - /P 120 0 R - /K [46 << - /Type /OBJR - /Pg 5270 0 R - /Obj 5264 0 R - >>] - /Pg 5270 0 R ->> -endobj - -122 0 obj -<< - /Type /StructElem - /S /Em - /P 120 0 R - /K [43] - /Pg 5270 0 R ->> -endobj - -123 0 obj -<< - /Type /StructElem - /S /Lbl - /P 118 0 R - /K [124 0 R] ->> -endobj - -124 0 obj -<< - /Type /StructElem - /S /Link - /P 123 0 R - /K [40 << - /Type /OBJR - /Pg 5270 0 R - /Obj 5263 0 R - >>] - /Pg 5270 0 R ->> -endobj - -125 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [130 0 R 126 0 R] ->> -endobj - -126 0 obj -<< - /Type /StructElem - /S /LBody - /P 125 0 R - /K [127 0 R] ->> -endobj - -127 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 126 0 R - /K [33 129 0 R 36 37 128 0 R 39] - /Pg 5270 0 R ->> -endobj - -128 0 obj -<< - /Type /StructElem - /S /Link - /P 127 0 R - /K [38 << - /Type /OBJR - /Pg 5270 0 R - /Obj 5262 0 R - >>] - /Pg 5270 0 R ->> -endobj - -129 0 obj -<< - /Type /StructElem - /S /Em - /P 127 0 R - /K [34 35] - /Pg 5270 0 R ->> -endobj - -130 0 obj -<< - /Type /StructElem - /S /Lbl - /P 125 0 R - /K [131 0 R] ->> -endobj - -131 0 obj -<< - /Type /StructElem - /S /Link - /P 130 0 R - /K [32 << - /Type /OBJR - /Pg 5270 0 R - /Obj 5261 0 R - >>] - /Pg 5270 0 R ->> -endobj - -132 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [137 0 R 133 0 R] ->> -endobj - -133 0 obj -<< - /Type /StructElem - /S /LBody - /P 132 0 R - /K [134 0 R] ->> -endobj - -134 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 133 0 R - /K [25 26 136 0 R 29 135 0 R 31] - /Pg 5270 0 R ->> -endobj - -135 0 obj -<< - /Type /StructElem - /S /Link - /P 134 0 R - /K [30 << - /Type /OBJR - /Pg 5270 0 R - /Obj 5260 0 R - >>] - /Pg 5270 0 R ->> -endobj - -136 0 obj -<< - /Type /StructElem - /S /Em - /P 134 0 R - /K [27 28] - /Pg 5270 0 R ->> -endobj - -137 0 obj -<< - /Type /StructElem - /S /Lbl - /P 132 0 R - /K [138 0 R] ->> -endobj - -138 0 obj -<< - /Type /StructElem - /S /Link - /P 137 0 R - /K [24 << - /Type /OBJR - /Pg 5270 0 R - /Obj 5259 0 R - >>] - /Pg 5270 0 R ->> -endobj - -139 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [144 0 R 140 0 R] ->> -endobj - -140 0 obj -<< - /Type /StructElem - /S /LBody - /P 139 0 R - /K [141 0 R] ->> -endobj - -141 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 140 0 R - /K [16 17 18 143 0 R 20 21 142 0 R 23] - /Pg 5270 0 R ->> -endobj - -142 0 obj -<< - /Type /StructElem - /S /Link - /P 141 0 R - /K [22 << - /Type /OBJR - /Pg 5270 0 R - /Obj 5258 0 R - >>] - /Pg 5270 0 R ->> -endobj - -143 0 obj -<< - /Type /StructElem - /S /Em - /P 141 0 R - /K [19] - /Pg 5270 0 R ->> -endobj - -144 0 obj -<< - /Type /StructElem - /S /Lbl - /P 139 0 R - /K [145 0 R] ->> -endobj - -145 0 obj -<< - /Type /StructElem - /S /Link - /P 144 0 R - /K [15 << - /Type /OBJR - /Pg 5270 0 R - /Obj 5257 0 R - >>] - /Pg 5270 0 R ->> -endobj - -146 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [150 0 R 147 0 R] ->> -endobj - -147 0 obj -<< - /Type /StructElem - /S /LBody - /P 146 0 R - /K [148 0 R] ->> -endobj - -148 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 147 0 R - /K [12 149 0 R 14] - /Pg 5270 0 R ->> -endobj - -149 0 obj -<< - /Type /StructElem - /S /Em - /P 148 0 R - /K [13] - /Pg 5270 0 R ->> -endobj - -150 0 obj -<< - /Type /StructElem - /S /Lbl - /P 146 0 R - /K [151 0 R] ->> -endobj - -151 0 obj -<< - /Type /StructElem - /S /Link - /P 150 0 R - /K [11 << - /Type /OBJR - /Pg 5270 0 R - /Obj 5256 0 R - >>] - /Pg 5270 0 R ->> -endobj - -152 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [155 0 R 153 0 R] ->> -endobj - -153 0 obj -<< - /Type /StructElem - /S /LBody - /P 152 0 R - /K [154 0 R] ->> -endobj - -154 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 153 0 R - /K [10] - /Pg 5270 0 R ->> -endobj - -155 0 obj -<< - /Type /StructElem - /S /Lbl - /P 152 0 R - /K [156 0 R] ->> -endobj - -156 0 obj -<< - /Type /StructElem - /S /Link - /P 155 0 R - /K [9 << - /Type /OBJR - /Pg 5270 0 R - /Obj 5255 0 R - >>] - /Pg 5270 0 R ->> -endobj - -157 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [162 0 R 158 0 R] ->> -endobj - -158 0 obj -<< - /Type /StructElem - /S /LBody - /P 157 0 R - /K [159 0 R] ->> -endobj - -159 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 158 0 R - /K [1 2 161 0 R 6 160 0 R 8] - /Pg 5270 0 R ->> -endobj - -160 0 obj -<< - /Type /StructElem - /S /Link - /P 159 0 R - /K [7 << - /Type /OBJR - /Pg 5270 0 R - /Obj 5254 0 R - >>] - /Pg 5270 0 R ->> -endobj - -161 0 obj -<< - /Type /StructElem - /S /Em - /P 159 0 R - /K [3 4 5] - /Pg 5270 0 R ->> -endobj - -162 0 obj -<< - /Type /StructElem - /S /Lbl - /P 157 0 R - /K [163 0 R] ->> -endobj - -163 0 obj -<< - /Type /StructElem - /S /Link - /P 162 0 R - /K [0 << - /Type /OBJR - /Pg 5270 0 R - /Obj 5253 0 R - >>] - /Pg 5270 0 R ->> -endobj - -164 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [169 0 R 165 0 R] ->> -endobj - -165 0 obj -<< - /Type /StructElem - /S /LBody - /P 164 0 R - /K [166 0 R] ->> -endobj - -166 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 165 0 R - /K [106 168 0 R 110 167 0 R 112] - /Pg 5251 0 R ->> -endobj - -167 0 obj -<< - /Type /StructElem - /S /Link - /P 166 0 R - /K [111 << - /Type /OBJR - /Pg 5251 0 R - /Obj 5250 0 R - >>] - /Pg 5251 0 R ->> -endobj - -168 0 obj -<< - /Type /StructElem - /S /Em - /P 166 0 R - /K [107 108 109] - /Pg 5251 0 R ->> -endobj - -169 0 obj -<< - /Type /StructElem - /S /Lbl - /P 164 0 R - /K [170 0 R] ->> -endobj - -170 0 obj -<< - /Type /StructElem - /S /Link - /P 169 0 R - /K [105 << - /Type /OBJR - /Pg 5251 0 R - /Obj 5249 0 R - >>] - /Pg 5251 0 R ->> -endobj - -171 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [176 0 R 172 0 R] ->> -endobj - -172 0 obj -<< - /Type /StructElem - /S /LBody - /P 171 0 R - /K [173 0 R] ->> -endobj - -173 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 172 0 R - /K [98 175 0 R 102 174 0 R 104] - /Pg 5251 0 R ->> -endobj - -174 0 obj -<< - /Type /StructElem - /S /Link - /P 173 0 R - /K [103 << - /Type /OBJR - /Pg 5251 0 R - /Obj 5248 0 R - >>] - /Pg 5251 0 R ->> -endobj - -175 0 obj -<< - /Type /StructElem - /S /Em - /P 173 0 R - /K [99 100 101] - /Pg 5251 0 R ->> -endobj - -176 0 obj -<< - /Type /StructElem - /S /Lbl - /P 171 0 R - /K [177 0 R] ->> -endobj - -177 0 obj -<< - /Type /StructElem - /S /Link - /P 176 0 R - /K [97 << - /Type /OBJR - /Pg 5251 0 R - /Obj 5247 0 R - >>] - /Pg 5251 0 R ->> -endobj - -178 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [183 0 R 179 0 R] ->> -endobj - -179 0 obj -<< - /Type /StructElem - /S /LBody - /P 178 0 R - /K [180 0 R] ->> -endobj - -180 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 179 0 R - /K [90 91 182 0 R 94 181 0 R 96] - /Pg 5251 0 R ->> -endobj - -181 0 obj -<< - /Type /StructElem - /S /Link - /P 180 0 R - /K [95 << - /Type /OBJR - /Pg 5251 0 R - /Obj 5246 0 R - >>] - /Pg 5251 0 R ->> -endobj - -182 0 obj -<< - /Type /StructElem - /S /Em - /P 180 0 R - /K [92 93] - /Pg 5251 0 R ->> -endobj - -183 0 obj -<< - /Type /StructElem - /S /Lbl - /P 178 0 R - /K [184 0 R] ->> -endobj - -184 0 obj -<< - /Type /StructElem - /S /Link - /P 183 0 R - /K [89 << - /Type /OBJR - /Pg 5251 0 R - /Obj 5245 0 R - >>] - /Pg 5251 0 R ->> -endobj - -185 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [190 0 R 186 0 R] ->> -endobj - -186 0 obj -<< - /Type /StructElem - /S /LBody - /P 185 0 R - /K [187 0 R] ->> -endobj - -187 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 186 0 R - /K [81 82 83 189 0 R 86 188 0 R 88] - /Pg 5251 0 R ->> -endobj - -188 0 obj -<< - /Type /StructElem - /S /Link - /P 187 0 R - /K [87 << - /Type /OBJR - /Pg 5251 0 R - /Obj 5244 0 R - >>] - /Pg 5251 0 R ->> -endobj - -189 0 obj -<< - /Type /StructElem - /S /Em - /P 187 0 R - /K [84 85] - /Pg 5251 0 R ->> -endobj - -190 0 obj -<< - /Type /StructElem - /S /Lbl - /P 185 0 R - /K [191 0 R] ->> -endobj - -191 0 obj -<< - /Type /StructElem - /S /Link - /P 190 0 R - /K [80 << - /Type /OBJR - /Pg 5251 0 R - /Obj 5243 0 R - >>] - /Pg 5251 0 R ->> -endobj - -192 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [197 0 R 193 0 R] ->> -endobj - -193 0 obj -<< - /Type /StructElem - /S /LBody - /P 192 0 R - /K [194 0 R] ->> -endobj - -194 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 193 0 R - /K [72 196 0 R 76 77 195 0 R 79] - /Pg 5251 0 R ->> -endobj - -195 0 obj -<< - /Type /StructElem - /S /Link - /P 194 0 R - /K [78 << - /Type /OBJR - /Pg 5251 0 R - /Obj 5242 0 R - >>] - /Pg 5251 0 R ->> -endobj - -196 0 obj -<< - /Type /StructElem - /S /Em - /P 194 0 R - /K [73 74 75] - /Pg 5251 0 R ->> -endobj - -197 0 obj -<< - /Type /StructElem - /S /Lbl - /P 192 0 R - /K [198 0 R] ->> -endobj - -198 0 obj -<< - /Type /StructElem - /S /Link - /P 197 0 R - /K [71 << - /Type /OBJR - /Pg 5251 0 R - /Obj 5241 0 R - >>] - /Pg 5251 0 R ->> -endobj - -199 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [204 0 R 200 0 R] ->> -endobj - -200 0 obj -<< - /Type /StructElem - /S /LBody - /P 199 0 R - /K [201 0 R] ->> -endobj - -201 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 200 0 R - /K [66 203 0 R 68 202 0 R 70] - /Pg 5251 0 R ->> -endobj - -202 0 obj -<< - /Type /StructElem - /S /Link - /P 201 0 R - /K [69 << - /Type /OBJR - /Pg 5251 0 R - /Obj 5240 0 R - >>] - /Pg 5251 0 R ->> -endobj - -203 0 obj -<< - /Type /StructElem - /S /Em - /P 201 0 R - /K [67] - /Pg 5251 0 R ->> -endobj - -204 0 obj -<< - /Type /StructElem - /S /Lbl - /P 199 0 R - /K [205 0 R] ->> -endobj - -205 0 obj -<< - /Type /StructElem - /S /Link - /P 204 0 R - /K [65 << - /Type /OBJR - /Pg 5251 0 R - /Obj 5239 0 R - >>] - /Pg 5251 0 R ->> -endobj - -206 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [209 0 R 207 0 R] ->> -endobj - -207 0 obj -<< - /Type /StructElem - /S /LBody - /P 206 0 R - /K [208 0 R] ->> -endobj - -208 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 207 0 R - /K [64] - /Pg 5251 0 R ->> -endobj - -209 0 obj -<< - /Type /StructElem - /S /Lbl - /P 206 0 R - /K [210 0 R] ->> -endobj - -210 0 obj -<< - /Type /StructElem - /S /Link - /P 209 0 R - /K [63 << - /Type /OBJR - /Pg 5251 0 R - /Obj 5238 0 R - >>] - /Pg 5251 0 R ->> -endobj - -211 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [214 0 R 212 0 R] ->> -endobj - -212 0 obj -<< - /Type /StructElem - /S /LBody - /P 211 0 R - /K [213 0 R] ->> -endobj - -213 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 212 0 R - /K [61 62] - /Pg 5251 0 R ->> -endobj - -214 0 obj -<< - /Type /StructElem - /S /Lbl - /P 211 0 R - /K [215 0 R] ->> -endobj - -215 0 obj -<< - /Type /StructElem - /S /Link - /P 214 0 R - /K [60 << - /Type /OBJR - /Pg 5251 0 R - /Obj 5237 0 R - >>] - /Pg 5251 0 R ->> -endobj - -216 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [220 0 R 217 0 R] ->> -endobj - -217 0 obj -<< - /Type /StructElem - /S /LBody - /P 216 0 R - /K [218 0 R] ->> -endobj - -218 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 217 0 R - /K [56 219 0 R 59] - /Pg 5251 0 R ->> -endobj - -219 0 obj -<< - /Type /StructElem - /S /Em - /P 218 0 R - /K [57 58] - /Pg 5251 0 R ->> -endobj - -220 0 obj -<< - /Type /StructElem - /S /Lbl - /P 216 0 R - /K [221 0 R] ->> -endobj - -221 0 obj -<< - /Type /StructElem - /S /Link - /P 220 0 R - /K [55 << - /Type /OBJR - /Pg 5251 0 R - /Obj 5236 0 R - >>] - /Pg 5251 0 R ->> -endobj - -222 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [227 0 R 223 0 R] ->> -endobj - -223 0 obj -<< - /Type /StructElem - /S /LBody - /P 222 0 R - /K [224 0 R] ->> -endobj - -224 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 223 0 R - /K [48 49 226 0 R 52 225 0 R 54] - /Pg 5251 0 R ->> -endobj - -225 0 obj -<< - /Type /StructElem - /S /Link - /P 224 0 R - /K [53 << - /Type /OBJR - /Pg 5251 0 R - /Obj 5235 0 R - >>] - /Pg 5251 0 R ->> -endobj - -226 0 obj -<< - /Type /StructElem - /S /Em - /P 224 0 R - /K [50 51] - /Pg 5251 0 R ->> -endobj - -227 0 obj -<< - /Type /StructElem - /S /Lbl - /P 222 0 R - /K [228 0 R] ->> -endobj - -228 0 obj -<< - /Type /StructElem - /S /Link - /P 227 0 R - /K [47 << - /Type /OBJR - /Pg 5251 0 R - /Obj 5234 0 R - >>] - /Pg 5251 0 R ->> -endobj - -229 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [234 0 R 230 0 R] ->> -endobj - -230 0 obj -<< - /Type /StructElem - /S /LBody - /P 229 0 R - /K [231 0 R] ->> -endobj - -231 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 230 0 R - /K [40 41 233 0 R 43 44 232 0 R 46] - /Pg 5251 0 R ->> -endobj - -232 0 obj -<< - /Type /StructElem - /S /Link - /P 231 0 R - /K [45 << - /Type /OBJR - /Pg 5251 0 R - /Obj 5233 0 R - >>] - /Pg 5251 0 R ->> -endobj - -233 0 obj -<< - /Type /StructElem - /S /Em - /P 231 0 R - /K [42] - /Pg 5251 0 R ->> -endobj - -234 0 obj -<< - /Type /StructElem - /S /Lbl - /P 229 0 R - /K [235 0 R] ->> -endobj - -235 0 obj -<< - /Type /StructElem - /S /Link - /P 234 0 R - /K [39 << - /Type /OBJR - /Pg 5251 0 R - /Obj 5232 0 R - >>] - /Pg 5251 0 R ->> -endobj - -236 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [241 0 R 237 0 R] ->> -endobj - -237 0 obj -<< - /Type /StructElem - /S /LBody - /P 236 0 R - /K [238 0 R] ->> -endobj - -238 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 237 0 R - /K [31 32 240 0 R 35 36 239 0 R 38] - /Pg 5251 0 R ->> -endobj - -239 0 obj -<< - /Type /StructElem - /S /Link - /P 238 0 R - /K [37 << - /Type /OBJR - /Pg 5251 0 R - /Obj 5231 0 R - >>] - /Pg 5251 0 R ->> -endobj - -240 0 obj -<< - /Type /StructElem - /S /Em - /P 238 0 R - /K [33 34] - /Pg 5251 0 R ->> -endobj - -241 0 obj -<< - /Type /StructElem - /S /Lbl - /P 236 0 R - /K [242 0 R] ->> -endobj - -242 0 obj -<< - /Type /StructElem - /S /Link - /P 241 0 R - /K [30 << - /Type /OBJR - /Pg 5251 0 R - /Obj 5230 0 R - >>] - /Pg 5251 0 R ->> -endobj - -243 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [248 0 R 244 0 R] ->> -endobj - -244 0 obj -<< - /Type /StructElem - /S /LBody - /P 243 0 R - /K [245 0 R] ->> -endobj - -245 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 244 0 R - /K [23 247 0 R 26 27 246 0 R 29] - /Pg 5251 0 R ->> -endobj - -246 0 obj -<< - /Type /StructElem - /S /Link - /P 245 0 R - /K [28 << - /Type /OBJR - /Pg 5251 0 R - /Obj 5229 0 R - >>] - /Pg 5251 0 R ->> -endobj - -247 0 obj -<< - /Type /StructElem - /S /Em - /P 245 0 R - /K [24 25] - /Pg 5251 0 R ->> -endobj - -248 0 obj -<< - /Type /StructElem - /S /Lbl - /P 243 0 R - /K [249 0 R] ->> -endobj - -249 0 obj -<< - /Type /StructElem - /S /Link - /P 248 0 R - /K [22 << - /Type /OBJR - /Pg 5251 0 R - /Obj 5228 0 R - >>] - /Pg 5251 0 R ->> -endobj - -250 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [255 0 R 251 0 R] ->> -endobj - -251 0 obj -<< - /Type /StructElem - /S /LBody - /P 250 0 R - /K [252 0 R] ->> -endobj - -252 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 251 0 R - /K [15 16 254 0 R 19 253 0 R 21] - /Pg 5251 0 R ->> -endobj - -253 0 obj -<< - /Type /StructElem - /S /Link - /P 252 0 R - /K [20 << - /Type /OBJR - /Pg 5251 0 R - /Obj 5227 0 R - >>] - /Pg 5251 0 R ->> -endobj - -254 0 obj -<< - /Type /StructElem - /S /Em - /P 252 0 R - /K [17 18] - /Pg 5251 0 R ->> -endobj - -255 0 obj -<< - /Type /StructElem - /S /Lbl - /P 250 0 R - /K [256 0 R] ->> -endobj - -256 0 obj -<< - /Type /StructElem - /S /Link - /P 255 0 R - /K [14 << - /Type /OBJR - /Pg 5251 0 R - /Obj 5226 0 R - >>] - /Pg 5251 0 R ->> -endobj - -257 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [262 0 R 258 0 R] ->> -endobj - -258 0 obj -<< - /Type /StructElem - /S /LBody - /P 257 0 R - /K [259 0 R] ->> -endobj - -259 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 258 0 R - /K [6 7 8 261 0 R 11 260 0 R 13] - /Pg 5251 0 R ->> -endobj - -260 0 obj -<< - /Type /StructElem - /S /Link - /P 259 0 R - /K [12 << - /Type /OBJR - /Pg 5251 0 R - /Obj 5225 0 R - >>] - /Pg 5251 0 R ->> -endobj - -261 0 obj -<< - /Type /StructElem - /S /Em - /P 259 0 R - /K [9 10] - /Pg 5251 0 R ->> -endobj - -262 0 obj -<< - /Type /StructElem - /S /Lbl - /P 257 0 R - /K [263 0 R] ->> -endobj - -263 0 obj -<< - /Type /StructElem - /S /Link - /P 262 0 R - /K [5 << - /Type /OBJR - /Pg 5251 0 R - /Obj 5224 0 R - >>] - /Pg 5251 0 R ->> -endobj - -264 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [269 0 R 265 0 R] ->> -endobj - -265 0 obj -<< - /Type /StructElem - /S /LBody - /P 264 0 R - /K [266 0 R] ->> -endobj - -266 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 265 0 R - /K [108 109 268 0 R << - /Type /MCR - /MCID 1 - /Pg 5251 0 R - >> << - /Type /MCR - /MCID 2 - /Pg 5251 0 R - >> 267 0 R << - /Type /MCR - /MCID 4 - /Pg 5251 0 R - >>] - /Pg 5221 0 R ->> -endobj - -267 0 obj -<< - /Type /StructElem - /S /Link - /P 266 0 R - /K [3 << - /Type /OBJR - /Pg 5251 0 R - /Obj 5223 0 R - >>] - /Pg 5251 0 R ->> -endobj - -268 0 obj -<< - /Type /StructElem - /S /Em - /P 266 0 R - /K [110 << - /Type /MCR - /MCID 0 - /Pg 5251 0 R - >>] - /Pg 5221 0 R ->> -endobj - -269 0 obj -<< - /Type /StructElem - /S /Lbl - /P 264 0 R - /K [270 0 R] ->> -endobj - -270 0 obj -<< - /Type /StructElem - /S /Link - /P 269 0 R - /K [107 << - /Type /OBJR - /Pg 5221 0 R - /Obj 5220 0 R - >>] - /Pg 5221 0 R ->> -endobj - -271 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [277 0 R 272 0 R] ->> -endobj - -272 0 obj -<< - /Type /StructElem - /S /LBody - /P 271 0 R - /K [273 0 R] ->> -endobj - -273 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 272 0 R - /K [98 276 0 R 100 275 0 R 103 104 274 0 R 106] - /Pg 5221 0 R ->> -endobj - -274 0 obj -<< - /Type /StructElem - /S /Link - /P 273 0 R - /K [105 << - /Type /OBJR - /Pg 5221 0 R - /Obj 5219 0 R - >>] - /Pg 5221 0 R ->> -endobj - -275 0 obj -<< - /Type /StructElem - /S /Em - /P 273 0 R - /K [101 102] - /Pg 5221 0 R ->> -endobj - -276 0 obj -<< - /Type /StructElem - /S /Em - /P 273 0 R - /K [99] - /Pg 5221 0 R ->> -endobj - -277 0 obj -<< - /Type /StructElem - /S /Lbl - /P 271 0 R - /K [278 0 R] ->> -endobj - -278 0 obj -<< - /Type /StructElem - /S /Link - /P 277 0 R - /K [97 << - /Type /OBJR - /Pg 5221 0 R - /Obj 5218 0 R - >>] - /Pg 5221 0 R ->> -endobj - -279 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [284 0 R 280 0 R] ->> -endobj - -280 0 obj -<< - /Type /StructElem - /S /LBody - /P 279 0 R - /K [281 0 R] ->> -endobj - -281 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 280 0 R - /K [90 91 283 0 R 93 94 282 0 R 96] - /Pg 5221 0 R ->> -endobj - -282 0 obj -<< - /Type /StructElem - /S /Link - /P 281 0 R - /K [95 << - /Type /OBJR - /Pg 5221 0 R - /Obj 5217 0 R - >>] - /Pg 5221 0 R ->> -endobj - -283 0 obj -<< - /Type /StructElem - /S /Em - /P 281 0 R - /K [92] - /Pg 5221 0 R ->> -endobj - -284 0 obj -<< - /Type /StructElem - /S /Lbl - /P 279 0 R - /K [285 0 R] ->> -endobj - -285 0 obj -<< - /Type /StructElem - /S /Link - /P 284 0 R - /K [89 << - /Type /OBJR - /Pg 5221 0 R - /Obj 5216 0 R - >>] - /Pg 5221 0 R ->> -endobj - -286 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [291 0 R 287 0 R] ->> -endobj - -287 0 obj -<< - /Type /StructElem - /S /LBody - /P 286 0 R - /K [288 0 R] ->> -endobj - -288 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 287 0 R - /K [82 83 290 0 R 86 289 0 R 88] - /Pg 5221 0 R ->> -endobj - -289 0 obj -<< - /Type /StructElem - /S /Link - /P 288 0 R - /K [87 << - /Type /OBJR - /Pg 5221 0 R - /Obj 5215 0 R - >>] - /Pg 5221 0 R ->> -endobj - -290 0 obj -<< - /Type /StructElem - /S /Em - /P 288 0 R - /K [84 85] - /Pg 5221 0 R ->> -endobj - -291 0 obj -<< - /Type /StructElem - /S /Lbl - /P 286 0 R - /K [292 0 R] ->> -endobj - -292 0 obj -<< - /Type /StructElem - /S /Link - /P 291 0 R - /K [81 << - /Type /OBJR - /Pg 5221 0 R - /Obj 5214 0 R - >>] - /Pg 5221 0 R ->> -endobj - -293 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [298 0 R 294 0 R] ->> -endobj - -294 0 obj -<< - /Type /StructElem - /S /LBody - /P 293 0 R - /K [295 0 R] ->> -endobj - -295 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 294 0 R - /K [75 297 0 R 78 296 0 R 80] - /Pg 5221 0 R ->> -endobj - -296 0 obj -<< - /Type /StructElem - /S /Link - /P 295 0 R - /K [79 << - /Type /OBJR - /Pg 5221 0 R - /Obj 5213 0 R - >>] - /Pg 5221 0 R ->> -endobj - -297 0 obj -<< - /Type /StructElem - /S /Em - /P 295 0 R - /K [76 77] - /Pg 5221 0 R ->> -endobj - -298 0 obj -<< - /Type /StructElem - /S /Lbl - /P 293 0 R - /K [299 0 R] ->> -endobj - -299 0 obj -<< - /Type /StructElem - /S /Link - /P 298 0 R - /K [74 << - /Type /OBJR - /Pg 5221 0 R - /Obj 5212 0 R - >>] - /Pg 5221 0 R ->> -endobj - -300 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [305 0 R 301 0 R] ->> -endobj - -301 0 obj -<< - /Type /StructElem - /S /LBody - /P 300 0 R - /K [302 0 R] ->> -endobj - -302 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 301 0 R - /K [67 68 304 0 R 70 71 303 0 R 73] - /Pg 5221 0 R ->> -endobj - -303 0 obj -<< - /Type /StructElem - /S /Link - /P 302 0 R - /K [72 << - /Type /OBJR - /Pg 5221 0 R - /Obj 5211 0 R - >>] - /Pg 5221 0 R ->> -endobj - -304 0 obj -<< - /Type /StructElem - /S /Em - /P 302 0 R - /K [69] - /Pg 5221 0 R ->> -endobj - -305 0 obj -<< - /Type /StructElem - /S /Lbl - /P 300 0 R - /K [306 0 R] ->> -endobj - -306 0 obj -<< - /Type /StructElem - /S /Link - /P 305 0 R - /K [66 << - /Type /OBJR - /Pg 5221 0 R - /Obj 5210 0 R - >>] - /Pg 5221 0 R ->> -endobj - -307 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [312 0 R 308 0 R] ->> -endobj - -308 0 obj -<< - /Type /StructElem - /S /LBody - /P 307 0 R - /K [309 0 R] ->> -endobj - -309 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 308 0 R - /K [58 59 60 311 0 R 62 310 0 R 65] - /Pg 5221 0 R ->> -endobj - -310 0 obj -<< - /Type /StructElem - /S /Link - /P 309 0 R - /K [63 << - /Type /OBJR - /Pg 5221 0 R - /Obj 5208 0 R - >> 64 << - /Type /OBJR - /Pg 5221 0 R - /Obj 5209 0 R - >>] - /Pg 5221 0 R ->> -endobj - -311 0 obj -<< - /Type /StructElem - /S /Em - /P 309 0 R - /K [61] - /Pg 5221 0 R ->> -endobj - -312 0 obj -<< - /Type /StructElem - /S /Lbl - /P 307 0 R - /K [313 0 R] ->> -endobj - -313 0 obj -<< - /Type /StructElem - /S /Link - /P 312 0 R - /K [57 << - /Type /OBJR - /Pg 5221 0 R - /Obj 5207 0 R - >>] - /Pg 5221 0 R ->> -endobj - -314 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [319 0 R 315 0 R] ->> -endobj - -315 0 obj -<< - /Type /StructElem - /S /LBody - /P 314 0 R - /K [316 0 R] ->> -endobj - -316 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 315 0 R - /K [51 52 318 0 R 54 317 0 R 56] - /Pg 5221 0 R ->> -endobj - -317 0 obj -<< - /Type /StructElem - /S /Link - /P 316 0 R - /K [55 << - /Type /OBJR - /Pg 5221 0 R - /Obj 5206 0 R - >>] - /Pg 5221 0 R ->> -endobj - -318 0 obj -<< - /Type /StructElem - /S /Em - /P 316 0 R - /K [53] - /Pg 5221 0 R ->> -endobj - -319 0 obj -<< - /Type /StructElem - /S /Lbl - /P 314 0 R - /K [320 0 R] ->> -endobj - -320 0 obj -<< - /Type /StructElem - /S /Link - /P 319 0 R - /K [50 << - /Type /OBJR - /Pg 5221 0 R - /Obj 5205 0 R - >>] - /Pg 5221 0 R ->> -endobj - -321 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [326 0 R 322 0 R] ->> -endobj - -322 0 obj -<< - /Type /StructElem - /S /LBody - /P 321 0 R - /K [323 0 R] ->> -endobj - -323 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 322 0 R - /K [44 45 325 0 R 47 324 0 R 49] - /Pg 5221 0 R ->> -endobj - -324 0 obj -<< - /Type /StructElem - /S /Link - /P 323 0 R - /K [48 << - /Type /OBJR - /Pg 5221 0 R - /Obj 5204 0 R - >>] - /Pg 5221 0 R ->> -endobj - -325 0 obj -<< - /Type /StructElem - /S /Em - /P 323 0 R - /K [46] - /Pg 5221 0 R ->> -endobj - -326 0 obj -<< - /Type /StructElem - /S /Lbl - /P 321 0 R - /K [327 0 R] ->> -endobj - -327 0 obj -<< - /Type /StructElem - /S /Link - /P 326 0 R - /K [43 << - /Type /OBJR - /Pg 5221 0 R - /Obj 5203 0 R - >>] - /Pg 5221 0 R ->> -endobj - -328 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [333 0 R 329 0 R] ->> -endobj - -329 0 obj -<< - /Type /StructElem - /S /LBody - /P 328 0 R - /K [330 0 R] ->> -endobj - -330 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 329 0 R - /K [36 332 0 R 39 40 331 0 R 42] - /Pg 5221 0 R ->> -endobj - -331 0 obj -<< - /Type /StructElem - /S /Link - /P 330 0 R - /K [41 << - /Type /OBJR - /Pg 5221 0 R - /Obj 5202 0 R - >>] - /Pg 5221 0 R ->> -endobj - -332 0 obj -<< - /Type /StructElem - /S /Em - /P 330 0 R - /K [37 38] - /Pg 5221 0 R ->> -endobj - -333 0 obj -<< - /Type /StructElem - /S /Lbl - /P 328 0 R - /K [334 0 R] ->> -endobj - -334 0 obj -<< - /Type /StructElem - /S /Link - /P 333 0 R - /K [35 << - /Type /OBJR - /Pg 5221 0 R - /Obj 5201 0 R - >>] - /Pg 5221 0 R ->> -endobj - -335 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [339 0 R 336 0 R] ->> -endobj - -336 0 obj -<< - /Type /StructElem - /S /LBody - /P 335 0 R - /K [337 0 R] ->> -endobj - -337 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 336 0 R - /K [31 32 33 338 0 R] - /Pg 5221 0 R ->> -endobj - -338 0 obj -<< - /Type /StructElem - /S /Link - /P 337 0 R - /K [34 << - /Type /OBJR - /Pg 5221 0 R - /Obj 5200 0 R - >>] - /Pg 5221 0 R ->> -endobj - -339 0 obj -<< - /Type /StructElem - /S /Lbl - /P 335 0 R - /K [340 0 R] ->> -endobj - -340 0 obj -<< - /Type /StructElem - /S /Link - /P 339 0 R - /K [30 << - /Type /OBJR - /Pg 5221 0 R - /Obj 5199 0 R - >>] - /Pg 5221 0 R ->> -endobj - -341 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [346 0 R 342 0 R] ->> -endobj - -342 0 obj -<< - /Type /StructElem - /S /LBody - /P 341 0 R - /K [343 0 R] ->> -endobj - -343 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 342 0 R - /K [23 24 345 0 R 27 344 0 R 29] - /Pg 5221 0 R ->> -endobj - -344 0 obj -<< - /Type /StructElem - /S /Link - /P 343 0 R - /K [28 << - /Type /OBJR - /Pg 5221 0 R - /Obj 5198 0 R - >>] - /Pg 5221 0 R ->> -endobj - -345 0 obj -<< - /Type /StructElem - /S /Em - /P 343 0 R - /K [25 26] - /Pg 5221 0 R ->> -endobj - -346 0 obj -<< - /Type /StructElem - /S /Lbl - /P 341 0 R - /K [347 0 R] ->> -endobj - -347 0 obj -<< - /Type /StructElem - /S /Link - /P 346 0 R - /K [22 << - /Type /OBJR - /Pg 5221 0 R - /Obj 5197 0 R - >>] - /Pg 5221 0 R ->> -endobj - -348 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [353 0 R 349 0 R] ->> -endobj - -349 0 obj -<< - /Type /StructElem - /S /LBody - /P 348 0 R - /K [350 0 R] ->> -endobj - -350 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 349 0 R - /K [15 16 352 0 R 18 19 351 0 R 21] - /Pg 5221 0 R ->> -endobj - -351 0 obj -<< - /Type /StructElem - /S /Link - /P 350 0 R - /K [20 << - /Type /OBJR - /Pg 5221 0 R - /Obj 5196 0 R - >>] - /Pg 5221 0 R ->> -endobj - -352 0 obj -<< - /Type /StructElem - /S /Em - /P 350 0 R - /K [17] - /Pg 5221 0 R ->> -endobj - -353 0 obj -<< - /Type /StructElem - /S /Lbl - /P 348 0 R - /K [354 0 R] ->> -endobj - -354 0 obj -<< - /Type /StructElem - /S /Link - /P 353 0 R - /K [14 << - /Type /OBJR - /Pg 5221 0 R - /Obj 5195 0 R - >>] - /Pg 5221 0 R ->> -endobj - -355 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [360 0 R 356 0 R] ->> -endobj - -356 0 obj -<< - /Type /StructElem - /S /LBody - /P 355 0 R - /K [357 0 R] ->> -endobj - -357 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 356 0 R - /K [8 359 0 R 10 11 358 0 R 13] - /Pg 5221 0 R ->> -endobj - -358 0 obj -<< - /Type /StructElem - /S /Link - /P 357 0 R - /K [12 << - /Type /OBJR - /Pg 5221 0 R - /Obj 5194 0 R - >>] - /Pg 5221 0 R ->> -endobj - -359 0 obj -<< - /Type /StructElem - /S /Em - /P 357 0 R - /K [9] - /Pg 5221 0 R ->> -endobj - -360 0 obj -<< - /Type /StructElem - /S /Lbl - /P 355 0 R - /K [361 0 R] ->> -endobj - -361 0 obj -<< - /Type /StructElem - /S /Link - /P 360 0 R - /K [7 << - /Type /OBJR - /Pg 5221 0 R - /Obj 5193 0 R - >>] - /Pg 5221 0 R ->> -endobj - -362 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [367 0 R 363 0 R] ->> -endobj - -363 0 obj -<< - /Type /StructElem - /S /LBody - /P 362 0 R - /K [364 0 R] ->> -endobj - -364 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 363 0 R - /K [1 366 0 R 3 4 365 0 R 6] - /Pg 5221 0 R ->> -endobj - -365 0 obj -<< - /Type /StructElem - /S /Link - /P 364 0 R - /K [5 << - /Type /OBJR - /Pg 5221 0 R - /Obj 5192 0 R - >>] - /Pg 5221 0 R ->> -endobj - -366 0 obj -<< - /Type /StructElem - /S /Em - /P 364 0 R - /K [2] - /Pg 5221 0 R ->> -endobj - -367 0 obj -<< - /Type /StructElem - /S /Lbl - /P 362 0 R - /K [368 0 R] ->> -endobj - -368 0 obj -<< - /Type /StructElem - /S /Link - /P 367 0 R - /K [0 << - /Type /OBJR - /Pg 5221 0 R - /Obj 5191 0 R - >>] - /Pg 5221 0 R ->> -endobj - -369 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [374 0 R 370 0 R] ->> -endobj - -370 0 obj -<< - /Type /StructElem - /S /LBody - /P 369 0 R - /K [371 0 R] ->> -endobj - -371 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 370 0 R - /K [101 373 0 R 104 105 372 0 R 107] - /Pg 5189 0 R ->> -endobj - -372 0 obj -<< - /Type /StructElem - /S /Link - /P 371 0 R - /K [106 << - /Type /OBJR - /Pg 5189 0 R - /Obj 5188 0 R - >>] - /Pg 5189 0 R ->> -endobj - -373 0 obj -<< - /Type /StructElem - /S /Em - /P 371 0 R - /K [102 103] - /Pg 5189 0 R ->> -endobj - -374 0 obj -<< - /Type /StructElem - /S /Lbl - /P 369 0 R - /K [375 0 R] ->> -endobj - -375 0 obj -<< - /Type /StructElem - /S /Link - /P 374 0 R - /K [100 << - /Type /OBJR - /Pg 5189 0 R - /Obj 5187 0 R - >>] - /Pg 5189 0 R ->> -endobj - -376 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [381 0 R 377 0 R] ->> -endobj - -377 0 obj -<< - /Type /StructElem - /S /LBody - /P 376 0 R - /K [378 0 R] ->> -endobj - -378 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 377 0 R - /K [93 94 380 0 R 96 97 379 0 R 99] - /Pg 5189 0 R ->> -endobj - -379 0 obj -<< - /Type /StructElem - /S /Link - /P 378 0 R - /K [98 << - /Type /OBJR - /Pg 5189 0 R - /Obj 5186 0 R - >>] - /Pg 5189 0 R ->> -endobj - -380 0 obj -<< - /Type /StructElem - /S /Em - /P 378 0 R - /K [95] - /Pg 5189 0 R ->> -endobj - -381 0 obj -<< - /Type /StructElem - /S /Lbl - /P 376 0 R - /K [382 0 R] ->> -endobj - -382 0 obj -<< - /Type /StructElem - /S /Link - /P 381 0 R - /K [92 << - /Type /OBJR - /Pg 5189 0 R - /Obj 5185 0 R - >>] - /Pg 5189 0 R ->> -endobj - -383 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [388 0 R 384 0 R] ->> -endobj - -384 0 obj -<< - /Type /StructElem - /S /LBody - /P 383 0 R - /K [385 0 R] ->> -endobj - -385 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 384 0 R - /K [84 85 387 0 R 88 89 386 0 R 91] - /Pg 5189 0 R ->> -endobj - -386 0 obj -<< - /Type /StructElem - /S /Link - /P 385 0 R - /K [90 << - /Type /OBJR - /Pg 5189 0 R - /Obj 5184 0 R - >>] - /Pg 5189 0 R ->> -endobj - -387 0 obj -<< - /Type /StructElem - /S /Em - /P 385 0 R - /K [86 87] - /Pg 5189 0 R ->> -endobj - -388 0 obj -<< - /Type /StructElem - /S /Lbl - /P 383 0 R - /K [389 0 R] ->> -endobj - -389 0 obj -<< - /Type /StructElem - /S /Link - /P 388 0 R - /K [83 << - /Type /OBJR - /Pg 5189 0 R - /Obj 5183 0 R - >>] - /Pg 5189 0 R ->> -endobj - -390 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [395 0 R 391 0 R] ->> -endobj - -391 0 obj -<< - /Type /StructElem - /S /LBody - /P 390 0 R - /K [392 0 R] ->> -endobj - -392 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 391 0 R - /K [76 77 394 0 R 79 80 393 0 R 82] - /Pg 5189 0 R ->> -endobj - -393 0 obj -<< - /Type /StructElem - /S /Link - /P 392 0 R - /K [81 << - /Type /OBJR - /Pg 5189 0 R - /Obj 5182 0 R - >>] - /Pg 5189 0 R ->> -endobj - -394 0 obj -<< - /Type /StructElem - /S /Em - /P 392 0 R - /K [78] - /Pg 5189 0 R ->> -endobj - -395 0 obj -<< - /Type /StructElem - /S /Lbl - /P 390 0 R - /K [396 0 R] ->> -endobj - -396 0 obj -<< - /Type /StructElem - /S /Link - /P 395 0 R - /K [75 << - /Type /OBJR - /Pg 5189 0 R - /Obj 5181 0 R - >>] - /Pg 5189 0 R ->> -endobj - -397 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [402 0 R 398 0 R] ->> -endobj - -398 0 obj -<< - /Type /StructElem - /S /LBody - /P 397 0 R - /K [399 0 R] ->> -endobj - -399 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 398 0 R - /K [69 401 0 R 72 400 0 R 74] - /Pg 5189 0 R ->> -endobj - -400 0 obj -<< - /Type /StructElem - /S /Link - /P 399 0 R - /K [73 << - /Type /OBJR - /Pg 5189 0 R - /Obj 5180 0 R - >>] - /Pg 5189 0 R ->> -endobj - -401 0 obj -<< - /Type /StructElem - /S /Em - /P 399 0 R - /K [70 71] - /Pg 5189 0 R ->> -endobj - -402 0 obj -<< - /Type /StructElem - /S /Lbl - /P 397 0 R - /K [403 0 R] ->> -endobj - -403 0 obj -<< - /Type /StructElem - /S /Link - /P 402 0 R - /K [68 << - /Type /OBJR - /Pg 5189 0 R - /Obj 5179 0 R - >>] - /Pg 5189 0 R ->> -endobj - -404 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [409 0 R 405 0 R] ->> -endobj - -405 0 obj -<< - /Type /StructElem - /S /LBody - /P 404 0 R - /K [406 0 R] ->> -endobj - -406 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 405 0 R - /K [61 62 408 0 R 64 407 0 R 67] - /Pg 5189 0 R ->> -endobj - -407 0 obj -<< - /Type /StructElem - /S /Link - /P 406 0 R - /K [65 << - /Type /OBJR - /Pg 5189 0 R - /Obj 5177 0 R - >> 66 << - /Type /OBJR - /Pg 5189 0 R - /Obj 5178 0 R - >>] - /Pg 5189 0 R ->> -endobj - -408 0 obj -<< - /Type /StructElem - /S /Em - /P 406 0 R - /K [63] - /Pg 5189 0 R ->> -endobj - -409 0 obj -<< - /Type /StructElem - /S /Lbl - /P 404 0 R - /K [410 0 R] ->> -endobj - -410 0 obj -<< - /Type /StructElem - /S /Link - /P 409 0 R - /K [60 << - /Type /OBJR - /Pg 5189 0 R - /Obj 5176 0 R - >>] - /Pg 5189 0 R ->> -endobj - -411 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [416 0 R 412 0 R] ->> -endobj - -412 0 obj -<< - /Type /StructElem - /S /LBody - /P 411 0 R - /K [413 0 R] ->> -endobj - -413 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 412 0 R - /K [51 52 415 0 R 57 414 0 R 59] - /Pg 5189 0 R ->> -endobj - -414 0 obj -<< - /Type /StructElem - /S /Link - /P 413 0 R - /K [58 << - /Type /OBJR - /Pg 5189 0 R - /Obj 5175 0 R - >>] - /Pg 5189 0 R ->> -endobj - -415 0 obj -<< - /Type /StructElem - /S /Em - /P 413 0 R - /K [53 54 55 56] - /Pg 5189 0 R ->> -endobj - -416 0 obj -<< - /Type /StructElem - /S /Lbl - /P 411 0 R - /K [417 0 R] ->> -endobj - -417 0 obj -<< - /Type /StructElem - /S /Link - /P 416 0 R - /K [50 << - /Type /OBJR - /Pg 5189 0 R - /Obj 5174 0 R - >>] - /Pg 5189 0 R ->> -endobj - -418 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [423 0 R 419 0 R] ->> -endobj - -419 0 obj -<< - /Type /StructElem - /S /LBody - /P 418 0 R - /K [420 0 R] ->> -endobj - -420 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 419 0 R - /K [43 422 0 R 46 47 421 0 R 49] - /Pg 5189 0 R ->> -endobj - -421 0 obj -<< - /Type /StructElem - /S /Link - /P 420 0 R - /K [48 << - /Type /OBJR - /Pg 5189 0 R - /Obj 5173 0 R - >>] - /Pg 5189 0 R ->> -endobj - -422 0 obj -<< - /Type /StructElem - /S /Em - /P 420 0 R - /K [44 45] - /Pg 5189 0 R ->> -endobj - -423 0 obj -<< - /Type /StructElem - /S /Lbl - /P 418 0 R - /K [424 0 R] ->> -endobj - -424 0 obj -<< - /Type /StructElem - /S /Link - /P 423 0 R - /K [42 << - /Type /OBJR - /Pg 5189 0 R - /Obj 5172 0 R - >>] - /Pg 5189 0 R ->> -endobj - -425 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [429 0 R 426 0 R] ->> -endobj - -426 0 obj -<< - /Type /StructElem - /S /LBody - /P 425 0 R - /K [427 0 R] ->> -endobj - -427 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 426 0 R - /K [39 428 0 R] - /Pg 5189 0 R ->> -endobj - -428 0 obj -<< - /Type /StructElem - /S /Link - /P 427 0 R - /K [40 << - /Type /OBJR - /Pg 5189 0 R - /Obj 5170 0 R - >> 41 << - /Type /OBJR - /Pg 5189 0 R - /Obj 5171 0 R - >>] - /Pg 5189 0 R ->> -endobj - -429 0 obj -<< - /Type /StructElem - /S /Lbl - /P 425 0 R - /K [430 0 R] ->> -endobj - -430 0 obj -<< - /Type /StructElem - /S /Link - /P 429 0 R - /K [38 << - /Type /OBJR - /Pg 5189 0 R - /Obj 5169 0 R - >>] - /Pg 5189 0 R ->> -endobj - -431 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [436 0 R 432 0 R] ->> -endobj - -432 0 obj -<< - /Type /StructElem - /S /LBody - /P 431 0 R - /K [433 0 R] ->> -endobj - -433 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 432 0 R - /K [31 32 435 0 R 34 35 434 0 R 37] - /Pg 5189 0 R ->> -endobj - -434 0 obj -<< - /Type /StructElem - /S /Link - /P 433 0 R - /K [36 << - /Type /OBJR - /Pg 5189 0 R - /Obj 5168 0 R - >>] - /Pg 5189 0 R ->> -endobj - -435 0 obj -<< - /Type /StructElem - /S /Em - /P 433 0 R - /K [33] - /Pg 5189 0 R ->> -endobj - -436 0 obj -<< - /Type /StructElem - /S /Lbl - /P 431 0 R - /K [437 0 R] ->> -endobj - -437 0 obj -<< - /Type /StructElem - /S /Link - /P 436 0 R - /K [30 << - /Type /OBJR - /Pg 5189 0 R - /Obj 5167 0 R - >>] - /Pg 5189 0 R ->> -endobj - -438 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [442 0 R 439 0 R] ->> -endobj - -439 0 obj -<< - /Type /StructElem - /S /LBody - /P 438 0 R - /K [440 0 R] ->> -endobj - -440 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 439 0 R - /K [27 441 0 R] - /Pg 5189 0 R ->> -endobj - -441 0 obj -<< - /Type /StructElem - /S /Link - /P 440 0 R - /K [28 << - /Type /OBJR - /Pg 5189 0 R - /Obj 5165 0 R - >> 29 << - /Type /OBJR - /Pg 5189 0 R - /Obj 5166 0 R - >>] - /Pg 5189 0 R ->> -endobj - -442 0 obj -<< - /Type /StructElem - /S /Lbl - /P 438 0 R - /K [443 0 R] ->> -endobj - -443 0 obj -<< - /Type /StructElem - /S /Link - /P 442 0 R - /K [26 << - /Type /OBJR - /Pg 5189 0 R - /Obj 5164 0 R - >>] - /Pg 5189 0 R ->> -endobj - -444 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [449 0 R 445 0 R] ->> -endobj - -445 0 obj -<< - /Type /StructElem - /S /LBody - /P 444 0 R - /K [446 0 R] ->> -endobj - -446 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 445 0 R - /K [20 448 0 R 23 447 0 R 25] - /Pg 5189 0 R ->> -endobj - -447 0 obj -<< - /Type /StructElem - /S /Link - /P 446 0 R - /K [24 << - /Type /OBJR - /Pg 5189 0 R - /Obj 5163 0 R - >>] - /Pg 5189 0 R ->> -endobj - -448 0 obj -<< - /Type /StructElem - /S /Em - /P 446 0 R - /K [21 22] - /Pg 5189 0 R ->> -endobj - -449 0 obj -<< - /Type /StructElem - /S /Lbl - /P 444 0 R - /K [450 0 R] ->> -endobj - -450 0 obj -<< - /Type /StructElem - /S /Link - /P 449 0 R - /K [19 << - /Type /OBJR - /Pg 5189 0 R - /Obj 5162 0 R - >>] - /Pg 5189 0 R ->> -endobj - -451 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [455 0 R 452 0 R] ->> -endobj - -452 0 obj -<< - /Type /StructElem - /S /LBody - /P 451 0 R - /K [453 0 R] ->> -endobj - -453 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 452 0 R - /K [15 454 0 R 18] - /Pg 5189 0 R ->> -endobj - -454 0 obj -<< - /Type /StructElem - /S /Em - /P 453 0 R - /K [16 17] - /Pg 5189 0 R ->> -endobj - -455 0 obj -<< - /Type /StructElem - /S /Lbl - /P 451 0 R - /K [456 0 R] ->> -endobj - -456 0 obj -<< - /Type /StructElem - /S /Link - /P 455 0 R - /K [14 << - /Type /OBJR - /Pg 5189 0 R - /Obj 5161 0 R - >>] - /Pg 5189 0 R ->> -endobj - -457 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [462 0 R 458 0 R] ->> -endobj - -458 0 obj -<< - /Type /StructElem - /S /LBody - /P 457 0 R - /K [459 0 R] ->> -endobj - -459 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 458 0 R - /K [8 461 0 R 11 460 0 R 13] - /Pg 5189 0 R ->> -endobj - -460 0 obj -<< - /Type /StructElem - /S /Link - /P 459 0 R - /K [12 << - /Type /OBJR - /Pg 5189 0 R - /Obj 5160 0 R - >>] - /Pg 5189 0 R ->> -endobj - -461 0 obj -<< - /Type /StructElem - /S /Em - /P 459 0 R - /K [9 10] - /Pg 5189 0 R ->> -endobj - -462 0 obj -<< - /Type /StructElem - /S /Lbl - /P 457 0 R - /K [463 0 R] ->> -endobj - -463 0 obj -<< - /Type /StructElem - /S /Link - /P 462 0 R - /K [7 << - /Type /OBJR - /Pg 5189 0 R - /Obj 5159 0 R - >>] - /Pg 5189 0 R ->> -endobj - -464 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [469 0 R 465 0 R] ->> -endobj - -465 0 obj -<< - /Type /StructElem - /S /LBody - /P 464 0 R - /K [466 0 R] ->> -endobj - -466 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 465 0 R - /K [1 468 0 R 4 467 0 R 6] - /Pg 5189 0 R ->> -endobj - -467 0 obj -<< - /Type /StructElem - /S /Link - /P 466 0 R - /K [5 << - /Type /OBJR - /Pg 5189 0 R - /Obj 5158 0 R - >>] - /Pg 5189 0 R ->> -endobj - -468 0 obj -<< - /Type /StructElem - /S /Em - /P 466 0 R - /K [2 3] - /Pg 5189 0 R ->> -endobj - -469 0 obj -<< - /Type /StructElem - /S /Lbl - /P 464 0 R - /K [470 0 R] ->> -endobj - -470 0 obj -<< - /Type /StructElem - /S /Link - /P 469 0 R - /K [0 << - /Type /OBJR - /Pg 5189 0 R - /Obj 5157 0 R - >>] - /Pg 5189 0 R ->> -endobj - -471 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [475 0 R 472 0 R] ->> -endobj - -472 0 obj -<< - /Type /StructElem - /S /LBody - /P 471 0 R - /K [473 0 R] ->> -endobj - -473 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 472 0 R - /K [95 96 474 0 R 99] - /Pg 5155 0 R ->> -endobj - -474 0 obj -<< - /Type /StructElem - /S /Em - /P 473 0 R - /K [97 98] - /Pg 5155 0 R ->> -endobj - -475 0 obj -<< - /Type /StructElem - /S /Lbl - /P 471 0 R - /K [476 0 R] ->> -endobj - -476 0 obj -<< - /Type /StructElem - /S /Link - /P 475 0 R - /K [94 << - /Type /OBJR - /Pg 5155 0 R - /Obj 5154 0 R - >>] - /Pg 5155 0 R ->> -endobj - -477 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [482 0 R 478 0 R] ->> -endobj - -478 0 obj -<< - /Type /StructElem - /S /LBody - /P 477 0 R - /K [479 0 R] ->> -endobj - -479 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 478 0 R - /K [87 88 481 0 R 90 91 480 0 R 93] - /Pg 5155 0 R ->> -endobj - -480 0 obj -<< - /Type /StructElem - /S /Link - /P 479 0 R - /K [92 << - /Type /OBJR - /Pg 5155 0 R - /Obj 5153 0 R - >>] - /Pg 5155 0 R ->> -endobj - -481 0 obj -<< - /Type /StructElem - /S /Em - /P 479 0 R - /K [89] - /Pg 5155 0 R ->> -endobj - -482 0 obj -<< - /Type /StructElem - /S /Lbl - /P 477 0 R - /K [483 0 R] ->> -endobj - -483 0 obj -<< - /Type /StructElem - /S /Link - /P 482 0 R - /K [86 << - /Type /OBJR - /Pg 5155 0 R - /Obj 5152 0 R - >>] - /Pg 5155 0 R ->> -endobj - -484 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [488 0 R 485 0 R] ->> -endobj - -485 0 obj -<< - /Type /StructElem - /S /LBody - /P 484 0 R - /K [486 0 R] ->> -endobj - -486 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 485 0 R - /K [81 82 83 487 0 R 85] - /Pg 5155 0 R ->> -endobj - -487 0 obj -<< - /Type /StructElem - /S /Em - /P 486 0 R - /K [84] - /Pg 5155 0 R ->> -endobj - -488 0 obj -<< - /Type /StructElem - /S /Lbl - /P 484 0 R - /K [489 0 R] ->> -endobj - -489 0 obj -<< - /Type /StructElem - /S /Link - /P 488 0 R - /K [80 << - /Type /OBJR - /Pg 5155 0 R - /Obj 5151 0 R - >>] - /Pg 5155 0 R ->> -endobj - -490 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [494 0 R 491 0 R] ->> -endobj - -491 0 obj -<< - /Type /StructElem - /S /LBody - /P 490 0 R - /K [492 0 R] ->> -endobj - -492 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 491 0 R - /K [76 493 0 R 79] - /Pg 5155 0 R ->> -endobj - -493 0 obj -<< - /Type /StructElem - /S /Em - /P 492 0 R - /K [77 78] - /Pg 5155 0 R ->> -endobj - -494 0 obj -<< - /Type /StructElem - /S /Lbl - /P 490 0 R - /K [495 0 R] ->> -endobj - -495 0 obj -<< - /Type /StructElem - /S /Link - /P 494 0 R - /K [75 << - /Type /OBJR - /Pg 5155 0 R - /Obj 5150 0 R - >>] - /Pg 5155 0 R ->> -endobj - -496 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [500 0 R 497 0 R] ->> -endobj - -497 0 obj -<< - /Type /StructElem - /S /LBody - /P 496 0 R - /K [498 0 R] ->> -endobj - -498 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 497 0 R - /K [71 72 499 0 R 74] - /Pg 5155 0 R ->> -endobj - -499 0 obj -<< - /Type /StructElem - /S /Em - /P 498 0 R - /K [73] - /Pg 5155 0 R ->> -endobj - -500 0 obj -<< - /Type /StructElem - /S /Lbl - /P 496 0 R - /K [501 0 R] ->> -endobj - -501 0 obj -<< - /Type /StructElem - /S /Link - /P 500 0 R - /K [70 << - /Type /OBJR - /Pg 5155 0 R - /Obj 5149 0 R - >>] - /Pg 5155 0 R ->> -endobj - -502 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [507 0 R 503 0 R] ->> -endobj - -503 0 obj -<< - /Type /StructElem - /S /LBody - /P 502 0 R - /K [504 0 R] ->> -endobj - -504 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 503 0 R - /K [63 64 506 0 R 67 505 0 R 69] - /Pg 5155 0 R ->> -endobj - -505 0 obj -<< - /Type /StructElem - /S /Link - /P 504 0 R - /K [68 << - /Type /OBJR - /Pg 5155 0 R - /Obj 5148 0 R - >>] - /Pg 5155 0 R ->> -endobj - -506 0 obj -<< - /Type /StructElem - /S /Em - /P 504 0 R - /K [65 66] - /Pg 5155 0 R ->> -endobj - -507 0 obj -<< - /Type /StructElem - /S /Lbl - /P 502 0 R - /K [508 0 R] ->> -endobj - -508 0 obj -<< - /Type /StructElem - /S /Link - /P 507 0 R - /K [62 << - /Type /OBJR - /Pg 5155 0 R - /Obj 5147 0 R - >>] - /Pg 5155 0 R ->> -endobj - -509 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [514 0 R 510 0 R] ->> -endobj - -510 0 obj -<< - /Type /StructElem - /S /LBody - /P 509 0 R - /K [511 0 R] ->> -endobj - -511 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 510 0 R - /K [55 56 513 0 R 59 512 0 R 61] - /Pg 5155 0 R ->> -endobj - -512 0 obj -<< - /Type /StructElem - /S /Link - /P 511 0 R - /K [60 << - /Type /OBJR - /Pg 5155 0 R - /Obj 5146 0 R - >>] - /Pg 5155 0 R ->> -endobj - -513 0 obj -<< - /Type /StructElem - /S /Em - /P 511 0 R - /K [57 58] - /Pg 5155 0 R ->> -endobj - -514 0 obj -<< - /Type /StructElem - /S /Lbl - /P 509 0 R - /K [515 0 R] ->> -endobj - -515 0 obj -<< - /Type /StructElem - /S /Link - /P 514 0 R - /K [54 << - /Type /OBJR - /Pg 5155 0 R - /Obj 5145 0 R - >>] - /Pg 5155 0 R ->> -endobj - -516 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [521 0 R 517 0 R] ->> -endobj - -517 0 obj -<< - /Type /StructElem - /S /LBody - /P 516 0 R - /K [518 0 R] ->> -endobj - -518 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 517 0 R - /K [46 47 48 520 0 R 50 51 519 0 R 53] - /Pg 5155 0 R ->> -endobj - -519 0 obj -<< - /Type /StructElem - /S /Link - /P 518 0 R - /K [52 << - /Type /OBJR - /Pg 5155 0 R - /Obj 5144 0 R - >>] - /Pg 5155 0 R ->> -endobj - -520 0 obj -<< - /Type /StructElem - /S /Em - /P 518 0 R - /K [49] - /Pg 5155 0 R ->> -endobj - -521 0 obj -<< - /Type /StructElem - /S /Lbl - /P 516 0 R - /K [522 0 R] ->> -endobj - -522 0 obj -<< - /Type /StructElem - /S /Link - /P 521 0 R - /K [45 << - /Type /OBJR - /Pg 5155 0 R - /Obj 5143 0 R - >>] - /Pg 5155 0 R ->> -endobj - -523 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [527 0 R 524 0 R] ->> -endobj - -524 0 obj -<< - /Type /StructElem - /S /LBody - /P 523 0 R - /K [525 0 R] ->> -endobj - -525 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 524 0 R - /K [42 526 0 R 44] - /Pg 5155 0 R ->> -endobj - -526 0 obj -<< - /Type /StructElem - /S /Em - /P 525 0 R - /K [43] - /Pg 5155 0 R ->> -endobj - -527 0 obj -<< - /Type /StructElem - /S /Lbl - /P 523 0 R - /K [528 0 R] ->> -endobj - -528 0 obj -<< - /Type /StructElem - /S /Link - /P 527 0 R - /K [41 << - /Type /OBJR - /Pg 5155 0 R - /Obj 5142 0 R - >>] - /Pg 5155 0 R ->> -endobj - -529 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [533 0 R 530 0 R] ->> -endobj - -530 0 obj -<< - /Type /StructElem - /S /LBody - /P 529 0 R - /K [531 0 R] ->> -endobj - -531 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 530 0 R - /K [39 532 0 R] - /Pg 5155 0 R ->> -endobj - -532 0 obj -<< - /Type /StructElem - /S /Link - /P 531 0 R - /K [40 << - /Type /OBJR - /Pg 5155 0 R - /Obj 5141 0 R - >>] - /Pg 5155 0 R ->> -endobj - -533 0 obj -<< - /Type /StructElem - /S /Lbl - /P 529 0 R - /K [534 0 R] ->> -endobj - -534 0 obj -<< - /Type /StructElem - /S /Link - /P 533 0 R - /K [38 << - /Type /OBJR - /Pg 5155 0 R - /Obj 5140 0 R - >>] - /Pg 5155 0 R ->> -endobj - -535 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [539 0 R 536 0 R] ->> -endobj - -536 0 obj -<< - /Type /StructElem - /S /LBody - /P 535 0 R - /K [537 0 R] ->> -endobj - -537 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 536 0 R - /K [35 538 0 R] - /Pg 5155 0 R ->> -endobj - -538 0 obj -<< - /Type /StructElem - /S /Link - /P 537 0 R - /K [36 << - /Type /OBJR - /Pg 5155 0 R - /Obj 5138 0 R - >> 37 << - /Type /OBJR - /Pg 5155 0 R - /Obj 5139 0 R - >>] - /Pg 5155 0 R ->> -endobj - -539 0 obj -<< - /Type /StructElem - /S /Lbl - /P 535 0 R - /K [540 0 R] ->> -endobj - -540 0 obj -<< - /Type /StructElem - /S /Link - /P 539 0 R - /K [34 << - /Type /OBJR - /Pg 5155 0 R - /Obj 5137 0 R - >>] - /Pg 5155 0 R ->> -endobj - -541 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [545 0 R 542 0 R] ->> -endobj - -542 0 obj -<< - /Type /StructElem - /S /LBody - /P 541 0 R - /K [543 0 R] ->> -endobj - -543 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 542 0 R - /K [28 544 0 R 32 33] - /Pg 5155 0 R ->> -endobj - -544 0 obj -<< - /Type /StructElem - /S /Em - /P 543 0 R - /K [29 30 31] - /Pg 5155 0 R ->> -endobj - -545 0 obj -<< - /Type /StructElem - /S /Lbl - /P 541 0 R - /K [546 0 R] ->> -endobj - -546 0 obj -<< - /Type /StructElem - /S /Link - /P 545 0 R - /K [27 << - /Type /OBJR - /Pg 5155 0 R - /Obj 5136 0 R - >>] - /Pg 5155 0 R ->> -endobj - -547 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [552 0 R 548 0 R] ->> -endobj - -548 0 obj -<< - /Type /StructElem - /S /LBody - /P 547 0 R - /K [549 0 R] ->> -endobj - -549 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 548 0 R - /K [19 20 551 0 R 23 24 550 0 R 26] - /Pg 5155 0 R ->> -endobj - -550 0 obj -<< - /Type /StructElem - /S /Link - /P 549 0 R - /K [25 << - /Type /OBJR - /Pg 5155 0 R - /Obj 5135 0 R - >>] - /Pg 5155 0 R ->> -endobj - -551 0 obj -<< - /Type /StructElem - /S /Em - /P 549 0 R - /K [21 22] - /Pg 5155 0 R ->> -endobj - -552 0 obj -<< - /Type /StructElem - /S /Lbl - /P 547 0 R - /K [553 0 R] ->> -endobj - -553 0 obj -<< - /Type /StructElem - /S /Link - /P 552 0 R - /K [18 << - /Type /OBJR - /Pg 5155 0 R - /Obj 5134 0 R - >>] - /Pg 5155 0 R ->> -endobj - -554 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [558 0 R 555 0 R] ->> -endobj - -555 0 obj -<< - /Type /StructElem - /S /LBody - /P 554 0 R - /K [556 0 R] ->> -endobj - -556 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 555 0 R - /K [14 15 16 557 0 R] - /Pg 5155 0 R ->> -endobj - -557 0 obj -<< - /Type /StructElem - /S /Link - /P 556 0 R - /K [17 << - /Type /OBJR - /Pg 5155 0 R - /Obj 5133 0 R - >>] - /Pg 5155 0 R ->> -endobj - -558 0 obj -<< - /Type /StructElem - /S /Lbl - /P 554 0 R - /K [559 0 R] ->> -endobj - -559 0 obj -<< - /Type /StructElem - /S /Link - /P 558 0 R - /K [13 << - /Type /OBJR - /Pg 5155 0 R - /Obj 5132 0 R - >>] - /Pg 5155 0 R ->> -endobj - -560 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [564 0 R 561 0 R] ->> -endobj - -561 0 obj -<< - /Type /StructElem - /S /LBody - /P 560 0 R - /K [562 0 R] ->> -endobj - -562 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 561 0 R - /K [8 563 0 R 12] - /Pg 5155 0 R ->> -endobj - -563 0 obj -<< - /Type /StructElem - /S /Em - /P 562 0 R - /K [9 10 11] - /Pg 5155 0 R ->> -endobj - -564 0 obj -<< - /Type /StructElem - /S /Lbl - /P 560 0 R - /K [565 0 R] ->> -endobj - -565 0 obj -<< - /Type /StructElem - /S /Link - /P 564 0 R - /K [7 << - /Type /OBJR - /Pg 5155 0 R - /Obj 5131 0 R - >>] - /Pg 5155 0 R ->> -endobj - -566 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [571 0 R 567 0 R] ->> -endobj - -567 0 obj -<< - /Type /StructElem - /S /LBody - /P 566 0 R - /K [568 0 R] ->> -endobj - -568 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 567 0 R - /K [1 570 0 R 4 569 0 R 6] - /Pg 5155 0 R ->> -endobj - -569 0 obj -<< - /Type /StructElem - /S /Link - /P 568 0 R - /K [5 << - /Type /OBJR - /Pg 5155 0 R - /Obj 5130 0 R - >>] - /Pg 5155 0 R ->> -endobj - -570 0 obj -<< - /Type /StructElem - /S /Em - /P 568 0 R - /K [2 3] - /Pg 5155 0 R ->> -endobj - -571 0 obj -<< - /Type /StructElem - /S /Lbl - /P 566 0 R - /K [572 0 R] ->> -endobj - -572 0 obj -<< - /Type /StructElem - /S /Link - /P 571 0 R - /K [0 << - /Type /OBJR - /Pg 5155 0 R - /Obj 5129 0 R - >>] - /Pg 5155 0 R ->> -endobj - -573 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [578 0 R 574 0 R] ->> -endobj - -574 0 obj -<< - /Type /StructElem - /S /LBody - /P 573 0 R - /K [575 0 R] ->> -endobj - -575 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 574 0 R - /K [105 577 0 R 108 576 0 R 110] - /Pg 5127 0 R ->> -endobj - -576 0 obj -<< - /Type /StructElem - /S /Link - /P 575 0 R - /K [109 << - /Type /OBJR - /Pg 5127 0 R - /Obj 5126 0 R - >>] - /Pg 5127 0 R ->> -endobj - -577 0 obj -<< - /Type /StructElem - /S /Em - /P 575 0 R - /K [106 107] - /Pg 5127 0 R ->> -endobj - -578 0 obj -<< - /Type /StructElem - /S /Lbl - /P 573 0 R - /K [579 0 R] ->> -endobj - -579 0 obj -<< - /Type /StructElem - /S /Link - /P 578 0 R - /K [104 << - /Type /OBJR - /Pg 5127 0 R - /Obj 5125 0 R - >>] - /Pg 5127 0 R ->> -endobj - -580 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [585 0 R 581 0 R] ->> -endobj - -581 0 obj -<< - /Type /StructElem - /S /LBody - /P 580 0 R - /K [582 0 R] ->> -endobj - -582 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 581 0 R - /K [98 584 0 R 100 101 583 0 R 103] - /Pg 5127 0 R ->> -endobj - -583 0 obj -<< - /Type /StructElem - /S /Link - /P 582 0 R - /K [102 << - /Type /OBJR - /Pg 5127 0 R - /Obj 5124 0 R - >>] - /Pg 5127 0 R ->> -endobj - -584 0 obj -<< - /Type /StructElem - /S /Em - /P 582 0 R - /K [99] - /Pg 5127 0 R ->> -endobj - -585 0 obj -<< - /Type /StructElem - /S /Lbl - /P 580 0 R - /K [586 0 R] ->> -endobj - -586 0 obj -<< - /Type /StructElem - /S /Link - /P 585 0 R - /K [97 << - /Type /OBJR - /Pg 5127 0 R - /Obj 5123 0 R - >>] - /Pg 5127 0 R ->> -endobj - -587 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [592 0 R 588 0 R] ->> -endobj - -588 0 obj -<< - /Type /StructElem - /S /LBody - /P 587 0 R - /K [589 0 R] ->> -endobj - -589 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 588 0 R - /K [90 591 0 R 93 94 590 0 R 96] - /Pg 5127 0 R ->> -endobj - -590 0 obj -<< - /Type /StructElem - /S /Link - /P 589 0 R - /K [95 << - /Type /OBJR - /Pg 5127 0 R - /Obj 5122 0 R - >>] - /Pg 5127 0 R ->> -endobj - -591 0 obj -<< - /Type /StructElem - /S /Em - /P 589 0 R - /K [91 92] - /Pg 5127 0 R ->> -endobj - -592 0 obj -<< - /Type /StructElem - /S /Lbl - /P 587 0 R - /K [593 0 R] ->> -endobj - -593 0 obj -<< - /Type /StructElem - /S /Link - /P 592 0 R - /K [89 << - /Type /OBJR - /Pg 5127 0 R - /Obj 5121 0 R - >>] - /Pg 5127 0 R ->> -endobj - -594 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [599 0 R 595 0 R] ->> -endobj - -595 0 obj -<< - /Type /StructElem - /S /LBody - /P 594 0 R - /K [596 0 R] ->> -endobj - -596 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 595 0 R - /K [83 84 598 0 R 86 597 0 R 88] - /Pg 5127 0 R ->> -endobj - -597 0 obj -<< - /Type /StructElem - /S /Link - /P 596 0 R - /K [87 << - /Type /OBJR - /Pg 5127 0 R - /Obj 5120 0 R - >>] - /Pg 5127 0 R ->> -endobj - -598 0 obj -<< - /Type /StructElem - /S /Em - /P 596 0 R - /K [85] - /Pg 5127 0 R ->> -endobj - -599 0 obj -<< - /Type /StructElem - /S /Lbl - /P 594 0 R - /K [600 0 R] ->> -endobj - -600 0 obj -<< - /Type /StructElem - /S /Link - /P 599 0 R - /K [82 << - /Type /OBJR - /Pg 5127 0 R - /Obj 5119 0 R - >>] - /Pg 5127 0 R ->> -endobj - -601 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [606 0 R 602 0 R] ->> -endobj - -602 0 obj -<< - /Type /StructElem - /S /LBody - /P 601 0 R - /K [603 0 R] ->> -endobj - -603 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 602 0 R - /K [75 76 605 0 R 79 604 0 R 81] - /Pg 5127 0 R ->> -endobj - -604 0 obj -<< - /Type /StructElem - /S /Link - /P 603 0 R - /K [80 << - /Type /OBJR - /Pg 5127 0 R - /Obj 5118 0 R - >>] - /Pg 5127 0 R ->> -endobj - -605 0 obj -<< - /Type /StructElem - /S /Em - /P 603 0 R - /K [77 78] - /Pg 5127 0 R ->> -endobj - -606 0 obj -<< - /Type /StructElem - /S /Lbl - /P 601 0 R - /K [607 0 R] ->> -endobj - -607 0 obj -<< - /Type /StructElem - /S /Link - /P 606 0 R - /K [74 << - /Type /OBJR - /Pg 5127 0 R - /Obj 5117 0 R - >>] - /Pg 5127 0 R ->> -endobj - -608 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [613 0 R 609 0 R] ->> -endobj - -609 0 obj -<< - /Type /StructElem - /S /LBody - /P 608 0 R - /K [610 0 R] ->> -endobj - -610 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 609 0 R - /K [67 612 0 R 71 611 0 R 73] - /Pg 5127 0 R ->> -endobj - -611 0 obj -<< - /Type /StructElem - /S /Link - /P 610 0 R - /K [72 << - /Type /OBJR - /Pg 5127 0 R - /Obj 5116 0 R - >>] - /Pg 5127 0 R ->> -endobj - -612 0 obj -<< - /Type /StructElem - /S /Em - /P 610 0 R - /K [68 69 70] - /Pg 5127 0 R ->> -endobj - -613 0 obj -<< - /Type /StructElem - /S /Lbl - /P 608 0 R - /K [614 0 R] ->> -endobj - -614 0 obj -<< - /Type /StructElem - /S /Link - /P 613 0 R - /K [66 << - /Type /OBJR - /Pg 5127 0 R - /Obj 5115 0 R - >>] - /Pg 5127 0 R ->> -endobj - -615 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [620 0 R 616 0 R] ->> -endobj - -616 0 obj -<< - /Type /StructElem - /S /LBody - /P 615 0 R - /K [617 0 R] ->> -endobj - -617 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 616 0 R - /K [58 59 619 0 R 62 63 618 0 R 65] - /Pg 5127 0 R ->> -endobj - -618 0 obj -<< - /Type /StructElem - /S /Link - /P 617 0 R - /K [64 << - /Type /OBJR - /Pg 5127 0 R - /Obj 5114 0 R - >>] - /Pg 5127 0 R ->> -endobj - -619 0 obj -<< - /Type /StructElem - /S /Em - /P 617 0 R - /K [60 61] - /Pg 5127 0 R ->> -endobj - -620 0 obj -<< - /Type /StructElem - /S /Lbl - /P 615 0 R - /K [621 0 R] ->> -endobj - -621 0 obj -<< - /Type /StructElem - /S /Link - /P 620 0 R - /K [57 << - /Type /OBJR - /Pg 5127 0 R - /Obj 5113 0 R - >>] - /Pg 5127 0 R ->> -endobj - -622 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [628 0 R 623 0 R] ->> -endobj - -623 0 obj -<< - /Type /StructElem - /S /LBody - /P 622 0 R - /K [624 0 R] ->> -endobj - -624 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 623 0 R - /K [49 627 0 R 51 626 0 R 54 625 0 R 56] - /Pg 5127 0 R ->> -endobj - -625 0 obj -<< - /Type /StructElem - /S /Link - /P 624 0 R - /K [55 << - /Type /OBJR - /Pg 5127 0 R - /Obj 5112 0 R - >>] - /Pg 5127 0 R ->> -endobj - -626 0 obj -<< - /Type /StructElem - /S /Em - /P 624 0 R - /K [52 53] - /Pg 5127 0 R ->> -endobj - -627 0 obj -<< - /Type /StructElem - /S /Em - /P 624 0 R - /K [50] - /Pg 5127 0 R ->> -endobj - -628 0 obj -<< - /Type /StructElem - /S /Lbl - /P 622 0 R - /K [629 0 R] ->> -endobj - -629 0 obj -<< - /Type /StructElem - /S /Link - /P 628 0 R - /K [48 << - /Type /OBJR - /Pg 5127 0 R - /Obj 5111 0 R - >>] - /Pg 5127 0 R ->> -endobj - -630 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [635 0 R 631 0 R] ->> -endobj - -631 0 obj -<< - /Type /StructElem - /S /LBody - /P 630 0 R - /K [632 0 R] ->> -endobj - -632 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 631 0 R - /K [42 634 0 R 45 633 0 R 47] - /Pg 5127 0 R ->> -endobj - -633 0 obj -<< - /Type /StructElem - /S /Link - /P 632 0 R - /K [46 << - /Type /OBJR - /Pg 5127 0 R - /Obj 5110 0 R - >>] - /Pg 5127 0 R ->> -endobj - -634 0 obj -<< - /Type /StructElem - /S /Em - /P 632 0 R - /K [43 44] - /Pg 5127 0 R ->> -endobj - -635 0 obj -<< - /Type /StructElem - /S /Lbl - /P 630 0 R - /K [636 0 R] ->> -endobj - -636 0 obj -<< - /Type /StructElem - /S /Link - /P 635 0 R - /K [41 << - /Type /OBJR - /Pg 5127 0 R - /Obj 5109 0 R - >>] - /Pg 5127 0 R ->> -endobj - -637 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [642 0 R 638 0 R] ->> -endobj - -638 0 obj -<< - /Type /StructElem - /S /LBody - /P 637 0 R - /K [639 0 R] ->> -endobj - -639 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 638 0 R - /K [34 641 0 R 37 38 640 0 R 40] - /Pg 5127 0 R ->> -endobj - -640 0 obj -<< - /Type /StructElem - /S /Link - /P 639 0 R - /K [39 << - /Type /OBJR - /Pg 5127 0 R - /Obj 5108 0 R - >>] - /Pg 5127 0 R ->> -endobj - -641 0 obj -<< - /Type /StructElem - /S /Em - /P 639 0 R - /K [35 36] - /Pg 5127 0 R ->> -endobj - -642 0 obj -<< - /Type /StructElem - /S /Lbl - /P 637 0 R - /K [643 0 R] ->> -endobj - -643 0 obj -<< - /Type /StructElem - /S /Link - /P 642 0 R - /K [33 << - /Type /OBJR - /Pg 5127 0 R - /Obj 5107 0 R - >>] - /Pg 5127 0 R ->> -endobj - -644 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [649 0 R 645 0 R] ->> -endobj - -645 0 obj -<< - /Type /StructElem - /S /LBody - /P 644 0 R - /K [646 0 R] ->> -endobj - -646 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 645 0 R - /K [25 648 0 R 29 647 0 R 32] - /Pg 5127 0 R ->> -endobj - -647 0 obj -<< - /Type /StructElem - /S /Link - /P 646 0 R - /K [30 << - /Type /OBJR - /Pg 5127 0 R - /Obj 5105 0 R - >> 31 << - /Type /OBJR - /Pg 5127 0 R - /Obj 5106 0 R - >>] - /Pg 5127 0 R ->> -endobj - -648 0 obj -<< - /Type /StructElem - /S /Em - /P 646 0 R - /K [26 27 28] - /Pg 5127 0 R ->> -endobj - -649 0 obj -<< - /Type /StructElem - /S /Lbl - /P 644 0 R - /K [650 0 R] ->> -endobj - -650 0 obj -<< - /Type /StructElem - /S /Link - /P 649 0 R - /K [24 << - /Type /OBJR - /Pg 5127 0 R - /Obj 5104 0 R - >>] - /Pg 5127 0 R ->> -endobj - -651 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [656 0 R 652 0 R] ->> -endobj - -652 0 obj -<< - /Type /StructElem - /S /LBody - /P 651 0 R - /K [653 0 R] ->> -endobj - -653 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 652 0 R - /K [18 655 0 R 20 654 0 R 23] - /Pg 5127 0 R ->> -endobj - -654 0 obj -<< - /Type /StructElem - /S /Link - /P 653 0 R - /K [21 << - /Type /OBJR - /Pg 5127 0 R - /Obj 5102 0 R - >> 22 << - /Type /OBJR - /Pg 5127 0 R - /Obj 5103 0 R - >>] - /Pg 5127 0 R ->> -endobj - -655 0 obj -<< - /Type /StructElem - /S /Em - /P 653 0 R - /K [19] - /Pg 5127 0 R ->> -endobj - -656 0 obj -<< - /Type /StructElem - /S /Lbl - /P 651 0 R - /K [657 0 R] ->> -endobj - -657 0 obj -<< - /Type /StructElem - /S /Link - /P 656 0 R - /K [17 << - /Type /OBJR - /Pg 5127 0 R - /Obj 5101 0 R - >>] - /Pg 5127 0 R ->> -endobj - -658 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [663 0 R 659 0 R] ->> -endobj - -659 0 obj -<< - /Type /StructElem - /S /LBody - /P 658 0 R - /K [660 0 R] ->> -endobj - -660 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 659 0 R - /K [10 662 0 R 13 14 661 0 R 16] - /Pg 5127 0 R ->> -endobj - -661 0 obj -<< - /Type /StructElem - /S /Link - /P 660 0 R - /K [15 << - /Type /OBJR - /Pg 5127 0 R - /Obj 5100 0 R - >>] - /Pg 5127 0 R ->> -endobj - -662 0 obj -<< - /Type /StructElem - /S /Em - /P 660 0 R - /K [11 12] - /Pg 5127 0 R ->> -endobj - -663 0 obj -<< - /Type /StructElem - /S /Lbl - /P 658 0 R - /K [664 0 R] ->> -endobj - -664 0 obj -<< - /Type /StructElem - /S /Link - /P 663 0 R - /K [9 << - /Type /OBJR - /Pg 5127 0 R - /Obj 5099 0 R - >>] - /Pg 5127 0 R ->> -endobj - -665 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [670 0 R 666 0 R] ->> -endobj - -666 0 obj -<< - /Type /StructElem - /S /LBody - /P 665 0 R - /K [667 0 R] ->> -endobj - -667 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 666 0 R - /K [1 669 0 R 4 5 6 668 0 R 8] - /Pg 5127 0 R ->> -endobj - -668 0 obj -<< - /Type /StructElem - /S /Link - /P 667 0 R - /K [7 << - /Type /OBJR - /Pg 5127 0 R - /Obj 5098 0 R - >>] - /Pg 5127 0 R ->> -endobj - -669 0 obj -<< - /Type /StructElem - /S /Em - /P 667 0 R - /K [2 3] - /Pg 5127 0 R ->> -endobj - -670 0 obj -<< - /Type /StructElem - /S /Lbl - /P 665 0 R - /K [671 0 R] ->> -endobj - -671 0 obj -<< - /Type /StructElem - /S /Link - /P 670 0 R - /K [0 << - /Type /OBJR - /Pg 5127 0 R - /Obj 5097 0 R - >>] - /Pg 5127 0 R ->> -endobj - -672 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [676 0 R 673 0 R] ->> -endobj - -673 0 obj -<< - /Type /StructElem - /S /LBody - /P 672 0 R - /K [674 0 R] ->> -endobj - -674 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 673 0 R - /K [107 675 0 R 109 110] - /Pg 5095 0 R ->> -endobj - -675 0 obj -<< - /Type /StructElem - /S /Em - /P 674 0 R - /K [108] - /Pg 5095 0 R ->> -endobj - -676 0 obj -<< - /Type /StructElem - /S /Lbl - /P 672 0 R - /K [677 0 R] ->> -endobj - -677 0 obj -<< - /Type /StructElem - /S /Link - /P 676 0 R - /K [106 << - /Type /OBJR - /Pg 5095 0 R - /Obj 5094 0 R - >>] - /Pg 5095 0 R ->> -endobj - -678 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [683 0 R 679 0 R] ->> -endobj - -679 0 obj -<< - /Type /StructElem - /S /LBody - /P 678 0 R - /K [680 0 R] ->> -endobj - -680 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 679 0 R - /K [98 682 0 R 101 102 103 681 0 R 105] - /Pg 5095 0 R ->> -endobj - -681 0 obj -<< - /Type /StructElem - /S /Link - /P 680 0 R - /K [104 << - /Type /OBJR - /Pg 5095 0 R - /Obj 5093 0 R - >>] - /Pg 5095 0 R ->> -endobj - -682 0 obj -<< - /Type /StructElem - /S /Em - /P 680 0 R - /K [99 100] - /Pg 5095 0 R ->> -endobj - -683 0 obj -<< - /Type /StructElem - /S /Lbl - /P 678 0 R - /K [684 0 R] ->> -endobj - -684 0 obj -<< - /Type /StructElem - /S /Link - /P 683 0 R - /K [97 << - /Type /OBJR - /Pg 5095 0 R - /Obj 5092 0 R - >>] - /Pg 5095 0 R ->> -endobj - -685 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [689 0 R 686 0 R] ->> -endobj - -686 0 obj -<< - /Type /StructElem - /S /LBody - /P 685 0 R - /K [687 0 R] ->> -endobj - -687 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 686 0 R - /K [94 688 0 R 96] - /Pg 5095 0 R ->> -endobj - -688 0 obj -<< - /Type /StructElem - /S /Em - /P 687 0 R - /K [95] - /Pg 5095 0 R ->> -endobj - -689 0 obj -<< - /Type /StructElem - /S /Lbl - /P 685 0 R - /K [690 0 R] ->> -endobj - -690 0 obj -<< - /Type /StructElem - /S /Link - /P 689 0 R - /K [93 << - /Type /OBJR - /Pg 5095 0 R - /Obj 5091 0 R - >>] - /Pg 5095 0 R ->> -endobj - -691 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [696 0 R 692 0 R] ->> -endobj - -692 0 obj -<< - /Type /StructElem - /S /LBody - /P 691 0 R - /K [693 0 R] ->> -endobj - -693 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 692 0 R - /K [87 695 0 R 89 90 694 0 R 92] - /Pg 5095 0 R ->> -endobj - -694 0 obj -<< - /Type /StructElem - /S /Link - /P 693 0 R - /K [91 << - /Type /OBJR - /Pg 5095 0 R - /Obj 5090 0 R - >>] - /Pg 5095 0 R ->> -endobj - -695 0 obj -<< - /Type /StructElem - /S /Em - /P 693 0 R - /K [88] - /Pg 5095 0 R ->> -endobj - -696 0 obj -<< - /Type /StructElem - /S /Lbl - /P 691 0 R - /K [697 0 R] ->> -endobj - -697 0 obj -<< - /Type /StructElem - /S /Link - /P 696 0 R - /K [86 << - /Type /OBJR - /Pg 5095 0 R - /Obj 5089 0 R - >>] - /Pg 5095 0 R ->> -endobj - -698 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [703 0 R 699 0 R] ->> -endobj - -699 0 obj -<< - /Type /StructElem - /S /LBody - /P 698 0 R - /K [700 0 R] ->> -endobj - -700 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 699 0 R - /K [77 78 702 0 R 81 82 83 701 0 R 85] - /Pg 5095 0 R ->> -endobj - -701 0 obj -<< - /Type /StructElem - /S /Link - /P 700 0 R - /K [84 << - /Type /OBJR - /Pg 5095 0 R - /Obj 5088 0 R - >>] - /Pg 5095 0 R ->> -endobj - -702 0 obj -<< - /Type /StructElem - /S /Em - /P 700 0 R - /K [79 80] - /Pg 5095 0 R ->> -endobj - -703 0 obj -<< - /Type /StructElem - /S /Lbl - /P 698 0 R - /K [704 0 R] ->> -endobj - -704 0 obj -<< - /Type /StructElem - /S /Link - /P 703 0 R - /K [76 << - /Type /OBJR - /Pg 5095 0 R - /Obj 5087 0 R - >>] - /Pg 5095 0 R ->> -endobj - -705 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [710 0 R 706 0 R] ->> -endobj - -706 0 obj -<< - /Type /StructElem - /S /LBody - /P 705 0 R - /K [707 0 R] ->> -endobj - -707 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 706 0 R - /K [68 69 709 0 R 72 73 708 0 R 75] - /Pg 5095 0 R ->> -endobj - -708 0 obj -<< - /Type /StructElem - /S /Link - /P 707 0 R - /K [74 << - /Type /OBJR - /Pg 5095 0 R - /Obj 5086 0 R - >>] - /Pg 5095 0 R ->> -endobj - -709 0 obj -<< - /Type /StructElem - /S /Em - /P 707 0 R - /K [70 71] - /Pg 5095 0 R ->> -endobj - -710 0 obj -<< - /Type /StructElem - /S /Lbl - /P 705 0 R - /K [711 0 R] ->> -endobj - -711 0 obj -<< - /Type /StructElem - /S /Link - /P 710 0 R - /K [67 << - /Type /OBJR - /Pg 5095 0 R - /Obj 5085 0 R - >>] - /Pg 5095 0 R ->> -endobj - -712 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [716 0 R 713 0 R] ->> -endobj - -713 0 obj -<< - /Type /StructElem - /S /LBody - /P 712 0 R - /K [714 0 R] ->> -endobj - -714 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 713 0 R - /K [62 715 0 R 65 66] - /Pg 5095 0 R ->> -endobj - -715 0 obj -<< - /Type /StructElem - /S /Em - /P 714 0 R - /K [63 64] - /Pg 5095 0 R ->> -endobj - -716 0 obj -<< - /Type /StructElem - /S /Lbl - /P 712 0 R - /K [717 0 R] ->> -endobj - -717 0 obj -<< - /Type /StructElem - /S /Link - /P 716 0 R - /K [61 << - /Type /OBJR - /Pg 5095 0 R - /Obj 5084 0 R - >>] - /Pg 5095 0 R ->> -endobj - -718 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [723 0 R 719 0 R] ->> -endobj - -719 0 obj -<< - /Type /StructElem - /S /LBody - /P 718 0 R - /K [720 0 R] ->> -endobj - -720 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 719 0 R - /K [55 722 0 R 57 58 721 0 R 60] - /Pg 5095 0 R ->> -endobj - -721 0 obj -<< - /Type /StructElem - /S /Link - /P 720 0 R - /K [59 << - /Type /OBJR - /Pg 5095 0 R - /Obj 5083 0 R - >>] - /Pg 5095 0 R ->> -endobj - -722 0 obj -<< - /Type /StructElem - /S /Em - /P 720 0 R - /K [56] - /Pg 5095 0 R ->> -endobj - -723 0 obj -<< - /Type /StructElem - /S /Lbl - /P 718 0 R - /K [724 0 R] ->> -endobj - -724 0 obj -<< - /Type /StructElem - /S /Link - /P 723 0 R - /K [54 << - /Type /OBJR - /Pg 5095 0 R - /Obj 5082 0 R - >>] - /Pg 5095 0 R ->> -endobj - -725 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [728 0 R 726 0 R] ->> -endobj - -726 0 obj -<< - /Type /StructElem - /S /LBody - /P 725 0 R - /K [727 0 R] ->> -endobj - -727 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 726 0 R - /K [52 53] - /Pg 5095 0 R ->> -endobj - -728 0 obj -<< - /Type /StructElem - /S /Lbl - /P 725 0 R - /K [729 0 R] ->> -endobj - -729 0 obj -<< - /Type /StructElem - /S /Link - /P 728 0 R - /K [51 << - /Type /OBJR - /Pg 5095 0 R - /Obj 5081 0 R - >>] - /Pg 5095 0 R ->> -endobj - -730 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [734 0 R 731 0 R] ->> -endobj - -731 0 obj -<< - /Type /StructElem - /S /LBody - /P 730 0 R - /K [732 0 R] ->> -endobj - -732 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 731 0 R - /K [46 47 733 0 R 49 50] - /Pg 5095 0 R ->> -endobj - -733 0 obj -<< - /Type /StructElem - /S /Em - /P 732 0 R - /K [48] - /Pg 5095 0 R ->> -endobj - -734 0 obj -<< - /Type /StructElem - /S /Lbl - /P 730 0 R - /K [735 0 R] ->> -endobj - -735 0 obj -<< - /Type /StructElem - /S /Link - /P 734 0 R - /K [45 << - /Type /OBJR - /Pg 5095 0 R - /Obj 5080 0 R - >>] - /Pg 5095 0 R ->> -endobj - -736 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [742 0 R 737 0 R] ->> -endobj - -737 0 obj -<< - /Type /StructElem - /S /LBody - /P 736 0 R - /K [738 0 R] ->> -endobj - -738 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 737 0 R - /K [36 741 0 R 38 39 740 0 R 42 739 0 R 44] - /Pg 5095 0 R ->> -endobj - -739 0 obj -<< - /Type /StructElem - /S /Link - /P 738 0 R - /K [43 << - /Type /OBJR - /Pg 5095 0 R - /Obj 5079 0 R - >>] - /Pg 5095 0 R ->> -endobj - -740 0 obj -<< - /Type /StructElem - /S /Em - /P 738 0 R - /K [40 41] - /Pg 5095 0 R ->> -endobj - -741 0 obj -<< - /Type /StructElem - /S /Em - /P 738 0 R - /K [37] - /Pg 5095 0 R ->> -endobj - -742 0 obj -<< - /Type /StructElem - /S /Lbl - /P 736 0 R - /K [743 0 R] ->> -endobj - -743 0 obj -<< - /Type /StructElem - /S /Link - /P 742 0 R - /K [35 << - /Type /OBJR - /Pg 5095 0 R - /Obj 5078 0 R - >>] - /Pg 5095 0 R ->> -endobj - -744 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [748 0 R 745 0 R] ->> -endobj - -745 0 obj -<< - /Type /StructElem - /S /LBody - /P 744 0 R - /K [746 0 R] ->> -endobj - -746 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 745 0 R - /K [31 32 747 0 R 34] - /Pg 5095 0 R ->> -endobj - -747 0 obj -<< - /Type /StructElem - /S /Em - /P 746 0 R - /K [33] - /Pg 5095 0 R ->> -endobj - -748 0 obj -<< - /Type /StructElem - /S /Lbl - /P 744 0 R - /K [749 0 R] ->> -endobj - -749 0 obj -<< - /Type /StructElem - /S /Link - /P 748 0 R - /K [30 << - /Type /OBJR - /Pg 5095 0 R - /Obj 5077 0 R - >>] - /Pg 5095 0 R ->> -endobj - -750 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [756 0 R 751 0 R] ->> -endobj - -751 0 obj -<< - /Type /StructElem - /S /LBody - /P 750 0 R - /K [752 0 R] ->> -endobj - -752 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 751 0 R - /K [22 755 0 R 24 754 0 R 26 27 753 0 R 29] - /Pg 5095 0 R ->> -endobj - -753 0 obj -<< - /Type /StructElem - /S /Link - /P 752 0 R - /K [28 << - /Type /OBJR - /Pg 5095 0 R - /Obj 5076 0 R - >>] - /Pg 5095 0 R ->> -endobj - -754 0 obj -<< - /Type /StructElem - /S /Em - /P 752 0 R - /K [25] - /Pg 5095 0 R ->> -endobj - -755 0 obj -<< - /Type /StructElem - /S /Em - /P 752 0 R - /K [23] - /Pg 5095 0 R ->> -endobj - -756 0 obj -<< - /Type /StructElem - /S /Lbl - /P 750 0 R - /K [757 0 R] ->> -endobj - -757 0 obj -<< - /Type /StructElem - /S /Link - /P 756 0 R - /K [21 << - /Type /OBJR - /Pg 5095 0 R - /Obj 5075 0 R - >>] - /Pg 5095 0 R ->> -endobj - -758 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [764 0 R 759 0 R] ->> -endobj - -759 0 obj -<< - /Type /StructElem - /S /LBody - /P 758 0 R - /K [760 0 R] ->> -endobj - -760 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 759 0 R - /K [12 763 0 R 14 762 0 R 18 761 0 R 20] - /Pg 5095 0 R ->> -endobj - -761 0 obj -<< - /Type /StructElem - /S /Link - /P 760 0 R - /K [19 << - /Type /OBJR - /Pg 5095 0 R - /Obj 5074 0 R - >>] - /Pg 5095 0 R ->> -endobj - -762 0 obj -<< - /Type /StructElem - /S /Em - /P 760 0 R - /K [15 16 17] - /Pg 5095 0 R ->> -endobj - -763 0 obj -<< - /Type /StructElem - /S /Em - /P 760 0 R - /K [13] - /Pg 5095 0 R ->> -endobj - -764 0 obj -<< - /Type /StructElem - /S /Lbl - /P 758 0 R - /K [765 0 R] ->> -endobj - -765 0 obj -<< - /Type /StructElem - /S /Link - /P 764 0 R - /K [11 << - /Type /OBJR - /Pg 5095 0 R - /Obj 5073 0 R - >>] - /Pg 5095 0 R ->> -endobj - -766 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [770 0 R 767 0 R] ->> -endobj - -767 0 obj -<< - /Type /StructElem - /S /LBody - /P 766 0 R - /K [768 0 R] ->> -endobj - -768 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 767 0 R - /K [6 7 8 769 0 R] - /Pg 5095 0 R ->> -endobj - -769 0 obj -<< - /Type /StructElem - /S /Link - /P 768 0 R - /K [9 << - /Type /OBJR - /Pg 5095 0 R - /Obj 5071 0 R - >> 10 << - /Type /OBJR - /Pg 5095 0 R - /Obj 5072 0 R - >>] - /Pg 5095 0 R ->> -endobj - -770 0 obj -<< - /Type /StructElem - /S /Lbl - /P 766 0 R - /K [771 0 R] ->> -endobj - -771 0 obj -<< - /Type /StructElem - /S /Link - /P 770 0 R - /K [5 << - /Type /OBJR - /Pg 5095 0 R - /Obj 5070 0 R - >>] - /Pg 5095 0 R ->> -endobj - -772 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [776 0 R 773 0 R] ->> -endobj - -773 0 obj -<< - /Type /StructElem - /S /LBody - /P 772 0 R - /K [774 0 R] ->> -endobj - -774 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 773 0 R - /K [1 2 3 775 0 R] - /Pg 5095 0 R ->> -endobj - -775 0 obj -<< - /Type /StructElem - /S /Link - /P 774 0 R - /K [4 << - /Type /OBJR - /Pg 5095 0 R - /Obj 5069 0 R - >>] - /Pg 5095 0 R ->> -endobj - -776 0 obj -<< - /Type /StructElem - /S /Lbl - /P 772 0 R - /K [777 0 R] ->> -endobj - -777 0 obj -<< - /Type /StructElem - /S /Link - /P 776 0 R - /K [0 << - /Type /OBJR - /Pg 5095 0 R - /Obj 5068 0 R - >>] - /Pg 5095 0 R ->> -endobj - -778 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [782 0 R 779 0 R] ->> -endobj - -779 0 obj -<< - /Type /StructElem - /S /LBody - /P 778 0 R - /K [780 0 R] ->> -endobj - -780 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 779 0 R - /K [76 781 0 R 78 79] - /Pg 5066 0 R ->> -endobj - -781 0 obj -<< - /Type /StructElem - /S /Em - /P 780 0 R - /K [77] - /Pg 5066 0 R ->> -endobj - -782 0 obj -<< - /Type /StructElem - /S /Lbl - /P 778 0 R - /K [783 0 R] ->> -endobj - -783 0 obj -<< - /Type /StructElem - /S /Link - /P 782 0 R - /K [75 << - /Type /OBJR - /Pg 5066 0 R - /Obj 5065 0 R - >>] - /Pg 5066 0 R ->> -endobj - -784 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [789 0 R 785 0 R] ->> -endobj - -785 0 obj -<< - /Type /StructElem - /S /LBody - /P 784 0 R - /K [786 0 R] ->> -endobj - -786 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 785 0 R - /K [67 68 788 0 R 71 72 787 0 R 74] - /Pg 5066 0 R ->> -endobj - -787 0 obj -<< - /Type /StructElem - /S /Link - /P 786 0 R - /K [73 << - /Type /OBJR - /Pg 5066 0 R - /Obj 5064 0 R - >>] - /Pg 5066 0 R ->> -endobj - -788 0 obj -<< - /Type /StructElem - /S /Em - /P 786 0 R - /K [69 70] - /Pg 5066 0 R ->> -endobj - -789 0 obj -<< - /Type /StructElem - /S /Lbl - /P 784 0 R - /K [790 0 R] ->> -endobj - -790 0 obj -<< - /Type /StructElem - /S /Link - /P 789 0 R - /K [66 << - /Type /OBJR - /Pg 5066 0 R - /Obj 5063 0 R - >>] - /Pg 5066 0 R ->> -endobj - -791 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [795 0 R 792 0 R] ->> -endobj - -792 0 obj -<< - /Type /StructElem - /S /LBody - /P 791 0 R - /K [793 0 R] ->> -endobj - -793 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 792 0 R - /K [63 794 0 R 65] - /Pg 5066 0 R ->> -endobj - -794 0 obj -<< - /Type /StructElem - /S /Em - /P 793 0 R - /K [64] - /Pg 5066 0 R ->> -endobj - -795 0 obj -<< - /Type /StructElem - /S /Lbl - /P 791 0 R - /K [796 0 R] ->> -endobj - -796 0 obj -<< - /Type /StructElem - /S /Link - /P 795 0 R - /K [62 << - /Type /OBJR - /Pg 5066 0 R - /Obj 5062 0 R - >>] - /Pg 5066 0 R ->> -endobj - -797 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [802 0 R 798 0 R] ->> -endobj - -798 0 obj -<< - /Type /StructElem - /S /LBody - /P 797 0 R - /K [799 0 R] ->> -endobj - -799 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 798 0 R - /K [55 56 57 801 0 R 59 800 0 R 61] - /Pg 5066 0 R ->> -endobj - -800 0 obj -<< - /Type /StructElem - /S /Link - /P 799 0 R - /K [60 << - /Type /OBJR - /Pg 5066 0 R - /Obj 5061 0 R - >>] - /Pg 5066 0 R ->> -endobj - -801 0 obj -<< - /Type /StructElem - /S /Em - /P 799 0 R - /K [58] - /Pg 5066 0 R ->> -endobj - -802 0 obj -<< - /Type /StructElem - /S /Lbl - /P 797 0 R - /K [803 0 R] ->> -endobj - -803 0 obj -<< - /Type /StructElem - /S /Link - /P 802 0 R - /K [54 << - /Type /OBJR - /Pg 5066 0 R - /Obj 5060 0 R - >>] - /Pg 5066 0 R ->> -endobj - -804 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [809 0 R 805 0 R] ->> -endobj - -805 0 obj -<< - /Type /StructElem - /S /LBody - /P 804 0 R - /K [806 0 R] ->> -endobj - -806 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 805 0 R - /K [48 808 0 R 50 51 807 0 R 53] - /Pg 5066 0 R ->> -endobj - -807 0 obj -<< - /Type /StructElem - /S /Link - /P 806 0 R - /K [52 << - /Type /OBJR - /Pg 5066 0 R - /Obj 5059 0 R - >>] - /Pg 5066 0 R ->> -endobj - -808 0 obj -<< - /Type /StructElem - /S /Em - /P 806 0 R - /K [49] - /Pg 5066 0 R ->> -endobj - -809 0 obj -<< - /Type /StructElem - /S /Lbl - /P 804 0 R - /K [810 0 R] ->> -endobj - -810 0 obj -<< - /Type /StructElem - /S /Link - /P 809 0 R - /K [47 << - /Type /OBJR - /Pg 5066 0 R - /Obj 5058 0 R - >>] - /Pg 5066 0 R ->> -endobj - -811 0 obj -<< - /Type /StructElem - /S /LI - /P 104 0 R - /K [816 0 R 812 0 R] ->> -endobj - -812 0 obj -<< - /Type /StructElem - /S /LBody - /P 811 0 R - /K [813 0 R] ->> -endobj - -813 0 obj -<< - /Type /StructElem - /S /BibEntry - /P 812 0 R - /K [40 815 0 R 44 814 0 R 46] - /Pg 5066 0 R ->> -endobj - -814 0 obj -<< - /Type /StructElem - /S /Link - /P 813 0 R - /K [45 << - /Type /OBJR - /Pg 5066 0 R - /Obj 5057 0 R - >>] - /Pg 5066 0 R ->> -endobj - -815 0 obj -<< - /Type /StructElem - /S /Em - /P 813 0 R - /K [41 42 43] - /Pg 5066 0 R ->> -endobj - -816 0 obj -<< - /Type /StructElem - /S /Lbl - /P 811 0 R - /K [817 0 R] ->> -endobj - -817 0 obj -<< - /Type /StructElem - /S /Link - /P 816 0 R - /K [39 << - /Type /OBJR - /Pg 5066 0 R - /Obj 5056 0 R - >>] - /Pg 5066 0 R ->> -endobj - -818 0 obj -<< - /Type /StructElem - /S /H1 - /P 103 0 R - /T (References) - /K [38] - /Pg 5066 0 R ->> -endobj - -819 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [28 29 820 0 R 31 32 33 34 35 36 37] - /Pg 5066 0 R ->> -endobj - -820 0 obj -<< - /Type /StructElem - /S /Link - /P 819 0 R - /K [30 << - /Type /OBJR - /Pg 5066 0 R - /Obj 5055 0 R - >>] - /Pg 5066 0 R ->> -endobj - -821 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [7 8 825 0 R 10 11 12 13 824 0 R 15 16 17 823 0 R 19 20 822 0 R 23 24 25 26 27] - /Pg 5066 0 R ->> -endobj - -822 0 obj -<< - /Type /StructElem - /S /Em - /P 821 0 R - /K [21 22] - /Pg 5066 0 R ->> -endobj - -823 0 obj -<< - /Type /StructElem - /S /Em - /P 821 0 R - /K [18] - /Pg 5066 0 R ->> -endobj - -824 0 obj -<< - /Type /StructElem - /S /Em - /P 821 0 R - /K [14] - /Pg 5066 0 R ->> -endobj - -825 0 obj -<< - /Type /StructElem - /S /Em - /P 821 0 R - /K [9] - /Pg 5066 0 R ->> -endobj - -826 0 obj -<< - /Type /StructElem - /S /H1 - /P 103 0 R - /T (Conclusion) - /K [5 6] - /Pg 5066 0 R ->> -endobj - -827 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [835 0 R 118 119 834 0 R 121 122 123 124 125 833 0 R 127 832 0 R 129 130 131 831 0 R 133 134 135 136 830 0 R 138 139 829 0 R 828 0 R << - /Type /MCR - /MCID 1 - /Pg 5066 0 R - >> << - /Type /MCR - /MCID 2 - /Pg 5066 0 R - >> << - /Type /MCR - /MCID 3 - /Pg 5066 0 R - >> << - /Type /MCR - /MCID 4 - /Pg 5066 0 R - >>] - /Pg 5053 0 R ->> -endobj - -828 0 obj -<< - /Type /StructElem - /S /Em - /P 827 0 R - /K [0] - /Pg 5066 0 R ->> -endobj - -829 0 obj -<< - /Type /StructElem - /S /Em - /P 827 0 R - /K [140] - /Pg 5053 0 R ->> -endobj - -830 0 obj -<< - /Type /StructElem - /S /Link - /P 827 0 R - /K [137 << - /Type /OBJR - /Pg 5053 0 R - /Obj 5052 0 R - >>] - /Pg 5053 0 R ->> -endobj - -831 0 obj -<< - /Type /StructElem - /S /Em - /P 827 0 R - /K [132] - /Pg 5053 0 R ->> -endobj - -832 0 obj -<< - /Type /StructElem - /S /Link - /P 827 0 R - /K [128 << - /Type /OBJR - /Pg 5053 0 R - /Obj 5051 0 R - >>] - /Pg 5053 0 R ->> -endobj - -833 0 obj -<< - /Type /StructElem - /S /Link - /P 827 0 R - /K [126 << - /Type /OBJR - /Pg 5053 0 R - /Obj 5050 0 R - >>] - /Pg 5053 0 R ->> -endobj - -834 0 obj -<< - /Type /StructElem - /S /Link - /P 827 0 R - /K [120 << - /Type /OBJR - /Pg 5053 0 R - /Obj 5049 0 R - >>] - /Pg 5053 0 R ->> -endobj - -835 0 obj -<< - /Type /StructElem - /S /Strong - /P 827 0 R - /K [117] - /Pg 5053 0 R ->> -endobj - -836 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [846 0 R 77 78 79 845 0 R 81 844 0 R 83 84 85 86 87 88 843 0 R 90 91 92 93 842 0 R 95 841 0 R 97 98 840 0 R 100 101 102 103 839 0 R 105 106 107 108 109 110 111 838 0 R 113 114 837 0 R 116] - /Pg 5053 0 R ->> -endobj - -837 0 obj -<< - /Type /StructElem - /S /Link - /P 836 0 R - /K [115 << - /Type /OBJR - /Pg 5053 0 R - /Obj 5048 0 R - >>] - /Pg 5053 0 R ->> -endobj - -838 0 obj -<< - /Type /StructElem - /S /Code - /P 836 0 R - /K [112] - /Pg 5053 0 R ->> -endobj - -839 0 obj -<< - /Type /StructElem - /S /Link - /P 836 0 R - /K [104 << - /Type /OBJR - /Pg 5053 0 R - /Obj 5047 0 R - >>] - /Pg 5053 0 R ->> -endobj - -840 0 obj -<< - /Type /StructElem - /S /Link - /P 836 0 R - /K [99 << - /Type /OBJR - /Pg 5053 0 R - /Obj 5046 0 R - >>] - /Pg 5053 0 R ->> -endobj - -841 0 obj -<< - /Type /StructElem - /S /Code - /P 836 0 R - /K [96] - /Pg 5053 0 R ->> -endobj - -842 0 obj -<< - /Type /StructElem - /S /Code - /P 836 0 R - /K [94] - /Pg 5053 0 R ->> -endobj - -843 0 obj -<< - /Type /StructElem - /S /Link - /P 836 0 R - /K [89 << - /Type /OBJR - /Pg 5053 0 R - /Obj 5045 0 R - >>] - /Pg 5053 0 R ->> -endobj - -844 0 obj -<< - /Type /StructElem - /S /Link - /P 836 0 R - /K [82 << - /Type /OBJR - /Pg 5053 0 R - /Obj 5044 0 R - >>] - /Pg 5053 0 R ->> -endobj - -845 0 obj -<< - /Type /StructElem - /S /Link - /P 836 0 R - /K [80 << - /Type /OBJR - /Pg 5053 0 R - /Obj 5043 0 R - >>] - /Pg 5053 0 R ->> -endobj - -846 0 obj -<< - /Type /StructElem - /S /Strong - /P 836 0 R - /K [76] - /Pg 5053 0 R ->> -endobj - -847 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [853 0 R 51 52 53 852 0 R 55 56 57 851 0 R 59 60 61 62 850 0 R 64 849 0 R 66 67 68 69 70 71 848 0 R 73 74 75] - /Pg 5053 0 R ->> -endobj - -848 0 obj -<< - /Type /StructElem - /S /Link - /P 847 0 R - /K [72 << - /Type /OBJR - /Pg 5053 0 R - /Obj 5042 0 R - >>] - /Pg 5053 0 R ->> -endobj - -849 0 obj -<< - /Type /StructElem - /S /Code - /P 847 0 R - /K [65] - /Pg 5053 0 R ->> -endobj - -850 0 obj -<< - /Type /StructElem - /S /Code - /P 847 0 R - /K [63] - /Pg 5053 0 R ->> -endobj - -851 0 obj -<< - /Type /StructElem - /S /Link - /P 847 0 R - /K [58 << - /Type /OBJR - /Pg 5053 0 R - /Obj 5041 0 R - >>] - /Pg 5053 0 R ->> -endobj - -852 0 obj -<< - /Type /StructElem - /S /Link - /P 847 0 R - /K [54 << - /Type /OBJR - /Pg 5053 0 R - /Obj 5040 0 R - >>] - /Pg 5053 0 R ->> -endobj - -853 0 obj -<< - /Type /StructElem - /S /Strong - /P 847 0 R - /K [50] - /Pg 5053 0 R ->> -endobj - -854 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [46 47 48 49] - /Pg 5053 0 R ->> -endobj - -855 0 obj -<< - /Type /StructElem - /S /H2 - /P 103 0 R - /T (Spatial Composability) - /K [44 45] - /Pg 5053 0 R ->> -endobj - -856 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [866 0 R 1 2 3 865 0 R 5 864 0 R 7 8 9 10 863 0 R 12 13 14 15 16 862 0 R 18 861 0 R 20 21 22 23 860 0 R 25 26 27 28 859 0 R 30 31 32 858 0 R 34 35 36 857 0 R 38 39 40 41 42 43] - /Pg 5053 0 R ->> -endobj - -857 0 obj -<< - /Type /StructElem - /S /Link - /P 856 0 R - /K [37 << - /Type /OBJR - /Pg 5053 0 R - /Obj 5039 0 R - >>] - /Pg 5053 0 R ->> -endobj - -858 0 obj -<< - /Type /StructElem - /S /Link - /P 856 0 R - /K [33 << - /Type /OBJR - /Pg 5053 0 R - /Obj 5038 0 R - >>] - /Pg 5053 0 R ->> -endobj - -859 0 obj -<< - /Type /StructElem - /S /Link - /P 856 0 R - /K [29 << - /Type /OBJR - /Pg 5053 0 R - /Obj 5037 0 R - >>] - /Pg 5053 0 R ->> -endobj - -860 0 obj -<< - /Type /StructElem - /S /Link - /P 856 0 R - /K [24 << - /Type /OBJR - /Pg 5053 0 R - /Obj 5036 0 R - >>] - /Pg 5053 0 R ->> -endobj - -861 0 obj -<< - /Type /StructElem - /S /Link - /P 856 0 R - /K [19 << - /Type /OBJR - /Pg 5053 0 R - /Obj 5035 0 R - >>] - /Pg 5053 0 R ->> -endobj - -862 0 obj -<< - /Type /StructElem - /S /Link - /P 856 0 R - /K [17 << - /Type /OBJR - /Pg 5053 0 R - /Obj 5034 0 R - >>] - /Pg 5053 0 R ->> -endobj - -863 0 obj -<< - /Type /StructElem - /S /Link - /P 856 0 R - /K [11 << - /Type /OBJR - /Pg 5053 0 R - /Obj 5033 0 R - >>] - /Pg 5053 0 R ->> -endobj - -864 0 obj -<< - /Type /StructElem - /S /Link - /P 856 0 R - /K [6 << - /Type /OBJR - /Pg 5053 0 R - /Obj 5032 0 R - >>] - /Pg 5053 0 R ->> -endobj - -865 0 obj -<< - /Type /StructElem - /S /Link - /P 856 0 R - /K [4 << - /Type /OBJR - /Pg 5053 0 R - /Obj 5031 0 R - >>] - /Pg 5053 0 R ->> -endobj - -866 0 obj -<< - /Type /StructElem - /S /Strong - /P 856 0 R - /K [0] - /Pg 5053 0 R ->> -endobj - -867 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [877 0 R 81 82 83 84 876 0 R 86 87 88 89 875 0 R 91 92 93 874 0 R 95 96 873 0 R 98 99 100 101 102 872 0 R 104 105 106 871 0 R 108 109 110 111 112 870 0 R 114 869 0 R 116 117 868 0 R 119 120 121 122 123 124 125 126 127 128 129 130 131] - /Pg 5029 0 R ->> -endobj - -868 0 obj -<< - /Type /StructElem - /S /Link - /P 867 0 R - /K [118 << - /Type /OBJR - /Pg 5029 0 R - /Obj 5028 0 R - >>] - /Pg 5029 0 R ->> -endobj - -869 0 obj -<< - /Type /StructElem - /S /Code - /P 867 0 R - /K [115] - /Pg 5029 0 R ->> -endobj - -870 0 obj -<< - /Type /StructElem - /S /Link - /P 867 0 R - /K [113 << - /Type /OBJR - /Pg 5029 0 R - /Obj 5027 0 R - >>] - /Pg 5029 0 R ->> -endobj - -871 0 obj -<< - /Type /StructElem - /S /Link - /P 867 0 R - /K [107 << - /Type /OBJR - /Pg 5029 0 R - /Obj 5026 0 R - >>] - /Pg 5029 0 R ->> -endobj - -872 0 obj -<< - /Type /StructElem - /S /Link - /P 867 0 R - /K [103 << - /Type /OBJR - /Pg 5029 0 R - /Obj 5025 0 R - >>] - /Pg 5029 0 R ->> -endobj - -873 0 obj -<< - /Type /StructElem - /S /Link - /P 867 0 R - /K [97 << - /Type /OBJR - /Pg 5029 0 R - /Obj 5024 0 R - >>] - /Pg 5029 0 R ->> -endobj - -874 0 obj -<< - /Type /StructElem - /S /Code - /P 867 0 R - /K [94] - /Pg 5029 0 R ->> -endobj - -875 0 obj -<< - /Type /StructElem - /S /Link - /P 867 0 R - /K [90 << - /Type /OBJR - /Pg 5029 0 R - /Obj 5023 0 R - >>] - /Pg 5029 0 R ->> -endobj - -876 0 obj -<< - /Type /StructElem - /S /Link - /P 867 0 R - /K [85 << - /Type /OBJR - /Pg 5029 0 R - /Obj 5022 0 R - >>] - /Pg 5029 0 R ->> -endobj - -877 0 obj -<< - /Type /StructElem - /S /Strong - /P 867 0 R - /K [80] - /Pg 5029 0 R ->> -endobj - -878 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [895 0 R 4 5 6 7 894 0 R 9 10 893 0 R 12 13 14 892 0 R 16 17 891 0 R 19 20 890 0 R 22 23 24 25 26 27 889 0 R 29 30 31 32 888 0 R 34 35 36 887 0 R 38 39 40 41 42 43 886 0 R 45 46 47 48 49 885 0 R 51 52 53 884 0 R 55 56 57 58 883 0 R 60 61 62 882 0 R 64 65 66 881 0 R 68 880 0 R 70 71 879 0 R 73 74 75 76 77 78 79] - /Pg 5029 0 R ->> -endobj - -879 0 obj -<< - /Type /StructElem - /S /Link - /P 878 0 R - /K [72 << - /Type /OBJR - /Pg 5029 0 R - /Obj 5021 0 R - >>] - /Pg 5029 0 R ->> -endobj - -880 0 obj -<< - /Type /StructElem - /S /Code - /P 878 0 R - /K [69] - /Pg 5029 0 R ->> -endobj - -881 0 obj -<< - /Type /StructElem - /S /Code - /P 878 0 R - /K [67] - /Pg 5029 0 R ->> -endobj - -882 0 obj -<< - /Type /StructElem - /S /Link - /P 878 0 R - /K [63 << - /Type /OBJR - /Pg 5029 0 R - /Obj 5020 0 R - >>] - /Pg 5029 0 R ->> -endobj - -883 0 obj -<< - /Type /StructElem - /S /Link - /P 878 0 R - /K [59 << - /Type /OBJR - /Pg 5029 0 R - /Obj 5019 0 R - >>] - /Pg 5029 0 R ->> -endobj - -884 0 obj -<< - /Type /StructElem - /S /Code - /P 878 0 R - /K [54] - /Pg 5029 0 R ->> -endobj - -885 0 obj -<< - /Type /StructElem - /S /Link - /P 878 0 R - /K [50 << - /Type /OBJR - /Pg 5029 0 R - /Obj 5018 0 R - >>] - /Pg 5029 0 R ->> -endobj - -886 0 obj -<< - /Type /StructElem - /S /Link - /P 878 0 R - /K [44 << - /Type /OBJR - /Pg 5029 0 R - /Obj 5017 0 R - >>] - /Pg 5029 0 R ->> -endobj - -887 0 obj -<< - /Type /StructElem - /S /Link - /P 878 0 R - /K [37 << - /Type /OBJR - /Pg 5029 0 R - /Obj 5016 0 R - >>] - /Pg 5029 0 R ->> -endobj - -888 0 obj -<< - /Type /StructElem - /S /Link - /P 878 0 R - /K [33 << - /Type /OBJR - /Pg 5029 0 R - /Obj 5015 0 R - >>] - /Pg 5029 0 R ->> -endobj - -889 0 obj -<< - /Type /StructElem - /S /Link - /P 878 0 R - /K [28 << - /Type /OBJR - /Pg 5029 0 R - /Obj 5014 0 R - >>] - /Pg 5029 0 R ->> -endobj - -890 0 obj -<< - /Type /StructElem - /S /Link - /P 878 0 R - /K [21 << - /Type /OBJR - /Pg 5029 0 R - /Obj 5013 0 R - >>] - /Pg 5029 0 R ->> -endobj - -891 0 obj -<< - /Type /StructElem - /S /Link - /P 878 0 R - /K [18 << - /Type /OBJR - /Pg 5029 0 R - /Obj 5012 0 R - >>] - /Pg 5029 0 R ->> -endobj - -892 0 obj -<< - /Type /StructElem - /S /Em - /P 878 0 R - /K [15] - /Pg 5029 0 R ->> -endobj - -893 0 obj -<< - /Type /StructElem - /S /Link - /P 878 0 R - /K [11 << - /Type /OBJR - /Pg 5029 0 R - /Obj 5011 0 R - >>] - /Pg 5029 0 R ->> -endobj - -894 0 obj -<< - /Type /StructElem - /S /Em - /P 878 0 R - /K [8] - /Pg 5029 0 R ->> -endobj - -895 0 obj -<< - /Type /StructElem - /S /Strong - /P 878 0 R - /K [3] - /Pg 5029 0 R ->> -endobj - -896 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [89 90 << - /Type /MCR - /MCID 0 - /Pg 5029 0 R - >> << - /Type /MCR - /MCID 1 - /Pg 5029 0 R - >> << - /Type /MCR - /MCID 2 - /Pg 5029 0 R - >>] - /Pg 5009 0 R ->> -endobj - -897 0 obj -<< - /Type /StructElem - /S /H2 - /P 103 0 R - /T (Temporal Composability) - /K [87 88] - /Pg 5009 0 R ->> -endobj - -898 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [909 0 R 45 46 908 0 R 48 907 0 R 50 51 906 0 R 53 905 0 R 55 904 0 R 57 903 0 R 59 60 61 62 63 64 902 0 R 67 68 69 70 71 72 901 0 R 74 75 76 77 78 900 0 R 80 899 0 R 82 83 84 85 86] - /Pg 5009 0 R ->> -endobj - -899 0 obj -<< - /Type /StructElem - /S /Link - /P 898 0 R - /K [81 << - /Type /OBJR - /Pg 5009 0 R - /Obj 5008 0 R - >>] - /Pg 5009 0 R ->> -endobj - -900 0 obj -<< - /Type /StructElem - /S /Link - /P 898 0 R - /K [79 << - /Type /OBJR - /Pg 5009 0 R - /Obj 5007 0 R - >>] - /Pg 5009 0 R ->> -endobj - -901 0 obj -<< - /Type /StructElem - /S /Em - /P 898 0 R - /K [73] - /Pg 5009 0 R ->> -endobj - -902 0 obj -<< - /Type /StructElem - /S /Em - /P 898 0 R - /K [65 66] - /Pg 5009 0 R ->> -endobj - -903 0 obj -<< - /Type /StructElem - /S /Em - /P 898 0 R - /K [58] - /Pg 5009 0 R ->> -endobj - -904 0 obj -<< - /Type /StructElem - /S /Em - /P 898 0 R - /K [56] - /Pg 5009 0 R ->> -endobj - -905 0 obj -<< - /Type /StructElem - /S /Em - /P 898 0 R - /K [54] - /Pg 5009 0 R ->> -endobj - -906 0 obj -<< - /Type /StructElem - /S /Em - /P 898 0 R - /K [52] - /Pg 5009 0 R ->> -endobj - -907 0 obj -<< - /Type /StructElem - /S /Link - /P 898 0 R - /K [49 << - /Type /OBJR - /Pg 5009 0 R - /Obj 5006 0 R - >>] - /Pg 5009 0 R ->> -endobj - -908 0 obj -<< - /Type /StructElem - /S /Link - /P 898 0 R - /K [47 << - /Type /OBJR - /Pg 5009 0 R - /Obj 5005 0 R - >>] - /Pg 5009 0 R ->> -endobj - -909 0 obj -<< - /Type /StructElem - /S /Strong - /P 898 0 R - /K [44] - /Pg 5009 0 R ->> -endobj - -910 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [917 0 R 9 10 916 0 R 12 915 0 R 14 15 914 0 R 17 18 19 20 21 22 913 0 R 24 25 26 27 28 29 30 912 0 R 33 34 911 0 R 36 37 38 39 40 41 42 43] - /Pg 5009 0 R ->> -endobj - -911 0 obj -<< - /Type /StructElem - /S /Link - /P 910 0 R - /K [35 << - /Type /OBJR - /Pg 5009 0 R - /Obj 5004 0 R - >>] - /Pg 5009 0 R ->> -endobj - -912 0 obj -<< - /Type /StructElem - /S /Formula - /P 910 0 R - /K [31 32] - /Pg 5009 0 R ->> -endobj - -913 0 obj -<< - /Type /StructElem - /S /Link - /P 910 0 R - /K [23 << - /Type /OBJR - /Pg 5009 0 R - /Obj 5003 0 R - >>] - /Pg 5009 0 R ->> -endobj - -914 0 obj -<< - /Type /StructElem - /S /Em - /P 910 0 R - /K [16] - /Pg 5009 0 R ->> -endobj - -915 0 obj -<< - /Type /StructElem - /S /Link - /P 910 0 R - /K [13 << - /Type /OBJR - /Pg 5009 0 R - /Obj 5002 0 R - >>] - /Pg 5009 0 R ->> -endobj - -916 0 obj -<< - /Type /StructElem - /S /Link - /P 910 0 R - /K [11 << - /Type /OBJR - /Pg 5009 0 R - /Obj 5001 0 R - >>] - /Pg 5009 0 R ->> -endobj - -917 0 obj -<< - /Type /StructElem - /S /Strong - /P 910 0 R - /K [8] - /Pg 5009 0 R ->> -endobj - -918 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [919 0 R 5 6 7] - /Pg 5009 0 R ->> -endobj - -919 0 obj -<< - /Type /StructElem - /S /Link - /P 918 0 R - /K [4 << - /Type /OBJR - /Pg 5009 0 R - /Obj 5000 0 R - >>] - /Pg 5009 0 R ->> -endobj - -920 0 obj -<< - /Type /StructElem - /S /H2 - /P 103 0 R - /T (Programming Paradigms) - /K [2 3] - /Pg 5009 0 R ->> -endobj - -921 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [927 0 R 69 70 926 0 R 72 73 925 0 R 76 77 78 79 80 81 924 0 R 83 923 0 R 85 86 87 922 0 R 89 90 91 92 << - /Type /MCR - /MCID 0 - /Pg 5009 0 R - >> << - /Type /MCR - /MCID 1 - /Pg 5009 0 R - >>] - /Pg 4998 0 R ->> -endobj - -922 0 obj -<< - /Type /StructElem - /S /Link - /P 921 0 R - /K [88 << - /Type /OBJR - /Pg 4998 0 R - /Obj 4997 0 R - >>] - /Pg 4998 0 R ->> -endobj - -923 0 obj -<< - /Type /StructElem - /S /Link - /P 921 0 R - /K [84 << - /Type /OBJR - /Pg 4998 0 R - /Obj 4996 0 R - >>] - /Pg 4998 0 R ->> -endobj - -924 0 obj -<< - /Type /StructElem - /S /Link - /P 921 0 R - /K [82 << - /Type /OBJR - /Pg 4998 0 R - /Obj 4995 0 R - >>] - /Pg 4998 0 R ->> -endobj - -925 0 obj -<< - /Type /StructElem - /S /Em - /P 921 0 R - /K [74 75] - /Pg 4998 0 R ->> -endobj - -926 0 obj -<< - /Type /StructElem - /S /Link - /P 921 0 R - /K [71 << - /Type /OBJR - /Pg 4998 0 R - /Obj 4994 0 R - >>] - /Pg 4998 0 R ->> -endobj - -927 0 obj -<< - /Type /StructElem - /S /Strong - /P 921 0 R - /K [68] - /Pg 4998 0 R ->> -endobj - -928 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [933 0 R 47 48 49 932 0 R 51 52 53 931 0 R 55 930 0 R 57 58 59 60 61 62 63 64 65 929 0 R 67] - /Pg 4998 0 R ->> -endobj - -929 0 obj -<< - /Type /StructElem - /S /Link - /P 928 0 R - /K [66 << - /Type /OBJR - /Pg 4998 0 R - /Obj 4993 0 R - >>] - /Pg 4998 0 R ->> -endobj - -930 0 obj -<< - /Type /StructElem - /S /Em - /P 928 0 R - /K [56] - /Pg 4998 0 R ->> -endobj - -931 0 obj -<< - /Type /StructElem - /S /Em - /P 928 0 R - /K [54] - /Pg 4998 0 R ->> -endobj - -932 0 obj -<< - /Type /StructElem - /S /Link - /P 928 0 R - /K [50 << - /Type /OBJR - /Pg 4998 0 R - /Obj 4992 0 R - >>] - /Pg 4998 0 R ->> -endobj - -933 0 obj -<< - /Type /StructElem - /S /Strong - /P 928 0 R - /K [46] - /Pg 4998 0 R ->> -endobj - -934 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [942 0 R 12 941 0 R 14 15 16 940 0 R 18 19 939 0 R 21 938 0 R 23 24 25 26 27 937 0 R 29 30 31 32 33 34 35 936 0 R 37 38 935 0 R 40 41 42 43 44 45] - /Pg 4998 0 R ->> -endobj - -935 0 obj -<< - /Type /StructElem - /S /Em - /P 934 0 R - /K [39] - /Pg 4998 0 R ->> -endobj - -936 0 obj -<< - /Type /StructElem - /S /Em - /P 934 0 R - /K [36] - /Pg 4998 0 R ->> -endobj - -937 0 obj -<< - /Type /StructElem - /S /Link - /P 934 0 R - /K [28 << - /Type /OBJR - /Pg 4998 0 R - /Obj 4991 0 R - >>] - /Pg 4998 0 R ->> -endobj - -938 0 obj -<< - /Type /StructElem - /S /Link - /P 934 0 R - /K [22 << - /Type /OBJR - /Pg 4998 0 R - /Obj 4990 0 R - >>] - /Pg 4998 0 R ->> -endobj - -939 0 obj -<< - /Type /StructElem - /S /Link - /P 934 0 R - /K [20 << - /Type /OBJR - /Pg 4998 0 R - /Obj 4989 0 R - >>] - /Pg 4998 0 R ->> -endobj - -940 0 obj -<< - /Type /StructElem - /S /Em - /P 934 0 R - /K [17] - /Pg 4998 0 R ->> -endobj - -941 0 obj -<< - /Type /StructElem - /S /Link - /P 934 0 R - /K [13 << - /Type /OBJR - /Pg 4998 0 R - /Obj 4988 0 R - >>] - /Pg 4998 0 R ->> -endobj - -942 0 obj -<< - /Type /StructElem - /S /Strong - /P 934 0 R - /K [11] - /Pg 4998 0 R ->> -endobj - -943 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [944 0 R 7 8 9 10] - /Pg 4998 0 R ->> -endobj - -944 0 obj -<< - /Type /StructElem - /S /Link - /P 943 0 R - /K [6 << - /Type /OBJR - /Pg 4998 0 R - /Obj 4987 0 R - >>] - /Pg 4998 0 R ->> -endobj - -945 0 obj -<< - /Type /StructElem - /S /H2 - /P 103 0 R - /T (Effect and Coeffect Systems) - /K [4 5] - /Pg 4998 0 R ->> -endobj - -946 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [2 3] - /Pg 4998 0 R ->> -endobj - -947 0 obj -<< - /Type /StructElem - /S /H1 - /P 103 0 R - /T (Related Work) - /K [0 1] - /Pg 4998 0 R ->> -endobj - -948 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [114 115 116] - /Pg 4985 0 R ->> -endobj - -949 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [955 0 R 81 82 83 954 0 R 90 91 92 93 953 0 R 95 96 97 98 99 100 101 952 0 R 103 104 105 951 0 R 107 108 109 110 950 0 R 112 113] - /Pg 4985 0 R ->> -endobj - -950 0 obj -<< - /Type /StructElem - /S /Link - /P 949 0 R - /K [111 << - /Type /OBJR - /Pg 4985 0 R - /Obj 4984 0 R - >>] - /Pg 4985 0 R ->> -endobj - -951 0 obj -<< - /Type /StructElem - /S /Link - /P 949 0 R - /K [106 << - /Type /OBJR - /Pg 4985 0 R - /Obj 4983 0 R - >>] - /Pg 4985 0 R ->> -endobj - -952 0 obj -<< - /Type /StructElem - /S /Link - /P 949 0 R - /K [102 << - /Type /OBJR - /Pg 4985 0 R - /Obj 4982 0 R - >>] - /Pg 4985 0 R ->> -endobj - -953 0 obj -<< - /Type /StructElem - /S /Link - /P 949 0 R - /K [94 << - /Type /OBJR - /Pg 4985 0 R - /Obj 4981 0 R - >>] - /Pg 4985 0 R ->> -endobj - -954 0 obj -<< - /Type /StructElem - /S /Formula - /P 949 0 R - /K [84 85 86 87 88 89] - /Pg 4985 0 R ->> -endobj - -955 0 obj -<< - /Type /StructElem - /S /Strong - /P 949 0 R - /K [80] - /Pg 4985 0 R ->> -endobj - -956 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [959 0 R 62 63 64 958 0 R 66 67 68 957 0 R 70 71 72 73 74 75 76 77 78 79] - /Pg 4985 0 R ->> -endobj - -957 0 obj -<< - /Type /StructElem - /S /Em - /P 956 0 R - /K [69] - /Pg 4985 0 R ->> -endobj - -958 0 obj -<< - /Type /StructElem - /S /Link - /P 956 0 R - /K [65 << - /Type /OBJR - /Pg 4985 0 R - /Obj 4980 0 R - >>] - /Pg 4985 0 R ->> -endobj - -959 0 obj -<< - /Type /StructElem - /S /Strong - /P 956 0 R - /K [61] - /Pg 4985 0 R ->> -endobj - -960 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [964 0 R 48 963 0 R 50 962 0 R 54 961 0 R 56 57 58 59 60] - /Pg 4985 0 R ->> -endobj - -961 0 obj -<< - /Type /StructElem - /S /Formula - /P 960 0 R - /K [55] - /Pg 4985 0 R ->> -endobj - -962 0 obj -<< - /Type /StructElem - /S /Formula - /P 960 0 R - /K [51 52 53] - /Pg 4985 0 R ->> -endobj - -963 0 obj -<< - /Type /StructElem - /S /Formula - /P 960 0 R - /K [49] - /Pg 4985 0 R ->> -endobj - -964 0 obj -<< - /Type /StructElem - /S /Strong - /P 960 0 R - /K [47] - /Pg 4985 0 R ->> -endobj - -965 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [34 969 0 R 36 37 968 0 R 39 967 0 R 41 42 966 0 R 44 45 46] - /Pg 4985 0 R ->> -endobj - -966 0 obj -<< - /Type /StructElem - /S /Link - /P 965 0 R - /K [43 << - /Type /OBJR - /Pg 4985 0 R - /Obj 4979 0 R - >>] - /Pg 4985 0 R ->> -endobj - -967 0 obj -<< - /Type /StructElem - /S /Em - /P 965 0 R - /K [40] - /Pg 4985 0 R ->> -endobj - -968 0 obj -<< - /Type /StructElem - /S /Em - /P 965 0 R - /K [38] - /Pg 4985 0 R ->> -endobj - -969 0 obj -<< - /Type /StructElem - /S /Em - /P 965 0 R - /K [35] - /Pg 4985 0 R ->> -endobj - -970 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [972 0 R 26 971 0 R 28 29 30 31 32 33] - /Pg 4985 0 R ->> -endobj - -971 0 obj -<< - /Type /StructElem - /S /Formula - /P 970 0 R - /K [27] - /Pg 4985 0 R ->> -endobj - -972 0 obj -<< - /Type /StructElem - /S /Strong - /P 970 0 R - /K [25] - /Pg 4985 0 R ->> -endobj - -973 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [978 0 R 3 977 0 R 5 6 7 8 976 0 R 10 11 975 0 R 18 19 20 21 974 0 R 23 24] - /Pg 4985 0 R ->> -endobj - -974 0 obj -<< - /Type /StructElem - /S /Link - /P 973 0 R - /K [22 << - /Type /OBJR - /Pg 4985 0 R - /Obj 4978 0 R - >>] - /Pg 4985 0 R ->> -endobj - -975 0 obj -<< - /Type /StructElem - /S /Formula - /P 973 0 R - /K [12 13 14 15 16 17] - /Pg 4985 0 R ->> -endobj - -976 0 obj -<< - /Type /StructElem - /S /Formula - /P 973 0 R - /K [9] - /Pg 4985 0 R ->> -endobj - -977 0 obj -<< - /Type /StructElem - /S /Formula - /P 973 0 R - /K [4] - /Pg 4985 0 R ->> -endobj - -978 0 obj -<< - /Type /StructElem - /S /Strong - /P 973 0 R - /K [2] - /Pg 4985 0 R ->> -endobj - -979 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [63 64 982 0 R 66 981 0 R 68 980 0 R 71 << - /Type /MCR - /MCID 0 - /Pg 4985 0 R - >> << - /Type /MCR - /MCID 1 - /Pg 4985 0 R - >>] - /Pg 4976 0 R ->> -endobj - -980 0 obj -<< - /Type /StructElem - /S /Formula - /P 979 0 R - /K [69 70] - /Pg 4976 0 R ->> -endobj - -981 0 obj -<< - /Type /StructElem - /S /Formula - /P 979 0 R - /K [67] - /Pg 4976 0 R ->> -endobj - -982 0 obj -<< - /Type /StructElem - /S /Formula - /P 979 0 R - /K [65] - /Pg 4976 0 R ->> -endobj - -983 0 obj -<< - /Type /StructElem - /S /H2 - /P 103 0 R - /T (Dependency Typing and Versioning) - /K [61 62] - /Pg 4976 0 R ->> -endobj - -984 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [53 54 55 56 57 58 59 60] - /Pg 4976 0 R ->> -endobj - -985 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [38 39 40 987 0 R 42 43 986 0 R 45 46 47 48 49 50 51 52] - /Pg 4976 0 R ->> -endobj - -986 0 obj -<< - /Type /StructElem - /S /Formula - /P 985 0 R - /K [44] - /Pg 4976 0 R ->> -endobj - -987 0 obj -<< - /Type /StructElem - /S /Formula - /P 985 0 R - /K [41] - /Pg 4976 0 R ->> -endobj - -988 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [26 27 28 29 30 31 32 33 34 35 36 37] - /Pg 4976 0 R ->> -endobj - -989 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [10 11 995 0 R 13 994 0 R 15 993 0 R 17 992 0 R 19 991 0 R 21 990 0 R 23 24 25] - /Pg 4976 0 R ->> -endobj - -990 0 obj -<< - /Type /StructElem - /S /Formula - /P 989 0 R - /K [22] - /Pg 4976 0 R ->> -endobj - -991 0 obj -<< - /Type /StructElem - /S /Formula - /P 989 0 R - /K [20] - /Pg 4976 0 R ->> -endobj - -992 0 obj -<< - /Type /StructElem - /S /Formula - /P 989 0 R - /K [18] - /Pg 4976 0 R ->> -endobj - -993 0 obj -<< - /Type /StructElem - /S /Formula - /P 989 0 R - /K [16] - /Pg 4976 0 R ->> -endobj - -994 0 obj -<< - /Type /StructElem - /S /Formula - /P 989 0 R - /K [14] - /Pg 4976 0 R ->> -endobj - -995 0 obj -<< - /Type /StructElem - /S /Formula - /P 989 0 R - /K [12] - /Pg 4976 0 R ->> -endobj - -996 0 obj -<< - /Type /StructElem - /S /H2 - /P 103 0 R - /T (Mutual Dependencies and Component Granularity) - /K [8 9] - /Pg 4976 0 R ->> -endobj - -997 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [108 109 110 999 0 R 112 113 << - /Type /MCR - /MCID 0 - /Pg 4976 0 R - >> << - /Type /MCR - /MCID 1 - /Pg 4976 0 R - >> << - /Type /MCR - /MCID 2 - /Pg 4976 0 R - >> 998 0 R << - /Type /MCR - /MCID 4 - /Pg 4976 0 R - >> << - /Type /MCR - /MCID 5 - /Pg 4976 0 R - >> << - /Type /MCR - /MCID 6 - /Pg 4976 0 R - >> << - /Type /MCR - /MCID 7 - /Pg 4976 0 R - >>] - /Pg 4973 0 R ->> -endobj - -998 0 obj -<< - /Type /StructElem - /S /Link - /P 997 0 R - /K [3 << - /Type /OBJR - /Pg 4976 0 R - /Obj 4975 0 R - >>] - /Pg 4976 0 R ->> -endobj - -999 0 obj -<< - /Type /StructElem - /S /Link - /P 997 0 R - /K [111 << - /Type /OBJR - /Pg 4973 0 R - /Obj 4971 0 R - >>] - /Pg 4973 0 R ->> -endobj - -1000 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [84 85 86 87 1006 0 R 89 90 1005 0 R 92 93 94 1004 0 R 96 97 1003 0 R 99 100 101 1002 0 R 103 1001 0 R 105 106 107] - /Pg 4973 0 R ->> -endobj - -1001 0 obj -<< - /Type /StructElem - /S /Link - /P 1000 0 R - /K [104 << - /Type /OBJR - /Pg 4973 0 R - /Obj 4970 0 R - >>] - /Pg 4973 0 R ->> -endobj - -1002 0 obj -<< - /Type /StructElem - /S /Link - /P 1000 0 R - /K [102 << - /Type /OBJR - /Pg 4973 0 R - /Obj 4969 0 R - >>] - /Pg 4973 0 R ->> -endobj - -1003 0 obj -<< - /Type /StructElem - /S /Link - /P 1000 0 R - /K [98 << - /Type /OBJR - /Pg 4973 0 R - /Obj 4968 0 R - >>] - /Pg 4973 0 R ->> -endobj - -1004 0 obj -<< - /Type /StructElem - /S /Code - /P 1000 0 R - /K [95] - /Pg 4973 0 R ->> -endobj - -1005 0 obj -<< - /Type /StructElem - /S /Link - /P 1000 0 R - /K [91 << - /Type /OBJR - /Pg 4973 0 R - /Obj 4967 0 R - >>] - /Pg 4973 0 R ->> -endobj - -1006 0 obj -<< - /Type /StructElem - /S /Code - /P 1000 0 R - /K [88] - /Pg 4973 0 R ->> -endobj - -1007 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [56 57 58 1014 0 R 60 61 1013 0 R 63 64 65 66 1012 0 R 68 69 70 1011 0 R 72 1010 0 R 74 75 1009 0 R 77 78 79 1008 0 R 81 82 83] - /Pg 4973 0 R ->> -endobj - -1008 0 obj -<< - /Type /StructElem - /S /Link - /P 1007 0 R - /K [80 << - /Type /OBJR - /Pg 4973 0 R - /Obj 4966 0 R - >>] - /Pg 4973 0 R ->> -endobj - -1009 0 obj -<< - /Type /StructElem - /S /Link - /P 1007 0 R - /K [76 << - /Type /OBJR - /Pg 4973 0 R - /Obj 4965 0 R - >>] - /Pg 4973 0 R ->> -endobj - -1010 0 obj -<< - /Type /StructElem - /S /Code - /P 1007 0 R - /K [73] - /Pg 4973 0 R ->> -endobj - -1011 0 obj -<< - /Type /StructElem - /S /Code - /P 1007 0 R - /K [71] - /Pg 4973 0 R ->> -endobj - -1012 0 obj -<< - /Type /StructElem - /S /Link - /P 1007 0 R - /K [67 << - /Type /OBJR - /Pg 4973 0 R - /Obj 4964 0 R - >>] - /Pg 4973 0 R ->> -endobj - -1013 0 obj -<< - /Type /StructElem - /S /Link - /P 1007 0 R - /K [62 << - /Type /OBJR - /Pg 4973 0 R - /Obj 4963 0 R - >>] - /Pg 4973 0 R ->> -endobj - -1014 0 obj -<< - /Type /StructElem - /S /Link - /P 1007 0 R - /K [59 << - /Type /OBJR - /Pg 4973 0 R - /Obj 4962 0 R - >>] - /Pg 4973 0 R ->> -endobj - -1015 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [1019 0 R 44 45 46 47 1018 0 R 49 50 51 1017 0 R 53 1016 0 R 55] - /Pg 4973 0 R ->> -endobj - -1016 0 obj -<< - /Type /StructElem - /S /Em - /P 1015 0 R - /K [54] - /Pg 4973 0 R ->> -endobj - -1017 0 obj -<< - /Type /StructElem - /S /Em - /P 1015 0 R - /K [52] - /Pg 4973 0 R ->> -endobj - -1018 0 obj -<< - /Type /StructElem - /S /Link - /P 1015 0 R - /K [48 << - /Type /OBJR - /Pg 4973 0 R - /Obj 4961 0 R - >>] - /Pg 4973 0 R ->> -endobj - -1019 0 obj -<< - /Type /StructElem - /S /Strong - /P 1015 0 R - /K [43] - /Pg 4973 0 R ->> -endobj - -1020 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [18 19 20 21 1031 0 R 1026 0 R 23 24 1025 0 R 26 1024 0 R 28 29 1023 0 R 31 1022 0 R 33 34 1021 0 R 36 37 38 39 40 41 42] - /Pg 4973 0 R ->> -endobj - -1021 0 obj -<< - /Type /StructElem - /S /Link - /P 1020 0 R - /K [35 << - /Type /OBJR - /Pg 4973 0 R - /Obj 4960 0 R - >>] - /Pg 4973 0 R ->> -endobj - -1022 0 obj -<< - /Type /StructElem - /S /Code - /P 1020 0 R - /K [32] - /Pg 4973 0 R ->> -endobj - -1023 0 obj -<< - /Type /StructElem - /S /Code - /P 1020 0 R - /K [30] - /Pg 4973 0 R ->> -endobj - -1024 0 obj -<< - /Type /StructElem - /S /Code - /P 1020 0 R - /K [27] - /Pg 4973 0 R ->> -endobj - -1025 0 obj -<< - /Type /StructElem - /S /Code - /P 1020 0 R - /K [25] - /Pg 4973 0 R ->> -endobj - -1026 0 obj -<< - /Type /StructElem - /S /Note - /P 1020 0 R - /ID (Note 6) - /K [1028 0 R 115 1027 0 R 117 118] - /Pg 4973 0 R ->> -endobj - -1027 0 obj -<< - /Type /StructElem - /S /Code - /P 1026 0 R - /K [116] - /Pg 4973 0 R ->> -endobj - -1028 0 obj -<< - /Type /StructElem - /S /Lbl - /P 1026 0 R - /K [1029 0 R] ->> -endobj - -1029 0 obj -<< - /Type /StructElem - /S /Link - /P 1028 0 R - /K [<< - /Type /OBJR - /Pg 4973 0 R - /Obj 4972 0 R - >> 1030 0 R] ->> -endobj - -1030 0 obj -<< - /Type /StructElem - /S /Span - /P 1029 0 R - /A [<< - /O /Layout - /BaselineShift 2.5866 - /LineHeight 3.24 - >>] - /K [114] - /Pg 4973 0 R ->> -endobj - -1031 0 obj -<< - /Type /StructElem - /S /Lbl - /P 1020 0 R - /K [1032 0 R] ->> -endobj - -1032 0 obj -<< - /Type /StructElem - /S /Link - /P 1031 0 R - /K [<< - /Type /OBJR - /Pg 4973 0 R - /Obj 4959 0 R - >> 1033 0 R] ->> -endobj - -1033 0 obj -<< - /Type /StructElem - /S /Span - /P 1032 0 R - /A [<< - /O /Layout - /BaselineShift 3.1614 - /LineHeight 3.96 - >>] - /K [22] - /Pg 4973 0 R ->> -endobj - -1034 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [1036 0 R 12 1035 0 R 14 15 16 17] - /Pg 4973 0 R ->> -endobj - -1035 0 obj -<< - /Type /StructElem - /S /Em - /P 1034 0 R - /K [13] - /Pg 4973 0 R ->> -endobj - -1036 0 obj -<< - /Type /StructElem - /S /Strong - /P 1034 0 R - /K [11] - /Pg 4973 0 R ->> -endobj - -1037 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [7 8 9 10] - /Pg 4973 0 R ->> -endobj - -1038 0 obj -<< - /Type /StructElem - /S /H2 - /P 103 0 R - /T (Language Independence and Selection) - /K [5 6] - /Pg 4973 0 R ->> -endobj - -1039 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [1043 0 R 60 61 62 63 64 65 66 1042 0 R 68 69 70 71 1041 0 R 73 74 75 << - /Type /MCR - /MCID 0 - /Pg 4973 0 R - >> 1040 0 R << - /Type /MCR - /MCID 2 - /Pg 4973 0 R - >> << - /Type /MCR - /MCID 3 - /Pg 4973 0 R - >> << - /Type /MCR - /MCID 4 - /Pg 4973 0 R - >>] - /Pg 4956 0 R ->> -endobj - -1040 0 obj -<< - /Type /StructElem - /S /Link - /P 1039 0 R - /K [1 << - /Type /OBJR - /Pg 4973 0 R - /Obj 4958 0 R - >>] - /Pg 4973 0 R ->> -endobj - -1041 0 obj -<< - /Type /StructElem - /S /Link - /P 1039 0 R - /K [72 << - /Type /OBJR - /Pg 4956 0 R - /Obj 4955 0 R - >>] - /Pg 4956 0 R ->> -endobj - -1042 0 obj -<< - /Type /StructElem - /S /Link - /P 1039 0 R - /K [67 << - /Type /OBJR - /Pg 4956 0 R - /Obj 4954 0 R - >>] - /Pg 4956 0 R ->> -endobj - -1043 0 obj -<< - /Type /StructElem - /S /Strong - /P 1039 0 R - /K [59] - /Pg 4956 0 R ->> -endobj - -1044 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [46 47 1045 0 R 49 50 51 52 53 54 55 56 57 58] - /Pg 4956 0 R ->> -endobj - -1045 0 obj -<< - /Type /StructElem - /S /Link - /P 1044 0 R - /K [48 << - /Type /OBJR - /Pg 4956 0 R - /Obj 4953 0 R - >>] - /Pg 4956 0 R ->> -endobj - -1046 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [1051 0 R 27 1050 0 R 29 30 31 32 33 1049 0 R 35 1048 0 R 37 38 39 1047 0 R 41 42 43 44 45] - /Pg 4956 0 R ->> -endobj - -1047 0 obj -<< - /Type /StructElem - /S /Code - /P 1046 0 R - /K [40] - /Pg 4956 0 R ->> -endobj - -1048 0 obj -<< - /Type /StructElem - /S /Link - /P 1046 0 R - /K [36 << - /Type /OBJR - /Pg 4956 0 R - /Obj 4952 0 R - >>] - /Pg 4956 0 R ->> -endobj - -1049 0 obj -<< - /Type /StructElem - /S /Link - /P 1046 0 R - /K [34 << - /Type /OBJR - /Pg 4956 0 R - /Obj 4951 0 R - >>] - /Pg 4956 0 R ->> -endobj - -1050 0 obj -<< - /Type /StructElem - /S /Link - /P 1046 0 R - /K [28 << - /Type /OBJR - /Pg 4956 0 R - /Obj 4950 0 R - >>] - /Pg 4956 0 R ->> -endobj - -1051 0 obj -<< - /Type /StructElem - /S /Strong - /P 1046 0 R - /K [26] - /Pg 4956 0 R ->> -endobj - -1052 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [21 22 23 24 25] - /Pg 4956 0 R ->> -endobj - -1053 0 obj -<< - /Type /StructElem - /S /H2 - /P 103 0 R - /T (Access Control and Sandboxing) - /K [19 20] - /Pg 4956 0 R ->> -endobj - -1054 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [1056 0 R 8 9 1055 0 R 11 12 13 14 15 16 17 18] - /Pg 4956 0 R ->> -endobj - -1055 0 obj -<< - /Type /StructElem - /S /Link - /P 1054 0 R - /K [10 << - /Type /OBJR - /Pg 4956 0 R - /Obj 4949 0 R - >>] - /Pg 4956 0 R ->> -endobj - -1056 0 obj -<< - /Type /StructElem - /S /Strong - /P 1054 0 R - /K [7] - /Pg 4956 0 R ->> -endobj - -1057 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [1061 0 R 66 67 68 1060 0 R 70 1059 0 R 72 73 << - /Type /MCR - /MCID 0 - /Pg 4956 0 R - >> 1058 0 R << - /Type /MCR - /MCID 2 - /Pg 4956 0 R - >> << - /Type /MCR - /MCID 3 - /Pg 4956 0 R - >> << - /Type /MCR - /MCID 4 - /Pg 4956 0 R - >> << - /Type /MCR - /MCID 5 - /Pg 4956 0 R - >> << - /Type /MCR - /MCID 6 - /Pg 4956 0 R - >>] - /Pg 4947 0 R ->> -endobj - -1058 0 obj -<< - /Type /StructElem - /S /Code - /P 1057 0 R - /K [1] - /Pg 4956 0 R ->> -endobj - -1059 0 obj -<< - /Type /StructElem - /S /Link - /P 1057 0 R - /K [71 << - /Type /OBJR - /Pg 4947 0 R - /Obj 4946 0 R - >>] - /Pg 4947 0 R ->> -endobj - -1060 0 obj -<< - /Type /StructElem - /S /Link - /P 1057 0 R - /K [69 << - /Type /OBJR - /Pg 4947 0 R - /Obj 4945 0 R - >>] - /Pg 4947 0 R ->> -endobj - -1061 0 obj -<< - /Type /StructElem - /S /Strong - /P 1057 0 R - /K [65] - /Pg 4947 0 R ->> -endobj - -1062 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [1063 0 R 59 60 61 62 63 64] - /Pg 4947 0 R ->> -endobj - -1063 0 obj -<< - /Type /StructElem - /S /Strong - /P 1062 0 R - /K [58] - /Pg 4947 0 R ->> -endobj - -1064 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [56 57] - /Pg 4947 0 R ->> -endobj - -1065 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [25 26 1073 0 R 28 29 1072 0 R 31 32 33 34 1071 0 R 36 1070 0 R 38 1069 0 R 40 41 1068 0 R 43 44 1067 0 R 46 47 48 49 1066 0 R 51 52 53 54 55] - /Pg 4947 0 R ->> -endobj - -1066 0 obj -<< - /Type /StructElem - /S /Em - /P 1065 0 R - /K [50] - /Pg 4947 0 R ->> -endobj - -1067 0 obj -<< - /Type /StructElem - /S /Em - /P 1065 0 R - /K [45] - /Pg 4947 0 R ->> -endobj - -1068 0 obj -<< - /Type /StructElem - /S /Em - /P 1065 0 R - /K [42] - /Pg 4947 0 R ->> -endobj - -1069 0 obj -<< - /Type /StructElem - /S /Code - /P 1065 0 R - /K [39] - /Pg 4947 0 R ->> -endobj - -1070 0 obj -<< - /Type /StructElem - /S /Em - /P 1065 0 R - /K [37] - /Pg 4947 0 R ->> -endobj - -1071 0 obj -<< - /Type /StructElem - /S /Code - /P 1065 0 R - /K [35] - /Pg 4947 0 R ->> -endobj - -1072 0 obj -<< - /Type /StructElem - /S /Em - /P 1065 0 R - /K [30] - /Pg 4947 0 R ->> -endobj - -1073 0 obj -<< - /Type /StructElem - /S /Link - /P 1065 0 R - /K [27 << - /Type /OBJR - /Pg 4947 0 R - /Obj 4944 0 R - >>] - /Pg 4947 0 R ->> -endobj - -1074 0 obj -<< - /Type /StructElem - /S /H2 - /P 103 0 R - /T (Service Multiplexing) - /K [23 24] - /Pg 4947 0 R ->> -endobj - -1075 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [18 19 20 21 22] - /Pg 4947 0 R ->> -endobj - -1076 0 obj -<< - /Type /StructElem - /S /H1 - /P 103 0 R - /T (Discussion) - /K [16 17] - /Pg 4947 0 R ->> -endobj - -1077 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [1078 0 R 9 10 11 12 13 14 15] - /Pg 4947 0 R ->> -endobj - -1078 0 obj -<< - /Type /StructElem - /S /Strong - /P 1077 0 R - /K [8] - /Pg 4947 0 R ->> -endobj - -1079 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [1082 0 R 66 1081 0 R 68 69 70 71 << - /Type /MCR - /MCID 0 - /Pg 4947 0 R - >> << - /Type /MCR - /MCID 1 - /Pg 4947 0 R - >> 1080 0 R << - /Type /MCR - /MCID 3 - /Pg 4947 0 R - >> << - /Type /MCR - /MCID 4 - /Pg 4947 0 R - >> << - /Type /MCR - /MCID 5 - /Pg 4947 0 R - >> << - /Type /MCR - /MCID 6 - /Pg 4947 0 R - >> << - /Type /MCR - /MCID 7 - /Pg 4947 0 R - >>] - /Pg 4941 0 R ->> -endobj - -1080 0 obj -<< - /Type /StructElem - /S /Link - /P 1079 0 R - /K [2 << - /Type /OBJR - /Pg 4947 0 R - /Obj 4943 0 R - >>] - /Pg 4947 0 R ->> -endobj - -1081 0 obj -<< - /Type /StructElem - /S /Link - /P 1079 0 R - /K [67 << - /Type /OBJR - /Pg 4941 0 R - /Obj 4938 0 R - >>] - /Pg 4941 0 R ->> -endobj - -1082 0 obj -<< - /Type /StructElem - /S /Strong - /P 1079 0 R - /K [65] - /Pg 4941 0 R ->> -endobj - -1083 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [1087 0 R 48 1086 0 R 50 51 52 53 54 55 56 57 1085 0 R 59 60 61 1084 0 R 63 64] - /Pg 4941 0 R ->> -endobj - -1084 0 obj -<< - /Type /StructElem - /S /Link - /P 1083 0 R - /K [62 << - /Type /OBJR - /Pg 4941 0 R - /Obj 4937 0 R - >>] - /Pg 4941 0 R ->> -endobj - -1085 0 obj -<< - /Type /StructElem - /S /Link - /P 1083 0 R - /K [58 << - /Type /OBJR - /Pg 4941 0 R - /Obj 4936 0 R - >>] - /Pg 4941 0 R ->> -endobj - -1086 0 obj -<< - /Type /StructElem - /S /Link - /P 1083 0 R - /K [49 << - /Type /OBJR - /Pg 4941 0 R - /Obj 4935 0 R - >>] - /Pg 4941 0 R ->> -endobj - -1087 0 obj -<< - /Type /StructElem - /S /Strong - /P 1083 0 R - /K [47] - /Pg 4941 0 R ->> -endobj - -1088 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [1091 0 R 33 34 1090 0 R 36 37 38 39 40 1089 0 R 42 43 44 45 46] - /Pg 4941 0 R ->> -endobj - -1089 0 obj -<< - /Type /StructElem - /S /Link - /P 1088 0 R - /K [41 << - /Type /OBJR - /Pg 4941 0 R - /Obj 4934 0 R - >>] - /Pg 4941 0 R ->> -endobj - -1090 0 obj -<< - /Type /StructElem - /S /Link - /P 1088 0 R - /K [35 << - /Type /OBJR - /Pg 4941 0 R - /Obj 4933 0 R - >>] - /Pg 4941 0 R ->> -endobj - -1091 0 obj -<< - /Type /StructElem - /S /Strong - /P 1088 0 R - /K [32] - /Pg 4941 0 R ->> -endobj - -1092 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [23 1106 0 R 1102 0 R 25 26 1099 0 R 1093 0 R 28 29 30 31] - /Pg 4941 0 R ->> -endobj - -1093 0 obj -<< - /Type /StructElem - /S /Note - /P 1092 0 R - /ID (Note 5) - /K [1096 0 R 76 1095 0 R 78 1094 0 R 80] - /Pg 4941 0 R ->> -endobj - -1094 0 obj -<< - /Type /StructElem - /S /Em - /P 1093 0 R - /K [79] - /Pg 4941 0 R ->> -endobj - -1095 0 obj -<< - /Type /StructElem - /S /Em - /P 1093 0 R - /K [77] - /Pg 4941 0 R ->> -endobj - -1096 0 obj -<< - /Type /StructElem - /S /Lbl - /P 1093 0 R - /K [1097 0 R] ->> -endobj - -1097 0 obj -<< - /Type /StructElem - /S /Link - /P 1096 0 R - /K [<< - /Type /OBJR - /Pg 4941 0 R - /Obj 4940 0 R - >> 1098 0 R] ->> -endobj - -1098 0 obj -<< - /Type /StructElem - /S /Span - /P 1097 0 R - /A [<< - /O /Layout - /BaselineShift 2.5866 - /LineHeight 3.24 - >>] - /K [75] - /Pg 4941 0 R ->> -endobj - -1099 0 obj -<< - /Type /StructElem - /S /Lbl - /P 1092 0 R - /K [1100 0 R] ->> -endobj - -1100 0 obj -<< - /Type /StructElem - /S /Link - /P 1099 0 R - /K [<< - /Type /OBJR - /Pg 4941 0 R - /Obj 4932 0 R - >> 1101 0 R] ->> -endobj - -1101 0 obj -<< - /Type /StructElem - /S /Span - /P 1100 0 R - /A [<< - /O /Layout - /BaselineShift 3.1614 - /LineHeight 3.96 - >>] - /K [27] - /Pg 4941 0 R ->> -endobj - -1102 0 obj -<< - /Type /StructElem - /S /Note - /P 1092 0 R - /ID (Note 4) - /K [1103 0 R 73 74] - /Pg 4941 0 R ->> -endobj - -1103 0 obj -<< - /Type /StructElem - /S /Lbl - /P 1102 0 R - /K [1104 0 R] ->> -endobj - -1104 0 obj -<< - /Type /StructElem - /S /Link - /P 1103 0 R - /K [<< - /Type /OBJR - /Pg 4941 0 R - /Obj 4939 0 R - >> 1105 0 R] ->> -endobj - -1105 0 obj -<< - /Type /StructElem - /S /Span - /P 1104 0 R - /A [<< - /O /Layout - /BaselineShift 2.5866 - /LineHeight 3.24 - >>] - /K [72] - /Pg 4941 0 R ->> -endobj - -1106 0 obj -<< - /Type /StructElem - /S /Lbl - /P 1092 0 R - /K [1107 0 R] ->> -endobj - -1107 0 obj -<< - /Type /StructElem - /S /Link - /P 1106 0 R - /K [<< - /Type /OBJR - /Pg 4941 0 R - /Obj 4931 0 R - >> 1108 0 R] ->> -endobj - -1108 0 obj -<< - /Type /StructElem - /S /Span - /P 1107 0 R - /A [<< - /O /Layout - /BaselineShift 3.1614 - /LineHeight 3.96 - >>] - /K [24] - /Pg 4941 0 R ->> -endobj - -1109 0 obj -<< - /Type /StructElem - /S /H2 - /P 103 0 R - /T (Case Study: Koishi) - /K [21 22] - /Pg 4941 0 R ->> -endobj - -1110 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [15 16 17 1111 0 R 19 20] - /Pg 4941 0 R ->> -endobj - -1111 0 obj -<< - /Type /StructElem - /S /Code - /P 1110 0 R - /K [18] - /Pg 4941 0 R ->> -endobj - -1112 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [1207 0 R 1113 0 R] ->> -endobj - -1113 0 obj -<< - /Type /StructElem - /S /Div - /P 1112 0 R - /K [1206 0 R 1204 0 R 1201 0 R 1199 0 R 1198 0 R 1197 0 R 1193 0 R 1191 0 R 1190 0 R 1188 0 R 1186 0 R 1185 0 R 1184 0 R 1183 0 R 1178 0 R 1176 0 R 1175 0 R 1174 0 R 1173 0 R 1172 0 R 1170 0 R 1168 0 R 1167 0 R 1166 0 R 1165 0 R 1161 0 R 1159 0 R 1158 0 R 1155 0 R 1153 0 R 1152 0 R 1151 0 R 1150 0 R 1148 0 R 1146 0 R 1145 0 R 1144 0 R 1139 0 R 1137 0 R 1136 0 R 1135 0 R 1134 0 R 1133 0 R 1131 0 R 1129 0 R 1128 0 R 1127 0 R 1126 0 R 1122 0 R 1120 0 R 1119 0 R 1118 0 R 1115 0 R 1114 0 R] ->> -endobj - -1114 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [] ->> -endobj - -1115 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [1117 0 R 1116 0 R] ->> -endobj - -1116 0 obj -<< - /Type /StructElem - /S /Span - /P 1115 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [14] - /Pg 4941 0 R ->> -endobj - -1117 0 obj -<< - /Type /StructElem - /S /Strong - /P 1115 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [13] - /Pg 4941 0 R ->> -endobj - -1118 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [] ->> -endobj - -1119 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [] ->> -endobj - -1120 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [1121 0 R] ->> -endobj - -1121 0 obj -<< - /Type /StructElem - /S /Span - /P 1120 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [12] - /Pg 4941 0 R ->> -endobj - -1122 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [1125 0 R 1124 0 R 1123 0 R] ->> -endobj - -1123 0 obj -<< - /Type /StructElem - /S /Span - /P 1122 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [11] - /Pg 4941 0 R ->> -endobj - -1124 0 obj -<< - /Type /StructElem - /S /Formula - /P 1122 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [10] - /Pg 4941 0 R ->> -endobj - -1125 0 obj -<< - /Type /StructElem - /S /Span - /P 1122 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [9] - /Pg 4941 0 R ->> -endobj - -1126 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [] ->> -endobj - -1127 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [] ->> -endobj - -1128 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [] ->> -endobj - -1129 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [1130 0 R] ->> -endobj - -1130 0 obj -<< - /Type /StructElem - /S /Span - /P 1129 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [8] - /Pg 4941 0 R ->> -endobj - -1131 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [1132 0 R] ->> -endobj - -1132 0 obj -<< - /Type /StructElem - /S /Span - /P 1131 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [7] - /Pg 4941 0 R ->> -endobj - -1133 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [] ->> -endobj - -1134 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [] ->> -endobj - -1135 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [] ->> -endobj - -1136 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [] ->> -endobj - -1137 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [1138 0 R] ->> -endobj - -1138 0 obj -<< - /Type /StructElem - /S /Span - /P 1137 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [6] - /Pg 4941 0 R ->> -endobj - -1139 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [1143 0 R 1142 0 R 1141 0 R 1140 0 R] ->> -endobj - -1140 0 obj -<< - /Type /StructElem - /S /Span - /P 1139 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [2 4] - /Pg 4941 0 R ->> -endobj - -1141 0 obj -<< - /Type /StructElem - /S /Strong - /P 1139 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [5] - /Pg 4941 0 R ->> -endobj - -1142 0 obj -<< - /Type /StructElem - /S /Strong - /P 1139 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [3] - /Pg 4941 0 R ->> -endobj - -1143 0 obj -<< - /Type /StructElem - /S /Strong - /P 1139 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [1] - /Pg 4941 0 R ->> -endobj - -1144 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [] ->> -endobj - -1145 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [] ->> -endobj - -1146 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [1147 0 R] ->> -endobj - -1147 0 obj -<< - /Type /StructElem - /S /Span - /P 1146 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [0] - /Pg 4941 0 R ->> -endobj - -1148 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [1149 0 R] ->> -endobj - -1149 0 obj -<< - /Type /StructElem - /S /Span - /P 1148 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [147] - /Pg 4929 0 R ->> -endobj - -1150 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [] ->> -endobj - -1151 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [] ->> -endobj - -1152 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [] ->> -endobj - -1153 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [1154 0 R] ->> -endobj - -1154 0 obj -<< - /Type /StructElem - /S /Span - /P 1153 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [146] - /Pg 4929 0 R ->> -endobj - -1155 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [1157 0 R 1156 0 R] ->> -endobj - -1156 0 obj -<< - /Type /StructElem - /S /Span - /P 1155 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [145] - /Pg 4929 0 R ->> -endobj - -1157 0 obj -<< - /Type /StructElem - /S /Strong - /P 1155 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [144] - /Pg 4929 0 R ->> -endobj - -1158 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [] ->> -endobj - -1159 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [1160 0 R] ->> -endobj - -1160 0 obj -<< - /Type /StructElem - /S /Span - /P 1159 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [143] - /Pg 4929 0 R ->> -endobj - -1161 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [1164 0 R 1163 0 R 1162 0 R] ->> -endobj - -1162 0 obj -<< - /Type /StructElem - /S /Span - /P 1161 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [142] - /Pg 4929 0 R ->> -endobj - -1163 0 obj -<< - /Type /StructElem - /S /Formula - /P 1161 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [141] - /Pg 4929 0 R ->> -endobj - -1164 0 obj -<< - /Type /StructElem - /S /Span - /P 1161 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [140] - /Pg 4929 0 R ->> -endobj - -1165 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [] ->> -endobj - -1166 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [] ->> -endobj - -1167 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [] ->> -endobj - -1168 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [1169 0 R] ->> -endobj - -1169 0 obj -<< - /Type /StructElem - /S /Span - /P 1168 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [139] - /Pg 4929 0 R ->> -endobj - -1170 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [1171 0 R] ->> -endobj - -1171 0 obj -<< - /Type /StructElem - /S /Span - /P 1170 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [138] - /Pg 4929 0 R ->> -endobj - -1172 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [] ->> -endobj - -1173 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [] ->> -endobj - -1174 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [] ->> -endobj - -1175 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [] ->> -endobj - -1176 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [1177 0 R] ->> -endobj - -1177 0 obj -<< - /Type /StructElem - /S /Span - /P 1176 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [137] - /Pg 4929 0 R ->> -endobj - -1178 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [1182 0 R 1181 0 R 1180 0 R 1179 0 R] ->> -endobj - -1179 0 obj -<< - /Type /StructElem - /S /Span - /P 1178 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [133 135] - /Pg 4929 0 R ->> -endobj - -1180 0 obj -<< - /Type /StructElem - /S /Strong - /P 1178 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [136] - /Pg 4929 0 R ->> -endobj - -1181 0 obj -<< - /Type /StructElem - /S /Strong - /P 1178 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [134] - /Pg 4929 0 R ->> -endobj - -1182 0 obj -<< - /Type /StructElem - /S /Strong - /P 1178 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [132] - /Pg 4929 0 R ->> -endobj - -1183 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [] ->> -endobj - -1184 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [] ->> -endobj - -1185 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [] ->> -endobj - -1186 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [1187 0 R] ->> -endobj - -1187 0 obj -<< - /Type /StructElem - /S /Span - /P 1186 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [131] - /Pg 4929 0 R ->> -endobj - -1188 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [1189 0 R] ->> -endobj - -1189 0 obj -<< - /Type /StructElem - /S /Strong - /P 1188 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [130] - /Pg 4929 0 R ->> -endobj - -1190 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [] ->> -endobj - -1191 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [1192 0 R] ->> -endobj - -1192 0 obj -<< - /Type /StructElem - /S /Span - /P 1191 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [129] - /Pg 4929 0 R ->> -endobj - -1193 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [1196 0 R 1195 0 R 1194 0 R] ->> -endobj - -1194 0 obj -<< - /Type /StructElem - /S /Span - /P 1193 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [128] - /Pg 4929 0 R ->> -endobj - -1195 0 obj -<< - /Type /StructElem - /S /Formula - /P 1193 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [127] - /Pg 4929 0 R ->> -endobj - -1196 0 obj -<< - /Type /StructElem - /S /Span - /P 1193 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [126] - /Pg 4929 0 R ->> -endobj - -1197 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [] ->> -endobj - -1198 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [] ->> -endobj - -1199 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [1200 0 R] ->> -endobj - -1200 0 obj -<< - /Type /StructElem - /S /Span - /P 1199 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [125] - /Pg 4929 0 R ->> -endobj - -1201 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [1203 0 R 1202 0 R] ->> -endobj - -1202 0 obj -<< - /Type /StructElem - /S /Span - /P 1201 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [124] - /Pg 4929 0 R ->> -endobj - -1203 0 obj -<< - /Type /StructElem - /S /Strong - /P 1201 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [123] - /Pg 4929 0 R ->> -endobj - -1204 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [1205 0 R] ->> -endobj - -1205 0 obj -<< - /Type /StructElem - /S /Span - /P 1204 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [122] - /Pg 4929 0 R ->> -endobj - -1206 0 obj -<< - /Type /StructElem - /S /Div - /P 1113 0 R - /K [] ->> -endobj - -1207 0 obj -<< - /Type /StructElem - /S /P - /P 1112 0 R - /K [1208 0 R 121] - /Pg 4929 0 R ->> -endobj - -1208 0 obj -<< - /Type /StructElem - /S /Strong - /P 1207 0 R - /K [120] - /Pg 4929 0 R ->> -endobj - -1209 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [1218 0 R 113 114 1215 0 R 1211 0 R 116 117 1210 0 R 119] - /Pg 4929 0 R ->> -endobj - -1210 0 obj -<< - /Type /StructElem - /S /Code - /P 1209 0 R - /K [118] - /Pg 4929 0 R ->> -endobj - -1211 0 obj -<< - /Type /StructElem - /S /Note - /P 1209 0 R - /ID (Note 3) - /K [1212 0 R 149 150] - /Pg 4929 0 R ->> -endobj - -1212 0 obj -<< - /Type /StructElem - /S /Lbl - /P 1211 0 R - /K [1213 0 R] ->> -endobj - -1213 0 obj -<< - /Type /StructElem - /S /Link - /P 1212 0 R - /K [<< - /Type /OBJR - /Pg 4929 0 R - /Obj 4928 0 R - >> 1214 0 R] ->> -endobj - -1214 0 obj -<< - /Type /StructElem - /S /Span - /P 1213 0 R - /A [<< - /O /Layout - /BaselineShift 2.5866 - /LineHeight 3.24 - >>] - /K [148] - /Pg 4929 0 R ->> -endobj - -1215 0 obj -<< - /Type /StructElem - /S /Lbl - /P 1209 0 R - /K [1216 0 R] ->> -endobj - -1216 0 obj -<< - /Type /StructElem - /S /Link - /P 1215 0 R - /K [<< - /Type /OBJR - /Pg 4929 0 R - /Obj 4927 0 R - >> 1217 0 R] ->> -endobj - -1217 0 obj -<< - /Type /StructElem - /S /Span - /P 1216 0 R - /A [<< - /O /Layout - /BaselineShift 3.1614 - /LineHeight 3.96 - >>] - /K [115] - /Pg 4929 0 R ->> -endobj - -1218 0 obj -<< - /Type /StructElem - /S /Strong - /P 1209 0 R - /K [112] - /Pg 4929 0 R ->> -endobj - -1219 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [107 1221 0 R 109 1220 0 R 111] - /Pg 4929 0 R ->> -endobj - -1220 0 obj -<< - /Type /StructElem - /S /Code - /P 1219 0 R - /K [110] - /Pg 4929 0 R ->> -endobj - -1221 0 obj -<< - /Type /StructElem - /S /Code - /P 1219 0 R - /K [108] - /Pg 4929 0 R ->> -endobj - -1222 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [1365 0 R 1223 0 R] ->> -endobj - -1223 0 obj -<< - /Type /StructElem - /S /Div - /P 1222 0 R - /K [1364 0 R 1362 0 R 1359 0 R 1357 0 R 1356 0 R 1355 0 R 1350 0 R 1348 0 R 1347 0 R 1344 0 R 1342 0 R 1341 0 R 1340 0 R 1339 0 R 1329 0 R 1327 0 R 1326 0 R 1325 0 R 1319 0 R 1317 0 R 1316 0 R 1315 0 R 1310 0 R 1308 0 R 1307 0 R 1305 0 R 1303 0 R 1302 0 R 1299 0 R 1297 0 R 1294 0 R 1292 0 R 1291 0 R 1290 0 R 1285 0 R 1283 0 R 1282 0 R 1277 0 R 1275 0 R 1274 0 R 1273 0 R 1272 0 R 1268 0 R 1266 0 R 1265 0 R 1264 0 R 1254 0 R 1252 0 R 1251 0 R 1250 0 R 1249 0 R 1248 0 R 1242 0 R 1240 0 R 1239 0 R 1238 0 R 1237 0 R 1231 0 R 1229 0 R 1228 0 R 1225 0 R 1224 0 R] ->> -endobj - -1224 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [] ->> -endobj - -1225 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [1227 0 R 1226 0 R] ->> -endobj - -1226 0 obj -<< - /Type /StructElem - /S /Span - /P 1225 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [106] - /Pg 4929 0 R ->> -endobj - -1227 0 obj -<< - /Type /StructElem - /S /Strong - /P 1225 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [105] - /Pg 4929 0 R ->> -endobj - -1228 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [] ->> -endobj - -1229 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [1230 0 R] ->> -endobj - -1230 0 obj -<< - /Type /StructElem - /S /Span - /P 1229 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [104] - /Pg 4929 0 R ->> -endobj - -1231 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [1236 0 R 1235 0 R 1234 0 R 1233 0 R 1232 0 R] ->> -endobj - -1232 0 obj -<< - /Type /StructElem - /S /Span - /P 1231 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [103] - /Pg 4929 0 R ->> -endobj - -1233 0 obj -<< - /Type /StructElem - /S /Formula - /P 1231 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [102] - /Pg 4929 0 R ->> -endobj - -1234 0 obj -<< - /Type /StructElem - /S /Span - /P 1231 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [101] - /Pg 4929 0 R ->> -endobj - -1235 0 obj -<< - /Type /StructElem - /S /Formula - /P 1231 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [100] - /Pg 4929 0 R ->> -endobj - -1236 0 obj -<< - /Type /StructElem - /S /Span - /P 1231 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [99] - /Pg 4929 0 R ->> -endobj - -1237 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [] ->> -endobj - -1238 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [] ->> -endobj - -1239 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [] ->> -endobj - -1240 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [1241 0 R] ->> -endobj - -1241 0 obj -<< - /Type /StructElem - /S /Span - /P 1240 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [98] - /Pg 4929 0 R ->> -endobj - -1242 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [1247 0 R 1246 0 R 1245 0 R 1244 0 R 1243 0 R] ->> -endobj - -1243 0 obj -<< - /Type /StructElem - /S /Span - /P 1242 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [97] - /Pg 4929 0 R ->> -endobj - -1244 0 obj -<< - /Type /StructElem - /S /Formula - /P 1242 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [96] - /Pg 4929 0 R ->> -endobj - -1245 0 obj -<< - /Type /StructElem - /S /Span - /P 1242 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [95] - /Pg 4929 0 R ->> -endobj - -1246 0 obj -<< - /Type /StructElem - /S /Formula - /P 1242 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [94] - /Pg 4929 0 R ->> -endobj - -1247 0 obj -<< - /Type /StructElem - /S /Span - /P 1242 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [93] - /Pg 4929 0 R ->> -endobj - -1248 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [] ->> -endobj - -1249 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [] ->> -endobj - -1250 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [] ->> -endobj - -1251 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [] ->> -endobj - -1252 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [1253 0 R] ->> -endobj - -1253 0 obj -<< - /Type /StructElem - /S /Span - /P 1252 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [92] - /Pg 4929 0 R ->> -endobj - -1254 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [1263 0 R 1262 0 R 1261 0 R 1260 0 R 1259 0 R 1258 0 R 1257 0 R 1256 0 R 1255 0 R] ->> -endobj - -1255 0 obj -<< - /Type /StructElem - /S /Span - /P 1254 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [90] - /Pg 4929 0 R ->> -endobj - -1256 0 obj -<< - /Type /StructElem - /S /Strong - /P 1254 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [91] - /Pg 4929 0 R ->> -endobj - -1257 0 obj -<< - /Type /StructElem - /S /Formula - /P 1254 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [89] - /Pg 4929 0 R ->> -endobj - -1258 0 obj -<< - /Type /StructElem - /S /Span - /P 1254 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [88] - /Pg 4929 0 R ->> -endobj - -1259 0 obj -<< - /Type /StructElem - /S /Formula - /P 1254 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [87] - /Pg 4929 0 R ->> -endobj - -1260 0 obj -<< - /Type /StructElem - /S /Span - /P 1254 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [86] - /Pg 4929 0 R ->> -endobj - -1261 0 obj -<< - /Type /StructElem - /S /Formula - /P 1254 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [85] - /Pg 4929 0 R ->> -endobj - -1262 0 obj -<< - /Type /StructElem - /S /Span - /P 1254 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [84] - /Pg 4929 0 R ->> -endobj - -1263 0 obj -<< - /Type /StructElem - /S /Strong - /P 1254 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [83] - /Pg 4929 0 R ->> -endobj - -1264 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [] ->> -endobj - -1265 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [] ->> -endobj - -1266 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [1267 0 R] ->> -endobj - -1267 0 obj -<< - /Type /StructElem - /S /Span - /P 1266 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [82] - /Pg 4929 0 R ->> -endobj - -1268 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [1271 0 R 1270 0 R 1269 0 R] ->> -endobj - -1269 0 obj -<< - /Type /StructElem - /S /Span - /P 1268 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [81] - /Pg 4929 0 R ->> -endobj - -1270 0 obj -<< - /Type /StructElem - /S /Formula - /P 1268 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [80] - /Pg 4929 0 R ->> -endobj - -1271 0 obj -<< - /Type /StructElem - /S /Span - /P 1268 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [79] - /Pg 4929 0 R ->> -endobj - -1272 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [] ->> -endobj - -1273 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [] ->> -endobj - -1274 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [] ->> -endobj - -1275 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [1276 0 R] ->> -endobj - -1276 0 obj -<< - /Type /StructElem - /S /Span - /P 1275 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [78] - /Pg 4929 0 R ->> -endobj - -1277 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [1281 0 R 1280 0 R 1279 0 R 1278 0 R] ->> -endobj - -1278 0 obj -<< - /Type /StructElem - /S /Span - /P 1277 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [74 76] - /Pg 4929 0 R ->> -endobj - -1279 0 obj -<< - /Type /StructElem - /S /Strong - /P 1277 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [77] - /Pg 4929 0 R ->> -endobj - -1280 0 obj -<< - /Type /StructElem - /S /Strong - /P 1277 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [75] - /Pg 4929 0 R ->> -endobj - -1281 0 obj -<< - /Type /StructElem - /S /Strong - /P 1277 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [73] - /Pg 4929 0 R ->> -endobj - -1282 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [] ->> -endobj - -1283 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [1284 0 R] ->> -endobj - -1284 0 obj -<< - /Type /StructElem - /S /Span - /P 1283 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [72] - /Pg 4929 0 R ->> -endobj - -1285 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [1289 0 R 1288 0 R 1287 0 R 1286 0 R] ->> -endobj - -1286 0 obj -<< - /Type /StructElem - /S /Formula - /P 1285 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [71] - /Pg 4929 0 R ->> -endobj - -1287 0 obj -<< - /Type /StructElem - /S /Span - /P 1285 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [70] - /Pg 4929 0 R ->> -endobj - -1288 0 obj -<< - /Type /StructElem - /S /Formula - /P 1285 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [69] - /Pg 4929 0 R ->> -endobj - -1289 0 obj -<< - /Type /StructElem - /S /Span - /P 1285 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [68] - /Pg 4929 0 R ->> -endobj - -1290 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [] ->> -endobj - -1291 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [] ->> -endobj - -1292 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [1293 0 R] ->> -endobj - -1293 0 obj -<< - /Type /StructElem - /S /Span - /P 1292 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [67] - /Pg 4929 0 R ->> -endobj - -1294 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [1296 0 R 1295 0 R] ->> -endobj - -1295 0 obj -<< - /Type /StructElem - /S /Span - /P 1294 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [66] - /Pg 4929 0 R ->> -endobj - -1296 0 obj -<< - /Type /StructElem - /S /Strong - /P 1294 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [65] - /Pg 4929 0 R ->> -endobj - -1297 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [1298 0 R] ->> -endobj - -1298 0 obj -<< - /Type /StructElem - /S /Span - /P 1297 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [64] - /Pg 4929 0 R ->> -endobj - -1299 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [1301 0 R 1300 0 R] ->> -endobj - -1300 0 obj -<< - /Type /StructElem - /S /Span - /P 1299 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [63] - /Pg 4929 0 R ->> -endobj - -1301 0 obj -<< - /Type /StructElem - /S /Strong - /P 1299 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [62] - /Pg 4929 0 R ->> -endobj - -1302 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [] ->> -endobj - -1303 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [1304 0 R] ->> -endobj - -1304 0 obj -<< - /Type /StructElem - /S /Span - /P 1303 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [61] - /Pg 4929 0 R ->> -endobj - -1305 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [1306 0 R] ->> -endobj - -1306 0 obj -<< - /Type /StructElem - /S /Span - /P 1305 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [60] - /Pg 4929 0 R ->> -endobj - -1307 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [] ->> -endobj - -1308 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [1309 0 R] ->> -endobj - -1309 0 obj -<< - /Type /StructElem - /S /Span - /P 1308 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [59] - /Pg 4929 0 R ->> -endobj - -1310 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [1314 0 R 1313 0 R 1312 0 R 1311 0 R] ->> -endobj - -1311 0 obj -<< - /Type /StructElem - /S /Span - /P 1310 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [54 56 58] - /Pg 4929 0 R ->> -endobj - -1312 0 obj -<< - /Type /StructElem - /S /Strong - /P 1310 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [57] - /Pg 4929 0 R ->> -endobj - -1313 0 obj -<< - /Type /StructElem - /S /Strong - /P 1310 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [55] - /Pg 4929 0 R ->> -endobj - -1314 0 obj -<< - /Type /StructElem - /S /Strong - /P 1310 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [53] - /Pg 4929 0 R ->> -endobj - -1315 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [] ->> -endobj - -1316 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [] ->> -endobj - -1317 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [1318 0 R] ->> -endobj - -1318 0 obj -<< - /Type /StructElem - /S /Span - /P 1317 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [52] - /Pg 4929 0 R ->> -endobj - -1319 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [1324 0 R 1323 0 R 1322 0 R 1321 0 R 1320 0 R] ->> -endobj - -1320 0 obj -<< - /Type /StructElem - /S /Span - /P 1319 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [51] - /Pg 4929 0 R ->> -endobj - -1321 0 obj -<< - /Type /StructElem - /S /Formula - /P 1319 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [50] - /Pg 4929 0 R ->> -endobj - -1322 0 obj -<< - /Type /StructElem - /S /Span - /P 1319 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [49] - /Pg 4929 0 R ->> -endobj - -1323 0 obj -<< - /Type /StructElem - /S /Formula - /P 1319 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [48] - /Pg 4929 0 R ->> -endobj - -1324 0 obj -<< - /Type /StructElem - /S /Span - /P 1319 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [47] - /Pg 4929 0 R ->> -endobj - -1325 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [] ->> -endobj - -1326 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [] ->> -endobj - -1327 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [1328 0 R] ->> -endobj - -1328 0 obj -<< - /Type /StructElem - /S /Span - /P 1327 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [46] - /Pg 4929 0 R ->> -endobj - -1329 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [1338 0 R 1337 0 R 1336 0 R 1335 0 R 1334 0 R 1333 0 R 1332 0 R 1331 0 R 1330 0 R] ->> -endobj - -1330 0 obj -<< - /Type /StructElem - /S /Span - /P 1329 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [42 44] - /Pg 4929 0 R ->> -endobj - -1331 0 obj -<< - /Type /StructElem - /S /Strong - /P 1329 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [45] - /Pg 4929 0 R ->> -endobj - -1332 0 obj -<< - /Type /StructElem - /S /Strong - /P 1329 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [43] - /Pg 4929 0 R ->> -endobj - -1333 0 obj -<< - /Type /StructElem - /S /Formula - /P 1329 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [41] - /Pg 4929 0 R ->> -endobj - -1334 0 obj -<< - /Type /StructElem - /S /Span - /P 1329 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [38 40] - /Pg 4929 0 R ->> -endobj - -1335 0 obj -<< - /Type /StructElem - /S /Strong - /P 1329 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [39] - /Pg 4929 0 R ->> -endobj - -1336 0 obj -<< - /Type /StructElem - /S /Formula - /P 1329 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [37] - /Pg 4929 0 R ->> -endobj - -1337 0 obj -<< - /Type /StructElem - /S /Span - /P 1329 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [36] - /Pg 4929 0 R ->> -endobj - -1338 0 obj -<< - /Type /StructElem - /S /Strong - /P 1329 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [35] - /Pg 4929 0 R ->> -endobj - -1339 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [] ->> -endobj - -1340 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [] ->> -endobj - -1341 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [] ->> -endobj - -1342 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [1343 0 R] ->> -endobj - -1343 0 obj -<< - /Type /StructElem - /S /Span - /P 1342 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [34] - /Pg 4929 0 R ->> -endobj - -1344 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [1346 0 R 1345 0 R] ->> -endobj - -1345 0 obj -<< - /Type /StructElem - /S /Span - /P 1344 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [33] - /Pg 4929 0 R ->> -endobj - -1346 0 obj -<< - /Type /StructElem - /S /Strong - /P 1344 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [32] - /Pg 4929 0 R ->> -endobj - -1347 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [] ->> -endobj - -1348 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [1349 0 R] ->> -endobj - -1349 0 obj -<< - /Type /StructElem - /S /Span - /P 1348 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [31] - /Pg 4929 0 R ->> -endobj - -1350 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [1354 0 R 1353 0 R 1352 0 R 1351 0 R] ->> -endobj - -1351 0 obj -<< - /Type /StructElem - /S /Formula - /P 1350 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [30] - /Pg 4929 0 R ->> -endobj - -1352 0 obj -<< - /Type /StructElem - /S /Span - /P 1350 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [29] - /Pg 4929 0 R ->> -endobj - -1353 0 obj -<< - /Type /StructElem - /S /Formula - /P 1350 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [28] - /Pg 4929 0 R ->> -endobj - -1354 0 obj -<< - /Type /StructElem - /S /Span - /P 1350 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [27] - /Pg 4929 0 R ->> -endobj - -1355 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [] ->> -endobj - -1356 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [] ->> -endobj - -1357 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [1358 0 R] ->> -endobj - -1358 0 obj -<< - /Type /StructElem - /S /Span - /P 1357 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [26] - /Pg 4929 0 R ->> -endobj - -1359 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [1361 0 R 1360 0 R] ->> -endobj - -1360 0 obj -<< - /Type /StructElem - /S /Span - /P 1359 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [25] - /Pg 4929 0 R ->> -endobj - -1361 0 obj -<< - /Type /StructElem - /S /Strong - /P 1359 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [24] - /Pg 4929 0 R ->> -endobj - -1362 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [1363 0 R] ->> -endobj - -1363 0 obj -<< - /Type /StructElem - /S /Span - /P 1362 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [23] - /Pg 4929 0 R ->> -endobj - -1364 0 obj -<< - /Type /StructElem - /S /Div - /P 1223 0 R - /K [] ->> -endobj - -1365 0 obj -<< - /Type /StructElem - /S /P - /P 1222 0 R - /K [1366 0 R 22] - /Pg 4929 0 R ->> -endobj - -1366 0 obj -<< - /Type /StructElem - /S /Strong - /P 1365 0 R - /K [21] - /Pg 4929 0 R ->> -endobj - -1367 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [1373 0 R 7 1372 0 R 9 1371 0 R 11 12 1370 0 R 14 15 1369 0 R 17 18 1368 0 R 20] - /Pg 4929 0 R ->> -endobj - -1368 0 obj -<< - /Type /StructElem - /S /Code - /P 1367 0 R - /K [19] - /Pg 4929 0 R ->> -endobj - -1369 0 obj -<< - /Type /StructElem - /S /Code - /P 1367 0 R - /K [16] - /Pg 4929 0 R ->> -endobj - -1370 0 obj -<< - /Type /StructElem - /S /Em - /P 1367 0 R - /K [13] - /Pg 4929 0 R ->> -endobj - -1371 0 obj -<< - /Type /StructElem - /S /Code - /P 1367 0 R - /K [10] - /Pg 4929 0 R ->> -endobj - -1372 0 obj -<< - /Type /StructElem - /S /Code - /P 1367 0 R - /K [8] - /Pg 4929 0 R ->> -endobj - -1373 0 obj -<< - /Type /StructElem - /S /Strong - /P 1367 0 R - /K [6] - /Pg 4929 0 R ->> -endobj - -1374 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [3 4 5] - /Pg 4929 0 R ->> -endobj - -1375 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [1595 0 R 1376 0 R] ->> -endobj - -1376 0 obj -<< - /Type /StructElem - /S /Div - /P 1375 0 R - /K [1594 0 R 1592 0 R 1589 0 R 1587 0 R 1586 0 R 1585 0 R 1581 0 R 1579 0 R 1578 0 R 1574 0 R 1572 0 R 1571 0 R 1566 0 R 1564 0 R 1563 0 R 1558 0 R 1556 0 R 1555 0 R 1554 0 R 1553 0 R 1543 0 R 1541 0 R 1540 0 R 1538 0 R 1536 0 R 1535 0 R 1534 0 R 1533 0 R 1529 0 R 1527 0 R 1526 0 R 1525 0 R 1520 0 R 1518 0 R 1517 0 R 1516 0 R 1515 0 R 1514 0 R 1504 0 R 1502 0 R 1501 0 R 1500 0 R 1499 0 R 1498 0 R 1497 0 R 1491 0 R 1489 0 R 1488 0 R 1487 0 R 1486 0 R 1485 0 R 1479 0 R 1477 0 R 1476 0 R 1475 0 R 1474 0 R 1473 0 R 1469 0 R 1467 0 R 1466 0 R 1465 0 R 1464 0 R 1458 0 R 1456 0 R 1455 0 R 1454 0 R 1453 0 R 1452 0 R 1451 0 R 1445 0 R 1443 0 R 1442 0 R 1441 0 R 1440 0 R 1439 0 R 1433 0 R 1431 0 R 1430 0 R 1429 0 R 1428 0 R 1427 0 R 1423 0 R 1421 0 R 1420 0 R 1419 0 R 1418 0 R 1416 0 R 1414 0 R 1413 0 R 1412 0 R 1411 0 R 1410 0 R 1409 0 R 1399 0 R 1397 0 R 1396 0 R 1393 0 R 1391 0 R 1390 0 R 1384 0 R 1382 0 R 1381 0 R 1378 0 R 1377 0 R] ->> -endobj - -1377 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1378 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1380 0 R 1379 0 R] ->> -endobj - -1379 0 obj -<< - /Type /StructElem - /S /Span - /P 1378 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [2] - /Pg 4929 0 R ->> -endobj - -1380 0 obj -<< - /Type /StructElem - /S /Strong - /P 1378 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [1] - /Pg 4929 0 R ->> -endobj - -1381 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1382 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1383 0 R] ->> -endobj - -1383 0 obj -<< - /Type /StructElem - /S /Span - /P 1382 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [0] - /Pg 4929 0 R ->> -endobj - -1384 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1389 0 R 1388 0 R 1387 0 R 1386 0 R 1385 0 R] ->> -endobj - -1385 0 obj -<< - /Type /StructElem - /S /Span - /P 1384 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [169] - /Pg 4925 0 R ->> -endobj - -1386 0 obj -<< - /Type /StructElem - /S /Formula - /P 1384 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [168] - /Pg 4925 0 R ->> -endobj - -1387 0 obj -<< - /Type /StructElem - /S /Span - /P 1384 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [167] - /Pg 4925 0 R ->> -endobj - -1388 0 obj -<< - /Type /StructElem - /S /Formula - /P 1384 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [166] - /Pg 4925 0 R ->> -endobj - -1389 0 obj -<< - /Type /StructElem - /S /Span - /P 1384 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [165] - /Pg 4925 0 R ->> -endobj - -1390 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1391 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1392 0 R] ->> -endobj - -1392 0 obj -<< - /Type /StructElem - /S /Span - /P 1391 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [164] - /Pg 4925 0 R ->> -endobj - -1393 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1395 0 R 1394 0 R] ->> -endobj - -1394 0 obj -<< - /Type /StructElem - /S /Span - /P 1393 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [163] - /Pg 4925 0 R ->> -endobj - -1395 0 obj -<< - /Type /StructElem - /S /Strong - /P 1393 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [162] - /Pg 4925 0 R ->> -endobj - -1396 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1397 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1398 0 R] ->> -endobj - -1398 0 obj -<< - /Type /StructElem - /S /Span - /P 1397 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [161] - /Pg 4925 0 R ->> -endobj - -1399 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1408 0 R 1407 0 R 1406 0 R 1405 0 R 1404 0 R 1403 0 R 1402 0 R 1401 0 R 1400 0 R] ->> -endobj - -1400 0 obj -<< - /Type /StructElem - /S /Span - /P 1399 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [160] - /Pg 4925 0 R ->> -endobj - -1401 0 obj -<< - /Type /StructElem - /S /Formula - /P 1399 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [159] - /Pg 4925 0 R ->> -endobj - -1402 0 obj -<< - /Type /StructElem - /S /Span - /P 1399 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [158] - /Pg 4925 0 R ->> -endobj - -1403 0 obj -<< - /Type /StructElem - /S /Formula - /P 1399 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [157] - /Pg 4925 0 R ->> -endobj - -1404 0 obj -<< - /Type /StructElem - /S /Span - /P 1399 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [156] - /Pg 4925 0 R ->> -endobj - -1405 0 obj -<< - /Type /StructElem - /S /Formula - /P 1399 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [155] - /Pg 4925 0 R ->> -endobj - -1406 0 obj -<< - /Type /StructElem - /S /Span - /P 1399 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [154] - /Pg 4925 0 R ->> -endobj - -1407 0 obj -<< - /Type /StructElem - /S /Formula - /P 1399 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [153] - /Pg 4925 0 R ->> -endobj - -1408 0 obj -<< - /Type /StructElem - /S /Span - /P 1399 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [152] - /Pg 4925 0 R ->> -endobj - -1409 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1410 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1411 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1412 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1413 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1414 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1415 0 R] ->> -endobj - -1415 0 obj -<< - /Type /StructElem - /S /Span - /P 1414 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [151] - /Pg 4925 0 R ->> -endobj - -1416 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1417 0 R] ->> -endobj - -1417 0 obj -<< - /Type /StructElem - /S /Strong - /P 1416 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [150] - /Pg 4925 0 R ->> -endobj - -1418 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1419 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1420 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1421 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1422 0 R] ->> -endobj - -1422 0 obj -<< - /Type /StructElem - /S /Span - /P 1421 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [149] - /Pg 4925 0 R ->> -endobj - -1423 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1426 0 R 1425 0 R 1424 0 R] ->> -endobj - -1424 0 obj -<< - /Type /StructElem - /S /Span - /P 1423 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [148] - /Pg 4925 0 R ->> -endobj - -1425 0 obj -<< - /Type /StructElem - /S /Formula - /P 1423 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [147] - /Pg 4925 0 R ->> -endobj - -1426 0 obj -<< - /Type /StructElem - /S /Span - /P 1423 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [146] - /Pg 4925 0 R ->> -endobj - -1427 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1428 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1429 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1430 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1431 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1432 0 R] ->> -endobj - -1432 0 obj -<< - /Type /StructElem - /S /Span - /P 1431 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [145] - /Pg 4925 0 R ->> -endobj - -1433 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1438 0 R 1437 0 R 1436 0 R 1435 0 R 1434 0 R] ->> -endobj - -1434 0 obj -<< - /Type /StructElem - /S /Span - /P 1433 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [144] - /Pg 4925 0 R ->> -endobj - -1435 0 obj -<< - /Type /StructElem - /S /Formula - /P 1433 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [143] - /Pg 4925 0 R ->> -endobj - -1436 0 obj -<< - /Type /StructElem - /S /Span - /P 1433 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [142] - /Pg 4925 0 R ->> -endobj - -1437 0 obj -<< - /Type /StructElem - /S /Formula - /P 1433 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [141] - /Pg 4925 0 R ->> -endobj - -1438 0 obj -<< - /Type /StructElem - /S /Span - /P 1433 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [140] - /Pg 4925 0 R ->> -endobj - -1439 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1440 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1441 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1442 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1443 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1444 0 R] ->> -endobj - -1444 0 obj -<< - /Type /StructElem - /S /Span - /P 1443 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [139] - /Pg 4925 0 R ->> -endobj - -1445 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1450 0 R 1449 0 R 1448 0 R 1447 0 R 1446 0 R] ->> -endobj - -1446 0 obj -<< - /Type /StructElem - /S /Span - /P 1445 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [138] - /Pg 4925 0 R ->> -endobj - -1447 0 obj -<< - /Type /StructElem - /S /Formula - /P 1445 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [137] - /Pg 4925 0 R ->> -endobj - -1448 0 obj -<< - /Type /StructElem - /S /Span - /P 1445 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [136] - /Pg 4925 0 R ->> -endobj - -1449 0 obj -<< - /Type /StructElem - /S /Formula - /P 1445 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [135] - /Pg 4925 0 R ->> -endobj - -1450 0 obj -<< - /Type /StructElem - /S /Span - /P 1445 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [134] - /Pg 4925 0 R ->> -endobj - -1451 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1452 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1453 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1454 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1455 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1456 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1457 0 R] ->> -endobj - -1457 0 obj -<< - /Type /StructElem - /S /Span - /P 1456 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [133] - /Pg 4925 0 R ->> -endobj - -1458 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1463 0 R 1462 0 R 1461 0 R 1460 0 R 1459 0 R] ->> -endobj - -1459 0 obj -<< - /Type /StructElem - /S /Span - /P 1458 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [131] - /Pg 4925 0 R ->> -endobj - -1460 0 obj -<< - /Type /StructElem - /S /Strong - /P 1458 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [132] - /Pg 4925 0 R ->> -endobj - -1461 0 obj -<< - /Type /StructElem - /S /Formula - /P 1458 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [130] - /Pg 4925 0 R ->> -endobj - -1462 0 obj -<< - /Type /StructElem - /S /Span - /P 1458 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [129] - /Pg 4925 0 R ->> -endobj - -1463 0 obj -<< - /Type /StructElem - /S /Strong - /P 1458 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [128] - /Pg 4925 0 R ->> -endobj - -1464 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1465 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1466 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1467 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1468 0 R] ->> -endobj - -1468 0 obj -<< - /Type /StructElem - /S /Span - /P 1467 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [127] - /Pg 4925 0 R ->> -endobj - -1469 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1472 0 R 1471 0 R 1470 0 R] ->> -endobj - -1470 0 obj -<< - /Type /StructElem - /S /Span - /P 1469 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [126] - /Pg 4925 0 R ->> -endobj - -1471 0 obj -<< - /Type /StructElem - /S /Formula - /P 1469 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [125] - /Pg 4925 0 R ->> -endobj - -1472 0 obj -<< - /Type /StructElem - /S /Span - /P 1469 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [124] - /Pg 4925 0 R ->> -endobj - -1473 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1474 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1475 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1476 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1477 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1478 0 R] ->> -endobj - -1478 0 obj -<< - /Type /StructElem - /S /Span - /P 1477 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [123] - /Pg 4925 0 R ->> -endobj - -1479 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1484 0 R 1483 0 R 1482 0 R 1481 0 R 1480 0 R] ->> -endobj - -1480 0 obj -<< - /Type /StructElem - /S /Span - /P 1479 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [122] - /Pg 4925 0 R ->> -endobj - -1481 0 obj -<< - /Type /StructElem - /S /Formula - /P 1479 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [121] - /Pg 4925 0 R ->> -endobj - -1482 0 obj -<< - /Type /StructElem - /S /Span - /P 1479 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [120] - /Pg 4925 0 R ->> -endobj - -1483 0 obj -<< - /Type /StructElem - /S /Formula - /P 1479 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [119] - /Pg 4925 0 R ->> -endobj - -1484 0 obj -<< - /Type /StructElem - /S /Span - /P 1479 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [118] - /Pg 4925 0 R ->> -endobj - -1485 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1486 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1487 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1488 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1489 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1490 0 R] ->> -endobj - -1490 0 obj -<< - /Type /StructElem - /S /Span - /P 1489 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [117] - /Pg 4925 0 R ->> -endobj - -1491 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1496 0 R 1495 0 R 1494 0 R 1493 0 R 1492 0 R] ->> -endobj - -1492 0 obj -<< - /Type /StructElem - /S /Span - /P 1491 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [116] - /Pg 4925 0 R ->> -endobj - -1493 0 obj -<< - /Type /StructElem - /S /Formula - /P 1491 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [115] - /Pg 4925 0 R ->> -endobj - -1494 0 obj -<< - /Type /StructElem - /S /Span - /P 1491 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [114] - /Pg 4925 0 R ->> -endobj - -1495 0 obj -<< - /Type /StructElem - /S /Formula - /P 1491 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [113] - /Pg 4925 0 R ->> -endobj - -1496 0 obj -<< - /Type /StructElem - /S /Span - /P 1491 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [112] - /Pg 4925 0 R ->> -endobj - -1497 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1498 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1499 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1500 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1501 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1502 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1503 0 R] ->> -endobj - -1503 0 obj -<< - /Type /StructElem - /S /Span - /P 1502 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [111] - /Pg 4925 0 R ->> -endobj - -1504 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1513 0 R 1512 0 R 1511 0 R 1510 0 R 1509 0 R 1508 0 R 1507 0 R 1506 0 R 1505 0 R] ->> -endobj - -1505 0 obj -<< - /Type /StructElem - /S /Span - /P 1504 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [109] - /Pg 4925 0 R ->> -endobj - -1506 0 obj -<< - /Type /StructElem - /S /Strong - /P 1504 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [110] - /Pg 4925 0 R ->> -endobj - -1507 0 obj -<< - /Type /StructElem - /S /Formula - /P 1504 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [108] - /Pg 4925 0 R ->> -endobj - -1508 0 obj -<< - /Type /StructElem - /S /Span - /P 1504 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [107] - /Pg 4925 0 R ->> -endobj - -1509 0 obj -<< - /Type /StructElem - /S /Formula - /P 1504 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [106] - /Pg 4925 0 R ->> -endobj - -1510 0 obj -<< - /Type /StructElem - /S /Span - /P 1504 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [105] - /Pg 4925 0 R ->> -endobj - -1511 0 obj -<< - /Type /StructElem - /S /Formula - /P 1504 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [104] - /Pg 4925 0 R ->> -endobj - -1512 0 obj -<< - /Type /StructElem - /S /Span - /P 1504 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [103] - /Pg 4925 0 R ->> -endobj - -1513 0 obj -<< - /Type /StructElem - /S /Strong - /P 1504 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [102] - /Pg 4925 0 R ->> -endobj - -1514 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1515 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1516 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1517 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1518 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1519 0 R] ->> -endobj - -1519 0 obj -<< - /Type /StructElem - /S /Span - /P 1518 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [101] - /Pg 4925 0 R ->> -endobj - -1520 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1524 0 R 1523 0 R 1522 0 R 1521 0 R] ->> -endobj - -1521 0 obj -<< - /Type /StructElem - /S /Span - /P 1520 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [97 99] - /Pg 4925 0 R ->> -endobj - -1522 0 obj -<< - /Type /StructElem - /S /Strong - /P 1520 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [100] - /Pg 4925 0 R ->> -endobj - -1523 0 obj -<< - /Type /StructElem - /S /Strong - /P 1520 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [98] - /Pg 4925 0 R ->> -endobj - -1524 0 obj -<< - /Type /StructElem - /S /Strong - /P 1520 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [96] - /Pg 4925 0 R ->> -endobj - -1525 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1526 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1527 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1528 0 R] ->> -endobj - -1528 0 obj -<< - /Type /StructElem - /S /Span - /P 1527 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [95] - /Pg 4925 0 R ->> -endobj - -1529 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1532 0 R 1531 0 R 1530 0 R] ->> -endobj - -1530 0 obj -<< - /Type /StructElem - /S /Span - /P 1529 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [94] - /Pg 4925 0 R ->> -endobj - -1531 0 obj -<< - /Type /StructElem - /S /Formula - /P 1529 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [93] - /Pg 4925 0 R ->> -endobj - -1532 0 obj -<< - /Type /StructElem - /S /Span - /P 1529 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [92] - /Pg 4925 0 R ->> -endobj - -1533 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1534 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1535 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1536 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1537 0 R] ->> -endobj - -1537 0 obj -<< - /Type /StructElem - /S /Span - /P 1536 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [91] - /Pg 4925 0 R ->> -endobj - -1538 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1539 0 R] ->> -endobj - -1539 0 obj -<< - /Type /StructElem - /S /Strong - /P 1538 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [90] - /Pg 4925 0 R ->> -endobj - -1540 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1541 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1542 0 R] ->> -endobj - -1542 0 obj -<< - /Type /StructElem - /S /Span - /P 1541 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [89] - /Pg 4925 0 R ->> -endobj - -1543 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1552 0 R 1551 0 R 1550 0 R 1549 0 R 1548 0 R 1547 0 R 1546 0 R 1545 0 R 1544 0 R] ->> -endobj - -1544 0 obj -<< - /Type /StructElem - /S /Span - /P 1543 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [88] - /Pg 4925 0 R ->> -endobj - -1545 0 obj -<< - /Type /StructElem - /S /Formula - /P 1543 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [87] - /Pg 4925 0 R ->> -endobj - -1546 0 obj -<< - /Type /StructElem - /S /Span - /P 1543 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [86] - /Pg 4925 0 R ->> -endobj - -1547 0 obj -<< - /Type /StructElem - /S /Formula - /P 1543 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [85] - /Pg 4925 0 R ->> -endobj - -1548 0 obj -<< - /Type /StructElem - /S /Span - /P 1543 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [84] - /Pg 4925 0 R ->> -endobj - -1549 0 obj -<< - /Type /StructElem - /S /Formula - /P 1543 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [83] - /Pg 4925 0 R ->> -endobj - -1550 0 obj -<< - /Type /StructElem - /S /Span - /P 1543 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [82] - /Pg 4925 0 R ->> -endobj - -1551 0 obj -<< - /Type /StructElem - /S /Formula - /P 1543 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [81] - /Pg 4925 0 R ->> -endobj - -1552 0 obj -<< - /Type /StructElem - /S /Span - /P 1543 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [80] - /Pg 4925 0 R ->> -endobj - -1553 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1554 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1555 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1556 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1557 0 R] ->> -endobj - -1557 0 obj -<< - /Type /StructElem - /S /Span - /P 1556 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [79] - /Pg 4925 0 R ->> -endobj - -1558 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1562 0 R 1561 0 R 1560 0 R 1559 0 R] ->> -endobj - -1559 0 obj -<< - /Type /StructElem - /S /Span - /P 1558 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [75 77] - /Pg 4925 0 R ->> -endobj - -1560 0 obj -<< - /Type /StructElem - /S /Strong - /P 1558 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [78] - /Pg 4925 0 R ->> -endobj - -1561 0 obj -<< - /Type /StructElem - /S /Strong - /P 1558 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [76] - /Pg 4925 0 R ->> -endobj - -1562 0 obj -<< - /Type /StructElem - /S /Strong - /P 1558 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [74] - /Pg 4925 0 R ->> -endobj - -1563 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1564 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1565 0 R] ->> -endobj - -1565 0 obj -<< - /Type /StructElem - /S /Span - /P 1564 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [73] - /Pg 4925 0 R ->> -endobj - -1566 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1570 0 R 1569 0 R 1568 0 R 1567 0 R] ->> -endobj - -1567 0 obj -<< - /Type /StructElem - /S /Formula - /P 1566 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [72] - /Pg 4925 0 R ->> -endobj - -1568 0 obj -<< - /Type /StructElem - /S /Span - /P 1566 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [71] - /Pg 4925 0 R ->> -endobj - -1569 0 obj -<< - /Type /StructElem - /S /Formula - /P 1566 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [70] - /Pg 4925 0 R ->> -endobj - -1570 0 obj -<< - /Type /StructElem - /S /Span - /P 1566 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [69] - /Pg 4925 0 R ->> -endobj - -1571 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1572 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1573 0 R] ->> -endobj - -1573 0 obj -<< - /Type /StructElem - /S /Span - /P 1572 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [68] - /Pg 4925 0 R ->> -endobj - -1574 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1577 0 R 1576 0 R 1575 0 R] ->> -endobj - -1575 0 obj -<< - /Type /StructElem - /S /Span - /P 1574 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [67] - /Pg 4925 0 R ->> -endobj - -1576 0 obj -<< - /Type /StructElem - /S /Formula - /P 1574 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [66] - /Pg 4925 0 R ->> -endobj - -1577 0 obj -<< - /Type /StructElem - /S /Span - /P 1574 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [65] - /Pg 4925 0 R ->> -endobj - -1578 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1579 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1580 0 R] ->> -endobj - -1580 0 obj -<< - /Type /StructElem - /S /Span - /P 1579 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [64] - /Pg 4925 0 R ->> -endobj - -1581 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1584 0 R 1583 0 R 1582 0 R] ->> -endobj - -1582 0 obj -<< - /Type /StructElem - /S /Span - /P 1581 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [63] - /Pg 4925 0 R ->> -endobj - -1583 0 obj -<< - /Type /StructElem - /S /Formula - /P 1581 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [62] - /Pg 4925 0 R ->> -endobj - -1584 0 obj -<< - /Type /StructElem - /S /Span - /P 1581 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [61] - /Pg 4925 0 R ->> -endobj - -1585 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1586 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1587 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1588 0 R] ->> -endobj - -1588 0 obj -<< - /Type /StructElem - /S /Span - /P 1587 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [60] - /Pg 4925 0 R ->> -endobj - -1589 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1591 0 R 1590 0 R] ->> -endobj - -1590 0 obj -<< - /Type /StructElem - /S /Span - /P 1589 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [59] - /Pg 4925 0 R ->> -endobj - -1591 0 obj -<< - /Type /StructElem - /S /Strong - /P 1589 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [58] - /Pg 4925 0 R ->> -endobj - -1592 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [1593 0 R] ->> -endobj - -1593 0 obj -<< - /Type /StructElem - /S /Span - /P 1592 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [57] - /Pg 4925 0 R ->> -endobj - -1594 0 obj -<< - /Type /StructElem - /S /Div - /P 1376 0 R - /K [] ->> -endobj - -1595 0 obj -<< - /Type /StructElem - /S /P - /P 1375 0 R - /K [1596 0 R 56] - /Pg 4925 0 R ->> -endobj - -1596 0 obj -<< - /Type /StructElem - /S /Strong - /P 1595 0 R - /K [55] - /Pg 4925 0 R ->> -endobj - -1597 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [1604 0 R 39 1603 0 R 41 42 1602 0 R 44 45 1601 0 R 47 48 1600 0 R 50 1599 0 R 52 1598 0 R 54] - /Pg 4925 0 R ->> -endobj - -1598 0 obj -<< - /Type /StructElem - /S /Code - /P 1597 0 R - /K [53] - /Pg 4925 0 R ->> -endobj - -1599 0 obj -<< - /Type /StructElem - /S /Code - /P 1597 0 R - /K [51] - /Pg 4925 0 R ->> -endobj - -1600 0 obj -<< - /Type /StructElem - /S /Code - /P 1597 0 R - /K [49] - /Pg 4925 0 R ->> -endobj - -1601 0 obj -<< - /Type /StructElem - /S /Code - /P 1597 0 R - /K [46] - /Pg 4925 0 R ->> -endobj - -1602 0 obj -<< - /Type /StructElem - /S /Em - /P 1597 0 R - /K [43] - /Pg 4925 0 R ->> -endobj - -1603 0 obj -<< - /Type /StructElem - /S /Em - /P 1597 0 R - /K [40] - /Pg 4925 0 R ->> -endobj - -1604 0 obj -<< - /Type /StructElem - /S /Strong - /P 1597 0 R - /K [38] - /Pg 4925 0 R ->> -endobj - -1605 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [33 1607 0 R 35 1606 0 R 37] - /Pg 4925 0 R ->> -endobj - -1606 0 obj -<< - /Type /StructElem - /S /Em - /P 1605 0 R - /K [36] - /Pg 4925 0 R ->> -endobj - -1607 0 obj -<< - /Type /StructElem - /S /Code - /P 1605 0 R - /K [34] - /Pg 4925 0 R ->> -endobj - -1608 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [15 1611 0 R 17 18 19 20 21 22 23 24 25 1610 0 R 27 28 29 1609 0 R 31 32] - /Pg 4925 0 R ->> -endobj - -1609 0 obj -<< - /Type /StructElem - /S /Link - /P 1608 0 R - /K [30 << - /Type /OBJR - /Pg 4925 0 R - /Obj 4924 0 R - >>] - /Pg 4925 0 R ->> -endobj - -1610 0 obj -<< - /Type /StructElem - /S /Link - /P 1608 0 R - /K [26 << - /Type /OBJR - /Pg 4925 0 R - /Obj 4923 0 R - >>] - /Pg 4925 0 R ->> -endobj - -1611 0 obj -<< - /Type /StructElem - /S /Em - /P 1608 0 R - /K [16] - /Pg 4925 0 R ->> -endobj - -1612 0 obj -<< - /Type /StructElem - /S /H3 - /P 103 0 R - /T (Hot Module Replacement) - /K [13 14] - /Pg 4925 0 R ->> -endobj - -1613 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [8 1614 0 R 10 11 12] - /Pg 4925 0 R ->> -endobj - -1614 0 obj -<< - /Type /StructElem - /S /Code - /P 1613 0 R - /K [9] - /Pg 4925 0 R ->> -endobj - -1615 0 obj -<< - /Type /StructElem - /S /L - /P 103 0 R - /A [<< - /O /List - /ListNumbering /Circle - >>] - /K [1635 0 R 1631 0 R 1627 0 R 1620 0 R 1616 0 R] ->> -endobj - -1616 0 obj -<< - /Type /StructElem - /S /LI - /P 1615 0 R - /K [1619 0 R 1617 0 R] ->> -endobj - -1617 0 obj -<< - /Type /StructElem - /S /LBody - /P 1616 0 R - /K [1618 0 R 7] - /Pg 4925 0 R ->> -endobj - -1618 0 obj -<< - /Type /StructElem - /S /Code - /P 1617 0 R - /K [6] - /Pg 4925 0 R ->> -endobj - -1619 0 obj -<< - /Type /StructElem - /S /Lbl - /P 1616 0 R - /K [5] - /Pg 4925 0 R ->> -endobj - -1620 0 obj -<< - /Type /StructElem - /S /LI - /P 1615 0 R - /K [1626 0 R 1621 0 R] ->> -endobj - -1621 0 obj -<< - /Type /StructElem - /S /LBody - /P 1620 0 R - /K [1625 0 R 100 101 102 1624 0 R 104 1623 0 R 106 << - /Type /MCR - /MCID 0 - /Pg 4925 0 R - >> 1622 0 R << - /Type /MCR - /MCID 2 - /Pg 4925 0 R - >> << - /Type /MCR - /MCID 3 - /Pg 4925 0 R - >> << - /Type /MCR - /MCID 4 - /Pg 4925 0 R - >>] - /Pg 4921 0 R ->> -endobj - -1622 0 obj -<< - /Type /StructElem - /S /Code - /P 1621 0 R - /K [1] - /Pg 4925 0 R ->> -endobj - -1623 0 obj -<< - /Type /StructElem - /S /Code - /P 1621 0 R - /K [105] - /Pg 4921 0 R ->> -endobj - -1624 0 obj -<< - /Type /StructElem - /S /Code - /P 1621 0 R - /K [103] - /Pg 4921 0 R ->> -endobj - -1625 0 obj -<< - /Type /StructElem - /S /Code - /P 1621 0 R - /K [99] - /Pg 4921 0 R ->> -endobj - -1626 0 obj -<< - /Type /StructElem - /S /Lbl - /P 1620 0 R - /K [98] - /Pg 4921 0 R ->> -endobj - -1627 0 obj -<< - /Type /StructElem - /S /LI - /P 1615 0 R - /K [1630 0 R 1628 0 R] ->> -endobj - -1628 0 obj -<< - /Type /StructElem - /S /LBody - /P 1627 0 R - /K [1629 0 R 96 97] - /Pg 4921 0 R ->> -endobj - -1629 0 obj -<< - /Type /StructElem - /S /Code - /P 1628 0 R - /K [95] - /Pg 4921 0 R ->> -endobj - -1630 0 obj -<< - /Type /StructElem - /S /Lbl - /P 1627 0 R - /K [94] - /Pg 4921 0 R ->> -endobj - -1631 0 obj -<< - /Type /StructElem - /S /LI - /P 1615 0 R - /K [1634 0 R 1632 0 R] ->> -endobj - -1632 0 obj -<< - /Type /StructElem - /S /LBody - /P 1631 0 R - /K [1633 0 R 92 93] - /Pg 4921 0 R ->> -endobj - -1633 0 obj -<< - /Type /StructElem - /S /Code - /P 1632 0 R - /K [91] - /Pg 4921 0 R ->> -endobj - -1634 0 obj -<< - /Type /StructElem - /S /Lbl - /P 1631 0 R - /K [90] - /Pg 4921 0 R ->> -endobj - -1635 0 obj -<< - /Type /StructElem - /S /LI - /P 1615 0 R - /K [1639 0 R 1636 0 R] ->> -endobj - -1636 0 obj -<< - /Type /StructElem - /S /LBody - /P 1635 0 R - /K [1638 0 R 87 1637 0 R 89] - /Pg 4921 0 R ->> -endobj - -1637 0 obj -<< - /Type /StructElem - /S /Code - /P 1636 0 R - /K [88] - /Pg 4921 0 R ->> -endobj - -1638 0 obj -<< - /Type /StructElem - /S /Code - /P 1636 0 R - /K [86] - /Pg 4921 0 R ->> -endobj - -1639 0 obj -<< - /Type /StructElem - /S /Lbl - /P 1635 0 R - /K [85] - /Pg 4921 0 R ->> -endobj - -1640 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [82 83 84] - /Pg 4921 0 R ->> -endobj - -1641 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [70 1644 0 R 72 73 74 75 1643 0 R 77 78 1642 0 R 80 81] - /Pg 4921 0 R ->> -endobj - -1642 0 obj -<< - /Type /StructElem - /S /Code - /P 1641 0 R - /K [79] - /Pg 4921 0 R ->> -endobj - -1643 0 obj -<< - /Type /StructElem - /S /Code - /P 1641 0 R - /K [76] - /Pg 4921 0 R ->> -endobj - -1644 0 obj -<< - /Type /StructElem - /S /Em - /P 1641 0 R - /K [71] - /Pg 4921 0 R ->> -endobj - -1645 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [1673 0 R 1647 0 R 1646 0 R] ->> -endobj - -1646 0 obj -<< - /Type /StructElem - /S /P - /P 1645 0 R - /K [68 69] - /Pg 4921 0 R ->> -endobj - -1647 0 obj -<< - /Type /StructElem - /S /L - /P 1645 0 R - /A [<< - /O /List - /ListNumbering /Circle - >>] - /K [1669 0 R 1665 0 R 1661 0 R 1657 0 R 1652 0 R 1648 0 R] ->> -endobj - -1648 0 obj -<< - /Type /StructElem - /S /LI - /P 1647 0 R - /K [1651 0 R 1649 0 R] ->> -endobj - -1649 0 obj -<< - /Type /StructElem - /S /LBody - /P 1648 0 R - /K [1650 0 R 67] - /Pg 4921 0 R ->> -endobj - -1650 0 obj -<< - /Type /StructElem - /S /Code - /P 1649 0 R - /K [66] - /Pg 4921 0 R ->> -endobj - -1651 0 obj -<< - /Type /StructElem - /S /Lbl - /P 1648 0 R - /K [65] - /Pg 4921 0 R ->> -endobj - -1652 0 obj -<< - /Type /StructElem - /S /LI - /P 1647 0 R - /K [1656 0 R 1653 0 R] ->> -endobj - -1653 0 obj -<< - /Type /StructElem - /S /LBody - /P 1652 0 R - /K [1655 0 R 62 1654 0 R 64] - /Pg 4921 0 R ->> -endobj - -1654 0 obj -<< - /Type /StructElem - /S /Code - /P 1653 0 R - /K [63] - /Pg 4921 0 R ->> -endobj - -1655 0 obj -<< - /Type /StructElem - /S /Code - /P 1653 0 R - /K [61] - /Pg 4921 0 R ->> -endobj - -1656 0 obj -<< - /Type /StructElem - /S /Lbl - /P 1652 0 R - /K [60] - /Pg 4921 0 R ->> -endobj - -1657 0 obj -<< - /Type /StructElem - /S /LI - /P 1647 0 R - /K [1660 0 R 1658 0 R] ->> -endobj - -1658 0 obj -<< - /Type /StructElem - /S /LBody - /P 1657 0 R - /K [1659 0 R 59] - /Pg 4921 0 R ->> -endobj - -1659 0 obj -<< - /Type /StructElem - /S /Code - /P 1658 0 R - /K [58] - /Pg 4921 0 R ->> -endobj - -1660 0 obj -<< - /Type /StructElem - /S /Lbl - /P 1657 0 R - /K [57] - /Pg 4921 0 R ->> -endobj - -1661 0 obj -<< - /Type /StructElem - /S /LI - /P 1647 0 R - /K [1664 0 R 1662 0 R] ->> -endobj - -1662 0 obj -<< - /Type /StructElem - /S /LBody - /P 1661 0 R - /K [1663 0 R 56] - /Pg 4921 0 R ->> -endobj - -1663 0 obj -<< - /Type /StructElem - /S /Code - /P 1662 0 R - /K [55] - /Pg 4921 0 R ->> -endobj - -1664 0 obj -<< - /Type /StructElem - /S /Lbl - /P 1661 0 R - /K [54] - /Pg 4921 0 R ->> -endobj - -1665 0 obj -<< - /Type /StructElem - /S /LI - /P 1647 0 R - /K [1668 0 R 1666 0 R] ->> -endobj - -1666 0 obj -<< - /Type /StructElem - /S /LBody - /P 1665 0 R - /K [1667 0 R 53] - /Pg 4921 0 R ->> -endobj - -1667 0 obj -<< - /Type /StructElem - /S /Code - /P 1666 0 R - /K [52] - /Pg 4921 0 R ->> -endobj - -1668 0 obj -<< - /Type /StructElem - /S /Lbl - /P 1665 0 R - /K [51] - /Pg 4921 0 R ->> -endobj - -1669 0 obj -<< - /Type /StructElem - /S /LI - /P 1647 0 R - /K [1672 0 R 1670 0 R] ->> -endobj - -1670 0 obj -<< - /Type /StructElem - /S /LBody - /P 1669 0 R - /K [1671 0 R 50] - /Pg 4921 0 R ->> -endobj - -1671 0 obj -<< - /Type /StructElem - /S /Code - /P 1670 0 R - /K [49] - /Pg 4921 0 R ->> -endobj - -1672 0 obj -<< - /Type /StructElem - /S /Lbl - /P 1669 0 R - /K [48] - /Pg 4921 0 R ->> -endobj - -1673 0 obj -<< - /Type /StructElem - /S /P - /P 1645 0 R - /K [1675 0 R 45 1674 0 R 47] - /Pg 4921 0 R ->> -endobj - -1674 0 obj -<< - /Type /StructElem - /S /Em - /P 1673 0 R - /K [46] - /Pg 4921 0 R ->> -endobj - -1675 0 obj -<< - /Type /StructElem - /S /Strong - /P 1673 0 R - /K [42 43 44] - /Pg 4921 0 R ->> -endobj - -1676 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [34 35 1678 0 R 37 1677 0 R 39 40 41] - /Pg 4921 0 R ->> -endobj - -1677 0 obj -<< - /Type /StructElem - /S /Em - /P 1676 0 R - /K [38] - /Pg 4921 0 R ->> -endobj - -1678 0 obj -<< - /Type /StructElem - /S /Link - /P 1676 0 R - /K [36 << - /Type /OBJR - /Pg 4921 0 R - /Obj 4920 0 R - >>] - /Pg 4921 0 R ->> -endobj - -1679 0 obj -<< - /Type /StructElem - /S /H3 - /P 103 0 R - /T (Declarative Configuration Layer) - /K [32 33] - /Pg 4921 0 R ->> -endobj - -1680 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [11 1686 0 R 13 14 15 1685 0 R 17 1684 0 R 19 1683 0 R 21 1682 0 R 24 25 1681 0 R 27 28 29 30 31] - /Pg 4921 0 R ->> -endobj - -1681 0 obj -<< - /Type /StructElem - /S /Em - /P 1680 0 R - /K [26] - /Pg 4921 0 R ->> -endobj - -1682 0 obj -<< - /Type /StructElem - /S /Em - /P 1680 0 R - /K [22 23] - /Pg 4921 0 R ->> -endobj - -1683 0 obj -<< - /Type /StructElem - /S /Code - /P 1680 0 R - /K [20] - /Pg 4921 0 R ->> -endobj - -1684 0 obj -<< - /Type /StructElem - /S /Code - /P 1680 0 R - /K [18] - /Pg 4921 0 R ->> -endobj - -1685 0 obj -<< - /Type /StructElem - /S /Code - /P 1680 0 R - /K [16] - /Pg 4921 0 R ->> -endobj - -1686 0 obj -<< - /Type /StructElem - /S /Em - /P 1680 0 R - /K [12] - /Pg 4921 0 R ->> -endobj - -1687 0 obj -<< - /Type /StructElem - /S /H2 - /P 103 0 R - /T (Component Loader) - /K [9 10] - /Pg 4921 0 R ->> -endobj - -1688 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [152 1693 0 R 154 155 1692 0 R 157 << - /Type /MCR - /MCID 0 - /Pg 4921 0 R - >> 1691 0 R << - /Type /MCR - /MCID 2 - /Pg 4921 0 R - >> 1690 0 R << - /Type /MCR - /MCID 4 - /Pg 4921 0 R - >> 1689 0 R << - /Type /MCR - /MCID 6 - /Pg 4921 0 R - >> << - /Type /MCR - /MCID 7 - /Pg 4921 0 R - >> << - /Type /MCR - /MCID 8 - /Pg 4921 0 R - >>] - /Pg 4917 0 R ->> -endobj - -1689 0 obj -<< - /Type /StructElem - /S /Link - /P 1688 0 R - /K [5 << - /Type /OBJR - /Pg 4921 0 R - /Obj 4919 0 R - >>] - /Pg 4921 0 R ->> -endobj - -1690 0 obj -<< - /Type /StructElem - /S /Formula - /P 1688 0 R - /K [3] - /Pg 4921 0 R ->> -endobj - -1691 0 obj -<< - /Type /StructElem - /S /Code - /P 1688 0 R - /K [1] - /Pg 4921 0 R ->> -endobj - -1692 0 obj -<< - /Type /StructElem - /S /Formula - /P 1688 0 R - /K [156] - /Pg 4917 0 R ->> -endobj - -1693 0 obj -<< - /Type /StructElem - /S /Em - /P 1688 0 R - /K [153] - /Pg 4917 0 R ->> -endobj - -1694 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [1705 0 R 124 125 1704 0 R 127 1703 0 R 129 1702 0 R 131 1701 0 R 133 134 135 1700 0 R 137 1699 0 R 139 140 1698 0 R 142 143 1697 0 R 145 146 1696 0 R 148 149 1695 0 R 151] - /Pg 4917 0 R ->> -endobj - -1695 0 obj -<< - /Type /StructElem - /S /Link - /P 1694 0 R - /K [150 << - /Type /OBJR - /Pg 4917 0 R - /Obj 4916 0 R - >>] - /Pg 4917 0 R ->> -endobj - -1696 0 obj -<< - /Type /StructElem - /S /Code - /P 1694 0 R - /K [147] - /Pg 4917 0 R ->> -endobj - -1697 0 obj -<< - /Type /StructElem - /S /Formula - /P 1694 0 R - /K [144] - /Pg 4917 0 R ->> -endobj - -1698 0 obj -<< - /Type /StructElem - /S /Em - /P 1694 0 R - /K [141] - /Pg 4917 0 R ->> -endobj - -1699 0 obj -<< - /Type /StructElem - /S /Code - /P 1694 0 R - /K [138] - /Pg 4917 0 R ->> -endobj - -1700 0 obj -<< - /Type /StructElem - /S /Code - /P 1694 0 R - /K [136] - /Pg 4917 0 R ->> -endobj - -1701 0 obj -<< - /Type /StructElem - /S /Link - /P 1694 0 R - /K [132 << - /Type /OBJR - /Pg 4917 0 R - /Obj 4915 0 R - >>] - /Pg 4917 0 R ->> -endobj - -1702 0 obj -<< - /Type /StructElem - /S /Code - /P 1694 0 R - /K [130] - /Pg 4917 0 R ->> -endobj - -1703 0 obj -<< - /Type /StructElem - /S /Code - /P 1694 0 R - /K [128] - /Pg 4917 0 R ->> -endobj - -1704 0 obj -<< - /Type /StructElem - /S /Code - /P 1694 0 R - /K [126] - /Pg 4917 0 R ->> -endobj - -1705 0 obj -<< - /Type /StructElem - /S /Link - /P 1694 0 R - /K [123 << - /Type /OBJR - /Pg 4917 0 R - /Obj 4914 0 R - >>] - /Pg 4917 0 R ->> -endobj - -1706 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [1760 0 R 1707 0 R] ->> -endobj - -1707 0 obj -<< - /Type /StructElem - /S /Div - /P 1706 0 R - /K [1759 0 R 1757 0 R 1754 0 R 1752 0 R 1751 0 R 1750 0 R 1746 0 R 1744 0 R 1743 0 R 1741 0 R 1739 0 R 1738 0 R 1737 0 R 1736 0 R 1729 0 R 1727 0 R 1726 0 R 1725 0 R 1717 0 R 1715 0 R 1714 0 R 1713 0 R 1709 0 R 1708 0 R] ->> -endobj - -1708 0 obj -<< - /Type /StructElem - /S /Div - /P 1707 0 R - /K [] ->> -endobj - -1709 0 obj -<< - /Type /StructElem - /S /Div - /P 1707 0 R - /K [1712 0 R 1711 0 R 1710 0 R] ->> -endobj - -1710 0 obj -<< - /Type /StructElem - /S /Span - /P 1709 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [122] - /Pg 4917 0 R ->> -endobj - -1711 0 obj -<< - /Type /StructElem - /S /Formula - /P 1709 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [121] - /Pg 4917 0 R ->> -endobj - -1712 0 obj -<< - /Type /StructElem - /S /Span - /P 1709 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [120] - /Pg 4917 0 R ->> -endobj - -1713 0 obj -<< - /Type /StructElem - /S /Div - /P 1707 0 R - /K [] ->> -endobj - -1714 0 obj -<< - /Type /StructElem - /S /Div - /P 1707 0 R - /K [] ->> -endobj - -1715 0 obj -<< - /Type /StructElem - /S /Div - /P 1707 0 R - /K [1716 0 R] ->> -endobj - -1716 0 obj -<< - /Type /StructElem - /S /Span - /P 1715 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [119] - /Pg 4917 0 R ->> -endobj - -1717 0 obj -<< - /Type /StructElem - /S /Div - /P 1707 0 R - /K [1724 0 R 1723 0 R 1722 0 R 1721 0 R 1720 0 R 1719 0 R 1718 0 R] ->> -endobj - -1718 0 obj -<< - /Type /StructElem - /S /Code - /P 1717 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [118] - /Pg 4917 0 R ->> -endobj - -1719 0 obj -<< - /Type /StructElem - /S /Span - /P 1717 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [113 115 117] - /Pg 4917 0 R ->> -endobj - -1720 0 obj -<< - /Type /StructElem - /S /Strong - /P 1717 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [116] - /Pg 4917 0 R ->> -endobj - -1721 0 obj -<< - /Type /StructElem - /S /Strong - /P 1717 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [114] - /Pg 4917 0 R ->> -endobj - -1722 0 obj -<< - /Type /StructElem - /S /Formula - /P 1717 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [112] - /Pg 4917 0 R ->> -endobj - -1723 0 obj -<< - /Type /StructElem - /S /Span - /P 1717 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [111] - /Pg 4917 0 R ->> -endobj - -1724 0 obj -<< - /Type /StructElem - /S /Strong - /P 1717 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [110] - /Pg 4917 0 R ->> -endobj - -1725 0 obj -<< - /Type /StructElem - /S /Div - /P 1707 0 R - /K [] ->> -endobj - -1726 0 obj -<< - /Type /StructElem - /S /Div - /P 1707 0 R - /K [] ->> -endobj - -1727 0 obj -<< - /Type /StructElem - /S /Div - /P 1707 0 R - /K [1728 0 R] ->> -endobj - -1728 0 obj -<< - /Type /StructElem - /S /Span - /P 1727 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [109] - /Pg 4917 0 R ->> -endobj - -1729 0 obj -<< - /Type /StructElem - /S /Div - /P 1707 0 R - /K [1735 0 R 1734 0 R 1733 0 R 1732 0 R 1731 0 R 1730 0 R] ->> -endobj - -1730 0 obj -<< - /Type /StructElem - /S /Span - /P 1729 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [104 106 108] - /Pg 4917 0 R ->> -endobj - -1731 0 obj -<< - /Type /StructElem - /S /Strong - /P 1729 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [107] - /Pg 4917 0 R ->> -endobj - -1732 0 obj -<< - /Type /StructElem - /S /Strong - /P 1729 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [105] - /Pg 4917 0 R ->> -endobj - -1733 0 obj -<< - /Type /StructElem - /S /Formula - /P 1729 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [103] - /Pg 4917 0 R ->> -endobj - -1734 0 obj -<< - /Type /StructElem - /S /Span - /P 1729 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [102] - /Pg 4917 0 R ->> -endobj - -1735 0 obj -<< - /Type /StructElem - /S /Strong - /P 1729 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [101] - /Pg 4917 0 R ->> -endobj - -1736 0 obj -<< - /Type /StructElem - /S /Div - /P 1707 0 R - /K [] ->> -endobj - -1737 0 obj -<< - /Type /StructElem - /S /Div - /P 1707 0 R - /K [] ->> -endobj - -1738 0 obj -<< - /Type /StructElem - /S /Div - /P 1707 0 R - /K [] ->> -endobj - -1739 0 obj -<< - /Type /StructElem - /S /Div - /P 1707 0 R - /K [1740 0 R] ->> -endobj - -1740 0 obj -<< - /Type /StructElem - /S /Span - /P 1739 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [100] - /Pg 4917 0 R ->> -endobj - -1741 0 obj -<< - /Type /StructElem - /S /Div - /P 1707 0 R - /K [1742 0 R] ->> -endobj - -1742 0 obj -<< - /Type /StructElem - /S /Strong - /P 1741 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [99] - /Pg 4917 0 R ->> -endobj - -1743 0 obj -<< - /Type /StructElem - /S /Div - /P 1707 0 R - /K [] ->> -endobj - -1744 0 obj -<< - /Type /StructElem - /S /Div - /P 1707 0 R - /K [1745 0 R] ->> -endobj - -1745 0 obj -<< - /Type /StructElem - /S /Span - /P 1744 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [98] - /Pg 4917 0 R ->> -endobj - -1746 0 obj -<< - /Type /StructElem - /S /Div - /P 1707 0 R - /K [1749 0 R 1748 0 R 1747 0 R] ->> -endobj - -1747 0 obj -<< - /Type /StructElem - /S /Span - /P 1746 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [97] - /Pg 4917 0 R ->> -endobj - -1748 0 obj -<< - /Type /StructElem - /S /Formula - /P 1746 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [96] - /Pg 4917 0 R ->> -endobj - -1749 0 obj -<< - /Type /StructElem - /S /Span - /P 1746 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [95] - /Pg 4917 0 R ->> -endobj - -1750 0 obj -<< - /Type /StructElem - /S /Div - /P 1707 0 R - /K [] ->> -endobj - -1751 0 obj -<< - /Type /StructElem - /S /Div - /P 1707 0 R - /K [] ->> -endobj - -1752 0 obj -<< - /Type /StructElem - /S /Div - /P 1707 0 R - /K [1753 0 R] ->> -endobj - -1753 0 obj -<< - /Type /StructElem - /S /Span - /P 1752 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [94] - /Pg 4917 0 R ->> -endobj - -1754 0 obj -<< - /Type /StructElem - /S /Div - /P 1707 0 R - /K [1756 0 R 1755 0 R] ->> -endobj - -1755 0 obj -<< - /Type /StructElem - /S /Span - /P 1754 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [93] - /Pg 4917 0 R ->> -endobj - -1756 0 obj -<< - /Type /StructElem - /S /Strong - /P 1754 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [92] - /Pg 4917 0 R ->> -endobj - -1757 0 obj -<< - /Type /StructElem - /S /Div - /P 1707 0 R - /K [1758 0 R] ->> -endobj - -1758 0 obj -<< - /Type /StructElem - /S /Span - /P 1757 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [91] - /Pg 4917 0 R ->> -endobj - -1759 0 obj -<< - /Type /StructElem - /S /Div - /P 1707 0 R - /K [] ->> -endobj - -1760 0 obj -<< - /Type /StructElem - /S /P - /P 1706 0 R - /K [1761 0 R 90] - /Pg 4917 0 R ->> -endobj - -1761 0 obj -<< - /Type /StructElem - /S /Strong - /P 1760 0 R - /K [89] - /Pg 4917 0 R ->> -endobj - -1762 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [61 1773 0 R 63 1772 0 R 65 1771 0 R 67 1770 0 R 69 70 1769 0 R 72 73 1768 0 R 75 76 1767 0 R 78 79 1766 0 R 81 1765 0 R 83 84 1764 0 R 86 1763 0 R 88] - /Pg 4917 0 R ->> -endobj - -1763 0 obj -<< - /Type /StructElem - /S /Link - /P 1762 0 R - /K [87 << - /Type /OBJR - /Pg 4917 0 R - /Obj 4913 0 R - >>] - /Pg 4917 0 R ->> -endobj - -1764 0 obj -<< - /Type /StructElem - /S /Code - /P 1762 0 R - /K [85] - /Pg 4917 0 R ->> -endobj - -1765 0 obj -<< - /Type /StructElem - /S /Link - /P 1762 0 R - /K [82 << - /Type /OBJR - /Pg 4917 0 R - /Obj 4912 0 R - >>] - /Pg 4917 0 R ->> -endobj - -1766 0 obj -<< - /Type /StructElem - /S /Code - /P 1762 0 R - /K [80] - /Pg 4917 0 R ->> -endobj - -1767 0 obj -<< - /Type /StructElem - /S /Code - /P 1762 0 R - /K [77] - /Pg 4917 0 R ->> -endobj - -1768 0 obj -<< - /Type /StructElem - /S /Code - /P 1762 0 R - /K [74] - /Pg 4917 0 R ->> -endobj - -1769 0 obj -<< - /Type /StructElem - /S /Em - /P 1762 0 R - /K [71] - /Pg 4917 0 R ->> -endobj - -1770 0 obj -<< - /Type /StructElem - /S /Code - /P 1762 0 R - /K [68] - /Pg 4917 0 R ->> -endobj - -1771 0 obj -<< - /Type /StructElem - /S /Code - /P 1762 0 R - /K [66] - /Pg 4917 0 R ->> -endobj - -1772 0 obj -<< - /Type /StructElem - /S /Em - /P 1762 0 R - /K [64] - /Pg 4917 0 R ->> -endobj - -1773 0 obj -<< - /Type /StructElem - /S /Link - /P 1762 0 R - /K [62 << - /Type /OBJR - /Pg 4917 0 R - /Obj 4911 0 R - >>] - /Pg 4917 0 R ->> -endobj - -1774 0 obj -<< - /Type /StructElem - /S /H3 - /P 103 0 R - /T (Context Access) - /K [59 60] - /Pg 4917 0 R ->> -endobj - -1775 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [43 1781 0 R 45 1780 0 R 47 1779 0 R 49 1778 0 R 51 52 1777 0 R 54 55 56 1776 0 R 58] - /Pg 4917 0 R ->> -endobj - -1776 0 obj -<< - /Type /StructElem - /S /Link - /P 1775 0 R - /K [57 << - /Type /OBJR - /Pg 4917 0 R - /Obj 4910 0 R - >>] - /Pg 4917 0 R ->> -endobj - -1777 0 obj -<< - /Type /StructElem - /S /Link - /P 1775 0 R - /K [53 << - /Type /OBJR - /Pg 4917 0 R - /Obj 4909 0 R - >>] - /Pg 4917 0 R ->> -endobj - -1778 0 obj -<< - /Type /StructElem - /S /Em - /P 1775 0 R - /K [50] - /Pg 4917 0 R ->> -endobj - -1779 0 obj -<< - /Type /StructElem - /S /Code - /P 1775 0 R - /K [48] - /Pg 4917 0 R ->> -endobj - -1780 0 obj -<< - /Type /StructElem - /S /Code - /P 1775 0 R - /K [46] - /Pg 4917 0 R ->> -endobj - -1781 0 obj -<< - /Type /StructElem - /S /Em - /P 1775 0 R - /K [44] - /Pg 4917 0 R ->> -endobj - -1782 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [34 35 1785 0 R 37 1784 0 R 39 1783 0 R 41 42] - /Pg 4917 0 R ->> -endobj - -1783 0 obj -<< - /Type /StructElem - /S /Link - /P 1782 0 R - /K [40 << - /Type /OBJR - /Pg 4917 0 R - /Obj 4908 0 R - >>] - /Pg 4917 0 R ->> -endobj - -1784 0 obj -<< - /Type /StructElem - /S /Code - /P 1782 0 R - /K [38] - /Pg 4917 0 R ->> -endobj - -1785 0 obj -<< - /Type /StructElem - /S /Link - /P 1782 0 R - /K [36 << - /Type /OBJR - /Pg 4917 0 R - /Obj 4907 0 R - >>] - /Pg 4917 0 R ->> -endobj - -1786 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [1983 0 R 1787 0 R] ->> -endobj - -1787 0 obj -<< - /Type /StructElem - /S /Div - /P 1786 0 R - /K [1982 0 R 1980 0 R 1977 0 R 1975 0 R 1974 0 R 1973 0 R 1968 0 R 1966 0 R 1965 0 R 1958 0 R 1956 0 R 1955 0 R 1951 0 R 1949 0 R 1948 0 R 1943 0 R 1941 0 R 1940 0 R 1932 0 R 1930 0 R 1929 0 R 1928 0 R 1927 0 R 1923 0 R 1921 0 R 1920 0 R 1918 0 R 1916 0 R 1915 0 R 1914 0 R 1913 0 R 1909 0 R 1907 0 R 1904 0 R 1902 0 R 1901 0 R 1900 0 R 1895 0 R 1893 0 R 1892 0 R 1882 0 R 1880 0 R 1879 0 R 1875 0 R 1873 0 R 1872 0 R 1865 0 R 1863 0 R 1862 0 R 1861 0 R 1860 0 R 1856 0 R 1854 0 R 1853 0 R 1851 0 R 1849 0 R 1848 0 R 1847 0 R 1846 0 R 1842 0 R 1840 0 R 1837 0 R 1835 0 R 1834 0 R 1833 0 R 1830 0 R 1828 0 R 1827 0 R 1823 0 R 1821 0 R 1820 0 R 1812 0 R 1810 0 R 1809 0 R 1808 0 R 1807 0 R 1803 0 R 1801 0 R 1800 0 R 1798 0 R 1796 0 R 1795 0 R 1794 0 R 1793 0 R 1789 0 R 1788 0 R] ->> -endobj - -1788 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1789 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1792 0 R 1791 0 R 1790 0 R] ->> -endobj - -1790 0 obj -<< - /Type /StructElem - /S /Span - /P 1789 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [33] - /Pg 4917 0 R ->> -endobj - -1791 0 obj -<< - /Type /StructElem - /S /Formula - /P 1789 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [32] - /Pg 4917 0 R ->> -endobj - -1792 0 obj -<< - /Type /StructElem - /S /Span - /P 1789 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [31] - /Pg 4917 0 R ->> -endobj - -1793 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1794 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1795 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1796 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1797 0 R] ->> -endobj - -1797 0 obj -<< - /Type /StructElem - /S /Span - /P 1796 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [30] - /Pg 4917 0 R ->> -endobj - -1798 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1799 0 R] ->> -endobj - -1799 0 obj -<< - /Type /StructElem - /S /Strong - /P 1798 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [29] - /Pg 4917 0 R ->> -endobj - -1800 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1801 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1802 0 R] ->> -endobj - -1802 0 obj -<< - /Type /StructElem - /S /Span - /P 1801 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [28] - /Pg 4917 0 R ->> -endobj - -1803 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1806 0 R 1805 0 R 1804 0 R] ->> -endobj - -1804 0 obj -<< - /Type /StructElem - /S /Span - /P 1803 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [27] - /Pg 4917 0 R ->> -endobj - -1805 0 obj -<< - /Type /StructElem - /S /Formula - /P 1803 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [26] - /Pg 4917 0 R ->> -endobj - -1806 0 obj -<< - /Type /StructElem - /S /Span - /P 1803 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [25] - /Pg 4917 0 R ->> -endobj - -1807 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1808 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1809 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1810 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1811 0 R] ->> -endobj - -1811 0 obj -<< - /Type /StructElem - /S /Span - /P 1810 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [24] - /Pg 4917 0 R ->> -endobj - -1812 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1819 0 R 1818 0 R 1817 0 R 1816 0 R 1815 0 R 1814 0 R 1813 0 R] ->> -endobj - -1813 0 obj -<< - /Type /StructElem - /S /Span - /P 1812 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [22] - /Pg 4917 0 R ->> -endobj - -1814 0 obj -<< - /Type /StructElem - /S /Strong - /P 1812 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [23] - /Pg 4917 0 R ->> -endobj - -1815 0 obj -<< - /Type /StructElem - /S /Formula - /P 1812 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [21] - /Pg 4917 0 R ->> -endobj - -1816 0 obj -<< - /Type /StructElem - /S /Span - /P 1812 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [20] - /Pg 4917 0 R ->> -endobj - -1817 0 obj -<< - /Type /StructElem - /S /Formula - /P 1812 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [19] - /Pg 4917 0 R ->> -endobj - -1818 0 obj -<< - /Type /StructElem - /S /Span - /P 1812 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [18] - /Pg 4917 0 R ->> -endobj - -1819 0 obj -<< - /Type /StructElem - /S /Strong - /P 1812 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [17] - /Pg 4917 0 R ->> -endobj - -1820 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1821 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1822 0 R] ->> -endobj - -1822 0 obj -<< - /Type /StructElem - /S /Span - /P 1821 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [16] - /Pg 4917 0 R ->> -endobj - -1823 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1826 0 R 1825 0 R 1824 0 R] ->> -endobj - -1824 0 obj -<< - /Type /StructElem - /S /Span - /P 1823 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [15] - /Pg 4917 0 R ->> -endobj - -1825 0 obj -<< - /Type /StructElem - /S /Formula - /P 1823 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [14] - /Pg 4917 0 R ->> -endobj - -1826 0 obj -<< - /Type /StructElem - /S /Span - /P 1823 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [13] - /Pg 4917 0 R ->> -endobj - -1827 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1828 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1829 0 R] ->> -endobj - -1829 0 obj -<< - /Type /StructElem - /S /Span - /P 1828 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [12] - /Pg 4917 0 R ->> -endobj - -1830 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1832 0 R 1831 0 R] ->> -endobj - -1831 0 obj -<< - /Type /StructElem - /S /Span - /P 1830 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [11] - /Pg 4917 0 R ->> -endobj - -1832 0 obj -<< - /Type /StructElem - /S /Strong - /P 1830 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [10] - /Pg 4917 0 R ->> -endobj - -1833 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1834 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1835 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1836 0 R] ->> -endobj - -1836 0 obj -<< - /Type /StructElem - /S /Span - /P 1835 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [9] - /Pg 4917 0 R ->> -endobj - -1837 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1839 0 R 1838 0 R] ->> -endobj - -1838 0 obj -<< - /Type /StructElem - /S /Span - /P 1837 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [8] - /Pg 4917 0 R ->> -endobj - -1839 0 obj -<< - /Type /StructElem - /S /Strong - /P 1837 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [7] - /Pg 4917 0 R ->> -endobj - -1840 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1841 0 R] ->> -endobj - -1841 0 obj -<< - /Type /StructElem - /S /Span - /P 1840 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [6] - /Pg 4917 0 R ->> -endobj - -1842 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1845 0 R 1844 0 R 1843 0 R] ->> -endobj - -1843 0 obj -<< - /Type /StructElem - /S /Span - /P 1842 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [5] - /Pg 4917 0 R ->> -endobj - -1844 0 obj -<< - /Type /StructElem - /S /Formula - /P 1842 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4] - /Pg 4917 0 R ->> -endobj - -1845 0 obj -<< - /Type /StructElem - /S /Span - /P 1842 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [3] - /Pg 4917 0 R ->> -endobj - -1846 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1847 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1848 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1849 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1850 0 R] ->> -endobj - -1850 0 obj -<< - /Type /StructElem - /S /Span - /P 1849 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [2] - /Pg 4917 0 R ->> -endobj - -1851 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1852 0 R] ->> -endobj - -1852 0 obj -<< - /Type /StructElem - /S /Strong - /P 1851 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [1] - /Pg 4917 0 R ->> -endobj - -1853 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1854 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1855 0 R] ->> -endobj - -1855 0 obj -<< - /Type /StructElem - /S /Span - /P 1854 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [0] - /Pg 4917 0 R ->> -endobj - -1856 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1859 0 R 1858 0 R 1857 0 R] ->> -endobj - -1857 0 obj -<< - /Type /StructElem - /S /Span - /P 1856 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [177] - /Pg 4905 0 R ->> -endobj - -1858 0 obj -<< - /Type /StructElem - /S /Formula - /P 1856 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [176] - /Pg 4905 0 R ->> -endobj - -1859 0 obj -<< - /Type /StructElem - /S /Span - /P 1856 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [175] - /Pg 4905 0 R ->> -endobj - -1860 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1861 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1862 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1863 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1864 0 R] ->> -endobj - -1864 0 obj -<< - /Type /StructElem - /S /Span - /P 1863 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [174] - /Pg 4905 0 R ->> -endobj - -1865 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1871 0 R 1870 0 R 1869 0 R 1868 0 R 1867 0 R 1866 0 R] ->> -endobj - -1866 0 obj -<< - /Type /StructElem - /S /Span - /P 1865 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [170 172] - /Pg 4905 0 R ->> -endobj - -1867 0 obj -<< - /Type /StructElem - /S /Strong - /P 1865 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [173] - /Pg 4905 0 R ->> -endobj - -1868 0 obj -<< - /Type /StructElem - /S /Span - /P 1865 0 R - /A [<< - /O /Layout - /Placement /Block - /BaselineShift -0.9786 - /LineHeight 4.88601 - >>] - /K [171] - /Pg 4905 0 R ->> -endobj - -1869 0 obj -<< - /Type /StructElem - /S /Formula - /P 1865 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [169] - /Pg 4905 0 R ->> -endobj - -1870 0 obj -<< - /Type /StructElem - /S /Span - /P 1865 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [168] - /Pg 4905 0 R ->> -endobj - -1871 0 obj -<< - /Type /StructElem - /S /Strong - /P 1865 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [167] - /Pg 4905 0 R ->> -endobj - -1872 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1873 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1874 0 R] ->> -endobj - -1874 0 obj -<< - /Type /StructElem - /S /Span - /P 1873 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [166] - /Pg 4905 0 R ->> -endobj - -1875 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1878 0 R 1877 0 R 1876 0 R] ->> -endobj - -1876 0 obj -<< - /Type /StructElem - /S /Span - /P 1875 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [165] - /Pg 4905 0 R ->> -endobj - -1877 0 obj -<< - /Type /StructElem - /S /Formula - /P 1875 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [164] - /Pg 4905 0 R ->> -endobj - -1878 0 obj -<< - /Type /StructElem - /S /Span - /P 1875 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [163] - /Pg 4905 0 R ->> -endobj - -1879 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1880 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1881 0 R] ->> -endobj - -1881 0 obj -<< - /Type /StructElem - /S /Span - /P 1880 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [162] - /Pg 4905 0 R ->> -endobj - -1882 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1891 0 R 1890 0 R 1889 0 R 1888 0 R 1887 0 R 1886 0 R 1885 0 R 1884 0 R 1883 0 R] ->> -endobj - -1883 0 obj -<< - /Type /StructElem - /S /Span - /P 1882 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [159 161] - /Pg 4905 0 R ->> -endobj - -1884 0 obj -<< - /Type /StructElem - /S /Span - /P 1882 0 R - /A [<< - /O /Layout - /Placement /Block - /BaselineShift -0.9786 - /LineHeight 4.88601 - >>] - /K [160] - /Pg 4905 0 R ->> -endobj - -1885 0 obj -<< - /Type /StructElem - /S /Formula - /P 1882 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [158] - /Pg 4905 0 R ->> -endobj - -1886 0 obj -<< - /Type /StructElem - /S /Span - /P 1882 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [157] - /Pg 4905 0 R ->> -endobj - -1887 0 obj -<< - /Type /StructElem - /S /Formula - /P 1882 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [156] - /Pg 4905 0 R ->> -endobj - -1888 0 obj -<< - /Type /StructElem - /S /Span - /P 1882 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [153 155] - /Pg 4905 0 R ->> -endobj - -1889 0 obj -<< - /Type /StructElem - /S /Strong - /P 1882 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [154] - /Pg 4905 0 R ->> -endobj - -1890 0 obj -<< - /Type /StructElem - /S /Formula - /P 1882 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [152] - /Pg 4905 0 R ->> -endobj - -1891 0 obj -<< - /Type /StructElem - /S /Span - /P 1882 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [151] - /Pg 4905 0 R ->> -endobj - -1892 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1893 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1894 0 R] ->> -endobj - -1894 0 obj -<< - /Type /StructElem - /S /Span - /P 1893 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [150] - /Pg 4905 0 R ->> -endobj - -1895 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1899 0 R 1898 0 R 1897 0 R 1896 0 R] ->> -endobj - -1896 0 obj -<< - /Type /StructElem - /S /Span - /P 1895 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [149] - /Pg 4905 0 R ->> -endobj - -1897 0 obj -<< - /Type /StructElem - /S /Formula - /P 1895 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [148] - /Pg 4905 0 R ->> -endobj - -1898 0 obj -<< - /Type /StructElem - /S /Span - /P 1895 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [145 147] - /Pg 4905 0 R ->> -endobj - -1899 0 obj -<< - /Type /StructElem - /S /Span - /P 1895 0 R - /A [<< - /O /Layout - /Placement /Block - /BaselineShift -0.9786 - /LineHeight 4.88601 - >>] - /K [146] - /Pg 4905 0 R ->> -endobj - -1900 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1901 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1902 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1903 0 R] ->> -endobj - -1903 0 obj -<< - /Type /StructElem - /S /Span - /P 1902 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [144] - /Pg 4905 0 R ->> -endobj - -1904 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1906 0 R 1905 0 R] ->> -endobj - -1905 0 obj -<< - /Type /StructElem - /S /Span - /P 1904 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [143] - /Pg 4905 0 R ->> -endobj - -1906 0 obj -<< - /Type /StructElem - /S /Strong - /P 1904 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [142] - /Pg 4905 0 R ->> -endobj - -1907 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1908 0 R] ->> -endobj - -1908 0 obj -<< - /Type /StructElem - /S /Span - /P 1907 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [141] - /Pg 4905 0 R ->> -endobj - -1909 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1912 0 R 1911 0 R 1910 0 R] ->> -endobj - -1910 0 obj -<< - /Type /StructElem - /S /Span - /P 1909 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [140] - /Pg 4905 0 R ->> -endobj - -1911 0 obj -<< - /Type /StructElem - /S /Formula - /P 1909 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [139] - /Pg 4905 0 R ->> -endobj - -1912 0 obj -<< - /Type /StructElem - /S /Span - /P 1909 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [138] - /Pg 4905 0 R ->> -endobj - -1913 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1914 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1915 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1916 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1917 0 R] ->> -endobj - -1917 0 obj -<< - /Type /StructElem - /S /Span - /P 1916 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [137] - /Pg 4905 0 R ->> -endobj - -1918 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1919 0 R] ->> -endobj - -1919 0 obj -<< - /Type /StructElem - /S /Strong - /P 1918 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [136] - /Pg 4905 0 R ->> -endobj - -1920 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1921 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1922 0 R] ->> -endobj - -1922 0 obj -<< - /Type /StructElem - /S /Span - /P 1921 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [135] - /Pg 4905 0 R ->> -endobj - -1923 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1926 0 R 1925 0 R 1924 0 R] ->> -endobj - -1924 0 obj -<< - /Type /StructElem - /S /Span - /P 1923 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [134] - /Pg 4905 0 R ->> -endobj - -1925 0 obj -<< - /Type /StructElem - /S /Formula - /P 1923 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [133] - /Pg 4905 0 R ->> -endobj - -1926 0 obj -<< - /Type /StructElem - /S /Span - /P 1923 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [132] - /Pg 4905 0 R ->> -endobj - -1927 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1928 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1929 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1930 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1931 0 R] ->> -endobj - -1931 0 obj -<< - /Type /StructElem - /S /Span - /P 1930 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [131] - /Pg 4905 0 R ->> -endobj - -1932 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1939 0 R 1938 0 R 1937 0 R 1936 0 R 1935 0 R 1934 0 R 1933 0 R] ->> -endobj - -1933 0 obj -<< - /Type /StructElem - /S /Span - /P 1932 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [129] - /Pg 4905 0 R ->> -endobj - -1934 0 obj -<< - /Type /StructElem - /S /Strong - /P 1932 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [130] - /Pg 4905 0 R ->> -endobj - -1935 0 obj -<< - /Type /StructElem - /S /Formula - /P 1932 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [128] - /Pg 4905 0 R ->> -endobj - -1936 0 obj -<< - /Type /StructElem - /S /Span - /P 1932 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [127] - /Pg 4905 0 R ->> -endobj - -1937 0 obj -<< - /Type /StructElem - /S /Formula - /P 1932 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [126] - /Pg 4905 0 R ->> -endobj - -1938 0 obj -<< - /Type /StructElem - /S /Span - /P 1932 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [125] - /Pg 4905 0 R ->> -endobj - -1939 0 obj -<< - /Type /StructElem - /S /Strong - /P 1932 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [124] - /Pg 4905 0 R ->> -endobj - -1940 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1941 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1942 0 R] ->> -endobj - -1942 0 obj -<< - /Type /StructElem - /S /Span - /P 1941 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [123] - /Pg 4905 0 R ->> -endobj - -1943 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1947 0 R 1946 0 R 1945 0 R 1944 0 R] ->> -endobj - -1944 0 obj -<< - /Type /StructElem - /S /Span - /P 1943 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [119 121] - /Pg 4905 0 R ->> -endobj - -1945 0 obj -<< - /Type /StructElem - /S /Strong - /P 1943 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [122] - /Pg 4905 0 R ->> -endobj - -1946 0 obj -<< - /Type /StructElem - /S /Strong - /P 1943 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [120] - /Pg 4905 0 R ->> -endobj - -1947 0 obj -<< - /Type /StructElem - /S /Strong - /P 1943 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [118] - /Pg 4905 0 R ->> -endobj - -1948 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1949 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1950 0 R] ->> -endobj - -1950 0 obj -<< - /Type /StructElem - /S /Span - /P 1949 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [117] - /Pg 4905 0 R ->> -endobj - -1951 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1954 0 R 1953 0 R 1952 0 R] ->> -endobj - -1952 0 obj -<< - /Type /StructElem - /S /Span - /P 1951 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [116] - /Pg 4905 0 R ->> -endobj - -1953 0 obj -<< - /Type /StructElem - /S /Formula - /P 1951 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [115] - /Pg 4905 0 R ->> -endobj - -1954 0 obj -<< - /Type /StructElem - /S /Span - /P 1951 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [114] - /Pg 4905 0 R ->> -endobj - -1955 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1956 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1957 0 R] ->> -endobj - -1957 0 obj -<< - /Type /StructElem - /S /Span - /P 1956 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [113] - /Pg 4905 0 R ->> -endobj - -1958 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1964 0 R 1963 0 R 1962 0 R 1961 0 R 1960 0 R 1959 0 R] ->> -endobj - -1959 0 obj -<< - /Type /StructElem - /S /Span - /P 1958 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [109 111] - /Pg 4905 0 R ->> -endobj - -1960 0 obj -<< - /Type /StructElem - /S /Strong - /P 1958 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [112] - /Pg 4905 0 R ->> -endobj - -1961 0 obj -<< - /Type /StructElem - /S /Strong - /P 1958 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [110] - /Pg 4905 0 R ->> -endobj - -1962 0 obj -<< - /Type /StructElem - /S /Formula - /P 1958 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [108] - /Pg 4905 0 R ->> -endobj - -1963 0 obj -<< - /Type /StructElem - /S /Span - /P 1958 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [107] - /Pg 4905 0 R ->> -endobj - -1964 0 obj -<< - /Type /StructElem - /S /Strong - /P 1958 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [106] - /Pg 4905 0 R ->> -endobj - -1965 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1966 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1967 0 R] ->> -endobj - -1967 0 obj -<< - /Type /StructElem - /S /Span - /P 1966 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [105] - /Pg 4905 0 R ->> -endobj - -1968 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1972 0 R 1971 0 R 1970 0 R 1969 0 R] ->> -endobj - -1969 0 obj -<< - /Type /StructElem - /S /Formula - /P 1968 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [100 101 102 103 104] - /Pg 4905 0 R ->> -endobj - -1970 0 obj -<< - /Type /StructElem - /S /Span - /P 1968 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [99] - /Pg 4905 0 R ->> -endobj - -1971 0 obj -<< - /Type /StructElem - /S /Formula - /P 1968 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [98] - /Pg 4905 0 R ->> -endobj - -1972 0 obj -<< - /Type /StructElem - /S /Span - /P 1968 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [97] - /Pg 4905 0 R ->> -endobj - -1973 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1974 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1975 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1976 0 R] ->> -endobj - -1976 0 obj -<< - /Type /StructElem - /S /Span - /P 1975 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [96] - /Pg 4905 0 R ->> -endobj - -1977 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1979 0 R 1978 0 R] ->> -endobj - -1978 0 obj -<< - /Type /StructElem - /S /Span - /P 1977 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [95] - /Pg 4905 0 R ->> -endobj - -1979 0 obj -<< - /Type /StructElem - /S /Strong - /P 1977 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [94] - /Pg 4905 0 R ->> -endobj - -1980 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [1981 0 R] ->> -endobj - -1981 0 obj -<< - /Type /StructElem - /S /Span - /P 1980 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [93] - /Pg 4905 0 R ->> -endobj - -1982 0 obj -<< - /Type /StructElem - /S /Div - /P 1787 0 R - /K [] ->> -endobj - -1983 0 obj -<< - /Type /StructElem - /S /P - /P 1786 0 R - /K [1984 0 R 92] - /Pg 4905 0 R ->> -endobj - -1984 0 obj -<< - /Type /StructElem - /S /Strong - /P 1983 0 R - /K [91] - /Pg 4905 0 R ->> -endobj - -1985 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [2009 0 R 52 2008 0 R 54 2007 0 R 56 2006 0 R 58 59 60 2005 0 R 62 63 2004 0 R 65 2003 0 R 67 2000 0 R 1994 0 R 69 1993 0 R 71 72 1992 0 R 74 75 1991 0 R 77 78 1990 0 R 80 1989 0 R 82 1988 0 R 84 85 1987 0 R 87 1986 0 R 89 90] - /Pg 4905 0 R ->> -endobj - -1986 0 obj -<< - /Type /StructElem - /S /Code - /P 1985 0 R - /K [88] - /Pg 4905 0 R ->> -endobj - -1987 0 obj -<< - /Type /StructElem - /S /Code - /P 1985 0 R - /K [86] - /Pg 4905 0 R ->> -endobj - -1988 0 obj -<< - /Type /StructElem - /S /Code - /P 1985 0 R - /K [83] - /Pg 4905 0 R ->> -endobj - -1989 0 obj -<< - /Type /StructElem - /S /Code - /P 1985 0 R - /K [81] - /Pg 4905 0 R ->> -endobj - -1990 0 obj -<< - /Type /StructElem - /S /Formula - /P 1985 0 R - /K [79] - /Pg 4905 0 R ->> -endobj - -1991 0 obj -<< - /Type /StructElem - /S /Code - /P 1985 0 R - /K [76] - /Pg 4905 0 R ->> -endobj - -1992 0 obj -<< - /Type /StructElem - /S /Code - /P 1985 0 R - /K [73] - /Pg 4905 0 R ->> -endobj - -1993 0 obj -<< - /Type /StructElem - /S /Code - /P 1985 0 R - /K [70] - /Pg 4905 0 R ->> -endobj - -1994 0 obj -<< - /Type /StructElem - /S /Note - /P 1985 0 R - /ID (Note 2) - /K [1997 0 R 1996 0 R 180 1995 0 R 182 183 184 185] - /Pg 4905 0 R ->> -endobj - -1995 0 obj -<< - /Type /StructElem - /S /Code - /P 1994 0 R - /K [181] - /Pg 4905 0 R ->> -endobj - -1996 0 obj -<< - /Type /StructElem - /S /Code - /P 1994 0 R - /K [179] - /Pg 4905 0 R ->> -endobj - -1997 0 obj -<< - /Type /StructElem - /S /Lbl - /P 1994 0 R - /K [1998 0 R] ->> -endobj - -1998 0 obj -<< - /Type /StructElem - /S /Link - /P 1997 0 R - /K [<< - /Type /OBJR - /Pg 4905 0 R - /Obj 4904 0 R - >> 1999 0 R] ->> -endobj - -1999 0 obj -<< - /Type /StructElem - /S /Span - /P 1998 0 R - /A [<< - /O /Layout - /BaselineShift 2.5866 - /LineHeight 3.24 - >>] - /K [178] - /Pg 4905 0 R ->> -endobj - -2000 0 obj -<< - /Type /StructElem - /S /Lbl - /P 1985 0 R - /K [2001 0 R] ->> -endobj - -2001 0 obj -<< - /Type /StructElem - /S /Link - /P 2000 0 R - /K [<< - /Type /OBJR - /Pg 4905 0 R - /Obj 4903 0 R - >> 2002 0 R] ->> -endobj - -2002 0 obj -<< - /Type /StructElem - /S /Span - /P 2001 0 R - /A [<< - /O /Layout - /BaselineShift 3.1614 - /LineHeight 3.96 - >>] - /K [68] - /Pg 4905 0 R ->> -endobj - -2003 0 obj -<< - /Type /StructElem - /S /Code - /P 1985 0 R - /K [66] - /Pg 4905 0 R ->> -endobj - -2004 0 obj -<< - /Type /StructElem - /S /Code - /P 1985 0 R - /K [64] - /Pg 4905 0 R ->> -endobj - -2005 0 obj -<< - /Type /StructElem - /S /Code - /P 1985 0 R - /K [61] - /Pg 4905 0 R ->> -endobj - -2006 0 obj -<< - /Type /StructElem - /S /Code - /P 1985 0 R - /K [57] - /Pg 4905 0 R ->> -endobj - -2007 0 obj -<< - /Type /StructElem - /S /Code - /P 1985 0 R - /K [55] - /Pg 4905 0 R ->> -endobj - -2008 0 obj -<< - /Type /StructElem - /S /Link - /P 1985 0 R - /K [53 << - /Type /OBJR - /Pg 4905 0 R - /Obj 4902 0 R - >>] - /Pg 4905 0 R ->> -endobj - -2009 0 obj -<< - /Type /StructElem - /S /Link - /P 1985 0 R - /K [51 << - /Type /OBJR - /Pg 4905 0 R - /Obj 4901 0 R - >>] - /Pg 4905 0 R ->> -endobj - -2010 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [2097 0 R 2011 0 R] ->> -endobj - -2011 0 obj -<< - /Type /StructElem - /S /Div - /P 2010 0 R - /K [2096 0 R 2094 0 R 2091 0 R 2088 0 R 2087 0 R 2086 0 R 2083 0 R 2081 0 R 2080 0 R 2079 0 R 2078 0 R 2076 0 R 2074 0 R 2073 0 R 2072 0 R 2068 0 R 2066 0 R 2065 0 R 2064 0 R 2063 0 R 2062 0 R 2057 0 R 2055 0 R 2054 0 R 2053 0 R 2052 0 R 2050 0 R 2048 0 R 2047 0 R 2043 0 R 2041 0 R 2040 0 R 2034 0 R 2031 0 R 2030 0 R 2024 0 R 2022 0 R 2021 0 R 2019 0 R 2017 0 R 2016 0 R 2013 0 R 2012 0 R] ->> -endobj - -2012 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [] ->> -endobj - -2013 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [2015 0 R 2014 0 R] ->> -endobj - -2014 0 obj -<< - /Type /StructElem - /S /Span - /P 2013 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [50] - /Pg 4905 0 R ->> -endobj - -2015 0 obj -<< - /Type /StructElem - /S /Strong - /P 2013 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [49] - /Pg 4905 0 R ->> -endobj - -2016 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [] ->> -endobj - -2017 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [2018 0 R] ->> -endobj - -2018 0 obj -<< - /Type /StructElem - /S /Span - /P 2017 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [48] - /Pg 4905 0 R ->> -endobj - -2019 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [2020 0 R] ->> -endobj - -2020 0 obj -<< - /Type /StructElem - /S /Span - /P 2019 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [47] - /Pg 4905 0 R ->> -endobj - -2021 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [] ->> -endobj - -2022 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [2023 0 R] ->> -endobj - -2023 0 obj -<< - /Type /StructElem - /S /Span - /P 2022 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [46] - /Pg 4905 0 R ->> -endobj - -2024 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [2029 0 R 2028 0 R 2027 0 R 2026 0 R 2025 0 R] ->> -endobj - -2025 0 obj -<< - /Type /StructElem - /S /Span - /P 2024 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [45] - /Pg 4905 0 R ->> -endobj - -2026 0 obj -<< - /Type /StructElem - /S /Formula - /P 2024 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [44] - /Pg 4905 0 R ->> -endobj - -2027 0 obj -<< - /Type /StructElem - /S /Span - /P 2024 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [43] - /Pg 4905 0 R ->> -endobj - -2028 0 obj -<< - /Type /StructElem - /S /Formula - /P 2024 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [42] - /Pg 4905 0 R ->> -endobj - -2029 0 obj -<< - /Type /StructElem - /S /Span - /P 2024 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [41] - /Pg 4905 0 R ->> -endobj - -2030 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [] ->> -endobj - -2031 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [2033 0 R 2032 0 R] ->> -endobj - -2032 0 obj -<< - /Type /StructElem - /S /Span - /P 2031 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [40] - /Pg 4905 0 R ->> -endobj - -2033 0 obj -<< - /Type /StructElem - /S /Div - /P 2031 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [] ->> -endobj - -2034 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [2039 0 R 2038 0 R 2037 0 R 2036 0 R 2035 0 R] ->> -endobj - -2035 0 obj -<< - /Type /StructElem - /S /Span - /P 2034 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [39] - /Pg 4905 0 R ->> -endobj - -2036 0 obj -<< - /Type /StructElem - /S /Formula - /P 2034 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [38] - /Pg 4905 0 R ->> -endobj - -2037 0 obj -<< - /Type /StructElem - /S /Span - /P 2034 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [37] - /Pg 4905 0 R ->> -endobj - -2038 0 obj -<< - /Type /StructElem - /S /Formula - /P 2034 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [36] - /Pg 4905 0 R ->> -endobj - -2039 0 obj -<< - /Type /StructElem - /S /Span - /P 2034 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [35] - /Pg 4905 0 R ->> -endobj - -2040 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [] ->> -endobj - -2041 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [2042 0 R] ->> -endobj - -2042 0 obj -<< - /Type /StructElem - /S /Span - /P 2041 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [34] - /Pg 4905 0 R ->> -endobj - -2043 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [2046 0 R 2045 0 R 2044 0 R] ->> -endobj - -2044 0 obj -<< - /Type /StructElem - /S /Span - /P 2043 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [33] - /Pg 4905 0 R ->> -endobj - -2045 0 obj -<< - /Type /StructElem - /S /Formula - /P 2043 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [32] - /Pg 4905 0 R ->> -endobj - -2046 0 obj -<< - /Type /StructElem - /S /Span - /P 2043 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [31] - /Pg 4905 0 R ->> -endobj - -2047 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [] ->> -endobj - -2048 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [2049 0 R] ->> -endobj - -2049 0 obj -<< - /Type /StructElem - /S /Span - /P 2048 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [30] - /Pg 4905 0 R ->> -endobj - -2050 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [2051 0 R] ->> -endobj - -2051 0 obj -<< - /Type /StructElem - /S /Span - /P 2050 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [29] - /Pg 4905 0 R ->> -endobj - -2052 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [] ->> -endobj - -2053 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [] ->> -endobj - -2054 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [] ->> -endobj - -2055 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [2056 0 R] ->> -endobj - -2056 0 obj -<< - /Type /StructElem - /S /Span - /P 2055 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [28] - /Pg 4905 0 R ->> -endobj - -2057 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [2061 0 R 2060 0 R 2059 0 R 2058 0 R] ->> -endobj - -2058 0 obj -<< - /Type /StructElem - /S /Formula - /P 2057 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [27] - /Pg 4905 0 R ->> -endobj - -2059 0 obj -<< - /Type /StructElem - /S /Span - /P 2057 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [26] - /Pg 4905 0 R ->> -endobj - -2060 0 obj -<< - /Type /StructElem - /S /Formula - /P 2057 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [25] - /Pg 4905 0 R ->> -endobj - -2061 0 obj -<< - /Type /StructElem - /S /Span - /P 2057 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [24] - /Pg 4905 0 R ->> -endobj - -2062 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [] ->> -endobj - -2063 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [] ->> -endobj - -2064 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [] ->> -endobj - -2065 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [] ->> -endobj - -2066 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [2067 0 R] ->> -endobj - -2067 0 obj -<< - /Type /StructElem - /S /Span - /P 2066 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [23] - /Pg 4905 0 R ->> -endobj - -2068 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [2071 0 R 2070 0 R 2069 0 R] ->> -endobj - -2069 0 obj -<< - /Type /StructElem - /S /Span - /P 2068 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [20 22] - /Pg 4905 0 R ->> -endobj - -2070 0 obj -<< - /Type /StructElem - /S /Strong - /P 2068 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [21] - /Pg 4905 0 R ->> -endobj - -2071 0 obj -<< - /Type /StructElem - /S /Strong - /P 2068 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [19] - /Pg 4905 0 R ->> -endobj - -2072 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [] ->> -endobj - -2073 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [] ->> -endobj - -2074 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [2075 0 R] ->> -endobj - -2075 0 obj -<< - /Type /StructElem - /S /Span - /P 2074 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [18] - /Pg 4905 0 R ->> -endobj - -2076 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [2077 0 R] ->> -endobj - -2077 0 obj -<< - /Type /StructElem - /S /Span - /P 2076 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [17] - /Pg 4905 0 R ->> -endobj - -2078 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [] ->> -endobj - -2079 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [] ->> -endobj - -2080 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [] ->> -endobj - -2081 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [2082 0 R] ->> -endobj - -2082 0 obj -<< - /Type /StructElem - /S /Span - /P 2081 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [16] - /Pg 4905 0 R ->> -endobj - -2083 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [2085 0 R 2084 0 R] ->> -endobj - -2084 0 obj -<< - /Type /StructElem - /S /Span - /P 2083 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [15] - /Pg 4905 0 R ->> -endobj - -2085 0 obj -<< - /Type /StructElem - /S /Strong - /P 2083 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [14] - /Pg 4905 0 R ->> -endobj - -2086 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [] ->> -endobj - -2087 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [] ->> -endobj - -2088 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [2090 0 R 2089 0 R] ->> -endobj - -2089 0 obj -<< - /Type /StructElem - /S /Span - /P 2088 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [13] - /Pg 4905 0 R ->> -endobj - -2090 0 obj -<< - /Type /StructElem - /S /Div - /P 2088 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [] ->> -endobj - -2091 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [2093 0 R 2092 0 R] ->> -endobj - -2092 0 obj -<< - /Type /StructElem - /S /Span - /P 2091 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [12] - /Pg 4905 0 R ->> -endobj - -2093 0 obj -<< - /Type /StructElem - /S /Strong - /P 2091 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [11] - /Pg 4905 0 R ->> -endobj - -2094 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [2095 0 R] ->> -endobj - -2095 0 obj -<< - /Type /StructElem - /S /Span - /P 2094 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [10] - /Pg 4905 0 R ->> -endobj - -2096 0 obj -<< - /Type /StructElem - /S /Div - /P 2011 0 R - /K [] ->> -endobj - -2097 0 obj -<< - /Type /StructElem - /S /P - /P 2010 0 R - /K [2098 0 R 9] - /Pg 4905 0 R ->> -endobj - -2098 0 obj -<< - /Type /StructElem - /S /Strong - /P 2097 0 R - /K [8] - /Pg 4905 0 R ->> -endobj - -2099 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [2116 0 R 173 2115 0 R 175 2114 0 R 177 2113 0 R 179 2112 0 R 181 182 2111 0 R 184 2110 0 R 186 2109 0 R 188 2108 0 R 190 191 2107 0 R 193 2106 0 R 195 2105 0 R 197 198 2104 0 R 200 2103 0 R 202 << - /Type /MCR - /MCID 0 - /Pg 4905 0 R - >> 2102 0 R << - /Type /MCR - /MCID 2 - /Pg 4905 0 R - >> 2101 0 R << - /Type /MCR - /MCID 4 - /Pg 4905 0 R - >> << - /Type /MCR - /MCID 5 - /Pg 4905 0 R - >> 2100 0 R << - /Type /MCR - /MCID 7 - /Pg 4905 0 R - >>] - /Pg 4899 0 R ->> -endobj - -2100 0 obj -<< - /Type /StructElem - /S /Formula - /P 2099 0 R - /K [6] - /Pg 4905 0 R ->> -endobj - -2101 0 obj -<< - /Type /StructElem - /S /Code - /P 2099 0 R - /K [3] - /Pg 4905 0 R ->> -endobj - -2102 0 obj -<< - /Type /StructElem - /S /Formula - /P 2099 0 R - /K [1] - /Pg 4905 0 R ->> -endobj - -2103 0 obj -<< - /Type /StructElem - /S /Link - /P 2099 0 R - /K [201 << - /Type /OBJR - /Pg 4899 0 R - /Obj 4898 0 R - >>] - /Pg 4899 0 R ->> -endobj - -2104 0 obj -<< - /Type /StructElem - /S /Code - /P 2099 0 R - /K [199] - /Pg 4899 0 R ->> -endobj - -2105 0 obj -<< - /Type /StructElem - /S /Em - /P 2099 0 R - /K [196] - /Pg 4899 0 R ->> -endobj - -2106 0 obj -<< - /Type /StructElem - /S /Link - /P 2099 0 R - /K [194 << - /Type /OBJR - /Pg 4899 0 R - /Obj 4897 0 R - >>] - /Pg 4899 0 R ->> -endobj - -2107 0 obj -<< - /Type /StructElem - /S /Code - /P 2099 0 R - /K [192] - /Pg 4899 0 R ->> -endobj - -2108 0 obj -<< - /Type /StructElem - /S /Formula - /P 2099 0 R - /K [189] - /Pg 4899 0 R ->> -endobj - -2109 0 obj -<< - /Type /StructElem - /S /Link - /P 2099 0 R - /K [187 << - /Type /OBJR - /Pg 4899 0 R - /Obj 4896 0 R - >>] - /Pg 4899 0 R ->> -endobj - -2110 0 obj -<< - /Type /StructElem - /S /Code - /P 2099 0 R - /K [185] - /Pg 4899 0 R ->> -endobj - -2111 0 obj -<< - /Type /StructElem - /S /Code - /P 2099 0 R - /K [183] - /Pg 4899 0 R ->> -endobj - -2112 0 obj -<< - /Type /StructElem - /S /Code - /P 2099 0 R - /K [180] - /Pg 4899 0 R ->> -endobj - -2113 0 obj -<< - /Type /StructElem - /S /Formula - /P 2099 0 R - /K [178] - /Pg 4899 0 R ->> -endobj - -2114 0 obj -<< - /Type /StructElem - /S /Code - /P 2099 0 R - /K [176] - /Pg 4899 0 R ->> -endobj - -2115 0 obj -<< - /Type /StructElem - /S /Em - /P 2099 0 R - /K [174] - /Pg 4899 0 R ->> -endobj - -2116 0 obj -<< - /Type /StructElem - /S /Link - /P 2099 0 R - /K [172 << - /Type /OBJR - /Pg 4899 0 R - /Obj 4895 0 R - >>] - /Pg 4899 0 R ->> -endobj - -2117 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [149 2126 0 R 151 2125 0 R 153 2124 0 R 155 2123 0 R 157 158 2122 0 R 160 2121 0 R 162 163 2120 0 R 166 2119 0 R 168 2118 0 R 170 171] - /Pg 4899 0 R ->> -endobj - -2118 0 obj -<< - /Type /StructElem - /S /Code - /P 2117 0 R - /K [169] - /Pg 4899 0 R ->> -endobj - -2119 0 obj -<< - /Type /StructElem - /S /Link - /P 2117 0 R - /K [167 << - /Type /OBJR - /Pg 4899 0 R - /Obj 4894 0 R - >>] - /Pg 4899 0 R ->> -endobj - -2120 0 obj -<< - /Type /StructElem - /S /Formula - /P 2117 0 R - /K [164 165] - /Pg 4899 0 R ->> -endobj - -2121 0 obj -<< - /Type /StructElem - /S /Code - /P 2117 0 R - /K [161] - /Pg 4899 0 R ->> -endobj - -2122 0 obj -<< - /Type /StructElem - /S /Code - /P 2117 0 R - /K [159] - /Pg 4899 0 R ->> -endobj - -2123 0 obj -<< - /Type /StructElem - /S /Link - /P 2117 0 R - /K [156 << - /Type /OBJR - /Pg 4899 0 R - /Obj 4893 0 R - >>] - /Pg 4899 0 R ->> -endobj - -2124 0 obj -<< - /Type /StructElem - /S /Link - /P 2117 0 R - /K [154 << - /Type /OBJR - /Pg 4899 0 R - /Obj 4892 0 R - >>] - /Pg 4899 0 R ->> -endobj - -2125 0 obj -<< - /Type /StructElem - /S /Code - /P 2117 0 R - /K [152] - /Pg 4899 0 R ->> -endobj - -2126 0 obj -<< - /Type /StructElem - /S /Em - /P 2117 0 R - /K [150] - /Pg 4899 0 R ->> -endobj - -2127 0 obj -<< - /Type /StructElem - /S /H3 - /P 103 0 R - /T (Component Lifecycle) - /K [147 148] - /Pg 4899 0 R ->> -endobj - -2128 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [2141 0 R 115 116 2140 0 R 118 119 2139 0 R 121 2138 0 R 123 2137 0 R 125 126 2136 0 R 128 2135 0 R 130 131 2134 0 R 133 134 2133 0 R 136 2132 0 R 138 2131 0 R 140 2130 0 R 142 143 2129 0 R 145 146] - /Pg 4899 0 R ->> -endobj - -2129 0 obj -<< - /Type /StructElem - /S /Code - /P 2128 0 R - /K [144] - /Pg 4899 0 R ->> -endobj - -2130 0 obj -<< - /Type /StructElem - /S /Link - /P 2128 0 R - /K [141 << - /Type /OBJR - /Pg 4899 0 R - /Obj 4891 0 R - >>] - /Pg 4899 0 R ->> -endobj - -2131 0 obj -<< - /Type /StructElem - /S /Formula - /P 2128 0 R - /K [139] - /Pg 4899 0 R ->> -endobj - -2132 0 obj -<< - /Type /StructElem - /S /Formula - /P 2128 0 R - /K [137] - /Pg 4899 0 R ->> -endobj - -2133 0 obj -<< - /Type /StructElem - /S /Code - /P 2128 0 R - /K [135] - /Pg 4899 0 R ->> -endobj - -2134 0 obj -<< - /Type /StructElem - /S /Code - /P 2128 0 R - /K [132] - /Pg 4899 0 R ->> -endobj - -2135 0 obj -<< - /Type /StructElem - /S /Link - /P 2128 0 R - /K [129 << - /Type /OBJR - /Pg 4899 0 R - /Obj 4890 0 R - >>] - /Pg 4899 0 R ->> -endobj - -2136 0 obj -<< - /Type /StructElem - /S /Formula - /P 2128 0 R - /K [127] - /Pg 4899 0 R ->> -endobj - -2137 0 obj -<< - /Type /StructElem - /S /Code - /P 2128 0 R - /K [124] - /Pg 4899 0 R ->> -endobj - -2138 0 obj -<< - /Type /StructElem - /S /Formula - /P 2128 0 R - /K [122] - /Pg 4899 0 R ->> -endobj - -2139 0 obj -<< - /Type /StructElem - /S /Code - /P 2128 0 R - /K [120] - /Pg 4899 0 R ->> -endobj - -2140 0 obj -<< - /Type /StructElem - /S /Code - /P 2128 0 R - /K [117] - /Pg 4899 0 R ->> -endobj - -2141 0 obj -<< - /Type /StructElem - /S /Strong - /P 2128 0 R - /K [114] - /Pg 4899 0 R ->> -endobj - -2142 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [2206 0 R 2143 0 R] ->> -endobj - -2143 0 obj -<< - /Type /StructElem - /S /Div - /P 2142 0 R - /K [2205 0 R 2203 0 R 2200 0 R 2198 0 R 2197 0 R 2196 0 R 2191 0 R 2189 0 R 2188 0 R 2187 0 R 2186 0 R 2181 0 R 2179 0 R 2178 0 R 2177 0 R 2176 0 R 2175 0 R 2162 0 R 2160 0 R 2159 0 R 2158 0 R 2157 0 R 2156 0 R 2155 0 R 2153 0 R 2151 0 R 2150 0 R 2149 0 R 2148 0 R 2147 0 R 2145 0 R 2144 0 R] ->> -endobj - -2144 0 obj -<< - /Type /StructElem - /S /Div - /P 2143 0 R - /K [] ->> -endobj - -2145 0 obj -<< - /Type /StructElem - /S /Div - /P 2143 0 R - /K [2146 0 R] ->> -endobj - -2146 0 obj -<< - /Type /StructElem - /S /Strong - /P 2145 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [113] - /Pg 4899 0 R ->> -endobj - -2147 0 obj -<< - /Type /StructElem - /S /Div - /P 2143 0 R - /K [] ->> -endobj - -2148 0 obj -<< - /Type /StructElem - /S /Div - /P 2143 0 R - /K [] ->> -endobj - -2149 0 obj -<< - /Type /StructElem - /S /Div - /P 2143 0 R - /K [] ->> -endobj - -2150 0 obj -<< - /Type /StructElem - /S /Div - /P 2143 0 R - /K [] ->> -endobj - -2151 0 obj -<< - /Type /StructElem - /S /Div - /P 2143 0 R - /K [2152 0 R] ->> -endobj - -2152 0 obj -<< - /Type /StructElem - /S /Span - /P 2151 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [112] - /Pg 4899 0 R ->> -endobj - -2153 0 obj -<< - /Type /StructElem - /S /Div - /P 2143 0 R - /K [2154 0 R] ->> -endobj - -2154 0 obj -<< - /Type /StructElem - /S /Span - /P 2153 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [111] - /Pg 4899 0 R ->> -endobj - -2155 0 obj -<< - /Type /StructElem - /S /Div - /P 2143 0 R - /K [] ->> -endobj - -2156 0 obj -<< - /Type /StructElem - /S /Div - /P 2143 0 R - /K [] ->> -endobj - -2157 0 obj -<< - /Type /StructElem - /S /Div - /P 2143 0 R - /K [] ->> -endobj - -2158 0 obj -<< - /Type /StructElem - /S /Div - /P 2143 0 R - /K [] ->> -endobj - -2159 0 obj -<< - /Type /StructElem - /S /Div - /P 2143 0 R - /K [] ->> -endobj - -2160 0 obj -<< - /Type /StructElem - /S /Div - /P 2143 0 R - /K [2161 0 R] ->> -endobj - -2161 0 obj -<< - /Type /StructElem - /S /Span - /P 2160 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [110] - /Pg 4899 0 R ->> -endobj - -2162 0 obj -<< - /Type /StructElem - /S /Div - /P 2143 0 R - /K [2174 0 R 2173 0 R 2172 0 R 2171 0 R 2170 0 R 2169 0 R 2168 0 R 2167 0 R 2166 0 R 2165 0 R 2164 0 R 2163 0 R] ->> -endobj - -2163 0 obj -<< - /Type /StructElem - /S /Span - /P 2162 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [108] - /Pg 4899 0 R ->> -endobj - -2164 0 obj -<< - /Type /StructElem - /S /Strong - /P 2162 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [109] - /Pg 4899 0 R ->> -endobj - -2165 0 obj -<< - /Type /StructElem - /S /Code - /P 2162 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [107] - /Pg 4899 0 R ->> -endobj - -2166 0 obj -<< - /Type /StructElem - /S /Span - /P 2162 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [106] - /Pg 4899 0 R ->> -endobj - -2167 0 obj -<< - /Type /StructElem - /S /Formula - /P 2162 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [105] - /Pg 4899 0 R ->> -endobj - -2168 0 obj -<< - /Type /StructElem - /S /Span - /P 2162 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [104] - /Pg 4899 0 R ->> -endobj - -2169 0 obj -<< - /Type /StructElem - /S /Code - /P 2162 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [103] - /Pg 4899 0 R ->> -endobj - -2170 0 obj -<< - /Type /StructElem - /S /Span - /P 2162 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [100 102] - /Pg 4899 0 R ->> -endobj - -2171 0 obj -<< - /Type /StructElem - /S /Strong - /P 2162 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [101] - /Pg 4899 0 R ->> -endobj - -2172 0 obj -<< - /Type /StructElem - /S /Formula - /P 2162 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [99] - /Pg 4899 0 R ->> -endobj - -2173 0 obj -<< - /Type /StructElem - /S /Span - /P 2162 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [98] - /Pg 4899 0 R ->> -endobj - -2174 0 obj -<< - /Type /StructElem - /S /Strong - /P 2162 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [97] - /Pg 4899 0 R ->> -endobj - -2175 0 obj -<< - /Type /StructElem - /S /Div - /P 2143 0 R - /K [] ->> -endobj - -2176 0 obj -<< - /Type /StructElem - /S /Div - /P 2143 0 R - /K [] ->> -endobj - -2177 0 obj -<< - /Type /StructElem - /S /Div - /P 2143 0 R - /K [] ->> -endobj - -2178 0 obj -<< - /Type /StructElem - /S /Div - /P 2143 0 R - /K [] ->> -endobj - -2179 0 obj -<< - /Type /StructElem - /S /Div - /P 2143 0 R - /K [2180 0 R] ->> -endobj - -2180 0 obj -<< - /Type /StructElem - /S /Span - /P 2179 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [96] - /Pg 4899 0 R ->> -endobj - -2181 0 obj -<< - /Type /StructElem - /S /Div - /P 2143 0 R - /K [2185 0 R 2184 0 R 2183 0 R 2182 0 R] ->> -endobj - -2182 0 obj -<< - /Type /StructElem - /S /Span - /P 2181 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [92 94] - /Pg 4899 0 R ->> -endobj - -2183 0 obj -<< - /Type /StructElem - /S /Strong - /P 2181 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [95] - /Pg 4899 0 R ->> -endobj - -2184 0 obj -<< - /Type /StructElem - /S /Strong - /P 2181 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [93] - /Pg 4899 0 R ->> -endobj - -2185 0 obj -<< - /Type /StructElem - /S /Strong - /P 2181 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [91] - /Pg 4899 0 R ->> -endobj - -2186 0 obj -<< - /Type /StructElem - /S /Div - /P 2143 0 R - /K [] ->> -endobj - -2187 0 obj -<< - /Type /StructElem - /S /Div - /P 2143 0 R - /K [] ->> -endobj - -2188 0 obj -<< - /Type /StructElem - /S /Div - /P 2143 0 R - /K [] ->> -endobj - -2189 0 obj -<< - /Type /StructElem - /S /Div - /P 2143 0 R - /K [2190 0 R] ->> -endobj - -2190 0 obj -<< - /Type /StructElem - /S /Span - /P 2189 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [90] - /Pg 4899 0 R ->> -endobj - -2191 0 obj -<< - /Type /StructElem - /S /Div - /P 2143 0 R - /K [2195 0 R 2194 0 R 2193 0 R 2192 0 R] ->> -endobj - -2192 0 obj -<< - /Type /StructElem - /S /Span - /P 2191 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [86 88] - /Pg 4899 0 R ->> -endobj - -2193 0 obj -<< - /Type /StructElem - /S /Strong - /P 2191 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [89] - /Pg 4899 0 R ->> -endobj - -2194 0 obj -<< - /Type /StructElem - /S /Strong - /P 2191 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [87] - /Pg 4899 0 R ->> -endobj - -2195 0 obj -<< - /Type /StructElem - /S /Strong - /P 2191 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [85] - /Pg 4899 0 R ->> -endobj - -2196 0 obj -<< - /Type /StructElem - /S /Div - /P 2143 0 R - /K [] ->> -endobj - -2197 0 obj -<< - /Type /StructElem - /S /Div - /P 2143 0 R - /K [] ->> -endobj - -2198 0 obj -<< - /Type /StructElem - /S /Div - /P 2143 0 R - /K [2199 0 R] ->> -endobj - -2199 0 obj -<< - /Type /StructElem - /S /Span - /P 2198 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [84] - /Pg 4899 0 R ->> -endobj - -2200 0 obj -<< - /Type /StructElem - /S /Div - /P 2143 0 R - /K [2202 0 R 2201 0 R] ->> -endobj - -2201 0 obj -<< - /Type /StructElem - /S /Span - /P 2200 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [83] - /Pg 4899 0 R ->> -endobj - -2202 0 obj -<< - /Type /StructElem - /S /Strong - /P 2200 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [82] - /Pg 4899 0 R ->> -endobj - -2203 0 obj -<< - /Type /StructElem - /S /Div - /P 2143 0 R - /K [2204 0 R] ->> -endobj - -2204 0 obj -<< - /Type /StructElem - /S /Span - /P 2203 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [81] - /Pg 4899 0 R ->> -endobj - -2205 0 obj -<< - /Type /StructElem - /S /Div - /P 2143 0 R - /K [] ->> -endobj - -2206 0 obj -<< - /Type /StructElem - /S /P - /P 2142 0 R - /K [2207 0 R 80] - /Pg 4899 0 R ->> -endobj - -2207 0 obj -<< - /Type /StructElem - /S /Strong - /P 2206 0 R - /K [79] - /Pg 4899 0 R ->> -endobj - -2208 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [2216 0 R 58 59 2215 0 R 61 62 2214 0 R 64 2213 0 R 66 67 2212 0 R 69 2211 0 R 73 2210 0 R 75 76 2209 0 R 78] - /Pg 4899 0 R ->> -endobj - -2209 0 obj -<< - /Type /StructElem - /S /Link - /P 2208 0 R - /K [77 << - /Type /OBJR - /Pg 4899 0 R - /Obj 4889 0 R - >>] - /Pg 4899 0 R ->> -endobj - -2210 0 obj -<< - /Type /StructElem - /S /Code - /P 2208 0 R - /K [74] - /Pg 4899 0 R ->> -endobj - -2211 0 obj -<< - /Type /StructElem - /S /Formula - /P 2208 0 R - /K [70 71 72] - /Pg 4899 0 R ->> -endobj - -2212 0 obj -<< - /Type /StructElem - /S /Link - /P 2208 0 R - /K [68 << - /Type /OBJR - /Pg 4899 0 R - /Obj 4888 0 R - >>] - /Pg 4899 0 R ->> -endobj - -2213 0 obj -<< - /Type /StructElem - /S /Link - /P 2208 0 R - /K [65 << - /Type /OBJR - /Pg 4899 0 R - /Obj 4887 0 R - >>] - /Pg 4899 0 R ->> -endobj - -2214 0 obj -<< - /Type /StructElem - /S /Code - /P 2208 0 R - /K [63] - /Pg 4899 0 R ->> -endobj - -2215 0 obj -<< - /Type /StructElem - /S /Code - /P 2208 0 R - /K [60] - /Pg 4899 0 R ->> -endobj - -2216 0 obj -<< - /Type /StructElem - /S /Link - /P 2208 0 R - /K [57 << - /Type /OBJR - /Pg 4899 0 R - /Obj 4886 0 R - >>] - /Pg 4899 0 R ->> -endobj - -2217 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [2320 0 R 2218 0 R] ->> -endobj - -2218 0 obj -<< - /Type /StructElem - /S /Div - /P 2217 0 R - /K [2319 0 R 2317 0 R 2314 0 R 2312 0 R 2311 0 R 2310 0 R 2303 0 R 2301 0 R 2300 0 R 2294 0 R 2292 0 R 2289 0 R 2287 0 R 2286 0 R 2285 0 R 2282 0 R 2280 0 R 2279 0 R 2278 0 R 2277 0 R 2270 0 R 2268 0 R 2267 0 R 2266 0 R 2259 0 R 2257 0 R 2256 0 R 2255 0 R 2253 0 R 2251 0 R 2250 0 R 2249 0 R 2245 0 R 2243 0 R 2242 0 R 2241 0 R 2240 0 R 2239 0 R 2233 0 R 2231 0 R 2230 0 R 2229 0 R 2228 0 R 2226 0 R 2224 0 R 2223 0 R 2220 0 R 2219 0 R] ->> -endobj - -2219 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [] ->> -endobj - -2220 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [2222 0 R 2221 0 R] ->> -endobj - -2221 0 obj -<< - /Type /StructElem - /S /Span - /P 2220 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [56] - /Pg 4899 0 R ->> -endobj - -2222 0 obj -<< - /Type /StructElem - /S /Strong - /P 2220 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [55] - /Pg 4899 0 R ->> -endobj - -2223 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [] ->> -endobj - -2224 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [2225 0 R] ->> -endobj - -2225 0 obj -<< - /Type /StructElem - /S /Span - /P 2224 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [54] - /Pg 4899 0 R ->> -endobj - -2226 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [2227 0 R] ->> -endobj - -2227 0 obj -<< - /Type /StructElem - /S /Span - /P 2226 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [53] - /Pg 4899 0 R ->> -endobj - -2228 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [] ->> -endobj - -2229 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [] ->> -endobj - -2230 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [] ->> -endobj - -2231 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [2232 0 R] ->> -endobj - -2232 0 obj -<< - /Type /StructElem - /S /Span - /P 2231 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [52] - /Pg 4899 0 R ->> -endobj - -2233 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [2238 0 R 2237 0 R 2236 0 R 2235 0 R 2234 0 R] ->> -endobj - -2234 0 obj -<< - /Type /StructElem - /S /Formula - /P 2233 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [46 47 48 49 50 51] - /Pg 4899 0 R ->> -endobj - -2235 0 obj -<< - /Type /StructElem - /S /Span - /P 2233 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [44 45] - /Pg 4899 0 R ->> -endobj - -2236 0 obj -<< - /Type /StructElem - /S /Code - /P 2233 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [43] - /Pg 4899 0 R ->> -endobj - -2237 0 obj -<< - /Type /StructElem - /S /Span - /P 2233 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [42] - /Pg 4899 0 R ->> -endobj - -2238 0 obj -<< - /Type /StructElem - /S /Strong - /P 2233 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [41] - /Pg 4899 0 R ->> -endobj - -2239 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [] ->> -endobj - -2240 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [] ->> -endobj - -2241 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [] ->> -endobj - -2242 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [] ->> -endobj - -2243 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [2244 0 R] ->> -endobj - -2244 0 obj -<< - /Type /StructElem - /S /Span - /P 2243 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [40] - /Pg 4899 0 R ->> -endobj - -2245 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [2248 0 R 2247 0 R 2246 0 R] ->> -endobj - -2246 0 obj -<< - /Type /StructElem - /S /Span - /P 2245 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [37 39] - /Pg 4899 0 R ->> -endobj - -2247 0 obj -<< - /Type /StructElem - /S /Strong - /P 2245 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [38] - /Pg 4899 0 R ->> -endobj - -2248 0 obj -<< - /Type /StructElem - /S /Strong - /P 2245 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [36] - /Pg 4899 0 R ->> -endobj - -2249 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [] ->> -endobj - -2250 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [] ->> -endobj - -2251 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [2252 0 R] ->> -endobj - -2252 0 obj -<< - /Type /StructElem - /S /Span - /P 2251 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [35] - /Pg 4899 0 R ->> -endobj - -2253 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [2254 0 R] ->> -endobj - -2254 0 obj -<< - /Type /StructElem - /S /Span - /P 2253 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [34] - /Pg 4899 0 R ->> -endobj - -2255 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [] ->> -endobj - -2256 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [] ->> -endobj - -2257 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [2258 0 R] ->> -endobj - -2258 0 obj -<< - /Type /StructElem - /S /Span - /P 2257 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [33] - /Pg 4899 0 R ->> -endobj - -2259 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [2265 0 R 2264 0 R 2263 0 R 2262 0 R 2261 0 R 2260 0 R] ->> -endobj - -2260 0 obj -<< - /Type /StructElem - /S /Formula - /P 2259 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [24 25 26 27 28 29 30 31 32] - /Pg 4899 0 R ->> -endobj - -2261 0 obj -<< - /Type /StructElem - /S /Span - /P 2259 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [22 23] - /Pg 4899 0 R ->> -endobj - -2262 0 obj -<< - /Type /StructElem - /S /Formula - /P 2259 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [21] - /Pg 4899 0 R ->> -endobj - -2263 0 obj -<< - /Type /StructElem - /S /Span - /P 2259 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [20] - /Pg 4899 0 R ->> -endobj - -2264 0 obj -<< - /Type /StructElem - /S /Code - /P 2259 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [19] - /Pg 4899 0 R ->> -endobj - -2265 0 obj -<< - /Type /StructElem - /S /Span - /P 2259 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [18] - /Pg 4899 0 R ->> -endobj - -2266 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [] ->> -endobj - -2267 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [] ->> -endobj - -2268 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [2269 0 R] ->> -endobj - -2269 0 obj -<< - /Type /StructElem - /S /Span - /P 2268 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [17] - /Pg 4899 0 R ->> -endobj - -2270 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [2276 0 R 2275 0 R 2274 0 R 2273 0 R 2272 0 R 2271 0 R] ->> -endobj - -2271 0 obj -<< - /Type /StructElem - /S /Formula - /P 2270 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [13 14 15 16] - /Pg 4899 0 R ->> -endobj - -2272 0 obj -<< - /Type /StructElem - /S /Span - /P 2270 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [11 12] - /Pg 4899 0 R ->> -endobj - -2273 0 obj -<< - /Type /StructElem - /S /Code - /P 2270 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [10] - /Pg 4899 0 R ->> -endobj - -2274 0 obj -<< - /Type /StructElem - /S /Span - /P 2270 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [9] - /Pg 4899 0 R ->> -endobj - -2275 0 obj -<< - /Type /StructElem - /S /Formula - /P 2270 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [8] - /Pg 4899 0 R ->> -endobj - -2276 0 obj -<< - /Type /StructElem - /S /Span - /P 2270 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [7] - /Pg 4899 0 R ->> -endobj - -2277 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [] ->> -endobj - -2278 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [] ->> -endobj - -2279 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [] ->> -endobj - -2280 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [2281 0 R] ->> -endobj - -2281 0 obj -<< - /Type /StructElem - /S /Span - /P 2280 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [6] - /Pg 4899 0 R ->> -endobj - -2282 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [2284 0 R 2283 0 R] ->> -endobj - -2283 0 obj -<< - /Type /StructElem - /S /Span - /P 2282 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [5] - /Pg 4899 0 R ->> -endobj - -2284 0 obj -<< - /Type /StructElem - /S /Strong - /P 2282 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4] - /Pg 4899 0 R ->> -endobj - -2285 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [] ->> -endobj - -2286 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [] ->> -endobj - -2287 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [2288 0 R] ->> -endobj - -2288 0 obj -<< - /Type /StructElem - /S /Span - /P 2287 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [3] - /Pg 4899 0 R ->> -endobj - -2289 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [2291 0 R 2290 0 R] ->> -endobj - -2290 0 obj -<< - /Type /StructElem - /S /Span - /P 2289 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [2] - /Pg 4899 0 R ->> -endobj - -2291 0 obj -<< - /Type /StructElem - /S /Strong - /P 2289 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [1] - /Pg 4899 0 R ->> -endobj - -2292 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [2293 0 R] ->> -endobj - -2293 0 obj -<< - /Type /StructElem - /S /Span - /P 2292 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [0] - /Pg 4899 0 R ->> -endobj - -2294 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [2299 0 R 2298 0 R 2297 0 R 2296 0 R 2295 0 R] ->> -endobj - -2295 0 obj -<< - /Type /StructElem - /S /Formula - /P 2294 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [248 249 250 251 252 253 254] - /Pg 4884 0 R ->> -endobj - -2296 0 obj -<< - /Type /StructElem - /S /Span - /P 2294 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [246 247] - /Pg 4884 0 R ->> -endobj - -2297 0 obj -<< - /Type /StructElem - /S /Code - /P 2294 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [245] - /Pg 4884 0 R ->> -endobj - -2298 0 obj -<< - /Type /StructElem - /S /Span - /P 2294 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [244] - /Pg 4884 0 R ->> -endobj - -2299 0 obj -<< - /Type /StructElem - /S /Strong - /P 2294 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [243] - /Pg 4884 0 R ->> -endobj - -2300 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [] ->> -endobj - -2301 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [2302 0 R] ->> -endobj - -2302 0 obj -<< - /Type /StructElem - /S /Span - /P 2301 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [242] - /Pg 4884 0 R ->> -endobj - -2303 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [2309 0 R 2308 0 R 2307 0 R 2306 0 R 2305 0 R 2304 0 R] ->> -endobj - -2304 0 obj -<< - /Type /StructElem - /S /Formula - /P 2303 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [238 239 240 241] - /Pg 4884 0 R ->> -endobj - -2305 0 obj -<< - /Type /StructElem - /S /Span - /P 2303 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [236 237] - /Pg 4884 0 R ->> -endobj - -2306 0 obj -<< - /Type /StructElem - /S /Code - /P 2303 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [235] - /Pg 4884 0 R ->> -endobj - -2307 0 obj -<< - /Type /StructElem - /S /Span - /P 2303 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [234] - /Pg 4884 0 R ->> -endobj - -2308 0 obj -<< - /Type /StructElem - /S /Formula - /P 2303 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [233] - /Pg 4884 0 R ->> -endobj - -2309 0 obj -<< - /Type /StructElem - /S /Span - /P 2303 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [232] - /Pg 4884 0 R ->> -endobj - -2310 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [] ->> -endobj - -2311 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [] ->> -endobj - -2312 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [2313 0 R] ->> -endobj - -2313 0 obj -<< - /Type /StructElem - /S /Span - /P 2312 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [231] - /Pg 4884 0 R ->> -endobj - -2314 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [2316 0 R 2315 0 R] ->> -endobj - -2315 0 obj -<< - /Type /StructElem - /S /Span - /P 2314 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [230] - /Pg 4884 0 R ->> -endobj - -2316 0 obj -<< - /Type /StructElem - /S /Strong - /P 2314 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [229] - /Pg 4884 0 R ->> -endobj - -2317 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [2318 0 R] ->> -endobj - -2318 0 obj -<< - /Type /StructElem - /S /Span - /P 2317 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [228] - /Pg 4884 0 R ->> -endobj - -2319 0 obj -<< - /Type /StructElem - /S /Div - /P 2218 0 R - /K [] ->> -endobj - -2320 0 obj -<< - /Type /StructElem - /S /P - /P 2217 0 R - /K [2321 0 R 227] - /Pg 4884 0 R ->> -endobj - -2321 0 obj -<< - /Type /StructElem - /S /Strong - /P 2320 0 R - /K [226] - /Pg 4884 0 R ->> -endobj - -2322 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [2332 0 R 190 2331 0 R 197 2330 0 R 200 2329 0 R 202 203 2328 0 R 205 2327 0 R 207 2326 0 R 209 2325 0 R 216 217 2324 0 R 222 223 2323 0 R 225] - /Pg 4884 0 R ->> -endobj - -2323 0 obj -<< - /Type /StructElem - /S /Code - /P 2322 0 R - /K [224] - /Pg 4884 0 R ->> -endobj - -2324 0 obj -<< - /Type /StructElem - /S /Formula - /P 2322 0 R - /K [218 219 220 221] - /Pg 4884 0 R ->> -endobj - -2325 0 obj -<< - /Type /StructElem - /S /Formula - /P 2322 0 R - /K [210 211 212 213 214 215] - /Pg 4884 0 R ->> -endobj - -2326 0 obj -<< - /Type /StructElem - /S /Code - /P 2322 0 R - /K [208] - /Pg 4884 0 R ->> -endobj - -2327 0 obj -<< - /Type /StructElem - /S /Link - /P 2322 0 R - /K [206 << - /Type /OBJR - /Pg 4884 0 R - /Obj 4883 0 R - >>] - /Pg 4884 0 R ->> -endobj - -2328 0 obj -<< - /Type /StructElem - /S /Code - /P 2322 0 R - /K [204] - /Pg 4884 0 R ->> -endobj - -2329 0 obj -<< - /Type /StructElem - /S /Link - /P 2322 0 R - /K [201 << - /Type /OBJR - /Pg 4884 0 R - /Obj 4882 0 R - >>] - /Pg 4884 0 R ->> -endobj - -2330 0 obj -<< - /Type /StructElem - /S /Formula - /P 2322 0 R - /K [198 199] - /Pg 4884 0 R ->> -endobj - -2331 0 obj -<< - /Type /StructElem - /S /Formula - /P 2322 0 R - /K [191 192 193 194 195 196] - /Pg 4884 0 R ->> -endobj - -2332 0 obj -<< - /Type /StructElem - /S /Strong - /P 2322 0 R - /K [189] - /Pg 4884 0 R ->> -endobj - -2333 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [140 2344 0 R 155 2343 0 R 157 158 2342 0 R 160 2341 0 R 165 2340 0 R 167 2339 0 R 175 2338 0 R 177 2337 0 R 179 2336 0 R 181 182 2335 0 R 184 185 2334 0 R 188] - /Pg 4884 0 R ->> -endobj - -2334 0 obj -<< - /Type /StructElem - /S /Em - /P 2333 0 R - /K [186 187] - /Pg 4884 0 R ->> -endobj - -2335 0 obj -<< - /Type /StructElem - /S /Em - /P 2333 0 R - /K [183] - /Pg 4884 0 R ->> -endobj - -2336 0 obj -<< - /Type /StructElem - /S /Code - /P 2333 0 R - /K [180] - /Pg 4884 0 R ->> -endobj - -2337 0 obj -<< - /Type /StructElem - /S /Formula - /P 2333 0 R - /K [178] - /Pg 4884 0 R ->> -endobj - -2338 0 obj -<< - /Type /StructElem - /S /Code - /P 2333 0 R - /K [176] - /Pg 4884 0 R ->> -endobj - -2339 0 obj -<< - /Type /StructElem - /S /Formula - /P 2333 0 R - /K [168 169 170 171 172 173 174] - /Pg 4884 0 R ->> -endobj - -2340 0 obj -<< - /Type /StructElem - /S /Code - /P 2333 0 R - /K [166] - /Pg 4884 0 R ->> -endobj - -2341 0 obj -<< - /Type /StructElem - /S /Formula - /P 2333 0 R - /K [161 162 163 164] - /Pg 4884 0 R ->> -endobj - -2342 0 obj -<< - /Type /StructElem - /S /Link - /P 2333 0 R - /K [159 << - /Type /OBJR - /Pg 4884 0 R - /Obj 4881 0 R - >>] - /Pg 4884 0 R ->> -endobj - -2343 0 obj -<< - /Type /StructElem - /S /Code - /P 2333 0 R - /K [156] - /Pg 4884 0 R ->> -endobj - -2344 0 obj -<< - /Type /StructElem - /S /Formula - /P 2333 0 R - /K [141 142 143 144 145 146 147 148 149 150 151 152 153 154] - /Pg 4884 0 R ->> -endobj - -2345 0 obj -<< - /Type /StructElem - /S /L - /P 103 0 R - /A [<< - /O /List - /ListNumbering /Circle - >>] - /K [2356 0 R 2351 0 R 2346 0 R] ->> -endobj - -2346 0 obj -<< - /Type /StructElem - /S /LI - /P 2345 0 R - /K [2350 0 R 2347 0 R] ->> -endobj - -2347 0 obj -<< - /Type /StructElem - /S /LBody - /P 2346 0 R - /K [2349 0 R 128 2348 0 R 139] - /Pg 4884 0 R ->> -endobj - -2348 0 obj -<< - /Type /StructElem - /S /Formula - /P 2347 0 R - /K [129 130 131 132 133 134 135 136 137 138] - /Pg 4884 0 R ->> -endobj - -2349 0 obj -<< - /Type /StructElem - /S /Code - /P 2347 0 R - /K [127] - /Pg 4884 0 R ->> -endobj - -2350 0 obj -<< - /Type /StructElem - /S /Lbl - /P 2346 0 R - /K [126] - /Pg 4884 0 R ->> -endobj - -2351 0 obj -<< - /Type /StructElem - /S /LI - /P 2345 0 R - /K [2355 0 R 2352 0 R] ->> -endobj - -2352 0 obj -<< - /Type /StructElem - /S /LBody - /P 2351 0 R - /K [2354 0 R 116 2353 0 R 125] - /Pg 4884 0 R ->> -endobj - -2353 0 obj -<< - /Type /StructElem - /S /Formula - /P 2352 0 R - /K [117 118 119 120 121 122 123 124] - /Pg 4884 0 R ->> -endobj - -2354 0 obj -<< - /Type /StructElem - /S /Code - /P 2352 0 R - /K [115] - /Pg 4884 0 R ->> -endobj - -2355 0 obj -<< - /Type /StructElem - /S /Lbl - /P 2351 0 R - /K [114] - /Pg 4884 0 R ->> -endobj - -2356 0 obj -<< - /Type /StructElem - /S /LI - /P 2345 0 R - /K [2360 0 R 2357 0 R] ->> -endobj - -2357 0 obj -<< - /Type /StructElem - /S /LBody - /P 2356 0 R - /K [2359 0 R 102 2358 0 R 113] - /Pg 4884 0 R ->> -endobj - -2358 0 obj -<< - /Type /StructElem - /S /Formula - /P 2357 0 R - /K [103 104 105 106 107 108 109 110 111 112] - /Pg 4884 0 R ->> -endobj - -2359 0 obj -<< - /Type /StructElem - /S /Code - /P 2357 0 R - /K [101] - /Pg 4884 0 R ->> -endobj - -2360 0 obj -<< - /Type /StructElem - /S /Lbl - /P 2356 0 R - /K [100] - /Pg 4884 0 R ->> -endobj - -2361 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [96 2362 0 R 98 99] - /Pg 4884 0 R ->> -endobj - -2362 0 obj -<< - /Type /StructElem - /S /Link - /P 2361 0 R - /K [97 << - /Type /OBJR - /Pg 4884 0 R - /Obj 4880 0 R - >>] - /Pg 4884 0 R ->> -endobj - -2363 0 obj -<< - /Type /StructElem - /S /H3 - /P 103 0 R - /T (Coeffect Operations) - /K [94 95] - /Pg 4884 0 R ->> -endobj - -2364 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [2377 0 R 62 2376 0 R 64 65 2375 0 R 67 2374 0 R 69 2373 0 R 71 2372 0 R 73 2371 0 R 75 76 2370 0 R 78 79 2369 0 R 81 82 2368 0 R 86 2367 0 R 88 89 2366 0 R 91 2365 0 R 93] - /Pg 4884 0 R ->> -endobj - -2365 0 obj -<< - /Type /StructElem - /S /Code - /P 2364 0 R - /K [92] - /Pg 4884 0 R ->> -endobj - -2366 0 obj -<< - /Type /StructElem - /S /Code - /P 2364 0 R - /K [90] - /Pg 4884 0 R ->> -endobj - -2367 0 obj -<< - /Type /StructElem - /S /Link - /P 2364 0 R - /K [87 << - /Type /OBJR - /Pg 4884 0 R - /Obj 4879 0 R - >>] - /Pg 4884 0 R ->> -endobj - -2368 0 obj -<< - /Type /StructElem - /S /Formula - /P 2364 0 R - /K [83 84 85] - /Pg 4884 0 R ->> -endobj - -2369 0 obj -<< - /Type /StructElem - /S /Code - /P 2364 0 R - /K [80] - /Pg 4884 0 R ->> -endobj - -2370 0 obj -<< - /Type /StructElem - /S /Code - /P 2364 0 R - /K [77] - /Pg 4884 0 R ->> -endobj - -2371 0 obj -<< - /Type /StructElem - /S /Code - /P 2364 0 R - /K [74] - /Pg 4884 0 R ->> -endobj - -2372 0 obj -<< - /Type /StructElem - /S /Code - /P 2364 0 R - /K [72] - /Pg 4884 0 R ->> -endobj - -2373 0 obj -<< - /Type /StructElem - /S /Code - /P 2364 0 R - /K [70] - /Pg 4884 0 R ->> -endobj - -2374 0 obj -<< - /Type /StructElem - /S /Link - /P 2364 0 R - /K [68 << - /Type /OBJR - /Pg 4884 0 R - /Obj 4878 0 R - >>] - /Pg 4884 0 R ->> -endobj - -2375 0 obj -<< - /Type /StructElem - /S /Formula - /P 2364 0 R - /K [66] - /Pg 4884 0 R ->> -endobj - -2376 0 obj -<< - /Type /StructElem - /S /Code - /P 2364 0 R - /K [63] - /Pg 4884 0 R ->> -endobj - -2377 0 obj -<< - /Type /StructElem - /S /Code - /P 2364 0 R - /K [61] - /Pg 4884 0 R ->> -endobj - -2378 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [34 2387 0 R 36 2386 0 R 40 2385 0 R 42 43 44 2384 0 R 46 47 2383 0 R 49 2382 0 R 2381 0 R 55 56 2380 0 R 58 2379 0 R 60] - /Pg 4884 0 R ->> -endobj - -2379 0 obj -<< - /Type /StructElem - /S /Code - /P 2378 0 R - /K [59] - /Pg 4884 0 R ->> -endobj - -2380 0 obj -<< - /Type /StructElem - /S /Code - /P 2378 0 R - /K [57] - /Pg 4884 0 R ->> -endobj - -2381 0 obj -<< - /Type /StructElem - /S /Formula - /P 2378 0 R - /K [51 52 53 54] - /Pg 4884 0 R ->> -endobj - -2382 0 obj -<< - /Type /StructElem - /S /Code - /P 2378 0 R - /K [50] - /Pg 4884 0 R ->> -endobj - -2383 0 obj -<< - /Type /StructElem - /S /Link - /P 2378 0 R - /K [48 << - /Type /OBJR - /Pg 4884 0 R - /Obj 4877 0 R - >>] - /Pg 4884 0 R ->> -endobj - -2384 0 obj -<< - /Type /StructElem - /S /Code - /P 2378 0 R - /K [45] - /Pg 4884 0 R ->> -endobj - -2385 0 obj -<< - /Type /StructElem - /S /Link - /P 2378 0 R - /K [41 << - /Type /OBJR - /Pg 4884 0 R - /Obj 4876 0 R - >>] - /Pg 4884 0 R ->> -endobj - -2386 0 obj -<< - /Type /StructElem - /S /Formula - /P 2378 0 R - /K [37 38 39] - /Pg 4884 0 R ->> -endobj - -2387 0 obj -<< - /Type /StructElem - /S /Code - /P 2378 0 R - /K [35] - /Pg 4884 0 R ->> -endobj - -2388 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [2527 0 R 2389 0 R] ->> -endobj - -2389 0 obj -<< - /Type /StructElem - /S /Div - /P 2388 0 R - /K [2526 0 R 2524 0 R 2521 0 R 2519 0 R 2518 0 R 2517 0 R 2513 0 R 2511 0 R 2510 0 R 2506 0 R 2504 0 R 2503 0 R 2500 0 R 2498 0 R 2497 0 R 2496 0 R 2495 0 R 2490 0 R 2488 0 R 2487 0 R 2486 0 R 2480 0 R 2478 0 R 2477 0 R 2476 0 R 2471 0 R 2469 0 R 2468 0 R 2465 0 R 2463 0 R 2460 0 R 2458 0 R 2457 0 R 2456 0 R 2452 0 R 2450 0 R 2449 0 R 2443 0 R 2441 0 R 2440 0 R 2437 0 R 2435 0 R 2434 0 R 2433 0 R 2432 0 R 2427 0 R 2425 0 R 2424 0 R 2423 0 R 2419 0 R 2417 0 R 2416 0 R 2415 0 R 2410 0 R 2408 0 R 2407 0 R 2406 0 R 2404 0 R 2402 0 R 2401 0 R 2397 0 R 2395 0 R 2394 0 R 2391 0 R 2390 0 R] ->> -endobj - -2390 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [] ->> -endobj - -2391 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [2393 0 R 2392 0 R] ->> -endobj - -2392 0 obj -<< - /Type /StructElem - /S /Span - /P 2391 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [33] - /Pg 4884 0 R ->> -endobj - -2393 0 obj -<< - /Type /StructElem - /S /Strong - /P 2391 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [32] - /Pg 4884 0 R ->> -endobj - -2394 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [] ->> -endobj - -2395 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [2396 0 R] ->> -endobj - -2396 0 obj -<< - /Type /StructElem - /S /Span - /P 2395 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [31] - /Pg 4884 0 R ->> -endobj - -2397 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [2400 0 R 2399 0 R 2398 0 R] ->> -endobj - -2398 0 obj -<< - /Type /StructElem - /S /Span - /P 2397 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [30] - /Pg 4884 0 R ->> -endobj - -2399 0 obj -<< - /Type /StructElem - /S /Formula - /P 2397 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [29] - /Pg 4884 0 R ->> -endobj - -2400 0 obj -<< - /Type /StructElem - /S /Span - /P 2397 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [28] - /Pg 4884 0 R ->> -endobj - -2401 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [] ->> -endobj - -2402 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [2403 0 R] ->> -endobj - -2403 0 obj -<< - /Type /StructElem - /S /Span - /P 2402 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [27] - /Pg 4884 0 R ->> -endobj - -2404 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [2405 0 R] ->> -endobj - -2405 0 obj -<< - /Type /StructElem - /S /Span - /P 2404 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [26] - /Pg 4884 0 R ->> -endobj - -2406 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [] ->> -endobj - -2407 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [] ->> -endobj - -2408 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [2409 0 R] ->> -endobj - -2409 0 obj -<< - /Type /StructElem - /S /Span - /P 2408 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [25] - /Pg 4884 0 R ->> -endobj - -2410 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [2414 0 R 2413 0 R 2412 0 R 2411 0 R] ->> -endobj - -2411 0 obj -<< - /Type /StructElem - /S /Span - /P 2410 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [22 24] - /Pg 4884 0 R ->> -endobj - -2412 0 obj -<< - /Type /StructElem - /S /Strong - /P 2410 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [23] - /Pg 4884 0 R ->> -endobj - -2413 0 obj -<< - /Type /StructElem - /S /Formula - /P 2410 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [21] - /Pg 4884 0 R ->> -endobj - -2414 0 obj -<< - /Type /StructElem - /S /Span - /P 2410 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [20] - /Pg 4884 0 R ->> -endobj - -2415 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [] ->> -endobj - -2416 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [] ->> -endobj - -2417 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [2418 0 R] ->> -endobj - -2418 0 obj -<< - /Type /StructElem - /S /Span - /P 2417 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [19] - /Pg 4884 0 R ->> -endobj - -2419 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [2422 0 R 2421 0 R 2420 0 R] ->> -endobj - -2420 0 obj -<< - /Type /StructElem - /S /Span - /P 2419 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [18] - /Pg 4884 0 R ->> -endobj - -2421 0 obj -<< - /Type /StructElem - /S /Formula - /P 2419 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [17] - /Pg 4884 0 R ->> -endobj - -2422 0 obj -<< - /Type /StructElem - /S /Span - /P 2419 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [16] - /Pg 4884 0 R ->> -endobj - -2423 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [] ->> -endobj - -2424 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [] ->> -endobj - -2425 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [2426 0 R] ->> -endobj - -2426 0 obj -<< - /Type /StructElem - /S /Span - /P 2425 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [15] - /Pg 4884 0 R ->> -endobj - -2427 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [2431 0 R 2430 0 R 2429 0 R 2428 0 R] ->> -endobj - -2428 0 obj -<< - /Type /StructElem - /S /Span - /P 2427 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [11 13] - /Pg 4884 0 R ->> -endobj - -2429 0 obj -<< - /Type /StructElem - /S /Strong - /P 2427 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [14] - /Pg 4884 0 R ->> -endobj - -2430 0 obj -<< - /Type /StructElem - /S /Strong - /P 2427 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [12] - /Pg 4884 0 R ->> -endobj - -2431 0 obj -<< - /Type /StructElem - /S /Strong - /P 2427 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [10] - /Pg 4884 0 R ->> -endobj - -2432 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [] ->> -endobj - -2433 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [] ->> -endobj - -2434 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [] ->> -endobj - -2435 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [2436 0 R] ->> -endobj - -2436 0 obj -<< - /Type /StructElem - /S /Span - /P 2435 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [9] - /Pg 4884 0 R ->> -endobj - -2437 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [2439 0 R 2438 0 R] ->> -endobj - -2438 0 obj -<< - /Type /StructElem - /S /Span - /P 2437 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [8] - /Pg 4884 0 R ->> -endobj - -2439 0 obj -<< - /Type /StructElem - /S /Strong - /P 2437 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [7] - /Pg 4884 0 R ->> -endobj - -2440 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [] ->> -endobj - -2441 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [2442 0 R] ->> -endobj - -2442 0 obj -<< - /Type /StructElem - /S /Span - /P 2441 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [6] - /Pg 4884 0 R ->> -endobj - -2443 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [2448 0 R 2447 0 R 2446 0 R 2445 0 R 2444 0 R] ->> -endobj - -2444 0 obj -<< - /Type /StructElem - /S /Span - /P 2443 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [5] - /Pg 4884 0 R ->> -endobj - -2445 0 obj -<< - /Type /StructElem - /S /Formula - /P 2443 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4] - /Pg 4884 0 R ->> -endobj - -2446 0 obj -<< - /Type /StructElem - /S /Span - /P 2443 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [3] - /Pg 4884 0 R ->> -endobj - -2447 0 obj -<< - /Type /StructElem - /S /Formula - /P 2443 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [2] - /Pg 4884 0 R ->> -endobj - -2448 0 obj -<< - /Type /StructElem - /S /Span - /P 2443 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [1] - /Pg 4884 0 R ->> -endobj - -2449 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [] ->> -endobj - -2450 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [2451 0 R] ->> -endobj - -2451 0 obj -<< - /Type /StructElem - /S /Span - /P 2450 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [0] - /Pg 4884 0 R ->> -endobj - -2452 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [2455 0 R 2454 0 R 2453 0 R] ->> -endobj - -2453 0 obj -<< - /Type /StructElem - /S /Span - /P 2452 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [195] - /Pg 4874 0 R ->> -endobj - -2454 0 obj -<< - /Type /StructElem - /S /Formula - /P 2452 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [194] - /Pg 4874 0 R ->> -endobj - -2455 0 obj -<< - /Type /StructElem - /S /Span - /P 2452 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [193] - /Pg 4874 0 R ->> -endobj - -2456 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [] ->> -endobj - -2457 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [] ->> -endobj - -2458 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [2459 0 R] ->> -endobj - -2459 0 obj -<< - /Type /StructElem - /S /Span - /P 2458 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [192] - /Pg 4874 0 R ->> -endobj - -2460 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [2462 0 R 2461 0 R] ->> -endobj - -2461 0 obj -<< - /Type /StructElem - /S /Span - /P 2460 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [191] - /Pg 4874 0 R ->> -endobj - -2462 0 obj -<< - /Type /StructElem - /S /Strong - /P 2460 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [190] - /Pg 4874 0 R ->> -endobj - -2463 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [2464 0 R] ->> -endobj - -2464 0 obj -<< - /Type /StructElem - /S /Span - /P 2463 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [189] - /Pg 4874 0 R ->> -endobj - -2465 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [2467 0 R 2466 0 R] ->> -endobj - -2466 0 obj -<< - /Type /StructElem - /S /Span - /P 2465 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [188] - /Pg 4874 0 R ->> -endobj - -2467 0 obj -<< - /Type /StructElem - /S /Strong - /P 2465 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [187] - /Pg 4874 0 R ->> -endobj - -2468 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [] ->> -endobj - -2469 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [2470 0 R] ->> -endobj - -2470 0 obj -<< - /Type /StructElem - /S /Span - /P 2469 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [186] - /Pg 4874 0 R ->> -endobj - -2471 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [2475 0 R 2474 0 R 2473 0 R 2472 0 R] ->> -endobj - -2472 0 obj -<< - /Type /StructElem - /S /Span - /P 2471 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [182 184] - /Pg 4874 0 R ->> -endobj - -2473 0 obj -<< - /Type /StructElem - /S /Strong - /P 2471 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [185] - /Pg 4874 0 R ->> -endobj - -2474 0 obj -<< - /Type /StructElem - /S /Strong - /P 2471 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [183] - /Pg 4874 0 R ->> -endobj - -2475 0 obj -<< - /Type /StructElem - /S /Strong - /P 2471 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [181] - /Pg 4874 0 R ->> -endobj - -2476 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [] ->> -endobj - -2477 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [] ->> -endobj - -2478 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [2479 0 R] ->> -endobj - -2479 0 obj -<< - /Type /StructElem - /S /Span - /P 2478 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [180] - /Pg 4874 0 R ->> -endobj - -2480 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [2485 0 R 2484 0 R 2483 0 R 2482 0 R 2481 0 R] ->> -endobj - -2481 0 obj -<< - /Type /StructElem - /S /Span - /P 2480 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [179] - /Pg 4874 0 R ->> -endobj - -2482 0 obj -<< - /Type /StructElem - /S /Formula - /P 2480 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [178] - /Pg 4874 0 R ->> -endobj - -2483 0 obj -<< - /Type /StructElem - /S /Span - /P 2480 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [175 177] - /Pg 4874 0 R ->> -endobj - -2484 0 obj -<< - /Type /StructElem - /S /Strong - /P 2480 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [176] - /Pg 4874 0 R ->> -endobj - -2485 0 obj -<< - /Type /StructElem - /S /Strong - /P 2480 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [174] - /Pg 4874 0 R ->> -endobj - -2486 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [] ->> -endobj - -2487 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [] ->> -endobj - -2488 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [2489 0 R] ->> -endobj - -2489 0 obj -<< - /Type /StructElem - /S /Span - /P 2488 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [173] - /Pg 4874 0 R ->> -endobj - -2490 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [2494 0 R 2493 0 R 2492 0 R 2491 0 R] ->> -endobj - -2491 0 obj -<< - /Type /StructElem - /S /Span - /P 2490 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [170 172] - /Pg 4874 0 R ->> -endobj - -2492 0 obj -<< - /Type /StructElem - /S /Strong - /P 2490 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [171] - /Pg 4874 0 R ->> -endobj - -2493 0 obj -<< - /Type /StructElem - /S /Formula - /P 2490 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [169] - /Pg 4874 0 R ->> -endobj - -2494 0 obj -<< - /Type /StructElem - /S /Span - /P 2490 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [168] - /Pg 4874 0 R ->> -endobj - -2495 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [] ->> -endobj - -2496 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [] ->> -endobj - -2497 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [] ->> -endobj - -2498 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [2499 0 R] ->> -endobj - -2499 0 obj -<< - /Type /StructElem - /S /Span - /P 2498 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [167] - /Pg 4874 0 R ->> -endobj - -2500 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [2502 0 R 2501 0 R] ->> -endobj - -2501 0 obj -<< - /Type /StructElem - /S /Span - /P 2500 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [166] - /Pg 4874 0 R ->> -endobj - -2502 0 obj -<< - /Type /StructElem - /S /Strong - /P 2500 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [165] - /Pg 4874 0 R ->> -endobj - -2503 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [] ->> -endobj - -2504 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [2505 0 R] ->> -endobj - -2505 0 obj -<< - /Type /StructElem - /S /Span - /P 2504 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [164] - /Pg 4874 0 R ->> -endobj - -2506 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [2509 0 R 2508 0 R 2507 0 R] ->> -endobj - -2507 0 obj -<< - /Type /StructElem - /S /Span - /P 2506 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [163] - /Pg 4874 0 R ->> -endobj - -2508 0 obj -<< - /Type /StructElem - /S /Formula - /P 2506 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [162] - /Pg 4874 0 R ->> -endobj - -2509 0 obj -<< - /Type /StructElem - /S /Span - /P 2506 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [161] - /Pg 4874 0 R ->> -endobj - -2510 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [] ->> -endobj - -2511 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [2512 0 R] ->> -endobj - -2512 0 obj -<< - /Type /StructElem - /S /Span - /P 2511 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [160] - /Pg 4874 0 R ->> -endobj - -2513 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [2516 0 R 2515 0 R 2514 0 R] ->> -endobj - -2514 0 obj -<< - /Type /StructElem - /S /Span - /P 2513 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [159] - /Pg 4874 0 R ->> -endobj - -2515 0 obj -<< - /Type /StructElem - /S /Formula - /P 2513 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [158] - /Pg 4874 0 R ->> -endobj - -2516 0 obj -<< - /Type /StructElem - /S /Span - /P 2513 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [157] - /Pg 4874 0 R ->> -endobj - -2517 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [] ->> -endobj - -2518 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [] ->> -endobj - -2519 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [2520 0 R] ->> -endobj - -2520 0 obj -<< - /Type /StructElem - /S /Span - /P 2519 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [156] - /Pg 4874 0 R ->> -endobj - -2521 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [2523 0 R 2522 0 R] ->> -endobj - -2522 0 obj -<< - /Type /StructElem - /S /Span - /P 2521 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [155] - /Pg 4874 0 R ->> -endobj - -2523 0 obj -<< - /Type /StructElem - /S /Strong - /P 2521 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [154] - /Pg 4874 0 R ->> -endobj - -2524 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [2525 0 R] ->> -endobj - -2525 0 obj -<< - /Type /StructElem - /S /Span - /P 2524 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [153] - /Pg 4874 0 R ->> -endobj - -2526 0 obj -<< - /Type /StructElem - /S /Div - /P 2389 0 R - /K [] ->> -endobj - -2527 0 obj -<< - /Type /StructElem - /S /P - /P 2388 0 R - /K [2528 0 R 152] - /Pg 4874 0 R ->> -endobj - -2528 0 obj -<< - /Type /StructElem - /S /Strong - /P 2527 0 R - /K [151] - /Pg 4874 0 R ->> -endobj - -2529 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [2535 0 R 138 2534 0 R 140 2533 0 R 144 2532 0 R 146 2531 0 R 148 2530 0 R 150] - /Pg 4874 0 R ->> -endobj - -2530 0 obj -<< - /Type /StructElem - /S /Code - /P 2529 0 R - /K [149] - /Pg 4874 0 R ->> -endobj - -2531 0 obj -<< - /Type /StructElem - /S /Formula - /P 2529 0 R - /K [147] - /Pg 4874 0 R ->> -endobj - -2532 0 obj -<< - /Type /StructElem - /S /Formula - /P 2529 0 R - /K [145] - /Pg 4874 0 R ->> -endobj - -2533 0 obj -<< - /Type /StructElem - /S /Formula - /P 2529 0 R - /K [141 142 143] - /Pg 4874 0 R ->> -endobj - -2534 0 obj -<< - /Type /StructElem - /S /Code - /P 2529 0 R - /K [139] - /Pg 4874 0 R ->> -endobj - -2535 0 obj -<< - /Type /StructElem - /S /Link - /P 2529 0 R - /K [137 << - /Type /OBJR - /Pg 4874 0 R - /Obj 4873 0 R - >>] - /Pg 4874 0 R ->> -endobj - -2536 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [98 2546 0 R 100 101 2545 0 R 103 104 2544 0 R 106 107 108 2543 0 R 110 2542 0 R 114 2541 0 R 116 117 2540 0 R 121 2539 0 R 126 127 2538 0 R 130 2537 0 R 134 135 136] - /Pg 4874 0 R ->> -endobj - -2537 0 obj -<< - /Type /StructElem - /S /Formula - /P 2536 0 R - /K [131 132 133] - /Pg 4874 0 R ->> -endobj - -2538 0 obj -<< - /Type /StructElem - /S /Formula - /P 2536 0 R - /K [128 129] - /Pg 4874 0 R ->> -endobj - -2539 0 obj -<< - /Type /StructElem - /S /Formula - /P 2536 0 R - /K [122 123 124 125] - /Pg 4874 0 R ->> -endobj - -2540 0 obj -<< - /Type /StructElem - /S /Formula - /P 2536 0 R - /K [118 119 120] - /Pg 4874 0 R ->> -endobj - -2541 0 obj -<< - /Type /StructElem - /S /Link - /P 2536 0 R - /K [115 << - /Type /OBJR - /Pg 4874 0 R - /Obj 4872 0 R - >>] - /Pg 4874 0 R ->> -endobj - -2542 0 obj -<< - /Type /StructElem - /S /Formula - /P 2536 0 R - /K [111 112 113] - /Pg 4874 0 R ->> -endobj - -2543 0 obj -<< - /Type /StructElem - /S /Code - /P 2536 0 R - /K [109] - /Pg 4874 0 R ->> -endobj - -2544 0 obj -<< - /Type /StructElem - /S /Code - /P 2536 0 R - /K [105] - /Pg 4874 0 R ->> -endobj - -2545 0 obj -<< - /Type /StructElem - /S /Code - /P 2536 0 R - /K [102] - /Pg 4874 0 R ->> -endobj - -2546 0 obj -<< - /Type /StructElem - /S /Link - /P 2536 0 R - /K [99 << - /Type /OBJR - /Pg 4874 0 R - /Obj 4871 0 R - >>] - /Pg 4874 0 R ->> -endobj - -2547 0 obj -<< - /Type /StructElem - /S /H3 - /P 103 0 R - /T (Effect Tracking) - /K [96 97] - /Pg 4874 0 R ->> -endobj - -2548 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [85 2552 0 R 87 88 2551 0 R 90 91 2550 0 R 93 2549 0 R 95] - /Pg 4874 0 R ->> -endobj - -2549 0 obj -<< - /Type /StructElem - /S /Link - /P 2548 0 R - /K [94 << - /Type /OBJR - /Pg 4874 0 R - /Obj 4870 0 R - >>] - /Pg 4874 0 R ->> -endobj - -2550 0 obj -<< - /Type /StructElem - /S /Link - /P 2548 0 R - /K [92 << - /Type /OBJR - /Pg 4874 0 R - /Obj 4869 0 R - >>] - /Pg 4874 0 R ->> -endobj - -2551 0 obj -<< - /Type /StructElem - /S /Link - /P 2548 0 R - /K [89 << - /Type /OBJR - /Pg 4874 0 R - /Obj 4868 0 R - >>] - /Pg 4874 0 R ->> -endobj - -2552 0 obj -<< - /Type /StructElem - /S /Link - /P 2548 0 R - /K [86 << - /Type /OBJR - /Pg 4874 0 R - /Obj 4867 0 R - >>] - /Pg 4874 0 R ->> -endobj - -2553 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /K [2641 0 R 2554 0 R] ->> -endobj - -2554 0 obj -<< - /Type /StructElem - /S /Div - /P 2553 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [2555 0 R] ->> -endobj - -2555 0 obj -<< - /Type /StructElem - /S /Table - /P 2554 0 R - /K [2638 0 R 2629 0 R 2556 0 R] ->> -endobj - -2556 0 obj -<< - /Type /StructElem - /S /TBody - /P 2555 0 R - /K [2627 0 R 2625 0 R 2620 0 R 2615 0 R 2610 0 R 2601 0 R 2594 0 R 2589 0 R 2584 0 R 2579 0 R 2574 0 R 2569 0 R 2564 0 R 2559 0 R 2557 0 R] ->> -endobj - -2557 0 obj -<< - /Type /StructElem - /S /TR - /P 2556 0 R - /K [2558 0 R] ->> -endobj - -2558 0 obj -<< - /Type /StructElem - /S /TD - /P 2557 0 R - /A [<< - /O /Table - /Headers [(U1x0y1) (U1x1y1)] - /ColSpan 2 - >> << - /O /Layout - /BorderColor [0 0 0] - /BorderStyle [/None /Solid /None /None] - /BorderThickness [0 0.8 0 0] - >>] - /K [] ->> -endobj - -2559 0 obj -<< - /Type /StructElem - /S /TR - /P 2556 0 R - /K [2562 0 R 2560 0 R] ->> -endobj - -2560 0 obj -<< - /Type /StructElem - /S /TD - /P 2559 0 R - /A [<< - /O /Table - /Headers [(U1x1y1)] - >>] - /K [2561 0 R 83] - /Pg 4874 0 R ->> -endobj - -2561 0 obj -<< - /Type /StructElem - /S /Code - /P 2560 0 R - /K [82] - /Pg 4874 0 R ->> -endobj - -2562 0 obj -<< - /Type /StructElem - /S /TD - /P 2559 0 R - /A [<< - /O /Table - /Headers [(U1x0y1)] - >>] - /K [2563 0 R] ->> -endobj - -2563 0 obj -<< - /Type /StructElem - /S /Formula - /P 2562 0 R - /K [81] - /Pg 4874 0 R ->> -endobj - -2564 0 obj -<< - /Type /StructElem - /S /TR - /P 2556 0 R - /K [2567 0 R 2565 0 R] ->> -endobj - -2565 0 obj -<< - /Type /StructElem - /S /TD - /P 2564 0 R - /A [<< - /O /Table - /Headers [(U1x1y1)] - >>] - /K [2566 0 R] ->> -endobj - -2566 0 obj -<< - /Type /StructElem - /S /Code - /P 2565 0 R - /K [80] - /Pg 4874 0 R ->> -endobj - -2567 0 obj -<< - /Type /StructElem - /S /TD - /P 2564 0 R - /A [<< - /O /Table - /Headers [(U1x0y1)] - >>] - /K [2568 0 R] ->> -endobj - -2568 0 obj -<< - /Type /StructElem - /S /Formula - /P 2567 0 R - /K [75 76 77 78 79] - /Pg 4874 0 R ->> -endobj - -2569 0 obj -<< - /Type /StructElem - /S /TR - /P 2556 0 R - /K [2572 0 R 2570 0 R] ->> -endobj - -2570 0 obj -<< - /Type /StructElem - /S /TD - /P 2569 0 R - /A [<< - /O /Table - /Headers [(U1x1y1)] - >>] - /K [2571 0 R] ->> -endobj - -2571 0 obj -<< - /Type /StructElem - /S /Code - /P 2570 0 R - /K [74] - /Pg 4874 0 R ->> -endobj - -2572 0 obj -<< - /Type /StructElem - /S /TD - /P 2569 0 R - /A [<< - /O /Table - /Headers [(U1x0y1)] - >>] - /K [2573 0 R] ->> -endobj - -2573 0 obj -<< - /Type /StructElem - /S /Formula - /P 2572 0 R - /K [70 71 72 73] - /Pg 4874 0 R ->> -endobj - -2574 0 obj -<< - /Type /StructElem - /S /TR - /P 2556 0 R - /K [2577 0 R 2575 0 R] ->> -endobj - -2575 0 obj -<< - /Type /StructElem - /S /TD - /P 2574 0 R - /A [<< - /O /Table - /Headers [(U1x1y1)] - >>] - /K [2576 0 R] ->> -endobj - -2576 0 obj -<< - /Type /StructElem - /S /Code - /P 2575 0 R - /K [69] - /Pg 4874 0 R ->> -endobj - -2577 0 obj -<< - /Type /StructElem - /S /TD - /P 2574 0 R - /A [<< - /O /Table - /Headers [(U1x0y1)] - >>] - /K [2578 0 R] ->> -endobj - -2578 0 obj -<< - /Type /StructElem - /S /Formula - /P 2577 0 R - /K [65 66 67 68] - /Pg 4874 0 R ->> -endobj - -2579 0 obj -<< - /Type /StructElem - /S /TR - /P 2556 0 R - /K [2582 0 R 2580 0 R] ->> -endobj - -2580 0 obj -<< - /Type /StructElem - /S /TD - /P 2579 0 R - /A [<< - /O /Table - /Headers [(U1x1y1)] - >>] - /K [2581 0 R 64] - /Pg 4874 0 R ->> -endobj - -2581 0 obj -<< - /Type /StructElem - /S /Code - /P 2580 0 R - /K [63] - /Pg 4874 0 R ->> -endobj - -2582 0 obj -<< - /Type /StructElem - /S /TD - /P 2579 0 R - /A [<< - /O /Table - /Headers [(U1x0y1)] - >>] - /K [2583 0 R] ->> -endobj - -2583 0 obj -<< - /Type /StructElem - /S /Formula - /P 2582 0 R - /K [61 62] - /Pg 4874 0 R ->> -endobj - -2584 0 obj -<< - /Type /StructElem - /S /TR - /P 2556 0 R - /K [2587 0 R 2585 0 R] ->> -endobj - -2585 0 obj -<< - /Type /StructElem - /S /TD - /P 2584 0 R - /A [<< - /O /Table - /Headers [(U1x1y1)] - >>] - /K [2586 0 R] ->> -endobj - -2586 0 obj -<< - /Type /StructElem - /S /Code - /P 2585 0 R - /K [60] - /Pg 4874 0 R ->> -endobj - -2587 0 obj -<< - /Type /StructElem - /S /TD - /P 2584 0 R - /A [<< - /O /Table - /Headers [(U1x0y1)] - >>] - /K [2588 0 R] ->> -endobj - -2588 0 obj -<< - /Type /StructElem - /S /Formula - /P 2587 0 R - /K [54 55 56 57 58 59] - /Pg 4874 0 R ->> -endobj - -2589 0 obj -<< - /Type /StructElem - /S /TR - /P 2556 0 R - /K [2592 0 R 2590 0 R] ->> -endobj - -2590 0 obj -<< - /Type /StructElem - /S /TD - /P 2589 0 R - /A [<< - /O /Table - /Headers [(U1x1y1)] - >>] - /K [2591 0 R] ->> -endobj - -2591 0 obj -<< - /Type /StructElem - /S /Code - /P 2590 0 R - /K [53] - /Pg 4874 0 R ->> -endobj - -2592 0 obj -<< - /Type /StructElem - /S /TD - /P 2589 0 R - /A [<< - /O /Table - /Headers [(U1x0y1)] - >>] - /K [2593 0 R] ->> -endobj - -2593 0 obj -<< - /Type /StructElem - /S /Formula - /P 2592 0 R - /K [47 48 49 50 51 52] - /Pg 4874 0 R ->> -endobj - -2594 0 obj -<< - /Type /StructElem - /S /TR - /P 2556 0 R - /K [2598 0 R 2595 0 R] ->> -endobj - -2595 0 obj -<< - /Type /StructElem - /S /TD - /P 2594 0 R - /A [<< - /O /Table - /Headers [(U1x1y1)] - >>] - /K [2597 0 R 45 2596 0 R] - /Pg 4874 0 R ->> -endobj - -2596 0 obj -<< - /Type /StructElem - /S /Code - /P 2595 0 R - /K [46] - /Pg 4874 0 R ->> -endobj - -2597 0 obj -<< - /Type /StructElem - /S /Code - /P 2595 0 R - /K [44] - /Pg 4874 0 R ->> -endobj - -2598 0 obj -<< - /Type /StructElem - /S /TD - /P 2594 0 R - /A [<< - /O /Table - /Headers [(U1x0y1)] - >>] - /K [2600 0 R 37 2599 0 R] - /Pg 4874 0 R ->> -endobj - -2599 0 obj -<< - /Type /StructElem - /S /Formula - /P 2598 0 R - /K [38 39 40 41 42 43] - /Pg 4874 0 R ->> -endobj - -2600 0 obj -<< - /Type /StructElem - /S /Formula - /P 2598 0 R - /K [33 34 35 36] - /Pg 4874 0 R ->> -endobj - -2601 0 obj -<< - /Type /StructElem - /S /TR - /P 2556 0 R - /K [2606 0 R 2602 0 R] ->> -endobj - -2602 0 obj -<< - /Type /StructElem - /S /TD - /P 2601 0 R - /A [<< - /O /Table - /Headers [(U1x1y1)] - >>] - /K [2605 0 R 29 2604 0 R 31 2603 0 R] - /Pg 4874 0 R ->> -endobj - -2603 0 obj -<< - /Type /StructElem - /S /Code - /P 2602 0 R - /K [32] - /Pg 4874 0 R ->> -endobj - -2604 0 obj -<< - /Type /StructElem - /S /Code - /P 2602 0 R - /K [30] - /Pg 4874 0 R ->> -endobj - -2605 0 obj -<< - /Type /StructElem - /S /Code - /P 2602 0 R - /K [28] - /Pg 4874 0 R ->> -endobj - -2606 0 obj -<< - /Type /StructElem - /S /TD - /P 2601 0 R - /A [<< - /O /Table - /Headers [(U1x0y1)] - >>] - /K [2609 0 R 22 2608 0 R 25 2607 0 R] - /Pg 4874 0 R ->> -endobj - -2607 0 obj -<< - /Type /StructElem - /S /Formula - /P 2606 0 R - /K [26 27] - /Pg 4874 0 R ->> -endobj - -2608 0 obj -<< - /Type /StructElem - /S /Formula - /P 2606 0 R - /K [23 24] - /Pg 4874 0 R ->> -endobj - -2609 0 obj -<< - /Type /StructElem - /S /Formula - /P 2606 0 R - /K [21] - /Pg 4874 0 R ->> -endobj - -2610 0 obj -<< - /Type /StructElem - /S /TR - /P 2556 0 R - /K [2613 0 R 2611 0 R] ->> -endobj - -2611 0 obj -<< - /Type /StructElem - /S /TD - /P 2610 0 R - /A [<< - /O /Table - /Headers [(U1x1y1)] - >>] - /K [2612 0 R] ->> -endobj - -2612 0 obj -<< - /Type /StructElem - /S /Code - /P 2611 0 R - /K [20] - /Pg 4874 0 R ->> -endobj - -2613 0 obj -<< - /Type /StructElem - /S /TD - /P 2610 0 R - /A [<< - /O /Table - /Headers [(U1x0y1)] - >>] - /K [2614 0 R] ->> -endobj - -2614 0 obj -<< - /Type /StructElem - /S /Formula - /P 2613 0 R - /K [15 16 17 18 19] - /Pg 4874 0 R ->> -endobj - -2615 0 obj -<< - /Type /StructElem - /S /TR - /P 2556 0 R - /K [2617 0 R 2616 0 R] ->> -endobj - -2616 0 obj -<< - /Type /StructElem - /S /TD - /P 2615 0 R - /A [<< - /O /Table - /Headers [(U1x1y1)] - >>] - /K [14] - /Pg 4874 0 R ->> -endobj - -2617 0 obj -<< - /Type /StructElem - /S /TD - /P 2615 0 R - /A [<< - /O /Table - /Headers [(U1x0y1)] - >>] - /K [2619 0 R 10 2618 0 R] - /Pg 4874 0 R ->> -endobj - -2618 0 obj -<< - /Type /StructElem - /S /Formula - /P 2617 0 R - /K [11 12 13] - /Pg 4874 0 R ->> -endobj - -2619 0 obj -<< - /Type /StructElem - /S /Formula - /P 2617 0 R - /K [8 9] - /Pg 4874 0 R ->> -endobj - -2620 0 obj -<< - /Type /StructElem - /S /TR - /P 2556 0 R - /K [2623 0 R 2621 0 R] ->> -endobj - -2621 0 obj -<< - /Type /StructElem - /S /TD - /P 2620 0 R - /A [<< - /O /Table - /Headers [(U1x1y1)] - >>] - /K [2622 0 R 7] - /Pg 4874 0 R ->> -endobj - -2622 0 obj -<< - /Type /StructElem - /S /Code - /P 2621 0 R - /K [6] - /Pg 4874 0 R ->> -endobj - -2623 0 obj -<< - /Type /StructElem - /S /TD - /P 2620 0 R - /A [<< - /O /Table - /Headers [(U1x0y1)] - >>] - /K [2624 0 R] ->> -endobj - -2624 0 obj -<< - /Type /StructElem - /S /Formula - /P 2623 0 R - /K [4 5] - /Pg 4874 0 R ->> -endobj - -2625 0 obj -<< - /Type /StructElem - /S /TR - /P 2556 0 R - /K [2626 0 R] ->> -endobj - -2626 0 obj -<< - /Type /StructElem - /S /TD - /P 2625 0 R - /A [<< - /O /Table - /Headers [(U1x0y1) (U1x1y1)] - /ColSpan 2 - >> << - /O /Layout - /BorderColor [0 0 0] - /BorderStyle [/Solid /None /None /None] - /BorderThickness [0.4 0 0 0] - >>] - /K [] ->> -endobj - -2627 0 obj -<< - /Type /StructElem - /S /TR - /P 2556 0 R - /K [2628 0 R] ->> -endobj - -2628 0 obj -<< - /Type /StructElem - /S /TD - /P 2627 0 R - /A [<< - /O /Table - /Headers [(U1x0y1) (U1x1y1)] - /ColSpan 2 - >> << - /O /Layout - /BorderColor [0 0 0] - /BorderStyle [/None /Solid /None /None] - /BorderThickness [0 0.4 0 0] - >>] - /K [] ->> -endobj - -2629 0 obj -<< - /Type /StructElem - /S /TBody - /P 2555 0 R - /K [2630 0 R] ->> -endobj - -2630 0 obj -<< - /Type /StructElem - /S /TR - /P 2629 0 R - /K [2633 0 R 2631 0 R] ->> -endobj - -2631 0 obj -<< - /Type /StructElem - /S /TH - /P 2630 0 R - /ID (U1x1y1) - /A [<< - /O /Table - /Scope /Column - /Headers [] - >>] - /K [2632 0 R] ->> -endobj - -2632 0 obj -<< - /Type /StructElem - /S /Strong - /P 2631 0 R - /K [3] - /Pg 4874 0 R ->> -endobj - -2633 0 obj -<< - /Type /StructElem - /S /TH - /P 2630 0 R - /ID (U1x0y1) - /A [<< - /O /Table - /Scope /Column - /Headers [] - >>] - /K [2637 0 R 2635 0 R 2634 0 R] ->> -endobj - -2634 0 obj -<< - /Type /StructElem - /S /Strong - /P 2633 0 R - /K [2] - /Pg 4874 0 R ->> -endobj - -2635 0 obj -<< - /Type /StructElem - /S /Link - /P 2633 0 R - /K [2636 0 R << - /Type /OBJR - /Pg 4874 0 R - /Obj 4866 0 R - >>] ->> -endobj - -2636 0 obj -<< - /Type /StructElem - /S /Strong - /P 2635 0 R - /K [1] - /Pg 4874 0 R ->> -endobj - -2637 0 obj -<< - /Type /StructElem - /S /Strong - /P 2633 0 R - /K [0] - /Pg 4874 0 R ->> -endobj - -2638 0 obj -<< - /Type /StructElem - /S /TBody - /P 2555 0 R - /K [2639 0 R] ->> -endobj - -2639 0 obj -<< - /Type /StructElem - /S /TR - /P 2638 0 R - /K [2640 0 R] ->> -endobj - -2640 0 obj -<< - /Type /StructElem - /S /TD - /P 2639 0 R - /A [<< - /O /Table - /Headers [] - /ColSpan 2 - >> << - /O /Layout - /BorderColor [0 0 0] - /BorderStyle [/Solid /None /None /None] - /BorderThickness [0.8 0 0 0] - >>] - /K [] ->> -endobj - -2641 0 obj -<< - /Type /StructElem - /S /Caption - /P 2553 0 R - /K [2642 0 R] ->> -endobj - -2642 0 obj -<< - /Type /StructElem - /S /Span - /P 2641 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [84] - /Pg 4874 0 R ->> -endobj - -2643 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [62 2660 0 R 64 65 2659 0 R 67 68 69 2658 0 R 71 2657 0 R 73 2656 0 R 75 2655 0 R 77 78 2654 0 R 80 2653 0 R 82 83 2652 0 R 85 86 87 2651 0 R 89 2650 0 R 91 2649 0 R 93 94 2648 0 R 100 2647 0 R 102 2646 0 R 104 2645 0 R 106 2644 0 R 108 109] - /Pg 4864 0 R ->> -endobj - -2644 0 obj -<< - /Type /StructElem - /S /Link - /P 2643 0 R - /K [107 << - /Type /OBJR - /Pg 4864 0 R - /Obj 4863 0 R - >>] - /Pg 4864 0 R ->> -endobj - -2645 0 obj -<< - /Type /StructElem - /S /Code - /P 2643 0 R - /K [105] - /Pg 4864 0 R ->> -endobj - -2646 0 obj -<< - /Type /StructElem - /S /Code - /P 2643 0 R - /K [103] - /Pg 4864 0 R ->> -endobj - -2647 0 obj -<< - /Type /StructElem - /S /Formula - /P 2643 0 R - /K [101] - /Pg 4864 0 R ->> -endobj - -2648 0 obj -<< - /Type /StructElem - /S /Formula - /P 2643 0 R - /K [95 96 97 98 99] - /Pg 4864 0 R ->> -endobj - -2649 0 obj -<< - /Type /StructElem - /S /Code - /P 2643 0 R - /K [92] - /Pg 4864 0 R ->> -endobj - -2650 0 obj -<< - /Type /StructElem - /S /Formula - /P 2643 0 R - /K [90] - /Pg 4864 0 R ->> -endobj - -2651 0 obj -<< - /Type /StructElem - /S /Code - /P 2643 0 R - /K [88] - /Pg 4864 0 R ->> -endobj - -2652 0 obj -<< - /Type /StructElem - /S /Link - /P 2643 0 R - /K [84 << - /Type /OBJR - /Pg 4864 0 R - /Obj 4862 0 R - >>] - /Pg 4864 0 R ->> -endobj - -2653 0 obj -<< - /Type /StructElem - /S /Code - /P 2643 0 R - /K [81] - /Pg 4864 0 R ->> -endobj - -2654 0 obj -<< - /Type /StructElem - /S /Code - /P 2643 0 R - /K [79] - /Pg 4864 0 R ->> -endobj - -2655 0 obj -<< - /Type /StructElem - /S /Formula - /P 2643 0 R - /K [76] - /Pg 4864 0 R ->> -endobj - -2656 0 obj -<< - /Type /StructElem - /S /Code - /P 2643 0 R - /K [74] - /Pg 4864 0 R ->> -endobj - -2657 0 obj -<< - /Type /StructElem - /S /Formula - /P 2643 0 R - /K [72] - /Pg 4864 0 R ->> -endobj - -2658 0 obj -<< - /Type /StructElem - /S /Code - /P 2643 0 R - /K [70] - /Pg 4864 0 R ->> -endobj - -2659 0 obj -<< - /Type /StructElem - /S /Link - /P 2643 0 R - /K [66 << - /Type /OBJR - /Pg 4864 0 R - /Obj 4861 0 R - >>] - /Pg 4864 0 R ->> -endobj - -2660 0 obj -<< - /Type /StructElem - /S /Em - /P 2643 0 R - /K [63] - /Pg 4864 0 R ->> -endobj - -2661 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [2664 0 R 53 54 55 2663 0 R 57 58 2662 0 R 60 61] - /Pg 4864 0 R ->> -endobj - -2662 0 obj -<< - /Type /StructElem - /S /Code - /P 2661 0 R - /K [59] - /Pg 4864 0 R ->> -endobj - -2663 0 obj -<< - /Type /StructElem - /S /Code - /P 2661 0 R - /K [56] - /Pg 4864 0 R ->> -endobj - -2664 0 obj -<< - /Type /StructElem - /S /Link - /P 2661 0 R - /K [52 << - /Type /OBJR - /Pg 4864 0 R - /Obj 4860 0 R - >>] - /Pg 4864 0 R ->> -endobj - -2665 0 obj -<< - /Type /StructElem - /S /H2 - /P 103 0 R - /T (Core Library) - /K [50 51] - /Pg 4864 0 R ->> -endobj - -2666 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [22 2675 0 R 24 2674 0 R 26 27 2673 0 R 29 30 31 32 33 2672 0 R 35 2671 0 R 37 38 2670 0 R 40 2669 0 R 42 43 44 2668 0 R 46 2667 0 R 48 49] - /Pg 4864 0 R ->> -endobj - -2667 0 obj -<< - /Type /StructElem - /S /Link - /P 2666 0 R - /K [47 << - /Type /OBJR - /Pg 4864 0 R - /Obj 4859 0 R - >>] - /Pg 4864 0 R ->> -endobj - -2668 0 obj -<< - /Type /StructElem - /S /Em - /P 2666 0 R - /K [45] - /Pg 4864 0 R ->> -endobj - -2669 0 obj -<< - /Type /StructElem - /S /Link - /P 2666 0 R - /K [41 << - /Type /OBJR - /Pg 4864 0 R - /Obj 4858 0 R - >>] - /Pg 4864 0 R ->> -endobj - -2670 0 obj -<< - /Type /StructElem - /S /Em - /P 2666 0 R - /K [39] - /Pg 4864 0 R ->> -endobj - -2671 0 obj -<< - /Type /StructElem - /S /Link - /P 2666 0 R - /K [36 << - /Type /OBJR - /Pg 4864 0 R - /Obj 4857 0 R - >>] - /Pg 4864 0 R ->> -endobj - -2672 0 obj -<< - /Type /StructElem - /S /Em - /P 2666 0 R - /K [34] - /Pg 4864 0 R ->> -endobj - -2673 0 obj -<< - /Type /StructElem - /S /Em - /P 2666 0 R - /K [28] - /Pg 4864 0 R ->> -endobj - -2674 0 obj -<< - /Type /StructElem - /S /Link - /P 2666 0 R - /K [25 << - /Type /OBJR - /Pg 4864 0 R - /Obj 4856 0 R - >>] - /Pg 4864 0 R ->> -endobj - -2675 0 obj -<< - /Type /StructElem - /S /Em - /P 2666 0 R - /K [23] - /Pg 4864 0 R ->> -endobj - -2676 0 obj -<< - /Type /StructElem - /S /H1 - /P 103 0 R - /T (Implementation and Case Study) - /K [20 21] - /Pg 4864 0 R ->> -endobj - -2677 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [6 7 8 9 10 2679 0 R 12 13 14 2678 0 R 16 17 18 19] - /Pg 4864 0 R ->> -endobj - -2678 0 obj -<< - /Type /StructElem - /S /Link - /P 2677 0 R - /K [15 << - /Type /OBJR - /Pg 4864 0 R - /Obj 4855 0 R - >>] - /Pg 4864 0 R ->> -endobj - -2679 0 obj -<< - /Type /StructElem - /S /Link - /P 2677 0 R - /K [11 << - /Type /OBJR - /Pg 4864 0 R - /Obj 4854 0 R - >>] - /Pg 4864 0 R ->> -endobj - -2680 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [2 3 4 5] - /Pg 4864 0 R ->> -endobj - -2681 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [2685 0 R 89 90 91 92 2684 0 R 94 95 96 97 98 2683 0 R 100 101 102 2682 0 R 104 << - /Type /MCR - /MCID 0 - /Pg 4864 0 R - >> << - /Type /MCR - /MCID 1 - /Pg 4864 0 R - >>] - /Pg 4852 0 R ->> -endobj - -2682 0 obj -<< - /Type /StructElem - /S /Code - /P 2681 0 R - /K [103] - /Pg 4852 0 R ->> -endobj - -2683 0 obj -<< - /Type /StructElem - /S /Code - /P 2681 0 R - /K [99] - /Pg 4852 0 R ->> -endobj - -2684 0 obj -<< - /Type /StructElem - /S /Code - /P 2681 0 R - /K [93] - /Pg 4852 0 R ->> -endobj - -2685 0 obj -<< - /Type /StructElem - /S /Strong - /P 2681 0 R - /K [88] - /Pg 4852 0 R ->> -endobj - -2686 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [2690 0 R 66 67 68 2689 0 R 70 2688 0 R 78 79 2687 0 R 81 82 83 84 85 86 87] - /Pg 4852 0 R ->> -endobj - -2687 0 obj -<< - /Type /StructElem - /S /Link - /P 2686 0 R - /K [80 << - /Type /OBJR - /Pg 4852 0 R - /Obj 4851 0 R - >>] - /Pg 4852 0 R ->> -endobj - -2688 0 obj -<< - /Type /StructElem - /S /Formula - /P 2686 0 R - /K [71 72 73 74 75 76 77] - /Pg 4852 0 R ->> -endobj - -2689 0 obj -<< - /Type /StructElem - /S /Code - /P 2686 0 R - /K [69] - /Pg 4852 0 R ->> -endobj - -2690 0 obj -<< - /Type /StructElem - /S /Strong - /P 2686 0 R - /K [65] - /Pg 4852 0 R ->> -endobj - -2691 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [63 64] - /Pg 4852 0 R ->> -endobj - -2692 0 obj -<< - /Type /StructElem - /S /H3 - /P 103 0 R - /T (Situating the Context Paradigm) - /K [61 62] - /Pg 4852 0 R ->> -endobj - -2693 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [57 58 2694 0 R 60] - /Pg 4852 0 R ->> -endobj - -2694 0 obj -<< - /Type /StructElem - /S /Link - /P 2693 0 R - /K [59 << - /Type /OBJR - /Pg 4852 0 R - /Obj 4850 0 R - >>] - /Pg 4852 0 R ->> -endobj - -2695 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [2706 0 R 2696 0 R] ->> -endobj - -2696 0 obj -<< - /Type /StructElem - /S /L - /P 2695 0 R - /A [<< - /O /List - /ListNumbering /Circle - >>] - /K [2702 0 R 2697 0 R] ->> -endobj - -2697 0 obj -<< - /Type /StructElem - /S /LI - /P 2696 0 R - /K [2701 0 R 2698 0 R] ->> -endobj - -2698 0 obj -<< - /Type /StructElem - /S /LBody - /P 2697 0 R - /K [2700 0 R 52 53 2699 0 R 56] - /Pg 4852 0 R ->> -endobj - -2699 0 obj -<< - /Type /StructElem - /S /Formula - /P 2698 0 R - /K [54 55] - /Pg 4852 0 R ->> -endobj - -2700 0 obj -<< - /Type /StructElem - /S /Em - /P 2698 0 R - /K [51] - /Pg 4852 0 R ->> -endobj - -2701 0 obj -<< - /Type /StructElem - /S /Lbl - /P 2697 0 R - /K [50] - /Pg 4852 0 R ->> -endobj - -2702 0 obj -<< - /Type /StructElem - /S /LI - /P 2696 0 R - /K [2705 0 R 2703 0 R] ->> -endobj - -2703 0 obj -<< - /Type /StructElem - /S /LBody - /P 2702 0 R - /K [2704 0 R 48 49] - /Pg 4852 0 R ->> -endobj - -2704 0 obj -<< - /Type /StructElem - /S /Em - /P 2703 0 R - /K [47] - /Pg 4852 0 R ->> -endobj - -2705 0 obj -<< - /Type /StructElem - /S /Lbl - /P 2702 0 R - /K [46] - /Pg 4852 0 R ->> -endobj - -2706 0 obj -<< - /Type /StructElem - /S /P - /P 2695 0 R - /K [2709 0 R 37 2708 0 R 43 2707 0 R 45] - /Pg 4852 0 R ->> -endobj - -2707 0 obj -<< - /Type /StructElem - /S /Em - /P 2706 0 R - /K [44] - /Pg 4852 0 R ->> -endobj - -2708 0 obj -<< - /Type /StructElem - /S /Formula - /P 2706 0 R - /K [38 39 40 41 42] - /Pg 4852 0 R ->> -endobj - -2709 0 obj -<< - /Type /StructElem - /S /Strong - /P 2706 0 R - /K [34 35 36] - /Pg 4852 0 R ->> -endobj - -2710 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [2714 0 R 24 2713 0 R 27 2712 0 R 29 30 2711 0 R 32 33] - /Pg 4852 0 R ->> -endobj - -2711 0 obj -<< - /Type /StructElem - /S /Em - /P 2710 0 R - /K [31] - /Pg 4852 0 R ->> -endobj - -2712 0 obj -<< - /Type /StructElem - /S /Em - /P 2710 0 R - /K [28] - /Pg 4852 0 R ->> -endobj - -2713 0 obj -<< - /Type /StructElem - /S /Formula - /P 2710 0 R - /K [25 26] - /Pg 4852 0 R ->> -endobj - -2714 0 obj -<< - /Type /StructElem - /S /Strong - /P 2710 0 R - /K [23] - /Pg 4852 0 R ->> -endobj - -2715 0 obj -<< - /Type /StructElem - /S /L - /P 103 0 R - /A [<< - /O /List - /ListNumbering /Circle - >>] - /K [2722 0 R 2719 0 R 2716 0 R] ->> -endobj - -2716 0 obj -<< - /Type /StructElem - /S /LI - /P 2715 0 R - /K [2718 0 R 2717 0 R] ->> -endobj - -2717 0 obj -<< - /Type /StructElem - /S /LBody - /P 2716 0 R - /K [19 20 21 22] - /Pg 4852 0 R ->> -endobj - -2718 0 obj -<< - /Type /StructElem - /S /Lbl - /P 2716 0 R - /K [18] - /Pg 4852 0 R ->> -endobj - -2719 0 obj -<< - /Type /StructElem - /S /LI - /P 2715 0 R - /K [2721 0 R 2720 0 R] ->> -endobj - -2720 0 obj -<< - /Type /StructElem - /S /LBody - /P 2719 0 R - /K [16 17] - /Pg 4852 0 R ->> -endobj - -2721 0 obj -<< - /Type /StructElem - /S /Lbl - /P 2719 0 R - /K [15] - /Pg 4852 0 R ->> -endobj - -2722 0 obj -<< - /Type /StructElem - /S /LI - /P 2715 0 R - /K [2724 0 R 2723 0 R] ->> -endobj - -2723 0 obj -<< - /Type /StructElem - /S /LBody - /P 2722 0 R - /K [14] - /Pg 4852 0 R ->> -endobj - -2724 0 obj -<< - /Type /StructElem - /S /Lbl - /P 2722 0 R - /K [13] - /Pg 4852 0 R ->> -endobj - -2725 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [2728 0 R 3 2727 0 R 6 7 8 2726 0 R 10 11 12] - /Pg 4852 0 R ->> -endobj - -2726 0 obj -<< - /Type /StructElem - /S /Formula - /P 2725 0 R - /K [9] - /Pg 4852 0 R ->> -endobj - -2727 0 obj -<< - /Type /StructElem - /S /Formula - /P 2725 0 R - /K [4 5] - /Pg 4852 0 R ->> -endobj - -2728 0 obj -<< - /Type /StructElem - /S /Strong - /P 2725 0 R - /K [2] - /Pg 4852 0 R ->> -endobj - -2729 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [107 2739 0 R 109 2738 0 R 112 2737 0 R 114 115 2736 0 R 117 118 119 2735 0 R 121 2734 0 R 123 2733 0 R 125 126 2732 0 R 128 2731 0 R 130 131 132 2730 0 R 134 << - /Type /MCR - /MCID 0 - /Pg 4852 0 R - >> << - /Type /MCR - /MCID 1 - /Pg 4852 0 R - >>] - /Pg 4848 0 R ->> -endobj - -2730 0 obj -<< - /Type /StructElem - /S /Formula - /P 2729 0 R - /K [133] - /Pg 4848 0 R ->> -endobj - -2731 0 obj -<< - /Type /StructElem - /S /Formula - /P 2729 0 R - /K [129] - /Pg 4848 0 R ->> -endobj - -2732 0 obj -<< - /Type /StructElem - /S /Formula - /P 2729 0 R - /K [127] - /Pg 4848 0 R ->> -endobj - -2733 0 obj -<< - /Type /StructElem - /S /Formula - /P 2729 0 R - /K [124] - /Pg 4848 0 R ->> -endobj - -2734 0 obj -<< - /Type /StructElem - /S /Formula - /P 2729 0 R - /K [122] - /Pg 4848 0 R ->> -endobj - -2735 0 obj -<< - /Type /StructElem - /S /Formula - /P 2729 0 R - /K [120] - /Pg 4848 0 R ->> -endobj - -2736 0 obj -<< - /Type /StructElem - /S /Formula - /P 2729 0 R - /K [116] - /Pg 4848 0 R ->> -endobj - -2737 0 obj -<< - /Type /StructElem - /S /Formula - /P 2729 0 R - /K [113] - /Pg 4848 0 R ->> -endobj - -2738 0 obj -<< - /Type /StructElem - /S /Formula - /P 2729 0 R - /K [110 111] - /Pg 4848 0 R ->> -endobj - -2739 0 obj -<< - /Type /StructElem - /S /Formula - /P 2729 0 R - /K [108] - /Pg 4848 0 R ->> -endobj - -2740 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [2756 0 R 2755 0 R 2754 0 R 2741 0 R] ->> -endobj - -2741 0 obj -<< - /Type /StructElem - /S /L - /P 2740 0 R - /A [<< - /O /List - /ListNumbering /Circle - >>] - /K [2750 0 R 2746 0 R 2742 0 R] ->> -endobj - -2742 0 obj -<< - /Type /StructElem - /S /LI - /P 2741 0 R - /K [2745 0 R 2743 0 R] ->> -endobj - -2743 0 obj -<< - /Type /StructElem - /S /LBody - /P 2742 0 R - /K [2744 0 R 106] - /Pg 4848 0 R ->> -endobj - -2744 0 obj -<< - /Type /StructElem - /S /Formula - /P 2743 0 R - /K [105] - /Pg 4848 0 R ->> -endobj - -2745 0 obj -<< - /Type /StructElem - /S /Lbl - /P 2742 0 R - /K [104] - /Pg 4848 0 R ->> -endobj - -2746 0 obj -<< - /Type /StructElem - /S /LI - /P 2741 0 R - /K [2749 0 R 2747 0 R] ->> -endobj - -2747 0 obj -<< - /Type /StructElem - /S /LBody - /P 2746 0 R - /K [2748 0 R 103] - /Pg 4848 0 R ->> -endobj - -2748 0 obj -<< - /Type /StructElem - /S /Formula - /P 2747 0 R - /K [100 101 102] - /Pg 4848 0 R ->> -endobj - -2749 0 obj -<< - /Type /StructElem - /S /Lbl - /P 2746 0 R - /K [99] - /Pg 4848 0 R ->> -endobj - -2750 0 obj -<< - /Type /StructElem - /S /LI - /P 2741 0 R - /K [2753 0 R 2751 0 R] ->> -endobj - -2751 0 obj -<< - /Type /StructElem - /S /LBody - /P 2750 0 R - /K [2752 0 R 98] - /Pg 4848 0 R ->> -endobj - -2752 0 obj -<< - /Type /StructElem - /S /Formula - /P 2751 0 R - /K [97] - /Pg 4848 0 R ->> -endobj - -2753 0 obj -<< - /Type /StructElem - /S /Lbl - /P 2750 0 R - /K [96] - /Pg 4848 0 R ->> -endobj - -2754 0 obj -<< - /Type /StructElem - /S /P - /P 2740 0 R - /K [95] - /Pg 4848 0 R ->> -endobj - -2755 0 obj -<< - /Type /StructElem - /S /Formula - /P 2740 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94] - /Pg 4848 0 R ->> -endobj - -2756 0 obj -<< - /Type /StructElem - /S /P - /P 2740 0 R - /K [2758 0 R 75 2757 0 R 78] - /Pg 4848 0 R ->> -endobj - -2757 0 obj -<< - /Type /StructElem - /S /Formula - /P 2756 0 R - /K [76 77] - /Pg 4848 0 R ->> -endobj - -2758 0 obj -<< - /Type /StructElem - /S /Strong - /P 2756 0 R - /K [72 73 74] - /Pg 4848 0 R ->> -endobj - -2759 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [60 2763 0 R 62 2762 0 R 65 2761 0 R 67 68 69 2760 0 R 71] - /Pg 4848 0 R ->> -endobj - -2760 0 obj -<< - /Type /StructElem - /S /Formula - /P 2759 0 R - /K [70] - /Pg 4848 0 R ->> -endobj - -2761 0 obj -<< - /Type /StructElem - /S /Link - /P 2759 0 R - /K [66 << - /Type /OBJR - /Pg 4848 0 R - /Obj 4847 0 R - >>] - /Pg 4848 0 R ->> -endobj - -2762 0 obj -<< - /Type /StructElem - /S /Formula - /P 2759 0 R - /K [63 64] - /Pg 4848 0 R ->> -endobj - -2763 0 obj -<< - /Type /StructElem - /S /Formula - /P 2759 0 R - /K [61] - /Pg 4848 0 R ->> -endobj - -2764 0 obj -<< - /Type /StructElem - /S /H3 - /P 103 0 R - /T (Unified Context) - /K [58 59] - /Pg 4848 0 R ->> -endobj - -2765 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [50 2767 0 R 52 2766 0 R 54 55 56 57] - /Pg 4848 0 R ->> -endobj - -2766 0 obj -<< - /Type /StructElem - /S /Formula - /P 2765 0 R - /K [53] - /Pg 4848 0 R ->> -endobj - -2767 0 obj -<< - /Type /StructElem - /S /Link - /P 2765 0 R - /K [51 << - /Type /OBJR - /Pg 4848 0 R - /Obj 4846 0 R - >>] - /Pg 4848 0 R ->> -endobj - -2768 0 obj -<< - /Type /StructElem - /S /H2 - /P 103 0 R - /T (The Context Paradigm) - /K [48 49] - /Pg 4848 0 R ->> -endobj - -2769 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [44 45 46 47] - /Pg 4848 0 R ->> -endobj - -2770 0 obj -<< - /Type /StructElem - /S /L - /P 103 0 R - /A [<< - /O /List - /ListNumbering /Circle - >>] - /K [2783 0 R 2774 0 R 2771 0 R] ->> -endobj - -2771 0 obj -<< - /Type /StructElem - /S /LI - /P 2770 0 R - /K [2773 0 R 2772 0 R] ->> -endobj - -2772 0 obj -<< - /Type /StructElem - /S /LBody - /P 2771 0 R - /K [42 43] - /Pg 4848 0 R ->> -endobj - -2773 0 obj -<< - /Type /StructElem - /S /Lbl - /P 2771 0 R - /K [41] - /Pg 4848 0 R ->> -endobj - -2774 0 obj -<< - /Type /StructElem - /S /LI - /P 2770 0 R - /K [2782 0 R 2775 0 R] ->> -endobj - -2775 0 obj -<< - /Type /StructElem - /S /LBody - /P 2774 0 R - /K [25 2781 0 R 27 2780 0 R 29 2779 0 R 31 32 33 2778 0 R 35 2777 0 R 37 38 2776 0 R 40] - /Pg 4848 0 R ->> -endobj - -2776 0 obj -<< - /Type /StructElem - /S /Code - /P 2775 0 R - /K [39] - /Pg 4848 0 R ->> -endobj - -2777 0 obj -<< - /Type /StructElem - /S /Code - /P 2775 0 R - /K [36] - /Pg 4848 0 R ->> -endobj - -2778 0 obj -<< - /Type /StructElem - /S /Code - /P 2775 0 R - /K [34] - /Pg 4848 0 R ->> -endobj - -2779 0 obj -<< - /Type /StructElem - /S /Code - /P 2775 0 R - /K [30] - /Pg 4848 0 R ->> -endobj - -2780 0 obj -<< - /Type /StructElem - /S /Code - /P 2775 0 R - /K [28] - /Pg 4848 0 R ->> -endobj - -2781 0 obj -<< - /Type /StructElem - /S /Code - /P 2775 0 R - /K [26] - /Pg 4848 0 R ->> -endobj - -2782 0 obj -<< - /Type /StructElem - /S /Lbl - /P 2774 0 R - /K [24] - /Pg 4848 0 R ->> -endobj - -2783 0 obj -<< - /Type /StructElem - /S /LI - /P 2770 0 R - /K [2792 0 R 2784 0 R] ->> -endobj - -2784 0 obj -<< - /Type /StructElem - /S /LBody - /P 2783 0 R - /K [7 2791 0 R 9 2790 0 R 11 2789 0 R 13 14 2788 0 R 16 2787 0 R 18 2786 0 R 20 21 2785 0 R 23] - /Pg 4848 0 R ->> -endobj - -2785 0 obj -<< - /Type /StructElem - /S /Code - /P 2784 0 R - /K [22] - /Pg 4848 0 R ->> -endobj - -2786 0 obj -<< - /Type /StructElem - /S /Code - /P 2784 0 R - /K [19] - /Pg 4848 0 R ->> -endobj - -2787 0 obj -<< - /Type /StructElem - /S /Code - /P 2784 0 R - /K [17] - /Pg 4848 0 R ->> -endobj - -2788 0 obj -<< - /Type /StructElem - /S /Code - /P 2784 0 R - /K [15] - /Pg 4848 0 R ->> -endobj - -2789 0 obj -<< - /Type /StructElem - /S /Code - /P 2784 0 R - /K [12] - /Pg 4848 0 R ->> -endobj - -2790 0 obj -<< - /Type /StructElem - /S /Code - /P 2784 0 R - /K [10] - /Pg 4848 0 R ->> -endobj - -2791 0 obj -<< - /Type /StructElem - /S /Code - /P 2784 0 R - /K [8] - /Pg 4848 0 R ->> -endobj - -2792 0 obj -<< - /Type /StructElem - /S /Lbl - /P 2783 0 R - /K [6] - /Pg 4848 0 R ->> -endobj - -2793 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [5] - /Pg 4848 0 R ->> -endobj - -2794 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /K [2801 0 R 2795 0 R] ->> -endobj - -2795 0 obj -<< - /Type /StructElem - /S /Div - /P 2794 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [2796 0 R] ->> -endobj - -2796 0 obj -<< - /Type /StructElem - /S /P - /P 2795 0 R - /K [2800 0 R 2799 0 R 2798 0 R 2797 0 R] ->> -endobj - -2797 0 obj -<< - /Type /StructElem - /S /Code - /P 2796 0 R - /K [3] - /Pg 4848 0 R ->> -endobj - -2798 0 obj -<< - /Type /StructElem - /S /Code - /P 2796 0 R - /K [2] - /Pg 4848 0 R ->> -endobj - -2799 0 obj -<< - /Type /StructElem - /S /Code - /P 2796 0 R - /K [1] - /Pg 4848 0 R ->> -endobj - -2800 0 obj -<< - /Type /StructElem - /S /Code - /P 2796 0 R - /K [0] - /Pg 4848 0 R ->> -endobj - -2801 0 obj -<< - /Type /StructElem - /S /Caption - /P 2794 0 R - /K [2802 0 R] ->> -endobj - -2802 0 obj -<< - /Type /StructElem - /S /Span - /P 2801 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4] - /Pg 4848 0 R ->> -endobj - -2803 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [172 2810 0 R 174 2809 0 R 176 177 2808 0 R 179 180 181 2807 0 R 183 2806 0 R 185 186 187 2805 0 R 189 190 2804 0 R 192] - /Pg 4844 0 R ->> -endobj - -2804 0 obj -<< - /Type /StructElem - /S /Link - /P 2803 0 R - /K [191 << - /Type /OBJR - /Pg 4844 0 R - /Obj 4843 0 R - >>] - /Pg 4844 0 R ->> -endobj - -2805 0 obj -<< - /Type /StructElem - /S /Em - /P 2803 0 R - /K [188] - /Pg 4844 0 R ->> -endobj - -2806 0 obj -<< - /Type /StructElem - /S /Code - /P 2803 0 R - /K [184] - /Pg 4844 0 R ->> -endobj - -2807 0 obj -<< - /Type /StructElem - /S /Code - /P 2803 0 R - /K [182] - /Pg 4844 0 R ->> -endobj - -2808 0 obj -<< - /Type /StructElem - /S /Code - /P 2803 0 R - /K [178] - /Pg 4844 0 R ->> -endobj - -2809 0 obj -<< - /Type /StructElem - /S /Code - /P 2803 0 R - /K [175] - /Pg 4844 0 R ->> -endobj - -2810 0 obj -<< - /Type /StructElem - /S /Code - /P 2803 0 R - /K [173] - /Pg 4844 0 R ->> -endobj - -2811 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [159 160 161 2813 0 R 166 167 2812 0 R 169 170 171] - /Pg 4844 0 R ->> -endobj - -2812 0 obj -<< - /Type /StructElem - /S /Formula - /P 2811 0 R - /K [168] - /Pg 4844 0 R ->> -endobj - -2813 0 obj -<< - /Type /StructElem - /S /Formula - /P 2811 0 R - /K [162 163 164 165] - /Pg 4844 0 R ->> -endobj - -2814 0 obj -<< - /Type /StructElem - /S /H3 - /P 103 0 R - /T (Asynchrony) - /K [157 158] - /Pg 4844 0 R ->> -endobj - -2815 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /K [2832 0 R 2816 0 R] ->> -endobj - -2816 0 obj -<< - /Type /StructElem - /S /Div - /P 2815 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [2817 0 R] ->> -endobj - -2817 0 obj -<< - /Type /StructElem - /S /P - /P 2816 0 R - /K [2831 0 R 2830 0 R 2829 0 R 2828 0 R 2827 0 R 2826 0 R 2825 0 R 2824 0 R 2823 0 R 2822 0 R 2821 0 R 2820 0 R 2819 0 R 2818 0 R] ->> -endobj - -2818 0 obj -<< - /Type /StructElem - /S /Formula - /P 2817 0 R - /K [147 148 149 150 151 152 153 154 155] - /Pg 4844 0 R ->> -endobj - -2819 0 obj -<< - /Type /StructElem - /S /Code - /P 2817 0 R - /K [146] - /Pg 4844 0 R ->> -endobj - -2820 0 obj -<< - /Type /StructElem - /S /Formula - /P 2817 0 R - /K [137 138 139 140 141 142 143 144 145] - /Pg 4844 0 R ->> -endobj - -2821 0 obj -<< - /Type /StructElem - /S /Code - /P 2817 0 R - /K [136] - /Pg 4844 0 R ->> -endobj - -2822 0 obj -<< - /Type /StructElem - /S /Formula - /P 2817 0 R - /K [127 128 129 130 131 132 133 134 135] - /Pg 4844 0 R ->> -endobj - -2823 0 obj -<< - /Type /StructElem - /S /Code - /P 2817 0 R - /K [126] - /Pg 4844 0 R ->> -endobj - -2824 0 obj -<< - /Type /StructElem - /S /Formula - /P 2817 0 R - /K [117 118 119 120 121 122 123 124 125] - /Pg 4844 0 R ->> -endobj - -2825 0 obj -<< - /Type /StructElem - /S /Code - /P 2817 0 R - /K [116] - /Pg 4844 0 R ->> -endobj - -2826 0 obj -<< - /Type /StructElem - /S /Formula - /P 2817 0 R - /K [107 108 109 110 111 112 113 114 115] - /Pg 4844 0 R ->> -endobj - -2827 0 obj -<< - /Type /StructElem - /S /Code - /P 2817 0 R - /K [106] - /Pg 4844 0 R ->> -endobj - -2828 0 obj -<< - /Type /StructElem - /S /Formula - /P 2817 0 R - /K [97 98 99 100 101 102 103 104 105] - /Pg 4844 0 R ->> -endobj - -2829 0 obj -<< - /Type /StructElem - /S /Code - /P 2817 0 R - /K [96] - /Pg 4844 0 R ->> -endobj - -2830 0 obj -<< - /Type /StructElem - /S /Formula - /P 2817 0 R - /K [95] - /Pg 4844 0 R ->> -endobj - -2831 0 obj -<< - /Type /StructElem - /S /Code - /P 2817 0 R - /K [94] - /Pg 4844 0 R ->> -endobj - -2832 0 obj -<< - /Type /StructElem - /S /Caption - /P 2815 0 R - /K [2833 0 R] ->> -endobj - -2833 0 obj -<< - /Type /StructElem - /S /Span - /P 2832 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [156] - /Pg 4844 0 R ->> -endobj - -2834 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [81 2839 0 R 83 2838 0 R 85 86 87 2837 0 R 89 2836 0 R 91 2835 0 R 93] - /Pg 4844 0 R ->> -endobj - -2835 0 obj -<< - /Type /StructElem - /S /Link - /P 2834 0 R - /K [92 << - /Type /OBJR - /Pg 4844 0 R - /Obj 4842 0 R - >>] - /Pg 4844 0 R ->> -endobj - -2836 0 obj -<< - /Type /StructElem - /S /Code - /P 2834 0 R - /K [90] - /Pg 4844 0 R ->> -endobj - -2837 0 obj -<< - /Type /StructElem - /S /Code - /P 2834 0 R - /K [88] - /Pg 4844 0 R ->> -endobj - -2838 0 obj -<< - /Type /StructElem - /S /Code - /P 2834 0 R - /K [84] - /Pg 4844 0 R ->> -endobj - -2839 0 obj -<< - /Type /StructElem - /S /Code - /P 2834 0 R - /K [82] - /Pg 4844 0 R ->> -endobj - -2840 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [65 2844 0 R 68 2843 0 R 71 72 2842 0 R 75 2841 0 R 78 79 80] - /Pg 4844 0 R ->> -endobj - -2841 0 obj -<< - /Type /StructElem - /S /Formula - /P 2840 0 R - /K [76 77] - /Pg 4844 0 R ->> -endobj - -2842 0 obj -<< - /Type /StructElem - /S /Formula - /P 2840 0 R - /K [73 74] - /Pg 4844 0 R ->> -endobj - -2843 0 obj -<< - /Type /StructElem - /S /Formula - /P 2840 0 R - /K [69 70] - /Pg 4844 0 R ->> -endobj - -2844 0 obj -<< - /Type /StructElem - /S /Formula - /P 2840 0 R - /K [66 67] - /Pg 4844 0 R ->> -endobj - -2845 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [30 2848 0 R 59 2847 0 R 61 2846 0 R 64] - /Pg 4844 0 R ->> -endobj - -2846 0 obj -<< - /Type /StructElem - /S /Formula - /P 2845 0 R - /K [62 63] - /Pg 4844 0 R ->> -endobj - -2847 0 obj -<< - /Type /StructElem - /S /Code - /P 2845 0 R - /K [60] - /Pg 4844 0 R ->> -endobj - -2848 0 obj -<< - /Type /StructElem - /S /Formula - /P 2845 0 R - /K [31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58] - /Pg 4844 0 R ->> -endobj - -2849 0 obj -<< - /Type /StructElem - /S /Formula - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29] - /Pg 4844 0 R ->> -endobj - -2850 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [0 2853 0 R 2 3 2852 0 R 10 2851 0 R 12] - /Pg 4844 0 R ->> -endobj - -2851 0 obj -<< - /Type /StructElem - /S /Formula - /P 2850 0 R - /K [11] - /Pg 4844 0 R ->> -endobj - -2852 0 obj -<< - /Type /StructElem - /S /Formula - /P 2850 0 R - /K [4 5 6 7 8 9] - /Pg 4844 0 R ->> -endobj - -2853 0 obj -<< - /Type /StructElem - /S /Em - /P 2850 0 R - /K [1] - /Pg 4844 0 R ->> -endobj - -2854 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [226 2866 0 R 228 2865 0 R 230 2864 0 R 232 2863 0 R 234 2862 0 R 236 2861 0 R 238 2860 0 R 240 241 2859 0 R 243 2858 0 R 245 2857 0 R 247 2856 0 R 249 2855 0 R 251] - /Pg 4840 0 R ->> -endobj - -2855 0 obj -<< - /Type /StructElem - /S /Code - /P 2854 0 R - /K [250] - /Pg 4840 0 R ->> -endobj - -2856 0 obj -<< - /Type /StructElem - /S /Code - /P 2854 0 R - /K [248] - /Pg 4840 0 R ->> -endobj - -2857 0 obj -<< - /Type /StructElem - /S /Formula - /P 2854 0 R - /K [246] - /Pg 4840 0 R ->> -endobj - -2858 0 obj -<< - /Type /StructElem - /S /Code - /P 2854 0 R - /K [244] - /Pg 4840 0 R ->> -endobj - -2859 0 obj -<< - /Type /StructElem - /S /Code - /P 2854 0 R - /K [242] - /Pg 4840 0 R ->> -endobj - -2860 0 obj -<< - /Type /StructElem - /S /Code - /P 2854 0 R - /K [239] - /Pg 4840 0 R ->> -endobj - -2861 0 obj -<< - /Type /StructElem - /S /Code - /P 2854 0 R - /K [237] - /Pg 4840 0 R ->> -endobj - -2862 0 obj -<< - /Type /StructElem - /S /Code - /P 2854 0 R - /K [235] - /Pg 4840 0 R ->> -endobj - -2863 0 obj -<< - /Type /StructElem - /S /Formula - /P 2854 0 R - /K [233] - /Pg 4840 0 R ->> -endobj - -2864 0 obj -<< - /Type /StructElem - /S /Code - /P 2854 0 R - /K [231] - /Pg 4840 0 R ->> -endobj - -2865 0 obj -<< - /Type /StructElem - /S /Formula - /P 2854 0 R - /K [229] - /Pg 4840 0 R ->> -endobj - -2866 0 obj -<< - /Type /StructElem - /S /Code - /P 2854 0 R - /K [227] - /Pg 4840 0 R ->> -endobj - -2867 0 obj -<< - /Type /StructElem - /S /H3 - /P 103 0 R - /T (Coherence) - /K [224 225] - /Pg 4840 0 R ->> -endobj - -2868 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [178 2876 0 R 182 183 2875 0 R 185 2874 0 R 203 204 2873 0 R 212 2872 0 R 214 2871 0 R 216 2870 0 R 218 2869 0 R 220 221 222 223] - /Pg 4840 0 R ->> -endobj - -2869 0 obj -<< - /Type /StructElem - /S /Code - /P 2868 0 R - /K [219] - /Pg 4840 0 R ->> -endobj - -2870 0 obj -<< - /Type /StructElem - /S /Code - /P 2868 0 R - /K [217] - /Pg 4840 0 R ->> -endobj - -2871 0 obj -<< - /Type /StructElem - /S /Formula - /P 2868 0 R - /K [215] - /Pg 4840 0 R ->> -endobj - -2872 0 obj -<< - /Type /StructElem - /S /Formula - /P 2868 0 R - /K [213] - /Pg 4840 0 R ->> -endobj - -2873 0 obj -<< - /Type /StructElem - /S /Formula - /P 2868 0 R - /K [205 206 207 208 209 210 211] - /Pg 4840 0 R ->> -endobj - -2874 0 obj -<< - /Type /StructElem - /S /Formula - /P 2868 0 R - /K [186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202] - /Pg 4840 0 R ->> -endobj - -2875 0 obj -<< - /Type /StructElem - /S /Em - /P 2868 0 R - /K [184] - /Pg 4840 0 R ->> -endobj - -2876 0 obj -<< - /Type /StructElem - /S /Formula - /P 2868 0 R - /K [179 180 181] - /Pg 4840 0 R ->> -endobj - -2877 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [170 2879 0 R 173 2878 0 R 175 176 177] - /Pg 4840 0 R ->> -endobj - -2878 0 obj -<< - /Type /StructElem - /S /Code - /P 2877 0 R - /K [174] - /Pg 4840 0 R ->> -endobj - -2879 0 obj -<< - /Type /StructElem - /S /Formula - /P 2877 0 R - /K [171 172] - /Pg 4840 0 R ->> -endobj - -2880 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /K [2887 0 R 2881 0 R] ->> -endobj - -2881 0 obj -<< - /Type /StructElem - /S /Div - /P 2880 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [2882 0 R] ->> -endobj - -2882 0 obj -<< - /Type /StructElem - /S /P - /P 2881 0 R - /K [2886 0 R 2885 0 R 2884 0 R 2883 0 R] ->> -endobj - -2883 0 obj -<< - /Type /StructElem - /S /Code - /P 2882 0 R - /K [168] - /Pg 4840 0 R ->> -endobj - -2884 0 obj -<< - /Type /StructElem - /S /Code - /P 2882 0 R - /K [167] - /Pg 4840 0 R ->> -endobj - -2885 0 obj -<< - /Type /StructElem - /S /Code - /P 2882 0 R - /K [166] - /Pg 4840 0 R ->> -endobj - -2886 0 obj -<< - /Type /StructElem - /S /Code - /P 2882 0 R - /K [165] - /Pg 4840 0 R ->> -endobj - -2887 0 obj -<< - /Type /StructElem - /S /Caption - /P 2880 0 R - /K [2888 0 R] ->> -endobj - -2888 0 obj -<< - /Type /StructElem - /S /Span - /P 2887 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [169] - /Pg 4840 0 R ->> -endobj - -2889 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [141 2895 0 R 143 144 145 2894 0 R 2893 0 R 151 152 2892 0 R 154 155 156 2891 0 R 158 159 2890 0 R 161 162 163 164] - /Pg 4840 0 R ->> -endobj - -2890 0 obj -<< - /Type /StructElem - /S /Link - /P 2889 0 R - /K [160 << - /Type /OBJR - /Pg 4840 0 R - /Obj 4839 0 R - >>] - /Pg 4840 0 R ->> -endobj - -2891 0 obj -<< - /Type /StructElem - /S /Code - /P 2889 0 R - /K [157] - /Pg 4840 0 R ->> -endobj - -2892 0 obj -<< - /Type /StructElem - /S /Link - /P 2889 0 R - /K [153 << - /Type /OBJR - /Pg 4840 0 R - /Obj 4838 0 R - >>] - /Pg 4840 0 R ->> -endobj - -2893 0 obj -<< - /Type /StructElem - /S /Formula - /P 2889 0 R - /K [147 148 149 150] - /Pg 4840 0 R ->> -endobj - -2894 0 obj -<< - /Type /StructElem - /S /Code - /P 2889 0 R - /K [146] - /Pg 4840 0 R ->> -endobj - -2895 0 obj -<< - /Type /StructElem - /S /Em - /P 2889 0 R - /K [142] - /Pg 4840 0 R ->> -endobj - -2896 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [124 2899 0 R 126 2898 0 R 128 129 130 2897 0 R 140] - /Pg 4840 0 R ->> -endobj - -2897 0 obj -<< - /Type /StructElem - /S /Formula - /P 2896 0 R - /K [131 132 133 134 135 136 137 138 139] - /Pg 4840 0 R ->> -endobj - -2898 0 obj -<< - /Type /StructElem - /S /Formula - /P 2896 0 R - /K [127] - /Pg 4840 0 R ->> -endobj - -2899 0 obj -<< - /Type /StructElem - /S /Formula - /P 2896 0 R - /K [125] - /Pg 4840 0 R ->> -endobj - -2900 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [2934 0 R 2901 0 R] ->> -endobj - -2901 0 obj -<< - /Type /StructElem - /S /Div - /P 2900 0 R - /K [2932 0 R 2930 0 R 2928 0 R 2926 0 R 2924 0 R 2922 0 R 2920 0 R 2918 0 R 2916 0 R 2914 0 R 2912 0 R 2910 0 R 2908 0 R 2902 0 R] ->> -endobj - -2902 0 obj -<< - /Type /StructElem - /S /Div - /P 2901 0 R - /K [2907 0 R 2906 0 R 2905 0 R 2904 0 R 2903 0 R] ->> -endobj - -2903 0 obj -<< - /Type /StructElem - /S /Formula - /P 2902 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [113 114 115 116 117 118 119 120 121 122 123] - /Pg 4840 0 R ->> -endobj - -2904 0 obj -<< - /Type /StructElem - /S /Formula - /P 2902 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112] - /Pg 4840 0 R ->> -endobj - -2905 0 obj -<< - /Type /StructElem - /S /Formula - /P 2902 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85] - /Pg 4840 0 R ->> -endobj - -2906 0 obj -<< - /Type /StructElem - /S /Formula - /P 2902 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [66 67] - /Pg 4840 0 R ->> -endobj - -2907 0 obj -<< - /Type /StructElem - /S /Formula - /P 2902 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [52 53 54 55 56 57 58 59 60 61 62 63 64 65] - /Pg 4840 0 R ->> -endobj - -2908 0 obj -<< - /Type /StructElem - /S /Div - /P 2901 0 R - /K [2909 0 R] ->> -endobj - -2909 0 obj -<< - /Type /StructElem - /S /Formula - /P 2908 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [51] - /Pg 4840 0 R ->> -endobj - -2910 0 obj -<< - /Type /StructElem - /S /Div - /P 2901 0 R - /K [2911 0 R] ->> -endobj - -2911 0 obj -<< - /Type /StructElem - /S /Formula - /P 2910 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [46 47 48 49 50] - /Pg 4840 0 R ->> -endobj - -2912 0 obj -<< - /Type /StructElem - /S /Div - /P 2901 0 R - /K [2913 0 R] ->> -endobj - -2913 0 obj -<< - /Type /StructElem - /S /Formula - /P 2912 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [45] - /Pg 4840 0 R ->> -endobj - -2914 0 obj -<< - /Type /StructElem - /S /Div - /P 2901 0 R - /K [2915 0 R] ->> -endobj - -2915 0 obj -<< - /Type /StructElem - /S /Formula - /P 2914 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [44] - /Pg 4840 0 R ->> -endobj - -2916 0 obj -<< - /Type /StructElem - /S /Div - /P 2901 0 R - /K [2917 0 R] ->> -endobj - -2917 0 obj -<< - /Type /StructElem - /S /Formula - /P 2916 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [43] - /Pg 4840 0 R ->> -endobj - -2918 0 obj -<< - /Type /StructElem - /S /Div - /P 2901 0 R - /K [2919 0 R] ->> -endobj - -2919 0 obj -<< - /Type /StructElem - /S /Formula - /P 2918 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [40 41 42] - /Pg 4840 0 R ->> -endobj - -2920 0 obj -<< - /Type /StructElem - /S /Div - /P 2901 0 R - /K [2921 0 R] ->> -endobj - -2921 0 obj -<< - /Type /StructElem - /S /Formula - /P 2920 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [37 38 39] - /Pg 4840 0 R ->> -endobj - -2922 0 obj -<< - /Type /StructElem - /S /Div - /P 2901 0 R - /K [2923 0 R] ->> -endobj - -2923 0 obj -<< - /Type /StructElem - /S /Formula - /P 2922 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [36] - /Pg 4840 0 R ->> -endobj - -2924 0 obj -<< - /Type /StructElem - /S /Div - /P 2901 0 R - /K [2925 0 R] ->> -endobj - -2925 0 obj -<< - /Type /StructElem - /S /Formula - /P 2924 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [34 35] - /Pg 4840 0 R ->> -endobj - -2926 0 obj -<< - /Type /StructElem - /S /Div - /P 2901 0 R - /K [2927 0 R] ->> -endobj - -2927 0 obj -<< - /Type /StructElem - /S /Formula - /P 2926 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [33] - /Pg 4840 0 R ->> -endobj - -2928 0 obj -<< - /Type /StructElem - /S /Div - /P 2901 0 R - /K [2929 0 R] ->> -endobj - -2929 0 obj -<< - /Type /StructElem - /S /Formula - /P 2928 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [30 31 32] - /Pg 4840 0 R ->> -endobj - -2930 0 obj -<< - /Type /StructElem - /S /Div - /P 2901 0 R - /K [2931 0 R] ->> -endobj - -2931 0 obj -<< - /Type /StructElem - /S /Formula - /P 2930 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [29] - /Pg 4840 0 R ->> -endobj - -2932 0 obj -<< - /Type /StructElem - /S /Div - /P 2901 0 R - /K [2933 0 R] ->> -endobj - -2933 0 obj -<< - /Type /StructElem - /S /Formula - /P 2932 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [26 27 28] - /Pg 4840 0 R ->> -endobj - -2934 0 obj -<< - /Type /StructElem - /S /P - /P 2900 0 R - /K [2936 0 R 21 2935 0 R 25] - /Pg 4840 0 R ->> -endobj - -2935 0 obj -<< - /Type /StructElem - /S /Formula - /P 2934 0 R - /K [22 23 24] - /Pg 4840 0 R ->> -endobj - -2936 0 obj -<< - /Type /StructElem - /S /Strong - /P 2934 0 R - /K [18 19 20] - /Pg 4840 0 R ->> -endobj - -2937 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [9 2939 0 R 13 2938 0 R 16 17] - /Pg 4840 0 R ->> -endobj - -2938 0 obj -<< - /Type /StructElem - /S /Formula - /P 2937 0 R - /K [14 15] - /Pg 4840 0 R ->> -endobj - -2939 0 obj -<< - /Type /StructElem - /S /Formula - /P 2937 0 R - /K [10 11 12] - /Pg 4840 0 R ->> -endobj - -2940 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [2968 0 R 2967 0 R 2964 0 R 2941 0 R] ->> -endobj - -2941 0 obj -<< - /Type /StructElem - /S /L - /P 2940 0 R - /A [<< - /O /List - /ListNumbering /Circle - >>] - /K [2960 0 R 2956 0 R 2951 0 R 2942 0 R] ->> -endobj - -2942 0 obj -<< - /Type /StructElem - /S /L - /P 2941 0 R - /A [<< - /O /List - /ListNumbering /Circle - >>] - /K [2947 0 R 2943 0 R] ->> -endobj - -2943 0 obj -<< - /Type /StructElem - /S /LI - /P 2942 0 R - /K [2946 0 R 2944 0 R] ->> -endobj - -2944 0 obj -<< - /Type /StructElem - /S /LBody - /P 2943 0 R - /K [2945 0 R 8] - /Pg 4840 0 R ->> -endobj - -2945 0 obj -<< - /Type /StructElem - /S /Formula - /P 2944 0 R - /K [4 5 6 7] - /Pg 4840 0 R ->> -endobj - -2946 0 obj -<< - /Type /StructElem - /S /Lbl - /P 2943 0 R - /K [3] - /Pg 4840 0 R ->> -endobj - -2947 0 obj -<< - /Type /StructElem - /S /LI - /P 2942 0 R - /K [2950 0 R 2948 0 R] ->> -endobj - -2948 0 obj -<< - /Type /StructElem - /S /LBody - /P 2947 0 R - /K [2949 0 R 2] - /Pg 4840 0 R ->> -endobj - -2949 0 obj -<< - /Type /StructElem - /S /Formula - /P 2948 0 R - /K [1] - /Pg 4840 0 R ->> -endobj - -2950 0 obj -<< - /Type /StructElem - /S /Lbl - /P 2947 0 R - /K [0] - /Pg 4840 0 R ->> -endobj - -2951 0 obj -<< - /Type /StructElem - /S /LI - /P 2941 0 R - /K [2955 0 R 2952 0 R] ->> -endobj - -2952 0 obj -<< - /Type /StructElem - /S /LBody - /P 2951 0 R - /K [2953 0 R] ->> -endobj - -2953 0 obj -<< - /Type /StructElem - /S /P - /P 2952 0 R - /K [2954 0 R 341] - /Pg 4836 0 R ->> -endobj - -2954 0 obj -<< - /Type /StructElem - /S /Formula - /P 2953 0 R - /K [340] - /Pg 4836 0 R ->> -endobj - -2955 0 obj -<< - /Type /StructElem - /S /Lbl - /P 2951 0 R - /K [339] - /Pg 4836 0 R ->> -endobj - -2956 0 obj -<< - /Type /StructElem - /S /LI - /P 2941 0 R - /K [2959 0 R 2957 0 R] ->> -endobj - -2957 0 obj -<< - /Type /StructElem - /S /LBody - /P 2956 0 R - /K [2958 0 R 338] - /Pg 4836 0 R ->> -endobj - -2958 0 obj -<< - /Type /StructElem - /S /Formula - /P 2957 0 R - /K [337] - /Pg 4836 0 R ->> -endobj - -2959 0 obj -<< - /Type /StructElem - /S /Lbl - /P 2956 0 R - /K [336] - /Pg 4836 0 R ->> -endobj - -2960 0 obj -<< - /Type /StructElem - /S /LI - /P 2941 0 R - /K [2963 0 R 2961 0 R] ->> -endobj - -2961 0 obj -<< - /Type /StructElem - /S /LBody - /P 2960 0 R - /K [2962 0 R 335] - /Pg 4836 0 R ->> -endobj - -2962 0 obj -<< - /Type /StructElem - /S /Formula - /P 2961 0 R - /K [334] - /Pg 4836 0 R ->> -endobj - -2963 0 obj -<< - /Type /StructElem - /S /Lbl - /P 2960 0 R - /K [333] - /Pg 4836 0 R ->> -endobj - -2964 0 obj -<< - /Type /StructElem - /S /P - /P 2940 0 R - /K [319 2966 0 R 324 2965 0 R 332] - /Pg 4836 0 R ->> -endobj - -2965 0 obj -<< - /Type /StructElem - /S /Formula - /P 2964 0 R - /K [325 326 327 328 329 330 331] - /Pg 4836 0 R ->> -endobj - -2966 0 obj -<< - /Type /StructElem - /S /Formula - /P 2964 0 R - /K [320 321 322 323] - /Pg 4836 0 R ->> -endobj - -2967 0 obj -<< - /Type /StructElem - /S /Formula - /P 2940 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318] - /Pg 4836 0 R ->> -endobj - -2968 0 obj -<< - /Type /StructElem - /S /P - /P 2940 0 R - /K [2971 0 R 229 2970 0 R 233 2969 0 R 238 239] - /Pg 4836 0 R ->> -endobj - -2969 0 obj -<< - /Type /StructElem - /S /Formula - /P 2968 0 R - /K [234 235 236 237] - /Pg 4836 0 R ->> -endobj - -2970 0 obj -<< - /Type /StructElem - /S /Formula - /P 2968 0 R - /K [230 231 232] - /Pg 4836 0 R ->> -endobj - -2971 0 obj -<< - /Type /StructElem - /S /Strong - /P 2968 0 R - /K [226 227 228] - /Pg 4836 0 R ->> -endobj - -2972 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [217 2975 0 R 219 2974 0 R 221 222 2973 0 R 224 225] - /Pg 4836 0 R ->> -endobj - -2973 0 obj -<< - /Type /StructElem - /S /Em - /P 2972 0 R - /K [223] - /Pg 4836 0 R ->> -endobj - -2974 0 obj -<< - /Type /StructElem - /S /Code - /P 2972 0 R - /K [220] - /Pg 4836 0 R ->> -endobj - -2975 0 obj -<< - /Type /StructElem - /S /Code - /P 2972 0 R - /K [218] - /Pg 4836 0 R ->> -endobj - -2976 0 obj -<< - /Type /StructElem - /S /H3 - /P 103 0 R - /T (Iteration) - /K [215 216] - /Pg 4836 0 R ->> -endobj - -2977 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [209 2979 0 R 211 212 2978 0 R 214] - /Pg 4836 0 R ->> -endobj - -2978 0 obj -<< - /Type /StructElem - /S /Link - /P 2977 0 R - /K [213 << - /Type /OBJR - /Pg 4836 0 R - /Obj 4835 0 R - >>] - /Pg 4836 0 R ->> -endobj - -2979 0 obj -<< - /Type /StructElem - /S /Formula - /P 2977 0 R - /K [210] - /Pg 4836 0 R ->> -endobj - -2980 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /K [3008 0 R 3006 0 R 3004 0 R 3002 0 R 3000 0 R 2998 0 R 2996 0 R 2994 0 R 2992 0 R 2990 0 R 2988 0 R 2986 0 R 2984 0 R 2981 0 R] ->> -endobj - -2981 0 obj -<< - /Type /StructElem - /S /Div - /P 2980 0 R - /K [2983 0 R 2982 0 R] ->> -endobj - -2982 0 obj -<< - /Type /StructElem - /S /Formula - /P 2981 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208] - /Pg 4836 0 R ->> -endobj - -2983 0 obj -<< - /Type /StructElem - /S /Formula - /P 2981 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [179 180 181 182 183 184 185 186 187 188 189 190] - /Pg 4836 0 R ->> -endobj - -2984 0 obj -<< - /Type /StructElem - /S /Div - /P 2980 0 R - /K [2985 0 R] ->> -endobj - -2985 0 obj -<< - /Type /StructElem - /S /Formula - /P 2984 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [178] - /Pg 4836 0 R ->> -endobj - -2986 0 obj -<< - /Type /StructElem - /S /Div - /P 2980 0 R - /K [2987 0 R] ->> -endobj - -2987 0 obj -<< - /Type /StructElem - /S /Formula - /P 2986 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [173 174 175 176 177] - /Pg 4836 0 R ->> -endobj - -2988 0 obj -<< - /Type /StructElem - /S /Div - /P 2980 0 R - /K [2989 0 R] ->> -endobj - -2989 0 obj -<< - /Type /StructElem - /S /Formula - /P 2988 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [172] - /Pg 4836 0 R ->> -endobj - -2990 0 obj -<< - /Type /StructElem - /S /Div - /P 2980 0 R - /K [2991 0 R] ->> -endobj - -2991 0 obj -<< - /Type /StructElem - /S /Formula - /P 2990 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [171] - /Pg 4836 0 R ->> -endobj - -2992 0 obj -<< - /Type /StructElem - /S /Div - /P 2980 0 R - /K [2993 0 R] ->> -endobj - -2993 0 obj -<< - /Type /StructElem - /S /Formula - /P 2992 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [170] - /Pg 4836 0 R ->> -endobj - -2994 0 obj -<< - /Type /StructElem - /S /Div - /P 2980 0 R - /K [2995 0 R] ->> -endobj - -2995 0 obj -<< - /Type /StructElem - /S /Formula - /P 2994 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [167 168 169] - /Pg 4836 0 R ->> -endobj - -2996 0 obj -<< - /Type /StructElem - /S /Div - /P 2980 0 R - /K [2997 0 R] ->> -endobj - -2997 0 obj -<< - /Type /StructElem - /S /Formula - /P 2996 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [164 165 166] - /Pg 4836 0 R ->> -endobj - -2998 0 obj -<< - /Type /StructElem - /S /Div - /P 2980 0 R - /K [2999 0 R] ->> -endobj - -2999 0 obj -<< - /Type /StructElem - /S /Formula - /P 2998 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [163] - /Pg 4836 0 R ->> -endobj - -3000 0 obj -<< - /Type /StructElem - /S /Div - /P 2980 0 R - /K [3001 0 R] ->> -endobj - -3001 0 obj -<< - /Type /StructElem - /S /Formula - /P 3000 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [161 162] - /Pg 4836 0 R ->> -endobj - -3002 0 obj -<< - /Type /StructElem - /S /Div - /P 2980 0 R - /K [3003 0 R] ->> -endobj - -3003 0 obj -<< - /Type /StructElem - /S /Formula - /P 3002 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [160] - /Pg 4836 0 R ->> -endobj - -3004 0 obj -<< - /Type /StructElem - /S /Div - /P 2980 0 R - /K [3005 0 R] ->> -endobj - -3005 0 obj -<< - /Type /StructElem - /S /Formula - /P 3004 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [158 159] - /Pg 4836 0 R ->> -endobj - -3006 0 obj -<< - /Type /StructElem - /S /Div - /P 2980 0 R - /K [3007 0 R] ->> -endobj - -3007 0 obj -<< - /Type /StructElem - /S /Formula - /P 3006 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [157] - /Pg 4836 0 R ->> -endobj - -3008 0 obj -<< - /Type /StructElem - /S /Div - /P 2980 0 R - /K [3009 0 R] ->> -endobj - -3009 0 obj -<< - /Type /StructElem - /S /Formula - /P 3008 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [154 155 156] - /Pg 4836 0 R ->> -endobj - -3010 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [132 3016 0 R 135 3015 0 R 137 138 3014 0 R 144 3013 0 R 146 147 3012 0 R 151 3011 0 R 153] - /Pg 4836 0 R ->> -endobj - -3011 0 obj -<< - /Type /StructElem - /S /Formula - /P 3010 0 R - /K [152] - /Pg 4836 0 R ->> -endobj - -3012 0 obj -<< - /Type /StructElem - /S /Formula - /P 3010 0 R - /K [148 149 150] - /Pg 4836 0 R ->> -endobj - -3013 0 obj -<< - /Type /StructElem - /S /Formula - /P 3010 0 R - /K [145] - /Pg 4836 0 R ->> -endobj - -3014 0 obj -<< - /Type /StructElem - /S /Formula - /P 3010 0 R - /K [139 140 141 142 143] - /Pg 4836 0 R ->> -endobj - -3015 0 obj -<< - /Type /StructElem - /S /Link - /P 3010 0 R - /K [136 << - /Type /OBJR - /Pg 4836 0 R - /Obj 4834 0 R - >>] - /Pg 4836 0 R ->> -endobj - -3016 0 obj -<< - /Type /StructElem - /S /Formula - /P 3010 0 R - /K [133 134] - /Pg 4836 0 R ->> -endobj - -3017 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [3024 0 R 3023 0 R 3018 0 R] ->> -endobj - -3018 0 obj -<< - /Type /StructElem - /S /P - /P 3017 0 R - /K [118 3022 0 R 120 121 3021 0 R 124 3020 0 R 128 3019 0 R 131] - /Pg 4836 0 R ->> -endobj - -3019 0 obj -<< - /Type /StructElem - /S /Formula - /P 3018 0 R - /K [129 130] - /Pg 4836 0 R ->> -endobj - -3020 0 obj -<< - /Type /StructElem - /S /Formula - /P 3018 0 R - /K [125 126 127] - /Pg 4836 0 R ->> -endobj - -3021 0 obj -<< - /Type /StructElem - /S /Formula - /P 3018 0 R - /K [122 123] - /Pg 4836 0 R ->> -endobj - -3022 0 obj -<< - /Type /StructElem - /S /Formula - /P 3018 0 R - /K [119] - /Pg 4836 0 R ->> -endobj - -3023 0 obj -<< - /Type /StructElem - /S /Formula - /P 3017 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117] - /Pg 4836 0 R ->> -endobj - -3024 0 obj -<< - /Type /StructElem - /S /P - /P 3017 0 R - /K [3031 0 R 51 3030 0 R 53 3029 0 R 67 3028 0 R 70 71 72 3027 0 R 74 3026 0 R 76 77 3025 0 R 79] - /Pg 4836 0 R ->> -endobj - -3025 0 obj -<< - /Type /StructElem - /S /Formula - /P 3024 0 R - /K [78] - /Pg 4836 0 R ->> -endobj - -3026 0 obj -<< - /Type /StructElem - /S /Formula - /P 3024 0 R - /K [75] - /Pg 4836 0 R ->> -endobj - -3027 0 obj -<< - /Type /StructElem - /S /Formula - /P 3024 0 R - /K [73] - /Pg 4836 0 R ->> -endobj - -3028 0 obj -<< - /Type /StructElem - /S /Formula - /P 3024 0 R - /K [68 69] - /Pg 4836 0 R ->> -endobj - -3029 0 obj -<< - /Type /StructElem - /S /Formula - /P 3024 0 R - /K [54 55 56 57 58 59 60 61 62 63 64 65 66] - /Pg 4836 0 R ->> -endobj - -3030 0 obj -<< - /Type /StructElem - /S /Em - /P 3024 0 R - /K [52] - /Pg 4836 0 R ->> -endobj - -3031 0 obj -<< - /Type /StructElem - /S /Strong - /P 3024 0 R - /K [48 49 50] - /Pg 4836 0 R ->> -endobj - -3032 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [29 3038 0 R 31 32 3037 0 R 34 35 3036 0 R 37 38 3035 0 R 40 41 42 43 3034 0 R 45 3033 0 R 47] - /Pg 4836 0 R ->> -endobj - -3033 0 obj -<< - /Type /StructElem - /S /Code - /P 3032 0 R - /K [46] - /Pg 4836 0 R ->> -endobj - -3034 0 obj -<< - /Type /StructElem - /S /Code - /P 3032 0 R - /K [44] - /Pg 4836 0 R ->> -endobj - -3035 0 obj -<< - /Type /StructElem - /S /Link - /P 3032 0 R - /K [39 << - /Type /OBJR - /Pg 4836 0 R - /Obj 4833 0 R - >>] - /Pg 4836 0 R ->> -endobj - -3036 0 obj -<< - /Type /StructElem - /S /Em - /P 3032 0 R - /K [36] - /Pg 4836 0 R ->> -endobj - -3037 0 obj -<< - /Type /StructElem - /S /Formula - /P 3032 0 R - /K [33] - /Pg 4836 0 R ->> -endobj - -3038 0 obj -<< - /Type /StructElem - /S /Em - /P 3032 0 R - /K [30] - /Pg 4836 0 R ->> -endobj - -3039 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [323 3051 0 R 325 326 3050 0 R 328 3049 0 R << - /Type /MCR - /MCID 1 - /Pg 4836 0 R - >> 3048 0 R << - /Type /MCR - /MCID 3 - /Pg 4836 0 R - >> 3047 0 R << - /Type /MCR - /MCID 6 - /Pg 4836 0 R - >> 3046 0 R << - /Type /MCR - /MCID 8 - /Pg 4836 0 R - >> 3045 0 R << - /Type /MCR - /MCID 10 - /Pg 4836 0 R - >> << - /Type /MCR - /MCID 11 - /Pg 4836 0 R - >> 3044 0 R << - /Type /MCR - /MCID 13 - /Pg 4836 0 R - >> 3043 0 R << - /Type /MCR - /MCID 20 - /Pg 4836 0 R - >> 3042 0 R << - /Type /MCR - /MCID 22 - /Pg 4836 0 R - >> << - /Type /MCR - /MCID 23 - /Pg 4836 0 R - >> 3041 0 R << - /Type /MCR - /MCID 25 - /Pg 4836 0 R - >> << - /Type /MCR - /MCID 26 - /Pg 4836 0 R - >> 3040 0 R << - /Type /MCR - /MCID 28 - /Pg 4836 0 R - >>] - /Pg 4829 0 R ->> -endobj - -3040 0 obj -<< - /Type /StructElem - /S /Em - /P 3039 0 R - /K [27] - /Pg 4836 0 R ->> -endobj - -3041 0 obj -<< - /Type /StructElem - /S /Formula - /P 3039 0 R - /K [24] - /Pg 4836 0 R ->> -endobj - -3042 0 obj -<< - /Type /StructElem - /S /Link - /P 3039 0 R - /K [21 << - /Type /OBJR - /Pg 4836 0 R - /Obj 4832 0 R - >>] - /Pg 4836 0 R ->> -endobj - -3043 0 obj -<< - /Type /StructElem - /S /Formula - /P 3039 0 R - /K [14 15 16 17 18 19] - /Pg 4836 0 R ->> -endobj - -3044 0 obj -<< - /Type /StructElem - /S /Formula - /P 3039 0 R - /K [12] - /Pg 4836 0 R ->> -endobj - -3045 0 obj -<< - /Type /StructElem - /S /Em - /P 3039 0 R - /K [9] - /Pg 4836 0 R ->> -endobj - -3046 0 obj -<< - /Type /StructElem - /S /Formula - /P 3039 0 R - /K [7] - /Pg 4836 0 R ->> -endobj - -3047 0 obj -<< - /Type /StructElem - /S /Formula - /P 3039 0 R - /K [4 5] - /Pg 4836 0 R ->> -endobj - -3048 0 obj -<< - /Type /StructElem - /S /Formula - /P 3039 0 R - /K [2] - /Pg 4836 0 R ->> -endobj - -3049 0 obj -<< - /Type /StructElem - /S /Link - /P 3039 0 R - /K [329 << - /Type /OBJR - /Pg 4829 0 R - /Obj 4827 0 R - >> 330 << - /Type /OBJR - /Pg 4829 0 R - /Obj 4828 0 R - >> << - /Type /MCR - /MCID 0 - /Pg 4836 0 R - >> << - /Type /OBJR - /Pg 4836 0 R - /Obj 4831 0 R - >>] - /Pg 4829 0 R ->> -endobj - -3050 0 obj -<< - /Type /StructElem - /S /Formula - /P 3039 0 R - /K [327] - /Pg 4829 0 R ->> -endobj - -3051 0 obj -<< - /Type /StructElem - /S /Code - /P 3039 0 R - /K [324] - /Pg 4829 0 R ->> -endobj - -3052 0 obj -<< - /Type /StructElem - /S /H3 - /P 103 0 R - /T (Idempotent Recovery) - /K [321 322] - /Pg 4829 0 R ->> -endobj - -3053 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /K [3060 0 R 3054 0 R] ->> -endobj - -3054 0 obj -<< - /Type /StructElem - /S /Div - /P 3053 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [3055 0 R] ->> -endobj - -3055 0 obj -<< - /Type /StructElem - /S /P - /P 3054 0 R - /K [3059 0 R 3058 0 R 3057 0 R 3056 0 R] ->> -endobj - -3056 0 obj -<< - /Type /StructElem - /S /Code - /P 3055 0 R - /K [319] - /Pg 4829 0 R ->> -endobj - -3057 0 obj -<< - /Type /StructElem - /S /Code - /P 3055 0 R - /K [318] - /Pg 4829 0 R ->> -endobj - -3058 0 obj -<< - /Type /StructElem - /S /Code - /P 3055 0 R - /K [317] - /Pg 4829 0 R ->> -endobj - -3059 0 obj -<< - /Type /StructElem - /S /Code - /P 3055 0 R - /K [316] - /Pg 4829 0 R ->> -endobj - -3060 0 obj -<< - /Type /StructElem - /S /Caption - /P 3053 0 R - /K [3061 0 R] ->> -endobj - -3061 0 obj -<< - /Type /StructElem - /S /Span - /P 3060 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [320] - /Pg 4829 0 R ->> -endobj - -3062 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [284 3072 0 R 286 287 288 3071 0 R 290 291 292 3070 0 R 296 3069 0 R 298 3068 0 R 300 301 3067 0 R 303 3066 0 R 305 306 3065 0 R 308 3064 0 R 310 311 312 3063 0 R 314 315] - /Pg 4829 0 R ->> -endobj - -3063 0 obj -<< - /Type /StructElem - /S /Link - /P 3062 0 R - /K [313 << - /Type /OBJR - /Pg 4829 0 R - /Obj 4826 0 R - >>] - /Pg 4829 0 R ->> -endobj - -3064 0 obj -<< - /Type /StructElem - /S /Code - /P 3062 0 R - /K [309] - /Pg 4829 0 R ->> -endobj - -3065 0 obj -<< - /Type /StructElem - /S /Formula - /P 3062 0 R - /K [307] - /Pg 4829 0 R ->> -endobj - -3066 0 obj -<< - /Type /StructElem - /S /Code - /P 3062 0 R - /K [304] - /Pg 4829 0 R ->> -endobj - -3067 0 obj -<< - /Type /StructElem - /S /Em - /P 3062 0 R - /K [302] - /Pg 4829 0 R ->> -endobj - -3068 0 obj -<< - /Type /StructElem - /S /Code - /P 3062 0 R - /K [299] - /Pg 4829 0 R ->> -endobj - -3069 0 obj -<< - /Type /StructElem - /S /Code - /P 3062 0 R - /K [297] - /Pg 4829 0 R ->> -endobj - -3070 0 obj -<< - /Type /StructElem - /S /Formula - /P 3062 0 R - /K [293 294 295] - /Pg 4829 0 R ->> -endobj - -3071 0 obj -<< - /Type /StructElem - /S /Em - /P 3062 0 R - /K [289] - /Pg 4829 0 R ->> -endobj - -3072 0 obj -<< - /Type /StructElem - /S /Em - /P 3062 0 R - /K [285] - /Pg 4829 0 R ->> -endobj - -3073 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [3086 0 R 3085 0 R 3083 0 R 3074 0 R] ->> -endobj - -3074 0 obj -<< - /Type /StructElem - /S /L - /P 3073 0 R - /A [<< - /O /List - /ListNumbering /Circle - >>] - /K [3079 0 R 3075 0 R] ->> -endobj - -3075 0 obj -<< - /Type /StructElem - /S /LI - /P 3074 0 R - /K [3078 0 R 3076 0 R] ->> -endobj - -3076 0 obj -<< - /Type /StructElem - /S /LBody - /P 3075 0 R - /K [3077 0 R 283] - /Pg 4829 0 R ->> -endobj - -3077 0 obj -<< - /Type /StructElem - /S /Formula - /P 3076 0 R - /K [279 280 281 282] - /Pg 4829 0 R ->> -endobj - -3078 0 obj -<< - /Type /StructElem - /S /Lbl - /P 3075 0 R - /K [278] - /Pg 4829 0 R ->> -endobj - -3079 0 obj -<< - /Type /StructElem - /S /LI - /P 3074 0 R - /K [3082 0 R 3080 0 R] ->> -endobj - -3080 0 obj -<< - /Type /StructElem - /S /LBody - /P 3079 0 R - /K [3081 0 R 275 276 277] - /Pg 4829 0 R ->> -endobj - -3081 0 obj -<< - /Type /StructElem - /S /Formula - /P 3080 0 R - /K [271 272 273 274] - /Pg 4829 0 R ->> -endobj - -3082 0 obj -<< - /Type /StructElem - /S /Lbl - /P 3079 0 R - /K [270] - /Pg 4829 0 R ->> -endobj - -3083 0 obj -<< - /Type /StructElem - /S /P - /P 3073 0 R - /K [263 3084 0 R 269] - /Pg 4829 0 R ->> -endobj - -3084 0 obj -<< - /Type /StructElem - /S /Formula - /P 3083 0 R - /K [264 265 266 267 268] - /Pg 4829 0 R ->> -endobj - -3085 0 obj -<< - /Type /StructElem - /S /Formula - /P 3073 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [254 255 256 257 258 259 260 261 262] - /Pg 4829 0 R ->> -endobj - -3086 0 obj -<< - /Type /StructElem - /S /P - /P 3073 0 R - /K [3089 0 R 249 3088 0 R 251 3087 0 R 253] - /Pg 4829 0 R ->> -endobj - -3087 0 obj -<< - /Type /StructElem - /S /Formula - /P 3086 0 R - /K [252] - /Pg 4829 0 R ->> -endobj - -3088 0 obj -<< - /Type /StructElem - /S /Em - /P 3086 0 R - /K [250] - /Pg 4829 0 R ->> -endobj - -3089 0 obj -<< - /Type /StructElem - /S /Strong - /P 3086 0 R - /K [246 247 248] - /Pg 4829 0 R ->> -endobj - -3090 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [236 237 238 3093 0 R 240 3092 0 R 242 243 3091 0 R 245] - /Pg 4829 0 R ->> -endobj - -3091 0 obj -<< - /Type /StructElem - /S /Link - /P 3090 0 R - /K [244 << - /Type /OBJR - /Pg 4829 0 R - /Obj 4825 0 R - >>] - /Pg 4829 0 R ->> -endobj - -3092 0 obj -<< - /Type /StructElem - /S /Formula - /P 3090 0 R - /K [241] - /Pg 4829 0 R ->> -endobj - -3093 0 obj -<< - /Type /StructElem - /S /Em - /P 3090 0 R - /K [239] - /Pg 4829 0 R ->> -endobj - -3094 0 obj -<< - /Type /StructElem - /S /H2 - /P 103 0 R - /T (Component Lifecycle) - /K [234 235] - /Pg 4829 0 R ->> -endobj - -3095 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [198 3101 0 R 200 3100 0 R 202 3099 0 R 219 3098 0 R 221 222 223 3097 0 R 228 229 230 231 3096 0 R 233] - /Pg 4829 0 R ->> -endobj - -3096 0 obj -<< - /Type /StructElem - /S /Link - /P 3095 0 R - /K [232 << - /Type /OBJR - /Pg 4829 0 R - /Obj 4824 0 R - >>] - /Pg 4829 0 R ->> -endobj - -3097 0 obj -<< - /Type /StructElem - /S /Formula - /P 3095 0 R - /K [224 225 226 227] - /Pg 4829 0 R ->> -endobj - -3098 0 obj -<< - /Type /StructElem - /S /Formula - /P 3095 0 R - /K [220] - /Pg 4829 0 R ->> -endobj - -3099 0 obj -<< - /Type /StructElem - /S /Formula - /P 3095 0 R - /K [203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218] - /Pg 4829 0 R ->> -endobj - -3100 0 obj -<< - /Type /StructElem - /S /Formula - /P 3095 0 R - /K [201] - /Pg 4829 0 R ->> -endobj - -3101 0 obj -<< - /Type /StructElem - /S /Formula - /P 3095 0 R - /K [199] - /Pg 4829 0 R ->> -endobj - -3102 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [3188 0 R 3103 0 R] ->> -endobj - -3103 0 obj -<< - /Type /StructElem - /S /Div - /P 3102 0 R - /K [3186 0 R 3184 0 R 3182 0 R 3180 0 R 3178 0 R 3176 0 R 3174 0 R 3172 0 R 3170 0 R 3168 0 R 3166 0 R 3164 0 R 3162 0 R 3160 0 R 3158 0 R 3156 0 R 3154 0 R 3152 0 R 3150 0 R 3148 0 R 3146 0 R 3144 0 R 3142 0 R 3140 0 R 3138 0 R 3136 0 R 3134 0 R 3132 0 R 3130 0 R 3128 0 R 3126 0 R 3124 0 R 3122 0 R 3120 0 R 3118 0 R 3116 0 R 3114 0 R 3112 0 R 3110 0 R 3108 0 R 3106 0 R 3104 0 R] ->> -endobj - -3104 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3105 0 R] ->> -endobj - -3105 0 obj -<< - /Type /StructElem - /S /Formula - /P 3104 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197] - /Pg 4829 0 R ->> -endobj - -3106 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3107 0 R] ->> -endobj - -3107 0 obj -<< - /Type /StructElem - /S /Formula - /P 3106 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [154] - /Pg 4829 0 R ->> -endobj - -3108 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3109 0 R] ->> -endobj - -3109 0 obj -<< - /Type /StructElem - /S /Formula - /P 3108 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [149 150 151 152 153] - /Pg 4829 0 R ->> -endobj - -3110 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3111 0 R] ->> -endobj - -3111 0 obj -<< - /Type /StructElem - /S /Formula - /P 3110 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [148] - /Pg 4829 0 R ->> -endobj - -3112 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3113 0 R] ->> -endobj - -3113 0 obj -<< - /Type /StructElem - /S /Formula - /P 3112 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [143 144 145 146 147] - /Pg 4829 0 R ->> -endobj - -3114 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3115 0 R] ->> -endobj - -3115 0 obj -<< - /Type /StructElem - /S /Formula - /P 3114 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [142] - /Pg 4829 0 R ->> -endobj - -3116 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3117 0 R] ->> -endobj - -3117 0 obj -<< - /Type /StructElem - /S /Formula - /P 3116 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [141] - /Pg 4829 0 R ->> -endobj - -3118 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3119 0 R] ->> -endobj - -3119 0 obj -<< - /Type /StructElem - /S /Formula - /P 3118 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [131 132 133 134 135 136 137 138 139 140] - /Pg 4829 0 R ->> -endobj - -3120 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3121 0 R] ->> -endobj - -3121 0 obj -<< - /Type /StructElem - /S /Formula - /P 3120 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [130] - /Pg 4829 0 R ->> -endobj - -3122 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3123 0 R] ->> -endobj - -3123 0 obj -<< - /Type /StructElem - /S /Formula - /P 3122 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [128 129] - /Pg 4829 0 R ->> -endobj - -3124 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3125 0 R] ->> -endobj - -3125 0 obj -<< - /Type /StructElem - /S /Formula - /P 3124 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [127] - /Pg 4829 0 R ->> -endobj - -3126 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3127 0 R] ->> -endobj - -3127 0 obj -<< - /Type /StructElem - /S /Formula - /P 3126 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [119 120 121 122 123 124 125 126] - /Pg 4829 0 R ->> -endobj - -3128 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3129 0 R] ->> -endobj - -3129 0 obj -<< - /Type /StructElem - /S /Formula - /P 3128 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [118] - /Pg 4829 0 R ->> -endobj - -3130 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3131 0 R] ->> -endobj - -3131 0 obj -<< - /Type /StructElem - /S /Formula - /P 3130 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [117] - /Pg 4829 0 R ->> -endobj - -3132 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3133 0 R] ->> -endobj - -3133 0 obj -<< - /Type /StructElem - /S /Formula - /P 3132 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116] - /Pg 4829 0 R ->> -endobj - -3134 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3135 0 R] ->> -endobj - -3135 0 obj -<< - /Type /StructElem - /S /Formula - /P 3134 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [85] - /Pg 4829 0 R ->> -endobj - -3136 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3137 0 R] ->> -endobj - -3137 0 obj -<< - /Type /StructElem - /S /Formula - /P 3136 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [80 81 82 83 84] - /Pg 4829 0 R ->> -endobj - -3138 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3139 0 R] ->> -endobj - -3139 0 obj -<< - /Type /StructElem - /S /Formula - /P 3138 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [79] - /Pg 4829 0 R ->> -endobj - -3140 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3141 0 R] ->> -endobj - -3141 0 obj -<< - /Type /StructElem - /S /Formula - /P 3140 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [74 75 76 77 78] - /Pg 4829 0 R ->> -endobj - -3142 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3143 0 R] ->> -endobj - -3143 0 obj -<< - /Type /StructElem - /S /Formula - /P 3142 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [73] - /Pg 4829 0 R ->> -endobj - -3144 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3145 0 R] ->> -endobj - -3145 0 obj -<< - /Type /StructElem - /S /Formula - /P 3144 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [72] - /Pg 4829 0 R ->> -endobj - -3146 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3147 0 R] ->> -endobj - -3147 0 obj -<< - /Type /StructElem - /S /Formula - /P 3146 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [62 63 64 65 66 67 68 69 70 71] - /Pg 4829 0 R ->> -endobj - -3148 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3149 0 R] ->> -endobj - -3149 0 obj -<< - /Type /StructElem - /S /Formula - /P 3148 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [61] - /Pg 4829 0 R ->> -endobj - -3150 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3151 0 R] ->> -endobj - -3151 0 obj -<< - /Type /StructElem - /S /Formula - /P 3150 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [59 60] - /Pg 4829 0 R ->> -endobj - -3152 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3153 0 R] ->> -endobj - -3153 0 obj -<< - /Type /StructElem - /S /Formula - /P 3152 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [58] - /Pg 4829 0 R ->> -endobj - -3154 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3155 0 R] ->> -endobj - -3155 0 obj -<< - /Type /StructElem - /S /Formula - /P 3154 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [45 46 47 48 49 50 51 52 53 54 55 56 57] - /Pg 4829 0 R ->> -endobj - -3156 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3157 0 R] ->> -endobj - -3157 0 obj -<< - /Type /StructElem - /S /Formula - /P 3156 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [44] - /Pg 4829 0 R ->> -endobj - -3158 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3159 0 R] ->> -endobj - -3159 0 obj -<< - /Type /StructElem - /S /Formula - /P 3158 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [43] - /Pg 4829 0 R ->> -endobj - -3160 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3161 0 R] ->> -endobj - -3161 0 obj -<< - /Type /StructElem - /S /Formula - /P 3160 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [30 31 32 33 34 35 36 37 38 39 40 41 42] - /Pg 4829 0 R ->> -endobj - -3162 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3163 0 R] ->> -endobj - -3163 0 obj -<< - /Type /StructElem - /S /Formula - /P 3162 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [29] - /Pg 4829 0 R ->> -endobj - -3164 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3165 0 R] ->> -endobj - -3165 0 obj -<< - /Type /StructElem - /S /Formula - /P 3164 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [24 25 26 27 28] - /Pg 4829 0 R ->> -endobj - -3166 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3167 0 R] ->> -endobj - -3167 0 obj -<< - /Type /StructElem - /S /Formula - /P 3166 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [23] - /Pg 4829 0 R ->> -endobj - -3168 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3169 0 R] ->> -endobj - -3169 0 obj -<< - /Type /StructElem - /S /Formula - /P 3168 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [18 19 20 21 22] - /Pg 4829 0 R ->> -endobj - -3170 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3171 0 R] ->> -endobj - -3171 0 obj -<< - /Type /StructElem - /S /Formula - /P 3170 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [17] - /Pg 4829 0 R ->> -endobj - -3172 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3173 0 R] ->> -endobj - -3173 0 obj -<< - /Type /StructElem - /S /Formula - /P 3172 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [16] - /Pg 4829 0 R ->> -endobj - -3174 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3175 0 R] ->> -endobj - -3175 0 obj -<< - /Type /StructElem - /S /Formula - /P 3174 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [14 15] - /Pg 4829 0 R ->> -endobj - -3176 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3177 0 R] ->> -endobj - -3177 0 obj -<< - /Type /StructElem - /S /Formula - /P 3176 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [13] - /Pg 4829 0 R ->> -endobj - -3178 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3179 0 R] ->> -endobj - -3179 0 obj -<< - /Type /StructElem - /S /Formula - /P 3178 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [11 12] - /Pg 4829 0 R ->> -endobj - -3180 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3181 0 R] ->> -endobj - -3181 0 obj -<< - /Type /StructElem - /S /Formula - /P 3180 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [10] - /Pg 4829 0 R ->> -endobj - -3182 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3183 0 R] ->> -endobj - -3183 0 obj -<< - /Type /StructElem - /S /Formula - /P 3182 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [2 3 4 5 6 7 8 9] - /Pg 4829 0 R ->> -endobj - -3184 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3185 0 R] ->> -endobj - -3185 0 obj -<< - /Type /StructElem - /S /Formula - /P 3184 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [1] - /Pg 4829 0 R ->> -endobj - -3186 0 obj -<< - /Type /StructElem - /S /Div - /P 3103 0 R - /K [3187 0 R] ->> -endobj - -3187 0 obj -<< - /Type /StructElem - /S /Formula - /P 3186 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [0] - /Pg 4829 0 R ->> -endobj - -3188 0 obj -<< - /Type /StructElem - /S /P - /P 3102 0 R - /K [3193 0 R 400 3192 0 R 402 3191 0 R 404 3190 0 R 406 3189 0 R 409] - /Pg 4822 0 R ->> -endobj - -3189 0 obj -<< - /Type /StructElem - /S /Formula - /P 3188 0 R - /K [407 408] - /Pg 4822 0 R ->> -endobj - -3190 0 obj -<< - /Type /StructElem - /S /Formula - /P 3188 0 R - /K [405] - /Pg 4822 0 R ->> -endobj - -3191 0 obj -<< - /Type /StructElem - /S /Formula - /P 3188 0 R - /K [403] - /Pg 4822 0 R ->> -endobj - -3192 0 obj -<< - /Type /StructElem - /S /Formula - /P 3188 0 R - /K [401] - /Pg 4822 0 R ->> -endobj - -3193 0 obj -<< - /Type /StructElem - /S /Strong - /P 3188 0 R - /K [397 398 399] - /Pg 4822 0 R ->> -endobj - -3194 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [3214 0 R 3213 0 R 3195 0 R] ->> -endobj - -3195 0 obj -<< - /Type /StructElem - /S /P - /P 3194 0 R - /K [331 3212 0 R 334 3211 0 R 340 3210 0 R 342 3209 0 R 344 345 3208 0 R 348 3207 0 R 350 3206 0 R 352 3205 0 R 354 3204 0 R 357 3203 0 R 360 3202 0 R 365 3201 0 R 367 368 3200 0 R 373 3199 0 R 378 379 3198 0 R 390 3197 0 R 393 3196 0 R 396] - /Pg 4822 0 R ->> -endobj - -3196 0 obj -<< - /Type /StructElem - /S /Formula - /P 3195 0 R - /K [394 395] - /Pg 4822 0 R ->> -endobj - -3197 0 obj -<< - /Type /StructElem - /S /Formula - /P 3195 0 R - /K [391 392] - /Pg 4822 0 R ->> -endobj - -3198 0 obj -<< - /Type /StructElem - /S /Formula - /P 3195 0 R - /K [380 381 382 383 384 385 386 387 388 389] - /Pg 4822 0 R ->> -endobj - -3199 0 obj -<< - /Type /StructElem - /S /Formula - /P 3195 0 R - /K [374 375 376 377] - /Pg 4822 0 R ->> -endobj - -3200 0 obj -<< - /Type /StructElem - /S /Formula - /P 3195 0 R - /K [369 370 371 372] - /Pg 4822 0 R ->> -endobj - -3201 0 obj -<< - /Type /StructElem - /S /Em - /P 3195 0 R - /K [366] - /Pg 4822 0 R ->> -endobj - -3202 0 obj -<< - /Type /StructElem - /S /Formula - /P 3195 0 R - /K [361 362 363 364] - /Pg 4822 0 R ->> -endobj - -3203 0 obj -<< - /Type /StructElem - /S /Formula - /P 3195 0 R - /K [358 359] - /Pg 4822 0 R ->> -endobj - -3204 0 obj -<< - /Type /StructElem - /S /Formula - /P 3195 0 R - /K [355 356] - /Pg 4822 0 R ->> -endobj - -3205 0 obj -<< - /Type /StructElem - /S /Em - /P 3195 0 R - /K [353] - /Pg 4822 0 R ->> -endobj - -3206 0 obj -<< - /Type /StructElem - /S /Formula - /P 3195 0 R - /K [351] - /Pg 4822 0 R ->> -endobj - -3207 0 obj -<< - /Type /StructElem - /S /Formula - /P 3195 0 R - /K [349] - /Pg 4822 0 R ->> -endobj - -3208 0 obj -<< - /Type /StructElem - /S /Formula - /P 3195 0 R - /K [346 347] - /Pg 4822 0 R ->> -endobj - -3209 0 obj -<< - /Type /StructElem - /S /Em - /P 3195 0 R - /K [343] - /Pg 4822 0 R ->> -endobj - -3210 0 obj -<< - /Type /StructElem - /S /Formula - /P 3195 0 R - /K [341] - /Pg 4822 0 R ->> -endobj - -3211 0 obj -<< - /Type /StructElem - /S /Formula - /P 3195 0 R - /K [335 336 337 338 339] - /Pg 4822 0 R ->> -endobj - -3212 0 obj -<< - /Type /StructElem - /S /Formula - /P 3195 0 R - /K [332 333] - /Pg 4822 0 R ->> -endobj - -3213 0 obj -<< - /Type /StructElem - /S /Formula - /P 3194 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330] - /Pg 4822 0 R ->> -endobj - -3214 0 obj -<< - /Type /StructElem - /S /P - /P 3194 0 R - /K [3215 0 R 289] - /Pg 4822 0 R ->> -endobj - -3215 0 obj -<< - /Type /StructElem - /S /Strong - /P 3214 0 R - /K [286 287 288] - /Pg 4822 0 R ->> -endobj - -3216 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [3218 0 R 280 3217 0 R 282 283 284 285] - /Pg 4822 0 R ->> -endobj - -3217 0 obj -<< - /Type /StructElem - /S /Em - /P 3216 0 R - /K [281] - /Pg 4822 0 R ->> -endobj - -3218 0 obj -<< - /Type /StructElem - /S /Strong - /P 3216 0 R - /K [279] - /Pg 4822 0 R ->> -endobj - -3219 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [269 270 271 272 273 274 3220 0 R 278] - /Pg 4822 0 R ->> -endobj - -3220 0 obj -<< - /Type /StructElem - /S /Formula - /P 3219 0 R - /K [275 276 277] - /Pg 4822 0 R ->> -endobj - -3221 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [3307 0 R 3222 0 R] ->> -endobj - -3222 0 obj -<< - /Type /StructElem - /S /Div - /P 3221 0 R - /K [3305 0 R 3303 0 R 3301 0 R 3299 0 R 3297 0 R 3295 0 R 3293 0 R 3291 0 R 3289 0 R 3287 0 R 3285 0 R 3283 0 R 3281 0 R 3279 0 R 3277 0 R 3275 0 R 3273 0 R 3271 0 R 3269 0 R 3267 0 R 3265 0 R 3263 0 R 3261 0 R 3259 0 R 3257 0 R 3255 0 R 3253 0 R 3251 0 R 3249 0 R 3247 0 R 3245 0 R 3243 0 R 3241 0 R 3239 0 R 3237 0 R 3235 0 R 3233 0 R 3231 0 R 3229 0 R 3227 0 R 3225 0 R 3223 0 R] ->> -endobj - -3223 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3224 0 R] ->> -endobj - -3224 0 obj -<< - /Type /StructElem - /S /Formula - /P 3223 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268] - /Pg 4822 0 R ->> -endobj - -3225 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3226 0 R] ->> -endobj - -3226 0 obj -<< - /Type /StructElem - /S /Formula - /P 3225 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [237] - /Pg 4822 0 R ->> -endobj - -3227 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3228 0 R] ->> -endobj - -3228 0 obj -<< - /Type /StructElem - /S /Formula - /P 3227 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [232 233 234 235 236] - /Pg 4822 0 R ->> -endobj - -3229 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3230 0 R] ->> -endobj - -3230 0 obj -<< - /Type /StructElem - /S /Formula - /P 3229 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [231] - /Pg 4822 0 R ->> -endobj - -3231 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3232 0 R] ->> -endobj - -3232 0 obj -<< - /Type /StructElem - /S /Formula - /P 3231 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [226 227 228 229 230] - /Pg 4822 0 R ->> -endobj - -3233 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3234 0 R] ->> -endobj - -3234 0 obj -<< - /Type /StructElem - /S /Formula - /P 3233 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [225] - /Pg 4822 0 R ->> -endobj - -3235 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3236 0 R] ->> -endobj - -3236 0 obj -<< - /Type /StructElem - /S /Formula - /P 3235 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [224] - /Pg 4822 0 R ->> -endobj - -3237 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3238 0 R] ->> -endobj - -3238 0 obj -<< - /Type /StructElem - /S /Formula - /P 3237 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [214 215 216 217 218 219 220 221 222 223] - /Pg 4822 0 R ->> -endobj - -3239 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3240 0 R] ->> -endobj - -3240 0 obj -<< - /Type /StructElem - /S /Formula - /P 3239 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [213] - /Pg 4822 0 R ->> -endobj - -3241 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3242 0 R] ->> -endobj - -3242 0 obj -<< - /Type /StructElem - /S /Formula - /P 3241 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [211 212] - /Pg 4822 0 R ->> -endobj - -3243 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3244 0 R] ->> -endobj - -3244 0 obj -<< - /Type /StructElem - /S /Formula - /P 3243 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [210] - /Pg 4822 0 R ->> -endobj - -3245 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3246 0 R] ->> -endobj - -3246 0 obj -<< - /Type /StructElem - /S /Formula - /P 3245 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [207 208 209] - /Pg 4822 0 R ->> -endobj - -3247 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3248 0 R] ->> -endobj - -3248 0 obj -<< - /Type /StructElem - /S /Formula - /P 3247 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [206] - /Pg 4822 0 R ->> -endobj - -3249 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3250 0 R] ->> -endobj - -3250 0 obj -<< - /Type /StructElem - /S /Formula - /P 3249 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [205] - /Pg 4822 0 R ->> -endobj - -3251 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3252 0 R] ->> -endobj - -3252 0 obj -<< - /Type /StructElem - /S /Formula - /P 3251 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204] - /Pg 4822 0 R ->> -endobj - -3253 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3254 0 R] ->> -endobj - -3254 0 obj -<< - /Type /StructElem - /S /Formula - /P 3253 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [166] - /Pg 4822 0 R ->> -endobj - -3255 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3256 0 R] ->> -endobj - -3256 0 obj -<< - /Type /StructElem - /S /Formula - /P 3255 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [161 162 163 164 165] - /Pg 4822 0 R ->> -endobj - -3257 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3258 0 R] ->> -endobj - -3258 0 obj -<< - /Type /StructElem - /S /Formula - /P 3257 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [160] - /Pg 4822 0 R ->> -endobj - -3259 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3260 0 R] ->> -endobj - -3260 0 obj -<< - /Type /StructElem - /S /Formula - /P 3259 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [155 156 157 158 159] - /Pg 4822 0 R ->> -endobj - -3261 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3262 0 R] ->> -endobj - -3262 0 obj -<< - /Type /StructElem - /S /Formula - /P 3261 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [154] - /Pg 4822 0 R ->> -endobj - -3263 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3264 0 R] ->> -endobj - -3264 0 obj -<< - /Type /StructElem - /S /Formula - /P 3263 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [153] - /Pg 4822 0 R ->> -endobj - -3265 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3266 0 R] ->> -endobj - -3266 0 obj -<< - /Type /StructElem - /S /Formula - /P 3265 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [143 144 145 146 147 148 149 150 151 152] - /Pg 4822 0 R ->> -endobj - -3267 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3268 0 R] ->> -endobj - -3268 0 obj -<< - /Type /StructElem - /S /Formula - /P 3267 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [142] - /Pg 4822 0 R ->> -endobj - -3269 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3270 0 R] ->> -endobj - -3270 0 obj -<< - /Type /StructElem - /S /Formula - /P 3269 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [140 141] - /Pg 4822 0 R ->> -endobj - -3271 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3272 0 R] ->> -endobj - -3272 0 obj -<< - /Type /StructElem - /S /Formula - /P 3271 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [139] - /Pg 4822 0 R ->> -endobj - -3273 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3274 0 R] ->> -endobj - -3274 0 obj -<< - /Type /StructElem - /S /Formula - /P 3273 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [128 129 130 131 132 133 134 135 136 137 138] - /Pg 4822 0 R ->> -endobj - -3275 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3276 0 R] ->> -endobj - -3276 0 obj -<< - /Type /StructElem - /S /Formula - /P 3275 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [127] - /Pg 4822 0 R ->> -endobj - -3277 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3278 0 R] ->> -endobj - -3278 0 obj -<< - /Type /StructElem - /S /Formula - /P 3277 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [126] - /Pg 4822 0 R ->> -endobj - -3279 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3280 0 R] ->> -endobj - -3280 0 obj -<< - /Type /StructElem - /S /Formula - /P 3279 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [119 120 121 122 123 124 125] - /Pg 4822 0 R ->> -endobj - -3281 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3282 0 R] ->> -endobj - -3282 0 obj -<< - /Type /StructElem - /S /Formula - /P 3281 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [118] - /Pg 4822 0 R ->> -endobj - -3283 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3284 0 R] ->> -endobj - -3284 0 obj -<< - /Type /StructElem - /S /Formula - /P 3283 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [113 114 115 116 117] - /Pg 4822 0 R ->> -endobj - -3285 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3286 0 R] ->> -endobj - -3286 0 obj -<< - /Type /StructElem - /S /Formula - /P 3285 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [112] - /Pg 4822 0 R ->> -endobj - -3287 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3288 0 R] ->> -endobj - -3288 0 obj -<< - /Type /StructElem - /S /Formula - /P 3287 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [111] - /Pg 4822 0 R ->> -endobj - -3289 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3290 0 R] ->> -endobj - -3290 0 obj -<< - /Type /StructElem - /S /Formula - /P 3289 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [110] - /Pg 4822 0 R ->> -endobj - -3291 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3292 0 R] ->> -endobj - -3292 0 obj -<< - /Type /StructElem - /S /Formula - /P 3291 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [109] - /Pg 4822 0 R ->> -endobj - -3293 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3294 0 R] ->> -endobj - -3294 0 obj -<< - /Type /StructElem - /S /Formula - /P 3293 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [104 105 106 107 108] - /Pg 4822 0 R ->> -endobj - -3295 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3296 0 R] ->> -endobj - -3296 0 obj -<< - /Type /StructElem - /S /Formula - /P 3295 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [103] - /Pg 4822 0 R ->> -endobj - -3297 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3298 0 R] ->> -endobj - -3298 0 obj -<< - /Type /StructElem - /S /Formula - /P 3297 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [101 102] - /Pg 4822 0 R ->> -endobj - -3299 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3300 0 R] ->> -endobj - -3300 0 obj -<< - /Type /StructElem - /S /Formula - /P 3299 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [100] - /Pg 4822 0 R ->> -endobj - -3301 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3302 0 R] ->> -endobj - -3302 0 obj -<< - /Type /StructElem - /S /Formula - /P 3301 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [95 96 97 98 99] - /Pg 4822 0 R ->> -endobj - -3303 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3304 0 R] ->> -endobj - -3304 0 obj -<< - /Type /StructElem - /S /Formula - /P 3303 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [94] - /Pg 4822 0 R ->> -endobj - -3305 0 obj -<< - /Type /StructElem - /S /Div - /P 3222 0 R - /K [3306 0 R] ->> -endobj - -3306 0 obj -<< - /Type /StructElem - /S /Formula - /P 3305 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [93] - /Pg 4822 0 R ->> -endobj - -3307 0 obj -<< - /Type /StructElem - /S /P - /P 3221 0 R - /K [3312 0 R 83 3311 0 R 85 3310 0 R 87 3309 0 R 89 3308 0 R 92] - /Pg 4822 0 R ->> -endobj - -3308 0 obj -<< - /Type /StructElem - /S /Formula - /P 3307 0 R - /K [90 91] - /Pg 4822 0 R ->> -endobj - -3309 0 obj -<< - /Type /StructElem - /S /Formula - /P 3307 0 R - /K [88] - /Pg 4822 0 R ->> -endobj - -3310 0 obj -<< - /Type /StructElem - /S /Formula - /P 3307 0 R - /K [86] - /Pg 4822 0 R ->> -endobj - -3311 0 obj -<< - /Type /StructElem - /S /Formula - /P 3307 0 R - /K [84] - /Pg 4822 0 R ->> -endobj - -3312 0 obj -<< - /Type /StructElem - /S /Strong - /P 3307 0 R - /K [80 81 82] - /Pg 4822 0 R ->> -endobj - -3313 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [63 64 3317 0 R 66 3316 0 R 71 72 3315 0 R 74 3314 0 R 79] - /Pg 4822 0 R ->> -endobj - -3314 0 obj -<< - /Type /StructElem - /S /Formula - /P 3313 0 R - /K [75 76 77 78] - /Pg 4822 0 R ->> -endobj - -3315 0 obj -<< - /Type /StructElem - /S /Formula - /P 3313 0 R - /K [73] - /Pg 4822 0 R ->> -endobj - -3316 0 obj -<< - /Type /StructElem - /S /Formula - /P 3313 0 R - /K [67 68 69 70] - /Pg 4822 0 R ->> -endobj - -3317 0 obj -<< - /Type /StructElem - /S /Formula - /P 3313 0 R - /K [65] - /Pg 4822 0 R ->> -endobj - -3318 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [3331 0 R 3330 0 R 3328 0 R 3319 0 R] ->> -endobj - -3319 0 obj -<< - /Type /StructElem - /S /L - /P 3318 0 R - /A [<< - /O /List - /ListNumbering /Circle - >>] - /K [3324 0 R 3320 0 R] ->> -endobj - -3320 0 obj -<< - /Type /StructElem - /S /LI - /P 3319 0 R - /K [3323 0 R 3321 0 R] ->> -endobj - -3321 0 obj -<< - /Type /StructElem - /S /LBody - /P 3320 0 R - /K [3322 0 R 60 61 62] - /Pg 4822 0 R ->> -endobj - -3322 0 obj -<< - /Type /StructElem - /S /Formula - /P 3321 0 R - /K [50 51 52 53 54 55 56 57 58 59] - /Pg 4822 0 R ->> -endobj - -3323 0 obj -<< - /Type /StructElem - /S /Lbl - /P 3320 0 R - /K [49] - /Pg 4822 0 R ->> -endobj - -3324 0 obj -<< - /Type /StructElem - /S /LI - /P 3319 0 R - /K [3327 0 R 3325 0 R] ->> -endobj - -3325 0 obj -<< - /Type /StructElem - /S /LBody - /P 3324 0 R - /K [3326 0 R 48] - /Pg 4822 0 R ->> -endobj - -3326 0 obj -<< - /Type /StructElem - /S /Formula - /P 3325 0 R - /K [40 41 42 43 44 45 46 47] - /Pg 4822 0 R ->> -endobj - -3327 0 obj -<< - /Type /StructElem - /S /Lbl - /P 3324 0 R - /K [39] - /Pg 4822 0 R ->> -endobj - -3328 0 obj -<< - /Type /StructElem - /S /P - /P 3318 0 R - /K [32 3329 0 R 38] - /Pg 4822 0 R ->> -endobj - -3329 0 obj -<< - /Type /StructElem - /S /Formula - /P 3328 0 R - /K [33 34 35 36 37] - /Pg 4822 0 R ->> -endobj - -3330 0 obj -<< - /Type /StructElem - /S /Formula - /P 3318 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31] - /Pg 4822 0 R ->> -endobj - -3331 0 obj -<< - /Type /StructElem - /S /P - /P 3318 0 R - /K [3332 0 R 10] - /Pg 4822 0 R ->> -endobj - -3332 0 obj -<< - /Type /StructElem - /S /Strong - /P 3331 0 R - /K [7 8 9] - /Pg 4822 0 R ->> -endobj - -3333 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [3335 0 R 1 3334 0 R 3 4 5 6] - /Pg 4822 0 R ->> -endobj - -3334 0 obj -<< - /Type /StructElem - /S /Em - /P 3333 0 R - /K [2] - /Pg 4822 0 R ->> -endobj - -3335 0 obj -<< - /Type /StructElem - /S /Strong - /P 3333 0 R - /K [0] - /Pg 4822 0 R ->> -endobj - -3336 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [193 3339 0 R 195 196 197 3338 0 R 199 200 3337 0 R 202 203] - /Pg 4820 0 R ->> -endobj - -3337 0 obj -<< - /Type /StructElem - /S /Em - /P 3336 0 R - /K [201] - /Pg 4820 0 R ->> -endobj - -3338 0 obj -<< - /Type /StructElem - /S /Em - /P 3336 0 R - /K [198] - /Pg 4820 0 R ->> -endobj - -3339 0 obj -<< - /Type /StructElem - /S /Formula - /P 3336 0 R - /K [194] - /Pg 4820 0 R ->> -endobj - -3340 0 obj -<< - /Type /StructElem - /S /H3 - /P 103 0 R - /T (Isolation and Interception) - /K [191 192] - /Pg 4820 0 R ->> -endobj - -3341 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [131 3359 0 R 133 3358 0 R 135 3357 0 R 137 138 3356 0 R 140 3355 0 R 147 3354 0 R 149 3353 0 R 154 3352 0 R 156 3351 0 R 158 3350 0 R 160 3349 0 R 165 3348 0 R 172 3347 0 R 174 3346 0 R 176 3345 0 R 181 3344 0 R 183 3343 0 R 185 186 3342 0 R 188 189 190] - /Pg 4820 0 R ->> -endobj - -3342 0 obj -<< - /Type /StructElem - /S /Formula - /P 3341 0 R - /K [187] - /Pg 4820 0 R ->> -endobj - -3343 0 obj -<< - /Type /StructElem - /S /Formula - /P 3341 0 R - /K [184] - /Pg 4820 0 R ->> -endobj - -3344 0 obj -<< - /Type /StructElem - /S /Formula - /P 3341 0 R - /K [182] - /Pg 4820 0 R ->> -endobj - -3345 0 obj -<< - /Type /StructElem - /S /Formula - /P 3341 0 R - /K [177 178 179 180] - /Pg 4820 0 R ->> -endobj - -3346 0 obj -<< - /Type /StructElem - /S /Formula - /P 3341 0 R - /K [175] - /Pg 4820 0 R ->> -endobj - -3347 0 obj -<< - /Type /StructElem - /S /Formula - /P 3341 0 R - /K [173] - /Pg 4820 0 R ->> -endobj - -3348 0 obj -<< - /Type /StructElem - /S /Formula - /P 3341 0 R - /K [166 167 168 169 170 171] - /Pg 4820 0 R ->> -endobj - -3349 0 obj -<< - /Type /StructElem - /S /Formula - /P 3341 0 R - /K [161 162 163 164] - /Pg 4820 0 R ->> -endobj - -3350 0 obj -<< - /Type /StructElem - /S /Formula - /P 3341 0 R - /K [159] - /Pg 4820 0 R ->> -endobj - -3351 0 obj -<< - /Type /StructElem - /S /Formula - /P 3341 0 R - /K [157] - /Pg 4820 0 R ->> -endobj - -3352 0 obj -<< - /Type /StructElem - /S /Formula - /P 3341 0 R - /K [155] - /Pg 4820 0 R ->> -endobj - -3353 0 obj -<< - /Type /StructElem - /S /Formula - /P 3341 0 R - /K [150 151 152 153] - /Pg 4820 0 R ->> -endobj - -3354 0 obj -<< - /Type /StructElem - /S /Formula - /P 3341 0 R - /K [148] - /Pg 4820 0 R ->> -endobj - -3355 0 obj -<< - /Type /StructElem - /S /Formula - /P 3341 0 R - /K [141 142 143 144 145 146] - /Pg 4820 0 R ->> -endobj - -3356 0 obj -<< - /Type /StructElem - /S /Formula - /P 3341 0 R - /K [139] - /Pg 4820 0 R ->> -endobj - -3357 0 obj -<< - /Type /StructElem - /S /Formula - /P 3341 0 R - /K [136] - /Pg 4820 0 R ->> -endobj - -3358 0 obj -<< - /Type /StructElem - /S /Formula - /P 3341 0 R - /K [134] - /Pg 4820 0 R ->> -endobj - -3359 0 obj -<< - /Type /StructElem - /S /Formula - /P 3341 0 R - /K [132] - /Pg 4820 0 R ->> -endobj - -3360 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [120 3362 0 R 124 125 126 127 128 3361 0 R 130] - /Pg 4820 0 R ->> -endobj - -3361 0 obj -<< - /Type /StructElem - /S /Link - /P 3360 0 R - /K [129 << - /Type /OBJR - /Pg 4820 0 R - /Obj 4819 0 R - >>] - /Pg 4820 0 R ->> -endobj - -3362 0 obj -<< - /Type /StructElem - /S /Formula - /P 3360 0 R - /K [121 122 123] - /Pg 4820 0 R ->> -endobj - -3363 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [3365 0 R 3364 0 R] ->> -endobj - -3364 0 obj -<< - /Type /StructElem - /S /Formula - /P 3363 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119] - /Pg 4820 0 R ->> -endobj - -3365 0 obj -<< - /Type /StructElem - /S /P - /P 3363 0 R - /K [3368 0 R 75 3367 0 R 79 3366 0 R 86] - /Pg 4820 0 R ->> -endobj - -3366 0 obj -<< - /Type /StructElem - /S /Formula - /P 3365 0 R - /K [80 81 82 83 84 85] - /Pg 4820 0 R ->> -endobj - -3367 0 obj -<< - /Type /StructElem - /S /Formula - /P 3365 0 R - /K [76 77 78] - /Pg 4820 0 R ->> -endobj - -3368 0 obj -<< - /Type /StructElem - /S /Strong - /P 3365 0 R - /K [72 73 74] - /Pg 4820 0 R ->> -endobj - -3369 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [56 57 3373 0 R 59 3372 0 R 62 3371 0 R 67 3370 0 R 69 70 71] - /Pg 4820 0 R ->> -endobj - -3370 0 obj -<< - /Type /StructElem - /S /Formula - /P 3369 0 R - /K [68] - /Pg 4820 0 R ->> -endobj - -3371 0 obj -<< - /Type /StructElem - /S /Formula - /P 3369 0 R - /K [63 64 65 66] - /Pg 4820 0 R ->> -endobj - -3372 0 obj -<< - /Type /StructElem - /S /Formula - /P 3369 0 R - /K [60 61] - /Pg 4820 0 R ->> -endobj - -3373 0 obj -<< - /Type /StructElem - /S /Formula - /P 3369 0 R - /K [58] - /Pg 4820 0 R ->> -endobj - -3374 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [3377 0 R 3376 0 R 3375 0 R] ->> -endobj - -3375 0 obj -<< - /Type /StructElem - /S /P - /P 3374 0 R - /K [55] - /Pg 4820 0 R ->> -endobj - -3376 0 obj -<< - /Type /StructElem - /S /Formula - /P 3374 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [47 48 49 50 51 52 53 54] - /Pg 4820 0 R ->> -endobj - -3377 0 obj -<< - /Type /StructElem - /S /P - /P 3374 0 R - /K [3379 0 R 44 3378 0 R 46] - /Pg 4820 0 R ->> -endobj - -3378 0 obj -<< - /Type /StructElem - /S /Em - /P 3377 0 R - /K [45] - /Pg 4820 0 R ->> -endobj - -3379 0 obj -<< - /Type /StructElem - /S /Strong - /P 3377 0 R - /K [41 42 43] - /Pg 4820 0 R ->> -endobj - -3380 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [30 3382 0 R 35 3381 0 R 37 38 39 40] - /Pg 4820 0 R ->> -endobj - -3381 0 obj -<< - /Type /StructElem - /S /Formula - /P 3380 0 R - /K [36] - /Pg 4820 0 R ->> -endobj - -3382 0 obj -<< - /Type /StructElem - /S /Formula - /P 3380 0 R - /K [31 32 33 34] - /Pg 4820 0 R ->> -endobj - -3383 0 obj -<< - /Type /StructElem - /S /Formula - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29] - /Pg 4820 0 R ->> -endobj - -3384 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [265 266 << - /Type /MCR - /MCID 0 - /Pg 4820 0 R - >> << - /Type /MCR - /MCID 1 - /Pg 4820 0 R - >> << - /Type /MCR - /MCID 2 - /Pg 4820 0 R - >> << - /Type /MCR - /MCID 3 - /Pg 4820 0 R - >> << - /Type /MCR - /MCID 4 - /Pg 4820 0 R - >> 3387 0 R << - /Type /MCR - /MCID 6 - /Pg 4820 0 R - >> << - /Type /MCR - /MCID 7 - /Pg 4820 0 R - >> 3386 0 R << - /Type /MCR - /MCID 11 - /Pg 4820 0 R - >> 3385 0 R << - /Type /MCR - /MCID 13 - /Pg 4820 0 R - >>] - /Pg 4817 0 R ->> -endobj - -3385 0 obj -<< - /Type /StructElem - /S /Em - /P 3384 0 R - /K [12] - /Pg 4820 0 R ->> -endobj - -3386 0 obj -<< - /Type /StructElem - /S /Formula - /P 3384 0 R - /K [8 9 10] - /Pg 4820 0 R ->> -endobj - -3387 0 obj -<< - /Type /StructElem - /S /Formula - /P 3384 0 R - /K [5] - /Pg 4820 0 R ->> -endobj - -3388 0 obj -<< - /Type /StructElem - /S /H3 - /P 103 0 R - /T (Specification and Notification) - /K [263 264] - /Pg 4817 0 R ->> -endobj - -3389 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [243 3393 0 R 250 3392 0 R 253 254 3391 0 R 256 3390 0 R 259 260 261 262] - /Pg 4817 0 R ->> -endobj - -3390 0 obj -<< - /Type /StructElem - /S /Formula - /P 3389 0 R - /K [257 258] - /Pg 4817 0 R ->> -endobj - -3391 0 obj -<< - /Type /StructElem - /S /Link - /P 3389 0 R - /K [255 << - /Type /OBJR - /Pg 4817 0 R - /Obj 4816 0 R - >>] - /Pg 4817 0 R ->> -endobj - -3392 0 obj -<< - /Type /StructElem - /S /Formula - /P 3389 0 R - /K [251 252] - /Pg 4817 0 R ->> -endobj - -3393 0 obj -<< - /Type /StructElem - /S /Formula - /P 3389 0 R - /K [244 245 246 247 248 249] - /Pg 4817 0 R ->> -endobj - -3394 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [3457 0 R 3400 0 R 3395 0 R] ->> -endobj - -3395 0 obj -<< - /Type /StructElem - /S /P - /P 3394 0 R - /K [216 3399 0 R 221 3398 0 R 228 3397 0 R 235 3396 0 R 242] - /Pg 4817 0 R ->> -endobj - -3396 0 obj -<< - /Type /StructElem - /S /Formula - /P 3395 0 R - /K [236 237 238 239 240 241] - /Pg 4817 0 R ->> -endobj - -3397 0 obj -<< - /Type /StructElem - /S /Formula - /P 3395 0 R - /K [229 230 231 232 233 234] - /Pg 4817 0 R ->> -endobj - -3398 0 obj -<< - /Type /StructElem - /S /Formula - /P 3395 0 R - /K [222 223 224 225 226 227] - /Pg 4817 0 R ->> -endobj - -3399 0 obj -<< - /Type /StructElem - /S /Formula - /P 3395 0 R - /K [217 218 219 220] - /Pg 4817 0 R ->> -endobj - -3400 0 obj -<< - /Type /StructElem - /S /Div - /P 3394 0 R - /K [3455 0 R 3453 0 R 3451 0 R 3449 0 R 3447 0 R 3445 0 R 3443 0 R 3441 0 R 3439 0 R 3437 0 R 3435 0 R 3433 0 R 3431 0 R 3429 0 R 3427 0 R 3425 0 R 3423 0 R 3421 0 R 3419 0 R 3417 0 R 3415 0 R 3413 0 R 3411 0 R 3409 0 R 3407 0 R 3405 0 R 3403 0 R 3401 0 R] ->> -endobj - -3401 0 obj -<< - /Type /StructElem - /S /Div - /P 3400 0 R - /K [3402 0 R] ->> -endobj - -3402 0 obj -<< - /Type /StructElem - /S /Formula - /P 3401 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215] - /Pg 4817 0 R ->> -endobj - -3403 0 obj -<< - /Type /StructElem - /S /Div - /P 3400 0 R - /K [3404 0 R] ->> -endobj - -3404 0 obj -<< - /Type /StructElem - /S /Formula - /P 3403 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [198] - /Pg 4817 0 R ->> -endobj - -3405 0 obj -<< - /Type /StructElem - /S /Div - /P 3400 0 R - /K [3406 0 R] ->> -endobj - -3406 0 obj -<< - /Type /StructElem - /S /Formula - /P 3405 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [197] - /Pg 4817 0 R ->> -endobj - -3407 0 obj -<< - /Type /StructElem - /S /Div - /P 3400 0 R - /K [3408 0 R] ->> -endobj - -3408 0 obj -<< - /Type /StructElem - /S /Formula - /P 3407 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [196] - /Pg 4817 0 R ->> -endobj - -3409 0 obj -<< - /Type /StructElem - /S /Div - /P 3400 0 R - /K [3410 0 R] ->> -endobj - -3410 0 obj -<< - /Type /StructElem - /S /Formula - /P 3409 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [191 192 193 194 195] - /Pg 4817 0 R ->> -endobj - -3411 0 obj -<< - /Type /StructElem - /S /Div - /P 3400 0 R - /K [3412 0 R] ->> -endobj - -3412 0 obj -<< - /Type /StructElem - /S /Formula - /P 3411 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [190] - /Pg 4817 0 R ->> -endobj - -3413 0 obj -<< - /Type /StructElem - /S /Div - /P 3400 0 R - /K [3414 0 R] ->> -endobj - -3414 0 obj -<< - /Type /StructElem - /S /Formula - /P 3413 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [189] - /Pg 4817 0 R ->> -endobj - -3415 0 obj -<< - /Type /StructElem - /S /Div - /P 3400 0 R - /K [3416 0 R] ->> -endobj - -3416 0 obj -<< - /Type /StructElem - /S /Formula - /P 3415 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [182 183 184 185 186 187 188] - /Pg 4817 0 R ->> -endobj - -3417 0 obj -<< - /Type /StructElem - /S /Div - /P 3400 0 R - /K [3418 0 R] ->> -endobj - -3418 0 obj -<< - /Type /StructElem - /S /Formula - /P 3417 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [181] - /Pg 4817 0 R ->> -endobj - -3419 0 obj -<< - /Type /StructElem - /S /Div - /P 3400 0 R - /K [3420 0 R] ->> -endobj - -3420 0 obj -<< - /Type /StructElem - /S /Formula - /P 3419 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [180] - /Pg 4817 0 R ->> -endobj - -3421 0 obj -<< - /Type /StructElem - /S /Div - /P 3400 0 R - /K [3422 0 R] ->> -endobj - -3422 0 obj -<< - /Type /StructElem - /S /Formula - /P 3421 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [179] - /Pg 4817 0 R ->> -endobj - -3423 0 obj -<< - /Type /StructElem - /S /Div - /P 3400 0 R - /K [3424 0 R] ->> -endobj - -3424 0 obj -<< - /Type /StructElem - /S /Formula - /P 3423 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [171 172 173 174 175 176 177 178] - /Pg 4817 0 R ->> -endobj - -3425 0 obj -<< - /Type /StructElem - /S /Div - /P 3400 0 R - /K [3426 0 R] ->> -endobj - -3426 0 obj -<< - /Type /StructElem - /S /Formula - /P 3425 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [170] - /Pg 4817 0 R ->> -endobj - -3427 0 obj -<< - /Type /StructElem - /S /Div - /P 3400 0 R - /K [3428 0 R] ->> -endobj - -3428 0 obj -<< - /Type /StructElem - /S /Formula - /P 3427 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [169] - /Pg 4817 0 R ->> -endobj - -3429 0 obj -<< - /Type /StructElem - /S /Div - /P 3400 0 R - /K [3430 0 R] ->> -endobj - -3430 0 obj -<< - /Type /StructElem - /S /Formula - /P 3429 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [165 166 167 168] - /Pg 4817 0 R ->> -endobj - -3431 0 obj -<< - /Type /StructElem - /S /Div - /P 3400 0 R - /K [3432 0 R] ->> -endobj - -3432 0 obj -<< - /Type /StructElem - /S /Formula - /P 3431 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [164] - /Pg 4817 0 R ->> -endobj - -3433 0 obj -<< - /Type /StructElem - /S /Div - /P 3400 0 R - /K [3434 0 R] ->> -endobj - -3434 0 obj -<< - /Type /StructElem - /S /Formula - /P 3433 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [163] - /Pg 4817 0 R ->> -endobj - -3435 0 obj -<< - /Type /StructElem - /S /Div - /P 3400 0 R - /K [3436 0 R] ->> -endobj - -3436 0 obj -<< - /Type /StructElem - /S /Formula - /P 3435 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [162] - /Pg 4817 0 R ->> -endobj - -3437 0 obj -<< - /Type /StructElem - /S /Div - /P 3400 0 R - /K [3438 0 R] ->> -endobj - -3438 0 obj -<< - /Type /StructElem - /S /Formula - /P 3437 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [161] - /Pg 4817 0 R ->> -endobj - -3439 0 obj -<< - /Type /StructElem - /S /Div - /P 3400 0 R - /K [3440 0 R] ->> -endobj - -3440 0 obj -<< - /Type /StructElem - /S /Formula - /P 3439 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [160] - /Pg 4817 0 R ->> -endobj - -3441 0 obj -<< - /Type /StructElem - /S /Div - /P 3400 0 R - /K [3442 0 R] ->> -endobj - -3442 0 obj -<< - /Type /StructElem - /S /Formula - /P 3441 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [159] - /Pg 4817 0 R ->> -endobj - -3443 0 obj -<< - /Type /StructElem - /S /Div - /P 3400 0 R - /K [3444 0 R] ->> -endobj - -3444 0 obj -<< - /Type /StructElem - /S /Formula - /P 3443 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [157 158] - /Pg 4817 0 R ->> -endobj - -3445 0 obj -<< - /Type /StructElem - /S /Div - /P 3400 0 R - /K [3446 0 R] ->> -endobj - -3446 0 obj -<< - /Type /StructElem - /S /Formula - /P 3445 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [156] - /Pg 4817 0 R ->> -endobj - -3447 0 obj -<< - /Type /StructElem - /S /Div - /P 3400 0 R - /K [3448 0 R] ->> -endobj - -3448 0 obj -<< - /Type /StructElem - /S /Formula - /P 3447 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [155] - /Pg 4817 0 R ->> -endobj - -3449 0 obj -<< - /Type /StructElem - /S /Div - /P 3400 0 R - /K [3450 0 R] ->> -endobj - -3450 0 obj -<< - /Type /StructElem - /S /Formula - /P 3449 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [154] - /Pg 4817 0 R ->> -endobj - -3451 0 obj -<< - /Type /StructElem - /S /Div - /P 3400 0 R - /K [3452 0 R] ->> -endobj - -3452 0 obj -<< - /Type /StructElem - /S /Formula - /P 3451 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [149 150 151 152 153] - /Pg 4817 0 R ->> -endobj - -3453 0 obj -<< - /Type /StructElem - /S /Div - /P 3400 0 R - /K [3454 0 R] ->> -endobj - -3454 0 obj -<< - /Type /StructElem - /S /Formula - /P 3453 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [148] - /Pg 4817 0 R ->> -endobj - -3455 0 obj -<< - /Type /StructElem - /S /Div - /P 3400 0 R - /K [3456 0 R] ->> -endobj - -3456 0 obj -<< - /Type /StructElem - /S /Formula - /P 3455 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [147] - /Pg 4817 0 R ->> -endobj - -3457 0 obj -<< - /Type /StructElem - /S /P - /P 3394 0 R - /K [3461 0 R 140 3460 0 R 142 3459 0 R 144 3458 0 R 146] - /Pg 4817 0 R ->> -endobj - -3458 0 obj -<< - /Type /StructElem - /S /Formula - /P 3457 0 R - /K [145] - /Pg 4817 0 R ->> -endobj - -3459 0 obj -<< - /Type /StructElem - /S /Formula - /P 3457 0 R - /K [143] - /Pg 4817 0 R ->> -endobj - -3460 0 obj -<< - /Type /StructElem - /S /Formula - /P 3457 0 R - /K [141] - /Pg 4817 0 R ->> -endobj - -3461 0 obj -<< - /Type /StructElem - /S /Strong - /P 3457 0 R - /K [137 138 139] - /Pg 4817 0 R ->> -endobj - -3462 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [112 3467 0 R 114 3466 0 R 116 117 3465 0 R 120 121 122 3464 0 R 129 3463 0 R 136] - /Pg 4817 0 R ->> -endobj - -3463 0 obj -<< - /Type /StructElem - /S /Formula - /P 3462 0 R - /K [130 131 132 133 134 135] - /Pg 4817 0 R ->> -endobj - -3464 0 obj -<< - /Type /StructElem - /S /Formula - /P 3462 0 R - /K [123 124 125 126 127 128] - /Pg 4817 0 R ->> -endobj - -3465 0 obj -<< - /Type /StructElem - /S /Formula - /P 3462 0 R - /K [118 119] - /Pg 4817 0 R ->> -endobj - -3466 0 obj -<< - /Type /StructElem - /S /Formula - /P 3462 0 R - /K [115] - /Pg 4817 0 R ->> -endobj - -3467 0 obj -<< - /Type /StructElem - /S /Formula - /P 3462 0 R - /K [113] - /Pg 4817 0 R ->> -endobj - -3468 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [3494 0 R 3493 0 R 3489 0 R 3469 0 R] ->> -endobj - -3469 0 obj -<< - /Type /StructElem - /S /L - /P 3468 0 R - /A [<< - /O /List - /ListNumbering /Circle - >>] - /K [3484 0 R 3479 0 R 3474 0 R 3470 0 R] ->> -endobj - -3470 0 obj -<< - /Type /StructElem - /S /LI - /P 3469 0 R - /K [3473 0 R 3471 0 R] ->> -endobj - -3471 0 obj -<< - /Type /StructElem - /S /LBody - /P 3470 0 R - /K [3472 0 R 111] - /Pg 4817 0 R ->> -endobj - -3472 0 obj -<< - /Type /StructElem - /S /Formula - /P 3471 0 R - /K [105 106 107 108 109 110] - /Pg 4817 0 R ->> -endobj - -3473 0 obj -<< - /Type /StructElem - /S /Lbl - /P 3470 0 R - /K [104] - /Pg 4817 0 R ->> -endobj - -3474 0 obj -<< - /Type /StructElem - /S /LI - /P 3469 0 R - /K [3478 0 R 3475 0 R] ->> -endobj - -3475 0 obj -<< - /Type /StructElem - /S /LBody - /P 3474 0 R - /K [3477 0 R 96 3476 0 R 103] - /Pg 4817 0 R ->> -endobj - -3476 0 obj -<< - /Type /StructElem - /S /Formula - /P 3475 0 R - /K [97 98 99 100 101 102] - /Pg 4817 0 R ->> -endobj - -3477 0 obj -<< - /Type /StructElem - /S /Formula - /P 3475 0 R - /K [93 94 95] - /Pg 4817 0 R ->> -endobj - -3478 0 obj -<< - /Type /StructElem - /S /Lbl - /P 3474 0 R - /K [92] - /Pg 4817 0 R ->> -endobj - -3479 0 obj -<< - /Type /StructElem - /S /LI - /P 3469 0 R - /K [3483 0 R 3480 0 R] ->> -endobj - -3480 0 obj -<< - /Type /StructElem - /S /LBody - /P 3479 0 R - /K [3482 0 R 84 3481 0 R 91] - /Pg 4817 0 R ->> -endobj - -3481 0 obj -<< - /Type /StructElem - /S /Formula - /P 3480 0 R - /K [85 86 87 88 89 90] - /Pg 4817 0 R ->> -endobj - -3482 0 obj -<< - /Type /StructElem - /S /Formula - /P 3480 0 R - /K [78 79 80 81 82 83] - /Pg 4817 0 R ->> -endobj - -3483 0 obj -<< - /Type /StructElem - /S /Lbl - /P 3479 0 R - /K [77] - /Pg 4817 0 R ->> -endobj - -3484 0 obj -<< - /Type /StructElem - /S /LI - /P 3469 0 R - /K [3488 0 R 3485 0 R] ->> -endobj - -3485 0 obj -<< - /Type /StructElem - /S /LBody - /P 3484 0 R - /K [3487 0 R 69 3486 0 R 76] - /Pg 4817 0 R ->> -endobj - -3486 0 obj -<< - /Type /StructElem - /S /Formula - /P 3485 0 R - /K [70 71 72 73 74 75] - /Pg 4817 0 R ->> -endobj - -3487 0 obj -<< - /Type /StructElem - /S /Formula - /P 3485 0 R - /K [65 66 67 68] - /Pg 4817 0 R ->> -endobj - -3488 0 obj -<< - /Type /StructElem - /S /Lbl - /P 3484 0 R - /K [64] - /Pg 4817 0 R ->> -endobj - -3489 0 obj -<< - /Type /StructElem - /S /P - /P 3468 0 R - /K [46 3492 0 R 50 3491 0 R 59 3490 0 R 62 63] - /Pg 4817 0 R ->> -endobj - -3490 0 obj -<< - /Type /StructElem - /S /Formula - /P 3489 0 R - /K [60 61] - /Pg 4817 0 R ->> -endobj - -3491 0 obj -<< - /Type /StructElem - /S /Formula - /P 3489 0 R - /K [51 52 53 54 55 56 57 58] - /Pg 4817 0 R ->> -endobj - -3492 0 obj -<< - /Type /StructElem - /S /Formula - /P 3489 0 R - /K [47 48 49] - /Pg 4817 0 R ->> -endobj - -3493 0 obj -<< - /Type /StructElem - /S /Formula - /P 3468 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [35 36 37 38 39 40 41 42 43 44 45] - /Pg 4817 0 R ->> -endobj - -3494 0 obj -<< - /Type /StructElem - /S /P - /P 3468 0 R - /K [3497 0 R 25 3496 0 R 31 3495 0 R 33 34] - /Pg 4817 0 R ->> -endobj - -3495 0 obj -<< - /Type /StructElem - /S /Em - /P 3494 0 R - /K [32] - /Pg 4817 0 R ->> -endobj - -3496 0 obj -<< - /Type /StructElem - /S /Formula - /P 3494 0 R - /K [26 27 28 29 30] - /Pg 4817 0 R ->> -endobj - -3497 0 obj -<< - /Type /StructElem - /S /Strong - /P 3494 0 R - /K [22 23 24] - /Pg 4817 0 R ->> -endobj - -3498 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [13 14 3500 0 R 16 3499 0 R 18 19 20 21] - /Pg 4817 0 R ->> -endobj - -3499 0 obj -<< - /Type /StructElem - /S /Link - /P 3498 0 R - /K [17 << - /Type /OBJR - /Pg 4817 0 R - /Obj 4815 0 R - >>] - /Pg 4817 0 R ->> -endobj - -3500 0 obj -<< - /Type /StructElem - /S /Link - /P 3498 0 R - /K [15 << - /Type /OBJR - /Pg 4817 0 R - /Obj 4814 0 R - >>] - /Pg 4817 0 R ->> -endobj - -3501 0 obj -<< - /Type /StructElem - /S /H3 - /P 103 0 R - /T (Coeffect Context) - /K [11 12] - /Pg 4817 0 R ->> -endobj - -3502 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [3504 0 R 239 240 241 << - /Type /MCR - /MCID 0 - /Pg 4817 0 R - >> << - /Type /MCR - /MCID 1 - /Pg 4817 0 R - >> << - /Type /MCR - /MCID 2 - /Pg 4817 0 R - >> << - /Type /MCR - /MCID 3 - /Pg 4817 0 R - >> << - /Type /MCR - /MCID 4 - /Pg 4817 0 R - >> << - /Type /MCR - /MCID 5 - /Pg 4817 0 R - >> 3503 0 R << - /Type /MCR - /MCID 7 - /Pg 4817 0 R - >> << - /Type /MCR - /MCID 8 - /Pg 4817 0 R - >> << - /Type /MCR - /MCID 9 - /Pg 4817 0 R - >> << - /Type /MCR - /MCID 10 - /Pg 4817 0 R - >>] - /Pg 4812 0 R ->> -endobj - -3503 0 obj -<< - /Type /StructElem - /S /Em - /P 3502 0 R - /K [6] - /Pg 4817 0 R ->> -endobj - -3504 0 obj -<< - /Type /StructElem - /S /Em - /P 3502 0 R - /K [238] - /Pg 4812 0 R ->> -endobj - -3505 0 obj -<< - /Type /StructElem - /S /H2 - /P 103 0 R - /T (Reactive Coeffects) - /K [236 237] - /Pg 4812 0 R ->> -endobj - -3506 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [213 3512 0 R 215 3511 0 R 223 3510 0 R 225 3509 0 R 227 228 229 230 3508 0 R 232 233 3507 0 R 235] - /Pg 4812 0 R ->> -endobj - -3507 0 obj -<< - /Type /StructElem - /S /Link - /P 3506 0 R - /K [234 << - /Type /OBJR - /Pg 4812 0 R - /Obj 4811 0 R - >>] - /Pg 4812 0 R ->> -endobj - -3508 0 obj -<< - /Type /StructElem - /S /Link - /P 3506 0 R - /K [231 << - /Type /OBJR - /Pg 4812 0 R - /Obj 4810 0 R - >>] - /Pg 4812 0 R ->> -endobj - -3509 0 obj -<< - /Type /StructElem - /S /Formula - /P 3506 0 R - /K [226] - /Pg 4812 0 R ->> -endobj - -3510 0 obj -<< - /Type /StructElem - /S /Formula - /P 3506 0 R - /K [224] - /Pg 4812 0 R ->> -endobj - -3511 0 obj -<< - /Type /StructElem - /S /Formula - /P 3506 0 R - /K [216 217 218 219 220 221 222] - /Pg 4812 0 R ->> -endobj - -3512 0 obj -<< - /Type /StructElem - /S /Formula - /P 3506 0 R - /K [214] - /Pg 4812 0 R ->> -endobj - -3513 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [190 3520 0 R 192 3519 0 R 196 197 3518 0 R 199 3517 0 R 202 3516 0 R 204 205 206 207 3515 0 R 209 3514 0 R 211 212] - /Pg 4812 0 R ->> -endobj - -3514 0 obj -<< - /Type /StructElem - /S /Formula - /P 3513 0 R - /K [210] - /Pg 4812 0 R ->> -endobj - -3515 0 obj -<< - /Type /StructElem - /S /Formula - /P 3513 0 R - /K [208] - /Pg 4812 0 R ->> -endobj - -3516 0 obj -<< - /Type /StructElem - /S /Formula - /P 3513 0 R - /K [203] - /Pg 4812 0 R ->> -endobj - -3517 0 obj -<< - /Type /StructElem - /S /Formula - /P 3513 0 R - /K [200 201] - /Pg 4812 0 R ->> -endobj - -3518 0 obj -<< - /Type /StructElem - /S /Formula - /P 3513 0 R - /K [198] - /Pg 4812 0 R ->> -endobj - -3519 0 obj -<< - /Type /StructElem - /S /Formula - /P 3513 0 R - /K [193 194 195] - /Pg 4812 0 R ->> -endobj - -3520 0 obj -<< - /Type /StructElem - /S /Em - /P 3513 0 R - /K [191] - /Pg 4812 0 R ->> -endobj - -3521 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [3523 0 R 3522 0 R] ->> -endobj - -3522 0 obj -<< - /Type /StructElem - /S /Formula - /P 3521 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189] - /Pg 4812 0 R ->> -endobj - -3523 0 obj -<< - /Type /StructElem - /S /P - /P 3521 0 R - /K [3527 0 R 157 3526 0 R 159 3525 0 R 161 3524 0 R 169] - /Pg 4812 0 R ->> -endobj - -3524 0 obj -<< - /Type /StructElem - /S /Formula - /P 3523 0 R - /K [162 163 164 165 166 167 168] - /Pg 4812 0 R ->> -endobj - -3525 0 obj -<< - /Type /StructElem - /S /Formula - /P 3523 0 R - /K [160] - /Pg 4812 0 R ->> -endobj - -3526 0 obj -<< - /Type /StructElem - /S /Formula - /P 3523 0 R - /K [158] - /Pg 4812 0 R ->> -endobj - -3527 0 obj -<< - /Type /StructElem - /S /Strong - /P 3523 0 R - /K [154 155 156] - /Pg 4812 0 R ->> -endobj - -3528 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [151 3529 0 R 153] - /Pg 4812 0 R ->> -endobj - -3529 0 obj -<< - /Type /StructElem - /S /Formula - /P 3528 0 R - /K [152] - /Pg 4812 0 R ->> -endobj - -3530 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [3538 0 R 3537 0 R 3536 0 R 3535 0 R 3534 0 R 3533 0 R 3532 0 R 3531 0 R] ->> -endobj - -3531 0 obj -<< - /Type /StructElem - /S /Span - /P 3530 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [150] - /Pg 4812 0 R ->> -endobj - -3532 0 obj -<< - /Type /StructElem - /S /Formula - /P 3530 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149] - /Pg 4812 0 R ->> -endobj - -3533 0 obj -<< - /Type /StructElem - /S /Span - /P 3530 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [133] - /Pg 4812 0 R ->> -endobj - -3534 0 obj -<< - /Type /StructElem - /S /Formula - /P 3530 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [131 132] - /Pg 4812 0 R ->> -endobj - -3535 0 obj -<< - /Type /StructElem - /S /Span - /P 3530 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [130] - /Pg 4812 0 R ->> -endobj - -3536 0 obj -<< - /Type /StructElem - /S /Formula - /P 3530 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [129] - /Pg 4812 0 R ->> -endobj - -3537 0 obj -<< - /Type /StructElem - /S /Span - /P 3530 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [128] - /Pg 4812 0 R ->> -endobj - -3538 0 obj -<< - /Type /StructElem - /S /Strong - /P 3530 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [125 126 127] - /Pg 4812 0 R ->> -endobj - -3539 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [3563 0 R 3540 0 R] ->> -endobj - -3540 0 obj -<< - /Type /StructElem - /S /Div - /P 3539 0 R - /K [3561 0 R 3559 0 R 3557 0 R 3555 0 R 3553 0 R 3551 0 R 3549 0 R 3547 0 R 3545 0 R 3541 0 R] ->> -endobj - -3541 0 obj -<< - /Type /StructElem - /S /Div - /P 3540 0 R - /K [3544 0 R 3543 0 R 3542 0 R] ->> -endobj - -3542 0 obj -<< - /Type /StructElem - /S /Formula - /P 3541 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [118 119 120 121 122 123 124] - /Pg 4812 0 R ->> -endobj - -3543 0 obj -<< - /Type /StructElem - /S /Formula - /P 3541 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [106 107 108 109 110 111 112 113 114 115 116 117] - /Pg 4812 0 R ->> -endobj - -3544 0 obj -<< - /Type /StructElem - /S /Formula - /P 3541 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [94 95 96 97 98 99 100 101 102 103 104 105] - /Pg 4812 0 R ->> -endobj - -3545 0 obj -<< - /Type /StructElem - /S /Div - /P 3540 0 R - /K [3546 0 R] ->> -endobj - -3546 0 obj -<< - /Type /StructElem - /S /Formula - /P 3545 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [93] - /Pg 4812 0 R ->> -endobj - -3547 0 obj -<< - /Type /StructElem - /S /Div - /P 3540 0 R - /K [3548 0 R] ->> -endobj - -3548 0 obj -<< - /Type /StructElem - /S /Formula - /P 3547 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [92] - /Pg 4812 0 R ->> -endobj - -3549 0 obj -<< - /Type /StructElem - /S /Div - /P 3540 0 R - /K [3550 0 R] ->> -endobj - -3550 0 obj -<< - /Type /StructElem - /S /Formula - /P 3549 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [91] - /Pg 4812 0 R ->> -endobj - -3551 0 obj -<< - /Type /StructElem - /S /Div - /P 3540 0 R - /K [3552 0 R] ->> -endobj - -3552 0 obj -<< - /Type /StructElem - /S /Formula - /P 3551 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [88 89 90] - /Pg 4812 0 R ->> -endobj - -3553 0 obj -<< - /Type /StructElem - /S /Div - /P 3540 0 R - /K [3554 0 R] ->> -endobj - -3554 0 obj -<< - /Type /StructElem - /S /Formula - /P 3553 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [86 87] - /Pg 4812 0 R ->> -endobj - -3555 0 obj -<< - /Type /StructElem - /S /Div - /P 3540 0 R - /K [3556 0 R] ->> -endobj - -3556 0 obj -<< - /Type /StructElem - /S /Formula - /P 3555 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [85] - /Pg 4812 0 R ->> -endobj - -3557 0 obj -<< - /Type /StructElem - /S /Div - /P 3540 0 R - /K [3558 0 R] ->> -endobj - -3558 0 obj -<< - /Type /StructElem - /S /Formula - /P 3557 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [84] - /Pg 4812 0 R ->> -endobj - -3559 0 obj -<< - /Type /StructElem - /S /Div - /P 3540 0 R - /K [3560 0 R] ->> -endobj - -3560 0 obj -<< - /Type /StructElem - /S /Formula - /P 3559 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [83] - /Pg 4812 0 R ->> -endobj - -3561 0 obj -<< - /Type /StructElem - /S /Div - /P 3540 0 R - /K [3562 0 R] ->> -endobj - -3562 0 obj -<< - /Type /StructElem - /S /Formula - /P 3561 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [80 81 82] - /Pg 4812 0 R ->> -endobj - -3563 0 obj -<< - /Type /StructElem - /S /P - /P 3539 0 R - /K [3566 0 R 68 3565 0 R 75 3564 0 R 79] - /Pg 4812 0 R ->> -endobj - -3564 0 obj -<< - /Type /StructElem - /S /Formula - /P 3563 0 R - /K [76 77 78] - /Pg 4812 0 R ->> -endobj - -3565 0 obj -<< - /Type /StructElem - /S /Formula - /P 3563 0 R - /K [69 70 71 72 73 74] - /Pg 4812 0 R ->> -endobj - -3566 0 obj -<< - /Type /StructElem - /S /Strong - /P 3563 0 R - /K [65 66 67] - /Pg 4812 0 R ->> -endobj - -3567 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [60 3568 0 R 63 64] - /Pg 4812 0 R ->> -endobj - -3568 0 obj -<< - /Type /StructElem - /S /Formula - /P 3567 0 R - /K [61 62] - /Pg 4812 0 R ->> -endobj - -3569 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [3577 0 R 3576 0 R 3575 0 R 3574 0 R 3573 0 R 3572 0 R 3571 0 R 3570 0 R] ->> -endobj - -3570 0 obj -<< - /Type /StructElem - /S /Span - /P 3569 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [59] - /Pg 4812 0 R ->> -endobj - -3571 0 obj -<< - /Type /StructElem - /S /Formula - /P 3569 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58] - /Pg 4812 0 R ->> -endobj - -3572 0 obj -<< - /Type /StructElem - /S /Span - /P 3569 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [41] - /Pg 4812 0 R ->> -endobj - -3573 0 obj -<< - /Type /StructElem - /S /Formula - /P 3569 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [39 40] - /Pg 4812 0 R ->> -endobj - -3574 0 obj -<< - /Type /StructElem - /S /Span - /P 3569 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [38] - /Pg 4812 0 R ->> -endobj - -3575 0 obj -<< - /Type /StructElem - /S /Formula - /P 3569 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [37] - /Pg 4812 0 R ->> -endobj - -3576 0 obj -<< - /Type /StructElem - /S /Span - /P 3569 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [36] - /Pg 4812 0 R ->> -endobj - -3577 0 obj -<< - /Type /StructElem - /S /Strong - /P 3569 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [33 34 35] - /Pg 4812 0 R ->> -endobj - -3578 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [3594 0 R 3593 0 R 3592 0 R 3591 0 R 3590 0 R 3589 0 R 3588 0 R 3587 0 R 3586 0 R 3585 0 R 3584 0 R 23 3583 0 R 3582 0 R 3581 0 R 3580 0 R 3579 0 R] - /Pg 4812 0 R ->> -endobj - -3579 0 obj -<< - /Type /StructElem - /S /Formula - /P 3578 0 R - /K [30 31 32] - /Pg 4812 0 R ->> -endobj - -3580 0 obj -<< - /Type /StructElem - /S /Formula - /P 3578 0 R - /K [28 29] - /Pg 4812 0 R ->> -endobj - -3581 0 obj -<< - /Type /StructElem - /S /Formula - /P 3578 0 R - /K [26 27] - /Pg 4812 0 R ->> -endobj - -3582 0 obj -<< - /Type /StructElem - /S /Formula - /P 3578 0 R - /K [25] - /Pg 4812 0 R ->> -endobj - -3583 0 obj -<< - /Type /StructElem - /S /Formula - /P 3578 0 R - /K [24] - /Pg 4812 0 R ->> -endobj - -3584 0 obj -<< - /Type /StructElem - /S /Formula - /P 3578 0 R - /K [21 22] - /Pg 4812 0 R ->> -endobj - -3585 0 obj -<< - /Type /StructElem - /S /Formula - /P 3578 0 R - /K [19 20] - /Pg 4812 0 R ->> -endobj - -3586 0 obj -<< - /Type /StructElem - /S /Formula - /P 3578 0 R - /K [17 18] - /Pg 4812 0 R ->> -endobj - -3587 0 obj -<< - /Type /StructElem - /S /Formula - /P 3578 0 R - /K [15 16] - /Pg 4812 0 R ->> -endobj - -3588 0 obj -<< - /Type /StructElem - /S /Formula - /P 3578 0 R - /K [13 14] - /Pg 4812 0 R ->> -endobj - -3589 0 obj -<< - /Type /StructElem - /S /Formula - /P 3578 0 R - /K [11 12] - /Pg 4812 0 R ->> -endobj - -3590 0 obj -<< - /Type /StructElem - /S /Formula - /P 3578 0 R - /K [10] - /Pg 4812 0 R ->> -endobj - -3591 0 obj -<< - /Type /StructElem - /S /Formula - /P 3578 0 R - /K [6 7 8 9] - /Pg 4812 0 R ->> -endobj - -3592 0 obj -<< - /Type /StructElem - /S /Formula - /P 3578 0 R - /K [3 4 5] - /Pg 4812 0 R ->> -endobj - -3593 0 obj -<< - /Type /StructElem - /S /Formula - /P 3578 0 R - /K [1 2] - /Pg 4812 0 R ->> -endobj - -3594 0 obj -<< - /Type /StructElem - /S /Formula - /P 3578 0 R - /K [0] - /Pg 4812 0 R ->> -endobj - -3595 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [263 3597 0 R 266 3596 0 R 270 271] - /Pg 4808 0 R ->> -endobj - -3596 0 obj -<< - /Type /StructElem - /S /Formula - /P 3595 0 R - /K [267 268 269] - /Pg 4808 0 R ->> -endobj - -3597 0 obj -<< - /Type /StructElem - /S /Formula - /P 3595 0 R - /K [264 265] - /Pg 4808 0 R ->> -endobj - -3598 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [3629 0 R 3599 0 R] ->> -endobj - -3599 0 obj -<< - /Type /StructElem - /S /Div - /P 3598 0 R - /K [3627 0 R 3625 0 R 3623 0 R 3621 0 R 3619 0 R 3617 0 R 3615 0 R 3613 0 R 3611 0 R 3609 0 R 3607 0 R 3605 0 R 3603 0 R 3600 0 R] ->> -endobj - -3600 0 obj -<< - /Type /StructElem - /S /Div - /P 3599 0 R - /K [3602 0 R 3601 0 R] ->> -endobj - -3601 0 obj -<< - /Type /StructElem - /S /Formula - /P 3600 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [248 249 250 251 252 253 254 255 256 257 258 259 260 261 262] - /Pg 4808 0 R ->> -endobj - -3602 0 obj -<< - /Type /StructElem - /S /Formula - /P 3600 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [236 237 238 239 240 241 242 243 244 245 246 247] - /Pg 4808 0 R ->> -endobj - -3603 0 obj -<< - /Type /StructElem - /S /Div - /P 3599 0 R - /K [3604 0 R] ->> -endobj - -3604 0 obj -<< - /Type /StructElem - /S /Formula - /P 3603 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [235] - /Pg 4808 0 R ->> -endobj - -3605 0 obj -<< - /Type /StructElem - /S /Div - /P 3599 0 R - /K [3606 0 R] ->> -endobj - -3606 0 obj -<< - /Type /StructElem - /S /Formula - /P 3605 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [230 231 232 233 234] - /Pg 4808 0 R ->> -endobj - -3607 0 obj -<< - /Type /StructElem - /S /Div - /P 3599 0 R - /K [3608 0 R] ->> -endobj - -3608 0 obj -<< - /Type /StructElem - /S /Formula - /P 3607 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [229] - /Pg 4808 0 R ->> -endobj - -3609 0 obj -<< - /Type /StructElem - /S /Div - /P 3599 0 R - /K [3610 0 R] ->> -endobj - -3610 0 obj -<< - /Type /StructElem - /S /Formula - /P 3609 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [228] - /Pg 4808 0 R ->> -endobj - -3611 0 obj -<< - /Type /StructElem - /S /Div - /P 3599 0 R - /K [3612 0 R] ->> -endobj - -3612 0 obj -<< - /Type /StructElem - /S /Formula - /P 3611 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [227] - /Pg 4808 0 R ->> -endobj - -3613 0 obj -<< - /Type /StructElem - /S /Div - /P 3599 0 R - /K [3614 0 R] ->> -endobj - -3614 0 obj -<< - /Type /StructElem - /S /Formula - /P 3613 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [225 226] - /Pg 4808 0 R ->> -endobj - -3615 0 obj -<< - /Type /StructElem - /S /Div - /P 3599 0 R - /K [3616 0 R] ->> -endobj - -3616 0 obj -<< - /Type /StructElem - /S /Formula - /P 3615 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [222 223 224] - /Pg 4808 0 R ->> -endobj - -3617 0 obj -<< - /Type /StructElem - /S /Div - /P 3599 0 R - /K [3618 0 R] ->> -endobj - -3618 0 obj -<< - /Type /StructElem - /S /Formula - /P 3617 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [221] - /Pg 4808 0 R ->> -endobj - -3619 0 obj -<< - /Type /StructElem - /S /Div - /P 3599 0 R - /K [3620 0 R] ->> -endobj - -3620 0 obj -<< - /Type /StructElem - /S /Formula - /P 3619 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [219 220] - /Pg 4808 0 R ->> -endobj - -3621 0 obj -<< - /Type /StructElem - /S /Div - /P 3599 0 R - /K [3622 0 R] ->> -endobj - -3622 0 obj -<< - /Type /StructElem - /S /Formula - /P 3621 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [218] - /Pg 4808 0 R ->> -endobj - -3623 0 obj -<< - /Type /StructElem - /S /Div - /P 3599 0 R - /K [3624 0 R] ->> -endobj - -3624 0 obj -<< - /Type /StructElem - /S /Formula - /P 3623 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [216 217] - /Pg 4808 0 R ->> -endobj - -3625 0 obj -<< - /Type /StructElem - /S /Div - /P 3599 0 R - /K [3626 0 R] ->> -endobj - -3626 0 obj -<< - /Type /StructElem - /S /Formula - /P 3625 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [215] - /Pg 4808 0 R ->> -endobj - -3627 0 obj -<< - /Type /StructElem - /S /Div - /P 3599 0 R - /K [3628 0 R] ->> -endobj - -3628 0 obj -<< - /Type /StructElem - /S /Formula - /P 3627 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [213 214] - /Pg 4808 0 R ->> -endobj - -3629 0 obj -<< - /Type /StructElem - /S /P - /P 3598 0 R - /K [3631 0 R 209 3630 0 R 212] - /Pg 4808 0 R ->> -endobj - -3630 0 obj -<< - /Type /StructElem - /S /Formula - /P 3629 0 R - /K [210 211] - /Pg 4808 0 R ->> -endobj - -3631 0 obj -<< - /Type /StructElem - /S /Strong - /P 3629 0 R - /K [206 207 208] - /Pg 4808 0 R ->> -endobj - -3632 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [191 3636 0 R 194 3635 0 R 198 3634 0 R 201 3633 0 R 205] - /Pg 4808 0 R ->> -endobj - -3633 0 obj -<< - /Type /StructElem - /S /Formula - /P 3632 0 R - /K [202 203 204] - /Pg 4808 0 R ->> -endobj - -3634 0 obj -<< - /Type /StructElem - /S /Formula - /P 3632 0 R - /K [199 200] - /Pg 4808 0 R ->> -endobj - -3635 0 obj -<< - /Type /StructElem - /S /Formula - /P 3632 0 R - /K [195 196 197] - /Pg 4808 0 R ->> -endobj - -3636 0 obj -<< - /Type /StructElem - /S /Formula - /P 3632 0 R - /K [192 193] - /Pg 4808 0 R ->> -endobj - -3637 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [3645 0 R 3644 0 R 3643 0 R 3642 0 R 3641 0 R 3640 0 R 3639 0 R 3638 0 R] ->> -endobj - -3638 0 obj -<< - /Type /StructElem - /S /Formula - /P 3637 0 R - /K [189 190] - /Pg 4808 0 R ->> -endobj - -3639 0 obj -<< - /Type /StructElem - /S /Formula - /P 3637 0 R - /K [188] - /Pg 4808 0 R ->> -endobj - -3640 0 obj -<< - /Type /StructElem - /S /Formula - /P 3637 0 R - /K [187] - /Pg 4808 0 R ->> -endobj - -3641 0 obj -<< - /Type /StructElem - /S /Formula - /P 3637 0 R - /K [185 186] - /Pg 4808 0 R ->> -endobj - -3642 0 obj -<< - /Type /StructElem - /S /Formula - /P 3637 0 R - /K [183 184] - /Pg 4808 0 R ->> -endobj - -3643 0 obj -<< - /Type /StructElem - /S /Formula - /P 3637 0 R - /K [182] - /Pg 4808 0 R ->> -endobj - -3644 0 obj -<< - /Type /StructElem - /S /Formula - /P 3637 0 R - /K [179 180 181] - /Pg 4808 0 R ->> -endobj - -3645 0 obj -<< - /Type /StructElem - /S /Formula - /P 3637 0 R - /K [178] - /Pg 4808 0 R ->> -endobj - -3646 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [167 3647 0 R 174 175 176 177] - /Pg 4808 0 R ->> -endobj - -3647 0 obj -<< - /Type /StructElem - /S /Formula - /P 3646 0 R - /K [168 169 170 171 172 173] - /Pg 4808 0 R ->> -endobj - -3648 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [3662 0 R 3661 0 R 3658 0 R 3649 0 R] ->> -endobj - -3649 0 obj -<< - /Type /StructElem - /S /L - /P 3648 0 R - /A [<< - /O /List - /ListNumbering /Circle - >>] - /K [3654 0 R 3650 0 R] ->> -endobj - -3650 0 obj -<< - /Type /StructElem - /S /LI - /P 3649 0 R - /K [3653 0 R 3651 0 R] ->> -endobj - -3651 0 obj -<< - /Type /StructElem - /S /LBody - /P 3650 0 R - /K [3652 0 R 166] - /Pg 4808 0 R ->> -endobj - -3652 0 obj -<< - /Type /StructElem - /S /Formula - /P 3651 0 R - /K [161 162 163 164 165] - /Pg 4808 0 R ->> -endobj - -3653 0 obj -<< - /Type /StructElem - /S /Lbl - /P 3650 0 R - /K [160] - /Pg 4808 0 R ->> -endobj - -3654 0 obj -<< - /Type /StructElem - /S /LI - /P 3649 0 R - /K [3657 0 R 3655 0 R] ->> -endobj - -3655 0 obj -<< - /Type /StructElem - /S /LBody - /P 3654 0 R - /K [3656 0 R 159] - /Pg 4808 0 R ->> -endobj - -3656 0 obj -<< - /Type /StructElem - /S /Formula - /P 3655 0 R - /K [156 157 158] - /Pg 4808 0 R ->> -endobj - -3657 0 obj -<< - /Type /StructElem - /S /Lbl - /P 3654 0 R - /K [155] - /Pg 4808 0 R ->> -endobj - -3658 0 obj -<< - /Type /StructElem - /S /P - /P 3648 0 R - /K [143 3660 0 R 148 3659 0 R 154] - /Pg 4808 0 R ->> -endobj - -3659 0 obj -<< - /Type /StructElem - /S /Formula - /P 3658 0 R - /K [149 150 151 152 153] - /Pg 4808 0 R ->> -endobj - -3660 0 obj -<< - /Type /StructElem - /S /Formula - /P 3658 0 R - /K [144 145 146 147] - /Pg 4808 0 R ->> -endobj - -3661 0 obj -<< - /Type /StructElem - /S /Formula - /P 3648 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142] - /Pg 4808 0 R ->> -endobj - -3662 0 obj -<< - /Type /StructElem - /S /P - /P 3648 0 R - /K [3665 0 R 76 3664 0 R 79 3663 0 R 83] - /Pg 4808 0 R ->> -endobj - -3663 0 obj -<< - /Type /StructElem - /S /Formula - /P 3662 0 R - /K [80 81 82] - /Pg 4808 0 R ->> -endobj - -3664 0 obj -<< - /Type /StructElem - /S /Formula - /P 3662 0 R - /K [77 78] - /Pg 4808 0 R ->> -endobj - -3665 0 obj -<< - /Type /StructElem - /S /Strong - /P 3662 0 R - /K [73 74 75] - /Pg 4808 0 R ->> -endobj - -3666 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [60 61 62 3669 0 R 65 3668 0 R 68 3667 0 R 72] - /Pg 4808 0 R ->> -endobj - -3667 0 obj -<< - /Type /StructElem - /S /Formula - /P 3666 0 R - /K [69 70 71] - /Pg 4808 0 R ->> -endobj - -3668 0 obj -<< - /Type /StructElem - /S /Formula - /P 3666 0 R - /K [66 67] - /Pg 4808 0 R ->> -endobj - -3669 0 obj -<< - /Type /StructElem - /S /Formula - /P 3666 0 R - /K [63 64] - /Pg 4808 0 R ->> -endobj - -3670 0 obj -<< - /Type /StructElem - /S /L - /P 103 0 R - /A [<< - /O /List - /ListNumbering /Decimal - >>] - /K [3677 0 R 3671 0 R] ->> -endobj - -3671 0 obj -<< - /Type /StructElem - /S /LI - /P 3670 0 R - /K [3676 0 R 3672 0 R] ->> -endobj - -3672 0 obj -<< - /Type /StructElem - /S /LBody - /P 3671 0 R - /K [34 3675 0 R 37 38 3674 0 R 52 3673 0 R 59] - /Pg 4808 0 R ->> -endobj - -3673 0 obj -<< - /Type /StructElem - /S /Formula - /P 3672 0 R - /K [53 54 55 56 57 58] - /Pg 4808 0 R ->> -endobj - -3674 0 obj -<< - /Type /StructElem - /S /Formula - /P 3672 0 R - /K [39 40 41 42 43 44 45 46 47 48 49 50 51] - /Pg 4808 0 R ->> -endobj - -3675 0 obj -<< - /Type /StructElem - /S /Formula - /P 3672 0 R - /K [35 36] - /Pg 4808 0 R ->> -endobj - -3676 0 obj -<< - /Type /StructElem - /S /Lbl - /P 3671 0 R - /K [33] - /Pg 4808 0 R ->> -endobj - -3677 0 obj -<< - /Type /StructElem - /S /LI - /P 3670 0 R - /K [3682 0 R 3678 0 R] ->> -endobj - -3678 0 obj -<< - /Type /StructElem - /S /LBody - /P 3677 0 R - /K [14 3681 0 R 16 17 3680 0 R 27 3679 0 R 32] - /Pg 4808 0 R ->> -endobj - -3679 0 obj -<< - /Type /StructElem - /S /Formula - /P 3678 0 R - /K [28 29 30 31] - /Pg 4808 0 R ->> -endobj - -3680 0 obj -<< - /Type /StructElem - /S /Formula - /P 3678 0 R - /K [18 19 20 21 22 23 24 25 26] - /Pg 4808 0 R ->> -endobj - -3681 0 obj -<< - /Type /StructElem - /S /Formula - /P 3678 0 R - /K [15] - /Pg 4808 0 R ->> -endobj - -3682 0 obj -<< - /Type /StructElem - /S /Lbl - /P 3677 0 R - /K [13] - /Pg 4808 0 R ->> -endobj - -3683 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [2 3686 0 R 4 3685 0 R 6 7 8 3684 0 R 10 11 12] - /Pg 4808 0 R ->> -endobj - -3684 0 obj -<< - /Type /StructElem - /S /Formula - /P 3683 0 R - /K [9] - /Pg 4808 0 R ->> -endobj - -3685 0 obj -<< - /Type /StructElem - /S /Formula - /P 3683 0 R - /K [5] - /Pg 4808 0 R ->> -endobj - -3686 0 obj -<< - /Type /StructElem - /S /Formula - /P 3683 0 R - /K [3] - /Pg 4808 0 R ->> -endobj - -3687 0 obj -<< - /Type /StructElem - /S /H3 - /P 103 0 R - /T (Revertible Effect Functions) - /K [0 1] - /Pg 4808 0 R ->> -endobj - -3688 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [3704 0 R 3703 0 R 3702 0 R 3701 0 R 3700 0 R 3699 0 R 3698 0 R 3697 0 R 3696 0 R 3695 0 R 3694 0 R 3693 0 R 3692 0 R 3691 0 R 3690 0 R 3689 0 R] ->> -endobj - -3689 0 obj -<< - /Type /StructElem - /S /Formula - /P 3688 0 R - /K [342 343] - /Pg 4806 0 R ->> -endobj - -3690 0 obj -<< - /Type /StructElem - /S /Formula - /P 3688 0 R - /K [340 341] - /Pg 4806 0 R ->> -endobj - -3691 0 obj -<< - /Type /StructElem - /S /Formula - /P 3688 0 R - /K [338 339] - /Pg 4806 0 R ->> -endobj - -3692 0 obj -<< - /Type /StructElem - /S /Formula - /P 3688 0 R - /K [336 337] - /Pg 4806 0 R ->> -endobj - -3693 0 obj -<< - /Type /StructElem - /S /Formula - /P 3688 0 R - /K [335] - /Pg 4806 0 R ->> -endobj - -3694 0 obj -<< - /Type /StructElem - /S /Formula - /P 3688 0 R - /K [334] - /Pg 4806 0 R ->> -endobj - -3695 0 obj -<< - /Type /StructElem - /S /Formula - /P 3688 0 R - /K [333] - /Pg 4806 0 R ->> -endobj - -3696 0 obj -<< - /Type /StructElem - /S /Formula - /P 3688 0 R - /K [332] - /Pg 4806 0 R ->> -endobj - -3697 0 obj -<< - /Type /StructElem - /S /Formula - /P 3688 0 R - /K [331] - /Pg 4806 0 R ->> -endobj - -3698 0 obj -<< - /Type /StructElem - /S /Formula - /P 3688 0 R - /K [330] - /Pg 4806 0 R ->> -endobj - -3699 0 obj -<< - /Type /StructElem - /S /Formula - /P 3688 0 R - /K [329] - /Pg 4806 0 R ->> -endobj - -3700 0 obj -<< - /Type /StructElem - /S /Formula - /P 3688 0 R - /K [328] - /Pg 4806 0 R ->> -endobj - -3701 0 obj -<< - /Type /StructElem - /S /Formula - /P 3688 0 R - /K [325 326 327] - /Pg 4806 0 R ->> -endobj - -3702 0 obj -<< - /Type /StructElem - /S /Formula - /P 3688 0 R - /K [322 323 324] - /Pg 4806 0 R ->> -endobj - -3703 0 obj -<< - /Type /StructElem - /S /Formula - /P 3688 0 R - /K [320 321] - /Pg 4806 0 R ->> -endobj - -3704 0 obj -<< - /Type /StructElem - /S /Formula - /P 3688 0 R - /K [318 319] - /Pg 4806 0 R ->> -endobj - -3705 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [287 3712 0 R 289 3711 0 R 291 3710 0 R 293 294 3709 0 R 296 3708 0 R 298 299 3707 0 R 313 314 3706 0 R 317] - /Pg 4806 0 R ->> -endobj - -3706 0 obj -<< - /Type /StructElem - /S /Formula - /P 3705 0 R - /K [315 316] - /Pg 4806 0 R ->> -endobj - -3707 0 obj -<< - /Type /StructElem - /S /Formula - /P 3705 0 R - /K [300 301 302 303 304 305 306 307 308 309 310 311 312] - /Pg 4806 0 R ->> -endobj - -3708 0 obj -<< - /Type /StructElem - /S /Formula - /P 3705 0 R - /K [297] - /Pg 4806 0 R ->> -endobj - -3709 0 obj -<< - /Type /StructElem - /S /Formula - /P 3705 0 R - /K [295] - /Pg 4806 0 R ->> -endobj - -3710 0 obj -<< - /Type /StructElem - /S /Formula - /P 3705 0 R - /K [292] - /Pg 4806 0 R ->> -endobj - -3711 0 obj -<< - /Type /StructElem - /S /Formula - /P 3705 0 R - /K [290] - /Pg 4806 0 R ->> -endobj - -3712 0 obj -<< - /Type /StructElem - /S /Formula - /P 3705 0 R - /K [288] - /Pg 4806 0 R ->> -endobj - -3713 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [3735 0 R 3714 0 R] ->> -endobj - -3714 0 obj -<< - /Type /StructElem - /S /Div - /P 3713 0 R - /K [3733 0 R 3731 0 R 3729 0 R 3727 0 R 3725 0 R 3723 0 R 3721 0 R 3719 0 R 3717 0 R 3715 0 R] ->> -endobj - -3715 0 obj -<< - /Type /StructElem - /S /Div - /P 3714 0 R - /K [3716 0 R] ->> -endobj - -3716 0 obj -<< - /Type /StructElem - /S /Formula - /P 3715 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [278 279 280 281 282 283 284 285 286] - /Pg 4806 0 R ->> -endobj - -3717 0 obj -<< - /Type /StructElem - /S /Div - /P 3714 0 R - /K [3718 0 R] ->> -endobj - -3718 0 obj -<< - /Type /StructElem - /S /Formula - /P 3717 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [277] - /Pg 4806 0 R ->> -endobj - -3719 0 obj -<< - /Type /StructElem - /S /Div - /P 3714 0 R - /K [3720 0 R] ->> -endobj - -3720 0 obj -<< - /Type /StructElem - /S /Formula - /P 3719 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [272 273 274 275 276] - /Pg 4806 0 R ->> -endobj - -3721 0 obj -<< - /Type /StructElem - /S /Div - /P 3714 0 R - /K [3722 0 R] ->> -endobj - -3722 0 obj -<< - /Type /StructElem - /S /Formula - /P 3721 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [271] - /Pg 4806 0 R ->> -endobj - -3723 0 obj -<< - /Type /StructElem - /S /Div - /P 3714 0 R - /K [3724 0 R] ->> -endobj - -3724 0 obj -<< - /Type /StructElem - /S /Formula - /P 3723 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [269 270] - /Pg 4806 0 R ->> -endobj - -3725 0 obj -<< - /Type /StructElem - /S /Div - /P 3714 0 R - /K [3726 0 R] ->> -endobj - -3726 0 obj -<< - /Type /StructElem - /S /Formula - /P 3725 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [267 268] - /Pg 4806 0 R ->> -endobj - -3727 0 obj -<< - /Type /StructElem - /S /Div - /P 3714 0 R - /K [3728 0 R] ->> -endobj - -3728 0 obj -<< - /Type /StructElem - /S /Formula - /P 3727 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [266] - /Pg 4806 0 R ->> -endobj - -3729 0 obj -<< - /Type /StructElem - /S /Div - /P 3714 0 R - /K [3730 0 R] ->> -endobj - -3730 0 obj -<< - /Type /StructElem - /S /Formula - /P 3729 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [264 265] - /Pg 4806 0 R ->> -endobj - -3731 0 obj -<< - /Type /StructElem - /S /Div - /P 3714 0 R - /K [3732 0 R] ->> -endobj - -3732 0 obj -<< - /Type /StructElem - /S /Formula - /P 3731 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [263] - /Pg 4806 0 R ->> -endobj - -3733 0 obj -<< - /Type /StructElem - /S /Div - /P 3714 0 R - /K [3734 0 R] ->> -endobj - -3734 0 obj -<< - /Type /StructElem - /S /Formula - /P 3733 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [261 262] - /Pg 4806 0 R ->> -endobj - -3735 0 obj -<< - /Type /StructElem - /S /P - /P 3713 0 R - /K [3738 0 R 254 3737 0 R 257 3736 0 R 260] - /Pg 4806 0 R ->> -endobj - -3736 0 obj -<< - /Type /StructElem - /S /Formula - /P 3735 0 R - /K [258 259] - /Pg 4806 0 R ->> -endobj - -3737 0 obj -<< - /Type /StructElem - /S /Formula - /P 3735 0 R - /K [255 256] - /Pg 4806 0 R ->> -endobj - -3738 0 obj -<< - /Type /StructElem - /S /Strong - /P 3735 0 R - /K [251 252 253] - /Pg 4806 0 R ->> -endobj - -3739 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [241 3742 0 R 244 3741 0 R 246 247 3740 0 R 250] - /Pg 4806 0 R ->> -endobj - -3740 0 obj -<< - /Type /StructElem - /S /Formula - /P 3739 0 R - /K [248 249] - /Pg 4806 0 R ->> -endobj - -3741 0 obj -<< - /Type /StructElem - /S /Formula - /P 3739 0 R - /K [245] - /Pg 4806 0 R ->> -endobj - -3742 0 obj -<< - /Type /StructElem - /S /Formula - /P 3739 0 R - /K [242 243] - /Pg 4806 0 R ->> -endobj - -3743 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [3745 0 R 3744 0 R] ->> -endobj - -3744 0 obj -<< - /Type /StructElem - /S /Formula - /P 3743 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240] - /Pg 4806 0 R ->> -endobj - -3745 0 obj -<< - /Type /StructElem - /S /P - /P 3743 0 R - /K [3749 0 R 208 3748 0 R 210 3747 0 R 212 3746 0 R 220] - /Pg 4806 0 R ->> -endobj - -3746 0 obj -<< - /Type /StructElem - /S /Formula - /P 3745 0 R - /K [213 214 215 216 217 218 219] - /Pg 4806 0 R ->> -endobj - -3747 0 obj -<< - /Type /StructElem - /S /Formula - /P 3745 0 R - /K [211] - /Pg 4806 0 R ->> -endobj - -3748 0 obj -<< - /Type /StructElem - /S /Formula - /P 3745 0 R - /K [209] - /Pg 4806 0 R ->> -endobj - -3749 0 obj -<< - /Type /StructElem - /S /Strong - /P 3745 0 R - /K [205 206 207] - /Pg 4806 0 R ->> -endobj - -3750 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [3759 0 R 3758 0 R 3757 0 R 3756 0 R 3755 0 R 3754 0 R 3753 0 R 3752 0 R 3751 0 R] ->> -endobj - -3751 0 obj -<< - /Type /StructElem - /S /Formula - /P 3750 0 R - /K [203 204] - /Pg 4806 0 R ->> -endobj - -3752 0 obj -<< - /Type /StructElem - /S /Formula - /P 3750 0 R - /K [201 202] - /Pg 4806 0 R ->> -endobj - -3753 0 obj -<< - /Type /StructElem - /S /Formula - /P 3750 0 R - /K [200] - /Pg 4806 0 R ->> -endobj - -3754 0 obj -<< - /Type /StructElem - /S /Formula - /P 3750 0 R - /K [199] - /Pg 4806 0 R ->> -endobj - -3755 0 obj -<< - /Type /StructElem - /S /Formula - /P 3750 0 R - /K [198] - /Pg 4806 0 R ->> -endobj - -3756 0 obj -<< - /Type /StructElem - /S /Formula - /P 3750 0 R - /K [196 197] - /Pg 4806 0 R ->> -endobj - -3757 0 obj -<< - /Type /StructElem - /S /Formula - /P 3750 0 R - /K [194 195] - /Pg 4806 0 R ->> -endobj - -3758 0 obj -<< - /Type /StructElem - /S /Formula - /P 3750 0 R - /K [192 193] - /Pg 4806 0 R ->> -endobj - -3759 0 obj -<< - /Type /StructElem - /S /Formula - /P 3750 0 R - /K [191] - /Pg 4806 0 R ->> -endobj - -3760 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [3764 0 R 3763 0 R 3762 0 R 3761 0 R] ->> -endobj - -3761 0 obj -<< - /Type /StructElem - /S /Span - /P 3760 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [190] - /Pg 4806 0 R ->> -endobj - -3762 0 obj -<< - /Type /StructElem - /S /Formula - /P 3760 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189] - /Pg 4806 0 R ->> -endobj - -3763 0 obj -<< - /Type /StructElem - /S /Span - /P 3760 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [170] - /Pg 4806 0 R ->> -endobj - -3764 0 obj -<< - /Type /StructElem - /S /Strong - /P 3760 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [167 168 169] - /Pg 4806 0 R ->> -endobj - -3765 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [78 3781 0 R 83 3780 0 R 85 86 3779 0 R 89 3778 0 R 95 3777 0 R 101 3776 0 R 103 3775 0 R 105 3774 0 R 107 3773 0 R 113 3772 0 R 116 117 3771 0 R 140 3770 0 R 143 144 3769 0 R 155 3768 0 R 157 3767 0 R 163 3766 0 R 166] - /Pg 4806 0 R ->> -endobj - -3766 0 obj -<< - /Type /StructElem - /S /Formula - /P 3765 0 R - /K [164 165] - /Pg 4806 0 R ->> -endobj - -3767 0 obj -<< - /Type /StructElem - /S /Formula - /P 3765 0 R - /K [158 159 160 161 162] - /Pg 4806 0 R ->> -endobj - -3768 0 obj -<< - /Type /StructElem - /S /Link - /P 3765 0 R - /K [156 << - /Type /OBJR - /Pg 4806 0 R - /Obj 4805 0 R - >>] - /Pg 4806 0 R ->> -endobj - -3769 0 obj -<< - /Type /StructElem - /S /Formula - /P 3765 0 R - /K [145 146 147 148 149 150 151 152 153 154] - /Pg 4806 0 R ->> -endobj - -3770 0 obj -<< - /Type /StructElem - /S /Formula - /P 3765 0 R - /K [141 142] - /Pg 4806 0 R ->> -endobj - -3771 0 obj -<< - /Type /StructElem - /S /Formula - /P 3765 0 R - /K [118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139] - /Pg 4806 0 R ->> -endobj - -3772 0 obj -<< - /Type /StructElem - /S /Formula - /P 3765 0 R - /K [114 115] - /Pg 4806 0 R ->> -endobj - -3773 0 obj -<< - /Type /StructElem - /S /Formula - /P 3765 0 R - /K [108 109 110 111 112] - /Pg 4806 0 R ->> -endobj - -3774 0 obj -<< - /Type /StructElem - /S /Formula - /P 3765 0 R - /K [106] - /Pg 4806 0 R ->> -endobj - -3775 0 obj -<< - /Type /StructElem - /S /Formula - /P 3765 0 R - /K [104] - /Pg 4806 0 R ->> -endobj - -3776 0 obj -<< - /Type /StructElem - /S /Formula - /P 3765 0 R - /K [102] - /Pg 4806 0 R ->> -endobj - -3777 0 obj -<< - /Type /StructElem - /S /Formula - /P 3765 0 R - /K [96 97 98 99 100] - /Pg 4806 0 R ->> -endobj - -3778 0 obj -<< - /Type /StructElem - /S /Formula - /P 3765 0 R - /K [90 91 92 93 94] - /Pg 4806 0 R ->> -endobj - -3779 0 obj -<< - /Type /StructElem - /S /Formula - /P 3765 0 R - /K [87 88] - /Pg 4806 0 R ->> -endobj - -3780 0 obj -<< - /Type /StructElem - /S /Formula - /P 3765 0 R - /K [84] - /Pg 4806 0 R ->> -endobj - -3781 0 obj -<< - /Type /StructElem - /S /Formula - /P 3765 0 R - /K [79 80 81 82] - /Pg 4806 0 R ->> -endobj - -3782 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [3812 0 R 3783 0 R] ->> -endobj - -3783 0 obj -<< - /Type /StructElem - /S /Div - /P 3782 0 R - /K [3810 0 R 3808 0 R 3806 0 R 3804 0 R 3802 0 R 3800 0 R 3798 0 R 3796 0 R 3794 0 R 3792 0 R 3790 0 R 3788 0 R 3786 0 R 3784 0 R] ->> -endobj - -3784 0 obj -<< - /Type /StructElem - /S /Div - /P 3783 0 R - /K [3785 0 R] ->> -endobj - -3785 0 obj -<< - /Type /StructElem - /S /Formula - /P 3784 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [66 67 68 69 70 71 72 73 74 75 76 77] - /Pg 4806 0 R ->> -endobj - -3786 0 obj -<< - /Type /StructElem - /S /Div - /P 3783 0 R - /K [3787 0 R] ->> -endobj - -3787 0 obj -<< - /Type /StructElem - /S /Formula - /P 3786 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [65] - /Pg 4806 0 R ->> -endobj - -3788 0 obj -<< - /Type /StructElem - /S /Div - /P 3783 0 R - /K [3789 0 R] ->> -endobj - -3789 0 obj -<< - /Type /StructElem - /S /Formula - /P 3788 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [60 61 62 63 64] - /Pg 4806 0 R ->> -endobj - -3790 0 obj -<< - /Type /StructElem - /S /Div - /P 3783 0 R - /K [3791 0 R] ->> -endobj - -3791 0 obj -<< - /Type /StructElem - /S /Formula - /P 3790 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [59] - /Pg 4806 0 R ->> -endobj - -3792 0 obj -<< - /Type /StructElem - /S /Div - /P 3783 0 R - /K [3793 0 R] ->> -endobj - -3793 0 obj -<< - /Type /StructElem - /S /Formula - /P 3792 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [58] - /Pg 4806 0 R ->> -endobj - -3794 0 obj -<< - /Type /StructElem - /S /Div - /P 3783 0 R - /K [3795 0 R] ->> -endobj - -3795 0 obj -<< - /Type /StructElem - /S /Formula - /P 3794 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [57] - /Pg 4806 0 R ->> -endobj - -3796 0 obj -<< - /Type /StructElem - /S /Div - /P 3783 0 R - /K [3797 0 R] ->> -endobj - -3797 0 obj -<< - /Type /StructElem - /S /Formula - /P 3796 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [55 56] - /Pg 4806 0 R ->> -endobj - -3798 0 obj -<< - /Type /StructElem - /S /Div - /P 3783 0 R - /K [3799 0 R] ->> -endobj - -3799 0 obj -<< - /Type /StructElem - /S /Formula - /P 3798 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [53 54] - /Pg 4806 0 R ->> -endobj - -3800 0 obj -<< - /Type /StructElem - /S /Div - /P 3783 0 R - /K [3801 0 R] ->> -endobj - -3801 0 obj -<< - /Type /StructElem - /S /Formula - /P 3800 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [52] - /Pg 4806 0 R ->> -endobj - -3802 0 obj -<< - /Type /StructElem - /S /Div - /P 3783 0 R - /K [3803 0 R] ->> -endobj - -3803 0 obj -<< - /Type /StructElem - /S /Formula - /P 3802 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [50 51] - /Pg 4806 0 R ->> -endobj - -3804 0 obj -<< - /Type /StructElem - /S /Div - /P 3783 0 R - /K [3805 0 R] ->> -endobj - -3805 0 obj -<< - /Type /StructElem - /S /Formula - /P 3804 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [49] - /Pg 4806 0 R ->> -endobj - -3806 0 obj -<< - /Type /StructElem - /S /Div - /P 3783 0 R - /K [3807 0 R] ->> -endobj - -3807 0 obj -<< - /Type /StructElem - /S /Formula - /P 3806 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [44 45 46 47 48] - /Pg 4806 0 R ->> -endobj - -3808 0 obj -<< - /Type /StructElem - /S /Div - /P 3783 0 R - /K [3809 0 R] ->> -endobj - -3809 0 obj -<< - /Type /StructElem - /S /Formula - /P 3808 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [43] - /Pg 4806 0 R ->> -endobj - -3810 0 obj -<< - /Type /StructElem - /S /Div - /P 3783 0 R - /K [3811 0 R] ->> -endobj - -3811 0 obj -<< - /Type /StructElem - /S /Formula - /P 3810 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [41 42] - /Pg 4806 0 R ->> -endobj - -3812 0 obj -<< - /Type /StructElem - /S /P - /P 3782 0 R - /K [3816 0 R 30 3815 0 R 33 3814 0 R 36 3813 0 R 40] - /Pg 4806 0 R ->> -endobj - -3813 0 obj -<< - /Type /StructElem - /S /Formula - /P 3812 0 R - /K [37 38 39] - /Pg 4806 0 R ->> -endobj - -3814 0 obj -<< - /Type /StructElem - /S /Formula - /P 3812 0 R - /K [34 35] - /Pg 4806 0 R ->> -endobj - -3815 0 obj -<< - /Type /StructElem - /S /Formula - /P 3812 0 R - /K [31 32] - /Pg 4806 0 R ->> -endobj - -3816 0 obj -<< - /Type /StructElem - /S /Strong - /P 3812 0 R - /K [27 28 29] - /Pg 4806 0 R ->> -endobj - -3817 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [20 3819 0 R 22 3818 0 R 25 26] - /Pg 4806 0 R ->> -endobj - -3818 0 obj -<< - /Type /StructElem - /S /Formula - /P 3817 0 R - /K [23 24] - /Pg 4806 0 R ->> -endobj - -3819 0 obj -<< - /Type /StructElem - /S /Formula - /P 3817 0 R - /K [21] - /Pg 4806 0 R ->> -endobj - -3820 0 obj -<< - /Type /StructElem - /S /Div - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [3835 0 R 3834 0 R 3832 0 R 3823 0 R 3821 0 R] ->> -endobj - -3821 0 obj -<< - /Type /StructElem - /S /P - /P 3820 0 R - /K [11 3822 0 R 19] - /Pg 4806 0 R ->> -endobj - -3822 0 obj -<< - /Type /StructElem - /S /Formula - /P 3821 0 R - /K [12 13 14 15 16 17 18] - /Pg 4806 0 R ->> -endobj - -3823 0 obj -<< - /Type /StructElem - /S /L - /P 3820 0 R - /A [<< - /O /List - /ListNumbering /Circle - >>] - /K [3828 0 R 3824 0 R] ->> -endobj - -3824 0 obj -<< - /Type /StructElem - /S /LI - /P 3823 0 R - /K [3827 0 R 3825 0 R] ->> -endobj - -3825 0 obj -<< - /Type /StructElem - /S /LBody - /P 3824 0 R - /K [3826 0 R 10] - /Pg 4806 0 R ->> -endobj - -3826 0 obj -<< - /Type /StructElem - /S /Formula - /P 3825 0 R - /K [6 7 8 9] - /Pg 4806 0 R ->> -endobj - -3827 0 obj -<< - /Type /StructElem - /S /Lbl - /P 3824 0 R - /K [5] - /Pg 4806 0 R ->> -endobj - -3828 0 obj -<< - /Type /StructElem - /S /LI - /P 3823 0 R - /K [3831 0 R 3829 0 R] ->> -endobj - -3829 0 obj -<< - /Type /StructElem - /S /LBody - /P 3828 0 R - /K [3830 0 R 4] - /Pg 4806 0 R ->> -endobj - -3830 0 obj -<< - /Type /StructElem - /S /Formula - /P 3829 0 R - /K [1 2 3] - /Pg 4806 0 R ->> -endobj - -3831 0 obj -<< - /Type /StructElem - /S /Lbl - /P 3828 0 R - /K [0] - /Pg 4806 0 R ->> -endobj - -3832 0 obj -<< - /Type /StructElem - /S /P - /P 3820 0 R - /K [164 3833 0 R 170] - /Pg 4803 0 R ->> -endobj - -3833 0 obj -<< - /Type /StructElem - /S /Formula - /P 3832 0 R - /K [165 166 167 168 169] - /Pg 4803 0 R ->> -endobj - -3834 0 obj -<< - /Type /StructElem - /S /Formula - /P 3820 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [156 157 158 159 160 161 162 163] - /Pg 4803 0 R ->> -endobj - -3835 0 obj -<< - /Type /StructElem - /S /P - /P 3820 0 R - /K [3838 0 R 151 3837 0 R 153 3836 0 R 155] - /Pg 4803 0 R ->> -endobj - -3836 0 obj -<< - /Type /StructElem - /S /Em - /P 3835 0 R - /K [154] - /Pg 4803 0 R ->> -endobj - -3837 0 obj -<< - /Type /StructElem - /S /Formula - /P 3835 0 R - /K [152] - /Pg 4803 0 R ->> -endobj - -3838 0 obj -<< - /Type /StructElem - /S /Strong - /P 3835 0 R - /K [148 149 150] - /Pg 4803 0 R ->> -endobj - -3839 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [147] - /Pg 4803 0 R ->> -endobj - -3840 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [128 3845 0 R 130 131 132 133 3844 0 R 135 3843 0 R 138 3842 0 R 141 142 143 3841 0 R 145 146] - /Pg 4803 0 R ->> -endobj - -3841 0 obj -<< - /Type /StructElem - /S /Link - /P 3840 0 R - /K [144 << - /Type /OBJR - /Pg 4803 0 R - /Obj 4802 0 R - >>] - /Pg 4803 0 R ->> -endobj - -3842 0 obj -<< - /Type /StructElem - /S /Formula - /P 3840 0 R - /K [139 140] - /Pg 4803 0 R ->> -endobj - -3843 0 obj -<< - /Type /StructElem - /S /Formula - /P 3840 0 R - /K [136 137] - /Pg 4803 0 R ->> -endobj - -3844 0 obj -<< - /Type /StructElem - /S /Formula - /P 3840 0 R - /K [134] - /Pg 4803 0 R ->> -endobj - -3845 0 obj -<< - /Type /StructElem - /S /Formula - /P 3840 0 R - /K [129] - /Pg 4803 0 R ->> -endobj - -3846 0 obj -<< - /Type /StructElem - /S /L - /P 103 0 R - /A [<< - /O /List - /ListNumbering /Circle - >>] - /K [3859 0 R 3853 0 R 3847 0 R] ->> -endobj - -3847 0 obj -<< - /Type /StructElem - /S /LI - /P 3846 0 R - /K [3852 0 R 3848 0 R] ->> -endobj - -3848 0 obj -<< - /Type /StructElem - /S /LBody - /P 3847 0 R - /K [3851 0 R 113 3850 0 R 118 3849 0 R 125 126 127] - /Pg 4803 0 R ->> -endobj - -3849 0 obj -<< - /Type /StructElem - /S /Formula - /P 3848 0 R - /K [119 120 121 122 123 124] - /Pg 4803 0 R ->> -endobj - -3850 0 obj -<< - /Type /StructElem - /S /Formula - /P 3848 0 R - /K [114 115 116 117] - /Pg 4803 0 R ->> -endobj - -3851 0 obj -<< - /Type /StructElem - /S /Em - /P 3848 0 R - /K [112] - /Pg 4803 0 R ->> -endobj - -3852 0 obj -<< - /Type /StructElem - /S /Lbl - /P 3847 0 R - /K [111] - /Pg 4803 0 R ->> -endobj - -3853 0 obj -<< - /Type /StructElem - /S /LI - /P 3846 0 R - /K [3858 0 R 3854 0 R] ->> -endobj - -3854 0 obj -<< - /Type /StructElem - /S /LBody - /P 3853 0 R - /K [3857 0 R 105 3856 0 R 108 3855 0 R 110] - /Pg 4803 0 R ->> -endobj - -3855 0 obj -<< - /Type /StructElem - /S /Formula - /P 3854 0 R - /K [109] - /Pg 4803 0 R ->> -endobj - -3856 0 obj -<< - /Type /StructElem - /S /Formula - /P 3854 0 R - /K [106 107] - /Pg 4803 0 R ->> -endobj - -3857 0 obj -<< - /Type /StructElem - /S /Em - /P 3854 0 R - /K [104] - /Pg 4803 0 R ->> -endobj - -3858 0 obj -<< - /Type /StructElem - /S /Lbl - /P 3853 0 R - /K [103] - /Pg 4803 0 R ->> -endobj - -3859 0 obj -<< - /Type /StructElem - /S /LI - /P 3846 0 R - /K [3862 0 R 3860 0 R] ->> -endobj - -3860 0 obj -<< - /Type /StructElem - /S /LBody - /P 3859 0 R - /K [3861 0 R 102] - /Pg 4803 0 R ->> -endobj - -3861 0 obj -<< - /Type /StructElem - /S /Em - /P 3860 0 R - /K [101] - /Pg 4803 0 R ->> -endobj - -3862 0 obj -<< - /Type /StructElem - /S /Lbl - /P 3859 0 R - /K [100] - /Pg 4803 0 R ->> -endobj - -3863 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [44 3873 0 R 51 3872 0 R 61 3871 0 R 63 64 3870 0 R 66 3869 0 R 70 3868 0 R 83 3867 0 R 85 86 3866 0 R 88 3865 0 R 96 97 3864 0 R 99] - /Pg 4803 0 R ->> -endobj - -3864 0 obj -<< - /Type /StructElem - /S /Formula - /P 3863 0 R - /K [98] - /Pg 4803 0 R ->> -endobj - -3865 0 obj -<< - /Type /StructElem - /S /Formula - /P 3863 0 R - /K [89 90 91 92 93 94 95] - /Pg 4803 0 R ->> -endobj - -3866 0 obj -<< - /Type /StructElem - /S /Formula - /P 3863 0 R - /K [87] - /Pg 4803 0 R ->> -endobj - -3867 0 obj -<< - /Type /StructElem - /S /Formula - /P 3863 0 R - /K [84] - /Pg 4803 0 R ->> -endobj - -3868 0 obj -<< - /Type /StructElem - /S /Formula - /P 3863 0 R - /K [71 72 73 74 75 76 77 78 79 80 81 82] - /Pg 4803 0 R ->> -endobj - -3869 0 obj -<< - /Type /StructElem - /S /Formula - /P 3863 0 R - /K [67 68 69] - /Pg 4803 0 R ->> -endobj - -3870 0 obj -<< - /Type /StructElem - /S /Formula - /P 3863 0 R - /K [65] - /Pg 4803 0 R ->> -endobj - -3871 0 obj -<< - /Type /StructElem - /S /Formula - /P 3863 0 R - /K [62] - /Pg 4803 0 R ->> -endobj - -3872 0 obj -<< - /Type /StructElem - /S /Formula - /P 3863 0 R - /K [52 53 54 55 56 57 58 59 60] - /Pg 4803 0 R ->> -endobj - -3873 0 obj -<< - /Type /StructElem - /S /Formula - /P 3863 0 R - /K [45 46 47 48 49 50] - /Pg 4803 0 R ->> -endobj - -3874 0 obj -<< - /Type /StructElem - /S /H3 - /P 103 0 R - /T (Effect Context) - /K [42 43] - /Pg 4803 0 R ->> -endobj - -3875 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [3878 0 R 22 23 24 25 3877 0 R 35 36 37 38 3876 0 R 40 41] - /Pg 4803 0 R ->> -endobj - -3876 0 obj -<< - /Type /StructElem - /S /Em - /P 3875 0 R - /K [39] - /Pg 4803 0 R ->> -endobj - -3877 0 obj -<< - /Type /StructElem - /S /Formula - /P 3875 0 R - /K [26 27 28 29 30 31 32 33 34] - /Pg 4803 0 R ->> -endobj - -3878 0 obj -<< - /Type /StructElem - /S /Em - /P 3875 0 R - /K [21] - /Pg 4803 0 R ->> -endobj - -3879 0 obj -<< - /Type /StructElem - /S /H2 - /P 103 0 R - /T (Revertible Effects) - /K [19 20] - /Pg 4803 0 R ->> -endobj - -3880 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [2 3883 0 R 4 5 6 3882 0 R 8 9 3881 0 R 11 12 13 14 15 16 17 18] - /Pg 4803 0 R ->> -endobj - -3881 0 obj -<< - /Type /StructElem - /S /Em - /P 3880 0 R - /K [10] - /Pg 4803 0 R ->> -endobj - -3882 0 obj -<< - /Type /StructElem - /S /Em - /P 3880 0 R - /K [7] - /Pg 4803 0 R ->> -endobj - -3883 0 obj -<< - /Type /StructElem - /S /Link - /P 3880 0 R - /K [3 << - /Type /OBJR - /Pg 4803 0 R - /Obj 4801 0 R - >>] - /Pg 4803 0 R ->> -endobj - -3884 0 obj -<< - /Type /StructElem - /S /H1 - /P 103 0 R - /T (Revertible Effects and Reactive Coeffects) - /K [0 1] - /Pg 4803 0 R ->> -endobj - -3885 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [167 168 169 170 171 3886 0 R 173] - /Pg 4799 0 R ->> -endobj - -3886 0 obj -<< - /Type /StructElem - /S /Link - /P 3885 0 R - /K [172 << - /Type /OBJR - /Pg 4799 0 R - /Obj 4798 0 R - >>] - /Pg 4799 0 R ->> -endobj - -3887 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [160 161 162 163 164 165 166] - /Pg 4799 0 R ->> -endobj - -3888 0 obj -<< - /Type /StructElem - /S /L - /P 103 0 R - /A [<< - /O /List - /ListNumbering /Circle - >>] - /K [3893 0 R 3889 0 R] ->> -endobj - -3889 0 obj -<< - /Type /StructElem - /S /LI - /P 3888 0 R - /K [3892 0 R 3890 0 R] ->> -endobj - -3890 0 obj -<< - /Type /StructElem - /S /LBody - /P 3889 0 R - /K [3891 0 R 156 157 158 159] - /Pg 4799 0 R ->> -endobj - -3891 0 obj -<< - /Type /StructElem - /S /Strong - /P 3890 0 R - /K [155] - /Pg 4799 0 R ->> -endobj - -3892 0 obj -<< - /Type /StructElem - /S /Lbl - /P 3889 0 R - /K [154] - /Pg 4799 0 R ->> -endobj - -3893 0 obj -<< - /Type /StructElem - /S /LI - /P 3888 0 R - /K [3896 0 R 3894 0 R] ->> -endobj - -3894 0 obj -<< - /Type /StructElem - /S /LBody - /P 3893 0 R - /K [3895 0 R 149 150 151 152 153] - /Pg 4799 0 R ->> -endobj - -3895 0 obj -<< - /Type /StructElem - /S /Strong - /P 3894 0 R - /K [148] - /Pg 4799 0 R ->> -endobj - -3896 0 obj -<< - /Type /StructElem - /S /Lbl - /P 3893 0 R - /K [147] - /Pg 4799 0 R ->> -endobj - -3897 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [136 137 3900 0 R 139 140 3899 0 R 142 143 144 3898 0 R 146] - /Pg 4799 0 R ->> -endobj - -3898 0 obj -<< - /Type /StructElem - /S /Link - /P 3897 0 R - /K [145 << - /Type /OBJR - /Pg 4799 0 R - /Obj 4797 0 R - >>] - /Pg 4799 0 R ->> -endobj - -3899 0 obj -<< - /Type /StructElem - /S /Em - /P 3897 0 R - /K [141] - /Pg 4799 0 R ->> -endobj - -3900 0 obj -<< - /Type /StructElem - /S /Em - /P 3897 0 R - /K [138] - /Pg 4799 0 R ->> -endobj - -3901 0 obj -<< - /Type /StructElem - /S /H2 - /P 103 0 R - /T (Relationship to Dynamic Composability) - /K [134 135] - /Pg 4799 0 R ->> -endobj - -3902 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [3918 0 R 72 3917 0 R 74 75 3916 0 R 91 92 3915 0 R 94 95 96 97 3914 0 R 99 100 3913 0 R 102 103 3912 0 R 105 3911 0 R 107 3910 0 R 109 3909 0 R 111 112 3908 0 R 114 3907 0 R 116 117 118 3906 0 R 120 121 122 3905 0 R 124 3904 0 R 126 127 128 129 130 3903 0 R 132 133] - /Pg 4799 0 R ->> -endobj - -3903 0 obj -<< - /Type /StructElem - /S /Link - /P 3902 0 R - /K [131 << - /Type /OBJR - /Pg 4799 0 R - /Obj 4796 0 R - >>] - /Pg 4799 0 R ->> -endobj - -3904 0 obj -<< - /Type /StructElem - /S /Link - /P 3902 0 R - /K [125 << - /Type /OBJR - /Pg 4799 0 R - /Obj 4795 0 R - >>] - /Pg 4799 0 R ->> -endobj - -3905 0 obj -<< - /Type /StructElem - /S /Link - /P 3902 0 R - /K [123 << - /Type /OBJR - /Pg 4799 0 R - /Obj 4794 0 R - >>] - /Pg 4799 0 R ->> -endobj - -3906 0 obj -<< - /Type /StructElem - /S /Link - /P 3902 0 R - /K [119 << - /Type /OBJR - /Pg 4799 0 R - /Obj 4793 0 R - >>] - /Pg 4799 0 R ->> -endobj - -3907 0 obj -<< - /Type /StructElem - /S /Formula - /P 3902 0 R - /K [115] - /Pg 4799 0 R ->> -endobj - -3908 0 obj -<< - /Type /StructElem - /S /Formula - /P 3902 0 R - /K [113] - /Pg 4799 0 R ->> -endobj - -3909 0 obj -<< - /Type /StructElem - /S /Formula - /P 3902 0 R - /K [110] - /Pg 4799 0 R ->> -endobj - -3910 0 obj -<< - /Type /StructElem - /S /Formula - /P 3902 0 R - /K [108] - /Pg 4799 0 R ->> -endobj - -3911 0 obj -<< - /Type /StructElem - /S /Formula - /P 3902 0 R - /K [106] - /Pg 4799 0 R ->> -endobj - -3912 0 obj -<< - /Type /StructElem - /S /Formula - /P 3902 0 R - /K [104] - /Pg 4799 0 R ->> -endobj - -3913 0 obj -<< - /Type /StructElem - /S /Formula - /P 3902 0 R - /K [101] - /Pg 4799 0 R ->> -endobj - -3914 0 obj -<< - /Type /StructElem - /S /Link - /P 3902 0 R - /K [98 << - /Type /OBJR - /Pg 4799 0 R - /Obj 4792 0 R - >>] - /Pg 4799 0 R ->> -endobj - -3915 0 obj -<< - /Type /StructElem - /S /Link - /P 3902 0 R - /K [93 << - /Type /OBJR - /Pg 4799 0 R - /Obj 4791 0 R - >>] - /Pg 4799 0 R ->> -endobj - -3916 0 obj -<< - /Type /StructElem - /S /Formula - /P 3902 0 R - /K [76 77 78 79 80 81 82 83 84 85 86 87 88 89 90] - /Pg 4799 0 R ->> -endobj - -3917 0 obj -<< - /Type /StructElem - /S /Em - /P 3902 0 R - /K [73] - /Pg 4799 0 R ->> -endobj - -3918 0 obj -<< - /Type /StructElem - /S /Strong - /P 3902 0 R - /K [71] - /Pg 4799 0 R ->> -endobj - -3919 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [3928 0 R 3 4 5 3927 0 R 7 8 9 10 11 3926 0 R 13 14 15 3925 0 R 23 24 3924 0 R 33 34 35 3923 0 R 50 3922 0 R 59 3921 0 R 61 3920 0 R 70] - /Pg 4799 0 R ->> -endobj - -3920 0 obj -<< - /Type /StructElem - /S /Formula - /P 3919 0 R - /K [62 63 64 65 66 67 68 69] - /Pg 4799 0 R ->> -endobj - -3921 0 obj -<< - /Type /StructElem - /S /Formula - /P 3919 0 R - /K [60] - /Pg 4799 0 R ->> -endobj - -3922 0 obj -<< - /Type /StructElem - /S /Formula - /P 3919 0 R - /K [51 52 53 54 55 56 57 58] - /Pg 4799 0 R ->> -endobj - -3923 0 obj -<< - /Type /StructElem - /S /Formula - /P 3919 0 R - /K [36 37 38 39 40 41 42 43 44 45 46 47 48 49] - /Pg 4799 0 R ->> -endobj - -3924 0 obj -<< - /Type /StructElem - /S /Formula - /P 3919 0 R - /K [25 26 27 28 29 30 31 32] - /Pg 4799 0 R ->> -endobj - -3925 0 obj -<< - /Type /StructElem - /S /Formula - /P 3919 0 R - /K [16 17 18 19 20 21 22] - /Pg 4799 0 R ->> -endobj - -3926 0 obj -<< - /Type /StructElem - /S /Link - /P 3919 0 R - /K [12 << - /Type /OBJR - /Pg 4799 0 R - /Obj 4790 0 R - >>] - /Pg 4799 0 R ->> -endobj - -3927 0 obj -<< - /Type /StructElem - /S /Link - /P 3919 0 R - /K [6 << - /Type /OBJR - /Pg 4799 0 R - /Obj 4789 0 R - >>] - /Pg 4799 0 R ->> -endobj - -3928 0 obj -<< - /Type /StructElem - /S /Strong - /P 3919 0 R - /K [2] - /Pg 4799 0 R ->> -endobj - -3929 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [198 199 << - /Type /MCR - /MCID 0 - /Pg 4799 0 R - >> << - /Type /MCR - /MCID 1 - /Pg 4799 0 R - >>] - /Pg 4787 0 R ->> -endobj - -3930 0 obj -<< - /Type /StructElem - /S /Formula - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [191 192 193 194 195 196 197] - /Pg 4787 0 R ->> -endobj - -3931 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [181 3934 0 R 183 184 3933 0 R 186 3932 0 R 188 189 190] - /Pg 4787 0 R ->> -endobj - -3932 0 obj -<< - /Type /StructElem - /S /Link - /P 3931 0 R - /K [187 << - /Type /OBJR - /Pg 4787 0 R - /Obj 4786 0 R - >>] - /Pg 4787 0 R ->> -endobj - -3933 0 obj -<< - /Type /StructElem - /S /Link - /P 3931 0 R - /K [185 << - /Type /OBJR - /Pg 4787 0 R - /Obj 4785 0 R - >>] - /Pg 4787 0 R ->> -endobj - -3934 0 obj -<< - /Type /StructElem - /S /Em - /P 3931 0 R - /K [182] - /Pg 4787 0 R ->> -endobj - -3935 0 obj -<< - /Type /StructElem - /S /H2 - /P 103 0 R - /T (Coeffects) - /K [179 180] - /Pg 4787 0 R ->> -endobj - -3936 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [153 3943 0 R 155 3942 0 R 157 158 159 160 3941 0 R 162 163 164 3940 0 R 166 3939 0 R 168 169 170 3938 0 R 172 173 174 3937 0 R 176 177 178] - /Pg 4787 0 R ->> -endobj - -3937 0 obj -<< - /Type /StructElem - /S /Link - /P 3936 0 R - /K [175 << - /Type /OBJR - /Pg 4787 0 R - /Obj 4784 0 R - >>] - /Pg 4787 0 R ->> -endobj - -3938 0 obj -<< - /Type /StructElem - /S /Link - /P 3936 0 R - /K [171 << - /Type /OBJR - /Pg 4787 0 R - /Obj 4783 0 R - >>] - /Pg 4787 0 R ->> -endobj - -3939 0 obj -<< - /Type /StructElem - /S /Link - /P 3936 0 R - /K [167 << - /Type /OBJR - /Pg 4787 0 R - /Obj 4782 0 R - >>] - /Pg 4787 0 R ->> -endobj - -3940 0 obj -<< - /Type /StructElem - /S /Link - /P 3936 0 R - /K [165 << - /Type /OBJR - /Pg 4787 0 R - /Obj 4781 0 R - >>] - /Pg 4787 0 R ->> -endobj - -3941 0 obj -<< - /Type /StructElem - /S /Link - /P 3936 0 R - /K [161 << - /Type /OBJR - /Pg 4787 0 R - /Obj 4780 0 R - >>] - /Pg 4787 0 R ->> -endobj - -3942 0 obj -<< - /Type /StructElem - /S /Formula - /P 3936 0 R - /K [156] - /Pg 4787 0 R ->> -endobj - -3943 0 obj -<< - /Type /StructElem - /S /Formula - /P 3936 0 R - /K [154] - /Pg 4787 0 R ->> -endobj - -3944 0 obj -<< - /Type /StructElem - /S /Formula - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [139 140 141 142 143 144 145 146 147 148 149 150 151 152] - /Pg 4787 0 R ->> -endobj - -3945 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [3953 0 R 104 105 3952 0 R 107 3951 0 R 109 110 111 112 113 3950 0 R 115 3949 0 R 122 3948 0 R 129 130 131 132 3947 0 R 134 135 3946 0 R 137 138] - /Pg 4787 0 R ->> -endobj - -3946 0 obj -<< - /Type /StructElem - /S /Em - /P 3945 0 R - /K [136] - /Pg 4787 0 R ->> -endobj - -3947 0 obj -<< - /Type /StructElem - /S /Link - /P 3945 0 R - /K [133 << - /Type /OBJR - /Pg 4787 0 R - /Obj 4779 0 R - >>] - /Pg 4787 0 R ->> -endobj - -3948 0 obj -<< - /Type /StructElem - /S /Formula - /P 3945 0 R - /K [123 124 125 126 127 128] - /Pg 4787 0 R ->> -endobj - -3949 0 obj -<< - /Type /StructElem - /S /Formula - /P 3945 0 R - /K [116 117 118 119 120 121] - /Pg 4787 0 R ->> -endobj - -3950 0 obj -<< - /Type /StructElem - /S /Formula - /P 3945 0 R - /K [114] - /Pg 4787 0 R ->> -endobj - -3951 0 obj -<< - /Type /StructElem - /S /Link - /P 3945 0 R - /K [108 << - /Type /OBJR - /Pg 4787 0 R - /Obj 4778 0 R - >>] - /Pg 4787 0 R ->> -endobj - -3952 0 obj -<< - /Type /StructElem - /S /Link - /P 3945 0 R - /K [106 << - /Type /OBJR - /Pg 4787 0 R - /Obj 4777 0 R - >>] - /Pg 4787 0 R ->> -endobj - -3953 0 obj -<< - /Type /StructElem - /S /Strong - /P 3945 0 R - /K [103] - /Pg 4787 0 R ->> -endobj - -3954 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [3962 0 R 50 51 3961 0 R 53 54 55 56 3960 0 R 58 59 3959 0 R 67 3958 0 R 69 70 71 3957 0 R 76 3956 0 R 85 86 3955 0 R 101 102] - /Pg 4787 0 R ->> -endobj - -3955 0 obj -<< - /Type /StructElem - /S /Formula - /P 3954 0 R - /K [87 88 89 90 91 92 93 94 95 96 97 98 99 100] - /Pg 4787 0 R ->> -endobj - -3956 0 obj -<< - /Type /StructElem - /S /Formula - /P 3954 0 R - /K [77 78 79 80 81 82 83 84] - /Pg 4787 0 R ->> -endobj - -3957 0 obj -<< - /Type /StructElem - /S /Formula - /P 3954 0 R - /K [72 73 74 75] - /Pg 4787 0 R ->> -endobj - -3958 0 obj -<< - /Type /StructElem - /S /Formula - /P 3954 0 R - /K [68] - /Pg 4787 0 R ->> -endobj - -3959 0 obj -<< - /Type /StructElem - /S /Formula - /P 3954 0 R - /K [60 61 62 63 64 65 66] - /Pg 4787 0 R ->> -endobj - -3960 0 obj -<< - /Type /StructElem - /S /Link - /P 3954 0 R - /K [57 << - /Type /OBJR - /Pg 4787 0 R - /Obj 4776 0 R - >>] - /Pg 4787 0 R ->> -endobj - -3961 0 obj -<< - /Type /StructElem - /S /Link - /P 3954 0 R - /K [52 << - /Type /OBJR - /Pg 4787 0 R - /Obj 4775 0 R - >>] - /Pg 4787 0 R ->> -endobj - -3962 0 obj -<< - /Type /StructElem - /S /Strong - /P 3954 0 R - /K [49] - /Pg 4787 0 R ->> -endobj - -3963 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [40 41 42 43 3964 0 R 45 46 47 48] - /Pg 4787 0 R ->> -endobj - -3964 0 obj -<< - /Type /StructElem - /S /Link - /P 3963 0 R - /K [44 << - /Type /OBJR - /Pg 4787 0 R - /Obj 4774 0 R - >>] - /Pg 4787 0 R ->> -endobj - -3965 0 obj -<< - /Type /StructElem - /S /Formula - /P 103 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [33 34 35 36 37 38 39] - /Pg 4787 0 R ->> -endobj - -3966 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [10 11 3973 0 R 13 3972 0 R 15 16 3971 0 R 22 23 3970 0 R 25 3969 0 R 27 3968 0 R 29 3967 0 R 31 32] - /Pg 4787 0 R ->> -endobj - -3967 0 obj -<< - /Type /StructElem - /S /Em - /P 3966 0 R - /K [30] - /Pg 4787 0 R ->> -endobj - -3968 0 obj -<< - /Type /StructElem - /S /Formula - /P 3966 0 R - /K [28] - /Pg 4787 0 R ->> -endobj - -3969 0 obj -<< - /Type /StructElem - /S /Formula - /P 3966 0 R - /K [26] - /Pg 4787 0 R ->> -endobj - -3970 0 obj -<< - /Type /StructElem - /S /Formula - /P 3966 0 R - /K [24] - /Pg 4787 0 R ->> -endobj - -3971 0 obj -<< - /Type /StructElem - /S /Formula - /P 3966 0 R - /K [17 18 19 20 21] - /Pg 4787 0 R ->> -endobj - -3972 0 obj -<< - /Type /StructElem - /S /Link - /P 3966 0 R - /K [14 << - /Type /OBJR - /Pg 4787 0 R - /Obj 4773 0 R - >>] - /Pg 4787 0 R ->> -endobj - -3973 0 obj -<< - /Type /StructElem - /S /Link - /P 3966 0 R - /K [12 << - /Type /OBJR - /Pg 4787 0 R - /Obj 4772 0 R - >>] - /Pg 4787 0 R ->> -endobj - -3974 0 obj -<< - /Type /StructElem - /S /H2 - /P 103 0 R - /T (Effects) - /K [8 9] - /Pg 4787 0 R ->> -endobj - -3975 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [2 3 4 3976 0 R 6 7] - /Pg 4787 0 R ->> -endobj - -3976 0 obj -<< - /Type /StructElem - /S /Link - /P 3975 0 R - /K [5 << - /Type /OBJR - /Pg 4787 0 R - /Obj 4771 0 R - >>] - /Pg 4787 0 R ->> -endobj - -3977 0 obj -<< - /Type /StructElem - /S /H1 - /P 103 0 R - /T (Preliminaries) - /K [0 1] - /Pg 4787 0 R ->> -endobj - -3978 0 obj -<< - /Type /StructElem - /S /L - /P 103 0 R - /A [<< - /O /List - /ListNumbering /Decimal - >>] - /K [3996 0 R 3991 0 R 3984 0 R 3979 0 R] ->> -endobj - -3979 0 obj -<< - /Type /StructElem - /S /LI - /P 3978 0 R - /K [3983 0 R 3980 0 R] ->> -endobj - -3980 0 obj -<< - /Type /StructElem - /S /LBody - /P 3979 0 R - /K [95 3982 0 R 97 3981 0 R 99 100 101 102 103 104] - /Pg 4769 0 R ->> -endobj - -3981 0 obj -<< - /Type /StructElem - /S /Link - /P 3980 0 R - /K [98 << - /Type /OBJR - /Pg 4769 0 R - /Obj 4768 0 R - >>] - /Pg 4769 0 R ->> -endobj - -3982 0 obj -<< - /Type /StructElem - /S /Strong - /P 3980 0 R - /K [96] - /Pg 4769 0 R ->> -endobj - -3983 0 obj -<< - /Type /StructElem - /S /Lbl - /P 3979 0 R - /K [94] - /Pg 4769 0 R ->> -endobj - -3984 0 obj -<< - /Type /StructElem - /S /LI - /P 3978 0 R - /K [3990 0 R 3985 0 R] ->> -endobj - -3985 0 obj -<< - /Type /StructElem - /S /LBody - /P 3984 0 R - /K [81 3989 0 R 83 3988 0 R 85 86 87 88 3987 0 R 90 3986 0 R 92 93] - /Pg 4769 0 R ->> -endobj - -3986 0 obj -<< - /Type /StructElem - /S /Link - /P 3985 0 R - /K [91 << - /Type /OBJR - /Pg 4769 0 R - /Obj 4767 0 R - >>] - /Pg 4769 0 R ->> -endobj - -3987 0 obj -<< - /Type /StructElem - /S /Strong - /P 3985 0 R - /K [89] - /Pg 4769 0 R ->> -endobj - -3988 0 obj -<< - /Type /StructElem - /S /Link - /P 3985 0 R - /K [84 << - /Type /OBJR - /Pg 4769 0 R - /Obj 4766 0 R - >>] - /Pg 4769 0 R ->> -endobj - -3989 0 obj -<< - /Type /StructElem - /S /Strong - /P 3985 0 R - /K [82] - /Pg 4769 0 R ->> -endobj - -3990 0 obj -<< - /Type /StructElem - /S /Lbl - /P 3984 0 R - /K [80] - /Pg 4769 0 R ->> -endobj - -3991 0 obj -<< - /Type /StructElem - /S /LI - /P 3978 0 R - /K [3995 0 R 3992 0 R] ->> -endobj - -3992 0 obj -<< - /Type /StructElem - /S /LBody - /P 3991 0 R - /K [71 3994 0 R 73 3993 0 R 75 76 77 78 79] - /Pg 4769 0 R ->> -endobj - -3993 0 obj -<< - /Type /StructElem - /S /Link - /P 3992 0 R - /K [74 << - /Type /OBJR - /Pg 4769 0 R - /Obj 4765 0 R - >>] - /Pg 4769 0 R ->> -endobj - -3994 0 obj -<< - /Type /StructElem - /S /Strong - /P 3992 0 R - /K [72] - /Pg 4769 0 R ->> -endobj - -3995 0 obj -<< - /Type /StructElem - /S /Lbl - /P 3991 0 R - /K [70] - /Pg 4769 0 R ->> -endobj - -3996 0 obj -<< - /Type /StructElem - /S /LI - /P 3978 0 R - /K [4001 0 R 3997 0 R] ->> -endobj - -3997 0 obj -<< - /Type /StructElem - /S /LBody - /P 3996 0 R - /K [58 4000 0 R 60 3999 0 R 62 63 64 3998 0 R 66 67 68 69] - /Pg 4769 0 R ->> -endobj - -3998 0 obj -<< - /Type /StructElem - /S /Em - /P 3997 0 R - /K [65] - /Pg 4769 0 R ->> -endobj - -3999 0 obj -<< - /Type /StructElem - /S /Link - /P 3997 0 R - /K [61 << - /Type /OBJR - /Pg 4769 0 R - /Obj 4764 0 R - >>] - /Pg 4769 0 R ->> -endobj - -4000 0 obj -<< - /Type /StructElem - /S /Strong - /P 3997 0 R - /K [59] - /Pg 4769 0 R ->> -endobj - -4001 0 obj -<< - /Type /StructElem - /S /Lbl - /P 3996 0 R - /K [57] - /Pg 4769 0 R ->> -endobj - -4002 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [26 4010 0 R 28 29 4009 0 R 31 4008 0 R 34 35 4007 0 R 37 4006 0 R 39 40 4005 0 R 42 43 4004 0 R 45 4003 0 R 47 48 49 50 51 52 53 54 55 56] - /Pg 4769 0 R ->> -endobj - -4003 0 obj -<< - /Type /StructElem - /S /Link - /P 4002 0 R - /K [46 << - /Type /OBJR - /Pg 4769 0 R - /Obj 4763 0 R - >>] - /Pg 4769 0 R ->> -endobj - -4004 0 obj -<< - /Type /StructElem - /S /Link - /P 4002 0 R - /K [44 << - /Type /OBJR - /Pg 4769 0 R - /Obj 4762 0 R - >>] - /Pg 4769 0 R ->> -endobj - -4005 0 obj -<< - /Type /StructElem - /S /Em - /P 4002 0 R - /K [41] - /Pg 4769 0 R ->> -endobj - -4006 0 obj -<< - /Type /StructElem - /S /Link - /P 4002 0 R - /K [38 << - /Type /OBJR - /Pg 4769 0 R - /Obj 4761 0 R - >>] - /Pg 4769 0 R ->> -endobj - -4007 0 obj -<< - /Type /StructElem - /S /Link - /P 4002 0 R - /K [36 << - /Type /OBJR - /Pg 4769 0 R - /Obj 4760 0 R - >>] - /Pg 4769 0 R ->> -endobj - -4008 0 obj -<< - /Type /StructElem - /S /Em - /P 4002 0 R - /K [32 33] - /Pg 4769 0 R ->> -endobj - -4009 0 obj -<< - /Type /StructElem - /S /Em - /P 4002 0 R - /K [30] - /Pg 4769 0 R ->> -endobj - -4010 0 obj -<< - /Type /StructElem - /S /Em - /P 4002 0 R - /K [27] - /Pg 4769 0 R ->> -endobj - -4011 0 obj -<< - /Type /StructElem - /S /H2 - /P 103 0 R - /T (Contributions) - /K [24 25] - /Pg 4769 0 R ->> -endobj - -4012 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [8 9 10 11 12 4013 0 R 14 15 16 17 18 19 20 21 22 23] - /Pg 4769 0 R ->> -endobj - -4013 0 obj -<< - /Type /StructElem - /S /Link - /P 4012 0 R - /K [13 << - /Type /OBJR - /Pg 4769 0 R - /Obj 4759 0 R - >>] - /Pg 4769 0 R ->> -endobj - -4014 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [88 89 90 91 << - /Type /MCR - /MCID 0 - /Pg 4769 0 R - >> << - /Type /MCR - /MCID 1 - /Pg 4769 0 R - >> 4015 0 R << - /Type /MCR - /MCID 3 - /Pg 4769 0 R - >> << - /Type /MCR - /MCID 4 - /Pg 4769 0 R - >> << - /Type /MCR - /MCID 5 - /Pg 4769 0 R - >> << - /Type /MCR - /MCID 6 - /Pg 4769 0 R - >> << - /Type /MCR - /MCID 7 - /Pg 4769 0 R - >>] - /Pg 4756 0 R ->> -endobj - -4015 0 obj -<< - /Type /StructElem - /S /Link - /P 4014 0 R - /K [2 << - /Type /OBJR - /Pg 4769 0 R - /Obj 4758 0 R - >>] - /Pg 4769 0 R ->> -endobj - -4016 0 obj -<< - /Type /StructElem - /S /H3 - /P 103 0 R - /T (The Coarse-Grained Workaround) - /K [86 87] - /Pg 4756 0 R ->> -endobj - -4017 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [77 78 79 80 81 82 83 84 85] - /Pg 4756 0 R ->> -endobj - -4018 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [45 46 4024 0 R 48 4023 0 R 50 51 52 53 4022 0 R 55 56 57 58 4021 0 R 60 61 62 63 64 4020 0 R 66 67 68 69 70 71 72 4019 0 R 74 75 76] - /Pg 4756 0 R ->> -endobj - -4019 0 obj -<< - /Type /StructElem - /S /Link - /P 4018 0 R - /K [73 << - /Type /OBJR - /Pg 4756 0 R - /Obj 4754 0 R - >>] - /Pg 4756 0 R ->> -endobj - -4020 0 obj -<< - /Type /StructElem - /S /Link - /P 4018 0 R - /K [65 << - /Type /OBJR - /Pg 4756 0 R - /Obj 4753 0 R - >>] - /Pg 4756 0 R ->> -endobj - -4021 0 obj -<< - /Type /StructElem - /S /Link - /P 4018 0 R - /K [59 << - /Type /OBJR - /Pg 4756 0 R - /Obj 4752 0 R - >>] - /Pg 4756 0 R ->> -endobj - -4022 0 obj -<< - /Type /StructElem - /S /Link - /P 4018 0 R - /K [54 << - /Type /OBJR - /Pg 4756 0 R - /Obj 4751 0 R - >>] - /Pg 4756 0 R ->> -endobj - -4023 0 obj -<< - /Type /StructElem - /S /Link - /P 4018 0 R - /K [49 << - /Type /OBJR - /Pg 4756 0 R - /Obj 4750 0 R - >>] - /Pg 4756 0 R ->> -endobj - -4024 0 obj -<< - /Type /StructElem - /S /Link - /P 4018 0 R - /K [47 << - /Type /OBJR - /Pg 4756 0 R - /Obj 4749 0 R - >>] - /Pg 4756 0 R ->> -endobj - -4025 0 obj -<< - /Type /StructElem - /S /H3 - /P 103 0 R - /T (Self-Evolving Agent Harnesses) - /K [43 44] - /Pg 4756 0 R ->> -endobj - -4026 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [36 37 4028 0 R 39 4027 0 R 41 42] - /Pg 4756 0 R ->> -endobj - -4027 0 obj -<< - /Type /StructElem - /S /Link - /P 4026 0 R - /K [40 << - /Type /OBJR - /Pg 4756 0 R - /Obj 4748 0 R - >>] - /Pg 4756 0 R ->> -endobj - -4028 0 obj -<< - /Type /StructElem - /S /Link - /P 4026 0 R - /K [38 << - /Type /OBJR - /Pg 4756 0 R - /Obj 4747 0 R - >>] - /Pg 4756 0 R ->> -endobj - -4029 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [4037 0 R 13 4036 0 R 15 16 17 18 4035 0 R 20 4032 0 R 22 23 24 25 26 27 28 4031 0 R 30 31 4030 0 R 33 34 35] - /Pg 4756 0 R ->> -endobj - -4030 0 obj -<< - /Type /StructElem - /S /Code - /P 4029 0 R - /K [32] - /Pg 4756 0 R ->> -endobj - -4031 0 obj -<< - /Type /StructElem - /S /Code - /P 4029 0 R - /K [29] - /Pg 4756 0 R ->> -endobj - -4032 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4029 0 R - /K [4033 0 R] ->> -endobj - -4033 0 obj -<< - /Type /StructElem - /S /Link - /P 4032 0 R - /K [<< - /Type /OBJR - /Pg 4756 0 R - /Obj 4746 0 R - >> 4034 0 R] ->> -endobj - -4034 0 obj -<< - /Type /StructElem - /S /Span - /P 4033 0 R - /A [<< - /O /Layout - /BaselineShift 3.1614 - /LineHeight 3.96 - >>] - /K [21] - /Pg 4756 0 R ->> -endobj - -4035 0 obj -<< - /Type /StructElem - /S /Code - /P 4029 0 R - /K [19] - /Pg 4756 0 R ->> -endobj - -4036 0 obj -<< - /Type /StructElem - /S /Code - /P 4029 0 R - /K [14] - /Pg 4756 0 R ->> -endobj - -4037 0 obj -<< - /Type /StructElem - /S /Strong - /P 4029 0 R - /K [12] - /Pg 4756 0 R ->> -endobj - -4038 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [4049 0 R 72 73 74 4048 0 R 76 77 78 << - /Type /MCR - /MCID 0 - /Pg 4756 0 R - >> << - /Type /MCR - /MCID 1 - /Pg 4756 0 R - >> 4045 0 R 4041 0 R << - /Type /MCR - /MCID 3 - /Pg 4756 0 R - >> << - /Type /MCR - /MCID 4 - /Pg 4756 0 R - >> 4040 0 R << - /Type /MCR - /MCID 6 - /Pg 4756 0 R - >> << - /Type /MCR - /MCID 7 - /Pg 4756 0 R - >> << - /Type /MCR - /MCID 8 - /Pg 4756 0 R - >> 4039 0 R << - /Type /MCR - /MCID 10 - /Pg 4756 0 R - >> << - /Type /MCR - /MCID 11 - /Pg 4756 0 R - >>] - /Pg 4743 0 R ->> -endobj - -4039 0 obj -<< - /Type /StructElem - /S /Code - /P 4038 0 R - /K [9] - /Pg 4756 0 R ->> -endobj - -4040 0 obj -<< - /Type /StructElem - /S /Code - /P 4038 0 R - /K [5] - /Pg 4756 0 R ->> -endobj - -4041 0 obj -<< - /Type /StructElem - /S /Note - /P 4038 0 R - /ID (Note 1) - /K [4042 0 R 93] - /Pg 4756 0 R ->> -endobj - -4042 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4041 0 R - /K [4043 0 R] ->> -endobj - -4043 0 obj -<< - /Type /StructElem - /S /Link - /P 4042 0 R - /K [<< - /Type /OBJR - /Pg 4756 0 R - /Obj 4755 0 R - >> 4044 0 R] ->> -endobj - -4044 0 obj -<< - /Type /StructElem - /S /Span - /P 4043 0 R - /A [<< - /O /Layout - /BaselineShift 2.5866 - /LineHeight 3.24 - >>] - /K [92] - /Pg 4756 0 R ->> -endobj - -4045 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4038 0 R - /K [4046 0 R] ->> -endobj - -4046 0 obj -<< - /Type /StructElem - /S /Link - /P 4045 0 R - /K [<< - /Type /OBJR - /Pg 4756 0 R - /Obj 4745 0 R - >> 4047 0 R] ->> -endobj - -4047 0 obj -<< - /Type /StructElem - /S /Span - /P 4046 0 R - /A [<< - /O /Layout - /BaselineShift 3.1614 - /LineHeight 3.96 - >>] - /K [2] - /Pg 4756 0 R ->> -endobj - -4048 0 obj -<< - /Type /StructElem - /S /Code - /P 4038 0 R - /K [75] - /Pg 4743 0 R ->> -endobj - -4049 0 obj -<< - /Type /StructElem - /S /Strong - /P 4038 0 R - /K [71] - /Pg 4743 0 R ->> -endobj - -4050 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [69 70] - /Pg 4743 0 R ->> -endobj - -4051 0 obj -<< - /Type /StructElem - /S /H3 - /P 103 0 R - /T (Plugin Systems) - /K [67 68] - /Pg 4743 0 R ->> -endobj - -4052 0 obj -<< - /Type /StructElem - /S /H2 - /P 103 0 R - /T (Motivating Examples) - /K [65 66] - /Pg 4743 0 R ->> -endobj - -4053 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [51 52 4055 0 R 54 55 56 57 4054 0 R 59 60 61 62 63 64] - /Pg 4743 0 R ->> -endobj - -4054 0 obj -<< - /Type /StructElem - /S /Link - /P 4053 0 R - /K [58 << - /Type /OBJR - /Pg 4743 0 R - /Obj 4742 0 R - >>] - /Pg 4743 0 R ->> -endobj - -4055 0 obj -<< - /Type /StructElem - /S /Link - /P 4053 0 R - /K [53 << - /Type /OBJR - /Pg 4743 0 R - /Obj 4741 0 R - >>] - /Pg 4743 0 R ->> -endobj - -4056 0 obj -<< - /Type /StructElem - /S /L - /P 103 0 R - /A [<< - /O /List - /ListNumbering /Circle - >>] - /K [4062 0 R 4057 0 R] ->> -endobj - -4057 0 obj -<< - /Type /StructElem - /S /LI - /P 4056 0 R - /K [4061 0 R 4058 0 R] ->> -endobj - -4058 0 obj -<< - /Type /StructElem - /S /LBody - /P 4057 0 R - /K [4060 0 R 44 4059 0 R 46 47 48 49 50] - /Pg 4743 0 R ->> -endobj - -4059 0 obj -<< - /Type /StructElem - /S /Em - /P 4058 0 R - /K [45] - /Pg 4743 0 R ->> -endobj - -4060 0 obj -<< - /Type /StructElem - /S /Strong - /P 4058 0 R - /K [43] - /Pg 4743 0 R ->> -endobj - -4061 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4057 0 R - /K [42] - /Pg 4743 0 R ->> -endobj - -4062 0 obj -<< - /Type /StructElem - /S /LI - /P 4056 0 R - /K [4066 0 R 4063 0 R] ->> -endobj - -4063 0 obj -<< - /Type /StructElem - /S /LBody - /P 4062 0 R - /K [4065 0 R 35 4064 0 R 37 38 39 40 41] - /Pg 4743 0 R ->> -endobj - -4064 0 obj -<< - /Type /StructElem - /S /Em - /P 4063 0 R - /K [36] - /Pg 4743 0 R ->> -endobj - -4065 0 obj -<< - /Type /StructElem - /S /Strong - /P 4063 0 R - /K [34] - /Pg 4743 0 R ->> -endobj - -4066 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4062 0 R - /K [33] - /Pg 4743 0 R ->> -endobj - -4067 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [30 31 32] - /Pg 4743 0 R ->> -endobj - -4068 0 obj -<< - /Type /StructElem - /S /H2 - /P 103 0 R - /T (Dimensions of Composability) - /K [28 29] - /Pg 4743 0 R ->> -endobj - -4069 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [2 3 4 4074 0 R 6 7 4073 0 R 9 10 11 4072 0 R 13 14 15 4071 0 R 17 18 19 20 21 4070 0 R 23 24 25 26 27] - /Pg 4743 0 R ->> -endobj - -4070 0 obj -<< - /Type /StructElem - /S /Link - /P 4069 0 R - /K [22 << - /Type /OBJR - /Pg 4743 0 R - /Obj 4740 0 R - >>] - /Pg 4743 0 R ->> -endobj - -4071 0 obj -<< - /Type /StructElem - /S /Link - /P 4069 0 R - /K [16 << - /Type /OBJR - /Pg 4743 0 R - /Obj 4739 0 R - >>] - /Pg 4743 0 R ->> -endobj - -4072 0 obj -<< - /Type /StructElem - /S /Em - /P 4069 0 R - /K [12] - /Pg 4743 0 R ->> -endobj - -4073 0 obj -<< - /Type /StructElem - /S /Em - /P 4069 0 R - /K [8] - /Pg 4743 0 R ->> -endobj - -4074 0 obj -<< - /Type /StructElem - /S /Link - /P 4069 0 R - /K [5 << - /Type /OBJR - /Pg 4743 0 R - /Obj 4738 0 R - >>] - /Pg 4743 0 R ->> -endobj - -4075 0 obj -<< - /Type /StructElem - /S /H1 - /P 103 0 R - /T (Introduction) - /K [0 1] - /Pg 4743 0 R ->> -endobj - -4076 0 obj -<< - /Type /StructElem - /S /TOC - /P 103 0 R - /K [4285 0 R 4259 0 R 4255 0 R 4242 0 R 4238 0 R 4173 0 R 4169 0 R 4130 0 R 4126 0 R 4105 0 R 4101 0 R 4084 0 R 4080 0 R 4077 0 R] ->> -endobj - -4077 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4076 0 R - /K [4078 0 R] ->> -endobj - -4078 0 obj -<< - /Type /StructElem - /S /Reference - /P 4077 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4079 0 R] ->> -endobj - -4079 0 obj -<< - /Type /StructElem - /S /Link - /P 4078 0 R - /K [54 55 << - /Type /OBJR - /Pg 4736 0 R - /Obj 4735 0 R - >>] - /Pg 4736 0 R ->> -endobj - -4080 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4076 0 R - /K [4081 0 R] ->> -endobj - -4081 0 obj -<< - /Type /StructElem - /S /Reference - /P 4080 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4082 0 R] ->> -endobj - -4082 0 obj -<< - /Type /StructElem - /S /Link - /P 4081 0 R - /K [4083 0 R 52 53 << - /Type /OBJR - /Pg 4736 0 R - /Obj 4734 0 R - >>] - /Pg 4736 0 R ->> -endobj - -4083 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4082 0 R - /K [51] - /Pg 4736 0 R ->> -endobj - -4084 0 obj -<< - /Type /StructElem - /S /TOC - /P 4076 0 R - /K [4097 0 R 4093 0 R 4089 0 R 4085 0 R] ->> -endobj - -4085 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4084 0 R - /K [4086 0 R] ->> -endobj - -4086 0 obj -<< - /Type /StructElem - /S /Reference - /P 4085 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4087 0 R] ->> -endobj - -4087 0 obj -<< - /Type /StructElem - /S /Link - /P 4086 0 R - /K [4088 0 R 49 50 << - /Type /OBJR - /Pg 4736 0 R - /Obj 4733 0 R - >>] - /Pg 4736 0 R ->> -endobj - -4088 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4087 0 R - /K [48] - /Pg 4736 0 R ->> -endobj - -4089 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4084 0 R - /K [4090 0 R] ->> -endobj - -4090 0 obj -<< - /Type /StructElem - /S /Reference - /P 4089 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4091 0 R] ->> -endobj - -4091 0 obj -<< - /Type /StructElem - /S /Link - /P 4090 0 R - /K [4092 0 R 46 47 << - /Type /OBJR - /Pg 4736 0 R - /Obj 4732 0 R - >>] - /Pg 4736 0 R ->> -endobj - -4092 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4091 0 R - /K [45] - /Pg 4736 0 R ->> -endobj - -4093 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4084 0 R - /K [4094 0 R] ->> -endobj - -4094 0 obj -<< - /Type /StructElem - /S /Reference - /P 4093 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4095 0 R] ->> -endobj - -4095 0 obj -<< - /Type /StructElem - /S /Link - /P 4094 0 R - /K [4096 0 R 43 44 << - /Type /OBJR - /Pg 4736 0 R - /Obj 4731 0 R - >>] - /Pg 4736 0 R ->> -endobj - -4096 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4095 0 R - /K [42] - /Pg 4736 0 R ->> -endobj - -4097 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4084 0 R - /K [4098 0 R] ->> -endobj - -4098 0 obj -<< - /Type /StructElem - /S /Reference - /P 4097 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4099 0 R] ->> -endobj - -4099 0 obj -<< - /Type /StructElem - /S /Link - /P 4098 0 R - /K [4100 0 R 40 41 << - /Type /OBJR - /Pg 4736 0 R - /Obj 4730 0 R - >>] - /Pg 4736 0 R ->> -endobj - -4100 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4099 0 R - /K [39] - /Pg 4736 0 R ->> -endobj - -4101 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4076 0 R - /K [4102 0 R] ->> -endobj - -4102 0 obj -<< - /Type /StructElem - /S /Reference - /P 4101 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4103 0 R] ->> -endobj - -4103 0 obj -<< - /Type /StructElem - /S /Link - /P 4102 0 R - /K [4104 0 R 37 38 << - /Type /OBJR - /Pg 4736 0 R - /Obj 4729 0 R - >>] - /Pg 4736 0 R ->> -endobj - -4104 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4103 0 R - /K [36] - /Pg 4736 0 R ->> -endobj - -4105 0 obj -<< - /Type /StructElem - /S /TOC - /P 4076 0 R - /K [4122 0 R 4118 0 R 4114 0 R 4110 0 R 4106 0 R] ->> -endobj - -4106 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4105 0 R - /K [4107 0 R] ->> -endobj - -4107 0 obj -<< - /Type /StructElem - /S /Reference - /P 4106 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4108 0 R] ->> -endobj - -4108 0 obj -<< - /Type /StructElem - /S /Link - /P 4107 0 R - /K [4109 0 R 34 35 << - /Type /OBJR - /Pg 4736 0 R - /Obj 4728 0 R - >>] - /Pg 4736 0 R ->> -endobj - -4109 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4108 0 R - /K [33] - /Pg 4736 0 R ->> -endobj - -4110 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4105 0 R - /K [4111 0 R] ->> -endobj - -4111 0 obj -<< - /Type /StructElem - /S /Reference - /P 4110 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4112 0 R] ->> -endobj - -4112 0 obj -<< - /Type /StructElem - /S /Link - /P 4111 0 R - /K [4113 0 R 31 32 << - /Type /OBJR - /Pg 4736 0 R - /Obj 4727 0 R - >>] - /Pg 4736 0 R ->> -endobj - -4113 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4112 0 R - /K [30] - /Pg 4736 0 R ->> -endobj - -4114 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4105 0 R - /K [4115 0 R] ->> -endobj - -4115 0 obj -<< - /Type /StructElem - /S /Reference - /P 4114 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4116 0 R] ->> -endobj - -4116 0 obj -<< - /Type /StructElem - /S /Link - /P 4115 0 R - /K [4117 0 R 28 29 << - /Type /OBJR - /Pg 4736 0 R - /Obj 4726 0 R - >>] - /Pg 4736 0 R ->> -endobj - -4117 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4116 0 R - /K [27] - /Pg 4736 0 R ->> -endobj - -4118 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4105 0 R - /K [4119 0 R] ->> -endobj - -4119 0 obj -<< - /Type /StructElem - /S /Reference - /P 4118 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4120 0 R] ->> -endobj - -4120 0 obj -<< - /Type /StructElem - /S /Link - /P 4119 0 R - /K [4121 0 R 25 26 << - /Type /OBJR - /Pg 4736 0 R - /Obj 4725 0 R - >>] - /Pg 4736 0 R ->> -endobj - -4121 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4120 0 R - /K [24] - /Pg 4736 0 R ->> -endobj - -4122 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4105 0 R - /K [4123 0 R] ->> -endobj - -4123 0 obj -<< - /Type /StructElem - /S /Reference - /P 4122 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4124 0 R] ->> -endobj - -4124 0 obj -<< - /Type /StructElem - /S /Link - /P 4123 0 R - /K [4125 0 R 22 23 << - /Type /OBJR - /Pg 4736 0 R - /Obj 4724 0 R - >>] - /Pg 4736 0 R ->> -endobj - -4125 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4124 0 R - /K [21] - /Pg 4736 0 R ->> -endobj - -4126 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4076 0 R - /K [4127 0 R] ->> -endobj - -4127 0 obj -<< - /Type /StructElem - /S /Reference - /P 4126 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4128 0 R] ->> -endobj - -4128 0 obj -<< - /Type /StructElem - /S /Link - /P 4127 0 R - /K [4129 0 R 19 20 << - /Type /OBJR - /Pg 4736 0 R - /Obj 4723 0 R - >>] - /Pg 4736 0 R ->> -endobj - -4129 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4128 0 R - /K [18] - /Pg 4736 0 R ->> -endobj - -4130 0 obj -<< - /Type /StructElem - /S /TOC - /P 4076 0 R - /K [4165 0 R 4148 0 R 4144 0 R 4135 0 R 4131 0 R] ->> -endobj - -4131 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4130 0 R - /K [4132 0 R] ->> -endobj - -4132 0 obj -<< - /Type /StructElem - /S /Reference - /P 4131 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4133 0 R] ->> -endobj - -4133 0 obj -<< - /Type /StructElem - /S /Link - /P 4132 0 R - /K [4134 0 R 16 17 << - /Type /OBJR - /Pg 4736 0 R - /Obj 4722 0 R - >>] - /Pg 4736 0 R ->> -endobj - -4134 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4133 0 R - /K [15] - /Pg 4736 0 R ->> -endobj - -4135 0 obj -<< - /Type /StructElem - /S /TOC - /P 4130 0 R - /K [4140 0 R 4136 0 R] ->> -endobj - -4136 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4135 0 R - /K [4137 0 R] ->> -endobj - -4137 0 obj -<< - /Type /StructElem - /S /Reference - /P 4136 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4138 0 R] ->> -endobj - -4138 0 obj -<< - /Type /StructElem - /S /Link - /P 4137 0 R - /K [4139 0 R 13 14 << - /Type /OBJR - /Pg 4736 0 R - /Obj 4721 0 R - >>] - /Pg 4736 0 R ->> -endobj - -4139 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4138 0 R - /K [12] - /Pg 4736 0 R ->> -endobj - -4140 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4135 0 R - /K [4141 0 R] ->> -endobj - -4141 0 obj -<< - /Type /StructElem - /S /Reference - /P 4140 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4142 0 R] ->> -endobj - -4142 0 obj -<< - /Type /StructElem - /S /Link - /P 4141 0 R - /K [4143 0 R 10 11 << - /Type /OBJR - /Pg 4736 0 R - /Obj 4720 0 R - >>] - /Pg 4736 0 R ->> -endobj - -4143 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4142 0 R - /K [9] - /Pg 4736 0 R ->> -endobj - -4144 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4130 0 R - /K [4145 0 R] ->> -endobj - -4145 0 obj -<< - /Type /StructElem - /S /Reference - /P 4144 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4146 0 R] ->> -endobj - -4146 0 obj -<< - /Type /StructElem - /S /Link - /P 4145 0 R - /K [4147 0 R 7 8 << - /Type /OBJR - /Pg 4736 0 R - /Obj 4719 0 R - >>] - /Pg 4736 0 R ->> -endobj - -4147 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4146 0 R - /K [6] - /Pg 4736 0 R ->> -endobj - -4148 0 obj -<< - /Type /StructElem - /S /TOC - /P 4130 0 R - /K [4161 0 R 4157 0 R 4153 0 R 4149 0 R] ->> -endobj - -4149 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4148 0 R - /K [4150 0 R] ->> -endobj - -4150 0 obj -<< - /Type /StructElem - /S /Reference - /P 4149 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4151 0 R] ->> -endobj - -4151 0 obj -<< - /Type /StructElem - /S /Link - /P 4150 0 R - /K [4152 0 R 4 5 << - /Type /OBJR - /Pg 4736 0 R - /Obj 4718 0 R - >>] - /Pg 4736 0 R ->> -endobj - -4152 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4151 0 R - /K [3] - /Pg 4736 0 R ->> -endobj - -4153 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4148 0 R - /K [4154 0 R] ->> -endobj - -4154 0 obj -<< - /Type /StructElem - /S /Reference - /P 4153 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4155 0 R] ->> -endobj - -4155 0 obj -<< - /Type /StructElem - /S /Link - /P 4154 0 R - /K [<< - /Type /OBJR - /Pg 4715 0 R - /Obj 4714 0 R - >> 4156 0 R 1 2 << - /Type /OBJR - /Pg 4736 0 R - /Obj 4717 0 R - >>] - /Pg 4736 0 R ->> -endobj - -4156 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4155 0 R - /K [0] - /Pg 4736 0 R ->> -endobj - -4157 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4148 0 R - /K [4158 0 R] ->> -endobj - -4158 0 obj -<< - /Type /StructElem - /S /Reference - /P 4157 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4159 0 R] ->> -endobj - -4159 0 obj -<< - /Type /StructElem - /S /Link - /P 4158 0 R - /K [4160 0 R 92 93 << - /Type /OBJR - /Pg 4715 0 R - /Obj 4713 0 R - >>] - /Pg 4715 0 R ->> -endobj - -4160 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4159 0 R - /K [91] - /Pg 4715 0 R ->> -endobj - -4161 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4148 0 R - /K [4162 0 R] ->> -endobj - -4162 0 obj -<< - /Type /StructElem - /S /Reference - /P 4161 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4163 0 R] ->> -endobj - -4163 0 obj -<< - /Type /StructElem - /S /Link - /P 4162 0 R - /K [4164 0 R 89 90 << - /Type /OBJR - /Pg 4715 0 R - /Obj 4712 0 R - >>] - /Pg 4715 0 R ->> -endobj - -4164 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4163 0 R - /K [88] - /Pg 4715 0 R ->> -endobj - -4165 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4130 0 R - /K [4166 0 R] ->> -endobj - -4166 0 obj -<< - /Type /StructElem - /S /Reference - /P 4165 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4167 0 R] ->> -endobj - -4167 0 obj -<< - /Type /StructElem - /S /Link - /P 4166 0 R - /K [4168 0 R 86 87 << - /Type /OBJR - /Pg 4715 0 R - /Obj 4711 0 R - >>] - /Pg 4715 0 R ->> -endobj - -4168 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4167 0 R - /K [85] - /Pg 4715 0 R ->> -endobj - -4169 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4076 0 R - /K [4170 0 R] ->> -endobj - -4170 0 obj -<< - /Type /StructElem - /S /Reference - /P 4169 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4171 0 R] ->> -endobj - -4171 0 obj -<< - /Type /StructElem - /S /Link - /P 4170 0 R - /K [4172 0 R 83 84 << - /Type /OBJR - /Pg 4715 0 R - /Obj 4710 0 R - >>] - /Pg 4715 0 R ->> -endobj - -4172 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4171 0 R - /K [82] - /Pg 4715 0 R ->> -endobj - -4173 0 obj -<< - /Type /StructElem - /S /TOC - /P 4076 0 R - /K [4234 0 R 4225 0 R 4221 0 R 4208 0 R 4204 0 R 4187 0 R 4183 0 R 4174 0 R] ->> -endobj - -4174 0 obj -<< - /Type /StructElem - /S /TOC - /P 4173 0 R - /K [4179 0 R 4175 0 R] ->> -endobj - -4175 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4174 0 R - /K [4176 0 R] ->> -endobj - -4176 0 obj -<< - /Type /StructElem - /S /Reference - /P 4175 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4177 0 R] ->> -endobj - -4177 0 obj -<< - /Type /StructElem - /S /Link - /P 4176 0 R - /K [4178 0 R 80 81 << - /Type /OBJR - /Pg 4715 0 R - /Obj 4709 0 R - >>] - /Pg 4715 0 R ->> -endobj - -4178 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4177 0 R - /K [79] - /Pg 4715 0 R ->> -endobj - -4179 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4174 0 R - /K [4180 0 R] ->> -endobj - -4180 0 obj -<< - /Type /StructElem - /S /Reference - /P 4179 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4181 0 R] ->> -endobj - -4181 0 obj -<< - /Type /StructElem - /S /Link - /P 4180 0 R - /K [4182 0 R 77 78 << - /Type /OBJR - /Pg 4715 0 R - /Obj 4708 0 R - >>] - /Pg 4715 0 R ->> -endobj - -4182 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4181 0 R - /K [76] - /Pg 4715 0 R ->> -endobj - -4183 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4173 0 R - /K [4184 0 R] ->> -endobj - -4184 0 obj -<< - /Type /StructElem - /S /Reference - /P 4183 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4185 0 R] ->> -endobj - -4185 0 obj -<< - /Type /StructElem - /S /Link - /P 4184 0 R - /K [4186 0 R 74 75 << - /Type /OBJR - /Pg 4715 0 R - /Obj 4707 0 R - >>] - /Pg 4715 0 R ->> -endobj - -4186 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4185 0 R - /K [73] - /Pg 4715 0 R ->> -endobj - -4187 0 obj -<< - /Type /StructElem - /S /TOC - /P 4173 0 R - /K [4200 0 R 4196 0 R 4192 0 R 4188 0 R] ->> -endobj - -4188 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4187 0 R - /K [4189 0 R] ->> -endobj - -4189 0 obj -<< - /Type /StructElem - /S /Reference - /P 4188 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4190 0 R] ->> -endobj - -4190 0 obj -<< - /Type /StructElem - /S /Link - /P 4189 0 R - /K [4191 0 R 71 72 << - /Type /OBJR - /Pg 4715 0 R - /Obj 4706 0 R - >>] - /Pg 4715 0 R ->> -endobj - -4191 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4190 0 R - /K [70] - /Pg 4715 0 R ->> -endobj - -4192 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4187 0 R - /K [4193 0 R] ->> -endobj - -4193 0 obj -<< - /Type /StructElem - /S /Reference - /P 4192 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4194 0 R] ->> -endobj - -4194 0 obj -<< - /Type /StructElem - /S /Link - /P 4193 0 R - /K [4195 0 R 68 69 << - /Type /OBJR - /Pg 4715 0 R - /Obj 4705 0 R - >>] - /Pg 4715 0 R ->> -endobj - -4195 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4194 0 R - /K [67] - /Pg 4715 0 R ->> -endobj - -4196 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4187 0 R - /K [4197 0 R] ->> -endobj - -4197 0 obj -<< - /Type /StructElem - /S /Reference - /P 4196 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4198 0 R] ->> -endobj - -4198 0 obj -<< - /Type /StructElem - /S /Link - /P 4197 0 R - /K [4199 0 R 65 66 << - /Type /OBJR - /Pg 4715 0 R - /Obj 4704 0 R - >>] - /Pg 4715 0 R ->> -endobj - -4199 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4198 0 R - /K [64] - /Pg 4715 0 R ->> -endobj - -4200 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4187 0 R - /K [4201 0 R] ->> -endobj - -4201 0 obj -<< - /Type /StructElem - /S /Reference - /P 4200 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4202 0 R] ->> -endobj - -4202 0 obj -<< - /Type /StructElem - /S /Link - /P 4201 0 R - /K [4203 0 R 62 63 << - /Type /OBJR - /Pg 4715 0 R - /Obj 4703 0 R - >>] - /Pg 4715 0 R ->> -endobj - -4203 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4202 0 R - /K [61] - /Pg 4715 0 R ->> -endobj - -4204 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4173 0 R - /K [4205 0 R] ->> -endobj - -4205 0 obj -<< - /Type /StructElem - /S /Reference - /P 4204 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4206 0 R] ->> -endobj - -4206 0 obj -<< - /Type /StructElem - /S /Link - /P 4205 0 R - /K [4207 0 R 59 60 << - /Type /OBJR - /Pg 4715 0 R - /Obj 4702 0 R - >>] - /Pg 4715 0 R ->> -endobj - -4207 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4206 0 R - /K [58] - /Pg 4715 0 R ->> -endobj - -4208 0 obj -<< - /Type /StructElem - /S /TOC - /P 4173 0 R - /K [4217 0 R 4213 0 R 4209 0 R] ->> -endobj - -4209 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4208 0 R - /K [4210 0 R] ->> -endobj - -4210 0 obj -<< - /Type /StructElem - /S /Reference - /P 4209 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4211 0 R] ->> -endobj - -4211 0 obj -<< - /Type /StructElem - /S /Link - /P 4210 0 R - /K [4212 0 R 56 57 << - /Type /OBJR - /Pg 4715 0 R - /Obj 4701 0 R - >>] - /Pg 4715 0 R ->> -endobj - -4212 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4211 0 R - /K [55] - /Pg 4715 0 R ->> -endobj - -4213 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4208 0 R - /K [4214 0 R] ->> -endobj - -4214 0 obj -<< - /Type /StructElem - /S /Reference - /P 4213 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4215 0 R] ->> -endobj - -4215 0 obj -<< - /Type /StructElem - /S /Link - /P 4214 0 R - /K [4216 0 R 53 54 << - /Type /OBJR - /Pg 4715 0 R - /Obj 4700 0 R - >>] - /Pg 4715 0 R ->> -endobj - -4216 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4215 0 R - /K [52] - /Pg 4715 0 R ->> -endobj - -4217 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4208 0 R - /K [4218 0 R] ->> -endobj - -4218 0 obj -<< - /Type /StructElem - /S /Reference - /P 4217 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4219 0 R] ->> -endobj - -4219 0 obj -<< - /Type /StructElem - /S /Link - /P 4218 0 R - /K [4220 0 R 50 51 << - /Type /OBJR - /Pg 4715 0 R - /Obj 4699 0 R - >>] - /Pg 4715 0 R ->> -endobj - -4220 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4219 0 R - /K [49] - /Pg 4715 0 R ->> -endobj - -4221 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4173 0 R - /K [4222 0 R] ->> -endobj - -4222 0 obj -<< - /Type /StructElem - /S /Reference - /P 4221 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4223 0 R] ->> -endobj - -4223 0 obj -<< - /Type /StructElem - /S /Link - /P 4222 0 R - /K [4224 0 R 47 48 << - /Type /OBJR - /Pg 4715 0 R - /Obj 4698 0 R - >>] - /Pg 4715 0 R ->> -endobj - -4224 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4223 0 R - /K [46] - /Pg 4715 0 R ->> -endobj - -4225 0 obj -<< - /Type /StructElem - /S /TOC - /P 4173 0 R - /K [4230 0 R 4226 0 R] ->> -endobj - -4226 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4225 0 R - /K [4227 0 R] ->> -endobj - -4227 0 obj -<< - /Type /StructElem - /S /Reference - /P 4226 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4228 0 R] ->> -endobj - -4228 0 obj -<< - /Type /StructElem - /S /Link - /P 4227 0 R - /K [4229 0 R 44 45 << - /Type /OBJR - /Pg 4715 0 R - /Obj 4697 0 R - >>] - /Pg 4715 0 R ->> -endobj - -4229 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4228 0 R - /K [43] - /Pg 4715 0 R ->> -endobj - -4230 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4225 0 R - /K [4231 0 R] ->> -endobj - -4231 0 obj -<< - /Type /StructElem - /S /Reference - /P 4230 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4232 0 R] ->> -endobj - -4232 0 obj -<< - /Type /StructElem - /S /Link - /P 4231 0 R - /K [4233 0 R 41 42 << - /Type /OBJR - /Pg 4715 0 R - /Obj 4696 0 R - >>] - /Pg 4715 0 R ->> -endobj - -4233 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4232 0 R - /K [40] - /Pg 4715 0 R ->> -endobj - -4234 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4173 0 R - /K [4235 0 R] ->> -endobj - -4235 0 obj -<< - /Type /StructElem - /S /Reference - /P 4234 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4236 0 R] ->> -endobj - -4236 0 obj -<< - /Type /StructElem - /S /Link - /P 4235 0 R - /K [4237 0 R 38 39 << - /Type /OBJR - /Pg 4715 0 R - /Obj 4695 0 R - >>] - /Pg 4715 0 R ->> -endobj - -4237 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4236 0 R - /K [37] - /Pg 4715 0 R ->> -endobj - -4238 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4076 0 R - /K [4239 0 R] ->> -endobj - -4239 0 obj -<< - /Type /StructElem - /S /Reference - /P 4238 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4240 0 R] ->> -endobj - -4240 0 obj -<< - /Type /StructElem - /S /Link - /P 4239 0 R - /K [4241 0 R 35 36 << - /Type /OBJR - /Pg 4715 0 R - /Obj 4694 0 R - >>] - /Pg 4715 0 R ->> -endobj - -4241 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4240 0 R - /K [34] - /Pg 4715 0 R ->> -endobj - -4242 0 obj -<< - /Type /StructElem - /S /TOC - /P 4076 0 R - /K [4251 0 R 4247 0 R 4243 0 R] ->> -endobj - -4243 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4242 0 R - /K [4244 0 R] ->> -endobj - -4244 0 obj -<< - /Type /StructElem - /S /Reference - /P 4243 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4245 0 R] ->> -endobj - -4245 0 obj -<< - /Type /StructElem - /S /Link - /P 4244 0 R - /K [4246 0 R 32 33 << - /Type /OBJR - /Pg 4715 0 R - /Obj 4693 0 R - >>] - /Pg 4715 0 R ->> -endobj - -4246 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4245 0 R - /K [31] - /Pg 4715 0 R ->> -endobj - -4247 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4242 0 R - /K [4248 0 R] ->> -endobj - -4248 0 obj -<< - /Type /StructElem - /S /Reference - /P 4247 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4249 0 R] ->> -endobj - -4249 0 obj -<< - /Type /StructElem - /S /Link - /P 4248 0 R - /K [4250 0 R 29 30 << - /Type /OBJR - /Pg 4715 0 R - /Obj 4692 0 R - >>] - /Pg 4715 0 R ->> -endobj - -4250 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4249 0 R - /K [28] - /Pg 4715 0 R ->> -endobj - -4251 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4242 0 R - /K [4252 0 R] ->> -endobj - -4252 0 obj -<< - /Type /StructElem - /S /Reference - /P 4251 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4253 0 R] ->> -endobj - -4253 0 obj -<< - /Type /StructElem - /S /Link - /P 4252 0 R - /K [4254 0 R 26 27 << - /Type /OBJR - /Pg 4715 0 R - /Obj 4691 0 R - >>] - /Pg 4715 0 R ->> -endobj - -4254 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4253 0 R - /K [25] - /Pg 4715 0 R ->> -endobj - -4255 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4076 0 R - /K [4256 0 R] ->> -endobj - -4256 0 obj -<< - /Type /StructElem - /S /Reference - /P 4255 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4257 0 R] ->> -endobj - -4257 0 obj -<< - /Type /StructElem - /S /Link - /P 4256 0 R - /K [4258 0 R 23 24 << - /Type /OBJR - /Pg 4715 0 R - /Obj 4690 0 R - >>] - /Pg 4715 0 R ->> -endobj - -4258 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4257 0 R - /K [22] - /Pg 4715 0 R ->> -endobj - -4259 0 obj -<< - /Type /StructElem - /S /TOC - /P 4076 0 R - /K [4281 0 R 4277 0 R 4264 0 R 4260 0 R] ->> -endobj - -4260 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4259 0 R - /K [4261 0 R] ->> -endobj - -4261 0 obj -<< - /Type /StructElem - /S /Reference - /P 4260 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4262 0 R] ->> -endobj - -4262 0 obj -<< - /Type /StructElem - /S /Link - /P 4261 0 R - /K [4263 0 R 20 21 << - /Type /OBJR - /Pg 4715 0 R - /Obj 4689 0 R - >>] - /Pg 4715 0 R ->> -endobj - -4263 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4262 0 R - /K [19] - /Pg 4715 0 R ->> -endobj - -4264 0 obj -<< - /Type /StructElem - /S /TOC - /P 4259 0 R - /K [4273 0 R 4269 0 R 4265 0 R] ->> -endobj - -4265 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4264 0 R - /K [4266 0 R] ->> -endobj - -4266 0 obj -<< - /Type /StructElem - /S /Reference - /P 4265 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4267 0 R] ->> -endobj - -4267 0 obj -<< - /Type /StructElem - /S /Link - /P 4266 0 R - /K [4268 0 R 17 18 << - /Type /OBJR - /Pg 4715 0 R - /Obj 4688 0 R - >>] - /Pg 4715 0 R ->> -endobj - -4268 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4267 0 R - /K [16] - /Pg 4715 0 R ->> -endobj - -4269 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4264 0 R - /K [4270 0 R] ->> -endobj - -4270 0 obj -<< - /Type /StructElem - /S /Reference - /P 4269 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4271 0 R] ->> -endobj - -4271 0 obj -<< - /Type /StructElem - /S /Link - /P 4270 0 R - /K [4272 0 R 14 15 << - /Type /OBJR - /Pg 4715 0 R - /Obj 4687 0 R - >>] - /Pg 4715 0 R ->> -endobj - -4272 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4271 0 R - /K [13] - /Pg 4715 0 R ->> -endobj - -4273 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4264 0 R - /K [4274 0 R] ->> -endobj - -4274 0 obj -<< - /Type /StructElem - /S /Reference - /P 4273 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4275 0 R] ->> -endobj - -4275 0 obj -<< - /Type /StructElem - /S /Link - /P 4274 0 R - /K [4276 0 R 11 12 << - /Type /OBJR - /Pg 4715 0 R - /Obj 4686 0 R - >>] - /Pg 4715 0 R ->> -endobj - -4276 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4275 0 R - /K [10] - /Pg 4715 0 R ->> -endobj - -4277 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4259 0 R - /K [4278 0 R] ->> -endobj - -4278 0 obj -<< - /Type /StructElem - /S /Reference - /P 4277 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4279 0 R] ->> -endobj - -4279 0 obj -<< - /Type /StructElem - /S /Link - /P 4278 0 R - /K [4280 0 R 8 9 << - /Type /OBJR - /Pg 4715 0 R - /Obj 4685 0 R - >>] - /Pg 4715 0 R ->> -endobj - -4280 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4279 0 R - /K [7] - /Pg 4715 0 R ->> -endobj - -4281 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4259 0 R - /K [4282 0 R] ->> -endobj - -4282 0 obj -<< - /Type /StructElem - /S /Reference - /P 4281 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4283 0 R] ->> -endobj - -4283 0 obj -<< - /Type /StructElem - /S /Link - /P 4282 0 R - /K [4284 0 R 5 6 << - /Type /OBJR - /Pg 4715 0 R - /Obj 4684 0 R - >>] - /Pg 4715 0 R ->> -endobj - -4284 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4283 0 R - /K [4] - /Pg 4715 0 R ->> -endobj - -4285 0 obj -<< - /Type /StructElem - /S /TOCI - /P 4076 0 R - /K [4286 0 R] ->> -endobj - -4286 0 obj -<< - /Type /StructElem - /S /Reference - /P 4285 0 R - /A [<< - /O /Layout - /Placement /Block - >>] - /K [4287 0 R] ->> -endobj - -4287 0 obj -<< - /Type /StructElem - /S /Link - /P 4286 0 R - /K [4288 0 R 2 3 << - /Type /OBJR - /Pg 4715 0 R - /Obj 4683 0 R - >>] - /Pg 4715 0 R ->> -endobj - -4288 0 obj -<< - /Type /StructElem - /S /Lbl - /P 4287 0 R - /K [1] - /Pg 4715 0 R ->> -endobj - -4289 0 obj -<< - /Type /StructElem - /S /H1 - /P 103 0 R - /T (Contents) - /K [0] - /Pg 4715 0 R ->> -endobj - -4290 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [12 13 4296 0 R 15 16 4295 0 R 18 19 4294 0 R 21 22 23 4293 0 R 25 26 27 4292 0 R 29 30 31 32 33 34 35 4291 0 R 37 38 39] - /Pg 4681 0 R ->> -endobj - -4291 0 obj -<< - /Type /StructElem - /S /Em - /P 4290 0 R - /K [36] - /Pg 4681 0 R ->> -endobj - -4292 0 obj -<< - /Type /StructElem - /S /Em - /P 4290 0 R - /K [28] - /Pg 4681 0 R ->> -endobj - -4293 0 obj -<< - /Type /StructElem - /S /Em - /P 4290 0 R - /K [24] - /Pg 4681 0 R ->> -endobj - -4294 0 obj -<< - /Type /StructElem - /S /Em - /P 4290 0 R - /K [20] - /Pg 4681 0 R ->> -endobj - -4295 0 obj -<< - /Type /StructElem - /S /Em - /P 4290 0 R - /K [17] - /Pg 4681 0 R ->> -endobj - -4296 0 obj -<< - /Type /StructElem - /S /Em - /P 4290 0 R - /K [14] - /Pg 4681 0 R ->> -endobj - -4297 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [11] - /Pg 4681 0 R ->> -endobj - -4298 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [4300 0 R 8 4299 0 R 10] - /Pg 4681 0 R ->> -endobj - -4299 0 obj -<< - /Type /StructElem - /S /Span - /P 4298 0 R - /A [<< - /O /Layout - /BaselineShift 3.1614 - /LineHeight 3.96 - >>] - /K [9] - /Pg 4681 0 R ->> -endobj - -4300 0 obj -<< - /Type /StructElem - /S /Span - /P 4298 0 R - /A [<< - /O /Layout - /BaselineShift 3.1614 - /LineHeight 3.96 - >>] - /K [7] - /Pg 4681 0 R ->> -endobj - -4301 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [1 4304 0 R 3 4303 0 R 5 4302 0 R] - /Pg 4681 0 R ->> -endobj - -4302 0 obj -<< - /Type /StructElem - /S /Span - /P 4301 0 R - /A [<< - /O /Layout - /BaselineShift 3.1614 - /LineHeight 3.96 - >>] - /K [6] - /Pg 4681 0 R ->> -endobj - -4303 0 obj -<< - /Type /StructElem - /S /Span - /P 4301 0 R - /A [<< - /O /Layout - /BaselineShift 3.1614 - /LineHeight 3.96 - >>] - /K [4] - /Pg 4681 0 R ->> -endobj - -4304 0 obj -<< - /Type /StructElem - /S /Span - /P 4301 0 R - /A [<< - /O /Layout - /BaselineShift 3.1614 - /LineHeight 3.96 - >>] - /K [2] - /Pg 4681 0 R ->> -endobj - -4305 0 obj -<< - /Type /StructElem - /S /P - /P 103 0 R - /K [0] - /Pg 4681 0 R ->> -endobj - -4306 0 obj -<< - /Type /PageLabel - /S /D - /St 1 ->> -endobj - -4307 0 obj -<< - /Type /PageLabel - /S /D - /St 2 ->> -endobj - -4308 0 obj -<< - /Type /PageLabel - /S /D - /St 3 ->> -endobj - -4309 0 obj -<< - /Type /PageLabel - /S /D - /St 4 ->> -endobj - -4310 0 obj -<< - /Type /PageLabel - /S /D - /St 5 ->> -endobj - -4311 0 obj -<< - /Type /PageLabel - /S /D - /St 6 ->> -endobj - -4312 0 obj -<< - /Type /PageLabel - /S /D - /St 7 ->> -endobj - -4313 0 obj -<< - /Type /PageLabel - /S /D - /St 8 ->> -endobj - -4314 0 obj -<< - /Type /PageLabel - /S /D - /St 9 ->> -endobj - -4315 0 obj -<< - /Type /PageLabel - /S /D - /St 10 ->> -endobj - -4316 0 obj -<< - /Type /PageLabel - /S /D - /St 11 ->> -endobj - -4317 0 obj -<< - /Type /PageLabel - /S /D - /St 12 ->> -endobj - -4318 0 obj -<< - /Type /PageLabel - /S /D - /St 13 ->> -endobj - -4319 0 obj -<< - /Type /PageLabel - /S /D - /St 14 ->> -endobj - -4320 0 obj -<< - /Type /PageLabel - /S /D - /St 15 ->> -endobj - -4321 0 obj -<< - /Type /PageLabel - /S /D - /St 16 ->> -endobj - -4322 0 obj -<< - /Type /PageLabel - /S /D - /St 17 ->> -endobj - -4323 0 obj -<< - /Type /PageLabel - /S /D - /St 18 ->> -endobj - -4324 0 obj -<< - /Type /PageLabel - /S /D - /St 19 ->> -endobj - -4325 0 obj -<< - /Type /PageLabel - /S /D - /St 20 ->> -endobj - -4326 0 obj -<< - /Type /PageLabel - /S /D - /St 21 ->> -endobj - -4327 0 obj -<< - /Type /PageLabel - /S /D - /St 22 ->> -endobj - -4328 0 obj -<< - /Type /PageLabel - /S /D - /St 23 ->> -endobj - -4329 0 obj -<< - /Type /PageLabel - /S /D - /St 24 ->> -endobj - -4330 0 obj -<< - /Type /PageLabel - /S /D - /St 25 ->> -endobj - -4331 0 obj -<< - /Type /PageLabel - /S /D - /St 26 ->> -endobj - -4332 0 obj -<< - /Type /PageLabel - /S /D - /St 27 ->> -endobj - -4333 0 obj -<< - /Type /PageLabel - /S /D - /St 28 ->> -endobj - -4334 0 obj -<< - /Type /PageLabel - /S /D - /St 29 ->> -endobj - -4335 0 obj -<< - /Type /PageLabel - /S /D - /St 30 ->> -endobj - -4336 0 obj -<< - /Type /PageLabel - /S /D - /St 31 ->> -endobj - -4337 0 obj -<< - /Type /PageLabel - /S /D - /St 32 ->> -endobj - -4338 0 obj -<< - /Type /PageLabel - /S /D - /St 33 ->> -endobj - -4339 0 obj -<< - /Type /PageLabel - /S /D - /St 34 ->> -endobj - -4340 0 obj -<< - /Type /PageLabel - /S /D - /St 35 ->> -endobj - -4341 0 obj -<< - /Type /PageLabel - /S /D - /St 36 ->> -endobj - -4342 0 obj -<< - /Type /PageLabel - /S /D - /St 37 ->> -endobj - -4343 0 obj -<< - /Type /PageLabel - /S /D - /St 38 ->> -endobj - -4344 0 obj -<< - /Type /PageLabel - /S /D - /St 39 ->> -endobj - -4345 0 obj -<< - /Type /PageLabel - /S /D - /St 40 ->> -endobj - -4346 0 obj -<< - /Type /PageLabel - /S /D - /St 41 ->> -endobj - -4347 0 obj -<< - /Type /PageLabel - /S /D - /St 42 ->> -endobj - -4348 0 obj -<< - /Type /PageLabel - /S /D - /St 43 ->> -endobj - -4349 0 obj -<< - /Type /PageLabel - /S /D - /St 44 ->> -endobj - -4350 0 obj -<< - /Type /PageLabel - /S /D - /St 45 ->> -endobj - -4351 0 obj -<< - /Type /PageLabel - /S /D - /St 46 ->> -endobj - -4352 0 obj -<< - /Type /PageLabel - /S /D - /St 47 ->> -endobj - -4353 0 obj -<< - /Type /PageLabel - /S /D - /St 48 ->> -endobj - -4354 0 obj -<< - /Type /Font - /Subtype /Type0 - /BaseFont /PGOLQH+TeXGyrePagella-Bold-Identity-H - /Encoding /Identity-H - /DescendantFonts [4355 0 R] - /ToUnicode 4358 0 R ->> -endobj - -4355 0 obj -<< - /Type /Font - /Subtype /CIDFontType0 - /BaseFont /PGOLQH+TeXGyrePagella-Bold - /CIDSystemInfo << - /Registry (Adobe) - /Ordering (Identity) - /Supplement 0 - >> - /FontDescriptor 4357 0 R - /DW 0 - /W [0 0 500 1 1 778 2 2 250 3 3 611 4 4 389 5 6 556 7 7 500 8 8 889 9 9 333 10 11 611 12 12 389 13 14 611 15 15 333 16 16 500 17 17 333 18 18 722 19 19 444 20 20 611 21 21 556 22 22 500 23 23 611 24 24 778 25 25 556 26 26 500 27 27 833 28 28 333 29 29 389 30 30 444 31 31 250 32 32 611 33 35 500 36 36 722 37 37 611 38 38 709 39 41 500 42 42 1000 43 43 667 44 44 1000 45 45 500 46 46 833 47 48 611 49 50 500 51 51 611 52 52 833 53 53 500 54 55 490 56 56 510.99997 57 57 833 58 58 250 59 59 833 60 60 250 61 62 778] ->> -endobj - -4356 0 obj -<< - /Length 13 - /Filter /FlateDecode ->> -stream -x # -endstream -endobj - -4357 0 obj -<< - /Type /FontDescriptor - /FontName /PGOLQH+TeXGyrePagella-Bold - /Flags 131076 - /FontBBox [10 -266 988 747] - /ItalicAngle 0 - /Ascent 720 - /Descent -258 - /CapHeight 681 - /StemV 168.6 - /CIDSet 4356 0 R - /FontFile3 4359 0 R ->> -endobj - -4358 0 obj -<< - /Length 1482 - /Type /CMap - /WMode 0 ->> -stream -%!PS-Adobe-3.0 Resource-CMap -%%DocumentNeededResources: procset CIDInit -%%IncludeResource: procset CIDInit -%%BeginResource: CMap Custom -%%Title: (Custom Adobe Identity 0) -%%Version: 1 -%%EndComments -/CIDInit /ProcSet findresource begin -12 dict begin -begincmap -/CIDSystemInfo 3 dict dup begin - /Registry (Adobe) def - /Ordering (Identity) def - /Supplement 0 def -end def -/CMapName /Custom def -/CMapVersion 1 def -/CMapType 0 def -/WMode 0 def -1 begincodespacerange -<0000> -endcodespacerange -62 beginbfchar -<0001> <0041> -<0002> <0020> -<0003> <0050> -<0004> <0072> -<0005> <006F> -<0006> <0067> -<0007> <0061> -<0008> <006D> -<0009> <0069> -<000A> <006E> -<000B> <0064> -<000C> <0066> -<000D> <0053> -<000E> <0070> -<000F> <0074> -<0010> <0065> -<0011> <006C> -<0012> <0043> -<0013> <0073> -<0014> <0062> -<0015> <0079> -<0016> <0031> -<0017> <006B> -<0018> <0055> -<0019> <0076> -<001A> <0032> -<001B> <0044> -<001C> <002D> -<001D> <0049> -<001E> <0063> -<001F> <002E> -<0020> <0075> -<0021> <0034> -<0022> <0037> -<0023> <0033> -<0024> <0052> -<0025> <0045> -<0026> <00660066> -<0027> <0039> -<0028> <0035> -<0029> <0036> -<002A> <0057> -<002B> <0054> -<002C> <004D> -<002D> <0078> -<002E> <0047> -<002F> <0068> -<0030> <00660069> -<0031> <0038> -<0032> <0030> -<0033> <004C> -<0034> <0048> -<0035> <007A> -<0036> <0028> -<0037> <0029> -<0038> <002F> -<0039> <004F> -<003A> <00A0> -<003B> <0077> -<003C> <003A> -<003D> <004B> -<003E> <0056> -endbfchar -endcmap -CMapName currentdict /CMap defineresource pop -end -end -%%EndResource -%%EOF -endstream -endobj - -4359 0 obj -<< - /Length 6443 - /Filter /FlateDecode - /Subtype /CIDFontType0C ->> -stream -xY TS׺N74OQVm8kE<"3$0Ϩ FAԶõRZǷy}u>}_1cBpe]l|<0U!^0ZDf*X<)czT@h3幩-6KfJl"Lڶ+d|<8/2vuHhlod;C­.VB1VY7yYm4#<Y - + -qۭoqܺyVN~` y#3Ra-[yxyɽLy#Wn;O xJ ,5*&ǔ4 ֘Bl(ߒْq_3 $>}<^ΕysL7B~0KKD];vh܆q>%nl~y>ugӞ5wson3wj| ]M|o N/|5ysMqrt{SMyUg'Á>QƘf}#ky PpŐqIRh hEbZQ58}|w:)OLGhIHVB[l[?٧A -?l"q.TaSW+yqyi&CCwZeUPXA+tȓD^$G8C@rbc*.9ԦVBJ"eqǍS p -zQFlG ~y_Ź?f؂ Nړ4acu3dRfpݳݸ~0ϼUGj6_N86ɮ`33 ]R*>*8L*pp{{]]aA gΑ1} -]Mە` ޅa)Mt#$EA4)IaJ[+*p$Y ־lki]KNRюrQ%kBd]XJ>_Ն.8C6T|m0d]DTRSQU5-cDj2 -~[f+II`mmڡ>>]Av1]KyJQZC崫8FATB+vlI݃)ʇ`NUP dIAGKel3S4P cЩ:f!?iuyY2+?K;@6Sk!1|'\tt_tD06wFQ*j|xK]Хz<0 -cH<9VN+tƳ6`54ȃ|d҅rJʿ"]8k'cZMApJKؑ;!"kCچqw^7Ǟe͝h(Nt`Ϧ_cO3V(0g~>◾-πRe%V -LCBC)qt.b ^htⲬ)(NvXvLv]>XMvӐ0ul"O*JU8^:3QErnA(Ψ%pe%kCD&M3-쨻8,6:?Bu*iJw['?0?mëh>שUt~{V5efdeE@-K'{ntŶxS~q;8;{f7sY'6 hAᡸ@p^u6} VdM҅,߀_.i6ݣ,?qUG\f^&(*?tY?/eק';QKtɠ$գH ~$y'jh(m:ܽo֯*}CgTt(e+ :ͧgRITr"%8U9 \h{͝Q*a~+ضVƝ7~1$<ZEEo+2_ P5ܭm͐RUw2v# 7{\En;4|ao=@͸]d(o=(bK=ZO;;jrUv90 Àק=WNM3Lu-33&Lm&j)~ 뚳98&&uebM T[-SA h'Fs6ݧ{fNqEY&>/2 %×vꋁֵͬ!])叁FGk!pQpFT}}J̞F -\˰K _h]YԠ+*9K-\ t1L;;MXnš)=Ecs8+U .jgYE*%)UŖSF>RҕWUPCqCZZkZe*_`Z%)RA -$*l #UŐy9b5m7-]GnZz?45`N⺪ka - 554SG6U\8oomi,[lPOrj`K)c)Z(F\Wk 4 "I愺_/\^-~rNU1 % -;\#85k o|O WjKԇ^׮=,u5pUg)a >'74Ӕ<$7?я$B6pF/eM^[Kve4pZ3m>x'S{xЀѱYdX-p!ΐ!N#~ 2r'n<~βZ4{K39]C1VHvDeB"s u - t! {p43O8 M1-:[Lzf폲Ȯ(gI$ߘ >;wN tHR'hhJlK0=;VSzf&/e3d8;[ʷn#Ɲƚq< -(qܽ˗.9$8 E/g,!(>f }k}>Q@@Hwrg`맃:-Vڈ!J'#Mǀw|mekwJ3w 878KyX\~wPeS -h-kn W r WEKjj_&VêTHdU"5Ʒ&6FM6} 9UB)7aMG<m -kch¢Wv9mEm3ű#1fRx?+bO[DsM۔s t 3%6RT?8,N՛`A%nY -ܢ`|F"H=Ѭ;+p^JYHD/\Phdm2[xB<*OO r"AEi9PmιW79>D-4@YBzMaO1+~pI߰ZSjRUKlq64Źwь5 jj+f6SF.)+Ө-Щӯ=dރVh{< yl:&˾k(* 9QܡܡK*Jҡ,N0&]b݁Wy5_Y^ḓΔm\]"Pl ,P%=Y,)'b8ХDMf6 ]$u@jcv['UFqx>]'3ve"=ynŵ ~ez]$I)/7Z=~bOqe~GkpWh.}U{K)7|k/ZD2Xs])w5unN(_ tdNh ɖSvoG|7SNި ; -Mll'l@ :DԀ<8;gKHP' >pj{*X[omMX -LJQr|*DP8 -%~E6-&L7D| -p6x`!UzOZ^HLuN1퉗`%j7L ;0M4|BLf<$vي#1 f!"5m?V >` ^(MznmmNG2IDW5F Er11MB&ql -2/ǣ7l=2asuї.;YhAo-%@t]>]fs؜Ye`siD1?>;SOקҳpι/d,|9i飯L`%`N ,-7lPS.B(THlv<: Q}`qCƻCB!o٢g8q8 -0CDY`d+هyFWWkKY&AǺ9^d34Sǁ&w)Ep(4.*/9'<2:>|!Φ8}@vӑXH - -ԴZ)U~j?SaI -Le*Tԇr /퀅ٞ=*K:Z/zLӹ)Tnn&Ƴcho<::^LC5ƇϏv:0rI*> e* P$ C]Be;#?Kn -?aI|T)KbPLx HaC~cQ=E/c)/,<!D(('ʬOƉ$h r rԴ4Qr'pV;Il HK -endstream -endobj - -4360 0 obj -<< - /Type /Font - /Subtype /Type0 - /BaseFont /HRSIWM+TeXGyrePagella-Regular-Identity-H - /Encoding /Identity-H - /DescendantFonts [4361 0 R] - /ToUnicode 4364 0 R ->> -endobj - -4361 0 obj -<< - /Type /Font - /Subtype /CIDFontType0 - /BaseFont /HRSIWM+TeXGyrePagella-Regular - /CIDSystemInfo << - /Registry (Adobe) - /Ordering (Identity) - /Supplement 0 - >> - /FontDescriptor 4363 0 R - /DW 0 - /W [0 0 500 1 1 667 2 2 287 3 3 333 4 4 500 5 5 582 6 6 250 7 7 525 8 8 582 9 9 500 10 10 250 11 11 500 12 12 1000 13 13 479 14 14 667 15 15 556 16 16 613 17 17 556 18 18 709 19 19 603 20 20 946 21 21 546 22 22 611 23 23 395 24 24 424 25 25 326 26 26 834 27 27 1000 28 28 883 29 29 601 30 30 291 31 31 333 32 32 565 33 33 444 34 34 560 35 35 250 36 36 553 37 37 250 38 38 278 39 39 623 40 40 500 41 41 516 42 42 556 43 43 778 44 44 608 45 45 605 46 46 774 47 47 500 48 48 611 49 49 604 50 50 832 51 52 500 53 53 763 54 55 500 56 56 668 57 58 500 59 59 556 60 60 831 61 61 337 62 62 611 63 63 500 64 64 778 65 65 786 66 66 726 67 67 722 68 69 428 70 70 560 71 72 456 73 73 250 74 74 897 75 75 500 76 76 611 77 77 333 78 78 250 79 79 234 80 80 486 81 82 500 83 83 208 84 84 480 85 85 500 86 87 441 88 88 500 89 89 278 90 90 208 91 91 786 92 92 667 93 93 444 94 94 486 95 95 278 96 96 747 97 97 371 98 98 500 99 99 479 100 100 603] ->> -endobj - -4362 0 obj -<< - /Length 13 - /Filter /FlateDecode ->> -stream -x~Z -endstream -endobj - -4363 0 obj -<< - /Type /FontDescriptor - /FontName /HRSIWM+TeXGyrePagella-Regular - /Flags 131076 - /FontBBox [-40 -283 1000 750] - /ItalicAngle 0 - /Ascent 726 - /Descent -281 - /CapHeight 692 - /StemV 95.4 - /CIDSet 4362 0 R - /FontFile3 4365 0 R ->> -endobj - -4364 0 obj -<< - /Length 2027 - /Type /CMap - /WMode 0 ->> -stream -%!PS-Adobe-3.0 Resource-CMap -%%DocumentNeededResources: procset CIDInit -%%IncludeResource: procset CIDInit -%%BeginResource: CMap Custom -%%Title: (Custom Adobe Identity 0) -%%Version: 1 -%%EndComments -/CIDInit /ProcSet findresource begin -12 dict begin -begincmap -/CIDSystemInfo 3 dict dup begin - /Registry (Adobe) def - /Ordering (Identity) def - /Supplement 0 def -end def -/CMapName /Custom def -/CMapVersion 1 def -/CMapType 0 def -/WMode 0 def -1 begincodespacerange -<0000> -endcodespacerange -100 beginbfchar -<0001> <0059> -<0002> <0069> -<0003> <0066> -<0004> <0061> -<0005> <006E> -<0006> <0020> -<0007> <0053> -<0008> <0068> -<0009> <0031> -<000A> <002C> -<000B> <0032> -<000C> <0057> -<000D> <0065> -<000E> <005A> -<000F> <0067> -<0010> <0054> -<0011> <0079> -<0012> <0043> -<0013> <0075> -<0014> <004D> -<0015> <006F> -<0016> <0064> -<0017> <0072> -<0018> <0073> -<0019> <0074> -<001A> <0077> -<001B> <2014> -<001C> <006D> -<001D> <0070> -<001E> <006C> -<001F> <002D> -<0020> <0076> -<0021> <0063> -<0022> <0071> -<0023> <002E> -<0024> <0062> -<0025> <003A> -<0026> <2019> -<0027> <00660066> -<0028> <007A> -<0029> <0078> -<002A> <006B> -<002B> <0041> -<002C> <0066006C> -<002D> <00660069> -<002E> <0044> -<002F> <0034> -<0030> <0045> -<0031> <0050> -<0032> <0048> -<0033> <0035> -<0034> <0033> -<0035> <0047> -<0036> <0036> -<0037> <0037> -<0038> <0052> -<0039> <0038> -<003A> <0039> -<003B> <0046> -<003C> <004E> -<003D> <0049> -<003E> <004C> -<003F> <0030> -<0040> <0055> -<0041> <004F> -<0042> <004B> -<0043> <0056> -<0044> <005B> -<0045> <005D> -<0046> <2022> -<0047> <0028> -<0048> <0029> -<0049> <003B> -<004A> <006600660069> -<004B> <2013> -<004C> <0042> -<004D> <004A> -<004E> <00A0> -<004F> <006A> -<0050> <002F> -<0051> <201C> -<0052> <201D> -<0053> <007C> -<0054> <2218> -<0055> <005F> -<0056> <007B> -<0057> <007D> -<0058> <00E4> -<0059> <2018> -<005A> <0027> -<005B> <0051> -<005C> <0058> -<005D> <003F> -<005E> <005C> -<005F> <0021> -<0060> <0040> -<0061> <0022> -<0062> <00E1> -<0063> <00E9> -<0064> <00FC> -endbfchar -endcmap -CMapName currentdict /CMap defineresource pop -end -end -%%EndResource -%%EOF -endstream -endobj - -4365 0 obj -<< - /Length 8677 - /Filter /FlateDecode - /Subtype /CIDFontType0C ->> -stream -xz tSwc8QC^e( <-PsKG:#$MZZ:mNt3DdEox[fݛ3[`6h@ xaEa]__`i -?2~@%X+ 'W #3]cafGncLu)bqﳕL}nNYV\Af\qYAǰwh$^Z€2q[)ӆF[oM~)PH4&hFUiZQdcȆHW+jH_bɂE\賓[Ǥ>r1?X./y>v[a_;0zEQJ7qPlS9F Ç2ȍ/{pFk RGz~/`Bl6FӘG.R<$a s@%򼠾Kf+g5g 8Bl,4Ȅ H+[p)ڐh|m;rh%هKp\abcK?{͘*bR^\IqT?:L-k8_ϳ+-m\ N( _k.'=PC+`$JxCl > -Ҥؽ+QNًl:H!GR㪩yȊp{[2eCةq Ӕk)dZQrGpT;%l7U*AU,,E?),ϴ1۞>Pژ[^QidkP6X -6~UacOCt:S?lr -e -MuI-0`_sY;TAiT4_XL  -;6:* W?T , ?~[%u $~Id{(+~'Ϥr+xaqSGxՠ?Ce(n[(;" >JV`Fێj/l{|k{J&qy9r86w.\_=e^Zi4i**;!_W@@Ic6*؁lt -ܯ|`%ߺlp}ݻ" r#-$2. )F -- )iHꃖ=k(˩ZrvW˥k[j]7mJb-% FUPRСB8tznbn -H@ @qSh'L UHUY@MCʼ- \>\ W/UEFL$^lqm ԝY4 - oWvbuRt=Hy 5h@*/oJ&pYBvve8ܧɫ:$\U" n*xMʼ-6e_ù{36p^(m`pnhO.+D余'ẽ0=d 3_jWdfGxsCf/ri2K ޹>uB 4dГpLm熕n;" -\W x_zx^dv|죀H0[a{(@a+5SԩT &1; y7|IH5P\K]~{$QO4k ]?n_Vy&6r? g*t0ۈ`vbVuP !gV *bUa%HP2ƎˮVKQwWNcÙhw/dn⇷ GoAo),[Lj߶O uW 8jJԥ` -OȖz?&D)[Zy0~[%E!& rOQ&R宨 umtoYK kT;SoT7B;GH{R '(m 2ۋn0\xuK6NeG^˿SeQ#.0pW;[_PW$Q=}JΌl|h5d][, "au6= Ûг5,;Tη Wjyj:e>"Xs1 ~U^eEPӧ -%<ph6"4i$0'{G -> 7B/5(A]3?NT)Z+dfjhɑlWzvRo7yj%iP"&f a"l&2lJ,'F]Nr1 E.*gpZa 5?"%巤f/:MA :);zv[@C]E~o)D7,ذp:g:Ttp|cRUڈq]wC'?b˷T,=5"cXe| C>;YPv -'(:c.\7QpOo`)Ed3r(w1ߎ.-zpui -cĔ;>{?~6z}&vaKuƓ:m - V+IJDqnN `)W -x+T ^jo5*I|QǑ+{I!PaAXnRʵl?Kˢ+(λ/<>hД Ъkܽ׹# 6úU *a HC~p[,6){4"+TzD˓+bjԭjcEpL_SGCƢmi<"b;6d%0~OO:~]55e 2pD`TP| )+H' -OvK}+ eF?L†EwOK'z[aDx!{t -а4ػ4 쫬>s [.l~4g_2rs 9@{YAfO~e}1 Rቇ?X/k1[Ђ-i֮}NV_QK6G%~+ӿE'PB|CfFk#<ÃvpdN߈x# -_5M0;G.M 5iTaHRcH0ʭ0fU "@qy ?O*a3sCeUi@Ę?9@JQzGKlUbkn5$ZE٫GD40Ü a %(𬦌 M@IrQil> Q 40NaUĿdD{SrpOM&h{6;JLGPD7ǫ2 |ḑ(-Kj'Zl7k\FoY -^Mz/4@㽠%ڨȆNj8D$19 -b!&<>@I<M|OF | j+X{%i-^T[L-i$zmQޑ!߄ S*% /)e{r ͕Zzu]'y&mMD/HQPbe,fk .Q]{>ʆh r=X ԫ֒Y -#vVbWsn*D5@o\>2"4;Ri;)NT\EGg]\ ka%R4Պ- -ҢH>pA$8^aXlkkс2M64(Ȇ2%5!6"KmvSkSفlVۙ{ NP -Q9eQN).|<9S.Zei=^f8 gt$0s Q+(ntÉ:Q bkH\$h ģ4l$O mme@]̘pR&MtWD"o՘r"L]Y_]~ץ+SB\i9x1gAɽ$ 7(un3&E`y3eC* Iz?Om]8-XFۦ$<]Pׯm߰^xVp1Fyy&»-_ؚt]'pNg:DP֤%tR98L:(wB +@etR|L%@m */.r- Wj[!.}[&ܸ{&PccYD^b\P$D=(a7np-<7Rq -n9d|Øjs -ۊہ~ѵ7m$7}I!5B!z,%(;^㺒2EQ \G582 -%Ū`T&ޕHLQ$BafS&sx0jn^Lq9FR)TA1F6\C;ȡN8 ח``Vʵ5 ->@~g9}j 0 e#Nzf?53;ñ&8J/}px${vQ2XTZН1!Un(wL>/o=B{~uv`CY]ٴGZr-g>oV>UXҙ>@"(c*Jc@`"d<z y>9V44M}Jr?GU*u| _BMiNLA zuIHϞw2%;|ޣikAy/ -ckjaa#Y9hٻW__Q?3O)_s 25>3|U`(ٹ\΄܂pbӓ }.b#-arA*9mySK`])07&={8эY,U/[+Wt0f7=&Y(.4?:O;R)UA! -MCB4$B]N a<)+.(U& r|W#ABp*X1vW}7{@k/Nb,iwlOUU Rt0#+WCݕ*wpwi -REzP߇mIbfjv2vPګ&)i~ !Dž8i`ԫR R)z5{׉֟nfqWMIPC<īk 0㳷1\žz1Jg&Qcab&9e&GIMeoɴd'Yerq"8#w'"\619QK)Ld7M -LzK -].QM@z L}`2)>I -wM6MdL/*RUl6/ҿC/դ]L !_C@ej#`<8ܯ07d Iaͅ l-)9kv L;vA4BQl}>m:Ts ->.yks{݆!o-w箑AZ}Qz&MVnHU[*T8dQ7DT4"!mno ۰Gb~=ILUB*R}8e* n@}; zL5׏~} - kvŋM-'e|`MS$a+)mK6U>Z?!EkSpT\TYj膋+t^izkaeSEo{̓=pjlɯK5M:^sGGiK>==}i+XTxe2>)6w ;6wyΕ]h߲|z<-F^6;?D~kT͖KfwnJgqwC}oP+)WP[-hhQh^,(44Rr;u)C+6dJc6:RI4Cb.n%51 qU,lY3W9.Ԧ7gqlX@+[)?807e -ޔMEm:4uJ#r S!s rT9bk#!%bu Cj"IBdddic`El(ztP]DNhe#5;ZXYj=š̓m`$3:&XAw2D|  Qx;7KIzYEV |] üV/]8<'3J 2Ix^BdCUFϿ>ogkrWë)ɤh{#cubMd-."}bCMoI'9-P%x5PHKs-,^)ۄ$t]ފU+JKw pg`#?.7ik6f0ne$ya HA@͞b:efw~))>2S5>V26¶Yb{R(9[VV_WP N1d]Ovpɿ,gpɰF*Ր6K|O -RR!"vB}]}11>茺zf׭{'돊ob]faߐ -endstream -endobj - -4366 0 obj -<< - /Type /Font - /Subtype /Type0 - /BaseFont /VHGYFM+TeXGyrePagella-Italic-Identity-H - /Encoding /Identity-H - /DescendantFonts [4367 0 R] - /ToUnicode 4370 0 R ->> -endobj - -4367 0 obj -<< - /Type /Font - /Subtype /CIDFontType0 - /BaseFont /VHGYFM+TeXGyrePagella-Italic - /CIDSystemInfo << - /Registry (Adobe) - /Ordering (Identity) - /Supplement 0 - >> - /FontDescriptor 4369 0 R - /DW 0 - /W [0 2 500 3 3 556 4 4 444 5 5 778 6 6 278 7 7 407 8 8 250 9 9 444 10 10 500 11 11 389 12 12 333 13 14 389 15 15 278 16 16 463 17 17 500 18 18 518 19 19 667 20 20 278 21 21 556 22 23 500 24 24 528 25 25 500 26 26 611 27 27 333 28 28 556 29 29 333 30 30 444 31 31 778 32 32 722 33 33 444 34 34 667 35 35 841 36 36 545 37 37 611 38 38 278 39 39 556 40 40 463 41 41 667 42 42 722 43 43 944 44 44 778 45 45 760 46 46 611 47 47 722 48 48 778 49 51 500 52 52 250 53 53 611 54 54 778 55 55 250 56 56 556 57 57 333 58 58 500 59 59 250 60 60 722 61 61 500 62 63 456 64 68 500 69 69 944 70 70 486 71 71 778 72 72 722 73 73 233 74 74 1000] ->> -endobj - -4368 0 obj -<< - /Length 13 - /Filter /FlateDecode ->> -stream -x -6 -endstream -endobj - -4369 0 obj -<< - /Type /FontDescriptor - /FontName /VHGYFM+TeXGyrePagella-Italic - /Flags 131140 - /FontBBox [-162 -276 1010 744] - /ItalicAngle -10 - /Ascent 733 - /Descent -276 - /CapHeight 692 - /StemV 95.4 - /CIDSet 4368 0 R - /FontFile3 4371 0 R ->> -endobj - -4370 0 obj -<< - /Length 1654 - /Type /CMap - /WMode 0 ->> -stream -%!PS-Adobe-3.0 Resource-CMap -%%DocumentNeededResources: procset CIDInit -%%IncludeResource: procset CIDInit -%%BeginResource: CMap Custom -%%Title: (Custom Adobe Identity 0) -%%Version: 1 -%%EndComments -/CIDInit /ProcSet findresource begin -12 dict begin -begincmap -/CIDSystemInfo 3 dict dup begin - /Registry (Adobe) def - /Ordering (Identity) def - /Supplement 0 def -end def -/CMapName /Custom def -/CMapVersion 1 def -/CMapType 0 def -/WMode 0 def -1 begincodespacerange -<0000> -endcodespacerange -74 beginbfchar -<0001> <0064> -<0002> <0079> -<0003> <006E> -<0004> <0061> -<0005> <006D> -<0006> <0069> -<0007> <0063> -<0008> <0020> -<0009> <006F> -<000A> <0070> -<000B> <0073> -<000C> <0074> -<000D> <0065> -<000E> <0072> -<000F> <006C> -<0010> <0062> -<0011> <0076> -<0012> <00660066> -<0013> <0043> -<0014> <0066> -<0015> <0075> -<0016> <0068> -<0017> <0067> -<0018> <00660069> -<0019> <0078> -<001A> <0054> -<001B> <0049> -<001C> <0053> -<001D> <002D> -<001E> <007A> -<001F> <0044> -<0020> <0077> -<0021> <006B> -<0022> <004B> -<0023> <25B7> -<0024> <0066006C> -<0025> <0045> -<0026> <006A> -<0027> <004C> -<0028> <0071> -<0029> <0052> -<002A> <0041> -<002B> <004D> -<002C> <0051> -<002D> <002B> -<002E> <0050> -<002F> <0047> -<0030> <004E> -<0031> <0032> -<0032> <0030> -<0033> <0031> -<0034> <003A> -<0035> <0042> -<0036> <004F> -<0037> <002E> -<0038> <0046> -<0039> <004A> -<003A> <0034> -<003B> <002C> -<003C> <0056> -<003D> <0035> -<003E> <0028> -<003F> <0029> -<0040> <0039> -<0041> <0033> -<0042> <0038> -<0043> <0036> -<0044> <0037> -<0045> <0057> -<0046> <002F> -<0047> <0055> -<0048> <0058> -<0049> <0027> -<004A> <2014> -endbfchar -endcmap -CMapName currentdict /CMap defineresource pop -end -end -%%EndResource -%%EOF -endstream -endobj - -4371 0 obj -<< - /Length 8773 - /Filter /FlateDecode - /Subtype /CIDFontType0C ->> -stream -xwX! Udi6qW$^`b!@G{Hlvc8&iFCzpf߶~~Ctt=GϹ}K3fxxzz> ܔ% -%$-ٜ| 溟>1ZCI3ϢG[̛HKLVpH^RZlZ[,AltLﲥKW.Yw}_^/_^f/)5 ["ž[^0,yK Kx~o8/&,!ʗ5=Ͼݴg]{}w,/-), EBɋd$_LXR xxzlv+Nn+YR3i>e{&{JA3᱕\ -b -&*|<2s|&ޙ:cdq463|Yg]+U~{'g<7ȓxO&۟\?=_o;%7F>'J4'N>HEonHS&ʌ%CH] ,Wz޽FINx9܏q*QFQ" QjvCF|]sLX d)3d8A(E*A-V}yK*RQRfX^XAOY)@\9b!F.^ ?6MNV ]P%+ADY~`xꮐWt86nU5uh6Rd!̹`.K -rE|H* MP:RZa9. EfꒁByr޶De C*āsī}IGfڶ#0%q Պ/V9Wݩѱz'A'<ɠgo᜷˥UCeni襐8) h*| #] LP.@vn;sp#'O"]`@" -3oLS -E`B2؏YS+ sdoe`APfIBUqzK 9t \fΆt݇$#(ͩi n"?.vq?9Y3N -^5 ݁c0X9ڇd" z/;BR'܄63QUQcjך:o}鼱\+(30s`Ŭ=Ilwh,'qrTߞ0V}T/ _gNP>OjA, 8 MaN_Q57!^ڿV/ -S0wP#=EV\Lo8Ͳ#G:`%֕Pi,.: } ڳʒ}EWg=i v$:,@4m#l!|#%,c7#"VŃϬCǰ ^B2RYt{5R27 -:?elwH VScpە\Wk~g` !vă 7lG86TvVX\. !Bbf_z0L'z~?<JGsUuv%ި}H޺j(ܚKfj.^A!Rcõ髍vC}qQXvWk=ImMbmבE OOŠ913p -ڮӜQn4|~yc./-0E -2~n`r\ bu!~zj%Ɂfp vv75u lX%ncD>{WH9v_ǩnd,:l -2VK{aa?^߅z/6\.}DJW4ݗ - f" 5+Ky^^$,,@>4Oɇpׅk)R,ǹ<̢7ҮOn;Fc>6z%]1KVc T]FkL&L^^@D;7fJJ47fW\RK0"v[4@>tC=ԉJSE缍MITCRH#-5==?Q笢_F - -e)?F<#HWڃs?w8-#Z; uρl2g9n8{<?a)_[^ٯz Pj/K?~UIOx5 \-S6z$tȁҬJ8 WdQ|T P0{ߧ 'U<-F@T[lI M};)x׋RPJ5V}->AH[)bɦq#JnfIϓt_,Q| Y]#E7B4ҁHHa4l#fd7@9TK vm _CFdz]6p6~GO9]#~`I8]y -x˳ KM(!1,jm3rPv-6) _ T태ZY`0 2C%/`XJp $FqIZA(*3#!+@{EKc]mUH) 菶%C=ݧ_7pxU.⓮ mذ#<:KBϒˇ"12|3W^NmwG}G\aRټ܂M bjb˗KvSd)fILϤRMW_ TCȒܯ4مF&!W)Ud6M/=6IK,ɽ|#fS*+SAt8m݈JVVGB547PԆAER).u8_go2(EDW7JR/(AĮ*u@Lw.4Auxغ=b; -};6"Tz,v -xW+RG-wzk8.(c`4 m X1UDKT*h@3H @{]ZBILPgᫀރV6_+d%X ud5ZZ^K` ۏEtNF%[MuC7t)(Y#5B%)3Co։TF9- }%"b!tɐ BejYUPT1U]ZeTY!m>O~~۩] yyo+0d=ZKN|N -|ΎW&ؤT+#Z*xiL9&7q2j+cv}-ZW=7}oCo`Vv*wαlPAS5ZiX,ط`%?FHCHm>>Cn緡ۭs++2:GBQ>JHOEs#E'B uI u}1 yC n ]Dq̒v2}͗M5P (\YJ(0HcΥ$tt0*W(ː͇Ͱz []eo ytNέ,Vrz5T/tAIރ?$aCJy^kOG/kS\*\/¢ZL(#Rnf*]iN{%$\Qr8dl/ ͟GpBEY-ا ]etPE$"ԊH.tH٠*pKP, ܙʴvc#& b -O щ7 2M>H)U_ّ߰JewX-9M}\;^99J|+Ç txZmɐIcLzNdj)=@f"> P6OaQM Ct|9]RJLtM*k~j?#?~0 20~Z~Yy!o7cZ^_o9y:!y oU)Lj]Pa+ $y\e^4%C‬Ӳ Ř))!u̍ CJbYUt_jeY]e"T2ksщ\JM#XB@)Ft@á4Fjlj -͊ݘFh*j=0 -W8<:Oѝ*wSt} gӦiڠZ-~pO6k3 ŕ-::QRJrI*>tR]ӷ\EAz/D05{(fofN tD."9H h6u+0kLHSd;<;u'BdeG?*G*~na'(|ԧ~(-fZ*LuY\ܮ:_W|*/3V~W_BGHBu~S$ -cm:^enл?{~w#,do跹~J]Za_)%ÎS%  %aFh,PK$~J')k!N.b.m͔Qk÷9@WQzE[j(y(㭗^B}T $J 0l׋c`e0ʟټџ@<O)GGF<_:a&uz'O յr]HU*c;yiEb n4hjQ*LJzSU¬TT:)+S nܹYoguFxL{+j;=.P4L'zgEh&heX;a0|F6t6 nR%Z1CxU[ -  -)C.g!:n9X.*Hr Q=$A'qui8SnM ߋV-JM~JR%O7)Z ij? g# i{0F ԢS~Q -a-8yChSHY@vs }ڍ_=T&|qI'w=K?@dabIȓѨ85 -0er JJPUZG -U*\x߽G(?j8l DLo8FIK1wobi$YB -Q[]09rh;}+ɷTIQOoCY?܄lH̏p.*֔4=oI1. sy9$;R¥ZN?4w@Y@" r\/+Jͥ@/m:cPz^k p@OO|YJs WYO?J¦٧@/¯z.z1ͦ٘%$cFD5H8 }%R'Ym^]a-\ܾ.'0o܏3hoz3|= }ueD!Ξp -F7n^½֬?r7Oڈϰt|C&`|W) K!01u4bv+pcR[ف4[^u9{4tF^xe\JDgQkq}0|p<ؑ3"ٵpX A]p,YzwOi_"k/ݭQʱdAć S2#9z+56^ܞC3A ޳w+*`'^w#zr8r}dGy#jߛA8ֆkS:db$ '0ξ5D8c'^;i*A"Jx$n_[sn\VeՊ4 DDx -xybgk4޵͡w 5=G/C%bJok򛄍 6QGó,_j4i9 Sz5i-w's*TKnSo"f!*,ih$ͽ̘zXGXƺLֺuP^ZT$NqG3ӡB.u r!OUESJ/s_΂z6DҒF fW1DQTL 7&8&b7&ۏ8'T%S3H)vɰɇ>_n;sa2A(֩"]idAe1V8:& .Ldk\T=v2PS4RCh {D}R ܃*T6+݈ݶ/@e54JR'B"$R~Li%2:LE<]6Stf -$ +P Tj uX4}?VmhP6ϘZ2FR-Z v2onx7PX K1\@!iLPTlg(DuX! -(E(LnAT%+k*Gd;^d;SVQzc{---3+"'H氧drG -endstream -endobj - -4372 0 obj -<< - /Type /Font - /Subtype /Type0 - /BaseFont /AINDEB+TeXGyrePagella-BoldItalic-Identity-H - /Encoding /Identity-H - /DescendantFonts [4373 0 R] - /ToUnicode 4376 0 R ->> -endobj - -4373 0 obj -<< - /Type /Font - /Subtype /CIDFontType0 - /BaseFont /AINDEB+TeXGyrePagella-BoldItalic - /CIDSystemInfo << - /Registry (Adobe) - /Ordering (Identity) - /Supplement 0 - >> - /FontDescriptor 4375 0 R - /DW 0 - /W [0 1 500 2 2 250 3 3 500 4 4 250 5 5 667 6 6 333 7 7 556 8 8 500 9 9 333 10 12 556 13 13 444 14 14 389 15 15 444 16 16 833 17 17 333 18 18 389 19 19 611 20 21 556 22 22 722 23 23 778 24 24 556 25 25 389 26 26 500 27 27 611 28 28 556 29 29 685 30 30 778 31 31 556 32 32 1000 33 33 556 34 34 593 35 35 444 36 36 500 37 37 722 38 38 537 39 40 556 41 41 611 42 42 778 43 43 389 44 44 500 45 45 778 46 46 833 47 47 611 48 48 778 49 49 944] ->> -endobj - -4374 0 obj -<< - /Length 13 - /Filter /FlateDecode ->> -stream -x -endstream -endobj - -4375 0 obj -<< - /Type /FontDescriptor - /FontName /AINDEB+TeXGyrePagella-BoldItalic - /Flags 131140 - /FontBBox [-130 -271 1073 726] - /ItalicAngle -10 - /Ascent 726 - /Descent -271 - /CapHeight 681 - /StemV 168.6 - /CIDSet 4374 0 R - /FontFile3 4377 0 R ->> -endobj - -4376 0 obj -<< - /Length 1300 - /Type /CMap - /WMode 0 ->> -stream -%!PS-Adobe-3.0 Resource-CMap -%%DocumentNeededResources: procset CIDInit -%%IncludeResource: procset CIDInit -%%BeginResource: CMap Custom -%%Title: (Custom Adobe Identity 0) -%%Version: 1 -%%EndComments -/CIDInit /ProcSet findresource begin -12 dict begin -begincmap -/CIDSystemInfo 3 dict dup begin - /Registry (Adobe) def - /Ordering (Identity) def - /Supplement 0 def -end def -/CMapName /Custom def -/CMapVersion 1 def -/CMapType 0 def -/WMode 0 def -1 begincodespacerange -<0000> -endcodespacerange -49 beginbfchar -<0001> <0031> -<0002> <002E> -<0003> <0032> -<0004> <0020> -<0005> <0050> -<0006> <006C> -<0007> <0075> -<0008> <0067> -<0009> <0069> -<000A> <006E> -<000B> <0053> -<000C> <0079> -<000D> <0073> -<000E> <0074> -<000F> <0065> -<0010> <006D> -<0011> <0066> -<0012> <002D> -<0013> <0045> -<0014> <0076> -<0015> <006F> -<0016> <0041> -<0017> <0048> -<0018> <0061> -<0019> <0072> -<001A> <0033> -<001B> <0054> -<001C> <0068> -<001D> <0043> -<001E> <0047> -<001F> <0064> -<0020> <0057> -<0021> <006B> -<0022> <00660066> -<0023> <0063> -<0024> <0078> -<0025> <0052> -<0026> <0062> -<0027> <0046> -<0028> <0070> -<0029> <00660069> -<002A> <004E> -<002B> <0049> -<002C> <0034> -<002D> <0055> -<002E> <004F> -<002F> <004C> -<0030> <0044> -<0031> <004D> -endbfchar -endcmap -CMapName currentdict /CMap defineresource pop -end -end -%%EndResource -%%EOF -endstream -endobj - -4377 0 obj -<< - /Length 6617 - /Filter /FlateDecode - /Subtype /CIDFontType0C ->> -stream -xyyxSպ~cYe%jqhgPT 2R,:Oi6iMm8k/z( ؝pCv-%р@';zrNbAhuNnQ>?- ŋ_Z^Kۖ', E aEa ې#fmxf3as$ Igž%'d|'*Ȱu[F>Lv~J !;ET/ 䧄%$'$y3A-=%l[z 8}W$` bav@ۣ <94c|`rZ]s+ҟStH 9wq(Z6:3{ۇ$Cp/cs#^s޻F.{::}Rܻޏk\G?XP r`"p^= hbz;Ϸ^0FԊJ1HaΝ's 8ԉ1(V/@ * CR+)&^,,hU.0-Ew* 8FR3N%5izS2v;_ٗ!¥z+1<\=Op{ksb y$>yN¿z (H,Nőm*g#=䞀0W{؅EhbԞ_ )::⴩5uX""L*2P vCsU' U6_WgTjWd/j̫۷ @F@!VW: 񅻳0`{|g$~og1$<˙oCas[?~(*R95AWSUkwZq]ejEՄƺFl}S- +1iqXm?Y!AU.Z8[s$|H_x0}8>݆2kD߉H~ȡcd> 8&kkۚS7fE=nSlN ur_iHZB5yjT rJjDH"A8n胱O; z[r(]$+Sڏ8]Q.F5 -nWA[7WI2/#hm.ffg$B9KMՐ9r;Qi jPdl(RzGo=cKr88\% SGcr&;K tyM:*3.mHPP+*L3X:8و>S8+)]o^ ӷS+[i2d+i2lksvh -g` -v.Bwq_G$TOV&> -ntRl;ŷpE(sY>/&cϷiEUX =+!ڛϝeGI%c~YF85s栮fg cEVQ -0o‰2>sHFf\dڔHzDɉ4DhxVLCT㰋A1scLlK@ -Z\U'+1(6I)o*tNД0!˧_DENQҎ4ȶ)~8b`/IT萡pSZ>Q˭#4&W-)t`48# wP^ͣ DyO8j6wFp@I-\m>8i>5sLceadFສZc`T;f{B Q ٗDuIl~zFҨ[k+1g˒i*UʳiC#8S9].^ Ez]DhQfX -/ G8GZt=r/|ebYa #apBT@&D -_ooMɎx(聓0`p#gpQe9j!:RVYU`t>'ADLxMD: -dӡqpG|CMx,)ixeO]-50~]\^x!?G ; kcnG4 %t=!8Ǡl} Pct9 -Ygh?ecH\gá;AZӃW܈nz4JE2EiDZH ) WYx1v#x~k3~QVR9,>ˎA?E=.xt WZk9HjExV+&:B×W8}i -~FϵK`&;Ο6 6kkq ,]u"S$H%L%Oߖ΃AoދgZZ<.YsELJ@e5P7S_{9d.AuϑՈj.3 y]6!u~$`8lr~es(ԀS)v2N) z%@\#.v_R?2փ{T6Yh.Ŧ|GDuJr{;Yydz, pFFn4;Uu]Ҵ,2x 3 -ILeTUZ|Ln45r]Xmd9Fʍ7h}՚M]%oJBȑ[2F7j=_ao}4엪 -(²ۘMZ1OgID"i -" -aq4K-^_"cwf4[t>X>35΢THO.LP ݁SbGR_o/m -;VQ)Zp#`g""N&O.ei3n@1sk"kU0tu?|@B}ou~@(tjZYH`% "M<"oSl~FR4t3TÁZ@]Eo .D REPJTc.9^+R9}soF}44//Ti% 9!^]3D_?C#4 BW#'|LmCtѪ# t#xxrV. J:VS_m?d?Zio]gQjaxa`?nWJQAIگEcxy;޴\`֫qTl1rq[ _FzS_c>}%OOT]+y_i[G9zPWӥ}/zSbIO8$wv;x/~!t -&dΧXنoO pWюAhVeG6#;U_29{Bc$@fbL6_P+]Vϴ/s,2V* -=2 zYb,"ԭ6;wV(GPB)Zvy|l+NCm}-`[sapb2 5'i޸)(eiC#$P\(Ө@QJ -JpC)r5u64Rlq BD$ߥ -V NW%2Þ_#5wׁ5n|o>;hȓ%Nξ~֖jF/f:tf몟hp?k ^x# ̟.NDT?z9nU0mF_M<:GkY'ۀ<wnU3=5W%?:OntJ^bu -ar#ڎ_<>M>%%3 bo'{C|Ԉ7?tjDn[V!<L~ɴ: >UTF_m`W1hs:yS3ئ%ʥZO#&潄`^U9r zʭZzHGzZL^[@o_>99D;Tag*]ظ<>r5TZKK7SBQ'`kt[y< { -..]e\>]/N٧Aw{UqOo|CݜG#ήeqm(|Bk;w`PweAT Ifp_ -/}c6u.kf_7Uhee]3S4@%THsZT.ZQi_ڌ`;-35鞛A{8Io3 :s] NXsx,[>3yIB|=Toͣr*s(}JLp@N_c B#7=&/dt:2v[.UzOC!I(5Eς+?B\ox@XH7Y X~s w'H+!/''~} jU4-*ܗ퍀%dzܫofr@h\bnΓp -hb A4䕖o#ydΒɰ/"+U` -Y_#n](@2m-Ґ*{/c7踸}dSklf)::>BQZ b(jfN@ʴB'Ј,DN_ -endstream -endobj - -4378 0 obj -<< - /Type /Font - /Subtype /Type0 - /BaseFont /FKQCWC+DejaVuSansMono - /Encoding /Identity-H - /DescendantFonts [4379 0 R] - /ToUnicode 4382 0 R ->> -endobj - -4379 0 obj -<< - /Type /Font - /Subtype /CIDFontType2 - /BaseFont /FKQCWC+DejaVuSansMono - /CIDSystemInfo << - /Registry (Adobe) - /Ordering (Identity) - /Supplement 0 - >> - /FontDescriptor 4381 0 R - /DW 0 - /CIDToGIDMap /Identity - /W [0 52 602.0508] ->> -endobj - -4380 0 obj -<< - /Length 13 - /Filter /FlateDecode ->> -stream -x~ -endstream -endobj - -4381 0 obj -<< - /Type /FontDescriptor - /FontName /FKQCWC+DejaVuSansMono - /Flags 131077 - /FontBBox [0 -235.83984 602.0508 765.1367] - /ItalicAngle 0 - /Ascent 759.7656 - /Descent -240.23438 - /CapHeight 759.7656 - /StemV 95.4 - /CIDSet 4380 0 R - /FontFile2 4383 0 R ->> -endobj - -4382 0 obj -<< - /Length 1334 - /Type /CMap - /WMode 0 ->> -stream -%!PS-Adobe-3.0 Resource-CMap -%%DocumentNeededResources: procset CIDInit -%%IncludeResource: procset CIDInit -%%BeginResource: CMap Custom -%%Title: (Custom Adobe Identity 0) -%%Version: 1 -%%EndComments -/CIDInit /ProcSet findresource begin -12 dict begin -begincmap -/CIDSystemInfo 3 dict dup begin - /Registry (Adobe) def - /Ordering (Identity) def - /Supplement 0 def -end def -/CMapName /Custom def -/CMapVersion 1 def -/CMapType 0 def -/WMode 0 def -1 begincodespacerange -<0000> -endcodespacerange -52 beginbfchar -<0001> <0061> -<0002> <0063> -<0003> <0074> -<0004> <0069> -<0005> <0076> -<0006> <0065> -<0007> <0064> -<0008> <0078> -<0009> <006E> -<000A> <0073> -<000B> <006F> -<000C> <0044> -<000D> <0070> -<000E> <002E> -<000F> <0067> -<0010> <0045> -<0011> <0028> -<0012> <0029> -<0013> <0072> -<0014> <0079> -<0015> <0041> -<0016> <0043> -<0017> <0054> -<0018> <0049> -<0019> <0056> -<001A> <004E> -<001B> <0052> -<001C> <004C> -<001D> <004F> -<001E> <0055> -<001F> <006D> -<0020> <004D> -<0021> <0062> -<0022> <006C> -<0023> <0068> -<0024> <0053> -<0025> <0075> -<0026> <0066> -<0027> <0042> -<0028> <0040> -<0029> <005B> -<002A> <005D> -<002B> <006A> -<002C> <006B> -<002D> <002C> -<002E> <0020> -<002F> <005F> -<0030> <0050> -<0031> <002F> -<0032> <0046> -<0033> <0071> -<0034> <0033> -endbfchar -endcmap -CMapName currentdict /CMap defineresource pop -end -end -%%EndResource -%%EOF -endstream -endobj - -4383 0 obj -<< - /Length 9557 - /Filter /FlateDecode ->> -stream -x{ xTչ3df2!!$!@r,AABD̡9KтEjQFRh+Z)0Yg=y?qfwy -A޹.P JU}(~/.Xr~t'@O]%f7w̛miTT ()]Ppwŋ~c1B~/R~FM.Q -/-+_}^Ptټ=}z4͞D#hZ(8P}8[^qBDZ_14&8x -:S83˨e<\tpTMZp(|([\A,oQ,^vs%Kx@7QI씁.ve)cqPI43ZMRW)Y'xA:m>[2~+~ -uۍ GCߠRIQl74^V&|zۍ:]sm5xRl:h<RQrq?P7؍HiRirخg5SmP|tQ^< -U]*) {=nZBz[;='te|㧪]=JQg{?5E -54רS(i -$=)E K?ZwۜM+]PPjX _eͶm8)T4>lyzy`_2>;/zY䙛J`9I =VXJYֽQȬe[1a'E\U)4h -08)E(ԝQRyQN_i{S>YȢ\IVlfx尤Y!X:+0^ -*oS@WRIVcݨEcZm({#6))]H E]ݜ-q.p^:Ew+"vhln:5p_L=TȽx_zFu/:k_ޫii,3;?žA9ݚNtቭuxj- &Thp;$([vt΋CcGq99ّ0wJRF3_y[EغꚚutR)?`.wyNy_p4V|#xkj*SE) - -jc#Ħ[tkŢtJpYBrseXy6vmqVBARt-–MW',3LdeIVce}5F5XOj!)#h= ED8z1d?lcV-dyٟ!1e+@=e JrDJV46f=_}#}ֵg=kkqNJ +qۢtuW#PCѵ.6У-{h"]$p^n祳S\e`cǗD'x뫟_z>zݖ3gZ}xGEX: -e|uo.Ehuf)۞9ngL2>.gJB+^ƍ7b6 nqru6~}ExT<%[Mb:I4b8׵= r 7"ylÝϷqrz0ӽ <؊e77Kk۰Soovϴ}÷@e܇ -);L帒؅@e*FRcq]R EֆQMqaGz35}v't@7 tH#7u!ܣt@SŠ͡kW}n#k/usv yj]K?yF%{8Ňe_F{,,,'x> -cyիJ=Y_f347K߅˒|[').S^-Űݭvx_QF(´An 6?[SiJv5kwo\ϋ~"?Ȏ|k+JmK: Zu8F͉tGx=;f4wTYbGgg7γHy5j%\ MúM`q;O7e19-ٷy}N8xr^>6sx69$ґ5.zq`Zqj=:D9䁡DLVW_ah#T!XQD+ 3* r:Bâgx(Zq8 w0\6FMqϾ,wݺ"s"KJ?7c3}AbqY1GJX?W=-63+\YeUɡ&flŸ#l4~T.;v}fZlɀ"o F2셒'sUK\&͒L6l# -@z=Cj5c(L[Cp>oS2_N6uP(*UYcԒdD WWرKZ,>ɓZUŵ4V-*jnS% FSKz:gۑycel kͰW^qVaX{w{S_(ٓmaKг牁>oG@GWC|C>8O%? $WBZ.ҏ4޲Z O3}jFHی,k8}v#:Ăm1(~GX-o}ݻ&<@}@h_Od $? 0,_^&M%dr 7Yډ(%'Ũ+bt]]VlBWbUWgv3s\yƛTߝ';@kksXTxe4٩%d}%iʹog;2?|O(oxv򙙭y˟|@zV{*O 8}v( 5g/#@1oֲ[悊R[d-a ȶѲݹцa:''iMnmXaS_^:rXxU4OY +*CeUM7Ωy /*P>ŅŹ8x%y4*qy-#.+j1fMa+'Oy(!fް/=0_HO3c?fb(AuԌR@-S+RaVUG.a.c:\a1Xט]&9/c4jkҽS#ơ~ Wv~0Hox}ý{5x^7dP䠨Aуb2n⪨JUZ^eV٪B"bbuVf2ŰN]l‘k˞6y#{.a“/+?i}DY}iTg0hb2-ˢ)60 ` nI٦ijM7Ԍce ˈ3;fbebi򨏥a6tɌɒ+i2s0,쀸 [Z-7xjK -'(xCך!mRm6!˶ã۩N --dUh̆H^v9Ƚ޻WğGl˿pm3Ό33̈YcH4kH~ w@cFL ݻ"x\t-q怘%ϑ=yHwӀhv1öע ;,++Lv j1%ə93^]O!M`Eo4xrЏ&7oPܒw^i8=+>ٴw[e#n,i&YM=9w [-iq/y^0.I'6v5}I1YXW]!1- -#.gwͲ"M0ņ1# Q"9!;2£醹z2lGkVo#k|fͦUkr+]KW=P7'Ď'xCXvGl9.Q_]w2-*YiZ;4bC3임4{zF)4;Th$lgiybfSrx*Bc3o;Q2>}:zLwZhEjH^3S{*>d#<|Md') m[mⳲAC:xamo~x6&jc`VhW}x y:,o7FڗnB#yhdArW6.[-@jwƒ-,-ȑ0Zn>jI@e3yێS[gb]]a9=ESXC#1pwuw>G|n>dr%kׯ^Ħ7;v72Wd[r "Yu^5p}%p_OGjB5'm"^ĥ8(ڽ3YpK[G37%gl.3g޽OoZǦ5u}_q,6zGϼRle~6 -[U:M 7Y7饢߮oM?L=T`/QJ`=֣]@%l%HF 2q yAC6vjpG ] 6ό?(AHv|bX}x]ʟi=AoNq-_vj-dGK>yPkzɶĶ>!BbW>{B{ ]64UH"hPDDOa.pƿSo5C5sPfdtE|7z!J/+io[,mJƶi)o5 3{Jf/5>;?cXi;vMH}߳KsmM.tYSRiҞ~I.&^Xl|H>+]BSXlhSSڙSW|IMo/Kr3[q&K NRM+w)_Mtۮ{f[ZE󝔸 -Cbvo}Bo͌ѷYdް%DyxX*&_V':ߔ#FQޓA%Spyu3‰ۯ$dӘ9vq{{.VXI٬ҫX_+2Quq~;R#Phda) ƽ"LD1,0כ'K6!;(2I%azlÂ60%!o=Рc aBPBCDC011#0ɐBr)O2cpe\5%\wPsi!yh6N48b0ƴm)=~R"CCICޓ(J&dJnƋɣ͎-ނo[grIxJL L2kBI-;}`A'|gr -WW_. [6]З[poqwCb8}~.giWAvO_D8FG[ς>3#qccͧ!%N :N -\DW}$--t&cw~+7n ͂:, A6CzNM>L*d~p&5APc`}ukPio1A{KAVOA/ -v zy!ws\E?{6l=N?S3v$(C?vhm[C6A[C Ж-u zdz"jy`z|cCC&SI .Z/hvU?:V z*Uqo*T+¨Nn*= h%yZRڃ/H=hEtTr *4wN+h|N4K7=砙4wt~4AS=4EdAtd$AMt*/h -AШ4(KECܼ(FFq40;@4tKC -\|4*>U- \TШgU|p nd|V7}5*UdAv|b.AY:x߃ -x^1ˊFQ_A}=Q{o,*ق=<+єa(W8OPz"rxp%ݢݙiw&SO%CP0J,ɅtG% J ㉂y*O(UuԵK * K --(*G ȈtY@'H'r -[sW9¸EN0Q#vr؅ڭkttX#+O7)Y -endstream -endobj - -4384 0 obj -<< - /Type /Font - /Subtype /Type0 - /BaseFont /GPMDBV+NewCMMath-Book-Identity-H - /Encoding /Identity-H - /DescendantFonts [4385 0 R] - /ToUnicode 4388 0 R ->> -endobj - -4385 0 obj -<< - /Type /Font - /Subtype /CIDFontType0 - /BaseFont /GPMDBV+NewCMMath-Book - /CIDSystemInfo << - /Registry (Adobe) - /Ordering (Identity) - /Supplement 0 - >> - /FontDescriptor 4387 0 R - /DW 0 - /W [0 0 500 1 1 625 2 2 611 3 3 361 4 4 278 5 5 584 6 6 444 7 7 306 8 8 444 9 10 389 11 11 500 12 12 389 13 13 278 14 14 497 15 15 603 16 16 654 17 17 750 18 18 1000 19 19 722 20 20 500 21 21 613 22 24 556 25 25 500 26 27 556 28 28 278 29 29 466 30 30 722 31 31 278 32 33 500 34 34 485 35 35 576 36 36 977 37 37 837 38 40 500 41 41 828 42 42 466 43 43 444 44 44 828 45 45 778 46 46 738 47 47 778 48 48 722 49 49 625 50 51 778 52 52 500 53 53 600 54 54 1000 55 55 490 56 56 833 57 57 392 58 58 581 59 59 572 60 60 518 61 61 569 62 62 611 63 63 706 64 64 556 65 65 528 66 66 412 67 67 667 68 68 778 69 69 531 70 70 906 71 71 500 72 72 654 73 73 569 74 74 528 75 75 610 76 77 422 78 78 407 79 79 666 80 80 477 81 81 500 82 82 528 83 83 776 84 84 706 85 85 569 86 86 662 87 87 500 88 88 319 89 89 527 90 90 447 91 91 319 92 92 639 93 94 500 95 95 469 96 96 500 97 97 710 98 98 849 99 99 722 100 100 521 101 101 1000 102 102 607 103 103 500 104 104 571 105 105 778 106 107 278 108 108 667 109 109 568 110 110 394 111 111 583 112 112 278 113 113 816 114 114 520 115 115 445 116 116 500 117 117 831 118 118 595 119 122 902 123 123 732 124 124 667 125 125 759 126 126 863 127 127 917 128 128 759 129 129 451 130 130 530 131 131 517 132 132 593 133 133 1149 134 134 354 135 135 406 136 136 782 137 137 651 138 138 494 139 139 612 140 140 576 141 141 750 142 142 554 143 143 556 144 144 485 145 145 750 146 146 514 147 147 345 148 148 958 149 149 559 150 150 510.99997 151 151 639 152 152 278 153 153 1000 154 154 503.00003 155 156 389 157 157 1000 158 158 778 159 159 839 160 160 529 161 161 429 162 162 653 163 163 1139 164 164 1361 165 165 1000 166 166 778 167 167 500 168 169 667 170 170 642] ->> -endobj - -4386 0 obj -<< - /Length 13 - /Filter /FlateDecode ->> -stream -x x -endstream -endobj - -4387 0 obj -<< - /Type /FontDescriptor - /FontName /GPMDBV+NewCMMath-Book - /Flags 131076 - /FontBBox [-32 -950 1236 1500] - /ItalicAngle 0 - /Ascent 806 - /Descent -194 - /CapHeight 683 - /StemV 95.4 - /CIDSet 4386 0 R - /FontFile3 4389 0 R ->> -endobj - -4388 0 obj -<< - /Length 3246 - /Type /CMap - /WMode 0 ->> -stream -%!PS-Adobe-3.0 Resource-CMap -%%DocumentNeededResources: procset CIDInit -%%IncludeResource: procset CIDInit -%%BeginResource: CMap Custom -%%Title: (Custom Adobe Identity 0) -%%Version: 1 -%%EndComments -/CIDInit /ProcSet findresource begin -12 dict begin -begincmap -/CIDSystemInfo 3 dict dup begin - /Registry (Adobe) def - /Ordering (Identity) def - /Supplement 0 def -end def -/CMapName /Custom def -/CMapVersion 1 def -/CMapType 0 def -/WMode 0 def -1 begincodespacerange -<0000> -endcodespacerange -100 beginbfchar -<0001> <0393> -<0002> <22A2> -<0003> -<0004> <003A> -<0005> -<0006> <0065> -<0007> <0066> -<0008> <0063> -<0009> <0074> -<000A> <0028> -<000B> <0031> -<000C> <0029> -<000D> <002C> -<000E> -<000F> -<0010> -<0011> -<0012> <2192> -<0013> <03A3> -<0014> <0067> -<0015> -<0016> <0070> -<0017> <0075> -<0018> <0068> -<0019> <0061> -<001A> <006E> -<001B> <0064> -<001C> <006C> -<001D> -<001E> <0077> -<001F> <0069> -<0020> <007B> -<0021> <006F> -<0022> -<0023> -<0024> <21A6> -<0025> <2026> -<0026> <007D> -<0027> <0032> -<0028> <0033> -<0029> -<002A> -<002B> -<002C> -<002D> <003D> -<002E> -<002F> <00D7> -<0030> <2115> -<0031> -<0032> <2264> -<0033> <002B> -<0034> <0030> -<0035> -<0036> <221E> -<0037> -<0038> <006D> -<0039> <0072> -<003A> -<003B> -<003C> -<003D> <0031> -<003E> -<003F> <0393> -<0040> <0053> -<0041> <0079> -<0042> <2218> -<0043> <2208> -<0044> <2212> -<0045> -<0046> <2254> -<0047> <0034> -<0048> -<0049> <0030> -<004A> <006B> -<004B> -<004C> <0028> -<004D> <0029> -<004E> <2032> -<004F> <2200> -<0050> -<0051> <0035> -<0052> <0076> -<0053> <22EF> -<0054> -<0055> <0032> -<0056> -<0057> <2217> -<0058> -<0059> -<005A> -<005B> -<005C> -<005D> <0036> -<005E> <22C4> -<005F> -<0060> <0037> -<0061> -<0062> -<0063> <0054> -<0064> -endbfchar -67 beginbfchar -<0065> <21C0> -<0066> -<0067> <0038> -<0068> -<0069> <2286> -<006A> <005B> -<006B> <005D> -<006C> <2209> -<006D> <2216> -<006E> <0073> -<006F> -<0070> <002E> -<0071> <03A3> -<0072> -<0073> <22A7> -<0074> <0039> -<0075> -<0076> -<0077> <007B> -<007B> <22AD> -<007C> <2227> -<007D> -<007E> -<007F> <004D> -<0080> -<0081> -<0082> -<0083> -<0084> -<0085> <2133FE00> -<0086> -<0087> -<0088> <2295> -<0089> -<008A> -<008B> <212D> -<008C> <210E> -<008D> <007B> -<008E> <2111> -<008F> <0062> -<0090> -<0091> <004E> -<0092> <004A> -<0093> -<0094> -<0095> -<0096> -<0097> -<0098> <007C> -<0099> <21D2> -<009A> -<009B> <27E8> -<009C> <27E9> -<009D> <21D4> -<009E> <22A5> -<009F> -<00A0> -<00A1> -<00A2> <0046> -<00A3> <221E> -<00A4> <221E> -<00A5> <2190> -<00A6> <2260> -<00A7> <2205> -<00A8> <222A> -<00A9> <2229> -<00AA> -endbfchar -endcmap -CMapName currentdict /CMap defineresource pop -end -end -%%EndResource -%%EOF -endstream -endobj - -4389 0 obj -<< - /Length 21370 - /Filter /FlateDecode - /Subtype /CIDFontType0C ->> -stream -x| XU6H_r2#1΢&㸌vEot@!d!aJhU;y7_wy99>}DG͙ קsZV\Oœ]hQ\ >]|ψY<}<mQ1ѱ̎陫32ǖ?>g[>ܥEܲ[ˊ seOϽckNn\a1/nn\^fAfZYfL\~Nܕ۶l_\ğ.wofQYܧ[97/ygO*.=S0{N3eOoܰuaOEYż܂n -M%.o"{qctsǜwn΁;b뮁;uflZ;&*:***1m\T'rG]m#u&Dl cd=;ww/3WJ}{0ne{}uC.w=;q~˹=;WPCϻ_G~Gzlcŏ_㉹O|J{GOv|ݛ׏nxu}j6 $lۚmmcG·wEJKT&~7ɜt={HN{9͓C'W޿>a{Ulr5>4l0U89ۦŞaqSa0ݔxuAnh:ڦ6@0BST+]V[u(EKg;H? -/a2Hƞ^bvqBQ׌*csQo׻. Ii!S1}%Cfp^m0/u -U)ʢ~r^ ubeg~{vWe j Tj4wAzz"Tc7ף x:6cI xދD] J[ P(P[Saro 5WYSwAWjet kZ\T*pѣkz&t^@^Ycqw@Qnuf"|?9DLlm6 k|r)\Жs)*PԢrַ -V䤃:=[ -:B6Q\k@fQ6re$kw^u\&gi'No qq.ַ ƌUר9G6:SpCᖮfGNEQZN[ )/:c3b&_Y+ϒEǚ-MN?@IBL T?Vm}_y.u+ԛ ik\20D "y 0*-J>S 86M'V(A -ʫv]Xܿv'' :62$p]{0͈a*hUmyU2O8L@Eޟ[WKC>b˞tayn~,kcy"e)b VݤEESM Ԑ#jnQz \&UpD @ά5H{Ӓw]m{ӡ7LF3]kEz굺ɻV?2 "5. |v&IoĜa)|Z ߍMSO6 -`MfZiɈm16a}s3), -n>Yg-cE'bR:? x ޡkZ:qTk 1jLڃ{Vw<ս -Z/~dQiwjtЂܢvL1w8&/o/ĭZÁ - *h@fV;@E*%sT]@5]mb_`WIvHNNH<YZ*.V0 mj(X(JA B |P5,W5]'j9l-&{xtA}9X+T"jnBЫA MੳCn!,~S#xbJr@L$H.FwCNylz&UJDJޒn~kov k;a,`Gr(-H39~wX՝7=/@1ټ]7~8ᎎ^*IW17}X3=1~*^N ^wۂTȉ,Q2$:+Q\=5R؉`$48+"ʠuFR;?_'=FarW@= -ԜUR/O!~}n!fb?BoG?M8lvCe N MkbAi6ۖ)"JfUrmS34m# ^[*PiT&CAZ.DݘL[+ Uz8d1yNS@0IK/d lҴ>;`qhP>u+@U -E%נ=?iAKp$v쉯@vE= v GL|;#>26Q$UMٔC2!ǡ/jոLV:V Q8Kxt:xWG@t\<*a t i/O>^*.}cCRNE -jt::ʇ*zsl "z߆7XC7`j SxZnE< G/0  -*aRZ4vt4AKQx$) -ABٮKxX*m qX-U\WÊ@Dj{ ww}66}zOHdƒca'ff 8NnPB&MxZ4_H 3&@`PfM-~T)=|=d_3R IZQO4kn3[b&Jq8mm76%\.)rahJă=zB߳c$' 0* -wmo~]eW%GrƢחq& -Z\Io#\? 3K"Iff뻴>ɔE ^htS5Ѵ"|5\aΓqj;~&od IR@XУiU6}%]]]\.wЩ5<ƫM5"ĪZU - P,U"pgp8C-Khlϋ:94eSəݣ\$c՞-XY՜#܏Hę?>q/YFuTX' -qk( ɻlOmVy*OKнI"㳽Gam a{yjJjJ627np"0r;=L$ R J$H|Nk!of:dEV~1tȆ򙾡 H`MMeS\l6 UWęA\0z*6_c6-]A/,z]-60s d@,Cxg +_q{&çZRI/NA -w"ly{}8vgsv|?z* -Ȯ  Q-Ջ dzAWih>z -{ CoaB}!݄2=W&U^a u,`Dƙ9ڙ=MZeW8vŃTa+]`3mvl`VD8Yn8-ܝӟNX*3b :4 c%5It_K=o62u;hw1qbGs[&[zNtY,.j!M%J*A uSIjԢv9C+ Fݺrc\ 1xˍ.eSOwBjEVvV( v^G5UhA:op4\gX|Dmr`"D2`}īPTjun+ 9qGCE68{;Ja+}߁Q8PWjfQQF˩!D=mفdH~F0RQ^)Ɂ.QCgP4Edw|=Tj# 9Xִs_,Xv7 [[uZr3t$6e KF%(E"}Q8KϾGL\aoĿƐgcR}ԥnj0UqAW턺\& -}rN u\ny8xz^c~G= -@;wJXZSX)(AcP&0m&7MZ.awx.!knvƐKP+q - vפdA -鼔D؄^M]]H[S g]5hoOd>(4,[f ¾HC] h6sB]&hn!yKSiZy<N=vSt}H衁ş!v\=9IcȝSOpVw3eRjm /{gyZd:r}EaQ~_Oxt9I?bGlw^+Z"Mt G&;N 4ez2&*X[LL3vsxkj 6i+A bv7kk\% YjQt\y`4NXo .EeX[H& RQ%s#PE#ʠVQkSʶj+r9Mr ^8n&Yv;3Dʌ5Qm87N~畮z^"J] - U{L64YTZĆΠń'Z!UTp5a:17}vq]!@B[ :5HΐZN5%]i*4>9uG'l:ڂd<",l9%NFT2Ʉڢ6*A2H@iT[ Z%H27bXd¢l4Od8|aj%zjj)z8WsƥlҵMf~jJ"D[6sĮ7rO^WM UإeJAMmyP+vXz\&ד AԮնpY"r\?i08lF>Ú`Z=2yPt̾e6 }wXſcCR묵Smzv(1 ˔jtb*tWKp j;wx78Vw5zGAe(ll y tA%1UkIJa* hܺZB6Rvy-M]@uoNxrsٟZ*(>^oC^(KbX+R 4UUZhyJ$I96HԳPf4݁d*U^GBV+@ -RҩF{qfvq$ߢ~&X0MFLmml˨~OX܏!e+MPt:АzbS[?-.9dm1J+Y{7$P5mw|l:irL4{j}V/MEW/s ?/ۛNgMY8"Ia,MߎôwT"PRvU/dbKfdz7ovGni%TBKľq@Ҳ7l7X^a\0&2qGBSC,L>}cރpWKjN4qGQ>RuV"VфF ˲rTɻkO_XQ8[D@̯AO :F-|TTH L -Ogpyxp^φp{b4D CH֮t:*f֗ipDLA\]C_#_Ɛf'qC^"utgKhMO X6B KdUA 5fRN*q,@wv5v~t Di8d!wqu?9uNztk\eUR9ab/ W}'cV#fN?*݃rVpfk*T}|O5X gYwϵ+uʽ_X#ddZ28;!tOigA+wKxM? O0 b{k1l -d2u TrړS$$V(4T5\ŕ"DSBkY&nz"PhrxT1s,2kΡ Za&u0) j"f"_#Q(h_ zь18-֢6 - Bڤ3`C=KfՊDkks,~Cbz@JA ;b@̼,.Nɗ:YWfvhJ`'rɂќNH"j Z;6t= P\U - 1I-uq3y1>tF}ɽ0Αp]k2!%~ Ae# A~VG0ԁ[R#֕4?2~G*kSxCAL,XA%ZUΚgvSwjސ*?Zt9oiyI9PvcރvGR WrPbPw z7yn9#87 5#SOS -8c^/V3@Wh5jij+Xo+5Ib+ZU.Yo @Ì6ôRDpqcK>zYT _Mڒ:8!iٌDP]Y~AKiP W`2t@AeH܀("⯥! bo;KDE!DE1 -:۪Zl7]]H'WAm|GSQ,bބoDoa5{Ł`}= A>:cj0P +5?mƯk Ď[p3~3qF;raE'¦Nulz8 4Ch !@VPbޖe@Eß_* -9 ֕sck@_Vc=Gˤ*C%2DcDHʉp}} UGJ%:cp91&J gѾOc0A'` -Kɗ @qP7Kb?Ozx)5r$%y;Ϫ7:aj(L(qƺ\-DZіuP=3a,.4SP($0m_#{ & `'•+.<ڵq4/Ɋ%$=:JKN2Oa8E/f6#ɑ҃ӈ|}X;zth4 09F%ľ M80YޭnXh:ʞ>VI$VY#>tת\B.siy/9?˺> -`y 16|#qHWoLYaUhxX Y̎s 5t#NyYpD88-V.~nRIVu!Q=T3։glHߙ VCf@-\n]?pt_(KۖqU0c; oΑsӵtXeWxdLt8U9G?pix#XGiKAWP u6wp(WXliy0u,F1l9(*9&3 ,$nY&E<@ؠqp -N>Ca#D33 =_28p*mfl'9$xV*%u/rZz`z^B5pnFWfVʌ ʋJ6l)wVZvR/N9㕑P7~`C\|g.5t5kwٰp놤 ՠi@y1f s:ҽ7do8p#tl-|(RmԽ@=|SI*?m)DbەeqMEaFTj,5꺪j `p: =^WiD L_ɐi(0LOIeQ@wt 7E>v8\.U'G{qQ_ZOcL_-(CeU͝mmԸ̝#cM'Xs!G\殞Ű 62QBfF`$Gדёѓ2Q|wvb;=lয়z3 slްm!)a=-7\mmg?al,ALj-FbMjAΤ5m\̽Yx{>~}s⑈d4e?^[kPSEnceЙfq]bQc_|5W'!}5m-ڨ5i,~{^_*H-ZN YLmK%gBŒX7.YK+⿒!6F)!j%Q Tʇ 1ގ=e:e!|'¸n(|>϶lFB ]%t -{ĥ\A*U}Io4~B\]M?EYܓpihxhN±@,* y36Ww6X&:lNo$I3@#ݧ6j @r\ĥF7pgulPzR JⷰG&8uϣ>! [k j1#e`wSCce* nzvTyReVW6U C\TSyD[ zkZh7Y~GQ;fk5Z-BMe3Eoe -¶0mAWԁKiRT+eHs3@5dG=׽gF: "[{ Ԟ:![#q,&}uI.bw67wrW24? V 29'/%jIQ |gxSR-mD-=wԡc#=mu3 BNKM] [!*=?5|l09̣eWK[q}5kɆ;|-mN*MBk9b}jOBQ"aqM5Α@p9\Zz 7kщ & -}N&B?kZ6|స\nz5B()+b΢grQ%ؚ!xSFXn=J hvSr<<BAFJ^aB/Q|eoJϦUnRV)5(o3u_QP9+e}-ŒCNP4HŒoMuzUvDwwh[e^o "^(DL* c10#ãO`MR+ 8e $`˽q^"ĿgSXc0j ·!1UǒzIc1%2}(i'ce~Yf8 ~dv?$Ų&>e_s?.y{%Scgg)&b}'eP>N?7u~n`ݜ$o#9=99=9N'evܧ7X*cY]$uX=GaɊّMlAV`í6GB+@JQ!/hdP ج]|k -5Ti0@ -EPj4Ann' !/1瑅m1`Ϊ6!*Zʨ}':QT:TQe"LV`5,K_x)?ǜwq3g}G.`ܱRD%B(=⠺IU ~ʠB! axVD-wI6?/{żpSH[ Bt \e6 qd w!hyxH8 \<|.C/cb&0Qx0+Z֦sȥrpx Q"^{_u?ʨuuœ O6!.Խ7#}#/NbgAW+[Ԅ1rԛfЈ*7IV$f''Kڭҷ}8%hGIICC;!8okyPG!  ud^ԭ&ʨkU/Cv1v?]G:abT"V$wM]iMS*+4X^CPk-4;U.R*}5t 8,qzC: zLKinX(a#lf)QeBΐM^=ގPElHQ Eg֛NOfsZgV5ii[;{;s댹-Ni "]}hh/@ Z%Wm'#6dclnO;ߖI݅7HMiBY%K5zN1Iv_Cq#ګ vhЉP=]5-dЗrA`oqϴ(_do -y];EEA}a=O[PjkjuI9ThHrqXRgԦ1V p%juqi^izoO.EBwDQҐٛXPa[9;c4zɸ^s)oڇaE!N -l/Z)%5W # F@Jz*ԩy@ Ar7%ږH%̸PV[-PO>uw6c$GURԃzob}v2- - eu4pU G - --pdb/uEA~OQ.tA -$x3*TV䀤*Kg XLv[CB,eS CI.=W DroVaQ>E+ `1:Ƣ)=D5 d]:CmQN+}N5RHTRCG0ٽ梢`9al ыޜM7'rԨƥj:0!_RbgyR3i=G8f;XUc5q⌧Gxf=F}_4| [IcI;2\,+.&Q$PGb_U -S lrXWҩٳm - ^OnC: [%mO=H]쳈B=(5N^[ H$,`- -s>0C3]+,njW ˋkx8 nװkj991jʿVqy7AG36VKV(sYKѿ\bUKs"4}'"d٦3#FN:@LeRe1Ssq={Ƈ96Fx=a4`P1(@Q+;*8kXjЛ9f'PVO>kr'LK`2'Gb Bv=x<D)7 KajQ7 V zpbv \B6&,t= a|8q_|lJK?}nھ/ ܐAg[FZ2Eb‰ƣaĺy:Io:zg:_RnYMNaZZnZnRN@N`% %uovSҳҳ+W15 j b# &vAH+8j뷬Ϧl/ݚєK|.Hm:=:#zd:BZ2vfJ!Ydbݼ顷羻dkuz#|X3jָ)늓[i'}IMI$816`1H!$ & 1vpl8nW Mi\|q֕vZJ蜳>})1ى -ƷI,%иX+s=!DH*J&ĖD?*CQ -dHW8d2_HXvg}cP߄pwX"cѼo^yAHfjV٠7;.@nEV>ԪBDgMЙ(!kW/n,e{dnB.xz[fv~㉐`dC>BU>-` VT/ s[1ȸ|.ZeAmTbciQ>Xhf Rz@SWׄčYx?2e,<Ë'^[&;"ۧUgO1RxT[Q\.)b(6.aM3a!хdì=.i(\j -!8 }l50R;Μ+l_gǃvSwc)=H)Ίrg3S^οMޔV}U6`i0 WkADhGfjMJL\./sv99/3Ե)@GvDC|Ijbu"1[ MRnaRejGuz .h4:;?kYA-u& -ͪBienF/z@=n A4[ ( 00wڻu‡T#;r@~5WPl4TtEEQ C]ΊlWۗZz]K @.jP{/zOE1q(ZCF4|*Xr{cdϛ]x EO]yj]txF{:-vJnebe$G"@)y !ԨX)r"{gL rſzӺ7uɺ|MKm#sa*,*@UIl'`. !aQ!*+%j A5\Ҏ77/KQg:2j2m =`k5vm|@1Q' ~zϋߩޕ^sL/RعEά$HL~ ?1oGg:* soq(;+ "UVe[I u>a3}o ⇤xc1g 7@k`&@,84w)HdRiJd\i,+R@dy%.,SJp~`${9JI ;-zQ^ƩPEL7}7p- vn4Xz+e@*ā-}.y*;2^[/L_eJݎ,{-ʖg~vDɗ㳞?kj%zAb;`o]r]E v,0ubũUP &X\x3&QW`c~|,X-zhDwR7#"  8(HL͌Ij IRs\4DGA߸}ÎGvq9%[dbP@Q zQҬ`}wGoD, -Ο/P܂_ u$ͻgHIedDzAvWt+B\f+et%&Zg;Gz ¹]pvbkuR3ϏK=j M8 z@(T1SY)P~ -k,^!}~q/\sgϺ='"xk{֢>h531RGzz=3oql~5^g1e2e- b 4# ~` IkAub ~x^ S D$Ek64{ažV)) -M;.%*xG9v_ނeœ7\{1@I(VT% ~u(.X^G 'A64rr1 hQ3^]VW ub⳿/;Ȫ1B Ꚍann}҈p"DW"k[體P4TŌg1@gF(A,_ Z bgZGeE?UwQ\w(sdd;=u0 {2 2{80j;'4zhnD lu.mGEQGh(eNE޾L[os5<q :^ kv%þ${{C7 -ׄd 9~Xp?eZ3YC17HR|Wd vP+JQHqٛb2a[;u,$!_BbN,~1ѣ hAi8/8{0bWf;)IW@?~bhK?Yl5E$ i6sqCtpӉR{@VU]oEW!YAlm<-[KClA.3jo:l?F&877jQj_mo -dSTq@]-!.,ZF/A4I#QPC8'aM8ؗF/IGj}kE/<8֒ƚ~}_P(( *7-IQ#{q7Ӹ462@亰 nd|IcD>rFiKMBk%eЍo1X}VNV^ZqZf%_ :g59^^Xv-G3t8bL\/ʵGZ ZKȲ5i !0m^ld C2RٳSK6ugT<;Tt҄g|TV -|ZvYhV[hcNxb2:D露x'I8BYSk~` fkʠ40=WqTQӠY|k;׸ε̍+2t K( MZL`˴aa ndҤɾy2lg mF u~$(cڙ(nBbZX0jL4DYKi{^f1A ЂNU'9 dwMN}{&KJS2hٗڕ6C],\wK{IzZ-fo^Xvk B}Yqڨ'mZ=NZQ+ceiu\)W -j3TJ*ն8tuV$t:h~|RITUrQna:Pŋ=›+K}i*T13D"["uF_\T(kerJTW&!E_ @'c0l"~qsBEMAAazkZYkzԊ_Zp_Caޖz;\B'p ocL8NJka%zn !5D]Bt%qe> -endobj - -4391 0 obj -<< - /Type /Font - /Subtype /CIDFontType0 - /BaseFont /ZXCGTT+LibertinusSerif-Regular - /CIDSystemInfo << - /Registry (Adobe) - /Ordering (Identity) - /Supplement 0 - >> - /FontDescriptor 4393 0 R - /DW 0 - /W [0 0 500 1 1 375] ->> -endobj - -4392 0 obj -<< - /Length 9 - /Filter /FlateDecode ->> -stream -x; -endstream -endobj - -4393 0 obj -<< - /Type /FontDescriptor - /FontName /ZXCGTT+LibertinusSerif-Regular - /Flags 131078 - /FontBBox [0 0 500 698] - /ItalicAngle 0 - /Ascent 894 - /Descent -246 - /CapHeight 658 - /StemV 95.4 - /CIDSet 4392 0 R - /FontFile3 4395 0 R ->> -endobj - -4394 0 obj -<< - /Length 619 - /Type /CMap - /WMode 0 ->> -stream -%!PS-Adobe-3.0 Resource-CMap -%%DocumentNeededResources: procset CIDInit -%%IncludeResource: procset CIDInit -%%BeginResource: CMap Custom -%%Title: (Custom Adobe Identity 0) -%%Version: 1 -%%EndComments -/CIDInit /ProcSet findresource begin -12 dict begin -begincmap -/CIDSystemInfo 3 dict dup begin - /Registry (Adobe) def - /Ordering (Identity) def - /Supplement 0 def -end def -/CMapName /Custom def -/CMapVersion 1 def -/CMapType 0 def -/WMode 0 def -1 begincodespacerange -<0000> -endcodespacerange -1 beginbfchar -<0001> <2023> -endbfchar -endcmap -CMapName currentdict /CMap defineresource pop -end -end -%%EndResource -%%EOF -endstream -endobj - -4395 0 obj -<< - /Length 344 - /Filter /FlateDecode - /Subtype /CIDFontType0C ->> -stream -xcd`aa`ddLJ-*+-N-L JM/I,ɹ!#CAAB<=EFBOVY \ (>񨀨W< ̌l|ގ)I)y%%E% -BHFY -EY% -%Ez L 8Θ;u3VNe4]yn\oMOQ4@!!&FFߔ?^cCe/s7ˏ~:nn}wߓX+ -bW}c3wOd{||95~Rl; -endstream -endobj - -4396 0 obj -<< - /Type /Font - /Subtype /Type0 - /BaseFont /LCCCWY+DejaVuSansMono-Bold - /Encoding /Identity-H - /DescendantFonts [4397 0 R] - /ToUnicode 4400 0 R ->> -endobj - -4397 0 obj -<< - /Type /Font - /Subtype /CIDFontType2 - /BaseFont /LCCCWY+DejaVuSansMono-Bold - /CIDSystemInfo << - /Registry (Adobe) - /Ordering (Identity) - /Supplement 0 - >> - /FontDescriptor 4399 0 R - /DW 0 - /CIDToGIDMap /Identity - /W [0 8 602.0508] ->> -endobj - -4398 0 obj -<< - /Length 10 - /Filter /FlateDecode ->> -stream -x -endstream -endobj - -4399 0 obj -<< - /Type /FontDescriptor - /FontName /LCCCWY+DejaVuSansMono-Bold - /Flags 131077 - /FontBBox [16.113281 -176.75781 602.0508 742.1875] - /ItalicAngle 0 - /Ascent 759.7656 - /Descent -240.23438 - /CapHeight 759.7656 - /StemV 168.6 - /CIDSet 4398 0 R - /FontFile2 4401 0 R ->> -endobj - -4400 0 obj -<< - /Length 717 - /Type /CMap - /WMode 0 ->> -stream -%!PS-Adobe-3.0 Resource-CMap -%%DocumentNeededResources: procset CIDInit -%%IncludeResource: procset CIDInit -%%BeginResource: CMap Custom -%%Title: (Custom Adobe Identity 0) -%%Version: 1 -%%EndComments -/CIDInit /ProcSet findresource begin -12 dict begin -begincmap -/CIDSystemInfo 3 dict dup begin - /Registry (Adobe) def - /Ordering (Identity) def - /Supplement 0 def -end def -/CMapName /Custom def -/CMapVersion 1 def -/CMapType 0 def -/WMode 0 def -1 begincodespacerange -<0000> -endcodespacerange -8 beginbfchar -<0001> <0052> -<0002> <0045> -<0003> <004C> -<0004> <004F> -<0005> <0041> -<0006> <0044> -<0007> <0055> -<0008> <004E> -endbfchar -endcmap -CMapName currentdict /CMap defineresource pop -end -end -%%EndResource -%%EOF -endstream -endobj - -4401 0 obj -<< - /Length 4326 - /Filter /FlateDecode ->> -stream -xXypTǙ^ϥc B\bFBpY⑑YB 4#Fd#&)qd ^(En[8*d7HȘVvf~0)nߛ/oYR Ђ~}U hC 7l Xis"}wv Ζ&뿋hӾnUh960Xg, uXW8V@ Я,e'pj c\62,`9j-Y. +{Hz*ѧe40N칪>NBc)hx g3qcylc,Wb6qp?g`q|2>>ȟ)>Ua:Yך+<;O-Dl.XZg+6 .3ŋSx Ϡ\u| gh)?,V`ɯ$c?zʒΊ|8>u -|~-2ܰFaKG]~͛u[<[{:/Tm]QnV3-!VX\fs|bcDi=*R0 Kl -bΎ)]Yv's\#C#"^H:,ve.,s ~[DtE"7evFLgvƈqό?> bG}#ƣ>v׃wAu+-Ah ras#d)dv"WpdUS8qHpdNc 8EVXKlV0C_Vh+KmqudO~k'Tmƾe\fo\Ƴgx!cz>ܘ=b.rӲxR|PL@+?)3_w>kc+Y׸`|x_{>fV9FxQoV>73 -f9,;SfkN9pMY++w4Ov]lkƟͥ#ءC1>Rob^1|v4gZ4Ւg!0϶c# PԌKiycl{0ե1e -;ŽY؞+{*Ӎ;>{߃8k=ԯ\'̶Mw^KDG.K`P;QcwFu~I"%!"8Wp1"1,=ZPδkX0,BPXp'A`l3plk?6a>5zR#̶lٶ!՘`1ΘtDjt"Bv"n0-(A Çf ݈] QJtE hXqyFatAB(GЄ- )G$}hC|hGZCIMi(a=:сN܋N#|#7KqAc8/* -ݦbBnİ(F zP8:у. ,vIEЁ0& -P"RFF ŨfюN|EZV67@_LEcYvÇN~)YċJlT6)?*{ãTU6nb33^YD3NӗSfd1>Ǜ"E3b2),׏,ɑsCWމO` z(k>hCF9Yk_^3υ1MĝЉz$16!遈X#С(J2"rwʈx(?Q=RÂ舶e,c73~}'zPm{)*ϔṇRYHVgvQh"S'M\* aH<5&9]2!m4qs9 ;X 1n !pEǍMؤ{@&3O1i+FQ߸Qع](&Eo5^+9b?]qUgتK(QA'%uLDsZMr@V碪';{*-8[GZ -i5(b 6b P/*PZlF%Qr2#sj܂JXMKaԣLb7'EZ#P˹*mTA֢^bGQ)mQM(UjP+bIVdz ֣XufoE5]3sɴLj$jlBw7uES lkkPoR!H(FQ:4k% ai9R\oȬV]Ŭ֌haSo FV -T GqV"JM?Rz(0DPQY=:>)*"e2n/<4LIm|t&ˎ%&P -HJjS[^8n&s›Z!*e$Ƣ/"nUE?DY *QRzQ6qdgbL7dPX #(:)j'#\wU`bNǪ iM.VN7vW{I&;ODnl\djhUΏDTbH}m-u`gs|j QWbnXrsHV1O(uaܯ=.<#9h@ v_0yy0dx-?w~ z=D} n:AA?2̫i0F$ŠW_~$ܫ|R#O ANM_X_4Ło/<__XKϗss}ߠ 3]w/e7 [Ơa?y:Oe҉']tOcGc==OG{#Gӑ<:F;>zԠG.Hzeʠ`@Z=v?f}!kЃux<.Q5RguDyDUt_e*3h05{:elfY3 /kîO3h44Mpڢgyije3hr. 3 +䂇Lʝ)lNM)NM)NrmTnsMyh85CnvnqeԹCpiiIK#g:|-_] -endstream -endobj - -4402 0 obj -[/ICCBased 4404 0 R] -endobj - -4403 0 obj -[/ICCBased 4405 0 R] -endobj - -4404 0 obj -<< - /Length 258 - /N 1 - /Range [0 1] - /Filter /FlateDecode ->> -stream -xuJPFOUvDD@`]\ -FMkIRB|&إnऋ(HrTų9` ըa&ʺ:l -3Ŭ*ުnh)&C|>b纝黓AvCƫ+ y') -̵8+/> -stream -x}Kq?UX 94%MQKSN#ԦQvBˡhFk ! -ՠZP~xx^ޗQx"^P c!H0 - 0l+ߣy7;׫;Q?V._tF3LEK)y z80eIPkT/%[p:8+%d"G `d_{ٹ֖gzm\8rSif1\CU` S] @o _ -endstream -endobj - -4406 0 obj -[4743 0 R /XYZ 70.86614 563.1574 0] -endobj - -4407 0 obj -[4743 0 R /XYZ 70.86614 227.6214 0] -endobj - -4408 0 obj -[4756 0 R /XYZ 70.86614 473.5624 0] -endobj - -4409 0 obj -[4756 0 R /XYZ 70.86614 189.85742 0] -endobj - -4410 0 obj -[4743 0 R /XYZ 70.86614 270.0724 0] -endobj - -4411 0 obj -[4769 0 R /XYZ 70.86614 546.0924 0] -endobj - -4412 0 obj -[4743 0 R /XYZ 70.86614 751.3704 0] -endobj - -4413 0 obj -[4787 0 R /XYZ 70.86614 660.6094 0] -endobj - -4414 0 obj -[4787 0 R /XYZ 70.86614 224.9267 0] -endobj - -4415 0 obj -[4799 0 R /XYZ 70.86614 484.6444 0] -endobj - -4416 0 obj -[4787 0 R /XYZ 70.86614 766.8504 0] -endobj - -4417 0 obj -[4803 0 R /XYZ 70.86614 438.3524 0] -endobj - -4418 0 obj -[4808 0 R /XYZ 70.86614 766.8504 0] -endobj - -4419 0 obj -[4803 0 R /XYZ 70.86614 592.29944 0] -endobj - -4420 0 obj -[4817 0 R /XYZ 70.86614 651.1064 0] -endobj - -4421 0 obj -[4817 0 R /XYZ 70.86614 149.31738 0] -endobj - -4422 0 obj -[4820 0 R /XYZ 70.86614 212.80957 0] -endobj - -4423 0 obj -[4812 0 R /XYZ 70.86614 162.83142 0] -endobj - -4424 0 obj -[4829 0 R /XYZ 70.86614 141.41962 0] -endobj - -4425 0 obj -[4836 0 R /XYZ 70.86614 326.0504 0] -endobj - -4426 0 obj -[4840 0 R /XYZ 70.86614 193.52795 0] -endobj - -4427 0 obj -[4844 0 R /XYZ 70.86614 367.3716 0] -endobj - -4428 0 obj -[4829 0 R /XYZ 70.86614 554.3584 0] -endobj - -4429 0 obj -[4848 0 R /XYZ 70.86614 358.31302 0] -endobj - -4430 0 obj -[4852 0 R /XYZ 70.86614 403.732 0] -endobj - -4431 0 obj -[4848 0 R /XYZ 70.86614 443.95 0] -endobj - -4432 0 obj -[4803 0 R /XYZ 70.86614 766.8504 0] -endobj - -4433 0 obj -[4874 0 R /XYZ 70.86614 461.0124 0] -endobj - -4434 0 obj -[4884 0 R /XYZ 70.86614 442.8364 0] -endobj - -4435 0 obj -[4899 0 R /XYZ 70.86614 266.8504 0] -endobj - -4436 0 obj -[4917 0 R /XYZ 70.86614 483.2844 0] -endobj - -4437 0 obj -[4864 0 R /XYZ 70.86614 344.5394 0] -endobj - -4438 0 obj -[4921 0 R /XYZ 70.86614 562.8894 0] -endobj - -4439 0 obj -[4925 0 R /XYZ 70.86614 644.3064 0] -endobj - -4440 0 obj -[4921 0 R /XYZ 70.86614 703.17444 0] -endobj - -4441 0 obj -[4941 0 R /XYZ 70.86614 614.0324 0] -endobj - -4442 0 obj -[4864 0 R /XYZ 70.86614 519.0904 0] -endobj - -4443 0 obj -[4947 0 R /XYZ 70.86614 460.6354 0] -endobj - -4444 0 obj -[4956 0 R /XYZ 70.86614 573.4164 0] -endobj - -4445 0 obj -[4973 0 R /XYZ 70.86614 703.17444 0] -endobj - -4446 0 obj -[4976 0 R /XYZ 70.86614 689.5124 0] -endobj - -4447 0 obj -[4976 0 R /XYZ 70.86614 171.0354 0] -endobj - -4448 0 obj -[4947 0 R /XYZ 70.86614 566.8764 0] -endobj - -4449 0 obj -[4998 0 R /XYZ 70.86614 687.9334 0] -endobj - -4450 0 obj -[5009 0 R /XYZ 70.86614 716.8364 0] -endobj - -4451 0 obj -[5009 0 R /XYZ 70.86614 150.51141 0] -endobj - -4452 0 obj -[5053 0 R /XYZ 70.86614 593.8784 0] -endobj - -4453 0 obj -[4998 0 R /XYZ 70.86614 766.8504 0] -endobj - -4454 0 obj -[5066 0 R /XYZ 70.86614 682.9724 0] -endobj - -4455 0 obj -[5066 0 R /XYZ 70.86614 331.1374 0] -endobj - -4456 0 obj -[5066 0 R /XYZ 70.86614 302.23438 0] -endobj - -4457 0 obj -[5066 0 R /XYZ 70.86614 268.1104 0] -endobj - -4458 0 obj -[5066 0 R /XYZ 70.86614 233.98639 0] -endobj - -4459 0 obj -[5066 0 R /XYZ 70.86614 199.86243 0] -endobj - -4460 0 obj -[5066 0 R /XYZ 70.86614 179.40039 0] -endobj - -4461 0 obj -[4756 0 R /XYZ 70.86614 101.267395 0] -endobj - -4462 0 obj -[5066 0 R /XYZ 70.86614 117.95239 0] -endobj - -4463 0 obj -[5095 0 R /XYZ 70.86614 766.8504 0] -endobj - -4464 0 obj -[5095 0 R /XYZ 70.86614 684.9404 0] -endobj - -4465 0 obj -[5095 0 R /XYZ 70.86614 650.8164 0] -endobj - -4466 0 obj -[5095 0 R /XYZ 70.86614 616.6924 0] -endobj - -4467 0 obj -[5095 0 R /XYZ 70.86614 582.56836 0] -endobj - -4468 0 obj -[5095 0 R /XYZ 70.86614 534.7824 0] -endobj - -4469 0 obj -[4756 0 R /XYZ 188.99736 745.5764 0] -endobj - -4470 0 obj -[5095 0 R /XYZ 70.86614 486.9964 0] -endobj - -4471 0 obj -[5095 0 R /XYZ 70.86614 452.8724 0] -endobj - -4472 0 obj -[5095 0 R /XYZ 70.86614 418.7484 0] -endobj - -4473 0 obj -[5095 0 R /XYZ 70.86614 370.9624 0] -endobj - -4474 0 obj -[5095 0 R /XYZ 70.86614 309.5144 0] -endobj - -4475 0 obj -[5095 0 R /XYZ 70.86614 248.0664 0] -endobj - -4476 0 obj -[5095 0 R /XYZ 70.86614 213.94238 0] -endobj - -4477 0 obj -[5095 0 R /XYZ 70.86614 193.48041 0] -endobj - -4478 0 obj -[5095 0 R /XYZ 70.86614 132.03241 0] -endobj - -4479 0 obj -[5127 0 R /XYZ 70.86614 766.8504 0] -endobj - -4480 0 obj -[5127 0 R /XYZ 70.86614 719.0644 0] -endobj - -4481 0 obj -[5127 0 R /XYZ 70.86614 671.2784 0] -endobj - -4482 0 obj -[5127 0 R /XYZ 70.86614 623.49243 0] -endobj - -4483 0 obj -[5127 0 R /XYZ 70.86614 575.7064 0] -endobj - -4484 0 obj -[5127 0 R /XYZ 70.86614 514.2584 0] -endobj - -4485 0 obj -[5127 0 R /XYZ 70.86614 466.4724 0] -endobj - -4486 0 obj -[5127 0 R /XYZ 70.86614 432.3484 0] -endobj - -4487 0 obj -[5127 0 R /XYZ 70.86614 370.9004 0] -endobj - -4488 0 obj -[5127 0 R /XYZ 70.86614 336.7764 0] -endobj - -4489 0 obj -[5127 0 R /XYZ 70.86614 275.32843 0] -endobj - -4490 0 obj -[5127 0 R /XYZ 70.86614 227.54242 0] -endobj - -4491 0 obj -[5127 0 R /XYZ 70.86614 166.09442 0] -endobj - -4492 0 obj -[5127 0 R /XYZ 70.86614 131.9704 0] -endobj - -4493 0 obj -[5155 0 R /XYZ 70.86614 766.8504 0] -endobj - -4494 0 obj -[4806 0 R /XYZ 70.86614 408.4204 0] -endobj - -4495 0 obj -[5155 0 R /XYZ 70.86614 719.0644 0] -endobj - -4496 0 obj -[5155 0 R /XYZ 70.86614 684.9404 0] -endobj - -4497 0 obj -[4829 0 R /XYZ 70.86614 211.88239 0] -endobj - -4498 0 obj -[4806 0 R /XYZ 70.86614 322.02838 0] -endobj - -4499 0 obj -[4808 0 R /XYZ 70.86614 259.5064 0] -endobj - -4500 0 obj -[5155 0 R /XYZ 70.86614 650.8164 0] -endobj - -4501 0 obj -[4840 0 R /XYZ 70.86614 436.0584 0] -endobj - -4502 0 obj -[5155 0 R /XYZ 70.86614 589.3684 0] -endobj - -4503 0 obj -[4844 0 R /XYZ 70.86614 551.676 0] -endobj - -4504 0 obj -[4848 0 R /XYZ 70.86614 766.8504 0] -endobj - -4505 0 obj -[4874 0 R /XYZ 70.86614 766.8504 0] -endobj - -4506 0 obj -[4852 0 R /XYZ 70.86614 530.7204 0] -endobj - -4507 0 obj -[4840 0 R /XYZ 70.86614 690.6024 0] -endobj - -4508 0 obj -[4874 0 R /XYZ 70.86614 273.1394 0] -endobj - -4509 0 obj -[4836 0 R /XYZ 70.86614 249.72339 0] -endobj - -4510 0 obj -[4836 0 R /XYZ 70.86614 626.2924 0] -endobj - -4511 0 obj -[4884 0 R /XYZ 70.86614 166.1914 0] -endobj - -4512 0 obj -[4899 0 R /XYZ 70.86614 531.0484 0] -endobj - -4513 0 obj -[4820 0 R /XYZ 70.86614 481.9704 0] -endobj - -4514 0 obj -[4822 0 R /XYZ 70.86614 552.6725 0] -endobj - -4515 0 obj -[4822 0 R /XYZ 70.86614 114.11548 0] -endobj - -4516 0 obj -[4905 0 R /XYZ 70.86614 733.27637 0] -endobj - -4517 0 obj -[4905 0 R /XYZ 84.86614 575.9684 0] -endobj - -4518 0 obj -[4905 0 R /XYZ 84.86614 676.9084 0] -endobj - -4519 0 obj -[4905 0 R /XYZ 70.86614 397.0664 0] -endobj - -4520 0 obj -[4905 0 R /XYZ 70.86614 133.45135 0] -endobj - -4521 0 obj -[4905 0 R /XYZ 460.86523 491.3384 0] -endobj - -4522 0 obj -[4917 0 R /XYZ 70.86614 356.8594 0] -endobj - -4523 0 obj -[5155 0 R /XYZ 70.86614 541.5824 0] -endobj - -4524 0 obj -[5155 0 R /XYZ 70.86614 507.4584 0] -endobj - -4525 0 obj -[4929 0 R /XYZ 70.86614 111.99536 0] -endobj - -4526 0 obj -[4929 0 R /XYZ 215.36813 305.1084 0] -endobj - -4527 0 obj -[4941 0 R /XYZ 70.86614 123.72339 0] -endobj - -4528 0 obj -[4941 0 R /XYZ 70.86614 101.267395 0] -endobj - -4529 0 obj -[4941 0 R /XYZ 424.47882 581.8794 0] -endobj - -4530 0 obj -[4941 0 R /XYZ 448.44293 568.2174 0] -endobj - -4531 0 obj -[5155 0 R /XYZ 70.86614 486.9964 0] -endobj - -4532 0 obj -[5155 0 R /XYZ 70.86614 466.5344 0] -endobj - -4533 0 obj -[5155 0 R /XYZ 70.86614 418.7484 0] -endobj - -4534 0 obj -[5155 0 R /XYZ 70.86614 370.9624 0] -endobj - -4535 0 obj -[5155 0 R /XYZ 70.86614 309.5144 0] -endobj - -4536 0 obj -[5155 0 R /XYZ 70.86614 241.26642 0] -endobj - -4537 0 obj -[4822 0 R /XYZ 70.86614 260.2793 0] -endobj - -4538 0 obj -[5155 0 R /XYZ 70.86614 207.1424 0] -endobj - -4539 0 obj -[5155 0 R /XYZ 70.86614 159.35638 0] -endobj - -4540 0 obj -[4973 0 R /XYZ 70.86614 111.99536 0] -endobj - -4541 0 obj -[5189 0 R /XYZ 70.86614 766.8504 0] -endobj - -4542 0 obj -[5189 0 R /XYZ 70.86614 732.7264 0] -endobj - -4543 0 obj -[5189 0 R /XYZ 70.86614 684.9404 0] -endobj - -4544 0 obj -[5189 0 R /XYZ 70.86614 650.8164 0] -endobj - -4545 0 obj -[5189 0 R /XYZ 70.86614 603.0304 0] -endobj - -4546 0 obj -[5189 0 R /XYZ 70.86614 568.9064 0] -endobj - -4547 0 obj -[5189 0 R /XYZ 70.86614 521.12036 0] -endobj - -4548 0 obj -[5189 0 R /XYZ 70.86614 486.9964 0] -endobj - -4549 0 obj -[5189 0 R /XYZ 70.86614 439.2104 0] -endobj - -4550 0 obj -[5189 0 R /XYZ 70.86614 377.7624 0] -endobj - -4551 0 obj -[4973 0 R /XYZ 246.03696 507.1394 0] -endobj - -4552 0 obj -[5189 0 R /XYZ 70.86614 329.9764 0] -endobj - -4553 0 obj -[5189 0 R /XYZ 70.86614 295.85242 0] -endobj - -4554 0 obj -[5189 0 R /XYZ 70.86614 248.0664 0] -endobj - -4555 0 obj -[5189 0 R /XYZ 70.86614 186.61841 0] -endobj - -4556 0 obj -[5189 0 R /XYZ 70.86614 138.8324 0] -endobj - -4557 0 obj -[5221 0 R /XYZ 70.86614 766.8504 0] -endobj - -4558 0 obj -[5221 0 R /XYZ 70.86614 732.7264 0] -endobj - -4559 0 obj -[5221 0 R /XYZ 70.86614 698.6024 0] -endobj - -4560 0 obj -[5221 0 R /XYZ 70.86614 650.8164 0] -endobj - -4561 0 obj -[5221 0 R /XYZ 70.86614 603.0304 0] -endobj - -4562 0 obj -[5221 0 R /XYZ 70.86614 568.9064 0] -endobj - -4563 0 obj -[5221 0 R /XYZ 70.86614 507.4584 0] -endobj - -4564 0 obj -[5221 0 R /XYZ 70.86614 459.6724 0] -endobj - -4565 0 obj -[5221 0 R /XYZ 70.86614 411.8864 0] -endobj - -4566 0 obj -[5221 0 R /XYZ 70.86614 364.1004 0] -endobj - -4567 0 obj -[5221 0 R /XYZ 70.86614 316.3144 0] -endobj - -4568 0 obj -[5221 0 R /XYZ 70.86614 282.19043 0] -endobj - -4569 0 obj -[5221 0 R /XYZ 70.86614 234.40442 0] -endobj - -4570 0 obj -[5221 0 R /XYZ 70.86614 186.61841 0] -endobj - -4571 0 obj -[5221 0 R /XYZ 70.86614 138.8324 0] -endobj - -4572 0 obj -[5251 0 R /XYZ 70.86614 732.7264 0] -endobj - -4573 0 obj -[5251 0 R /XYZ 70.86614 684.9404 0] -endobj - -4574 0 obj -[5251 0 R /XYZ 70.86614 637.1544 0] -endobj - -4575 0 obj -[5251 0 R /XYZ 70.86614 589.3684 0] -endobj - -4576 0 obj -[5251 0 R /XYZ 70.86614 527.9204 0] -endobj - -4577 0 obj -[5251 0 R /XYZ 70.86614 480.1344 0] -endobj - -4578 0 obj -[5251 0 R /XYZ 70.86614 432.3484 0] -endobj - -4579 0 obj -[5251 0 R /XYZ 70.86614 398.2244 0] -endobj - -4580 0 obj -[5251 0 R /XYZ 70.86614 364.1004 0] -endobj - -4581 0 obj -[5251 0 R /XYZ 70.86614 343.6384 0] -endobj - -4582 0 obj -[5251 0 R /XYZ 70.86614 309.5144 0] -endobj - -4583 0 obj -[5251 0 R /XYZ 70.86614 261.7284 0] -endobj - -4584 0 obj -[5251 0 R /XYZ 70.86614 213.94238 0] -endobj - -4585 0 obj -[5251 0 R /XYZ 70.86614 166.15637 0] -endobj - -4586 0 obj -[5251 0 R /XYZ 70.86614 132.03241 0] -endobj - -4587 0 obj -[5270 0 R /XYZ 70.86614 766.8504 0] -endobj - -4588 0 obj -[5270 0 R /XYZ 70.86614 705.4024 0] -endobj - -4589 0 obj -[5270 0 R /XYZ 70.86614 684.9404 0] -endobj - -4590 0 obj -[5270 0 R /XYZ 70.86614 664.4784 0] -endobj - -4591 0 obj -[5270 0 R /XYZ 70.86614 616.6924 0] -endobj - -4592 0 obj -[5270 0 R /XYZ 70.86614 568.9064 0] -endobj - -4593 0 obj -[5270 0 R /XYZ 70.86614 521.12036 0] -endobj - -4594 0 obj -[5270 0 R /XYZ 70.86614 473.3344 0] -endobj - -4595 0 obj -[5270 0 R /XYZ 70.86614 425.5484 0] -endobj - -4596 0 obj -[4743 0 R /XYZ 178.1254 701.1934 0] -endobj - -4597 0 obj -[4743 0 R /XYZ 423.09903 660.2074 0] -endobj - -4598 0 obj -[4743 0 R /XYZ 382.28867 632.8834 0] -endobj - -4599 0 obj -[4743 0 R /XYZ 508.94345 367.1224 0] -endobj - -4600 0 obj -[4743 0 R /XYZ 153.22902 353.4604 0] -endobj - -4601 0 obj -[4756 0 R /XYZ 524.4094 513.3844 0] -endobj - -4602 0 obj -[4756 0 R /XYZ 317.62296 441.4094 0] -endobj - -4603 0 obj -[4756 0 R /XYZ 125.0658 427.7474 0] -endobj - -4604 0 obj -[4756 0 R /XYZ 465.35275 414.0854 0] -endobj - -4605 0 obj -[4756 0 R /XYZ 278.04752 400.4234 0] -endobj - -4606 0 obj -[4756 0 R /XYZ 238.44057 359.4374 0] -endobj - -4607 0 obj -[4769 0 R /XYZ 219.96544 670.46643 0] -endobj - -4608 0 obj -[4769 0 R /XYZ 107.44759 486.6154 0] -endobj - -4609 0 obj -[4769 0 R /XYZ 237.97284 486.6154 0] -endobj - -4610 0 obj -[4787 0 R /XYZ 293.1822 628.4564 0] -endobj - -4611 0 obj -[4787 0 R /XYZ 408.30182 530.1707 0] -endobj - -4612 0 obj -[4787 0 R /XYZ 108.7478 468.7227 0] -endobj - -4613 0 obj -[4787 0 R /XYZ 270.1342 407.2747 0] -endobj - -4614 0 obj -[4787 0 R /XYZ 167.72777 352.6267 0] -endobj - -4615 0 obj -[4787 0 R /XYZ 210.38522 267.32867 0] -endobj - -4616 0 obj -[4787 0 R /XYZ 355.5598 267.32867 0] -endobj - -4617 0 obj -[4787 0 R /XYZ 412.81937 267.32867 0] -endobj - -4618 0 obj -[4787 0 R /XYZ 503.99344 267.32867 0] -endobj - -4619 0 obj -[4787 0 R /XYZ 235.28406 192.77368 0] -endobj - -4620 0 obj -[4799 0 R /XYZ 363.59082 711.4524 0] -endobj - -4621 0 obj -[4799 0 R /XYZ 322.45868 581.6944 0] -endobj - -4622 0 obj -[4799 0 R /XYZ 211.09238 527.0464 0] -endobj - -4623 0 obj -[4799 0 R /XYZ 381.96036 527.0464 0] -endobj - -4624 0 obj -[4799 0 R /XYZ 153.25615 513.3844 0] -endobj - -4625 0 obj -[4803 0 R /XYZ 317.83813 194.46942 0] -endobj - -4626 0 obj -[4817 0 R /XYZ 317.01538 618.95337 0] -endobj - -4627 0 obj -[4836 0 R /XYZ 168.51923 670.46643 0] -endobj - -4628 0 obj -[4840 0 R /XYZ 292.8334 462.5704 0] -endobj - -4629 0 obj -[4925 0 R /XYZ 355.30414 530.1814 0] -endobj - -4630 0 obj -[4925 0 R /XYZ 414.00015 530.1814 0] -endobj - -4631 0 obj -[4947 0 R /XYZ 291.5864 428.4824 0] -endobj - -4632 0 obj -[4947 0 R /XYZ 168.92632 107.51837 0] -endobj - -4633 0 obj -[4956 0 R /XYZ 524.4094 684.1284 0] -endobj - -4634 0 obj -[4956 0 R /XYZ 321.3684 425.1674 0] -endobj - -4635 0 obj -[4956 0 R /XYZ 145.59686 124.665405 0] -endobj - -4636 0 obj -[4956 0 R /XYZ 120.04367 111.00342 0] -endobj - -4637 0 obj -[4973 0 R /XYZ 310.54578 479.8154 0] -endobj - -4638 0 obj -[4973 0 R /XYZ 481.62567 302.27142 0] -endobj - -4639 0 obj -[4973 0 R /XYZ 136.55405 288.60938 0] -endobj - -4640 0 obj -[4973 0 R /XYZ 246.84358 274.9474 0] -endobj - -4641 0 obj -[4973 0 R /XYZ 443.16983 274.9474 0] -endobj - -4642 0 obj -[4973 0 R /XYZ 393.09418 199.8374 0] -endobj - -4643 0 obj -[4973 0 R /XYZ 162.6677 186.17542 0] -endobj - -4644 0 obj -[4973 0 R /XYZ 395.751 186.17542 0] -endobj - -4645 0 obj -[4973 0 R /XYZ 178.73436 138.3894 0] -endobj - -4646 0 obj -[4976 0 R /XYZ 238.37125 745.5764 0] -endobj - -4647 0 obj -[4985 0 R /XYZ 209.40015 656.8044 0] -endobj - -4648 0 obj -[4985 0 R /XYZ 443.829 533.9084 0] -endobj - -4649 0 obj -[4985 0 R /XYZ 209.55678 411.0124 0] -endobj - -4650 0 obj -[4985 0 R /XYZ 122.979576 226.60638 0] -endobj - -4651 0 obj -[4985 0 R /XYZ 292.35217 185.62042 0] -endobj - -4652 0 obj -[4985 0 R /XYZ 398.23715 171.95837 0] -endobj - -4653 0 obj -[4998 0 R /XYZ 334.1413 567.0084 0] -endobj - -4654 0 obj -[4998 0 R /XYZ 414.36783 539.6844 0] -endobj - -4655 0 obj -[4998 0 R /XYZ 240.69826 355.2784 0] -endobj - -4656 0 obj -[4998 0 R /XYZ 390.9383 211.8584 0] -endobj - -4657 0 obj -[4998 0 R /XYZ 355.56662 157.21039 0] -endobj - -4658 0 obj -[4998 0 R /XYZ 524.4094 157.21039 0] -endobj - -4659 0 obj -[5009 0 R /XYZ 283.5666 636.8974 0] -endobj - -4660 0 obj -[5009 0 R /XYZ 111.38758 595.9114 0] -endobj - -4661 0 obj -[5009 0 R /XYZ 272.62112 397.8434 0] -endobj - -4662 0 obj -[5009 0 R /XYZ 219.68813 206.57538 0] -endobj - -4663 0 obj -[5029 0 R /XYZ 239.16399 615.8184 0] -endobj - -4664 0 obj -[5029 0 R /XYZ 112.72849 602.1564 0] -endobj - -4665 0 obj -[5029 0 R /XYZ 276.56262 602.1564 0] -endobj - -4666 0 obj -[5029 0 R /XYZ 503.99344 574.8324 0] -endobj - -4667 0 obj -[5029 0 R /XYZ 306.7424 335.7784 0] -endobj - -4668 0 obj -[5029 0 R /XYZ 177.65485 294.79242 0] -endobj - -4669 0 obj -[5029 0 R /XYZ 298.93057 294.79242 0] -endobj - -4670 0 obj -[5029 0 R /XYZ 334.41858 253.8064 0] -endobj - -4671 0 obj -[5053 0 R /XYZ 485.22726 745.5764 0] -endobj - -4672 0 obj -[5053 0 R /XYZ 308.39426 731.9144 0] -endobj - -4673 0 obj -[5053 0 R /XYZ 486.7188 704.5904 0] -endobj - -4674 0 obj -[5053 0 R /XYZ 263.03928 690.9284 0] -endobj - -4675 0 obj -[5053 0 R /XYZ 289.94495 677.2664 0] -endobj - -4676 0 obj -[5053 0 R /XYZ 497.94345 486.6154 0] -endobj - -4677 0 obj -[5053 0 R /XYZ 399.76514 343.1954 0] -endobj - -4678 0 obj -[5053 0 R /XYZ 394.7261 145.12738 0] -endobj - -4679 0 obj -[5053 0 R /XYZ 172.12447 131.4654 0] -endobj - -4680 0 obj -[5053 0 R /XYZ 275.54834 104.14142 0] -endobj - -4681 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /XObject << - /x0 5272 0 R - >> - /Font << - /f0 4354 0 R - /f1 4360 0 R - /f2 4366 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 0 - /Parent 1 0 R - /Contents 4682 0 R ->> -endobj - -4682 0 obj -<< - /Length 2833 - /Filter /FlateDecode ->> -stream -x\[o\~?֛VlFE-΃Hxl6@=r8% xp8o<{jpse/^t]nosG~=fqݽ|^~{ FH Nqeyހfw߀y~ӄ p2Շރ pN0sFa՟ݷW/7qcﯾ~`atYpgN(=vK엻uv. ˮ#_W=ծ؅09=o_O0S0Sq$5*4Ѹ(=XDg7f3RSgvۙ^g(e4HK*DK܍G]ӽY F -^;ϬԪ`7 QpSz$6D mFf#{~^Q;3[0gYBɝ?P&#%wVۇ^m-{w޼W|mtF#g EFk%'(y<߲jb@ޝ+m)-R8]q /۹Cr틈}.HuZ) Tԕ#jW8n(ub ŬUF -`ɶRaE&(<&QPi#7~oچEB]\Hh_D-P8ZD5k@ܩ㺪E'9R -TvOfHES*ilq~vK6{2Qk -y+ĭGEϭ\n2?ѣ1CswNrJjҷ;ڽq|?H9RӄJo[fjPdQ}Zh༓-6f6޴ǩr"k]26ѤӖrRTxyW @(=Y2۵Y;:|"dfe/׭h pT5bɟ](Uo|.wcjcd9.e#vu"&t/ -ҏ&F˕z%Ww|'+&z4\ Ňs|]citaBz;\ЇvLjυkzJL3LqdE#\ [@؜>q}ݻm' 5~a{aL $} -endstream -endobj - -4683 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 689.9764 524.4094 697.4674] - /Border [0 0 0] - /Dest (sec:introduction) - /F 4 - /StructParent 1 - /Contents ->> -endobj - -4684 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 671.3144 524.4094 678.9264] - /Border [0 0 0] - /Dest (subsec:composability) - /F 4 - /StructParent 2 - /Contents ->> -endobj - -4685 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 652.6524 524.4094 660.2644] - /Border [0 0 0] - /Dest (subsec:motivation) - /F 4 - /StructParent 3 - /Contents ->> -endobj - -4686 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 633.9904 524.4094 641.6024] - /Border [0 0 0] - /Dest (subsubsec:motivation-plugins) - /F 4 - /StructParent 4 - /Contents ->> -endobj - -4687 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 615.32837 524.4094 622.9404] - /Border [0 0 0] - /Dest (subsubsec:motivation-harnesses) - /F 4 - /StructParent 5 - /Contents ->> -endobj - -4688 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 596.6664 524.4094 604.2784] - /Border [0 0 0] - /Dest (subsubsec:motivation-workaround) - /F 4 - /StructParent 6 - /Contents ->> -endobj - -4689 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 578.0044 524.4094 585.6164] - /Border [0 0 0] - /Dest (subsec:contributions) - /F 4 - /StructParent 7 - /Contents ->> -endobj - -4690 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 549.4634 524.4094 556.9544] - /Border [0 0 0] - /Dest (sec:preliminary) - /F 4 - /StructParent 8 - /Contents ->> -endobj - -4691 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 530.8014 524.4094 538.4134] - /Border [0 0 0] - /Dest (subsec:effects) - /F 4 - /StructParent 9 - /Contents ->> -endobj - -4692 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 512.1394 524.4094 519.7514] - /Border [0 0 0] - /Dest (subsec:coeffects) - /F 4 - /StructParent 10 - /Contents ->> -endobj - -4693 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 493.4774 524.4094 501.0894] - /Border [0 0 0] - /Dest 4415 0 R - /F 4 - /StructParent 11 - /Contents ->> -endobj - -4694 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 464.9364 524.4094 472.4274] - /Border [0 0 0] - /Dest (sec:theory) - /F 4 - /StructParent 12 - /Contents ->> -endobj - -4695 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 446.2744 524.4094 453.8864] - /Border [0 0 0] - /Dest (subsec:revertible-effects) - /F 4 - /StructParent 13 - /Contents ->> -endobj - -4696 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 427.6124 524.4094 435.2244] - /Border [0 0 0] - /Dest (subsubsec:eff-formalization) - /F 4 - /StructParent 14 - /Contents ->> -endobj - -4697 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 408.9504 524.4094 416.5624] - /Border [0 0 0] - /Dest (subsubsec:eff-composition) - /F 4 - /StructParent 15 - /Contents ->> -endobj - -4698 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 390.2884 524.4094 397.9004] - /Border [0 0 0] - /Dest (subsec:reactive-coeffects) - /F 4 - /StructParent 16 - /Contents ->> -endobj - -4699 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 371.6264 524.4094 379.2384] - /Border [0 0 0] - /Dest (subsubsec:coeff-context) - /F 4 - /StructParent 17 - /Contents ->> -endobj - -4700 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 352.9644 524.4094 360.5764] - /Border [0 0 0] - /Dest (subsubsec:coeff-reactive) - /F 4 - /StructParent 18 - /Contents ->> -endobj - -4701 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 334.3024 524.4094 341.9144] - /Border [0 0 0] - /Dest (subsubsec:coeff-isolate-intercept) - /F 4 - /StructParent 19 - /Contents ->> -endobj - -4702 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 315.64038 524.4094 323.25238] - /Border [0 0 0] - /Dest (subsec:component-lifecycle) - /F 4 - /StructParent 20 - /Contents ->> -endobj - -4703 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 296.9784 524.4094 304.5904] - /Border [0 0 0] - /Dest (subsubsec:eff-idempotent) - /F 4 - /StructParent 21 - /Contents ->> -endobj - -4704 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 278.3164 524.4094 285.9284] - /Border [0 0 0] - /Dest (subsubsec:lifecycle-iteration) - /F 4 - /StructParent 22 - /Contents ->> -endobj - -4705 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 259.65442 524.4094 267.26642] - /Border [0 0 0] - /Dest (subsubsec:lifecycle-coherence) - /F 4 - /StructParent 23 - /Contents ->> -endobj - -4706 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 240.99237 524.4094 248.60437] - /Border [0 0 0] - /Dest (subsubsec:lifecycle-asynchrony) - /F 4 - /StructParent 24 - /Contents ->> -endobj - -4707 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 222.33038 524.4094 229.94238] - /Border [0 0 0] - /Dest (subsec:context-paradigm) - /F 4 - /StructParent 25 - /Contents ->> -endobj - -4708 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 203.6684 524.4094 211.2804] - /Border [0 0 0] - /Dest (subsubsec:unified-context) - /F 4 - /StructParent 26 - /Contents ->> -endobj - -4709 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 185.00641 524.4094 192.61841] - /Border [0 0 0] - /Dest (subsubsec:context-situating) - /F 4 - /StructParent 27 - /Contents ->> -endobj - -4710 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 156.4654 524.4094 163.95642] - /Border [0 0 0] - /Dest (sec:system) - /F 4 - /StructParent 28 - /Contents ->> -endobj - -4711 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 137.8034 524.4094 145.4154] - /Border [0 0 0] - /Dest (subsec:core-impl) - /F 4 - /StructParent 29 - /Contents ->> -endobj - -4712 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 119.14142 524.4094 126.75342] - /Border [0 0 0] - /Dest (subsubsec:effect-api) - /F 4 - /StructParent 30 - /Contents ->> -endobj - -4713 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 100.47937 524.4094 108.09143] - /Border [0 0 0] - /Dest (subsubsec:coeffect-api) - /F 4 - /StructParent 31 - /Contents ->> -endobj - -4714 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 89.42938 524.4094 89.42938] - /Border [0 0 0] - /Dest (subsubsec:component-api) - /F 4 - /StructParent 32 - /Contents ->> -endobj - -4715 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4354 0 R - /f1 4360 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 33 - /Tabs /S - /Parent 1 0 R - /Contents 4716 0 R - /Annots [4683 0 R 4684 0 R 4685 0 R 4686 0 R 4687 0 R 4688 0 R 4689 0 R 4690 0 R 4691 0 R 4692 0 R 4693 0 R 4694 0 R 4695 0 R 4696 0 R 4697 0 R 4698 0 R 4699 0 R 4700 0 R 4701 0 R 4702 0 R 4703 0 R 4704 0 R 4705 0 R 4706 0 R 4707 0 R 4708 0 R 4709 0 R 4710 0 R 4711 0 R 4712 0 R 4713 0 R 4714 0 R] ->> -endobj - -4716 0 obj -<< - /Length 16038 - /Filter /FlateDecode ->> -stream -xݽ]smq$޿hkLzժıv"ơ~Ф:s\Ч./_}{ʪo쫻o_~w7_o_?{|w~ꗿW_W_ݿ|=Onݭ_]-L-w篾ͺj|_~պuv?}c|柿֯ޗ+.Һ]w_7_ׯZo]uTrz+W]RJ-6K _$k7`Q˿}a4[>Çwg!fƤDt2DLfĭv)ZJӉ$gZLI1^&jͤhދ@mkqZ9[%ݕJқ8n[[a.RS7M+h&γ;D0(YTq[ϐ!kl-٥|d%gSQ5&aF],dPL>)5A۶T&N -I+e~]8AxQUӖIж ]RjmdRuSZ;!ͨb{eq"hgi+U˒ɜeKeJb|zIu7s"&3T|de"lZ7זS<3X皢`%QbDQ?ň+VI[ -Uĉ}KV;5TvŮ}ؿ?Ro~ʧkN2G'Ok%qzt{]<Ϳ$|<#??{~Bſ○)^my>ŸfdV<g,M,rQH-Z~PBH%sGeT2S̑=.b! A(F7xuY8[9{lu~m7S茇ޗ+~$U -?Ky/W)B$F~nEĮpK%yH)Ѕg#&FZE{ƤgH-R6(L2ir%k"y|Uh! m^bJwi]F{d7Ńoѵ6-av*rO\!$ܓCz/h\»54]'y_dёK&b35I)chH횂^<~jH-S82_Mh7_h+nj%cq_ѷU7_ղ;>i -+ -~o1) kQY8^Ek;>9 --߉ k/SĚLK* ޲!S2r#Tt9k_eJG.;F> -Wў01;$jC*?7(.$,V*GK&D{ҀO s#2yØX*H%5P"7SrxrȁJ;C.^)x-9|32c\n%gw"ERz9+Ӷs z8 ߈M;C9Up$q"GHcxs*G-yrevd E=pW!WF Q|?oQzXIdf$Z^S.k^HLmA/TTzߗΛzF$8|AG$|čprcm>Fͷ-I6 -pފ DoPTH.1 #ݷN'$}IE%'\`۔ࣾp̓GXi ~9b" 1Ybb,Bx~>>BZQ\lӦ&VӦ}y11 !YMGL̵iO:zjb(>~H57o⇚1#q\CK-7 >)GKS{F‡qZ|3̀PyG8#6hn8g6 -$xNx)%' Xeq ?$h$QZI.N~a?J _0"Mf HHP|2֒!%B_\)_DcH? ]7JV5v[ķ_0 =ȅÝ?>槲)>w9">`>TFև_|/E//^ȅZ1El3,#l*"h8`K"PC6-hIN"D^ĞD`*ˑDpc%t;X;ea!꜏>Χ Q|PLťر#E"@35$|D5qfbt:M$Du#E̅ H5%ޟrX"aRrtXȱkOYHK(b$ĥQ˂G EXڏ+i@ՄDGB6{c|شBa c8G 8];W>"nOz+"HP'qBZ ΀"@>#$8;_@-D^|y3Ryҗu3J[@4#>}SO`ECd>{pׯW KOψV{ߌ\i-;ѯ+|%ʂ -,u$ ͵4b;rn7/6mcKGM6RN2e[ӞZSCр ֜vweU)m% blɠ\S59B\QV+.i`MAp?RA* %˝r!59 cC{|Cu],BtYkH͓b<: KiUː5N?ȴ#5FH*pJiڬUgM 'z2c=׷B8"sHTZ3b{& a|ECdˎ"?MsÖZ#>ۍEO<%qxz"4Aԃu{m&?ŏ76 _uӮbTpz]4|&7x8qqC PI)h!JG:vl=8*t)޴o!I.,| )%I?DoJ?uDXȔ6>H7m|PEC[N^KQ EG : O r*v姂 \9C% Jd>Z%H !MothmxNЂ.@/hR6Ě/ECt2 z_,YXYvS*D;\Jzr=B?eBaLiK2Iєц %=B0T&V>VS)-A u_D;Pҳ7? =;_x,jI瑏}n zE>{U)Vӥ>wp_](>↸"|fmH3k+$+Ϭ5I|fMe d (Ay;4g'GQR'+`́"%5Q8HNZN}d} 4pG6ZJɐҔfI3WRr[)6xE/i5e$^|]R{#EG>?h5'-S]~s]IX#mxbIBG\(NY<?L4M/Iuھ+Ñ#xO-åm:^HHR:^v1gT1ۛ6L!SY@'bO(ڡ'J;1GA:sHFmR9v# ġ}?~mDS-/1sqa'cr%v8|J-->\9xW封W\'5c%k2Lx?u3#O“Մ[eWs2vNۯE=I#Yo؛Y !PI!zdLH$e|`_R4o _yQE>Z -^Kl6IEc$ _MRm;H-qD - ?!o(6lI!*5ߗR$i9ra=3 V@[O&iB<#c G$Hj["R {:I{Q!S|}?\0R᣾!ԑG|MEi-e|ۨE/YwXnf ?D[>wwJtr}3͗_-]ItYï==;}`q~*| OE2I/.9_[_\ggv Dl7ܠWB7dHffᣀxwц?\z2Ȟo/5$8-ݭYmoʡ@'i6B~lxs#]CG*GT͝#DF!G3 i @Z^NCV*ݵ; 7B,ӫE[w -t8ah"|LGh-O|Љh/ֲxmF6x£ Z>£4 ?&YSωO %צ.dw[[?Vk3]ȗClq/Sr^0?~[Y#懮Nx$ I >ի~hP} ?+PNdƽnzK(lҳ{3)HR?c HcPՈw<6N-C(1!2Jfs|Ite8`o[^-#En\(JtGxEF$"F#Σ@“C#QG1'1J*C^D -x1mĥ!q8QCV3)Ky hݖǀc`Wh!Jdh}2dHOk+ -^D E.6/]D@0U2;@ım,ZmtQQ gcl&qB$ش? %ՊHޮJɅ[$VYI!nFiO֡J;ߒDGt0 Uاy2zT~mC!/)KکJ틄?YQSA;Cn9-ڏ:釡.ڡ8:!ߑ9Or`E/T>|,iӂbN6Kw#T~:Ւ$|hԻ[fvl$uqn*7%Kt"j85lL(_3R{õ"ң>Qu?.Y.mA IsMqF d->pMua"ᇴ&%8JCw=4 , 8aE{OoU~#|FODTV&$MtOUi݁= 5uDy|I,C]uh4#+*w|q'&97$Ǥ$]H-?mbÒj&618hbpaSX/aS7 ?d7{Z, q=x5 T%`C-,ǡqhE]7Z,4Ʃ\'74|@:ذ^݋A#mUvumT;oqv[h·6~[|f̣b\۝ty5SRĉ|na2jGܱ(qQu:y[|: g6I%$+ ->$O‡Dpqךh8 szA#ӊow^$q礼?$H)i?TTO~Hu|.YG"D$\HHIy9ҠmL ^SoMΛ$|4āMp3AƉunI#iS6& {-5p>:(v*|sɚ%lCޗnsVnw>Zy}$|hDK/=eGOXjࣦKz*sH#3h0(t"K -+:&p.= wkj\;oF"fwK#u7͗ti2ƹ7o̷ lz+ m ^7K~*mY(1o*w ߥ,i&>4xXc!آ t&[a˂xl }79m- wIH]S។PMn8dzb[5Xʼn$|uQC [+Y0X!+W[]~tv҆?[v͝%+6UNJ9 Uw=6@q$ %Y,|t! -c 'ykt}SEGګr,KDwUH?]bieIo?TȗQKl"Q~x;GLQ Infǖ8DG^T1Orkbw]Nh_R}C+3~Jo:\5:\+:\;6|(s[27(sianvanq~^ \.xKt9xUޮ0AC1-[yktTڅkk.6U!M|1"ZRs{~}O.N_ >[Cf/|pތ1;Ni#0$!LCoYokcN#9]H -{R|Ȭ ,$| ?lgJ4b7`-9hoQܞ{z8f&(!`ƧZ\hQl(H5^9I!$t8w٦២Fj: 6 #B;'IchlZ0KrIq2h#}z8H%( -9`/C{wk|JE9}ܞQC6pvv]qū-c7vW9n,d|Ջ^ܟ?7{޷yߨou߲xڨCʩ26~7S\O tbq$%~TwK,?& $:3 -<"zٽS2ۓ*j *p7q F$|=<{dm̈$mn@ɦ]$62i33,(mfF<)'B̋? g=p6 R7,MTrz79^G5.$ ^3$؛65͌Ӧfq/&|G T a~EfD{mnFD<\I#UJnmIht09 d.䌈An":|4;BxD7I~ xЦѷMO"=\#7J_ >78vofnwyЃY<̿y}ٓi[?ܝJvԒ6Q/NƁՑ76N&AndmKdKx,XR"A,1eTUE0TD&EЂ,VHei("At ,żt56`DWpl6mXhlY$|EuQ@d'l&./f'ے -t!E0$fDEв oih@", M<,".VK5rJY.Y`D7zE$RхEв&@7Y)pRD8h(!`P@5`-& -ܨ] Ի2(}o'Oj N ?h%q#o?MD5˒نDP}`bIo}q`HNŸz$%\W"QW%\[?%*>ެ#5˹}We7ky|iB;r`?y&FÝ?T|'AweoJl"2O~ύ4B^WK -zO#KR}Ƨźt6n+i3& ]5< ~b*5e'RI{IXڍ6 ~$o.4f7*Ք57@Y N,c"+TfoOX6V(jCJ5 hssr+YbeڢNN&..6$WOϢPƗ^]bu.ھ:)hl[ >>%zxv[hD%cF]-x#h A‡޼U'Xnћ_+sU4 Y.R$㣲V#8"l q8O0v{}8me?3|Ijˇެ'2%UM$D \4P,oIݼ jQ8tGs>H0Xl?7l9El,mC[ُp\"CqH$(HΦ-$g$,Gƛ<: $Nt$Csh8/޴siМ6As֤l\a{4gZ@"9o"9/~μ-9ߠ)I[%p9hm͗+_?"-?k̍8oʨ[ix,%HAȌ"DK2K(68AAY|H%m N`\%B&r^g55G=-k-oHi0ch,0I0{E(~ɲ<h!>I{ &K P4ZEАi/q{; e<,F%Z$Ž6K8c, {$7lxo^ȸ$p1 .䟒:'Ep2B*5EסUy6N.B"8~츽@&uS \2<ݫmE"ݫ-xp^z -&~>,K#Y 1Bۍ5u@"8^Tx\HuxzbzX0{%.e앇z=y,G ks[Sy51mUt:/] c'iO -?YumPOqS\Я2#g:'G#h4aP,CbAbh'"$_~{ Ȋ#ZAq~n{ IJGPz  `{\BYy⍛W500g7 hkY -T5.by$${, -\ܣ5m ̒`x@T`D"r,֣ʒ\)/}P iEV) 5AH8:JbZ-)S"hpI$(6yG覭Ë2d /ȑ"0L)%M==t -.űDG +vjzWk]Q&F/DR4LAjRK[˾lyϾw壍uszɚ07tRA#%n4A6X("!,SVJ"-Z'ŞEǜ ] +u$| %u$͈OC"JAwcI!$' ?d,Gx!g z"AF~T*F{#} \*O`2 $d:Ảrø7F#(O8EHBB#,vAKG~6&;w)ɪE#eu]8LW" bUHmLE ),|mڞf7 -=E(LޘcKO#ɱZTpK 'w)&׹B"_l^\QX#kVZ<.塸rHëJXޮgAW~QG'un35-OZݣ&6uYVobA$FàL_bC7B ~lK/JW [B O8Lo4hH4YޒK<Rbś|5?5HGO > -Gz5IuzSj>J!юc~F؈ t;NS~À|7ݡ?2brt(҅9X^iK4 ?%*J| T[N>h;S4gGnuJ\yk*x!鴈ۥ^X.6R9[Rœɽu1oKr7iH2]WWE^7E_ݯ֪kڶn~==u~X7+l1A!q)xiJ$H1Es^Ryqe F#xHsU~KȟؼGi*<WdгrI_bԌ"9RėUėeSiy/1yx/1"r{hJ2XpG 8Jju`)"=ZFķG3F8M$h 75GXo:M>he [ ,D|oqH7yZf`RG"}azK#x'ތi~5CZy8Lf܊Keu\ksI}ղKcTzA_=Nxg!ՏϢ߽3Co=~ sP쨮֖ ֏۩eR47qQmƤ(ѥ8s(J%R5) D^j"Ҳc*".9Pb - d*4&R}*#BUrPMH@_^ʆ9P{I 6Իm誶wXZ@kZԛ*}*)T.'D%ojMq#7,pQǞV?ۍ9 ێ)'pMh8#_CGR_S{/#syH%xjH0F@ sNZt: ON4_7x)o`JMf ]|;$|؎9hxٮq؎,quG&:&U> ->th!i94|Eb& [`GC&M]ҵX h6,J-P7ml<$#i"tm]~ -EI4q7x*{hg"fD '|ly3g)Eް&ݛ%;'hO'{9G ~Eֺpߠ%.WmI#q!rv{ŝʿ?p*?'}߾fZkd~G)̙8,(?u,!D`zr- -HdX.܃EVpf!w PH(X%k2HćBƏN"@ -P,,ۅ-`Llkp*o1~! n iJ,5;y{I!&"YF4M֒Zbxoo4=CF> v , $T.E> І n,HPGxu(%v{IHQR<!8tLͤ:U9$Ӛ:(l7̧I 4pQD"@m9o&=5v2H W^crX# -JgiZR!HH^7":VhbOAH.b :8B8{H ݅6:O,x#UjmOK;״:V,~n3ٷ7_Je-/O~ve4Zhp;`oNt(*!JB Ŷ+ ?ToBДw !D.똘џlDP[{.|q"J ,_fI d z{FbQTM*t,DI-FAo !"Q["7 RtC&ےE2 No&3&h>eOb!g_h1y4zh;x.=[F̠)ۤ3Zg fQ#4%+@G=Z,E7 d7@HJ O'VCmS4G"VbMaDZE2\,bI"%xP -q,5B )j#E⾐"@R>/ :$|],xYn¼;5?u/#5/0DjzGݖnT?ݿ}7~o}sϿۏwWQ O4׈sjޡbA -endstream -endobj - -4717 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 749.2384 524.4094 756.8504] - /Border [0 0 0] - /Dest (subsubsec:component-api) - /F 4 - /StructParent 34 - /Contents ->> -endobj - -4718 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 730.5764 524.4094 738.1884] - /Border [0 0 0] - /Dest (subsubsec:context-access) - /F 4 - /StructParent 35 - /Contents ->> -endobj - -4719 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 711.9144 524.4094 719.52637] - /Border [0 0 0] - /Dest (subsec:loader-hmr) - /F 4 - /StructParent 36 - /Contents ->> -endobj - -4720 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 693.2524 524.4094 700.8644] - /Border [0 0 0] - /Dest (subsubsec:config-layer) - /F 4 - /StructParent 37 - /Contents ->> -endobj - -4721 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 674.5904 524.4094 682.2024] - /Border [0 0 0] - /Dest (subsubsec:hmr) - /F 4 - /StructParent 38 - /Contents ->> -endobj - -4722 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 655.9284 524.4094 663.5404] - /Border [0 0 0] - /Dest (subsec:koishi) - /F 4 - /StructParent 39 - /Contents ->> -endobj - -4723 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 627.3874 524.4094 634.8784] - /Border [0 0 0] - /Dest (sec:discussion) - /F 4 - /StructParent 40 - /Contents ->> -endobj - -4724 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 608.7254 524.4094 616.3374] - /Border [0 0 0] - /Dest (subsec:scaling) - /F 4 - /StructParent 41 - /Contents ->> -endobj - -4725 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 590.0634 524.4094 597.6754] - /Border [0 0 0] - /Dest (subsec:capabilities) - /F 4 - /StructParent 42 - /Contents ->> -endobj - -4726 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 571.40137 524.4094 579.0134] - /Border [0 0 0] - /Dest (subsec:language) - /F 4 - /StructParent 43 - /Contents ->> -endobj - -4727 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 552.7394 524.4094 560.35144] - /Border [0 0 0] - /Dest (subsec:granularity) - /F 4 - /StructParent 44 - /Contents ->> -endobj - -4728 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 534.0774 524.4094 541.6894] - /Border [0 0 0] - /Dest (subsec:versioning) - /F 4 - /StructParent 45 - /Contents ->> -endobj - -4729 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 505.5364 524.4094 513.0274] - /Border [0 0 0] - /Dest (sec:related) - /F 4 - /StructParent 46 - /Contents ->> -endobj - -4730 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 486.8744 524.4094 494.4864] - /Border [0 0 0] - /Dest (subsec:rw-effects) - /F 4 - /StructParent 47 - /Contents ->> -endobj - -4731 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 468.2124 524.4094 475.8244] - /Border [0 0 0] - /Dest (subsec:rw-paradigms) - /F 4 - /StructParent 48 - /Contents ->> -endobj - -4732 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 449.5504 524.4094 457.1624] - /Border [0 0 0] - /Dest (subsec:rw-temporal) - /F 4 - /StructParent 49 - /Contents ->> -endobj - -4733 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 430.8884 524.4094 438.5004] - /Border [0 0 0] - /Dest (subsec:rw-spatial) - /F 4 - /StructParent 50 - /Contents ->> -endobj - -4734 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 402.3474 524.4094 409.8384] - /Border [0 0 0] - /Dest (sec:conclusion) - /F 4 - /StructParent 51 - /Contents ->> -endobj - -4735 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 373.8064 524.4094 381.2974] - /Border [0 0 0] - /Dest 4455 0 R - /F 4 - /StructParent 52 - /Contents ->> -endobj - -4736 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4360 0 R - /f1 4354 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 53 - /Tabs /S - /Parent 1 0 R - /Contents 4737 0 R - /Annots [4717 0 R 4718 0 R 4719 0 R 4720 0 R 4721 0 R 4722 0 R 4723 0 R 4724 0 R 4725 0 R 4726 0 R 4727 0 R 4728 0 R 4729 0 R 4730 0 R 4731 0 R 4732 0 R 4733 0 R 4734 0 R 4735 0 R] ->> -endobj - -4737 0 obj -<< - /Length 9777 - /Filter /FlateDecode ->> -stream -x}]Ǒ=xA,\ -6l$ ;Vu- d}pz>83Cii⩞~駻9U~?/_߿z?_߾?˫woG>zӟ^~旿św_ݠ7j]쫽LsUZ{틯7o޼?~};~o|G~To~_^麺['~onqxn0+Yk-뛿|$z̋ڈoټ۫un;ߢ*i%K >MOZ( Ƣ\R3?i&SM/if,QQӦRܓok2z[GچvQ[ҕ,7ڻkZٷ-9,Ei$cm|ȊS /4S%_b:k^UHhD7mI;[,}ēv*)额}hd}xe?E;7hM6זmc&xӆ[shmX=|"d UӤǚel c}[TrrXF5cXkц!x~%hfZc^cXլ*')}b;sC|{~.]~z1C=3_?PxalïbY[\s#,KGmssM}Wfl={p5{ɞ~Ow)]]wGV -6dj T|#!HO=]bKRȆscMwIdU҆&'hϒI)_ >Â-:fE)K,8w R[d:тK@ABYi7u{^:;i7u{vSw$2V@TG&ÛvU U^ж$2Ti'r{N7{$ɽ ?-rKTWn,WOZ#":ɱn?VB" D戃8vb>v~̹~r Ơ+P,|up $JNز */|H-n9頺y-)́_VOl5$NI)/,D+x{w Rmh k؂>]jfs6/~L4eQb >Vڧ|jI&2$x/?z6Grb8xߖ)Q[,xpE;68i.7VqH#ItVA1|}@+dV1QCFApcN p6$dJ}(Zq q{y\HNu-9 -}@,F6+RJÿc_I~/3Z sϖ@|e׊gޅ" eRAG&opiACGW> ~B-G͛~z%U > z|X_: =%[V ?$YV-6;HGkzNތoKۿbJgqR\<Y{,}^|* SU0G۴~>o% )Ť2鸔\SBǁ[  -̓uIj,?9 ӓ|,[8r]ԆxP) 7~l4o~ȴ)_GSP7##s -҂臺B^2 ΅RP r^Z(ɂGX4$out@헃L!>%gi4۲C FZ.VI-5i'Lt$BReE9m⇑ג+PɎ?h -GVPJ~h 堏L1"*&P矅:$t$ mYLBO2@>C-*=zؓMQm%X.*=1c(@HSKN'[G'bzʁ]鉖 GhӼZ]&4/4kSp×Auie|~T{ d}0@t|x?vq^6f`wr9^[2Z\RBRdy!F2 2Z)NdBG#9^2TH@#Z]Kz17(]v(B B@ #ZroUPX@pAHB8q$ /I`DYZp,Bd6h/@I _N + cDaPEZs1;^<^D Z7QSXx!J"]FhGI:Zܲ5!z^dލhf^d/6E=AJed "^@9H(x!Ff T5-Fe?ϰ[zfCb<^-luy䅀ܖ2d;!1<;A|S(Dy`̥RFЉ ([G RL@2+_8rSZY HD)5ZTHHSj'u . I.IBj}Kt_t/$v񽻄^ƿt@0?l'ffUa)o5zT\m8o}sƂk -vq0e @C /Yyz]BOO~t۰ Nx8b`$4>bk ៶prbc8I.6+N8c:ZI b ->YG4_$oN"ᣅkG1͈?bN{P̺W"76T6J3B}p&l݃.'ZymW$B01[ܛl4|ϖ>#< ,| NQHBUA?:jAłz_@qGOVڑ!#HГGcC;e?(=-Dwl8KOGsюҲ=ujR|Բ}vd;TE!v4sd9 ?%,G88m;q{Tѷ@quw*mwu|oÿzǷd~^6sKj7 ?d e|GaD;>ZJ" 5 -9F~X"i#~,|u=紓Tb"ᣝdWƉ ~"ᣟd)/-O4Th({O"*7q]AQ։~E;v;t~Pp2;sv;sv;s" 7=&Y3&hG7I:%vC4 ;+@ɔq)M 8(;ԩCG%r%Nv$SćzC|w W tn.gL/RKQں2 85D>*cjryT~:WPv,/ɇ&. ?6?X0m~/{WQRR۫}~bj)>=zs}&}C Z`JY3F~89׬NO19ӍGI.>́% 8{^lhul^uњ&6킵٦hښ9$6CA[ʹco9ؼgs҆h‡e9Y;۵8]🾨PzYO9z]Fz /ˮn7_off}ۿu1ف_G]TS/;wJmAA_$#'Lkߖ'ҚdXv8$BΓ/[YPWqC"~sݑߠ=]oIϤ*4`Á-w~BDGtc2GF_$vY<OE?*G8H/M;6@UVX4/V$?I!k%$7:x5pexRlBZ>tISC@|[#Yn}o)F<Bβs Q=h!qv" -.8y!BlG1H:-f~33PJM}x!JNZPYz -}B/E 8uf5Αvef PAG'Qy!D $ya A/DJde!x{oh3vk/.C ]% \9ϴ3O0s0˥3 QIJr'3 eڋ[:“own6V;l/DI!i!JEke%yJcv66U -}i!A5͎鱆N66mc5S} nSDJ 疽)!y6r\-6=2mzByKzT Ti3)9լ=sfMYt.^Y@5>`YڊvǢA[78ryQ#CL;# Ÿх?Z E[ո(mu6 #K -FQHLS4wZ) ?dI. -AqaBݞp6O1-=t6 dۦmf(  ?P&y 6O1lQmcuLgy<3NV[(d *p:ߗʂCTsClR)Z.XLÍuU}Q (;{ѶNpJC:)4mDS_:ӤLod@_*yjH mx{gop!hFGRމBy#kPaZ)꒱҅48qXBAXA,DZJyUzx;S-ǴE㇬L+l.K)G=>M6?+$m~`XZ̓JX+. AR -H)‡ci!CGP?20aX -ڄ]i-|JN{saWiïC ?%&i1,4 >AvO}vaX1|K%̓GmGFw~JZ6fXxgcX!֨g Ò 3$nm0, Z!)ïd1ïԛ1-|J5`U9+)8W^VҤmǮT1 R9mo>v%+ρ[7nکڮA %cWJ8#î{/JYpWۜWJگz,|xsJ:4_ە5Ҧm~EۛK4Q H,ْ~ bKsXzx>TXzȄWE hE24|7*>z6Kv2q|(fu]&i#V%p! hX!v  D]< ?eJwV"Ꮨ. aI -̓xm,4 *~\[#9PG4$bz[ YP hi% I !DٸskfWXJ#3t~H-?,1>ei -<6ޱuo!>wKE;2øO .$N;U_2 )ho1kT% z  %s!ZhGfkۚ@ >4䠃\{w;Ў̇] އ UYf#ajCvE¿c^I'evBO];t{Ί֒f-EK]M77ѳu ɺ._eX}_=$ ؇fOҏe6)GvЎ$-Ddlȼ'2-Dy!Re{q h!zx bPqv,e̟bJN1VpNL)uBlqZ8VBh3nU.œ%Ê 2̷[rC 0nut*Xy!܇h!-l?ER芇r iS_lFF aF(*6nUCmZY2ZG=!|3R +-G[ #l(ŋP' (Cgb9#Ǎ\ 1 a82UC4Z\O=Qule?3[3DAI [3DP G.Qʇ8/J}d%RH ҍFP؎3V3J -Br-s'o. "(d͘KVQwV3DJ.'YEލ!nr2'\4pu'h!~,Яzu&B棈tuFiQl.)"dG(Y0CɴRl$hދdOu1.S-pRV-Z{:sB`IZGb -E,z\=EݙKeeз)p.Rbh`Q5B!,@[m(2\2ش.b#` $. -l.Vr3?_߾ǟ/xݯ>;O_}O_\WN:,x.֧O" -endstream -endobj - -4738 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [182.8334 688.1684 188.3334 701.8304] - /Border [0 0 0] - /Dest 4456 0 R - /F 4 - /StructParent 54 - /Contents (1) ->> -endobj - -4739 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [427.80704 647.1824 433.30704 660.8444] - /Border [0 0 0] - /Dest 4457 0 R - /F 4 - /StructParent 55 - /Contents (2) ->> -endobj - -4740 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [386.99667 619.8584 392.49667 633.5204] - /Border [0 0 0] - /Dest 4458 0 R - /F 4 - /StructParent 56 - /Contents (3) ->> -endobj - -4741 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [513.6514 354.0974 519.1514 367.7594] - /Border [0 0 0] - /Dest 4459 0 R - /F 4 - /StructParent 57 - /Contents (4) ->> -endobj - -4742 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [157.93703 340.4354 163.43703 354.0974] - /Border [0 0 0] - /Dest 4460 0 R - /F 4 - /StructParent 58 - /Contents (5) ->> -endobj - -4743 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4354 0 R - /f1 4360 0 R - /f2 4366 0 R - /f3 4372 0 R - /f4 4378 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 59 - /Tabs /S - /Parent 1 0 R - /Contents 4744 0 R - /Annots [4738 0 R 4739 0 R 4740 0 R 4741 0 R 4742 0 R] ->> -endobj - -4744 0 obj -<< - /Length 4497 - /Filter /FlateDecode ->> -stream -xks$8KXޏ*G Hop,KUݙZfg||9jZVwۇ]gg]wbwﻫo~_]?{Ǜwg_|}o^]}훗_D;]qsJ2#~=og3]oϮx'Tw0=~=Uncwg1&1!V„#&fI+]20Ik捡&:!H&+$>J;9Dy7B@ǿaﳔ\ȑӁ9;y޲#Ì Cy\NWQǏbYar}E#|ް+:;޸+ -KfÊ}||,v"J DVGdLvQV4P z>lCZƕ9EkI'y--sdM1Ϩ2Z8'j6i[QbmQ5 ^>Z>Ta6Dy'$#7'^tzmLU&&FM -MjbóD06DO%oGnqݣtJm@ Pu,ڂmt@X?6uY#d44m`ʖv>꤀'Y0CΛR% vUD - j ?:i`!톉7e\ -;6gE^dܮp3N"14 g5 qSO`Krl ,!Y6ybD|qjjYP&QKもHG`4'˕eF/n $.: -G=7f9dE&80 Z.$|G]O -ppqa[78j>ࡖ(vK&GvQ -NHRZ)Iɼ_ ӒŦSD W7p)XFPr` ",cT)AR1UnRґvh - -awdT6 (+c1%[l1 (oYvumzqUbs UpLrmrEBE㑗*nV6, Ngq,+Xc~CqB/V.b -fjrXŔȀbJdC -2n $Mز(a)3 -mؐ@vS}VOU3K5)B -B.閒t 3}TAPPθs?{"B| z;0잤l()&Ȅ  H={ңnoĒ5HaY LQp&tOҋɊt$ 'G| ~>-e7ޅtT ΋*xaJh+a Cm$ʼ?uQBp$S& t<./T[ɐq -3ōGeqdgha_ΒSa s53HVtavnkL0(қ8f$Qͳӭ,`)`He0V^J8 DB9<5ޒA39-~N"yJh&vж Y8Wz%ÜIl"cWܙ< bREA-m,S{Uk80%8+ #diA;k 6nUvU٣X0V)[B&VrS@J Fڰ_4a8CHajNv~)qC bĹ9Ѹּ"gi/bw7O>|TOO l Z3>jNPk|X!0#/ֱYJXOr'drlJU# Qk:q?gsI)UjC2R=/ZSL*ԤSҩ$jQ m_RM4iI`g=] FLJbi8@DPvDE*l*,8W 4]pѦpLM mW8$A^4Vb{mn v</k\Hu5 |Q%> h"Y$JoV0pxpZrr]TӀX:5Q myʦB-ʨ,W5E(NoLˊ}Bi"&dT^!-Q,[qa,!nz 'dI }9cciQ\&ڱǓ#"YrGsMT0एKukmn9Ԥ,P ',33V[`1= ZiDD.RʣL&0~XɈP VOdbڱ ZJ+XͳZ1WӾxE5Px(&er ]dsq,(k[*פb m_e5c32R3%0ZTB'qN$8;N|Nkm Ax;Rl"̄Exru* k`OLYb!]V{0~ tBE0Fc&rFzԒ -myVDFIf/ĢeB-*wS?X~Pi1xy | ;)gQHJ;)f 6{o$'SZn:2DUuU|ng]/Kj<㱈xdN[|f=qrT!oF=3;Bh|< -Du}`]eg竌l mR+ga.(d|Zzϼʯ`zg`UM0Oew\xub9º{M^g&d -WbΪ~ukv ڧ6&!ZxywZāYy.U,4}P\9,Է -h07,,$HHoJ Tԣ9&ߘ?K= o~<.w!auDuűدO-+YehctA]m"Gj$ x`Gc4jc_ƺ墲^" ъ; |Acg}_1*Sۖ)_n 콆ѵ?kiq㝡Q3 Ӝ@57%u(lNIpJF uPi{|X^DuXT6A4s*#z-ɕx jCpClwvaR)D{ j8gxPY/I".C,cUjS/PD)x$ȼS :n`J8iu%Z[zsۡQ*Mily&^S/}Dtf926)/V. N{Aa}Z07FAI|giNHiLm_f4jB)B6j/h0 <_kyWy;Ȣ%5YlPV#-^t&x -2KJf%87,`^;*,σa]2C E$VzuLaj{ -x:^ XO$;^Ӛ6"rKe6X-F|okݿ@ (`N|kaz0x֋HE6CRևfh nj꼕"%3-0(\q^U,Nfk. /7wv/v~ow޼{_]?{Ǜwmw3aLXKԨT -endstream -endobj - -4745 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [188.99736 732.5514 192.29736 746.2134] - /Border [0 0 0] - /Dest 4461 0 R - /F 4 - /StructParent 60 - /Contents (Footnote 1) ->> -endobj - -4746 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [395.27713 630.11743 398.57712 643.7794] - /Border [0 0 0] - /Dest 4461 0 R - /F 4 - /StructParent 61 - /Contents (Footnote 1) ->> -endobj - -4747 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [75.57414 486.6974 81.07414 500.3594] - /Border [0 0 0] - /Dest 4457 0 R - /F 4 - /StructParent 62 - /Contents (2) ->> -endobj - -4748 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [86.57414 486.6974 92.07414 500.3594] - /Border [0 0 0] - /Dest 4462 0 R - /F 4 - /StructParent 63 - /Contents (6) ->> -endobj - -4749 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [322.33093 428.3844 327.83093 442.0464] - /Border [0 0 0] - /Dest 4463 0 R - /F 4 - /StructParent 64 - /Contents (7) ->> -endobj - -4750 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [333.33093 428.3844 338.83093 442.0464] - /Border [0 0 0] - /Dest 4464 0 R - /F 4 - /StructParent 65 - /Contents (9) ->> -endobj - -4751 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [129.7738 414.7224 140.7738 428.3844] - /Border [0 0 0] - /Dest 4465 0 R - /F 4 - /StructParent 66 - /Contents (10) ->> -endobj - -4752 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [470.06073 401.0604 481.06073 414.7224] - /Border [0 0 0] - /Dest 4466 0 R - /F 4 - /StructParent 67 - /Contents (11) ->> -endobj - -4753 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [282.75552 387.3984 293.75552 401.0604] - /Border [0 0 0] - /Dest 4467 0 R - /F 4 - /StructParent 68 - /Contents (12) ->> -endobj - -4754 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [243.14856 346.4124 254.14856 360.0744] - /Border [0 0 0] - /Dest 4468 0 R - /F 4 - /StructParent 69 - /Contents (13) ->> -endobj - -4755 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [79.86614 82.78937 82.56614 93.517395] - /Border [0 0 0] - /Dest 4469 0 R - /F 4 - /StructParent 70 - /Contents (1) ->> -endobj - -4756 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4360 0 R - /f1 4378 0 R - /f2 4354 0 R - /f3 4372 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 71 - /Tabs /S - /Parent 1 0 R - /Contents 4757 0 R - /Annots [4745 0 R 4746 0 R 4747 0 R 4748 0 R 4749 0 R 4750 0 R 4751 0 R 4752 0 R 4753 0 R 4754 0 R 4755 0 R] ->> -endobj - -4757 0 obj -<< - /Length 5456 - /Filter /FlateDecode ->> -stream -x=]+z#嬵o&;e;%qbr}Z]#f\wi ZU`v Awoovݧnnw{oի_}wnwݻw_|bWn^NFuݕ{e`{Mϛ;s#m7_ldw~+;7?{-Zjwχ__vWN g1?ZJ{L!G_ЏPCga>jwiw]vV?{-!@Rˮ?~ D.}s8l82Ed!?Nˌ:z9Β`22{Oӯ:N-egNh+v4{M$Q8aʉ r skiNBd3Q?1?t7|u/ZS(VS'\i -@ڿFx)c\3=g0ɺ>dgZvzw۟gK*F.X)u<%)"x7Ї[W^^f\fz(R.\ƧLP3̇2jãs)WBcOߓGpD`Ao''Y'x"hA4-ִ ËL1Zf -BgkriJ[ dD`gUB::.ji':~\:*xRE߾ZC~~|ij )E\"pvh+j [U3EՁzCM0JKn\O8jPg.Y&QhfF'>#dVl6⭐4)hK]m+P$ -J$T0f]|ϩH@V2g0`෧B jIץ7Z9{+\/[tKb6+@K6`s~t˂GN yF!H ] NACZ)o2:5=5FI4m䣙g6vp@thOdͶXլ8DW&vΓ9J ˆ| 0۹ͮAcgäqҍS` )\Kޟh[zWre6 WlAÒz)0k5=bFdwDN1 FsER+^)sXvvݧ_R>r4C ]6Q6.Ut@GUy5jH+&0tqŠ@A+U&W> @$a?܋no!M/#tzјdlr; vIc-E!l' 3O!ӒނberV)7[0lq~ ,.NLa(=όYANR):PZ(;CP& -#V+hM" AG :~TEE0"u©%% U/l\#lE/] -^ƕШbx`) >[$;i*A繠%-"uzPa5IJ*͋(K -wԌ͋. j޺ͺ-qk׽kjXkO1FT<ߦ:'ɦY&JX. pڈS]T'sN "LW WÁH9Ў8뜂eʡ' NTtM''v4~S\Y*ptVP@uRamif0Czsu66'6Z6|r[Y'f눅İJgp)d[r#!85-A›9-{l{#!I]cVM̿:kvVYBSD4NxHD.5`Vzq -dU.lIQKF} UYkٛCizʰ1:)MO60fCazG0q/f5™دpB_Z HUR&D|8c*0Bx;z 1^ e=]#; Ŗwҡ4t/B0qJNi@u:]Bmc:aZ45`^܉:(ImB t@\kd-hu"I5Uq䡱bV5J\4^Һ$|XIZ![Zr Bgsyn\iw; nR;9&γI$aO`&$PCa % Ug -P RH/YA]/2Y!`ۊG5)F'a sD1{+QOs*9?ġJφ3M/զЯ9?ݞ pN!D΋#4ǧ~D) YY^]YBt ;T)@Oy!:jk>QCƪD7|o1Se(7ά@*29{p$ՠkQ"< 8ޯ96 /T"jGM X4`V`Xv O,&+?$M8_@KUf!R@Z:4 "4ӴdҴm}@xئ9K̰5 155Ml/8@p*89M\Y[jT}JQ6{N6u +ti]נR&gfe]O6l{t[&$2{!ګQ֘l(YE(mg )*gY G= H8_ -C=*)X5Mr}l2`iZj%ɪN$ev$$EJp-Xdj%[H縴΁^Rur笛*i L$reSjgi-!<<݋ 6EU A9b%!&zag1 VM4ȎFYf#,/$keځuکgKwUP-W|[Ʋ AI׳aAKO;(B8X-jqTV}2{zP!tbia޳ZEOh* :A3z,$egKGs`K*U/|h "=);CAT pC+mxx*(ShJbʶ>,UNXyB_ -'X] ~NsioW >V%f;hTmQyY?1@)\ԓ0itF%,7ޭxf[ qO\#(*p1;orETyk \u1g{csPwqSK&NjMIN֗-P6 >O%Om%:a9)ߺTbpʶB+[$L5MAO"=XA&P -iuK'ԕB7aɒ7D167y", d*)= -Tۉ*W2۴롾!3 geiTKmdRe?oI{PcCP> -endobj - -4759 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [224.67343 657.4414 235.67343 671.1034] - /Border [0 0 0] - /Dest 4470 0 R - /F 4 - /StructParent 73 - /Contents (14) ->> -endobj - -4760 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [112.155594 473.5904 123.155594 487.2524] - /Border [0 0 0] - /Dest 4471 0 R - /F 4 - /StructParent 74 - /Contents (15) ->> -endobj - -4761 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [128.25504 473.5904 139.25504 487.2524] - /Border [0 0 0] - /Dest 4472 0 R - /F 4 - /StructParent 75 - /Contents (16) ->> -endobj - -4762 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [242.68085 473.5904 253.68085 487.2524] - /Border [0 0 0] - /Dest 4473 0 R - /F 4 - /StructParent 76 - /Contents (17) ->> -endobj - -4763 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [258.7803 473.5904 269.7803 487.2524] - /Border [0 0 0] - /Dest 4474 0 R - /F 4 - /StructParent 77 - /Contents (18) ->> -endobj - -4764 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [264.2438 357.49442 316.85895 371.1564] - /Border [0 0 0] - /Dest (subsec:revertible-effects) - /F 4 - /StructParent 78 - /Contents (Section 3.1) ->> -endobj - -4765 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [267.97797 302.84637 321.2902 316.50842] - /Border [0 0 0] - /Dest (subsec:reactive-coeffects) - /F 4 - /StructParent 79 - /Contents (Section 3.2) ->> -endobj - -4766 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [313.2113 248.19843 364.57465 261.8604] - /Border [0 0 0] - /Dest (subsec:component-lifecycle) - /F 4 - /StructParent 80 - /Contents (Section 3.3) ->> -endobj - -4767 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [394.14352 220.87439 446.3582 234.53638] - /Border [0 0 0] - /Dest (subsec:context-paradigm) - /F 4 - /StructParent 81 - /Contents (Section 3.4) ->> -endobj - -4768 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [289.3024 193.55042 333.3956 207.2124] - /Border [0 0 0] - /Dest (sec:system) - /F 4 - /StructParent 82 - /Contents (Section 4) ->> -endobj - -4769 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4360 0 R - /f1 4354 0 R - /f2 4366 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 83 - /Tabs /S - /Parent 1 0 R - /Contents 4770 0 R - /Annots [4758 0 R 4759 0 R 4760 0 R 4761 0 R 4762 0 R 4763 0 R 4764 0 R 4765 0 R 4766 0 R 4767 0 R 4768 0 R] ->> -endobj - -4770 0 obj -<< - /Length 5367 - /Filter /FlateDecode ->> -stream -x]o$7r_Qfpn/8Xo$Y ͍tYU,[by%H_^><>꺻_꾿ïq_7?=_mo>/˫~}؞}埾׿]NvU]^.(mݓ~%?mߞ;?~ON:+~7"t>IyL{#v+?/`0AI~]SG)d+n+rt'*]k)òя\\bF󧿞~ɐh/}P3c78UtoA4Ŭ͜\teJW!m_PQAӷYΤhW0h:&[n=Rb׹Q~*v˱ J($|]SK=k'Y(Ԕ'{J˃IMgy1զ;Sflc0gJq`֔mn3!-}҈־cߤrPn6M,84*\)ͩ[ZDTv=|k˗vBK,謙DgK}^J1"h{" wMqqOi255E%& yܴҥFn1xZn')-NTA7\呝ÇHkH*YC,ZWBNPz2 IOJphaz - Yd/nA翿JWPAFYL 6ĊNZ}[.ݎRTøiqj@nJSZ)Og|7Rp ;Kn+^ -5KRƽ7Ngdgb2ir3l918Wdx5QbZEv)(V`YCz| ƭ0p]m0,ßZ dLLQ -Eߥ`4$8; :P% - -ɰ 'j#5Stn֋^.њsl>C >rWn"`#qy".eXr]pܣ\`-A F ڶe0&k23)n,orݸ,;3ɋ3Bk"DrV)v,-A:iıpY@-LILpyaXr -LAå(1\q 5NN̐e5H/)F6>0t]n^2(LRQ~=Ϛ[cTY@%Dk$)\r_:lS7.\29$HwUbU1IZH LъB`i.ĭH.XQ&&x+z{"E&;gf=*,0 /,qUs&.S zʼnMv/wsI16}=ST 9iD4q/Id nmIcA4q)ck94EJ -?xzt-%~ƽ)gH /܁E)_MH۟OBEm4wjQ]3E.3! hmeUMVXqmBONzlA6 -AۜadM*L g2b1[X(yʐOF=0# -&axAjs 7D:< rei8ו{gMuM+B*c -Z9i ڄ5x[bEԔh=ec-Oa~P %Wֵ,aeAX\\*:耈U+D0ŋdZ:f -EtfW -0blL`Ep^ -&it|/-pΥR%Ǒo̥/Pi>Q6g2{ZU365ZKGX+DuXսh|<)8N& N&C*%)- 4Gf.hepXlR=ܦC3^fR̡-w"e>/$͉ B'64ZO!SҜbO&Oml_~;B:ӄSzWAI5Ć~Jli],fCI,ck-ÒҠB<}ђSRC`}<%ĵp -J|oW-aGq"o^T,KAW`!P!UpZ}c'dѝ aXx[<\[>"/> -endobj - -4772 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [297.8902 615.4314 308.8902 629.0934] - /Border [0 0 0] - /Dest 4475 0 R - /F 4 - /StructParent 85 - /Contents (19) ->> -endobj - -4773 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [314.86404 615.4314 325.86404 629.0934] - /Border [0 0 0] - /Dest 4476 0 R - /F 4 - /StructParent 86 - /Contents (20) ->> -endobj - -4774 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [413.00983 517.1457 424.00983 530.80774] - /Border [0 0 0] - /Dest 4477 0 R - /F 4 - /StructParent 87 - /Contents (21) ->> -endobj - -4775 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [210.92213 469.3597 221.92213 483.0217] - /Border [0 0 0] - /Dest 4471 0 R - /F 4 - /StructParent 88 - /Contents (15) ->> -endobj - -4776 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [113.4558 455.6977 124.4558 469.3597] - /Border [0 0 0] - /Dest 4478 0 R - /F 4 - /StructParent 89 - /Contents (22) ->> -endobj - -4777 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [274.8422 394.2497 285.8422 407.9117] - /Border [0 0 0] - /Dest 4472 0 R - /F 4 - /StructParent 90 - /Contents (16) ->> -endobj - -4778 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [291.6684 394.2497 302.6684 407.9117] - /Border [0 0 0] - /Dest 4479 0 R - /F 4 - /StructParent 91 - /Contents (23) ->> -endobj - -4779 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [172.43578 339.6017 183.43578 353.2637] - /Border [0 0 0] - /Dest 4480 0 R - /F 4 - /StructParent 92 - /Contents (24) ->> -endobj - -4780 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [215.09322 254.30371 226.09322 267.9657] - /Border [0 0 0] - /Dest 4481 0 R - /F 4 - /StructParent 93 - /Contents (25) ->> -endobj - -4781 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [360.26782 254.30371 371.26782 267.9657] - /Border [0 0 0] - /Dest 4482 0 R - /F 4 - /StructParent 94 - /Contents (26) ->> -endobj - -4782 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [376.27432 254.30371 387.27432 267.9657] - /Border [0 0 0] - /Dest 4483 0 R - /F 4 - /StructParent 95 - /Contents (27) ->> -endobj - -4783 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [417.52737 254.30371 428.52737 267.9657] - /Border [0 0 0] - /Dest 4484 0 R - /F 4 - /StructParent 96 - /Contents (28) ->> -endobj - -4784 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [508.70145 254.30371 519.7015 267.9657] - /Border [0 0 0] - /Dest 4485 0 R - /F 4 - /StructParent 97 - /Contents (29) ->> -endobj - -4785 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [239.99207 179.74872 250.99207 193.4107] - /Border [0 0 0] - /Dest 4473 0 R - /F 4 - /StructParent 98 - /Contents (17) ->> -endobj - -4786 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [257.33554 179.74872 268.33554 193.4107] - /Border [0 0 0] - /Dest 4486 0 R - /F 4 - /StructParent 99 - /Contents (30) ->> -endobj - -4787 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4354 0 R - /f1 4360 0 R - /f2 4384 0 R - /f3 4366 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 100 - /Tabs /S - /Parent 1 0 R - /Contents 4788 0 R - /Annots [4771 0 R 4772 0 R 4773 0 R 4774 0 R 4775 0 R 4776 0 R 4777 0 R 4778 0 R 4779 0 R 4780 0 R 4781 0 R 4782 0 R 4783 0 R 4784 0 R 4785 0 R 4786 0 R] ->> -endobj - -4788 0 obj -<< - /Length 5807 - /Filter /FlateDecode ->> -stream -x=ra$^稉)G)INo(Yt)Or.fy^ h }իw7oO>W7oừ0~꫷7?<{w]|gWrswϾ|ӯA bxE=8 7?_\Û^o.>խP ׷}{~!Aq#HS'?^ />Z= e*¥Lm8 ֖yuhuO;0贱5Lޏ^xi@_Wi2'ߴUԯ|ksD=m%V/~7LIayG(2zPvt*fnw;xk~&\ς;IdLO4-a*‚u'NI&#ƒ2(T$H_-n>Yզ30k>yVv7 L"YGt\Be%F`X}\YJEMD$n -VKMY)HNN3U?dR(/[@e.Jx-pL9 X;)ʐSIpL(%Fk+;AjG\]-F9c(CˠePwqLQ:lxQh:O_{RBB$hvIY#{ OQcT 9z*VvBj4K+5Ÿ"JۂUm2C딖8U Q)JD[_Ay=l2,l iia-SH%VS-%Is:U}ߎ OB2c L\?IL|V9fJ;@U &0fIHѮדW_莕,(C2/y:b=,YSM= -4uԨ@U?[f;{dΞ45u҃C "5(?FeY5 Fq1$ZGpKa@+'Ð,h9k׼n? B6[d太ML=oحRr27!jR9e,MﺚRNm{4Hfu$7JǤ\`NUoU="%ůjNo7H!hʛm5m-n 嫘(%a̾ NaAFճ&͐ɝ( H7:M6dDb?M6!#%҂Ub,PT"-$:E}H 4֐@t!Gh[ jwInTqTqbxp y\fXK AdR=@92 -hcfONc AAiuT ejD@B[3.tj-NW>^fbf%T2%>d(xna;l-exmPχ-e))g7s0^^ 0|>Ȃu8ȒA86,1ΝMxS %~|n ,iqRZo@RpCx(]lOHQzTGy#%8u1՛_o~_'_~B4p?g5hx sK+)c1b-Q#}K(G9/.įúPz&;{_Lɞq k~8Rp#D" 0@f 8rW |Tf樘Eݟ75!48ڂ|\ -f.<{ $HF+.+ۓuلe,;E j41-<'l?'!* 1OF(Ħŷf+GY`>hbN75cV-PBGB5́FI#ck.ɶKt2B`b)n*/Ϗs[:1aWuԵW|Ix -|L)YJ\&\B/x2;?_ շ%jd$3 - vR௚R%Q\IQ7v%zZ"hKi/dkX4 -T&%9SZD }t5iKV2\}e)PکpUcگmYKGmQdӗSorrXY>m+YYjeK5t-| 9^H?ʀ hfbB$d85X" -mndHl0?f:m|Kԏ,tv)@[dF4.-6`<.tv%/nۮ<`n!ytv#APBq;lۙlkT0|9R#mҵ7 O£dt=^z'/ci }7K*uIDr,}\ORX/Y蕻Co5E= ] uq#;M\sZd,bKA::q5DZOMDG˶?-ʎq_GZ,0-Qab-#ܬ's=kI8߿cSH sԪo'~M)@+W9oڽU˅LaoZ !u/#1՝ڵ6 YGduW#w}+_e$=_#~a˞d8?Wݒ6]QB)_N$v,Y(䬗W?O^46VTItNd57Dѿ:ѭw:3pZ,. ]QC_LnX̐BFcfb*/~E0j'D3ȾVEa' `%vj]?JZ@>c'kWki4=xdĤfӓQc t huvN[vzY_D-_j$&k+%'j#NBS3=e}DD8C*"~Ck .=aJj -[Pfto/iDgyZ!CN4>JveCЪm#jdTДZzK1/<we/ɱziol~uW"֚${(I8T?zHLyC.9:"  -2[L3qTæUtvy.Ɓ'>E*sԕM<nIM{hn~cs協];!;J4  m TIe7ų"EOv{.$Pf_2觑CQMg9yL0 )ȟ<&X:%7l9|:[2IՖh+BɆʻ @i -+ /v_RlQǠ u7uMqA&J(mtCJTFM݈M~72o.inPr!m2)Ao{j!ek S%vߒJ6\%Zֆ7cnFZ8alQ;GUqs&\~%NɘIã.'CBj3TG9ҿY. s7{[R7n[~MS֟ɰ>s_ gzamCJnWDqjCkAy'|FKS[颡-¿VB6? -#># Lw,^ kr -nzE6q1b;@d'ٽB9<d7̀#J@heR+B\h'q-PSR -bEhteЗnb?c.!i,S-;@OẀ zBj(e qTGhi@N9SC%"ijB)Lw 5m] DLa6ckJfJx2w"0-@`C)3&0 d[%>,Z:}-!R0QZ{O\qj&~T=ΚFR=9G[sԦlW4F> -endobj - -4790 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [389.9495 671.1034 400.9495 684.7654] - /Border [0 0 0] - /Dest 4473 0 R - /F 4 - /StructParent 102 - /Contents (17) ->> -endobj - -4791 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [327.1667 568.66943 338.1667 582.3314] - /Border [0 0 0] - /Dest 4488 0 R - /F 4 - /StructParent 103 - /Contents (32) ->> -endobj - -4792 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [202.81924 555.0074 213.81924 568.66943] - /Border [0 0 0] - /Dest 4474 0 R - /F 4 - /StructParent 104 - /Contents (18) ->> -endobj - -4793 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [215.80038 514.02136 226.80038 527.6834] - /Border [0 0 0] - /Dest 4489 0 R - /F 4 - /StructParent 105 - /Contents (33) ->> -endobj - -4794 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [386.66837 514.02136 397.66837 527.6834] - /Border [0 0 0] - /Dest 4490 0 R - /F 4 - /StructParent 106 - /Contents (34) ->> -endobj - -4795 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [403.2961 514.02136 414.2961 527.6834] - /Border [0 0 0] - /Dest 4491 0 R - /F 4 - /StructParent 107 - /Contents (35) ->> -endobj - -4796 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [157.96414 500.3594 168.96414 514.02136] - /Border [0 0 0] - /Dest 4492 0 R - /F 4 - /StructParent 108 - /Contents (36) ->> -endobj - -4797 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [289.38113 398.4804 332.71014 412.1424] - /Border [0 0 0] - /Dest (sec:introduction) - /F 4 - /StructParent 109 - /Contents (Section 1) ->> -endobj - -4798 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [98.00314 132.16443 141.33214 145.82642] - /Border [0 0 0] - /Dest (sec:theory) - /F 4 - /StructParent 110 - /Contents (Section 3) ->> -endobj - -4799 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4360 0 R - /f1 4354 0 R - /f2 4384 0 R - /f3 4366 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 111 - /Tabs /S - /Parent 1 0 R - /Contents 4800 0 R - /Annots [4789 0 R 4790 0 R 4791 0 R 4792 0 R 4793 0 R 4794 0 R 4795 0 R 4796 0 R 4797 0 R 4798 0 R] ->> -endobj - -4800 0 obj -<< - /Length 5926 - /Filter /FlateDecode ->> -stream -x=]s 7*.ɲ|+)KRg٬]h4Y*/IbFݸyپwf;|0ܼnO7~qo曷w?݌统?mx˯^^|ˋ{x~5A b ֢ Û_.nވ/7_^vsqN ?\BBݿO] R ? 9l9#!8܀VPx54Xiy'a1w^2C{k"vQ!6!C`&f&4;4W w5`6] B~;30 ~Z#^G%tF{#ZCyg4OC?}Y~ gSqY*Xi'ҜΥDy;r>\iD͝6VN[8~.fQ&+kؐ̿wA8r?P E/kBJ -.pGsH0OhP2}\?l,9ز`O{E0i7WW pGkoBeAy:fKl0B*%p T=y*Q:4=KM?Pڰ6Qb/܇,_# 4(6jɆڴ!PY&/{(pWW_-W䶆GAB?; S{ BXߏHioBX%l:ZPhzX;pvMrM*Y+}Zq:vDmzox:+apV kdF̭|TIљdlDhJVU]_S~Bϙoڬև*=λ2AmZ3pYuPvyw()y2iFyp,Kj!e cڟırG(%žeyELB2hl <@pv膢IwC~€5n \?]5Ҋ˹! xT5B04Zu:< N  -֛>}tr-M -NOsjE͟@o'cIb@M3en1GF)?'q1-%gP7H[0(kɯjLu|+U[u#M 5BW -U?V֗bnD`>%жjSP _@)EFj"…ZC:EGKHP Py`A 5[+,h9FβPDz VU'r'8^jDRDޡĩЈ/$VP8Q(A51SE)m5HK[w-(yh Ǽ淔3INIԹ8.dZs/|wՄ -J)Yorol_}/bMPnO߽=J,FZC?% -51̶lKU D)!`{Q(Y2,V,DAZ#|5Y)QZzE!.AMkJժ50PƚL+sk|FŧA7`i(k,_㝆^ nP[AAXUE -NĨ9u.][6$t/iApŽNoj듖2 z -# iٶ| E[B+&<&+)SS٨ȇutZzt:|-̴v̌3_CK:3ݘږ[+׉}oq%9٤ĩ4p~in䧠XŹ%ӟ]8;O<5ƒY5qn)jvVXUvnynH -ɫ8*׽xR4Fe9 ' ۖK$#vaCӆM{lKsasAԘ~rE,$I\:N?_JRD:ЖQUy|pM"*qwDtRR@f$fGQ/~ʖ+=3Q5"UhAITMjeޢlQq>VҟJ-H@ˎMp3&nlN_ 3c#! -(rSÀC-`Հ> V;kivi8^;ڧ`ƬwJ|, ZZC -t_S=)ݭ -׷OAwdWX}: *)3=X`tTzitDO|}dTh0Ny:*F~5(#_*h X17c_kbtm!H/@IyauNPo•Nr)2Rjo̤Z~T_=r6ӠKW(dO~RxpƸK9zbNrg[hFp iDA*sM>I${[U4]`9%._R!@O|lt*R -*nŬjIo _zioHAS!n8E!۠)oڱa:妎2rZ`aRPR"Kq!1 Y>_nZiqmlpvP;b|Gv|,P̪4 -hzƵ~kh8@W~0ڸs v_Vg;xjyQnb{岵ɶ^AcQ`o&,~adK7ا]1BM q{q=8' hX?6KFk :W4HAx&bݥ&QLH˓b 99]L/R%+4 DkqMۜ >ud,}Hv;Y HTlk <&ĥca˴^V,OxfSᡝhX_ܷJ^(7ōj!Z#d$I7:Mk0`6r &OCRHED~jE<^V?'ptޛWxAnGD-ة^Ra`1gϷ9ݤ[x;_*t K*Ov^2Qy)|+%E˞&yJ?'\J$2@fz۠8gw>>{b Jh̬aId+G2/p~x#=GTk8^A'sc'w?&3cKhuWU+lw}xj|Vw)3 ǀW&E~+`ӌLlj}S'eh$CJQH~Y_bIzsêo0;`-y᳞dB -&loJ^ME8@4 ?AvJ>04Fe+Z:0贱˜Myᐣg3ur]SJқ~V{{]0oxDśrHG93JP|>jbdS9LKwQ%GWب 5ʇ<(I-Z{FYh Q#Gr5J}J<جH4^<;HՇΙE(݌4MOvgm|@ ᗆ?3I!URwYOZP3RI"/Lm(-ƞT>¾w1PS/Gc}rⴭKxu53Gv,vDt)"nØl9O~G3lZ r~x<%≤Ǐ`©vp8]'d2B:b,IUJhZU N.$9:R:W/&]̏J ߒKHDU"?XF ]IR1Ms۱ɢi&gV%O%mL7p3?5}*/q0QwOztʟLΒXފ{5wQBؚXz|tͼһxss5z7t{ʫ@IPe䅿jLdreQFs-GVRLOx`qddLq."+;@#mK gQmZ̶A>Juie۪VOM|»c 9v(vx؅5k*̴=+䵓TyYNNc"";2~)UR^@N8xʁJcTȵS୔ SdD}>ŷ!o3t윀ex9CO]ǟwN;iH(M3PĞRHiyhYSU+,6ju2Hm}8!|ZО]&sV{־86S>D)l]rkM@ 1fr |>W\&*q=-B --%q5 53U77`eܕjuT.̵+#{+Ĩ1QE[#3 yKrd$0 :>[|lvi~-7ސJPXyOCUf<|V9֕״R~JSن0[܁:e1&JڍI&F{#G[#N$̴(LOlå.ږ^YD>E1229b4cp'vZ#X"6s@,y ʼnYg%T̙K{:. -nr#qTH SGH!=`!E%&}Ccz -/pײYàf -5 -d٧PC*` Uo! \V ZTDmRe5% (EWf.jhu />BD1e^f9O 6a\dG!tl*CW۲j ̓jOpP&A)qOmKmeF@ tjzh_lݽNh{? ?|aˏo~_7>|ؾ݌统?mx({C@cN9CT/g -endstream -endobj - -4801 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [391.98032 717.3104 434.9935 730.9724] - /Border [0 0 0] - /Dest (sec:preliminary) - /F 4 - /StructParent 112 - /Contents (Section 2) ->> -endobj - -4802 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [322.54614 181.4444 333.54614 195.10638] - /Border [0 0 0] - /Dest 4493 0 R - /F 4 - /StructParent 113 - /Contents (37) ->> -endobj - -4803 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4354 0 R - /f1 4360 0 R - /f2 4366 0 R - /f3 4384 0 R - /f4 4372 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 114 - /Tabs /S - /Parent 1 0 R - /Contents 4804 0 R - /Annots [4801 0 R 4802 0 R] ->> -endobj - -4804 0 obj -<< - /Length 5927 - /Filter /FlateDecode ->> -stream -x=r\7rH]:K5k;Ne7,z);sfg0C'/8@;_>lݾL}t1M/77y_~?כvonww/>d.gr{ϟ}$LrLN -o-i'Bpzz9녜ӛ 9<\\ p;|?R>.n⋛ Ix%@N).'eJ}9]~ nf7H*?~-by|nP>'4[L͋Y3TMRRR :d9{9)/ wg3f2\46;,G2Oل'_?@{V csRge6dF7j GKX^Z  NA;/,kbqS `EۋьA9-,/Ô!0e41ͯ}7G_~Rybt_[ڦpVXCjhIHaC@zi/7LNA'拌X{!_E< 7\YQ'B|Wg -^>nQy`0-,/f5Q<=6mdQ(ZCSٓ!/o?Mx{Iik U/ }M8>w:݂aJB0$7RCKvڀB/;gy3%K^]AJJz壏e ™E)9vQhJ v/@Y*h<'0SwCnx\-* i&oS %>1Cn/f<ܽlc5} ^0sӴ u@7'vkZ Ʋ_^RVIk;^AEauWgH.o+K4^Zz,h[-"9c&Im`̲`9*U׃O?FEnHPGC I^`SX#o:z{KS:4Br^]T~O9 "WL|Z̔7cY6qnߓ]%q38XKmC!zZTWn\ƦH̉F Ƽ PhU}Z" 8RX#[FRgop"XzHĬSJ -<0$0$+6K&u8n)b)ME/ЎyDߥ]aZѪ+Gq#qy$OzdU6}I!)]\EGL׾c"8]*$ S^I+\m4+NĢFH)HLI⤛k c mq +eDF>h7|iB)Au6M[H&a3Pz6`.›>é=K~x9fP8-Lt$ԩȢH܌-ځHV=ry]W/QLhtx37#:c Iv,RH DۅȞLrD6D1Q IYʴY CJߥ"~*r?s2Ja8 -:nr @B{=hhdDx˞xI;54O@DKRsly͙u*-a߳r:vېAu` -Mu$ 쩁Q|ʋk<֞]%>aN @Dt`zM'>nN&3{/xv_ڱS#.y_WЖ4N1e+xܞ}iWUR33A<ݜn.+8rgx3u%Rǯ->(Aa W'&’HXb"Q&TF2I$1+wh@thCDC׵ ڛY) ֧ѡp= "@S!ez.'AY`'lx-O]ZzcAOsOagE[qgvN^63 t0B?\Cr\BٕfՒL;ec -dCO:ϑHc`PѫUVN(N߲ANIV|rjLvHN/MVclh£=EJA55RP&X"5<|Zl]g3}.*jS=7zff^gpghrqqo[Y8. N Dm|pvEYdgg=J&"A -PX }Wzq9A@ /L]LQqA.`†P@4ik~IS2gs;1̀.rha` @E -+CqbV'h*ժ5Kq4HzeɭYUW3WYNA,Gk@'ue\lyry5mlBΙv:[ b&*ԗ\h -Pqy7pM"gwKA 3Xzm#2 FaaȭNXASuRvRzV' dt˧ԹKZ)01] bKZ—QuݶR5 -姡mP XB02eb#fЗ%5]@8X6ԵINd7iA$O]LNm6z% J40B}~גhi8ӒS0:ǒfJAOF;ҍKc\?6ǒ^|/˜vbE$W2 |yHbߑ4|bgfrS߶ ƚϯ6-nmz@XPd7AHgl򛤟\e?xo) -;`Џp$i4A !֑RB[l &ڭߪ us!-ՀçwZ`xd'z|fd=Akp6cnCu/B'\#S6b ̃F,xuY&$SOf}O{)2xӓ[&_{R2اX}7],3ȇhlb޾`IOW -QKĽm6\ -lГpN(ݹzExW ra'?!_,G3M$oLNGy_vWoNWw^$3Ji4Z#2y5Z|]mJ/: f -j #]Tdw%7e!Zͩ64tA/ɷ/ƹYIM[FmG+CR0O҉`C]۪7M -Xg_Kމ4|Qi-58yʊ14xp5Q&F5=斧l c d>sa@&-E??^?1CMMU@-1 ` ITz'HmT`@M1H  ٛ:)D{>3y5Քz.'J++FLG`Ju>cOίjQQHy} -e_ ;VsaȏZmo vNCLyB4$⭇]^9 -u뷏ŬCo=\\Ђ%_RFh4woy0􅡋czED=b=ʹ\lM4I!ȃl+  5W}ML%V+lj.hE{b4>jO2=ACU~~ue8\̇2_2U}tԛϫgyh\ykb_O]V4)e6f!hd0jek䣹GooP cgk ZY˖\_wWL4lPWB/Ne]~%^Rl%1d| / CuGݞ_uwZ4YY>P3[ʆr#lF,_U^ -^-B0ݜ=ރS"NYIz>5錹v[uDu?t!BMu<6r1tڸHG [:Q:,D$3˿*䗽Ta%0Zh.S$ G>FB_XVN>ۏ&bHaf'o^N>& -&U2egWV@DJ|ؼ}K+67y7?ݯ7tG7{ӻͻODcl7wƾmm -endstream -endobj - -4805 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [259.9224 538.3174 311.83884 551.9794] - /Border [0 0 0] - /Dest 4494 0 R - /F 4 - /StructParent 115 - /Contents (Theorem 4) ->> -endobj - -4806 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4360 0 R - /f1 4384 0 R - /f2 4354 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 116 - /Tabs /S - /Parent 1 0 R - /Contents 4807 0 R - /Annots [4805 0 R] ->> -endobj - -4807 0 obj -<< - /Length 6944 - /Filter /FlateDecode ->> -stream -x]Yq~_00&*:"(<eQ7 Jt ¡ޝ;f{vndvUVfV_>ݏ?z}7|0<뿾~w?k?zo߼{z߾ۛ_ro~7_÷}_ a! acD 20Mg/o€8aaO7}Bn~>qtO*!!GQ Ib7oB -1@ -CS;x'bua<oQ{B|t| >uDG}ar _~;dMqSgOedB<%%v1fn꿬P/ y $_Աg DP޾U'dӶ9ebjscUqce08jpdnzp;Ȇjbwa0o8޶ żv~FR AM[^BA\1!zv ^k"n"136ruGV냃/vǷ=M`:| -SNv݁voH?oóP½f)__޼(-9H|֍D܅=uwOw/kT}\{ D -YM*?$!/O8)Vqϰ\MsM) -̨M [';.窱nk.Nuh.9^T2f^RU G-(cSffME-2fE7k* \"79FfPB-}7"rφp -?Q$ - 3V)e$1#'q"YZ[xړD@cZ9)G US8bGJ rak쁺 -20riRO?27/&`Lzcn/PŸNdƫByIhc8k#1Ab]FAl2RFՍ!h:n K?k_ZeT̝Atb@Z|-]ՈHEI;J)ׯyq@DB\_k"h-b'We.W;ѽ1Ge|!Ǽ׎~/ (~MR%^zy -ByW %Տ^F1"*|ExuE#X/BF>hQ(}<ڶBv8FL- S:ɋP /{w&O?r>Hg눗sn.DDM' ޾Ϯ5"̩ Z(w~Yn\.\n8jډmK ~hd`"CAͫmqednlFVV5}JuF5HkʺۑDMonK鷜6/MrF7=G:umޫ2;(qV%Gz[VʸXd4q׾FoTbN2h*枋[˒hvB ͱ&,h?5߭)֌@TYZ0I֬!EԳNܧk1dq;Fh Q\<äy Qq#wBRb?Z{U*zRp/Kʐ"/qʍ`收C+ 1F1xfBX!D䭮$!,@Hζ۠>GX-kbo= 1p$.w5ٻ0ݾrL}z_:&|M%Z"@Z`Ƴ~8^)Q۱L~U8s4_z2i;{1z*Vv&qШPdMb3C.h:܀9&Ni-RKЯj>BɐR\ɇ&[q\_>4'ٔ?VD$qR7VP C-.be Q5t'rZdYi֙S`rh:pJ+3p -{5]QJg"_|RRGUVIvPq#P 4ٽU<@o c-eMi3P+CG@TnS]Hn) Яze=^U !!FMKpPABB9AE(oAD )@IdyXL@7Y֜gq}[v'`N"~|^R(Ļxnڻ?D ,w}\J$nݎo q#rw$&JgX tUC&|^J#!`ı8]趟#%ș9C$+Z s.nap {P;ᶟ*`( {w(ܾtLVyL9nk:fKU/unN"vc1 -.P-Kܼv2؁=LRĦў^?fч>xW\ڋn;iB;h}tѪ͞>C9/F9<#3q?Ycp⦆m %ۂ|ju^D#b^7^_(`I T]u_~н  ,@!.BU †^D6wuJ[B89t rl}N M Dz VŗE@>v ZˣgJ\ -Ao;8ucv3d6:K 7  ؽ4VG9nke>ß,ʄ\Itܱj> r<1>H=vֿ6iYǪX_%U~]j R7Z5QA)^UBKp"fP#XbKp@)5\G3ZGѿi$݉j3@@,޹̚h 61$ lA7@pH\a %Qp"Lm\4@9z_z4C`kw'5At%+t[%eӋuv@VnO:pJ.WGy_܄ yw7n 40͋Z35AYJ i$`b1`TH!0efdGhx}g6QsjgmGEBL!A(ӝkBPR1$8A -ډ -cZPđ(5 a$4 "em&q=!qFOTHzy )y50AmM&e4$!(.B7-,PKJ=mz {ݓS_R=ىQRdkvv}ܱw/;BSBf:nIe5 鹶߇̰飥AK7[IB^Bj9>aib^QXQ t5a!&3(l d8ؤWK-kP9I%ĺI"AL9*#ÿ).1p1AF@q@-(V4gzW\nlR*a!>?9pZִ1T KtZxu#>`ru1<OB gbS .*8&/@5@AW_]]bGZmr C~Z_ -o+o𬺜o/7 _r!;r <̆A*<5kZrQ;P"#vɸE8}T{8Cۚp^ !P{Wp\Ԫn6bYfG4!eջC ?P#Vvl<] reGkNf Un9\ P=.!$t??0SHa;#UV5&Kێf6(Ndrn'Ƹpkr1iw!:S㪔QL#&1J0(>Tv] @B8gow -}g,'OG -?:#oOGjoO!!v ť@(Mk⏨P4ys߅%(tag(+oóhJ"vhPv^ɼI\ }XqKd!U jorWBveSK()gY 4M%t?pw>yw NosJ,UMUv؊4$]]NTa3W% zF2B +;o~|j3Cˊ( - -Թs ߮mlJ. sq ZbVkڳEm%H(֪^?K.l I&ޫ& -s zjf,'-Y% .N! p@TթR(7mBWcLxt"쩌hԼp9 lqT/T[z簶Y61sP6x$@ \x_r9I=2P|'#б{ip719fךX.fHxw19(^] ؒwq7X*~w55]AlĢL݆ `S(VF(9SXE)Y -沬$!Y֚iVIPreoSanN"MlW?y~?xTub͏$kjN<͸On<+ Bi -ѡEH{熋&cեuuQJ I7E[}哉Q"y9&W8].a <|ި*aCyXچ,l?S.0huƏ)vs> -A(1sujG? rUx=^&Z9dߟSnveV&W r)n'rv-YǥGc@BO.Dvq3᎞#0Eշ'Nx~>||)y7ew΃ONTEၣʧ3vX9cXtEKᔬU.ʆkZ[] Ic7J vE-1ehc.8 <.ĈaJ_j䋃[01K3GhxΊד_:]`4Wf]0s(]'Rv96ΪޛD1(Qhw#[՛ ens-}9i!6 B!QbD]. -1[,] Wt?,B_a >k.G]%lk:>ͭcѷ?>0ZqQA*c>q8})}>ylK8D( -HG9|o*ONRiG#n!%<0`5T3 -NY2hkv1>6xzf?5GUg -@f۞3qu| 2KS5~&C GlQ%s:S*+S P(EOBʌ޺V\]{F|6-_xs4V ul&i<-)LxRZ&i<)5<W 3Q)}X Ķ'%f*>fg!C.M~+mjomP<"hjWD !kmz6 9y Đd)q;l1m)Z6&+EB&Tr!I q*55cfp>)f./f4?%@ɗ=%t]5!ΜS'Bdۗs ט%Cɉc׸Q| z$dn#KGMX5j5e.IGyd&.4vKbo=ҒwEWY9P.'#ݽz7_?ݻww7ݽyo?z9OWw?{;&Hj~;_<_:@] -endstream -endobj - -4808 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4372 0 R - /f1 4360 0 R - /f2 4384 0 R - /f3 4354 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 117 - /Parent 1 0 R - /Contents 4809 0 R ->> -endobj - -4809 0 obj -<< - /Length 6139 - /Filter /FlateDecode ->> -stream -x][m~_14؛A\Z%+%QRYJM*aI2SRWߧ0gef0ӽsF*끫=;gFgn޾zu}E=՟^?~=_|=?=ꇷW7o__|iO.|o_t\Pv)r]tg׽zwvr_^]_|.{ewy/Px?i{ŗ/~osJH+N~|=bn?ߎ.Gr3w/ o숼@?>__vr=}x$R^|vr\($2xf/Wbp'5\2W~ ~SY -H#LE^=c^v{3\@_{<py.(XL)Qt=!/_ڏN5Nw9".t/B[_س[.*-}O^~E{;'y` DwΑ-ws{a K\, ,={<@0qs'sWиhى7H|{xZv=ʳ_.SUoG__G{w`n |L]}Y¿քx?8_NNjwb,:%9`2 ޺8eE϶?{9QHKV#e E'3.s!ihuՏ~hGVخ0kԬ%7#qݷu{29so7~b5/ wqVr]ܩ=\x;.l2檬Y &uo,FeD63 D&i8GBW؎Iͩ uXm?^b2ÇFொpBl/sdFn޲wem~i8إٚؓdfL-qI=åWN}qif'#ƫ>_$EJemG>P>=@\rwK,a9u; ID,Fra_zACS׏gXSSKϱ>,rafTh6>Y-]1nI'_:D&z4,wƹohr>Uqq!R6Vv\0UۭA8}]nKbo w36`#s{)Ҟeq' UR׸lCXԺ#v;Zc(rYyp[?IY=WϴS}"_3͆ -E< - 0`+F!:a πAEDC iuٓ@FIro '!v8Mqfp-‚9|x}dn:qx5N -V,|qee4]pV _1bN R^~]"$kMh:# -&2b c޸{n Y"O7 +s*Sءq9hObz0%b&,NBP>Š| țVfDD %-[WLBA{"qmLH~Rm3CnL3bH+Ό% =3cc/@)jXr)0Cc!rel0fh2@)5̽AG_JM8sw+d+ma."6ZfK@i -2İ -f دbJoFy ʙoL#8gέ0tA g\c(e4]Ȍ,YoSldTbv %ur -w,-7mfQufz 8XLL=,)I^oϮ@9q}maа,TY_i2ATR/8|=M ZFTG$ ķт u뇬4cfu=MuB;:&O1x<#O͖ۘ8)a-zӰX?Ė<0=1g ?m KEt]TWes s{L=pedX] Z;WM-ÅWbZ^^[lԱ1O}b0DIIglP~&82 &F^"([ [Ƒ] -2(d8\+T_yf9d,Z3-0[fLn#%,!gNsXt.'rs)KQ+P|PK~Q+ "4 E/`AP]a; ,P2(kPlD:X(bBz)m` fZA --1s[Gs_< ́i3MtRJ,G:KQ`- G!`@]cR4XXgS3R4a;XgoAߴ!%\A零P[(bh@_6 -XGEvkQfTe=- Eh8)99~u ʏ6v&e@G460v{s^=5ѴcZAEw`ǨHhi y\4vn1-٩PklG7tFEҔL'54m5mvH2S r*E{ -0z?p羪lvf{/ü4{%\5^(C pv޽ XE?*8z7^SN(RLY$if͆b Z(ofG1@r~f5;^V_^ufyaW]unI}B/5*Nufr΀\Iq:|Ҕ}+5Swnѳ_blDFXBuݤ ?Np7UXj=mr< }]\$˝NP3[$fsqɷaLI@k|E~ ʸv3h \X('~2Q֙1>:mPoVbt<;(ӗo0 W&$1!  HkފR0r@`N5bh4K -+/?vs&jf5]A;CpR3de4^v>4/&= UXupY &/=,L/Lti ӛB>5t{nCQZgD(cFxwܒ#Rm-_bmܼ}sJ0%s'('.{_.\uO/B"'AwY89zldSJ%2)0v S!SsPM 'p}5׌uA:8r8A( K_0U3'N?bxkfwCR'(Z]їcLj:e9,ID8\o&^}k=yǀ'R[fQn!BFF꿭Pߓ =@NK$96(^%K?R՞=2{wDQGsnޢStMFUzwV"Sҥ&%:$l=M.Qix:R0"_Ӷ3Ɯg-(f  9wABr\ͨ}[ -ĀYXUz1PωS$zɘb;I[r&g5ِ+9KkЯN9("St031m6b1D>"ì0ɏ0r_V_'&[2az{+Ll=*QvMiG%=r!6%H>KTd_7Q3C()dtG ?M.!aV坌N}qv5.cŸk88e~ƆM3-f -h' 9xT ČXPC5ts_.v3conO?_ћof\&/6DlWLbA(}R<ݔ95``}C1:9}QBYT;DQ IL8i/d:gF:յ14ɪm$NcmU[$R634 fyTHneb>)1dhb)&|Ťg:L$?4Cm=x.{9DM!'J_ ,~meb",=+;82!/Gu -gb!%Ims5w>4et+QeC@?څPaf(KvYR> -endobj - -4811 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [186.94914 178.54639 238.52814 192.20837] - /Border [0 0 0] - /Dest (subsec:reactive-coeffects) - /F 4 - /StructParent 119 - /Contents (Section 3.2) ->> -endobj - -4812 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - /c1 4403 0 R - >> - /Font << - /f0 4384 0 R - /f1 4354 0 R - /f2 4360 0 R - /f3 4366 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 120 - /Tabs /S - /Parent 1 0 R - /Contents 4813 0 R - /Annots [4810 0 R 4811 0 R] ->> -endobj - -4813 0 obj -<< - /Length 6514 - /Filter /FlateDecode ->> -stream -x=k#qW"u8 TcʼntK$V*RJߧz\r= ͠@wxoy~oG/_O߿~ׯWǿ޽_bn~鳛#~鳛!qxj IaPP4WqxM>M ~sc)9D 874dP@$B\R%qxsC3 -F4q DF}jϿyYO/]}1D̃rw+7q㫻ۛO^vx_7z^[%DhR>j/$6np(3 )F`΁5!n8z ԨyHB -t]Y+h bɃRi/ -hRۯ68Pj<,Qq* Qm4rM+|9`0s<<~Y-lݰbLx,k_D#!ҟz4.;s`n5/lKL@4(Q x#i0) -9HPt.& kj;cHXpEEWѵrB%⠠A -횳A"P+A'I -v:Bf_"a9u:QG*ə3G]\o,ʊd~IO\XG$Y dN[!v6 $1'Sm* ATF9R{ ɡ)9_h>uJn-,FbC&?޽ v |7V8͘.⸝䪦\-?bQ 7w5\ᬽ9|ٯO^:j 9%A -XhM |~<8Q6<ͷXS/k\9K TS :2/"';Mt\G! -ޡXJSSgit  Ol7oLzor>D:M8KvZ>{ [<3X2ò0|*.Կg*6"` ZٷP[K~IH9G!Anՠ{b04+)5Xɍ!?]8qx[ι&n?c(1x,F <ߓ$,}%ndsrciA[P2R\/-#ŕ3(".'!ŕYr'xW@ZeIUNUwc x=yb/ǃA6SAo_[7 p XX?\'tމ6$۽Q3jgE5 !B˪uqkrA2e k\bZ9 6Mnu}hz7qݧV->%>B]=stء!S_Δ/ѧ3& { {/N;[*.["xF&&>ͺ%]djV!}dr6x$/iNީJE3ޤ>R7foLv#SNw{q29 -;;A;Gߩ{,U;(z'E>Nbsm6-R-AXf3NǵsUOy:qip'K4b}jns{]Al#U%Z{-mn=okl0[X/=)l)/k[PAlJ6YU`s݉G:UޕӴEҨ}a 9-w/l/i;f|yAy&6̉WU{1VՁwQE;s{ר"-bvF 5 # j`?$,K"[ dԒ_)u VSr2ʀ^5P _ŕ ! Pr(jY^J@P0K?j]g1aj?v761>TBů1vY + -wj?7YnQL+t4D714d~M -AJleQkB !FK_8A3JlU'0ĥV @?7ҳQňƋj tLG,q# JyPDU~UF Dv*`ˎD3F`]UPpEuZ(L܏B3HD) z4=r8`4 fGؚ~ *CV5Ћ@M3JǪ++굱?ѐ8PON lA&;c5as,@UeՊxLw"P{Z hqR#N\[֍BU`{bn#j产{5UO x,@51raV֘d S>VӀ``H 3/~;K]-~r~|q2eb2d7;T{Jֵ2kw@~{XO^UY[]QV_bb 7Txn0I -dq'Z&RPkyqqVrE NRP 咉-lQĒn-eki VRY -ʈ[B|ywox+^[43~&;^'Cpqw+k̡3MnV>V1X{~uK+peW1/\Lr_0'W9ʷtevMrbi ́B͚_BNiJġLtoyG l$z:4 7{(P֫ϐ)6]jwu`rwΡz[)[ $ZPN pk![9%h{^'wpr1iF7 p&nUh4|>n:ssn:s|¢m;gd)g_\$eTmDpPݒJvV_ -Hsdit!``pKsUkĨA%Ih2]~s/V4VUd ݛ`\ĢҳR  v?+w#P~"s>T~͢$r7Uu-!1'yxNm͢It ^qj59c7cխ쳎v ]W>~YQtk,Qb.U$1ݸsVq-v!]U@J`w -|cůL -R/kb+ -7ΖxQJ|$c:AƐnE/J3th~Gl :bu7'1n郷zsECñݼ贖)]8&<% -<n+m foF2OB0sk3$P}ij)'a?|LoPMRKOww<`?mFR~H-+pbk;!؋jXCn'P:[kvesF+=_-쫓ɐyƖgnډ 9W=. oiv`cx{(mwf5lޯ\LqK`ޯ~Ja_G2FfDXTDB[hYuBK;wcm st:' ?O'sn~CtknRnCߙK\]tVlO}K]ck]3ѭek5͟r:[̾;T-KyւቨFI8D͆]"ݫ'›G'%̅4K̇}!v0LwN,e3ۡ\ t^ <ݵ9VO9v"Sjuiխ87%eMS`F'VT\n2bjRcvUR\J,ԒmPB@-ݮivؙ 6M*JJrpk`,ppEF{ 6i[3͓G+ϴFgXsg^TA?.텫N$h"eb#5h匦"8r]1T8[.l4tz׸xxkz8st}nJ?y4ʫeWcCٕGLc] ;/XG1c tfW6{"򘕸2/u*ߋ4^7O^+;?Z%Y<rK<1 {g"/yꕪd&yY9ݞ)d-g:EbXJx~<>#rN }b(}ěqvS)+IW'zu24fq [;QޮL)*2Ѯ`Nco_%]rױ ۴(F3-t*<[ -mˌꚳ㓶P۞yGl=ߏJυأ hroeTܪ;琘[s{}M `rs Afsc%n9έ\L+C,y''Kg Zn_vjBt_]W -hZ59|f惞|0R+R%YHՙ?̮gxT`is(WSCoAusN.E R_ll .d/i@/Yߛo_ [E:AWsk6Z1]t.K4Sฤm﯎t8Mߑh& - -ɴB!k#];:p8m'rƨ%fj̷Vdnnmj Vhe,k39-awaqO<ҋd79y,1͞e7Wxӏ͗߿wݿ~k_={fy4HG\N? -endstream -endobj - -4814 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [321.7234 605.9284 332.7234 619.5904] - /Border [0 0 0] - /Dest 4495 0 R - /F 4 - /StructParent 121 - /Contents (38) ->> -endobj - -4815 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [340.1572 605.9284 351.1572 619.5904] - /Border [0 0 0] - /Dest 4496 0 R - /F 4 - /StructParent 122 - /Contents (39) ->> -endobj - -4816 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [330.0642 189.77643 383.65222 203.43842] - /Border [0 0 0] - /Dest (subsec:revertible-effects) - /F 4 - /StructParent 123 - /Contents (Section 3.1) ->> -endobj - -4817 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4360 0 R - /f1 4366 0 R - /f2 4372 0 R - /f3 4354 0 R - /f4 4384 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 124 - /Tabs /S - /Parent 1 0 R - /Contents 4818 0 R - /Annots [4814 0 R 4815 0 R 4816 0 R] ->> -endobj - -4818 0 obj -<< - /Length 6211 - /Filter /FlateDecode ->> -stream -x]Y$~_XaVK B}+`df*f驪LF0H/7om>/7ۻyqW_z__~?>xO>ӫ_rkOlP_v 8f&`^ܩWj'7WjyzF ͛W[{o_mRӷJW}Rw>PfB$U *MWޛ8o]dSmm5_{9-V3o2`!8g#w=蝴ء:tM Nq.9#pW\XX5uzx9cz@~VM:1]2gw%Ø21:F)>|s=ku81]әpQ$s}r{Ij?5u˸smx|w*LZϧ0gY%aSuBDmsm;^O\!F4E6QˏĄ~2o+4ŋvⳅ^p1Йξ{Qgm&=5}*_-Z[ ,&)d"zU(A)RPRGkdyvyC,u^j-E˒Yp1Ku"QG,G/w@&oL3<ܽقeJ3sgd1$èK!VU´w_of^) c/U=u̬/ بWUQh|6;{$O|u0W^5;(mJilIF1ˮ-?di$"gJؔ;ŋ1USy;qGԒKeoBq-ud\}vP9?a5Z3(ԑ`P(2K F$21OƥfgflֹVU߽<9)u'-Xj_aug9互Օq-f k[~Fdfv6b\-.Ɲ3Zt:PSĭބp7108MdˤRp%^1 ⶣ)DW}LG2Svj3&R5gTh=+SMT;XjK D--lwqinf@T,~m{"KT)// y%4zPhu8cw>2}.W ^cގ⊢Džx!'\ ֒\pҤ|"m-gBI>V Ӌ"K'l߽B.wom̪_hU0S3SAb(&Nr"0nmkO-њ/3 XKtgIe.\ʑM-r\4T*EsȱX|L@{.c9\HMfP}\$ P l@p4@Km!6~l Zf<>,ъR!Q._.C?[=b',oZD`4=%IJ)AnJYsxT[P$#ƈ`U#!:-^Z[E}73gf93gTGno%3c%r6hb:NM_4Ξ[gl9n:f)5P;N}[ `H݁rԷ% F y&4=9ًᩏ#&g#)/8#(jޥ+Dcz鋖!N` -| LJ8YCsG|G^})/:<ĶaQbg^s6.؞3UJ9|8^|hU˧ӑEGƳ;& '[jle}3 -ƶ_Me.Z4  =8|7$쩣g'%TؤI$Pn#7o׫~n@q4^HhLD=N*{4t)) ѫIjqUaW6"9lbMsq "Rի0l:v!"W!SfW阁yZx&/&0)t؟AѤcL4[#[xPV.>lO:VM^ -#[kcP*_RJSCj@OP<\p}fP<m#CUO\딂NjY=T̵LK'SPk "k{8O+lm<0 w&Bz ZE`Akc -_y"3@ |?A1?vLY4Rt:Mΰѝ YnzT:XղŋB\0ZkOYJkT0k!wtjʝ6(/`LDҖ7^NhJ}7·e9SI4,ҋ>DwTi-)yV)1Ӱ 1  ~> o{HHaJf!a: N:V^-T-p}dcu:4 ;{^$WΛi,ٚv9{-IN!Κh"/s\?ip F*:v]lluq@JYesiBx%lZ*guecJ'(Y%8yUeCSثZ($ڪ$~^d!| -B/`=6"{ZA/@X -H15M^d`HfbdaVP迨YT m [|r1W4Z2\cn] Cjw2}k.DAshC9բ]ARnrzݎaU -PX̞thX"|1RR4J,4R`ρXt8@ P~:9tN37~`qq0D@L&H\I=z -HEB$S]C鳺1(M_̃6I)Y 8Jx*ETK_OXT(WXtz]ly\QQ 5kkƋ, ia`TJ,GA7T җJjO3|uMW!͂40-hW/K_vEyO ~ -@tYJuti<`Y cҿd9F-+ F-,1jy)HS՘EoF -1RńIn34- =Bӌ*JDD3u?X\e +fQ-_:xaBP[ 'T̀:YP"c9FW4NQm0kHaȢE -"W& 2ɥr &xc21L)@R[* rD+pV%c@Ŏ7Gb0ePz9x'2M`@*IŔشtHY рQ P[ 0z0.Y]~ X,?tLgVX( T;ykc3M' Eg8TvN$k_|&X۳ -$` tS)@xgH71(@DH ̞F#42:Aq2Q:>H )4/!d$TA;nO9CII '=RG g)!zH&bq<:UF._VMIJ~w?G=1IiѡUls=G3@*@ZAQ{c6}/bK V_oK06{f Uw3 a{z`480WNǦu{BJT$eH`O+c:2x07{ꀗJʁqZ0ג̠F -M ҭu]NNZ;{܌!?d WglL kg@te~owvm 4ZJ0D\< II(`/%W)IFt U -^TA?+۳p£,hz|FTc[3/۞ -7k /{KL]0^3FsS6ZC=mHnBT[1e|qrpȕ$xa3tD9C2Ur^yUs\kɟ %ZO0ğ谑Rqr׭BcKLA 3r@cs iך=2܊:pO+24~ң1B2 ڀvZcba6)0*Ls,ZֽH:YU↲!.W3-A^+j/3[p4\S>?3/vu,wu?m۟n>zWJ}Â!P}i*c -})B? %ݲAx)3 S^ -Կ9<0mm:rbE8N}U>Ud-gef[k(\Uw~zb㋻$s6Kج[~EYTeI갧Ctaq/`s`IEt--|s@`^f~~8Y8,0r!9$fW"5uTrG?mћRd:%eGUZ% tmMNꊫZ65XE?\z'1EHRY^*fŇw?PaNͳ`d:lR-+'(7O愦 Y?K7d:e䗗RHYhb4wxyn6ۻyɻߥo柿/^{L_݌rۇwlQ 0tfڎv.vP -endstream -endobj - -4819 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [350.45316 328.3786 402.03214 342.0406] - /Border [0 0 0] - /Dest (subsec:component-lifecycle) - /F 4 - /StructParent 125 - /Contents (Section 3.3) ->> -endobj - -4820 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4360 0 R - /f1 4384 0 R - /f2 4366 0 R - /f3 4354 0 R - /f4 4372 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 126 - /Tabs /S - /Parent 1 0 R - /Contents 4821 0 R - /Annots [4819 0 R] ->> -endobj - -4821 0 obj -<< - /Length 5900 - /Filter /FlateDecode ->> -stream -x][s7r~rbW-4"d|@ɒTLidMS8<3gqfAƇFᣏ.ŏ/yrwW_|ۗÓ/_~>f?v|ooӯ>?_ 1< ֢ Ë.Ë/󋻋On.psWǏ㏛.[!ķB -p=(1$&A@thT?վWl%5ʦ? -89?;oL̇}`MCfsMI|33~fpWU/8 -. A6O Mw܏ 7x?0L)Y*L{zbݼnϿB}WBZCIj 1[l/NzihbmZDi 2Gɒaוy 3q/4 :AI"5ŞM+ѺidOCn6Ή=Nnz\-huj}Qy^fX3`[ 늣T,5JcXCjD]|l7Sυ뒭پGɰ&e oO>riEZf x̧G O6h0A/ͫiq*2C LיUnfc xE('g f:ùha "?ؕ+@eHzh%&!5SIAKi?SV<d3dl1}{CǙ~da55ŠY'E2$dCJg2Ujov#&`$##C]|s\+cYG-w \M{j{GJJW)0xN#GVhe&3GTMn"uK@KStvBv#G:s&=C\RԦrS@ȫORo%uˑ O~)Sj OI.,KIr;*l&#OADcr$k;PwA#@.F hudP$}gEh@mq$?ݷ,sǤ|8nhjY5aDQtI|pDQt }hEހwzsHH-:@ڦbx3՞7W>r:*KmƂm'Z#O,.젓O>&WK!'swqr>I(W -tN]"5uwښuء4`[g6,dGQ)U'<^* #/?PdX4-ܬb.bfIgzG+r)eB$(mmrycw_8| -QB,F'sH}8{{Ӑ.`)uTXE2%Tvsdt^  kL -ˍޖniE7Ɓp2aZ`զڙjEWZ1ТԶϔ7M2ӮeBLɔxqi=aK6!RZTY}ؚKѠ8|l'JiDPœv[~M^d˗y5e~|b˫g茾$ÇYCj!Ȅe]bZa=gMOά1հr#$hߗZs,x'#2gJF=?.TkT -6mrNz!]R82Yn,K{ׁБנ?p)cTUv$FQydOg q$@\\F'+'e&Pz-\%#c.ђ@:ϞjX2f:plgӰdȢCޠ xB!I6;Zj74:nKQ0(~GQǩTΡ_U2-;>Q+RE95Q{^Et+>QK T+kvvsYA7rSl;,Vʙam.Lo;E֑N%o@ؘ#ѮɑwԹ$YG'p2&6EL]Mk^Nĥ_96Vw+YP*&$u+#"\˛w1=A[[LuJ4AuS'5o(xvk 2) F@i-ܠi'fxБxm|#vbԏtct jsl/س@MhD,O@f^) Zɴ+!a$ ̺ͪ\dǑ_6*oAA,ZJ2s[2.6US e.Ik $&A.YMj+&Ϟd6ltgQ,&M |mo*FO,&ݔX貇 9RNK(rUDYZda磜UJ=\:X:;Dެrnt|VG)˞!SS6qZ^=ܯͶh_#r@tχ7$̗ %N4Y&m'Ը*%frG?nPP.:O.I}7]Ym*Oneϲ+r%7@4R}8Sbc RxLNEA: -btڷ>RZ~@D[0qf+,Wa.j$%DL'jG O 1dTE928mr'ʉsi-EqG˩9[8KSMOpm{9Io|+P1.t -R $-Em5DPY'td1r-$%~ -W,}4La%|TF}IiE-S_ʯU͸ž׵ؒЯ$ܒo&eNd%m6Evӊ!Y]:__c/˹l7eL5j0VgH|Z1ߧW]/1󂲤˘\D;uo3Rm#`R(#TP Q(Qz0ըgnr:YqR q Vr/>$kʼnftQi)=ӪF FT1#&8$ JX_qYZ}H$kוcw@6R,zX^Mٛ U wg -F[av]O8n^ -wt.gb,gh:2Y OUƂyɊy1҄ːTzȂuGZX-,8!0qU酿w3'|Uhg^6WܩVkcRu6 ɥYzvӺ)8Kɘ-e,J3!l69$ G{: jqEa -? HG`Hq@VtXk[,`W8Fn@* -Y.%!HXnXEu1=܎hNd9P +k+  -٬{r]~z`O|$™-<) 5wOOORANz9*xL|L>U }cM}ekI)Gg6+TxߴjBUG:Kb.I}N(b"yՉ|> ɏ1;4BبfN=?;ܡUhB-+)B8׵TpR~n-Q:k}=2TrO_N=nh!ؾHMAΉÆQUyBQ;1{:q*nAHזbfR~ms)jtJk}[y7fA1Kdj1]-~;"螼|Tydr ί87BϳjЉw3 -\-1@PAⴎsQ$+Y:&]+>wq."bFioke7XD6@MvaJ-%u,qM0;M ^_tbJAnub~5d1e!~(dD}8fI۟lվoUQw"[ҟ^CnzQ}@6Il#K6zbK:x0{GPy6}qdԫ4io(䳪F֯vi:LOVPG]HL<1[J\iSD(k #DήH "gEb6rzօ5ZKf|f{Lk'>礵YccQl.>Xd?]\e[]ϔ9s̴GZ,UаЂaZz9^lsاׯn_v?~'ov7?}/w}9<͛t7wdT!͓t | -endstream -endobj - -4822 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4354 0 R - /f1 4360 0 R - /f2 4366 0 R - /f3 4384 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 127 - /Parent 1 0 R - /Contents 4823 0 R ->> -endobj - -4823 0 obj -<< - /Length 7941 - /Filter /FlateDecode ->> -stream -x]Y~ׯ8EZ$ "KIgW50z=njKb^|vWo|pxë7{/^/}˷y{_e?w}OO~ϟN~}pO{u/=;'xpwxC@9D@'/޸Û>q{Oˏ=/v}툎??OفP24рx{04F|xOK *@r5@.W2&v ̧od:"YT 䄼O5!3'jnyz8 Ot - <`JW9 x:n?P(P`̓4#uluI{׿_>}=:s7"C8Z9-!E<Ā(>{ë}|/p_z˿w4btTТ͆?e牞Mm9-ZEB Z}gpd%YkA%<&U:1Xr*(WR`?OsUCx!}x!FZ!V3Gw|j_B$!D;,MĖ4F! -!f~qQgt*OMh=b&#_X^$Xi;0Ƒ?t Il$Y4S;6bUpoTĹ>59@8qvc+dpHӒ 2>n0rY@"3 -d QBYCj*=Zk -Ca+59x>O63l?Ϫq ~4w_ -v]?pߙyZ|nzo~`v2t]u {kF_$caDŽX1RۇU}r:|K B5VoZ̅5jļQm_$wa5_՜[zAvU *go9*F][&5Dy-|M{"{(sҞiO6T=ES,+LoO'zO'2EӞ|N>ҞiO RujQJnQt0ΣJ/8r^!d9hĞzWC}?uMoaԅJxs+牸L|@n /_M֖oT!7O_q+4+ur]>ɫ%EJHd%3P&n^u_y|uW.*v[~&_<6L^|?NO@~;7SPC)׭& IpI\!8~9Ql --\Yz4zn\ly")c>t~QVWi,HeɘVt^>DbhEإOWk^ըK3)S(bԢid9~)2a1:|הfsQRS(}%_pfx?4KN~>@m[X=[WFdNOf`Fժ3cJ~=*D* f=VX 1#jz¢Cxa} -9?1"Fyrxȫ2%sqĺ}3| m"5lKcEK \K2o5XU0mMJՋ:B/E'PMzyqqСC~W_'fSΡM/iC5frTcY^%Y _U4 ՛18Q;;*^ DPmGVo!;Neg~I_%AB`B:)a#\B"8 -@dR֝{.!vٹS}ԑPSSɒeW"˔A㮄7}B?9*rvjGdSTo#p)U/>o;)leMA^2LR\̩cbQ.k爀)HӫjQ˹yzDxށOi>`81wrQW'jgfp7xtqWG)A )Ο@İq7r*S1~Mc@VS⊋_yU Af܇\g -. LEh *GP[ BoDr ɷbT0 6`a`+oIS  -U<Z7: #ȡ^C%u< -S+5HH;gC}:A HO05AymW#F7]ji5Pr|ү["oy^rasW9C1Vc+H@j%Lě@`;5620 yo7^S_FZ1\v_S~ك+ -gHGQLj55vZkH_)A7`%ZRj%K^Nf@v%SyziEZrM -j3Mz?kRP; VXzkRpq^am XIA{,'+~9)h] IA[+ -8DjYK/)hIA{KZK -ᜪ.vEw%++)G,Gb2ׄiJ"L4H\萬ڞ1@.a󥦗ŤHk0rӐ^"vn'C^|/5*/8#(/=Z/BmoHz\kP#k6դ.2=_5({¸jE 1XTaHoeːZ¥Iq+߼~) 򯗽.Pɛ_zK޸x+S"A/_r 8SA%.CPjM '%F-ԪVLRYX´WW;dknڕNwb.LԂAɼPUe05!ĔVlp!pDR V2` -PU5^U:@W)2+"R 34n'AjɊx$ PbEԀjɊ+XlՊ@UFxKVzA՚KK.),#k=~~S=f'=b^c*F.v{)J0w`q,3h7fazkՎXj%O+& =cuyצXA+>x,'D{ziU봤I~_pLʔ +6  ^rKƷG6PgڻnG)e|AjzW(}ݟxHK{tCm}ժҤvz+%|"]9'w+|ng/'ūm]%4Mlj0+7-7,mzÖ<WSnq}8խJTG^ʷK݅vP:++_ >TK'q뼱&{9jvHz[}>׋zsq2/e)۹,P1<&T9}'g~lnvIUw  ufW׿ڲ;کmSiwDsMڅM44lsY<#FsSix0Z^ U/:!AsK -UH8WbVӡ3F?fV)7M.(K6'^!zrl==U*\NkcB.yq ;.فgCf_ߴ0 ^:-к8,ZjGsScA\+?&n-gz8y{wotQ9IV4Xw9,Q0S?NZ_~nIZ}D3!>u{t~H4b6*<~(H Hwr¼FrcrI)X twaԾ `?٫jK\g9G@dš#[ȺF %6W`xO -M";aZD"'U\~T!${pGUiz~%K;.V3dLL+ȈyA Nsdn`G%p]K;, VQ, r*PX *Xf UK"1p Z}"TLK K|zsyT1- :q7hԔVȝPfBVӈyHơg&yv2AZCg=nVjCJ\헖6A-{\dp-aa yb^M!~l"fiySLbGfe(2P*jVNNպ,d`?*J+b_a/ݞ 8>.Ku/?\[ xC!Ǻsf:$JjtgB –0Ѱhu ֎;~64]36o[So);pAxý- -f#AHjiT1AͤMx̞ך\k,^.b41>_JDSbm,:fi t'1q UN ,?ҪfӢ%˳!!@p\@橛_2Ho⸴ĒPÀ"`G'|[2MPQG+RA1ݐC;^T"S;fW],@@@$~8Ƕ -LXB.ձ~~t*U6*&_S0kh(v -Ҩ`#}MA1ɬ1M›{iżh@c),c)|D0BG$ )b2im*_3B$f ? -K L̎VQ!r:8oC2AH;lf Dqm17` sG۠@\a`0+ n -SC -;Gda+\P*%g^&#l:4d$%[v| zxtct4p9.xThӘ2G>|~Sa8%pGmS3.;w=mr)sB -mtsJ9sGZa9MVGj 2NW -jLA0QA,T,O --9]b1#(WYu6kIYcYG7须"kZE(QdZ jVUY|)<>"W6馡ͦȮ( V[&:ss 9C&:G`p.ʪ g߾{Dg7?~x^|O/_{;5c9G}C(0 -endstream -endobj - -4824 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [461.69614 570.07336 513.27515 583.7354] - /Border [0 0 0] - /Dest (subsec:capabilities) - /F 4 - /StructParent 128 - /Contents (Section 5.2) ->> -endobj - -4825 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 454.5324 122.445145 468.1944] - /Border [0 0 0] - /Dest (subsec:context-paradigm) - /F 4 - /StructParent 129 - /Contents (Section 3.4) ->> -endobj - -4826 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [201.28658 225.36938 241.48993 239.03137] - /Border [0 0 0] - /Dest 4497 0 R - /F 4 - /StructParent 130 - /Contents (Figure 1) ->> -endobj - -4827 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [495.9211 82.57959 522.7611 96.24158] - /Border [0 0 0] - /Dest 4498 0 R - /F 4 - /StructParent 131 - /Contents (Definition 5) ->> -endobj - -4828 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [522.7611 82.57959 526.4241 96.24158] - /Border [0 0 0] - /Dest 4498 0 R - /F 4 - /StructParent 132 - /Contents (Definition 5) ->> -endobj - -4829 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4384 0 R - /f1 4360 0 R - /f2 4354 0 R - /f3 4366 0 R - /f4 4378 0 R - /f5 4372 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 133 - /Tabs /S - /Parent 1 0 R - /Contents 4830 0 R - /Annots [4824 0 R 4825 0 R 4826 0 R 4827 0 R 4828 0 R] ->> -endobj - -4830 0 obj -<< - /Length 7277 - /Filter /FlateDecode ->> -stream -x=]Fn+Hj48%+˹D~X%kUj lirɻKhw?}v{۫w]Oo~}ߧ_~}=ӛܦ_Տ?\f'ݧ=}_n_{:uS` (( -V~{zvf髝^UWv;wJ{}ϻ_|PGʒkAh2W- 9lg4X膃` ^E6tA xρV[ <0J+'eRoq 7qjk -Ǯt("D\e(Zj.~#N!g] %NI*z3#8g}!N퀨 xNR_! 6zS{"/{ "k;5_79_ƔS!4lhСwZ1$4Я_kM2.W)\ֈ5"(xqCZfRoĉ-,C'q3+ZHe_bHH˺ڀzRu~uR)F,Yv,S,Fe ۳DZrL}x փʺx9AZϩN_|pw%[.{Y',(%Y7;5ƧʇgpAkry!G`[=S T =_c)V*V_r=_c U/ea<낇ԧ '( -.gh!ՋEJ~l/%a*7c#@p~l/e)7`K% ɂq/!#@ m_8GƁ;/gI΋lzB]_uFh7~f^WcnDo>>n?:/v=Ty/KeU֨|Tˋ6oųygtSzF+p>s[s8ݞl5)PV8D̓!Chw~Br+v?4 -ll@g1l-lOIƯ!g[REl!ېe[N#vNj?(-^[NacNL2z@A\USK1zV?Pjp-BIemFA<=6qm*C'%x (HuZiI naUem/%T:jTJ!߫2ԺRhAUe(ir&߮rY6 -f\H%V*f.!e(fJE3밅CL+|j^e3WK3ġT9sḃf@3δRHA$]2lͨ|zdCc6A+& k"`oA $﵉ԦuͶkmKGd[mF6?ksicf[mF6?k3iD@ ²6o*nۆhr6'@1K 濑}4paKE'ȶFv6ېB -o-l; 4mg_fCo;+E1)9YR [=l E .ͷBсkl[iͺ ~Ԍ3k B>4S.Wߪp1Î. |; x܉g\ ipz[+ %YT';:_l1|m.&칿Ϧ>ᱵ6巽Ͷ:ms1f{|j0)c]L@P^gFZee[]LT@z?b"*s˓mv11MFm?vBmWlËU.u7@NYTҗM/943&5}-|;JHӒ|=TTNn[}>s2;/u&JXO*qϯ #|daY()g˶ io RUA~admHב<86~}-4h́Jc-4۽:VcH.T#)0$ ! 3fKjL80zn9=hP:@!oT@֣n8orb&O<VY'mZY%xpu=D۴b* ?I+Y>&ͥJƢE2@MH]ZcT$oBOiM+;wel7j^+K -eg;iX|Q\>"Tlbh81hK]C|t ACŘw8j#a Q -j}5c} NI449t*X=ɖ3)۾NLfT|(Hd]<3р -;tAN;eHF<;@}@ynv} EFM:Hu}*d-9Sm;x4JKQUCSs'Qƃ>u'1$p7}Z}BR -US {@?QsPQs(Fkr-Cq!Q޴دFw'M]2L_\\g'*qgrc{<'hwD.9P+cU܇XT;|Y8C2cf;0nJGGL8GꦂEf!gŮn3_h*n4ۨoр&#Ͷ[IZ+vtm}PŦ!l#c:kά\,)QʈjQdOg4iX<V3?H攐;,&N1*7ELHGo'BxOM-s:ψG;æbQ_^/> }uZWrx^D4*f 3xd{UK+2tjz4Wa3@UAsG*":H[LlCv珝Ӓ2]\I|k"y|ʊ@{}PFRñ{1 Qֈzq>6um;4{vQG)䊌C Z%m0* `JI(gOTsP 3 7&=;3sL n;{| HS0f5QaGI%(^N G79|i;-h) bKY" qb(d{>\FC'+>3=:UF`麼'ń9ZR9aDz94'+t yfh?g0'qCqwa[x@ЇaeRr!'GL͏<(uP~;6^/Ljm42A]:pKN\!8Cj""@˰>8Gkž,&9-~]w95ɻ}wϳWh%'.B)N3! Yc.j1_ʙ;0xx-b9~{R8?A_pw /5[WvO۴#Zq-3- `!I3[иpYS^N< -VN)Z1mYĽk&N2'@!Dx0ajnFbfnPJqmbBPVmvףE-he>"iHDA ҿUoeD -x}`n0 :VT+wqdU&U,凫q]Ϗ`NC̎ou/Rt,O.vvNVHF -F"{W|H7'x۲"|BҞ# 5]CcߊNۻ~r>KПj`4`͂t,0O=v`=R`|KM19Y,l!ضT1=0QhL -{̀#Kc ,;l]hm3b9;m`i0EVD60t(UY̠:TZD,.q0TI- 6MBuoG5`#`HOs_:\.gܰNq'B:0 .;7FP|ag - n0AfNM{ *v/Afm:]m0>O/۠O\FJ&4搼x,O&}m2d ^N+C}iO} -zvpꦤ4n,L\D2LTH#|}NFA+mA<+٩؈J9[.=;uʐkm]GƂaɎFRɘ* -TAckX3~t xYrxm6}mNGl0>CVvW:&<{,,!j?ԁ%2&WTsbL2 Wbr#|]wGҋh'lUF礁^1uLOc#}@&{1U@ XGzq`kA|gy.Y 勞HYa8'P%tj}* ssd̻"*#]CL=FYE;,0]5ȑKQ9YU7:nu`5L; 3b) Ne6r#3BU .D+f+<сW-M%)4) --ڰ$2oH;i=14yU_!T"-N/C4MfMs9K[Җ?j̚Pq^K ?Y Du PF\VۗR@/)v{]R` ){[R`W¯qooTCpG)0y^l)y^6c^$ѩm)fxt`X5O-k|V4iM}-Y}.O,=(%O:bSxmnVյ^!-ܮxkۥD'א"Eb0a)‡mg+'Nyn$˚B(d͝ -A57{IQs ʶeNMDR g/4QΪCiL,t!?6{v>R{*o{aT"Y56_M6;wcslۉU{v"vˉ1|m“]{ XNl˾*&O}CiĄΆ㍖tgf;ytmVXX[MtUՑ6ȃ4->|SnyP8#!׼QZګ1/Q-޼Pzv\*n؊Mh xj o6?yZ6wY&_vrZՋw_/`Pd^"sfTqj:&ykv82j]pŭwip=p^ 0]ogw?>}ͷApC5cN绗Ͽٙ?қvveRA:p AP6 -w;*&ٍv -5ׄ^@jAݱsw4:زwETuigZpL۳]Ͻ -^.4(tSD;J/K[6lAvfHeaEФmoFB"ݞ.DЦ -Զ%B:xx`;N/?ưw.!KgtfOOO5UUkL2nbI/A}v.vz;W,`o:5a|꣍eYΒO/?|Z"߭^HfJ1:F[53udf?8绨`]{N4 4 Btlkl9^1 -ɵmKYLlß\E~g;vD0Fkwټ|vI_.^LkO7scRK'hpk;m&ڶOQ f$ΥGb!\'(4!bLIX&3è6 &OV_0 ='zGS/!7{K˩,Sg>*-OTTGO>@pJV=iQx81fܒ?;!G{*5_""`H/"u>Oo~}O}뻿{wonӯ^?ǟo~~mZQ.6N; -endstream -endobj - -4831 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 746.2134 101.63025 759.87537] - /Border [0 0 0] - /Dest 4498 0 R - /F 4 - /StructParent 134 - /Contents (Definition 5) ->> -endobj - -4832 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [426.6189 732.5514 483.94568 746.2134] - /Border [0 0 0] - /Dest 4499 0 R - /F 4 - /StructParent 135 - /Contents (Definition 7) ->> -endobj - -4833 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [173.22722 657.4414 184.22722 671.1034] - /Border [0 0 0] - /Dest 4500 0 R - /F 4 - /StructParent 136 - /Contents (40) ->> -endobj - -4834 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [260.59808 453.1714 318.8676 466.8334] - /Border [0 0 0] - /Dest 4499 0 R - /F 4 - /StructParent 137 - /Contents (Definition 7) ->> -endobj - -4835 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [118.39714 339.1854 178.22614 352.8474] - /Border [0 0 0] - /Dest (subsubsec:eff-composition) - /F 4 - /StructParent 138 - /Contents (Section 3.1.2) ->> -endobj - -4836 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4360 0 R - /f1 4384 0 R - /f2 4366 0 R - /f3 4378 0 R - /f4 4354 0 R - /f5 4372 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 139 - /Tabs /S - /Parent 1 0 R - /Contents 4837 0 R - /Annots [4831 0 R 4832 0 R 4833 0 R 4834 0 R 4835 0 R] ->> -endobj - -4837 0 obj -<< - /Length 7328 - /Filter /FlateDecode ->> -stream -x]Y~h-%#yPȡ[r>&eyCx>Bmh4êB"3HG?yqO6=>||۟+߾O7Ͽ|ʟ^l~'~O|O__?ܼxx n6/ޜ^.?^7EOo%Ef}y'x;rR('$W!=̩9n>짅hcMBp-v O{v|wv[y.GkjL"~ -4NЃpУ[[r>ִ 仇, -4N 65`м(ɥ(0%G$1Cܡ7kAb766ػ6 -η[[݆eaMޡe+t|SZkRfl)s4L!ˑ<T=&:sQw'f?<$Af7y,{چ}bO??;CY ":G:6~sq8ylп(WN ƖwCxpU@sEBd:ΗFW:4d/z]~+12"#QS9s(J>Bb[cyv QM,6\ӓ0̓L#Ӣ 6q*o(盻M8|yq}~3Kymvn/?A|&iY F褥͢#Cv/oZx_i'Osޒ]G [RúKn#2;{c9WfwZ>KO o.pqszp"\"[)l9 #84GS>/+:T}hTϜx:|K+1;ӘɎ>TglN 6\|2ifOlQ ZF\Bt@ܕq;*5` D i@L$gzjE%2P"5 8->J##B$ "VX{j]Uk129nvz da1MUgBgYNOp+4sZj. I2D@JL=LRV`9X!1BJM 23>QtcσIKsZ^BD6ބh, - ṞQu~^+tMPr+єasjdJ3f8_ȋB[QhKHII,NFGu"`'GfX^l=#E Ǔ¥M< p__9{-}NMj$I BZT}$q`$m5D=s7G鿞ӕkH2NQ*g Zo9ӪRI4jEX^R]9sJ=[ݣtմzr]y%6s's˩be UӸfDé. i AhQ#ӚѲgXʒj~cZԢ5LipĐK9*G dEXԪUszsuV$=Ygߓ-!U3βE$07dG -u1Kډˑ'Ye6ǘ&dHb?aq!P2DHAS#9`l]pSowXcƤ8.mfk;]=lx580Rjez -g*%74"A`l/f]L%`obϣf]mr,UxvU_:)|1j K&_|E|5T\VQ%g%Ҟ.n )jlѫ},lWSX[\֬k|RMD >8R#`r;Y\!u0&6,T O>4v)5"8 ÷dUs;bVK}Ԛ=0?%h2x?veֶ34wA+^;k0[2 U03yĐig*j&C)qHlҪ1V7KH Re%۴³"W;+<Nۮي>҇=' MD"ήO;'r"(L.+{Ix&39ݞŲ?>Atƕئ{&Z[#p / e*i͓^tK]m!Ф"6%/k 7~ pfo -br?WPXʮ֫Y_?mjV(i1i ˘+,]=qoMΨ{U>@7[:5P!ʚ+gZëy*$=j秆vf5GD;.,dVsT {xsj2obVCdu- -5Ɛ}-v9/!19Ls7]^_ |@__UW*[1WM_ikp UC1kBfĒPQ y%Q桅PA[lJ]tyҐ{]0םa9> AAE\؆j{<0T8<`'>ppPz=srCnO9utC|= ÐcPviJI )eYT_ B6|S}$`0` Fu z2t97b;ѕ8}|Knuc9:|KJ8lG|)SgPqntkגh2@*d@@Uj;"祺 -M.Ƙm18%)/#K1!@ͩ`.9q:U&&cpio,P9ȍB}/Lrp F%PR׺Aǂ/e-e`F'6 -LQhǐT0MDBrֺ :vcRH ܍tA1hEe0} -SYԓx@VևD=j8*Zfxc!05q_V3)-`xye\2NYlQqϪi))k25fi&"x -[1}n^<كN%vnZ8|ѾYk`ݮ侻pۍ۲g > -*u-i%b2#"-s=igղ#O&N5Ŕ2Z|NZjɜĄ) ee -vsmrgf\/bZnO?CU `ʪQr|{j)Yj&cT{]ha{lkzJ#$CxE؅.4TR `ʑGCf̔[gtm hW*O:Q4K}̛D)aytKIC_jͮ#/_ t}\eŢW5rI0}Rj_TRͳ1\Z65*J)Fr EؼLZur{|sTA2"m_T3-3*Ӱ/kٵxv^k&}{Mf~?{T+89D߯bǣo=xyV,w[B63v6kԮ31?AJH@bCH/9zk*x2Z:x"0=}5'GEVs\^w*kCL˧LҢ]>!pC (JMՂ L_,,-!=7[m_v Su=^ڙ*8QLio6tǝ$ -ry%$NiŞtX:ibIjj[G3o7fodV"v_uSiԱ-gh( lޫ=jU-'Ou!R̜l^Чy RE3D&]>>,ML/RstI 9:ςXNwvjq7poGpMo%c)=ӦNᅩ&x}uԋXQsG׳2դ= -V (oxȜ@W -Ӎ@Npjn'O_~s9"~=Ƙk?es6 bJGS/XnP5A}Fw{_N]7,;m鹁se*$+,*@s.]ߖĜrZ_ *Q.]06elf8msm9_XVMB[V'KIR5A4[g hՠ+EMSS*-#7X(zZTB4u?LHq7Y '5.}xuPJ5]A@IQs[4_ʸooRtx@oYS^jKZH*p< s !rOǠaU񹓆rgƅ 1yyو klev"ìb9mw]^MسJEd[U mQ)xL!/ݳi̺EC0frXkع1~HosD Z^Qzјxa/PߗிaPB(7 @+U -1mr#Z"B\\ >t{V)P(k;( 7^x+[!V W=LZս*J[ӭV1<nuLCxpnj`!}? &4/y0د@J-z K: 7჎+YVɁg.ثR(.IA(x^n:C,^܆ :eBI@R^,AMo}\y}DzmD뢣}/ 2iUKD΁')P$!Go~[/ j)PA?X``/ pK GcT -4 -sXs=.Z ǐ\L!.孿Aٰdpq@݀j(ĕj7 P W! <VU,Ճd,O f4%Q=p"iCD JBgۣa lyDࢿ"*G%ޅ*"|7QC9>΂h*&Qc t]T $3dEQ$'`7E\#qz3Mک(BiE]%6q[ h&ѣU(bK.48~4P*LR\Ppg(:c\`RyH%\s!Ւ!uX`.#V F zzRD\ -jB=z#53XPWKsKg= *X`XOR?_vЕ~¼6 F2.`MG]PHBu-ѸKWnS4̎QҎPaO=X9r}F*~` k钾K(ÎcNl U !iHjH}X+]d -ɹ)\^ !q -\zY^P֯MߵczwIgb36 =<=g?z||Oo?ǿzo_??ۗ?xǷj$'{,ζ9i;Zc -endstream -endobj - -4838 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [468.37003 476.86942 508.41824 490.5314] - /Border [0 0 0] - /Dest 4501 0 R - /F 4 - /StructParent 140 - /Contents (Figure 2) ->> -endobj - -4839 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [297.5414 449.5454 308.5414 463.2074] - /Border [0 0 0] - /Dest 4502 0 R - /F 4 - /StructParent 141 - /Contents (41) ->> -endobj - -4840 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4390 0 R - /f1 4384 0 R - /f2 4360 0 R - /f3 4354 0 R - /f4 4366 0 R - /f5 4378 0 R - /f6 4372 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 142 - /Tabs /S - /Parent 1 0 R - /Contents 4841 0 R - /Annots [4838 0 R 4839 0 R] ->> -endobj - -4841 0 obj -<< - /Length 6945 - /Filter /FlateDecode ->> -stream -x=kqW C9`D$p@&H" u"eQ@޽ٙ驙ݞ=2nog۟^>hu޾o?wO~y=^Mz?t77O>~o>=~ˋѾwu?;uD,;27__cwv=}Wu_ o_>#"}|:!,a Z@ۏ#!2!bDH_ D2|=j-rcZVOw)?~l~=ϷO:݇4}{O4#~01AfUΐb!Z$Cu ֻ#Sj V T)P©#6J$B' -8 msU{P{בzml:۹]x[@(m~?~(+Wv<ӑX QYA^*iYFlW#v87w9wN$U7H[C/ǑcdAk]ZBt 18k*:mE<5g' B\Ӄ_CTݎыEx/ dkֿ45h!H~M2ioОugQ)/"`{Ċ 6y+.ћ˭|A.?xQupeQ=u#b:I}t/v43LO\9!Wz;j<84UB!_\3ĸjH\fOanM;z$lJc,b%n`u< U?DXAA?,S<L$B~4֔.qȎlrQ60QV5#o -Ur@?V zM u28cv< -YpV( f"xd-@m4ܲGQX@T3@7Kճ ;) $ƄץCTt$dmO?.aI]&|3kBـ;Mq %x6@~k:.-k[J5(g0~>(n -!w. ᒪQŨ ?__=G%'Qk_se;ȀLUxn5/^(Mv2Y0TNfϛLm &<9 x޿@ |Jժ*ƁqNřߪ'΂ {A HgJ"7)ƙ6TUoJU52&߁i~iZU FxntUD#>A$mO?*$ࣵ/ @aD {8Mpx%>OVT_A]/NuY˼_Z@mз{,X:|[?AfEOCaI-9yTлE:z(AW5Qz]JfR.$8NJyUJH|u!"/f^x>ruFi_284ZSԹ zݷ7Xu碀3_P^^9l8{*A<7/ P4`cbФa EX4)\1{V$㥴״gdxdA5R T xP2*c`%ZHL4ѵNFvfm6A\mp\د[,up1ph-!/+Wռ)q) oZQPCg$ԓr 9M>VI~We*% 0r\a;յ/~~o/|I?p DdET -xk4U#HSQ`i\IGѱ?d̼61bPC61!X A5'/eę7 -K=#/mL?-m0y )! 6V^<.Bk0<!.MJ1%BPKXE* "bs\CeGE,u]2hZpzƐw9njBC]8g< Ƙ\Ʀg'iJf6eW4k|,XsVxfu~ʴvJU4@ -3kQ;.+JlDq5Lhjojd ͖܌<)J }TʹVp%\<,5k =vBOuC]*\5ӿ.z!J/"O΁Hܙy{W))8p;a)FJ-uMmI_V*$Fwu5S33u aeMn -ɣB!Ds0; -i&5U >NEHm4˓|OiZ 9V!Cו?8 .vZEL.CvM&iԌ;h&"nB;(o[wp^Պ=):!T__M XkRdNܳ=/4DXHsm֟Z6%#IJbkb:eu-Y2M"Y=O`TK*9,Mŕ9WaL}Uףnz^-UgBzގbjW 1:[J%Yr8Gv AiWQHГ`M2RˤO#Nnv>Y8FՕ+܅WgW'+qf)bpF,L; Y,x@56z'jͼ@V ɪ^Mf\tMzt>\M&CgRNwݳO37;aGCwJp -Dؽޥl":L%1xk?k rDw} -VIF5@g`GS)؆ Ӗ(qX%Z[zMX{גl[ 'b"l*n$Q Xk -᝴DJ'u+ -W#p P*}8U,r{#8لbC v)Quz7||e%몈A.a+sG(Q -:`.LyB`ψ zqL40Tb hVNdW"͘ ~9C !ثJ@4 -Hy\0 -as; { ȀH -/؏ jx=j/~$;8 '"6Ąd -AR'=+-z^ .DvI`GЇT)8 2ޙ82Gр.դO0v&1~?{zʖTxt*%{$h̸:zqvG"ٱԯ_{WT^đKdb~Ӂ$"/id/c[Z,`.VVxoELEQD,3Y Hd C`' "K-]%[EYK}Ȉ>R]$:&>>C#N9>\%䷌*"Kmi"I=$.28pΛ!p([Nßë~mjO)`|ۢh#X=n߁E0їkLY1{azTuR% FQ?(YJE; 6YM5I!T7S|mZơrfN? h*믐fOv<Tf/g -QCcZ`m^u:A: -؞oլx"U4#B., T~xv^nB AE*rFy5pHNY{KpJ<uLϾxek!>2tY'= Gf >+-أFQsBkRccct-Rbg%S3? -U'tggWY9w[) &"ON}=iXWCGmwtTowT%Ij,eVUoHh_dS22D*ff"2f9ZkKd#Tuz -C'۩Ιw\œu{zL]ls5 -: S j$t$`BM -^`Oz]1i7Y&r,L^mR{+J3 Rj{@&dua^%gniF -e>0銥3c.űZRٱ>e=jd_$bnU\d(5d"U!6A#UDiQ[t$,/I}RԤ."ip4z>:+fQ Dn0 -r6]yOگ3p)u' -:MJ52H[PVv&ݒsRf+ -Նs֧a{A Iy//>}\%QC!"ԾQ:Xi1@6HچӦn9&6eutDT1.MEL6/bXm9X?ڪɪ).5eߩL]HՖ?I 0R/l+kҘ$ L m@ @p7az>)n50WR@J6Բ[D@#s-(PjPDUFLȜ+~PQ}n@dmfD)*1Р\cI,Wm^}3ɑ[Y8sswnӪf6J]xIqeU@Ij?ً__7n&X,϶ƥ`r_$M!gAQUdp$^ת7UGgk/Vmz"7*֙P8mUfM`&f'a$ pGUwht`8;" WDznEqp$솃p-Xf7oVhݥ%InUeCt%g5"іoF@ZSibsO+T)=QTg59UK՛FY/z"Ֆl B FQ^B`Y@&*s>X2RB˔[wV)N"Y\FV}im%B9]7( xطk"X>_Q`WEBf_f%520;9&>54I0/y&ʸ,-ÝkNwqy -gwz+Wr9 - 0/] -aCSY?mSr^ 1O qhڥdKpv~ثƜEsO\HyjHjlpy^xf=)L=ՀD AF=`V.>V;e`-n/*ȴŵ# x)r ZJ/Y~#F:P> -endobj - -4843 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [467.11914 178.77362 506.78516 192.43561] - /Border [0 0 0] - /Dest 4504 0 R - /F 4 - /StructParent 144 - /Contents (Figure 4) ->> -endobj - -4844 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4360 0 R - /f1 4366 0 R - /f2 4384 0 R - /f3 4378 0 R - /f4 4372 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 145 - /Tabs /S - /Parent 1 0 R - /Contents 4845 0 R - /Annots [4842 0 R 4843 0 R] ->> -endobj - -4845 0 obj -<< - /Length 5807 - /Filter /FlateDecode ->> -stream -x=]7n+g;u"GI*wuvҾٮz-NI+go}uS Mrgz;"<~zۇ6]O~y|W/竛^ǯ绛m<}|ŗ7_rs;Q(kIwN`uwvۿnuׯǗ뷛o>EƫD{= -mv~I+mQ:2ç~h& w% |~H>Ri̲8NE{]wכ9oݕ xd[q?Cw0U|Y@Qq$> s~1.JWݣ) ͹gnǰMV|Jܖ"vqʦ-:r!S3 =$&鷽Jb.1VN0-BF1^v^u[n$4{2S ބ2tn*fz+߃7V ި@@+  `n5PNyĆ2i^^LwT eO co% 6Sѝx4FJIjګ((Y\BVQB)?ERH5x;G+Iu`4;%QLOۻ|Q›:0S (߭TٿŻS_[PAEz<ó'e,`/=K>|Ϣ;kIiv}tGmS|IiE`U u%]yy<ӒFr`zU$EP_ $~^-J=ӾhQy+eV^z.u()_I1v|o$gЃо*$ Oxnkyu쫌/ɼ`i}90$Ajua$Z(f:^x!Q(Z%e92q8y1?$K>J RZJ%bA+мn'Fk8!4xMZ##5b`),͏iK9Mc_uj<')1-GjMVYW WiVHOFXV~+:FNleo 9 3XMQ,Us*\N[㑙tScqy^HihN $[4qThbU3+GTc#x NoS:=R5P;PX35/=5eL>=5wIL@׈$1UdIN2M<")X Uo͎LUe"' P-)>VQx2_ځ5ht/ 龤d$ѢE Y͏2 4ju]Vfh^)+JO %-kE\'?DZ9@e"tƚȉ'}Ɓsw]d#7t-x"_a1&:4:~q?.eѪf|CXbj?u9UvMODXY5]hTp39u5V -CIqXVMNL.JCy>?yti?HKօ [G0HN„y6>̀!"0<nؓA''ƳԊ_>_= 25R)J\a z*(@pp>;-9ʀGyy#E\ )>(*̲Dt7 HDG.Ě_tijG0Wa;rڳ/+ :m:Q/7vu/ݗq -;Thnpo6/<ۤlǓ7Xs19gG앱ʺn{PKt Y)m\G`ɑ#!`awۀӀtP`!U/Ru8x !eu =mT6A6^ A c!Fe4h|EG6F b.7E༵?l]M`;CX*xV8\ hڙ<Vs5ÛPU L?pu4kbSmkjX/.7x"1/DbgfDd}L-Q8T`83Wcb4Tq1%CX2>J0dՙ aQϬ_U4eM~9TcATV7q*뛵PU8TT8aY'U :g4hU: -jS9b;+ĶvgeY8bWǿgCbS.ڈs~Vkܟ~]N賻6rwsAFn`N^طMᲢy|.k;7\T5gwnk.bӪs -΍*k;7r.e١:R T:b ?'<;TPY <E9m=;T7YYԈ]*( 8TEبb_ PW8b -Fi+٠pVnp.b4v$8-iEPu:Gl;JA^ D]L Be&D핎{\¡wv!zw/D_T=C^ 1,iwɓ![!jT9F Џ=ۗfLo~zM7[#0PѱZMąAkr1t8bK|3c8BUn JK憮䟕TL>Ka"nOPgjfLJ%rJ/vFsl*akm2Ty^cV~m֬uVE>^Bjn^a@:-y߄XZ8ҫj3vH`5UN+eY$8N}y -gxeu꟥.K!jԸ)Nf]]( ,"t쏨"P)6FXYr9eU3s~luSispb,Ys45Mg]&lV&W| -ݰ6Mh^cҞ+32sT5u< 0%PD&e$EԺNqgiBH6r:mt'71>Ĉb O>b%6EhHUX:%˟n4v]vUpbFj-OIlN6LZ/'EoV+m4UKl M r@ ֊Ӧ=m,>$=5]eqPwZH\5Gwʋ>ѩEHϟ]@aA]˺adq,q@"}5~9-/^_m~z$ŬC0W_|T&¡;Y(Ad:sPڧĦCxЯǴװODqG7[|v;DGI&Jի6瞵OJ1Q<'XU1tRo4^K^^ Gah2CDd1&,6drx%cd71vOZDF Օ-g7^\KzΞeIY-Cd\a486`#?/)C'al1#,`ɌGj7t_xӸxy|܂!ٙ[kaf,C|ђ|~ZnߎbQcqxAAl&NK8j- GGUqGdJv`B!DN9݅]<ޓ߿gXOoRߠƮ* -󜞤VD&}IB"N۫ Kr\ӌw%J:i ges,(2R9L;or^mܟNȩ؀̞m\Ե{%/sq]l&^&ƋCHX6"wQDžBCb]t1u \[j>vw -'V1@퉨{@sto=-jO8$_yo-j_=ܮV@`m7DB7cT6ؓ$ovڱ7o _#TTJbCGOl8A>t!y9_<ߋ${2\-A::^Gπ>d2ҭ*kIbQxzYƩz"&2%^LMV NE^ %xەJys(/a=5VAQ89:;cЂ1i lo{x7{xx_//޽{xu~ǟn~~w'v%}9m&SVGM O4 -endstream -endobj - -4846 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [213.19614 398.77203 265.11087 412.43402] - /Border [0 0 0] - /Dest (subsec:component-lifecycle) - /F 4 - /StructParent 146 - /Contents (Section 3.3) ->> -endobj - -4847 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [249.16646 313.135 300.0526 326.797] - /Border [0 0 0] - /Dest (subsec:revertible-effects) - /F 4 - /StructParent 147 - /Contents (Section 3.1) ->> -endobj - -4848 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - /c1 4403 0 R - >> - /Font << - /f0 4378 0 R - /f1 4396 0 R - /f2 4360 0 R - /f3 4354 0 R - /f4 4384 0 R - /f5 4372 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 148 - /Tabs /S - /Parent 1 0 R - /Contents 4849 0 R - /Annots [4846 0 R 4847 0 R] ->> -endobj - -4849 0 obj -<< - /Length 5170 - /Filter /FlateDecode ->> -stream -x]ݓ7nU]KHe*j-JI+eo\)L&N*v # x~]\=onySO?^zOoo>t}}}e绯Z|l.o! RխlIalv~w1͇lPgЃ/M6WV$/ Cy_%l>  VJT@xD)&5(U£NS {4$4O )u`VEɃYgS/-FQs-yW6VګAaX2xO~zbkE q'jaIFaHM7:ràZP$+(; fqC@WCW|5P pu;麃R]ct X e Cy{^YޑCpHL AN_Yf0CfJѭʯ~tTr0N|l)*v*u-qC Y#^@' G4z)ȢV>(g* &B+uPp(ΊWl[e|]I`Zj P ۿ.%x#]ۻI}×tـl rΡDhv@ZI a_A}zꛐ>_vXn~y~ٺC^Z'"Ƃa恋Ϯw]ko>%|%I>iN6yNˋ?. -"#zr$9mNʈZO@_ q(ZU35 A"O ' N'I3$1e(,J3 $Gz.DA(n3J1Rob iJA|#Nj)R-j1'4<'64E%{KE#^Ij{| 9% ;<[նV]7Ս]_쐠5[4d eA%Rb]V9X!DC|s7%ÇFdJYp"}V -%-a/.n޽~RQ]4pl_>eNj(oɴOAw,sOkt-K C}gC6z5[˖%R=GBwn垘vf&J!a<IeLB9ۘ,'a_LN -cF3QϹv -IHmr(A4t"V30. {f + 濔z`q_e AN`%'e+g ha%jXF?2u5ǓpyϯZZCohTBj!GТidHh6p7Z<(jřv@h7-[Y6ʐ t._&5vzm. -!iB)we֏Jފ  -Li$ A䘋RPA!m6(Pk -?~B6dZ!Dž\B['3VGkbKuJ:eAWZfX_ 8ƯLl,K1GOOC/]BRMA~V{HXPPRHP<{?c 4 MbEbFu -68HG3>3,i\N7Ztv#=GM3~T==_1at4]4g:loVU (qM4 gj<7&lz:n$ŚgfJ,G)O\ґA6[jqjDv7pԧ@uU^.jҜ9oB *cj%KM>a.e=08d4qjԲN_XwɁM9 -iJh?i)q#. YaIև[!h.)E,3iJ:%Z,G ψ\!ڊ'X Xi<4MbB-uHuvRS.~15U9T@]/F-q ͒5U V\ "(Tp1h(m)Ƨ$[xSփlqrU’"뽃t.o)+"sIg=7rN%Y"nP"30eJn^蝡RS ,xIdH%7hdNjG^h󮪭s jܟ|:+sn\1`M$Yߏ -V{- Zo3oTN9 NYO>wo|v&pg}%Ox#ƌk C4J;RzF:Ĥp?YJ8AH(%öV{9Tw"v&n`D"іe:9(* u &`5e*]4wZ";{a8aֿ0 *$7S% I) Yx( %yq @͇W(Jj|XxS^1lCՂN<>j_0N[̼&"m)^^\,x,%alp'IHMG,O27yKHPޭP76T{3xwҲl`5b@8~~fֈey[! s:}*8)F4+ΪjC^ؘ*+Z>7х59ŜKrQc930ƣ#|ԇ,S͕nLqn] -l;TBk_T!'Z(bJh)|4o"Q -dSł7wJ [!6ôrDhg-bRi4Zhe1H*E@"+ٟIG>$zF:i((CpHzs0#8Amcr4|!S?[}2IaS3eƖ%ҡ + 9r"= CɽIٱ*ʇj׳t@MR -5E"y@BZ e6W~ >g#m4ðոBZOU{>[pD[Ra Yzp0W$ H#ARw%Ш6!mN%R{T4j ޜԡJ8 XABWtL~Rq,>v_'x&\l4`rYmtZ qHZɁ#>8rofa"P} a)Hi(fH'6ƛ$MlfA0[2p.Ze3+uWU,{b{sі۽Ź2[u"zYHrg)4- ƭu{ IJ{)ٲR't[T,_}@6;CگcbR\y<[YuE_ gbdq+!lQH:8Hcpݶkݤen?ȴd&-.2(EƮ @rpSm׆BQ Y}6wWB!q`Ƶecg(Uu;VfW.dָ\R`oR!v"M%؉ӶꄂjXxdGD +νNfUOG$qǹ'O'O4K lPEk^ -Vզ> $MSc8Ouc|~@TMV6tj؋ **YIV{k -CmAo5!YU}#A9I`w[{٫: iaY#e JQ-u.mĻJÔfyep.T̵H54)0gU-[}npd9RQX% -ܹ%$v\]-#xQ}foLlªaǚU7E&:'l8'@έZd:|)5%{\wFQxf׃a*+x܅#6z' М(Oo 0Y]1;E{ZW|sơE2mkG-EpHϓ3{ %ЦM2:74Z0~D Mnح'Q^O2JBnvF[ա0Z32>m=Kj>m-1*VO)Hkkx~ g] U+wr:B܆4n{*S̷SEI!~_)0l;N+ ԾXh>qV7ۛ}> -endobj - -4851 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [107.86602 297.10602 118.86602 310.768] - /Border [0 0 0] - /Dest 4478 0 R - /F 4 - /StructParent 150 - /Contents (22) ->> -endobj - -4852 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4360 0 R - /f1 4354 0 R - /f2 4384 0 R - /f3 4366 0 R - /f4 4372 0 R - /f5 4378 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 151 - /Tabs /S - /Parent 1 0 R - /Contents 4853 0 R - /Annots [4850 0 R 4851 0 R] ->> -endobj - -4853 0 obj -<< - /Length 5365 - /Filter /FlateDecode ->> -stream -x=ks+G QSN~9ĬbEKR畏YW]n0w1@/kn_>߿w|ru//?_}?y~ǷWw~ŋ?.n~7g?^NvQ]"zllD=|q \O.dwxqNvJuwNw?_|凜Kǿ%6￑WOQ2 -eaugAnRjUbZs(8i&ig '–{ob em&c;=.1 ,:^)>G{|#Xd4/+_ 襱+ -5pMB:/t4k4k N;v=1J$l1ӛIRgY ްZT/w+)_~bA¸p4ÿVb6X*d޽ h NPGn. Ͽ _ <0%_4X*cXMi9K^xg<_1W<]2SR\HW/ʐAilD&SFғv8ʀ{efrl32f̯y{ {eL 4v,G8#RڧOrՏ',R>n…u=V_XwṄƐaslY>%ʱS\Ⱥ;n|nj`8$i/]<:F8f~.w75Zߐy(#)>ʧljOAk5Z8ɘTW 6:κM#! l:W,i Ӕc.MiфhHYC!TJvMpoq֊1֬VqW.*^&NA Tc_"Mrwt8ojw'T6H{ -w<崉|hW csu":K3dFvdfRgi:>a2%tXӵgh̥!:Mp'FDJ)H"eiŲyz%nI٬AGrwyǜgVvf íf{O;P!TyCs"XT&=\jꪗ;TH L ~an{iQvguk, IڬrE%CǵߟBdbH@1C{$=Y6+\2P4Fqo1j[jnP/tėb`6qJxg.*T$_ -DE̚ORC4XdϯOa;i͝ڒZאQ߂0Z.U kc9V=m\d35T HnqQ gFGX< Kf*N&h 9k)qGQ":F==̌V }Xz/B,f!jR7< -ay)LRj7[j](p;e-gAhT؎ Tsj T_,Ӳ8L(cUxF"IE yw2a18.aBteX֟2+CfcCɨGfc)^(`T͑[D*S0XNO&]V2RA{[P/ -Zί)SAhw~8ŠSݲ rtއ_A5#YMZ -Go!H;θkA^)8Q+[jIZ-=\0ʈ\āW Q4I3s^x)tejX#:lΕ3S n8[r#ZWuE-c vHxSpML(bb ԹÀFD4 -n@;J-iL쳿ǀ2W+A@_CGN(6Y`] 0iD47AKh{6'|Lۀ3)RGۋ˦%4h|A\z=3G4 Cω+ןrs#&s W$GYaT8IߌuZ!3ښ,wYhH)u[dA -)$5^ZVN;퍖"i$}OèVO'UN[t4M.k) I;̇dX`fYд46x\ja M)VsE$:hr#Bs W NbTH(Ifsd?OE~qR8 ڗ顠EE) - V֪gNRp̑G`ز 8XSs+o+oyDsHRS_!O"D/ժ* -l"vX7$aD#XM#8 1 \̙m5!o}.X#±0tUk O -넍:I)GVM5F(m>ejE3(p\%bUDHFގ1f$ML8'5.x-v/`|k -y9F0ʩqrxc ђ6D{NydžVM -ճxl - ,_\)Lۖ4Vo20mI\<"upEV@ýz+`7g2B -;a0 ⾬EK$A a[FJPSx)rkS;s yNX:βც=6Vҭ`J&s5"P`o8TN& -K[XF0an C{VOR|*G\Y#][6D@RAS10;0"fiaF7E#&my@5JR҇E y` L-uLeA?̻] k'N}: {1Z3əشbMY8`eVyӞI)y9xYlOSOvQ}H߸aـfQ}2B'*ɩxx|p%̞D~dqѣn+k෧)IqAtD].HO&Le4d/> -endobj - -4855 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [467.71432 582.3314 518.84344 595.9934] - /Border [0 0 0] - /Dest (subsec:reactive-coeffects) - /F 4 - /StructParent 153 - /Contents (Section 3.2) ->> -endobj - -4856 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [407.13937 469.5504 452.5994 483.2124] - /Border [0 0 0] - /Dest (sec:theory) - /F 4 - /StructParent 154 - /Contents (Section 3) ->> -endobj - -4857 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [468.31793 414.9024 519.39343 428.5644] - /Border [0 0 0] - /Dest (subsec:core-impl) - /F 4 - /StructParent 155 - /Contents (Section 4.1) ->> -endobj - -4858 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [465.84985 401.2404 519.39343 414.9024] - /Border [0 0 0] - /Dest (subsec:loader-hmr) - /F 4 - /StructParent 156 - /Contents (Section 4.2) ->> -endobj - -4859 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [213.6029 373.9164 267.18137 387.5784] - /Border [0 0 0] - /Dest (subsec:koishi) - /F 4 - /StructParent 157 - /Contents (Section 4.3) ->> -endobj - -4860 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 299.3614 107.09487 313.02338] - /Border [0 0 0] - /Dest 4505 0 R - /F 4 - /StructParent 158 - /Contents (Table 1) ->> -endobj - -4861 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [184.06622 210.58942 235.26276 224.2514] - /Border [0 0 0] - /Dest (subsec:component-lifecycle) - /F 4 - /StructParent 159 - /Contents (Section 3.3) ->> -endobj - -4862 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [218.00346 155.9414 281.07553 169.6034] - /Border [0 0 0] - /Dest 4506 0 R - /F 4 - /StructParent 160 - /Contents (Definition 25) ->> -endobj - -4863 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [489.91193 128.61737 524.4094 142.27942] - /Border [0 0 0] - /Dest 4505 0 R - /F 4 - /StructParent 161 - /Contents (Table 1) ->> -endobj - -4864 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4360 0 R - /f1 4354 0 R - /f2 4366 0 R - /f3 4378 0 R - /f4 4384 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 162 - /Tabs /S - /Parent 1 0 R - /Contents 4865 0 R - /Annots [4854 0 R 4855 0 R 4856 0 R 4857 0 R 4858 0 R 4859 0 R 4860 0 R 4861 0 R 4862 0 R 4863 0 R] ->> -endobj - -4865 0 obj -<< - /Length 5456 - /Filter /FlateDecode ->> -stream -xr_14eǫ "ۺRv|@ҤTL):}j;3@ < -I }qnj=yrug϶ۋ=;WzuwW?}ۋ훷GOv}>?:~>ELJHtݩgZ;磳+]rĻ_n>;? o>8qiL7T%&2G %6ݩ0/~t\vMA禡e>d() LGL5 ^w7#먔#E 15)ǥ8ݦtRlqRG6)TM=(o8S(Qh[s$Zu+f5ɉQ9(,18kKr"0A"O).6rEL5jA 13˹'qNfwW"tC4=~7 ؟B'>ƦZnHF'I@HL̺O G5TFA uՔZ |nP$% J Ngi=՞m:8"JQyV .0rZVSM)_d7`>~Db>]vrnI 0b[){<8 Uɷ`⩅pDdBr \4/Et5sUbfI$ǰ >:ʪ|CkvAx~'&>Cl3#}3:+j ɖA j0j)oZi2EWsXL\4&Ea3.PtGW3Η>2a-S!?뎴e37a\r@rJYDX?Q,8!`c!@ d$*%Sc`+c!>G/@3W=)2ĒJ)D3W+̌ge҅1$?ӤfH.L` -e8viA Ğ-|H:^Gfaa,G 2 uX$b@FG2j HɜTLϮ^ɋ/^p싧1mHjɢ +$~I s2- WpŌ gc=%>(~rY$p]?wpo)뽬0`5 [ j ڔk =ꆰV)i\WUi2Y̜z-29hB`\xEXv5 |{ p:O"ql<㌷g`&KB`W5KIu[`9IQ ";4`|YŎak`1FϿ]T1 Ȥ)cy?Xh<ǔpu oxTfİ7YDX`^_  WɔffPt(BQ7԰9\E(6"K U!23^C@c6N0G"8G ՀL98GvP$΋KժTCV(Y_ s&ԩ*q-cBG&R#b DIqpE{{@6[ .|LGMqI}n.P*%Et$3άvA1'tJDপdNpݧ׷ &-5DM4g I\Kҥ^}_'b1Qʮ=, h'J>]hā;&TPn ?(5vVRK,Ƞd&UW 0_8JڢP &#x`$Y - -qřGjhz -Xv8c^Q72F7#iboT kRyܠ4jObI |?OѐP1k0;X.A*UL+̻>HCn4܋%} FQHWA`Z**miОQdq=N^^=t}W6!lI4&`PHp:-*sV>O,aIuKgf**pr'8qx ۺd7ޚ {h%aE'9*1Ds&J#0 -M 7hc!K Fv+&AS*PUg 5xϬ>-[+_-X3]Lk'KaD>=e843̑KrQ=- -RQ 0S&Km'.@l 0fTQ]-G^\~)hu+N@_Nܫ j!ʻI?qk f8'\VQ ƍr ]Ѷ -)ZC*]ͨAWX4͈TPz M"R~\3i>Wӷi(<oy U\}Ri,ͨEoC -/UPSY&)mlc͠s\ ]E2!T0F*X߬a^oVPHi7;=5mMZ*pf5$ -)&tp8|FDr~NAWB:^`C`MF\JA%kS{Ip"gXGqviLΫץ' ֎dSh/}fk'Ng۾Bɐph40'v- {,d3HW=. <(R(f @ub:UtuLxΠO(sK5ٽ s[2 wVeE~5f>=d-ﵱLWe)pGQ1jI!}]dJAc, N^"l0%ȵB*qa"l8TfJ(t_I4Wqɔ_΃F]vH[ 1{+n\e_Wo$d`p%o˖] HDLenI}UI˞T[6`6}l7ska1_x͸RC0ҍ (äή(ؓ\lD9ڒ.bdPeo̩1Q-Z깪[ט CлIRMInMOC 36k)}$x&V{-Cf<V޺Ԧ!&}҇GNRSS dMEt?j/;b<4 NYٲJdG="ߝ}mGXHMό"A{n3?Tu)$oM TʯU+ŒB2掠ˑ򪈙J r.Qk]Bim}wqj;TNB~0|$NX.z}Z ̫Q3i̹IAx{3BF#?3esv3^˵ -Z^=j;L! ZжT`v>{]bqItkL:=WKgE9ͪbI#W&dt=;ZV>~%,KWG_6t%QcB.u%T{[yPr&H_=QU;=\i؄SWYB]yKLc^'G5vK>%saJg/Tf3baV,p57rJUμ:֑!ZyІ)08?Z-}? ʮ.lvX )--3J6i7# d(WQ%a;as׌a$\!ĿU0ѧgV>ֻ}ycHCzI?S>$PZ& kb/U+񂢮,H6P^ /C -%nj:Zdc{d$qmùMXեgA- sS[ةur-z3 -T[;B]Q8.G +&l6ZGv3Kpi :0yoĸh{d ^;9|ԫCua9Irk%bӣ1-L8"õ -^E; $7M@utlYz ߲K> DPkd KU;Is`a -N=bI#{: s_{[A ^=EO=K6Sm\\m0v{qݷgn}o~;{__b-ߐL(;#XƄ5xtU]4 -endstream -endobj - -4866 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [180.62326 741.2904 222.00327 753.6004] - /Border [0 0 0] - /Dest (sec:theory) - /F 4 - /StructParent 163 - /Contents (Section 3) ->> -endobj - -4867 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [463.0277 515.1334 524.4094 528.7954] - /Border [0 0 0] - /Dest (subsubsec:effect-api) - /F 4 - /StructParent 164 - /Contents (Section 4.1.1) ->> -endobj - -4868 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [464.3611 501.4714 524.4094 515.1334] - /Border [0 0 0] - /Dest (subsubsec:coeffect-api) - /F 4 - /StructParent 165 - /Contents (Section 4.1.2) ->> -endobj - -4869 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [229.18156 487.8094 288.63504 501.4714] - /Border [0 0 0] - /Dest (subsubsec:component-api) - /F 4 - /StructParent 166 - /Contents (Section 4.1.3) ->> -endobj - -4870 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 474.1474 130.69514 487.8094] - /Border [0 0 0] - /Dest (subsubsec:context-access) - /F 4 - /StructParent 167 - /Contents (Section 4.1.4) ->> -endobj - -4871 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [263.94278 415.8344 316.6733 429.4964] - /Border [0 0 0] - /Dest (subsec:revertible-effects) - /F 4 - /StructParent 168 - /Contents (Section 3.1) ->> -endobj - -4872 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [346.99957 361.1864 411.01254 374.8484] - /Border [0 0 0] - /Dest 4507 0 R - /F 4 - /StructParent 169 - /Contents (Definition 23) ->> -endobj - -4873 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [87.36614 286.07642 146.54327 299.7384] - /Border [0 0 0] - /Dest 4508 0 R - /F 4 - /StructParent 170 - /Contents (Algorithm 1) ->> -endobj - -4874 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4354 0 R - /f1 4384 0 R - /f2 4378 0 R - /f3 4360 0 R - /f4 4372 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 171 - /Tabs /S - /Parent 1 0 R - /Contents 4875 0 R - /Annots [4866 0 R 4867 0 R 4868 0 R 4869 0 R 4870 0 R 4871 0 R 4872 0 R 4873 0 R] ->> -endobj - -4875 0 obj -<< - /Length 5323 - /Filter /FlateDecode ->> -stream -x]K(ZW-97`k i[ԮLEaH7ġvܲ~]]ThR<̰{DC\=?y}|i/|}ͻ_]_5WO_~>~usonoy'<{[|vJJ)Q7/^bzwN7v; hl~]`qƂ7$?P0ƀ)\|{w'_|n tHZ#`+>=asszۏ#U%ќ~}Ps2fb#Xy?OV-!]#m _J +77[`Eh 'VT/\*E"ɧNUtFA^[QsDސ h0(n)-GLۖZH[64~N# 1ʪwR <)Q:|1#Ow0IURp@ݽn}IZlY<2Be k0H\B%{$'@ D|k]EȸzNVŷa1;ףV(j+ijcŔCmrggÁ'?I6zijy^Fks9!>07]] $9;E"5An ->(wS[ -d\t hCFnyj.pX4圠mi{<8-s -KzsՓ#޹ 0v[2;.s 12=X[Q&jtbv RfIɬ+z>+2Δ1T{kqsJ8._ĕd7Vtciw"MN+3d|^!`6%LR >Xc+^)%ǔs2y~*SXk!`JULB3jO.̰ MDՋnyU{(謯 &y`QyCkܩr3*3/&[2_&F %F TXN=z:qR -ôžhy3'QnNLtOA))gc&(:e (h Վ -=q\F-l? I6 l<\D/h,¬WM ٬@͈'qII]]ьXPU:ƺJ dѳ˟ Uâ*kJX׳mO_5A!14;h{T8 _tle``Ն`A l*0ܜ$R-sii48k1:oQT?. tEtsST{.\m61{a?KF`Z, eRyճ=qXk -VCl~0'YRKZ=11z`f:)KAHjB,6D;F*vg89 -BװG  뇱wE̜{YNO 3s#$9qy+k/Dj_#kQY{+y, Qփ&9E&F%@ bɣ +l|W*m!`z<g&D{Ӗγ yAlXhΙCLAyQS1~zd -.'HBDNh*#}#0o,f6h7X/x)wpDR OV6dK~ѠBn1 -:%ME@DSٽ3{"vRߢ$¤;`3ԙKq@N:rŜW}B-eUy5 8ACpYkLQr5!}G65B\GZ~"} ;j*ULATKt"y"4J6}{<ƈR9L-c S՛w S^ /&چő[ds')3@0ۗf+rjGx '1V*1Hmn+@keTQ!KȆN5qH?m,OKCJ6R/'͒TSɷ+*Kanؑ:ֵ@Vxkko#]tԸFU0S@0J5|o&I&_@v /ʐ>@b}J^<YЈ.72'2s+grJu^[sSaǮ'縷8 *pxl .PeS[KBo{`ycD\W%fZRr1LʖG_}|{w_^^ǯnͻ;2=S> -endobj - -4877 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [311.19995 572.0674 370.8978 585.7294] - /Border [0 0 0] - /Dest (subsubsec:lifecycle-iteration) - /F 4 - /StructParent 173 - /Contents (Section 3.3.2) ->> -endobj - -4878 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [197.09962 524.2814 261.27277 537.94336] - /Border [0 0 0] - /Dest 4510 0 R - /F 4 - /StructParent 174 - /Contents (Definition 21) ->> -endobj - -4879 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [408.45615 469.6334 468.06592 483.2954] - /Border [0 0 0] - /Dest (subsubsec:component-api) - /F 4 - /StructParent 175 - /Contents (Section 4.1.3) ->> -endobj - -4880 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [258.05804 397.6584 309.11444 411.3204] - /Border [0 0 0] - /Dest (subsec:reactive-coeffects) - /F 4 - /StructParent 176 - /Contents (Section 3.2) ->> -endobj - -4881 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [75.88214 308.8864 134.90927 322.5484] - /Border [0 0 0] - /Dest 4511 0 R - /F 4 - /StructParent 177 - /Contents (Algorithm 2) ->> -endobj - -4882 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [363.2142 220.11438 415.47824 233.77643] - /Border [0 0 0] - /Dest (subsec:revertible-effects) - /F 4 - /StructParent 178 - /Contents (Section 3.1) ->> -endobj - -4883 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [402.55 206.4524 463.17172 220.11438] - /Border [0 0 0] - /Dest 4511 0 R - /F 4 - /StructParent 179 - /Contents (Algorithm 2) ->> -endobj - -4884 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4360 0 R - /f1 4384 0 R - /f2 4354 0 R - /f3 4378 0 R - /f4 4372 0 R - /f5 4366 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 180 - /Tabs /S - /Parent 1 0 R - /Contents 4885 0 R - /Annots [4876 0 R 4877 0 R 4878 0 R 4879 0 R 4880 0 R 4881 0 R 4882 0 R 4883 0 R] ->> -endobj - -4885 0 obj -<< - /Length 6976 - /Filter /FlateDecode ->> -stream -x=]s$5i)#bx c`a޸*UR*yUR*ߙJ]vwO/?~H_~7w髗/vCO/|zO/z;թJw^ApNS筃`u^\V]owS{{o~#k1/VA5*p{;F㉇oUiEDj -^< A{h ׋8LJWN`5P;ُcOo׌ bo^v;_ѩxtzF//TVu{y{z7x⻏WJ}^|+B3@h=ljY(*>Tt~Wt|g,:mk }g˿&7br 9vy &jnO~r١:ϿY4jܑ=d\rqKt7ehc -?P抜jtO}s'2 -%D)S^O -?oE RՒ Nqo+c'?1H4H4V!Q;(d́dL5-$s":Q{dV6'BFjq, U:ҜbDMu%tK8P,MP;pj5Jyب4<[dl}'g(3YI %XKeF='5v6UU#/2=KxXX}B|Qnz * -3!2ф=™"qY}!W(Af^YvX\h:24$!ͰkCĺZ1-cK^[0[ꉋklගo"Q\ {82vkc~T5CHEW٥b2>h* -=,e9;R`:ԑz+%pF2QqFcyl;d 3,h.i_\Q;]QByf IUHm%RjV\ErZOՠq5zo$p؊ztSa`s܉~_bNWkPiE@>mvvF6 -ַl'|uPmo/W9FOXCU"R[/:ST+O֙Yxq7tla3T0ՖlY8F)P=υ -0=vwn8BXxzƁ ) ?3xTL#FC,mbCF5eVVmƆ>\$ -Vd#΃Vl Rfg@)9͛WwlebtN:`C=@eT),n}"a>H6Xv\*nI PG)E.RF6ЮŔQN,n'gΏ͙w6'y5QB0?61g`̹,jIT -:HyBUo c+^pxa|m$Ɉd\t>[{h1%y8CWO ^OlK//<)!]vfKf>l a5Q٤*WѳYfFKn &Z".LuF0xYlܺ+zoǢ  6/ycwBA 4V(K]b8QA޹}hMl(v(F\ Duj\2&?M [< -te7W/Y7qf.D] ld֤AK%=m.9 k,(<,pFy@X-'ں&NjUH(K!iێ#=?l@iRy)H"An BuI\TWr&ʌ2gz2C3nqh<RȦnC³ -H>T\結 ؾgB;-1+ovOeڈ9c8tǭ]l{&c!PJlЕYSfJSBIw%}ɳawK@7s;6EJ rj!rƥ:%[ws!JַA -=zpC:l*rT ﱕyJ%6ʖ&΋Nɉ J $y΋Wb;X' )>X㺲SJ5Gg1@/|gq y -5x)~Ɉ !:xe?4,@`c|&ַ`C|&큲M{RAKk۷=_^[D6NzfE4oqD3]܈sr}v[!D V_נx;?d#cj C/g )v`56 ڈ#O$ M6A -ֵG>aŵ;#~/^4.%N;iDxg*/[0hlA`t`b[~eKސU={1IՓeéz^?G7&CG1>K3zbWctJ-5)h@湺ؤ.b[ e{be#{z VG4-W 48> g;78Y*r摶`OD.( & -{EDꨧ`~YKW>@ S YC / 1~d7 (kPcW Ş5VeqDi+ܪ{,ӿ?{E$B.  6]+^js쫚3 ׭wh2).Ke'ogJCD,c="6faEʶ_K%LH-c̦ی$r@4n&*@e -X :;Q F5)dR`Q-(j.[11!2N? -!- m!bE!d }MBbDV[ Ȋ MӱT@6J2-tIFr -I6{$kC T {ˤ7dƵH@*YÃ3"ns(ƥ>Zp._yB5sY[⡌KVBtapRUͶM#GoQ<>ε\vf5q -QdSMʓm.IM]swONVʓހb`$&9-˙1|Y@ٔD* ŧ0z wI,f⪲Xtzܛv]$(֡ǐqlMiB* NG@!VmgCRșǐlGG1)$IɔajGDg؆jVVҨA l3[`<`&&½ZWN_a4f,Ĵk9O4q.QXsF(Ӯ+KH8+]ޞ+zL鮈qWڻyw܊1&rf5Wz(Ж.8˞:eQl*&_,-O}H +ss֩HJMV57kp[YI'т -9\Ek +/ߞxcf[z dۭ.k_L:SUslN & 8?ۧ(xiGI;4O̹BR%/7MyJ݀b.YD2˧ӏ1!Y!}v38ぶYl; m:?hQPQ#*%=E3hWdn摎"/?Y&,|jNJͥ|DRb@^P&PLK 1D'.}$n}B!(碝Da;Mǧq>x8d%blHdz%e.+ >kbz*/x|=i>4z&R{LbͷQ\~h!hmvOqew)+?=5g-^9ȶ{;[*Z?6غ -j^&^*Dl#"`L7XT#Ӻtd%U~;>l+})!\wdYGɫ6َ)vf7>X[t&A=)z7x}[Vtٹg ,c%ТE}5M%'IgFWGnz4ƥ:0ZږldjdLD4b[j -Qe-Ju -fjA9]I݌K^ݜhBAa}E8*Tl[4_~clK*w0N" O4T 0w9lgY6*BҮlޓr!~i? 7q6ɤCZ#+\澬pIcS$9Cd6s]MK*DU5kW /Tj|vw |fhnUmBuW~FրMg_?|q0#{;j ,sK|$)7V\QEVYt`}75{bB~$j MI_&NŅ^Spn*#eXPo`|N/oO|Dnc^Zkbjmv+ - kEZѩŜr-t@,lmORiȮg^Ӷ Ϥ6vvudP2nXK#PtO d|{C)4=+zk21R!ͬ`*vdb}O+)0cۄc걳1;a6:ҝ"&)ՂqS~Y' 4jAP*vT}Q/Ϙ@bd!Xv|֬(Yfv~FK@aS@dvN7*%vNJyX:aVSl_#nQݡ;zS|C2|v7?v]ҷ/?wƇΦiƆHA_OeШӵ -endstream -endobj - -4886 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [87.36614 598.6334 147.40263 612.2954] - /Border [0 0 0] - /Dest 4512 0 R - /F 4 - /StructParent 181 - /Contents (Algorithm 3) ->> -endobj - -4887 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [140.40207 571.3094 200.47287 584.97144] - /Border [0 0 0] - /Dest (subsubsec:component-api) - /F 4 - /StructParent 182 - /Contents (Section 4.1.3) ->> -endobj - -4888 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [149.96503 557.6474 213.69797 571.3094] - /Border [0 0 0] - /Dest 4513 0 R - /F 4 - /StructParent 183 - /Contents (Definition 15) ->> -endobj - -4889 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [276.43414 530.32336 336.26315 543.9854] - /Border [0 0 0] - /Dest (subsubsec:component-api) - /F 4 - /StructParent 184 - /Contents (Section 4.1.3) ->> -endobj - -4890 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [259.87186 334.6334 325.1928 348.2954] - /Border [0 0 0] - /Dest 4514 0 R - /F 4 - /StructParent 185 - /Contents (Definition 17) ->> -endobj - -4891 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [383.5707 307.3094 446.11862 320.97137] - /Border [0 0 0] - /Dest 4515 0 R - /F 4 - /StructParent 186 - /Contents (Definition 19) ->> -endobj - -4892 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 208.01038 122.27716 221.67242] - /Border [0 0 0] - /Dest (subsec:core-impl) - /F 4 - /StructParent 187 - /Contents (Section 4.1) ->> -endobj - -4893 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [382.14737 208.01038 441.80838 221.67242] - /Border [0 0 0] - /Dest (subsubsec:lifecycle-asynchrony) - /F 4 - /StructParent 188 - /Contents (Section 3.3.4) ->> -endobj - -4894 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [270.15045 180.6864 330.23697 194.34839] - /Border [0 0 0] - /Dest (subsubsec:unified-context) - /F 4 - /StructParent 189 - /Contents (Section 3.4.1) ->> -endobj - -4895 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [87.36614 146.56238 148.84537 160.22443] - /Border [0 0 0] - /Dest 4516 0 R - /F 4 - /StructParent 190 - /Contents (Algorithm 4) ->> -endobj - -4896 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [260.3851 119.2384 290.7564 132.90039] - /Border [0 0 0] - /Dest 4517 0 R - /F 4 - /StructParent 191 - /Contents (Line 9) ->> -endobj - -4897 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [277.53036 105.576416 306.98016 119.2384] - /Border [0 0 0] - /Dest 4518 0 R - /F 4 - /StructParent 192 - /Contents (Line 2) ->> -endobj - -4898 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [362.92276 91.91443 422.8277 105.576416] - /Border [0 0 0] - /Dest 4519 0 R - /F 4 - /StructParent 193 - /Contents (Algorithm 5) ->> -endobj - -4899 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4360 0 R - /f1 4354 0 R - /f2 4384 0 R - /f3 4378 0 R - /f4 4366 0 R - /f5 4372 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 194 - /Tabs /S - /Parent 1 0 R - /Contents 4900 0 R - /Annots [4886 0 R 4887 0 R 4888 0 R 4889 0 R 4890 0 R 4891 0 R 4892 0 R 4893 0 R 4894 0 R 4895 0 R 4896 0 R 4897 0 R 4898 0 R] ->> -endobj - -4900 0 obj -<< - /Length 6217 - /Filter /FlateDecode ->> -stream -x=]s#SIW쓜:'$Kћʿt,:= h77v߽z>nv>}wmwޥ^Տo_˯\|퓋q/}r?U)yDto>\ܼݛ_.d˛ Ip!?f/tւ0RwoO<~#ˏRR i' zB -'0ݷ A=v " `@HŜ H!5ُ;m~g@?̈́=1 FϯnoyHP/.dBng/7W݋]|b[OW q$=3FI *v݋?5`\ l+<>˗wT4`˫*MSYJ~:=#1z $,˓ Ke(Rjj1j>eY ^;R /{pߍtGk;([+#l\Bt8 0^ڐ74!zMi ^xs$8 ` e0(r+(Z05 - LCqStM"ӧ&m"P~k$'QnAHI&E^N C*ԃzMPNX#cFI*4g  -2z*@ŹwjQ4O\'Fm((Piа68:0aQ@$,`Vm+LC"mA)Yi-!&wBgvp|BI` FHSp4c).8aO&7M%-nk>2"ν9$%cKt86JH#ZӆxEяhFyk\u0IY hg4b(yΊ瞣UVo0/g0@ wR4'NA(;ru" -NnK+$aA}$狷` 3aG?Ҡּ"dFZs9# {-\1'@İ>X= !kd*U/wѠn+" )nMs/ VT򏙫_,P)kp=&MzBMzT ߣ6|HZ]u#MJf!T/ׯnm`Xްa *p2ki 5@†2Wb>fz-6=_J [|845Cָ)gJY:ئvO&1knL f0ݲDW1[s4p3"9`Li2fixt&xۂX -mWvkBn"QD4ɥ!G8^mW81o8įp{{02ѧ ps:15MƣZȂ`yk{_'4 t4#D ?%BXL7nH#Wq#x,3ۡ3B6XڳE7Rh!Ms?E*gx{ӴR/\[=L1h-LÂ`2/ ZбǔʆMo* -'ZM1:&Ј))-MQs"J|ů#QDgbڗb2{QJɦE+{؈x_N(p?1.x0l)MNʮYMd#K{XPBb_uE!2")O(dEod3ڒH60*P2a`-*mxl/ojIM>.^D@~nqE4]J!%U"+Ha!Wd- 0 -y5`][%Ձُ;'c1N8ߍL0P5r@sO1*X㧷?f?>nؕQ50Rz厈M leƆ=>22 0R 䇽I氅fNp:G#%y (i~23 ($))pyzEID( crz`qK*?H#6ݣX:KmVUwak-*=ZNe̽1oDoLyix4IG@B#akM F@_H+!& *i a'gȒaNYF潡'T TƨMQt.@_H]:LZ$UQH2BWsDX-oV p_ 4 G6g'CP"⦌&e`Ow@غjI^H}m!RL[eoIŤz\I綤BYJ!fPhMuS~z.x_$Mchm%C: --9SE=W\h'fm=7Zj>P_dR l^QQ9`}7t0^nY~eL+S d~f -_VDPr̻aP g)zpӳ"9?o]P]LӪˉ\|hfx'V(C_ո$+kL)n>ZyffA8r -Ax[^޻lʇ2fť!F\AOu^\οq(S1U9yNq]<cX@ԅhQkz!&2O8BK'k"`FmD|z;^ ЛZ?M,Rn y ̣u팈T–BLIIh;U?{h|wr%W ވZ~ -M?΋ <ƣT"y'D/5 -XΩOعmKME}h -O}i@ai-o0QN,X }*S N6#x "~v-h{گ-[69w;#I༉T*d+?;HƈO9wHUmlP[r;eÊoJD k{8A-n闔#xWBEWGc#szkPW(f,AΪk2b$1B:wSBS%}W/^ջjUe#fn抂<',o ԋRP6ngSo0Q3'wN,ڞƂFUa栴$G$\[j,g-k2)<Hieap{*;$Z&!jG&m)( /̃ʸzIhWp2nɲ0q_d Ip$ |& -ZXN+BTf ׅ8Tp~aϊJhe-Բ,Yy;$tK{Ctd1NjgNFdGY7rK̛ gPgXA&HZDyқ8 ̣+eƬ塪bɰtVS6eR;)AXx喕Z8D4q -5 Ԅ^I1l%~/ yRU)cU}IJ(؄9cs*(A)hHѻsR ->j9 oJ_j=4*F&Uqm/>JmWꂘCCZ EK qRաސPs!ز hSYjqb9_b9`Ssńur萄P΃gA*fHwmN`]2j(YJ JO!bhq2IY -o7 -~LiBY^z}(8G;N)b4&t^] /3BGP@;MjK!M@GstpolP-zU ^2 EUM^~aKG*0X&gFXj(kgVxI'+A"&`7&Ϡ*zl}WxV\c:$!LJ1Ʀ2Izϓb -mQUFE\^⍦CB>g;oJ#ʒDp0Y =vUP"vE}lɁ, -K>743"j]GZֈ%4f\P h1. v @ n0sp1hs!HͻBqÒPMxpIi:!+#t(N (8HXo a^`jD&]*K ]<;d6so}CZX!E z7gnj'TT9̙uOT" ؔ\L8 gBY +\YڣN+/38TzdO[(5R} z=-G 63"Wؖp@P~cr՛}wӷzv7]E__[4nB6h䤲v J -endstream -endobj - -4901 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [87.36614 519.29944 146.85141 532.9614] - /Border [0 0 0] - /Dest 4519 0 R - /F 4 - /StructParent 195 - /Contents (Algorithm 5) ->> -endobj - -4902 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [326.38528 519.29944 386.20056 532.9614] - /Border [0 0 0] - /Dest (subsubsec:lifecycle-asynchrony) - /F 4 - /StructParent 196 - /Contents (Section 3.3.4) ->> -endobj - -4903 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [460.86523 478.31342 464.16522 491.9754] - /Border [0 0 0] - /Dest 4520 0 R - /F 4 - /StructParent 197 - /Contents (Footnote 2) ->> -endobj - -4904 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [79.86614 114.97339 82.56614 125.701355] - /Border [0 0 0] - /Dest 4521 0 R - /F 4 - /StructParent 198 - /Contents (2) ->> -endobj - -4905 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4360 0 R - /f1 4384 0 R - /f2 4378 0 R - /f3 4354 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 199 - /Tabs /S - /Parent 1 0 R - /Contents 4906 0 R - /Annots [4901 0 R 4902 0 R 4903 0 R 4904 0 R] ->> -endobj - -4906 0 obj -<< - /Length 5213 - /Filter /FlateDecode ->> -stream -x]mqb3mxGȡ(˲哨T(Rb<*u\)Ac'ZUFxpCg~z8ܾ77~6|ӛś܇nwwwv}W_?]~e: t3g *τt{~ww_^~wwq~'88twM ܟw3oߒ |7}+{Źs}'4{zu N1tn~fl2 S8_}Ost.bIYg)t*;wNxg'K̀Ę`,d D瘛g#?ɖg"Qa$zϤڶ ..js?(d49 9X`ʄG%$i0Z~ #_ 9GH.*{eϩdH&9V9 -dQ9`44_P8v0h1T$9YΔBBf8x7n 3Mƫ4t֩jU@umHgr rKgWQZgVf Ah5FyK8l [Z&bܺZ<'LZN9 e 3- Q {W%\Z^L|DB)ڜE؊\ Y͵pcYkG?:J7owl%G,cmXռYNظ '=kR\ΨP/5ˌTHgs -(:-RR뀫YǾ-P(© qvu"yM*Q?z9ycbH_T~y?x,"mD{}+C{=(EnCN)i>) ]!TY|TFKjLAuTڵk߶ ޠ芺Tq&us_41ˡ2ɪL9n}qC-0kX3]Af-B̺c0V0-ihsX'BhtZeG)hV -xW+;q!MӀ[ewEff%o~VRIErPԀ0Ϝrhd .fJ ewT8qmlel\fn묞84 (YnIC&#M`]b0 ‡=]ڼCau+xDOЎm$O}"K(})Ax:mv%]LArLqve/Bj.\u@p|͜[9Ȍ Y[$XC&=bgd7LpSp>W)%|Wz!D@j~$ӽptaNz}ԗy@P8U,!Y裝sd:dN16ճ.0Y/S֚eg\`Z385e4?5:׸<`#C-`6kpLvQ!-sf -*cL;7xo xR"m~N8\" -NvaeVbyęAm̊ZP[:3+;0e{*6s(q]L ^Gb\ 8mظdm"6h-Sp9 <ɔ1@85#iW7P4lI5: <5^0ƶ"H֞yfS~Ѯc*k))6|/pIpcicP{ NEI˭r* yHat+-Y3CY3Nѣn`VDZKB˵_`!gBcS۬6^0KݘaH#ܸ4l7~sat[`_cNJ/ 0{4?TYBԕ duYtFECY* 5 #`4 -IЋ& -#SGS0*פ0{& -TޘT2k$r!,)0;(QhVj xғRiޤfkuiL*bGQgRJ5sC k2.,3&Q,qtv_z&)z\3[ S"ą&; >6x5}*ÕArϼ;+ߌJQgPy% JJ+n108-2"iU$x%,ak:VX|q/qJ"3qEbfl0&[W{ :~0n&K)=iē/)]֋dByabf\zitWk<{^)cF( (dʝ,~%T:IYZns*+Q*kݙ ~'{z8ܾ7_|8>6|ӛ7>܇nwwwВ@Zi`&v('ddq?+ -endstream -endobj - -4907 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [210.73615 585.1914 270.70114 598.8534] - /Border [0 0 0] - /Dest (subsubsec:lifecycle-coherence) - /F 4 - /StructParent 200 - /Contents (Section 3.3.3) ->> -endobj - -4908 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [349.41644 585.1914 409.38144 598.8534] - /Border [0 0 0] - /Dest (subsubsec:coeffect-api) - /F 4 - /StructParent 201 - /Contents (Section 4.1.2) ->> -endobj - -4909 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [304.4633 523.7434 363.29776 537.4054] - /Border [0 0 0] - /Dest 4508 0 R - /F 4 - /StructParent 202 - /Contents (Algorithm 1) ->> -endobj - -4910 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [411.42615 496.4194 471.25513 510.0814] - /Border [0 0 0] - /Dest (subsubsec:lifecycle-coherence) - /F 4 - /StructParent 203 - /Contents (Section 3.3.3) ->> -endobj - -4911 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [210.50237 438.1064 273.43668 451.7684] - /Border [0 0 0] - /Dest (subsubsec:coeffect-api) - /F 4 - /StructParent 204 - /Contents (Section 4.1.2) ->> -endobj - -4912 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [298.89136 369.7964 357.71567 383.4584] - /Border [0 0 0] - /Dest 4522 0 R - /F 4 - /StructParent 205 - /Contents (Algorithm 6) ->> -endobj - -4913 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [301.9643 356.1344 361.79327 369.7964] - /Border [0 0 0] - /Dest (subsubsec:coeffect-api) - /F 4 - /StructParent 206 - /Contents (Section 4.1.2) ->> -endobj - -4914 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [87.36614 215.0924 146.8631 228.7544] - /Border [0 0 0] - /Dest 4522 0 R - /F 4 - /StructParent 207 - /Contents (Algorithm 6) ->> -endobj - -4915 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [458.63428 201.43042 517.46844 215.0924] - /Border [0 0 0] - /Dest 4511 0 R - /F 4 - /StructParent 208 - /Contents (Algorithm 2) ->> -endobj - -4916 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [75.88214 119.458374 135.71114 133.12042] - /Border [0 0 0] - /Dest (subsubsec:component-api) - /F 4 - /StructParent 209 - /Contents (Section 4.1.3) ->> -endobj - -4917 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4360 0 R - /f1 4354 0 R - /f2 4384 0 R - /f3 4378 0 R - /f4 4366 0 R - /f5 4372 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 210 - /Tabs /S - /Parent 1 0 R - /Contents 4918 0 R - /Annots [4907 0 R 4908 0 R 4909 0 R 4910 0 R 4911 0 R 4912 0 R 4913 0 R 4914 0 R 4915 0 R 4916 0 R] ->> -endobj - -4918 0 obj -<< - /Length 5497 - /Filter /FlateDecode ->> -stream -x=kqW sLo$R-KNYS|HSR9+ =hcO1?pfFht|~O]w}wsW/?n~sÛm~|w{xx??|8 }y7yɅNf| uM[S0XJdQbJLLR0{L}{qJFk}Zۭ$ LDt݉Ǒd@UgJ"T&aO/)񜿿I$j[ Zl0M8$Ji̥54h\@ULmQ\`V6Mj7cA4 "˥I%BF8=W!9Ѹ9?u7s&Ka -A Lă̹Z$&[lݳAߜ فBU$!U4sTІmшVͨ4 7ejKCJJ2fBT$~T" >jHVcl!vƽ!:fA.εpu݊ Ǝ.9svss`:O2/ӆ%}&1pgdޘ|Kh"N /A` !@U؉"HLsd) ?q݂a`oMo$[S2(AeO2EaQԬ)Mn lyBGȀt3dzk`G"5:I#]&/,N\R~>ts(pm6+6Wa6ά k-:9Q?-סFC"\fQ ˙ }7(} )>Y-gVM됝cd|rcWMTA)1!rRy(o&rz(f+tv# -yUeZM6kB$Za2Xt}0D -1&ZI1UdZ]f\wbY/=1 8H;="I_ּ5A:o0 ._m*%6ŸWYh jBkt=5ҕcb&){-(-j-VJ$^<.([QC| : !/9$2hd1ȓoCm`&4-B ׂ9%x楁PC/F Gc(Ja}G\զQ)7jc=ݻ4MXz+tPɓ1b@ mrT/ U%bٕ̾KU\Ć@^LOfcV!5x^.jw5Ye -LOdtUHp1Y jiBuSf!]bx g -Th0 *#^O[K=:2lr`21WNrŔr -d7idNLxk"_)l3BX$gFZݰ)36#iS& jJo_4FT6[1ꀗ4ۍ|iUjyUV@cQhDYO2PQ6c.gƸrbHZ-Dj\HOrMxx\yԖ{so]k_g:Nx0b^k(B3KxN?- -qΦtŁS"o&5狫5"Rk<"_ F3emv]Eo3N8s8eMX:N刂 _ϗcqxOۣ '܊Q} 5SH1b&1GpmDJYV:e`^)ieyFp$ATudC5 *Ӳ`22NN 'ڇ*2Rzt@%\>52e#, jc"놶LDmT2쬄!/b;PHXpZUn -@ ȂuZwm,0\5!0/s̮|󯾲`֟P E0iDnWJ٭Ey.6;˕N&ҾJ7 J:bDq8F͐QsqRM$j6 +r( 2NmN_*lA2lj[rDRQ)J1cXzȉ:J# j^ Ij2&r3$:5J0q^E>+v8Ԉ8=?\d#j-Ⴔ欅H1*Y}Li˄g[ؖ0#}<~rN?'(}Phm1OS ɜjy5) -Y3PZm=lH.dVą^D'Ӓ[ܰgn*TBT| ȤE(xXHfT(@RYS) 2bx= U{-PCtkDʔ)'Go~f Gv6򰟭:\5L_h0z[kgǪ% -@e "eeаgUe(&KG|j,$nD~0}w g{osk>'#y]'j{%e%` !Pٸ-lTĩEHZ-sΦ@u 2, -UmQZNCDlxzyRFHb13v{`,&эiѱZ\j׶V޽Dj#9COcC=fbh zmhk_(M{1"Xo}c77 pm, 4lZYii[x;۩מvSKذ5a,>OMfWiZ/j/Ltf^BQak 7s(90<ڪt pW:nY)ًdWBWK6aj.i=.i3|7-!k,Z7*o^?UQ[T/=/jd-ziո}q;z:݌]oܦٻlVE㗦j~6}tQ7uښp4GF3 Ǚu~QT@G 8Zx%l'@q -Ug'\|/. #IIHbxڻG -ϬjzR_v'QR-m-`փtkɨ \'$5LD0#~ߥ8nъR2ZR֣rjdv5[XYFp.\XQsXQPzR%6U%k!ItCn@Ck^U-b}_ux!n'O}'󂣵;7h[*ݒJERi9h?`bZQl?j2q YH<߸G/5"jgqkZCseޅk|0ZVLcva3`{肆l׎y~(i@֋fy6G#ԸhľHB22 v+gJmD8Mb6Y5e5ĝIܡC|4g,Vd˘Z[LoG'G4Di&x>%wS4HzT'Nkzp[jf̿i>Sͧ^Q-`,1%7;9WF57‘N.ca2N= 5~mQ6"zgy? *p<.8:04ه0ks|QlE(cODS{&;$`+MDFqk -R njwjwfJN)y>T6ׅv:zGxHGe#7@Cx6@/n(Ȃ+VY}HE=k9fY ,ŕXXQdowgPR3#w3@{u* L`]FEdcF*цG.#h'Of5җc;}V[ݛna$5vĭ6e6c~>b5|>[\Q#]u.^ -1hj0Q0W8ulX j)),n7 $R;;y &;RxP/ZeRxͮǵB2em۽ 4d7iù܁֚wSRA2ۥX4Cv~yXCŷOPV.G>af^iɖ4>RO@w+dyCΧ^ƆWh((ޚC*U›zzhmY.mxy `1 PbaυZpYؙ(e$5p']J8īTYZ^mMT֕ oҋC#N^;tV]RLʇ -Y[Z3U5TsܩC(\T9^ ϰ&t#r9> -endobj - -4920 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [184.48878 504.0494 243.92665 517.7114] - /Border [0 0 0] - /Dest (subsubsec:unified-context) - /F 4 - /StructParent 212 - /Contents (Section 3.4.1) ->> -endobj - -4921 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4360 0 R - /f1 4378 0 R - /f2 4384 0 R - /f3 4354 0 R - /f4 4366 0 R - /f5 4372 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 213 - /Tabs /S - /Parent 1 0 R - /Contents 4922 0 R - /Annots [4919 0 R 4920 0 R] ->> -endobj - -4922 0 obj -<< - /Length 5034 - /Filter /FlateDecode ->> -stream -xے}m`kuʡb S8!ž˚80TOttttC^vm.~g׷Ӌ|_˫~o75_]ttu?^߼^|i/xwl\7y"ǙVIus-onͯۋϮ.xs|!ݯ_.\o7\{w4OeV -mGF KA-!] x& ? ?s3 ⋫l2Fd3Vpl Tڱvsur9yPxnM# +ėᨁ2i o+~N/TBeNxk+3=l}iEսdKq.>B`ͦ!v%Mj^" `N2%]L./rK!r8."1R3E"@:IuTW0p'CIG8М2i\Os'/M@u\IQ\EX2/?Pm 蠴g};`MÎz{R=\llkM .4skarU84GhdkebUH1[D ڤ&0`fǬ `#%bi)b0E,(?+Zژ[ʵ+{FNލnp 2r}O!4؇߯{LE$%D0."}VĎ"0Gz9Z,3%Q9:jQD(@ƃ3\y!r -UnHS'̇5R2g)_w<}ŋ?~:G9]C -eAȲ$fkncGA \( -ohk1/64W<J.wp:⨴l3g㉻F Ү <"X)9ƕ4;>%f*Jp~e;u..;-)aX`GH!d-hajgNW!h`ĠwƾMxtQ5*ln?c1U*xz|{zb1B:&$;ahp Zp5$.:'o?H2NJ%g4!?N -f:j*8Orl -F t !y,ܙ}HDX<=+ mKθ2gN@sŔ oyɻpΓqh]9":K[R,RiNm{?qQed E{d(u"~y*%w"̕D01'I8E}VD,GS$y)K9\1m&hI^JbG -y* U{5PT;CatiG)0*d;eO`E$p8m }DA[֑01*/;쏰?@("$M+bț!(b\8Te8EqXnZpθXg=hyH xާ>NM$h\qz0eB+BWd 9sjAglLh.;^0kzXk)G5S8OU~T^%êNN8F:I`W`tK4fh2'NFwnG1 <51,#d.t2 a(y<_hxʹίYw)E/G}/ -ЊZh_{@M pԒջ"v"єY&TH_M8t9̛t a,1͉0rm HGVӘ&=Ը,(nB.g&8ɜNOg fA&9ZIQ=Zx.d&DsMg$5&̪q  ;f(o\\+2X]˜vf0 -Xbcc~ ] ž d#TX&aFNs-]ܖm%v0ONɶre ( ճxD+w/Ƽsf0g4E( -2Nۊ0l(P+`E$`U҂Y9+yދ?aE2.+W/ק+45.xˬr("F2DW:0*Iī t U2"+6H@QTr~PLgR>> -2G% 1$.JH88L5SǁOZr$ˢXVM@I -8D{EXIGY+K5(+x~| -iUθb=hq͆|H'S -VRf MLqy>0$kWEG9=7jLhxofYa^exȩӱԺᡢ,ȇR~eset$CrάcHO2dyZ(Ĩ+k33"e{co)rwT gg\)U޲1V^}Kh61۾¢K? -(->rD\hif4'?19,bڶVTr }/@\UQc Z̓-gVυB)j&U6 o%qdHaS|!IkIaX^vAc ] B#Z0-K@VH#{]wm- \E:43_ꕘgJ: -ҖlLl'f6x2UkTo\|2j*ea EɌz B|Y : )U̹JSjE#?GoxCa!8Ĉd=+g%;i,=gFk0A󉑌k+\]x(LST/!F*җ&id42ClKzGy:| JvyVzd!8댉~ҏBՠ--B6E@e;,iNjqfO4,b> K1#  aʪ=zMrk&[=C?&p_/ -.M|l<\TV_* ,aA3Z4O8*֒j;$/1"b&z}XVߙ.ĸIV,f ΀l+ސ]5 mK gf5yEo"qjD>>d] -C5 3wqy<׈b,E,X ,5Dtoi:Ips֒0I"eXXNWhAHd ,[-#cE\­XYs8Si.2pH;aA[)Vf,GJ řZu5qG2Q d+K!,Vja&fUO# 9Ic"i,ec4㟂%'.zbcOD/o]Uӓא{% d1!7Wڈ -,ar!HWբ^ Ƀk/L5S4_U4 -#%uљKdAq!ҙ'Br ԕ1Agőc9b׊9'FToRKB I)Zc3D9 -c$7^nŐ".35 W qXcd-g2iEkZ2P3nTgBf 5 KW_iob1j-)[A Ɇ94CMxۿy}}?߳w?5_~vˏ_f۷]zeC DZa̒ۑx;P -endstream -endobj - -4923 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [360.01215 517.1564 371.01215 530.81836] - /Border [0 0 0] - /Dest 4523 0 R - /F 4 - /StructParent 214 - /Contents (42) ->> -endobj - -4924 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [418.70813 517.1564 429.70813 530.81836] - /Border [0 0 0] - /Dest 4524 0 R - /F 4 - /StructParent 215 - /Contents (43) ->> -endobj - -4925 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4360 0 R - /f1 4378 0 R - /f2 4372 0 R - /f3 4366 0 R - /f4 4354 0 R - /f5 4384 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 216 - /Tabs /S - /Parent 1 0 R - /Contents 4926 0 R - /Annots [4923 0 R 4924 0 R] ->> -endobj - -4926 0 obj -<< - /Length 5049 - /Filter /FlateDecode ->> -stream -x]ݓq߿bhNCQ"错rAÑILG弪}jfw0A_7OnﯯGv]wdzӻ..?}WwŋwW?t9\=~}ݷ/.^rus?~A;ޝC=€LHvoy/;.ow׼..?55__YwL !~u?>w{ցpۄ>lmI}։YǏm'od}]ݿ -Ⱦ -#7R1WqK"0ZdF{)7SGߢ G%FM -$Vū4?:hĞ'LG=Ht/YaR3m'au&[Ϥ^ -+pd8gݹFoU09U caҘ>lp֝V}'2cc:9ΣE6%2 Y#^bS=+䎍:P璖 xUU<52)QSAAAb B{AJqQ,\Qze/$A(h2ipDŽ`YwߕMCd#t= obFҎEHLb JA^b5iF JnMQPRI%lʄt?&LјE8ˬDjH7X$#N'΄[1F̈́}Cf:vR+||br)O#  -HxE u"` S`/q7USS%QPK'&Iupw?+oӥ64$:TU ĊT4#5IHMBG"y(mLVRGWdϳW}R| Bs5I{ڐ]]$zNޜ1IF4<&P1!\* Ù2FU J#n9*9փxUf I<ߒ4"P܉>[\B % sk*^T7w1~'R9 Y0e "_s G>Z$ -᥇|cKlo?K#@ˠ* W?_{g8q䖆98<|Z#2(HFR8B:Q4iVާzDJDH܏]&5r5׸OebjukM!0l*!.>~x\<|[ϵ̩2gӘ_*JMq+:qUynO4r"A>+>s?YT_1+unxid?kMB2)*3p2QQANO=nH" B4aAOn^)Z>L0VFtB V{Z3: t~C4 -3WP*@GŁ I>` -ia=!R|jfEBZ|=OuiKXT+’r1 -܁Kd(Q & IQ `3 喛lސ֪gVϏ KpLKFN9;OӏsjRILLqe܎ڷВ,y2vD(kZ9lzZ|k1N%j g k6CE/rA*h9ׄ`f#XA"(L -z&mDR|QxȂPg,Q%I91=T"7P pv4`RYmԗȣ#"'Biƍ0eRm!6BERS{]=UޙCuRV>NĊN)N)pLk[6j9[53@#5﫠^XKg%)VTh*FdH_0a4~ >r7Y.P<ӘRx1^=E?RJ٫K/*2 GX^!-m45F'snq Z=)ޯKp h+{Pba֔Uy^i`^=Z031CUZtKH܃0rmӊO z{^etNgדd˅a -hZX;P'Zi戁YFÏCTpARh+z!.êR,+B^_v\UW1au7*zN,XB'r5,Za[9*GZ(gN'kiǴ9_,\=#Nyɽf& %b?_$IBYPߵ W^ yfC趥txٛ[5(lbP#^)(T.Hc;dB5~z] G 8~-TƻTl)Zί$p/ $6!8ϳL+)?iw0 }b|(lLP% -IIW š^YBJ5?yq0Sq]Z( iָ*1$+qݩe/s,+j|j*M<3vhw3i&˄ӽ,b)1Lɦ a }ge7` J3tM3HìY68 3Z'Xɇlrv#ز3.xpncL+ 3K7]bts3^2ۨs3SS\PNᇚBݺA%Z4YA:rgz*ÏupSVV̪F۬"{=K<_oXHxrVcْK@{,_P5 -KPrEoHFcVvIv0 uG?я Y0{{ -Iީ*dN=EOׁ%uTTZC8;M*ԡ@7n -HUA(=Sd^P uʾQ|'Y0bR )_@Z `f:7-o*hb+,D-eL܃>IBQ/JXsrHչ%AifF ݷUZ3[3dd^26bn(I2_bLR -̡ -\4QrLC ʟ|qw fof<0L_= )?m5\V/w= -q(]@Dn -"(wYμZf'F/2Cj7 9:/ -*ow1QXqr8<4PRZU9`NTZ6OMTz?=-z~7p-V|82ܰ56ޣ n_gB -:cS 5OzpOz:b/ z4WeppKޕ 4+, bAh?eX)|@S!H驟AB& sV HJ3)5# # :B9&֛rp,? -' I6f'[Ѩ &iX~ _ Co -i1 1@`HǴ,=Ms`%e ->_$`,7,`M2E2I{#u@5Lܹ /W*B1@Vhm8+ WH'ߧ_s-]~D}saS -.~]q='ZK&3Hu&i+zۧlkX:!FX2C;.C/ \Tx8KFEFPpɡB\zO0-Y SV=e+Jq?n+wؗ ̟ILe XAN/ jUs}B{nz:N\%uhm~%<4fC[J&b a1ճ7@#'&Zv[x]jf֮+Ỹc8ō-Z)n܂ww7*Y-nDoy호WՂq үZ;KfR2q#zA7,ejܸ+&Iˌ;k=ORQq#MjB2)VV~OQ/GEW (z'n;7ZZ.1zJof~Mֱ ~ǖU{ihoƮ7KIcݣ=`Tgi6 yxm[ʌho^쩛ډp5.\Sr%hVLVړShz)Ϗtq?e ԯrq0Sd#ٿLu~mDK,v ~w?t]|q~}/ﺋg?~Տo?ޠ݆uH% o~ -endstream -endobj - -4927 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [215.36813 292.08337 218.66814 305.74542] - /Border [0 0 0] - /Dest 4525 0 R - /F 4 - /StructParent 217 - /Contents (Footnote 3) ->> -endobj - -4928 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [79.86614 93.517395 82.56614 104.24536] - /Border [0 0 0] - /Dest 4526 0 R - /F 4 - /StructParent 218 - /Contents (3) ->> -endobj - -4929 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4360 0 R - /f1 4354 0 R - /f2 4378 0 R - /f3 4366 0 R - /f4 4384 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 219 - /Tabs /S - /Parent 1 0 R - /Contents 4930 0 R - /Annots [4927 0 R 4928 0 R] ->> -endobj - -4930 0 obj -<< - /Length 4465 - /Filter /FlateDecode ->> -stream -x][~?bpU! I )/668r>s\$5hZ}Swكݛ/w9{]wg.='.~xu.77.7<˧6g݈>g oxs˙3TcaNsռ|9{ɛlx o8yͽo?~SZ2/izϥ$tg6o 3׶SUW1<"ѳ gfm=F5Oőͳax%UÇ_y)O}E[ly)@79ڜk_φo7}slno%-%o -cw]\~ -~φMKrHTrX~>RAWRo4s _^Cqy'.?u>ᇳ.ee~@v@U"Nkz -kXoB*@ɞEvXޕ]Ū3J2.g3Z;9k%%wЄԪBIt5V+- *RΞGQoLxkYpi5/vrD_vwECpś[o -[axª-"4OSۄ 񌫵T)ru-i$jlRU\%Lg+bRA8f`J ʖWThCw;M|AZ4/M-#QρI*E;"8Uiҳ/Zȁ~xC48VM- -VKM' V-,ίk4Gb*+joKj2j9Y:QLu5{Nax_fWdCڗܡ%KKxCËUv^z)Lpi&< etoce#'+]erSbhOVWoWRVkSܭ xpǺOvn?r%4 ӳa'WEZ3, f) jhViY9%9E\7K5B5OYQPşQ;% 꾹<Тyh -*].4p:#ԦUܭ-ø&n.s[N8?V}3uBf]ѢefV -Ib9G Z@=P Q$}Kz}3֏mNŶ50dB/5#rq -D5z~tL2pτc!t SoWB'i/Vࢡ"0or6[ o^ӣgFEjڣ>[&a-,$w)t62?lɁptU1%& m^_h۝ +Ukǖ vU;ZEWE`<t -7m -ro3%D‘țP9n+$lgvm z\5LtNä'jOdQhb5!5 `d(Xk4Ɛ؉2_n4_A* J*lF!Y5;EGb5_h-8`5[($쫬\*kQbH}zޣPE i>z:f -CbIfHRZ2Ԫ3CU<"=j{,$ 3 G1k@2{ÌS'Gmc2L~lMRB 9nu=-O&{3:Z>hiℸaVx5 g@>8m9ǣ~@"ҌԁfҸPIk+03;pPMp"\2nOI\̝8Me|ؓuz;b,[O!Fafy޻/J;cODhv}~DHbME ԯVLOR'g>*7\3Z'hEZIGù}HӃSgZqVQ\C}}"fluvw84hӣ = mnup:4h8+ bUI"HTj~ǿ,B[&) 7;3PYmL]U'V|jEECI9 Sp{\f׾'8njN@]D }Ny;$Mts-8~ g;B!::o#U -ubPց\FRm8+a*I- -p$W) tQE`l$d3aD[*~#`sfǔ(USĨ5c'j("ρ¿NkH3u[)iY Ds22 jd'Ssʼ7p˔'w؋FxO#c|9"&LQd^'Yc/ƏyژÖs5v/wzўQ#{9ȳ1D2@.U")s2실]WS[>|B-e&MG9lڵF{z]ҡ&-NU1`W+>]<~4NfwiiWG$ d^Ll쥪37g2_2u+ܭt*Y}t4nwW?4ߝ=|۽{}޿jUt\^޼H'=hM -=8{V$}{E -endstream -endobj - -4931 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [424.47882 568.8544 427.7788 582.51636] - /Border [0 0 0] - /Dest 4527 0 R - /F 4 - /StructParent 220 - /Contents (Footnote 4) ->> -endobj - -4932 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [448.44293 555.1924 451.74295 568.8544] - /Border [0 0 0] - /Dest 4528 0 R - /F 4 - /StructParent 221 - /Contents (Footnote 5) ->> -endobj - -4933 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [436.5668 480.0824 488.00662 493.74442] - /Border [0 0 0] - /Dest (subsec:core-impl) - /F 4 - /StructParent 222 - /Contents (Section 4.1) ->> -endobj - -4934 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [448.2978 425.4344 492.196 439.0964] - /Border [0 0 0] - /Dest (sec:theory) - /F 4 - /StructParent 223 - /Contents (Section 3) ->> -endobj - -4935 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 336.6624 131.14336 350.3244] - /Border [0 0 0] - /Dest (subsubsec:motivation-plugins) - /F 4 - /StructParent 224 - /Contents (Section 1.2.1) ->> -endobj - -4936 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [123.86342 254.69043 176.0907 268.35242] - /Border [0 0 0] - /Dest (subsec:revertible-effects) - /F 4 - /StructParent 225 - /Contents (Section 3.1) ->> -endobj - -4937 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [146.12852 227.3664 206.04572 241.02838] - /Border [0 0 0] - /Dest (subsubsec:motivation-plugins) - /F 4 - /StructParent 226 - /Contents (Section 1.2.1) ->> -endobj - -4938 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 179.58038 130.88567 193.24237] - /Border [0 0 0] - /Dest (subsubsec:motivation-plugins) - /F 4 - /StructParent 227 - /Contents (Section 1.2.1) ->> -endobj - -4939 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [79.86614 105.24536 82.56614 115.97339] - /Border [0 0 0] - /Dest 4529 0 R - /F 4 - /StructParent 228 - /Contents (4) ->> -endobj - -4940 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [79.86614 82.78937 82.56614 93.517395] - /Border [0 0 0] - /Dest 4530 0 R - /F 4 - /StructParent 229 - /Contents (5) ->> -endobj - -4941 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4360 0 R - /f1 4354 0 R - /f2 4384 0 R - /f3 4378 0 R - /f4 4366 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 230 - /Tabs /S - /Parent 1 0 R - /Contents 4942 0 R - /Annots [4931 0 R 4932 0 R 4933 0 R 4934 0 R 4935 0 R 4936 0 R 4937 0 R 4938 0 R 4939 0 R 4940 0 R] ->> -endobj - -4942 0 obj -<< - /Length 5550 - /Filter /FlateDecode ->> -stream -x=rHJLXvJmɩI5;3@\wqnt7nn<}igO?4]^_o徹|u_o~|ٿ}|E^\#>bhxÛ 8μB7X ݻo?p&MnÛ~bF+~poKAy|V<ߡW,jÙ=sՋo7y@#ϛ)˴_Jt8̴UwkDZu8g­:\y'WlO"7_6`f?pLHr owa~ 7_]E?ll>ߞ#5DSt7snN%L#`q,.LoΛ azcnKp"meVU"Qs[Ic`x˸[\f$ZOKOeJ50500+ǢE@qy2| ,0^0˖qjiOZQ8a&o_ NI}~eU*\aKW;DK/ DKS+$̋qr|Q60{;zrpP5 -zV% 7ֵT&|_Y!,cۼU 2Z,\"jm9{GGYye]rs_}Vdcb{W^"|N1g|PA*vq=o.\i}ұ#1j`H( -1ƨ2FPobbOrEz aO kbֻhkt+RO`I |y^µ[ ֳK,'f2 @-۵3ZDC0Rpkzo\Eppay9/GQl`@BVCN#Ssb~U&@IgcԆZ=wl%ȯ;3"Jt\Ic'ĭbUzr 0NH<\Uv-5=]l^̃m˼׬j<#L^"V?' v㗿~|ZDԥoY++0ZI;Q3fA'^+:,72Z!*ll-cP90%>B%c &&0=+t+:ֲUjżTIa69-[|^JՅ\n&=][Sw@ )<,C]n-sh|֔!A?0B"_vK\7a\ b®lj#yCֽ_gǧ9~@4*Ɛl6nr^cK$ⳐP7sؕM,fR9k ؄&súp)ǎlzB#Kh l .=B-K˭M@{_M2 -ɬ--nAK,gR8TBϑb -5'«FSC<8Vq:ǎb&U&mmp%q5*ړ# -+ˌ~ 1PhʾcnC5&Gh؏ -B0gq2:v`DUffF.v/.@zj"C%TJ +ة00L)=< -eT}vDUFIPJ#, zUɫgO/Z\Zc#,JZPE, ǹU`$ȕ+,Qpݸ D/ZT`dyBzBM,0-)Rˡr -r#=fc!Q>^3Q!#I $SvAThvHΕ&mh;aAކ [mhYpQyM(e-B;ݰm23Ƈ%Aޙ^3z@LJ^ŷLn^o>6BYƭlۆ7?ojk|azKKwyŸ8LӭQ]{-ʵq T;u '>kXՖݧLJ 'G?*.-98)TV43k|9PhI諺q228ŢoBwʳb<>כnooor{|ck199u7)_l& -endstream -endobj - -4943 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [75.88214 732.5514 126.86732 746.2134] - /Border [0 0 0] - /Dest (subsec:reactive-coeffects) - /F 4 - /StructParent 231 - /Contents (Section 3.2) ->> -endobj - -4944 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [296.2944 415.4574 307.2944 429.11942] - /Border [0 0 0] - /Dest 4531 0 R - /F 4 - /StructParent 232 - /Contents (44) ->> -endobj - -4945 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [173.63432 94.49341 184.63432 108.155396] - /Border [0 0 0] - /Dest 4532 0 R - /F 4 - /StructParent 233 - /Contents (45) ->> -endobj - -4946 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [191.8974 94.49341 202.8974 108.155396] - /Border [0 0 0] - /Dest 4533 0 R - /F 4 - /StructParent 234 - /Contents (46) ->> -endobj - -4947 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4360 0 R - /f1 4354 0 R - /f2 4366 0 R - /f3 4378 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 235 - /Tabs /S - /Parent 1 0 R - /Contents 4948 0 R - /Annots [4943 0 R 4944 0 R 4945 0 R 4946 0 R] ->> -endobj - -4948 0 obj -<< - /Length 5092 - /Filter /FlateDecode ->> -stream -x=k$qWf& 9X7YV{ќ27zvU,ُanEXU7_>>>ӟ辻x?}˛_~z~0x㏻O>o>7~Y'_JuݝvFMod+iÕWoeTOWR?JN^ɽ)?i8T@:ET;O%- ݸ]86Ni9_e&N^7(DdJ7}xA 7gD2 }0zuB%` eQ3eh$#$VCmx˚xzfw9 2RN@l]7 DL{֝ {/`QՂ ӆ9Ls1]QWh{W .;&:7,®}Z -3iq{ț Vh73o =4vsnt/s7<\WiAb7̈]cH'y}<3߀T&a -?l?},RK:mE8V^hW)#)Ny炐HGJWŏDW(WV7lJu<!{@Q;plX90$s2N9i 1ϟs.匎rQzAb/;a>hV%S4)s-Q.> N >^cE=A!z2r:y3xضX1οu&縕(a ꙽v)8KȤe^Wy+fGZ3$xn\ŋ5Aߑwy庝VwrlR9Cia("/ Mh~~GPpy`/K¿sO]0y3QX夶^k1\,(g@m#&HՄ*{bge8ܡRsYer5[&e{:Gf3c`ĺK`3!Šʇ`%*%P%PAA^U-=<}_|!>!NySnl[/z L[$;{Nc(,,PfBu9XexpKyX9/kՄ lMlm-gb6K3 ߃Q%%rNsQvzFI DX -J  1oQaXQ -G$7#:eY5 QX+:QӁdQR)@+/g R^)l7tXl}P3̎f0 ,Lo*ƒ%'v4jb}Yn &wI]ؔ/&*&|+| -gBcmkO}~ZV^hm9n}H&̲RQW.QUA%0zSٞ9\5UlꂋZ(&e+I יڰ _*@Ǻhl@V% 7:NS^O0 -%-oQC'QOr mj(6l/6Mu0PTTBVr!2ˀ7bku+=T-gׁPNbL(L/)$drw a*8R*89f~7.~8a+zZF\sEUG|m%uy~kY^װg>T.hO!JN tI0d-v*-^!-M5,>7v]PpEacpS"M>xiH͚}i꺁CfE%N+t -1cD, &NC\yI3Vc1) I:0hDϧbudQK&**.I޿GfÉ6Da[9Pzmkf#ΚŭnzUNS~Ԩ7[*"2쮻K@BL ǎoHy.rh5"zaiPRRhg / 293yyKf1aS$s 3hAϿHErA~Yܛr腎v;WQ@J qZ5PQZ!n5 - -tP&.6!Qeq5̺V${ Y˴^Ȇ#ҵ@K ? (Lf=i W/e^ߑVzUN2"rw"HٗiP2)It 1ZѤ+C5+, -h?(*U6sNR3tk&+ I -n#AaʭȔ_f8.fILw)A>qkׁJ:8}MŴ(,Ʋdt܏@]خa`~:ȓ*xNզ"?SEz{f-(5ƹ˼&'،*qU),֘9-*g\ \/ѵtߌm#K?C)UE':nq4X'"Mc+סfbo4ԛ $Eb ҠWa hcD!C嫰: -M4[qQǩ9!B=*?t!-p4ވoe(Zn RƖu<.fLBrsŐ%?!hdۉ50w ̧ _nEdO:&XLyjѿ֥CXxdnl9FAƛPakT[=T{W>j ق7KÝ#)"j>RWeu/[?`>뗀 n2 -WԟF_mf'1|+SvEdd/~ől/#󯗤 zTlJvڴ85zadS+b/YC~zn `-fџ/@w|CZZ\WnE)3r(id_i!_6⾅f-[b]U:y᳠B~G2HePJDZ:>Lo \` -@ --(-9X/bgsWV!o&uX ۲+FF+\%Ko9xe1hE/.y3dE Hi\5CJ(UڵG_ٔ!B, fۧka=;Nh/AP73H=r̈́Kbؤ4pzB$T)*7xKC%@$9._4ZԂS=+f3nNqc*O.wgky]QulҚ^Սx} [e!HkDm՞ɼ=4YlG\ŇAR6MRQq/n]4%_~*uy5g#MBKio6м~KY/1U ;afaxBc -%aٴ mr*97>`'i4r$2K )i?( -/2clj[ -lvV8ӛ:$>Z2U'ݒ& O]\yNS|C6ku؅[Th8td~XE-@L\rrGNBohcej-V/ګ(YUCdEW슫T]<U!ND{g^c $PkOE{186@k)L8t"`5jku9QDQUevӝRH-c4FE%L֨ E3]o3^cLhy[6\ڳ(o_]k8N.@$3-6IG)GԅH̷AR:UR{ŔBƪJD ІMʖ7PaA\1YX#iя6Q| zN&6 7{fSs%F<n>lLj|( ' C19o!sȃl5fvT~D?ȢE?dK?ゴ|`Vh,Eux/t~\ޱ)A "/oqm[k eh+ %bsVgR,Tofu6`(ʎ'*Sv(N<B iS* D6=M[V2}:>UKɿPv8&¥_M{^[[$k2jb#P #(#TJ -LeֳmdZ&5Jf/ 3.=DՁ,>I"յ{~ǻ~oAeۓScc -\S'1FO >ڸ&,4v<^?籌z0nw~\ OwR+CPxv2EE ѧdk?խ_1bA85W2¶Ky)t?Ԟ7W?B)jo5d+]7}ڰ&PۭVޖ>POc^ Kgzpl]B ~Pwӕt2jҧ)>& Ӕf-3JĶwo;,ӟ辻7ǿ0x,aBwN[yn7\R -endstream -endobj - -4949 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [75.57414 657.4414 86.57414 671.1034] - /Border [0 0 0] - /Dest 4534 0 R - /F 4 - /StructParent 236 - /Contents (47) ->> -endobj - -4950 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [455.87366 453.1284 519.39343 466.7904] - /Border [0 0 0] - /Dest (subsubsec:context-access) - /F 4 - /StructParent 237 - /Contents (Section 4.1.4) ->> -endobj - -4951 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [326.0764 412.1424 337.0764 425.8044] - /Border [0 0 0] - /Dest 4535 0 R - /F 4 - /StructParent 238 - /Contents (48) ->> -endobj - -4952 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [342.5764 412.1424 353.5764 425.8044] - /Border [0 0 0] - /Dest 4536 0 R - /F 4 - /StructParent 239 - /Contents (50) ->> -endobj - -4953 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [456.27435 309.70837 518.84344 323.37042] - /Border [0 0 0] - /Dest 4537 0 R - /F 4 - /StructParent 240 - /Contents (Definition 18) ->> -endobj - -4954 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [150.30486 111.64038 161.30486 125.30243] - /Border [0 0 0] - /Dest 4538 0 R - /F 4 - /StructParent 241 - /Contents (51) ->> -endobj - -4955 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [124.75167 97.97839 135.75166 111.64038] - /Border [0 0 0] - /Dest 4539 0 R - /F 4 - /StructParent 242 - /Contents (52) ->> -endobj - -4956 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4360 0 R - /f1 4378 0 R - /f2 4354 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 243 - /Tabs /S - /Parent 1 0 R - /Contents 4957 0 R - /Annots [4949 0 R 4950 0 R 4951 0 R 4952 0 R 4953 0 R 4954 0 R 4955 0 R] ->> -endobj - -4957 0 obj -<< - /Length 5393 - /Filter /FlateDecode ->> -stream -x=]s䶑T\"dW]_z ZgYd\uW@wFwм{?{th>i^O/? ܽ~~y?{OO?o>7{V566m~{?/dϧŧ_ܽRy{)RӟJ}Өڝfo[jms\vJ=טp"Ga!/oƱ, )2A>S?iqI,3ic}<7ҺUӉc2&PڊΘ@w<;?IZ#s,6dYrV4z13SUv ew(`a2#hf$vzRF)PIb4D4BPvbg]4/GqbrWWq̻lX5 yρkjpn4 U4,#3:13tvvJVi-e):,ޡN Xmhy0BEw$c;nJC$|n1Bm@D$w9r+2y X)6Lr_UU*u0ː6oV*::%yΠNAe ^&m?+8bn?NÉUns>HFq36K+2V(cN< xoC*p<2i%紘]!֛mN;xN; -=+S]f|M. om-:˕w -F7rܑ[9?1Bيg2uvL+ZZdG5 UsBŢfl ]Lc1HD4R,Q'F ?6J9}TE뷅m6:a+6IڐyQM UD5S$G)92Zhݏϫ>9no3\DPuosxK2A9) Qɔ `86S"EԤѢ~ -X#ЇN ;\ZV H':UL Zrh9h"¼H 1vrLzXN[LX--1 "cP)[6T EI<(/hi:''B2pcYh4 (8bW&)V<;^9UhRvpTny*6evy)nvs]iM%3zb3 H1BK FhV {ύ0[b(Y _I^E,6-W5Ŧq`xP_d -{AS/XfQA>jl)f» Y 7~3>~F֬&+fos}ۡ#iSs,(*0xOլ_SOq0?Ll%,V\f-PN*SX,9e]9iDo7|INض. -_Vk*dQ"AG0SUf04*rA7>)+`B"\j [7`{)tֽ xGJAɠ7RO -Ңj5EM*[?|@ p=x´v 6~~AT1W۝JKh'ͦmW"X7M?;ey٤,~,9%! D8b6`dqx1K}D9]DQ=2٢hQAJ3i焔U%RR['FnxUYT%eJQ)ڡz}#k^ l -*; kZ-l3qje5_$-!#M~zQĴGPv i --@7(ā긏LUsNuy7hv"\( "*m &'lNt"<ȺZA.[Հ.0T'=,om9/Δ 4 - $U0ڡUHqr&6rB8ݟ( el Pd7PSEq!# dUl_'p q]ځ(7Z *+zi^ȡ[5>K*raL[ʑ6VU(%Ng(zj(иNnvtli9oR< 5b9( fk@三-R '+B_@W 򢗢:֗"AHlX{.*' ϰRDʅ@N 9]:kK?mLCX% =hEU+³(xhR .]i$ *`֨7]+:[P wڊVvv̉@F4:vKŶd/EQ_#JCwrG^\.a%/-[ evP&ykgZ:;<%b, ,4u- Ưĭ Sf%IrUi;t\~pK -T|Ğ-r2^ -J ɺ^NzwFNH*G%AAӎA -qa%+CoۤNyf4Z'ǦFD 8f)$6,e'&z2lZ0K)Sey礌.4%bs{qcy+([xf=Wk6M_tfW]/\udۛInaSa+h.t^- RvVїlͭ=lRo1Ś"{n‹ 銢% )(-ZS*!D?cEQE"YGR56)$ơO7HūB}IjpH^ ^5BC5˧an" r;j(RLܱ`||olw2@JFA `[ׁ)˿lZdIUl 7 -\Gn+VruDk[mՅ6 oh[ٚ% P)@@ga p^-#ũ/\P Akp+tUB%OrY=c3uBvn0WTV8e~(Z5ebbf`#]*L_{M)ځ;tʎ>t0Aۜ~aSZau݋_>i[IcҮf<%UQ([P^YNVEpFg{1zH^x?PI{bշKG$Mlſ~YfaV3)D}k -2SuWM,U9^S܇YV->|rNxb(a^}+A^yK'nUήib!F%_b5qk Z&N%kZVTbKً$DzoWV T;P:JBSD(>➂ts0T@N -ȟ Ě3{KkaoXZțgh>\}ӕU8+kT26+'G%Gk }Fqhu{Nr~8L}idw ?)щotNJ-&V[%}6=>TxtÈ&^#Ed[B*HQoROe6H[@ЛCTu?"E9=M!<ۂ9w,QL-kRys UIC1ˈEoHrT!xqgirnɒ]'%ge__*51L%ӃHK۔BZ۪}) -)mET*4> -endobj - -4959 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [246.03696 494.1144 249.33694 507.7764] - /Border [0 0 0] - /Dest 4540 0 R - /F 4 - /StructParent 245 - /Contents (Footnote 6) ->> -endobj - -4960 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [315.25378 466.7904 326.25378 480.4524] - /Border [0 0 0] - /Dest 4541 0 R - /F 4 - /StructParent 246 - /Contents (53) ->> -endobj - -4961 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [311.1513 350.6944 322.1513 364.3564] - /Border [0 0 0] - /Dest 4496 0 R - /F 4 - /StructParent 247 - /Contents (39) ->> -endobj - -4962 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [140.36269 289.2464 201.18646 302.9084] - /Border [0 0 0] - /Dest (subsubsec:coeff-context) - /F 4 - /StructParent 248 - /Contents (Section 3.2.1) ->> -endobj - -4963 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [486.33368 289.2464 497.33368 302.9084] - /Border [0 0 0] - /Dest 4542 0 R - /F 4 - /StructParent 249 - /Contents (54) ->> -endobj - -4964 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [141.26205 275.5844 152.26205 289.2464] - /Border [0 0 0] - /Dest 4543 0 R - /F 4 - /StructParent 250 - /Contents (55) ->> -endobj - -4965 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [251.55157 261.92242 262.55157 275.5844] - /Border [0 0 0] - /Dest 4544 0 R - /F 4 - /StructParent 251 - /Contents (56) ->> -endobj - -4966 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [447.87784 261.92242 458.87784 275.5844] - /Border [0 0 0] - /Dest 4545 0 R - /F 4 - /StructParent 252 - /Contents (57) ->> -endobj - -4967 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [397.8022 186.81238 408.8022 200.47443] - /Border [0 0 0] - /Dest 4546 0 R - /F 4 - /StructParent 253 - /Contents (58) ->> -endobj - -4968 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [167.3757 173.15039 178.3757 186.81238] - /Border [0 0 0] - /Dest 4547 0 R - /F 4 - /StructParent 254 - /Contents (59) ->> -endobj - -4969 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [400.45898 173.15039 411.45898 186.81238] - /Border [0 0 0] - /Dest 4548 0 R - /F 4 - /StructParent 255 - /Contents (60) ->> -endobj - -4970 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [416.3656 173.15039 427.3656 186.81238] - /Border [0 0 0] - /Dest 4549 0 R - /F 4 - /StructParent 256 - /Contents (61) ->> -endobj - -4971 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [183.44235 125.36438 194.44235 139.02643] - /Border [0 0 0] - /Dest 4550 0 R - /F 4 - /StructParent 257 - /Contents (62) ->> -endobj - -4972 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [79.86614 93.517395 82.56614 104.24536] - /Border [0 0 0] - /Dest 4551 0 R - /F 4 - /StructParent 258 - /Contents (6) ->> -endobj - -4973 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4360 0 R - /f1 4354 0 R - /f2 4366 0 R - /f3 4378 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 259 - /Tabs /S - /Parent 1 0 R - /Contents 4974 0 R - /Annots [4958 0 R 4959 0 R 4960 0 R 4961 0 R 4962 0 R 4963 0 R 4964 0 R 4965 0 R 4966 0 R 4967 0 R 4968 0 R 4969 0 R 4970 0 R 4971 0 R 4972 0 R] ->> -endobj - -4974 0 obj -<< - /Length 5950 - /Filter /FlateDecode ->> -stream -x=]q+|T3CH)N(J627IG銎\){f0 {Fwqw_ w~͛O??>??>|tw _|W/.n^|{wՋ] 9`xyxŷNJD]NHu׃>u,Ҝ8 -3HύWo."@oxP ˖)a3W6(b?J9a?1p=<%%:qSr<<3V"O,Nsf,4i-Ԃ-:QKbgbz>I zPӆH] -ki+w]d93%hK ;8@v ur#)-lpF3zF.SNWrsM,gY*QSIӏ ͒Vҭ&<ƂwJ<ų*UR -DW`BJ") n(13XHO|hu\Z܀kbX;_8%En)"QSzPhz{U? V9h/xE9bQQ')=1(/': :m.NC !]7%̩Diu]$<Tf4]#) -Ό_'y͠PJ0Zsi$S6Vfq9 7XiU˳%WfQQiȉƦɞ 8k3c%\?I‰fo*Ҷ) SGnlU ҳ[!Be9{h -'5 "h?]SuQpJt6FKiYzcrrgA]]Av ܀xD5Ama'7< E+SHBx~7# - 5g&LGQXYן^|}vʋ|Rg>ƽzNɳ3M#{1b{=Q5F%7jw9 .Tc>Aef3+ϣai1z,NN7j"l8: tu/@Mrkd 6XnxKH_i-60.Ĩ>7e/YoR/j0Rrr+;wUO|;(`x{d*긐.,T_E$45y5XPJ! f=y}+_F0D淤;| (yǒ9[ -nXQi,S̛Bd~i\ fgqd冲VEc -&vT9\BJ).l>?k48bhd>-X1![p4lP%H0S^rNl;'kH, -1Ў3 ӅF¬SִeLex 5Mgk'u!Ʃ0I'9L~egOt_"NӢp܏xU߳9jz286پd,j!琌̉1\n A87W{ϴ:, $#dvSp#9"C]ƌҖHIG4\rr&ܼcӲ,UaYDxW~SNQ ։eA v F6䵫ksi\KOLұd@m1S=+m rj1Ёaps#–j"i_<]!$|&|.NyDWLҪ0p$lb wі*]q4Q/^lnZooo;])Q)Usm).J%d:?]o-R& -]2'DK>bWy,1$z4 +IAHL̎* Uhج!0DWK蚐d.iJ/d&9D(")0=H,qO:!bLI5aFK#HʡBBpղJ - 0V -!4_%1鳞HOMpX7[r J4atD`JYt#9:"-ֆe\.I]6N1 ՂA5TS*86h-D<3sH`;lhISP9ȧ}P{&8w -ۨ`s[Ņ3y_6 -%iC7f}Y,2` -gq@:FPVE|Uu[i-Et +8vevgs.TJg]fiK -)5.x -(Ԑ͐4 }mxa [c02Tz/%Yj02@\1M'˜Z;I5!2*X+:l -mȻ4U-̨M yW0kUE'^H7JW" -paO" xH n@śi n<]"^HWza9k:4TecqB1ѭ%cB~ZG\OCoXQAh5M : -hg" ~|5H"sOReu;JRc3͉%dQQ [d kҁH v3jy?\>B}%C43#9b}`.˚|DGL%pdU2&yãdY#qepP|)+sߣgNVȼ&N4Z_"GCP,C 3fdLBV[iα{OD]VǕD -!Z YG 6 d-r8f+ SMoS,t!MO NWJ?m -C"ؠb -U`8~7V-UqHG8Tq@kI]PRk(k͖c 1%)v%l4 5-j&fy*BĘ -hR4s,J*TN&,[\]%튛NVrj,-bsXK.o;O'y$L4$,HW'/vn|FH -C5 7P*('V{MqV8*@wJ-I[W3rV6jq.2j*1TR'zŲfUmvpf3e] `9su\őORCdP]*fT[ ^6lydeMkg`@By :.bUm^Wѱ-c:lLP-.6[ܳdWݞKݫI6"6GFK Jx*R^ܨ #E>׹h.B!H53Ic?bĨӷH{Ҋ,;ϔ`|Vv]xZ mxY)lӡw޲W*o>g{b @ش;E#W6isK*N}k\2WQ j50ڀY!]P9e#v1c sZ󲱣#Ja{/j"Ht%k+O$L)ʠRMG[80>Vr>XST2٤9A!I)|N6L;cZkvT@Y -Jh:TB;iQqRƺbɨCW$b~ %BBE!)˰v¡zNXk@PʩS}Q -X2]@ƫXL -Ы=_uaԾ Jɢ 9l~}Y -@m*4s?nz lދrFD:l",Br0,F3HzeढEռlQ+9f2Yc8[ -aNҏ0Q ɤw 4F`|mV^0چԄO Aʂl4 uD!T*DO@yl;#RzķkJvƄlL9uzsV@(Y-ŠuE>pZ AU4S N ;?֕Fc, %f`,{ɨv,Rf)s71~;HЧݵ+"(jkʂiMZGbd`pJ< Y|\n6lG]=62xJ[ul$' -2P-Fj ^>AM\M,mKq)i6#'|l|xSR2ᶥJMqlSd93T5js)hV"2J&/Kcŀhjq9n$KC п|::#?)@>fTBy0gQ}Шv?e}+d5]oYFZA*Q* H\D2C}zF>D:Ig.|+lf+Kep;vEMQJ!R|8"nM0Λ1cJP(kVΡ9(+AQN ZH7$Ʋ$c~8 HDп&~|#h! -Wzz&'MxzRa^󚚅ҠwxZH6;WAҢ&HZHhy`Q-.nh$upB;I=/$|:9RVB!GdǼYGY5YLq>[4ŐP-y*(+1 S$nT`4ӐT.nAΉ F iøxLY#TIdm^Qe޵|H 鳔rvhdl+XyG[S|Ǫ%HZ_ )ƽ"\9]2! - tF["=\uYN#f#(`_2jk3J1ہ&`?>iyB$o%Fӿ6q(b`eI,I~10G.ߟ*beGt.p֟mb2ܐE6q;nMeVmcûsukn= _*wGv%x}!/t! .>?]yҩ92UU8O.E#C+Lr3(vἎ]@d$=?>|tGVUƗ-n2v|MzB -endstream -endobj - -4975 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [243.07924 732.5514 254.07924 746.2134] - /Border [0 0 0] - /Dest 4552 0 R - /F 4 - /StructParent 260 - /Contents (63) ->> -endobj - -4976 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4360 0 R - /f1 4354 0 R - /f2 4384 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 261 - /Tabs /S - /Parent 1 0 R - /Contents 4977 0 R - /Annots [4975 0 R] ->> -endobj - -4977 0 obj -<< - /Length 4873 - /Filter /FlateDecode ->> -stream -x]~\nNOH) E-|N\4kwbvfE4;v_vwDQIK'w7櫯Κv{s7?5Wnmwfgg/yvvǛ7Ͼ~F6Tk[eoЦ/gWL6ޮϞ^zsvN6J5?׿}?lvvJJwTJ ep=$)5eԪQrU;nl>PMC|gxz@q;LG*FZ@9K:.U}xiYSaڈ;cKW8Ŭ}u"~:?[5怗Ə^\cŊqvg{N气 ۘ"Z`hcMtϨkdn;Ѧ+l솚!} 0ƎDK!|$v8(ww^dC6$^gC\dX57{M2 h3o E~1&ؓE+ -,.UZVueh41 -eB^A;2hv! O1R=TyyFXsM7B$~i+l:/wuV\Z5 )4KG:8aX*9i'v^f<jdNY-C,ta{5 -6V#8#`Bᄌ*QR)!jdJ8nM15( Z8T[ܫ6P`RPA33 WЌv|D/*b]']UfEOqt3t['MF?IJJ( l@Uilti? ]}rvlBY;HQ^[_TA׵ҸKD6Ⱥ٫%E2ꐮR2r):עuF -mXuRYÅ`h0a3Occ;%]I~%F2e&[72Ō3h FE#xz`<^-"{?t. qv4z`qA!!tUKelf~NO EНjIop/Ŋؙ GwdQދs%`9I!2 `Y2BdzUQy)^Ac>Iۉ[w{T܄ɼ Zxf<#*0&K%_8r y@SnT"~Z -kB`G8".#˩Rv/<1Y)Aӊ#.A煹) g%R:8%2Y(_-B#;\ɟ 0f MTMȔA{Rxfʁe}-{ F.tOUA&drōfsuu3( 7 -ig& 0ї -4A(lE~N]2萈VQJ YlqK P{9~Y -:6MY ${ٚgz^\Fx-CWx{\F&8F/Ȫ?8ATH6=`E:6jbUL!d03^Tz_C$HT49aX16J֜R˖vO*cnu*" "74*JH3nT1,pBH4Z, c#{)q΢Ke. #7.sVK%oGҞ*-p2?9[z+oZ'fd\ZK4-J OUS{_~98𗸀97̥&rAj߰uŇ.̥l+,vs U$6S]9Y[KpG#C{pL[ ~JC tg:6sf4 jfnOUW[-.\ -r>ieů5;0:iPd=#G\NWRE+@ֶ͐'iKY0%uZ5'o0l5Nz^p#"\wHqnyUՠ'IOg!￯= -DrBA=O)eZa8'޷)%xi UiyAL<}~rRGN4qiiJiՄ:T;)ًc -l543&"5d|X-D#C\} 3V-بA -g"Do13Yfǀs'wߤ!5ȶ @eZf s --gL[W0.(u&T9UitsvwDʁv~*Rt?Ptn4m$ƸjY!čV cɛsUr]3VM[`7QQA˸+{~e7#"깚EڿDYy3V"ltwMaS3(X-Pq | ֕#cK[}5A"VM,{#S[+^[>؇j\HIIX -P>Fo%GT̖ͥldߐK%RTRThM@.u>RIrL9 V%Ixc+;[ple6G۪ORڡ =5տ4% "JSĐH~M$,W*s>фKL N6ہ@p@V+4lG`ѝ|b9B`Aխsb4Mk~Q ['L曖Q{sXI45HЧLgC:d geo*/WMm<b%|M9 ,N8,hHj'ֽ E)}2.5J\.,vA_"RvO6nnCym_~7?5W/?|mwfÚjPwS"(w+2 -endstream -endobj - -4978 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [214.10814 643.7794 225.10814 657.4414] - /Border [0 0 0] - /Dest 4553 0 R - /F 4 - /StructParent 262 - /Contents (64) ->> -endobj - -4979 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [448.53702 520.8834 459.53702 534.5454] - /Border [0 0 0] - /Dest 4554 0 R - /F 4 - /StructParent 263 - /Contents (65) ->> -endobj - -4980 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [214.26477 397.9874 225.26477 411.6494] - /Border [0 0 0] - /Dest 4555 0 R - /F 4 - /StructParent 264 - /Contents (66) ->> -endobj - -4981 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [127.68758 213.58142 138.68758 227.24341] - /Border [0 0 0] - /Dest 4556 0 R - /F 4 - /StructParent 265 - /Contents (67) ->> -endobj - -4982 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [297.06018 172.5954 308.06018 186.25739] - /Border [0 0 0] - /Dest 4557 0 R - /F 4 - /StructParent 266 - /Contents (68) ->> -endobj - -4983 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [418.09393 172.5954 429.09393 186.25739] - /Border [0 0 0] - /Dest 4477 0 R - /F 4 - /StructParent 267 - /Contents (21) ->> -endobj - -4984 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [402.94513 158.93341 413.94513 172.5954] - /Border [0 0 0] - /Dest 4558 0 R - /F 4 - /StructParent 268 - /Contents (69) ->> -endobj - -4985 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4360 0 R - /f1 4354 0 R - /f2 4384 0 R - /f3 4366 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 269 - /Tabs /S - /Parent 1 0 R - /Contents 4986 0 R - /Annots [4978 0 R 4979 0 R 4980 0 R 4981 0 R 4982 0 R 4983 0 R 4984 0 R] ->> -endobj - -4986 0 obj -<< - /Length 5815 - /Filter /FlateDecode ->> -stream -x][[~_q\mb_ -רRdߒ<׉FN7 -H:Gp8ijv^,Dp8f8x~yf3<}z6 7n]\~opo~|ڼ>{lg/~qv/W=_|_{&>\ 3oЃӁIp n~=ï7/pywvB Ǐ˟Ͼ{\Y o}r3˹ڃR5LM L̤ J?91\B-gj AOWU3ޥ<;3 *h_DȴiM#úɸlcbY2{|EmvD,U=?bJ㙰]0\~u_Vg{4n^z;_!yqP*"GyEV5$, YZIM[pPe## ׿$:sqSvפT -Yډ0LM~{"L׫|w1y"WùJ Ldt.(WBX#dF8-ZxS]6_?a2qPZ* ';)]ȶh3(\5QܤZjTTR- ēux=h,9\ 2mF#dJ" n] &7hI}-׸dΤK#u(N@h?։~F΋Ԩ҅1c7)e#/[Y&5hśvf:\ xUTAκ6ٕ@V-,vy2 ,+BYhb*l4N EFLzck!Hɜ\17߮syW8ųpeOp; R%;Q^0]JJ& GMHJ55!MNGaPRgѲf qXϥR46&&AχLd*OOnu*:#`Md:청`Y0-RsN3!0`%JerİLͧYHov6J+b[/[<.HDE.R-ҷ#ynEy঄eJ-{wy5OvS1\/3_׸LIeZycm>f)#Z/::\#?~b#+Cf ClXj/)U]Y%rժ1=!yNM -"s!6#ZPd6Zu!v&D08B2 -'GcA8슁ݬF -Id[؂qoQ <i?ߓ.0Cwv5@#opѨl40h),u@>:#/ [$kX4F=VYI"GowWZ͡_pI TrMC SjHA<k)GyI%cMv"EfF{Jq]v#噗_"z5g1qʍk47#Zr=AD\ySEe"]s~p;6j!)( 01+#FGd+,+tbE` "-&  DP})ByyJ+x>b`ZdžO+EnW]ڮ0ʀWip?ԡg3^K^7]>WQ#EN5]FjQJS3n O9U(zRٮ@tܩù[a5z 7bh(%UP8xfߜBfт&e ۹K(gmT]jZ C:R5s~EJ*j1w9kX9ő:F(mH=#fΑT,pfxd[5oIvdž5)V0C j2"Mb"&9jH(Q歑\1}|5KərR%/TdE$ſNߊD+!FXlrm*NB t ,jZ+e -:Ҫpq(edmY,@.ߋ#^wa/&K"Ks[v5֓c7Nۨ7#>rZ7z/8URxTk${lt_~q}xhJ />NpE.E<3ib+,@tT-C -y}!9ƍ}duj2n@ &C, U9.0-YD:RiD B۩'oeR#ZkGNJKeZf^7 lمYʏЪZ]ʠYw SΟ?Vi#+7. +kRbZ5X&?29!+)#bK汪6$eBE.rޝk䈽zQKz"=_7:s |g9ߴUtԧ>ʤf{<l{{%LV2mn5;!7\V:nȩVX<,X Wl+D @oKdTz O;UIws^9o%60fJM%|F/#(ɳ-$foa2TFWzĥN!}wVCӯVB3x܉L evlRnBInt=kxuJ&fp/Z8vo6s;c<eEnk.} vX!Eח.̢)Rx`X{1bM!MڹIp M#' ī;괕23'jFfc`pZ.ˎ2c?Ee쩮 Uh'ћNf6Ő͂F"=@Đx9lJ:ڛ(/cK3{jC\1a-rYX@o nur yz!oka2"G(68zrYJ(H+j~jhthI{U гk誇P?pJ~(aQxyHFXYNYW:M4{Q:󰲜qi 8AXHutvr;)ySlE~|9)N -^P91~h*%G6Ee_ -TST2er8}ro oc=NHMoIRbe۸G s#:OR{@j iMK_z*˦ 8ʝ!f 38:8Cj% -n$:FbE95粔ly)\l+w3 -z=$d9\̮UO?LvIci58,i㌣qqBNAlxU9'#+ܧ=tma;%pPo2(pv8`z} -:=pL@&,ځz#TvQ߮[7/r=caICa9Me+1WTYjüHi)l s%ωÔ!HF`c9ߊz ,%]2DCpf*:_d1W"FJWrr0 [ЍHv72NݖxУCl4/+k"8>HEΏOM+߳\ :&Kr㭆9{,c&t<ԕZc*ԜF+3 -V<+C 5x:ha}W(h%H3&۪tz4⡅MaҀ qtƟ0eډBF쑡0B/$%ɻMZA.EYR1$(OzV,(ukľͤ?fΨ=Ѳy&gNImTv]{YEθu3 (`ώ;+vM{^0W_zXܣgis`j@GA6I%`3J>QId }sq]W$*)/@Iř^OcQCT'`^ʦ)})?¾,g/]I+g[k8i!B%XTᅠL8YnŸARXfEA⧤=/da47lPY_9ntq/fVL)Z=2"/!d! ]NZ#Ǎ1=9$ e-!rܶM+O _`^foNM8ϡtt}aR*.¢rL?JR2ޱv*MWc :ӲnfkV*.q-WN?elLޖ%}|&ԢZ`g^5N~ZT*rBh{ST%RIXIf2ܐ A9S}0zS$O]Jbܤ0DH6UHTԀdbN@eh8 V+қn.·oOĦSQr)MPzL)\$4Ac q˅_@ uFp@?@1pD,]emx+9/⛑cp}@( c-J~nNZ(عR+<aMECBlր$$GT&ˍ#ᤛn~2 -(/TPP7'R8r YzX!}4ЇgAȃrNl0&/ -I钰6](0Bo$#"e@j~A>d)/`:@J,Ax1#V8DdV"?k 43%B+#2r~\~_R6OĢ3y&@3"0Mfƴ?"y~twz;0e30|ލ_]n&,cɢ:~m -endstream -endobj - -4987 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 642.7554 114.800316 656.4174] - /Border [0 0 0] - /Dest (sec:preliminary) - /F 4 - /StructParent 270 - /Contents (Section 2) ->> -endobj - -4988 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [348.7979 581.3074 402.13605 594.9694] - /Border [0 0 0] - /Dest (subsec:effects) - /F 4 - /StructParent 271 - /Contents (Section 2.1) ->> -endobj - -4989 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [338.8493 553.9834 349.8493 567.6454] - /Border [0 0 0] - /Dest 4559 0 R - /F 4 - /StructParent 272 - /Contents (70) ->> -endobj - -4990 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [355.08704 553.9834 366.08704 567.6454] - /Border [0 0 0] - /Dest 4560 0 R - /F 4 - /StructParent 273 - /Contents (71) ->> -endobj - -4991 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [419.0758 526.6594 430.0758 540.3214] - /Border [0 0 0] - /Dest 4561 0 R - /F 4 - /StructParent 274 - /Contents (72) ->> -endobj - -4992 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [245.40627 342.2534 256.40625 355.9154] - /Border [0 0 0] - /Dest 4562 0 R - /F 4 - /StructParent 275 - /Contents (73) ->> -endobj - -4993 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [193.23015 219.29541 244.80914 232.9574] - /Border [0 0 0] - /Dest (subsec:revertible-effects) - /F 4 - /StructParent 276 - /Contents (Section 3.1) ->> -endobj - -4994 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [395.6463 198.83337 406.6463 212.49542] - /Border [0 0 0] - /Dest 4563 0 R - /F 4 - /StructParent 277 - /Contents (74) ->> -endobj - -4995 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [360.2746 144.18542 371.2746 157.84741] - /Border [0 0 0] - /Dest 4564 0 R - /F 4 - /StructParent 278 - /Contents (75) ->> -endobj - -4996 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [378.12582 144.18542 389.12582 157.84741] - /Border [0 0 0] - /Dest 4565 0 R - /F 4 - /StructParent 279 - /Contents (76) ->> -endobj - -4997 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [75.57414 130.52338 86.57414 144.18542] - /Border [0 0 0] - /Dest 4566 0 R - /F 4 - /StructParent 280 - /Contents (77) ->> -endobj - -4998 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4354 0 R - /f1 4360 0 R - /f2 4366 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 281 - /Tabs /S - /Parent 1 0 R - /Contents 4999 0 R - /Annots [4987 0 R 4988 0 R 4989 0 R 4990 0 R 4991 0 R 4992 0 R 4993 0 R 4994 0 R 4995 0 R 4996 0 R 4997 0 R] ->> -endobj - -4999 0 obj -<< - /Length 5610 - /Filter /FlateDecode ->> -stream -x][d~_qfgMOjݥ8^o"! gR:$t.=/SUPEQ'䓫}s8?ۻ8|o~t~?޽]}i_}Wz;|׿_NvQ]"zll}lq%<>^*~w?H)>+M/Bӡ:bJmCzS;: *+6sSҝs85o-1*SMG_w7Zhٻ?s}c;= 8L{yv4|VDKqZY&EΎzԅ" C5|idZs$)cbˉ S駋8^X;95iuXKm.L$,Ũf*PB&ֲaײ|-)К*䒑w.Tzd4TjőyHEg62B];uS郍L\=_kV.[w`V楼N} )Օ X G:OG?imW ꩵ,X)N(3#^s8'`q81R7(oqJL3R;8lX?,DZYҹۤ[TmCSd:MQ,emNrS2i!1!/;ם6Mak+Wȱ/sNeN+ 8hT\|[m8ћ^l^S ri}P:YFzǾ}Y`Krf (Ϗ]o -&dS1>q|{`=CE83BJ&{$`Owxd 7*(?Q>0l u:+c܉Vjnf -l~]MYn8gBT6Ia? XFd3 Q;⹢yObNX)wY[8VG`#2gS`1"\ *B&T5D6fHЂΜGH$8瞞w.)q++獵mDZyst]۝ҙ6xxzE5Y5cYG-εHn)FBw:Ӿ5(?1Jxg_#ey+Uf5_Tzؘ(W~WD!7""5Bq0~aGդz2T|Y 6Aл-QJכ^&cV򒶕ڷ'hƳ,/o[#vĵA reֽ=102@su Y C>4ȑrgfQժu9:ufCjSTj:g N/"AZ>8m7u/|\ f1uT^()KbS_P? Xe{")df۸5 ++5\wQ vvOF>MHg@E\[*+ѬYm7uⰪ2~]֓t4٘:wXcEf.,- ^',k~TF:^y! -B[F^[܈:NEp!QK*IX*mW7(0vh츮$C`LHV~?әmfl ˚N`998V;mA8 -+T_ -fXuu(pf(D3A->1d!@IGVf3AW)v5=4GaC5-1 -߯hwEwzG3a -%Q Ii`J@&[`MԕֈԑQ!Jf1vlo-JX!,M!GidOPBm؛{68!* 5fhs![a|z.LKwj|ya~/PђT0]q:fS6C H{>5FĚ`J+a/ [l)ʨfy0ExI*̷Q6 -^JI8\ -0(=<WbC_wDV̩[b1䈑ڪPc3dq&692j -n DmXg V-ғ׶p:Rkjlzۛ7A {L3+L DQMIoB @VPtSM4qZބqh귄Ln\fGz 72ZѪXPק໡\1Է%ON lbj2< U3M-Z64D!%EpFI3Mv16n0](U BC˸K59vΕ. g|'&82zpSY(;Jѯ`OvF?sY'l0^B"Pf)2jPԨ'N *J5m^"-: -GڄH+l=s* <:!3m$N 6 W(oؓ\˩bJm$Erl$imLl9$ Q[.SOT0E8GA 4$m$㱐?%M"s E$/xۣS+$& -H8"VG-^2r5r*,j_7`FF&4iZtC|62@7Ln*el@5`?s(h!0 1Qp)gA]C$= 5 +e@jN< N2`ZK<+ ;@nIqֿ`=E[:C`x{eCZE׀0`j`C:* Rhe]*w ^g'0>`Ԍ RJr'IiFrjf.9* -Vz֋qm5>pPȴn^ 9v(1]PfJ{mO -L*ۋii{ı~cϩ8uF%NzE;.e_[E0+j5gA+#Ae \ :̴mmY#(KKѐ5텷֪5>̕eP2<`OJrm+6M@0q0Tíi5+'d4.-Y#Ɬ@}_w>g4 q_U1F٣GP붋Zq tRyDEߊySX;Z$wl-.m$vMM۬2:p!/f,d_k-^,=_[B,·[1 7B!SH&'֊(Md;>6r@wXS3C%O2Q))kk6b/(%ysp[v:o0x5v5-"фzjr4 H;f2,t ߀臄f+o * (p}-M@@ѭR¸Ϫh*z;\e5<8B:«L_8a -ǜW'KI(TY'L[&˜aUtc, 6RT BENR KMA -< B[:@[Y,P`8ysQ754 mwN1 )AxoFv'#\o{mSZӶ<~O򫯤|ŧcmo ޷sZpƮ5Hbx /d֙/ʻluZi*TqdT-'='j'\zOC5)[?D4-!z%t[ Y'MY*c%i*Ľ}!Xb5Gs(..E+]=Gff\ENP*^l;9вg4 34@zaa2_5J"56~$Ekk+8%kxu675v7}.}Mj2KxS - R ]bC#!hB+XNJbPXv  -ѕԖAsZ[kV&g6W儲Yrf 8kUrQeA,9]/t!;03hHюۊkQ)yN.ϯ uYe
- -

{t('welcome.title')}

-

{t('welcome.paragraph.0')}

-
{t('welcome.paragraph.1')}
-

- {emphasizedFeedback(t('welcome.paragraph.2'), t('welcome.feedbackEmphasis'))} -

- {state.error === null ? null :

{t('welcome.error')}

} -
- -
-
- - ) -} diff --git a/packages/client/ui-settings-general/src/client/index.ts b/packages/client/ui-settings-general/src/client/index.ts index 3a868dc3b4..e1a94934c7 100644 --- a/packages/client/ui-settings-general/src/client/index.ts +++ b/packages/client/ui-settings-general/src/client/index.ts @@ -17,9 +17,6 @@ import { bindSnapshotSelector } from '@deepseek-ai/dsh-client-web-react' import type {} from '@deepseek-ai/dsh-client-ui-settings/client' // Type-only: pulls ctx.locale into this program. import type {} from '@deepseek-ai/dsh-client-locale/client' -// Type-only: pulls the ctx.remote merge and the forwarded-event key face -// (the settings invalidation rides the allowlist) into this program. -import type {} from '@deepseek-ai/dsh-api-remotes/client' import type { SettingsOnboardingStep, SettingsRootInjected, SettingsSectionRow, } from './shell-contract.ts' @@ -29,10 +26,6 @@ import { GeneralSection } from './GeneralSection.tsx' import { SettingsDocumentAction } from './SettingsDocumentAction.tsx' import type { SettingsDocumentActionInjected } from './SettingsDocumentAction.tsx' import { refreshDocumentIfLoaded, SettingsDocumentStore } from './settings-document-store.ts' -import type { WelcomeNoticeInjected } from './WelcomeNotice.tsx' -import { WelcomeNotice } from './WelcomeNotice.tsx' -import { refreshWelcomeIfLoaded, WelcomeNoticeStore } from './welcome-store.ts' -import { WELCOME_NOTICE_SETTINGS_NAMESPACE } from '../onboarding-copy.ts' import { en, zh, type SettingsKey } from './locales.ts' export type { @@ -44,8 +37,6 @@ export type { export type { SettingsDocumentActionInjected, SettingsDocumentActionProps } from './SettingsDocumentAction.tsx' export type { SettingsDocumentState } from './settings-document-store.ts' export { SettingsDocumentStore } from './settings-document-store.ts' -export type { WelcomeNoticeInjected, WelcomeNoticeProps } from './WelcomeNotice.tsx' -export type { WelcomeNoticeState } from './welcome-store.ts' export type { SettingsKey } from './locales.ts' declare module '@deepseek-ai/dsh-client-ui-slots' { @@ -63,7 +54,7 @@ const NS = 'settings' * ui-settings' apply, whose activation order relative to this one is NOT * constrained; registrations depend on their slots through `slots.inject()`. */ -export const inject = ['slots', 'locale', 'connection', 'remote'] +export const inject = ['slots', 'locale', 'connection'] /** * Register the `settings` dictionaries, the chrome content, and the General @@ -87,27 +78,9 @@ export function apply(ctx: ClientContext): void { const useSnapshot = bindSnapshotSelector(documentController.store) return (): SettingsDocumentActionInjected => ({ controller: documentController, useSnapshot }) })() - const welcomeController = new WelcomeNoticeStore(connection.api, connection.isLoopback ? 'host' : 'memory') - const useWelcomeSnapshot = bindSnapshotSelector(welcomeController.store) - const welcomeInjected = (): WelcomeNoticeInjected => ({ - controller: welcomeController, - useSnapshot: useWelcomeSnapshot, - }) - - ctx.effect(() => { - const refresh = (): void => { refreshWelcomeIfLoaded(welcomeController) } - const disposers = [ - ctx.remote.$on('settings/document-updated', (ns) => { - if (ns !== WELCOME_NOTICE_SETTINGS_NAMESPACE) return - refresh() - }), - ctx.on('connection/reset', () => { - refresh() - refreshDocumentIfLoaded(documentController) - }), - ] - return () => { for (const dispose of disposers) dispose() } - }, 'ui-settings-general: metadata invalidations') + ctx.effect(() => ctx.on('connection/reset', () => { + refreshDocumentIfLoaded(documentController) + }), 'ui-settings-general: metadata invalidations') // The settings shell: this package occupies the sidebar-owned hole and // declares the settings slots. Ledger → nav-row projection as an observable // source (uSES contract: getSnapshot returns the cached rows until the @@ -202,11 +175,4 @@ export function apply(ctx: ClientContext): void { locale: NS, children: { 'settings.general.item': { kind: 'list', scope: 'root' } }, }, GeneralSection)) - ctx.slots.inject('settings.onboarding', () => ctx.slots.register({ - name: 'settings.onboarding', - id: 'welcome-notice', - order: -100, - locale: NS, - inject: welcomeInjected, - }, WelcomeNotice)) } diff --git a/packages/client/ui-settings-general/src/client/locales.ts b/packages/client/ui-settings-general/src/client/locales.ts index 41a44eae3f..a557855323 100644 --- a/packages/client/ui-settings-general/src/client/locales.ts +++ b/packages/client/ui-settings-general/src/client/locales.ts @@ -1,5 +1,4 @@ -/** Shell chrome, General-nav, and welcome-notice dictionaries; feature rows own their copy. */ -import { WELCOME_NOTICE_COPY } from '../onboarding-copy.ts' +/** Shell chrome and General-nav dictionaries; feature rows own their copy. */ /** Simplified Chinese dictionary (the key-set source of truth). */ export const zh = { @@ -9,13 +8,6 @@ export const zh = { 'openDocument': '打开配置文件', 'openDocument.error': '无法打开配置文件', 'general.nav': '通用设置', - 'welcome.title': WELCOME_NOTICE_COPY.zh.title, - 'welcome.paragraph.0': WELCOME_NOTICE_COPY.zh.paragraphs[0], - 'welcome.paragraph.1': WELCOME_NOTICE_COPY.zh.paragraphs[1], - 'welcome.paragraph.2': WELCOME_NOTICE_COPY.zh.paragraphs[2], - 'welcome.feedbackEmphasis': WELCOME_NOTICE_COPY.zh.feedbackEmphasis, - 'welcome.continue': WELCOME_NOTICE_COPY.zh.continueLabel, - 'welcome.error': '暂时无法保存确认状态,请重试。', } satisfies Record /** The settings namespace key union. */ @@ -29,11 +21,4 @@ export const en = { 'openDocument': 'Open configuration file', 'openDocument.error': 'Could not open configuration file', 'general.nav': 'General', - 'welcome.title': WELCOME_NOTICE_COPY.en.title, - 'welcome.paragraph.0': WELCOME_NOTICE_COPY.en.paragraphs[0], - 'welcome.paragraph.1': WELCOME_NOTICE_COPY.en.paragraphs[1], - 'welcome.paragraph.2': WELCOME_NOTICE_COPY.en.paragraphs[2], - 'welcome.feedbackEmphasis': WELCOME_NOTICE_COPY.en.feedbackEmphasis, - 'welcome.continue': WELCOME_NOTICE_COPY.en.continueLabel, - 'welcome.error': 'The acknowledgement could not be saved. Please try again.', } satisfies Record diff --git a/packages/client/ui-settings-general/src/index.ts b/packages/client/ui-settings-general/src/index.ts index 0cea245db5..ed600b1c1c 100644 --- a/packages/client/ui-settings-general/src/index.ts +++ b/packages/client/ui-settings-general/src/index.ts @@ -3,28 +3,24 @@ import type { Context } from '@deepseek-ai/cordis' import z from '@deepseek-ai/schemastery' import { settingsNamespace } from '@deepseek-ai/dsh-settings' -import { - WELCOME_NOTICE_ACK_FIELD, WELCOME_NOTICE_SETTINGS_NAMESPACE, -} from './onboarding-copy.ts' -export { - WELCOME_NOTICE_ACK_FIELD, WELCOME_NOTICE_COPY, WELCOME_NOTICE_SETTINGS_NAMESPACE, - WELCOME_NOTICE_VERSION, -} from './onboarding-copy.ts' +/** Durable settings namespace for product-wide GUI onboarding facts. */ +const ONBOARDING_SETTINGS_NAMESPACE = 'ui-onboarding' interface OnboardingSettings { + /** Last version acknowledged by the current product welcome step. */ welcomeNoticeVersion?: string } const OnboardingSettingsSchema: z = z.object({ - [WELCOME_NOTICE_ACK_FIELD]: z.string(), + welcomeNoticeVersion: z.string(), }) /** Register the durable GUI-onboarding section when a settings provider exists. */ export function apply(ctx: Context): void { ctx.inject(['settings'], (settingsCtx) => { settingsCtx.settings.register( - settingsNamespace(WELCOME_NOTICE_SETTINGS_NAMESPACE), + settingsNamespace(ONBOARDING_SETTINGS_NAMESPACE), OnboardingSettingsSchema, ) }) diff --git a/packages/client/ui-settings-general/src/invariant.ts b/packages/client/ui-settings-general/src/invariant.ts index adfd582ca6..10db92524e 100644 --- a/packages/client/ui-settings-general/src/invariant.ts +++ b/packages/client/ui-settings-general/src/invariant.ts @@ -16,7 +16,7 @@ export const inject = ['invariants'] /** * No runtime invariant: the settings seam validates and publishes the durable - * welcome section, while slot conflicts fail loud in the slot core. The local + * onboarding section, while slot conflicts fail loud in the slot core. The local * document action is browser state over typed RPC responses and is covered by * store/component tests rather than a Cordis runtime relationship. */ diff --git a/packages/client/ui-settings-general/src/onboarding-copy.ts b/packages/client/ui-settings-general/src/onboarding-copy.ts deleted file mode 100644 index 8b29402b4b..0000000000 --- a/packages/client/ui-settings-general/src/onboarding-copy.ts +++ /dev/null @@ -1,35 +0,0 @@ -/** Durable settings namespace for product-wide GUI onboarding facts. */ -export const WELCOME_NOTICE_SETTINGS_NAMESPACE = 'ui-onboarding' - -/** Field storing the last welcome notice version the user acknowledged. */ -export const WELCOME_NOTICE_ACK_FIELD = 'welcomeNoticeVersion' - -/** - * Bump only when the notice changes materially and every user should see it - * again. The acknowledgement is compared for exact equality. - */ -export const WELCOME_NOTICE_VERSION = '2026-08-11.1' - -/** The complete editable welcome notice in both supported GUI locales. */ -export const WELCOME_NOTICE_COPY = { - zh: { - title: '内测声明', - paragraphs: [ - '感谢您愿意拨冗试用 DeepSeek Harness。当前版本仍处于内部测试阶段,功能仍待完善,体验难免有些粗糙。', - '“如切如磋,如琢如磨。” 产品的成长,离不开一次次真实的碰撞与坦诚的反馈。您在真实使用中发现的问题,也可能促使我们重新审视,甚至推翻已有的设计。', - '内测版本默认不会上传 Session Log。如需在提交反馈时共享会话日志,可以设置环境变量 DSH_TELEMETRY_MODE=FEEDBACK_ONLY;如需持续上传,可以设置 DSH_TELEMETRY_MODE=FULL,但该模式同时会启用 dsh-sdk 命令遥测,上报匿名 ID、命令结果以及脱敏后的项目配置。另外,如果您有任何反馈与建议,请在企业微信群中留言告诉我们。每一条反馈,都会帮助我们把它打磨得更好。', - ], - feedbackEmphasis: '如果您有任何反馈与建议,请在企业微信群中留言告诉我们', - continueLabel: '继续', - }, - en: { - title: '内测声明', - paragraphs: [ - '感谢您愿意拨冗试用 DeepSeek Harness。当前版本仍处于内部测试阶段,功能仍待完善,体验难免有些粗糙。', - '“如切如磋,如琢如磨。” 产品的成长,离不开一次次真实的碰撞与坦诚的反馈。您在真实使用中发现的问题,也可能促使我们重新审视,甚至推翻已有的设计。', - '内测版本默认不会上传 Session Log。如需在提交反馈时共享会话日志,可以设置环境变量 DSH_TELEMETRY_MODE=FEEDBACK_ONLY;如需持续上传,可以设置 DSH_TELEMETRY_MODE=FULL,但该模式同时会启用 dsh-sdk 命令遥测,上报匿名 ID、命令结果以及脱敏后的项目配置。另外,如果您有任何反馈与建议,请在企业微信群中留言告诉我们。每一条反馈,都会帮助我们把它打磨得更好。', - ], - feedbackEmphasis: '如果您有任何反馈与建议,请在企业微信群中留言告诉我们', - continueLabel: '继续', - }, -} as const diff --git a/packages/client/ui-settings-general/tests/apply.client.spec.ts b/packages/client/ui-settings-general/tests/apply.client.spec.ts index 6c0f5131f2..d6c3ffff02 100644 --- a/packages/client/ui-settings-general/tests/apply.client.spec.ts +++ b/packages/client/ui-settings-general/tests/apply.client.spec.ts @@ -1,18 +1,15 @@ -/** Ownerless-copy registrations: the six seats, dictionaries, thunked labels, and HMR recovery. */ +/** Ownerless-copy registrations: the five seats, dictionaries, thunked labels, and HMR recovery. */ import { Context } from '@deepseek-ai/cordis' import { describe, expect, it, vi } from 'vitest' import { resolveSlotLabel } from '@deepseek-ai/dsh-client-ui-slots' import { SlotRegistry } from '@deepseek-ai/dsh-client-runtime/client' import { LocaleRuntime } from '@deepseek-ai/dsh-client-locale/client' -import { TestRemote, usePinnedBrowserLanguages } from '@deepseek-ai/dsh-client-test-runtime' +import { usePinnedBrowserLanguages } from '@deepseek-ai/dsh-client-test-runtime' import { apply, inject } from '@deepseek-ai/dsh-client-ui-settings-general/client' import { CloseLabel, HeaderContent, TriggerContent } from '../src/client/chrome.tsx' import { GeneralSection } from '../src/client/GeneralSection.tsx' import { SettingsDocumentAction } from '../src/client/SettingsDocumentAction.tsx' import type { SettingsDocumentActionInjected } from '../src/client/SettingsDocumentAction.tsx' -import { WelcomeNotice } from '../src/client/WelcomeNotice.tsx' -import type { WelcomeNoticeInjected } from '../src/client/WelcomeNotice.tsx' -import { WELCOME_NOTICE_SETTINGS_NAMESPACE } from '../src/onboarding-copy.ts' // The service reads its initial locale from the browser; these specs assert // the shipped Chinese copy, so they state the browser they assume. @@ -25,7 +22,6 @@ const SEATS = [ ['settings.action', SettingsDocumentAction], ['settings.close', CloseLabel], ['settings.section', GeneralSection], - ['settings.onboarding', WelcomeNotice], ] as const async function bench(isLoopback = true) { @@ -33,9 +29,6 @@ async function bench(isLoopback = true) { await ctx.plugin(SlotRegistry).await() const locale = new LocaleRuntime(ctx) ctx.provide('locale', locale) - // The plugins inject `remote`; forwarded events reach them through the - // same `$dispatch` handoff the connection sink makes. - new TestRemote(ctx) const settingsDescribe = vi.fn(() => Promise.resolve({ rpcId: 'settings-general' as never, result: { @@ -43,14 +36,7 @@ async function bench(isLoopback = true) { value: { writable: true, hasDocument: true, - namespaces: [{ - ns: WELCOME_NOTICE_SETTINGS_NAMESPACE, - schema: {}, - value: {}, - applies: 'live' as const, - secrets: [], - revision: 0, - }], + namespaces: [], }, }, })) @@ -89,10 +75,10 @@ function generalEntry(slots: SlotRegistry) { describe('ui-settings-general apply', () => { it('declares the services it uses', () => { - expect(inject).toEqual(['slots', 'locale', 'connection', 'remote']) + expect(inject).toEqual(['slots', 'locale', 'connection']) }) - it('fills all six seats for declarations before or after apply', async () => { + it('fills all five seats for declarations before or after apply', async () => { const before = await bench() declare(before.slots) await before.ctx.plugin({ inject: [...inject], apply }).await() @@ -105,8 +91,9 @@ describe('ui-settings-general apply', () => { expect(resolveSlotLabel(entry.options.label)).toBe('通用设置') expect(before.slots.spec('settings.general.item')).toEqual({ kind: 'list', scope: 'root' }) expect(before.slots.entries('settings.general.item')).toEqual([]) - const welcome = before.slots.entries('settings.onboarding')[0]! - expect(welcome.options).toMatchObject({ id: 'welcome-notice', order: -100 }) + // The onboarding hole stays declared for feature-owned steps; this plugin + // no longer seats one. + expect(before.slots.entries('settings.onboarding')).toEqual([]) const action = before.slots.entries('settings.action')[0]! const actionInjected = (action.inject as unknown as () => SettingsDocumentActionInjected)() expect(actionInjected.controller.store.getSnapshot().status).toBe('idle') @@ -162,22 +149,6 @@ describe('ui-settings-general apply', () => { expect(resolveSlotLabel(generalEntry(b.slots)!.options.label)).toBe('通用设置') }) - it('refreshes loaded welcome state only for its settings namespace or a reconnect', async () => { - const b = await bench() - declare(b.slots) - await b.ctx.plugin({ inject: [...inject], apply }).await() - const entry = b.slots.entries('settings.onboarding')[0]! - const { controller } = (entry.inject as unknown as () => WelcomeNoticeInjected)() - await controller.load() - expect(b.settingsDescribe).toHaveBeenCalledOnce() - b.ctx.remote.$dispatch('settings/document-updated', ['unrelated', 1]) - expect(b.settingsDescribe).toHaveBeenCalledOnce() - b.ctx.remote.$dispatch('settings/document-updated', [WELCOME_NOTICE_SETTINGS_NAMESPACE, 1]) - await vi.waitFor(() => { expect(b.settingsDescribe).toHaveBeenCalledTimes(2) }) - b.ctx.emit('connection/reset') - await vi.waitFor(() => { expect(b.settingsDescribe).toHaveBeenCalledTimes(3) }) - }) - it('refreshes loaded document availability on reconnect without reading it eagerly', async () => { const b = await bench() declare(b.slots) @@ -192,19 +163,13 @@ describe('ui-settings-general apply', () => { await vi.waitFor(() => { expect(b.settingsDescribe).toHaveBeenCalledTimes(2) }) }) - it('keeps remote welcome acknowledgement process-local', async () => { + it('withholds the loopback-only document action off-loopback', async () => { const b = await bench(false) declare(b.slots) const fiber = b.ctx.plugin({ inject: [...inject], apply }) await fiber.await() - const entry = b.slots.entries('settings.onboarding')[0]! - const { controller } = (entry.inject as unknown as () => WelcomeNoticeInjected)() - - await controller.load() - await expect(controller.acknowledge()).resolves.toBe(true) - expect(controller.store.getSnapshot()).toMatchObject({ status: 'ready', acknowledged: true }) - expect(b.settingsDescribe).not.toHaveBeenCalled() expect(b.slots.entries('settings.action')).toEqual([]) + expect(b.settingsDescribe).not.toHaveBeenCalled() await fiber.dispose() for (const [name] of SEATS) expect(b.slots.entries(name)).toEqual([]) }) diff --git a/packages/client/ui-settings-general/tests/host.client.spec.ts b/packages/client/ui-settings-general/tests/host.client.spec.ts index 5e82764f47..f5bc43b3e1 100644 --- a/packages/client/ui-settings-general/tests/host.client.spec.ts +++ b/packages/client/ui-settings-general/tests/host.client.spec.ts @@ -2,7 +2,9 @@ import { Context } from '@deepseek-ai/cordis' import { describe, expect, it } from 'vitest' import { SettingsProvider, settingsNamespace, type SettingsNamespace } from '@deepseek-ai/dsh-settings' import { apply } from '../src/index.ts' -import { WELCOME_NOTICE_SETTINGS_NAMESPACE } from '../src/onboarding-copy.ts' + +/** Mirrors the module-local namespace id in src/index.ts. */ +const ONBOARDING_SETTINGS_NAMESPACE = 'ui-onboarding' class MemorySettings extends SettingsProvider { readonly writable = true @@ -19,11 +21,11 @@ describe('ui-settings-general host', () => { const fiber = ctx.plugin({ apply }) await fiber.await() expect(ctx.settings.describe().map(row => row.ns)).toContain( - settingsNamespace(WELCOME_NOTICE_SETTINGS_NAMESPACE), + settingsNamespace(ONBOARDING_SETTINGS_NAMESPACE), ) await fiber.dispose() expect(ctx.settings.describe().map(row => row.ns)).not.toContain( - settingsNamespace(WELCOME_NOTICE_SETTINGS_NAMESPACE), + settingsNamespace(ONBOARDING_SETTINGS_NAMESPACE), ) }) }) diff --git a/packages/client/ui-settings-general/tests/settings-root.client.spec.tsx b/packages/client/ui-settings-general/tests/settings-root.client.spec.tsx index 430bb2daee..c9ec593974 100644 --- a/packages/client/ui-settings-general/tests/settings-root.client.spec.tsx +++ b/packages/client/ui-settings-general/tests/settings-root.client.spec.tsx @@ -229,7 +229,7 @@ describe('SettingsPanel navigation', () => { it('paints no takeover chrome of its own around the mounted step', () => { // The chrome (mask, opaque stage, #root inert) belongs to the step via - // the OnboardingSurface primitive — a mounted-but-deciding step that + // the step-owned dialog surface — a mounted-but-deciding step that // renders null must show and block nothing (the reload white-flash fix; // onboarding-surface.spec.tsx pins the primitive's half). const appRoot = document.createElement('div') diff --git a/packages/client/ui-settings-general/tests/shell.client.spec.ts b/packages/client/ui-settings-general/tests/shell.client.spec.ts index 0c95e8b8d3..32c354deda 100644 --- a/packages/client/ui-settings-general/tests/shell.client.spec.ts +++ b/packages/client/ui-settings-general/tests/shell.client.spec.ts @@ -49,7 +49,7 @@ const CHILD_SPECS = { describe('ui-settings apply', () => { it('declares only the slot registry (a pure composition face, no locale)', () => { - expect(inject).toEqual(['slots', 'locale', 'connection', 'remote']) + expect(inject).toEqual(['slots', 'locale', 'connection']) }) it('registers the shell and declares every child slot, before or after the declaration', async () => { @@ -110,8 +110,6 @@ describe('ui-settings apply', () => { b.slots.register({ name: 'settings.onboarding', id: 'default-order' } as never, () => null) const steps = onboardingSteps.getSnapshot() expect(steps).toEqual([ - // This package's own onboarding page, registered by the same apply. - { id: 'welcome-notice', order: -100 }, { id: 'welcome', order: -100 }, { id: 'credential', order: 0 }, { id: 'default-order', order: 0 }, diff --git a/packages/client/ui-settings-models/README.i18n.yaml b/packages/client/ui-settings-models/README.i18n.yaml index ddd679e690..f26ca67bc3 100644 --- a/packages/client/ui-settings-models/README.i18n.yaml +++ b/packages/client/ui-settings-models/README.i18n.yaml @@ -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/client/ui-settings-models/README.md -README.md: 642dc3ffc7f3f45a523cd6e84b13d34e2d25dc2a -README.zh.md: 408f2017636ef2d9a5a57fef253f2f05b61a22fb +README.md: f0094c4f2687beaf6a5e5f7a1a8dc3d4ebdbcbc0 +README.zh.md: 68bb64ddeebfd65644edbb5e11fd2e147214d44a diff --git a/packages/client/ui-settings-models/README.md b/packages/client/ui-settings-models/README.md index 642dc3ffc7..f0094c4f26 100644 --- a/packages/client/ui-settings-models/README.md +++ b/packages/client/ui-settings-models/README.md @@ -2,11 +2,13 @@ English | [中文](README.zh.md) -Models settings plugin: the provider configuration page and official-DeepSeek conditional onboarding step. It joins three wire domains into one shared snapshot — `llm.providers` (the configurable-provider directory with each route's live/dormant state), `settings.describe` (serialized schemas, layered redacted values, secret slots), and `credentials.describe` (value-free configured/source/writable badges) — and renders provider rows with one editor card at a time, without presenting route liveness as provider status. +Models settings and product-onboarding plugin. The same client Cordis plugin registers the Models page plus two ordered first-run dialogs: a versioned internal-testing notice and the conditional official-DeepSeek credential step. Both steps share one modal wrapper and remain sequenced by `settings.onboarding`. The Models plane joins three wire domains into one shared snapshot — `llm.providers` (the configurable-provider directory with each route's live/dormant state), `settings.describe` (serialized schemas, layered redacted values, secret slots), and `credentials.describe` (value-free configured/source/writable badges) — and renders provider rows with one editor card at a time, without presenting route liveness as provider status. Rows are the *configured* providers (their profile resolves in the owning namespace); a whole-section provider whose key is not configured anywhere renders as its open setup card instead of a row, but only in the first-run posture — while no provider is registered with the credential its profile names — and only until the user closes that card, after which it is an ordinary row carrying the missing-key dot. Each card kind owns its own open state, so closing one never discards a draft in another. The add flow is a card carrying the dormant-directory provider select — a bare-mounted `llm-pi-ai` offers its whole installed catalog before any route exists. The pi-ai card additionally edits that route's **model list** and can ask the provider what it serves. A row labels API-key state with a green solid dot only when a referenced credential is confirmed configured, and with a red solid dot only when a named reference is confirmed missing; reference-free provider-native authentication and unavailable credential enrichment remain unmarked. The editor is a hand-written card per adapter family: the primary field is a single **API key** input — the page never asks for an environment-variable name; a typed key stores **write-only** through `credentials.set` under the profile's reference, deriving `_API_KEY` when the profile has none, and the pi-ai profile records that derivation as `apiKeyEnv`, so `settings.yaml` never carries a key value. Leaving a new pi-ai provider's key blank saves a reference-free profile and therefore preserves provider-native authentication such as the Bedrock credential chain or Vertex ADC. A successful Apply emits a local accessible status message without echoing secret material. The collapsed 自定义设置 fold carries the curated extras — `baseURL` for both families (the deepseek placeholder shows the public endpoint), each adapter's model catalog, and the **display name** and **API protocol** of a pi-ai route the adapter does not ship. Those two are what a hand-declared route names for itself: the create card asks for both because nothing can default them, so the editor reaches both rather than leaving them to `settings.yaml`. Clearing the name unsets it and the route falls back to its id, which is what the placeholder shows; the protocol has no such fallback. A catalog route gets neither — it defaults its name from its catalog entry, and its models each carry their own protocol, so a route-level one could only override every one of them. The Provider ID stays fixed: it is the settings key, the name every other namespace and every logged session references, and the stem of a credential reference the page cannot read back to move. Reasoning effort is deliberately NOT among them: it is a per-model capability and the models under one provider disagree about which levels they accept, so a provider-scoped control could only be set to a value some of them reject — which would hide even the models that support the level. The composer's model picker offers each model its own levels, and a switch there records provider, model, and effort together as the default for the next session. The profile field stays in `settings.yaml` for a deployment that knows its route. Each DeepSeek row edits `id`, optional display `name`, and optional `contextWindow`/`maxTokens`; existing fields outside that curated set survive edits, while every other profile field stays owned by `settings.yaml`. A row is deletable only when the user layer alone carries it (removal restores the composition base), and its localized confirmation dialog names the provider in the title, description, and final action. A row is tagged **Custom** when the directory entry says the owning adapter ships nothing under that key. The tag follows that answer alone: having a stored profile does not make a route custom — narrowing a shipped provider's models stores one too — and an adapter that reports nothing leaves its rows untagged rather than being read as shipped. -The DeepSeek step projects first-run readiness from that same joined snapshot after earlier onboarding pages complete. The step exists to leave the user with a model to talk to, so ANY provider they can already reach ends it without rendering — a registered route whose named credential reference is stored, including a read-only launch-environment credential, or one whose profile names no reference at all and therefore authenticates natively. Only a user with none of those is asked about DeepSeek, the one route the prompt can offer a key field for. It recognizes the official adapter through its `llm-deepseek` configurable-provider declaration, so an undeclared live route with the same provider id is not treated as repairable configuration. Only a mounted, active adapter with a missing writable reference shows the page that opens Settings on Models, whose existing setup card exclusively owns key input and `credentials.set`; the step never holds a secret. An absent adapter, inactive route, failed join, read-only deployment, or unusable settings or credential capability completes the step without rendering so onboarding cannot block the product; Models remains the diagnostic surface. +The notice step owns its exact copy and version in `src/onboarding-copy.ts`. On loopback it compares and writes `ui-onboarding.welcomeNoticeVersion` through the existing settings API; only an explicit Continue records the current version. A non-loopback browser cannot use that Host-only namespace, so acknowledgement is process-local and the notice returns after reload. + +After that notice completes, the DeepSeek step projects first-run readiness from the same joined Models snapshot. ANY provider the user can already reach ends it without rendering — a registered route whose named credential reference is stored, including a read-only launch-environment credential, or one whose profile names no reference and therefore authenticates natively. Only a user with none is asked for the official DeepSeek key. A mounted, active adapter with a missing writable reference renders the existing `ProviderEditor` in credential-only mode inside the shared onboarding modal; `credentials.set` stays the only secret write, and no provider settings are changed. Configure later completes only this coordinator pass. An absent adapter, inactive route, failed join, read-only deployment, or unusable settings or credential capability completes the step without rendering; Models remains the diagnostic surface. Every edit lands as `settings.mutate` path ops against the stored section — a set per changed field, an unset per cleared one, and a single unset for a deleted provider row. The page only ever holds the REDACTED descriptor, so it mutates the fields it can see rather than rebuilding a section. DeepSeek's `models` is one replace-by-value array: the editor shows inherited effective rows until the first model edit materializes the complete array in the user layer, while reset unsets that override. A row carries the model id and display name; its context window and output cap sit behind the row's own disclosure, with the same fields the pi-ai provider form uses. Either capacity is typed as a count with an optional decimal `K` or `M` suffix (`256K`, `1M`; `1M` is 1000K) and stored as the plain count, spelled back in the shortest form that round-trips. Empty ids, duplicate ids, empty explicit names, and unreadable, non-positive, or fractional capacities fail before any write. A typed API key is judged on its own field the same way: after trimming, it must be non-empty and every character must be printable ASCII (`[\x21-\x7E]`), which is exactly what an HTTP header value can carry — the twin of `normalizeApiKey` in `@deepseek-ai/dsh-llm`, mirrored here because the source-plane split forbids importing it. A value matching a pasted `NAME=value` environment line or wrapped in matching quotes is refused as the same format failure; that pasted-line check runs only in the browser, since a false positive in a resolver would leave the environment refusing the key as well. A field holding only whitespace fails rather than being silently dropped, while an empty field is not a failure at all: it means keep the stored key on an editor card, and authenticate some other way on a create card. A refused key blocks both the write and the endpoint interrogation, so the page never spends a round trip to be told what the field already says. Each settings write carries the card's current `revision`, so a concurrent write from another tab or an external `settings.yaml` edit is refused as `settings-conflict`; after settings commit, the card adopts the returned redacted user subtree and revision before storing the credential, which makes a failed credential stage retry only that stage. Deletion removes a configured, writable credential only when the profile names the page's derived `_API_KEY` target, then unsets the profile; both operations are idempotent, and a partial failure remains in the identified confirmation dialog for retry. Environment credentials, custom references, and credentials whose target cannot be identified remain untouched. Once loaded, the page subscribes directly to forwarded `settings/document-updated`, `credentials/updated`, and `llm/adapters-updated` owner events, plus local `connection/reset`, so an external `settings.yaml` edit, a second tab, or a settings-born route converges without polling. diff --git a/packages/client/ui-settings-models/README.zh.md b/packages/client/ui-settings-models/README.zh.md index 408f201763..68bb64ddee 100644 --- a/packages/client/ui-settings-models/README.zh.md +++ b/packages/client/ui-settings-models/README.zh.md @@ -2,11 +2,13 @@ [English](README.md) | 中文 -模型设置插件:提供方配置页和按条件显示的 DeepSeek 官方首次使用引导步骤。它把三个协议领域汇聚为一个共享快照:`llm.providers`(可配置提供方目录,含每条路由的存活/休眠状态)、`settings.describe`(序列化 schema、分层脱敏值、secret slot)与 `credentials.describe`(不含值的 configured/source/writable 徽标);页面据此渲染提供方行,一次只展开一张编辑卡片,且不把路由存活状态呈现为提供方状态。 +模型设置与产品引导插件。同一个 client Cordis 插件会注册 Models 页面和两个有序的首次使用弹窗:版本化内测声明,以及按条件显示的 DeepSeek 官方凭据步骤。两个步骤共用同一套弹窗组件,并继续由 `settings.onboarding` 排序。Models 平面把三个协议领域汇聚为一个共享快照:`llm.providers`(可配置提供方目录,含每条路由的存活/休眠状态)、`settings.describe`(序列化 schema、分层脱敏值、secret slot)与 `credentials.describe`(不含值的 configured/source/writable 徽标);页面据此渲染提供方行,一次只展开一张编辑卡片,且不把路由存活状态呈现为提供方状态。 行是*已配置*的提供方(其 profile 在所属 namespace 中解析得出);其配置键未在任何位置配置的整分节提供方会渲染为其展开的设置卡片而非一行,但仅限首次运行姿态——即尚无任何提供方已注册且备齐其 profile 所指名的凭据——且仅持续到用户关闭该卡片为止,此后它就是一行带缺失密钥点的普通行。每一类卡片各自持有自己的展开状态,因此关掉其中一张绝不会丢弃另一张里的草稿。「新增」流程则是一张承载休眠目录提供方选择框的卡片——裸挂载的 `llm-pi-ai` 在任何路由存在之前就能提供其完整的已安装 catalog。pi-ai 卡片还会编辑该路由的**模型列表**,并可查询提供方所提供的模型。只有确认引用的凭据已配置时,行才会以绿色实心点标示 API 密钥状态;只有确认具名引用缺失时,才会以红色实心点标示。无引用的提供方原生认证以及无法取得凭据补充信息时都不显示状态点。编辑器是每个适配器家族各一张的手写卡片:主字段是单独一个 **API 密钥**输入框——页面从不询问环境变量名;键入的密钥经 `credentials.set` 以**只写**方式存入 profile 的引用之下,profile 没有引用时便派生 `_API_KEY`,pi-ai profile 会把这次派生记录为 `apiKeyEnv`,因此 `settings.yaml` 从不携带密钥值。为新的 pi-ai 提供方留空密钥会保存一个不带引用的 profile,因此能保留提供方原生认证,例如 Bedrock 凭据链或 Vertex ADC。「应用」成功后会发出本地无障碍状态消息,且绝不回显任何机密内容。收起的「自定义设置」折叠区承载精选的额外字段——两个家族都有 `baseURL`(deepseek 的占位符显示公共端点)、各适配器自己的模型目录,以及适配器未提供的那类 pi-ai 路由的**显示名称**与 **API 协议**。这两个字段是手工声明路由为自己命名的东西:创建卡片之所以索要它们,正因为没有东西能为它们兜底,因此编辑器也够得着这两个,而不是把它们留给 `settings.yaml`。清空名称即取消设置,路由退回自己的 id——占位符显示的就是它;协议没有这样的兜底。内置目录路由两个都不给:它的名称由目录条目兜底,它的每个模型各自带着自己的协议,路由级协议只可能把它们全部覆盖掉。Provider ID 保持固定:它是 settings 的键、是其他每个 namespace 与每一条已记录会话引用的名字,也是页面读不回、因而搬不走的凭据引用词干。推理等级刻意**不在**其中:它是按模型的能力,而同一提供方下各模型接受的档位并不一致,因此提供方级的控件只可能被设成其中一些模型会拒绝的值——那会连支持该档位的模型也一并隐藏。输入框的模型选择器为每个模型提供它自己的档位,在那里切换会把提供方、模型、推理等级一并记为下一个会话的默认值。profile 字段仍留在 `settings.yaml`,供清楚自己路由的部署使用。每条 DeepSeek 模型行可编辑 `id`、可选的显示名称 `name` 与可选的 `contextWindow`/`maxTokens`;精选集合以外的现有字段会在编辑后保留,其余每个 profile 字段仍归 `settings.yaml` 所有。只有当某行仅由用户层承载时它才可删除(删除会还原组合 base),其本地化确认对话框会在标题、说明和最终操作中点名该提供方。当目录条目表明拥有该路由的适配器在这个键下什么都没有时,该行会带上 **自定义** 标签。标签只跟随这个答案:存了 profile 并不使一条路由成为自定义——收窄一个内置提供方的模型同样会存下 profile——而什么都不回答的适配器,其路由保持无标签,不会被当成内置。 -前序首次使用引导页面完成后,DeepSeek 步骤会从同一个联接快照得出首次运行就绪状态。该步骤的存在是为了让用户手上有一个可对话的模型,因此只要用户已经能触达**任何**一个提供方,它就直接完成而不渲染——已注册且其具名凭据引用已存储的路由(包括来自启动环境且只读的凭据),或 profile 根本不指名任何引用、因而走原生认证的路由。只有二者皆无的用户才会被问到 DeepSeek,即这条提示唯一能为其提供密钥输入框的路由。它通过 `llm-deepseek` 的可配置提供方声明识别官方适配器,因此同 id 但未声明的存活路由不属于可修复配置。只有已挂载且活跃、引用可写但尚未配置的适配器才会显示前往「设置」Models 分区的页面;密钥输入和 `credentials.set` 仅由该分区已有的设置卡片负责,该步骤绝不持有 secret。适配器缺失、路由不活跃、联接失败、部署只读或设置/凭据能力不可用时,该步骤均不渲染并直接完成,以免首次使用引导阻塞产品;Models 页仍是诊断界面。 +声明步骤在 `src/onboarding-copy.ts` 中持有完整文案和版本。回环访问会通过既有 settings API 比较并写入 `ui-onboarding.welcomeNoticeVersion`;只有明确点击「继续」才会记录当前版本。非回环浏览器无法使用这项仅限 Host 的 namespace,因此确认仅在当前进程有效,重载后声明会再次出现。 + +声明完成后,DeepSeek 步骤会从同一个 Models 联接快照得出首次运行就绪状态。只要用户已经能触达**任何**一个提供方,它就直接完成而不渲染——已注册且其具名凭据引用已存储的路由(包括来自启动环境且只读的凭据),或 profile 根本不指名引用、因而走原生认证的路由。只有二者皆无的用户才会被要求填写 DeepSeek 官方密钥。适配器已挂载且活跃、引用可写但尚未配置时,既有 `ProviderEditor` 会以仅凭据模式渲染在共用引导弹窗中;`credentials.set` 仍是唯一的 secret 写入,且不会改变提供方设置。「稍后配置」只完成协调器当前这一轮。适配器缺失、路由不活跃、联接失败、部署只读或设置/凭据能力不可用时,该步骤不渲染并直接完成;Models 页仍是诊断界面。 每一次编辑都以 `settings.mutate` 的路径 op 落到已存分节上——每个变更字段一条 set、每个清空字段一条 unset、删除提供方行则是单独一条 unset。页面自始至终只持有**脱敏后**的 descriptor,因此它只修改自己看得见的字段,而不重建分节。DeepSeek 的 `models` 是一个按值整体替换的数组:编辑器会显示继承而来的生效模型行,直到第一次模型编辑将完整数组具化到用户层;重置则会取消该覆盖。每个模型行承载模型 ID 与显示名称,其上下文窗口与最大输出 token 数则收在该行自己的折叠区里,使用与 pi-ai 提供方表单相同的字段。两项容量都按数值键入,可带十进制的 `K` 或 `M` 后缀(`256K`、`1M`;`1M` 即 1000K),存储为纯数值,回显时写成能够往返的最短形式。空 ID、重复 ID、显式填写的空名称,以及无法读取、非正数或非整数的容量都会在写入前失败。键入的 API 密钥同样在它自己的字段上被判定:trim 之后必须非空,且每个字符都是可打印 ASCII(`[\x21-\x7E]`)——这正是 HTTP 标头值所能承载的范围,是 `@deepseek-ai/dsh-llm` 中 `normalizeApiKey` 的孪生体,因源码平面分割禁止直接引入而在此镜像。与整行粘贴的 `NAME=value` 环境变量匹配或首尾成对引号包裹的值,会以同一条格式失败被拒绝;这项粘贴行检查只在浏览器中运行,因为 resolver 中的一次误判会连带让环境变量这条路也拒绝该密钥。只含空白的输入框会失败而不是被静默丢弃;留空则完全不是失败:在编辑卡片上意味着保持已存储的密钥,在新建卡片上则意味着以其他方式鉴权。被拒绝的密钥会同时拦截写入与端点探测,因此页面不会白花一次往返去换取字段上已经写明的答案。每次 settings 写入都携带卡片当前的 `revision`,因此来自另一个标签页或对 `settings.yaml` 的外部编辑所产生的并发写入会以 `settings-conflict` 被拒绝;settings 提交成功后,卡片会在存储凭据前采用响应返回的脱敏用户子树与 revision,因此凭据阶段失败时,重试只会重复该阶段。删除操作只会在 profile 指向页面派生的 `_API_KEY` 目标时清除已配置且可写的凭据,随后取消设置 profile;两项操作都具备幂等性,部分失败会停留在点名目标的确认对话框中供重试。环境凭据、自定义引用和无法识别目标的凭据保持不变。页面加载完成后会直接订阅转发的 owner 事件 `settings/document-updated`、`credentials/updated`、`llm/adapters-updated`,以及本地 `connection/reset`,因此外部的 `settings.yaml` 编辑、第二个标签页或 settings 新生的路由都无需轮询即可收敛。 diff --git a/packages/client/ui-settings-models/package.json b/packages/client/ui-settings-models/package.json index 71dbde5bd4..423755475c 100644 --- a/packages/client/ui-settings-models/package.json +++ b/packages/client/ui-settings-models/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-client-ui-settings-models", - "description": "Models settings and official-DeepSeek first-run routing over one live provider/settings/credential join", - "version": "0.0.1-rc.5", + "description": "Models settings and shared product-onboarding dialogs over existing settings and credential joins", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -44,7 +44,7 @@ "bundle": "tsdown", "watch": "tsdown --watch" }, - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "workspace:^", "@deepseek-ai/dsh-api-remotes": "workspace:^", diff --git a/packages/client/ui-settings-models/src/client/DeepSeekOnboardingDialog.module.css b/packages/client/ui-settings-models/src/client/DeepSeekOnboardingDialog.module.css index 221239d7bb..9f7ecbc611 100644 --- a/packages/client/ui-settings-models/src/client/DeepSeekOnboardingDialog.module.css +++ b/packages/client/ui-settings-models/src/client/DeepSeekOnboardingDialog.module.css @@ -1,99 +1,16 @@ -.page { - position: relative; - z-index: 1; - width: min(640px, calc(100vw - 64px)); - max-height: 100vh; - padding: clamp(104px, 18vh, 156px) 0 40px; - box-sizing: border-box; - overflow-y: auto; - color: var(--dsw-alias-label-primary); -} - -.brand { - display: flex; - align-items: center; - margin-bottom: 42px; - color: var(--dsw-alias-label-primary); -} - -.title { - margin: 0; - font-size: 28px; - line-height: 36px; - font-weight: 600; - letter-spacing: -0.02em; - outline: none; -} - .description { - margin: 16px 0 0; - font-size: 16px; - line-height: 28px; + margin: 0; + font-size: 14px; + line-height: 24px; color: var(--dsw-alias-label-secondary); } -.actions { - display: flex; - align-items: center; - justify-content: flex-end; - gap: 12px; - margin-top: 32px; -} - -.primary { - min-width: 132px; -} - -.brand, -.title, -.description, -.actions { - animation: credential-enter 280ms cubic-bezier(0.23, 1, 0.32, 1) both; -} - -.title { animation-delay: 40ms; } -.description { animation-delay: 80ms; } -.actions { animation-delay: 120ms; } - -@keyframes credential-enter { - from { - opacity: 0; - transform: translateY(8px); - } - - to { - opacity: 1; - transform: translateY(0); - } -} - -@media (prefers-reduced-motion: reduce) { - .brand, - .title, - .description, - .actions { - animation: none; - } +.editor { + margin-top: 24px; } @media (max-width: 560px) { - .page { - width: calc(100vw - 40px); - padding-top: 64px; - } - - .brand { - margin-bottom: 30px; - } - - .actions { - align-items: stretch; - flex-direction: column-reverse; - margin-top: 32px; - } - - .primary, - .later { - width: 100%; + .editor { + margin-top: 20px; } } diff --git a/packages/client/ui-settings-models/src/client/DeepSeekOnboardingDialog.tsx b/packages/client/ui-settings-models/src/client/DeepSeekOnboardingDialog.tsx index 302d4592f8..24e2112096 100644 --- a/packages/client/ui-settings-models/src/client/DeepSeekOnboardingDialog.tsx +++ b/packages/client/ui-settings-models/src/client/DeepSeekOnboardingDialog.tsx @@ -2,33 +2,39 @@ * Official-DeepSeek first-run step. Readiness comes from the same * provider/settings/credential join as the Models page: any provider the user * can already talk to ends the step, and only a user with none is offered the - * official DeepSeek route. The prompt itself only routes to that page's single - * credential editor. + * official DeepSeek route. The step reuses that page's credential editor in + * the onboarding plugin's shared modal, so the key is entered once. */ -import { useEffect, useRef } from 'react' +import { useEffect } from 'react' import type { ReactNode } from 'react' -import type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots' -import { BrandWordmark, Button, OnboardingSurface } from '@deepseek-ai/dsh-client-ui-primitives' -import type { SnapshotSelectorHook } from '@deepseek-ai/dsh-client-web-react' +import type { IApiClient } from '@deepseek-ai/dsh-api-remotes/client' +import type { SnapshotStore } from '@deepseek-ai/dsh-client-runtime/client' +import type { InjectFace, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots' import type { ModelsSettingsState, ModelsSettingsStore } from './store.ts' import { onboardingReadiness } from './store.ts' +import { ProviderEditor } from './ProviderEditor.tsx' import type { en } from './locales.ts' +import { OnboardingModal } from './OnboardingModal.tsx' import styles from './DeepSeekOnboardingDialog.module.css' -/** Injected dependencies of {@link DeepSeekOnboardingDialog}. */ +/** Registration-side dependencies of {@link DeepSeekOnboardingDialog}. */ export interface DeepSeekOnboardingInjected { + hooks: { + /** Shared Models-page join state, bound by the slot renderer. */ + models: SnapshotStore + } /** Shared Models-page join controller. */ controller: ModelsSettingsStore - /** Subscription hook bound to the shared join snapshot. */ - useSnapshot: SnapshotSelectorHook + /** Existing wire face reused by the Models credential editor. */ + api: Pick /** Feature copy. */ t: (key: keyof typeof en) => string } /** Slot owner props plus the feature's injected dependencies. */ export type DeepSeekOnboardingDialogProps = - PropsRuntime<'settings.onboarding'> & DeepSeekOnboardingInjected + PropsRuntime<'settings.onboarding'> & InjectFace /* v8 ignore next 3 -- closed-union defaults only defend future source widening */ function assertNever(_value: never): never { @@ -36,16 +42,15 @@ function assertNever(_value: never): never { } /** - * Prompt a first-run user to open Models while no provider can serve requests - * and the official adapter exists with an unconfigured effective credential. + * Prompt a first-run user for the official DeepSeek credential while no + * provider can serve requests and that credential is writable. * @param props - settings-shell owner state and Models feature dependencies. - * @returns the onboarding page or null when onboarding needs no intervention. + * @returns the onboarding modal or null when onboarding needs no intervention. */ export function DeepSeekOnboardingDialog(props: DeepSeekOnboardingDialogProps): ReactNode { - const { complete, openSection, controller, useSnapshot, t } = props - const state = useSnapshot(snapshot => snapshot) + const { complete, controller, useModels, api, t } = props + const state = useModels(snapshot => snapshot) const readiness = onboardingReadiness(state) - const titleRef = useRef(null) useEffect(() => { if (state.status === 'idle') void controller.load() @@ -59,18 +64,6 @@ export function DeepSeekOnboardingDialog(props: DeepSeekOnboardingDialogProps): ) complete() }, [complete, readiness.kind]) - useEffect(() => { - if (readiness.kind === 'credential-missing') titleRef.current?.focus() - }, [readiness.kind]) - - const openModels = (): void => { - complete() - openSection('models') - } - - // Null covers the still-deciding and nothing-to-do states alike: the - // takeover chrome below is part of THIS render, so declining paints and - // blocks nothing while the shared join is in flight. switch (readiness.kind) { case 'loading': case 'adapter-absent': @@ -84,28 +77,44 @@ export function DeepSeekOnboardingDialog(props: DeepSeekOnboardingDialogProps): return assertNever(readiness) } + const row = state.rows.find(candidate => + candidate.entry.provider === 'deepseek-official' + && candidate.entry.settingsNs === 'llm-deepseek' + && candidate.entry.settingsPath.length === 0) + const namespace = state.namespaces.get('llm-deepseek') + /* v8 ignore next 2 -- credential-missing is derived only from this exact joined row. */ + if (row === undefined || namespace === undefined) return null + + const finishCredential = (changed: boolean): void => { + if (!changed) { + complete() + return + } + void controller.load() + } + return ( - -
- -

- {t('onboardingTitle')} -

-

{t('onboardingDescription')}

-
- - -
-
-
+ +

{t('onboardingDescription')}

+
+ +
+
) } diff --git a/packages/client/ui-settings-models/src/client/EditorFooter.tsx b/packages/client/ui-settings-models/src/client/EditorFooter.tsx index adcb009cdf..6306609ca5 100644 --- a/packages/client/ui-settings-models/src/client/EditorFooter.tsx +++ b/packages/client/ui-settings-models/src/client/EditorFooter.tsx @@ -29,6 +29,8 @@ export interface EditorFooterProps { submitLabel: keyof typeof en /** Commit label while a commit is in flight. */ submitBusyLabel: keyof typeof en + /** Dismiss label; defaults to the settings editor copy. */ + cancelLabel?: keyof typeof en /** Dismiss the card without committing. */ onCancel: () => void /** Run the card's commit. */ @@ -50,7 +52,7 @@ export function EditorFooter(props: EditorFooterProps): ReactNode { disabled={props.busy} onClick={props.onCancel} > - {t('cancel')} + {t(props.cancelLabel ?? 'cancel')} + + + ) +} diff --git a/packages/client/ui-settings-models/src/client/index.ts b/packages/client/ui-settings-models/src/client/index.ts index 08d77a1832..dc7f32e370 100644 --- a/packages/client/ui-settings-models/src/client/index.ts +++ b/packages/client/ui-settings-models/src/client/index.ts @@ -1,8 +1,9 @@ /** - * Models settings plugin, browser half. Registers the `models` nav entry and - * official-DeepSeek first-run overlay into shell-declared slots. Both consume - * one provider/settings/credential join; the overlay routes missing-key users - * to the full page's single credential editor. Export discipline: + * Models settings and product-onboarding plugin, browser half. It registers + * the Models page plus the ordered internal-testing and official-DeepSeek + * onboarding dialogs, whose UI shares this package's modal wrapper. The Host + * settings and credential contracts stay behind their existing wire APIs. + * Export discipline: * packages/client/AGENTS.md. */ import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client' @@ -19,15 +20,19 @@ import { ModelsSection } from './ModelsSection.tsx' import type { ModelsSectionInjected } from './ModelsSection.tsx' import { DeepSeekOnboardingDialog } from './DeepSeekOnboardingDialog.tsx' import type { DeepSeekOnboardingInjected } from './DeepSeekOnboardingDialog.tsx' +import { WelcomeNotice } from './WelcomeNotice.tsx' +import type { WelcomeNoticeInjected } from './WelcomeNotice.tsx' +import { refreshWelcomeIfLoaded, WelcomeNoticeStore } from './welcome-store.ts' import { ModelsSettingsStore } from './store.ts' import { en, zh, type ModelsKey } from './locales.ts' +import { WELCOME_NOTICE_SETTINGS_NAMESPACE } from '../onboarding-copy.ts' export type { ModelsSectionInjected, ModelsSectionProps } from './ModelsSection.tsx' export type { ModelsKey } from './locales.ts' declare module '@deepseek-ai/dsh-client-ui-slots' { interface LocaleNamespaceMap { - /** The Models page + onboarding overlay copy. */ + /** The Models page + product-onboarding copy. */ 'settings.models': ModelsKey } } @@ -74,21 +79,38 @@ export function apply(ctx: ClientContext): void { api: connection.api, t, }) - const onboardingInjected = (): DeepSeekOnboardingInjected => ({ + const deepSeekOnboardingInjected = (): DeepSeekOnboardingInjected => ({ controller, - useSnapshot, + hooks: { models: controller.store }, + api: connection.api, + t, + }) + const welcomeController = new WelcomeNoticeStore( + connection.api, + connection.isLoopback ? 'host' : 'memory', + ) + const welcomeInjected = (): WelcomeNoticeInjected => ({ + controller: welcomeController, + hooks: { welcome: welcomeController.store }, t, }) // Pushed invalidations converge every open surface without polling: any // settings/credentials/topology change refetches once the page loaded. ctx.effect(() => { - const refresh = (): void => { refreshIfLoaded(controller) } + const refreshModels = (): void => { refreshIfLoaded(controller) } + const refreshAll = (): void => { + refreshModels() + refreshWelcomeIfLoaded(welcomeController) + } const disposers = [ - ctx.remote.$on('settings/document-updated', refresh), - ctx.remote.$on('credentials/updated', refresh), - ctx.remote.$on('llm/adapters-updated', refresh), - ctx.on('connection/reset', refresh), + ctx.remote.$on('settings/document-updated', (ns) => { + refreshModels() + if (ns === WELCOME_NOTICE_SETTINGS_NAMESPACE) refreshWelcomeIfLoaded(welcomeController) + }), + ctx.remote.$on('credentials/updated', refreshModels), + ctx.remote.$on('llm/adapters-updated', refreshModels), + ctx.on('connection/reset', refreshAll), ] return () => { for (const dispose of disposers) dispose() } }, 'ui-settings-models: pushed invalidations') @@ -100,10 +122,16 @@ export function apply(ctx: ClientContext): void { label: () => t('nav'), inject: injected, }, ModelsSection)) + ctx.slots.inject('settings.onboarding', () => ctx.slots.register({ + name: 'settings.onboarding', + id: 'welcome-notice', + order: -100, + inject: welcomeInjected, + }, WelcomeNotice)) ctx.slots.inject('settings.onboarding', () => ctx.slots.register({ name: 'settings.onboarding', id: 'deepseek-official', order: 0, - inject: onboardingInjected, + inject: deepSeekOnboardingInjected, }, DeepSeekOnboardingDialog)) } diff --git a/packages/client/ui-settings-models/src/client/locales.ts b/packages/client/ui-settings-models/src/client/locales.ts index 561a5df494..a49a4f0ef2 100644 --- a/packages/client/ui-settings-models/src/client/locales.ts +++ b/packages/client/ui-settings-models/src/client/locales.ts @@ -1,5 +1,7 @@ /** Copy dictionaries for the Models settings section. */ +import { WELCOME_NOTICE_COPY } from '../onboarding-copy.ts' + /** English strings (the key-set source of truth for this pair). */ export const en = { nav: 'Models', @@ -85,17 +87,23 @@ export const en = { customNeedsModels: 'A custom provider needs at least one model.', create: 'Create provider', creating: 'Creating\u2026', + welcomeTitle: WELCOME_NOTICE_COPY.en.title, + welcomeBody: WELCOME_NOTICE_COPY.en.body, + welcomeContinue: WELCOME_NOTICE_COPY.en.continueLabel, + welcomeError: 'The acknowledgement could not be saved. Please try again.', onboardingTitle: 'Add an API key to get started', onboardingDescription: 'Configure the official DeepSeek provider to start building.', - onboardingGoToSettings: 'Go to settings', onboardingLater: 'Configure later', + onboardingSave: 'Save and continue', + onboardingSaving: 'Saving…', + keyRequired: 'Enter an API key to continue.', } /** The settings.models namespace key union. */ export type ModelsKey = keyof typeof en /** Chinese strings (same keys as {@link en}). */ -export const zh: typeof en = { +export const zh: { [Key in keyof typeof en]: string } = { nav: '模型', title: '模型', intro: '填入各提供方的 API 密钥即可使用其模型。', @@ -179,8 +187,14 @@ export const zh: typeof en = { customNeedsModels: '自定义提供方至少需要一个模型。', create: '创建提供方', creating: '创建中\u2026', + welcomeTitle: WELCOME_NOTICE_COPY.zh.title, + welcomeBody: WELCOME_NOTICE_COPY.zh.body, + welcomeContinue: WELCOME_NOTICE_COPY.zh.continueLabel, + welcomeError: '暂时无法保存确认状态,请重试。', onboardingTitle: '添加一个 API Key 开始使用', onboardingDescription: '配置 DeepSeek 官方模型,即可开始使用。', - onboardingGoToSettings: '前往配置', onboardingLater: '稍后配置', + onboardingSave: '保存并继续', + onboardingSaving: '保存中…', + keyRequired: '请输入 API 密钥后继续。', } diff --git a/packages/client/ui-settings-general/src/client/welcome-store.ts b/packages/client/ui-settings-models/src/client/welcome-store.ts similarity index 94% rename from packages/client/ui-settings-general/src/client/welcome-store.ts rename to packages/client/ui-settings-models/src/client/welcome-store.ts index 48f96bcb94..6e139f1a43 100644 --- a/packages/client/ui-settings-general/src/client/welcome-store.ts +++ b/packages/client/ui-settings-models/src/client/welcome-store.ts @@ -74,8 +74,7 @@ export class WelcomeNoticeStore { } /** - * Acknowledge this copy version. The Host path mutation is idempotent across - * tabs and preserves sibling settings; remote fallback changes only this store. + * Persist this copy version, or advance only this process for a remote browser. * @returns true when the selected persistence mode accepted the acknowledgement. */ async acknowledge(): Promise { @@ -118,8 +117,7 @@ export class WelcomeNoticeStore { /** * Refresh only after welcome state has left idle. A memory-mode load retains - * acknowledgement so reconnect and settings-change refreshes do not reopen a - * process-local notice. + * acknowledgement so reconnect does not reopen a process-local notice. * @param controller - welcome state owner whose current status decides whether to load. */ export function refreshWelcomeIfLoaded(controller: WelcomeNoticeStore): void { diff --git a/packages/client/ui-settings-models/src/onboarding-copy.ts b/packages/client/ui-settings-models/src/onboarding-copy.ts new file mode 100644 index 0000000000..d52371a9cf --- /dev/null +++ b/packages/client/ui-settings-models/src/onboarding-copy.ts @@ -0,0 +1,25 @@ +/** Durable settings namespace for product-wide GUI onboarding facts. */ +export const WELCOME_NOTICE_SETTINGS_NAMESPACE = 'ui-onboarding' + +/** Field storing the last welcome notice version the user acknowledged. */ +export const WELCOME_NOTICE_ACK_FIELD = 'welcomeNoticeVersion' + +/** + * Bump only when the notice changes materially and every user should see it + * again. The acknowledgement is compared for exact equality. + */ +export const WELCOME_NOTICE_VERSION = '2026-08-13.1' + +/** The complete editable internal-testing notice in both supported GUI locales. */ +export const WELCOME_NOTICE_COPY = { + zh: { + title: '内测声明', + body: 'DeepSeek Harness 目前的 0.1 版本仍处在面向 Harness 开发者进行测试的阶段,还有许多地方需要持续改进和打磨,希望听取广大开发者的反馈建议。预计 DeepSeek Harness 的核心插件以及基础 API 都会在接下来的一段时间内快速迭代、持续演化。\n\n我们期待与全球开发者一起,在开源、开放、可复用、可组合的基础设施之上,共同探索智能上限。欢迎全球 Harness 开发者加入 DSH 插件生态。', + continueLabel: '继续', + }, + en: { + title: 'Internal Testing Notice', + body: "DeepSeek Harness 0.1 remains in testing for Harness developers. Many areas need further improvement, and we welcome feedback from the developer community. DeepSeek Harness's core plugins and foundational APIs will continue to evolve rapidly over the coming months.\n\nWe look forward to exploring the limits of intelligence with developers around the world, building on open-source, open, reusable, and composable infrastructure. We welcome Harness developers everywhere to join the DSH plugin ecosystem.", + continueLabel: 'Continue', + }, +} as const diff --git a/packages/client/ui-settings-models/tests/apply.client.spec.ts b/packages/client/ui-settings-models/tests/apply.client.spec.ts index e914b1fe5b..39ba3e4b65 100644 --- a/packages/client/ui-settings-models/tests/apply.client.spec.ts +++ b/packages/client/ui-settings-models/tests/apply.client.spec.ts @@ -8,12 +8,13 @@ import { TestRemote, usePinnedBrowserLanguages } from '@deepseek-ai/dsh-client-t import { apply, inject, refreshIfLoaded } from '@deepseek-ai/dsh-client-ui-settings-models/client' import { ModelsSection } from '../src/client/ModelsSection.tsx' import { DeepSeekOnboardingDialog } from '../src/client/DeepSeekOnboardingDialog.tsx' +import { WelcomeNotice } from '../src/client/WelcomeNotice.tsx' // The service reads its initial locale from the browser; these specs assert // the shipped Chinese copy, so they state the browser they assume. usePinnedBrowserLanguages('zh-CN') -async function bench() { +async function bench(isLoopback = true) { const ctx = new Context() await ctx.plugin(SlotRegistry).await() const locale = new LocaleRuntime(ctx) @@ -23,7 +24,7 @@ async function bench() { new TestRemote(ctx) // The apply path only captures the wire face; no call leaves this fake // until a section actually loads. - ctx.provide('connection', { api: {} } as never) + ctx.provide('connection', { api: {}, isLoopback } as never) return { ctx, slots: ctx.get('slots') as SlotRegistry, locale } } @@ -60,9 +61,20 @@ describe('ui-settings-models apply', () => { expect(typeof injected.controller.load).toBe('function') expect(typeof injected.useSnapshot).toBe('function') expect(injected.api).toBeDefined() - const onboarding = before.slots.entries('settings.onboarding')[0]! - expect(onboarding.component).toBe(DeepSeekOnboardingDialog) - expect(onboarding.options).toMatchObject({ id: 'deepseek-official', order: 0 }) + const onboarding = before.slots.entries('settings.onboarding') + expect(onboarding).toHaveLength(2) + expect(onboarding.find(entry => entry.options.id === 'welcome-notice')).toMatchObject({ + component: WelcomeNotice, + options: { id: 'welcome-notice', order: -100 }, + }) + const deepSeek = onboarding.find(entry => entry.options.id === 'deepseek-official')! + expect(deepSeek.component).toBe(DeepSeekOnboardingDialog) + expect(deepSeek.options).toMatchObject({ id: 'deepseek-official', order: 0 }) + const deepSeekInjected = ( + deepSeek.inject as unknown as () => import('../src/client/DeepSeekOnboardingDialog.tsx').DeepSeekOnboardingInjected + )() + expect(deepSeekInjected.hooks.models).toBe(injected.controller.store) + expect(deepSeekInjected.api).toBeDefined() const after = await bench() await after.ctx.plugin({ inject: [...inject], apply }).await() @@ -71,7 +83,7 @@ describe('ui-settings-models apply', () => { declare(after.slots) await Promise.resolve() expect(after.slots.entries('settings.section')[0]!.component).toBe(ModelsSection) - expect(after.slots.entries('settings.onboarding')[0]!.component).toBe(DeepSeekOnboardingDialog) + expect(after.slots.entries('settings.onboarding')).toHaveLength(2) // The self-inflicted ledger notifications hit the duplicate guard. expect(after.slots.entries('settings.section')).toHaveLength(1) }) @@ -110,7 +122,7 @@ describe('ui-settings-models apply', () => { declare(b.slots) await Promise.resolve() expect(b.slots.entries('settings.section')[0]!.component).toBe(ModelsSection) - expect(b.slots.entries('settings.onboarding')[0]!.component).toBe(DeepSeekOnboardingDialog) + expect(b.slots.entries('settings.onboarding')).toHaveLength(2) // The locale path also recovers through the same ledger re-check. b.locale.setLocale('en') expect(resolveSlotLabel(b.slots.entries('settings.section')[0]!.options.label)).toBe('Models') @@ -130,6 +142,22 @@ describe('ui-settings-models apply', () => { expect(() => b.locale.register('settings.models', 'zh', {})).not.toThrow() expect(() => b.locale.register('settings.models', 'en', {})).not.toThrow() }) + + it('keeps remote-browser acknowledgement in process memory', async () => { + const b = await bench(false) + declare(b.slots) + await b.ctx.plugin({ inject: [...inject], apply }).await() + const entry = b.slots.entries('settings.onboarding') + .find(candidate => candidate.options.id === 'welcome-notice')! + const injected = ( + entry.inject as unknown as () => import('../src/client/WelcomeNotice.tsx').WelcomeNoticeInjected + )() + + await injected.controller.load() + expect(injected.controller.store.getSnapshot()).toEqual({ + status: 'ready', acknowledged: false, error: null, + }) + }) }) describe('pushed invalidations', () => { @@ -164,8 +192,10 @@ describe('pushed invalidations', () => { const b = await bench() declare(b.slots) await b.ctx.plugin({ inject: [...inject], apply }).await() + const entry = b.slots.entries('settings.onboarding') + .find(candidate => candidate.options.id === 'deepseek-official')! const injected = ( - b.slots.entries('settings.onboarding')[0]!.inject as unknown as + entry.inject as unknown as () => import('../src/client/DeepSeekOnboardingDialog.tsx').DeepSeekOnboardingInjected )() injected.controller.store.update((state) => { state.status = 'ready' }) @@ -173,4 +203,25 @@ describe('pushed invalidations', () => { b.ctx.remote.$dispatch('credentials/updated', ['DEEPSEEK_API_KEY']) expect(load).toHaveBeenCalledTimes(1) }) + + it('routes only the onboarding namespace invalidation into welcome state', async () => { + const b = await bench() + declare(b.slots) + await b.ctx.plugin({ inject: [...inject], apply }).await() + const entry = b.slots.entries('settings.onboarding') + .find(candidate => candidate.options.id === 'welcome-notice')! + const injected = ( + entry.inject as unknown as + () => import('../src/client/WelcomeNotice.tsx').WelcomeNoticeInjected + )() + injected.hooks.welcome.update((state) => { state.status = 'ready' }) + const load = vi.spyOn(injected.controller, 'load').mockResolvedValue() + + b.ctx.remote.$dispatch('settings/document-updated', ['llm-deepseek', 1]) + expect(load).not.toHaveBeenCalled() + b.ctx.remote.$dispatch('settings/document-updated', ['ui-onboarding', 2]) + expect(load).toHaveBeenCalledOnce() + b.ctx.emit('connection/reset') + expect(load).toHaveBeenCalledTimes(2) + }) }) diff --git a/packages/client/ui-settings-models/tests/components.client.spec.tsx b/packages/client/ui-settings-models/tests/components.client.spec.tsx index 01f0a32349..66ba8d33a4 100644 --- a/packages/client/ui-settings-models/tests/components.client.spec.tsx +++ b/packages/client/ui-settings-models/tests/components.client.spec.tsx @@ -48,7 +48,7 @@ const PiAiConfig = Schema.object({ const DeepSeekConfig = Schema.object({ apiKeyEnv: Schema.string().role('credential-ref'), baseURL: Schema.string().pattern(/^https:\/\//), - reasoningEffort: Schema.union(['off', 'high', 'max']), + reasoningEffort: Schema.union(['off', 'low', 'high', 'max']), defaultContextWindow: Schema.number().step(1).min(1), models: Schema.array(Schema.object({ id: Schema.string().required(), @@ -355,6 +355,65 @@ describe('ModelsSection', () => { expect(screen.queryByRole('status')).toBeNull() }) + it('reuses the provider editor as a required credential-only onboarding form', async () => { + let finishSet: ((response: RpcResponse>) => void) | undefined + const set = vi.fn(() => new Promise>>((resolve) => { + finishSet = resolve + })) + const { face, mutate } = scriptedFace({ set }) + const onClose = vi.fn() + const { ProviderEditor } = await import('../src/client/ProviderEditor.tsx') + + render() + + const key = screen.getByLabelText(en.keyInput) + const save = screen.getByText(en.onboardingSave) + expect(document.activeElement).toBe(key) + expect(key.required).toBe(true) + expect(save.disabled).toBe(true) + expect(screen.getByText(en.onboardingLater)).toBeTruthy() + expect(screen.queryByText(en.customized)).toBeNull() + expect(screen.queryByLabelText(en.baseUrl)).toBeNull() + + fireEvent.change(key, { target: { value: ' ' } }) + expect(screen.getByText(en.keyRequired)).toBeTruthy() + expect(key.getAttribute('aria-invalid')).toBe('true') + expect(save.disabled).toBe(true) + + fireEvent.change(key, { target: { value: ' sk-onboarding ' } }) + expect(screen.queryByText(en.keyRequired)).toBeNull() + expect(save.disabled).toBe(false) + fireEvent.click(save) + + expect(await screen.findByText(en.onboardingSaving)).toBeTruthy() + expect(set).toHaveBeenCalledWith({ ref: 'DEEPSEEK_API_KEY', value: 'sk-onboarding' }) + expect(mutate).not.toHaveBeenCalled() + expect(onClose).not.toHaveBeenCalled() + + if (finishSet === undefined) throw new Error('credential write did not start') + await act(async () => { + finishSet?.(ok({})) + await Promise.resolve() + }) + expect(onClose).toHaveBeenCalledWith(true) + }) + it('applies customized deepseek fields as path ops', async () => { const { mutate } = await mountDeepSeekCard({ mutate: vi.fn(() => Promise.resolve(ok(wireNamespaces()[0]))), diff --git a/packages/client/ui-settings-models/tests/onboarding-dialog.client.spec.tsx b/packages/client/ui-settings-models/tests/onboarding-dialog.client.spec.tsx index 2aea95b705..ebb5992cfe 100644 --- a/packages/client/ui-settings-models/tests/onboarding-dialog.client.spec.tsx +++ b/packages/client/ui-settings-models/tests/onboarding-dialog.client.spec.tsx @@ -2,14 +2,18 @@ /** First-run DeepSeek prompt behavior over the shared Models join. */ import { act, cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react' import { afterEach, describe, expect, it, vi } from 'vitest' -import type { RpcResponse } from '@deepseek-ai/dsh-api-remotes/client' +import Schema from '@deepseek-ai/schemastery' +import type { RpcResponse, SettingsNamespaceView } from '@deepseek-ai/dsh-api-remotes/client' import { bindSnapshotSelector } from '@deepseek-ai/dsh-client-web-react' import { DeepSeekOnboardingDialog } from '../src/client/DeepSeekOnboardingDialog.tsx' import type { DeepSeekOnboardingDialogProps } from '../src/client/DeepSeekOnboardingDialog.tsx' import { ModelsSettingsStore } from '../src/client/store.ts' import { en } from '../src/client/locales.ts' -afterEach(cleanup) +afterEach(() => { + cleanup() + document.getElementById('root')?.remove() +}) let nextRpc = 0 function ok(value: T): RpcResponse { @@ -22,6 +26,33 @@ function fail(message: string): RpcResponse { } } +const DeepSeekConfig = Schema.object({ + apiKeyEnv: Schema.string().role('credential-ref'), + baseURL: Schema.string().pattern(/^https:\/\//), + reasoningEffort: Schema.union(['off', 'low', 'high', 'max']), + defaultContextWindow: Schema.number().step(1).min(1), + models: Schema.array(Schema.object({ + id: Schema.string().required(), + name: Schema.string(), + description: Schema.string(), + contextWindow: Schema.number().step(1).min(1), + })), +}) + +function deepSeekNamespace(apiKeyEnv: string | null): SettingsNamespaceView { + const value = apiKeyEnv === null ? {} : { apiKeyEnv } + return { + ns: 'llm-deepseek', + schema: JSON.parse(JSON.stringify(DeepSeekConfig.toJSON())) as unknown, + value, + base: value, + user: {}, + applies: 'live', + secrets: [], + revision: 0, + } +} + function harness(options: { provider?: boolean providerSettingsNs?: string @@ -33,9 +64,24 @@ function harness(options: { describeFailure?: string settingsWritable?: boolean providersReject?: boolean + setFailure?: string + setReject?: string } = {}) { + if (document.getElementById('root') === null) { + const appRoot = document.createElement('div') + appRoot.id = 'root' + document.body.append(appRoot) + } let fileConfigured = false const configured = options.configured ?? (() => fileConfigured) + const apiKeyEnv = options.apiKeyEnv === undefined ? 'DEEPSEEK_API_KEY' : options.apiKeyEnv + const mutate = vi.fn(() => Promise.resolve(ok(deepSeekNamespace(apiKeyEnv)))) + const set = vi.fn((_payload: { ref: string; value: string }) => { + if (options.setReject !== undefined) return Promise.reject(new Error(options.setReject)) + if (options.setFailure !== undefined) return Promise.resolve(fail(options.setFailure)) + fileConfigured = true + return Promise.resolve(ok({})) + }) const face = { llm: { providers: () => { @@ -56,19 +102,10 @@ function harness(options: { settings: { describe: () => Promise.resolve(ok({ writable: options.settingsWritable ?? true, - namespaces: options.settingsNamespace === false - ? [] - : [{ - ns: 'llm-deepseek', - schema: {}, - value: options.apiKeyEnv === null - ? {} - : { apiKeyEnv: options.apiKeyEnv ?? 'DEEPSEEK_API_KEY' }, - applies: 'live' as const, - secrets: [], - revision: 0, - }], + hasDocument: false, + namespaces: options.settingsNamespace === false ? [] : [deepSeekNamespace(apiKeyEnv)], })), + mutate, }, credentials: { describe: () => options.describeFailure === undefined @@ -84,6 +121,7 @@ function harness(options: { }, })) : Promise.resolve(fail(options.describeFailure)), + set, }, } const controller = new ModelsSettingsStore(face as never) @@ -97,40 +135,91 @@ function harness(options: { useSessions: unusedHook, useWorkspaces: unusedHook, controller, - useSnapshot: bindSnapshotSelector(controller.store), + useModels: bindSnapshotSelector(controller.store), + api: face as never, t: key => en[key], } - return { controller, complete, openSection, props, configure: () => { fileConfigured = true } } + return { + controller, complete, openSection, props, mutate, set, + configure: () => { fileConfigured = true }, + } } describe('DeepSeekOnboardingDialog', () => { - it('loads on first entry and presents one accessible route to Models', async () => { + it('renders when the shell root is absent', async () => { const h = harness() + document.getElementById('root')!.remove() render() - expect(await screen.findByRole('region', { name: en.onboardingTitle })).toBeTruthy() - expect(screen.getByText(en.onboardingDescription)).toBeTruthy() - const action = screen.getByRole('button', { name: en.onboardingGoToSettings }) - expect(action).toBeTruthy() - expect(document.activeElement).toBe(screen.getByRole('heading', { name: en.onboardingTitle })) - expect(screen.queryByRole('textbox')).toBeNull() + expect(await screen.findByRole('dialog', { name: en.onboardingTitle })).toBeTruthy() }) - it('opens the Models section and dismisses the prompt', async () => { + it('loads a credential-only modal, inerts the product, and focuses the key', async () => { const h = harness() render() - await screen.findByRole('region') - fireEvent.click(screen.getByRole('button', { name: en.onboardingGoToSettings })) - expect(h.complete).toHaveBeenCalledOnce() - expect(h.openSection).toHaveBeenCalledWith('models') + expect(await screen.findByRole('dialog', { name: en.onboardingTitle })).toBeTruthy() + expect(document.getElementById('root')?.inert).toBe(true) + expect(screen.getByText(en.onboardingDescription)).toBeTruthy() + const key = screen.getByLabelText(en.keyInput) + await waitFor(() => { expect(document.activeElement).toBe(key) }) + expect(screen.queryByText(en.customized)).toBeNull() + }) + + it('cannot be dismissed implicitly and restores the previous inert state', async () => { + const h = harness() + const appRoot = document.getElementById('root')! + appRoot.inert = true + const view = render() + await screen.findByRole('dialog') + + fireEvent.keyDown(document, { key: 'Escape' }) + fireEvent.click(document.querySelector('[class*="mask"]')!) + expect(screen.getByRole('dialog')).toBeTruthy() + expect(h.complete).not.toHaveBeenCalled() + + view.unmount() + expect(appRoot.inert).toBe(true) + }) + + it('requires a non-blank key before Save and continue is available', async () => { + const h = harness() + render() + await screen.findByRole('dialog') + const save = screen.getByRole('button', { name: en.onboardingSave }) + expect(save.disabled).toBe(true) + fireEvent.change(screen.getByLabelText(en.keyInput), { target: { value: ' ' } }) + expect(save.disabled).toBe(true) + expect(screen.getByText(en.keyRequired)).toBeTruthy() + expect(h.set).not.toHaveBeenCalled() + }) + + it('keeps the modal open and reports rejected and failed credential writes', async () => { + for (const [options, message] of [ + [{ setFailure: 'credential was rejected' }, 'credential was rejected'], + [{ setReject: 'connection lost' }, 'connection lost'], + ] as const) { + const h = harness(options) + const view = render() + await screen.findByRole('dialog') + fireEvent.change(screen.getByLabelText(en.keyInput), { target: { value: 'sk-live' } }) + fireEvent.click(screen.getByRole('button', { name: en.onboardingSave })) + expect(await screen.findByText(message)).toBeTruthy() + expect(screen.getByRole('dialog')).toBeTruthy() + expect(screen.getByRole('button', { name: en.onboardingSave }).disabled).toBe(false) + expect(h.complete).not.toHaveBeenCalled() + expect(h.mutate).not.toHaveBeenCalled() + view.unmount() + } }) it('allows configure-later dismissal without opening settings', async () => { const h = harness() render() - await screen.findByRole('region') + await screen.findByRole('dialog') fireEvent.click(screen.getByRole('button', { name: en.onboardingLater })) expect(h.complete).toHaveBeenCalledOnce() expect(h.openSection).not.toHaveBeenCalled() + expect(h.set).not.toHaveBeenCalled() + expect(h.mutate).not.toHaveBeenCalled() }) it('does not block the product when DeepSeek setup is unavailable', async () => { @@ -145,7 +234,7 @@ describe('DeepSeekOnboardingDialog', () => { ]) { const view = render() await act(async () => { await h.controller.load() }) - expect(screen.queryByRole('region')).toBeNull() + expect(screen.queryByRole('dialog')).toBeNull() await waitFor(() => { expect(h.complete).toHaveBeenCalledOnce() }) expect(h.openSection).not.toHaveBeenCalled() view.unmount() @@ -160,7 +249,7 @@ describe('DeepSeekOnboardingDialog', () => { ]) { const view = render() await act(async () => { await h.controller.load() }) - expect(screen.queryByRole('region')).toBeNull() + expect(screen.queryByRole('dialog')).toBeNull() await waitFor(() => { expect(h.complete).toHaveBeenCalledOnce() }) view.unmount() } @@ -169,10 +258,10 @@ describe('DeepSeekOnboardingDialog', () => { it('closes when an external credential invalidation refreshes the shared join', async () => { const h = harness() render() - await screen.findByRole('region') + await screen.findByRole('dialog') h.configure() await act(async () => { await h.controller.load() }) - await waitFor(() => { expect(screen.queryByRole('region')).toBeNull() }) + await waitFor(() => { expect(screen.queryByRole('dialog')).toBeNull() }) expect(h.complete).toHaveBeenCalledOnce() }) }) diff --git a/packages/client/ui-settings-general/tests/welcome-notice.client.spec.tsx b/packages/client/ui-settings-models/tests/welcome-notice.client.spec.tsx similarity index 60% rename from packages/client/ui-settings-general/tests/welcome-notice.client.spec.tsx rename to packages/client/ui-settings-models/tests/welcome-notice.client.spec.tsx index 74feea89a5..8b8858c64a 100644 --- a/packages/client/ui-settings-general/tests/welcome-notice.client.spec.tsx +++ b/packages/client/ui-settings-models/tests/welcome-notice.client.spec.tsx @@ -5,19 +5,25 @@ import { bindSnapshotSelector } from '@deepseek-ai/dsh-client-web-react' import { WelcomeNotice } from '../src/client/WelcomeNotice.tsx' import type { WelcomeNoticeProps } from '../src/client/WelcomeNotice.tsx' import { WelcomeNoticeStore } from '../src/client/welcome-store.ts' -import { zh } from '../src/client/locales.ts' +import { en, zh } from '../src/client/locales.ts' import { WELCOME_NOTICE_ACK_FIELD, WELCOME_NOTICE_COPY, WELCOME_NOTICE_SETTINGS_NAMESPACE, WELCOME_NOTICE_VERSION, } from '../src/onboarding-copy.ts' -afterEach(cleanup) +afterEach(() => { + cleanup() + document.getElementById('root')?.remove() +}) function response(value: T) { return { rpcId: 'welcome-rpc' as never, result: { ok: true as const, value } } } function mount(version?: string, mutateImpl: () => Promise = () => Promise.resolve(response({}))) { + const appRoot = document.createElement('div') + appRoot.id = 'root' + document.body.append(appRoot) const mutate = vi.fn(mutateImpl) const api = { settings: { @@ -28,6 +34,8 @@ function mount(version?: string, mutateImpl: () => Promise = () => Prom ns: WELCOME_NOTICE_SETTINGS_NAMESPACE, schema: {}, value: version === undefined ? {} : { [WELCOME_NOTICE_ACK_FIELD]: version }, + base: {}, + user: {}, applies: 'live' as const, secrets: [], revision: 0, @@ -46,35 +54,44 @@ function mount(version?: string, mutateImpl: () => Promise = () => Prom useSessions: unusedHook, useWorkspaces: unusedHook, controller, - useSnapshot: bindSnapshotSelector(controller.store), - t: key => key in zh ? zh[key as keyof typeof zh] : key, + useWelcome: bindSnapshotSelector(controller.store), + t: key => zh[key], } - return { ...render(), complete, controller, mutate } + return { ...render(), complete, controller, mutate, appRoot } } describe('WelcomeNotice', () => { - it('uses the same Chinese owner copy in both GUI locales', () => { - expect(WELCOME_NOTICE_COPY.en).toEqual(WELCOME_NOTICE_COPY.zh) + it('uses the exact owner copy in both GUI locales', () => { + expect(WELCOME_NOTICE_COPY.en).toEqual({ + title: 'Internal Testing Notice', + body: "DeepSeek Harness 0.1 remains in testing for Harness developers. Many areas need further improvement, and we welcome feedback from the developer community. DeepSeek Harness's core plugins and foundational APIs will continue to evolve rapidly over the coming months.\n\nWe look forward to exploring the limits of intelligence with developers around the world, building on open-source, open, reusable, and composable infrastructure. We welcome Harness developers everywhere to join the DSH plugin ecosystem.", + continueLabel: 'Continue', + }) + expect(en.welcomeBody).toBe(WELCOME_NOTICE_COPY.en.body) + expect(zh.welcomeBody).toBe(WELCOME_NOTICE_COPY.zh.body) }) - it('renders the owner copy with one primary action and no dismissal control', async () => { + it('renders one blocking modal action and focuses the title', async () => { const h = mount() - const page = await screen.findByRole('region', { name: WELCOME_NOTICE_COPY.zh.title }) - expect(screen.getByText(WELCOME_NOTICE_COPY.zh.title)).toBeTruthy() - for (const text of WELCOME_NOTICE_COPY.zh.paragraphs) expect(page.textContent).toContain(text) - expect(page.textContent?.match(/感谢您愿意拨冗试用 DeepSeek Harness/g) ?? []).toHaveLength(1) - const buttons = page.querySelectorAll('button') - expect(buttons).toHaveLength(1) + const dialog = await screen.findByRole('dialog', { name: WELCOME_NOTICE_COPY.zh.title }) + for (const paragraph of WELCOME_NOTICE_COPY.zh.body.split('\n\n')) { + expect(screen.getByText(paragraph, { exact: true })).toBeTruthy() + } + expect(dialog.querySelectorAll('p')).toHaveLength(2) + expect(dialog.querySelectorAll('button')).toHaveLength(1) expect(screen.getByRole('button', { name: WELCOME_NOTICE_COPY.zh.continueLabel })).toBeTruthy() expect(document.activeElement).toBe(screen.getByRole('heading', { name: WELCOME_NOTICE_COPY.zh.title })) + expect(h.appRoot.inert).toBe(true) + fireEvent.keyDown(document, { key: 'Escape' }) + fireEvent.click(document.querySelector('[class*="mask"]')!) expect(h.complete).not.toHaveBeenCalled() - expect(screen.getByRole('region')).toBeTruthy() + expect(screen.getByRole('dialog')).toBeTruthy() }) it('completes only after the acknowledgement write commits', async () => { const h = mount() - await screen.findByRole('region') + await screen.findByRole('dialog') fireEvent.click(screen.getByRole('button', { name: WELCOME_NOTICE_COPY.zh.continueLabel })) await act(async () => { await Promise.resolve() }) expect(h.mutate).toHaveBeenCalledOnce() @@ -84,7 +101,7 @@ describe('WelcomeNotice', () => { it('skips itself when this exact version was already acknowledged', async () => { const h = mount(WELCOME_NOTICE_VERSION) await act(async () => { await h.controller.load() }) - expect(screen.queryByRole('region')).toBeNull() + expect(screen.queryByRole('dialog')).toBeNull() expect(h.complete).toHaveBeenCalledOnce() }) @@ -92,15 +109,22 @@ describe('WelcomeNotice', () => { let resolveWrite!: (value: unknown) => void const write = new Promise((resolve) => { resolveWrite = resolve }) const h = mount(undefined, () => write) - await screen.findByRole('region') + await screen.findByRole('dialog') const action = screen.getByRole('button', { name: WELCOME_NOTICE_COPY.zh.continueLabel }) fireEvent.click(action) expect(action.disabled).toBe(true) resolveWrite({ rpcId: 'welcome-refused' as never, - result: { ok: false, error: { code: 'settings-rejected', message: 'read only', details: { ns: WELCOME_NOTICE_SETTINGS_NAMESPACE } } }, + result: { + ok: false, + error: { + code: 'settings-rejected', + message: 'read only', + details: { ns: WELCOME_NOTICE_SETTINGS_NAMESPACE }, + }, + }, }) - expect((await screen.findByRole('alert')).textContent).toBe('暂时无法保存确认状态,请重试。') + expect((await screen.findByRole('alert')).textContent).toBe(zh.welcomeError) expect(h.complete).not.toHaveBeenCalled() }) }) diff --git a/packages/client/ui-settings-general/tests/welcome-store.client.spec.ts b/packages/client/ui-settings-models/tests/welcome-store.client.spec.ts similarity index 88% rename from packages/client/ui-settings-general/tests/welcome-store.client.spec.ts rename to packages/client/ui-settings-models/tests/welcome-store.client.spec.ts index bfa5e16999..e1fa7572c3 100644 --- a/packages/client/ui-settings-general/tests/welcome-store.client.spec.ts +++ b/packages/client/ui-settings-models/tests/welcome-store.client.spec.ts @@ -1,7 +1,6 @@ import { describe, expect, it, vi } from 'vitest' import type { RpcResponse } from '@deepseek-ai/dsh-api-remotes/client' -import { WelcomeNoticeStore } from '../src/client/welcome-store.ts' -import { refreshWelcomeIfLoaded } from '../src/client/welcome-store.ts' +import { refreshWelcomeIfLoaded, WelcomeNoticeStore } from '../src/client/welcome-store.ts' import { WELCOME_NOTICE_ACK_FIELD, WELCOME_NOTICE_SETTINGS_NAMESPACE, WELCOME_NOTICE_VERSION, } from '../src/onboarding-copy.ts' @@ -16,6 +15,8 @@ function namespace(version?: string) { ns: WELCOME_NOTICE_SETTINGS_NAMESPACE, schema: {}, value: version === undefined ? {} : { [WELCOME_NOTICE_ACK_FIELD]: version }, + base: {}, + user: {}, applies: 'live' as const, secrets: [], revision: 0, @@ -53,7 +54,9 @@ describe('WelcomeNoticeStore', () => { ] as const) { const api = { settings: { - describe: vi.fn(() => Promise.resolve(ok({ writable: true, hasDocument: false, namespaces: [namespace(version)] }))), + describe: vi.fn(() => Promise.resolve(ok({ + writable: true, hasDocument: false, namespaces: [namespace(version)], + }))), }, } const controller = new WelcomeNoticeStore(api as never) @@ -88,8 +91,7 @@ describe('WelcomeNoticeStore', () => { const nonError = new WelcomeNoticeStore({ // Durable/wire failures are unknown; exercise containment of a non-Error rejection. - // oxlint-disable-next-line typescript/prefer-promise-reject-errors - settings: { describe: () => Promise.reject('offline string') }, + settings: { describe: () => Promise.reject(new Error('offline string')) }, } as never) await nonError.load() expect(nonError.store.getSnapshot().error).toBe('offline string') @@ -123,7 +125,14 @@ describe('WelcomeNoticeStore', () => { const save = new WelcomeNoticeStore({ settings: { mutate: () => Promise.resolve({ rpcId: 'failed-save' as never, - result: { ok: false, error: { code: 'settings-rejected', message: 'denied', details: { ns: WELCOME_NOTICE_SETTINGS_NAMESPACE } } }, + result: { + ok: false, + error: { + code: 'settings-rejected', + message: 'denied', + details: { ns: WELCOME_NOTICE_SETTINGS_NAMESPACE }, + }, + }, }) }, } as never) await expect(save.acknowledge()).resolves.toBe(false) @@ -134,11 +143,15 @@ describe('WelcomeNoticeStore', () => { const first = deferred>() const describe = vi.fn() .mockImplementationOnce(() => first.promise) - .mockImplementationOnce(() => Promise.resolve(ok({ writable: true, hasDocument: false, namespaces: [namespace()] }))) + .mockImplementationOnce(() => Promise.resolve(ok({ + writable: true, hasDocument: false, namespaces: [namespace()], + }))) const controller = new WelcomeNoticeStore({ settings: { describe } } as never) const stale = controller.load() await controller.load() - first.resolve(ok({ writable: true, hasDocument: false, namespaces: [namespace(WELCOME_NOTICE_VERSION)] })) + first.resolve(ok({ + writable: true, hasDocument: false, namespaces: [namespace(WELCOME_NOTICE_VERSION)], + })) await stale expect(controller.store.getSnapshot().acknowledged).toBe(false) @@ -157,7 +170,9 @@ describe('WelcomeNoticeStore', () => { it('contains stale acknowledgement settlements and refreshes only a loaded store', async () => { const write = deferred>() - const describe = vi.fn(() => Promise.resolve(ok({ writable: true, hasDocument: false, namespaces: [namespace()] }))) + const describe = vi.fn(() => Promise.resolve(ok({ + writable: true, hasDocument: false, namespaces: [namespace()], + }))) const controller = new WelcomeNoticeStore({ settings: { mutate: () => write.promise, describe }, } as never) diff --git a/packages/client/ui-settings-plugin-inventory/package.json b/packages/client/ui-settings-plugin-inventory/package.json index 9b24c3e6af..95af8a15fa 100644 --- a/packages/client/ui-settings-plugin-inventory/package.json +++ b/packages/client/ui-settings-plugin-inventory/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-client-ui-settings-plugin-inventory", "description": "Read-only Cordis Loader inventory tab in Web Plugins settings", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -44,7 +44,7 @@ "bundle": "tsdown", "watch": "tsdown --watch" }, - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-api-remotes": "workspace:^", "@deepseek-ai/dsh-client-locale": "workspace:^", diff --git a/packages/client/ui-settings-plugins/README.i18n.yaml b/packages/client/ui-settings-plugins/README.i18n.yaml index 09e742cf23..ae8c3a78bf 100644 --- a/packages/client/ui-settings-plugins/README.i18n.yaml +++ b/packages/client/ui-settings-plugins/README.i18n.yaml @@ -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/client/ui-settings-plugins/README.md -README.md: 53418f8939649bae4413625a37630e46e7060d15 -README.zh.md: 8d4a2bf8d1af662e9f8e05ccc607cc8b66731731 +README.md: 92ba426b6bee3ae73e184dfcfd418e889bd47086 +README.zh.md: dc319ea9f128016b6df821575cb4d75740f04579 diff --git a/packages/client/ui-settings-plugins/README.md b/packages/client/ui-settings-plugins/README.md index 53418f8939..92ba426b6b 100644 --- a/packages/client/ui-settings-plugins/README.md +++ b/packages/client/ui-settings-plugins/README.md @@ -6,13 +6,13 @@ The **Plugins** settings section and its **Plugin configuration** tab. The secti ## What appears here -A card renders only when its namespace is both registered by a live Host plugin and served to the browser. A deployment that does not compose the owning plugin — or serves the namespace to no client — renders nothing for it rather than an empty or disabled card, so the configurable tab reflects what this deployment actually runs. +The configurable tab reads which settings namespaces the Host serves and dispatches one slot key per namespace, so what renders is the intersection of two ledgers: the namespaces a live Host plugin registered, and the cards registered under those keys. A served namespace no card claims renders nothing — another surface owns it, or this deployment ships no browser half for it — and a card whose namespace this deployment does not serve is never dispatched, so an uncomposed plugin leaves no trace and does not hold the tab back from its empty line. The empty line waits for the Host's first answer, so an unanswered read never reads as "this deployment configures no plugin". Cards appear in the order they registered, which is stable for the cards one package installs together and not stable across plugins: apply order between packages is unconstrained. -The first batch covers the shell executor (`bash`), the agent loop's tool-call parallelism (`agent-loop`), and the DeepSeek search provider (`web-search-deepseek`). +The cards this package ships cover the shell executor (`bash`), the agent loop's tool-call parallelism (`agent-loop`), and the DeepSeek search provider (`web-search-deepseek`). ## Extension point -The section declares `settings.plugins.tab`, a root list slot whose labels become ordered tabs. It keeps a tab mounted after its first selection, so local drafts and read-only snapshots survive tab switches. The package registers its own `configurable` contribution, which declares the nested `settings.plugin.item` list slot. A plugin that ships a browser half registers its own card into that nested slot and owns its controls; this package neither enumerates namespaces nor renders a form it was not given. Both levels follow the contribution's `order`. +The section declares `settings.plugins.tab`, a root list slot whose labels become ordered tabs. It keeps a tab mounted after its first selection, so local drafts and read-only snapshots survive tab switches. The package registers its own `configurable` contribution, which declares the nested `settings.plugin.item` slot — keyed on the settings namespace a card edits. A plugin that ships a browser half registers its own card under its own namespace and owns every part of it: chrome, controls, and copy. Keying on the namespace is what lets a plugin distributed outside this repository appear here — it registers the namespace on the Host and the card in the browser, and the tab pairs the two without learning what the namespace means. Tabs follow the contribution's `order`; cards follow registration order. ## Writes @@ -35,6 +35,6 @@ None; this package neither assembles nor sends a provider request. ## Known Limitations and Deferred Work - **Only host-plane plugins appear** — a plugin an agent preset mounts carries its configuration inline in that preset's `agent.cordis.yml` and cannot register a settings namespace at all (a second session mounting the same preset would fail on a duplicate registration), so this section lists nothing for it. Editing those values remains the preset editor's job. -- **Exposure is a Host allowlist, not a plugin declaration** — a namespace absent from the api-proxy's allowlist answers `settings-not-exposed` even when its owner registered it, so a plugin distributed outside this repository cannot surface its own configuration here without a change in `packages/host/apiproxy`. +- **A card still needs a browser bundle** — the browser half must be a `dsh.client` package built in the client module system's lazy-CJS factory format, and the `clientBundle` preset that emits it lives in `packages/client/tsdown.client.ts` rather than a published package, so a plugin outside this repository has to reproduce that build itself. The bundle-purity gate also forbids importing this package's card chrome or form model as values, so such a card owns its own staging and revision fencing. +- **The served namespaces re-read on two signals only** — the wire announces settings-document commits and connection resets, not registrations, so a namespace whose owner registers after the tab's read joins the list on the next document commit or reconnect. - **The shell card follows the composed executor** — the POSIX and PowerShell executor families share the `bash` namespace because a host composes exactly one of them, so the served schema differs by platform (PowerShell adds `pwshPath`) even though the card edits the same two fields on both, and a deployment composing neither shows no card. -- **The empty line counts registered cards, not visible ones** — a card whose namespace this deployment does not expose renders nothing, but still counts, so a deployment that exposes none shows an empty list rather than the empty line. The count is also read once, because the renderer caches a root entry's inject face; a card registered later does not raise it. diff --git a/packages/client/ui-settings-plugins/README.zh.md b/packages/client/ui-settings-plugins/README.zh.md index 8d4a2bf8d1..dc319ea9f1 100644 --- a/packages/client/ui-settings-plugins/README.zh.md +++ b/packages/client/ui-settings-plugins/README.zh.md @@ -6,13 +6,13 @@ ## 这里会出现什么 -只有当某个命名空间既被存活的 Host 插件注册、又被服务给浏览器时,它的卡片才会渲染。未组装该插件的部署——或未向任何客户端服务该命名空间的部署——不会渲染空卡片或禁用卡片,而是什么都不渲染,因此“插件配置”标签页反映的是该部署实际运行的东西。 +“插件配置”标签页读取 Host 服务了哪些 settings 命名空间,并为每个命名空间派发一个 slot 键,因此渲染出来的是两份账本的交集:存活 Host 插件注册的命名空间,以及注册在这些键上的卡片。被服务却无人认领的命名空间什么都不渲染——它归别的界面所有,或本部署没有为它提供浏览器半侧;而命名空间未被本部署服务的卡片根本不会被派发,因此未组装的插件不留任何痕迹,也不会挡住那行空态文案。空态文案要等 Host 的第一次答复,因此一次尚未答复的读取绝不会被读成“本部署没有可配置的插件”。卡片按自身注册的顺序出现;对同一个包一起安装的卡片这是稳定的,对跨插件的卡片则不稳定:包与包之间的 apply 顺序是无约束的。 -第一批覆盖 shell 执行器(`bash`)、agent 循环的工具调用并行度(`agent-loop`)以及 DeepSeek 搜索提供方(`web-search-deepseek`)。 +本包自带的卡片覆盖 shell 执行器(`bash`)、agent 循环的工具调用并行度(`agent-loop`)以及 DeepSeek 搜索提供方(`web-search-deepseek`)。 ## 扩展点 -本分区声明根级列表 slot `settings.plugins.tab`,其标签会成为有序标签页。某个标签页首次被选择后会保持挂载,因此本地草稿与只读快照在切换标签页时不会丢失。本包注册自己的 `configurable` 贡献,由它声明嵌套的 `settings.plugin.item` 列表 slot。带浏览器半侧的插件把自己的卡片注册进这个嵌套 slot 并拥有其控件;本包既不枚举命名空间,也不渲染未被交给它的表单。两层排序都遵循贡献的 `order`。 +本分区声明根级列表 slot `settings.plugins.tab`,其标签会成为有序标签页。某个标签页首次被选择后会保持挂载,因此本地草稿与只读快照在切换标签页时不会丢失。本包注册自己的 `configurable` 贡献,由它声明嵌套的 `settings.plugin.item` slot——以卡片所编辑的 settings 命名空间为键。带浏览器半侧的插件把自己的卡片注册在自己的命名空间上,并拥有它的全部:外观、控件与文案。以命名空间为键,正是在本仓库之外分发的插件能出现在这里的原因——它在 Host 上注册命名空间、在浏览器里注册卡片,由标签页把两者配对,而无需知道命名空间意味着什么。标签页遵循贡献的 `order`;卡片遵循注册顺序。 ## 写入 @@ -35,6 +35,6 @@ ## 已知限制与暂缓事项 - **只有宿主平面的插件会出现**——由 agent preset 挂载的插件把配置内联在该 preset 的 `agent.cordis.yml` 中,且根本无法注册 settings 命名空间(同一 preset 挂载第二个会话时会因重复注册而失败),因此本分区不会列出它。编辑那些值仍是 preset 编辑器的职责。 -- **暴露是 Host 的白名单,而非插件的声明**——不在 api-proxy 白名单中的命名空间,即便其拥有方已注册,也只会得到 `settings-not-exposed`,因此在本仓库之外分发的插件无法在不改动 `packages/host/apiproxy` 的前提下让自己的配置出现在这里。 +- **卡片仍然需要一份浏览器 bundle**——浏览器半侧必须是按客户端模块系统的 lazy-CJS factory 格式构建的 `dsh.client` 包,而产出它的 `clientBundle` 预设位于 `packages/client/tsdown.client.ts`,并非已发布的包,因此本仓库之外的插件得自行复刻该构建。bundle 纯净度门禁同时禁止以值的形式导入本包的卡片外观与表单模型,所以这样的卡片要自行拥有暂存与 revision 设栅。 +- **被服务的命名空间只在两种信号上重读**——协议通告的是 settings 文档提交与连接重置,而非注册行为,因此在标签页读取之后才被其拥有方注册的命名空间,要等下一次文档提交或重连才会加入列表。 - **shell 卡片跟随被组装的执行器**——POSIX 与 PowerShell 两个执行器家族共用 `bash` 命名空间,因为一个宿主只组装其中之一,所以被服务的 schema 随平台不同(PowerShell 多出 `pwshPath`),尽管卡片在两者下编辑的都是同样两个字段;而两者都不组装的部署不会显示这张卡片。 -- **空态数的是已注册卡片,不是可见卡片**——命名空间未被本部署暴露的卡片什么都不渲染,但仍计入数量,因此一个都不暴露的部署看到的是空列表而非那行空态文案。该计数还只读取一次,因为渲染器会缓存根级 entry 的 inject face;之后注册的卡片不会让它变大。 diff --git a/packages/client/ui-settings-plugins/package.json b/packages/client/ui-settings-plugins/package.json index a5464633ab..a9fd7b8e9d 100644 --- a/packages/client/ui-settings-plugins/package.json +++ b/packages/client/ui-settings-plugins/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-client-ui-settings-plugins", "description": "Plugins settings section with feature-owned tabs and configurable host-plane plugin cards", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -45,7 +45,7 @@ "bundle": "tsdown", "watch": "tsdown --watch" }, - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "workspace:^", "@deepseek-ai/dsh-api-remotes": "workspace:^", diff --git a/packages/client/ui-settings-plugins/src/client/ConfigurablePluginsTab.tsx b/packages/client/ui-settings-plugins/src/client/ConfigurablePluginsTab.tsx index 4e7b575fd5..c9b4365a3a 100644 --- a/packages/client/ui-settings-plugins/src/client/ConfigurablePluginsTab.tsx +++ b/packages/client/ui-settings-plugins/src/client/ConfigurablePluginsTab.tsx @@ -1,25 +1,43 @@ -/** Configurable Host plugins contributed to the shared Plugins section. */ +/** + * Configurable Host plugins contributed to the shared Plugins section. + * + * The tab enumerates settings namespaces but never interprets one — a card + * arrives through `settings.plugin.item` keyed by the namespace it edits, so a + * plugin that ships a browser half owns its own card and this tab only decides + * which keys to dispatch. + */ +import { Fragment } from 'react' import type { InjectFace, PropsLocale, PropsRenderSlots, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots' import type {} from './slot-contract.ts' +import type { ConfigurablePluginsTabFace } from './tab-store.ts' import css from './PluginsSettingsSection.module.css' -/** Registration-side business face for the configurable tab. */ -export interface ConfigurablePluginsTabInjected { - /** How many cards the slot ledger held when the tab registration mounted. */ - cardCount: number -} - /** Props the renderer binds for the configurable tab. */ export type ConfigurablePluginsTabProps = PropsRuntime<'settings.plugins.tab'> & PropsLocale<'settings.plugins'> & PropsRenderSlots<'settings.plugin.item'> - & InjectFace + & InjectFace -/** Render cards registered by plugins that expose editable settings. */ -export function ConfigurablePluginsTab({ t, renderSlot, cardCount }: ConfigurablePluginsTabProps) { - return cardCount === 0 - ?

{t('empty')}

- :
    {renderSlot('settings.plugin.item', {})}
+/** + * Render cards registered by plugins that expose editable settings. + * @param props - locale copy, slot rendering, and the namespaces to dispatch. + * @returns the card list, or the empty line once the Host has answered. + */ +export function ConfigurablePluginsTab(props: ConfigurablePluginsTabProps) { + const { t, renderSlot } = props + const { loaded, namespaces } = props.useConfigurablePlugins(snapshot => snapshot) + if (namespaces.length > 0) { + return ( +
    + {namespaces.map(ns => ( + // One dispatch per namespace, so the list identity is the namespace + // rather than a position that shifts as cards arrive. + {renderSlot('settings.plugin.item', {}, { entryKey: ns })} + ))} +
+ ) + } + return loaded ?

{t('empty')}

: null } diff --git a/packages/client/ui-settings-plugins/src/client/index.ts b/packages/client/ui-settings-plugins/src/client/index.ts index dd0b80d89a..82dea6d796 100644 --- a/packages/client/ui-settings-plugins/src/client/index.ts +++ b/packages/client/ui-settings-plugins/src/client/index.ts @@ -23,17 +23,18 @@ import type {} from '@deepseek-ai/dsh-api-remotes/client' import { AgentLoopCard } from './AgentLoopCard.tsx' import { BashCard } from './BashCard.tsx' import { ConfigurablePluginsTab } from './ConfigurablePluginsTab.tsx' -import type { ConfigurablePluginsTabInjected } from './ConfigurablePluginsTab.tsx' import { PluginsSettingsSection } from './PluginsSettingsSection.tsx' import type { PluginsSettingsSectionInjected, PluginsSettingsTabEntry } from './PluginsSettingsSection.tsx' import { WebSearchCard } from './WebSearchCard.tsx' import { AGENT_LOOP_NS, AgentLoopCardController } from './agent-loop-card-controller.ts' import { SHELL_NS, BashCardController } from './bash-card-controller.ts' +import { ConfigurablePluginsTabController } from './tab-store.ts' import { WEB_SEARCH_NS, WebSearchCardController } from './web-search-card-controller.ts' import { en, zh } from './locales.ts' export type { PluginsSettingsSectionInjected, PluginsSettingsSectionProps } from './PluginsSettingsSection.tsx' -export type { ConfigurablePluginsTabInjected, ConfigurablePluginsTabProps } from './ConfigurablePluginsTab.tsx' +export type { ConfigurablePluginsTabProps } from './ConfigurablePluginsTab.tsx' +export type { ConfigurablePluginsTabFace, ConfigurablePluginsTabState } from './tab-store.ts' export type { PluginCardProps } from './PluginCard.tsx' export type { SettingsPluginItemOwnerProps } from './slot-contract.ts' export type { FieldProps } from './fields.tsx' @@ -71,6 +72,27 @@ export function apply(ctx: ClientContext): void { 'ui-settings-plugins: credential invalidations', ) + // Which namespaces the Host serves is a registration fact the wire does not + // announce, so the directory re-reads on the two signals that can carry a + // changed composition: a settings document commit and a reconnect. + const configurable = new ConfigurablePluginsTabController( + api, () => ctx.slots.entries('settings.plugin.item')) + ctx.effect(() => () => { configurable.dispose() }, 'ui-settings-plugins: tab directory') + ctx.effect( + () => ctx.remote.$on('settings/document-updated', () => { void configurable.load() }), + 'ui-settings-plugins: served-namespace invalidations', + ) + ctx.effect( + () => ctx.on('connection/reset', () => { void configurable.load() }), + 'ui-settings-plugins: served-namespace reconnect', + ) + // A card registered after the first read joins the list without a wire call. + ctx.effect( + () => ctx.slots.subscribe('settings.plugin.item', () => { configurable.refresh() }), + 'ui-settings-plugins: card ledger', + ) + void configurable.load() + let tabsVersion = -1 let tabsRevision = -1 let tabs: readonly PluginsSettingsTabEntry[] = [] @@ -126,31 +148,26 @@ export function apply(ctx: ClientContext): void { order: 0, label: () => t('configurableTab'), locale: NS, - inject: (): ConfigurablePluginsTabInjected => ({ - cardCount: ctx.slots.entries('settings.plugin.item').length, - }), - children: { 'settings.plugin.item': { kind: 'list', scope: 'root' } }, + inject: () => configurable.inject(), + children: { 'settings.plugin.item': { kind: 'keyed', scope: 'root' } }, }, ConfigurablePluginsTab)) ctx.slots.inject('settings.plugin.item', function* () { yield ctx.slots.register({ name: 'settings.plugin.item', - id: 'bash', - order: 0, + key: SHELL_NS, locale: NS, inject: () => bash.inject(), }, BashCard) yield ctx.slots.register({ name: 'settings.plugin.item', - id: 'agent-loop', - order: 10, + key: AGENT_LOOP_NS, locale: NS, inject: () => agentLoop.inject(), }, AgentLoopCard) yield ctx.slots.register({ name: 'settings.plugin.item', - id: 'web-search', - order: 20, + key: WEB_SEARCH_NS, locale: NS, inject: () => webSearch.inject(), }, WebSearchCard) diff --git a/packages/client/ui-settings-plugins/src/client/slot-contract.ts b/packages/client/ui-settings-plugins/src/client/slot-contract.ts index 02b00ea35b..ecb84acadc 100644 --- a/packages/client/ui-settings-plugins/src/client/slot-contract.ts +++ b/packages/client/ui-settings-plugins/src/client/slot-contract.ts @@ -1,19 +1,22 @@ /** - * The `settings.plugin.item` slot type — one plugin's card inside the plugin - * configuration section. Options: `id` (card key), `order` (card position). - * A card draws its own internals; the section only stacks them and reports - * how many there are. + * The `settings.plugin.item` slot type — one plugin's card inside the + * configurable-plugins tab, keyed by the settings namespace the card edits. + * Options: `key` (the namespace). A card draws its own internals; the tab only + * decides which namespaces to dispatch and stacks what comes back. * - * TYPE HOME RATIONALE: unlike `settings.general.item`, whose registrants span - * packages that cannot reference its declarer, every current registrant of - * this slot ships in this package, and a plugin registering its own card - * already depends on this package for the card chrome. The type therefore - * lives with the section that declares it at runtime. + * Keying on the namespace is what lets a plugin distributed outside this + * repository contribute a card: it registers its own settings namespace on the + * Host and its own card under that key in the browser, and the tab pairs the + * two without ever learning what the namespace means. + * + * TYPE HOME RATIONALE: the tab declares this slot at runtime, and a plugin + * registering its own card already depends on this package for the slot's + * declaration. The type therefore lives with its declarer. */ declare module '@deepseek-ai/dsh-client-ui-slots' { interface SlotMap { /** One plugin's card inside the plugin configuration section (see module JSDoc). */ - 'settings.plugin.item': { kind: 'list'; scope: 'root'; owner: SettingsPluginItemOwnerProps } + 'settings.plugin.item': { kind: 'keyed'; scope: 'root'; owner: SettingsPluginItemOwnerProps } } } diff --git a/packages/client/ui-settings-plugins/src/client/tab-store.ts b/packages/client/ui-settings-plugins/src/client/tab-store.ts new file mode 100644 index 0000000000..a4ed4439f2 --- /dev/null +++ b/packages/client/ui-settings-plugins/src/client/tab-store.ts @@ -0,0 +1,123 @@ +/** + * The configurable-plugins tab's card list. + * + * The tab dispatches its slot by settings namespace, so what it renders is + * the intersection of two ledgers: the namespaces the Host serves and the + * cards registered into `settings.plugin.item`. A served namespace no card + * claims renders nothing — another surface owns it, or this deployment ships + * no browser half for it — and a card whose namespace the Host does not serve + * is never dispatched, so a plugin this deployment did not compose leaves no + * trace and does not count toward the empty line. + */ + +import type { IApiClient } from '@deepseek-ai/dsh-client-connection/client' +import type { StoredEntry } from '@deepseek-ai/dsh-client-ui-slots' +import { createSnapshotStore, type SnapshotStore } from '@deepseek-ai/dsh-client-runtime/client' + +/** What the section renders. */ +export interface ConfigurablePluginsTabState { + /** + * Whether the Host has answered once. The empty line waits for it: an + * unanswered read is not the same statement as "this deployment configures + * no plugin", and saying the second while the first is true would flash a + * wrong answer on every open. + */ + loaded: boolean + /** + * Namespaces to dispatch, in the order their cards registered, narrowed to + * those the Host serves. Card registration order rather than the Host's + * description order: the latter follows plugin activation, which async + * settings injection can reorder between boots, and a settings page whose + * cards move between visits is worse than one whose order a registrant + * chose. + */ + namespaces: string[] +} + +/** The registration-side face the tab's slot entry injects. */ +export interface ConfigurablePluginsTabFace { + hooks: { + /** Section snapshot bound by the renderer as usePluginConfigSection. */ + configurablePlugins: SnapshotStore + } +} + +/** Reads the served namespaces and pairs them with the cards that claim them. */ +export class ConfigurablePluginsTabController { + private readonly store = createSnapshotStore({ loaded: false, namespaces: [] }) + /** Last Host answer; kept so a slot mutation republishes without a wire read. */ + private served: readonly string[] = [] + private loaded = false + private generation = 0 + private disposed = false + + /** + * @param api - settings wire face. + * @param entries - reads the cards currently registered into the section's slot. + */ + constructor( + private readonly api: Pick, + private readonly entries: () => readonly StoredEntry[], + ) {} + + /** Opaque read of {@link disposed}: control flow cannot narrow it across awaits. */ + private isDisposed(): boolean { + return this.disposed + } + + /** + * Re-read the served namespaces from the Host and republish. + * @returns settlement after the read, or immediately once disposed. + */ + async load(): Promise { + if (this.isDisposed()) return + const generation = ++this.generation + let response: Awaited> + try { + response = await this.api.settings.describe({}) + } catch (_settingsReadFailure) { + // The tab keeps the namespaces it last knew; the next invalidation + // or reconnect reads again. + return + } + if (this.isDisposed() || generation !== this.generation || !response.result.ok) return + this.served = response.result.value.namespaces.map(view => view.ns) + this.loaded = true + this.publish() + } + + /** Republish after the slot ledger changed; a card registered late joins here. */ + refresh(): void { + if (this.disposed) return + this.publish() + } + + /** Stop publishing; an in-flight read settles without touching the store. */ + dispose(): void { + this.disposed = true + this.generation += 1 + } + + /** + * Build the face the tab's slot registration injects. + * @returns the tab's snapshot source. + */ + inject(): ConfigurablePluginsTabFace { + return { hooks: { configurablePlugins: this.store } } + } + + private publish(): void { + const served = new Set(this.served) + const namespaces = this.entries().flatMap(entry => + entry.options.key !== undefined && served.has(entry.options.key) ? [entry.options.key] : []) + const previous = this.store.getSnapshot() + // Every settings-document commit re-reads, and most of them change nothing + // this section shows. An observable source must keep its snapshot + // reference until the fact moves, or each unrelated save re-renders the + // whole card list (packages/client/AGENTS.md reactive rule 5). + if (previous.loaded === this.loaded + && previous.namespaces.length === namespaces.length + && previous.namespaces.every((ns, index) => ns === namespaces[index])) return + this.store.set({ loaded: this.loaded, namespaces }) + } +} diff --git a/packages/client/ui-settings-plugins/src/invariant.ts b/packages/client/ui-settings-plugins/src/invariant.ts index 5e21f38157..4b0eba850c 100644 --- a/packages/client/ui-settings-plugins/src/invariant.ts +++ b/packages/client/ui-settings-plugins/src/invariant.ts @@ -16,8 +16,8 @@ export const inject = ['invariants'] /** * No runtime invariant: this is a browser-side settings surface whose node half owns no event - * stream or mutable runtime data; the layering, write refusals, and exposure boundary are Host - * contracts covered by the owning plugins and the api-proxy. + * stream or mutable runtime data; the layering and write refusals are Host contracts covered by + * the owning plugins and the api-proxy. */ const install: InvariantInstaller = () => {} diff --git a/packages/client/ui-settings-plugins/tests/apply.client.spec.ts b/packages/client/ui-settings-plugins/tests/apply.client.spec.ts index 112f088006..2934097b94 100644 --- a/packages/client/ui-settings-plugins/tests/apply.client.spec.ts +++ b/packages/client/ui-settings-plugins/tests/apply.client.spec.ts @@ -9,19 +9,38 @@ import { TestRemote, usePinnedBrowserLanguages } from '@deepseek-ai/dsh-client-t import { SettingsScopeBinder } from '@deepseek-ai/dsh-client-ui-settings/client' import { apply, inject } from '@deepseek-ai/dsh-client-ui-settings-plugins/client' import type { - ConfigurablePluginsTabInjected, PluginsSettingsSectionInjected, + ConfigurablePluginsTabFace, PluginsSettingsSectionInjected, } from '@deepseek-ai/dsh-client-ui-settings-plugins/client' // The service reads its initial locale from the browser; these specs assert // the shipped Chinese copy, so they state the browser they assume. usePinnedBrowserLanguages('zh-CN') -async function bench() { +/** + * @param served - namespaces the Host describes; omitted answers a failed read, + * which is what most of these specs want (no card has anything to render). + */ +async function bench(served?: string[]) { const ctx = new Context() await ctx.plugin(SlotRegistry).await() const locale = new LocaleRuntime(ctx) ctx.provide('locale', locale) const describeCredentials = vi.fn(() => Promise.resolve({ rpcId: 'c', result: { ok: false, error: {} } })) + const describeSettings = vi.fn(() => Promise.resolve(served === undefined + ? { rpcId: 's', result: { ok: false, error: {} } } + : { + rpcId: 's', + result: { + ok: true, + value: { + writable: true, + hasDocument: true, + namespaces: served.map(ns => ({ + ns, schema: {}, value: {}, applies: 'live', secrets: [], revision: 0, + })), + }, + }, + })) // The section binds its scopes through the Settings surface's service, and // forwarded Host events reach it through the same `$dispatch` handoff the // connection sink makes. @@ -29,12 +48,12 @@ async function bench() { ctx.provide('connection', { isLoopback: true, api: { - settings: { describe: vi.fn(() => Promise.resolve({ rpcId: 's', result: { ok: false, error: {} } })) }, + settings: { describe: describeSettings }, credentials: { describe: describeCredentials }, }, } as never) await ctx.plugin(SettingsScopeBinder).await() - return { ctx, slots: ctx.get('slots') as SlotRegistry, describeCredentials } + return { ctx, slots: ctx.get('slots') as SlotRegistry, describeCredentials, describeSettings } } function declareRoot(slots: SlotRegistry): () => void { @@ -63,20 +82,11 @@ describe('ui-settings-plugins apply', () => { const tab = slots.entries('settings.plugins.tab')[0]! expect(tab.options).toMatchObject({ id: 'configurable', order: 0 }) expect(resolveSlotLabel(tab.options.label)).toBe('插件配置') - expect(slots.spec('settings.plugin.item')).toMatchObject({ kind: 'list', scope: 'root' }) + expect(slots.spec('settings.plugin.item')).toMatchObject({ kind: 'keyed', scope: 'root' }) }) - it('registers one card per host-plane section it ships, in a stable order', async () => { - const { ctx, slots } = await bench() - declareRoot(slots) - await ctx.plugin({ inject: [...inject], apply }).await() - - expect(slots.entries('settings.plugin.item').map(entry => entry.options.id)) - .toEqual(['bash', 'agent-loop', 'web-search']) - }) - - it('injects a live tab projection, a card count, and one business face per card', async () => { + it('injects a live tab projection, the card directory, and one business face per card', async () => { const { ctx, slots } = await bench() declareRoot(slots) await ctx.plugin({ inject: [...inject], apply }).await() @@ -99,7 +109,8 @@ describe('ui-settings-plugins apply', () => { unsubscribe() const tab = slots.entries('settings.plugins.tab')[0]! - expect((tab.inject as unknown as () => ConfigurablePluginsTabInjected)()).toEqual({ cardCount: 3 }) + const tabFace = (tab.inject as unknown as () => ConfigurablePluginsTabFace)() + expect(Object.keys(tabFace.hooks)).toEqual(['configurablePlugins']) for (const entry of slots.entries('settings.plugin.item')) { const face = (entry as { inject?: () => unknown }).inject?.() as { hooks: Record } // Each card injects exactly one snapshot store plus its own actions. @@ -107,6 +118,58 @@ describe('ui-settings-plugins apply', () => { } }) + it('keys each card it ships on the settings namespace that card edits', async () => { + const { ctx, slots } = await bench() + declareRoot(slots) + + await ctx.plugin({ inject: [...inject], apply }).await() + + expect(slots.entries('settings.plugin.item').map(entry => entry.options.key)) + .toEqual(['shell', 'agent-loop', 'web-search-deepseek']) + }) + + it('dispatches the served namespaces its cards claim, and no others', async () => { + // ui-theme is served but belongs to another surface, and a deployment + // composing no PowerShell/POSIX executor serves no `bash` at all. + const { ctx, slots } = await bench(['agent-loop', 'ui-theme', 'web-search-deepseek']) + declareRoot(slots) + await ctx.plugin({ inject: [...inject], apply }).await() + + const tab = slots.entries('settings.plugins.tab')[0]! + const face = (tab.inject as unknown as () => ConfigurablePluginsTabFace)() + await vi.waitFor(() => { + expect(face.hooks.configurablePlugins.getSnapshot().namespaces) + .toEqual(['agent-loop', 'web-search-deepseek']) + }) + }) + + it('re-reads the served namespaces when the Host commits a settings document', async () => { + // Which namespaces the Host serves is a registration fact the wire never + // announces on its own, so the tab rides the invalidation that can + // accompany a changed composition. + const { ctx, slots, describeSettings } = await bench(['bash']) + declareRoot(slots) + await ctx.plugin({ inject: [...inject], apply }).await() + await vi.waitFor(() => { expect(describeSettings).toHaveBeenCalled() }) + describeSettings.mockClear() + + ctx.remote.$dispatch('settings/document-updated', ['bash', 1]) + + await vi.waitFor(() => { expect(describeSettings).toHaveBeenCalled() }) + }) + + it('re-reads the served namespaces after a reconnect', async () => { + const { ctx, slots, describeSettings } = await bench(['bash']) + declareRoot(slots) + await ctx.plugin({ inject: [...inject], apply }).await() + await vi.waitFor(() => { expect(describeSettings).toHaveBeenCalled() }) + describeSettings.mockClear() + + ctx.emit('connection/reset') + + await vi.waitFor(() => { expect(describeSettings).toHaveBeenCalled() }) + }) + it('re-reads the credential when the Host reports the watched reference changed', async () => { const { ctx, slots, describeCredentials } = await bench() declareRoot(slots) diff --git a/packages/client/ui-settings-plugins/tests/section.client.spec.tsx b/packages/client/ui-settings-plugins/tests/section.client.spec.tsx index fda55c3bf1..f521d7189f 100644 --- a/packages/client/ui-settings-plugins/tests/section.client.spec.tsx +++ b/packages/client/ui-settings-plugins/tests/section.client.spec.tsx @@ -22,6 +22,7 @@ import type { WebSearchCardProps } from '../src/client/WebSearchCard.tsx' import type { AgentLoopCardState } from '../src/client/agent-loop-card-controller.ts' import type { BashCardState } from '../src/client/bash-card-controller.ts' import type { CardFieldState, CardShell } from '../src/client/card-form.ts' +import type { ConfigurablePluginsTabState } from '../src/client/tab-store.ts' import type { WebSearchCardState } from '../src/client/web-search-card-controller.ts' import { en } from '../src/client/locales.ts' @@ -59,11 +60,20 @@ function renderSection(rows: readonly PluginsSettingsTabEntry[]) { render() } -function renderConfigurable(cardCount: number, cards = 'cards') { +/** + * Render the tab over the namespaces it was told to dispatch, with `cards` + * standing in for the slot ledger: a key it names renders that text, and one + * it does not renders nothing, exactly as an unclaimed key does. + */ +function renderConfigurable(namespaces: string[], cards: Record = {}, loaded = true) { + const store = createSnapshotStore({ loaded, namespaces }) const props = { t, - cardCount, - renderSlot: () =>
  • {cards}
  • , + useConfigurablePlugins: bindSnapshotSelector(store), + renderSlot: (_name: string, _owner: object, opts?: { entryKey?: string }) => { + const card = opts?.entryKey === undefined ? undefined : cards[opts.entryKey] + return card === undefined ? null :
  • {card}
  • + }, } as unknown as ConfigurablePluginsTabProps render() } @@ -153,16 +163,24 @@ describe('PluginsSettingsSection', () => { describe('ConfigurablePluginsTab', () => { it('says so when no plugin contributed a card', () => { - renderConfigurable(0) + renderConfigurable([], { bash: 'shell' }) expect(screen.getByText(en.empty)).toBeTruthy() - expect(screen.queryByText('cards')).toBeNull() + expect(screen.queryByText('shell')).toBeNull() }) - it('renders the card list once a plugin contributed one', () => { - renderConfigurable(1) + it('withholds the empty line until the Host has answered once', () => { + // An unanswered read is not the statement that this deployment configures + // no plugin; saying it anyway would flash a wrong answer on every open. + renderConfigurable([], { bash: 'shell' }, false) - expect(screen.getByText('cards')).toBeTruthy() + expect(screen.queryByText(en.empty)).toBeNull() + }) + + it('dispatches one card per namespace, keyed by it', () => { + renderConfigurable(['bash', 'agent-loop'], { bash: 'shell', 'agent-loop': 'loop' }) + + expect(screen.getAllByRole('listitem').map(item => item.textContent)).toEqual(['shell', 'loop']) expect(screen.queryByText(en.empty)).toBeNull() }) }) diff --git a/packages/client/ui-settings-plugins/tests/stores.client.spec.ts b/packages/client/ui-settings-plugins/tests/stores.client.spec.ts index 15ad7cf76a..9901bc5eb1 100644 --- a/packages/client/ui-settings-plugins/tests/stores.client.spec.ts +++ b/packages/client/ui-settings-plugins/tests/stores.client.spec.ts @@ -8,6 +8,7 @@ import { stubSettingsScope, type StubSettingsScope } from '@deepseek-ai/dsh-clie import { CardForm, numberField, textField } from '../src/client/card-form.ts' import { AgentLoopCardController, type AgentLoopSettings } from '../src/client/agent-loop-card-controller.ts' import { BashCardController, type BashSettings } from '../src/client/bash-card-controller.ts' +import { ConfigurablePluginsTabController } from '../src/client/tab-store.ts' import { WebSearchCardController, type WebSearchSettings } from '../src/client/web-search-card-controller.ts' /** Make the stub behave like a Host that accepts every write. */ @@ -380,7 +381,7 @@ describe('AgentLoopCardController', () => { }) describe('WebSearchCardController', () => { - it('reads the credential state for the reference the section names', async () => { + it('reads the credential state for the reference the tab names', async () => { const host = stubSettingsScope() const credentials = credentialsApi(true) const controller = new WebSearchCardController(host.scope, credentials.api) @@ -460,7 +461,7 @@ describe('WebSearchCardController', () => { }) }) - it('addresses the reference the section declares rather than the default', async () => { + it('addresses the reference the tab declares rather than the default', async () => { const host = stubSettingsScope() const credentials = credentialsApi(false) const controller = new WebSearchCardController(host.scope, credentials.api) @@ -538,3 +539,131 @@ describe('WebSearchCardController', () => { expect(credentials.set).not.toHaveBeenCalled() }) }) + +describe('ConfigurablePluginsTabController', () => { + function settingsApi(namespaces: string[]) { + const describe = vi.fn(() => Promise.resolve({ + rpcId: 's-1' as never, + result: { + ok: true as const, + value: { + writable: true, + hasDocument: true, + namespaces: namespaces.map(ns => ({ + ns, schema: {}, value: {}, applies: 'live' as const, secrets: [], revision: 0, + })), + }, + }, + })) + return { api: { settings: { describe } } as never, describe } + } + + /** Slot ledger stand-in: one stored entry per registered card key. */ + function ledger(...keys: string[]) { + return keys.map(key => ({ component: null, options: { key } })) + } + + it('dispatches the served namespaces a card claims, in card registration order', async () => { + const settings = settingsApi(['bash', 'ui-theme', 'agent-loop']) + const controller = new ConfigurablePluginsTabController(settings.api, () => ledger('agent-loop', 'bash')) + + await controller.load() + + // ui-theme is served but claimed by no card here — another surface owns + // it. The order is the cards', not the Host's: plugin activation can + // reorder the description between boots. + expect(controller.inject().hooks.configurablePlugins.getSnapshot().namespaces) + .toEqual(['agent-loop', 'bash']) + }) + + it('never dispatches a card whose namespace this deployment does not serve', async () => { + const settings = settingsApi(['bash']) + const controller = new ConfigurablePluginsTabController(settings.api, () => ledger('bash', 'web-search-deepseek')) + + await controller.load() + + expect(controller.inject().hooks.configurablePlugins.getSnapshot().namespaces).toEqual(['bash']) + }) + + it('takes a card registered after the read without asking the Host again', async () => { + const settings = settingsApi(['bash']) + let entries = ledger() + const controller = new ConfigurablePluginsTabController(settings.api, () => entries) + await controller.load() + expect(controller.inject().hooks.configurablePlugins.getSnapshot().namespaces).toEqual([]) + + entries = ledger('bash') + controller.refresh() + + expect(controller.inject().hooks.configurablePlugins.getSnapshot().namespaces).toEqual(['bash']) + expect(settings.describe).toHaveBeenCalledOnce() + }) + + it('keeps the namespaces it knew when a read fails', async () => { + const settings = settingsApi(['bash']) + const controller = new ConfigurablePluginsTabController(settings.api, () => ledger('bash')) + await controller.load() + settings.describe.mockRejectedValueOnce(new Error('offline')) + + await controller.load() + + expect(controller.inject().hooks.configurablePlugins.getSnapshot().namespaces).toEqual(['bash']) + }) + + it('publishes nothing once disposed, and never claims it was answered', async () => { + const settings = settingsApi(['bash']) + const controller = new ConfigurablePluginsTabController(settings.api, () => ledger('bash')) + + controller.dispose() + await controller.load() + + expect(controller.inject().hooks.configurablePlugins.getSnapshot()) + .toEqual({ loaded: false, namespaces: [] }) + expect(settings.describe).not.toHaveBeenCalled() + }) + + it('ignores a slot-ledger change that arrives after disposal', async () => { + const settings = settingsApi(['bash']) + let entries = ledger() + const controller = new ConfigurablePluginsTabController(settings.api, () => entries) + await controller.load() + + controller.dispose() + entries = ledger('bash') + controller.refresh() + + expect(controller.inject().hooks.configurablePlugins.getSnapshot().namespaces).toEqual([]) + }) + + it('drops a read a newer one superseded', async () => { + // The section re-reads on every settings-document invalidation, so a slow + // first answer must not overwrite the newer one that already landed. + const settings = settingsApi(['bash']) + const controller = new ConfigurablePluginsTabController(settings.api, () => ledger('bash', 'agent-loop')) + const slow = Promise.withResolvers() + settings.describe.mockReturnValueOnce(slow.promise as never) + const stale = controller.load() + + await controller.load() + expect(controller.inject().hooks.configurablePlugins.getSnapshot().namespaces).toEqual(['bash']) + slow.resolve({ + rpcId: 's-0', + result: { ok: true, value: { writable: true, hasDocument: true, namespaces: [ + { ns: 'agent-loop', schema: {}, value: {}, applies: 'live', secrets: [], revision: 0 }, + ] } }, + }) + await stale + + expect(controller.inject().hooks.configurablePlugins.getSnapshot().namespaces).toEqual(['bash']) + }) + + it('reports the Host answered even when it serves nothing this tab shows', async () => { + const settings = settingsApi(['ui-theme']) + const controller = new ConfigurablePluginsTabController(settings.api, () => ledger('bash')) + + await controller.load() + + expect(controller.inject().hooks.configurablePlugins.getSnapshot()) + .toEqual({ loaded: true, namespaces: [] }) + }) +}) diff --git a/packages/client/ui-settings/package.json b/packages/client/ui-settings/package.json index 96114115e7..485092d2b9 100644 --- a/packages/client/ui-settings/package.json +++ b/packages/client/ui-settings/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-client-ui-settings", "description": "Settings domain base plugin: the settings-namespace scope service and the canonical settings slot-type contract", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -43,7 +43,7 @@ "bundle": "tsdown", "watch": "tsdown --watch" }, - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "workspace:^", "@deepseek-ai/dsh-api-remotes": "workspace:^", diff --git a/packages/client/ui-settings/src/client/contract/slots.ts b/packages/client/ui-settings/src/client/contract/slots.ts index 76c5f540f9..5413f8cb29 100644 --- a/packages/client/ui-settings/src/client/contract/slots.ts +++ b/packages/client/ui-settings/src/client/contract/slots.ts @@ -64,13 +64,11 @@ declare module '@deepseek-ai/dsh-client-ui-slots' { * Root-scoped onboarding steps contributed by settings features. The * shell mounts one ordered step at a time; the active registrant either * completes itself or keeps ownership until the user completes its sole - * path. Registrants own readiness, copy, dialog behavior, AND the - * takeover chrome: a step wraps its visible content in the - * OnboardingSurface primitive (mask, opaque stage, `#root` inert) and - * renders null while its private facts are still loading — the shell - * paints no chrome of its own, so a mounted-but-deciding step shows and - * blocks nothing (prevents a white flash on reload: a bare unwrapped step - * would render without mask or stage). + * path. Registrants own readiness, copy, dialog behavior, AND visible + * chrome: a step wraps its visible content in its modal surface (including + * `#root` inert ownership) and renders null while private facts are still + * loading. The shell paints no chrome of its own, so a mounted-but-deciding + * step shows and blocks nothing. */ 'settings.onboarding': { kind: 'list'; scope: 'root'; owner: SettingsOnboardingOwnerProps } /** diff --git a/packages/client/ui-sidebar/README.i18n.yaml b/packages/client/ui-sidebar/README.i18n.yaml index 562396d88f..ac3531b205 100644 --- a/packages/client/ui-sidebar/README.i18n.yaml +++ b/packages/client/ui-sidebar/README.i18n.yaml @@ -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/client/ui-sidebar/README.md -README.md: 9974118f69901de985e012e1b62f95a0bcee64c2 -README.zh.md: 11b0aa142cf62626ab6105e2c405d506e35349b0 +README.md: 7cc4fe0a722fe5f8cf0e983a0e3fdb30cd31bb64 +README.zh.md: 96b6f60f871758c126e6c387c6ce3f0993039af0 diff --git a/packages/client/ui-sidebar/README.md b/packages/client/ui-sidebar/README.md index 9974118f69..7cc4fe0a72 100644 --- a/packages/client/ui-sidebar/README.md +++ b/packages/client/ui-sidebar/README.md @@ -8,6 +8,8 @@ New Session starts the runtime's page-local frontend Session Intent. The runtime `SidebarRootComponentProps` composes the layout owner share, the global `useSessions` and `useWorkspaces` hooks, the declared `sidebar.workspaces` and `sidebar.settings` child slots, and injected `startSession` plus sidebar-toggle callbacks. There is no plugin store. +During a live collapse, the shell holds the expanded content at its current width while it fades out for 150ms. The four upper controls—the shell toggle and New Session plus add and search rendered through `sidebar.workspaces`—then share one 150ms fade and 49px leftward translation into the 56px rail, ending with the layout's 300ms column slide; every 36px control box follows the same path to the rail's 10px left inset. The bottom-pinned `sidebar.settings` control shares the fade timing but has no horizontal translation. A page that starts collapsed renders the rail statically, and reduced-motion mode disables both transitions. + Scrollbars in the column are a pointer affordance: the shell rebinds ui-theme's [scrollbar indirection](../ui-theme/README.md) to `transparent` whenever the pointer is outside it, and keeps the thumb drawn for 2s after the pointer leaves, so a list nobody is pointing at carries no bar. The reservation that keeps rows from moving belongs to the scrolling region ([ui-workspace](../ui-workspace/README.md)), so revealing a thumb never reflows. The foot is the `sidebar.settings` seat: the sidebar renders only the bottom-pinned layout slot and shares its column state (`wide`); ui-settings registers the trigger row and settings panel there. diff --git a/packages/client/ui-sidebar/README.zh.md b/packages/client/ui-sidebar/README.zh.md index 11b0aa142c..96b6f60f87 100644 --- a/packages/client/ui-sidebar/README.zh.md +++ b/packages/client/ui-sidebar/README.zh.md @@ -8,6 +8,8 @@ New Session 会启动运行时的页面局部前端 Session Intent。运行时 `SidebarRootComponentProps` 组合布局 owner share、全局 `useSessions` 和 `useWorkspaces` 钩子、已声明的 `sidebar.workspaces` 与 `sidebar.settings` 子 slot,以及注入的 `startSession` 与侧边栏切换回调。这里没有插件 store。 +实时收起时,外壳会把展开内容固定在当前宽度,并用 150ms 将其淡出。随后,上方四个控件——外壳的侧栏切换与新建会话,以及通过 `sidebar.workspaces` 渲染的添加和搜索——共用一次 150ms 的淡入和 49px 左移,在布局的 300ms 栏滑动结束时一起进入 56px 轨道;每个 36px 控件盒都会沿同一条路径到达轨道左侧 10px 的内边距。固定在底部的 `sidebar.settings` 控件只共用淡入时序,不发生横向位移。页面初始即为收起状态时会静态渲染轨道;减少动态效果模式会禁用两段过渡。 + 栏内的滚动条是一种指针可供性:只要指针不在栏内,外壳就把 ui-theme 的[滚动条间接层](../ui-theme/README.md)重新绑定为 `transparent`;指针离开后滑块再保留 2 秒,因此没人指向的列表不会带着滚动条。避免行位移的空间预留属于滚动区域本身([ui-workspace](../ui-workspace/README.md)),所以显示滑块不会引起重排。 页脚承载 `sidebar.settings`:侧边栏只渲染固定在底部的布局 slot,并共享其栏状态(`wide`);ui-settings 在此注册触发行和设置面板。 diff --git a/packages/client/ui-sidebar/package.json b/packages/client/ui-sidebar/package.json index fa43d4ac8f..cfda6d55fc 100644 --- a/packages/client/ui-sidebar/package.json +++ b/packages/client/ui-sidebar/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-client-ui-sidebar", "description": "Sidebar plugin: session multi-level tree, search, grouping, state dots", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -43,7 +43,7 @@ "bundle": "tsdown", "watch": "tsdown --watch" }, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "clsx": "^2.0.0" }, diff --git a/packages/client/ui-sidebar/src/client/SidebarRoot.module.css b/packages/client/ui-sidebar/src/client/SidebarRoot.module.css index be8f12efb6..300075b88d 100644 --- a/packages/client/ui-sidebar/src/client/SidebarRoot.module.css +++ b/packages/client/ui-sidebar/src/client/SidebarRoot.module.css @@ -58,24 +58,35 @@ from { opacity: 0; } } -/* Rail controls hold hidden while the column slides shut, then fade in over - the slide's tail: .railIn applies at settle (150ms into the 0.3s AppFrame - track transition), so a 100ms delay + 150ms fade starts just before the - slide ends (250ms) and finishes at 400ms; `backwards` keeps them at - opacity 0 through the delay. Only a live collapse gets .railIn — a - refresh straight into the collapsed state renders statically. */ +/* At the 150ms rail settle, the four upper controls enter from the former + rail right edge over the remaining 150ms of the AppFrame track transition. + The bottom-pinned settings seat shares their opacity timeline but stays + horizontally fixed. Only a live collapse gets .railIn; a cold collapsed + render stays static. */ .railIn .iconButton, .railIn .newSession, +.railIn .regionArea { + animation: rail-in 150ms var(--ds-ease-in-out) backwards; +} + .railIn .footArea { - animation: rail-in 150ms var(--ds-ease-in-out) 100ms backwards; + animation: rail-fade-in 150ms var(--ds-ease-in-out) backwards; } @keyframes rail-in { + from { + opacity: 0; + transform: translateX(49px); + } +} + +@keyframes rail-fade-in { from { opacity: 0; } } -/* Logo row (figma pad (4,8,4,8)): brand left, panel toggle right-anchored — - the toggle is the rail's expand control and slides in with the right edge. */ +/* Logo row (figma pad (4,8,4,8)): expanded keeps the panel toggle at the + right edge; the rail gives every control the same base left anchor before + the shared entry translation is applied. */ .logoRow { flex: none; display: flex; @@ -93,6 +104,7 @@ height: 36px; padding: 0; margin-bottom: 12px; + justify-content: flex-start; } /* Brand group (figma I133:7632): the full wordmark rides the text ink @@ -185,6 +197,8 @@ } .collapsed .newSession { + align-self: flex-start; + width: 36px; height: 36px; padding: 0; margin: 0 0 12px; @@ -262,7 +276,8 @@ .fading > *, .railIn .iconButton, .railIn .newSession, - .railIn .footArea { + .railIn .footArea, + .railIn .regionArea { transition: none; animation: none; } diff --git a/packages/client/ui-sidebar/src/client/SidebarRoot.tsx b/packages/client/ui-sidebar/src/client/SidebarRoot.tsx index 9f63b9d2f5..d3fe6a63c1 100644 --- a/packages/client/ui-sidebar/src/client/SidebarRoot.tsx +++ b/packages/client/ui-sidebar/src/client/SidebarRoot.tsx @@ -2,12 +2,13 @@ * Sidebar shell: column geometry only. Collapse is a slide plus crossfade: * content freezes at its expanded width (inline style) and fades out in place * while the sliding column (AppFrame grid tracks) clips it — nothing reflows - * mid-slide. At settle the wide-only content unmounts and the control rows - * snap to the 56px rail (one icon each, same top-down order) fading in as the - * slide ends. The workspace/session browsing region between the New Session - * button and the foot is the `sidebar.workspaces` registrant's, and the foot - * holds `sidebar.settings` plus `sidebar.footer.action`; the shell hands them the wide flag - * (plus an expand request callback for the browser). + * mid-slide. At settle the wide-only content unmounts and the four upper + * controls enter the 56px rail from the same horizontal offset (one icon each, + * same top-down order) on one fade that ends with the slide. The bottom-pinned + * settings control only fades. The workspace/session browsing region between + * the New Session button and the foot is the `sidebar.workspaces` registrant's, + * and the foot holds `sidebar.settings` plus `sidebar.footer.action`; the shell + * hands them the wide flag (plus an expand request callback for the browser). * * The column also owns whether the scroll regions nested in it draw a * scrollbar at all: the shell tracks the pointer and rebinds ui-theme's diff --git a/packages/client/ui-sidebar/tests/sidebar-styles.client.spec.ts b/packages/client/ui-sidebar/tests/sidebar-styles.client.spec.ts index c4abce1911..19e7a54380 100644 --- a/packages/client/ui-sidebar/tests/sidebar-styles.client.spec.ts +++ b/packages/client/ui-sidebar/tests/sidebar-styles.client.spec.ts @@ -1,4 +1,4 @@ -/** Sidebar shell inset contract shared with the nested workspace browser. */ +/** Sidebar shell style contracts shared with its slot-owned controls. */ import { readFileSync } from 'node:fs' import { fileURLToPath } from 'node:url' import { describe, expect, it } from 'vitest' @@ -25,7 +25,7 @@ function declarations(selector: string): Map | undefined { return undefined } -describe('SidebarRoot.module.css inset', () => { +describe('SidebarRoot.module.css', () => { it('shares and cancels the wide shell trailing padding structurally', () => { const root = declarations('.root') expect(root?.get('--dsh-sidebar-inline-padding')).toBe('12px') @@ -39,4 +39,28 @@ describe('SidebarRoot.module.css inset', () => { expect(declarations('.collapsed .regionArea')?.get('padding-left')).toBe('0') expect(declarations('.collapsed .regionArea')?.get('margin-right')).toBe('0') }) + + it('moves the four upper controls while the settings seat only fades', () => { + const animation = 'rail-in 150ms var(--ds-ease-in-out) backwards' + for (const selector of [ + '.railIn .iconButton', + '.railIn .newSession', + '.railIn .regionArea', + ]) { + expect(declarations(selector)?.get('animation')).toBe(animation) + } + expect(declarations('.railIn .footArea')?.get('animation')).toBe( + 'rail-fade-in 150ms var(--ds-ease-in-out) backwards', + ) + expect(css).toMatch( + /@keyframes rail-in\s*\{\s*from\s*\{\s*opacity: 0;\s*transform: translateX\(49px\);\s*}\s*}/, + ) + expect(css).toMatch(/@keyframes rail-fade-in\s*\{\s*from\s*\{\s*opacity: 0;\s*}\s*}/) + }) + + it('gives shell rail controls the same base anchor for their shared translation', () => { + expect(declarations('.collapsed .logoRow')?.get('justify-content')).toBe('flex-start') + expect(declarations('.collapsed .newSession')?.get('align-self')).toBe('flex-start') + expect(declarations('.collapsed .newSession')?.get('width')).toBe('36px') + }) }) diff --git a/packages/client/ui-skill/package.json b/packages/client/ui-skill/package.json index bfea498ad0..b2026095f2 100644 --- a/packages/client/ui-skill/package.json +++ b/packages/client/ui-skill/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-client-ui-skill", "description": "Web skill references and the dedicated skill tool row", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -45,7 +45,7 @@ "bundle": "tsdown", "watch": "tsdown --watch" }, - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-api-remotes": "workspace:^", "@deepseek-ai/dsh-client-connection": "workspace:^", diff --git a/packages/client/ui-slots/package.json b/packages/client/ui-slots/package.json index 99db753250..351daf442b 100644 --- a/packages/client/ui-slots/package.json +++ b/packages/client/ui-slots/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-client-ui-slots", "description": "Slot registry pure core: SlotMap declaration merging, single register composition API, four-share props types, store-seat types, renderer install seam", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -25,7 +25,7 @@ "./src/*": "./src/*", "./package.json": "./package.json" }, - "license": "BSD-3-Clause", + "license": "MIT", "devDependencies": { "@deepseek-ai/dsh-invariants": "workspace:^", "@types/react": "~18.3.1", diff --git a/packages/client/ui-subagent/package.json b/packages/client/ui-subagent/package.json index 20cc8ef3ba..0e0b7aadae 100644 --- a/packages/client/ui-subagent/package.json +++ b/packages/client/ui-subagent/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-client-ui-subagent", "description": "Subagent conversation catalog, continuation routing UI, and '@' reference source", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -45,7 +45,7 @@ "bundle": "tsdown", "watch": "tsdown --watch" }, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "react": "^18.2.0" }, diff --git a/packages/client/ui-theme/README.i18n.yaml b/packages/client/ui-theme/README.i18n.yaml index 6187195b04..0e5c91000d 100644 --- a/packages/client/ui-theme/README.i18n.yaml +++ b/packages/client/ui-theme/README.i18n.yaml @@ -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/client/ui-theme/README.md -README.md: 9388d5c05e5625d1a38b27c4565edf3ed47b3b6d -README.zh.md: 9995980e4a64b07c376f90e223c1ec83b5881b73 +README.md: e84a21f085eaef7546321edc90847a9a3f9bb2b8 +README.zh.md: 758b6f52d330f4518a2df5267117b61446102ea7 diff --git a/packages/client/ui-theme/README.md b/packages/client/ui-theme/README.md index 9388d5c05e..e84a21f085 100644 --- a/packages/client/ui-theme/README.md +++ b/packages/client/ui-theme/README.md @@ -8,7 +8,7 @@ When the host composition includes an HTTP server, the host half injects a synch `src/styles/` holds five sheets, all imported by the web shell's `base.css`: `base.css`, `design-platform.css`, `scrollbar.css`, `gradient-shadow-text.css`, and `shiki.css`. `scrollbar.css` is the sole consumer of the `--dsw-alias-scrollbar-*` tokens and must follow `design-platform.css`, which declares them. -Scrollbar rebinding contract: `scrollbar.css` binds `--dsh-scrollbar-thumb` and `--dsh-scrollbar-thumb-hover` on `body` to the l1 (base-surface) tokens, and both rendering paths read that pair. An elevated surface (menu, popover, dialog) sets `--dsh-scrollbar-thumb: var(--dsw-alias-scrollbar-bg-l2)` and `--dsh-scrollbar-thumb-hover: var(--dsw-alias-scrollbar-hover-l2)` on its own container; one rebind retints whichever path the engine took. The pair's other legal target is `transparent`, which draws no thumb at all — [ui-sidebar](../ui-sidebar/README.md) rebinds its column that way while the pointer is elsewhere. A rebind to the l1 pair is not a rebind; it restates the base-surface default. +Scrollbar rebinding contract: `scrollbar.css` binds `--dsh-scrollbar-thumb` and `--dsh-scrollbar-thumb-hover` on `body` to the l1 (base-surface) tokens, and both rendering paths read that pair. An elevated surface (menu, popover, dialog) sets `--dsh-scrollbar-thumb: var(--dsw-alias-scrollbar-bg-l2)` and `--dsh-scrollbar-thumb-hover: var(--dsw-alias-scrollbar-hover-l2)` on its own container; one rebind retints whichever path the engine took. The pair's other legal target is `transparent`, which draws no thumb at all — [ui-sidebar](../ui-sidebar/README.md) rebinds its column that way while the pointer is elsewhere. A rebind to the l1 pair is not a rebind; it restates the base-surface default. `--dsh-scrollbar-width` mirrors the WebKit bar's layout width for surfaces that align themselves beside a space-consuming bar — [ui-conversation](../ui-conversation/README.md) reads it for the overlay composer seat's `right` offset — and the scrollbar-styles spec pairs it with the mirrored rule and the consumer. The two paths are mutually exclusive by construction. `scrollbar-width`/`scrollbar-color` sit inside `@supports not selector(::-webkit-scrollbar)` because a non-`auto` value of either makes Chromium and Safari discard every `::-webkit-scrollbar*` rule for that element, `::-webkit-scrollbar-thumb:hover` included — declaring both unconditionally leaves `--dsh-scrollbar-thumb-hover` with no rendering anywhere. Firefox therefore takes the standard properties and WebKit-based engines take the pseudo-elements, so the hover token only ever renders through the pseudo-element path. Reasoning and the measured computed values: [the scrollbar Agent Note](../../../.agents/notes/implemented/bug-fix/2026-07-28-themed-scrollbars-and-reserved-gutter.md). diff --git a/packages/client/ui-theme/README.zh.md b/packages/client/ui-theme/README.zh.md index 9995980e4a..758b6f52d3 100644 --- a/packages/client/ui-theme/README.zh.md +++ b/packages/client/ui-theme/README.zh.md @@ -8,7 +8,7 @@ `src/styles/` 下有五张样式表,全部由 web 壳的 `base.css` 导入:`base.css`、`design-platform.css`、`scrollbar.css`、`gradient-shadow-text.css` 与 `shiki.css`。`scrollbar.css` 是 `--dsw-alias-scrollbar-*` token 的唯一消费方,必须排在声明这些 token 的 `design-platform.css` 之后。 -滚动条重新绑定约定:`scrollbar.css` 在 `body` 上把 `--dsh-scrollbar-thumb` 与 `--dsh-scrollbar-thumb-hover` 绑定到 l1(基础表面)token,两条渲染路径都读取这一组变量。高层级表面(菜单、浮层、对话框)在自己的容器上设置 `--dsh-scrollbar-thumb: var(--dsw-alias-scrollbar-bg-l2)` 与 `--dsh-scrollbar-thumb-hover: var(--dsw-alias-scrollbar-hover-l2)`;一次重新绑定即可为引擎实际走的那条路径换色。这组变量的另一个合法目标是 `transparent`,即完全不绘制滑块——[ui-sidebar](../ui-sidebar/README.md) 在指针不在栏内时就这样重新绑定自己的列。绑回 l1 那组不算重新绑定,它只是重述基础表面的默认值。 +滚动条重新绑定约定:`scrollbar.css` 在 `body` 上把 `--dsh-scrollbar-thumb` 与 `--dsh-scrollbar-thumb-hover` 绑定到 l1(基础表面)token,两条渲染路径都读取这一组变量。高层级表面(菜单、浮层、对话框)在自己的容器上设置 `--dsh-scrollbar-thumb: var(--dsw-alias-scrollbar-bg-l2)` 与 `--dsh-scrollbar-thumb-hover: var(--dsw-alias-scrollbar-hover-l2)`;一次重新绑定即可为引擎实际走的那条路径换色。这组变量的另一个合法目标是 `transparent`,即完全不绘制滑块——[ui-sidebar](../ui-sidebar/README.md) 在指针不在栏内时就这样重新绑定自己的列。绑回 l1 那组不算重新绑定,它只是重述基础表面的默认值。`--dsh-scrollbar-width` 镜像 WebKit 滚动条的布局宽度,供需要与占布局宽度的滚动条对齐的表面使用——[ui-conversation](../ui-conversation/README.md) 用它作为覆盖 composer 座位 `right` 偏移——scrollbar-styles 规格把它与镜像规则及消费者配对检查。 两条路径在构造上互斥。`scrollbar-width`/`scrollbar-color` 写在 `@supports not selector(::-webkit-scrollbar)` 之内,因为这两个属性中的任一个只要取非 `auto` 值,Chromium 与 Safari 就会丢弃该元素上的全部 `::-webkit-scrollbar*` 规则,`::-webkit-scrollbar-thumb:hover` 也在其中——若无条件地同时声明,`--dsh-scrollbar-thumb-hover` 在任何引擎上都不会被渲染。因此 Firefox 走标准属性,WebKit 系引擎走伪元素,hover token 只经由伪元素这条路径渲染。相关原理与实测计算值见[滚动条 Agent Note](../../../.agents/notes/implemented/bug-fix/2026-07-28-themed-scrollbars-and-reserved-gutter.md)。 diff --git a/packages/client/ui-theme/package.json b/packages/client/ui-theme/package.json index 85bc5eada4..6f320cd92f 100644 --- a/packages/client/ui-theme/package.json +++ b/packages/client/ui-theme/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-client-ui-theme", "description": "Theme plugin: Host bootstrap for the pre-plugin palette; DOM-free ThemeRuntime for light/dark/system state; --dsw-* token styles and Appearance settings row", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -43,7 +43,7 @@ "immediately": true } }, - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "workspace:^", "@deepseek-ai/dsh-api-remotes": "workspace:^", diff --git a/packages/client/ui-theme/src/styles/scrollbar.css b/packages/client/ui-theme/src/styles/scrollbar.css index 31b5a8aabe..71f67d4f57 100644 --- a/packages/client/ui-theme/src/styles/scrollbar.css +++ b/packages/client/ui-theme/src/styles/scrollbar.css @@ -17,6 +17,11 @@ body { --dsh-scrollbar-thumb: var(--dsw-alias-scrollbar-bg-l1); --dsh-scrollbar-thumb-hover: var(--dsw-alias-scrollbar-hover-l1); + /* The WebKit bar's layout width, mirrored by the ::-webkit-scrollbar rule + below. A surface that must align itself beside a space-consuming bar + (ConversationRoot's overlay composer seat) reads this instead of + hardcoding the number. */ + --dsh-scrollbar-width: 8px; } /* The two paths are mutually exclusive, and the gate is load-bearing rather diff --git a/packages/client/ui-theme/tests/scrollbar-styles.client.spec.ts b/packages/client/ui-theme/tests/scrollbar-styles.client.spec.ts index b6ed3f0c90..e9234846eb 100644 --- a/packages/client/ui-theme/tests/scrollbar-styles.client.spec.ts +++ b/packages/client/ui-theme/tests/scrollbar-styles.client.spec.ts @@ -2,10 +2,11 @@ * Scrollbar stylesheet contract, asserted against the CSS text on disk: every * --dsw-alias-scrollbar-* token design-platform.css defines has a consumer, * scrollbar.css binds the base-surface pair through the rebindable - * indirection, and elevated surfaces rebind that indirection in complete - * pairs. The expected token set is scanned out of design-platform.css, so - * adding, renaming, or dropping a scrollbar token moves these assertions with - * it. + * indirection, the width variable mirrors the ::-webkit-scrollbar rule for + * consumers that align beside the bar, and elevated surfaces rebind that + * indirection in complete pairs. The expected token set is scanned out of + * design-platform.css, so adding, renaming, or dropping a scrollbar token + * moves these assertions with it. */ import { readdirSync, readFileSync } from 'node:fs' import { join } from 'node:path' @@ -341,6 +342,67 @@ describe('scrollbar.css base-surface binding', () => { }) }) +describe('scrollbar.css width variable', () => { + const WIDTH_VARIABLE = `${INDIRECTION_PREFIX}width` + + it('defines the width variable on body as a static length', () => { + // The overlay seat compensation reads a fixed number, not a second + // indirection: the mirror check below compares the WebKit rule against + // this value, so a var()-to-var() chain would compare one indirection to + // another instead of pinning the number. + const value = scrollbarRules + .filter(rule => rule.selectors.includes('body')) + .flatMap(rule => rule.declarations) + .findLast(([property]) => property === WIDTH_VARIABLE)?.[1] + expect(value, WIDTH_VARIABLE).toBeDefined() + expect(value, WIDTH_VARIABLE).toMatch(/^\d+(?:\.\d+)?px$/) + }) + + it('mirrors the ::-webkit-scrollbar width rule with the variable value', () => { + // The compensation stays aligned with the WebKit bar only while both read + // the same number. A change to one side without the other puts the overlay + // seat a band off from Chat on WebKit engines. + const variableValue = scrollbarRules + .filter(rule => rule.selectors.includes('body')) + .flatMap(rule => rule.declarations) + .findLast(([property]) => property === WIDTH_VARIABLE)?.[1] + const webkitWidth = scrollbarRules + .filter(rule => rule.selectors.includes('::-webkit-scrollbar')) + .flatMap(rule => rule.declarations) + .findLast(([property]) => property === 'width')?.[1] + expect(webkitWidth, '::-webkit-scrollbar width').toBeDefined() + expect(webkitWidth).toBe(variableValue) + }) + + it('every reader of the width variable outside ui-theme references a defined variable', () => { + // The consumer is ConversationRoot's overlay composer seat + // (`right: var(--dsh-scrollbar-width)`); a rename in scrollbar.css without + // the consumer, or a typo in the consumer, leaves the value + // guaranteed-invalid and the seat loses the band. The equal-rectangle e2e + // would catch it only on an engine that draws the bar, so the sheet + // contract states it here. + const defined = new Set( + scrollbarRules + .flatMap(rule => rule.declarations) + .filter(([property]) => property.startsWith(INDIRECTION_PREFIX)) + .map(([property]) => property), + ) + expect(defined).toContain(WIDTH_VARIABLE) + const readers: string[] = [] + for (const file of packageStylesheets()) { + if (file === fileURLToPath(new URL('scrollbar.css', STYLES))) continue + for (const rule of parseRules(readFileSync(file, 'utf8'))) { + for (const [property, value] of rule.declarations) { + for (const name of varReferences(value)) { + if (name === WIDTH_VARIABLE) readers.push(`${file} ${rule.selectors.join(', ')}: ${property}`) + } + } + } + } + expect(readers.length, 'compensation consumer').toBeGreaterThan(0) + }) +}) + describe('scrollbar.css selectors', () => { const scrollbarColorSelectors = scrollbarRules .filter(rule => rule.declarations.some(([property]) => property === 'scrollbar-color')) diff --git a/packages/client/ui-tool/package.json b/packages/client/ui-tool/package.json index 42acc17b65..80bc4f2586 100644 --- a/packages/client/ui-tool/package.json +++ b/packages/client/ui-tool/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-client-ui-tool", "description": "Client Tool call-tree renderer and keyed per-tool presentation slot", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -43,7 +43,7 @@ "bundle": "tsdown", "watch": "tsdown --watch" }, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "clsx": "^2.0.0" }, diff --git a/packages/client/ui-trajectory/README.i18n.yaml b/packages/client/ui-trajectory/README.i18n.yaml index b3b7d8ac47..c3a40c880f 100644 --- a/packages/client/ui-trajectory/README.i18n.yaml +++ b/packages/client/ui-trajectory/README.i18n.yaml @@ -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/client/ui-trajectory/README.md -README.md: d3786b6460c5df7eaa6d24e68c80025e7fb29ae4 -README.zh.md: b3bc88d8ab73ccc0da9a49d1867fe2c66be5ca43 +README.md: 9ad42a3d3bcfb8fbf4842a66577e65794a716dfd +README.zh.md: df7661ef7d4861dbc6c8e365a18b3e3252d4d4af diff --git a/packages/client/ui-trajectory/README.md b/packages/client/ui-trajectory/README.md index d3786b6460..9ad42a3d3b 100644 --- a/packages/client/ui-trajectory/README.md +++ b/packages/client/ui-trajectory/README.md @@ -2,7 +2,7 @@ English | [中文](README.zh.md) -Trajectory renders a turn-aware event ledger with selectable User, Assistant, Tool, and nested Subtool records. Thick rules mark Turn boundaries, compact inline markers identify Steps, and the main ledger keeps only index, event, and content; selection opens a local inspector for token usage, duration, Input, Output, and Timing. Scrollable Summary regions keep their scrollbar thumbs transparent until the region is hovered or contains keyboard focus, without changing the reserved scroll geometry. A standalone compaction request appears chronologically in its own `Between turns` section, while a numbered compaction remains inside its owning turn. Long ledgers open at the current tail, load one older page when the user reaches the loaded range's top, and mount only the visible row window plus a small overscan; request-only separators share the next measurable virtual item, while semantic row keys and ARIA indexes survive prepends. Selection, timeline navigation, folding, search, and Request totals cover the currently loaded window. The ledger covers records with an explicit loading row until the initial tail is positioned and while an older page is pending. A fixed Overview above the ledger projects real record start/duration timing from left to right; when earlier records remain unloaded and the viewport includes the loaded domain's start, a neutral ellipsis control identifies the omitted prefix and loads one earlier page without assigning unknown history fabricated duration. Assistant spans divide recorded TTFT from decoding, and a 500 ms hover reveals exact clock and duration details. Dragging an interval focuses the ledger on every record active at any point in that inclusive range, while clearing the selection restores the full loaded ledger. Wheel gestures zoom the time domain. A right-button click clears the selected interval, while a right-button drag pans an already zoomed viewport without changing it. The initial view and streaming updates stay at the tail; scrolling upward suspends following so new records do not interrupt inspection of earlier rows. Content-only stream frames preserve virtual row keys and heights, reuse measurements, and do not issue repeated tail-scroll writes. Completed replies retain assembled blocks, timing, and usage in Trajectory target State, while the shared Session window keeps the raw Events. Trajectory asks the conversation shell to float the composer over the full-height ledger, while its responsive vertical scrollers reserve the composer's live height so final rows remain reachable. Trajectory-owned Definitions assemble business records, including cancellation-frozen Assistant and Tool records, from the shared Session window, so Trajectory neither reads nor changes the Chat conversation snapshot. The package provides no service and declares no Context merge; it registers target-specific Event Definitions, a Trajectory view builder, and one tab in the conversation's `'conversation.view'` slot ring. Contract: api-contracts v3 §8. +Trajectory renders a turn-aware event ledger with selectable User, Assistant, Tool, and nested Subtool records. Thick rules mark Turn boundaries, compact inline markers identify Steps, and the main ledger keeps only index, event, and content; selection opens a local inspector for token usage, duration, Input, Output, and Timing. Scrollable Summary regions keep their scrollbar thumbs transparent until the region is hovered or contains keyboard focus, without changing the reserved scroll geometry. A standalone compaction request appears chronologically in its own `Between turns` section, while a numbered compaction remains inside its owning turn. Long ledgers open at the current tail, load one older page when the user reaches the loaded range's top, and mount only the visible row window plus a small overscan; request-only separators share the next measurable virtual item, while semantic row keys and ARIA indexes survive prepends. Selection, timeline navigation, folding, search, and Request totals cover the currently loaded window. The ledger covers records with an explicit loading row until the initial tail is positioned. While an older prefix remains unloaded, a first-row control precedes the loaded records, loads one earlier page on click, and changes in place to a disabled loading status while that page is pending. A fixed Overview above the ledger projects real record start/duration timing from left to right; when earlier records remain unloaded and the viewport includes the loaded domain's start, a neutral ellipsis control identifies the omitted prefix and loads one earlier page without assigning unknown history fabricated duration. Assistant spans divide recorded TTFT from decoding, and a 500 ms hover reveals exact clock and duration details. Dragging an interval focuses the ledger on every record active at any point in that inclusive range, while clearing the selection restores the full loaded ledger. Wheel gestures zoom the time domain. A right-button click clears the selected interval, while a right-button drag pans an already zoomed viewport without changing it. The initial view and streaming updates stay at the tail; scrolling upward suspends following so new records do not interrupt inspection of earlier rows. Content-only stream frames preserve virtual row keys and heights, reuse measurements, and do not issue repeated tail-scroll writes. Completed replies retain assembled blocks, timing, and usage in Trajectory target State, while the shared Session window keeps the raw Events. Trajectory asks the conversation shell to float the composer over the full-height ledger, while its responsive vertical scrollers reserve the composer's live height so final rows remain reachable. Trajectory-owned Definitions assemble business records, including cancellation-frozen Assistant and Tool records, from the shared Session window, so Trajectory neither reads nor changes the Chat conversation snapshot. The package provides no service and declares no Context merge; it registers target-specific Event Definitions, a Trajectory view builder, and one tab in the conversation's `'conversation.view'` slot ring. Contract: api-contracts v3 §8. ## Model Experience diff --git a/packages/client/ui-trajectory/README.zh.md b/packages/client/ui-trajectory/README.zh.md index b3bc88d8ab..df7661ef7d 100644 --- a/packages/client/ui-trajectory/README.zh.md +++ b/packages/client/ui-trajectory/README.zh.md @@ -2,7 +2,7 @@ [English](README.md) | 中文 -Trajectory 渲染按轮次组织的事件记录表,其中可选择用户、助手、工具和嵌套子工具记录。较粗的分割线标示轮次边界,紧凑的行内标记标识步骤,主记录表仅保留索引、事件和内容;选择记录则会打开局部检查器,查看 token 用量、耗时、输入、输出和计时。可滚动的概述区域默认保持滚动条滑块透明,直到鼠标悬停该区域或其中包含键盘焦点时才显示,同时不改变滚动条预留的几何空间。独立运行的压缩(compaction)请求会按时间顺序显示在自己的 `Between turns` 区段中,而带编号的压缩仍位于其所属轮次内。长记录表打开时定位于当前尾部,用户到达已加载范围顶部时加载一页更早的历史,并且只挂载可见行窗口和少量额外缓冲行;仅含请求的分隔行并入下一个具备可测高度的虚拟项,语义行键和 ARIA 索引在向前补页后保持不变。选择、时间线导航、折叠、搜索和请求汇总只覆盖当前已加载的窗口。初始尾部完成定位前以及更早页面的加载尚未完成时,记录表会用明确的加载行遮住真实记录。固定在记录表上方的 Overview 区域从左到右投影记录的真实开始时间与耗时;仍有更早记录未加载且 viewport 包含已加载时间域起点时,中性的省略号控件会标识被省略的前缀,并可加载一页更早历史,而不会为未知部分虚构耗时。助手时间条会区分记录到的 TTFT 与解码时间,悬停 500 ms 后可查看精确时刻和耗时详情。拖选一个区间会将记录表聚焦到活动区间与该闭区间有重叠的所有记录,清除选择则恢复完整的已加载记录表。滚轮手势用于缩放时间域。右键单击会清除所选区间;在已放大的 viewport 上按住右键拖动则只会平移视图,不会改变该区间。初始视图和流式更新都会停留在尾部;向上滚动会暂停跟随,因此新记录不会打断对旧记录的检查。仅含内容更新的流式帧会保持虚拟行的键和高度不变、复用测量结果,并且不会重复写入末尾滚动位置。已完成的回复会在 Trajectory target State 中保留组装后的 blocks、计时与用量,共享 Session 窗口则保留原始 Event。Trajectory 要求会话壳将 composer 作为浮层置于全高记录表上方;其响应式纵向滚动容器会预留 composer 的实时高度,确保仍可滚动到最后几行。Trajectory 自有的 Definition 从共享 Session 窗口组装业务记录,其中包括因取消而冻结的助手和工具记录,因此 Trajectory 既不读取也不改变 Chat 会话快照。该包不提供 service,也不声明 Context 合并;它会注册 target 专属 Event Definition、Trajectory view builder,以及会话 `'conversation.view'` slot 环中的一个视图标签页。约定:api-contracts v3 §8。 +Trajectory 渲染按轮次组织的事件记录表,其中可选择用户、助手、工具和嵌套子工具记录。较粗的分割线标示轮次边界,紧凑的行内标记标识步骤,主记录表仅保留索引、事件和内容;选择记录则会打开局部检查器,查看 token 用量、耗时、输入、输出和计时。可滚动的概述区域默认保持滚动条滑块透明,直到鼠标悬停该区域或其中包含键盘焦点时才显示,同时不改变滚动条预留的几何空间。独立运行的压缩(compaction)请求会按时间顺序显示在自己的 `Between turns` 区段中,而带编号的压缩仍位于其所属轮次内。长记录表打开时定位于当前尾部,用户到达已加载范围顶部时加载一页更早的历史,并且只挂载可见行窗口和少量额外缓冲行;仅含请求的分隔行并入下一个具备可测高度的虚拟项,语义行键和 ARIA 索引在向前补页后保持不变。选择、时间线导航、折叠、搜索和请求汇总只覆盖当前已加载的窗口。初始尾部完成定位前,记录表会用明确的加载行遮住真实记录。更早的前缀仍未加载时,已加载记录前会始终保留首行控件;单击它会加载一页更早的历史,页面加载期间则会原地变为禁用的加载状态。固定在记录表上方的 Overview 区域从左到右投影记录的真实开始时间与耗时;仍有更早记录未加载且 viewport 包含已加载时间域起点时,中性的省略号控件会标识被省略的前缀,并可加载一页更早历史,而不会为未知部分虚构耗时。助手时间条会区分记录到的 TTFT 与解码时间,悬停 500 ms 后可查看精确时刻和耗时详情。拖选一个区间会将记录表聚焦到活动区间与该闭区间有重叠的所有记录,清除选择则恢复完整的已加载记录表。滚轮手势用于缩放时间域。右键单击会清除所选区间;在已放大的 viewport 上按住右键拖动则只会平移视图,不会改变该区间。初始视图和流式更新都会停留在尾部;向上滚动会暂停跟随,因此新记录不会打断对旧记录的检查。仅含内容更新的流式帧会保持虚拟行的键和高度不变、复用测量结果,并且不会重复写入末尾滚动位置。已完成的回复会在 Trajectory target State 中保留组装后的 blocks、计时与用量,共享 Session 窗口则保留原始 Event。Trajectory 要求会话壳将 composer 作为浮层置于全高记录表上方;其响应式纵向滚动容器会预留 composer 的实时高度,确保仍可滚动到最后几行。Trajectory 自有的 Definition 从共享 Session 窗口组装业务记录,其中包括因取消而冻结的助手和工具记录,因此 Trajectory 既不读取也不改变 Chat 会话快照。该包不提供 service,也不声明 Context 合并;它会注册 target 专属 Event Definition、Trajectory view builder,以及会话 `'conversation.view'` slot 环中的一个视图标签页。约定:api-contracts v3 §8。 ## 模型体验 diff --git a/packages/client/ui-trajectory/package.json b/packages/client/ui-trajectory/package.json index 0c3da436e6..375053ba7c 100644 --- a/packages/client/ui-trajectory/package.json +++ b/packages/client/ui-trajectory/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-client-ui-trajectory", "description": "Trajectory event ledger with an interactive timing overview: pure-consumer plugin registering into the conversation ViewMap (no service)", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -43,7 +43,7 @@ "bundle": "tsdown", "watch": "tsdown --watch" }, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "@tanstack/react-virtual": "^3.14.9", "diff": "^9.0.0" diff --git a/packages/client/ui-trajectory/src/client/TrajectoryTable.module.css b/packages/client/ui-trajectory/src/client/TrajectoryTable.module.css index b1d9be9930..71d0b3031b 100644 --- a/packages/client/ui-trajectory/src/client/TrajectoryTable.module.css +++ b/packages/client/ui-trajectory/src/client/TrajectoryTable.module.css @@ -55,6 +55,53 @@ animation: history-loading-spin 700ms linear infinite; } +.table tbody .historyLoadRow td { + height: 30px; + padding: 0; +} + +/* The pagination control does not create a trajectory turn boundary. */ +.table tbody .historyLoadRow + tr[data-turn-start='true'] td::before { + content: none; +} + +.historyLoadButton { + display: flex; + width: 100%; + height: 29px; + align-items: center; + justify-content: center; + gap: 6px; + border: 0; + background: var(--dsw-alias-bg-layer-1); + color: var(--dsw-alias-label-secondary); + cursor: pointer; + font: var(--dsw-font-xxs-12); +} + +.historyLoadButton:hover:not(:disabled) { + background: var(--dsw-alias-interactive-bg-hover); + color: var(--dsw-alias-label-primary); +} + +.historyLoadButton:focus-visible { + outline: 2px solid var(--dsw-alias-state-business-primary); + outline-offset: -2px; +} + +.historyLoadButton:disabled { + cursor: default; +} + +.visuallyHidden { + position: absolute; + width: 1px; + height: 1px; + overflow: hidden; + clip: rect(0 0 0 0); + white-space: nowrap; +} + .table:not([data-scroll-ready='true']) { visibility: hidden; } @@ -137,7 +184,7 @@ border: 0; } -.table tbody tr:not([data-collapsed-summary]):not([data-virtual-spacer]) { +.table tbody tr:not([data-collapsed-summary]):not([data-virtual-spacer]):not([data-history-load]) { cursor: default; outline: none; transition: @@ -149,7 +196,7 @@ opacity: 0.24; } -.table tbody tr:not([data-collapsed-summary]):not([data-virtual-spacer]):not([data-selected='true']):hover { +.table tbody tr:not([data-collapsed-summary]):not([data-virtual-spacer]):not([data-history-load]):not([data-selected='true']):hover { background: var(--dsw-alias-interactive-bg-hover); } diff --git a/packages/client/ui-trajectory/src/client/TrajectoryTable.tsx b/packages/client/ui-trajectory/src/client/TrajectoryTable.tsx index 5d2d4d8e31..dab72e6778 100644 --- a/packages/client/ui-trajectory/src/client/TrajectoryTable.tsx +++ b/packages/client/ui-trajectory/src/client/TrajectoryTable.tsx @@ -30,6 +30,7 @@ import css from './TrajectoryTable.module.css' const BOTTOM_FOLLOW_THRESHOLD_PX = 2 const OLDER_LOAD_THRESHOLD_PX = 48 +const HISTORY_LOAD_ROW_HEIGHT_PX = 30 const VIRTUALIZATION_THRESHOLD = 100 const VIRTUAL_OVERSCAN_ROWS = 12 const VIRTUAL_INITIAL_VIEWPORT_HEIGHT_PX = 600 @@ -364,6 +365,8 @@ export interface TrajectoryTableProps { recordFocus?: { readonly index: number } | null /** Whether the initial history tail is still loading. */ historyLoading?: boolean + /** Whether one older history page request is pending anywhere. */ + olderHistoryLoading?: boolean /** First loaded raw event, used to preserve scroll position after prepending a page. */ historyStartSeq?: number | undefined /** Whether one older history page can be requested. */ @@ -1698,6 +1701,7 @@ export function TrajectoryTable({ recordSelection = null, recordFocus = null, historyLoading = false, + olderHistoryLoading = false, historyStartSeq, hasOlderRecords = false, onLoadOlder, @@ -1769,6 +1773,7 @@ export function TrajectoryTable({ const virtualRowStructure = useStableVirtualRowStructure(projectedVirtualRows) const virtualizationEnabled = hasOlderRecords || records.length > VIRTUALIZATION_THRESHOLD + const virtualScrollMargin = hasOlderRecords ? HISTORY_LOAD_ROW_HEIGHT_PX : 0 const estimateVirtualRowSize = useCallback( (index: number) => virtualRowStructure[index]?.height ?? 30, [virtualRowStructure], @@ -1787,6 +1792,7 @@ export function TrajectoryTable({ initialRect: { width: 0, height: VIRTUAL_INITIAL_VIEWPORT_HEIGHT_PX }, anchorTo: 'end', overscan: VIRTUAL_OVERSCAN_ROWS, + scrollMargin: virtualScrollMargin, scrollEndThreshold: BOTTOM_FOLLOW_THRESHOLD_PX, }) const virtualIndexByRecordId = useMemo(() => { @@ -1801,10 +1807,15 @@ export function TrajectoryTable({ return indexes }, [projectedVirtualRows]) const virtualItems = virtualizationEnabled ? rowVirtualizer.getVirtualItems() : [] - const virtualTop = virtualItems[0]?.start ?? 0 + const virtualTop = Math.max(0, (virtualItems[0]?.start ?? 0) - virtualScrollMargin) const virtualBottom = virtualItems.length === 0 ? 0 - : Math.max(0, rowVirtualizer.getTotalSize() - (virtualItems.at(-1)?.end ?? 0)) + : Math.max( + 0, + rowVirtualizer.getTotalSize() + + virtualScrollMargin + - (virtualItems.at(-1)?.end ?? 0), + ) const renderedRecords = virtualizationEnabled ? virtualItems.flatMap((item) => { const row = projectedVirtualRows[item.index] @@ -2123,12 +2134,13 @@ export function TrajectoryTable({ virtualIndexByRecordId, virtualizationEnabled, ]) - const requestOlder = useCallback((pane: HTMLDivElement) => { + const requestOlder = useCallback((pane: HTMLDivElement, requireTop: boolean) => { if ( !hasOlderRecords || onLoadOlder === undefined || loadingOlder.current - || pane.scrollTop > OLDER_LOAD_THRESHOLD_PX + || olderHistoryLoading + || (requireTop && pane.scrollTop > OLDER_LOAD_THRESHOLD_PX) ) return loadingOlder.current = true setOlderLoading(true) @@ -2143,7 +2155,7 @@ export function TrajectoryTable({ loadingOlder.current = false setOlderLoading(false) }) - }, [hasOlderRecords, historyStartSeq, onLoadOlder]) + }, [hasOlderRecords, historyStartSeq, olderHistoryLoading, onLoadOlder]) useLayoutEffect(() => { const pane = tablePaneRef.current if (pane === null) return @@ -2176,10 +2188,9 @@ export function TrajectoryTable({ virtualizationEnabled, ]) - const loadingLabel = olderLoading - ? 'Loading earlier history…' - : 'Loading trajectory…' - const showLoading = historyLoading || olderLoading || !tableScrollReady + const olderBusy = olderHistoryLoading || olderLoading + const showInitialLoading = historyLoading || !tableScrollReady + const historyRowOffset = hasOlderRecords ? 1 : 0 return (
    @@ -2192,30 +2203,62 @@ export function TrajectoryTable({ followsTableTail.current = pane.scrollHeight - pane.clientHeight - pane.scrollTop <= BOTTOM_FOLLOW_THRESHOLD_PX - requestOlder(pane) + requestOlder(pane, true) }} onClick={(event) => { if (event.target === event.currentTarget) clearAllSelections() }} > - {showLoading && ( + {showInitialLoading && (
    )} + {hasOlderRecords && ( + + + + )} {virtualTop > 0 && (
    + +

    > -endobj - -5001 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [288.27457 623.87244 299.27457 637.5344] - /Border [0 0 0] - /Dest 4567 0 R - /F 4 - /StructParent 283 - /Contents (78) ->> -endobj - -5002 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [307.49673 623.87244 318.49673 637.5344] - /Border [0 0 0] - /Dest 4568 0 R - /F 4 - /StructParent 284 - /Contents (79) ->> -endobj - -5003 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [116.09558 582.8864 127.09558 596.5484] - /Border [0 0 0] - /Dest 4569 0 R - /F 4 - /StructParent 285 - /Contents (80) ->> -endobj - -5004 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [467.82358 500.9144 518.84344 514.5764] - /Border [0 0 0] - /Dest (subsec:reactive-coeffects) - /F 4 - /StructParent 286 - /Contents (Section 3.2) ->> -endobj - -5005 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [277.32913 384.8184 288.32913 398.4804] - /Border [0 0 0] - /Dest 4570 0 R - /F 4 - /StructParent 287 - /Contents (81) ->> -endobj - -5006 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [294.39148 384.8184 305.39148 398.4804] - /Border [0 0 0] - /Dest 4571 0 R - /F 4 - /StructParent 288 - /Contents (82) ->> -endobj - -5007 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [224.39613 193.55042 235.39613 207.2124] - /Border [0 0 0] - /Dest 4572 0 R - /F 4 - /StructParent 289 - /Contents (83) ->> -endobj - -5008 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [240.76514 193.55042 251.76514 207.2124] - /Border [0 0 0] - /Dest 4573 0 R - /F 4 - /StructParent 290 - /Contents (84) ->> -endobj - -5009 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4360 0 R - /f1 4354 0 R - /f2 4366 0 R - /f3 4384 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 291 - /Tabs /S - /Parent 1 0 R - /Contents 5010 0 R - /Annots [5000 0 R 5001 0 R 5002 0 R 5003 0 R 5004 0 R 5005 0 R 5006 0 R 5007 0 R 5008 0 R] ->> -endobj - -5010 0 obj -<< - /Length 5477 - /Filter /FlateDecode ->> -stream -x=ْ$7nٞͤCctay֌vV\[< _  ."_>>>i_|w_4_y͡??߽|qg|ͧ7@ӯ?kdݨF6SM^&(imlz#>o>yljގw~凜K-wMtFwҸo5BJ{/A*kQ:$Um:DtrizdQEtRܕK'`jұցVd5~f~5t#Yj]s7Sypg2kа=mm{ -$y_ȄZ?4y͟hX`pP]:j@T/480}< -Q!A76ަ 5`3Ӈ!W(JTN/'s߽((u*{d.45!z3F&3)sR2L4#+*fטA.OChR ԦD*na·f5qP}qQUhK?En٥9biH!M6YG*PnNS3O0S!?7+<)Iz-<4e5d?iϐn)F$F"%ړ)4䃬hՑY U:^ +D(xZj0Dwk2QlyQ͖:NI+bFSk(66:&q>:9[So*3#4L@{@yBX6=DVm5gmDwpZΡjnzgrRb=iY:c^*`j*W J)vK!2={,ƻoE?켋&8=j>|,a,hcXDt{Gr4I/=N ނ{a}Wqh[$m1PXՓuPaXk>ٮynv*V`]XOӾ" (_Ǹ#1<~#=Lծ%^҆IKՑ%9!tWQIb1.6 YC;ʼKuN8/m^ЅMN@U~DJeV 'cE&kE5AڸUKHL#äLX~Ufi -.¯d @dܰ7`o (Mw}XWeЀZפM_3SO n&SU*r(\0kJ:?qiDutB}7}rl5ykQriCN6jt)3-')@E-U3$`iHDWtaMC+ŋ㯏o/> )_q?'+O9tkJɗ\J$90mpйlؐX rSVm GR6uojDϹx)*cĴIդ3ozTćѬ*/'h -_?nvwݡ*d^BEyrq4ɜFYQ^4X׬SWU'JҷF"%F)D9EɥjӥK׋*5J9Պ֚$[$*ƢmBwkUƷbNftjД=?ϑb4Ȁp!P.& .j(_#8f鶸 58/CՆ UWBի(aR׳|df2p - "is?c2 >AOk.>& --*#dҰ)[a`A] gDխLNɦ5iAy֩oZ}jU7k+eZDPC꺲dkTQ-VJ -r:atTf=NWp?fz[m Kv%VlAj:S!#zD%;m4J -@ב[d@%(0;YTWq9]:5XkD{L߷E6AD!s WN(c, 9]D+#yPg2ɞ+N'smTw :9>wkvx«BZD=~tCZH;i5 zȎ/67xGȾF.kq6][+6` B<)}D$`Ђ"-A g55^\JҔzyFmI8zYώzL:цUS_ӮqF! jv$T11A_O}]bC5ŀeGa:&G,\A -;r<CEuR -:d!-fuֹi'.7nxX6ް^Q -׽1I_jP1*_xgAF.jnb zh"@ЖT[%w K@Xa*f!ȡL%ǜ `\JWHuh*`wJ_SAUI vMPӈTNij)JgC^L}LYCۜ%g)uWsTڊ +ephgW9\1IUhİ(FфH W<=),PM$UcQ7Ұޤ>8+f7ʐs֕v@D_~9 +W')EWad!@|H^ 3/A*PVW􄞓(ҐJZ:Դ[/^vQ$ՠڈ6FVWfD N'VAkZ(fcd>eڎ4gBʖ~gT]Tpڂe>JϑvuLϩZIMJxuRd;8:F'GC9'qF\6?]-$flJ12:"i3[G`HKf U…!WtȞL(*Bw=1,lAwHbDlq·2]?!t./XRa~mfh7PhX)w"E4ȗ8UZ8]'!nL &jCgXņ8>eSVWy+zkZE*VMjƀZTLhi}ˊmɩ,|['-ZT[VW$P=U*TS7J3FӔZ(3 -TT6;h˗EveGi_).a&7JLyJ&IT`Kz l\@ +:?Op|{_|w?t~ix}pǟ.lZ()s*c?ߔ -endstream -endobj - -5011 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [406.6614 657.4414 417.6614 671.1034] - /Border [0 0 0] - /Dest 4532 0 R - /F 4 - /StructParent 292 - /Contents (45) ->> -endobj - -5012 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [313.45062 643.7794 324.45062 657.4414] - /Border [0 0 0] - /Dest 4533 0 R - /F 4 - /StructParent 293 - /Contents (46) ->> -endobj - -5013 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [468.4083 643.7794 519.39343 657.4414] - /Border [0 0 0] - /Dest (subsec:scaling) - /F 4 - /StructParent 294 - /Contents (Section 5.1) ->> -endobj - -5014 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [243.872 602.7934 254.872 616.4554] - /Border [0 0 0] - /Dest 4574 0 R - /F 4 - /StructParent 295 - /Contents (85) ->> -endobj - -5015 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [117.43649 589.1314 128.4365 602.7934] - /Border [0 0 0] - /Dest 4575 0 R - /F 4 - /StructParent 296 - /Contents (86) ->> -endobj - -5016 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [281.27063 589.1314 292.27063 602.7934] - /Border [0 0 0] - /Dest 4576 0 R - /F 4 - /StructParent 297 - /Contents (87) ->> -endobj - -5017 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [508.70145 561.8074 519.7015 575.46936] - /Border [0 0 0] - /Dest 4577 0 R - /F 4 - /StructParent 298 - /Contents (88) ->> -endobj - -5018 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [369.36508 534.4834 380.36508 548.1454] - /Border [0 0 0] - /Dest 4470 0 R - /F 4 - /StructParent 299 - /Contents (14) ->> -endobj - -5019 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [152.61218 493.4974 163.61218 507.1594] - /Border [0 0 0] - /Dest 4523 0 R - /F 4 - /StructParent 300 - /Contents (42) ->> -endobj - -5020 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [204.64723 493.4974 215.64723 507.1594] - /Border [0 0 0] - /Dest 4524 0 R - /F 4 - /StructParent 301 - /Contents (43) ->> -endobj - -5021 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [178.02861 466.1734 229.13483 479.8354] - /Border [0 0 0] - /Dest (subsec:loader-hmr) - /F 4 - /StructParent 302 - /Contents (Section 4.2) ->> -endobj - -5022 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [130.3328 336.4154 141.3328 350.0774] - /Border [0 0 0] - /Dest 4531 0 R - /F 4 - /StructParent 303 - /Contents (44) ->> -endobj - -5023 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [311.4504 322.75342 322.4504 336.4154] - /Border [0 0 0] - /Dest 4578 0 R - /F 4 - /StructParent 304 - /Contents (89) ->> -endobj - -5024 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [339.76633 309.09143 350.76633 322.75342] - /Border [0 0 0] - /Dest 4493 0 R - /F 4 - /StructParent 305 - /Contents (37) ->> -endobj - -5025 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [182.36285 281.7674 193.36285 295.42938] - /Border [0 0 0] - /Dest 4579 0 R - /F 4 - /StructParent 306 - /Contents (90) ->> -endobj - -5026 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [303.63855 281.7674 314.63855 295.42938] - /Border [0 0 0] - /Dest 4580 0 R - /F 4 - /StructParent 307 - /Contents (91) ->> -endobj - -5027 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [143.21643 240.78137 204.36157 254.44342] - /Border [0 0 0] - /Dest (subsubsec:motivation-plugins) - /F 4 - /StructParent 308 - /Contents (Section 1.2.1) ->> -endobj - -5028 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [339.1266 240.78137 350.1266 254.44342] - /Border [0 0 0] - /Dest 4581 0 R - /F 4 - /StructParent 309 - /Contents (92) ->> -endobj - -5029 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4360 0 R - /f1 4354 0 R - /f2 4366 0 R - /f3 4378 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 310 - /Tabs /S - /Parent 1 0 R - /Contents 5030 0 R - /Annots [5011 0 R 5012 0 R 5013 0 R 5014 0 R 5015 0 R 5016 0 R 5017 0 R 5018 0 R 5019 0 R 5020 0 R 5021 0 R 5022 0 R 5023 0 R 5024 0 R 5025 0 R 5026 0 R 5027 0 R 5028 0 R] ->> -endobj - -5030 0 obj -<< - /Length 6837 - /Filter /FlateDecode ->> -stream -x=r7vQ(mL -Ľv"7)%eebʙvO܀4yhq=88splw?ݼv_|㟾ǻfw?._M;3&Vj(mb<}-Fy/~K#Lm(>}T{\~Gv~Mmi\n9t`-^i'EW ڙGB>fcۜ-v~Zܾl>%QVZKaDꬫ A}ؽ׋/^^'M1H1\PaS#PGp\-xڸjhPnB-.JUТONZxX{| s_5C)~ 0␝B?8C;QpTyݯ]<]uVZ!Hho{zrLV5*s>,{Gbh7߿4(w܁6+;oЌOO;{bHaIp?K_NPx5M78a#-G@/?5.Hj6`[NC%q9wt{Llj[ MS2Oh>H n3jN\f2T]D4cԐu8#9]!#\a -fyσ"x봔pßHE)~+me!X@VI{{,cr - 'ё:_ --KKK?tRTu.0)s[d<`hLܨ՟ЩhMCQlH*C FUJB4>UPi[&:UHǞ`(qoP/8僎VKH>o}*xY CZ@N:540&o -'"ں0)VZ'_U_:mp6ڤC;ڄ;~(Y*\v~ }J= `ጤ'VUEɼQapN*Ƚ!߸E,? ~?=udL8Ug @^57rY[[H]9{̸Wo +㑰IZ[ Bjψ OZ5Dc˿o}_~?npdu9$4Z C3YǿdvՅ ĨͭX4JA_M[QeNe{<9c3#>>5 a46A%5gDer؆f`a. -CTD:BAwtalZ 6)Z.CmR{-ZTl?F&^|T^G6d7V@@6Rx/U b8L'^P\]-Z5 =Qz) y*jz-_pb<|V9 (> Y$`UM>줉:`̠}/aFblWaPajSħfޥ#tb^(_,~1&- Gv*DRbIFAG-Ʀ8RpɶmׄYrTyHqۀ Ft-;&hf"і<@a[#Zv,Rj=,R^=|J%D6G{e>K)aSCN,'(]+ZDG-oMOT֋ wјpPF &t?""Rɥe 0-5#օUr]iQ^@kJ<]F9oMDIcdOF/ƥ4Cj𾪑xB񏟮}#xb,M1n)jT=V?vg2ef ey\YPzpN|%hR0<u^BtP0r OFX/ jt0 X^ (3txڹzRI7jѹDyK<̳.HS( 24hMV٫Xz&IYo˫ -*ս;[]U7 TdIYDH ܠ bTۑuinAd-T/C&:kO4KmQ0:ּd@JP};pF1XJFFbЃM2K #gcV.6%R<_F( ҥOK—FνB23GRVQ p`J>P"=o6Sj튲Z8 -}%δKh_zh0fYo9|}QQ%Ͱ J%Ca+P2Uch>P//"vozx~1.L›%wGP!Cg7W*HʑAՀ zF2ƙh+PmmBؿ 7"ckDdr1kX#OfBgH8L X]j^4uUƯtDK"fPˢT'E:7oTiJfUX}/BjiT6]BtHj&&;2ҪEv1Yd.[x)5je$EfWцDdkB!̡$ө'Cku]! c*fًa8;?n(dU}5-{P<6RBq# 췪OR5HL,s:%%F/-ΌROjHD* XӕL* n^B;`FfW"z o~tf3nuqQb-JĈN4(mEzlTwpQ>8WWЮ6PjHE(N↠KoI!$hu_\neM:eNA΋Qz+ %WDa2NH'rVHA&H)-¤zL1I]; Wz6cI>ԙ&4JLBS_)۽ sfS3*h$=ŢqTmԥDBCKJ -+OZϰHRO4T V)Y\O] Nyߤ\MAu?nhD׊v :|H_B]Jv0$kh=%p`Kˆ9}v-rH?`o{ڿ"BnK4fW -Wwjpq q܅#%iS!j{U0\y5Er͏, WYn:I(t鯰~ƟN^ܥ"wS)AM=콊)gdۜ1OE[dDyKʸ<ؖi0(\ 2hJ<gpiU<kL=d"T+/mشlSP6j9_x \f6 =Ԑ"^ߊhL6M]Z0QY7lJT/~U"@yV=7F}[jPJVU=Sb{2DQyl),L{k.<2AESϞ]fV+lj|\1ƛE4'2Gj}T}u,'cm*8d&a|rJaw<3= -7%9Iȫ6lL340PRōUlE}I$,m˒*BOO&ɡI[UOCy=l]} ,c羕RojhWB_ $F%%(Jz⡐fůaN J亐/Drd&m|MBP~[a >j %9 dWjiicdAkZK|sxűdt@E"5],gˏ`H'G%5!ՋMv@?2͡"bEYEG66bS=tjShmjۭk3&Bk=mShi$br5 -d:wP1$M:rqI14u@6XGTc47 b17u24|&.'@lRVNEf R\7~4b6)!nB9"j+W2BPZM:eR -s54?eXGW܇\JnR\w0.~eXDk*tN`IKuϜh@ ~"R-rddEo?PZhk *u0(|)K"(>(vvM?T7tJ_7* $|艒M0],<[qxDeIfꌱy!L6 `tC+원Ie1z1'rhdSdYo 0*&z$*ƅvj]6jB,Wrь:aF5ʥ 1dQWhR& =("5i?@lXUO'7)U ޻h:܍r{!mVK H?Z{qY#+$y@|mxVv2՞`_VV{o6_cQ?g3̔-AhG Zs@PKcqNTKғ FP"GC F.@cL:^gDXY0Qi3L(,1oCMĴKvO2`P5lQ0' -WeUY1'tTbX4 z0ۥ,@GA%@S[ !5p52\;Uw*.GsFHIŦF꡴7 -RJ+ -+#,, JR=6Wym pnq-)Kt4BbLJ Z&1NfUNA0ZSQtqx}dxq-2.^f={*jI'/љ#sy6c۩%;nbHFjO.Бa,߯`Y - U%b!m3s٪T>xBs3fMb 3pt,eKm W?j) W3i t͒ځ*f<0yz/L+6ь.g r: x`zB%.?CA4SWRFH+ +TY -۔X'=ղDX X POŸsFuc5Xr$o::H }iPxb l\. y!$M) =7kmeJc8to^Έl9%p ^%b -F?Ntq ,˹ȬVA}II6fu -ib9iemE`K maM~ H=;0U!6V,gR*,c3HXDVh}sFy[1R Z%y;t-۪pV^`הaf &=F芻Syj$ĉ\FʌޓidWB=h.ٌ/ WxVTWtNqnV{4z tKPO5xi(*cHBlFYH E Nz}.|#4 lw{vwwo~}ٻw0oov_{wf?oo~y{{s-9oqC |Q'w -endstream -endobj - -5031 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [489.93527 732.5514 500.93527 746.2134] - /Border [0 0 0] - /Dest 4582 0 R - /F 4 - /StructParent 311 - /Contents (93) ->> -endobj - -5032 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [508.15146 732.5514 519.1514 746.2134] - /Border [0 0 0] - /Dest 4583 0 R - /F 4 - /StructParent 312 - /Contents (94) ->> -endobj - -5033 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [313.10226 718.8894 324.10226 732.5514] - /Border [0 0 0] - /Dest 4584 0 R - /F 4 - /StructParent 313 - /Contents (95) ->> -endobj - -5034 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [491.42682 691.5654 502.42682 705.2274] - /Border [0 0 0] - /Dest 4585 0 R - /F 4 - /StructParent 314 - /Contents (96) ->> -endobj - -5035 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [508.70145 691.5654 519.7015 705.2274] - /Border [0 0 0] - /Dest 4586 0 R - /F 4 - /StructParent 315 - /Contents (97) ->> -endobj - -5036 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [267.74725 677.9034 278.74725 691.5654] - /Border [0 0 0] - /Dest 4587 0 R - /F 4 - /StructParent 316 - /Contents (98) ->> -endobj - -5037 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [294.65292 664.2414 305.65292 677.9034] - /Border [0 0 0] - /Dest 4588 0 R - /F 4 - /StructParent 317 - /Contents (99) ->> -endobj - -5038 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [345.86566 664.2414 351.36566 677.9034] - /Border [0 0 0] - /Dest 4459 0 R - /F 4 - /StructParent 318 - /Contents (4) ->> -endobj - -5039 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [508.70145 664.2414 519.7015 677.9034] - /Border [0 0 0] - /Dest 4543 0 R - /F 4 - /StructParent 319 - /Contents (55) ->> -endobj - -5040 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [409.15625 473.5904 420.15625 487.2524] - /Border [0 0 0] - /Dest 4496 0 R - /F 4 - /StructParent 320 - /Contents (39) ->> -endobj - -5041 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [502.65146 473.5904 519.1514 487.2524] - /Border [0 0 0] - /Dest 4589 0 R - /F 4 - /StructParent 321 - /Contents (100) ->> -endobj - -5042 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [160.42686 377.9564 211.92822 391.6184] - /Border [0 0 0] - /Dest (subsec:reactive-coeffects) - /F 4 - /StructParent 322 - /Contents (Section 3.2) ->> -endobj - -5043 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [404.4731 330.1704 420.9731 343.8324] - /Border [0 0 0] - /Dest 4590 0 R - /F 4 - /StructParent 323 - /Contents (101) ->> -endobj - -5044 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [426.4229 330.1704 442.9229 343.8324] - /Border [0 0 0] - /Dest 4591 0 R - /F 4 - /StructParent 324 - /Contents (102) ->> -endobj - -5045 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [420.18588 302.84637 436.68588 316.50842] - /Border [0 0 0] - /Dest 4591 0 R - /F 4 - /StructParent 325 - /Contents (102) ->> -endobj - -5046 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [423.9508 275.5224 434.9508 289.1844] - /Border [0 0 0] - /Dest 4534 0 R - /F 4 - /StructParent 326 - /Contents (47) ->> -endobj - -5047 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [216.92166 248.19843 269.61102 261.8604] - /Border [0 0 0] - /Dest (subsec:scaling) - /F 4 - /StructParent 327 - /Contents (Section 5.1) ->> -endobj - -5048 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [75.88214 152.56439 135.71114 166.22638] - /Border [0 0 0] - /Dest (subsubsec:lifecycle-asynchrony) - /F 4 - /StructParent 328 - /Contents (Section 3.3.4) ->> -endobj - -5049 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [399.4341 132.10242 415.9341 145.7644] - /Border [0 0 0] - /Dest 4592 0 R - /F 4 - /StructParent 329 - /Contents (103) ->> -endobj - -5050 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [176.83247 118.44043 193.33247 132.10242] - /Border [0 0 0] - /Dest 4593 0 R - /F 4 - /StructParent 330 - /Contents (104) ->> -endobj - -5051 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [198.4779 118.44043 214.9779 132.10242] - /Border [0 0 0] - /Dest 4594 0 R - /F 4 - /StructParent 331 - /Contents (105) ->> -endobj - -5052 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [280.25635 91.116394 296.75635 104.77838] - /Border [0 0 0] - /Dest 4595 0 R - /F 4 - /StructParent 332 - /Contents (106) ->> -endobj - -5053 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4354 0 R - /f1 4360 0 R - /f2 4378 0 R - /f3 4366 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 333 - /Tabs /S - /Parent 1 0 R - /Contents 5054 0 R - /Annots [5031 0 R 5032 0 R 5033 0 R 5034 0 R 5035 0 R 5036 0 R 5037 0 R 5038 0 R 5039 0 R 5040 0 R 5041 0 R 5042 0 R 5043 0 R 5044 0 R 5045 0 R 5046 0 R 5047 0 R 5048 0 R 5049 0 R 5050 0 R 5051 0 R 5052 0 R] ->> -endobj - -5054 0 obj -<< - /Length 6459 - /Filter /FlateDecode ->> -stream -x=ks+FG.T ޏQNUtѕ]W>f]uW3 4 bVb$h4w/.v{w? ~Wv~z8vۻ?l>n.^o^]|0ۛWjnwi^|wLY+t`Ry=ݿOʦbjFݔIɃ\䇟5 h5B0of-_+|~nۋE '!E`\Apn=v0uؖVZj"XU:QQWxLq~'ލ>0\&'=Ahxhq܌O?n0=oT<> Rr~S33aDxqRIf=ƒ1c,b\dS(aFStf,đ-d؇{t\E$:퇄{~!y3nKrI0O˪g^R1灉XxmJ: t/&h+<0)=L䫫5z`AE - |- ELJظ0 DM_WcKż ZʣU% Bm!2; -t`,{apE*o2$ALkO,1#/G(CqTУ<4 %\-UE)h >Jnܔ*{S؇,[fM`v̔gKTys2'cy漎YZc"I?U#[MJu4KgqÂ2&T),?o``@#4-ީ?? m:[)W}x]u 2Cݢ0[ʝ_L=|TeFLK;9B:dDr|,`쀝:QpWiSGG/pɛ T&xKi0]#sΣ0LPL׵(s7 Ic~ڢp%eNxpm:2f ~~u,kAnˊP+8.Y @ǂ&j&r¤|Ӷ61ѢXD,5a_FJ(pPGۭ2hf 8wG܁nh@LYT?[s4)Dz۵`8{~Q]歱{.`j)1j ;eY酾!qhim!M,*F;@7 KW,y&w/ը0}n ݹzɭ9, -*d+q3+pO,(Mꂬ-jLn6,zUCd ^'B9Ac -_ Xa# -Wq\I= ᗥS_Z-HqF5/ -Fꅱ,x'R1C K#o"6Ġ0k90Hk>脼g )٠e{p3@ ZDw}AoL9BG%0LbAЁi&4W&eOAeĩ2Ƕňgs_}X>.݅P<(hH\"HE~=0FmHX.#j[Ox#RtN --EP,1WcoMEJSW5nd]Wg)9neЩh+}m3mˑ!a I|SyQX{WJ1|wu4$C1cN'6sXWWC8LyYe,Ha bfxs'uT?Z{[ܘM)+01Cm ^:4G=fFki2أZ Mۋh*v*.pzDig)#3缸vL -?KJ? - -%Rl'ݲHn6oS#JAu#rq͖:rVXϢÃ}o2%/'u8JO?HP-Mߡewʲh"~Eq -tBf8ιHEN~;JWDd]Պ/cƦiBwi١T̹P ү,4`*HFh\R0m97c:(mWҟL01"{23m -1mK4 [ -RTV2goBOu8!: Z<7~ J؉vP51d}>=a2ȋ9p&Dsw7lVy~Z8)$%Z1RM'X/J_Eg -ɦWt43RcwJ.D-zL83@@Ev`RKOP5; -bp܌HmF-8i矋D:D<Z>ZP]Z[ͼ7wO3[Зg)u˴y .@1@EIW#kW!!> Diӌ@ rҁ(Hg`B -G8W@6%єut9 iU&RGU_ryc9F5:BhͥM|z,Ha*uJ3D:bՐfnBpΞOpH#mLFuEB=;+|څ+xY0elY%tvpr=قF:!YX*A3ٲwY Η 5iI,ƒGw#GN 8;I`M /z~jWa$&eq?&iѩsXd/0HEzDmT+f0$!0؟M 6l:ͺ^BfQ8eQ66Yxb mqi%k6sꣂ" ΥiU, dFI- cxVGL -`MA6֊z ->萚d PQ 1D5^ -~GrSR $jS18jchusk=C8͓A=\M٢4?fv(YYK -^Ը>JX{ϟ\3JBa´Ԣw.#*7!LXQCcUD 2gRsZس6ۻ abƆ~ykK.eƪФ<4N\$"KüMW年M,f&aNU3j˫xІO,ɺB1{'jbS0DV2hԞWHHB:ҵCyq5;iOhGG`?OcFYubp ՄɦdI0iHgA+|ݞ.1Rzx͜x#ZD]EDsٕ#+-Y-<U:R1TN+.I~2z!iW -) ] %Tr6?W~1g W ;܅LH]l;˼ZbK,EZ45'~UT˧.?)4 {]~r|ƛ at$l | eڹe<'j^`UʆV׼$dm7|c>A,}T-8|zqy4v cR2oy*hղqYG`UTgWO|1Pᯏ ߉zTFnmxMլָ?CQ{%$#l6ˉ «L%#YV᫵̓oz1;IJ'Y@\b(`LhfZHΗGvɖG9Gx4~]5 %d3fW]fO)ͷL -dw02XziPml?2.I*>_GVoC-m@K4:Zi< -_Z?s=O7_~n?~w7?n=퇏B`AsV -endstream -endobj - -5055 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [237.94225 435.3644 299.514 449.0264] - /Border [0 0 0] - /Dest (subsubsec:motivation-harnesses) - /F 4 - /StructParent 334 - /Contents (Section 1.2.2) ->> -endobj - -5056 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 281.5974 85.78214 295.2594] - /Border [0 0 0] - /Dest 4596 0 R - /F 4 - /StructParent 335 - /Contents ([1]) ->> -endobj - -5057 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [413.16415 267.93542 523.01013 281.5974] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/361598.361623) - >> - /F 4 - /StructParent 336 - /Contents (https://doi.org/10.1145/361598.361623) ->> -endobj - -5058 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 247.47339 85.78214 261.13538] - /Border [0 0 0] - /Dest 4597 0 R - /F 4 - /StructParent 337 - /Contents ([2]) ->> -endobj - -5059 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [169.31615 233.8114 290.16214 247.47339] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/1053331.1053345) - >> - /F 4 - /StructParent 338 - /Contents (https://doi.org/10.1145/1053331.1053345) ->> -endobj - -5060 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 213.34943 85.78214 227.01141] - /Border [0 0 0] - /Dest 4598 0 R - /F 4 - /StructParent 339 - /Contents ([3]) ->> -endobj - -5061 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [442.35815 199.68738 521.95416 213.34943] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/2890784) - >> - /F 4 - /StructParent 340 - /Contents (https://doi.org/10.1145/2890784) ->> -endobj - -5062 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 179.2254 85.78214 192.88739] - /Border [0 0 0] - /Dest 4599 0 R - /F 4 - /StructParent 341 - /Contents ([4]) ->> -endobj - -5063 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 158.76343 85.78214 172.42542] - /Border [0 0 0] - /Dest 4600 0 R - /F 4 - /StructParent 342 - /Contents ([5]) ->> -endobj - -5064 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [275.27914 117.777405 385.12515 131.43939] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/378795.378858) - >> - /F 4 - /StructParent 343 - /Contents (https://doi.org/10.1145/378795.378858) ->> -endobj - -5065 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 97.31543 85.78214 110.97742] - /Border [0 0 0] - /Dest 4601 0 R - /F 4 - /StructParent 344 - /Contents ([6]) ->> -endobj - -5066 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4366 0 R - /f1 4360 0 R - /f2 4354 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 345 - /Tabs /S - /Parent 1 0 R - /Contents 5067 0 R - /Annots [5055 0 R 5056 0 R 5057 0 R 5058 0 R 5059 0 R 5060 0 R 5061 0 R 5062 0 R 5063 0 R 5064 0 R 5065 0 R] ->> -endobj - -5067 0 obj -<< - /Length 5044 - /Filter /FlateDecode ->> -stream -x=[w$&0l,n,,@<&f3iuKRI}<|/ϴ.RT~tzx{j>i_N{?}???4|f폯o~|꓋Ooh_~W cB4͕hgB7NwLV7?]\_ <]\?Fqtqο OoRaw߄;|ӛqcYЦHQCsrjKι?T?9s H6#zFDӃ(;__b++| -_xІqι:?Fx&a?rY7`Pd{6F6BūaDA2Q` mw@7FN%,I 3n:ņK6N(:I1=<<'r%1>4rE|Ƶ?e4uIt;X^08eĉhu6_NlŸRrf/ᕶr@/iւ1]}#IE/s-C+י- 86pKRf7 -l|f*+'-d3)'m΃m"BA+."ZUKSlj[ش9EB̎ 3 ,"AȀh fy(ki+YiU5X0F?zǖ1m.S[#XJ3icޡEE" cTO[ _d_cBjPj5wlx#3A9d]>`N߼\4apUЖbH^zr[0F%)$d`zTKQafLP3O:[Lgv[̮uVhPZ -xew\HiI!찎# rJ! Gj3XYa!o|Zk]l3G;/tIikyE J,X׶x(sj[-ghij0D鞎CT%4>tcGvLkr{Ν3& n!J/=d;nCǒʶL-Ղ(Tc҂Mh^q1 8ZN{F=;`Y i;;نB -Χ|*c:\}'/VEޣ[u J,ˀ4&;8vP -mgfM0y)ɸ[#]ەmʼnҺ >!$ύ ꁧ>$<Ocɇ}BHX}[n7$*$Bs`, VBB <]Z)wV pi^!.t{^`'lna3c`#0i^[~Eovd8J41ݐZNF _iG(ҝ[˄dC!0X%ižJ^Zߕs{%%D yM}Fij֠ǑO7u wxxt`>2ۊ`bѲnI1b.+l飝dFl] nA6EL.f@\ԷW ͯ?D򹆐1[}]"Ē+Zԙdl0$}q]DfbED^[fnzܡi|[ཬO/tL4Q88V KJ4@MT! E5C - -)EVm:R4v[ZôL+-4pA߮ǦmLk5A aq`;D_J@poXslJX4CK@9*R\!"dPe MVzVC*R=kTZh˯<%j!%MFLMJuOu@BvgYr9^],J``zKM3;}||_Kf9jyӼ2{AQ'&]u1Mh)ҙ&O? -Հ"yV0w̯M/)bp4)nO*T2yLxMp0a ):4_FW"?;p&SUiFvdt}N~j88W$Ʈ=6Vb^l&.0@62eժP$I&'6?!ݚ^QT>:-M28f}7ۻQ7T-9OK;^eрyl ;̀,t!gm3g!Irx+9b>|kjrDu$父yκ'9 u$[ (8;ٳfWkWj.1ҙeZl3eI6uQd|4T t:\ESB2}ἎLj];,1Pv#^/jfTj"z59>-VHƜ6}Nɾvhذ҂ /?,<鑨u˔9ve t$_&&!d2K% Ht4 s]"ܔ`e5ǩ]f=ޗy - ]LH3\`"x3WR^8/yO?>#1ܡ2*qY)92㧧T3GOȞgR9xy{bטS -Ŭ*0TP&]PR'1^@#&<58 ]=鐑&5?xIȩȔ6 -YiZ6j^)pXWz>?Ɔbv#R\-Hӓi8]FnDFYk \l3n̗/60 1-4hR.m;&UUFIL2`i+---vBPwlK: YybiI9x"E;)ZeZ` W<Ƿ k0a;-2 "-CWȎ3ae/7J.eimJS |/WH$ d ] PDA` 3Kն'UMlxBݔ/ž`pFO5ci뢍@_ v|A,D61Y|͂:Km$ޓUYW0\2'6.qHS:kVԐcꈎ3eealU&R2oO_3 -#hOWճA .@WMфb0/5Z-R,8!ZɤWҊ -U4{L\yMU)DyIxfa[B@hp Ħ}bDwzFC|k1?uP#ʛc\S|?Gu4Ʈ -/܉J҄؋HOjs"r5'i҂5Sc -FX2JKXo{uV[Ŷ(l +klm/B  U&t 6TL;_KÁPJD%a#jZidJGO/YiHfjThy4;=P:_-Ү`Nr\ ulXqюU3flg]{I -voB@XtB0d1҂)D Sdذw#GcX *_:,U8>[;mWr)ջG2X. Bi'w~{hcF5ƀ4='J0lHƌ\D3ZTA:&[kTbn)ʐ6HLQ H e[~RclC`3+j(7g"@ޒ#Ť Lτ&fޑy㐜\nq Hl\]ʲ/p`<1WXv9 als]w^7h2c+.{0!MoAذ*#3#Li&nnf`<# =qt]{2/"6:j|ǤmZU/Iy͗C'Q@<|);DɿϞż4ѥoQ.v;k^q -lj -6&]smj,!Okuݕ'F|tzx{No?4^tzrwgoޜn_x{zI&k#X'YOH_w -endstream -endobj - -5068 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 746.2134 85.78214 759.87537] - /Border [0 0 0] - /Dest 4602 0 R - /F 4 - /StructParent 346 - /Contents ([7]) ->> -endobj - -5069 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [183.08813 732.5514 419.91815 746.2134] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://openai.com/index/harness-engineering/) - >> - /F 4 - /StructParent 347 - /Contents (https://openai.com/index/harness-engineering/) ->> -endobj - -5070 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 712.0894 85.78214 725.7514] - /Border [0 0 0] - /Dest 4602 0 R - /F 4 - /StructParent 348 - /Contents ([8]) ->> -endobj - -5071 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [242.77809 698.42737 526.4241 712.0894] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://www.anthropic.com/engineering/harness-design-long-running-apps) - >> - /F 4 - /StructParent 349 - /Contents (https://www.anthropic.com/engineering/harness-design-long-running-apps) ->> -endobj - -5072 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [103.932144 684.7654 195.93614 698.42737] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://www.anthropic.com/engineering/harness-design-long-running-apps) - >> - /F 4 - /StructParent 350 - /Contents (https://www.anthropic.com/engineering/harness-design-long-running-apps) ->> -endobj - -5073 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 664.3034 85.78214 677.9654] - /Border [0 0 0] - /Dest 4602 0 R - /F 4 - /StructParent 351 - /Contents ([9]) ->> -endobj - -5074 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [387.49014 650.6414 521.23914 664.3034] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1007/s11704-024-40231-1) - >> - /F 4 - /StructParent 352 - /Contents (https://doi.org/10.1007/s11704-024-40231-1) ->> -endobj - -5075 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 630.1794 91.28214 643.84143] - /Border [0 0 0] - /Dest 4603 0 R - /F 4 - /StructParent 353 - /Contents ([10]) ->> -endobj - -5076 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [125.31614 616.5174 204.91214 630.1794] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/3704435) - >> - /F 4 - /StructParent 354 - /Contents (https://doi.org/10.1145/3704435) ->> -endobj - -5077 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 596.0554 91.28214 609.7174] - /Border [0 0 0] - /Dest 4604 0 R - /F 4 - /StructParent 355 - /Contents ([11]) ->> -endobj - -5078 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 561.9314 91.28214 575.5934] - /Border [0 0 0] - /Dest 4605 0 R - /F 4 - /StructParent 356 - /Contents ([12]) ->> -endobj - -5079 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [355.66714 534.6074 467.96616 548.2694] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.24963/ijcai.2024/890) - >> - /F 4 - /StructParent 357 - /Contents (https://doi.org/10.24963/ijcai.2024/890) ->> -endobj - -5080 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 514.1454 91.28214 527.8074] - /Border [0 0 0] - /Dest 4606 0 R - /F 4 - /StructParent 358 - /Contents ([13]) ->> -endobj - -5081 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 466.3594 91.28214 480.0214] - /Border [0 0 0] - /Dest 4607 0 R - /F 4 - /StructParent 359 - /Contents ([14]) ->> -endobj - -5082 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 432.2354 91.28214 445.8974] - /Border [0 0 0] - /Dest 4608 0 R - /F 4 - /StructParent 360 - /Contents ([15]) ->> -endobj - -5083 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [233.44614 418.5734 379.90015 432.2354] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1016/0890-5401(91)90052-4) - >> - /F 4 - /StructParent 361 - /Contents (https://doi.org/10.1016/0890-5401(91)90052-4) ->> -endobj - -5084 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 398.1114 91.28214 411.7734] - /Border [0 0 0] - /Dest 4608 0 R - /F 4 - /StructParent 362 - /Contents ([16]) ->> -endobj - -5085 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 350.3254 91.28214 363.9874] - /Border [0 0 0] - /Dest 4609 0 R - /F 4 - /StructParent 363 - /Contents ([17]) ->> -endobj - -5086 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [169.31615 309.33942 313.06415 323.0014] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1007/978-3-642-39212-2_35) - >> - /F 4 - /StructParent 364 - /Contents (https://doi.org/10.1007/978-3-642-39212-2_35) ->> -endobj - -5087 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 288.87738 91.28214 302.53943] - /Border [0 0 0] - /Dest 4609 0 R - /F 4 - /StructParent 365 - /Contents ([18]) ->> -endobj - -5088 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [310.53415 247.89142 431.38013 261.5534] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/2951913.2951939) - >> - /F 4 - /StructParent 366 - /Contents (https://doi.org/10.1145/2951913.2951939) ->> -endobj - -5089 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 227.42938 91.28214 241.09143] - /Border [0 0 0] - /Dest 4610 0 R - /F 4 - /StructParent 367 - /Contents ([19]) ->> -endobj - -5090 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [264.92813 213.7674 344.52414 227.42938] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.2307/2266170) - >> - /F 4 - /StructParent 368 - /Contents (https://doi.org/10.2307/2266170) ->> -endobj - -5091 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 193.30542 91.28214 206.9674] - /Border [0 0 0] - /Dest 4610 0 R - /F 4 - /StructParent 369 - /Contents ([20]) ->> -endobj - -5092 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 172.84338 91.28214 186.50537] - /Border [0 0 0] - /Dest 4611 0 R - /F 4 - /StructParent 370 - /Contents ([21]) ->> -endobj - -5093 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [125.31614 131.85742 224.16214 145.51941] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/73560.73564) - >> - /F 4 - /StructParent 371 - /Contents (https://doi.org/10.1145/73560.73564) ->> -endobj - -5094 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 111.395386 91.28214 125.05737] - /Border [0 0 0] - /Dest 4612 0 R - /F 4 - /StructParent 372 - /Contents ([22]) ->> -endobj - -5095 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4360 0 R - /f1 4366 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 373 - /Tabs /S - /Parent 1 0 R - /Contents 5096 0 R - /Annots [5068 0 R 5069 0 R 5070 0 R 5071 0 R 5072 0 R 5073 0 R 5074 0 R 5075 0 R 5076 0 R 5077 0 R 5078 0 R 5079 0 R 5080 0 R 5081 0 R 5082 0 R 5083 0 R 5084 0 R 5085 0 R 5086 0 R 5087 0 R 5088 0 R 5089 0 R 5090 0 R 5091 0 R 5092 0 R 5093 0 R 5094 0 R] ->> -endobj - -5096 0 obj -<< - /Length 5301 - /Filter /FlateDecode ->> -stream -x][s~hR*aJٵTbKL?Ph+9̸* ppf7}rq98}ڧn/ӧ'MspO?S;_Ç/N^~qro/ۆO~"hgB7N{&U_ONxsj77'׼9+w=o}Ԝ8!!DpżBo@J}>.82+ngG*C|}݇롖5O94bjD㋹Y>8sk?=;7k"YHo\ʘ=J5a?R.xi8 {p&NKa -ȋ/WK6.6rť%=ކIsj̹ X|QIwqz۳Y;]#F!)WiUcNɓzQUƝ2gg[PM -.+f%paPmF3$å3Fajd]Bj0aZ; ϱZp0A +|VࢮT4}g:)T y&FrGI"&H瘱Nl0IB~-j/Pe5QɁܭfڹHFG/PZ]9kf4 xn"PU߀!I}{{NVj&h}XfsK+,/Y]M}ɘǍ[ 6z%'fAPo6R(-) -AaF;bK~$,U2l.Z`e&V_zӄap _غђXIX:L K0I/Z6@ -zn$y":z@[T|. .(jTgFvAs<ډr(L43/WP!  }^~gS.&ի4 L۸͝VaCCVSmN0罐̶',*`/-z\q+-j.kQqR`@C -V]`nYfÍPWnMg1W([$pXA_` -Hs]-6 O8P(3f9} !s> >- [ST ZU[qNpX'?ȫP.T*DHz*XSuk FcOrVXY`ѻy:Ab:Aw 019}((e5L4]czg 7h cC2G,A cb}+xGq*(]E\~ FE0)֊UQz!1 ٴXu7ovM2:˱˭֕02)^.K%C^#l$Z@EFRYѽ\$'ADh a.1)tU[4;<2;QCa1AQ~9-7 zZc}rHPWZ3#;5C^)yЯ!%фݵWw:܃/B f{AU q$N6I6+!'Ъ,2tF:+f%B_H^_ΰֶZl+ߪ Sz`HLx@zYwx!eɂ}TJ "sE/T]F樓l7/[PnڂŶO~%??qY5'~%a%ܮOR2<>͈<7bI,0/$ xLWW|w#'P`Z"~cZ>`@t~wΙO`Ǥ!m%xSmFrlFUDɘ$SEzqBhÅwFJ@\IYxT~ᤦ:fx$D&rg'59>.LSzCgP` -y딛&EgkRnM¤'fm+|i\_Ը6u&dRorK UBh%Lڬ} j=a"#E/-e"mU&HYY$ 'EħkPG_I@ Ɛ}Gb]w (8mUqZ;t0p7$Z -h i{2|œ՚ױr Β%HE -Rf5hA: 3khGh"uTwOr }:; \G)bv-Jn/py?7?>x8|~wo>~<~:￿C(^2\0k -#7, -endstream -endobj - -5097 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 746.2134 91.28214 759.87537] - /Border [0 0 0] - /Dest 4613 0 R - /F 4 - /StructParent 374 - /Contents ([23]) ->> -endobj - -5098 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [245.49113 718.8894 369.07614 732.5514] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1007/3-540-45931-6_24) - >> - /F 4 - /StructParent 375 - /Contents (https://doi.org/10.1007/3-540-45931-6_24) ->> -endobj - -5099 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 698.42737 91.28214 712.0894] - /Border [0 0 0] - /Dest 4614 0 R - /F 4 - /StructParent 376 - /Contents ([24]) ->> -endobj - -5100 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [125.31614 671.1034 263.56415 684.7654] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1007/978-3-642-00590-9_7) - >> - /F 4 - /StructParent 377 - /Contents (https://doi.org/10.1007/978-3-642-00590-9_7) ->> -endobj - -5101 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 650.6414 91.28214 664.3034] - /Border [0 0 0] - /Dest 4615 0 R - /F 4 - /StructParent 378 - /Contents ([25]) ->> -endobj - -5102 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [483.31345 636.9794 524.4094 650.6414] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1016/j.entcs.2015.12.003) - >> - /F 4 - /StructParent 379 - /Contents (https://doi.org/10.1016/j.entcs.2015.12.003) ->> -endobj - -5103 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [103.932144 623.3174 191.81114 636.9794] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1016/j.entcs.2015.12.003) - >> - /F 4 - /StructParent 380 - /Contents (https://doi.org/10.1016/j.entcs.2015.12.003) ->> -endobj - -5104 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 602.8554 91.28214 616.5174] - /Border [0 0 0] - /Dest 4616 0 R - /F 4 - /StructParent 381 - /Contents ([26]) ->> -endobj - -5105 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [483.31345 589.1934 524.4094 602.8554] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.4204/eptcs.153.8) - >> - /F 4 - /StructParent 382 - /Contents (https://doi.org/10.4204/eptcs.153.8) ->> -endobj - -5106 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [103.932144 575.5314 156.22614 589.1934] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.4204/eptcs.153.8) - >> - /F 4 - /StructParent 383 - /Contents (https://doi.org/10.4204/eptcs.153.8) ->> -endobj - -5107 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 555.0694 91.28214 568.73145] - /Border [0 0 0] - /Dest 4616 0 R - /F 4 - /StructParent 384 - /Contents ([27]) ->> -endobj - -5108 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [103.932144 514.0834 224.77814 527.74536] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/3009837.3009872) - >> - /F 4 - /StructParent 385 - /Contents (https://doi.org/10.1145/3009837.3009872) ->> -endobj - -5109 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 493.6214 91.28214 507.2834] - /Border [0 0 0] - /Dest 4617 0 R - /F 4 - /StructParent 386 - /Contents ([28]) ->> -endobj - -5110 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [103.932144 466.2974 235.48114 479.9594] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1016/j.jlamp.2014.02.001) - >> - /F 4 - /StructParent 387 - /Contents (https://doi.org/10.1016/j.jlamp.2014.02.001) ->> -endobj - -5111 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 445.8354 91.28214 459.4974] - /Border [0 0 0] - /Dest 4618 0 R - /F 4 - /StructParent 388 - /Contents ([29]) ->> -endobj - -5112 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [287.61014 432.1734 367.20615 445.8354] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/3408995) - >> - /F 4 - /StructParent 389 - /Contents (https://doi.org/10.1145/3408995) ->> -endobj - -5113 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 411.7114 91.28214 425.3734] - /Border [0 0 0] - /Dest 4619 0 R - /F 4 - /StructParent 390 - /Contents ([30]) ->> -endobj - -5114 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [275.27914 370.7254 396.12515 384.3874] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/2628136.2628160) - >> - /F 4 - /StructParent 391 - /Contents (https://doi.org/10.1145/2628136.2628160) ->> -endobj - -5115 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 350.2634 91.28214 363.9254] - /Border [0 0 0] - /Dest 4620 0 R - /F 4 - /StructParent 392 - /Contents ([31]) ->> -endobj - -5116 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [394.88446 336.6014 523.85944 350.2634] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1016/j.entcs.2008.05.029) - >> - /F 4 - /StructParent 393 - /Contents (https://doi.org/10.1016/j.entcs.2008.05.029) ->> -endobj - -5117 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 316.1394 91.28214 329.8014] - /Border [0 0 0] - /Dest 4621 0 R - /F 4 - /StructParent 394 - /Contents ([32]) ->> -endobj - -5118 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [103.932144 275.15338 247.68015 288.81543] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1007/978-3-642-54833-8_19) - >> - /F 4 - /StructParent 395 - /Contents (https://doi.org/10.1007/978-3-642-54833-8_19) ->> -endobj - -5119 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 254.6914 91.28214 268.3534] - /Border [0 0 0] - /Dest 4622 0 R - /F 4 - /StructParent 396 - /Contents ([33]) ->> -endobj - -5120 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [103.932144 227.36737 224.77814 241.02942] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/1932681.1863568) - >> - /F 4 - /StructParent 397 - /Contents (https://doi.org/10.1145/1932681.1863568) ->> -endobj - -5121 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 206.9054 91.28214 220.56738] - /Border [0 0 0] - /Dest 4623 0 R - /F 4 - /StructParent 398 - /Contents ([34]) ->> -endobj - -5122 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [215.53815 165.91937 325.38416 179.58142] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/292540.292555) - >> - /F 4 - /StructParent 399 - /Contents (https://doi.org/10.1145/292540.292555) ->> -endobj - -5123 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 145.4574 91.28214 159.11938] - /Border [0 0 0] - /Dest 4623 0 R - /F 4 - /StructParent 400 - /Contents ([35]) ->> -endobj - -5124 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [250.87015 131.79541 360.71616 145.4574] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/360051.360056) - >> - /F 4 - /StructParent 401 - /Contents (https://doi.org/10.1145/360051.360056) ->> -endobj - -5125 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 111.333374 91.28214 124.99542] - /Border [0 0 0] - /Dest 4624 0 R - /F 4 - /StructParent 402 - /Contents ([36]) ->> -endobj - -5126 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [332.40213 97.67139 411.99814 111.333374] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/3498692) - >> - /F 4 - /StructParent 403 - /Contents (https://doi.org/10.1145/3498692) ->> -endobj - -5127 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4360 0 R - /f1 4366 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 404 - /Tabs /S - /Parent 1 0 R - /Contents 5128 0 R - /Annots [5097 0 R 5098 0 R 5099 0 R 5100 0 R 5101 0 R 5102 0 R 5103 0 R 5104 0 R 5105 0 R 5106 0 R 5107 0 R 5108 0 R 5109 0 R 5110 0 R 5111 0 R 5112 0 R 5113 0 R 5114 0 R 5115 0 R 5116 0 R 5117 0 R 5118 0 R 5119 0 R 5120 0 R 5121 0 R 5122 0 R 5123 0 R 5124 0 R 5125 0 R 5126 0 R] ->> -endobj - -5128 0 obj -<< - /Length 5218 - /Filter /FlateDecode ->> -stream -x]r7}WCV-и k$Kk+l/c)6-/UUK5 ]kv2 kn;{/Oã~n۫oG~yڿ;{{嫳^:XWeG_ucJz쌴^v7mohw3fwvwgwc|2[JßS]Wgo1A -bgr&σCta-ЇO6SR1蘕?U$\'6iө CktSMggDo?O7=uS'&;='$T!7["&i Y׶Bc檖ޥ{"ms'Vaovt6'V^լ]=7i ?ϔ1R>q](I@"E0ϓ$i L{k07c-֪h@pw@ȦP̼%=ih` ;[Ż혙mйwSD~Ԑlù aAWl,tY<LCJF>Lfܼ|GbۯV"(ML91dKzq.oo=ŗϦ ft=1X]8#vԹ[+nBMgAi>g|3|{x,4 D\*"-c]k>Ea̽z<<ο=qY~Qp[@jFF<8d6iPF+i:MVXkX[-(,nDȪض&tPu|co]A4"t|}1|,}lܧPZYbX3F\L<%zApZ4Ю_s_G"dzSm1J<]dQvb,m#2Jb2VMʄ7 bT6#6(w(?/K`'* Lm:,~5u W9'B4XLWF)\7s0Ki`$a j0`jo`5}2>L `+с?)ӜDiTLp.39 Z땀}a c-cxfӱi8an#((9LIWF:tw!R Ay̜Ͱ GF\': ,[4KSJ.Japa&Y "Dqz|czh2[0j2&۱]('63jojm<s8g|Y$yG, ^.. `R@`KU@ƘmUows^\c߱ DSw@=lȁ)Ƀbo1ŗYFzXSg&YI{U𷶉Z < W̘]@2EVX |=(<6MgI0XPtȯ: uZfHH \~āo*QA!,*Ng֚uJ˙iK_-A)Y Nʀ҄6 - JZ):TcQ#7 -JFU3\OAWXYn:L -!>Xy xz9i?F=SysMQbkk!:]ttʞ-8QqPKEuZ$R40>FW3 w&'>QaoG+P{$5B)*$Ykfk:L("L4n -/Uou`Q&B'ى -k,nBL{8q)wA>MXEPyS ^V3@'!M_\$1{ o|t}?0Rb̒QIۙ@gt,j-:fi<-X,q@n&ә+2CKbLϚ:]IפD˵2J]oVs.Q4L>%+6`☹XcKWK]*SD/hʞj[2#[6BL:9}ES W%P4=L(\VV4ED~'PÅ@TIb"u*IQ*NQ.> ӕ~0ŭēr_,*ύD<$,56k?0K#;R["8wO.aBEg8oE:"8 򩃮}ʞz-&Γ:Z`2Z%0nôηr01 e 8%+Z:9DRȬ`Bר̂x(Leb(&9ƾC}?VY;"@zubނMF2Wc&y_FHa'hU"(JlPY>HۈĦ6$<0@ɚ+F`h]ʮqQwo> g*("/~?("yoft!Xh܆HB=G14T#'$FTܠ!gyp@pbyQQ7Iy[.]t z\K '@j9GVO >]<QXoPoMa4_'_΁C(b_r(x1&snBJO8赌PFicمkN(VNvEYIFB -")y H=VE2# Oa;q1-MQ`>Ct6r"Ɔ564JdĘ.ƫ ctm+Zd9*93-'^'/a"DH) HLxY/8&Ϝ ^ud"GdYF^\&,WJ3XֿĨS}eҝbDDw4euc"j"Xu‰D&uU+&+Z_!kӐ׽EYjlmQZEZO/F' -R\^AI t>wY5l*x_){$ATՌglSxS2Azr.iAT$`hQֶoNU_SֶmPXySkSͺnb׽tkP%DqLLuЕ:KE\(qRFX) -LF Eܝ\'!5 7 -+IKWPZN -*x+27R 镭qɆjLK)@G)ĔioTA9b{-; ҥaAMV,\T5:۽3(J=/љB-'wE%@iȈ - Dy4b:z*6 QPEo -鞱 FmpC0C J*)QN( S0 xhc<w 4X׽ڛYqTfd|l.V͒I|'Ӟx!T귧Áy]3EQ$Jrcj$$jQֶx ^[08Ǧi_BޞGiMĔنI0fǞެpfDww;7j݋!jA-%SZ$S < reaz]PV)}E"BJb6ʘ쎅 0'xN*MBao<9K!tpø>"'5w\ -W -,ccgzfn?6R KkȌKIM`M 4F;dBMr<\ٹ[ id?91&uU h܏;P1ƭFn& .0>Ž x{ރr\ɋﳱ[]/nPZA%_+ֽӖ!|.p7hr+L'9G>*LD > aH R=HjTGgUq2H q:Y:[xIM8 @OHU'Ntݎzl b]gV{a ]S ؐW|HMؖ!0g*ۂU ź;Ow/w㲞Mu&QZԲ1UՋ$A&iCA%#FuNYXg:=qڀÏ82q0=YE$ۢ"B+N(/=%fn6$ΐUV`([:"YtIbYyA>OϨmgxWq/nsj8~ ]f [^pC 8.KМ@/;9ӞiDrW 4yuo%kSMmVj[$wL ]5KVjHx?s>CQ`OE}2&lfYT_OȄq( a_tAħxǮ+t;q:ZEou -"]ȁ ql4]40 ACW0Y;c L] -ޛ[=;q '[~|98EÔPS!/Q`F?wītkg[x$[h3 .^xD%%A$^6-=NhA *.Z '=Uj;1G"[`m"=%...QT2H:?kzz€/ȞV 8Q0ǯ|r?%J{ 03Fv;]8tyݏۗ4> -endobj - -5130 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [103.932144 718.8894 202.77814 732.5514] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/38713.38742) - >> - /F 4 - /StructParent 406 - /Contents (https://doi.org/10.1145/38713.38742) ->> -endobj - -5131 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 698.42737 91.28214 712.0894] - /Border [0 0 0] - /Dest 4626 0 R - /F 4 - /StructParent 407 - /Contents ([38]) ->> -endobj - -5132 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 664.3034 91.28214 677.9654] - /Border [0 0 0] - /Dest 4626 0 R - /F 4 - /StructParent 408 - /Contents ([39]) ->> -endobj - -5133 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [233.11613 650.6414 470.02313 664.3034] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://martinfowler.com/articles/injection.html) - >> - /F 4 - /StructParent 409 - /Contents (https://martinfowler.com/articles/injection.html) ->> -endobj - -5134 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 630.1794 91.28214 643.84143] - /Border [0 0 0] - /Dest 4627 0 R - /F 4 - /StructParent 410 - /Contents ([40]) ->> -endobj - -5135 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [264.81815 589.1934 388.24915 602.8554] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1007/3-540-57182-5\\_8) - >> - /F 4 - /StructParent 411 - /Contents (https://doi.org/10.1007/3-540-57182-5\\_8) ->> -endobj - -5136 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 568.73145 91.28214 582.39343] - /Border [0 0 0] - /Dest 4628 0 R - /F 4 - /StructParent 412 - /Contents ([41]) ->> -endobj - -5137 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 520.94543 91.28214 534.6074] - /Border [0 0 0] - /Dest 4629 0 R - /F 4 - /StructParent 413 - /Contents ([42]) ->> -endobj - -5138 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [387.86646 520.94543 524.4094 534.6074] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://webpack.js.org/api/hot-module-replacement/) - >> - /F 4 - /StructParent 414 - /Contents (https://webpack.js.org/api/hot-module-replacement/) ->> -endobj - -5139 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [103.932144 507.2834 230.02515 520.94543] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://webpack.js.org/api/hot-module-replacement/) - >> - /F 4 - /StructParent 415 - /Contents (https://webpack.js.org/api/hot-module-replacement/) ->> -endobj - -5140 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 486.8214 91.28214 500.4834] - /Border [0 0 0] - /Dest 4630 0 R - /F 4 - /StructParent 416 - /Contents ([43]) ->> -endobj - -5141 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [292.59314 486.8214 447.93515 500.4834] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://vite.dev/guide/api-hmr) - >> - /F 4 - /StructParent 417 - /Contents (https://vite.dev/guide/api-hmr) ->> -endobj - -5142 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 466.3594 91.28214 480.0214] - /Border [0 0 0] - /Dest 4631 0 R - /F 4 - /StructParent 418 - /Contents ([44]) ->> -endobj - -5143 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 445.8974 91.28214 459.5594] - /Border [0 0 0] - /Dest 4632 0 R - /F 4 - /StructParent 419 - /Contents ([45]) ->> -endobj - -5144 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [125.31614 418.5734 207.66214 432.2354] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1109/32.60317) - >> - /F 4 - /StructParent 420 - /Contents (https://doi.org/10.1109/32.60317) ->> -endobj - -5145 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 398.1114 91.28214 411.7734] - /Border [0 0 0] - /Dest 4632 0 R - /F 4 - /StructParent 421 - /Contents ([46]) ->> -endobj - -5146 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [388.97513 370.7874 498.59015 384.4494] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1109/tse.2007.70733) - >> - /F 4 - /StructParent 422 - /Contents (https://doi.org/10.1109/tse.2007.70733) ->> -endobj - -5147 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 350.3254 91.28214 363.9874] - /Border [0 0 0] - /Dest 4633 0 R - /F 4 - /StructParent 423 - /Contents ([47]) ->> -endobj - -5148 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [103.932144 309.33942 242.18015 323.0014] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1007/978-3-540-76778-7_1) - >> - /F 4 - /StructParent 424 - /Contents (https://doi.org/10.1007/978-3-540-76778-7_1) ->> -endobj - -5149 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 288.87738 91.28214 302.53943] - /Border [0 0 0] - /Dest 4634 0 R - /F 4 - /StructParent 425 - /Contents ([48]) ->> -endobj - -5150 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 254.75342 91.28214 268.4154] - /Border [0 0 0] - /Dest 4634 0 R - /F 4 - /StructParent 426 - /Contents ([49]) ->> -endobj - -5151 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 220.6294 91.28214 234.29138] - /Border [0 0 0] - /Dest 4634 0 R - /F 4 - /StructParent 427 - /Contents ([50]) ->> -endobj - -5152 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 186.50537 91.28214 200.16742] - /Border [0 0 0] - /Dest 4635 0 R - /F 4 - /StructParent 428 - /Contents ([51]) ->> -endobj - -5153 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [266.66614 159.1814 376.51215 172.84338] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/168619.168635) - >> - /F 4 - /StructParent 429 - /Contents (https://doi.org/10.1145/168619.168635) ->> -endobj - -5154 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 138.71942 91.28214 152.38141] - /Border [0 0 0] - /Dest 4636 0 R - /F 4 - /StructParent 430 - /Contents ([52]) ->> -endobj - -5155 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4360 0 R - /f1 4366 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 431 - /Tabs /S - /Parent 1 0 R - /Contents 5156 0 R - /Annots [5129 0 R 5130 0 R 5131 0 R 5132 0 R 5133 0 R 5134 0 R 5135 0 R 5136 0 R 5137 0 R 5138 0 R 5139 0 R 5140 0 R 5141 0 R 5142 0 R 5143 0 R 5144 0 R 5145 0 R 5146 0 R 5147 0 R 5148 0 R 5149 0 R 5150 0 R 5151 0 R 5152 0 R 5153 0 R 5154 0 R] ->> -endobj - -5156 0 obj -<< - /Length 5106 - /Filter /FlateDecode ->> -stream -x=r7q[!7P4uͱRF4ikbr3?QuՖbȮ‘Hqzqpwui<9jӋN/?}_79ݫ?6>Κϟx_Ckyǯ{$hgZ[&G7oq>zzyě;\͕??}{/V79zqyF XGvsjIZnO=~0G|Xx,( ͗~Jmkïux3­a Ȫ_9|"l/Z -Y"JIVf -aH|ya>D% *\9FVn s\Vk=B0.Sikj5&Wgi6M]4 㠛GJ3.F()uo&ٽ=+ 'n)P0 B|drDnL<5. :YJGAD"uprlqPvIyڇ!qJy@ʄ=y]gZMmx(nyRK A"`mޓ#|f~N|=4fzy|>qE"#\2X4~|ǫo]i#U\'f{)<.W/Nh^`nlL\\U?DG؜ )^g[z;ӢxH#γyhM}z'K/0>š={%J/Y+5+̒ёiShb-h$:gʢVKU_7.uݭ﹵p M z~GeTL4OA{5m@΍ȐJG{qQ񘡈%ǸJ"4߿ <aVGR11Nt 7ӮP$s(fQ95M;dz^ib&Zv8"^M1Ljp# -u^y ' &VtWLAnDh>*?\QtNZor} WI@|R ם-p^VZD0)Bbr\kF|ON:xv{a$9_&N LdB -2: ǁs AU -0~.~1$TzuBBX c(cFڀʼn}-Zf |dyje‡,Y)54S@Ʂ%;q]Pp,`Y1٨jLTz}_6Fa$%LX|z++#bRN Wbl_C[C|`7$ yQ6D;ԯQ(' yLCm:JٍYHǤuC#4( ڙ ̔)w6- 4z4 ftLCi#"@L7W(qNL'#6 uji}e5F(L+ M94-ծAuUTՃ%V3/0.%ejFĜ#Ac-,=dnh fgL+zR]AΏLN( 0γK}ǀ~V?H -Эd^*o.ΪBn1se)jT Z3h-8c5飡t;; "SEx.ikՋ="FkBeʇ?1_H4(fTκ@< yCc 3P'.V'}zӵeB׭{m4]0'5l#fq~:,!Q)8S/ƳIupШ*͵oue%zh@=8t1[yh)[L2"?M~F2u&)M@OFNxyHz@9I\-ͶL8Vm4-q ֠ hE癒F%q:'ט䄄 n˭Br.P +h8 <b5RJP\OﶳJui0K]%XYdĵ.i%ܕHނ|";OlĉDK摉:rh}#JހFDŽ -ٸ%"-> -~՘׮l;7/h1KOQl+6TˬZ.Q] GEbـu;8]"Hx чI~~Ia"i2w} 9cT7(Axǥs_O6}cb7a?|d݅ŗqivXô-Tր#Rg?C'&MEeՄT  NQ<&w}K$X|hXt?[ ɔ(6djG 7⦘`:Eu-l%U‘+("[Z~Ҏ4.(+'s (5I -tX!qiN3zUX*uB+BKhIh/bN'DwyUh3L_PFm:MX.G_&$퓌 ia]ND' OTud -J $?fVJZ;*˧r9(:u{ 4ߢ#4b4u)a]yr[Pc01edZxז8d$PYUshNX*%,docb4$Ѯ čeĎi7' :P}+A+Gۅ`J-vͽ<2N7MD99m(72°u%Wjez>rz\Cf%whr:vUˁcn(yOY Y2CF1DɁ!JnqkT}RXeXnոg<^"qĘm"g@? a)B1(\ #&PfבKPE|f.8%.`Y5O򍋼$P.Ms`'7,^򖵭\pK%O݅,yÅ?*}'= LM\ԡ-aY_dHr@& -ϙq362XLjiٰr"f RN.S%&jײn厽Lr2Q9L9l[eF-h -T4FbY Q¬)ɬFXk~<g!=^<CQ9^|(.~iW\? 9Ky{N_q̘yUBD"PeڤL\3[[LH=vMvId2>D+K}@,1&Fbd?P2ax,"b`!9O+  зZpϼ|vt`3ZHX$,<87ei\0sa/AoM ЍB=ŏ)̢Vy޴ksz/TצU> -endobj - -5158 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [392.97916 732.5514 510.96515 746.2134] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1002/SPE.4380210404) - >> - /F 4 - /StructParent 433 - /Contents (https://doi.org/10.1002/SPE.4380210404) ->> -endobj - -5159 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 712.0894 91.28214 725.7514] - /Border [0 0 0] - /Dest 4638 0 R - /F 4 - /StructParent 434 - /Contents ([54]) ->> -endobj - -5160 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [322.68915 684.7654 421.53516 698.42737] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/75277.75283) - >> - /F 4 - /StructParent 435 - /Contents (https://doi.org/10.1145/75277.75283) ->> -endobj - -5161 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 664.3034 91.28214 677.9654] - /Border [0 0 0] - /Dest 4639 0 R - /F 4 - /StructParent 436 - /Contents ([55]) ->> -endobj - -5162 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 630.1794 91.28214 643.84143] - /Border [0 0 0] - /Dest 4640 0 R - /F 4 - /StructParent 437 - /Contents ([56]) ->> -endobj - -5163 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [322.68915 602.8554 443.53516 616.5174] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/1190216.1190229) - >> - /F 4 - /StructParent 438 - /Contents (https://doi.org/10.1145/1190216.1190229) ->> -endobj - -5164 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 582.39343 91.28214 596.0554] - /Border [0 0 0] - /Dest 4641 0 R - /F 4 - /StructParent 439 - /Contents ([57]) ->> -endobj - -5165 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [386.45844 582.39343 526.60944 596.0554] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://www.typescriptlang.org/docs/handbook/declaration-merging.html) - >> - /F 4 - /StructParent 440 - /Contents (https://www.typescriptlang.org/docs/handbook/declaration-merging.html) ->> -endobj - -5166 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [103.932144 568.73145 332.56714 582.39343] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://www.typescriptlang.org/docs/handbook/declaration-merging.html) - >> - /F 4 - /StructParent 441 - /Contents (https://www.typescriptlang.org/docs/handbook/declaration-merging.html) ->> -endobj - -5167 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 548.2694 91.28214 561.9314] - /Border [0 0 0] - /Dest 4642 0 R - /F 4 - /StructParent 442 - /Contents ([58]) ->> -endobj - -5168 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [204.53815 520.94543 325.38416 534.6074] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/1869631.1869638) - >> - /F 4 - /StructParent 443 - /Contents (https://doi.org/10.1145/1869631.1869638) ->> -endobj - -5169 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 500.4834 91.28214 514.1454] - /Border [0 0 0] - /Dest 4643 0 R - /F 4 - /StructParent 444 - /Contents ([59]) ->> -endobj - -5170 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [401.79245 500.4834 524.4094 514.1454] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://docs.python.org/3/howto/descriptor.html) - >> - /F 4 - /StructParent 445 - /Contents (https://docs.python.org/3/howto/descriptor.html) ->> -endobj - -5171 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [103.932144 486.8214 225.16315 500.4834] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://docs.python.org/3/howto/descriptor.html) - >> - /F 4 - /StructParent 446 - /Contents (https://docs.python.org/3/howto/descriptor.html) ->> -endobj - -5172 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 466.3594 91.28214 480.0214] - /Border [0 0 0] - /Dest 4644 0 R - /F 4 - /StructParent 447 - /Contents ([60]) ->> -endobj - -5173 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [169.31615 439.0354 268.16214 452.6974] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/38765.38821) - >> - /F 4 - /StructParent 448 - /Contents (https://doi.org/10.1145/38765.38821) ->> -endobj - -5174 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 418.5734 91.28214 432.2354] - /Border [0 0 0] - /Dest 4644 0 R - /F 4 - /StructParent 449 - /Contents ([61]) ->> -endobj - -5175 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [249.25314 377.5874 370.09915 391.2494] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/1028976.1029004) - >> - /F 4 - /StructParent 450 - /Contents (https://doi.org/10.1145/1028976.1029004) ->> -endobj - -5176 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 357.1254 91.28214 370.7874] - /Border [0 0 0] - /Dest 4645 0 R - /F 4 - /StructParent 451 - /Contents ([62]) ->> -endobj - -5177 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [483.31345 343.4634 524.4094 357.1254] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1007/s12243-008-0072-z) - >> - /F 4 - /StructParent 452 - /Contents (https://doi.org/10.1007/s12243-008-0072-z) ->> -endobj - -5178 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [103.932144 329.8014 191.08514 343.4634] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1007/s12243-008-0072-z) - >> - /F 4 - /StructParent 453 - /Contents (https://doi.org/10.1007/s12243-008-0072-z) ->> -endobj - -5179 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 309.33942 91.28214 323.0014] - /Border [0 0 0] - /Dest 4646 0 R - /F 4 - /StructParent 454 - /Contents ([63]) ->> -endobj - -5180 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [378.28314 295.67743 499.12915 309.33942] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/2489837.2489840) - >> - /F 4 - /StructParent 455 - /Contents (https://doi.org/10.1145/2489837.2489840) ->> -endobj - -5181 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 275.2154 91.28214 288.87738] - /Border [0 0 0] - /Dest 4647 0 R - /F 4 - /StructParent 456 - /Contents ([64]) ->> -endobj - -5182 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [196.81615 247.89142 312.88815 261.5534] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1016/j.jss.2016.04.008) - >> - /F 4 - /StructParent 457 - /Contents (https://doi.org/10.1016/j.jss.2016.04.008) ->> -endobj - -5183 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 227.42938 91.28214 241.09143] - /Border [0 0 0] - /Dest 4648 0 R - /F 4 - /StructParent 458 - /Contents ([65]) ->> -endobj - -5184 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [147.31615 186.44342 268.16214 200.10541] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/3426428.3426922) - >> - /F 4 - /StructParent 459 - /Contents (https://doi.org/10.1145/3426428.3426922) ->> -endobj - -5185 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 165.98138 91.28214 179.64337] - /Border [0 0 0] - /Dest 4649 0 R - /F 4 - /StructParent 460 - /Contents ([66]) ->> -endobj - -5186 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [260.94614 138.65741 377.01813 152.3194] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1016/j.jss.2012.02.018) - >> - /F 4 - /StructParent 461 - /Contents (https://doi.org/10.1016/j.jss.2012.02.018) ->> -endobj - -5187 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 118.19537 91.28214 131.85742] - /Border [0 0 0] - /Dest 4650 0 R - /F 4 - /StructParent 462 - /Contents ([67]) ->> -endobj - -5188 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [226.07614 90.8714 324.92215 104.53339] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/73560.73566) - >> - /F 4 - /StructParent 463 - /Contents (https://doi.org/10.1145/73560.73566) ->> -endobj - -5189 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4360 0 R - /f1 4366 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 464 - /Tabs /S - /Parent 1 0 R - /Contents 5190 0 R - /Annots [5157 0 R 5158 0 R 5159 0 R 5160 0 R 5161 0 R 5162 0 R 5163 0 R 5164 0 R 5165 0 R 5166 0 R 5167 0 R 5168 0 R 5169 0 R 5170 0 R 5171 0 R 5172 0 R 5173 0 R 5174 0 R 5175 0 R 5176 0 R 5177 0 R 5178 0 R 5179 0 R 5180 0 R 5181 0 R 5182 0 R 5183 0 R 5184 0 R 5185 0 R 5186 0 R 5187 0 R 5188 0 R] ->> -endobj - -5190 0 obj -<< - /Length 5269 - /Filter /FlateDecode ->> -stream -x]Y7r~_Qj.奰U\͓ʳwTuUHU$72G7 -@&/?df]<ٿwf=xpu7ys~>W?>ygvO=={ӳ~j>w'3g]=ͯgoxg'g9x;!wg?|#C ?Ξ_{#WR ]y7}>~u4Nb4&|*%m4xwISWjjHq{uWNI wdv -{[?KSb׉_ EeP)6=(*Wx+_C;do8h:쟗+E˷;bhX}3Kty7vD:6vP5TMx[Pޞ.#:nd|zɭ3d=e4+&>Cd57q%K+ %߉?vwש/8z+_uƤ{m,Xf2pJepZIucA1l*(S-X]Jc i#Ta>3%u gNrfM,,[-z'J =>G JXNk>+ [gW>K2HY$1(f -n@%p1`Fa dH Pˌ]0}v iOWU?!9gR NFA7 )~l­d| ,d:WfrM~yUx*֟$vd^+%pѱPX:_mr݆i)G9cE8}E6 @EyA]9b94^ph6g:Q Qi'0mC -b<XZ9 -d-ioPgx 8;{pg6Τ w68h:g^({,{!{h{L2{ZYsKOW姨$̬.&m g8mо/o!;qbB4W28&j'm+a>op`qfܽá| "gE©9,:W  tE -8P2m&5)vYte3;߉-lP#@h*/M&"5M:8 :znxI:Sjhםq1cSV,9 AݬLz۾oUz} ^*~|.x1W- $3uݲB&0uԒno<>N}Z[|]MIH -ヺ-WRE98E篙p]=ݬy RS: +)3泻2qnçY_.`:mZ,\*\K`KZ(#V`f{ڥTIEzfz'-kb1g}OcIiuQ_#J"{t$9s 93W-?(@r͌rlcQE@S>o(BS4)qMrEx3|R~:{k;/>c; =oh:5`H܏A %S&8pWGZ2AJS;:f5rKk牴NYD޷ͭgNptӝZ;zuP'3(Z$z*R2uLX9%l"Lo|֣׃Nl=N20ͅtJh,nẒ >TqpR}9Ո(7C;.{TS7KGzv 7w3 o|FT B- -nNBջZj36r9s@|D>7e;+ -4mׇ&7L[kM.o|({cC>G<1*udLsΟε#M>@np?ZҰTSɨl$UƖ2#XʉKx2j[EW僌B\\7߯<?{8W\Y zI}Z=fpY:n0-=SM=;2F$qRZ<%ۦ$cFmc@FH+äeCG[AC!eM&-r& ğS5m_ݧ$~ZJy MFj)"h|o%j% qi$G0k󵼊Of)Mj#wuGN(Ԙ2Bv8 _Tl gںapɓ뭺s}l{nJǾ8U bH 4ٵQh~jak [_I)G93[Ⱛ`o&\gO\/~O,˼[?ypHS-h`ɵ~Vqw=+n|7,p< DZS)A|0kkB2 czYڐy ]I^Lojn2@4+t:8#:}(Fb2XjҚYd,(LXsi^hڭir}'Ixۈ{Jvτgvv Y;Ҭk윜7?vz"IaҀm@<li9zĐo@GOٝڠ0{ƅj6L!r̶wk ^ \ݣQjͤ^Yg p^D/^PTP8x]slIr81ަQZu 'kK =dUI3 66'U7a/B\74X .Q*mOgƸ"PV -.0gseo͵=;an:LL6I"8{fuAQe2WŪ\{Ŝ+a:N:&efG!T'߻"-W>~qс^R6GaE3/0kro]7ysœ_>ÇۛWڿpM&LuF0/'APu[m -endstream -endobj - -5191 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 746.2134 91.28214 759.87537] - /Border [0 0 0] - /Dest 4651 0 R - /F 4 - /StructParent 465 - /Contents ([68]) ->> -endobj - -5192 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [125.31614 732.5514 207.66214 746.2134] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1109/2.161279) - >> - /F 4 - /StructParent 466 - /Contents (https://doi.org/10.1109/2.161279) ->> -endobj - -5193 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 712.0894 91.28214 725.7514] - /Border [0 0 0] - /Dest 4652 0 R - /F 4 - /StructParent 467 - /Contents ([69]) ->> -endobj - -5194 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [266.44614 698.42737 377.49115 712.0894] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1006/inco.1994.1055) - >> - /F 4 - /StructParent 468 - /Contents (https://doi.org/10.1006/inco.1994.1055) ->> -endobj - -5195 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 677.9654 91.28214 691.6274] - /Border [0 0 0] - /Dest 4653 0 R - /F 4 - /StructParent 469 - /Contents ([70]) ->> -endobj - -5196 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [152.81615 650.6414 232.41214 664.3034] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/3428194) - >> - /F 4 - /StructParent 470 - /Contents (https://doi.org/10.1145/3428194) ->> -endobj - -5197 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 630.1794 91.28214 643.84143] - /Border [0 0 0] - /Dest 4653 0 R - /F 4 - /StructParent 471 - /Contents ([71]) ->> -endobj - -5198 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [333.17215 602.8554 412.76813 616.5174] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/3527320) - >> - /F 4 - /StructParent 472 - /Contents (https://doi.org/10.1145/3527320) ->> -endobj - -5199 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 582.39343 91.28214 596.0554] - /Border [0 0 0] - /Dest 4654 0 R - /F 4 - /StructParent 473 - /Contents ([72]) ->> -endobj - -5200 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [129.48514 568.73145 238.49515 582.39343] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://effect.website/) - >> - /F 4 - /StructParent 474 - /Contents (https://effect.website/) ->> -endobj - -5201 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 548.2694 91.28214 561.9314] - /Border [0 0 0] - /Dest 4655 0 R - /F 4 - /StructParent 475 - /Contents ([73]) ->> -endobj - -5202 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [215.53815 507.2834 344.51315 520.94543] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1016/j.entcs.2018.11.009) - >> - /F 4 - /StructParent 476 - /Contents (https://doi.org/10.1016/j.entcs.2018.11.009) ->> -endobj - -5203 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 486.8214 91.28214 500.4834] - /Border [0 0 0] - /Dest 4656 0 R - /F 4 - /StructParent 477 - /Contents ([74]) ->> -endobj - -5204 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [103.932144 459.4974 183.52814 473.1594] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/3341714) - >> - /F 4 - /StructParent 478 - /Contents (https://doi.org/10.1145/3341714) ->> -endobj - -5205 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 439.0354 91.28214 452.6974] - /Border [0 0 0] - /Dest 4657 0 R - /F 4 - /StructParent 479 - /Contents ([75]) ->> -endobj - -5206 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [103.932144 411.7114 183.52814 425.3734] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/3563319) - >> - /F 4 - /StructParent 480 - /Contents (https://doi.org/10.1145/3563319) ->> -endobj - -5207 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 391.2494 91.28214 404.9114] - /Border [0 0 0] - /Dest 4657 0 R - /F 4 - /StructParent 481 - /Contents ([76]) ->> -endobj - -5208 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [469.68445 377.5874 526.60944 391.2494] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/https://doi.org/10.1016/j.tcs.2023.114063) - >> - /F 4 - /StructParent 482 - /Contents (https://doi.org/https://doi.org/10.1016/j.tcs.2023.114063) ->> -endobj - -5209 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [103.932144 363.9254 245.68915 377.5874] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/https://doi.org/10.1016/j.tcs.2023.114063) - >> - /F 4 - /StructParent 483 - /Contents (https://doi.org/https://doi.org/10.1016/j.tcs.2023.114063) ->> -endobj - -5210 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 343.4634 91.28214 357.1254] - /Border [0 0 0] - /Dest 4658 0 R - /F 4 - /StructParent 484 - /Contents ([77]) ->> -endobj - -5211 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [152.81615 316.1394 232.41214 329.8014] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/3689750) - >> - /F 4 - /StructParent 485 - /Contents (https://doi.org/10.1145/3689750) ->> -endobj - -5212 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 295.67743 91.28214 309.33942] - /Border [0 0 0] - /Dest 4659 0 R - /F 4 - /StructParent 486 - /Contents ([78]) ->> -endobj - -5213 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [373.59714 282.01538 481.69415 295.67743] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.5381/jot.2008.7.3.a4) - >> - /F 4 - /StructParent 487 - /Contents (https://doi.org/10.5381/jot.2008.7.3.a4) ->> -endobj - -5214 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 261.5534 91.28214 275.2154] - /Border [0 0 0] - /Dest 4659 0 R - /F 4 - /StructParent 488 - /Contents ([79]) ->> -endobj - -5215 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [285.91614 234.22937 406.76215 247.89142] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/1146841.1146842) - >> - /F 4 - /StructParent 489 - /Contents (https://doi.org/10.1145/1146841.1146842) ->> -endobj - -5216 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 213.7674 91.28214 227.42938] - /Border [0 0 0] - /Dest 4660 0 R - /F 4 - /StructParent 490 - /Contents ([80]) ->> -endobj - -5217 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [152.81615 186.44342 268.88815 200.10541] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1016/j.jss.2012.03.024) - >> - /F 4 - /StructParent 491 - /Contents (https://doi.org/10.1016/j.jss.2012.03.024) ->> -endobj - -5218 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 165.98138 91.28214 179.64337] - /Border [0 0 0] - /Dest 4661 0 R - /F 4 - /StructParent 492 - /Contents ([81]) ->> -endobj - -5219 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [264.81815 138.65741 363.33414 152.3194] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1007/BFb0053381) - >> - /F 4 - /StructParent 493 - /Contents (https://doi.org/10.1007/BFb0053381) ->> -endobj - -5220 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 118.19537 91.28214 131.85742] - /Border [0 0 0] - /Dest 4661 0 R - /F 4 - /StructParent 494 - /Contents ([82]) ->> -endobj - -5221 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4360 0 R - /f1 4366 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 495 - /Tabs /S - /Parent 1 0 R - /Contents 5222 0 R - /Annots [5191 0 R 5192 0 R 5193 0 R 5194 0 R 5195 0 R 5196 0 R 5197 0 R 5198 0 R 5199 0 R 5200 0 R 5201 0 R 5202 0 R 5203 0 R 5204 0 R 5205 0 R 5206 0 R 5207 0 R 5208 0 R 5209 0 R 5210 0 R 5211 0 R 5212 0 R 5213 0 R 5214 0 R 5215 0 R 5216 0 R 5217 0 R 5218 0 R 5219 0 R 5220 0 R] ->> -endobj - -5222 0 obj -<< - /Length 5118 - /Filter /FlateDecode ->> -stream -x]Ys7~( -Y:3#HhbMy9툝Quэw_8z]ݍ~hGSJLvF:…ͯGg7yswvGgiXw~]z(/ۣWGoqjB 8\zӝZF$Fww~1563do7cǻRBoR$?Oa#selѦ@946ʧƦq3 c@ﻻe{+/wdΉV,]((v77X7N+E`kMqʶ̒6\fz^vBrصiq`nlnmcW0p` E Im0" |3}4x,_~gWN[lt8FQqjּmTàN6?2d~e*i K(3$8m(%B6 E0m -x;lx^K\=T2, BGSY4Dž tXǠ_?' c]Q+H]JBVL0~s\Ѐyx?/;s4S,YtN"ŀhořUJ䗐;eD**hBY l+xAX*(p Q3>YP=hOJq|,S-îLD8GEYRVU~5: /ict.1 <˂ gҝ&񀢥_QGE -P~S6B4i5p@ &5L!df(uY*Y gQ.amV1O!Fj!fY=:~s.@{@lgڟUak,F XL ;sgV٪̓g2ӄ6i"㗛N.Lm)eZ3%s4ENc:p-;7+gN[@ыc,·j#sH ukؿYsLb4S+ $cXX.>L|V Tqda4U,pj2 O2mS)Q^S^b#_-p5js(~Ȣ -rxs/,7=w҄|"9d"" 8f<C,) A'e֮82OԷ''ԟvH=Eo9?U"*;bq<`Iy'<>ȳJ4\40P. ?!"ZK1O!3HjY8kZͤ{γ["SVԏB Q3DX^ɀ%`dmhO٘0e5& )"Q.5Ӕ]>2\5f,Yq;{Nqy?R6#:址q vGiU&2\Tt3NVz8VrNG ۣ -'13^`_N$/=g\gȰ:^gy7Yͼ/nPTh Lii69QօͽOZNǛ1zL9iVf^͸5,(RZCq-'t!nV{PyԹ>F)dHyˍз)(ӏ|wP Po!SZC 'DЖ;Vsx 2]y1KɪR0ELt<=(] -tTHU$ Z.'BHIm\JmuUQmϪT[Y6D"dO-tl:'3AoK%:%`gG{_G :j_@3`}F-O>jzEGrL6܈}B40r!{uRS(aNv>x c({᜴5l]/,7@>,7,^Xnn[bnTvܐڨܰ[ܰ333QN"T\ K͉9!"C `(Y4 -\JN^vX\A)j. -+g=!t% ji$"-)=6Z S@嚴2`4@@` oQCHnQc QHG)N慝-Ɇx -CxM6DѼk TYSÏM7nzS/8#;Z1Z-4|EAqn ,$'*Bؚ[2IפuG \CÇRUH:W@AGuJ2C?X[ 2@1nmk# b(8pg1_z> );$kbԚ⪁wK/R].2J] K{'s^ 0X1VYZ"Th0P>̜TL6;g(Sd>p%VX}& ;W},&(1֒IGhR# -՘SjGR0[8'FuRMg:$wU-Q5uH۲oWzeqRZpEnahjaVj:ڥ&ҮrTvm -k $\QfZW3Gq`4hl2/L'5Qᶾ+R1Pt9=8gGV JtZS}:;Efet9cIŃB|U2M޾]iO4qmzKr,1*4A2CB9Ʋvnu1-ז8΍Ͷ  -' ptF@'SAH sr`0v; AlNFzyɢ]7"Ыe(Udrg| [SC4 ,cgF 3>$ ȠΏ_L!Ix#5P"OtBՉ(͝쏎r;:6a9pѸs,N - 8Әbt PT5+i\bɭ"T\}_*1 ڻJ) p_ܿ3/:4ʋlB U1! :8*"n̠+,ACS# ʙUmŶo;cx(A.8& KˈvT˲FK]%CDy -[%ք9؊m7(²O -ʧ(x%t֦Z>N%I!DQV1XG'MUnaSqm 91-슱LpmbUra6p|71\y&SG:,Z#09%Ti'@ ->ޥ<fFp3-ci2i Yd -_TZpq*-@`~Pr$jV'ܪR㺌 -vQ5U}q:KCΫ Lx( XM$NO6EL+kr0z8} 2a56C;`=4,q9nG˶~<lLowq -1:"m9D(SY -C9$̦ -^H?`0 }km#3BcJd+WuB[;I.fw ä^ A|IǘRu8 .Ju0lN* yJ^2-o{dHXdO|/ AY5zQ{5]Q:Y؀ٟVFo,-F4]Z- CR-[hIh%*V.tߢЁ]E_QŞX\Luf_u;Q ~,!; 2;[`/PR -glyfԌ3rΆ̀RZF|Fh~ψr*ƷjUDܷVUTW,= u hU~ -WOfݏg?n߯;}_>]m?|V c;ňcJ]CHj -endstream -endobj - -5223 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [125.31614 732.5514 248.90114 746.2134] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1007/3-540-45337-7_18) - >> - /F 4 - /StructParent 496 - /Contents (https://doi.org/10.1007/3-540-45337-7_18) ->> -endobj - -5224 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 712.0894 91.28214 725.7514] - /Border [0 0 0] - /Dest 4662 0 R - /F 4 - /StructParent 497 - /Contents ([83]) ->> -endobj - -5225 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [382.00113 684.7654 491.84714 698.42737] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/508386.508404) - >> - /F 4 - /StructParent 498 - /Contents (https://doi.org/10.1145/508386.508404) ->> -endobj - -5226 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 664.3034 91.28214 677.9654] - /Border [0 0 0] - /Dest 4662 0 R - /F 4 - /StructParent 499 - /Contents ([84]) ->> -endobj - -5227 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [401.52615 636.9794 511.37213 650.6414] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/976270.976273) - >> - /F 4 - /StructParent 500 - /Contents (https://doi.org/10.1145/976270.976273) ->> -endobj - -5228 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 616.5174 91.28214 630.1794] - /Border [0 0 0] - /Dest 4663 0 R - /F 4 - /StructParent 501 - /Contents ([85]) ->> -endobj - -5229 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [266.72113 589.1934 376.56714 602.8554] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/378795.378798) - >> - /F 4 - /StructParent 502 - /Contents (https://doi.org/10.1145/378795.378798) ->> -endobj - -5230 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 568.73145 91.28214 582.39343] - /Border [0 0 0] - /Dest 4664 0 R - /F 4 - /StructParent 503 - /Contents ([86]) ->> -endobj - -5231 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [147.31615 527.74536 268.16214 541.4074] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/1040305.1040321) - >> - /F 4 - /StructParent 504 - /Contents (https://doi.org/10.1145/1040305.1040321) ->> -endobj - -5232 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 507.2834 91.28214 520.94543] - /Border [0 0 0] - /Dest 4665 0 R - /F 4 - /StructParent 505 - /Contents ([87]) ->> -endobj - -5233 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [125.31614 479.9594 204.91214 493.6214] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/2629460) - >> - /F 4 - /StructParent 506 - /Contents (https://doi.org/10.1145/2629460) ->> -endobj - -5234 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 459.4974 91.28214 473.1594] - /Border [0 0 0] - /Dest 4666 0 R - /F 4 - /StructParent 507 - /Contents ([88]) ->> -endobj - -5235 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [378.18414 432.1734 522.3831 445.8354] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1109/SANER.2017.7884621) - >> - /F 4 - /StructParent 508 - /Contents (https://doi.org/10.1109/SANER.2017.7884621) ->> -endobj - -5236 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 411.7114 91.28214 425.3734] - /Border [0 0 0] - /Dest 4667 0 R - /F 4 - /StructParent 509 - /Contents ([89]) ->> -endobj - -5237 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 377.5874 91.28214 391.2494] - /Border [0 0 0] - /Dest 4668 0 R - /F 4 - /StructParent 510 - /Contents ([90]) ->> -endobj - -5238 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 343.4634 91.28214 357.1254] - /Border [0 0 0] - /Dest 4669 0 R - /F 4 - /StructParent 511 - /Contents ([91]) ->> -endobj - -5239 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 323.0014 91.28214 336.6634] - /Border [0 0 0] - /Dest 4670 0 R - /F 4 - /StructParent 512 - /Contents ([92]) ->> -endobj - -5240 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [444.26346 309.33942 523.85944 323.0014] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/3763067) - >> - /F 4 - /StructParent 513 - /Contents (https://doi.org/10.1145/3763067) ->> -endobj - -5241 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 288.87738 91.28214 302.53943] - /Border [0 0 0] - /Dest 4671 0 R - /F 4 - /StructParent 514 - /Contents ([93]) ->> -endobj - -5242 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [188.03815 261.5534 297.88416 275.2154] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/224964.224987) - >> - /F 4 - /StructParent 515 - /Contents (https://doi.org/10.1145/224964.224987) ->> -endobj - -5243 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 241.09143 91.28214 254.75342] - /Border [0 0 0] - /Dest 4671 0 R - /F 4 - /StructParent 516 - /Contents ([94]) ->> -endobj - -5244 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [376.65515 213.7674 497.50113 227.42938] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/1065944.1065952) - >> - /F 4 - /StructParent 517 - /Contents (https://doi.org/10.1145/1065944.1065952) ->> -endobj - -5245 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 193.30542 91.28214 206.9674] - /Border [0 0 0] - /Dest 4672 0 R - /F 4 - /StructParent 518 - /Contents ([95]) ->> -endobj - -5246 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [385.25714 165.98138 495.10315 179.64337] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/165123.165164) - >> - /F 4 - /StructParent 519 - /Contents (https://doi.org/10.1145/165123.165164) ->> -endobj - -5247 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 145.51941 91.28214 159.1814] - /Border [0 0 0] - /Dest 4673 0 R - /F 4 - /StructParent 520 - /Contents ([96]) ->> -endobj - -5248 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [428.20114 131.85742 518.6981 145.51941] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1147/rd.53.0183) - >> - /F 4 - /StructParent 521 - /Contents (https://doi.org/10.1147/rd.53.0183) ->> -endobj - -5249 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 111.395386 91.28214 125.05737] - /Border [0 0 0] - /Dest 4673 0 R - /F 4 - /StructParent 522 - /Contents ([97]) ->> -endobj - -5250 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [319.92813 97.7334 415.92514 111.395386] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1147/rd.176.0525) - >> - /F 4 - /StructParent 523 - /Contents (https://doi.org/10.1147/rd.176.0525) ->> -endobj - -5251 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4366 0 R - /f1 4360 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 524 - /Tabs /S - /Parent 1 0 R - /Contents 5252 0 R - /Annots [5223 0 R 5224 0 R 5225 0 R 5226 0 R 5227 0 R 5228 0 R 5229 0 R 5230 0 R 5231 0 R 5232 0 R 5233 0 R 5234 0 R 5235 0 R 5236 0 R 5237 0 R 5238 0 R 5239 0 R 5240 0 R 5241 0 R 5242 0 R 5243 0 R 5244 0 R 5245 0 R 5246 0 R 5247 0 R 5248 0 R 5249 0 R 5250 0 R] ->> -endobj - -5252 0 obj -<< - /Length 5388 - /Filter /FlateDecode ->> -stream -x]YsF~節C֎ ->44lX5[~hɣuiG TUVց( NԑuW_>9tOup}wt?_}=wmjׇgϞu/~yg?~K{?h߫XG;=f8paew nyF^\=~ b<7c;18x6Ss|7Wgxʼnrrwcs80c)=}H$X&ǎfx*`T򑈏DB:>-TM)Snɀc3tP;c'w&ʹ#3fV:3=+NJk+Tg[2awc1߯=^K"r[(rElAz}xafNǣ0&9/_u_"GٺQ]!Jxa$9_M2W׶?ʂ5R~:k`/ g{ks:G+m -}j\.VmȣpV8h<۠i8e'1~}{4Gب'@Y"<>G%Δi4TV|8n @dMx1|j'&gqmd*Ήь_Xz|-_? -nٴz/ ݂2"_ss2M{͏c$:[*h@Yb㬥e0@9&\ӄ4Ecy[޼E1e}5Ep+f"hlTLEU.}afqkl;#_F#*1aW[\ qc oZuؾpmr.b][3dl cgd宓cY:ޗJҁ|3|}^̹D+T _Zy(@\ʔ&8+#8?~aKXN(eLlW}3 Gģj?1&#VִV&KEkCl_Λ S}fu^Gs>51V y\V>o -P%܃ezӓPR}[/oW(ZNaDWR\b٫C7|u6޵ PH݀ (>1بMsHJ(f@'x/N1=ËBx"om"8ńkʈza1GAQ6A ΋P9 -]G IpQ٢6hZ!МHJwp( 1 KH -=kA%c<1J%l"uHI>CήUf\G7GB"9P_B!X@BȸHve\ek-Z (ָ=TkhA+2!'m;&Q6Ia~z5 -DN+H0"_]РD) -j*a-/t!U f漕̻F/MIRآ|%M4>xbk3<˪D(.Um5{Zbʋ_9N8[ㄇl{6O~S٪ ,214ךk׳]hInoѽ_]1h'&Jl-0bB\M`յAM1t "7^C9,RTC - P+̅?Z$zjy5c!o{ywD}}Z%J LqGYKb⬤+/-FTÆA -$TnkJ*e uR5fa q#1/$B#k)T9⌋;tc1r-&=MĆ~/62Z&|L[…pB*Tu$zpHBqoUfzБΊ 9dW S̓l`,4ՇLw *Cu61aUo-=r*QX8b~` 5O!DDdQn)]L@ JYdضũH3ݨZ߄SRz&ْ%7C8>i#݆[]2J[Vӄ[%L ʓjjʘ`v -'8l|'9O Oq].ۄ -8h>~rv؛ݙáa[Sɶ+VF2a3( o|Xf)+$4r"T,3-{vW};WF_<ƓW#Y[ƶ&J)T?0*/aFF#mO)r+(f^ -'r8i .QT~AE[$=xiwwLAQ;HaEeJʖg9qvZYYb.GvG1t[Ġ 8I$K͉⛸Z6GAYTnT[_'zֶ/R%>#EEK{ )ĴʹN{ :oTw"X:W;6VU ZHz0Z^j U -0ډ-sq i U,y+_nPpXQJ(ϪV[qW||քOYxjRE{€ba_ҿ; ` XG9S @i[FiЪޏ-Hs|Ԇ`Nx=hs^0 -d[CK0rn`Gi[`ϰڐG?Ԧ), ^ {~GjwIa,aVn2(|m#똏Jfr+4aUL%$FlG QiuhLh> .UA~Zue -C qi8|^Q,XMj PHnF4xtǬ!2y)aw$ħu- /K"V@jVD갩vɱU&{Qm4@ A,C.Q$XT%g| 󮤱dj= -DEma)l -ܖwbu[ 11L2?kꮸ^5)@4%g_8>^6RM4&HA}զ\9춥QeehLMʓ9tOL$s*oRAV~^ Jsd[hMZ3w`NyuELtd=j@ͮ0|TA}{Yj"Z/'Qb"\ݢ^2Q Α' 2=j/d-;/0pby1>3*y}RVNHVoyX RZ&o\fNcdwR&PT|}i\pw L" 7ET0?'؈Qw;%JWe-h#L#MHr}Ŗ]|F="Z;Û8ڕw/=ZpZȊGxY1O"=ՊB)mRoJC4#RJµzqJ]uD7daMWl"qtelL8nPpQ(MHG:qK(-$Dϒ'b4ٛfGt^R!Ҡ˻IvcT8OJ6CbRW?8E /u1`\ Q閵p_ #R[(g_6ySѓXYp5Hv4ᥗb>. 1K2bqcW$_+S3 $apǜivȀt@bXx6 #TPu-m2MK1 -S -uZc0 εL wX1 Sdd0Ռ<*xXIŵ$R+uX2w -^0}zV6vX+{aE-G^IZ[Eb]ݠBXGwSNq`@S-s,jTP@0 ; (`%nR!c(yDnzHV懐\&e3'&J+*t:.a^ ^ndojUH` ck&,秣T[O4XaMK? ?@Qr]E .7-cLFfdJg|>!o!$r/FX.B%F@wk 0>Paj*@aFQQ[Ď̽!e.TY#Ub3W<zYIzi;WpFd~cS:Cpy~b&4y*Iַؕ%Rj=%|L;{zHu.2L7 L3㷇R[cؔyI2ŀo4ԡ $!\wEδDM*R~|OŞ܇KR1!\522,&Fa, mv#7|>m0K%W[xDkT3' n0އxht([)f@j s?ۏnGW>|Gy?`;ňcJ.!\ -endstream -endobj - -5253 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 746.2134 91.28214 759.87537] - /Border [0 0 0] - /Dest 4674 0 R - /F 4 - /StructParent 525 - /Contents ([98]) ->> -endobj - -5254 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [103.932144 705.2274 224.77814 718.8894] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/1244381.1244404) - >> - /F 4 - /StructParent 526 - /Contents (https://doi.org/10.1145/1244381.1244404) ->> -endobj - -5255 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 684.7654 91.28214 698.42737] - /Border [0 0 0] - /Dest 4675 0 R - /F 4 - /StructParent 527 - /Contents ([99]) ->> -endobj - -5256 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 664.3034 96.78214 677.9654] - /Border [0 0 0] - /Dest 4676 0 R - /F 4 - /StructParent 528 - /Contents ([100]) ->> -endobj - -5257 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 643.84143 96.78214 657.5034] - /Border [0 0 0] - /Dest 4677 0 R - /F 4 - /StructParent 529 - /Contents ([101]) ->> -endobj - -5258 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [147.31615 616.5174 248.28514 630.1794] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1109/SCC.2007.74) - >> - /F 4 - /StructParent 530 - /Contents (https://doi.org/10.1109/SCC.2007.74) ->> -endobj - -5259 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 596.0554 96.78214 609.7174] - /Border [0 0 0] - /Dest 4677 0 R - /F 4 - /StructParent 531 - /Contents ([102]) ->> -endobj - -5260 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [391.93414 568.73145 523.03217 582.39343] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1109/ICSE.2004.1317483) - >> - /F 4 - /StructParent 532 - /Contents (https://doi.org/10.1109/ICSE.2004.1317483) ->> -endobj - -5261 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 548.2694 96.78214 561.9314] - /Border [0 0 0] - /Dest 4678 0 R - /F 4 - /StructParent 533 - /Contents ([103]) ->> -endobj - -5262 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [169.31615 520.94543 279.16214 534.6074] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/258948.258973) - >> - /F 4 - /StructParent 534 - /Contents (https://doi.org/10.1145/258948.258973) ->> -endobj - -5263 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 500.4834 96.78214 514.1454] - /Border [0 0 0] - /Dest 4679 0 R - /F 4 - /StructParent 535 - /Contents ([104]) ->> -endobj - -5264 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [406.43213 473.1594 508.02814 486.8214] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1007/11693024_20) - >> - /F 4 - /StructParent 536 - /Contents (https://doi.org/10.1007/11693024_20) ->> -endobj - -5265 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 452.6974 96.78214 466.3594] - /Border [0 0 0] - /Dest 4679 0 R - /F 4 - /StructParent 537 - /Contents ([105]) ->> -endobj - -5266 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [391.82645 439.0354 524.4094 452.6974] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://infoscience.epfl.ch/record/176887) - >> - /F 4 - /StructParent 538 - /Contents (https://infoscience.epfl.ch/record/176887) ->> -endobj - -5267 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [103.932144 425.3734 173.68314 439.0354] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://infoscience.epfl.ch/record/176887) - >> - /F 4 - /StructParent 539 - /Contents (https://infoscience.epfl.ch/record/176887) ->> -endobj - -5268 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [70.86614 404.9114 96.78214 418.5734] - /Border [0 0 0] - /Dest 4680 0 R - /F 4 - /StructParent 540 - /Contents ([106]) ->> -endobj - -5269 0 obj -<< - /Type /Annot - /Subtype /Link - /Rect [103.932144 377.5874 224.77814 391.2494] - /Border [0 0 0] - /A << - /Type /Action - /S /URI - /URI (https://doi.org/10.1145/2501654.2501666) - >> - /F 4 - /StructParent 541 - /Contents (https://doi.org/10.1145/2501654.2501666) ->> -endobj - -5270 0 obj -<< - /Type /Page - /Resources << - /ProcSet [/PDF /Text /ImageC /ImageB] - /ColorSpace << - /c0 4402 0 R - >> - /Font << - /f0 4360 0 R - /f1 4366 0 R - >> - >> - /MediaBox [0 0 595.2756 841.8898] - /StructParents 542 - /Tabs /S - /Parent 1 0 R - /Contents 5271 0 R - /Annots [5253 0 R 5254 0 R 5255 0 R 5256 0 R 5257 0 R 5258 0 R 5259 0 R 5260 0 R 5261 0 R 5262 0 R 5263 0 R 5264 0 R 5265 0 R 5266 0 R 5267 0 R 5268 0 R 5269 0 R] ->> -endobj - -5271 0 obj -<< - /Length 3295 - /Filter /FlateDecode ->> -stream -x\ms ~b=r&>;ut%O3V~IH:SKri}g_lОn ><ݾ:6Of|=׻/ӛ~b_ߝ}w:9yqruj;j?+І6Y)ږFKCdsa+qyzqjsEƚ+pqa˃3JQy_L9^ڜ~:>]0F13~(fv0ޢy̸!ǟ(e(Z7c놻TB3]_N(o - 1x_AίOfD@vݰfHw{)2ib8 g龩nXVnx,ec" d_SY Hi%n3+U(tdRr4G$~G#s4EXtG[+~U==U -U5"JN91I$ɤm[Dvv[a LY.MBS9l.Gن׍da(> -7NL_ǖf lEl-HZv$8 kB‘:#4SLTW{ Y55V2VT>}mW>?:+9}`8Ϲq7ΈLHI&CDm;)] -U%^ݓN?X(XgE:DH>ʈ QQ댰k"J %㼝 .b|[JҊ9e7ߊ%b^t\#H)Yn/촡D6ECmY^%7΅V8[p'8I"LO<=EShH"2B~s+g^2}V%Dk,RhH"{AAC05X. JhҊbP,R`Dv\1qgIǟ&IAF45IbHK֑Nq1GUFA"}_X]`Z3rdJ%Ȅkdo QkC]>Au?F`[3ki'1<>(S-iCXۧl-,,Ր -j@YYVNٸ"\VN)ss(CNCCZZ9mߺơ,>GaS7BPk'`7vQҔ {N~KJDr?_rۧӷa.8*GYI!\X^lRtBggGj& -ĝ}m\LUo~ -bD-/0D Gpڒ0c6[gU=%N>K3v)ָFyO#냅-aݢ,gun#Q`; yVqpeT#Ft]kvHanp ޓ?!Qϴ6=hOTmq)M3īDsliG( rѕќύ<$Mņ,e;[{m')D'KK jB0( G3%x;&*e(+ümF BR,p$ŷnr2,suB"D)M8$9$ZuHUTJNh(^}|0 # auqA(guCYk=/yBSG)ߘWw岅17w2oڃ\P0W^Bg=<5:,7U՜{aq,ғ@-F芨HĈ=1/e;JjZ?K/k<1Ĵt*+1*d̿4Djםxu(YFH,QtBh3U bH7d!xo^}X (# @2<#%Ձ0['3 !DhmjRΙѻG 3S5oݨi{"!JSAۣaNH+}h FL+A҈QNyY4JUʋEGI>;ƒ@ -cx߹`6A*&7͇e¯nn G6&tרuhJX -endstream -endobj - -5272 0 obj -<< - /Length 1412 - /Type /XObject - /Subtype /Form - /Filter /FlateDecode - /BBox [0 0 146.25 31.019531] - /Matrix [1 0 0 1 0 0] - /Resources << - /ExtGState << - /a0 << - /CA 1 - /ca 1 - >> - >> - /XObject << - /x6 5273 0 R - >> - >> ->> -stream -xmV;%5 } -]`r.1 -dOҗ&I!I79I߿/~uӧ~k}7ۖN.uOtX.\"[3Eg 泛(KHERXErȸ$}'a$g DFZ,أȹ +O@g@l2$,$(V }hs,zhlIw;7"jny{0ڬGr$[a$ay98*]k,A.j[9$H8ܨ﵅S72Ҹ+`2a OSRg(o-8"[/Mgpb7NZmt:|*EG/@`ESԜ`Pa gy]7*;L5"I8`P6VE8db(=Χ'V8չjDx'YP]q_%!ڞ-n?ljaPi_Z0+q/67f-5 U'XZ"J*,b!!}XZ?3JGyhY:GO} pyRt{7&FrH)0.!E䓵ݑqLFձ7sF[ g@T_Y{wlkt-pCb/w $R|,&"uDӐT"f285kR.ɫNq_Vvj.hDi? b] LH;?jӑs_.vm '_3Lq*0Xs{cM|i -UT:bL;u>zw`&FyHLoim??eX -endstream -endobj - -5273 0 obj -<< - /Length 2113 - /BBox [0 0 147 32] - /Filter /FlateDecode - /Resources 5274 0 R - /Subtype /Form - /Type /XObject ->> -stream -xmXIr,u2~t| G8Kjyh%X|,{ȕ߼\\/_־GW)w_uu,?҈}}^|`tΘ}Y(^.Z3Pq2lN{[q.Pnwkqlz\D h?1V¹6iSqwN_{!L|︨ת:/"\E Q5CE胺^$hc?l fvq_NX @C?kӈ a(ӑ@TV8lۂ\}kTuP H8(Yl-Y5B.)- -Z,9aĬYʝ$;o}9ΐ,yٕ?sfn l%80vq:=qC"̡pjE5<%#i~HX&P8%&iBvb;Y:9/\7(f`M"Xd*u9k*Yd%Κ$H n(' TUiB 0SWfkӎ`Q;kY8ܱ(wq5<`k伈 ָ91kkxi73B7|$qίKF/W22vZ0[_n!ᅧ79SYfҭglNgCf]n;rKԻX_<$Bd3PGYKf6z4](se6\b]^ j;'}F._k){?Nb{Q\>&{PS[-"C:^k6׵J{T y Md!4ڵ8r|> -; 7X}Pif[pRPy0" lF$hҵv> - >> ->> -endobj - -5275 0 obj -<< - /Title (A Programming Paradigm for Spatiotemporal Composability) - /Author (Yifan Shi, Wei Zhang, Tianyi Cui) - /Creator (Typst 0.14.2) - /ModDate (D:20260731154505+08'00) - /CreationDate (D:20260731154505+08'00) ->> -endobj - -5276 0 obj -<< - /Length 1223 - /Type /Metadata - /Subtype /XML ->> -stream -A Programming Paradigm for Spatiotemporal ComposabilityYifan Shi, Wei Zhang, Tianyi CuiTypst 0.14.2en2026-07-31T15:45:05+08:002026-07-31T15:45:05+08:0048application/pdf8/8Hb0n3/ti5Ewx/bKL9Ww==HHwsV4w2OKoHWq5hDV/GeA==proof1.7 -endstream -endobj - -5277 0 obj -<< - /Type /Catalog - /Pages 1 0 R - /Metadata 5276 0 R - /PageLabels 53 0 R - /Lang (en) - /StructTreeRoot 54 0 R - /MarkInfo << - /Marked true - /Suspects false - >> - /ViewerPreferences << - /Direction /L2R - >> - /Outlines 2 0 R - /Names << - /Dests << - /Names [(sec:conclusion) 4454 0 R (sec:discussion) 4448 0 R (sec:introduction) 4412 0 R (sec:preliminary) 4416 0 R (sec:related) 4453 0 R (sec:system) 4442 0 R (sec:theory) 4432 0 R (subsec:capabilities) 4444 0 R (subsec:coeffects) 4414 0 R (subsec:component-lifecycle) 4428 0 R (subsec:composability) 4406 0 R (subsec:context-paradigm) 4431 0 R (subsec:contributions) 4411 0 R (subsec:core-impl) 4437 0 R (subsec:effects) 4413 0 R (subsec:granularity) 4446 0 R (subsec:koishi) 4441 0 R (subsec:language) 4445 0 R (subsec:loader-hmr) 4440 0 R (subsec:motivation) 4410 0 R (subsec:reactive-coeffects) 4423 0 R (subsec:revertible-effects) 4419 0 R (subsec:rw-effects) 4449 0 R (subsec:rw-paradigms) 4450 0 R (subsec:rw-spatial) 4452 0 R (subsec:rw-temporal) 4451 0 R (subsec:scaling) 4443 0 R (subsec:versioning) 4447 0 R (subsubsec:coeff-context) 4420 0 R (subsubsec:coeff-isolate-intercept) 4422 0 R (subsubsec:coeff-reactive) 4421 0 R (subsubsec:coeffect-api) 4434 0 R (subsubsec:component-api) 4435 0 R (subsubsec:config-layer) 4438 0 R (subsubsec:context-access) 4436 0 R (subsubsec:context-situating) 4430 0 R (subsubsec:eff-composition) 4418 0 R (subsubsec:eff-formalization) 4417 0 R (subsubsec:eff-idempotent) 4424 0 R (subsubsec:effect-api) 4433 0 R (subsubsec:hmr) 4439 0 R (subsubsec:lifecycle-asynchrony) 4427 0 R (subsubsec:lifecycle-coherence) 4426 0 R (subsubsec:lifecycle-iteration) 4425 0 R (subsubsec:motivation-harnesses) 4408 0 R (subsubsec:motivation-plugins) 4407 0 R (subsubsec:motivation-workaround) 4409 0 R (subsubsec:unified-context) 4429 0 R] - >> - >> ->> -endobj - -xref -0 5278 -0000000000 65535 f -0000000016 00000 n -0000000507 00000 n -0000000588 00000 n -0000000726 00000 n -0000000839 00000 n -0000000999 00000 n -0000001101 00000 n -0000001232 00000 n -0000001349 00000 n -0000001448 00000 n -0000001604 00000 n -0000001700 00000 n -0000001813 00000 n -0000001939 00000 n -0000002124 00000 n -0000002274 00000 n -0000002379 00000 n -0000002497 00000 n -0000002662 00000 n -0000002769 00000 n -0000002905 00000 n -0000003022 00000 n -0000003188 00000 n -0000003298 00000 n -0000003413 00000 n -0000003528 00000 n -0000003629 00000 n -0000003781 00000 n -0000003887 00000 n -0000004008 00000 n -0000004181 00000 n -0000004325 00000 n -0000004431 00000 n -0000004556 00000 n -0000004681 00000 n -0000004786 00000 n -0000004949 00000 n -0000005071 00000 n -0000005184 00000 n -0000005291 00000 n -0000005445 00000 n -0000005554 00000 n -0000005687 00000 n -0000005826 00000 n -0000005975 00000 n -0000006096 00000 n -0000006252 00000 n -0000006368 00000 n -0000006493 00000 n -0000006619 00000 n -0000006729 00000 n -0000006840 00000 n -0000006933 00000 n -0000007532 00000 n -0000014516 00000 n -0000014895 00000 n -0000015760 00000 n -0000016283 00000 n -0000017013 00000 n -0000017878 00000 n -0000018842 00000 n -0000020661 00000 n -0000022246 00000 n -0000023804 00000 n -0000026919 00000 n -0000029386 00000 n -0000031583 00000 n -0000034005 00000 n -0000035860 00000 n -0000039569 00000 n -0000042567 00000 n -0000045664 00000 n -0000047951 00000 n -0000049707 00000 n -0000050941 00000 n -0000051905 00000 n -0000052914 00000 n -0000054697 00000 n -0000057011 00000 n -0000058857 00000 n -0000060550 00000 n -0000061991 00000 n -0000062973 00000 n -0000064522 00000 n -0000065900 00000 n -0000066648 00000 n -0000067333 00000 n -0000068036 00000 n -0000069120 00000 n -0000069715 00000 n -0000070670 00000 n -0000071433 00000 n -0000072180 00000 n -0000073255 00000 n -0000074402 00000 n -0000075061 00000 n -0000075968 00000 n -0000076875 00000 n -0000077694 00000 n -0000078577 00000 n -0000079485 00000 n -0000080409 00000 n -0000080909 00000 n -0000083583 00000 n -0000084559 00000 n -0000084648 00000 n -0000084732 00000 n -0000084854 00000 n -0000085006 00000 n -0000085097 00000 n -0000085179 00000 n -0000085331 00000 n -0000085420 00000 n -0000085504 00000 n -0000085612 00000 n -0000085826 00000 n -0000085908 00000 n -0000086060 00000 n -0000086149 00000 n -0000086233 00000 n -0000086358 00000 n -0000086510 00000 n -0000086601 00000 n -0000086683 00000 n -0000086835 00000 n -0000086924 00000 n -0000087008 00000 n -0000087130 00000 n -0000087282 00000 n -0000087376 00000 n -0000087458 00000 n -0000087610 00000 n -0000087699 00000 n -0000087783 00000 n -0000087905 00000 n -0000088057 00000 n -0000088151 00000 n -0000088233 00000 n -0000088385 00000 n -0000088474 00000 n -0000088558 00000 n -0000088686 00000 n -0000088838 00000 n -0000088929 00000 n -0000089011 00000 n -0000089163 00000 n -0000089252 00000 n -0000089336 00000 n -0000089444 00000 n -0000089535 00000 n -0000089617 00000 n -0000089769 00000 n -0000089858 00000 n -0000089942 00000 n -0000090039 00000 n -0000090121 00000 n -0000090272 00000 n -0000090361 00000 n -0000090445 00000 n -0000090563 00000 n -0000090714 00000 n -0000090808 00000 n -0000090890 00000 n -0000091041 00000 n -0000091130 00000 n -0000091214 00000 n -0000091336 00000 n -0000091489 00000 n -0000091589 00000 n -0000091671 00000 n -0000091824 00000 n -0000091913 00000 n -0000091997 00000 n -0000092118 00000 n -0000092271 00000 n -0000092370 00000 n -0000092452 00000 n -0000092604 00000 n -0000092693 00000 n -0000092777 00000 n -0000092899 00000 n -0000093051 00000 n -0000093145 00000 n -0000093227 00000 n -0000093379 00000 n -0000093468 00000 n -0000093552 00000 n -0000093677 00000 n -0000093829 00000 n -0000093923 00000 n -0000094005 00000 n -0000094157 00000 n -0000094246 00000 n -0000094330 00000 n -0000094452 00000 n -0000094604 00000 n -0000094701 00000 n -0000094783 00000 n -0000094935 00000 n -0000095024 00000 n -0000095108 00000 n -0000095227 00000 n -0000095379 00000 n -0000095470 00000 n -0000095552 00000 n -0000095704 00000 n -0000095793 00000 n -0000095877 00000 n -0000095974 00000 n -0000096056 00000 n -0000096208 00000 n -0000096297 00000 n -0000096381 00000 n -0000096481 00000 n -0000096563 00000 n -0000096715 00000 n -0000096804 00000 n -0000096888 00000 n -0000096996 00000 n -0000097090 00000 n -0000097172 00000 n -0000097324 00000 n -0000097413 00000 n -0000097497 00000 n -0000097619 00000 n -0000097771 00000 n -0000097865 00000 n -0000097947 00000 n -0000098099 00000 n -0000098188 00000 n -0000098272 00000 n -0000098397 00000 n -0000098549 00000 n -0000098640 00000 n -0000098722 00000 n -0000098874 00000 n -0000098963 00000 n -0000099047 00000 n -0000099172 00000 n -0000099324 00000 n -0000099418 00000 n -0000099500 00000 n -0000099652 00000 n -0000099741 00000 n -0000099825 00000 n -0000099947 00000 n -0000100099 00000 n -0000100193 00000 n -0000100275 00000 n -0000100427 00000 n -0000100516 00000 n -0000100600 00000 n -0000100722 00000 n -0000100874 00000 n -0000100968 00000 n -0000101050 00000 n -0000101202 00000 n -0000101291 00000 n -0000101375 00000 n -0000101497 00000 n -0000101649 00000 n -0000101742 00000 n -0000101824 00000 n -0000101975 00000 n -0000102064 00000 n -0000102148 00000 n -0000102422 00000 n -0000102573 00000 n -0000102717 00000 n -0000102799 00000 n -0000102952 00000 n -0000103041 00000 n -0000103125 00000 n -0000103262 00000 n -0000103415 00000 n -0000103511 00000 n -0000103602 00000 n -0000103684 00000 n -0000103836 00000 n -0000103925 00000 n -0000104009 00000 n -0000104134 00000 n -0000104286 00000 n -0000104377 00000 n -0000104459 00000 n -0000104611 00000 n -0000104700 00000 n -0000104784 00000 n -0000104906 00000 n -0000105058 00000 n -0000105152 00000 n -0000105234 00000 n -0000105386 00000 n -0000105475 00000 n -0000105559 00000 n -0000105678 00000 n -0000105830 00000 n -0000105924 00000 n -0000106006 00000 n -0000106158 00000 n -0000106247 00000 n -0000106331 00000 n -0000106456 00000 n -0000106608 00000 n -0000106699 00000 n -0000106781 00000 n -0000106933 00000 n -0000107022 00000 n -0000107106 00000 n -0000107231 00000 n -0000107445 00000 n -0000107536 00000 n -0000107618 00000 n -0000107770 00000 n -0000107859 00000 n -0000107943 00000 n -0000108065 00000 n -0000108217 00000 n -0000108308 00000 n -0000108390 00000 n -0000108542 00000 n -0000108631 00000 n -0000108715 00000 n -0000108837 00000 n -0000108989 00000 n -0000109080 00000 n -0000109162 00000 n -0000109314 00000 n -0000109403 00000 n -0000109487 00000 n -0000109609 00000 n -0000109761 00000 n -0000109855 00000 n -0000109937 00000 n -0000110089 00000 n -0000110178 00000 n -0000110262 00000 n -0000110373 00000 n -0000110525 00000 n -0000110607 00000 n -0000110759 00000 n -0000110848 00000 n -0000110932 00000 n -0000111054 00000 n -0000111206 00000 n -0000111300 00000 n -0000111382 00000 n -0000111534 00000 n -0000111623 00000 n -0000111707 00000 n -0000111832 00000 n -0000111984 00000 n -0000112075 00000 n -0000112157 00000 n -0000112309 00000 n -0000112398 00000 n -0000112482 00000 n -0000112603 00000 n -0000112755 00000 n -0000112845 00000 n -0000112927 00000 n -0000113078 00000 n -0000113167 00000 n -0000113251 00000 n -0000113369 00000 n -0000113520 00000 n -0000113610 00000 n -0000113692 00000 n -0000113843 00000 n -0000113932 00000 n -0000114016 00000 n -0000114142 00000 n -0000114295 00000 n -0000114391 00000 n -0000114473 00000 n -0000114626 00000 n -0000114715 00000 n -0000114799 00000 n -0000114924 00000 n -0000115076 00000 n -0000115167 00000 n -0000115249 00000 n -0000115401 00000 n -0000115490 00000 n -0000115574 00000 n -0000115699 00000 n -0000115851 00000 n -0000115945 00000 n -0000116027 00000 n -0000116179 00000 n -0000116268 00000 n -0000116352 00000 n -0000116477 00000 n -0000116629 00000 n -0000116720 00000 n -0000116802 00000 n -0000116954 00000 n -0000117043 00000 n -0000117127 00000 n -0000117246 00000 n -0000117398 00000 n -0000117492 00000 n -0000117574 00000 n -0000117726 00000 n -0000117815 00000 n -0000117899 00000 n -0000118021 00000 n -0000118235 00000 n -0000118326 00000 n -0000118408 00000 n -0000118560 00000 n -0000118649 00000 n -0000118733 00000 n -0000118855 00000 n -0000119007 00000 n -0000119107 00000 n -0000119189 00000 n -0000119341 00000 n -0000119430 00000 n -0000119514 00000 n -0000119636 00000 n -0000119788 00000 n -0000119882 00000 n -0000119964 00000 n -0000120116 00000 n -0000120205 00000 n -0000120289 00000 n -0000120394 00000 n -0000120608 00000 n -0000120690 00000 n -0000120842 00000 n -0000120931 00000 n -0000121015 00000 n -0000121140 00000 n -0000121292 00000 n -0000121383 00000 n -0000121465 00000 n -0000121617 00000 n -0000121706 00000 n -0000121790 00000 n -0000121895 00000 n -0000122109 00000 n -0000122191 00000 n -0000122343 00000 n -0000122432 00000 n -0000122516 00000 n -0000122635 00000 n -0000122787 00000 n -0000122881 00000 n -0000122963 00000 n -0000123115 00000 n -0000123204 00000 n -0000123288 00000 n -0000123396 00000 n -0000123490 00000 n -0000123572 00000 n -0000123724 00000 n -0000123813 00000 n -0000123897 00000 n -0000124015 00000 n -0000124167 00000 n -0000124260 00000 n -0000124342 00000 n -0000124493 00000 n -0000124582 00000 n -0000124666 00000 n -0000124782 00000 n -0000124933 00000 n -0000125025 00000 n -0000125107 00000 n -0000125258 00000 n -0000125347 00000 n -0000125431 00000 n -0000125542 00000 n -0000125636 00000 n -0000125718 00000 n -0000125870 00000 n -0000125959 00000 n -0000126043 00000 n -0000126168 00000 n -0000126320 00000 n -0000126411 00000 n -0000126493 00000 n -0000126645 00000 n -0000126734 00000 n -0000126818 00000 n -0000126932 00000 n -0000127023 00000 n -0000127105 00000 n -0000127257 00000 n -0000127346 00000 n -0000127430 00000 n -0000127538 00000 n -0000127632 00000 n -0000127714 00000 n -0000127866 00000 n -0000127955 00000 n -0000128039 00000 n -0000128150 00000 n -0000128241 00000 n -0000128323 00000 n -0000128475 00000 n -0000128564 00000 n -0000128648 00000 n -0000128770 00000 n -0000128922 00000 n -0000129016 00000 n -0000129098 00000 n -0000129250 00000 n -0000129339 00000 n -0000129423 00000 n -0000129545 00000 n -0000129697 00000 n -0000129791 00000 n -0000129873 00000 n -0000130025 00000 n -0000130114 00000 n -0000130198 00000 n -0000130326 00000 n -0000130478 00000 n -0000130569 00000 n -0000130651 00000 n -0000130803 00000 n -0000130892 00000 n -0000130976 00000 n -0000131084 00000 n -0000131175 00000 n -0000131257 00000 n -0000131409 00000 n -0000131498 00000 n -0000131582 00000 n -0000131687 00000 n -0000131839 00000 n -0000131921 00000 n -0000132073 00000 n -0000132162 00000 n -0000132246 00000 n -0000132351 00000 n -0000132565 00000 n -0000132647 00000 n -0000132799 00000 n -0000132888 00000 n -0000132972 00000 n -0000133083 00000 n -0000133180 00000 n -0000133262 00000 n -0000133414 00000 n -0000133503 00000 n -0000133587 00000 n -0000133712 00000 n -0000133864 00000 n -0000133958 00000 n -0000134040 00000 n -0000134192 00000 n -0000134281 00000 n -0000134365 00000 n -0000134476 00000 n -0000134628 00000 n -0000134710 00000 n -0000134862 00000 n -0000134951 00000 n -0000135035 00000 n -0000135142 00000 n -0000135238 00000 n -0000135320 00000 n -0000135471 00000 n -0000135560 00000 n -0000135644 00000 n -0000135760 00000 n -0000135911 00000 n -0000136003 00000 n -0000136085 00000 n -0000136236 00000 n -0000136325 00000 n -0000136409 00000 n -0000136531 00000 n -0000136684 00000 n -0000136780 00000 n -0000136862 00000 n -0000137015 00000 n -0000137104 00000 n -0000137188 00000 n -0000137313 00000 n -0000137466 00000 n -0000137557 00000 n -0000137639 00000 n -0000137791 00000 n -0000137880 00000 n -0000137964 00000 n -0000138086 00000 n -0000138238 00000 n -0000138332 00000 n -0000138414 00000 n -0000138566 00000 n -0000138655 00000 n -0000138739 00000 n -0000138861 00000 n -0000139013 00000 n -0000139104 00000 n -0000139186 00000 n -0000139338 00000 n -0000139427 00000 n -0000139511 00000 n -0000139633 00000 n -0000139785 00000 n -0000139879 00000 n -0000139961 00000 n -0000140113 00000 n -0000140202 00000 n -0000140286 00000 n -0000140405 00000 n -0000140557 00000 n -0000140654 00000 n -0000140736 00000 n -0000140888 00000 n -0000140977 00000 n -0000141061 00000 n -0000141186 00000 n -0000141338 00000 n -0000141432 00000 n -0000141514 00000 n -0000141666 00000 n -0000141755 00000 n -0000141839 00000 n -0000141969 00000 n -0000142121 00000 n -0000142215 00000 n -0000142306 00000 n -0000142388 00000 n -0000142540 00000 n -0000142629 00000 n -0000142713 00000 n -0000142832 00000 n -0000142984 00000 n -0000143078 00000 n -0000143160 00000 n -0000143312 00000 n -0000143401 00000 n -0000143485 00000 n -0000143607 00000 n -0000143759 00000 n -0000143853 00000 n -0000143935 00000 n -0000144087 00000 n -0000144176 00000 n -0000144260 00000 n -0000144379 00000 n -0000144593 00000 n -0000144690 00000 n -0000144772 00000 n -0000144924 00000 n -0000145013 00000 n -0000145097 00000 n -0000145216 00000 n -0000145430 00000 n -0000145521 00000 n -0000145603 00000 n -0000145755 00000 n -0000145844 00000 n -0000145928 00000 n -0000146050 00000 n -0000146202 00000 n -0000146296 00000 n -0000146378 00000 n -0000146529 00000 n -0000146618 00000 n -0000146702 00000 n -0000146822 00000 n -0000146973 00000 n -0000147065 00000 n -0000147147 00000 n -0000147298 00000 n -0000147387 00000 n -0000147471 00000 n -0000147585 00000 n -0000147677 00000 n -0000147759 00000 n -0000147912 00000 n -0000148001 00000 n -0000148085 00000 n -0000148214 00000 n -0000148367 00000 n -0000148462 00000 n -0000148544 00000 n -0000148696 00000 n -0000148785 00000 n -0000148869 00000 n -0000148977 00000 n -0000149068 00000 n -0000149150 00000 n -0000149302 00000 n -0000149391 00000 n -0000149475 00000 n -0000149597 00000 n -0000149749 00000 n -0000149840 00000 n -0000149922 00000 n -0000150074 00000 n -0000150163 00000 n -0000150247 00000 n -0000150375 00000 n -0000150527 00000 n -0000150621 00000 n -0000150703 00000 n -0000150855 00000 n -0000150944 00000 n -0000151028 00000 n -0000151153 00000 n -0000151305 00000 n -0000151399 00000 n -0000151481 00000 n -0000151633 00000 n -0000151722 00000 n -0000151806 00000 n -0000151917 00000 n -0000152011 00000 n -0000152093 00000 n -0000152245 00000 n -0000152334 00000 n -0000152418 00000 n -0000152540 00000 n -0000152692 00000 n -0000152783 00000 n -0000152865 00000 n -0000153017 00000 n -0000153106 00000 n -0000153190 00000 n -0000153290 00000 n -0000153372 00000 n -0000153524 00000 n -0000153613 00000 n -0000153697 00000 n -0000153811 00000 n -0000153902 00000 n -0000153984 00000 n -0000154136 00000 n -0000154225 00000 n -0000154309 00000 n -0000154442 00000 n -0000154594 00000 n -0000154688 00000 n -0000154779 00000 n -0000154861 00000 n -0000155013 00000 n -0000155102 00000 n -0000155186 00000 n -0000155297 00000 n -0000155388 00000 n -0000155470 00000 n -0000155622 00000 n -0000155711 00000 n -0000155795 00000 n -0000155928 00000 n -0000156080 00000 n -0000156171 00000 n -0000156262 00000 n -0000156344 00000 n -0000156496 00000 n -0000156585 00000 n -0000156669 00000 n -0000156799 00000 n -0000156951 00000 n -0000157048 00000 n -0000157139 00000 n -0000157221 00000 n -0000157373 00000 n -0000157462 00000 n -0000157546 00000 n -0000157654 00000 n -0000157867 00000 n -0000157949 00000 n -0000158100 00000 n -0000158189 00000 n -0000158273 00000 n -0000158381 00000 n -0000158532 00000 n -0000158614 00000 n -0000158765 00000 n -0000158854 00000 n -0000158938 00000 n -0000159049 00000 n -0000159140 00000 n -0000159222 00000 n -0000159374 00000 n -0000159463 00000 n -0000159547 00000 n -0000159672 00000 n -0000159824 00000 n -0000159918 00000 n -0000160000 00000 n -0000160152 00000 n -0000160241 00000 n -0000160325 00000 n -0000160433 00000 n -0000160524 00000 n -0000160606 00000 n -0000160758 00000 n -0000160847 00000 n -0000160931 00000 n -0000161056 00000 n -0000161208 00000 n -0000161299 00000 n -0000161381 00000 n -0000161533 00000 n -0000161622 00000 n -0000161706 00000 n -0000161828 00000 n -0000161980 00000 n -0000162071 00000 n -0000162153 00000 n -0000162305 00000 n -0000162394 00000 n -0000162478 00000 n -0000162597 00000 n -0000162749 00000 n -0000162846 00000 n -0000162928 00000 n -0000163080 00000 n -0000163189 00000 n -0000163311 00000 n -0000163463 00000 n -0000163628 00000 n -0000163722 00000 n -0000163813 00000 n -0000163904 00000 n -0000163994 00000 n -0000164104 00000 n -0000164531 00000 n -0000164621 00000 n -0000164713 00000 n -0000164866 00000 n -0000164958 00000 n -0000165111 00000 n -0000165264 00000 n -0000165417 00000 n -0000165513 00000 n -0000165787 00000 n -0000165940 00000 n -0000166034 00000 n -0000166187 00000 n -0000166339 00000 n -0000166432 00000 n -0000166525 00000 n -0000166677 00000 n -0000166829 00000 n -0000166981 00000 n -0000167076 00000 n -0000167271 00000 n -0000167423 00000 n -0000167516 00000 n -0000167609 00000 n -0000167761 00000 n -0000167913 00000 n -0000168008 00000 n -0000168107 00000 n -0000168230 00000 n -0000168492 00000 n -0000168644 00000 n -0000168796 00000 n -0000168948 00000 n -0000169100 00000 n -0000169252 00000 n -0000169404 00000 n -0000169556 00000 n -0000169707 00000 n -0000169858 00000 n -0000169952 00000 n -0000170272 00000 n -0000170425 00000 n -0000170519 00000 n -0000170672 00000 n -0000170825 00000 n -0000170978 00000 n -0000171130 00000 n -0000171223 00000 n -0000171375 00000 n -0000171527 00000 n -0000171622 00000 n -0000172020 00000 n -0000172172 00000 n -0000172265 00000 n -0000172358 00000 n -0000172510 00000 n -0000172662 00000 n -0000172755 00000 n -0000172907 00000 n -0000173059 00000 n -0000173211 00000 n -0000173363 00000 n -0000173515 00000 n -0000173667 00000 n -0000173819 00000 n -0000173910 00000 n -0000174062 00000 n -0000174152 00000 n -0000174246 00000 n -0000174495 00000 n -0000174619 00000 n -0000174887 00000 n -0000175039 00000 n -0000175191 00000 n -0000175282 00000 n -0000175376 00000 n -0000175467 00000 n -0000175558 00000 n -0000175649 00000 n -0000175740 00000 n -0000175892 00000 n -0000176044 00000 n -0000176139 00000 n -0000176365 00000 n -0000176517 00000 n -0000176616 00000 n -0000176768 00000 n -0000176859 00000 n -0000177011 00000 n -0000177163 00000 n -0000177257 00000 n -0000177358 00000 n -0000177509 00000 n -0000177630 00000 n -0000177923 00000 n -0000178075 00000 n -0000178227 00000 n -0000178379 00000 n -0000178473 00000 n -0000178625 00000 n -0000178720 00000 n -0000178898 00000 n -0000179050 00000 n -0000179141 00000 n -0000179232 00000 n -0000179384 00000 n -0000179479 00000 n -0000179711 00000 n -0000179802 00000 n -0000179893 00000 n -0000180045 00000 n -0000180197 00000 n -0000180349 00000 n -0000180440 00000 n -0000180592 00000 n -0000180687 00000 n -0000180791 00000 n -0000180942 00000 n -0000181069 00000 n -0000181160 00000 n -0000181272 00000 n -0000181371 00000 n -0000181586 00000 n -0000181739 00000 n -0000181892 00000 n -0000182045 00000 n -0000182197 00000 n -0000182308 00000 n -0000182403 00000 n -0000182562 00000 n -0000182653 00000 n -0000182805 00000 n -0000182900 00000 n -0000183043 00000 n -0000183139 00000 n -0000183241 00000 n -0000183337 00000 n -0000183432 00000 n -0000183578 00000 n -0000183730 00000 n -0000183821 00000 n -0000183912 00000 n -0000184003 00000 n -0000184127 00000 n -0000184223 00000 n -0000184318 00000 n -0000184479 00000 n -0000184631 00000 n -0000184742 00000 n -0000184837 00000 n -0000184932 00000 n -0000185026 00000 n -0000185256 00000 n -0000185355 00000 n -0000185451 00000 n -0000185547 00000 n -0000185681 00000 n -0000185792 00000 n -0000185934 00000 n -0000186030 00000 n -0000186126 00000 n -0000186249 00000 n -0000186414 00000 n -0000186510 00000 n -0000186606 00000 n -0000186702 00000 n -0000186798 00000 n -0000186894 00000 n -0000186990 00000 n -0000187135 00000 n -0000187622 00000 n -0000187773 00000 n -0000187926 00000 n -0000188128 00000 n -0000188283 00000 n -0000188438 00000 n -0000188592 00000 n -0000188687 00000 n -0000188841 00000 n -0000188936 00000 n -0000189150 00000 n -0000189304 00000 n -0000189458 00000 n -0000189553 00000 n -0000189648 00000 n -0000189802 00000 n -0000189956 00000 n -0000190110 00000 n -0000190261 00000 n -0000190354 00000 n -0000190447 00000 n -0000190601 00000 n -0000190698 00000 n -0000190906 00000 n -0000191060 00000 n -0000191155 00000 n -0000191250 00000 n -0000191345 00000 n -0000191440 00000 n -0000191577 00000 n -0000191673 00000 n -0000191758 00000 n -0000191903 00000 n -0000192076 00000 n -0000192161 00000 n -0000192306 00000 n -0000192478 00000 n -0000192599 00000 n -0000192692 00000 n -0000192789 00000 n -0000192886 00000 n -0000193022 00000 n -0000193396 00000 n -0000193549 00000 n -0000193703 00000 n -0000193857 00000 n -0000193954 00000 n -0000194087 00000 n -0000194241 00000 n -0000194419 00000 n -0000194514 00000 n -0000194668 00000 n -0000194822 00000 n -0000194976 00000 n -0000195073 00000 n -0000195176 00000 n -0000195308 00000 n -0000195442 00000 n -0000195596 00000 n -0000195692 00000 n -0000196146 00000 n -0000196240 00000 n -0000196394 00000 n -0000196548 00000 n -0000196645 00000 n -0000196760 00000 n -0000196857 00000 n -0000196951 00000 n -0000197180 00000 n -0000197273 00000 n -0000197366 00000 n -0000197459 00000 n -0000197554 00000 n -0000197647 00000 n -0000197742 00000 n -0000197835 00000 n -0000197989 00000 n -0000198112 00000 n -0000198215 00000 n -0000198328 00000 n -0000198445 00000 n -0000198541 00000 n -0000199035 00000 n -0000199188 00000 n -0000199342 00000 n -0000199439 00000 n -0000199605 00000 n -0000199759 00000 n -0000199913 00000 n -0000200067 00000 n -0000200164 00000 n -0000200315 00000 n -0000200469 00000 n -0000200623 00000 n -0000200720 00000 n -0000200865 00000 n -0000201008 00000 n -0000201101 00000 n -0000201194 00000 n -0000201279 00000 n -0000201424 00000 n -0000201596 00000 n -0000201681 00000 n -0000201826 00000 n -0000201998 00000 n -0000202120 00000 n -0000202205 00000 n -0000202350 00000 n -0000202522 00000 n -0000202607 00000 n -0000202752 00000 n -0000202924 00000 n -0000203045 00000 n -0000203157 00000 n -0000203252 00000 n -0000203397 00000 n -0000203959 00000 n -0000204036 00000 n -0000204130 00000 n -0000204277 00000 n -0000204426 00000 n -0000204503 00000 n -0000204580 00000 n -0000204665 00000 n -0000204812 00000 n -0000204915 00000 n -0000205062 00000 n -0000205212 00000 n -0000205358 00000 n -0000205435 00000 n -0000205512 00000 n -0000205589 00000 n -0000205674 00000 n -0000205820 00000 n -0000205905 00000 n -0000206051 00000 n -0000206128 00000 n -0000206205 00000 n -0000206282 00000 n -0000206359 00000 n -0000206444 00000 n -0000206590 00000 n -0000206702 00000 n -0000206850 00000 n -0000206998 00000 n -0000207146 00000 n -0000207294 00000 n -0000207371 00000 n -0000207448 00000 n -0000207533 00000 n -0000207679 00000 n -0000207764 00000 n -0000207912 00000 n -0000207989 00000 n -0000208066 00000 n -0000208143 00000 n -0000208228 00000 n -0000208376 00000 n -0000208470 00000 n -0000208618 00000 n -0000208768 00000 n -0000208845 00000 n -0000208930 00000 n -0000209078 00000 n -0000209181 00000 n -0000209329 00000 n -0000209480 00000 n -0000209628 00000 n -0000209705 00000 n -0000209782 00000 n -0000209859 00000 n -0000209944 00000 n -0000210092 00000 n -0000210177 00000 n -0000210325 00000 n -0000210402 00000 n -0000210479 00000 n -0000210556 00000 n -0000210633 00000 n -0000210718 00000 n -0000210866 00000 n -0000210978 00000 n -0000211130 00000 n -0000211280 00000 n -0000211430 00000 n -0000211580 00000 n -0000211657 00000 n -0000211734 00000 n -0000211811 00000 n -0000211896 00000 n -0000212044 00000 n -0000212129 00000 n -0000212279 00000 n -0000212356 00000 n -0000212441 00000 n -0000212589 00000 n -0000212692 00000 n -0000212840 00000 n -0000212991 00000 n -0000213139 00000 n -0000213216 00000 n -0000213293 00000 n -0000213378 00000 n -0000213526 00000 n -0000213620 00000 n -0000213768 00000 n -0000213918 00000 n -0000214003 00000 n -0000214151 00000 n -0000214228 00000 n -0000214330 00000 n -0000214428 00000 n -0000214572 00000 n -0000214668 00000 n -0000214792 00000 n -0000214877 00000 n -0000215022 00000 n -0000215195 00000 n -0000215280 00000 n -0000215425 00000 n -0000215598 00000 n -0000215696 00000 n -0000215814 00000 n -0000215910 00000 n -0000216006 00000 n -0000216151 00000 n -0000216785 00000 n -0000216862 00000 n -0000216956 00000 n -0000217104 00000 n -0000217254 00000 n -0000217331 00000 n -0000217416 00000 n -0000217564 00000 n -0000217685 00000 n -0000217833 00000 n -0000217984 00000 n -0000218132 00000 n -0000218283 00000 n -0000218430 00000 n -0000218507 00000 n -0000218584 00000 n -0000218661 00000 n -0000218746 00000 n -0000218893 00000 n -0000219014 00000 n -0000219161 00000 n -0000219311 00000 n -0000219458 00000 n -0000219608 00000 n -0000219755 00000 n -0000219832 00000 n -0000219909 00000 n -0000219986 00000 n -0000220063 00000 n -0000220148 00000 n -0000220295 00000 n -0000220452 00000 n -0000220599 00000 n -0000220748 00000 n -0000220898 00000 n -0000221045 00000 n -0000221195 00000 n -0000221342 00000 n -0000221492 00000 n -0000221639 00000 n -0000221788 00000 n -0000221865 00000 n -0000221942 00000 n -0000222027 00000 n -0000222174 00000 n -0000222277 00000 n -0000222424 00000 n -0000222574 00000 n -0000222721 00000 n -0000222798 00000 n -0000222875 00000 n -0000222952 00000 n -0000223037 00000 n -0000223184 00000 n -0000223296 00000 n -0000223446 00000 n -0000223595 00000 n -0000223744 00000 n -0000223893 00000 n -0000223970 00000 n -0000224055 00000 n -0000224202 00000 n -0000224314 00000 n -0000224464 00000 n -0000224611 00000 n -0000224761 00000 n -0000224908 00000 n -0000224985 00000 n -0000225062 00000 n -0000225147 00000 n -0000225294 00000 n -0000225388 00000 n -0000225535 00000 n -0000225684 00000 n -0000225769 00000 n -0000225916 00000 n -0000226010 00000 n -0000226157 00000 n -0000226306 00000 n -0000226383 00000 n -0000226468 00000 n -0000226615 00000 n -0000226700 00000 n -0000226847 00000 n -0000226924 00000 n -0000227009 00000 n -0000227156 00000 n -0000227268 00000 n -0000227421 00000 n -0000227570 00000 n -0000227719 00000 n -0000227868 00000 n -0000227945 00000 n -0000228022 00000 n -0000228107 00000 n -0000228254 00000 n -0000228375 00000 n -0000228522 00000 n -0000228672 00000 n -0000228819 00000 n -0000228969 00000 n -0000229116 00000 n -0000229193 00000 n -0000229270 00000 n -0000229355 00000 n -0000229502 00000 n -0000229659 00000 n -0000229809 00000 n -0000229958 00000 n -0000230107 00000 n -0000230257 00000 n -0000230407 00000 n -0000230556 00000 n -0000230706 00000 n -0000230853 00000 n -0000231002 00000 n -0000231079 00000 n -0000231156 00000 n -0000231233 00000 n -0000231318 00000 n -0000231465 00000 n -0000231559 00000 n -0000231706 00000 n -0000231855 00000 n -0000231932 00000 n -0000232017 00000 n -0000232164 00000 n -0000232276 00000 n -0000232426 00000 n -0000232573 00000 n -0000232723 00000 n -0000232870 00000 n -0000232947 00000 n -0000233024 00000 n -0000233109 00000 n -0000233256 00000 n -0000233350 00000 n -0000233497 00000 n -0000233646 00000 n -0000233731 00000 n -0000233878 00000 n -0000233955 00000 n -0000234056 00000 n -0000234153 00000 n -0000234320 00000 n -0000234415 00000 n -0000234510 00000 n -0000234603 00000 n -0000234698 00000 n -0000234792 00000 n -0000234888 00000 n -0000234982 00000 n -0000235127 00000 n -0000236139 00000 n -0000236216 00000 n -0000236310 00000 n -0000236456 00000 n -0000236604 00000 n -0000236681 00000 n -0000236766 00000 n -0000236912 00000 n -0000237033 00000 n -0000237181 00000 n -0000237332 00000 n -0000237480 00000 n -0000237631 00000 n -0000237779 00000 n -0000237856 00000 n -0000237941 00000 n -0000238089 00000 n -0000238183 00000 n -0000238331 00000 n -0000238481 00000 n -0000238558 00000 n -0000238643 00000 n -0000238791 00000 n -0000238948 00000 n -0000239096 00000 n -0000239247 00000 n -0000239395 00000 n -0000239546 00000 n -0000239694 00000 n -0000239845 00000 n -0000239993 00000 n -0000240144 00000 n -0000240292 00000 n -0000240369 00000 n -0000240446 00000 n -0000240523 00000 n -0000240600 00000 n -0000240677 00000 n -0000240762 00000 n -0000240910 00000 n -0000240995 00000 n -0000241145 00000 n -0000241222 00000 n -0000241299 00000 n -0000241376 00000 n -0000241461 00000 n -0000241609 00000 n -0000241712 00000 n -0000241860 00000 n -0000242011 00000 n -0000242159 00000 n -0000242236 00000 n -0000242313 00000 n -0000242390 00000 n -0000242467 00000 n -0000242552 00000 n -0000242700 00000 n -0000242821 00000 n -0000242969 00000 n -0000243120 00000 n -0000243268 00000 n -0000243419 00000 n -0000243567 00000 n -0000243644 00000 n -0000243721 00000 n -0000243798 00000 n -0000243875 00000 n -0000243960 00000 n -0000244108 00000 n -0000244229 00000 n -0000244377 00000 n -0000244528 00000 n -0000244676 00000 n -0000244827 00000 n -0000244975 00000 n -0000245052 00000 n -0000245129 00000 n -0000245206 00000 n -0000245283 00000 n -0000245360 00000 n -0000245445 00000 n -0000245593 00000 n -0000245714 00000 n -0000245862 00000 n -0000246012 00000 n -0000246163 00000 n -0000246311 00000 n -0000246461 00000 n -0000246538 00000 n -0000246615 00000 n -0000246692 00000 n -0000246777 00000 n -0000246925 00000 n -0000247028 00000 n -0000247176 00000 n -0000247327 00000 n -0000247475 00000 n -0000247552 00000 n -0000247629 00000 n -0000247706 00000 n -0000247783 00000 n -0000247868 00000 n -0000248016 00000 n -0000248137 00000 n -0000248285 00000 n -0000248436 00000 n -0000248584 00000 n -0000248735 00000 n -0000248883 00000 n -0000248960 00000 n -0000249037 00000 n -0000249114 00000 n -0000249191 00000 n -0000249276 00000 n -0000249424 00000 n -0000249545 00000 n -0000249693 00000 n -0000249844 00000 n -0000249992 00000 n -0000250143 00000 n -0000250291 00000 n -0000250368 00000 n -0000250445 00000 n -0000250522 00000 n -0000250599 00000 n -0000250676 00000 n -0000250761 00000 n -0000250909 00000 n -0000251066 00000 n -0000251214 00000 n -0000251364 00000 n -0000251515 00000 n -0000251663 00000 n -0000251814 00000 n -0000251962 00000 n -0000252113 00000 n -0000252261 00000 n -0000252411 00000 n -0000252488 00000 n -0000252565 00000 n -0000252642 00000 n -0000252719 00000 n -0000252804 00000 n -0000252952 00000 n -0000253064 00000 n -0000253214 00000 n -0000253364 00000 n -0000253513 00000 n -0000253662 00000 n -0000253739 00000 n -0000253816 00000 n -0000253901 00000 n -0000254048 00000 n -0000254151 00000 n -0000254298 00000 n -0000254448 00000 n -0000254595 00000 n -0000254672 00000 n -0000254749 00000 n -0000254826 00000 n -0000254911 00000 n -0000255058 00000 n -0000255143 00000 n -0000255292 00000 n -0000255369 00000 n -0000255454 00000 n -0000255601 00000 n -0000255758 00000 n -0000255905 00000 n -0000256055 00000 n -0000256202 00000 n -0000256352 00000 n -0000256499 00000 n -0000256649 00000 n -0000256796 00000 n -0000256946 00000 n -0000257093 00000 n -0000257170 00000 n -0000257247 00000 n -0000257324 00000 n -0000257409 00000 n -0000257556 00000 n -0000257668 00000 n -0000257818 00000 n -0000257967 00000 n -0000258116 00000 n -0000258265 00000 n -0000258342 00000 n -0000258427 00000 n -0000258574 00000 n -0000258686 00000 n -0000258836 00000 n -0000258983 00000 n -0000259133 00000 n -0000259280 00000 n -0000259357 00000 n -0000259442 00000 n -0000259589 00000 n -0000259692 00000 n -0000259839 00000 n -0000259989 00000 n -0000260136 00000 n -0000260213 00000 n -0000260298 00000 n -0000260445 00000 n -0000260548 00000 n -0000260695 00000 n -0000260845 00000 n -0000260992 00000 n -0000261069 00000 n -0000261146 00000 n -0000261231 00000 n -0000261378 00000 n -0000261472 00000 n -0000261619 00000 n -0000261768 00000 n -0000261853 00000 n -0000262000 00000 n -0000262077 00000 n -0000262178 00000 n -0000262275 00000 n -0000262456 00000 n -0000262551 00000 n -0000262646 00000 n -0000262741 00000 n -0000262836 00000 n -0000262929 00000 n -0000263022 00000 n -0000263119 00000 n -0000263234 00000 n -0000263327 00000 n -0000263422 00000 n -0000263582 00000 n -0000263736 00000 n -0000263890 00000 n -0000263983 00000 n -0000264108 00000 n -0000264216 00000 n -0000264310 00000 n -0000264483 00000 n -0000264576 00000 n -0000264680 00000 n -0000264774 00000 n -0000264867 00000 n -0000264960 00000 n -0000265317 00000 n -0000265411 00000 n -0000265507 00000 n -0000265603 00000 n -0000265698 00000 n -0000265792 00000 n -0000265885 00000 n -0000265993 00000 n -0000266088 00000 n -0000266182 00000 n -0000266275 00000 n -0000266383 00000 n -0000266478 00000 n -0000266572 00000 n -0000266665 00000 n -0000266782 00000 n -0000266877 00000 n -0000266972 00000 n -0000267066 00000 n -0000267163 00000 n -0000267305 00000 n -0000267400 00000 n -0000267495 00000 n -0000267588 00000 n -0000267742 00000 n -0000267837 00000 n -0000268020 00000 n -0000268113 00000 n -0000268218 00000 n -0000268313 00000 n -0000268407 00000 n -0000268500 00000 n -0000268617 00000 n -0000268712 00000 n -0000268807 00000 n -0000268901 00000 n -0000268994 00000 n -0000269099 00000 n -0000269194 00000 n -0000269288 00000 n -0000269381 00000 n -0000269486 00000 n -0000269581 00000 n -0000269675 00000 n -0000269768 00000 n -0000269873 00000 n -0000269968 00000 n -0000270062 00000 n -0000270155 00000 n -0000270260 00000 n -0000270355 00000 n -0000270449 00000 n -0000270562 00000 n -0000270655 00000 n -0000270758 00000 n -0000270882 00000 n -0000270975 00000 n -0000271129 00000 n -0000271263 00000 n -0000271447 00000 n -0000271540 00000 n -0000271636 00000 n -0000271731 00000 n -0000271826 00000 n -0000271921 00000 n -0000272014 00000 n -0000272132 00000 n -0000272593 00000 n -0000272746 00000 n -0000272843 00000 n -0000272937 00000 n -0000273036 00000 n -0000273130 00000 n -0000273389 00000 n -0000273544 00000 n -0000273640 00000 n -0000273739 00000 n -0000273833 00000 n -0000273929 00000 n -0000274025 00000 n -0000274180 00000 n -0000274276 00000 n -0000274372 00000 n -0000274468 00000 n -0000274623 00000 n -0000274768 00000 n -0000275060 00000 n -0000275137 00000 n -0000275240 00000 n -0000275388 00000 n -0000275539 00000 n -0000275687 00000 n -0000275764 00000 n -0000275841 00000 n -0000275926 00000 n -0000276074 00000 n -0000276213 00000 n -0000276361 00000 n -0000276517 00000 n -0000276667 00000 n -0000276817 00000 n -0000276968 00000 n -0000277116 00000 n -0000277266 00000 n -0000277343 00000 n -0000277420 00000 n -0000277505 00000 n -0000277653 00000 n -0000277783 00000 n -0000277939 00000 n -0000278089 00000 n -0000278239 00000 n -0000278390 00000 n -0000278538 00000 n -0000278688 00000 n -0000278765 00000 n -0000278842 00000 n -0000278919 00000 n -0000279004 00000 n -0000279152 00000 n -0000279237 00000 n -0000279386 00000 n -0000279463 00000 n -0000279548 00000 n -0000279695 00000 n -0000279798 00000 n -0000279945 00000 n -0000280095 00000 n -0000280242 00000 n -0000280319 00000 n -0000280396 00000 n -0000280481 00000 n -0000280628 00000 n -0000280722 00000 n -0000280869 00000 n -0000281018 00000 n -0000281103 00000 n -0000281250 00000 n -0000281327 00000 n -0000281428 00000 n -0000281525 00000 n -0000281763 00000 n -0000281917 00000 n -0000282012 00000 n -0000282166 00000 n -0000282261 00000 n -0000282356 00000 n -0000282451 00000 n -0000282544 00000 n -0000282639 00000 n -0000282734 00000 n -0000282827 00000 n -0000282981 00000 n -0000283098 00000 n -0000283270 00000 n -0000283424 00000 n -0000283578 00000 n -0000283671 00000 n -0000283766 00000 n -0000283861 00000 n -0000283954 00000 n -0000284087 00000 n -0000284241 00000 n -0000284336 00000 n -0000284490 00000 n -0000284635 00000 n -0000285485 00000 n -0000285562 00000 n -0000285665 00000 n -0000285812 00000 n -0000285962 00000 n -0000286109 00000 n -0000286186 00000 n -0000286263 00000 n -0000286340 00000 n -0000286425 00000 n -0000286572 00000 n -0000286657 00000 n -0000286806 00000 n -0000286883 00000 n -0000286968 00000 n -0000287115 00000 n -0000287218 00000 n -0000287365 00000 n -0000287515 00000 n -0000287662 00000 n -0000287739 00000 n -0000287816 00000 n -0000287893 00000 n -0000287978 00000 n -0000288125 00000 n -0000288264 00000 n -0000288411 00000 n -0000288560 00000 n -0000288710 00000 n -0000288857 00000 n -0000289007 00000 n -0000289154 00000 n -0000289303 00000 n -0000289380 00000 n -0000289465 00000 n -0000289612 00000 n -0000289715 00000 n -0000289862 00000 n -0000290012 00000 n -0000290159 00000 n -0000290236 00000 n -0000290321 00000 n -0000290468 00000 n -0000290562 00000 n -0000290709 00000 n -0000290858 00000 n -0000290935 00000 n -0000291012 00000 n -0000291097 00000 n -0000291243 00000 n -0000291337 00000 n -0000291483 00000 n -0000291631 00000 n -0000291716 00000 n -0000291862 00000 n -0000291965 00000 n -0000292111 00000 n -0000292260 00000 n -0000292406 00000 n -0000292483 00000 n -0000292560 00000 n -0000292637 00000 n -0000292722 00000 n -0000292868 00000 n -0000292953 00000 n -0000293101 00000 n -0000293178 00000 n -0000293263 00000 n -0000293409 00000 n -0000293512 00000 n -0000293660 00000 n -0000293811 00000 n -0000293959 00000 n -0000294036 00000 n -0000294113 00000 n -0000294190 00000 n -0000294275 00000 n -0000294423 00000 n -0000294553 00000 n -0000294705 00000 n -0000294855 00000 n -0000295054 00000 n -0000295205 00000 n -0000295353 00000 n -0000295503 00000 n -0000295580 00000 n -0000295665 00000 n -0000295813 00000 n -0000295916 00000 n -0000296064 00000 n -0000296215 00000 n -0000296363 00000 n -0000296440 00000 n -0000296525 00000 n -0000296673 00000 n -0000296830 00000 n -0000296982 00000 n -0000297181 00000 n -0000297332 00000 n -0000297480 00000 n -0000297631 00000 n -0000297783 00000 n -0000297933 00000 n -0000298084 00000 n -0000298232 00000 n -0000298309 00000 n -0000298394 00000 n -0000298542 00000 n -0000298654 00000 n -0000298802 00000 n -0000298953 00000 n -0000299105 00000 n -0000299304 00000 n -0000299381 00000 n -0000299458 00000 n -0000299543 00000 n -0000299691 00000 n -0000299785 00000 n -0000299933 00000 n -0000300083 00000 n -0000300168 00000 n -0000300316 00000 n -0000300419 00000 n -0000300567 00000 n -0000300718 00000 n -0000300866 00000 n -0000300943 00000 n -0000301020 00000 n -0000301097 00000 n -0000301182 00000 n -0000301330 00000 n -0000301415 00000 n -0000301565 00000 n -0000301642 00000 n -0000301727 00000 n -0000301875 00000 n -0000301978 00000 n -0000302126 00000 n -0000302277 00000 n -0000302425 00000 n -0000302502 00000 n -0000302579 00000 n -0000302656 00000 n -0000302741 00000 n -0000302889 00000 n -0000303028 00000 n -0000303176 00000 n -0000303326 00000 n -0000303477 00000 n -0000303625 00000 n -0000303776 00000 n -0000303924 00000 n -0000304074 00000 n -0000304151 00000 n -0000304236 00000 n -0000304384 00000 n -0000304496 00000 n -0000304648 00000 n -0000304798 00000 n -0000304948 00000 n -0000305098 00000 n -0000305175 00000 n -0000305260 00000 n -0000305408 00000 n -0000305511 00000 n -0000305659 00000 n -0000305810 00000 n -0000305958 00000 n -0000306035 00000 n -0000306120 00000 n -0000306268 00000 n -0000306398 00000 n -0000306550 00000 n -0000306700 00000 n -0000306850 00000 n -0000307001 00000 n -0000307149 00000 n -0000307299 00000 n -0000307376 00000 n -0000307461 00000 n -0000307609 00000 n -0000307721 00000 n -0000307888 00000 n -0000308035 00000 n -0000308185 00000 n -0000308332 00000 n -0000308409 00000 n -0000308486 00000 n -0000308571 00000 n -0000308718 00000 n -0000308812 00000 n -0000308959 00000 n -0000309108 00000 n -0000309193 00000 n -0000309340 00000 n -0000309417 00000 n -0000309518 00000 n -0000309615 00000 n -0000309928 00000 n -0000310023 00000 n -0000310118 00000 n -0000310213 00000 n -0000310308 00000 n -0000310406 00000 n -0000310501 00000 n -0000310596 00000 n -0000310691 00000 n -0000310845 00000 n -0000310941 00000 n -0000311037 00000 n -0000311122 00000 n -0000311267 00000 n -0000311440 00000 n -0000311525 00000 n -0000311670 00000 n -0000311842 00000 n -0000311937 00000 n -0000312032 00000 n -0000312127 00000 n -0000312222 00000 n -0000312317 00000 n -0000312471 00000 n -0000312625 00000 n -0000312770 00000 n -0000313233 00000 n -0000313310 00000 n -0000313404 00000 n -0000313551 00000 n -0000313700 00000 n -0000313777 00000 n -0000313862 00000 n -0000314009 00000 n -0000314094 00000 n -0000314241 00000 n -0000314318 00000 n -0000314403 00000 n -0000314550 00000 n -0000314671 00000 n -0000314818 00000 n -0000314968 00000 n -0000315115 00000 n -0000315265 00000 n -0000315412 00000 n -0000315489 00000 n -0000315583 00000 n -0000315730 00000 n -0000315859 00000 n -0000315980 00000 n -0000316127 00000 n -0000316277 00000 n -0000316424 00000 n -0000316574 00000 n -0000316721 00000 n -0000316798 00000 n -0000316883 00000 n -0000317030 00000 n -0000317133 00000 n -0000317280 00000 n -0000317430 00000 n -0000317577 00000 n -0000317654 00000 n -0000317739 00000 n -0000317886 00000 n -0000317971 00000 n -0000318118 00000 n -0000318195 00000 n -0000318272 00000 n -0000318349 00000 n -0000318434 00000 n -0000318581 00000 n -0000318693 00000 n -0000318843 00000 n -0000318990 00000 n -0000319140 00000 n -0000319287 00000 n -0000319364 00000 n -0000319441 00000 n -0000319518 00000 n -0000319595 00000 n -0000319680 00000 n -0000319827 00000 n -0000319930 00000 n -0000320080 00000 n -0000320229 00000 n -0000320378 00000 n -0000320455 00000 n -0000320532 00000 n -0000320617 00000 n -0000320764 00000 n -0000320849 00000 n -0000320996 00000 n -0000321073 00000 n -0000321150 00000 n -0000321227 00000 n -0000321312 00000 n -0000321459 00000 n -0000321553 00000 n -0000321700 00000 n -0000321849 00000 n -0000321926 00000 n -0000322003 00000 n -0000322097 00000 n -0000322244 00000 n -0000322373 00000 n -0000322467 00000 n -0000322614 00000 n -0000322763 00000 n -0000322848 00000 n -0000322995 00000 n -0000323072 00000 n -0000323172 00000 n -0000323268 00000 n -0000323837 00000 n -0000323934 00000 n -0000324028 00000 n -0000324125 00000 n -0000324280 00000 n -0000324376 00000 n -0000324470 00000 n -0000324625 00000 n -0000324721 00000 n -0000324820 00000 n -0000324975 00000 n -0000325071 00000 n -0000325167 00000 n -0000325263 00000 n -0000325362 00000 n -0000325458 00000 n -0000325552 00000 n -0000325707 00000 n -0000325928 00000 n -0000326024 00000 n -0000326179 00000 n -0000326282 00000 n -0000326378 00000 n -0000326474 00000 n -0000326629 00000 n -0000326784 00000 n -0000326880 00000 n -0000326974 00000 n -0000327098 00000 n -0000327383 00000 n -0000327479 00000 n -0000327634 00000 n -0000327733 00000 n -0000327832 00000 n -0000327928 00000 n -0000328024 00000 n -0000328179 00000 n -0000328278 00000 n -0000328374 00000 n -0000328473 00000 n -0000328569 00000 n -0000328665 00000 n -0000328763 00000 n -0000328908 00000 n -0000329272 00000 n -0000329349 00000 n -0000329434 00000 n -0000329584 00000 n -0000329661 00000 n -0000329738 00000 n -0000329815 00000 n -0000329892 00000 n -0000329977 00000 n -0000330125 00000 n -0000330210 00000 n -0000330358 00000 n -0000330435 00000 n -0000330512 00000 n -0000330589 00000 n -0000330666 00000 n -0000330743 00000 n -0000330828 00000 n -0000330976 00000 n -0000331160 00000 n -0000331308 00000 n -0000331458 00000 n -0000331606 00000 n -0000331754 00000 n -0000331905 00000 n -0000332053 00000 n -0000332201 00000 n -0000332353 00000 n -0000332503 00000 n -0000332653 00000 n -0000332800 00000 n -0000332949 00000 n -0000333026 00000 n -0000333103 00000 n -0000333180 00000 n -0000333257 00000 n -0000333342 00000 n -0000333489 00000 n -0000333601 00000 n -0000333751 00000 n -0000333900 00000 n -0000334049 00000 n -0000334198 00000 n -0000334275 00000 n -0000334352 00000 n -0000334429 00000 n -0000334514 00000 n -0000334661 00000 n -0000334773 00000 n -0000334923 00000 n -0000335072 00000 n -0000335221 00000 n -0000335370 00000 n -0000335447 00000 n -0000335524 00000 n -0000335609 00000 n -0000335756 00000 n -0000335850 00000 n -0000335997 00000 n -0000336146 00000 n -0000336231 00000 n -0000336378 00000 n -0000336455 00000 n -0000336556 00000 n -0000336653 00000 n -0000336849 00000 n -0000337003 00000 n -0000337098 00000 n -0000337202 00000 n -0000337356 00000 n -0000337510 00000 n -0000337605 00000 n -0000337700 00000 n -0000337854 00000 n -0000337999 00000 n -0000338507 00000 n -0000338584 00000 n -0000338678 00000 n -0000338825 00000 n -0000338974 00000 n -0000339051 00000 n -0000339136 00000 n -0000339283 00000 n -0000339368 00000 n -0000339515 00000 n -0000339592 00000 n -0000339669 00000 n -0000339746 00000 n -0000339831 00000 n -0000339978 00000 n -0000340099 00000 n -0000340264 00000 n -0000340414 00000 n -0000340561 00000 n -0000340708 00000 n -0000340857 00000 n -0000340934 00000 n -0000341011 00000 n -0000341088 00000 n -0000341165 00000 n -0000341250 00000 n -0000341397 00000 n -0000341500 00000 n -0000341650 00000 n -0000341799 00000 n -0000341948 00000 n -0000342025 00000 n -0000342102 00000 n -0000342187 00000 n -0000342334 00000 n -0000342419 00000 n -0000342566 00000 n -0000342643 00000 n -0000342720 00000 n -0000342805 00000 n -0000342952 00000 n -0000343082 00000 n -0000343256 00000 n -0000343406 00000 n -0000343556 00000 n -0000343703 00000 n -0000343850 00000 n -0000343997 00000 n -0000344074 00000 n -0000344151 00000 n -0000344236 00000 n -0000344383 00000 n -0000344513 00000 n -0000344672 00000 n -0000344822 00000 n -0000344969 00000 n -0000345115 00000 n -0000345264 00000 n -0000345410 00000 n -0000345487 00000 n -0000345564 00000 n -0000345641 00000 n -0000345726 00000 n -0000345872 00000 n -0000345966 00000 n -0000346112 00000 n -0000346260 00000 n -0000346337 00000 n -0000346414 00000 n -0000346499 00000 n -0000346645 00000 n -0000346739 00000 n -0000346885 00000 n -0000347033 00000 n -0000347118 00000 n -0000347264 00000 n -0000347385 00000 n -0000347560 00000 n -0000347712 00000 n -0000347860 00000 n -0000348008 00000 n -0000348158 00000 n -0000348235 00000 n -0000348320 00000 n -0000348468 00000 n -0000348598 00000 n -0000348761 00000 n -0000348913 00000 n -0000349061 00000 n -0000349209 00000 n -0000349360 00000 n -0000349508 00000 n -0000349585 00000 n -0000349662 00000 n -0000349747 00000 n -0000349895 00000 n -0000349989 00000 n -0000350137 00000 n -0000350287 00000 n -0000350372 00000 n -0000350520 00000 n -0000350597 00000 n -0000350699 00000 n -0000350797 00000 n -0000351027 00000 n -0000351123 00000 n -0000351234 00000 n -0000351353 00000 n -0000351449 00000 n -0000351604 00000 n -0000351700 00000 n -0000351855 00000 n -0000351958 00000 n -0000352077 00000 n -0000352175 00000 n -0000352422 00000 n -0000352520 00000 n -0000352614 00000 n -0000352710 00000 n -0000352809 00000 n -0000352905 00000 n -0000353028 00000 n -0000353124 00000 n -0000353235 00000 n -0000353390 00000 n -0000353486 00000 n -0000353637 00000 n -0000353792 00000 n -0000353885 00000 n -0000354004 00000 n -0000354139 00000 n -0000354235 00000 n -0000354330 00000 n -0000354423 00000 n -0000354542 00000 n -0000354669 00000 n -0000354765 00000 n -0000354860 00000 n -0000354953 00000 n -0000355072 00000 n -0000355207 00000 n -0000355303 00000 n -0000355398 00000 n -0000355504 00000 n -0000355658 00000 n -0000355780 00000 n -0000356039 00000 n -0000356134 00000 n -0000356229 00000 n -0000356383 00000 n -0000356487 00000 n -0000356582 00000 n -0000356677 00000 n -0000356772 00000 n -0000356867 00000 n -0000356962 00000 n -0000357116 00000 n -0000357214 00000 n -0000357309 00000 n -0000357404 00000 n -0000357612 00000 n -0000357707 00000 n -0000357802 00000 n -0000357909 00000 n -0000358004 00000 n -0000358158 00000 n -0000358253 00000 n -0000358407 00000 n -0000358511 00000 n -0000358606 00000 n -0000358751 00000 n -0000359412 00000 n -0000359489 00000 n -0000359583 00000 n -0000359730 00000 n -0000359879 00000 n -0000359956 00000 n -0000360041 00000 n -0000360188 00000 n -0000360291 00000 n -0000360438 00000 n -0000360588 00000 n -0000360735 00000 n -0000360812 00000 n -0000360897 00000 n -0000361044 00000 n -0000361129 00000 n -0000361276 00000 n -0000361353 00000 n -0000361430 00000 n -0000361515 00000 n -0000361662 00000 n -0000361774 00000 n -0000361924 00000 n -0000362073 00000 n -0000362223 00000 n -0000362370 00000 n -0000362447 00000 n -0000362524 00000 n -0000362609 00000 n -0000362756 00000 n -0000362859 00000 n -0000363006 00000 n -0000363156 00000 n -0000363303 00000 n -0000363380 00000 n -0000363457 00000 n -0000363542 00000 n -0000363689 00000 n -0000363801 00000 n -0000363951 00000 n -0000364100 00000 n -0000364249 00000 n -0000364398 00000 n -0000364475 00000 n -0000364552 00000 n -0000364629 00000 n -0000364714 00000 n -0000364860 00000 n -0000364954 00000 n -0000365100 00000 n -0000365248 00000 n -0000365325 00000 n -0000365410 00000 n -0000365556 00000 n -0000365677 00000 n -0000365823 00000 n -0000365972 00000 n -0000366118 00000 n -0000366267 00000 n -0000366413 00000 n -0000366490 00000 n -0000366575 00000 n -0000366721 00000 n -0000366824 00000 n -0000366972 00000 n -0000367123 00000 n -0000367271 00000 n -0000367348 00000 n -0000367425 00000 n -0000367510 00000 n -0000367658 00000 n -0000367752 00000 n -0000367900 00000 n -0000368050 00000 n -0000368135 00000 n -0000368283 00000 n -0000368377 00000 n -0000368525 00000 n -0000368675 00000 n -0000368752 00000 n -0000368837 00000 n -0000368985 00000 n -0000369097 00000 n -0000369249 00000 n -0000369399 00000 n -0000369549 00000 n -0000369699 00000 n -0000369776 00000 n -0000369853 00000 n -0000369938 00000 n -0000370086 00000 n -0000370207 00000 n -0000370355 00000 n -0000370506 00000 n -0000370658 00000 n -0000370808 00000 n -0000370958 00000 n -0000371035 00000 n -0000371112 00000 n -0000371197 00000 n -0000371345 00000 n -0000371457 00000 n -0000371609 00000 n -0000371759 00000 n -0000371910 00000 n -0000372058 00000 n -0000372135 00000 n -0000372212 00000 n -0000372289 00000 n -0000372374 00000 n -0000372522 00000 n -0000372616 00000 n -0000372764 00000 n -0000372914 00000 n -0000372991 00000 n -0000373076 00000 n -0000373224 00000 n -0000373327 00000 n -0000373475 00000 n -0000373626 00000 n -0000373774 00000 n -0000373851 00000 n -0000373936 00000 n -0000374084 00000 n -0000374187 00000 n -0000374335 00000 n -0000374486 00000 n -0000374634 00000 n -0000374711 00000 n -0000374788 00000 n -0000374873 00000 n -0000375021 00000 n -0000375115 00000 n -0000375263 00000 n -0000375413 00000 n -0000375498 00000 n -0000375646 00000 n -0000375723 00000 n -0000375825 00000 n -0000375923 00000 n -0000376089 00000 n -0000376185 00000 n -0000376284 00000 n -0000376383 00000 n -0000376490 00000 n -0000376586 00000 n -0000376741 00000 n -0000376994 00000 n -0000377101 00000 n -0000377204 00000 n -0000377315 00000 n -0000377422 00000 n -0000377577 00000 n -0000377684 00000 n -0000377780 00000 n -0000377876 00000 n -0000377972 00000 n -0000378126 00000 n -0000378244 00000 n -0000378389 00000 n -0000378543 00000 n -0000378697 00000 n -0000378851 00000 n -0000379005 00000 n -0000379098 00000 n -0000379235 00000 n -0000379340 00000 n -0000379553 00000 n -0000379637 00000 n -0000379915 00000 n -0000380008 00000 n -0000380163 00000 n -0000380258 00000 n -0000380395 00000 n -0000380493 00000 n -0000380586 00000 n -0000380723 00000 n -0000380818 00000 n -0000380955 00000 n -0000381065 00000 n -0000381158 00000 n -0000381295 00000 n -0000381390 00000 n -0000381527 00000 n -0000381634 00000 n -0000381727 00000 n -0000381864 00000 n -0000381959 00000 n -0000382096 00000 n -0000382203 00000 n -0000382296 00000 n -0000382451 00000 n -0000382546 00000 n -0000382683 00000 n -0000382784 00000 n -0000382877 00000 n -0000383014 00000 n -0000383109 00000 n -0000383246 00000 n -0000383359 00000 n -0000383452 00000 n -0000383589 00000 n -0000383684 00000 n -0000383821 00000 n -0000383934 00000 n -0000384027 00000 n -0000384191 00000 n -0000384286 00000 n -0000384381 00000 n -0000384545 00000 n -0000384658 00000 n -0000384765 00000 n -0000384858 00000 n -0000385034 00000 n -0000385129 00000 n -0000385224 00000 n -0000385319 00000 n -0000385495 00000 n -0000385596 00000 n -0000385697 00000 n -0000385795 00000 n -0000385888 00000 n -0000386025 00000 n -0000386120 00000 n -0000386257 00000 n -0000386367 00000 n -0000386460 00000 n -0000386606 00000 n -0000386770 00000 n -0000386874 00000 n -0000386973 00000 n -0000387066 00000 n -0000387220 00000 n -0000387314 00000 n -0000387451 00000 n -0000387550 00000 n -0000387634 00000 n -0000387912 00000 n -0000387996 00000 n -0000388274 00000 n -0000388361 00000 n -0000388454 00000 n -0000388617 00000 n -0000388713 00000 n -0000388894 00000 n -0000388990 00000 n -0000389135 00000 n -0000389231 00000 n -0000389327 00000 n -0000389414 00000 n -0000389498 00000 n -0000389759 00000 n -0000389848 00000 n -0000389995 00000 n -0000390323 00000 n -0000390478 00000 n -0000390574 00000 n -0000390670 00000 n -0000390769 00000 n -0000390879 00000 n -0000390974 00000 n -0000391072 00000 n -0000391167 00000 n -0000391321 00000 n -0000391416 00000 n -0000391511 00000 n -0000391609 00000 n -0000391704 00000 n -0000391802 00000 n -0000391897 00000 n -0000392051 00000 n -0000392144 00000 n -0000392280 00000 n -0000392375 00000 n -0000392470 00000 n -0000392624 00000 n -0000392739 00000 n -0000392965 00000 n -0000393119 00000 n -0000393212 00000 n -0000393366 00000 n -0000393459 00000 n -0000393613 00000 n -0000393706 00000 n -0000393799 00000 n -0000393953 00000 n -0000394046 00000 n -0000394178 00000 n -0000394316 00000 n -0000394470 00000 n -0000394624 00000 n -0000394720 00000 n -0000394991 00000 n -0000395087 00000 n -0000395182 00000 n -0000395277 00000 n -0000395374 00000 n -0000395537 00000 n -0000395691 00000 n -0000395807 00000 n -0000395902 00000 n -0000395999 00000 n -0000396093 00000 n -0000396226 00000 n -0000396332 00000 n -0000396486 00000 n -0000396631 00000 n -0000396778 00000 n -0000396871 00000 n -0000396991 00000 n -0000397092 00000 n -0000397185 00000 n -0000397279 00000 n -0000397372 00000 n -0000397480 00000 n -0000397573 00000 n -0000397667 00000 n -0000397792 00000 n -0000397885 00000 n -0000397995 00000 n -0000398098 00000 n -0000398240 00000 n -0000398333 00000 n -0000398426 00000 n -0000398527 00000 n -0000398624 00000 n -0000398779 00000 n -0000398872 00000 n -0000398977 00000 n -0000399071 00000 n -0000399164 00000 n -0000399263 00000 n -0000399357 00000 n -0000399450 00000 n -0000399546 00000 n -0000399640 00000 n -0000399772 00000 n -0000399869 00000 n -0000399968 00000 n -0000400064 00000 n -0000400414 00000 n -0000400513 00000 n -0000400612 00000 n -0000400711 00000 n -0000400810 00000 n -0000400909 00000 n -0000401008 00000 n -0000401107 00000 n -0000401206 00000 n -0000401309 00000 n -0000401408 00000 n -0000401571 00000 n -0000401727 00000 n -0000401820 00000 n -0000401926 00000 n -0000402025 00000 n -0000402120 00000 n -0000402213 00000 n -0000402319 00000 n -0000402426 00000 n -0000402520 00000 n -0000402613 00000 n -0000402718 00000 n -0000402816 00000 n -0000402910 00000 n -0000403002 00000 n -0000403197 00000 n -0000403310 00000 n -0000403411 00000 n -0000403514 00000 n -0000403659 00000 n -0000403757 00000 n -0000403911 00000 n -0000404012 00000 n -0000404110 00000 n -0000404228 00000 n -0000404352 00000 n -0000404450 00000 n -0000404604 00000 n -0000404727 00000 n -0000404827 00000 n -0000404982 00000 n -0000405075 00000 n -0000405174 00000 n -0000405268 00000 n -0000405361 00000 n -0000405538 00000 n -0000405633 00000 n -0000405728 00000 n -0000405823 00000 n -0000405918 00000 n -0000406013 00000 n -0000406108 00000 n -0000406202 00000 n -0000406295 00000 n -0000406479 00000 n -0000406574 00000 n -0000406669 00000 n -0000406764 00000 n -0000406859 00000 n -0000406954 00000 n -0000407049 00000 n -0000407143 00000 n -0000407236 00000 n -0000407326 00000 n -0000407419 00000 n -0000407556 00000 n -0000407666 00000 n -0000407760 00000 n -0000407854 00000 n -0000407948 00000 n -0000408042 00000 n -0000408131 00000 n -0000408277 00000 n -0000408484 00000 n -0000408639 00000 n -0000408733 00000 n -0000408829 00000 n -0000408925 00000 n -0000409021 00000 n -0000409117 00000 n -0000409213 00000 n -0000409351 00000 n -0000409450 00000 n -0000409561 00000 n -0000409676 00000 n -0000409769 00000 n -0000409906 00000 n -0000410106 00000 n -0000410237 00000 n -0000410333 00000 n -0000410464 00000 n -0000410560 00000 n -0000410691 00000 n -0000410787 00000 n -0000410918 00000 n -0000411014 00000 n -0000411145 00000 n -0000411241 00000 n -0000411369 00000 n -0000411464 00000 n -0000411562 00000 n -0000411657 00000 n -0000411746 00000 n -0000411894 00000 n -0000412051 00000 n -0000412205 00000 n -0000412300 00000 n -0000412395 00000 n -0000412490 00000 n -0000412585 00000 n -0000412733 00000 n -0000412834 00000 n -0000412935 00000 n -0000413036 00000 n -0000413137 00000 n -0000413264 00000 n -0000413365 00000 n -0000413460 00000 n -0000413639 00000 n -0000413836 00000 n -0000413963 00000 n -0000414061 00000 n -0000414168 00000 n -0000414260 00000 n -0000414512 00000 n -0000414608 00000 n -0000414704 00000 n -0000414803 00000 n -0000414899 00000 n -0000414995 00000 n -0000415091 00000 n -0000415187 00000 n -0000415283 00000 n -0000415382 00000 n -0000415478 00000 n -0000415577 00000 n -0000415673 00000 n -0000415787 00000 n -0000416003 00000 n -0000416099 00000 n -0000416195 00000 n -0000416294 00000 n -0000416393 00000 n -0000416516 00000 n -0000416679 00000 n -0000416773 00000 n -0000416880 00000 n -0000417006 00000 n -0000417102 00000 n -0000417205 00000 n -0000417298 00000 n -0000417435 00000 n -0000417545 00000 n -0000417641 00000 n -0000417737 00000 n -0000417833 00000 n -0000417929 00000 n -0000418018 00000 n -0000418166 00000 n -0000418368 00000 n -0000418523 00000 n -0000418619 00000 n -0000418774 00000 n -0000418885 00000 n -0000418981 00000 n -0000419075 00000 n -0000419214 00000 n -0000419345 00000 n -0000419444 00000 n -0000419543 00000 n -0000419688 00000 n -0000419890 00000 n -0000420011 00000 n -0000420202 00000 n -0000420443 00000 n -0000420644 00000 n -0000420797 00000 n -0000420986 00000 n -0000421071 00000 n -0000421221 00000 n -0000421306 00000 n -0000421468 00000 n -0000421553 00000 n -0000421703 00000 n -0000421788 00000 n -0000421938 00000 n -0000422023 00000 n -0000422173 00000 n -0000422258 00000 n -0000422414 00000 n -0000422499 00000 n -0000422655 00000 n -0000422740 00000 n -0000422890 00000 n -0000422975 00000 n -0000423128 00000 n -0000423213 00000 n -0000423363 00000 n -0000423448 00000 n -0000423604 00000 n -0000423689 00000 n -0000423839 00000 n -0000423924 00000 n -0000424080 00000 n -0000424193 00000 n -0000424297 00000 n -0000424400 00000 n -0000424517 00000 n -0000424618 00000 n -0000424722 00000 n -0000424885 00000 n -0000425050 00000 n -0000425197 00000 n -0000425290 00000 n -0000425394 00000 n -0000425497 00000 n -0000425590 00000 n -0000425683 00000 n -0000425787 00000 n -0000425884 00000 n -0000425977 00000 n -0000426070 00000 n -0000426157 00000 n -0000426259 00000 n -0000426358 00000 n -0000426453 00000 n -0000426546 00000 n -0000426652 00000 n -0000426751 00000 n -0000426846 00000 n -0000426939 00000 n -0000427045 00000 n -0000427144 00000 n -0000427239 00000 n -0000427358 00000 n -0000427481 00000 n -0000427592 00000 n -0000428055 00000 n -0000428187 00000 n -0000428298 00000 n -0000428405 00000 n -0000428511 00000 n -0000428650 00000 n -0000428744 00000 n -0000428840 00000 n -0000428936 00000 n -0000429050 00000 n -0000429172 00000 n -0000429327 00000 n -0000429426 00000 n -0000429627 00000 n -0000429721 00000 n -0000429940 00000 n -0000430135 00000 n -0000430220 00000 n -0000430371 00000 n -0000430456 00000 n -0000430623 00000 n -0000430708 00000 n -0000430859 00000 n -0000430944 00000 n -0000431095 00000 n -0000431180 00000 n -0000431331 00000 n -0000431416 00000 n -0000431575 00000 n -0000431660 00000 n -0000431819 00000 n -0000431904 00000 n -0000432055 00000 n -0000432140 00000 n -0000432295 00000 n -0000432380 00000 n -0000432531 00000 n -0000432616 00000 n -0000432771 00000 n -0000432856 00000 n -0000433007 00000 n -0000433092 00000 n -0000433251 00000 n -0000433429 00000 n -0000433528 00000 n -0000433635 00000 n -0000433734 00000 n -0000433849 00000 n -0000434004 00000 n -0000434107 00000 n -0000434261 00000 n -0000434410 00000 n -0000434513 00000 n -0000434620 00000 n -0000434723 00000 n -0000434822 00000 n -0000435101 00000 n -0000435283 00000 n -0000435381 00000 n -0000435479 00000 n -0000435577 00000 n -0000435678 00000 n -0000435812 00000 n -0000435905 00000 n -0000436008 00000 n -0000436189 00000 n -0000436284 00000 n -0000436379 00000 n -0000436533 00000 n -0000436626 00000 n -0000436724 00000 n -0000436817 00000 n -0000437714 00000 n -0000437807 00000 n -0000437905 00000 n -0000438059 00000 n -0000438172 00000 n -0000438270 00000 n -0000438362 00000 n -0000438459 00000 n -0000438558 00000 n -0000438655 00000 n -0000438984 00000 n -0000439083 00000 n -0000439179 00000 n -0000439303 00000 n -0000439396 00000 n -0000439533 00000 n -0000439643 00000 n -0000439739 00000 n -0000439835 00000 n -0000439931 00000 n -0000440027 00000 n -0000440116 00000 n -0000440264 00000 n -0000440522 00000 n -0000440677 00000 n -0000440773 00000 n -0000440872 00000 n -0000440968 00000 n -0000441062 00000 n -0000441158 00000 n -0000441254 00000 n -0000441361 00000 n -0000441455 00000 n -0000441549 00000 n -0000441712 00000 n -0000441859 00000 n -0000441952 00000 n -0000442058 00000 n -0000442169 00000 n -0000442264 00000 n -0000442357 00000 n -0000442471 00000 n -0000442582 00000 n -0000442677 00000 n -0000442783 00000 n -0000442898 00000 n -0000443081 00000 n -0000443209 00000 n -0000443308 00000 n -0000443402 00000 n -0000443508 00000 n -0000443651 00000 n -0000443806 00000 n -0000443905 00000 n -0000443999 00000 n -0000444123 00000 n -0000444313 00000 n -0000444468 00000 n -0000444579 00000 n -0000444678 00000 n -0000444837 00000 n -0000444936 00000 n -0000445035 00000 n -0000445180 00000 n -0000445634 00000 n -0000445719 00000 n -0000446038 00000 n -0000446123 00000 n -0000446274 00000 n -0000446359 00000 n -0000446526 00000 n -0000446611 00000 n -0000446762 00000 n -0000446847 00000 n -0000447014 00000 n -0000447099 00000 n -0000447250 00000 n -0000447335 00000 n -0000447486 00000 n -0000447571 00000 n -0000447758 00000 n -0000447843 00000 n -0000447994 00000 n -0000448079 00000 n -0000448234 00000 n -0000448319 00000 n -0000448470 00000 n -0000448555 00000 n -0000448734 00000 n -0000448819 00000 n -0000448970 00000 n -0000449055 00000 n -0000449206 00000 n -0000449291 00000 n -0000449548 00000 n -0000449633 00000 n -0000449783 00000 n -0000449868 00000 n -0000450030 00000 n -0000450115 00000 n -0000450265 00000 n -0000450350 00000 n -0000450512 00000 n -0000450597 00000 n -0000450747 00000 n -0000450832 00000 n -0000450982 00000 n -0000451067 00000 n -0000451244 00000 n -0000451329 00000 n -0000451479 00000 n -0000451564 00000 n -0000451717 00000 n -0000451802 00000 n -0000451952 00000 n -0000452037 00000 n -0000452223 00000 n -0000452308 00000 n -0000452458 00000 n -0000452543 00000 n -0000452693 00000 n -0000452778 00000 n -0000452964 00000 n -0000453049 00000 n -0000453199 00000 n -0000453284 00000 n -0000453446 00000 n -0000453531 00000 n -0000453681 00000 n -0000453766 00000 n -0000453928 00000 n -0000454013 00000 n -0000454163 00000 n -0000454248 00000 n -0000454398 00000 n -0000454483 00000 n -0000454636 00000 n -0000454721 00000 n -0000454871 00000 n -0000454956 00000 n -0000455109 00000 n -0000455194 00000 n -0000455344 00000 n -0000455429 00000 n -0000455592 00000 n -0000455677 00000 n -0000455826 00000 n -0000455911 00000 n -0000456060 00000 n -0000456214 00000 n -0000456317 00000 n -0000456416 00000 n -0000456515 00000 n -0000456614 00000 n -0000456720 00000 n -0000456874 00000 n -0000457200 00000 n -0000457303 00000 n -0000457406 00000 n -0000457541 00000 n -0000457652 00000 n -0000457763 00000 n -0000457857 00000 n -0000457968 00000 n -0000458071 00000 n -0000458174 00000 n -0000458268 00000 n -0000458367 00000 n -0000458466 00000 n -0000458569 00000 n -0000458663 00000 n -0000458762 00000 n -0000458877 00000 n -0000458980 00000 n -0000459291 00000 n -0000459393 00000 n -0000459499 00000 n -0000459625 00000 n -0000459719 00000 n -0000459817 00000 n -0000459942 00000 n -0000460049 00000 n -0000460194 00000 n -0000460648 00000 n -0000460733 00000 n -0000461004 00000 n -0000461089 00000 n -0000461240 00000 n -0000461325 00000 n -0000461492 00000 n -0000461577 00000 n -0000461728 00000 n -0000461813 00000 n -0000461980 00000 n -0000462065 00000 n -0000462216 00000 n -0000462301 00000 n -0000462452 00000 n -0000462537 00000 n -0000462724 00000 n -0000462809 00000 n -0000462960 00000 n -0000463045 00000 n -0000463200 00000 n -0000463285 00000 n -0000463436 00000 n -0000463521 00000 n -0000463680 00000 n -0000463765 00000 n -0000463916 00000 n -0000464001 00000 n -0000464152 00000 n -0000464237 00000 n -0000464536 00000 n -0000464621 00000 n -0000464772 00000 n -0000464857 00000 n -0000465024 00000 n -0000465109 00000 n -0000465260 00000 n -0000465345 00000 n -0000465512 00000 n -0000465597 00000 n -0000465748 00000 n -0000465833 00000 n -0000465984 00000 n -0000466069 00000 n -0000466256 00000 n -0000466341 00000 n -0000466492 00000 n -0000466577 00000 n -0000466732 00000 n -0000466817 00000 n -0000466968 00000 n -0000467053 00000 n -0000467244 00000 n -0000467329 00000 n -0000467480 00000 n -0000467565 00000 n -0000467716 00000 n -0000467801 00000 n -0000467976 00000 n -0000468061 00000 n -0000468212 00000 n -0000468297 00000 n -0000468464 00000 n -0000468549 00000 n -0000468700 00000 n -0000468785 00000 n -0000468936 00000 n -0000469021 00000 n -0000469172 00000 n -0000469257 00000 n -0000469408 00000 n -0000469493 00000 n -0000469660 00000 n -0000469745 00000 n -0000469896 00000 n -0000469981 00000 n -0000470136 00000 n -0000470221 00000 n -0000470372 00000 n -0000470457 00000 n -0000470619 00000 n -0000470704 00000 n -0000470854 00000 n -0000470939 00000 n -0000471089 00000 n -0000471238 00000 n -0000471339 00000 n -0000471437 00000 n -0000471535 00000 n -0000471633 00000 n -0000471736 00000 n -0000471881 00000 n -0000471988 00000 n -0000472086 00000 n -0000472193 00000 n -0000472291 00000 n -0000472454 00000 n -0000472601 00000 n -0000472694 00000 n -0000472805 00000 n -0000472930 00000 n -0000473024 00000 n -0000473117 00000 n -0000473222 00000 n -0000473341 00000 n -0000473435 00000 n -0000473539 00000 n -0000473649 00000 n -0000473859 00000 n -0000473960 00000 n -0000474060 00000 n -0000474176 00000 n -0000474268 00000 n -0000474364 00000 n -0000474511 00000 n -0000474605 00000 n -0000474699 00000 n -0000474798 00000 n -0000474929 00000 n -0000475271 00000 n -0000475370 00000 n -0000475469 00000 n -0000475568 00000 n -0000475679 00000 n -0000475778 00000 n -0000475877 00000 n -0000475996 00000 n -0000476107 00000 n -0000476206 00000 n -0000476305 00000 n -0000476404 00000 n -0000476515 00000 n -0000476614 00000 n -0000476733 00000 n -0000476832 00000 n -0000476931 00000 n -0000477030 00000 n -0000477129 00000 n -0000477263 00000 n -0000477418 00000 n -0000477525 00000 n -0000477670 00000 n -0000477936 00000 n -0000478061 00000 n -0000478174 00000 n -0000478278 00000 n -0000478381 00000 n -0000478529 00000 n -0000478627 00000 n -0000478734 00000 n -0000478835 00000 n -0000478933 00000 n -0000479087 00000 n -0000479179 00000 n -0000479350 00000 n -0000479463 00000 n -0000479556 00000 n -0000479659 00000 n -0000479783 00000 n -0000479881 00000 n -0000479988 00000 n -0000480182 00000 n -0000480775 00000 n -0000480868 00000 n -0000480970 00000 n -0000481067 00000 n -0000481202 00000 n -0000481362 00000 n -0000481465 00000 n -0000481620 00000 n -0000481723 00000 n -0000481842 00000 n -0000481996 00000 n -0000482141 00000 n -0000482260 00000 n -0000482379 00000 n -0000482498 00000 n -0000482609 00000 n -0000482937 00000 n -0000483022 00000 n -0000483237 00000 n -0000483322 00000 n -0000483473 00000 n -0000483558 00000 n -0000483709 00000 n -0000483794 00000 n -0000483945 00000 n -0000484030 00000 n -0000484197 00000 n -0000484282 00000 n -0000484433 00000 n -0000484518 00000 n -0000484669 00000 n -0000484754 00000 n -0000484929 00000 n -0000485014 00000 n -0000485165 00000 n -0000485250 00000 n -0000485401 00000 n -0000485486 00000 n -0000485637 00000 n -0000485722 00000 n -0000485901 00000 n -0000485986 00000 n -0000486137 00000 n -0000486222 00000 n -0000486373 00000 n -0000486458 00000 n -0000486621 00000 n -0000486706 00000 n -0000486857 00000 n -0000486942 00000 n -0000487093 00000 n -0000487178 00000 n -0000487329 00000 n -0000487414 00000 n -0000487565 00000 n -0000487650 00000 n -0000487801 00000 n -0000487886 00000 n -0000488037 00000 n -0000488122 00000 n -0000488277 00000 n -0000488362 00000 n -0000488513 00000 n -0000488598 00000 n -0000488749 00000 n -0000488834 00000 n -0000488985 00000 n -0000489070 00000 n -0000489237 00000 n -0000489322 00000 n -0000489473 00000 n -0000489558 00000 n -0000489709 00000 n -0000489850 00000 n -0000489949 00000 n -0000490048 00000 n -0000490147 00000 n -0000490253 00000 n -0000490422 00000 n -0000490541 00000 n -0000490660 00000 n -0000490763 00000 n -0000490862 00000 n -0000490961 00000 n -0000491124 00000 n -0000491289 00000 n -0000491382 00000 n -0000491488 00000 n -0000491607 00000 n -0000491702 00000 n -0000491795 00000 n -0000491913 00000 n -0000492029 00000 n -0000492133 00000 n -0000492227 00000 n -0000492320 00000 n -0000492437 00000 n -0000492550 00000 n -0000492663 00000 n -0000492757 00000 n -0000492850 00000 n -0000492967 00000 n -0000493080 00000 n -0000493187 00000 n -0000493281 00000 n -0000493412 00000 n -0000493513 00000 n -0000493632 00000 n -0000493736 00000 n -0000493916 00000 n -0000494044 00000 n -0000494137 00000 n -0000494247 00000 n -0000494350 00000 n -0000494477 00000 n -0000494631 00000 n -0000494785 00000 n -0000494904 00000 n -0000495543 00000 n -0000495635 00000 n -0000495729 00000 n -0000495852 00000 n -0000496038 00000 n -0000496193 00000 n -0000496348 00000 n -0000496447 00000 n -0000496546 00000 n -0000496669 00000 n -0000496768 00000 n -0000496971 00000 n -0000497070 00000 n -0000497169 00000 n -0000497268 00000 n -0000497371 00000 n -0000497470 00000 n -0000497577 00000 n -0000497671 00000 n -0000497816 00000 n -0000498043 00000 n -0000498184 00000 n -0000498307 00000 n -0000498406 00000 n -0000498505 00000 n -0000498611 00000 n -0000498716 00000 n -0000498815 00000 n -0000499014 00000 n -0000499162 00000 n -0000499373 00000 n -0000499521 00000 n -0000499676 00000 n -0000499824 00000 n -0000499975 00000 n -0000500123 00000 n -0000500281 00000 n -0000500426 00000 n -0000500592 00000 n -0000500695 00000 n -0000500870 00000 n -0000501065 00000 n -0000501254 00000 n -0000501339 00000 n -0000501489 00000 n -0000501574 00000 n -0000501724 00000 n -0000501809 00000 n -0000501959 00000 n -0000502044 00000 n -0000502200 00000 n -0000502285 00000 n -0000502438 00000 n -0000502523 00000 n -0000502673 00000 n -0000502758 00000 n -0000502908 00000 n -0000502993 00000 n -0000503143 00000 n -0000503228 00000 n -0000503384 00000 n -0000503509 00000 n -0000503613 00000 n -0000503726 00000 n -0000503829 00000 n -0000503935 00000 n -0000504036 00000 n -0000504235 00000 n -0000504382 00000 n -0000504580 00000 n -0000504727 00000 n -0000504880 00000 n -0000505027 00000 n -0000505177 00000 n -0000505324 00000 n -0000505479 00000 n -0000505714 00000 n -0000505818 00000 n -0000505919 00000 n -0000506020 00000 n -0000506118 00000 n -0000506216 00000 n -0000506317 00000 n -0000506418 00000 n -0000506519 00000 n -0000506620 00000 n -0000506721 00000 n -0000506822 00000 n -0000506920 00000 n -0000507023 00000 n -0000507124 00000 n -0000507223 00000 n -0000507320 00000 n -0000507442 00000 n -0000507549 00000 n -0000507652 00000 n -0000507797 00000 n -0000507999 00000 n -0000508093 00000 n -0000508300 00000 n -0000508495 00000 n -0000508580 00000 n -0000508731 00000 n -0000508816 00000 n -0000508983 00000 n -0000509068 00000 n -0000509219 00000 n -0000509304 00000 n -0000509455 00000 n -0000509540 00000 n -0000509691 00000 n -0000509776 00000 n -0000509931 00000 n -0000510016 00000 n -0000510175 00000 n -0000510260 00000 n -0000510411 00000 n -0000510496 00000 n -0000510651 00000 n -0000510736 00000 n -0000510887 00000 n -0000510972 00000 n -0000511127 00000 n -0000511212 00000 n -0000511363 00000 n -0000511448 00000 n -0000511603 00000 n -0000511718 00000 n -0000511821 00000 n -0000511927 00000 n -0000512071 00000 n -0000512178 00000 n -0000512281 00000 n -0000512388 00000 n -0000512491 00000 n -0000512636 00000 n -0000512739 00000 n -0000512838 00000 n -0000512937 00000 n -0000513040 00000 n -0000513143 00000 n -0000513242 00000 n -0000513349 00000 n -0000513448 00000 n -0000513565 00000 n -0000513684 00000 n -0000513847 00000 n -0000513994 00000 n -0000514087 00000 n -0000514193 00000 n -0000514308 00000 n -0000514403 00000 n -0000514496 00000 n -0000514602 00000 n -0000514709 00000 n -0000514804 00000 n -0000514923 00000 n -0000515038 00000 n -0000515149 00000 n -0000515516 00000 n -0000515641 00000 n -0000515745 00000 n -0000515846 00000 n -0000515949 00000 n -0000516082 00000 n -0000516186 00000 n -0000516287 00000 n -0000516388 00000 n -0000516535 00000 n -0000516628 00000 n -0000516763 00000 n -0000516876 00000 n -0000517010 00000 n -0000517111 00000 n -0000517205 00000 n -0000517298 00000 n -0000517433 00000 n -0000517540 00000 n -0000517662 00000 n -0000517760 00000 n -0000517854 00000 n -0000517988 00000 n -0000518085 00000 n -0000518182 00000 n -0000518279 00000 n -0000518407 00000 n -0000518624 00000 n -0000518727 00000 n -0000518830 00000 n -0000518933 00000 n -0000519036 00000 n -0000519135 00000 n -0000519234 00000 n -0000519333 00000 n -0000519432 00000 n -0000519531 00000 n -0000519630 00000 n -0000519729 00000 n -0000519828 00000 n -0000519935 00000 n -0000520042 00000 n -0000520145 00000 n -0000520248 00000 n -0000520443 00000 n -0000520546 00000 n -0000520693 00000 n -0000520792 00000 n -0000520891 00000 n -0000520990 00000 n -0000521089 00000 n -0000521188 00000 n -0000521333 00000 n -0000521499 00000 n -0000521584 00000 n -0000521767 00000 n -0000521852 00000 n -0000522003 00000 n -0000522088 00000 n -0000522255 00000 n -0000522340 00000 n -0000522491 00000 n -0000522576 00000 n -0000522731 00000 n -0000522816 00000 n -0000522971 00000 n -0000523056 00000 n -0000523207 00000 n -0000523292 00000 n -0000523447 00000 n -0000523532 00000 n -0000523683 00000 n -0000523768 00000 n -0000523923 00000 n -0000524051 00000 n -0000524154 00000 n -0000524257 00000 n -0000524363 00000 n -0000524498 00000 n -0000524601 00000 n -0000524700 00000 n -0000524803 00000 n -0000524948 00000 n -0000525175 00000 n -0000525316 00000 n -0000525439 00000 n -0000525538 00000 n -0000525637 00000 n -0000525743 00000 n -0000525897 00000 n -0000526000 00000 n -0000526103 00000 n -0000526202 00000 n -0000526301 00000 n -0000526400 00000 n -0000526503 00000 n -0000526606 00000 n -0000526709 00000 n -0000526808 00000 n -0000526971 00000 n -0000527119 00000 n -0000527342 00000 n -0000527490 00000 n -0000527648 00000 n -0000527954 00000 n -0000528057 00000 n -0000528172 00000 n -0000528327 00000 n -0000528462 00000 n -0000528565 00000 n -0000528748 00000 n -0000528851 00000 n -0000528966 00000 n -0000529065 00000 n -0000529164 00000 n -0000529263 00000 n -0000529374 00000 n -0000529484 00000 n -0000529585 00000 n -0000529683 00000 n -0000529790 00000 n -0000529935 00000 n -0000530137 00000 n -0000530222 00000 n -0000530405 00000 n -0000530490 00000 n -0000530640 00000 n -0000530725 00000 n -0000530887 00000 n -0000530972 00000 n -0000531122 00000 n -0000531207 00000 n -0000531357 00000 n -0000531442 00000 n -0000531592 00000 n -0000531677 00000 n -0000531830 00000 n -0000531915 00000 n -0000532068 00000 n -0000532153 00000 n -0000532303 00000 n -0000532388 00000 n -0000532541 00000 n -0000532626 00000 n -0000532776 00000 n -0000532861 00000 n -0000533023 00000 n -0000533108 00000 n -0000533258 00000 n -0000533343 00000 n -0000533496 00000 n -0000533633 00000 n -0000533737 00000 n -0000533838 00000 n -0000533939 00000 n -0000534042 00000 n -0000534160 00000 n -0000534261 00000 n -0000534359 00000 n -0000534531 00000 n -0000534635 00000 n -0000534751 00000 n -0000534898 00000 n -0000534991 00000 n -0000535096 00000 n -0000535199 00000 n -0000535292 00000 n -0000535385 00000 n -0000535489 00000 n -0000535590 00000 n -0000535683 00000 n -0000535789 00000 n -0000535904 00000 n -0000536083 00000 n -0000536211 00000 n -0000536305 00000 n -0000536404 00000 n -0000536510 00000 n -0000536602 00000 n -0000536783 00000 n -0000536938 00000 n -0000537041 00000 n -0000537144 00000 n -0000537243 00000 n -0000537342 00000 n -0000537497 00000 n -0000537590 00000 n -0000537730 00000 n -0000537849 00000 n -0000537960 00000 n -0000538054 00000 n -0000538149 00000 n -0000538242 00000 n -0000538374 00000 n -0000538473 00000 n -0000538576 00000 n -0000538670 00000 n -0000538765 00000 n -0000538858 00000 n -0000538964 00000 n -0000539058 00000 n -0000539153 00000 n -0000539373 00000 n -0000539471 00000 n -0000539587 00000 n -0000539685 00000 n -0000539783 00000 n -0000539914 00000 n -0000540018 00000 n -0000540116 00000 n -0000540214 00000 n -0000540336 00000 n -0000540449 00000 n -0000540566 00000 n -0000540711 00000 n -0000540804 00000 n -0000540926 00000 n -0000541019 00000 n -0000541140 00000 n -0000541291 00000 n -0000541384 00000 n -0000541476 00000 n -0000541629 00000 n -0000541771 00000 n -0000541892 00000 n -0000542047 00000 n -0000542163 00000 n -0000542309 00000 n -0000542402 00000 n -0000542520 00000 n -0000542618 00000 n -0000542713 00000 n -0000542806 00000 n -0000542928 00000 n -0000543026 00000 n -0000543121 00000 n -0000543268 00000 n -0000543423 00000 n -0000543517 00000 n -0000543611 00000 n -0000543753 00000 n -0000544107 00000 n -0000544262 00000 n -0000544417 00000 n -0000544572 00000 n -0000544727 00000 n -0000544826 00000 n -0000544925 00000 n -0000545024 00000 n -0000545123 00000 n -0000545222 00000 n -0000545321 00000 n -0000545420 00000 n -0000545574 00000 n -0000545728 00000 n -0000545868 00000 n -0000545961 00000 n -0000546058 00000 n -0000546281 00000 n -0000546400 00000 n -0000546498 00000 n -0000546617 00000 n -0000546754 00000 n -0000546873 00000 n -0000546989 00000 n -0000547143 00000 n -0000547296 00000 n -0000547392 00000 n -0000547592 00000 n -0000547766 00000 n -0000547909 00000 n -0000548064 00000 n -0000548219 00000 n -0000548313 00000 n -0000548427 00000 n -0000548654 00000 n -0000548809 00000 n -0000548964 00000 n -0000549119 00000 n -0000549274 00000 n -0000549429 00000 n -0000549528 00000 n -0000549627 00000 n -0000549829 00000 n -0000550061 00000 n -0000550155 00000 n -0000550310 00000 n -0000550429 00000 n -0000550548 00000 n -0000550647 00000 n -0000550802 00000 n -0000550957 00000 n -0000551055 00000 n -0000551268 00000 n -0000551406 00000 n -0000551525 00000 n -0000551632 00000 n -0000551730 00000 n -0000551846 00000 n -0000552000 00000 n -0000552154 00000 n -0000552251 00000 n -0000552372 00000 n -0000552526 00000 n -0000552693 00000 n -0000552880 00000 n -0000552973 00000 n -0000553071 00000 n -0000553169 00000 n -0000553267 00000 n -0000553377 00000 n -0000553531 00000 n -0000553685 00000 n -0000553793 00000 n -0000553900 00000 n -0000554053 00000 n -0000554167 00000 n -0000554332 00000 n -0000554425 00000 n -0000554565 00000 n -0000554719 00000 n -0000554816 00000 n -0000554910 00000 n -0000555003 00000 n -0000555159 00000 n -0000555313 00000 n -0000555410 00000 n -0000555564 00000 n -0000555661 00000 n -0000555755 00000 n -0000555848 00000 n -0000555980 00000 n -0000556134 00000 n -0000556231 00000 n -0000556325 00000 n -0000556418 00000 n -0000556565 00000 n -0000556658 00000 n -0000556812 00000 n -0000556909 00000 n -0000557003 00000 n -0000557229 00000 n -0000557383 00000 n -0000557537 00000 n -0000557630 00000 n -0000557784 00000 n -0000557938 00000 n -0000558034 00000 n -0000558127 00000 n -0000558220 00000 n -0000558336 00000 n -0000558476 00000 n -0000558630 00000 n -0000559103 00000 n -0000559256 00000 n -0000559388 00000 n -0000559503 00000 n -0000559723 00000 n -0000559877 00000 n -0000560031 00000 n -0000560185 00000 n -0000560339 00000 n -0000560493 00000 n -0000560647 00000 n -0000560779 00000 n -0000560900 00000 n -0000561054 00000 n -0000561208 00000 n -0000561404 00000 n -0000561499 00000 n -0000561594 00000 n -0000561679 00000 n -0000561824 00000 n -0000561996 00000 n -0000562091 00000 n -0000562186 00000 n -0000562283 00000 n -0000562913 00000 n -0000563007 00000 n -0000563101 00000 n -0000563220 00000 n -0000563305 00000 n -0000563450 00000 n -0000563622 00000 n -0000563707 00000 n -0000563852 00000 n -0000564023 00000 n -0000564118 00000 n -0000564215 00000 n -0000564309 00000 n -0000564426 00000 n -0000564548 00000 n -0000564690 00000 n -0000564844 00000 n -0000564998 00000 n -0000565144 00000 n -0000565237 00000 n -0000565366 00000 n -0000565459 00000 n -0000565556 00000 n -0000565650 00000 n -0000565743 00000 n -0000565872 00000 n -0000565965 00000 n -0000566062 00000 n -0000566156 00000 n -0000566253 00000 n -0000566383 00000 n -0000566573 00000 n -0000566727 00000 n -0000566881 00000 n -0000566974 00000 n -0000567066 00000 n -0000567219 00000 n -0000567332 00000 n -0000567533 00000 n -0000567619 00000 n -0000567762 00000 n -0000567919 00000 n -0000568005 00000 n -0000568148 00000 n -0000568314 00000 n -0000568408 00000 n -0000568520 00000 n -0000568606 00000 n -0000568749 00000 n -0000568915 00000 n -0000569009 00000 n -0000569095 00000 n -0000569238 00000 n -0000569404 00000 n -0000569498 00000 n -0000569584 00000 n -0000569727 00000 n -0000569893 00000 n -0000569987 00000 n -0000570073 00000 n -0000570216 00000 n -0000570382 00000 n -0000570476 00000 n -0000570562 00000 n -0000570705 00000 n -0000570871 00000 n -0000570965 00000 n -0000571086 00000 n -0000571172 00000 n -0000571315 00000 n -0000571481 00000 n -0000571575 00000 n -0000571661 00000 n -0000571804 00000 n -0000571970 00000 n -0000572064 00000 n -0000572150 00000 n -0000572293 00000 n -0000572459 00000 n -0000572553 00000 n -0000572639 00000 n -0000572782 00000 n -0000572948 00000 n -0000573042 00000 n -0000573128 00000 n -0000573271 00000 n -0000573437 00000 n -0000573531 00000 n -0000573617 00000 n -0000573760 00000 n -0000573926 00000 n -0000574020 00000 n -0000574141 00000 n -0000574227 00000 n -0000574370 00000 n -0000574536 00000 n -0000574630 00000 n -0000574724 00000 n -0000574810 00000 n -0000574953 00000 n -0000575119 00000 n -0000575213 00000 n -0000575299 00000 n -0000575442 00000 n -0000575608 00000 n -0000575701 00000 n -0000575787 00000 n -0000575930 00000 n -0000576094 00000 n -0000576187 00000 n -0000576299 00000 n -0000576385 00000 n -0000576528 00000 n -0000576692 00000 n -0000576785 00000 n -0000576871 00000 n -0000577014 00000 n -0000577237 00000 n -0000577330 00000 n -0000577416 00000 n -0000577559 00000 n -0000577725 00000 n -0000577819 00000 n -0000577905 00000 n -0000578048 00000 n -0000578214 00000 n -0000578308 00000 n -0000578394 00000 n -0000578537 00000 n -0000578703 00000 n -0000578797 00000 n -0000578883 00000 n -0000579026 00000 n -0000579192 00000 n -0000579286 00000 n -0000579434 00000 n -0000579528 00000 n -0000579614 00000 n -0000579757 00000 n -0000579923 00000 n -0000580017 00000 n -0000580103 00000 n -0000580246 00000 n -0000580412 00000 n -0000580506 00000 n -0000580592 00000 n -0000580735 00000 n -0000580901 00000 n -0000580995 00000 n -0000581107 00000 n -0000581193 00000 n -0000581336 00000 n -0000581502 00000 n -0000581596 00000 n -0000581682 00000 n -0000581825 00000 n -0000581991 00000 n -0000582085 00000 n -0000582171 00000 n -0000582314 00000 n -0000582480 00000 n -0000582574 00000 n -0000582660 00000 n -0000582803 00000 n -0000582969 00000 n -0000583063 00000 n -0000583149 00000 n -0000583292 00000 n -0000583458 00000 n -0000583552 00000 n -0000583655 00000 n -0000583741 00000 n -0000583884 00000 n -0000584050 00000 n -0000584144 00000 n -0000584230 00000 n -0000584373 00000 n -0000584539 00000 n -0000584633 00000 n -0000584719 00000 n -0000584862 00000 n -0000585028 00000 n -0000585122 00000 n -0000585208 00000 n -0000585351 00000 n -0000585517 00000 n -0000585611 00000 n -0000585705 00000 n -0000585791 00000 n -0000585934 00000 n -0000586100 00000 n -0000586194 00000 n -0000586280 00000 n -0000586423 00000 n -0000586589 00000 n -0000586683 00000 n -0000586769 00000 n -0000586912 00000 n -0000587078 00000 n -0000587172 00000 n -0000587258 00000 n -0000587401 00000 n -0000587567 00000 n -0000587661 00000 n -0000587764 00000 n -0000587850 00000 n -0000587993 00000 n -0000588159 00000 n -0000588253 00000 n -0000588339 00000 n -0000588482 00000 n -0000588648 00000 n -0000588742 00000 n -0000588828 00000 n -0000588971 00000 n -0000589137 00000 n -0000589231 00000 n -0000589317 00000 n -0000589460 00000 n -0000589626 00000 n -0000589720 00000 n -0000589832 00000 n -0000589918 00000 n -0000590061 00000 n -0000590227 00000 n -0000590321 00000 n -0000590424 00000 n -0000590510 00000 n -0000590653 00000 n -0000590819 00000 n -0000590913 00000 n -0000590999 00000 n -0000591142 00000 n -0000591308 00000 n -0000591402 00000 n -0000591488 00000 n -0000591631 00000 n -0000591797 00000 n -0000591891 00000 n -0000591977 00000 n -0000592120 00000 n -0000592284 00000 n -0000592377 00000 n -0000592463 00000 n -0000592606 00000 n -0000592770 00000 n -0000592863 00000 n -0000592949 00000 n -0000593092 00000 n -0000593256 00000 n -0000593349 00000 n -0000593456 00000 n -0000593664 00000 n -0000593757 00000 n -0000593850 00000 n -0000593943 00000 n -0000594036 00000 n -0000594129 00000 n -0000594222 00000 n -0000594313 00000 n -0000594424 00000 n -0000594595 00000 n -0000594766 00000 n -0000594887 00000 n -0000595058 00000 n -0000595229 00000 n -0000595400 00000 n -0000595490 00000 n -0000595550 00000 n -0000595610 00000 n -0000595670 00000 n -0000595730 00000 n -0000595790 00000 n -0000595850 00000 n -0000595910 00000 n -0000595970 00000 n -0000596030 00000 n -0000596091 00000 n -0000596152 00000 n -0000596213 00000 n -0000596274 00000 n -0000596335 00000 n -0000596396 00000 n -0000596457 00000 n -0000596518 00000 n -0000596579 00000 n -0000596640 00000 n -0000596701 00000 n -0000596762 00000 n -0000596823 00000 n -0000596884 00000 n -0000596945 00000 n -0000597006 00000 n -0000597067 00000 n -0000597128 00000 n -0000597189 00000 n -0000597250 00000 n -0000597311 00000 n -0000597372 00000 n -0000597433 00000 n -0000597494 00000 n -0000597555 00000 n -0000597616 00000 n -0000597677 00000 n -0000597738 00000 n -0000597799 00000 n -0000597860 00000 n -0000597921 00000 n -0000597982 00000 n -0000598043 00000 n -0000598104 00000 n -0000598165 00000 n -0000598226 00000 n -0000598287 00000 n -0000598348 00000 n -0000598409 00000 n -0000598593 00000 n -0000599339 00000 n -0000599431 00000 n -0000599686 00000 n -0000601251 00000 n -0000607801 00000 n -0000607988 00000 n -0000609151 00000 n -0000609243 00000 n -0000609502 00000 n -0000611612 00000 n -0000620396 00000 n -0000620582 00000 n -0000621445 00000 n -0000621537 00000 n -0000621798 00000 n -0000623535 00000 n -0000632415 00000 n -0000632605 00000 n -0000633280 00000 n -0000633372 00000 n -0000633638 00000 n -0000635021 00000 n -0000641745 00000 n -0000641913 00000 n -0000642183 00000 n -0000642275 00000 n -0000642555 00000 n -0000643972 00000 n -0000653610 00000 n -0000653789 00000 n -0000655702 00000 n -0000655794 00000 n -0000656046 00000 n -0000659375 00000 n -0000680853 00000 n -0000681041 00000 n -0000681297 00000 n -0000681384 00000 n -0000681638 00000 n -0000682339 00000 n -0000682789 00000 n -0000682962 00000 n -0000683236 00000 n -0000683325 00000 n -0000683619 00000 n -0000684418 00000 n -0000688825 00000 n -0000688865 00000 n -0000688905 00000 n -0000689265 00000 n -0000689689 00000 n -0000689744 00000 n -0000689799 00000 n -0000689854 00000 n -0000689910 00000 n -0000689965 00000 n -0000690020 00000 n -0000690075 00000 n -0000690130 00000 n -0000690185 00000 n -0000690240 00000 n -0000690295 00000 n -0000690350 00000 n -0000690405 00000 n -0000690461 00000 n -0000690516 00000 n -0000690572 00000 n -0000690628 00000 n -0000690684 00000 n -0000690740 00000 n -0000690795 00000 n -0000690851 00000 n -0000690906 00000 n -0000690961 00000 n -0000691017 00000 n -0000691071 00000 n -0000691124 00000 n -0000691179 00000 n -0000691234 00000 n -0000691289 00000 n -0000691344 00000 n -0000691399 00000 n -0000691454 00000 n -0000691509 00000 n -0000691564 00000 n -0000691620 00000 n -0000691675 00000 n -0000691730 00000 n -0000691785 00000 n -0000691840 00000 n -0000691896 00000 n -0000691951 00000 n -0000692006 00000 n -0000692061 00000 n -0000692116 00000 n -0000692171 00000 n -0000692227 00000 n -0000692282 00000 n -0000692337 00000 n -0000692392 00000 n -0000692447 00000 n -0000692503 00000 n -0000692558 00000 n -0000692614 00000 n -0000692670 00000 n -0000692726 00000 n -0000692783 00000 n -0000692839 00000 n -0000692894 00000 n -0000692949 00000 n -0000693004 00000 n -0000693059 00000 n -0000693115 00000 n -0000693170 00000 n -0000693226 00000 n -0000693281 00000 n -0000693336 00000 n -0000693391 00000 n -0000693446 00000 n -0000693501 00000 n -0000693556 00000 n -0000693612 00000 n -0000693668 00000 n -0000693724 00000 n -0000693779 00000 n -0000693834 00000 n -0000693889 00000 n -0000693945 00000 n -0000694000 00000 n -0000694055 00000 n -0000694110 00000 n -0000694165 00000 n -0000694220 00000 n -0000694275 00000 n -0000694331 00000 n -0000694387 00000 n -0000694443 00000 n -0000694498 00000 n -0000694553 00000 n -0000694608 00000 n -0000694663 00000 n -0000694718 00000 n -0000694774 00000 n -0000694830 00000 n -0000694885 00000 n -0000694940 00000 n -0000694995 00000 n -0000695050 00000 n -0000695104 00000 n -0000695159 00000 n -0000695214 00000 n -0000695269 00000 n -0000695324 00000 n -0000695379 00000 n -0000695435 00000 n -0000695490 00000 n -0000695545 00000 n -0000695600 00000 n -0000695655 00000 n -0000695710 00000 n -0000695766 00000 n -0000695822 00000 n -0000695877 00000 n -0000695932 00000 n -0000695987 00000 n -0000696043 00000 n -0000696099 00000 n -0000696154 00000 n -0000696209 00000 n -0000696264 00000 n -0000696320 00000 n -0000696376 00000 n -0000696432 00000 n -0000696489 00000 n -0000696545 00000 n -0000696601 00000 n -0000696656 00000 n -0000696711 00000 n -0000696766 00000 n -0000696821 00000 n -0000696876 00000 n -0000696932 00000 n -0000696987 00000 n -0000697042 00000 n -0000697098 00000 n -0000697154 00000 n -0000697209 00000 n -0000697264 00000 n -0000697319 00000 n -0000697374 00000 n -0000697429 00000 n -0000697484 00000 n -0000697540 00000 n -0000697595 00000 n -0000697650 00000 n -0000697705 00000 n -0000697761 00000 n -0000697816 00000 n -0000697872 00000 n -0000697927 00000 n -0000697983 00000 n -0000698038 00000 n -0000698093 00000 n -0000698148 00000 n -0000698203 00000 n -0000698258 00000 n -0000698313 00000 n -0000698368 00000 n -0000698423 00000 n -0000698478 00000 n -0000698533 00000 n -0000698588 00000 n -0000698643 00000 n -0000698699 00000 n -0000698755 00000 n -0000698811 00000 n -0000698866 00000 n -0000698921 00000 n -0000698976 00000 n -0000699031 00000 n -0000699086 00000 n -0000699141 00000 n -0000699196 00000 n -0000699251 00000 n -0000699306 00000 n -0000699361 00000 n -0000699416 00000 n -0000699471 00000 n -0000699526 00000 n -0000699582 00000 n -0000699638 00000 n -0000699694 00000 n -0000699749 00000 n -0000699804 00000 n -0000699859 00000 n -0000699914 00000 n -0000699969 00000 n -0000700024 00000 n -0000700080 00000 n -0000700135 00000 n -0000700190 00000 n -0000700245 00000 n -0000700301 00000 n -0000700357 00000 n -0000700413 00000 n -0000700469 00000 n -0000700524 00000 n -0000700580 00000 n -0000700635 00000 n -0000700691 00000 n -0000700747 00000 n -0000700803 00000 n -0000700860 00000 n -0000700916 00000 n -0000700972 00000 n -0000701027 00000 n -0000701083 00000 n -0000701138 00000 n -0000701193 00000 n -0000701249 00000 n -0000701306 00000 n -0000701362 00000 n -0000701419 00000 n -0000701476 00000 n -0000701533 00000 n -0000701589 00000 n -0000701645 00000 n -0000701701 00000 n -0000701757 00000 n -0000701813 00000 n -0000701870 00000 n -0000701927 00000 n -0000701984 00000 n -0000702039 00000 n -0000702095 00000 n -0000702151 00000 n -0000702206 00000 n -0000702263 00000 n -0000702318 00000 n -0000702373 00000 n -0000702431 00000 n -0000702488 00000 n -0000702544 00000 n -0000702601 00000 n -0000702658 00000 n -0000702714 00000 n -0000702770 00000 n -0000702826 00000 n -0000702882 00000 n -0000702937 00000 n -0000702993 00000 n -0000703049 00000 n -0000703105 00000 n -0000703159 00000 n -0000703215 00000 n -0000703273 00000 n -0000703330 00000 n -0000703387 00000 n -0000703442 00000 n -0000703498 00000 n -0000703554 00000 n -0000703609 00000 n -0000703666 00000 n -0000703722 00000 n -0000703777 00000 n -0000703833 00000 n -0000703889 00000 n -0000703946 00000 n -0000704002 00000 n -0000704058 00000 n -0000704114 00000 n -0000704170 00000 n -0000704225 00000 n -0000704282 00000 n -0000704339 00000 n -0000704395 00000 n -0000704451 00000 n -0000704507 00000 n -0000704562 00000 n -0000704618 00000 n -0000704674 00000 n -0000704730 00000 n -0000704786 00000 n -0000704842 00000 n -0000704898 00000 n -0000704955 00000 n -0000705313 00000 n -0000708227 00000 n -0000708515 00000 n -0000708875 00000 n -0000709200 00000 n -0000709524 00000 n -0000709911 00000 n -0000710298 00000 n -0000710602 00000 n -0000710893 00000 n -0000711167 00000 n -0000711452 00000 n -0000711839 00000 n -0000712238 00000 n -0000712568 00000 n -0000712892 00000 n -0000713270 00000 n -0000713604 00000 n -0000713936 00000 n -0000714325 00000 n -0000714707 00000 n -0000715048 00000 n -0000715393 00000 n -0000715703 00000 n -0000716015 00000 n -0000716332 00000 n -0000716674 00000 n -0000717004 00000 n -0000717398 00000 n -0000717754 00000 n -0000718055 00000 n -0000718382 00000 n -0000718727 00000 n -0000719071 00000 n -0000719680 00000 n -0000735800 00000 n -0000736144 00000 n -0000736469 00000 n -0000736788 00000 n -0000737179 00000 n -0000737525 00000 n -0000737847 00000 n -0000738130 00000 n -0000738461 00000 n -0000738833 00000 n -0000739226 00000 n -0000739662 00000 n -0000740044 00000 n -0000740332 00000 n -0000740694 00000 n -0000741034 00000 n -0000741377 00000 n -0000741715 00000 n -0000741998 00000 n -0000742265 00000 n -0000742757 00000 n -0000752615 00000 n -0000752795 00000 n -0000752977 00000 n -0000753159 00000 n -0000753339 00000 n -0000753521 00000 n -0000753944 00000 n -0000758522 00000 n -0000758713 00000 n -0000758905 00000 n -0000759085 00000 n -0000759265 00000 n -0000759447 00000 n -0000759629 00000 n -0000759810 00000 n -0000759993 00000 n -0000760176 00000 n -0000760359 00000 n -0000760540 00000 n -0000760998 00000 n -0000766535 00000 n -0000766718 00000 n -0000766901 00000 n -0000767086 00000 n -0000767269 00000 n -0000767452 00000 n -0000767633 00000 n -0000767844 00000 n -0000768056 00000 n -0000768268 00000 n -0000768478 00000 n -0000768671 00000 n -0000769110 00000 n -0000774558 00000 n -0000774752 00000 n -0000774933 00000 n -0000775116 00000 n -0000775300 00000 n -0000775483 00000 n -0000775664 00000 n -0000775845 00000 n -0000776026 00000 n -0000776209 00000 n -0000776393 00000 n -0000776577 00000 n -0000776761 00000 n -0000776945 00000 n -0000777128 00000 n -0000777312 00000 n -0000777496 00000 n -0000778000 00000 n -0000783888 00000 n -0000784073 00000 n -0000784255 00000 n -0000784438 00000 n -0000784623 00000 n -0000784808 00000 n -0000784993 00000 n -0000785176 00000 n -0000785361 00000 n -0000785562 00000 n -0000785758 00000 n -0000786208 00000 n -0000792215 00000 n -0000792414 00000 n -0000792599 00000 n -0000792996 00000 n -0000799004 00000 n -0000799194 00000 n -0000799544 00000 n -0000806569 00000 n -0000806906 00000 n -0000813126 00000 n -0000813340 00000 n -0000813554 00000 n -0000813951 00000 n -0000820546 00000 n -0000820728 00000 n -0000820910 00000 n -0000821123 00000 n -0000821529 00000 n -0000827821 00000 n -0000828034 00000 n -0000828422 00000 n -0000834403 00000 n -0000834740 00000 n -0000842762 00000 n -0000842969 00000 n -0000843179 00000 n -0000843371 00000 n -0000843563 00000 n -0000843755 00000 n -0000844198 00000 n -0000851556 00000 n -0000851750 00000 n -0000851943 00000 n -0000852127 00000 n -0000852320 00000 n -0000852534 00000 n -0000852977 00000 n -0000860386 00000 n -0000860577 00000 n -0000860759 00000 n -0000861194 00000 n -0000868220 00000 n -0000868409 00000 n -0000868601 00000 n -0000868998 00000 n -0000874886 00000 n -0000875101 00000 n -0000875310 00000 n -0000875745 00000 n -0000880996 00000 n -0000881206 00000 n -0000881390 00000 n -0000881806 00000 n -0000887252 00000 n -0000887464 00000 n -0000887676 00000 n -0000887870 00000 n -0000888073 00000 n -0000888277 00000 n -0000888476 00000 n -0000888665 00000 n -0000888879 00000 n -0000889074 00000 n -0000889264 00000 n -0000889733 00000 n -0000895270 00000 n -0000895465 00000 n -0000895672 00000 n -0000895881 00000 n -0000896093 00000 n -0000896305 00000 n -0000896516 00000 n -0000896711 00000 n -0000896904 00000 n -0000897355 00000 n -0000902759 00000 n -0000902953 00000 n -0000903170 00000 n -0000903366 00000 n -0000903578 00000 n -0000903790 00000 n -0000903982 00000 n -0000904195 00000 n -0000904386 00000 n -0000904856 00000 n -0000911913 00000 n -0000912105 00000 n -0000912318 00000 n -0000912513 00000 n -0000912726 00000 n -0000912920 00000 n -0000913115 00000 n -0000913319 00000 n -0000913540 00000 n -0000913755 00000 n -0000913949 00000 n -0000914136 00000 n -0000914326 00000 n -0000914520 00000 n -0000915035 00000 n -0000921333 00000 n -0000921526 00000 n -0000921746 00000 n -0000921939 00000 n -0000922123 00000 n -0000922519 00000 n -0000927813 00000 n -0000928031 00000 n -0000928242 00000 n -0000928434 00000 n -0000928652 00000 n -0000928863 00000 n -0000929056 00000 n -0000929266 00000 n -0000929457 00000 n -0000929651 00000 n -0000929865 00000 n -0000930353 00000 n -0000935931 00000 n -0000936132 00000 n -0000936346 00000 n -0000936762 00000 n -0000941877 00000 n -0000942062 00000 n -0000942247 00000 n -0000942663 00000 n -0000947793 00000 n -0000947987 00000 n -0000948170 00000 n -0000948567 00000 n -0000953113 00000 n -0000953305 00000 n -0000953497 00000 n -0000953700 00000 n -0000953892 00000 n -0000954108 00000 n -0000954321 00000 n -0000954539 00000 n -0000954757 00000 n -0000954940 00000 n -0000955122 00000 n -0000955591 00000 n -0000961222 00000 n -0000961433 00000 n -0000961616 00000 n -0000961802 00000 n -0000961986 00000 n -0000962382 00000 n -0000967555 00000 n -0000967737 00000 n -0000967950 00000 n -0000968132 00000 n -0000968314 00000 n -0000968511 00000 n -0000968697 00000 n -0000968882 00000 n -0000969286 00000 n -0000974760 00000 n -0000974962 00000 n -0000975154 00000 n -0000975338 00000 n -0000975520 00000 n -0000975732 00000 n -0000975916 00000 n -0000976100 00000 n -0000976285 00000 n -0000976470 00000 n -0000976654 00000 n -0000976838 00000 n -0000977024 00000 n -0000977208 00000 n -0000977394 00000 n -0000977577 00000 n -0000978072 00000 n -0000984103 00000 n -0000984287 00000 n -0000984637 00000 n -0000989591 00000 n -0000989775 00000 n -0000989959 00000 n -0000990143 00000 n -0000990329 00000 n -0000990514 00000 n -0000990699 00000 n -0000990884 00000 n -0000991307 00000 n -0000997203 00000 n -0000997403 00000 n -0000997603 00000 n -0000997785 00000 n -0000997969 00000 n -0000998151 00000 n -0000998335 00000 n -0000998548 00000 n -0000998732 00000 n -0000998916 00000 n -0000999102 00000 n -0000999286 00000 n -0000999726 00000 n -0001005417 00000 n -0001005632 00000 n -0001005817 00000 n -0001006002 00000 n -0001006186 00000 n -0001006398 00000 n -0001006582 00000 n -0001006766 00000 n -0001006951 00000 n -0001007136 00000 n -0001007577 00000 n -0001013135 00000 n -0001013317 00000 n -0001013501 00000 n -0001013701 00000 n -0001013881 00000 n -0001014064 00000 n -0001014248 00000 n -0001014432 00000 n -0001014616 00000 n -0001014800 00000 n -0001014984 00000 n -0001015188 00000 n -0001015370 00000 n -0001015553 00000 n -0001015739 00000 n -0001015924 00000 n -0001016109 00000 n -0001016328 00000 n -0001016512 00000 n -0001017034 00000 n -0001023952 00000 n -0001024136 00000 n -0001024319 00000 n -0001024503 00000 n -0001024687 00000 n -0001024870 00000 n -0001025054 00000 n -0001025238 00000 n -0001025421 00000 n -0001025604 00000 n -0001025788 00000 n -0001025972 00000 n -0001026184 00000 n -0001026367 00000 n -0001026550 00000 n -0001026737 00000 n -0001026919 00000 n -0001027121 00000 n -0001027341 00000 n -0001027525 00000 n -0001027712 00000 n -0001027897 00000 n -0001028084 00000 n -0001028642 00000 n -0001035182 00000 n -0001035399 00000 n -0001035582 00000 n -0001035877 00000 n -0001036062 00000 n -0001036361 00000 n -0001036546 00000 n -0001036830 00000 n -0001037014 00000 n -0001037199 00000 n -0001037496 00000 n -0001037680 00000 n -0001038120 00000 n -0001043245 00000 n -0001043429 00000 n -0001043739 00000 n -0001043922 00000 n -0001044282 00000 n -0001044644 00000 n -0001044827 00000 n -0001045131 00000 n -0001045316 00000 n -0001045598 00000 n -0001045782 00000 n -0001045966 00000 n -0001046264 00000 n -0001046448 00000 n -0001046632 00000 n -0001046816 00000 n -0001047124 00000 n -0001047308 00000 n -0001047492 00000 n -0001047801 00000 n -0001047987 00000 n -0001048286 00000 n -0001048472 00000 n -0001048755 00000 n -0001048940 00000 n -0001049126 00000 n -0001049418 00000 n -0001049605 00000 n -0001050170 00000 n -0001055552 00000 n -0001055737 00000 n -0001056037 00000 n -0001056222 00000 n -0001056528 00000 n -0001056712 00000 n -0001057017 00000 n -0001057324 00000 n -0001057508 00000 n -0001057797 00000 n -0001058088 00000 n -0001058273 00000 n -0001058573 00000 n -0001058757 00000 n -0001059064 00000 n -0001059248 00000 n -0001059530 00000 n -0001059714 00000 n -0001060012 00000 n -0001060196 00000 n -0001060502 00000 n -0001060686 00000 n -0001060997 00000 n -0001061181 00000 n -0001061482 00000 n -0001061667 00000 n -0001061963 00000 n -0001062148 00000 n -0001062443 00000 n -0001062630 00000 n -0001062914 00000 n -0001063506 00000 n -0001068805 00000 n -0001068990 00000 n -0001069281 00000 n -0001069466 00000 n -0001069650 00000 n -0001069966 00000 n -0001070151 00000 n -0001070453 00000 n -0001070639 00000 n -0001070824 00000 n -0001071144 00000 n -0001071466 00000 n -0001071650 00000 n -0001071930 00000 n -0001072114 00000 n -0001072298 00000 n -0001072582 00000 n -0001072766 00000 n -0001073062 00000 n -0001073246 00000 n -0001073554 00000 n -0001073740 00000 n -0001073925 00000 n -0001074110 00000 n -0001074296 00000 n -0001074591 00000 n -0001074777 00000 n -0001075333 00000 n -0001080520 00000 n -0001080705 00000 n -0001081001 00000 n -0001081185 00000 n -0001081476 00000 n -0001081660 00000 n -0001081845 00000 n -0001082143 00000 n -0001082328 00000 n -0001082687 00000 n -0001083048 00000 n -0001083232 00000 n -0001083531 00000 n -0001083715 00000 n -0001084028 00000 n -0001084343 00000 n -0001084527 00000 n -0001084817 00000 n -0001085001 00000 n -0001085299 00000 n -0001085483 00000 n -0001085784 00000 n -0001086087 00000 n -0001086272 00000 n -0001086572 00000 n -0001086757 00000 n -0001087060 00000 n -0001087246 00000 n -0001087546 00000 n -0001087732 00000 n -0001088035 00000 n -0001088221 00000 n -0001088511 00000 n -0001089121 00000 n -0001094471 00000 n -0001094656 00000 n -0001094940 00000 n -0001095124 00000 n -0001095421 00000 n -0001095605 00000 n -0001095887 00000 n -0001096072 00000 n -0001096354 00000 n -0001096539 00000 n -0001096807 00000 n -0001096991 00000 n -0001097298 00000 n -0001097482 00000 n -0001097765 00000 n -0001097949 00000 n -0001098232 00000 n -0001098416 00000 n -0001098750 00000 n -0001099085 00000 n -0001099269 00000 n -0001099551 00000 n -0001099737 00000 n -0001100037 00000 n -0001100221 00000 n -0001100521 00000 n -0001100706 00000 n -0001101010 00000 n -0001101196 00000 n -0001101485 00000 n -0001101671 00000 n -0001102263 00000 n -0001107462 00000 n -0001107762 00000 n -0001107946 00000 n -0001108241 00000 n -0001108425 00000 n -0001108719 00000 n -0001108903 00000 n -0001109197 00000 n -0001109383 00000 n -0001109682 00000 n -0001109867 00000 n -0001110149 00000 n -0001110333 00000 n -0001110636 00000 n -0001110820 00000 n -0001111004 00000 n -0001111188 00000 n -0001111372 00000 n -0001111655 00000 n -0001111841 00000 n -0001112135 00000 n -0001112321 00000 n -0001112620 00000 n -0001112805 00000 n -0001113101 00000 n -0001113286 00000 n -0001113575 00000 n -0001113762 00000 n -0001114053 00000 n -0001114627 00000 n -0001120096 00000 n -0001120281 00000 n -0001120580 00000 n -0001120765 00000 n -0001120950 00000 n -0001121136 00000 n -0001121426 00000 n -0001121611 00000 n -0001121915 00000 n -0001122100 00000 n -0001122395 00000 n -0001122580 00000 n -0001122870 00000 n -0001123055 00000 n -0001123356 00000 n -0001123659 00000 n -0001123844 00000 n -0001124143 00000 n -0001124618 00000 n -0001127994 00000 n -0001129714 00000 n -0001131985 00000 n -0001132073 00000 n -0001132313 00000 n -0001133628 00000 n -trailer -<< - /Size 5278 - /Root 5277 0 R - /Info 5275 0 R - /ID [(HHwsV4w2OKoHWq5hDV/GeA==) (8/8Hb0n3/ti5Ewx/bKL9Ww==)] ->> -startxref -1135503 -%%EOF \ No newline at end of file diff --git a/docs/cordis-primer.i18n.yaml b/docs/cordis-primer.i18n.yaml index cec0660aae..949846bee5 100644 --- a/docs/cordis-primer.i18n.yaml +++ b/docs/cordis-primer.i18n.yaml @@ -3,4 +3,4 @@ # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write docs/cordis-primer.md cordis-primer.md: 2a3afe180623d89b006dfa3e73aba5567c15bbe9 -cordis-primer.zh.md: bdce14cf9f157959d6419f88c9c69570102b9c0c +cordis-primer.zh.md: d4d60f60717ffdc01499fdffadba2808557b285f diff --git a/docs/cordis-primer.zh.md b/docs/cordis-primer.zh.md index bdce14cf9f..d4d60f6071 100644 --- a/docs/cordis-primer.zh.md +++ b/docs/cordis-primer.zh.md @@ -12,6 +12,8 @@ Cordis 是 DeepSeek Harness 底层以 vendor 方式引入的插件框架。本 - **类型化事件用于通信。** 服务通过 TypeScript 声明合并注册事件名,然后以 `emit`、`waterfall`(瀑布式事件)、`parallel` 或 `serial` 方式分发,分别对应监听者观察、包装、并行扇出或按序执行。 - **注册是可逆的副作用。** 提示词片段、工具 schema、适配器、提供方和监听器通过 `ctx.effect()` 或 `ctx.on()` 安装,reload 和 teardown 时会按预期撤销。 + + ## 分发模式 每个事件具有以下分发模式之一,且只能通过对应方法分发。 diff --git a/docs/cordis-tutorial/03-services.i18n.yaml b/docs/cordis-tutorial/03-services.i18n.yaml index 372e028a47..80ea0f275f 100644 --- a/docs/cordis-tutorial/03-services.i18n.yaml +++ b/docs/cordis-tutorial/03-services.i18n.yaml @@ -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 docs/cordis-tutorial/03-services.md -03-services.md: 32007284be99ef46b4621089c9b3a80317e77189 -03-services.zh.md: d82be29aa69686b8dc10cc6a45a658683c017cbd +03-services.md: ebfc400dbbc701a3c164c7d30c371dec879d7d73 +03-services.zh.md: fcfd8be7f7fe654a4f4943cf591b5ab7bfc27fc6 diff --git a/docs/cordis-tutorial/03-services.md b/docs/cordis-tutorial/03-services.md index 32007284be..ebfc400dbb 100644 --- a/docs/cordis-tutorial/03-services.md +++ b/docs/cordis-tutorial/03-services.md @@ -75,7 +75,7 @@ Swap the two lines in `cordis.yml` and rerun: same output. Try removing `./greet `inject` is not a one-shot boot check. If a required service disappears while the app runs — its provider was unloaded or hot-replaced — every dependent plugin is unloaded too, and loads again when the service returns. Combined with effects ([chapter 2](02-lifecycle-and-effects.md)), this prevents a running consumer from retaining a reference to an unavailable service: its own registrations are unwound when the dependency disappears. -This is also why service replacement works in config: unload the `dsh-bash-local` entry, mount a different `bash` provider, and every plugin injecting `'bash'` cleanly restarts against the new implementation. +This is also why service replacement works in config: unload the `dsh-bash-local` entry, mount a different `shell` provider, and every plugin injecting `'shell'` cleanly restarts against the new implementation. ## Optional dependencies diff --git a/docs/cordis-tutorial/03-services.zh.md b/docs/cordis-tutorial/03-services.zh.md index d82be29aa6..fcfd8be7f7 100644 --- a/docs/cordis-tutorial/03-services.zh.md +++ b/docs/cordis-tutorial/03-services.zh.md @@ -75,7 +75,7 @@ Hello, world! `inject` 并非一次性的启动检查。如果应用运行期间所需服务消失,例如提供方被卸载或热替换,每个依赖插件也会随之卸载,并在服务恢复后再次加载。结合 effect([第 2 章](02-lifecycle-and-effects.md)),这能防止运行中的消费方保留对不可用服务的引用:依赖消失时,它自己的注册也会撤销。 -这也是配置中可以替换服务的原因:卸载 Cordis 配置项 `dsh-bash-local`,挂载另一个 `bash` 提供方,所有注入 `'bash'` 的插件都会重新启动并使用新实现。 +这也是配置中可以替换服务的原因:卸载 Cordis 配置项 `dsh-bash-local`,挂载另一个 `shell` 提供方,所有注入 `'shell'` 的插件都会重新启动并使用新实现。 ## 可选依赖 diff --git a/docs/cordis-tutorial/06-composition-and-hmr.i18n.yaml b/docs/cordis-tutorial/06-composition-and-hmr.i18n.yaml index 6a79850803..c61ee1a5ea 100644 --- a/docs/cordis-tutorial/06-composition-and-hmr.i18n.yaml +++ b/docs/cordis-tutorial/06-composition-and-hmr.i18n.yaml @@ -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 docs/cordis-tutorial/06-composition-and-hmr.md -06-composition-and-hmr.md: 87ea26014657ae8c8199e1ebb486556c827d96ca -06-composition-and-hmr.zh.md: 830f55de7c1be351fe701cb068197543602619a7 +06-composition-and-hmr.md: 2b53aa28be99851e77a71de76337f2beb4003e8d +06-composition-and-hmr.zh.md: cd4afa1d5465a5442bfd6b771ebcd61c46fe2983 diff --git a/docs/cordis-tutorial/06-composition-and-hmr.md b/docs/cordis-tutorial/06-composition-and-hmr.md index 87ea260146..2b53aa28be 100644 --- a/docs/cordis-tutorial/06-composition-and-hmr.md +++ b/docs/cordis-tutorial/06-composition-and-hmr.md @@ -18,7 +18,7 @@ A config entry accepts metadata beyond `name` and `config`: `id` gives the entry a stable identity so the loader can tell an edit to an existing entry apart from a removal plus an addition. `disabled: true` unmounts a plugin without deleting its entry — flip it back and the plugin (and everything PENDING on its services) loads again. -Groups nest a sub-list of entries that load and unload as one unit, and `isolate` gives a group its own instance of a service name — two groups can each see a differently-configured `bash` without affecting each other. The [Cordis primer](../cordis-primer.md) and the [service isolation example](../user/develop/framework/service.md#service-isolation) cover the details. +Groups nest a sub-list of entries that load and unload as one unit, and `isolate` gives a group its own instance of a service name — two groups can each see a differently configured `shell` provider without affecting each other. The [Cordis primer](../cordis-primer.md) and the [service isolation example](../user/develop/framework/service.md#service-isolation) cover the details. ## Hot module replacement diff --git a/docs/cordis-tutorial/06-composition-and-hmr.zh.md b/docs/cordis-tutorial/06-composition-and-hmr.zh.md index 830f55de7c..cd4afa1d54 100644 --- a/docs/cordis-tutorial/06-composition-and-hmr.zh.md +++ b/docs/cordis-tutorial/06-composition-and-hmr.zh.md @@ -18,7 +18,7 @@ Cordis 配置项除了 `name` 和 `config`,还接受其他元数据: `id` 为 Cordis 配置项提供稳定标识,使 loader 能区分修改现有 Cordis 配置项与先删除再添加。`disabled: true` 会卸载插件而不删除其 Cordis 配置项;改回原值后,插件以及所有因依赖其服务而处于 PENDING 的插件都会再次加载。 -组可以嵌套一份 Cordis 配置项子列表,并将其作为一个单元加载和卸载;`isolate` 则为一个组提供某项服务名称的独立实例,因此两个组可以各自看到配置不同的 `bash`,互不影响。[Cordis 入门](../cordis-primer.md)和[服务隔离示例](../user/develop/framework/service.md#service-isolation)介绍了详细内容。 +组可以嵌套一份 Cordis 配置项子列表,并将其作为一个单元加载和卸载;`isolate` 则为一个组提供某项服务名称的独立实例,因此两个组可以各自看到配置不同的 `shell` 提供方,互不影响。[Cordis 入门](../cordis-primer.md)和[服务隔离示例](../user/develop/framework/service.md#service-isolation)介绍了详细内容。 ## 热模块替换 diff --git a/docs/cordis-tutorial/index.i18n.yaml b/docs/cordis-tutorial/index.i18n.yaml index 9e18b6899e..68591da3e4 100644 --- a/docs/cordis-tutorial/index.i18n.yaml +++ b/docs/cordis-tutorial/index.i18n.yaml @@ -3,4 +3,4 @@ # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write docs/cordis-tutorial/index.md index.md: c51965e186ce8d78b577c1005c1c3e1831b91be1 -index.zh.md: 8811930eba0f3e24ecbc47521e65582502257473 +index.zh.md: 22e1918672a34219ca0cf5efaa43a8eb693e6996 diff --git a/docs/cordis-tutorial/index.zh.md b/docs/cordis-tutorial/index.zh.md index 8811930eba..22e1918672 100644 --- a/docs/cordis-tutorial/index.zh.md +++ b/docs/cordis-tutorial/index.zh.md @@ -10,6 +10,8 @@ Cordis 是 DeepSeek Harness 底层的插件框架:它是一个小型运行时 如果你要为 harness 本身编写插件——由 `cordis.yml` 加载、在 Web UI 中驱动,而不是下面这个启动器——请从[第一个 Harness 插件](../user/develop/basic/index.md)开始。 + + ## 准备工作 你需要克隆本仓库并安装依赖;[开发指南](../development.md#setup-tutorial)列出了前置条件。本教程不需要 API 密钥;所有示例均可在无密钥环境中运行。 diff --git a/docs/defensive-patterns.i18n.yaml b/docs/defensive-patterns.i18n.yaml index e845e8182b..9a82a28afd 100644 --- a/docs/defensive-patterns.i18n.yaml +++ b/docs/defensive-patterns.i18n.yaml @@ -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 docs/defensive-patterns.md -defensive-patterns.md: b6e643cad6180ea35a363f2c4131b2c24f5f70af -defensive-patterns.zh.md: e1a6abdfd2138a51a13ceaf418bf6df1d0c65579 +defensive-patterns.md: 9db582354628a13abd43c5bd052dbbfd6e52f79f +defensive-patterns.zh.md: 7bebbe3c1964f2b826afc523eaa4af7be180e36e diff --git a/docs/defensive-patterns.md b/docs/defensive-patterns.md index b6e643cad6..9db5823546 100644 --- a/docs/defensive-patterns.md +++ b/docs/defensive-patterns.md @@ -27,3 +27,7 @@ A user-supplied listener that throws must not reject the promise it runs inside ## Never hand untrusted output the ambient environment or predictable paths Spawned commands get a scrubbed env (drop `*KEY*`/`*SECRET*`/`*TOKEN*`/`*PASSWORD*`) so harness credentials cannot leak into output, `env`, or spill files. Temp/spill files use a private (0700) dir, random names, and exclusive owner-only opens (`'wx'`, `0o600`) — predictable world-readable paths invite symlink races and disclosure. + +## Unlink link-shaped paths + +A path that may be a symlink or Windows junction is removed with `lstatSync().isSymbolicLink()` then `unlinkSync`: unlink deletes only the link and refuses a real directory, so it never follows the link into its target. Windows `rmSync(link)` throws `ERR_FS_EISDIR` on a junction; recursive deletion may descend through one into its target. Reserve recursive `rmSync` for known real directories. diff --git a/docs/defensive-patterns.zh.md b/docs/defensive-patterns.zh.md index e1a6abdfd2..7bebbe3c19 100644 --- a/docs/defensive-patterns.zh.md +++ b/docs/defensive-patterns.zh.md @@ -26,4 +26,8 @@ ## 绝不将环境变量或可预测路径暴露给不可信输出 -启动的命令应使用经过清理的环境变量,移除名称匹配 `*KEY*`、`*SECRET*`、`*TOKEN*` 或 `*PASSWORD*` 的项,防止 harness 凭证通过命令输出、`env` 或 spill 文件泄漏。临时文件和 spill 文件应放在权限为 0700 的私有目录中,使用随机文件名,并以独占且仅所有者可访问的方式打开(`'wx'`、`0o600`);可预测且所有用户均可读的路径会引发符号链接竞态和信息泄露。 +启动的命令应使用经过清理的环境变量,移除名称匹配 `*KEY*`、`*SECRET*`、`*TOKEN*` 或 `*PASSWORD*` 的项,防止 harness 凭证通过命令输出、`env` 或 spill 文件泄漏。临时文件和 spill 文件应放在权限为 0700 的私有目录中,使用随机文件名,并以独占且仅所有者可访问的方式打开(`'wx'`、`0o600`);可预测且全局可读的路径会引发符号链接竞态和信息泄露。 + +## 用 unlink 删除链接形态的路径 + +可能是符号链接或 Windows junction 的路径,应先用 `lstatSync().isSymbolicLink()` 判断,再用 `unlinkSync` 删除:unlink 只删除链接本身并拒绝真实目录,因此绝不会跟随链接进入其目标。Windows 上对 junction 调用 `rmSync(link)` 会抛 `ERR_FS_EISDIR`;递归删除可能穿过 junction 进入其目标。真实目录才使用带 `recursive` 的 `rmSync`。 diff --git a/docs/glossary.i18n.yaml b/docs/glossary.i18n.yaml index ddedb8d9c7..f462345f43 100644 --- a/docs/glossary.i18n.yaml +++ b/docs/glossary.i18n.yaml @@ -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 docs/glossary.md -glossary.md: 1c8bbc86544092b1e8c752e53eed0a1217baa329 -glossary.zh.md: 510853d3d6a6f579c8e4cd609d714fe891e9cf10 +glossary.md: 9bff818d5a9f7688e8d2a2425b6e6a9555be3847 +glossary.zh.md: 98bbbefb8bfd152324b23e9791eb938398c12602 diff --git a/docs/glossary.md b/docs/glossary.md index 1c8bbc8654..9bff818d5a 100644 --- a/docs/glossary.md +++ b/docs/glossary.md @@ -6,7 +6,7 @@ Domain vocabulary for DeepSeek Harness uses one canonical term per concept. Term ## capability-seam -- **seam** — a *swappable capability* with three roles: a **Service Definition** (the Cordis `Service` that owns its `ctx.` and vocabulary types — an abstract class such as `ShellExecutor`, or a concrete registry such as `WebRuntime`, never a TypeScript `interface`), one or more **Service providers**, and one or more **Consumers** that inject the service. `packages/shell` is the canonical example: `dsh-shell` (Service Definition), `dsh-bash-local` / `dsh-bash-sandbox` (providers), and `dsh-tool-bash` (Consumer). Roles normally occupy separate packages when they evolve independently, but a package may own multiple roles when they are one concern (`dsh-llm` owns its Service Definition and Consumer). The seam is the complete capability, never one role; reserve the term for that meaning and name a constituent by its role, class, service, contract, or extension point. +- **seam** — a *swappable capability* with three roles: a **Service Definition** (the Cordis `Service` that owns its `ctx.` and vocabulary types — an abstract class such as `ShellExecutor`, or a concrete registry such as `WebRuntime`, never a TypeScript `interface`), one or more **Service Providers**, and one or more **Consumers** that inject the service. `packages/shell` is the canonical example: `dsh-shell` (Service Definition), `dsh-bash-local` / `dsh-bash-sandbox` (providers), and `dsh-tool-bash` (Consumer). Roles normally occupy separate packages when they evolve independently, but a package may own multiple roles when they are one concern (`dsh-llm` owns its Service Definition and Consumer). The seam is the complete capability, never one role; reserve the term for that meaning and name a constituent by its role, class, service, contract, or extension point. ## agent-scope diff --git a/docs/glossary.zh.md b/docs/glossary.zh.md index 510853d3d6..98bbbefb8b 100644 --- a/docs/glossary.zh.md +++ b/docs/glossary.zh.md @@ -6,7 +6,7 @@ DeepSeek Harness 的领域词汇为每个概念规定一个规范术语。各术 ## capability-seam -- **seam**:一种包含三种角色的*可替换能力*:**Service Definition**(拥有自身 `ctx.` 和词汇类型的 Cordis `Service`——可以是 `ShellExecutor` 这样的抽象类,也可以是 `WebRuntime` 这样的具体注册表,绝不是 TypeScript `interface`)、一个或多个 **Service provider**,以及一个或多个注入该服务的 **Consumer**。`packages/shell` 是规范范例:`dsh-shell`(Service Definition)、`dsh-bash-local` / `dsh-bash-sandbox`(提供方),以及 `dsh-tool-bash`(Consumer)。角色需要独立演进时通常位于不同包,但属于同一关注点时,一个包也可以承担多个角色(`dsh-llm` 同时承担 Service Definition 和 Consumer)。seam 是完整能力,绝不是其中一个角色;该术语仅保留此义,能力成员应按其角色、类、服务、约定或扩展点命名。 +- **seam**:一种包含三种角色的*可替换能力*:**Service Definition**(拥有自身 `ctx.` 和词汇类型的 Cordis `Service`——可以是 `ShellExecutor` 这样的抽象类,也可以是 `WebRuntime` 这样的具体注册表,绝不是 TypeScript `interface`)、一个或多个 **Service Provider**,以及一个或多个注入该服务的 **Consumer**。`packages/shell` 是规范范例:`dsh-shell`(Service Definition)、`dsh-bash-local` / `dsh-bash-sandbox`(提供方),以及 `dsh-tool-bash`(Consumer)。角色需要独立演进时通常位于不同包,但属于同一关注点时,一个包也可以承担多个角色(`dsh-llm` 同时承担 Service Definition 和 Consumer)。seam 是完整能力,绝不是其中一个角色;该术语仅保留此义,能力成员应按其角色、类、服务、约定或扩展点命名。 ## agent-scope diff --git a/docs/i18n/terminology.md b/docs/i18n/terminology.md index d1e58a99b4..feb1c96792 100644 --- a/docs/i18n/terminology.md +++ b/docs/i18n/terminology.md @@ -56,7 +56,8 @@ | Round | Round | | 回合、目标回合、Ralph 回合 | 外层策略使用 Round 时,领域层级为 Session > Round > Turn(轮次) > Step(步骤);Round 是可选的外层策略迭代,并非每个会话轮次都具有的通用层级。Goal Round 与 Ralph Round 均保留英文。一个 Round 承载一个轮次,步骤隶属于该轮次;明确的零步骤轮次仍保持原义。 | | schema | schema | | | | | schema DSL | schema DSL | | | | -| seam | seam | | 接缝 | 一个可替换能力的整体,包含 Service Definition / Service provider / Consumer 三种角色;角色需要独立演化时才拆包,也可由同一包承担多个角色。以 `packages/shell` 为范例;Service Definition 是 Cordis `Service`(抽象类或具体 registry 服务),不是 TypeScript interface。任何单一角色、普通边界或扩展点都不能称为 seam。本仓库正文保留英文;与 `extension point` 是不同概念 | +| seam | seam | | 接缝 | 一个可替换能力的整体,包含 Service Definition / Service Provider / Consumer 三种角色;角色需要独立演化时才拆包,也可由同一包承担多个角色。以 `packages/shell` 为范例;Service Definition 是 Cordis `Service`(抽象类或具体 registry 服务),不是 TypeScript interface。任何单一角色、普通边界或扩展点都不能称为 seam。本仓库正文保留英文;与 `extension point` 是不同概念 | +| Service Provider | Service Provider | | Service provider | 能力 seam 的命名角色;单数固定写作 Service Provider,复数写作 Service Providers。泛指提供服务的 provider 不适用本词条 | | skill | skill | skill(技能) | | | | slot | slot | | 坑位、孔位 | 客户端架构中的具名可注册位置,保留英文 | | spill | spill | | | 工具输出超限落盘机制;组合词写 `spill 文件`、`spill 路径` | @@ -97,7 +98,7 @@ | cancel | 取消 | | | | | canary test | canary 测试 | | 金丝雀测试 | 本仓库保留 `canary` | | capability | 能力 | | | 必须与 `feature` → `功能` 区分 | -| capability seam | 能力 seam | | 功能 seam、能力接缝 | 本仓库 Service Definition、Service provider 与 Consumer 三种角色组成完整可替换能力的命名架构概念;普通 `seam` 仍按其词条处理 | +| capability seam | 能力 seam | | 功能 seam、能力接缝 | 本仓库 Service Definition、Service Provider 与 Consumer 三种角色组成完整可替换能力的命名架构概念;普通 `seam` 仍按其词条处理 | | feature | 功能 | | 能力 | SDK 产品与工程模型中的可管理产品单元 | | feature option | 功能选项 | | variant | 一项 SDK 功能内有限、可选择的实现或配置 | | checkpoint | 检查点 | | | | diff --git a/docs/persistence-catalog.i18n.yaml b/docs/persistence-catalog.i18n.yaml index 37859f5f2e..bc6e3dde66 100644 --- a/docs/persistence-catalog.i18n.yaml +++ b/docs/persistence-catalog.i18n.yaml @@ -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 docs/persistence-catalog.md -persistence-catalog.md: 032f7ae45d05b688fd317e9aa46363f658f19b76 -persistence-catalog.zh.md: 4f3ace46f7abb2d87be1cd66cbead0ac6b0cccda +persistence-catalog.md: c400298f7d37c590918820bcbda10e6550f197e8 +persistence-catalog.zh.md: 65ec0e3fbdd226c51a371dc9a90f10db5c929c7a diff --git a/docs/persistence-catalog.md b/docs/persistence-catalog.md index 032f7ae45d..c400298f7d 100644 --- a/docs/persistence-catalog.md +++ b/docs/persistence-catalog.md @@ -96,6 +96,8 @@ Sources: [`packages/core/session/src/types.ts:336`](../packages/core/session/src ### `agent/*` + + #### `agent/inbox/spliced` — log-only ```ts persistence-catalog @@ -117,6 +119,8 @@ Source: [`packages/core/agent/src/types.ts:19`](../packages/core/agent/src/types ### `agent-preset/*` + + #### `agent-preset/selected` — log-only ```ts persistence-catalog @@ -133,6 +137,8 @@ Source: [`packages/preset/agent-presets/src/session.ts:26`](../packages/preset/a ### `approval/*` + + #### `approval/asked` — log-only ```ts persistence-catalog @@ -156,6 +162,8 @@ Types: [CallId](subsystems/core.md) Source: [`packages/interaction/user-approval/src/index.ts:44`](../packages/interaction/user-approval/src/index.ts) + + #### `approval/decided` — log-only ```ts persistence-catalog @@ -172,6 +180,8 @@ Source: [`packages/interaction/user-approval/src/index.ts:44`](../packages/inter Source: [`packages/interaction/user-approval/src/index.ts:55`](../packages/interaction/user-approval/src/index.ts) + + #### `approval/policy` — log-only ```ts persistence-catalog @@ -194,6 +204,8 @@ Source: [`packages/interaction/user-approval/src/index.ts:67`](../packages/inter ### `assistant/*` + + #### `assistant/chunk` — log-only ```ts persistence-catalog @@ -205,6 +217,8 @@ Types: [StreamChunk](subsystems/llm-streaming.md) Source: [`packages/core/session/src/types.ts:266`](../packages/core/session/src/types.ts) + + #### `assistant/message` — surface ```ts persistence-catalog @@ -223,6 +237,8 @@ Source: [`packages/core/session/src/types.ts:273`](../packages/core/session/src/ ### `command/*` + + #### `command/done` — log-only ```ts persistence-catalog @@ -242,6 +258,8 @@ Source: [`packages/core/session/src/types.ts:273`](../packages/core/session/src/ Source: [`packages/interaction/commands/src/types.ts:95`](../packages/interaction/commands/src/types.ts) + + #### `command/run` — log-only ```ts persistence-catalog @@ -262,6 +280,8 @@ Source: [`packages/interaction/commands/src/types.ts:88`](../packages/interactio ### `compaction/*` + + #### `compaction/end` — log-only ```ts persistence-catalog @@ -274,6 +294,8 @@ Source: [`packages/interaction/commands/src/types.ts:88`](../packages/interactio Source: [`packages/compaction/compaction/src/types.ts:71`](../packages/compaction/compaction/src/types.ts) + + #### `compaction/prune` — log-only ```ts persistence-catalog @@ -298,6 +320,8 @@ Source: [`packages/compaction/compaction/src/types.ts:71`](../packages/compactio Source: [`packages/compaction/compaction/src/types.ts:81`](../packages/compaction/compaction/src/types.ts) + + #### `compaction/start` — log-only ```ts persistence-catalog @@ -311,6 +335,8 @@ Source: [`packages/compaction/compaction/src/types.ts:81`](../packages/compactio Source: [`packages/compaction/compaction/src/types.ts:23`](../packages/compaction/compaction/src/types.ts) + + #### `compaction/summary` — log-only ```ts persistence-catalog @@ -365,6 +391,8 @@ Source: [`packages/compaction/compaction/src/types.ts:33`](../packages/compactio ### `feedback/*` + + #### `feedback/record` — log-only ```ts persistence-catalog @@ -379,6 +407,8 @@ Source: [`packages/feedback/command-feedback/src/index.ts:62`](../packages/feedb ### `goal/*` + + #### `goal/change` — log-only ```ts persistence-catalog @@ -392,6 +422,8 @@ Source: [`packages/goal/goal/src/domain.ts:66`](../packages/goal/goal/src/domain ### `hook/*` + + #### `hook/invoked` — log-only ```ts persistence-catalog @@ -415,6 +447,8 @@ Source: [`packages/goal/goal/src/domain.ts:66`](../packages/goal/goal/src/domain Source: [`packages/hooks/hook-protocol/src/types.ts:19`](../packages/hooks/hook-protocol/src/types.ts) + + #### `hook/result` — log-only ```ts persistence-catalog @@ -438,6 +472,8 @@ Source: [`packages/hooks/hook-protocol/src/types.ts:31`](../packages/hooks/hook- ### `llm/*` + + #### `llm/retry` — log-only ```ts persistence-catalog @@ -447,6 +483,8 @@ Source: [`packages/hooks/hook-protocol/src/types.ts:31`](../packages/hooks/hook- Source: [`packages/llm/llm-retry/src/types.ts:9`](../packages/llm/llm-retry/src/types.ts) + + #### `llm/retry-started` — log-only ```ts persistence-catalog @@ -458,6 +496,8 @@ Source: [`packages/llm/llm-retry/src/types.ts:11`](../packages/llm/llm-retry/src ### `permission/*` + + #### `permission/preset` — log-only ```ts persistence-catalog @@ -474,6 +514,8 @@ Source: [`packages/interaction/permission-presets/src/index.ts:50`](../packages/ ### `plan/*` + + #### `plan/mode` — log-only ```ts persistence-catalog @@ -489,6 +531,8 @@ Source: [`packages/plan/plan-mode/src/index.ts:53`](../packages/plan/plan-mode/s ### `request/*` + + #### `request/context` — log-only ```ts persistence-catalog @@ -501,6 +545,8 @@ Source: [`packages/plan/plan-mode/src/index.ts:53`](../packages/plan/plan-mode/s Source: [`packages/core/session/src/types.ts:309`](../packages/core/session/src/types.ts) + + #### `request/header` — log-only ```ts persistence-catalog @@ -515,6 +561,8 @@ Source: [`packages/core/session/src/types.ts:304`](../packages/core/session/src/ ### `sandbox/*` + + #### `sandbox/mode` — log-only ```ts persistence-catalog @@ -536,6 +584,8 @@ Source: [`packages/sandbox/sandbox-policy/src/session-mode.ts:33`](../packages/s ### `schedule/*` + + #### `schedule/change` — log-only ```ts persistence-catalog @@ -552,6 +602,8 @@ Source: [`packages/schedule/schedule/src/types.ts:219`](../packages/schedule/sch ### `session/*` + + #### `session/end-seed` — log-only ```ts persistence-catalog @@ -582,6 +634,8 @@ Source: [`packages/schedule/schedule/src/types.ts:219`](../packages/schedule/sch Source: [`packages/core/session/src/types.ts:332`](../packages/core/session/src/types.ts) + + #### `session/title` — log-only ```ts persistence-catalog @@ -596,6 +650,8 @@ Types: [SessionTitleEventData](subsystems/session-title.md) Source: [`packages/session/session-title/src/index.ts:100`](../packages/session/session-title/src/index.ts) + + #### `session/title-llm-request` — log-only ```ts persistence-catalog @@ -609,6 +665,8 @@ Source: [`packages/session/session-title-llm/src/index.ts:43`](../packages/sessi ### `step/*` + + #### `step/end` — log-only ```ts persistence-catalog @@ -618,6 +676,8 @@ Source: [`packages/session/session-title-llm/src/index.ts:43`](../packages/sessi Source: [`packages/core/session/src/types.ts:256`](../packages/core/session/src/types.ts) + + #### `step/start` — log-only ```ts persistence-catalog @@ -629,6 +689,8 @@ Source: [`packages/core/session/src/types.ts:254`](../packages/core/session/src/ ### `subagent/*` + + #### `subagent/descriptor` — log-only ```ts persistence-catalog @@ -646,6 +708,8 @@ Source: [`packages/subagent/subagent/src/descriptor.ts:37`](../packages/subagent ### `todo/*` + + #### `todo/write` — log-only ```ts persistence-catalog @@ -659,6 +723,8 @@ Source: [`packages/core/session/src/types.ts:299`](../packages/core/session/src/ ### `tool/*` + + #### `tool/call` — log-only ```ts persistence-catalog @@ -674,6 +740,8 @@ Types: [CallId](subsystems/core.md) Source: [`packages/core/session/src/types.ts:279`](../packages/core/session/src/types.ts) + + #### `tool/code-dispatch` — log-only ```ts persistence-catalog @@ -697,6 +765,8 @@ Source: [`packages/core/session/src/types.ts:279`](../packages/core/session/src/ Source: [`packages/core/tools/src/types.ts:56`](../packages/core/tools/src/types.ts) + + #### `tool/code-dispatch-start` — log-only ```ts persistence-catalog @@ -718,6 +788,8 @@ Source: [`packages/core/tools/src/types.ts:56`](../packages/core/tools/src/types Source: [`packages/core/tools/src/types.ts:40`](../packages/core/tools/src/types.ts) + + #### `tool/result` — surface ```ts persistence-catalog @@ -745,6 +817,8 @@ Source: [`packages/core/session/src/types.ts:291`](../packages/core/session/src/ ### `tool-workflow/*` + + #### `tool-workflow/agent-end` — log-only ```ts persistence-catalog @@ -757,6 +831,8 @@ Source: [`packages/core/session/src/types.ts:291`](../packages/core/session/src/ Source: [`packages/workflow/tool-workflow/src/types.ts:57`](../packages/workflow/tool-workflow/src/types.ts) + + #### `tool-workflow/agent-start` — log-only ```ts persistence-catalog @@ -769,6 +845,8 @@ Source: [`packages/workflow/tool-workflow/src/types.ts:57`](../packages/workflow Source: [`packages/workflow/tool-workflow/src/types.ts:52`](../packages/workflow/tool-workflow/src/types.ts) + + #### `tool-workflow/run-end` — log-only ```ts persistence-catalog @@ -781,6 +859,8 @@ Source: [`packages/workflow/tool-workflow/src/types.ts:52`](../packages/workflow Source: [`packages/workflow/tool-workflow/src/types.ts:62`](../packages/workflow/tool-workflow/src/types.ts) + + #### `tool-workflow/run-start` — log-only ```ts persistence-catalog @@ -795,6 +875,8 @@ Source: [`packages/workflow/tool-workflow/src/types.ts:47`](../packages/workflow ### `turn/*` + + #### `turn/end` — log-only ```ts persistence-catalog @@ -813,6 +895,8 @@ Types: [TurnEndReason](subsystems/session.md) Source: [`packages/core/session/src/types.ts:252`](../packages/core/session/src/types.ts) + + #### `turn/start` — log-only ```ts persistence-catalog @@ -829,6 +913,8 @@ Source: [`packages/core/session/src/types.ts:243`](../packages/core/session/src/ ### `user/*` + + #### `user/message` — surface ```ts persistence-catalog @@ -846,6 +932,8 @@ Source: [`packages/core/session/src/types.ts:264`](../packages/core/session/src/ ### `web/*` + + #### `web/deepseek-search-llm-request` — log-only ```ts persistence-catalog diff --git a/docs/persistence-catalog.zh.md b/docs/persistence-catalog.zh.md index 4f3ace46f7..65ec0e3fbd 100644 --- a/docs/persistence-catalog.zh.md +++ b/docs/persistence-catalog.zh.md @@ -98,6 +98,8 @@ export type SessionEvent = { ### `agent/*` + + #### `agent/inbox/spliced` — log-only ```ts persistence-catalog @@ -119,6 +121,8 @@ export type SessionEvent = { ### `agent-preset/*` + + #### `agent-preset/selected` — log-only ```ts persistence-catalog @@ -135,6 +139,8 @@ export type SessionEvent = { ### `approval/*` + + #### `approval/asked` — log-only ```ts persistence-catalog @@ -158,6 +164,8 @@ export type SessionEvent = { 来源:[`packages/interaction/user-approval/src/index.ts:44`](../packages/interaction/user-approval/src/index.ts) + + #### `approval/decided` — log-only ```ts persistence-catalog @@ -174,6 +182,8 @@ export type SessionEvent = { 来源:[`packages/interaction/user-approval/src/index.ts:55`](../packages/interaction/user-approval/src/index.ts) + + #### `approval/policy` — log-only ```ts persistence-catalog @@ -196,6 +206,8 @@ export type SessionEvent = { ### `assistant/*` + + #### `assistant/chunk` — log-only ```ts persistence-catalog @@ -207,6 +219,8 @@ export type SessionEvent = { 来源:[`packages/core/session/src/types.ts:266`](../packages/core/session/src/types.ts) + + #### `assistant/message` — surface ```ts persistence-catalog @@ -225,6 +239,8 @@ export type SessionEvent = { ### `command/*` + + #### `command/done` — log-only ```ts persistence-catalog @@ -244,6 +260,8 @@ export type SessionEvent = { 来源:[`packages/interaction/commands/src/types.ts:95`](../packages/interaction/commands/src/types.ts) + + #### `command/run` — log-only ```ts persistence-catalog @@ -264,6 +282,8 @@ export type SessionEvent = { ### `compaction/*` + + #### `compaction/end` — log-only ```ts persistence-catalog @@ -276,6 +296,8 @@ export type SessionEvent = { 来源:[`packages/compaction/compaction/src/types.ts:71`](../packages/compaction/compaction/src/types.ts) + + #### `compaction/prune` — log-only ```ts persistence-catalog @@ -300,6 +322,8 @@ export type SessionEvent = { 来源:[`packages/compaction/compaction/src/types.ts:81`](../packages/compaction/compaction/src/types.ts) + + #### `compaction/start` — log-only ```ts persistence-catalog @@ -313,6 +337,8 @@ export type SessionEvent = { 来源:[`packages/compaction/compaction/src/types.ts:23`](../packages/compaction/compaction/src/types.ts) + + #### `compaction/summary` — log-only ```ts persistence-catalog @@ -367,6 +393,8 @@ export type SessionEvent = { ### `feedback/*` + + #### `feedback/record` — log-only ```ts persistence-catalog @@ -381,6 +409,8 @@ export type SessionEvent = { ### `goal/*` + + #### `goal/change` — log-only ```ts persistence-catalog @@ -394,6 +424,8 @@ export type SessionEvent = { ### `hook/*` + + #### `hook/invoked` — log-only ```ts persistence-catalog @@ -417,6 +449,8 @@ export type SessionEvent = { 来源:[`packages/hooks/hook-protocol/src/types.ts:19`](../packages/hooks/hook-protocol/src/types.ts) + + #### `hook/result` — log-only ```ts persistence-catalog @@ -440,6 +474,8 @@ export type SessionEvent = { ### `llm/*` + + #### `llm/retry` — log-only ```ts persistence-catalog @@ -449,6 +485,8 @@ export type SessionEvent = { 来源:[`packages/llm/llm-retry/src/types.ts:9`](../packages/llm/llm-retry/src/types.ts) + + #### `llm/retry-started` — log-only ```ts persistence-catalog @@ -460,6 +498,8 @@ export type SessionEvent = { ### `permission/*` + + #### `permission/preset` — log-only ```ts persistence-catalog @@ -476,6 +516,8 @@ export type SessionEvent = { ### `plan/*` + + #### `plan/mode` — log-only ```ts persistence-catalog @@ -491,6 +533,8 @@ export type SessionEvent = { ### `request/*` + + #### `request/context` — log-only ```ts persistence-catalog @@ -503,6 +547,8 @@ export type SessionEvent = { 来源:[`packages/core/session/src/types.ts:309`](../packages/core/session/src/types.ts) + + #### `request/header` — log-only ```ts persistence-catalog @@ -517,6 +563,8 @@ export type SessionEvent = { ### `sandbox/*` + + #### `sandbox/mode` — log-only ```ts persistence-catalog @@ -538,6 +586,8 @@ export type SessionEvent = { ### `schedule/*` + + #### `schedule/change` — log-only ```ts persistence-catalog @@ -554,6 +604,8 @@ export type SessionEvent = { ### `session/*` + + #### `session/end-seed` — log-only ```ts persistence-catalog @@ -584,6 +636,8 @@ export type SessionEvent = { 来源:[`packages/core/session/src/types.ts:332`](../packages/core/session/src/types.ts) + + #### `session/title` — log-only ```ts persistence-catalog @@ -598,6 +652,8 @@ export type SessionEvent = { 来源:[`packages/session/session-title/src/index.ts:100`](../packages/session/session-title/src/index.ts) + + #### `session/title-llm-request` — log-only ```ts persistence-catalog @@ -611,6 +667,8 @@ export type SessionEvent = { ### `step/*` + + #### `step/end` — log-only ```ts persistence-catalog @@ -620,6 +678,8 @@ export type SessionEvent = { 来源:[`packages/core/session/src/types.ts:256`](../packages/core/session/src/types.ts) + + #### `step/start` — log-only ```ts persistence-catalog @@ -631,6 +691,8 @@ export type SessionEvent = { ### `subagent/*` + + #### `subagent/descriptor` — log-only ```ts persistence-catalog @@ -648,6 +710,8 @@ export type SessionEvent = { ### `todo/*` + + #### `todo/write` — log-only ```ts persistence-catalog @@ -661,6 +725,8 @@ export type SessionEvent = { ### `tool/*` + + #### `tool/call` — log-only ```ts persistence-catalog @@ -676,6 +742,8 @@ export type SessionEvent = { 来源:[`packages/core/session/src/types.ts:279`](../packages/core/session/src/types.ts) + + #### `tool/code-dispatch` — log-only ```ts persistence-catalog @@ -699,6 +767,8 @@ export type SessionEvent = { 来源:[`packages/core/tools/src/types.ts:56`](../packages/core/tools/src/types.ts) + + #### `tool/code-dispatch-start` — log-only ```ts persistence-catalog @@ -720,6 +790,8 @@ export type SessionEvent = { 来源:[`packages/core/tools/src/types.ts:40`](../packages/core/tools/src/types.ts) + + #### `tool/result` — surface ```ts persistence-catalog @@ -747,6 +819,8 @@ export type SessionEvent = { ### `tool-workflow/*` + + #### `tool-workflow/agent-end` — log-only ```ts persistence-catalog @@ -759,6 +833,8 @@ export type SessionEvent = { 来源:[`packages/workflow/tool-workflow/src/types.ts:57`](../packages/workflow/tool-workflow/src/types.ts) + + #### `tool-workflow/agent-start` — log-only ```ts persistence-catalog @@ -771,6 +847,8 @@ export type SessionEvent = { 来源:[`packages/workflow/tool-workflow/src/types.ts:52`](../packages/workflow/tool-workflow/src/types.ts) + + #### `tool-workflow/run-end` — log-only ```ts persistence-catalog @@ -783,6 +861,8 @@ export type SessionEvent = { 来源:[`packages/workflow/tool-workflow/src/types.ts:62`](../packages/workflow/tool-workflow/src/types.ts) + + #### `tool-workflow/run-start` — log-only ```ts persistence-catalog @@ -797,6 +877,8 @@ export type SessionEvent = { ### `turn/*` + + #### `turn/end` — log-only ```ts persistence-catalog @@ -815,6 +897,8 @@ export type SessionEvent = { 来源:[`packages/core/session/src/types.ts:252`](../packages/core/session/src/types.ts) + + #### `turn/start` — log-only ```ts persistence-catalog @@ -831,6 +915,8 @@ export type SessionEvent = { ### `user/*` + + #### `user/message` — surface ```ts persistence-catalog @@ -848,6 +934,8 @@ export type SessionEvent = { ### `web/*` + + #### `web/deepseek-search-llm-request` — log-only ```ts persistence-catalog diff --git a/docs/subsystems/code-runtime.i18n.yaml b/docs/subsystems/code-runtime.i18n.yaml index cf1e004c03..6c5d91599c 100644 --- a/docs/subsystems/code-runtime.i18n.yaml +++ b/docs/subsystems/code-runtime.i18n.yaml @@ -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 docs/subsystems/code-runtime.md -code-runtime.md: e677bcaef26f7999181825934b880514e425f615 -code-runtime.zh.md: e94dd77b1e430e7bd15633881d65521409819574 +code-runtime.md: 09036819d4fb6a4e2f83cf7923584780ca2211f8 +code-runtime.zh.md: 2e717f17313ce23cb37616199bd83776c0a40756 diff --git a/docs/subsystems/code-runtime.md b/docs/subsystems/code-runtime.md index e677bcaef2..09036819d4 100644 --- a/docs/subsystems/code-runtime.md +++ b/docs/subsystems/code-runtime.md @@ -2,7 +2,7 @@ English | [中文](code-runtime.zh.md) -The code-execution seam — a [capability seam](../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md) whose Service Definition ([dsh-code-runtime](../../packages/code-runtime/code-runtime), `ctx.codeRuntime`) runs one model-written program against host-provided async bindings and reports what it printed and returned. Code execution is **one optional capability**, not part of the agent-loop spine — so its vocabulary lives here, not in [core.md](core.md). Backends differ by execution substrate and source language, both readonly descriptors on the service; the worker-thread Service provider and tool-registry Consumer are specified by the [Code Mode foundation](../../.agents/notes/implemented/feature/2026-06-15-code-mode.md) and [typed-return contract](../../.agents/notes/implemented/feature/2026-07-20-code-mode-typed-tool-returns.md). +The code-execution seam — a [capability seam](../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md) whose Service Definition ([dsh-code-runtime](../../packages/code-runtime/code-runtime), `ctx.codeRuntime`) runs one model-written program against host-provided async bindings and reports what it printed and returned. Code execution is **one optional capability**, not part of the agent-loop spine — so its vocabulary lives here, not in [core.md](core.md). Backends differ by execution substrate and source language, both readonly descriptors on the service; the worker-thread Service Provider and tool-registry Consumer are specified by the [Code Mode foundation](../../.agents/notes/implemented/feature/2026-06-15-code-mode.md) and [typed-return contract](../../.agents/notes/implemented/feature/2026-07-20-code-mode-typed-tool-returns.md). Source: [`packages/code-runtime/code-runtime/src/types.ts`](../../packages/code-runtime/code-runtime/src/types.ts) diff --git a/docs/subsystems/code-runtime.zh.md b/docs/subsystems/code-runtime.zh.md index e94dd77b1e..2e717f1731 100644 --- a/docs/subsystems/code-runtime.zh.md +++ b/docs/subsystems/code-runtime.zh.md @@ -2,7 +2,7 @@ [English](code-runtime.md) | 中文 -代码执行 seam 是一个[能力 seam](../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md):其 Service Definition([dsh-code-runtime](../../packages/code-runtime/code-runtime),`ctx.codeRuntime`)使用宿主提供的异步绑定运行一段模型编写的程序,并报告其打印内容与返回值。代码执行是**一项可选能力**,不属于 agent loop(智能体循环)主干,因此其词汇定义在此而非 [core.md](core.md) 中。各后端的执行基底与源语言不同,这两项均为服务上的只读描述符;worker-thread Service provider 与工具注册表 Consumer 的约定见 [Code Mode 基础设计](../../.agents/notes/implemented/feature/2026-06-15-code-mode.md) 和[类型化返回约定](../../.agents/notes/implemented/feature/2026-07-20-code-mode-typed-tool-returns.md)。 +代码执行 seam 是一个[能力 seam](../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md):其 Service Definition([dsh-code-runtime](../../packages/code-runtime/code-runtime),`ctx.codeRuntime`)使用宿主提供的异步绑定运行一段模型编写的程序,并报告其打印内容与返回值。代码执行是**一项可选能力**,不属于 agent loop(智能体循环)主干,因此其词汇定义在此而非 [core.md](core.md) 中。各后端的执行基底与源语言不同,这两项均为服务上的只读描述符;worker-thread Service Provider 与工具注册表 Consumer 的约定见 [Code Mode 基础设计](../../.agents/notes/implemented/feature/2026-06-15-code-mode.md) 和[类型化返回约定](../../.agents/notes/implemented/feature/2026-07-20-code-mode-typed-tool-returns.md)。 源码:[`packages/code-runtime/code-runtime/src/types.ts`](../../packages/code-runtime/code-runtime/src/types.ts) diff --git a/docs/subsystems/compaction.i18n.yaml b/docs/subsystems/compaction.i18n.yaml index b3c2ffad64..33e1c12cd8 100644 --- a/docs/subsystems/compaction.i18n.yaml +++ b/docs/subsystems/compaction.i18n.yaml @@ -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 docs/subsystems/compaction.md -compaction.md: 1e14c60161ef945069d9e6f72767dabdfa42e702 -compaction.zh.md: 60f5afb8c673c94c9c6f5802fb4f12e224e04203 +compaction.md: 95a3d4b844c6126a09d4fdaafdedcf987b21d1c6 +compaction.zh.md: 3b72bb4f81675119d869fb2f7439f4640e6a5a86 diff --git a/docs/subsystems/compaction.md b/docs/subsystems/compaction.md index 1e14c60161..95a3d4b844 100644 --- a/docs/subsystems/compaction.md +++ b/docs/subsystems/compaction.md @@ -2,7 +2,7 @@ English | [中文](compaction.zh.md) -The compaction seam — a [capability seam](../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md) split like bash: Service Definition ([dsh-compaction](../../packages/compaction/compaction), `ctx.compaction`), Service provider (a backend such as [dsh-compaction-basic](../../packages/compaction/compaction-basic)), and human Consumer ([dsh-command-compact](../../packages/compaction/command-compact)). Compaction is **one optional capability**, not part of the agent-loop spine — so its vocabulary lives here, not in [core.md](core.md). A tokenizer- or template-based backend is a sibling package implementing the same interface. Unlike bash, the interface necessarily depends on `dsh-session` and `dsh-llm`: its verbs act on an agent-owned `Session`, and its durable summary event uses the `ContentBlock` vocabulary (see the [compaction capability-seam Agent Note](../../.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.md)). +The compaction seam — a [capability seam](../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md) split like bash: Service Definition ([dsh-compaction](../../packages/compaction/compaction), `ctx.compaction`), Service Provider (a backend such as [dsh-compaction-basic](../../packages/compaction/compaction-basic)), and human Consumer ([dsh-command-compact](../../packages/compaction/command-compact)). Compaction is **one optional capability**, not part of the agent-loop spine — so its vocabulary lives here, not in [core.md](core.md). A tokenizer- or template-based backend is a sibling package implementing the same interface. Unlike bash, the interface necessarily depends on `dsh-session` and `dsh-llm`: its verbs act on an agent-owned `Session`, and its durable summary event uses the `ContentBlock` vocabulary (see the [compaction capability-seam Agent Note](../../.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.md)). Source: [`packages/compaction/compaction/src/types.ts`](../../packages/compaction/compaction/src/types.ts) diff --git a/docs/subsystems/compaction.zh.md b/docs/subsystems/compaction.zh.md index 60f5afb8c6..3b72bb4f81 100644 --- a/docs/subsystems/compaction.zh.md +++ b/docs/subsystems/compaction.zh.md @@ -2,7 +2,7 @@ [English](compaction.md) | 中文 -压缩 seam 是一个[能力 seam](../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md),与 bash 一样分为 Service Definition([dsh-compaction](../../packages/compaction/compaction),`ctx.compaction`)、Service provider(例如 [dsh-compaction-basic](../../packages/compaction/compaction-basic) 后端)和面向用户的 Consumer([dsh-command-compact](../../packages/compaction/command-compact))。压缩是**一项可选能力**,不属于 agent loop(智能体循环)主干,因此其词汇定义在此而非 [core.md](core.md) 中。基于 tokenizer 或模板的后端是实现同一接口的兄弟包。与 bash 不同,该接口必然依赖 `dsh-session` 和 `dsh-llm`:其动词作用于 agent 所有的 `Session`,而其持久摘要事件使用 `ContentBlock` 词汇(见[压缩能力 seam Agent Note](../../.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.md))。 +压缩 seam 是一个[能力 seam](../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md),与 bash 一样分为 Service Definition([dsh-compaction](../../packages/compaction/compaction),`ctx.compaction`)、Service Provider(例如 [dsh-compaction-basic](../../packages/compaction/compaction-basic) 后端)和面向用户的 Consumer([dsh-command-compact](../../packages/compaction/command-compact))。压缩是**一项可选能力**,不属于 agent loop(智能体循环)主干,因此其词汇定义在此而非 [core.md](core.md) 中。基于 tokenizer 或模板的后端是实现同一接口的兄弟包。与 bash 不同,该接口必然依赖 `dsh-session` 和 `dsh-llm`:其动词作用于 agent 所有的 `Session`,而其持久摘要事件使用 `ContentBlock` 词汇(见[压缩能力 seam Agent Note](../../.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.md))。 源码:[`packages/compaction/compaction/src/types.ts`](../../packages/compaction/compaction/src/types.ts) diff --git a/docs/subsystems/core.i18n.yaml b/docs/subsystems/core.i18n.yaml index 041f874d47..1265b726fe 100644 --- a/docs/subsystems/core.i18n.yaml +++ b/docs/subsystems/core.i18n.yaml @@ -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 docs/subsystems/core.md -core.md: 6eda80cbd164168c3c4a846c9bc50a8fc12b0c92 -core.zh.md: 14c2e78bc3fff959fb0c0040eae0f382985ecdf4 +core.md: d14ad52e57572d5b0b110a0b16ff734e3499bdf5 +core.zh.md: 9ace28731f2532f571b66f2e7f6a3ea4a2c4e345 diff --git a/docs/subsystems/core.md b/docs/subsystems/core.md index 6eda80cbd1..d14ad52e57 100644 --- a/docs/subsystems/core.md +++ b/docs/subsystems/core.md @@ -257,6 +257,8 @@ Its full fields, the `defineTool`/`ValueSchemaSpec`/`ParameterSchemaSpec` typed Two patterns recur across every subsystem and are documented once, here. + + ### The `…Map → derived-union` pattern Almost every extensible sum type in the harness follows one pattern: an interface keyed by a discriminant tag (the `…Map`), from which the union is derived with `keyof`. Plugins add variants by **declaration merging** — no edit to the owning package. diff --git a/docs/subsystems/core.zh.md b/docs/subsystems/core.zh.md index 14c2e78bc3..9ace28731f 100644 --- a/docs/subsystems/core.zh.md +++ b/docs/subsystems/core.zh.md @@ -263,6 +263,8 @@ type SessionStartSource = 'startup' | 'resume' | 'clear' | 'compact' 两个模式在每个子系统中反复出现,只在此处记录一次。 + + ### `…Map → derived-union` 模式 harness 中几乎所有可扩展的和类型都遵循同一模式:一个以判别标签为键的接口(`…Map`),联合类型由 `keyof` 派生。插件通过**声明合并**添加变体——无需修改拥有该类型的包。 diff --git a/docs/subsystems/jobs.i18n.yaml b/docs/subsystems/jobs.i18n.yaml index 83199a1ad8..747741008d 100644 --- a/docs/subsystems/jobs.i18n.yaml +++ b/docs/subsystems/jobs.i18n.yaml @@ -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 docs/subsystems/jobs.md -jobs.md: 67998599f8bc8c9b50278e9eaab8b6a5c70a33bc -jobs.zh.md: 41f60e450dcb85ee867a6c44f1e0053950f3ec71 +jobs.md: b11dc7fbe869dcaa9e71e6956a76559476391775 +jobs.zh.md: 03c3ceee8953c8c4c70f060b7e9d88371c1ebd7b diff --git a/docs/subsystems/jobs.md b/docs/subsystems/jobs.md index 67998599f8..b11dc7fbe8 100644 --- a/docs/subsystems/jobs.md +++ b/docs/subsystems/jobs.md @@ -154,7 +154,7 @@ interface JobRead { ## Service behavior -The abstract [`JobRegistry`](../../packages/jobs/jobs/src/index.ts) Service Definition specifies atomic `start`, caller-scoped `get` and `list`, `read`, `kill`, bounded `wait`, failure-isolated `onJobDone` and `onJobsChanged` listeners, and when `attachController` becomes available; [`LocalJobRegistry`](../../packages/jobs/jobs-local/src/index.ts) is the process-local Service provider. Authorization compares owner sessions; owner cleanup and admission use the exact registered `Agent` instance. The local provider's positive-safe-integer `maxConcurrentJobsPerOwner` config defaults to `10` and counts `running` plus `stopping` records per exact owner, with one shared bucket for unowned jobs; terminal producer settlement releases capacity. See [`dsh-jobs`](../../packages/jobs/jobs/README.md) for the Service Definition contract, [`dsh-jobs-local`](../../packages/jobs/jobs-local/README.md) for the registry lifecycle and admission policy, and [`dsh-tool-jobs`](../../packages/jobs/tool-jobs/README.md) for the model-facing Consumer. +The abstract [`JobRegistry`](../../packages/jobs/jobs/src/index.ts) Service Definition specifies atomic `start`, caller-scoped `get` and `list`, `read`, `kill`, bounded `wait`, failure-isolated `onJobDone` and `onJobsChanged` listeners, and when `attachController` becomes available; [`LocalJobRegistry`](../../packages/jobs/jobs-local/src/index.ts) is the process-local Service Provider. Authorization compares owner sessions; owner cleanup and admission use the exact registered `Agent` instance. The local provider's positive-safe-integer `maxConcurrentJobsPerOwner` config defaults to `10` and counts `running` plus `stopping` records per exact owner, with one shared bucket for unowned jobs; terminal producer settlement releases capacity. See [`dsh-jobs`](../../packages/jobs/jobs/README.md) for the Service Definition contract, [`dsh-jobs-local`](../../packages/jobs/jobs-local/README.md) for the registry lifecycle and admission policy, and [`dsh-tool-jobs`](../../packages/jobs/tool-jobs/README.md) for the model-facing Consumer. diff --git a/docs/subsystems/jobs.zh.md b/docs/subsystems/jobs.zh.md index 41f60e450d..03c3ceee89 100644 --- a/docs/subsystems/jobs.zh.md +++ b/docs/subsystems/jobs.zh.md @@ -154,7 +154,7 @@ interface JobRead { ## 服务行为 -抽象的 [`JobRegistry`](../../packages/jobs/jobs/src/index.ts) Service Definition 规定原子 `start`、限定调用方作用域的 `get` 和 `list`、`read`、`kill`、有界 `wait`、故障隔离的 `onJobDone` 与 `onJobsChanged` 监听器,以及 `attachController` 何时可用;[`LocalJobRegistry`](../../packages/jobs/jobs-local/src/index.ts) 是其进程局部 Service provider。授权会比较拥有者会话;拥有者清理与准入会使用确切的已注册 `Agent` 实例。本地 Service provider 的 `maxConcurrentJobsPerOwner` 配置必须是正的安全整数,默认值为 `10`;它按确切 owner 统计 `running` 与 `stopping` 记录,所有无 owner 任务共享一个服务级桶,并在生产方终止结算后释放容量。Service Definition 约定见 [`dsh-jobs`](../../packages/jobs/jobs/README.md),注册表生命周期与准入策略见 [`dsh-jobs-local`](../../packages/jobs/jobs-local/README.md),面向模型的 Consumer 见 [`dsh-tool-jobs`](../../packages/jobs/tool-jobs/README.md)。 +抽象的 [`JobRegistry`](../../packages/jobs/jobs/src/index.ts) Service Definition 规定原子 `start`、限定调用方作用域的 `get` 和 `list`、`read`、`kill`、有界 `wait`、故障隔离的 `onJobDone` 与 `onJobsChanged` 监听器,以及 `attachController` 何时可用;[`LocalJobRegistry`](../../packages/jobs/jobs-local/src/index.ts) 是其进程局部 Service Provider。授权会比较拥有者会话;拥有者清理与准入会使用确切的已注册 `Agent` 实例。本地 Service Provider 的 `maxConcurrentJobsPerOwner` 配置必须是正的安全整数,默认值为 `10`;它按确切 owner 统计 `running` 与 `stopping` 记录,所有无 owner 任务共享一个服务级桶,并在生产方终止结算后释放容量。Service Definition 约定见 [`dsh-jobs`](../../packages/jobs/jobs/README.md),注册表生命周期与准入策略见 [`dsh-jobs-local`](../../packages/jobs/jobs-local/README.md),面向模型的 Consumer 见 [`dsh-tool-jobs`](../../packages/jobs/tool-jobs/README.md)。 diff --git a/docs/subsystems/llm-streaming.i18n.yaml b/docs/subsystems/llm-streaming.i18n.yaml index d1d2810cfe..8f287e2a0f 100644 --- a/docs/subsystems/llm-streaming.i18n.yaml +++ b/docs/subsystems/llm-streaming.i18n.yaml @@ -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 docs/subsystems/llm-streaming.md -llm-streaming.md: 0f395245332e735c04997bd1ca82f66fa9286104 -llm-streaming.zh.md: fbaa47d14d57e7377be4db6ecaa04f11997572a6 +llm-streaming.md: 7c0e0865f8dcc0e7722bb2205d0129d9e0ca3086 +llm-streaming.zh.md: 5c31909ee79137c6c5eef101235b43a2419b1339 diff --git a/docs/subsystems/llm-streaming.md b/docs/subsystems/llm-streaming.md index 0f39524533..7c0e0865f8 100644 --- a/docs/subsystems/llm-streaming.md +++ b/docs/subsystems/llm-streaming.md @@ -151,10 +151,35 @@ type ContextFormed = | { readonly form: 'recall' } ``` + + ## `StreamChunk` — the raw protocol A streaming response interleaves several typed blocks (text, reasoning, multiple tool calls). `index` ties each delta to its block; `block-end` carries the fully-assembled `ContentBlock` so consumers don't have to re-assemble deltas themselves. It is a **closed** discriminated union — a `switch` over `type` ends with `assertNever`, so adding a variant breaks compilation at every consumer that must handle it. +```ts type-equiv +/** + * Adapter-private lossless-JSON state for replaying a successful response, + * carried by a terminal `finish` chunk and stored on the assembled assistant + * message's model source. Both halves stay opaque to the harness; only the + * split is shared vocabulary, so assembly can keep stored metadata aligned + * with stored content without reading either half. + */ +interface ReplayEnvelope { + /** Response-level adapter-private metadata (ids, native stop reason). */ + response: unknown + /** + * Per-block adapter-private metadata, one entry per emitted block in + * first-seen stream order. When assembly drops a block it drops the entry at + * the same position; entries whose length does not match the emitted block + * count discard the whole envelope. An adapter whose metadata is independent + * of block structure omits this field and the envelope passes through + * assembly unchanged. + */ + blocks?: readonly unknown[] +} +``` + ```ts type-equiv /** * Raw streaming protocol emitted by adapters. @@ -174,8 +199,8 @@ type StreamChunk = | { type: 'finish' reason: FinishReason - /** Adapter-private lossless-JSON state for replaying a successful response. */ - replayState?: unknown + /** Replay metadata for a successful response; see {@link ReplayEnvelope}. */ + replayState?: ReplayEnvelope } ``` @@ -211,7 +236,7 @@ Every adapter MUST obey these, and every consumer may rely on them: - **Context overflow has one canonical code.** Both DeepSeek adapters classify explicit provider detail through `isContextWindowExceededError()` and surface `CONTEXT_WINDOW_EXCEEDED`, whether the failure arrives as a thrown HTTP `LlmError` or an in-band finish error. Consumers route on the code, never provider text. - **An empty completion is a retryable error, not a silent success.** Both adapters map a terminal `stop` finish that carried no content blocks to `finish {kind:'error'}` with the canonical `EMPTY_RESPONSE` code, and `dsh-llm-retry` retries it by default; see [empty model responses are retryable](../../.agents/notes/implemented/bug-fix/2026-07-24-empty-model-response-is-retryable.md). - **Every provider HTTP request carries the app-attribution header.** Adapters send `attributionHeaders()` (below) - the `User-Agent` baseline - and prove it with a wire-level test. -- **Replay state is adapter-owned.** A successful `finish` may carry lossless-JSON state needed to reconstruct a native provider response. The loop stores it with the assembled assistant message. On a later request, `LlmRuntime` passes the state only when the historical provider and target provider are currently registered to the exact same adapter instance. That adapter validates the state and owns any cross-model or cross-provider conversion; other adapters receive the provider-neutral content plus provider/model fields without the private state. +- **Replay state is adapter-owned; its split is shared.** A successful `finish` may carry a `ReplayEnvelope`: opaque response-level metadata plus optional per-block entries aligned with the emitted block sequence. The alignment is the harness's vocabulary — when assembly drops a block it drops the entry at the same position, so stored metadata always describes stored content. The loop stores the pruned envelope with the assembled assistant message. On a later request, `LlmRuntime` passes the state only when the historical provider and target provider are currently registered to the exact same adapter instance. That adapter validates the state and owns any cross-model or cross-provider conversion; other adapters receive the provider-neutral content plus provider/model fields without the private state. Durable content stays authoritative: a stored state the reading adapter cannot use degrades that one message to provider-neutral conversion with a diagnostic instead of failing the request. ## `ResolvedRetryPolicy` @@ -265,6 +290,8 @@ interface TokenUsage { `BlockAssembler` ([`packages/llm/llm/src/assembler.ts`](../../packages/llm/llm/src/assembler.ts)) is the single shared implementation that folds a `StreamChunk` stream back into `ContentBlock`s, usage, finish reason, and replay state. The loop logs the raw chunks while feeding the same chunks through an assembler, then stores the assembled assistant content with the provider and model that produced it. A consumer that needs the assembled result without re-implementing the fold uses this. +One keep/drop decision covers content and metadata together: a `max-tokens` finish drops every tool call because a truncated call is unsafe to execute, and the same decision prunes the replay envelope's per-block entry at each dropped position. `blocks()` and `replayState` therefore cannot disagree, whatever assembly removes. + ```ts public-api /** * Incrementally assembles raw {@link StreamChunk}s into complete @@ -294,8 +321,12 @@ declare class BlockAssembler { get usage(): TokenUsage | undefined; /** Finish reason from the `finish` chunk; `{kind: 'stop'}` when the stream ended without one. */ get finish(): FinishReason; - /** Adapter-private replay state from the terminal finish chunk, if any. */ - get replayState(): unknown; + /** + * Replay metadata from the terminal finish chunk, if any, with per-block + * entries pruned in step with {@link blocks}. Undefined when the envelope's + * entries do not align with the emitted blocks. + */ + get replayState(): ReplayEnvelope | undefined; /** * The assembled assistant message. * @param source - producer attribution for the assembled message. diff --git a/docs/subsystems/llm-streaming.zh.md b/docs/subsystems/llm-streaming.zh.md index fbaa47d14d..5c31909ee7 100644 --- a/docs/subsystems/llm-streaming.zh.md +++ b/docs/subsystems/llm-streaming.zh.md @@ -157,6 +157,29 @@ type ContextFormed = 一个流式响应交错包含多种类型的块(文本、推理(reasoning)、多个工具调用)。`index` 将每个 delta 关联到其所属块;`block-end` 携带完整组装好的 `ContentBlock`,消费方无需自行重新组装 delta。这是一个**封闭的**可辨识联合类型:对 `type` 的 `switch` 以 `assertNever` 结尾,因此新增变体会在每个必须处理它的消费方处触发编译错误。 +```ts type-equiv +/** + * Adapter-private lossless-JSON state for replaying a successful response, + * carried by a terminal `finish` chunk and stored on the assembled assistant + * message's model source. Both halves stay opaque to the harness; only the + * split is shared vocabulary, so assembly can keep stored metadata aligned + * with stored content without reading either half. + */ +interface ReplayEnvelope { + /** Response-level adapter-private metadata (ids, native stop reason). */ + response: unknown + /** + * Per-block adapter-private metadata, one entry per emitted block in + * first-seen stream order. When assembly drops a block it drops the entry at + * the same position; entries whose length does not match the emitted block + * count discard the whole envelope. An adapter whose metadata is independent + * of block structure omits this field and the envelope passes through + * assembly unchanged. + */ + blocks?: readonly unknown[] +} +``` + ```ts type-equiv /** * Raw streaming protocol emitted by adapters. @@ -176,8 +199,8 @@ type StreamChunk = | { type: 'finish' reason: FinishReason - /** Adapter-private lossless-JSON state for replaying a successful response. */ - replayState?: unknown + /** Replay metadata for a successful response; see {@link ReplayEnvelope}. */ + replayState?: ReplayEnvelope } ``` @@ -215,7 +238,7 @@ interface LlmFailure { - **上下文溢出只有一个规范 code。** 两个 DeepSeek 适配器都通过 `isContextWindowExceededError()` 对提供方的显式细节分类并暴露 `CONTEXT_WINDOW_EXCEEDED`,无论失败以抛出的 HTTP `LlmError` 还是带内 finish error 到达。消费方按 code 路由,绝不依赖提供方文本。 - **空 completion 是可重试错误,而不是静默的成功结果。** 两个适配器都把没有携带任何内容块的终止性 `stop` 结束映射为携带规范 `EMPTY_RESPONSE` code 的 `finish {kind:'error'}`,`dsh-llm-retry` 默认会重试它;详见[空模型响应可重试](../../.agents/notes/implemented/bug-fix/2026-07-24-empty-model-response-is-retryable.md)。 - **每个提供方 HTTP 请求都携带应用归属头。** 适配器发送 `attributionHeaders()`(见下文)作为 `User-Agent` 基线,并通过协议级测试加以证明。 -- **回放状态归适配器所有。** 成功的 `finish` 可以携带重建提供方原生响应所需的无损 JSON 状态。循环会将其与组装后的 assistant 消息一起存储。后续请求中,仅当历史提供方与目标提供方当前注册到完全相同的适配器实例时,`LlmRuntime` 才会传递该状态。该适配器负责校验状态并拥有所有跨模型或跨提供方转换;其他适配器只会收到提供方无关的内容以及提供方/模型字段,不会收到私有状态。 +- **回放状态归适配器所有;其切分是共享词汇。** 成功的 `finish` 可以携带一个 `ReplayEnvelope`:不透明的响应级元数据,加上与发射块序列对齐的可选逐块条目。对齐关系是 harness 的词汇——组装丢弃某个块时,同一位置的条目一并丢弃,因此存储的元数据始终描述存储的内容。循环把裁剪后的数据与组装后的 assistant 消息一起存储。后续请求中,仅当历史提供方与目标提供方当前注册到完全相同的适配器实例时,`LlmRuntime` 才会传递该状态。该适配器负责校验状态并拥有所有跨模型或跨提供方转换;其他适配器只会收到提供方无关的内容以及提供方/模型字段,不会收到私有状态。持久化内容保持权威:读取适配器无法使用的已存状态只会把这一条消息降级为提供方无关转换并带出诊断,而不是让请求失败。 ## `ResolvedRetryPolicy` @@ -273,6 +296,8 @@ interface TokenUsage { `BlockAssembler`([`packages/llm/llm/src/assembler.ts`](../../packages/llm/llm/src/assembler.ts))是唯一的共享实现,负责把 `StreamChunk` 流折叠回 `ContentBlock`、usage、结束原因与回放状态。循环在记录原始分片的同时,把同一批分片送入 assembler,再将组装后的 assistant 内容连同生成它的提供方和模型一起存储。需要组装结果、又不想重新实现 fold 的消费方使用它。 +内容与元数据共用同一次保留/丢弃决定:`max-tokens` 结束会丢弃每个工具调用,因为被截断的调用不能安全执行,而同一决定会在每个被丢弃的位置裁剪回放数据的逐块条目。无论组装移除什么,`blocks()` 与 `replayState` 都不可能不一致。 + ```ts public-api /** * Incrementally assembles raw {@link StreamChunk}s into complete @@ -302,8 +327,12 @@ declare class BlockAssembler { get usage(): TokenUsage | undefined; /** Finish reason from the `finish` chunk; `{kind: 'stop'}` when the stream ended without one. */ get finish(): FinishReason; - /** Adapter-private replay state from the terminal finish chunk, if any. */ - get replayState(): unknown; + /** + * Replay metadata from the terminal finish chunk, if any, with per-block + * entries pruned in step with {@link blocks}. Undefined when the envelope's + * entries do not align with the emitted blocks. + */ + get replayState(): ReplayEnvelope | undefined; /** * The assembled assistant message. * @param source - producer attribution for the assembled message. diff --git a/docs/subsystems/lsp.i18n.yaml b/docs/subsystems/lsp.i18n.yaml index d001f5c6d6..4de29d66b7 100644 --- a/docs/subsystems/lsp.i18n.yaml +++ b/docs/subsystems/lsp.i18n.yaml @@ -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 docs/subsystems/lsp.md -lsp.md: 66317acc25860cfeaa3d8fb35daf2947e811e18c -lsp.zh.md: 8d975e30cb5065fd89645166c657050233eb81da +lsp.md: 18ed0e178c73702534a9964557a3dabf7bb9dd11 +lsp.zh.md: 8b154143057f05d74bf28b715a385a2ec65fbbff diff --git a/docs/subsystems/lsp.md b/docs/subsystems/lsp.md index 66317acc25..18ed0e178c 100644 --- a/docs/subsystems/lsp.md +++ b/docs/subsystems/lsp.md @@ -2,7 +2,7 @@ English | [中文](lsp.zh.md) -The LSP seam — a [capability seam](../../.agents/notes/implemented/architecture/2026-07-15-lsp-capability-seam.md) exposing semantic code navigation on one `ctx.lsp` service, split across packages: Service Definition ([dsh-lsp](../../packages/lsp/lsp), `ctx.lsp` + the provider registry), a generic Service provider ([dsh-lsp-stdio](../../packages/lsp/lsp-stdio), a configured stdio language-server host), and Consumer ([dsh-tool-lsp](../../packages/lsp/tool-lsp), the `lsp` tool schema). LSP is **one optional capability**, not part of the agent-loop spine — so its vocabulary lives here, not in [core.md](core.md). A provider swap does not change how the model asks for navigation. +The LSP seam — a [capability seam](../../.agents/notes/implemented/architecture/2026-07-15-lsp-capability-seam.md) exposing semantic code navigation on one `ctx.lsp` service, split across packages: Service Definition ([dsh-lsp](../../packages/lsp/lsp), `ctx.lsp` + the provider registry), a generic Service Provider ([dsh-lsp-stdio](../../packages/lsp/lsp-stdio), a configured stdio language-server host), and Consumer ([dsh-tool-lsp](../../packages/lsp/tool-lsp), the `lsp` tool schema). LSP is **one optional capability**, not part of the agent-loop spine — so its vocabulary lives here, not in [core.md](core.md). A provider swap does not change how the model asks for navigation. Source: [`packages/lsp/lsp/src/types.ts`](../../packages/lsp/lsp/src/types.ts) diff --git a/docs/subsystems/lsp.zh.md b/docs/subsystems/lsp.zh.md index 8d975e30cb..8b15414305 100644 --- a/docs/subsystems/lsp.zh.md +++ b/docs/subsystems/lsp.zh.md @@ -2,7 +2,7 @@ [English](lsp.md) | 中文 -LSP seam 是一个[能力 seam](../../.agents/notes/implemented/architecture/2026-07-15-lsp-capability-seam.md):它在单一 `ctx.lsp` 服务上公开语义代码导航,并拆分到多个包:Service Definition([dsh-lsp](../../packages/lsp/lsp),`ctx.lsp` + 提供方注册表)、通用 Service provider([dsh-lsp-stdio](../../packages/lsp/lsp-stdio),经过配置的 stdio 语言服务器宿主)和 Consumer([dsh-tool-lsp](../../packages/lsp/tool-lsp),即 `lsp` 工具 schema)。LSP 是**一项可选能力**,不属于 agent loop(智能体循环)主干,因此其词汇定义在此而非 [core.md](core.md) 中。更换提供方不会改变模型请求导航的方式。 +LSP seam 是一个[能力 seam](../../.agents/notes/implemented/architecture/2026-07-15-lsp-capability-seam.md):它在单一 `ctx.lsp` 服务上公开语义代码导航,并拆分到多个包:Service Definition([dsh-lsp](../../packages/lsp/lsp),`ctx.lsp` + 提供方注册表)、通用 Service Provider([dsh-lsp-stdio](../../packages/lsp/lsp-stdio),经过配置的 stdio 语言服务器宿主)和 Consumer([dsh-tool-lsp](../../packages/lsp/tool-lsp),即 `lsp` 工具 schema)。LSP 是**一项可选能力**,不属于 agent loop(智能体循环)主干,因此其词汇定义在此而非 [core.md](core.md) 中。更换提供方不会改变模型请求导航的方式。 源文件:[`packages/lsp/lsp/src/types.ts`](../../packages/lsp/lsp/src/types.ts) diff --git a/docs/subsystems/persistence.i18n.yaml b/docs/subsystems/persistence.i18n.yaml index 6d0ca447a2..2950610348 100644 --- a/docs/subsystems/persistence.i18n.yaml +++ b/docs/subsystems/persistence.i18n.yaml @@ -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 docs/subsystems/persistence.md -persistence.md: fde8348d64a200eda5133abf66deedee6be09857 -persistence.zh.md: a2a836d81d153a2697c1d739345501e7e6770eef +persistence.md: 5b1b224e419aca205baba69894ed64467b8fb4e1 +persistence.zh.md: a91e7d66b92270c82287d054e619b665e96ea206 diff --git a/docs/subsystems/persistence.md b/docs/subsystems/persistence.md index fde8348d64..5b1b224e41 100644 --- a/docs/subsystems/persistence.md +++ b/docs/subsystems/persistence.md @@ -36,6 +36,8 @@ interface SessionLocation { } ``` + + ## `SessionHeader` — metadata beside the log Per-session metadata travels **separately** from the event log: format version, cwd, lineage, and the seed boundary are storage concerns, not conversation events, so they stay out of `SessionEventMap` and never reach `deriveMessages()`. The header is attached to a `Session` via `session.header`. diff --git a/docs/subsystems/persistence.zh.md b/docs/subsystems/persistence.zh.md index a2a836d81d..a91e7d66b9 100644 --- a/docs/subsystems/persistence.zh.md +++ b/docs/subsystems/persistence.zh.md @@ -36,6 +36,8 @@ interface SessionLocation { } ``` + + ## `SessionHeader`:日志旁的元数据 每个会话的元数据与事件日志**分开**存储:格式版本、cwd、血统与 seed 边界是存储层关注点而非对话事件,因此不进入 `SessionEventMap`,也不会到达 `deriveMessages()`。header 通过 `session.header` 附加到 `Session` 上。 diff --git a/docs/subsystems/session-query.i18n.yaml b/docs/subsystems/session-query.i18n.yaml index 0d9bb279a4..e53e0a969e 100644 --- a/docs/subsystems/session-query.i18n.yaml +++ b/docs/subsystems/session-query.i18n.yaml @@ -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 docs/subsystems/session-query.md -session-query.md: 647b50a297a434308769ab3c5f1af0af7480b937 -session-query.zh.md: 7b03f8515501abe5e1ab35d50f6a6a230a96cf0c +session-query.md: 6ddde5b8a19ebc65952b5a24003c48f55ff5a244 +session-query.zh.md: b7d4ab4910c99c9f77c17f0279f2d4fd3c336659 diff --git a/docs/subsystems/session-query.md b/docs/subsystems/session-query.md index 647b50a297..6ddde5b8a1 100644 --- a/docs/subsystems/session-query.md +++ b/docs/subsystems/session-query.md @@ -332,7 +332,7 @@ interface SessionEventTraceObservation extends SessionEventTrace { ## Errors -The closed code union distinguishes request validation, missing targets, malformed surface logs, optional-backend failure, and contradictory source metadata. +The closed code union distinguishes request validation, missing targets, malformed surface logs, optional-backend failure, deployment-disabled search, and contradictory source metadata. ```ts type-equiv /** Stable machine-routable failure taxonomy for session reads, traces, and search. */ @@ -350,6 +350,7 @@ type SessionQueryErrorCode = | 'SESSION_QUERY_INVALID_SURFACE' | 'SESSION_QUERY_INVALID_WINDOW' | 'SESSION_QUERY_PERSISTENCE_FAILED' + | 'SESSION_QUERY_SEARCH_DISABLED' | 'SESSION_QUERY_SESSION_NOT_FOUND' | 'SESSION_QUERY_STALE_CURSOR' | 'SESSION_QUERY_SOURCE_CONFLICT' diff --git a/docs/subsystems/session-query.zh.md b/docs/subsystems/session-query.zh.md index 7b03f85155..b7d4ab4910 100644 --- a/docs/subsystems/session-query.zh.md +++ b/docs/subsystems/session-query.zh.md @@ -332,7 +332,7 @@ interface SessionEventTraceObservation extends SessionEventTrace { ## 错误 -封闭的 code 联合类型区分请求校验、目标缺失、surface 日志格式错误、可选后端故障与矛盾的源元数据。 +封闭的 code 联合类型区分请求校验、目标缺失、surface 日志格式错误、可选后端故障、部署关闭搜索与矛盾的源元数据。 ```ts type-equiv /** Stable machine-routable failure taxonomy for session reads, traces, and search. */ @@ -350,6 +350,7 @@ type SessionQueryErrorCode = | 'SESSION_QUERY_INVALID_SURFACE' | 'SESSION_QUERY_INVALID_WINDOW' | 'SESSION_QUERY_PERSISTENCE_FAILED' + | 'SESSION_QUERY_SEARCH_DISABLED' | 'SESSION_QUERY_SESSION_NOT_FOUND' | 'SESSION_QUERY_STALE_CURSOR' | 'SESSION_QUERY_SOURCE_CONFLICT' diff --git a/docs/subsystems/session-telemetry.i18n.yaml b/docs/subsystems/session-telemetry.i18n.yaml index 31bcdef024..49f5b9c328 100644 --- a/docs/subsystems/session-telemetry.i18n.yaml +++ b/docs/subsystems/session-telemetry.i18n.yaml @@ -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 docs/subsystems/session-telemetry.md -session-telemetry.md: f6a51dbd1de43525e0a1b062f11a140317a1cdd9 -session-telemetry.zh.md: 8cfd04121f9ab9741fd4a968c3f73eb6983992b7 +session-telemetry.md: dd00e428c3ecb1e0158be09cce83d1a262ab0c62 +session-telemetry.zh.md: 835fc0ff2f2daa1f4ac90fe615a62aa36f7fe41d diff --git a/docs/subsystems/session-telemetry.md b/docs/subsystems/session-telemetry.md index f6a51dbd1d..dd00e428c3 100644 --- a/docs/subsystems/session-telemetry.md +++ b/docs/subsystems/session-telemetry.md @@ -2,7 +2,7 @@ English | [中文](session-telemetry.zh.md) -Outbound session reporting is split as a [capability seam](../capability-seams.md): the Service Definition and capture coordinator ([dsh-session-telemetry](../../packages/session/session-telemetry), `ctx.sessionTelemetry`) own the capture points, fixed chunk projection, `session-telemetry/record` redaction waterfall, handoff cursor, and minimal backend contract; the Service provider a deployment loads ([dsh-session-telemetry-otel](../../packages/session/session-telemetry-otel)) is the OpenTelemetry JS SDK's log pipeline configured verbatim. It is one optional capability, not part of the agent-loop spine, and nothing here reaches a model request. The boundary axiom — the harness's aspect ends at `emit()`; batching, retry, queueing, and loss policy belong to the reporting SDK — and the rejected alternatives are pinned in the [revival Agent Note](../../.agents/notes/implemented/feature/2026-07-23-session-telemetry-otel-revival.md); the capture points, cursor, and projection contracts live in the [Service Definition README](../../packages/session/session-telemetry/README.md). +Outbound session reporting is split as a [capability seam](../capability-seams.md): the Service Definition and capture coordinator ([dsh-session-telemetry](../../packages/session/session-telemetry), `ctx.sessionTelemetry`) own the capture points, fixed chunk projection, `session-telemetry/record` redaction waterfall, handoff cursor, and minimal backend contract; the Service Provider a deployment loads ([dsh-session-telemetry-otel](../../packages/session/session-telemetry-otel)) is the OpenTelemetry JS SDK's log pipeline configured verbatim. It is one optional capability, not part of the agent-loop spine, and nothing here reaches a model request. The boundary axiom — the harness's aspect ends at `emit()`; batching, retry, queueing, and loss policy belong to the reporting SDK — and the rejected alternatives are pinned in the [revival Agent Note](../../.agents/notes/implemented/feature/2026-07-23-session-telemetry-otel-revival.md); the capture points, cursor, and projection contracts live in the [Service Definition README](../../packages/session/session-telemetry/README.md). Source: [`packages/session/session-telemetry/src/index.ts`](../../packages/session/session-telemetry/src/index.ts) diff --git a/docs/subsystems/session-telemetry.zh.md b/docs/subsystems/session-telemetry.zh.md index 8cfd04121f..835fc0ff2f 100644 --- a/docs/subsystems/session-telemetry.zh.md +++ b/docs/subsystems/session-telemetry.zh.md @@ -2,7 +2,7 @@ [English](session-telemetry.md) | 中文 -对外的会话上报拆分为一项[能力 seam](../capability-seams.md):Service Definition 与捕获协调器([dsh-session-telemetry](../../packages/session/session-telemetry),`ctx.sessionTelemetry`)拥有捕获点、固定分片投影、`session-telemetry/record` 脱敏 waterfall(瀑布式事件)、handoff 游标与最小后端约定;部署方加载的 Service provider([dsh-session-telemetry-otel](../../packages/session/session-telemetry-otel))则是原样配置的 OpenTelemetry JS SDK 日志流水线。它是一项可选能力,不属于 agent loop(智能体循环)主干,这里也没有任何内容会进入模型请求。边界公理(harness 的职责止于 `emit()`;批处理、重试、排队与丢失策略都属于上报 SDK)连同被否决的替代方案,均已在[复活 Agent Note](../../.agents/notes/implemented/feature/2026-07-23-session-telemetry-otel-revival.md)中定案;捕获点、游标与投影的约定见 [Service Definition README](../../packages/session/session-telemetry/README.md)。 +对外的会话上报拆分为一项[能力 seam](../capability-seams.md):Service Definition 与捕获协调器([dsh-session-telemetry](../../packages/session/session-telemetry),`ctx.sessionTelemetry`)拥有捕获点、固定分片投影、`session-telemetry/record` 脱敏 waterfall(瀑布式事件)、handoff 游标与最小后端约定;部署方加载的 Service Provider([dsh-session-telemetry-otel](../../packages/session/session-telemetry-otel))则是原样配置的 OpenTelemetry JS SDK 日志流水线。它是一项可选能力,不属于 agent loop(智能体循环)主干,这里也没有任何内容会进入模型请求。边界公理(harness 的职责止于 `emit()`;批处理、重试、排队与丢失策略都属于上报 SDK)连同被否决的替代方案,均已在[复活 Agent Note](../../.agents/notes/implemented/feature/2026-07-23-session-telemetry-otel-revival.md)中定案;捕获点、游标与投影的约定见 [Service Definition README](../../packages/session/session-telemetry/README.md)。 源码:[`packages/session/session-telemetry/src/index.ts`](../../packages/session/session-telemetry/src/index.ts) diff --git a/docs/subsystems/session.i18n.yaml b/docs/subsystems/session.i18n.yaml index 8ee4185e54..1c33960769 100644 --- a/docs/subsystems/session.i18n.yaml +++ b/docs/subsystems/session.i18n.yaml @@ -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 docs/subsystems/session.md -session.md: 4c40971fe58952b32635aa5eb767a42f73108b00 -session.zh.md: d958b03fcdad91b58cc277636e599cce46a2c7fb +session.md: aea9d00b38e384e7a973ce168c3a75a62e70a8bb +session.zh.md: 8c56029af5144569f1ab6df73a8fe2278f9ef5b4 diff --git a/docs/subsystems/session.md b/docs/subsystems/session.md index 4c40971fe5..aea9d00b38 100644 --- a/docs/subsystems/session.md +++ b/docs/subsystems/session.md @@ -149,6 +149,8 @@ interface TodoItem { } ``` + + ### The request header event: `request/header` The request envelope — the `EpochHeader` (call config + markers for adapter-supplied defaults + rendered system prompt + assembled tool schemas) — is logged session state, so every conversation request is a pure function of the log (the reconstructability Agent Note). A full `request/header` snapshot with reason `'initial'` or `'resume'` records each loop-instance boundary; a later changed request records another full snapshot with reason `'change'`. `foldRequestHeader(events)` reconstructs the header by selecting the latest snapshot. The event is not a `SurfaceEventType`: it produces no LLM message. @@ -586,7 +588,7 @@ An explicitly supplied empty seed writes `session/end-seed` at seq 0, which dist It exists because seed history and live work are otherwise byte-identical, which defeats any plugin owning a standalone open/close bracket: an unmatched `compaction/start` reads the same whether the writer crashed mid-compaction or is compacting right now. An opening marker before `session/end-seed` came from the constructor seed and belongs to an ended lifecycle, whatever ended it (a crash, a succeeding process, or a fork out of a still-running parent), so its owner may treat it as dead. That covers only brackets *this* session inherited: a concurrently live session holding an open bracket over the same history has its own boundary elsewhere, so tolerating concurrent writers needs a liveness signal beyond the log. Core writes the boundary and reads nothing from it — a bracket's vocabulary stays with its owning plugin, which is why crash repair closes turn/step/tool boundaries and never `compaction/*`. -Activity ordering excludes the boundary through `lastActivityTime(events)`: picking a session up is not work, and lazy resume means browsing writes one, so a resume picker or session list ordering by log tail would float every opened session to the top. +Consumers that order Sessions by human activity exclude this boundary: picking a Session up is not work, so ordering by the log tail would float every opened Session to the top. ## Plugin-contributed log-only events diff --git a/docs/subsystems/session.zh.md b/docs/subsystems/session.zh.md index d958b03fcd..8c56029af5 100644 --- a/docs/subsystems/session.zh.md +++ b/docs/subsystems/session.zh.md @@ -590,7 +590,7 @@ interface TurnEndReasonMap { 它之所以必要,是因为种子历史与实时工作在字节层面完全相同,这会让任何拥有独立开/闭括号的插件失效:一个未配对的 `compaction/start`,无论写入方是在压缩中途崩溃、还是此刻正在压缩,读起来都一样。在 `session/end-seed` 之前的开启标记来自构造种子,并且属于一个已结束的生命周期,无论结束原因为何(崩溃、进程接替,或从仍在运行的父会话 fork 出来),因此其所有方可以视之为已死。这只覆盖*本*会话继承的括号:另一个并发存活的会话可能在同一段历史上持有开放括号,而它自己的边界在别处,因此容忍并发写入方还需要日志之外的存活信号。核心写入该边界但不从中读取任何内容——括号的词汇表仍归其所属插件,这也正是崩溃修复只关闭轮次/步骤/工具边界而从不处理 `compaction/*` 的原因。 -活动排序通过 `lastActivityTime(events)` 排除该边界:接手会话不算工作,而惰性恢复意味着浏览就会写入一个,因此按日志尾部排序的恢复选择器或会话列表会把每个打开过的会话顶到最前。 +按真人活动排序 Session 的消费方会排除该边界:接手 Session 不算工作,因此按日志尾部排序会把每个打开过的 Session 顶到最前。 ## 插件贡献的仅日志事件 diff --git a/docs/subsystems/shell.i18n.yaml b/docs/subsystems/shell.i18n.yaml index 822ce1fb60..a7b6bf45fc 100644 --- a/docs/subsystems/shell.i18n.yaml +++ b/docs/subsystems/shell.i18n.yaml @@ -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 docs/subsystems/shell.md -shell.md: 10f96936390a2b77f961ca6222d1e8c4019bbd9c -shell.zh.md: af0bc72b620c747ce107acdfeade699967e38568 +shell.md: b9f8e3aebb69348ea241be93d6fd5559068c4029 +shell.zh.md: 1ea086819f3badc92376d39cb13e584da772572b diff --git a/docs/subsystems/shell.md b/docs/subsystems/shell.md index 10f9693639..b9f8e3aebb 100644 --- a/docs/subsystems/shell.md +++ b/docs/subsystems/shell.md @@ -2,7 +2,7 @@ English | [中文](shell.zh.md) -The bash execution seam is split across a Service Definition ([dsh-shell](../../packages/shell/shell), `ctx.shell`), Service providers ([dsh-bash-local](../../packages/shell/bash-local) and [dsh-bash-sandbox](../../packages/shell/bash-sandbox)), and Consumer ([dsh-tool-bash](../../packages/shell/tool-bash), the `bash` schema). Generic background-job ids, ownership, and controls live in [jobs.md](jobs.md); this seam returns a task-free process handle. Raw process-group mechanics live behind the [subprocess seam](subprocess.md). +The bash execution seam is split across a Service Definition ([dsh-shell](../../packages/shell/shell), `ctx.shell`), Service Providers ([dsh-bash-local](../../packages/shell/bash-local) and [dsh-bash-sandbox](../../packages/shell/bash-sandbox)), and Consumer ([dsh-tool-bash](../../packages/shell/tool-bash), the `bash` schema). Generic background-job ids, ownership, and controls live in [jobs.md](jobs.md); this seam returns a task-free process handle. Raw process-group mechanics live behind the [subprocess seam](subprocess.md). Source: [`packages/shell/shell/src/types.ts`](../../packages/shell/shell/src/types.ts) diff --git a/docs/subsystems/shell.zh.md b/docs/subsystems/shell.zh.md index af0bc72b62..1ea086819f 100644 --- a/docs/subsystems/shell.zh.md +++ b/docs/subsystems/shell.zh.md @@ -2,7 +2,7 @@ [English](shell.md) | 中文 -bash 执行 seam 分为 Service Definition([dsh-shell](../../packages/shell/shell),`ctx.shell`)、Service provider([dsh-bash-local](../../packages/shell/bash-local) 与 [dsh-bash-sandbox](../../packages/shell/bash-sandbox))和 Consumer([dsh-tool-bash](../../packages/shell/tool-bash),即 `bash` schema)。通用后台任务的 job id、所有权与控制位于 [jobs.md](jobs.md);本 seam 返回一个不含任务概念的进程句柄。原始进程组机制封装在[子进程 seam](subprocess.md)之后。 +bash 执行 seam 分为 Service Definition([dsh-shell](../../packages/shell/shell),`ctx.shell`)、Service Provider([dsh-bash-local](../../packages/shell/bash-local) 与 [dsh-bash-sandbox](../../packages/shell/bash-sandbox))和 Consumer([dsh-tool-bash](../../packages/shell/tool-bash),即 `bash` schema)。通用后台任务的 job id、所有权与控制位于 [jobs.md](jobs.md);本 seam 返回一个不含任务概念的进程句柄。原始进程组机制封装在[子进程 seam](subprocess.md)之后。 源码:[`packages/shell/shell/src/types.ts`](../../packages/shell/shell/src/types.ts) diff --git a/docs/subsystems/skills.i18n.yaml b/docs/subsystems/skills.i18n.yaml index 97746ffff7..922f1eb95e 100644 --- a/docs/subsystems/skills.i18n.yaml +++ b/docs/subsystems/skills.i18n.yaml @@ -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 docs/subsystems/skills.md -skills.md: 98d5efea0b534e8232aeae03eda3de10259756e3 -skills.zh.md: 8a2b03da4b7bab0a3142eab3cc07f66f379dfd28 +skills.md: cd935692c00f89544dc324b33e847d8d588b78a8 +skills.zh.md: f574db048e1850ee425309fe015cd21a075eefc6 diff --git a/docs/subsystems/skills.md b/docs/subsystems/skills.md index 98d5efea0b..cd935692c0 100644 --- a/docs/subsystems/skills.md +++ b/docs/subsystems/skills.md @@ -2,7 +2,7 @@ English | [中文](skills.zh.md) -The [skill capability family](../../packages/skill) includes the Service Definition ([dsh-skill](../../packages/skill/skill), `ctx.skills`), the local Service provider ([dsh-skill-filesystem](../../packages/skill/skill-filesystem)), the optional packaged badge provider ([dsh-skill-badge](../../packages/skill/skill-badge)), and the Consumer ([dsh-tool-skill](../../packages/skill/tool-skill)). The registry merges provider catalogs across its host and per-scope layers; providers contribute local or packaged skills; the Consumer owns the initial and replacement catalogs plus the model-facing `skill` tool. Skills are optional instructions, not session events, so their vocabulary lives here rather than in [core.md](core.md). +The [skill capability family](../../packages/skill) includes the Service Definition ([dsh-skill](../../packages/skill/skill), `ctx.skills`), the local Service Provider ([dsh-skill-filesystem](../../packages/skill/skill-filesystem)), the optional packaged badge provider ([dsh-skill-badge](../../packages/skill/skill-badge)), and the Consumer ([dsh-tool-skill](../../packages/skill/tool-skill)). The registry merges provider catalogs across its host and per-scope layers; providers contribute local or packaged skills; the Consumer owns the initial and replacement catalogs plus the model-facing `skill` tool. Skills are optional instructions, not session events, so their vocabulary lives here rather than in [core.md](core.md). Source: [`packages/skill/skill/src/index.ts`](../../packages/skill/skill/src/index.ts), [`packages/skill/skill-filesystem/src/index.ts`](../../packages/skill/skill-filesystem/src/index.ts), [`packages/skill/skill-badge/src/index.ts`](../../packages/skill/skill-badge/src/index.ts), and [`packages/skill/tool-skill/src/index.ts`](../../packages/skill/tool-skill/src/index.ts). diff --git a/docs/subsystems/skills.zh.md b/docs/subsystems/skills.zh.md index 8a2b03da4b..f574db048e 100644 --- a/docs/subsystems/skills.zh.md +++ b/docs/subsystems/skills.zh.md @@ -2,7 +2,7 @@ [English](skills.md) | 中文 -[skill(技能)能力族](../../packages/skill) 包含 Service Definition([dsh-skill](../../packages/skill/skill),`ctx.skills`)、本地 Service provider([dsh-skill-filesystem](../../packages/skill/skill-filesystem))、可选的随包徽章提供方([dsh-skill-badge](../../packages/skill/skill-badge))和 Consumer([dsh-tool-skill](../../packages/skill/tool-skill))。注册表在其宿主层与各 scope 层之间合并各提供方的目录;提供方贡献本地或随包 skill;Consumer 拥有初始目录和替换目录,以及面向模型的 `skill` 工具。skill 是可选的指令而非会话事件,因此其词汇定义在此处而非 [core.md](core.md)。 +[skill(技能)能力族](../../packages/skill) 包含 Service Definition([dsh-skill](../../packages/skill/skill),`ctx.skills`)、本地 Service Provider([dsh-skill-filesystem](../../packages/skill/skill-filesystem))、可选的随包徽章提供方([dsh-skill-badge](../../packages/skill/skill-badge))和 Consumer([dsh-tool-skill](../../packages/skill/tool-skill))。注册表在其宿主层与各 scope 层之间合并各提供方的目录;提供方贡献本地或随包 skill;Consumer 拥有初始目录和替换目录,以及面向模型的 `skill` 工具。skill 是可选的指令而非会话事件,因此其词汇定义在此处而非 [core.md](core.md)。 源码:[`packages/skill/skill/src/index.ts`](../../packages/skill/skill/src/index.ts)、[`packages/skill/skill-filesystem/src/index.ts`](../../packages/skill/skill-filesystem/src/index.ts)、[`packages/skill/skill-badge/src/index.ts`](../../packages/skill/skill-badge/src/index.ts) 与 [`packages/skill/tool-skill/src/index.ts`](../../packages/skill/tool-skill/src/index.ts)。 diff --git a/docs/subsystems/spill.i18n.yaml b/docs/subsystems/spill.i18n.yaml index 100914ab62..61283ed82a 100644 --- a/docs/subsystems/spill.i18n.yaml +++ b/docs/subsystems/spill.i18n.yaml @@ -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 docs/subsystems/spill.md -spill.md: 97d18ca2cf06c2062655eb6b22547280e4ee93e7 -spill.zh.md: 32783c748d6097359a7b71950f14ad97ebc924f5 +spill.md: ad59e88b1f059d0127bdf48155450890b1bf7c9a +spill.zh.md: 015ff6fc378c21e30f1cd84c985843f8c06cd44a diff --git a/docs/subsystems/spill.md b/docs/subsystems/spill.md index 97d18ca2cf..ad59e88b1f 100644 --- a/docs/subsystems/spill.md +++ b/docs/subsystems/spill.md @@ -2,7 +2,7 @@ English | [中文](spill.zh.md) -The spill storage seam — a [capability seam](../../.agents/notes/implemented/architecture/2026-07-08-tool-output-spill-files.md) that persists a tool's oversized text and returns a model-facing locator plus retrieval guidance, split across packages: Service Definition ([dsh-spill](../../packages/spill/spill), `ctx.spillStore`), Service provider ([dsh-spill-local](../../packages/spill/spill-local), private session-scoped files on the host filesystem), and Consumer ([dsh-spill-policy](../../packages/spill/spill-policy), the `tools/post-execute` policy). Spill is **one optional capability**, not part of the agent-loop spine — so its vocabulary lives here, not in [core.md](core.md). Preview mechanics stay in [dsh-output-retention](../../packages/util/output-retention); this seam only saves the final text the policy hands it. +The spill storage seam — a [capability seam](../../.agents/notes/implemented/architecture/2026-07-08-tool-output-spill-files.md) that persists a tool's oversized text and returns a model-facing locator plus retrieval guidance, split across packages: Service Definition ([dsh-spill](../../packages/spill/spill), `ctx.spillStore`), Service Provider ([dsh-spill-local](../../packages/spill/spill-local), private session-scoped files on the host filesystem), and Consumer ([dsh-spill-policy](../../packages/spill/spill-policy), the `tools/post-execute` policy). Spill is **one optional capability**, not part of the agent-loop spine — so its vocabulary lives here, not in [core.md](core.md). Preview mechanics stay in [dsh-output-retention](../../packages/util/output-retention); this seam only saves the final text the policy hands it. Source: [`packages/spill/spill/src/types.ts`](../../packages/spill/spill/src/types.ts) diff --git a/docs/subsystems/spill.zh.md b/docs/subsystems/spill.zh.md index 32783c748d..015ff6fc37 100644 --- a/docs/subsystems/spill.zh.md +++ b/docs/subsystems/spill.zh.md @@ -2,7 +2,7 @@ [English](spill.md) | 中文 -spill 存储 seam 是一项[能力 seam](../../.agents/notes/implemented/architecture/2026-07-08-tool-output-spill-files.md),它持久保存工具的超大文本,并返回面向模型的定位符与检索指引;该能力拆分到三个包:Service Definition([dsh-spill](../../packages/spill/spill),`ctx.spillStore`)、Service provider([dsh-spill-local](../../packages/spill/spill-local),宿主文件系统中会话作用域的私有文件)和 Consumer([dsh-spill-policy](../../packages/spill/spill-policy),`tools/post-execute` 策略)。spill 是**一项可选能力**,不属于 agent loop(智能体循环)主干,因此其词汇记录在此处,而不在 [core.md](core.md) 中。预览机制仍归 [dsh-output-retention](../../packages/util/output-retention) 所有;该 seam 只保存策略交给它的最终文本。 +spill 存储 seam 是一项[能力 seam](../../.agents/notes/implemented/architecture/2026-07-08-tool-output-spill-files.md),它持久保存工具的超大文本,并返回面向模型的定位符与检索指引;该能力拆分到三个包:Service Definition([dsh-spill](../../packages/spill/spill),`ctx.spillStore`)、Service Provider([dsh-spill-local](../../packages/spill/spill-local),宿主文件系统中会话作用域的私有文件)和 Consumer([dsh-spill-policy](../../packages/spill/spill-policy),`tools/post-execute` 策略)。spill 是**一项可选能力**,不属于 agent loop(智能体循环)主干,因此其词汇记录在此处,而不在 [core.md](core.md) 中。预览机制仍归 [dsh-output-retention](../../packages/util/output-retention) 所有;该 seam 只保存策略交给它的最终文本。 源码:[`packages/spill/spill/src/types.ts`](../../packages/spill/spill/src/types.ts) diff --git a/docs/subsystems/storage.i18n.yaml b/docs/subsystems/storage.i18n.yaml index fa120bc1fa..68128fdb1b 100644 --- a/docs/subsystems/storage.i18n.yaml +++ b/docs/subsystems/storage.i18n.yaml @@ -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 docs/subsystems/storage.md -storage.md: 33933f70176e1f4960eb423f9a1067f50b6762e4 -storage.zh.md: 2ab3473a83b7588f186ce8f3b83819b29985ae88 +storage.md: 7e7f8d2b5a98b20308ae8115484a25066c045d52 +storage.zh.md: 41d2d1520a846d988c6c7a0b08a7576cee44ff7a diff --git a/docs/subsystems/storage.md b/docs/subsystems/storage.md index 33933f7017..7e7f8d2b5a 100644 --- a/docs/subsystems/storage.md +++ b/docs/subsystems/storage.md @@ -2,7 +2,7 @@ English | [中文](storage.zh.md) -The storage subsystem persists everything that is not a session event log (session logs have their own seam — [persistence.md](persistence.md)). It is one optional capability, not part of the agent-loop spine, split as a [capability seam](../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md): the hub and Service Definition ([dsh-storage](../../packages/storage/storage), `ctx.storage`), the Service providers ([dsh-storage-json](../../packages/storage/storage-json), registered as `json`, and [dsh-storage-sqlite](../../packages/storage/storage-sqlite), registered as `sqlite`), and the Consumer data form ([dsh-storage-domain](../../packages/storage/storage-domain), `ctx.storageDomain`, also reachable as `ctx.storage.domain`) — the backend contract's only Consumer and the typed API everything else uses. The hub performs no IO itself: backends own media, data forms own semantics, and product packages never touch backends directly. Design record: [domain KV storage Agent Note](../../.agents/notes/proposed/architecture/2026-07-24-domain-kv-storage-and-workspace.md). +The storage subsystem persists everything that is not a session event log (session logs have their own seam — [persistence.md](persistence.md)). It is one optional capability, not part of the agent-loop spine, split as a [capability seam](../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md): the hub and Service Definition ([dsh-storage](../../packages/storage/storage), `ctx.storage`), the Service Providers ([dsh-storage-json](../../packages/storage/storage-json), registered as `json`, and [dsh-storage-sqlite](../../packages/storage/storage-sqlite), registered as `sqlite`), and the Consumer data form ([dsh-storage-domain](../../packages/storage/storage-domain), `ctx.storageDomain`, also reachable as `ctx.storage.domain`) — the backend contract's only Consumer and the typed API everything else uses. The hub performs no IO itself: backends own media, data forms own semantics, and product packages never touch backends directly. Design record: [domain KV storage Agent Note](../../.agents/notes/proposed/architecture/2026-07-24-domain-kv-storage-and-workspace.md). Source: [`packages/storage/storage/src/backend.ts`](../../packages/storage/storage/src/backend.ts) · [`packages/storage/storage-domain/src/spec.ts`](../../packages/storage/storage-domain/src/spec.ts) · [`packages/storage/storage-domain/src/events.ts`](../../packages/storage/storage-domain/src/events.ts) diff --git a/docs/subsystems/storage.zh.md b/docs/subsystems/storage.zh.md index 2ab3473a83..41d2d1520a 100644 --- a/docs/subsystems/storage.zh.md +++ b/docs/subsystems/storage.zh.md @@ -2,7 +2,7 @@ [English](storage.md) | 中文 -存储子系统持久保存一切不属于会话事件日志的数据(会话日志有自己的 seam——见 [persistence.md](persistence.md))。它是一项可选能力,不属于 agent loop(智能体循环)主干,并按[能力 seam](../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md) 拆分:枢纽(hub)与 Service Definition([dsh-storage](../../packages/storage/storage),`ctx.storage`)、Service provider(注册为 `json` 的 [dsh-storage-json](../../packages/storage/storage-json) 与注册为 `sqlite` 的 [dsh-storage-sqlite](../../packages/storage/storage-sqlite)),以及 Consumer 数据形式([dsh-storage-domain](../../packages/storage/storage-domain),`ctx.storageDomain`,也可经 `ctx.storage.domain` 访问)——它是后端约定的唯一 Consumer,也是其他一切所使用的类型化 API。枢纽自身不做任何 IO:后端拥有介质,数据形式拥有语义,产品包绝不直接触碰后端。设计记录:[领域 KV 存储 Agent Note](../../.agents/notes/proposed/architecture/2026-07-24-domain-kv-storage-and-workspace.md)。 +存储子系统持久保存一切不属于会话事件日志的数据(会话日志有自己的 seam——见 [persistence.md](persistence.md))。它是一项可选能力,不属于 agent loop(智能体循环)主干,并按[能力 seam](../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md) 拆分:枢纽(hub)与 Service Definition([dsh-storage](../../packages/storage/storage),`ctx.storage`)、Service Provider(注册为 `json` 的 [dsh-storage-json](../../packages/storage/storage-json) 与注册为 `sqlite` 的 [dsh-storage-sqlite](../../packages/storage/storage-sqlite)),以及 Consumer 数据形式([dsh-storage-domain](../../packages/storage/storage-domain),`ctx.storageDomain`,也可经 `ctx.storage.domain` 访问)——它是后端约定的唯一 Consumer,也是其他一切所使用的类型化 API。枢纽自身不做任何 IO:后端拥有介质,数据形式拥有语义,产品包绝不直接触碰后端。设计记录:[领域 KV 存储 Agent Note](../../.agents/notes/proposed/architecture/2026-07-24-domain-kv-storage-and-workspace.md)。 源码:[`packages/storage/storage/src/backend.ts`](../../packages/storage/storage/src/backend.ts) · [`packages/storage/storage-domain/src/spec.ts`](../../packages/storage/storage-domain/src/spec.ts) · [`packages/storage/storage-domain/src/events.ts`](../../packages/storage/storage-domain/src/events.ts) diff --git a/docs/subsystems/subagent.i18n.yaml b/docs/subsystems/subagent.i18n.yaml index d0a1715e39..a86dc8de4a 100644 --- a/docs/subsystems/subagent.i18n.yaml +++ b/docs/subsystems/subagent.i18n.yaml @@ -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 docs/subsystems/subagent.md -subagent.md: 4d02c177533e8dbc192d5460b65bb4348f565c41 -subagent.zh.md: 483446187dcd2386f0f3d7d50d3fa7b97d09e02c +subagent.md: a683a679e6017351540ee4b73adc74375ef0a1d6 +subagent.zh.md: 61391cd297c0eb14f4c0d8eac4539b551cb60bda diff --git a/docs/subsystems/subagent.md b/docs/subsystems/subagent.md index 4d02c17753..a683a679e6 100644 --- a/docs/subsystems/subagent.md +++ b/docs/subsystems/subagent.md @@ -4,7 +4,7 @@ English | [中文](subagent.zh.md) The subagent seam lets an agent delegate work to a child agent. Like [bash](shell.md), it is **one optional capability**, not part of the agent loop, so its types live here rather than in [core.md](core.md). It differs from the other capability seams because **multiple provider implementations coexist** in one context, registered by name (`ctx.subagents`), while bash allows only one executor. Its registry follows the [LLM adapter registry](llm-streaming.md), not the single-service bash executor. -Service Definition: [dsh-subagent](../../packages/subagent/subagent) (`ctx.subagents` + the vocabulary below). Service providers are sibling packages (`dsh-subagent-spawn-in-process`, `-fork`, `-acp`, `-codex`, `-claude-code`, `-dsh-sdk`); the model-facing Consumers are [dsh-tool-subagent](../../packages/subagent/tool-subagent) (per-provider delegation), [dsh-tool-subagent-control](../../packages/subagent/tool-subagent-control) (the optional global `send_message`, `interrupt_agent`, and `list_agents` controls), and [dsh-tool-subagent-report](../../packages/subagent/tool-subagent-report) (the optional child-scoped `report` return channel). The same `ctx.subagents` service owns continuable-child orchestration through an internal activation manager and read-only child and descendant discovery straight from the session store and optional session persistence. Product-provider rationale lives in [the Codex and Claude Code Agent Note](../../.agents/notes/implemented/feature/2026-08-04-claude-code-and-codex-subagent-backends.md); common-seam rationale lives in [the subagent Agent Note](../../.agents/notes/implemented/feature/2026-06-21-subagent-capability-seam.md), [the continuable subagents Agent Note](../../.agents/notes/implemented/feature/2026-07-28-continuable-subagent-conversations.md), [the report-tool Agent Note](../../.agents/notes/implemented/feature/2026-07-30-continuable-subagent-report-tool.md), [the durable catalog Agent Note](../../.agents/notes/implemented/feature/2026-07-22-durable-subagent-catalog-and-list-agents.md), [the list-identity-projection Agent Note](../../.agents/notes/implemented/architecture/2026-08-06-subagent-list-identity-projection.md), and [the merged-service Agent Note](../../.agents/notes/implemented/simplification/2026-07-26-merge-subagent-control-service.md). +Service Definition: [dsh-subagent](../../packages/subagent/subagent) (`ctx.subagents` + the vocabulary below). Service Providers are sibling packages (`dsh-subagent-spawn-in-process`, `-fork`, `-acp`, `-codex`, `-claude-code`, `-dsh-sdk`); the model-facing Consumers are [dsh-tool-subagent](../../packages/subagent/tool-subagent) (per-provider delegation), [dsh-tool-subagent-control](../../packages/subagent/tool-subagent-control) (the optional global `send_message`, `interrupt_agent`, and `list_agents` controls), and [dsh-tool-subagent-report](../../packages/subagent/tool-subagent-report) (the optional child-scoped `report` return channel). The same `ctx.subagents` service owns continuable-child orchestration through an internal activation manager and read-only child and descendant discovery straight from the session store and optional session persistence. Product-provider rationale lives in [the Codex and Claude Code Agent Note](../../.agents/notes/implemented/feature/2026-08-04-claude-code-and-codex-subagent-backends.md); common-seam rationale lives in [the subagent Agent Note](../../.agents/notes/implemented/feature/2026-06-21-subagent-capability-seam.md), [the continuable subagents Agent Note](../../.agents/notes/implemented/feature/2026-07-28-continuable-subagent-conversations.md), [the report-tool Agent Note](../../.agents/notes/implemented/feature/2026-07-30-continuable-subagent-report-tool.md), [the durable catalog Agent Note](../../.agents/notes/implemented/feature/2026-07-22-durable-subagent-catalog-and-list-agents.md), [the list-identity-projection Agent Note](../../.agents/notes/implemented/architecture/2026-08-06-subagent-list-identity-projection.md), and [the merged-service Agent Note](../../.agents/notes/implemented/simplification/2026-07-26-merge-subagent-control-service.md). Sources: [`packages/subagent/subagent/src/types.ts`](../../packages/subagent/subagent/src/types.ts), [`packages/subagent/subagent/src/index.ts`](../../packages/subagent/subagent/src/index.ts), and [`packages/subagent/subagent/src/continuation.ts`](../../packages/subagent/subagent/src/continuation.ts) diff --git a/docs/subsystems/subagent.zh.md b/docs/subsystems/subagent.zh.md index 483446187d..61391cd297 100644 --- a/docs/subsystems/subagent.zh.md +++ b/docs/subsystems/subagent.zh.md @@ -4,7 +4,7 @@ subagent seam 让一个 agent(智能体)将工作委派给子 agent。与 [bash](shell.md) 一样,它是**一项可选能力**,不属于 agent loop(智能体循环),因此其类型定义在此而非 [core.md](core.md) 中。它不同于其他能力 seam,因为**同一上下文中可共存多个提供方实现**,并按名称注册(`ctx.subagents`),而 bash 只允许一个执行器。该注册表遵循 [LLM(大语言模型)适配器注册表](llm-streaming.md),而非单服务的 bash 执行器。 -Service Definition:[dsh-subagent](../../packages/subagent/subagent)(`ctx.subagents` + 下文词汇)。Service provider 是六个兄弟包:`dsh-subagent-spawn-in-process`、`-fork`、`-acp`、`-codex`、`-claude-code`、`-dsh-sdk`;面向模型的 Consumer 包括 [dsh-tool-subagent](../../packages/subagent/tool-subagent)(按提供方委派)、[dsh-tool-subagent-control](../../packages/subagent/tool-subagent-control)(可选的全局 `send_message`、`interrupt_agent` 与 `list_agents` 控制工具)和 [dsh-tool-subagent-report](../../packages/subagent/tool-subagent-report)(可选的 child 作用域 `report` 返回通道)。同一个 `ctx.subagents` 服务通过内部激活管理器负责可继续子 agent 编排,并直接基于会话存储和可选的会话持久化提供只读的 child 与后代发现。产品提供方设计理由见 [Codex 与 Claude Code Agent Note](../../.agents/notes/implemented/feature/2026-08-04-claude-code-and-codex-subagent-backends.md);通用 seam 的设计理由见 [subagent Agent Note](../../.agents/notes/implemented/feature/2026-06-21-subagent-capability-seam.md)、[可继续 subagent Agent Note](../../.agents/notes/implemented/feature/2026-07-28-continuable-subagent-conversations.md)、[report 工具 Agent Note](../../.agents/notes/implemented/feature/2026-07-30-continuable-subagent-report-tool.md)、[持久化目录 Agent Note](../../.agents/notes/implemented/feature/2026-07-22-durable-subagent-catalog-and-list-agents.md)、[列表身份投影 Agent Note](../../.agents/notes/implemented/architecture/2026-08-06-subagent-list-identity-projection.md)和[服务合并 Agent Note](../../.agents/notes/implemented/simplification/2026-07-26-merge-subagent-control-service.md)。 +Service Definition:[dsh-subagent](../../packages/subagent/subagent)(`ctx.subagents` + 下文词汇)。Service Provider 是六个兄弟包:`dsh-subagent-spawn-in-process`、`-fork`、`-acp`、`-codex`、`-claude-code`、`-dsh-sdk`;面向模型的 Consumer 包括 [dsh-tool-subagent](../../packages/subagent/tool-subagent)(按提供方委派)、[dsh-tool-subagent-control](../../packages/subagent/tool-subagent-control)(可选的全局 `send_message`、`interrupt_agent` 与 `list_agents` 控制工具)和 [dsh-tool-subagent-report](../../packages/subagent/tool-subagent-report)(可选的 child 作用域 `report` 返回通道)。同一个 `ctx.subagents` 服务通过内部激活管理器负责可继续子 agent 编排,并直接基于会话存储和可选的会话持久化提供只读的 child 与后代发现。产品提供方设计理由见 [Codex 与 Claude Code Agent Note](../../.agents/notes/implemented/feature/2026-08-04-claude-code-and-codex-subagent-backends.md);通用 seam 的设计理由见 [subagent Agent Note](../../.agents/notes/implemented/feature/2026-06-21-subagent-capability-seam.md)、[可继续 subagent Agent Note](../../.agents/notes/implemented/feature/2026-07-28-continuable-subagent-conversations.md)、[report 工具 Agent Note](../../.agents/notes/implemented/feature/2026-07-30-continuable-subagent-report-tool.md)、[持久化目录 Agent Note](../../.agents/notes/implemented/feature/2026-07-22-durable-subagent-catalog-and-list-agents.md)、[列表身份投影 Agent Note](../../.agents/notes/implemented/architecture/2026-08-06-subagent-list-identity-projection.md)和[服务合并 Agent Note](../../.agents/notes/implemented/simplification/2026-07-26-merge-subagent-control-service.md)。 源码:[`packages/subagent/subagent/src/types.ts`](../../packages/subagent/subagent/src/types.ts)、[`packages/subagent/subagent/src/index.ts`](../../packages/subagent/subagent/src/index.ts)和 [`packages/subagent/subagent/src/continuation.ts`](../../packages/subagent/subagent/src/continuation.ts) diff --git a/docs/subsystems/subprocess.i18n.yaml b/docs/subsystems/subprocess.i18n.yaml index 191ea52af5..d063134567 100644 --- a/docs/subsystems/subprocess.i18n.yaml +++ b/docs/subsystems/subprocess.i18n.yaml @@ -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 docs/subsystems/subprocess.md -subprocess.md: 3cc6e33ce2befc6bc65e258507881df542b7c149 -subprocess.zh.md: 1189ceb0526418ee92e0da280e118c10991508d5 +subprocess.md: af6770e8c04f79ab1981967d5a3bca5a39b954be +subprocess.zh.md: 19f20e7fcd675d87cf768258d1ab9c37bf80a836 diff --git a/docs/subsystems/subprocess.md b/docs/subsystems/subprocess.md index 3cc6e33ce2..af6770e8c0 100644 --- a/docs/subsystems/subprocess.md +++ b/docs/subsystems/subprocess.md @@ -2,7 +2,7 @@ English | [中文](subprocess.zh.md) -The subprocess seam is split across a Service Definition ([dsh-subprocess](../../packages/subprocess/subprocess), `ctx.subprocess`) and Service provider ([dsh-subprocess-local](../../packages/subprocess/subprocess-local)); its Consumers are other capability seams and out-of-process backends: the [bash executor family](shell.md) uses collected batch output, LSP uses raw protocol pipes, the PTY backend uses the terminal primitive, and the ACP subagent backend uses piped ndjson plus inherited stderr. This seam owns the managed `DSH_*` environment namespace, the shared credential scrub (`scrubbedParentEnv`), and the `CollectedOutput` shape; [dsh-shell](../../packages/shell/shell) re-exports the vocabulary so bash consumers keep one import root. +The subprocess seam is split across a Service Definition ([dsh-subprocess](../../packages/subprocess/subprocess), `ctx.subprocess`) and Service Provider ([dsh-subprocess-local](../../packages/subprocess/subprocess-local)); its Consumers are other capability seams and out-of-process backends: the [bash executor family](shell.md) uses collected batch output, LSP uses raw protocol pipes, the PTY backend uses the terminal primitive, and the ACP subagent backend uses piped ndjson plus inherited stderr. This seam owns the managed `DSH_*` environment namespace, the shared credential scrub (`scrubbedParentEnv`), and the `CollectedOutput` shape; [dsh-shell](../../packages/shell/shell) re-exports the vocabulary so bash consumers keep one import root. Source: [`packages/subprocess/subprocess/src/types.ts`](../../packages/subprocess/subprocess/src/types.ts) and [`packages/subprocess/subprocess/src/index.ts`](../../packages/subprocess/subprocess/src/index.ts) diff --git a/docs/subsystems/subprocess.zh.md b/docs/subsystems/subprocess.zh.md index 1189ceb052..19f20e7fcd 100644 --- a/docs/subsystems/subprocess.zh.md +++ b/docs/subsystems/subprocess.zh.md @@ -2,7 +2,7 @@ [English](subprocess.md) | 中文 -子进程 seam 分为 Service Definition([dsh-subprocess](../../packages/subprocess/subprocess),`ctx.subprocess`)与 Service provider([dsh-subprocess-local](../../packages/subprocess/subprocess-local));它的 Consumer 是其他能力 seam 与进程外后端:[bash 执行器家族](shell.md)使用收集模式的批量输出,LSP 使用原始协议管道,PTY 后端使用终端原语,ACP(Agent Client Protocol)subagent 后端则使用通过管道传输的 ndjson,并让 stderr 采用 inherit。该 seam 拥有受管的 `DSH_*` 环境命名空间、共享的凭据清除(`scrubbedParentEnv`)与 `CollectedOutput` 形状;[dsh-shell](../../packages/shell/shell) 重导出这套词汇,使 bash 消费方保持单一导入入口。 +子进程 seam 分为 Service Definition([dsh-subprocess](../../packages/subprocess/subprocess),`ctx.subprocess`)与 Service Provider([dsh-subprocess-local](../../packages/subprocess/subprocess-local));它的 Consumer 是其他能力 seam 与进程外后端:[bash 执行器家族](shell.md)使用收集模式的批量输出,LSP 使用原始协议管道,PTY 后端使用终端原语,ACP(Agent Client Protocol)subagent 后端则使用通过管道传输的 ndjson,并让 stderr 采用 inherit。该 seam 拥有受管的 `DSH_*` 环境命名空间、共享的凭据清除(`scrubbedParentEnv`)与 `CollectedOutput` 形状;[dsh-shell](../../packages/shell/shell) 重导出这套词汇,使 bash 消费方保持单一导入入口。 源码:[`packages/subprocess/subprocess/src/types.ts`](../../packages/subprocess/subprocess/src/types.ts) 与 [`packages/subprocess/subprocess/src/index.ts`](../../packages/subprocess/subprocess/src/index.ts) diff --git a/docs/subsystems/system-prompt.i18n.yaml b/docs/subsystems/system-prompt.i18n.yaml index 3ac169b4e0..0b69a5ca8c 100644 --- a/docs/subsystems/system-prompt.i18n.yaml +++ b/docs/subsystems/system-prompt.i18n.yaml @@ -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 docs/subsystems/system-prompt.md -system-prompt.md: f03d11866bcdcf3bcb5c5fe96931b059cb8d0336 -system-prompt.zh.md: 23b3e0b20cc4772baf22727d2e57866aa7cbbeb0 +system-prompt.md: 8a6006d0b96552b52d0b050c304a11a95add8d9e +system-prompt.zh.md: 02be9eed795d3a6c8e43403048f135d493b6509d diff --git a/docs/subsystems/system-prompt.md b/docs/subsystems/system-prompt.md index f03d11866b..8a6006d0b9 100644 --- a/docs/subsystems/system-prompt.md +++ b/docs/subsystems/system-prompt.md @@ -117,6 +117,14 @@ section(section: PromptSection): () => void */ context(context: PromptContext): () => void +/** + * Suppress every dynamic runtime-context contribution in the calling + * context's scope without changing the services that own or enforce those + * facts. Multiple suppressors remain independently disposable. + * @returns the exact Cordis effect disposer. + */ +suppressRuntimeContext(): () => void + /** * Register a tool-schema provider in the calling context's scope. Global and * matching scoped providers both contribute; returning the reserved @@ -148,7 +156,7 @@ variable(name: string, provider: (context: AssembleContext) => string | undefine async assemble(context: AssembleContext = {}): Promise ``` -Source: [`packages/core/system-prompt/src/index.ts:334`](../../packages/core/system-prompt/src/index.ts) +Source: [`packages/core/system-prompt/src/index.ts:338`](../../packages/core/system-prompt/src/index.ts) diff --git a/docs/subsystems/system-prompt.zh.md b/docs/subsystems/system-prompt.zh.md index 23b3e0b20c..02be9eed79 100644 --- a/docs/subsystems/system-prompt.zh.md +++ b/docs/subsystems/system-prompt.zh.md @@ -117,6 +117,14 @@ section(section: PromptSection): () => void */ context(context: PromptContext): () => void +/** + * Suppress every dynamic runtime-context contribution in the calling + * context's scope without changing the services that own or enforce those + * facts. Multiple suppressors remain independently disposable. + * @returns the exact Cordis effect disposer. + */ +suppressRuntimeContext(): () => void + /** * Register a tool-schema provider in the calling context's scope. Global and * matching scoped providers both contribute; returning the reserved @@ -148,7 +156,7 @@ variable(name: string, provider: (context: AssembleContext) => string | undefine async assemble(context: AssembleContext = {}): Promise ``` -Source: [`packages/core/system-prompt/src/index.ts:334`](../../packages/core/system-prompt/src/index.ts) +Source: [`packages/core/system-prompt/src/index.ts:338`](../../packages/core/system-prompt/src/index.ts) diff --git a/docs/subsystems/web.i18n.yaml b/docs/subsystems/web.i18n.yaml index 3dfe626acd..840865ef35 100644 --- a/docs/subsystems/web.i18n.yaml +++ b/docs/subsystems/web.i18n.yaml @@ -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 docs/subsystems/web.md -web.md: 741df8d92c20817cb3115dafffba7c7be9205aec -web.zh.md: 0cce8500834896c156ff85d935b9e80853a3196c +web.md: 3bcd3ac24927c8c51baeabd770e2bd91c5ad1b77 +web.zh.md: 3348be2b808dc286364f5a795b236cb299acd6a6 diff --git a/docs/subsystems/web.md b/docs/subsystems/web.md index 741df8d92c..3bcd3ac249 100644 --- a/docs/subsystems/web.md +++ b/docs/subsystems/web.md @@ -2,7 +2,7 @@ English | [中文](web.zh.md) -The web access seam — a [capability seam](../../.agents/notes/implemented/architecture/2026-06-24-web-capability-seam.md) that spans **two operations** (search and fetch) on one `ctx.web` service, split across packages: Service Definition ([dsh-web](../../packages/web/web), `ctx.web` + the provider registries), Service providers ([dsh-web-search-exa](../../packages/web/web-search-exa), [dsh-web-search-perplexity](../../packages/web/web-search-perplexity), [dsh-web-search-deepseek](../../packages/web/web-search-deepseek), [dsh-web-fetch-http](../../packages/web/web-fetch-http)), and Consumer ([dsh-tool-web](../../packages/web/tool-web), the `web_search`/`web_fetch` tool schemas). Web is **one optional capability**, not part of the agent-loop spine — so its vocabulary lives here, not in [core.md](core.md). A search-provider swap does not change how the model asks for a query, and a fetch-provider swap does not change how the model asks for a URL. +The web access seam — a [capability seam](../../.agents/notes/implemented/architecture/2026-06-24-web-capability-seam.md) that spans **two operations** (search and fetch) on one `ctx.web` service, split across packages: Service Definition ([dsh-web](../../packages/web/web), `ctx.web` + the provider registries), Service Providers ([dsh-web-search-exa](../../packages/web/web-search-exa), [dsh-web-search-perplexity](../../packages/web/web-search-perplexity), [dsh-web-search-deepseek](../../packages/web/web-search-deepseek), [dsh-web-fetch-http](../../packages/web/web-fetch-http)), and Consumer ([dsh-tool-web](../../packages/web/tool-web), the `web_search`/`web_fetch` tool schemas). Web is **one optional capability**, not part of the agent-loop spine — so its vocabulary lives here, not in [core.md](core.md). A search-provider swap does not change how the model asks for a query, and a fetch-provider swap does not change how the model asks for a URL. Source: [`packages/web/web/src/types.ts`](../../packages/web/web/src/types.ts) diff --git a/docs/subsystems/web.zh.md b/docs/subsystems/web.zh.md index 0cce850083..3348be2b80 100644 --- a/docs/subsystems/web.zh.md +++ b/docs/subsystems/web.zh.md @@ -2,7 +2,7 @@ [English](web.md) | 中文 -Web 访问 seam 是一个[能力 seam](../../.agents/notes/implemented/architecture/2026-06-24-web-capability-seam.md),在同一个 `ctx.web` 服务上横跨**两项操作**(search 与 fetch),并拆分到多个包:Service Definition([dsh-web](../../packages/web/web),`ctx.web` + 提供方注册表)、Service provider([dsh-web-search-exa](../../packages/web/web-search-exa)、[dsh-web-search-perplexity](../../packages/web/web-search-perplexity)、[dsh-web-search-deepseek](../../packages/web/web-search-deepseek)、[dsh-web-fetch-http](../../packages/web/web-fetch-http))与 Consumer([dsh-tool-web](../../packages/web/tool-web),即 `web_search`/`web_fetch` 工具 schema)。Web 是**一项可选能力**,不属于 agent loop(智能体循环)主干,因此其词汇定义在此而非 [core.md](core.md) 中。更换 search 提供方不会改变模型提交查询的方式,更换 fetch 提供方也不会改变模型请求 URL 的方式。 +Web 访问 seam 是一个[能力 seam](../../.agents/notes/implemented/architecture/2026-06-24-web-capability-seam.md),在同一个 `ctx.web` 服务上横跨**两项操作**(search 与 fetch),并拆分到多个包:Service Definition([dsh-web](../../packages/web/web),`ctx.web` + 提供方注册表)、Service Provider([dsh-web-search-exa](../../packages/web/web-search-exa)、[dsh-web-search-perplexity](../../packages/web/web-search-perplexity)、[dsh-web-search-deepseek](../../packages/web/web-search-deepseek)、[dsh-web-fetch-http](../../packages/web/web-fetch-http))与 Consumer([dsh-tool-web](../../packages/web/tool-web),即 `web_search`/`web_fetch` 工具 schema)。Web 是**一项可选能力**,不属于 agent loop(智能体循环)主干,因此其词汇定义在此而非 [core.md](core.md) 中。更换 search 提供方不会改变模型提交查询的方式,更换 fetch 提供方也不会改变模型请求 URL 的方式。 源码:[`packages/web/web/src/types.ts`](../../packages/web/web/src/types.ts) diff --git a/docs/subsystems/workflow.i18n.yaml b/docs/subsystems/workflow.i18n.yaml index 8f9d56e57e..2237e355a1 100644 --- a/docs/subsystems/workflow.i18n.yaml +++ b/docs/subsystems/workflow.i18n.yaml @@ -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 docs/subsystems/workflow.md -workflow.md: bf11ec3a40f9c964fbc535a0368b30e422b5452e -workflow.zh.md: b87bffd4780d167b4106276bfbca53e48ef6d833 +workflow.md: f2c987fbc2ca3a334c55bf0b299764e2b3e6bb06 +workflow.zh.md: b4e6e6afe73b20f1da39c1548c072cf7aeb1f441 diff --git a/docs/subsystems/workflow.md b/docs/subsystems/workflow.md index bf11ec3a40..f2c987fbc2 100644 --- a/docs/subsystems/workflow.md +++ b/docs/subsystems/workflow.md @@ -4,7 +4,7 @@ English | [中文](workflow.zh.md) The workflow seam lets an agent run a model-written orchestration SCRIPT that starts subagents. Like [subagent](subagent.md) it is **one optional capability**, not part of the agent loop, so its types and operations live here rather than in [core.md](core.md). Like bash, it permits ONE engine implementation per context to provide `ctx.workflowEngine`; there is no named-provider registry (a second engine replaces the first through plugin configuration rather than running beside it). -Service Definition: [dsh-workflow](../../packages/workflow/workflow) (`ctx.workflowEngine` + the vocabulary below). The Service provider is [dsh-workflow-worker-thread](../../packages/workflow/workflow-worker-thread) (a `node:worker_threads` engine — one worker per run, the script's vm context inside it); the model-facing Consumer is [dsh-tool-workflow](../../packages/workflow/tool-workflow). The proposal and rationale: [the dynamic-workflows Agent Note](../../.agents/notes/implemented/feature/2026-07-05-dynamic-workflows.md). +Service Definition: [dsh-workflow](../../packages/workflow/workflow) (`ctx.workflowEngine` + the vocabulary below). The Service Provider is [dsh-workflow-worker-thread](../../packages/workflow/workflow-worker-thread) (a `node:worker_threads` engine — one worker per run, the script's vm context inside it); the model-facing Consumer is [dsh-tool-workflow](../../packages/workflow/tool-workflow). The proposal and rationale: [the dynamic-workflows Agent Note](../../.agents/notes/implemented/feature/2026-07-05-dynamic-workflows.md). Sources: browser-safe vocabulary in [`packages/workflow/workflow/src/types.ts`](../../packages/workflow/workflow/src/types.ts), Host request and live-run handles in [`runtime-types.ts`](../../packages/workflow/workflow/src/runtime-types.ts). diff --git a/docs/subsystems/workflow.zh.md b/docs/subsystems/workflow.zh.md index b87bffd478..b4e6e6afe7 100644 --- a/docs/subsystems/workflow.zh.md +++ b/docs/subsystems/workflow.zh.md @@ -4,7 +4,7 @@ 工作流 seam 允许 agent(智能体)运行由模型编写、会启动 subagent 的编排脚本。与 [subagent](subagent.md) 一样,它是**一项可选能力**,不属于 agent loop,因此其类型和操作记录在此处,而非 [core.md](core.md)。与 bash 一样,每个上下文只允许一个引擎实现提供 `ctx.workflowEngine`;没有命名提供方注册表(第二个引擎通过插件配置替换第一个,而不与它同时运行)。 -Service Definition:[dsh-workflow](../../packages/workflow/workflow)(`ctx.workflowEngine` + 下文词汇)。Service provider 是 [dsh-workflow-worker-thread](../../packages/workflow/workflow-worker-thread)(一个 `node:worker_threads` 引擎——每个 run 一个 worker,脚本的 vm 上下文位于其中);面向模型的 Consumer 是 [dsh-tool-workflow](../../packages/workflow/tool-workflow)。提案与设计理由见 [dynamic-workflows Agent Note](../../.agents/notes/implemented/feature/2026-07-05-dynamic-workflows.md)。 +Service Definition:[dsh-workflow](../../packages/workflow/workflow)(`ctx.workflowEngine` + 下文词汇)。Service Provider 是 [dsh-workflow-worker-thread](../../packages/workflow/workflow-worker-thread)(一个 `node:worker_threads` 引擎——每个 run 一个 worker,脚本的 vm 上下文位于其中);面向模型的 Consumer 是 [dsh-tool-workflow](../../packages/workflow/tool-workflow)。提案与设计理由见 [dynamic-workflows Agent Note](../../.agents/notes/implemented/feature/2026-07-05-dynamic-workflows.md)。 源码:浏览器安全词汇位于 [`packages/workflow/workflow/src/types.ts`](../../packages/workflow/workflow/src/types.ts),Host 请求与活跃运行句柄位于 [`runtime-types.ts`](../../packages/workflow/workflow/src/runtime-types.ts)。 diff --git a/docs/tool-catalog.i18n.yaml b/docs/tool-catalog.i18n.yaml index 9cbc5707a4..3ed16072ca 100644 --- a/docs/tool-catalog.i18n.yaml +++ b/docs/tool-catalog.i18n.yaml @@ -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 docs/tool-catalog.md -tool-catalog.md: ea89508500ec6e73e6e56c4e5d0ac2c35897b342 -tool-catalog.zh.md: 076cc63151e3b9ee8b3828ded65df9ebf09c9430 +tool-catalog.md: 50563c97c6cd5496871ea7fa52c4823a56b088fd +tool-catalog.zh.md: ed0c7e3f70cffbecd3d20a1556bcb0cd4204df00 diff --git a/docs/tool-catalog.md b/docs/tool-catalog.md index ea89508500..50563c97c6 100644 --- a/docs/tool-catalog.md +++ b/docs/tool-catalog.md @@ -40,6 +40,8 @@ This table connects model-visible tool names to the plugin package and service s | `@deepseek-ai/dsh-tool-workflow` | `workflow` | `ctx.tools`, `ctx.workflowEngine`, `ctx.systemPrompt`, `a calling Agent (exec.agent parents the script children)` | `tool/call`, `tool/result` | - | - | | `@deepseek-ai/dsh-tool-web` | `web_fetch`, `web_search` | `ctx.tools`, `ctx.web`, `ctx.systemPrompt` | `tool/call`, `tool/result` | - | web_search and web_fetch keep provider selection behind ctx.web so model-visible schemas stay stable across backend swaps. | + + ## `@deepseek-ai/dsh-tool-ask-user` ### `ask_user_question` @@ -112,11 +114,13 @@ Source: [`packages/interaction/tool-ask-user/src/index.ts`](../packages/interact ask_user_question pauses the tool call until the active UI provider returns a human answer. + + ## `@deepseek-ai/dsh-tools` ### `run_code` -Execute a TypeScript program against the available tools. Write the BODY of an async function (erasable syntax only; top-level `await` and `return` work) and call tools as `await tools.name(args)` per the declarations in the system prompt. Only what you print or return comes back — curate it. +Execute a TypeScript program against the available tools. Takes two required arguments: `code`, the BODY of an async function (erasable syntax only; top-level `await` and `return` work), and `description`, a short summary of what the program does. Call tools as `await tools.name(args)` per the declarations in the system prompt. Only what you print or return comes back — curate it. ```json { @@ -142,6 +146,8 @@ Source: [`packages/core/tools/src/code-mode.ts`](../packages/core/tools/src/code Owned by the tool registry as a reserved transport outside filterable capability layers under `mode: code` / `mode: both` (see the Code Mode Agent Note). Under `code` it is the registry's only wire contribution; the other visible capabilities are declared in a generated SDK section in the loaded runtime's language, and a program calls them through bindings scheduled under the native concurrency contract (submission-ordered starts and policy; concurrency-safe bodies overlap up to `maxParallelSubCalls`) that re-enter the complete guarded tool pipeline and link each nested execution to this outer result. + + ## `@deepseek-ai/dsh-plan-mode` ### `exit_plan_mode` @@ -167,6 +173,8 @@ Source: [`packages/plan/plan-mode/src/index.ts`](../packages/plan/plan-mode/src/ exit_plan_mode stays in the model-facing schema while planning is inactive so transitions add no tool-catalog churn on top of the plan-policy change. Its execute path rejects calls outside plan mode; in plan mode it presents the plan over the user-questions seam (approve / keep planning with feedback), and approval logs plan mode inactive at the step boundary. + + ## `@deepseek-ai/dsh-tool-bash` ### `bash` @@ -209,6 +217,8 @@ Source: [`packages/shell/tool-bash/src/index.ts`](../packages/shell/tool-bash/sr The bash tool is the model-facing consumer of the bash executor seam. A `run_in_background` run registers with the generic `ctx.jobs` runtime and is collected/stopped through the `job_*` tools from `@deepseek-ai/dsh-tool-jobs`; the `enableRunInBackground` config (default true) removes the parameter entirely when disabled. + + ## `@deepseek-ai/dsh-tool-pwsh` ### `pwsh` @@ -251,6 +261,8 @@ Source: [`packages/shell/tool-pwsh/src/index.ts`](../packages/shell/tool-pwsh/sr The pwsh tool is the PowerShell-dialect consumer of the bash executor seam for Windows compositions (a PowerShell executor such as `@deepseek-ai/dsh-pwsh-local` backs `ctx.shell`); it mirrors the bash tool call-for-call minus sandbox controls — `run_in_background` runs register with the generic `ctx.jobs` runtime and are collected/stopped through the `job_*` tools, and the managed `DSH_*` environment comes from `@deepseek-ai/dsh-shell-env`. Each call runs in a fresh process (no persistent PTY session), with native `C:\...` paths and `$env:NAME` variables. + + ## `@deepseek-ai/dsh-tool-cordis` ### `cordis_define` @@ -487,6 +499,8 @@ Source: [`packages/extensions/tool-cordis/src/index.ts`](../packages/extensions/ Not in any shipped tree (a deliberate opt-in — dynamic package code reaches the real runtime, see .agents/notes/implemented/feature/2026-07-08-self-referential-cordis-toolset.md). The toolset injects `ctx.dynamicCordisRunner` from `@deepseek-ai/dsh-cordis-host-runner`, which owns the definition registry and the vm sandbox; a composition missing it never activates the tools. A running package may register ADDITIONAL model-visible tools until it is stopped, undefined, or DSH restarts; a full changed request header logs those tool-set changes. + + ## `@deepseek-ai/dsh-tool-bash-persistent` ### `bash` @@ -512,6 +526,8 @@ Source: [`packages/shell/tool-bash-persistent/src/index.ts`](../packages/shell/t One owner-isolated persistent bash tool; deployment composition supplies the PTY backend and may override the model-facing environment description. + + ## `@deepseek-ai/dsh-tool-str-replace-editor` ### `str_replace_editor` @@ -580,6 +596,8 @@ Source: [`packages/fs/tool-str-replace-editor/src/index.ts`](../packages/fs/tool Standalone view/create/unique literal replace/line insert tool over the filesystem seam; it composes with any shell or terminal API. + + ## `@deepseek-ai/dsh-tool-fs` ### `edit` @@ -695,6 +713,8 @@ Source: [`packages/fs/tool-fs/src/index.ts`](../packages/fs/tool-fs/src/index.ts The read-before-write/edit policy is added by `@deepseek-ai/dsh-fs-observation-policy` (an `fs/*` event-gate plugin, no schema change); a deployment that loads these tools is expected to also load it. `read_image` is not registered without `ctx.attachments`; its schema is route-independent, and execution refuses unless the exact routed model declares image input. + + ## `@deepseek-ai/dsh-tool-fs-search` ### `glob` @@ -753,6 +773,8 @@ Source: [`packages/fs/tool-fs-search/src/index.ts`](../packages/fs/tool-fs-searc glob and grep are unconditional discovery tools that spawn the packaged ripgrep binary (`@vscode/ripgrep`) through ctx.subprocess as ordinary foreground calls (never background jobs) — no host `rg` install and no shell layer. The catalog uses `sampleOverCapGlobResults: true`; deployments must choose that behavior explicitly. Capped results save the complete formatted list through the optional ctx.spillStore backend; returned locators are follow-up-readable/searchable when the backend exposes local paths in co-located deployments. + + ## `@deepseek-ai/dsh-tool-terminal` ### `terminal_close` @@ -916,6 +938,8 @@ Source: [`packages/terminal/tool-terminal/src/index.ts`](../packages/terminal/to The six terminal tools are opt-in and complement one-shot shell/filesystem tools. `terminal_send(run_in_background: true)` registers with `ctx.jobs`; TUI, named key sequences, BEL, resize, auto-start, and cross-agent sharing are absent from the schema. + + ## `@deepseek-ai/dsh-tool-goal` ### `create_goal` @@ -1008,6 +1032,8 @@ Source: [`packages/goal/tool-goal/src/index.ts`](../packages/goal/tool-goal/src/ create, edit, pause, and resume require direct-human root authority; complete and blocked also accept the exact current goal round. The default blocked lower bound is three admitted rounds. + + ## `@deepseek-ai/dsh-schedule` ### `schedule_create` @@ -1103,6 +1129,8 @@ Source: [`packages/schedule/schedule/src/tools.ts`](../packages/schedule/schedul Registered only inside live root Agent scopes created after the opt-in Schedule plugin loads. Version 1 accepts after_seconds, explicit absolute at, and bounded fixed-rate every_seconds, and discloses session-local delivery; management reads and mutations require the shared Session persistence barrier. + + ## `@deepseek-ai/dsh-tool-lsp` ### `lsp` @@ -1149,6 +1177,8 @@ Source: [`packages/lsp/tool-lsp/src/index.ts`](../packages/lsp/tool-lsp/src/inde The lsp tool keeps provider selection and language-server subprocesses behind ctx.lsp, so its model-visible schema stays stable across providers. Requires a registered provider (e.g. `@deepseek-ai/dsh-lsp-stdio`) at runtime; without one, a query returns the structured `LSP_UNAVAILABLE` error rather than changing the schema. + + ## `@deepseek-ai/dsh-tool-ralph` ### `ralph` @@ -1178,6 +1208,8 @@ Source: [`packages/workflow/tool-ralph/src/index.ts`](../packages/workflow/tool- A fixed foreground workflow starts one fresh structured child per round; the model selects only the immutable objective and an optional round cap. + + ## `@deepseek-ai/dsh-tool-skill` ### `skill` @@ -1201,6 +1233,8 @@ Load the full instructions for an available skill. Call this with the exact skil Source: [`packages/skill/tool-skill/src/index.ts`](../packages/skill/tool-skill/src/index.ts) + + ## `@deepseek-ai/dsh-tool-session-query` ### `session_event_read` @@ -1434,6 +1468,8 @@ Source: [`packages/session-query/tool-session-query/src/index.ts`](../packages/s The five read-only tools hide provider cursors and authorize every result from the immutable calling agent session. The package is opt-in; compositions that need enforced deadlines or bounded inline output also mount the generic timeout or spill policies. + + ## `@deepseek-ai/dsh-tool-subagent` ### `subagent` @@ -1468,6 +1504,8 @@ Source: [`packages/subagent/tool-subagent/src/index.ts`](../packages/subagent/to The registered tool name is the load-time `toolName` config (default `subagent`); the schema above is that default. The shipped compositions load this package once per subagent backend, so the model additionally sees `subagent_fork` bound to the fork backend. Each instance's description, `run_in_background` parameter, and system-prompt policy follow its own `backgroundMode` and `enableRunInBackground`, so the two shipped schemas are not identical: `subagent` is `continuable` and defaults omitted calls to background with automatic settlement delivery, while `subagent_fork` stays `one-shot` and defaults them to foreground — see `packages/bundle/base/cordis.patch.yml` and `examples/acp-agent/cordis.yml`. + + ## `@deepseek-ai/dsh-tool-subagent-control` ### `interrupt_agent` @@ -1541,6 +1579,8 @@ Source: [`packages/subagent/tool-subagent-control/src/index.ts`](../packages/sub The globally named control tools over continuable background subagents: provider-bound `tool-subagent` instances register distinct delegation tools, while this package registers `send_message` and `interrupt_agent` once, plus `list_agents` from its separately loaded `/list-agents` plugin (whose catalog rows use the sessionProjections and live Agent registries). + + ## `@deepseek-ai/dsh-tool-subagent-report` ### `report` @@ -1566,6 +1606,8 @@ Source: [`packages/subagent/tool-subagent-report/src/index.ts`](../packages/suba Registered per continuable in-process child rather than globally, so this schema is visible only inside such a child and survives its global `toolFilter`. The same contribution installs the child-scoped `tool:report` prompt section, which this catalog does not render. The parent-facing `send_message` tool is installed independently. + + ## `@deepseek-ai/dsh-tool-jobs` ### `job_kill` @@ -1637,6 +1679,8 @@ Source: [`packages/jobs/tool-jobs/src/index.ts`](../packages/jobs/tool-jobs/src/ The kind-agnostic background-job controller: background bash commands, PTY sends, and subagents are read, listed, and killed through the same three tools. Loading the plugin attaches the controller that arms producers' `ctx.jobs.start()`. + + ## `@deepseek-ai/dsh-tool-todo` ### `todo_write` @@ -1685,6 +1729,8 @@ Source: [`packages/todo/tool-todo/src/index.ts`](../packages/todo/tool-todo/src/ todo_write is session-owned state; UIs render the latest todo/write event as a checklist. `allowParallelInProgress` is required with no default, so the catalog states its choice: `true`, whose description invites several `in_progress` items. A deployment choosing `false` receives the same tool with a description asking for exactly one active task. + + ## `@deepseek-ai/dsh-tool-workflow` ### `workflow` @@ -1778,6 +1824,8 @@ Constraints: concurrency and total-agent caps apply; no filesystem, network, tim Source: [`packages/workflow/tool-workflow/src/index.ts`](../packages/workflow/tool-workflow/src/index.ts) + + ## `@deepseek-ai/dsh-tool-web` ### `web_fetch` diff --git a/docs/tool-catalog.zh.md b/docs/tool-catalog.zh.md index 076cc63151..ed0c7e3f70 100644 --- a/docs/tool-catalog.zh.md +++ b/docs/tool-catalog.zh.md @@ -42,6 +42,8 @@ | `@deepseek-ai/dsh-tool-workflow` | `workflow` | `ctx.tools`、`ctx.workflowEngine`、`ctx.systemPrompt`、`a calling Agent (exec.agent parents the script children)` | `tool/call`、`tool/result` | - | - | | `@deepseek-ai/dsh-tool-web` | `web_fetch`、`web_search` | `ctx.tools`、`ctx.web`、`ctx.systemPrompt` | `tool/call`、`tool/result` | - | web_search 和 web_fetch 将提供方选择置于 ctx.web 之后,使模型可见 schema 在更换后端时保持稳定。 | + + ## `@deepseek-ai/dsh-tool-ask-user` ### `ask_user_question` @@ -114,11 +116,13 @@ ask_user_question 会暂停工具调用,直到当前 UI 提供方返回人类答案。 + + ## `@deepseek-ai/dsh-tools` ### `run_code` -针对可用工具执行 TypeScript 程序。请编写异步函数的**函数体**(仅使用可擦除语法;支持顶层 `await` 和 `return`),并根据系统提示词中的声明,以 `await tools.name(args)` 形式调用工具。只有打印或返回的内容会传回,请谨慎筛选。 +针对可用工具执行 TypeScript 程序。接受两个必填参数:`code`,即异步函数的**函数体**(仅使用可擦除语法;支持顶层 `await` 和 `return`);以及 `description`,简要说明该程序做什么。请根据系统提示词中的声明,以 `await tools.name(args)` 形式调用工具。只有打印或返回的内容会传回,请谨慎筛选。 ```json { @@ -144,6 +148,8 @@ ask_user_question 会暂停工具调用,直到当前 UI 提供方返回人类 在 `mode: code`/`mode: both` 下,它由工具注册表所有,作为可过滤能力层之外的保留传输机制(参见 Code Mode Agent Note)。在 `code` 下,它是注册表对协议格式的唯一贡献;其他可见能力在使用已加载运行时语言生成的 SDK 章节中声明。程序通过 binding 调用这些能力,调用按照原生并发约定调度:启动顺序和策略遵循提交顺序,并发安全的函数体最多重叠执行 `maxParallelSubCalls` 个。调用会重新进入完整且受守卫保护的工具流水线,并将每个嵌套执行关联到此外层结果。 + + ## `@deepseek-ai/dsh-plan-mode` ### `exit_plan_mode` @@ -169,6 +175,8 @@ ask_user_question 会暂停工具调用,直到当前 UI 提供方返回人类 规划未激活时,exit_plan_mode 仍保留在面向模型的 schema 中,这样状态转换不会在规划策略变更之外额外造成工具目录变动。其执行路径会拒绝规划模式之外的调用;在规划模式下,它通过用户交互 seam 提交计划(批准/根据反馈继续规划),批准后会在步骤边界记录规划模式已停用。 + + ## `@deepseek-ai/dsh-tool-bash` ### `bash` @@ -211,6 +219,8 @@ ask_user_question 会暂停工具调用,直到当前 UI 提供方返回人类 bash 工具是 bash 执行器 seam 面向模型的消费方。使用 `run_in_background` 的运行会注册到通用 `ctx.jobs` 运行时,并通过 `job_*` 工具(来自 `@deepseek-ai/dsh-tool-jobs`)收集/停止;禁用 `enableRunInBackground` 配置(默认为 true)后,该参数会被完全移除。 + + ## `@deepseek-ai/dsh-tool-pwsh` ### `pwsh` @@ -253,6 +263,8 @@ bash 工具是 bash 执行器 seam 面向模型的消费方。使用 `run_in_bac pwsh 工具是 Windows 组合中 bash 执行器 seam 的 PowerShell 方言消费方(由 `@deepseek-ai/dsh-pwsh-local` 等 PowerShell 执行器为 `ctx.shell` 提供后端);除沙箱接口外,它逐项对应 bash 工具调用。使用 `run_in_background` 的运行会注册到通用 `ctx.jobs` 运行时,并通过 `job_*` 工具收集/停止;托管的 `DSH_*` 环境来自 `@deepseek-ai/dsh-shell-env`。每次调用都在新进程中运行,不使用持久 PTY 会话。路径采用原生 `C:\...` 形式,变量采用 `$env:NAME`。 + + ## `@deepseek-ai/dsh-tool-cordis` ### `cordis_define` @@ -489,6 +501,8 @@ pwsh 工具是 Windows 组合中 bash 执行器 seam 的 PowerShell 方言消费 不在任何随产品发布的树中,需要显式选择启用;动态 Package 代码可以访问真实运行时,见 .agents/notes/implemented/feature/2026-07-08-self-referential-cordis-toolset.md。该工具集注入 `@deepseek-ai/dsh-cordis-host-runner` 提供的 `ctx.dynamicCordisRunner`,后者拥有定义注册表和 vm 沙箱;组合缺少它时这些工具不会激活。运行中的 Package 在停止、undefine 或 DSH 重启前可以注册**额外的**模型可见工具;发生这类工具集变化时,系统会记录完整且有变动的请求头。 + + ## `@deepseek-ai/dsh-tool-bash-persistent` ### `bash` @@ -514,6 +528,8 @@ pwsh 工具是 Windows 组合中 bash 执行器 seam 的 PowerShell 方言消费 一个按所有者隔离的持久 bash 工具;部署组合提供 PTY 后端,并可覆盖面向模型的环境描述。 + + ## `@deepseek-ai/dsh-tool-str-replace-editor` ### `str_replace_editor` @@ -584,6 +600,8 @@ pwsh 工具是 Windows 组合中 bash 执行器 seam 的 PowerShell 方言消费 基于文件系统 seam 的独立查看/创建/唯一字面量替换/按行插入工具;可与任何 shell 或终端接口组合。 + + ## `@deepseek-ai/dsh-tool-fs` ### `edit` @@ -699,6 +717,8 @@ pwsh 工具是 Windows 组合中 bash 执行器 seam 的 PowerShell 方言消费 先读后写/编辑策略由 `@deepseek-ai/dsh-fs-observation-policy` 添加;它是一个 `fs/*` 事件门禁插件,不会改变 schema。加载这些工具的部署按预期也应加载该插件。没有 `ctx.attachments` 时 `read_image` 不会注册;其 schema 与路由无关,执行时除非确切路由的模型声明图像输入,否则拒绝。 + + ## `@deepseek-ai/dsh-tool-fs-search` ### `glob` @@ -757,6 +777,8 @@ pwsh 工具是 Windows 组合中 bash 执行器 seam 的 PowerShell 方言消费 glob 和 grep 是无条件可用的发现工具,通过 ctx.subprocess spawn 随包提供的 ripgrep 二进制文件(`@vscode/ripgrep`),并作为普通前台调用运行,绝不作为后台任务;无需在宿主机安装 `rg`,也不经过 shell 层。本目录使用 `sampleOverCapGlobResults: true`;部署必须显式选择该行为。结果超过上限时,会通过可选的 ctx.spillStore 后端保存完整的格式化列表;在共置部署中,如果后端公开本地路径,返回的定位信息可供后续读取/搜索。 + + ## `@deepseek-ai/dsh-tool-terminal` ### `terminal_close` @@ -920,6 +942,8 @@ glob 和 grep 是无条件可用的发现工具,通过 ctx.subprocess spawn 这 6 个终端工具需要选择启用,用于补充一次性 bash/文件系统工具。`terminal_send(run_in_background: true)` 会注册到 `ctx.jobs`;schema 不包含 TUI、具名按键序列、BEL、调整尺寸、自动启动和跨 agent 共享。 + + ## `@deepseek-ai/dsh-tool-goal` ### `create_goal` @@ -1012,6 +1036,8 @@ glob 和 grep 是无条件可用的发现工具,通过 ctx.subprocess spawn create、edit、pause 和 resume 要求直接来自人类的根权限;complete 和 blocked 也接受确切的当前 Goal Round。blocked 的默认下限是 3 个获准的 Round。 + + ## `@deepseek-ai/dsh-schedule` ### `schedule_create` @@ -1107,6 +1133,8 @@ create、edit、pause 和 resume 要求直接来自人类的根权限;complete 仅在选择启用的 Schedule 插件加载后创建的 live 根 Agent scope 内注册。版本 1 接受 after_seconds、显式绝对 at 和有界固定速率 every_seconds,并披露 session-local 交付;管理读取与变更必须通过共享的 Session 持久化 barrier。 + + ## `@deepseek-ai/dsh-tool-lsp` ### `lsp` @@ -1153,6 +1181,8 @@ create、edit、pause 和 resume 要求直接来自人类的根权限;complete lsp 工具将提供方选择和语言服务器子进程置于 ctx.lsp 之后,因此其模型可见 schema 在更换提供方时保持稳定。运行时要求已注册提供方,例如 `@deepseek-ai/dsh-lsp-stdio`;如果没有提供方,查询会返回结构化 `LSP_UNAVAILABLE` 错误,而不会改变 schema。 + + ## `@deepseek-ai/dsh-tool-ralph` ### `ralph` @@ -1182,6 +1212,8 @@ lsp 工具将提供方选择和语言服务器子进程置于 ctx.lsp 之后, 固定的前台工作流会在每个 Round 启动一个全新的结构化子级;模型只能选择不可变目标和可选的 Round 上限。 + + ## `@deepseek-ai/dsh-tool-skill` ### `skill` @@ -1205,6 +1237,8 @@ lsp 工具将提供方选择和语言服务器子进程置于 ctx.lsp 之后, 来源:[`packages/skill/tool-skill/src/index.ts`](../packages/skill/tool-skill/src/index.ts) + + ## `@deepseek-ai/dsh-tool-session-query` ### `session_event_read` @@ -1438,6 +1472,8 @@ lsp 工具将提供方选择和语言服务器子进程置于 ctx.lsp 之后, 这 5 个只读工具会隐藏提供方游标,并根据不可变的调用 agent 会话为每个结果授权。该包需要选择启用;需要强制截止时间或限制行内输出的组合还会挂载通用超时或 spill 策略。 + + ## `@deepseek-ai/dsh-tool-subagent` ### `subagent` @@ -1472,6 +1508,8 @@ lsp 工具将提供方选择和语言服务器子进程置于 ctx.lsp 之后, 注册的工具名称取决于加载时 `toolName` 配置(默认为 `subagent`);上述 schema 对应默认值。随产品发布的组合会为每个 subagent 后端加载一次该包,因此模型还会看到绑定到 fork 后端的 `subagent_fork`。每个实例的描述、`run_in_background` 参数与 system prompt 策略取决于它自己的 `backgroundMode` 和 `enableRunInBackground`,因此两个随附 schema 并不相同:`subagent` 为 `continuable`,省略参数时默认后台运行,并由 runtime 自动投递结束结果;`subagent_fork` 保持 `one-shot`,省略参数时默认前台运行。详见 `packages/bundle/base/cordis.patch.yml` 和 `examples/acp-agent/cordis.yml`。 + + ## `@deepseek-ai/dsh-tool-subagent-control` ### `interrupt_agent` @@ -1545,6 +1583,8 @@ lsp 工具将提供方选择和语言服务器子进程置于 ctx.lsp 之后, 这些是控制可继续后台 subagent 的全局命名工具:绑定提供方的 `tool-subagent` 实例注册不同的委派工具;本包注册一次 `send_message` 和 `interrupt_agent`,另由 `list_agents` 通过单独加载的 `/list-agents` 插件提供,其目录行使用 sessionProjections 和实时 Agent 注册表。 + + ## `@deepseek-ai/dsh-tool-subagent-report` ### `report` @@ -1570,6 +1610,8 @@ lsp 工具将提供方选择和语言服务器子进程置于 ctx.lsp 之后, 按可继续的进程内子级注册,而非全局注册,因此该 schema 仅在这种子级内部可见,并且不受其全局 `toolFilter` 影响。同一份贡献还会安装子级作用域的 `tool:report` 系统提示词 section,本目录不渲染该 section。面向父级的 `send_message` 工具单独安装。 + + ## `@deepseek-ai/dsh-tool-jobs` ### `job_kill` @@ -1641,6 +1683,8 @@ lsp 工具将提供方选择和语言服务器子进程置于 ctx.lsp 之后, 与任务种类无关的后台任务控制器:后台 bash 命令、PTY 发送和 subagent 都通过相同的 3 个工具读取、列出和终止。加载该插件会挂接控制器,从而启用生产方的 `ctx.jobs.start()`。 + + ## `@deepseek-ai/dsh-tool-todo` ### `todo_write` @@ -1689,6 +1733,8 @@ lsp 工具将提供方选择和语言服务器子进程置于 ctx.lsp 之后, todo_write 是会话所有的状态;UI 将最新的 todo/write 事件渲染为检查清单。`allowParallelInProgress` 是没有默认值的必填项,因此本目录明确选择 `true`,对应描述允许同时存在多个 `in_progress` 项。选择 `false` 的部署会获得同一工具,但描述会要求只能有 1 个活动任务。 + + ## `@deepseek-ai/dsh-tool-workflow` ### `workflow` @@ -1783,6 +1829,8 @@ todo_write 是会话所有的状态;UI 将最新的 todo/write 事件渲染为 来源:[`packages/workflow/tool-workflow/src/index.ts`](../packages/workflow/tool-workflow/src/index.ts) + + ## `@deepseek-ai/dsh-tool-web` ### `web_fetch` diff --git a/docs/user/develop/basic/index.i18n.yaml b/docs/user/develop/basic/index.i18n.yaml index 0dd8723e1b..96e27f6c6d 100644 --- a/docs/user/develop/basic/index.i18n.yaml +++ b/docs/user/develop/basic/index.i18n.yaml @@ -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 docs/user/develop/basic/index.md -index.md: 494b7869be6ffdf5767fac260b36b2585305b516 -index.zh.md: a55b8e31151c5cfa5445069974be9fa022fea1eb +index.md: 08199624e638aaf4a36b04446c39c228b2af6025 +index.zh.md: c45a30d0bfffaf4a6c78303f9ca043c3397c8a08 diff --git a/docs/user/develop/basic/index.md b/docs/user/develop/basic/index.md index 494b7869be..08199624e6 100644 --- a/docs/user/develop/basic/index.md +++ b/docs/user/develop/basic/index.md @@ -45,14 +45,16 @@ export function apply(ctx: Context) { ## Register it in cordis.yml -Create `scratch-plugin/cordis.yml` as a Web overlay that inserts the local plugin: +Run `pwd` from the repository root, then create `scratch-plugin/cordis.yml` as a Web overlay that inserts the local plugin. Replace `/absolute/path/to/deepseek-harness` below with the printed path: ```yaml - insert: - id: hello - name: './src/my-plugin.ts' + name: '/absolute/path/to/deepseek-harness/scratch-plugin/src/my-plugin.ts' ``` +The plugin path must be absolute. A patch file contributes configuration but does not change the profile directory from which the loader resolves module paths. + Start the Web UI with that overlay: ```sh diff --git a/docs/user/develop/basic/index.zh.md b/docs/user/develop/basic/index.zh.md index a55b8e3115..c45a30d0bf 100644 --- a/docs/user/develop/basic/index.zh.md +++ b/docs/user/develop/basic/index.zh.md @@ -45,14 +45,16 @@ export function apply(ctx: Context) { ## 注册到 cordis.yml -创建 `scratch-plugin/cordis.yml`,作为插入本地插件的 Web 覆盖层: +在仓库根目录运行 `pwd`,然后创建 `scratch-plugin/cordis.yml`,作为插入本地插件的 Web 覆盖层。请将下文的 `/absolute/path/to/deepseek-harness` 替换为命令打印的路径: ```yaml - insert: - id: hello - name: './src/my-plugin.ts' + name: '/absolute/path/to/deepseek-harness/scratch-plugin/src/my-plugin.ts' ``` +插件路径必须是绝对路径。patch 文件只贡献配置,不会改变 loader 解析模块路径时使用的 profile 目录。 + 使用该覆盖层启动 Web UI: ```sh diff --git a/docs/user/develop/basic/publish.i18n.yaml b/docs/user/develop/basic/publish.i18n.yaml index 649408dead..da1ac1e88c 100644 --- a/docs/user/develop/basic/publish.i18n.yaml +++ b/docs/user/develop/basic/publish.i18n.yaml @@ -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 docs/user/develop/basic/publish.md -publish.md: 588531a28020ebe620643cd1aaaa43de000e658a -publish.zh.md: b86bd43369c027972705394fded43ae053248c0f +publish.md: 9548fe2f8e4636dd160c79cd0d50f01f8bdfd3d1 +publish.zh.md: 2cff05edcca55bac5fde9d2e7d24ed9c8b48a6f5 diff --git a/docs/user/develop/basic/publish.md b/docs/user/develop/basic/publish.md index 588531a280..9548fe2f8e 100644 --- a/docs/user/develop/basic/publish.md +++ b/docs/user/develop/basic/publish.md @@ -2,7 +2,9 @@ English | [中文](publish.zh.md) -The previous tutorials loaded a local plugin through a `--patch` overlay. This tutorial packages it as an installable **bundle**, installs it into a **profile** with `dsh plugin add`, and explains the layer order that determines the composed configuration. Complete [plugin configuration](./config.md) first. +The previous tutorials loaded a local plugin through a `--patch` overlay. This tutorial packages it as an installable **bundle**, installs it into a **profile** with `dsh plugin add`, and explains the layer order that determines the composed configuration. It assumes the `dsh` CLI is installed. Complete [plugin configuration](./config.md) first. + +To use a fresh source checkout instead, complete the [run-from-source section](../../../../README.md#run-from-source), keep this tutorial's `hello-plugin` directory at the repository root, and run the remaining `dsh ...` commands from there as `pnpm dsh ...`. See [source execution](../../../../apps/cli/reference/README.md#source-execution) for build and launcher behavior. ## Two concepts, two manifests @@ -15,6 +17,12 @@ A bundle is what you author and distribute; a profile is what a user boots with ### The bundle manifest +Create the package directory: + +```sh +mkdir -p hello-plugin +``` + ``` hello-plugin/ ├── package.json # declares dsh.bundle @@ -22,6 +30,8 @@ hello-plugin/ └── index.js # plugin modules the patch rows reference ``` +Create `hello-plugin/package.json`: + ```json { "name": "dsh-hello-plugin", @@ -33,7 +43,17 @@ hello-plugin/ } ``` -The patch file is a YAML array of patch entries, like the `--patch` overlays you have been writing, except plugin rows reference the package by name instead of a relative source path so Node resolution finds the installed code: +Create `hello-plugin/index.js` with the plugin entry point: + +```js +export const name = 'hello-plugin' + +export function apply() { + console.log('[hello-plugin] plugin loaded!') +} +``` + +Create `hello-plugin/cordis.patch.yml`. The patch is a YAML array like the `--patch` overlays you have been writing, except plugin rows reference the package by name instead of a relative source path so Node resolution finds the installed code: ```yaml - insert: @@ -54,11 +74,10 @@ You never write a profile manifest by hand: `dsh plugin` creates and maintains i ## Install into a profile -`dsh plugin --profile ` forwards to pnpm in the profile directory, so every pnpm verb works. Install your package from its checkout: +`dsh plugin --profile ` forwards to pnpm in the profile directory, so every pnpm verb works. From the directory that contains `hello-plugin`, install the package checkout: ```sh -cd hello-plugin -dsh plugin --profile demo add . +dsh plugin --profile demo add ./hello-plugin ``` The first use initializes the profile (with `@deepseek-ai/dsh-base` as its first bundle), pnpm links the checkout, and `dsh` appends the bundle to `dsh.profile.bundles` because the package declares `dsh.bundle`: diff --git a/docs/user/develop/basic/publish.zh.md b/docs/user/develop/basic/publish.zh.md index b86bd43369..2cff05edcc 100644 --- a/docs/user/develop/basic/publish.zh.md +++ b/docs/user/develop/basic/publish.zh.md @@ -2,7 +2,9 @@ [English](publish.md) | 中文 -前几篇教程通过 `--patch` overlay 加载本地插件。本教程把它打包成可安装的**组合包**(bundle),用 `dsh plugin add` 安装进一个 **profile**,并解释决定组合后配置的层顺序。请先完成[插件配置](./config.md)。 +前几篇教程通过 `--patch` overlay 加载本地插件。本教程把它打包成可安装的**组合包**(bundle),用 `dsh plugin add` 安装进一个 **profile**,并解释决定组合后配置的层顺序。本文假设 `dsh` CLI 已安装。请先完成[插件配置](./config.md)。 + +如果改用全新的源码 checkout,请先按照[从源码运行章节](../../../../README.md#run-from-source)完成准备,将本教程的 `hello-plugin` 目录放在仓库根目录,并从该目录把下文的 `dsh ...` 命令改为 `pnpm dsh ...`。构建与启动器行为见[源码执行](../../../../apps/cli/reference/README.md#source-execution)。 ## 两个概念,两种 manifest @@ -15,6 +17,12 @@ ### 组合包 manifest +创建包目录: + +```sh +mkdir -p hello-plugin +``` + ``` hello-plugin/ ├── package.json # declares dsh.bundle @@ -22,6 +30,8 @@ hello-plugin/ └── index.js # plugin modules the patch rows reference ``` +创建 `hello-plugin/package.json`: + ```json { "name": "dsh-hello-plugin", @@ -33,7 +43,17 @@ hello-plugin/ } ``` -patch 文件与一直在写的 `--patch` overlay 一样,是一个 patch 条目的 YAML 数组;区别是插件行按包名而不是相对源码路径引用这个包,这样 Node 的模块解析才能找到已安装的代码: +创建 `hello-plugin/index.js`,写入插件入口: + +```js +export const name = 'hello-plugin' + +export function apply() { + console.log('[hello-plugin] plugin loaded!') +} +``` + +创建 `hello-plugin/cordis.patch.yml`。这个 patch 与一直在写的 `--patch` overlay 一样,是一个 patch 条目的 YAML 数组;区别是插件行按包名而不是相对源码路径引用这个包,这样 Node 的模块解析才能找到已安装的代码: ```yaml - insert: @@ -54,11 +74,10 @@ profile manifest 从不需要手写:`dsh plugin` 负责创建和维护它。 ## 安装进 profile -`dsh plugin --profile ` 在 profile 目录内转发给 pnpm,因此所有 pnpm 子命令都可用。从 checkout 安装你的包: +`dsh plugin --profile ` 在 profile 目录内转发给 pnpm,因此所有 pnpm 子命令都可用。在包含 `hello-plugin` 的目录中安装该包的 checkout: ```sh -cd hello-plugin -dsh plugin --profile demo add . +dsh plugin --profile demo add ./hello-plugin ``` 首次使用会初始化 profile(`@deepseek-ai/dsh-base` 作为它的第一个组合包),pnpm 链接该 checkout,而 `dsh` 因为这个包声明了 `dsh.bundle`,把它追加进 `dsh.profile.bundles`: diff --git a/docs/user/develop/basic/tool.i18n.yaml b/docs/user/develop/basic/tool.i18n.yaml index 8044c4adaa..1b5cac6c87 100644 --- a/docs/user/develop/basic/tool.i18n.yaml +++ b/docs/user/develop/basic/tool.i18n.yaml @@ -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 docs/user/develop/basic/tool.md -tool.md: a149f6876c573c9ece4b066ef6c211f69b0b03a8 -tool.zh.md: bcce5001497908cefa643749caee8da0e9859cf7 +tool.md: eb262d131a7f2b540827e86e56f8c0a28cb5f904 +tool.zh.md: d33d9946a73881df2cd44ebf3695819d02d013ab diff --git a/docs/user/develop/basic/tool.md b/docs/user/develop/basic/tool.md index a149f6876c..eb262d131a 100644 --- a/docs/user/develop/basic/tool.md +++ b/docs/user/develop/basic/tool.md @@ -49,4 +49,4 @@ Open `http://127.0.0.1:3080` and ask: `Use the greet tool to greet Ada.` The mod - [Plugin configuration](./config.md) — make the greeting configurable. - [Tool authoring reference](../../../cookbook/adding-a-tool.md) — look up nested schemas, canonical values, background work, policy hooks, Code Mode, and UI cards. -- [Capability layering](../practice/) — split a replaceable capability into Service Definition, Service provider, and Consumer packages. +- [Capability layering](../practice/) — split a replaceable capability into Service Definition, Service Provider, and Consumer packages. diff --git a/docs/user/develop/basic/tool.zh.md b/docs/user/develop/basic/tool.zh.md index bcce500149..d33d9946a7 100644 --- a/docs/user/develop/basic/tool.zh.md +++ b/docs/user/develop/basic/tool.zh.md @@ -49,4 +49,4 @@ pnpm dsh web --patch ./scratch-plugin/cordis.yml - [插件配置](./config.md) — 让问候语可配置。 - [工具编写参考](../../../cookbook/adding-a-tool.md) — 查阅嵌套 schema、规范值、后台工作、策略钩子、Code Mode 和 UI 卡片。 -- [能力分层](../practice/) — 将可替换能力拆分为 Service Definition、Service provider 和 Consumer 三类包。 +- [能力分层](../practice/) — 将可替换能力拆分为 Service Definition、Service Provider 和 Consumer 三类包。 diff --git a/docs/user/develop/framework/events.i18n.yaml b/docs/user/develop/framework/events.i18n.yaml index b5f1cc7745..7b62e40d71 100644 --- a/docs/user/develop/framework/events.i18n.yaml +++ b/docs/user/develop/framework/events.i18n.yaml @@ -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 docs/user/develop/framework/events.md -events.md: 4a6ecbad614cf2debccaee9ace1086273d8fb95b -events.zh.md: c77747bf6ac767c69e4f2d9cfe7375b71bd388e6 +events.md: 1d9fe5c8f5068de6ad8b2abaa85cf67be35c8459 +events.zh.md: 8bb9447a270cc2db966b1e01298a831a60a1b9c1 diff --git a/docs/user/develop/framework/events.md b/docs/user/develop/framework/events.md index 4a6ecbad61..1d9fe5c8f5 100644 --- a/docs/user/develop/framework/events.md +++ b/docs/user/develop/framework/events.md @@ -40,7 +40,7 @@ ctx.on('my-plugin/ready', ({ id }) => { ### bail — short circuit -Listeners run in order; the first non-`undefined` result becomes the final result: +Listeners run in order; the first result other than `null`, `false`, or `undefined` becomes the final result: ```ts ignore-check // Dispatch @@ -49,13 +49,13 @@ const result = ctx.bail('some-check', input) // Listen: a returned value stops later listeners. ctx.on('some-check', (input) => { if (shouldBlock(input)) return 'blocked' - // Return undefined to continue to the next listener. + // Return null, false, or undefined to continue to the next listener. }) ``` ### serial — ordered execution -Listeners run in registration order and asynchronous results are awaited. The first listener to return a non-empty value stops further execution: +Listeners run in registration order and asynchronous results are awaited. The first result other than `null`, `false`, or `undefined` stops further execution: ```ts ignore-check await ctx.serial('setup-phase', context) diff --git a/docs/user/develop/framework/events.zh.md b/docs/user/develop/framework/events.zh.md index c77747bf6a..8bb9447a27 100644 --- a/docs/user/develop/framework/events.zh.md +++ b/docs/user/develop/framework/events.zh.md @@ -40,7 +40,7 @@ ctx.on('my-plugin/ready', ({ id }) => { ### bail — 短路 -依次调用监听器,第一个非 `undefined` 的返回值将作为最终结果: +监听器按顺序运行,第一个不是 `null`、`false` 或 `undefined` 的返回值会成为最终结果: ```ts ignore-check // Dispatch @@ -49,13 +49,13 @@ const result = ctx.bail('some-check', input) // Listen: a returned value stops later listeners. ctx.on('some-check', (input) => { if (shouldBlock(input)) return 'blocked' - // Return undefined to continue to the next listener. + // Return null, false, or undefined to continue to the next listener. }) ``` ### serial — 顺序执行 -监听器按注册顺序依次执行,并等待异步结果;第一个返回非空值的监听器会终止后续执行: +监听器按注册顺序依次执行,并等待异步结果;第一个不是 `null`、`false` 或 `undefined` 的返回值会终止后续执行: ```ts ignore-check await ctx.serial('setup-phase', context) diff --git a/docs/user/develop/framework/service.i18n.yaml b/docs/user/develop/framework/service.i18n.yaml index 69b91821ba..507fc26f86 100644 --- a/docs/user/develop/framework/service.i18n.yaml +++ b/docs/user/develop/framework/service.i18n.yaml @@ -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 docs/user/develop/framework/service.md -service.md: a9e873f1ba969b1f2d22266f8ec03207f84eeddc -service.zh.md: a201280bc38176f57f5354ab205ae700c7b04a89 +service.md: 03f4e7dc4df934495a4b203066183753b621339e +service.zh.md: 2f4c01e0ea6a87a87ca694b265b07e07098f3e59 diff --git a/docs/user/develop/framework/service.md b/docs/user/develop/framework/service.md index a9e873f1ba..03f4e7dc4d 100644 --- a/docs/user/develop/framework/service.md +++ b/docs/user/develop/framework/service.md @@ -117,7 +117,7 @@ This prevents a plugin from calling a service that no longer exists. name: '@deepseek-ai/cordis-plugin-group' group: true isolate: - bash: true + shell: true config: - name: '@deepseek-ai/dsh-bash-local' config: @@ -128,7 +128,7 @@ This prevents a plugin from calling a service that no longer exists. name: '@deepseek-ai/cordis-plugin-group' group: true isolate: - bash: true + shell: true config: - name: '@deepseek-ai/dsh-bash-local' config: diff --git a/docs/user/develop/framework/service.zh.md b/docs/user/develop/framework/service.zh.md index a201280bc3..2f4c01e0ea 100644 --- a/docs/user/develop/framework/service.zh.md +++ b/docs/user/develop/framework/service.zh.md @@ -108,6 +108,8 @@ export function apply(ctx: Context) { 这可以防止插件调用已不存在的服务。 + + ## 服务隔离 `cordis.yml` 支持服务隔离——同一个服务可以有多个实例,不同插件组看到不同实例: @@ -117,7 +119,7 @@ export function apply(ctx: Context) { name: '@deepseek-ai/cordis-plugin-group' group: true isolate: - bash: true + shell: true config: - name: '@deepseek-ai/dsh-bash-local' config: @@ -128,7 +130,7 @@ export function apply(ctx: Context) { name: '@deepseek-ai/cordis-plugin-group' group: true isolate: - bash: true + shell: true config: - name: '@deepseek-ai/dsh-bash-local' config: diff --git a/docs/user/develop/practice/index.i18n.yaml b/docs/user/develop/practice/index.i18n.yaml index dd582b0886..2db0900779 100644 --- a/docs/user/develop/practice/index.i18n.yaml +++ b/docs/user/develop/practice/index.i18n.yaml @@ -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 docs/user/develop/practice/index.md -index.md: 3619a39f4a39b42cf4269d3778f233ecc1731933 -index.zh.md: 8bd378af5eaf2741c34d76a152fa8a62a947bf41 +index.md: cc6bd7a234305f6fa193341f15354b40855f72e9 +index.zh.md: aed13b00f9bc74946aace614953bed30705c8281 diff --git a/docs/user/develop/practice/index.md b/docs/user/develop/practice/index.md index 3619a39f4a..cc6bd7a234 100644 --- a/docs/user/develop/practice/index.md +++ b/docs/user/develop/practice/index.md @@ -6,14 +6,14 @@ This page has two parts: a concept reference for the three-role capability patte ## Concept reference -When a capability is general enough to need replaceable providers, such as Bash execution, Harness separates three roles: a **Service Definition**, a **Service provider**, and a **Consumer**. Put the roles in separate packages when they need to evolve or be replaced independently; a package may otherwise own more than one role. The complete capability is its seam. No individual role is a seam. +When a capability is general enough to need replaceable providers, such as Bash execution, Harness separates three roles: a **Service Definition**, a **Service Provider**, and a **Consumer**. Put the roles in separate packages when they need to evolve or be replaced independently; a package may otherwise own more than one role. The complete capability is its seam. No individual role is a seam. ## Bash example The Bash execution capability consists of: - **Service Definition** (`dsh-shell`) — defines the Cordis service and Bash request and result types -- **Service provider** (`dsh-bash-local`) — executes commands on the local machine +- **Service Provider** (`dsh-bash-local`) — executes commands on the local machine - **Consumer** (`dsh-tool-bash`) — exposes the capability as a model-callable tool ``` @@ -23,7 +23,7 @@ The Bash execution capability consists of: └─────────────┘ └──────────────────┘ └──────────────┘ ▲ │ └────────────────────────────────────────────┘ - inject: ['bash'] + inject: ['shell'] ``` ## Benefits of the split @@ -44,14 +44,14 @@ The Service Definition and tool remain unchanged while the provider changes. ### Evolve independently - The Service Definition changes rarely after callers depend on its contract. -- Service providers can improve performance and security independently. +- Service Providers can improve performance and security independently. - Consumers can change how they present the capability to the model. ### Decouple dependencies -- The Service provider depends on the Service Definition. +- The Service Provider depends on the Service Definition. - The Consumer depends on the Service Definition. -- The Service provider and Consumer **do not depend on each other**. +- The Service Provider and Consumer **do not depend on each other**. The [capability-seam reference](../../../capability-seams.md) owns the current built-in families and package links. @@ -87,7 +87,7 @@ export interface MyCapResult { } ``` -### Step 2: write a Service provider +### Step 2: write a Service Provider ```ts ignore-check // packages/my-cap/my-cap-local/src/index.ts @@ -147,7 +147,7 @@ export function apply(ctx: Context) { ## Design points - **Do not split preemptively** — use separate packages only when the roles need to evolve independently. A simple tool plugin does not. -- **The Service Definition owns Request/Result types** — Service providers and Consumers depend only on the Service Definition package. +- **The Service Definition owns Request/Result types** — Service Providers and Consumers depend only on the Service Definition package. - **Explicit > implicit** — resolve defaults in an explicit `resolve(request): Spec` step rather than hiding `?? default` expressions inside `run()`. ## Next steps diff --git a/docs/user/develop/practice/index.zh.md b/docs/user/develop/practice/index.zh.md index 8bd378af5e..aed13b00f9 100644 --- a/docs/user/develop/practice/index.zh.md +++ b/docs/user/develop/practice/index.zh.md @@ -6,14 +6,14 @@ ## 概念参考 -当一项能力足够通用,需要支持可替换的提供方时(例如 Bash 执行),harness 会区分三种角色:**Service Definition**、**Service provider** 和 **Consumer**。角色需要独立演进或替换时,将它们放入不同包;否则一个包可以承担多个角色。完整能力构成其 seam。任何单一角色都不是 seam。 +当一项能力足够通用,需要支持可替换的提供方时(例如 Bash 执行),harness 会区分三种角色:**Service Definition**、**Service Provider** 和 **Consumer**。角色需要独立演进或替换时,将它们放入不同包;否则一个包可以承担多个角色。完整能力构成其 seam。任何单一角色都不是 seam。 ## 以 Bash 为例 以 Bash 执行能力为例: - **Service Definition** (`dsh-shell`):定义 Cordis 服务以及 Bash 请求和结果类型 -- **Service provider** (`dsh-bash-local`):在本地计算机上执行命令 +- **Service Provider** (`dsh-bash-local`):在本地计算机上执行命令 - **Consumer** (`dsh-tool-bash`):将该能力公开为模型可调用的工具 ``` @@ -23,7 +23,7 @@ └─────────────┘ └──────────────────┘ └──────────────┘ ▲ │ └────────────────────────────────────────────┘ - inject: ['bash'] + inject: ['shell'] ``` ## 拆分的好处 @@ -44,14 +44,14 @@ ### 独立演进 - 调用方开始依赖 Service Definition 的约定后,Service Definition 很少改动。 -- Service provider 可以独立优化性能和安全性。 +- Service Provider 可以独立优化性能和安全性。 - Consumer 可以调整能力向模型呈现的方式。 ### 依赖解耦 -- Service provider 依赖 Service Definition。 +- Service Provider 依赖 Service Definition。 - Consumer 依赖 Service Definition。 -- Service provider 和 Consumer **互不依赖**。 +- Service Provider 和 Consumer **互不依赖**。 当前内置系列及其包链接由[能力 seam 参考](../../../capability-seams.md)负责。 @@ -87,7 +87,7 @@ export interface MyCapResult { } ``` -### 第二步:编写 Service provider +### 第二步:编写 Service Provider ```ts ignore-check // packages/my-cap/my-cap-local/src/index.ts @@ -147,7 +147,7 @@ export function apply(ctx: Context) { ## 设计要点 - **不要预防性拆分**:只有角色需要独立演进时,才使用不同包。简单的工具插件无需拆分。 -- **Service Definition 拥有 Request/Result 类型**:Service provider 和 Consumer 只依赖 Service Definition 包。 +- **Service Definition 拥有 Request/Result 类型**:Service Provider 和 Consumer 只依赖 Service Definition 包。 - **显式优于隐式**:实现应通过显式的 `resolve(request): Spec` 步骤处理默认值,而不是在 `run()` 中隐藏 `?? default`。 ## 下一步 diff --git a/docs/user/develop/practice/llm-adapter.i18n.yaml b/docs/user/develop/practice/llm-adapter.i18n.yaml index 6c91f15cb1..d7d431bd5e 100644 --- a/docs/user/develop/practice/llm-adapter.i18n.yaml +++ b/docs/user/develop/practice/llm-adapter.i18n.yaml @@ -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 docs/user/develop/practice/llm-adapter.md -llm-adapter.md: aba4a6d0c8ee42e78ca5a804d9a0dd9b31c1e240 -llm-adapter.zh.md: 5c7a6483e29a28871257df6a31e13d859a245097 +llm-adapter.md: 882e82d880ac622cf886c6c24e75a1987e1c6702 +llm-adapter.zh.md: 27c480af2a19a68ac35900a2ce1b5e9dbdc85bf8 diff --git a/docs/user/develop/practice/llm-adapter.md b/docs/user/develop/practice/llm-adapter.md index aba4a6d0c8..882e82d880 100644 --- a/docs/user/develop/practice/llm-adapter.md +++ b/docs/user/develop/practice/llm-adapter.md @@ -32,12 +32,12 @@ class MyAdapter extends LlmAdapter { export interface Config { apiKey: string - models: string[] + providers: string[] } export const Config: Schema = Schema.object({ apiKey: Schema.string().required(), - models: Schema.array(Schema.string()).required(), + providers: Schema.array(Schema.string()).required(), }) export const name = 'my-llm-adapter' @@ -45,7 +45,7 @@ export const inject = ['llm'] export function apply(ctx: Context, config: Config) { const adapter = new MyAdapter(config.apiKey) - ctx.llm.registerAdapter(config.models, adapter) + ctx.llm.registerAdapter(config.providers, adapter) } ``` @@ -117,10 +117,10 @@ Override `resolveModel(provider, model, signal?)` to return exact provider/model ## Register an adapter ```ts ignore-check -ctx.llm.registerAdapter(['model-name-1', 'model-name-2'], adapter) +ctx.llm.registerAdapter(['my-provider'], adapter) ``` -The first argument lists the model names handled by the adapter. If `cordis.yml` selects `model: model-name-1`, the service routes that request to this adapter. +The first argument lists provider routes handled by the adapter. `GenerateOptions.provider` selects the registered adapter, while `GenerateOptions.model` passes an adapter-owned model id without lifecycle registration. Override `listModels()` when the adapter can advertise model choices to selectors. ## Use it from cordis.yml @@ -129,18 +129,16 @@ The first argument lists the model names handled by the adapter. If `cordis.yml` name: './src/my-llm-adapter.ts' config: apiKey: !!js process.env.MY_API_KEY - models: - - my-model-v1 - - my-model-v2 + providers: + - my-provider - id: agent-loop name: '@deepseek-ai/dsh-agent-loop' config: agents: - id: main - provider: my-llm - model: my-model-v1 # References the model registered above. - workspaceContext: false + provider: my-provider + model: my-model-v1 ``` ## Reference implementations diff --git a/docs/user/develop/practice/llm-adapter.zh.md b/docs/user/develop/practice/llm-adapter.zh.md index 5c7a6483e2..27c480af2a 100644 --- a/docs/user/develop/practice/llm-adapter.zh.md +++ b/docs/user/develop/practice/llm-adapter.zh.md @@ -32,12 +32,12 @@ class MyAdapter extends LlmAdapter { export interface Config { apiKey: string - models: string[] + providers: string[] } export const Config: Schema = Schema.object({ apiKey: Schema.string().required(), - models: Schema.array(Schema.string()).required(), + providers: Schema.array(Schema.string()).required(), }) export const name = 'my-llm-adapter' @@ -45,7 +45,7 @@ export const inject = ['llm'] export function apply(ctx: Context, config: Config) { const adapter = new MyAdapter(config.apiKey) - ctx.llm.registerAdapter(config.models, adapter) + ctx.llm.registerAdapter(config.providers, adapter) } ``` @@ -117,10 +117,10 @@ async function* exampleChunks(): AsyncIterable { ## 注册适配器 ```ts ignore-check -ctx.llm.registerAdapter(['model-name-1', 'model-name-2'], adapter) +ctx.llm.registerAdapter(['my-provider'], adapter) ``` -第一个参数是该适配器支持的模型名列表。当用户在 `cordis.yml` 中配置 `model: model-name-1` 时,框架会将请求路由到该适配器。 +第一个参数是该适配器处理的提供方路由列表。`GenerateOptions.provider` 选择已注册的适配器,`GenerateOptions.model` 则传入由适配器拥有、无需在生命周期启动时注册的模型 id。适配器能够向选择器公布模型选项时,请覆写 `listModels()`。 ## 在 cordis.yml 中使用 @@ -129,18 +129,16 @@ ctx.llm.registerAdapter(['model-name-1', 'model-name-2'], adapter) name: './src/my-llm-adapter.ts' config: apiKey: !!js process.env.MY_API_KEY - models: - - my-model-v1 - - my-model-v2 + providers: + - my-provider - id: agent-loop name: '@deepseek-ai/dsh-agent-loop' config: agents: - id: main - provider: my-llm - model: my-model-v1 # References the model registered above. - workspaceContext: false + provider: my-provider + model: my-model-v1 ``` ## 实战参考 diff --git a/docs/user/guide/index.i18n.yaml b/docs/user/guide/index.i18n.yaml index 51f8a8802d..ba745feed8 100644 --- a/docs/user/guide/index.i18n.yaml +++ b/docs/user/guide/index.i18n.yaml @@ -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 docs/user/guide/index.md -index.md: 80d288b1aba37e7f0863fe5fc8237cbd2a6ab9b5 -index.zh.md: addfbc94ff93ed015e52f509a23a3f981e36770b +index.md: 2ae8847e3e04e131517e505bbc3c5f2c1047a45c +index.zh.md: 7e4a140e11ca409755d63ade41a31d9b3cc4d4b6 diff --git a/docs/user/guide/index.md b/docs/user/guide/index.md index 80d288b1ab..2ae8847e3e 100644 --- a/docs/user/guide/index.md +++ b/docs/user/guide/index.md @@ -2,16 +2,18 @@ English | [中文](index.zh.md) -Start the Web UI through the [root README](../../../README.md#run); the command prints its URL. This guide begins after that server is running. - -The invoking directory is the default workspace, so the agent can inspect and modify the project where you started `dsh`. +Start the Web UI through the [root README](../../../README.md#run); the command prints its URL. This guide begins after that server is running. The `dsh` process uses its invoking directory as the default filesystem location, but a fresh Web UI has no selected workspace until you add one. ## Configure a model -Open **Settings → Models**, enter a DeepSeek API key, and save it. The model route becomes usable immediately without restarting the server. +Open **Settings → Models**, enter a [DeepSeek API key](https://platform.deepseek.com/), and save it. The model route becomes usable immediately without restarting the server. The [model configuration guide](./providers.md) covers other providers and custom OpenAI-compatible endpoints. +## Choose a workspace + +Click **Choose workspace**, add the project directory where you started `dsh`, and select it. The session composer remains unavailable until a workspace is selected. + ## Run a task Start a session and send: diff --git a/docs/user/guide/index.zh.md b/docs/user/guide/index.zh.md index addfbc94ff..7e4a140e11 100644 --- a/docs/user/guide/index.zh.md +++ b/docs/user/guide/index.zh.md @@ -2,23 +2,25 @@ [English](index.md) | 中文 -先按照[根 README](../../../README.md#run)启动 Web UI;命令会打印其访问地址。本指南从服务器已经运行的状态开始。 - -调用目录是默认工作区,因此 agent(智能体)可以检查并修改启动 `dsh` 时所在的项目。 +请先按照[根目录 README](../../../README.md#run) 中的说明启动 Web UI;命令会打印其访问地址。本指南从服务器已经运行的状态开始。`dsh` 进程会把启动时所在的目录作为默认文件系统位置;全新的 Web UI 则不会选中任何工作区,你需要添加一个工作区。 ## 配置模型 -打开**设置 → 模型**,输入 DeepSeek API 密钥并保存。模型路由会立即可用,不需要重启服务器。 +打开**设置 → 模型**,输入 [DeepSeek API 密钥](https://platform.deepseek.com/)并保存。模型路由会立即可用,不需要重启服务器。 [模型配置指南](./providers.md)介绍其他提供方和自定义 OpenAI 兼容端点。 +## 选择工作区 + +点击**选择工作区**,添加启动 `dsh` 时所在的项目目录,然后选中它。选中工作区前,会话输入框不可用。 + ## 运行任务 启动一个会话并发送: > Summarize this repository and identify its main packages. -agent 可以读取和编辑工作区文件、运行命令、委派工作并维护计划。当操作在当前权限策略下需要审批时,Web UI 会先询问你。 +Agent(智能体)可以读取和编辑工作区文件、运行命令、委派工作并维护计划。如果根据当前权限策略,某项操作需要审批,Web UI 会先询问你。 ## 继续使用 diff --git a/examples/acp-agent/cordis.yml b/examples/acp-agent/cordis.yml index d37e09f2b8..ee44969d02 100644 --- a/examples/acp-agent/cordis.yml +++ b/examples/acp-agent/cordis.yml @@ -123,7 +123,8 @@ # Fork stays one-shot because a continuable child's `report` tool and prompt # section precede the inherited history a fork reuses; `run_in_background` is off -# because this example mounts no task service. See .agents/notes/implemented/architecture/2026-08-10-fork-children-stay-one-shot.md. +# as an explicit foreground-only choice even though agent-spine-demo mounts the +# generic Job runtime. See .agents/notes/implemented/architecture/2026-08-10-fork-children-stay-one-shot.md. - id: tool-subagent-fork name: '@deepseek-ai/dsh-tool-subagent' config: diff --git a/examples/acp-agent/product-subagent-both.cordis.snapshot.yml b/examples/acp-agent/product-subagent-both.cordis.snapshot.yml index 73d22eae27..0f8760cb91 100644 --- a/examples/acp-agent/product-subagent-both.cordis.snapshot.yml +++ b/examples/acp-agent/product-subagent-both.cordis.snapshot.yml @@ -27,12 +27,12 @@ config: provider: codex toolName: subagent_codex - enableRunInBackground: false + backgroundMode: one-shot maxDepth: provider-managed - id: tool-subagent-claude-code name: '@deepseek-ai/dsh-tool-subagent' config: provider: claude-code toolName: subagent_claude_code - enableRunInBackground: false + backgroundMode: one-shot maxDepth: provider-managed diff --git a/examples/acp-agent/product-subagent-both.cordis.yml b/examples/acp-agent/product-subagent-both.cordis.yml index ce9d054058..6a75bec332 100644 --- a/examples/acp-agent/product-subagent-both.cordis.yml +++ b/examples/acp-agent/product-subagent-both.cordis.yml @@ -1,5 +1,5 @@ -# Add both native product providers and the same independent foreground tool -# rows an Agent Preset may contribute. Loading the composition starts neither +# Add both native product providers and the same independent one-shot tool rows +# an Agent Preset may contribute. Loading the composition starts neither # product; the scenario pins both model-visible schemas. - id: base name: '@deepseek-ai/cordis-plugin-include' @@ -16,12 +16,12 @@ config: provider: codex toolName: subagent_codex - enableRunInBackground: false + backgroundMode: one-shot maxDepth: provider-managed - id: tool-subagent-claude-code name: '@deepseek-ai/dsh-tool-subagent' config: provider: claude-code toolName: subagent_claude_code - enableRunInBackground: false + backgroundMode: one-shot maxDepth: provider-managed diff --git a/examples/acp-agent/product-subagent-codex.cordis.snapshot.yml b/examples/acp-agent/product-subagent-codex.cordis.snapshot.yml index 8b8cd8604c..69171c7dbf 100644 --- a/examples/acp-agent/product-subagent-codex.cordis.snapshot.yml +++ b/examples/acp-agent/product-subagent-codex.cordis.snapshot.yml @@ -25,5 +25,5 @@ config: provider: codex toolName: subagent_codex - enableRunInBackground: false + backgroundMode: one-shot maxDepth: provider-managed diff --git a/examples/acp-agent/product-subagent-codex.cordis.yml b/examples/acp-agent/product-subagent-codex.cordis.yml index 55f9985b7d..2a95679e14 100644 --- a/examples/acp-agent/product-subagent-codex.cordis.yml +++ b/examples/acp-agent/product-subagent-codex.cordis.yml @@ -1,4 +1,4 @@ -# Add the native Codex product provider and its preset-shaped foreground tool to +# Add the native Codex product provider and its preset-shaped one-shot tool to # the real ACP composition. The model is told not to call it; the scenario pins # the assembled request schema without starting Codex. - id: base @@ -14,5 +14,5 @@ config: provider: codex toolName: subagent_codex - enableRunInBackground: false + backgroundMode: one-shot maxDepth: provider-managed diff --git a/examples/acp-agent/tests/acp.snapshot.ts b/examples/acp-agent/tests/acp.snapshot.ts index db4a2b5d2f..87ef397ee2 100644 --- a/examples/acp-agent/tests/acp.snapshot.ts +++ b/examples/acp-agent/tests/acp.snapshot.ts @@ -348,6 +348,13 @@ const SCENARIOS: Scenario[] = [ // reply, and a clean completed retry turn. Its overlay only pins a deterministic // 1 ms zero-jitter delay, so it shares the default header class. { name: 'empty-response-retry', hasModelTurn: true, recorded: false, configPath: RETRY_CONFIG }, + // Keyless, authored (like error-finish): a live model cannot be coaxed into + // a deterministic mid-tool-call output-limit truncation. Turn 1's script ends + // at `max-tokens` with an unfinished tool call and adapter replay metadata for + // both blocks; the durable assistant/message pins assembly dropping the tool + // call AND pruning its per-block replay entry in the same decision, and turn 2 + // proves the session continues past the truncated step. + { name: 'max-tokens-continue', hasModelTurn: true, recorded: false }, // Keyless, authored (like error-finish/cancel): deterministically forcing a // LIVE model to repeat one call three times is not a stable recording, so // the fixture scripts five identical todo_write calls and pins BOTH reminder diff --git a/examples/acp-agent/tests/fixtures/subagent/subagent-claude-code/cordis.yml b/examples/acp-agent/tests/fixtures/subagent/subagent-claude-code/cordis.yml index fcdc0c4fb6..45b62f880f 100644 --- a/examples/acp-agent/tests/fixtures/subagent/subagent-claude-code/cordis.yml +++ b/examples/acp-agent/tests/fixtures/subagent/subagent-claude-code/cordis.yml @@ -1,4 +1,4 @@ -# Test-only composition of both public opt-in providers and foreground tools. +# Test-only composition of both public opt-in providers and one-shot task tools. # The owning e2e boots this tree but never invokes a model or product process. - id: fixture name: './fixture.ts' @@ -20,7 +20,7 @@ config: provider: codex toolName: subagent_codex - enableRunInBackground: false + backgroundMode: one-shot maxDepth: 'provider-managed' - id: tool-subagent-claude-code @@ -28,7 +28,7 @@ config: provider: claude-code toolName: subagent_claude_code - enableRunInBackground: false + backgroundMode: one-shot maxDepth: 'provider-managed' - id: agent-spine diff --git a/examples/acp-agent/tests/fixtures/subagent/subagent-claude-code/driver.ts b/examples/acp-agent/tests/fixtures/subagent/subagent-claude-code/driver.ts index d7540e1a2d..c10e9d110c 100644 --- a/examples/acp-agent/tests/fixtures/subagent/subagent-claude-code/driver.ts +++ b/examples/acp-agent/tests/fixtures/subagent/subagent-claude-code/driver.ts @@ -53,11 +53,16 @@ try { required: tool.parameters.required, } }) + const jobTools = ctx.tools.schemas() + .map(schema => schema.name) + .filter(name => name === 'job_kill' || name === 'job_list' || name === 'job_output') + .sort() process.stdout.write(`${JSON.stringify({ registeredProviders: ctx.subagents.list(), providers, tools, + jobTools, starts, })}\n`) } finally { diff --git a/examples/acp-agent/tests/fixtures/subagent/subagent-codex/cordis.yml b/examples/acp-agent/tests/fixtures/subagent/subagent-codex/cordis.yml index e770b11c95..6afe2b888d 100644 --- a/examples/acp-agent/tests/fixtures/subagent/subagent-codex/cordis.yml +++ b/examples/acp-agent/tests/fixtures/subagent/subagent-codex/cordis.yml @@ -1,4 +1,4 @@ -# Test-only composition of the public opt-in provider and foreground tool. +# Test-only composition of the public opt-in provider and one-shot task tool. # The owning e2e boots this tree but never invokes the model or Codex. - id: fixture name: './fixture.ts' @@ -17,7 +17,7 @@ config: provider: codex toolName: subagent_codex - enableRunInBackground: false + backgroundMode: one-shot maxDepth: 'provider-managed' - id: agent-spine diff --git a/examples/acp-agent/tests/fixtures/subagent/subagent-codex/driver.ts b/examples/acp-agent/tests/fixtures/subagent/subagent-codex/driver.ts index 873f5e36de..51cd5eaa6f 100644 --- a/examples/acp-agent/tests/fixtures/subagent/subagent-codex/driver.ts +++ b/examples/acp-agent/tests/fixtures/subagent/subagent-codex/driver.ts @@ -31,6 +31,10 @@ try { if (typeof properties !== 'object' || properties === null || Array.isArray(properties)) { throw new Error('subagent_codex tool has invalid parameter properties') } + const jobTools = ctx.tools.schemas() + .map(schema => schema.name) + .filter(name => name === 'job_kill' || name === 'job_list' || name === 'job_output') + .sort() process.stdout.write(`${JSON.stringify({ providers: ctx.subagents.list(), @@ -44,6 +48,7 @@ try { parameterNames: Object.keys(properties).sort(), required: tool.parameters.required, }, + jobTools, starts, })}\n`) } finally { diff --git a/examples/acp-agent/tests/fs-diff-bound.cordis.snapshot.yml b/examples/acp-agent/tests/fs-diff-bound.cordis.snapshot.yml index 4cc6ba1f3e..ac89b962eb 100644 --- a/examples/acp-agent/tests/fs-diff-bound.cordis.snapshot.yml +++ b/examples/acp-agent/tests/fs-diff-bound.cordis.snapshot.yml @@ -41,6 +41,6 @@ - id: deepseek-v4-flash contextWindow: 1000000 defaultMaxTokens: 256000 - reasoningEfforts: ['off', 'high', 'max'] + reasoningEfforts: ['off', 'low', 'high', 'max'] defaultReasoningEffort: max - id: deepseek-v4-pro diff --git a/examples/acp-agent/tests/snapshots/advanced-toolchain/system-prompt.expected.md b/examples/acp-agent/tests/snapshots/advanced-toolchain/system-prompt.expected.md index 5e266ddbc0..1d2682498e 100644 --- a/examples/acp-agent/tests/snapshots/advanced-toolchain/system-prompt.expected.md +++ b/examples/acp-agent/tests/snapshots/advanced-toolchain/system-prompt.expected.md @@ -131,7 +131,7 @@ Use subagent in the background by default. Start independent delegations togethe ## Writing code for run_code -Pass `run_code` the body of an async TypeScript function (erasable syntax only — no `enum` or namespaces; type annotations are advisory, the code runs type-stripped). Inside the program: +`run_code` takes two required arguments: `code` — the body of an async TypeScript function (erasable syntax only — no `enum` or namespaces; type annotations are advisory, the code runs type-stripped) — and `description`, a short summary of what the program does. Inside the program: - Call tools as `await tools.name(args)` — quoted access for exotic names: `tools["my-tool"](args)`. Every call resolves to the tool's typed canonical JSON value. Tool arguments must be lossless JSON. - A FAILED tool call rejects with `ToolCallError`, whose `toolName` identifies the failed tool and whose `message` is human-readable — `try/catch` it to handle and continue. diff --git a/examples/acp-agent/tests/snapshots/advanced-toolchain/tool-schemas.expected.json b/examples/acp-agent/tests/snapshots/advanced-toolchain/tool-schemas.expected.json index eba901f611..aec8cea715 100644 --- a/examples/acp-agent/tests/snapshots/advanced-toolchain/tool-schemas.expected.json +++ b/examples/acp-agent/tests/snapshots/advanced-toolchain/tool-schemas.expected.json @@ -443,7 +443,7 @@ }, { "name": "run_code", - "description": "Execute a TypeScript program against the available tools. Write the BODY of an async function (erasable syntax only; top-level `await` and `return` work) and call tools as `await tools.name(args)` per the declarations in the system prompt. Only what you print or return comes back — curate it.", + "description": "Execute a TypeScript program against the available tools. Takes two required arguments: `code`, the BODY of an async function (erasable syntax only; top-level `await` and `return` work), and `description`, a short summary of what the program does. Call tools as `await tools.name(args)` per the declarations in the system prompt. Only what you print or return comes back — curate it.", "parameters": { "type": "object", "properties": { diff --git a/examples/acp-agent/tests/snapshots/both-mode-turn/system-prompt.expected.md b/examples/acp-agent/tests/snapshots/both-mode-turn/system-prompt.expected.md index 9ed911462a..57603571d8 100644 --- a/examples/acp-agent/tests/snapshots/both-mode-turn/system-prompt.expected.md +++ b/examples/acp-agent/tests/snapshots/both-mode-turn/system-prompt.expected.md @@ -25,7 +25,7 @@ Use subagent in the background by default. Start independent delegations togethe ## Writing code for run_code -Pass `run_code` the body of an async TypeScript function (erasable syntax only — no `enum` or namespaces; type annotations are advisory, the code runs type-stripped). Inside the program: +`run_code` takes two required arguments: `code` — the body of an async TypeScript function (erasable syntax only — no `enum` or namespaces; type annotations are advisory, the code runs type-stripped) — and `description`, a short summary of what the program does. Inside the program: - Call tools as `await tools.name(args)` — quoted access for exotic names: `tools["my-tool"](args)`. Every call resolves to the tool's typed canonical JSON value. Tool arguments must be lossless JSON. - A FAILED tool call rejects with `ToolCallError`, whose `toolName` identifies the failed tool and whose `message` is human-readable — `try/catch` it to handle and continue. diff --git a/examples/acp-agent/tests/snapshots/both-mode-turn/tool-schemas.expected.json b/examples/acp-agent/tests/snapshots/both-mode-turn/tool-schemas.expected.json index ae72cfca19..c76cd2ef49 100644 --- a/examples/acp-agent/tests/snapshots/both-mode-turn/tool-schemas.expected.json +++ b/examples/acp-agent/tests/snapshots/both-mode-turn/tool-schemas.expected.json @@ -246,7 +246,7 @@ }, { "name": "run_code", - "description": "Execute a TypeScript program against the available tools. Write the BODY of an async function (erasable syntax only; top-level `await` and `return` work) and call tools as `await tools.name(args)` per the declarations in the system prompt. Only what you print or return comes back — curate it.", + "description": "Execute a TypeScript program against the available tools. Takes two required arguments: `code`, the BODY of an async function (erasable syntax only; top-level `await` and `return` work), and `description`, a short summary of what the program does. Call tools as `await tools.name(args)` per the declarations in the system prompt. Only what you print or return comes back — curate it.", "parameters": { "type": "object", "properties": { diff --git a/examples/acp-agent/tests/snapshots/code-mode-turn/system-prompt.expected.md b/examples/acp-agent/tests/snapshots/code-mode-turn/system-prompt.expected.md index e0398b0322..0659f8e2a5 100644 --- a/examples/acp-agent/tests/snapshots/code-mode-turn/system-prompt.expected.md +++ b/examples/acp-agent/tests/snapshots/code-mode-turn/system-prompt.expected.md @@ -27,7 +27,7 @@ Use subagent in the background by default. Start independent delegations togethe ## Writing code for run_code -Pass `run_code` the body of an async TypeScript function (erasable syntax only — no `enum` or namespaces; type annotations are advisory, the code runs type-stripped). Inside the program: +`run_code` takes two required arguments: `code` — the body of an async TypeScript function (erasable syntax only — no `enum` or namespaces; type annotations are advisory, the code runs type-stripped) — and `description`, a short summary of what the program does. Inside the program: - Call tools as `await tools.name(args)` — quoted access for exotic names: `tools["my-tool"](args)`. Every call resolves to the tool's typed canonical JSON value. Tool arguments must be lossless JSON. - A FAILED tool call rejects with `ToolCallError`, whose `toolName` identifies the failed tool and whose `message` is human-readable — `try/catch` it to handle and continue. diff --git a/examples/acp-agent/tests/snapshots/code-mode-turn/tool-schemas.expected.json b/examples/acp-agent/tests/snapshots/code-mode-turn/tool-schemas.expected.json index a9ee29aa7a..2a94d503e2 100644 --- a/examples/acp-agent/tests/snapshots/code-mode-turn/tool-schemas.expected.json +++ b/examples/acp-agent/tests/snapshots/code-mode-turn/tool-schemas.expected.json @@ -2,7 +2,7 @@ "initial": [ { "name": "run_code", - "description": "Execute a TypeScript program against the available tools. Write the BODY of an async function (erasable syntax only; top-level `await` and `return` work) and call tools as `await tools.name(args)` per the declarations in the system prompt. Only what you print or return comes back — curate it.", + "description": "Execute a TypeScript program against the available tools. Takes two required arguments: `code`, the BODY of an async function (erasable syntax only; top-level `await` and `return` work), and `description`, a short summary of what the program does. Call tools as `await tools.name(args)` per the declarations in the system prompt. Only what you print or return comes back — curate it.", "parameters": { "type": "object", "properties": { diff --git a/examples/acp-agent/tests/snapshots/max-tokens-continue/input.json b/examples/acp-agent/tests/snapshots/max-tokens-continue/input.json new file mode 100644 index 0000000000..ebd0c642bb --- /dev/null +++ b/examples/acp-agent/tests/snapshots/max-tokens-continue/input.json @@ -0,0 +1,8 @@ +{ + "steps": [ + { "op": "initialize" }, + { "op": "newSession" }, + { "op": "prompt", "text": "This turn is cut off at the output limit while calling a tool." }, + { "op": "prompt", "text": "Continue: summarize what happened without retrying the tool." } + ] +} diff --git a/examples/acp-agent/tests/snapshots/max-tokens-continue/session.jsonl b/examples/acp-agent/tests/snapshots/max-tokens-continue/session.jsonl new file mode 100644 index 0000000000..6e2f7a6d1c --- /dev/null +++ b/examples/acp-agent/tests/snapshots/max-tokens-continue/session.jsonl @@ -0,0 +1,33 @@ +{"type":"session","version":0,"id":"7f1c9a04-5b52-4a7e-9a63-1d2ab7c90d11","createdAt":1786348800000,"cwd":"{{cwd}}","delegationDepth":0} +{"type":"agent/inbox/spliced","seq":0,"time":1786348800001,"data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"This turn is cut off at the output limit while calling a tool."}],"source":{"kind":"user"},"role":"user","id":"3a6a5c9e-0f9c-4c8f-9f57-6f2f7f3d5a01"}]}} +{"type":"turn/start","seq":1,"time":1786348800002,"data":{"turn":1}} +{"type":"agent/inbox/spliced","seq":2,"time":1786348800002,"data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} +{"type":"step/start","seq":3,"time":1786348800003,"data":{"turn":1,"step":1}} +{"type":"user/message","seq":4,"time":1786348800004,"data":{"content":[{"type":"text","text":"This turn is cut off at the output limit while calling a tool."}],"source":{"kind":"user"},"role":"user","id":"3a6a5c9e-0f9c-4c8f-9f57-6f2f7f3d5a01"},"surfaceOp":"append"} +{"type":"user/message","seq":5,"time":1786348800005,"data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."}],"source":{"kind":"plugin","plugin":"@deepseek-ai/dsh-system-prompt","form":"snapshot","sections":[{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."}]},"role":"user","id":"5b7f2d1c-9c44-4c58-8a3e-2f6f8b9d4c02"},"surfaceOp":"append"} +{"type":"session/title","seq":6,"time":1786348800005,"data":{"title":"This turn is cut off","messageSeqs":[4],"source":{"kind":"fallback"}}} +{"type":"request/header","seq":7,"time":1786348800006,"data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"system":"{{system}}","tools":"{{tools}}"},"reason":"initial"}} +{"type":"request/context","seq":8,"time":1786348800006,"data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} +{"type":"assistant/chunk","seq":9,"time":1786348800010,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"text"}}} +{"type":"assistant/chunk","seq":10,"time":1786348800011,"data":{"turn":1,"step":1,"chunk":{"type":"text-delta","index":0,"text":"Starting the write now."}}} +{"type":"assistant/chunk","seq":11,"time":1786348800012,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"Starting the write now."}}}} +{"type":"assistant/chunk","seq":12,"time":1786348800013,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}}} +{"type":"assistant/chunk","seq":13,"time":1786348800014,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call-cut","name":"bash","argumentsDelta":"{\"command\":\"echo demo > "}}} +{"type":"assistant/chunk","seq":14,"time":1786348800015,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":2864,"outputTokens":12}}}} +{"type":"assistant/chunk","seq":15,"time":1786348800016,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"max-tokens"},"replayState":{"response":{"kind":"pi-ai","version":2,"api":"openai-completions","provider":"deepseek-official","model":"deepseek-v4-flash","stopReason":"length"},"blocks":[{"type":"text"},{"type":"tool-call"}]}}}} +{"type":"assistant/message","seq":16,"time":1786348800016,"data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"Starting the write now."}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash","replayState":{"response":{"kind":"pi-ai","version":2,"api":"openai-completions","provider":"deepseek-official","model":"deepseek-v4-flash","stopReason":"length"},"blocks":[{"type":"text"}]}},"id":"9d5f7c2a-1e63-4d6b-8f14-7a2c5e9b3d03"},"usage":{"inputTokens":2864,"outputTokens":12}},"sourceEventSeqs":[9,10,11,12,13,14,15],"surfaceOp":"append"} +{"type":"step/end","seq":17,"time":1786348800016,"data":{"turn":1,"step":1}} +{"type":"turn/end","seq":18,"time":1786348800016,"data":{"turn":1,"reason":{"kind":"max-tokens"}}} +{"type":"agent/inbox/spliced","seq":19,"time":1786348800020,"data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Continue: summarize what happened without retrying the tool."}],"source":{"kind":"user"},"role":"user","id":"1c8e6b4f-3d27-4a91-b5c8-9e4f7a2d6c04"}]}} +{"type":"turn/start","seq":20,"time":1786348800021,"data":{"turn":2}} +{"type":"agent/inbox/spliced","seq":21,"time":1786348800021,"data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} +{"type":"step/start","seq":22,"time":1786348800022,"data":{"turn":2,"step":1}} +{"type":"user/message","seq":23,"time":1786348800023,"data":{"content":[{"type":"text","text":"Continue: summarize what happened without retrying the tool."}],"source":{"kind":"user"},"role":"user","id":"1c8e6b4f-3d27-4a91-b5c8-9e4f7a2d6c04"},"surfaceOp":"append"} +{"type":"assistant/chunk","seq":24,"time":1786348800030,"data":{"turn":2,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"text"}}} +{"type":"assistant/chunk","seq":25,"time":1786348800031,"data":{"turn":2,"step":1,"chunk":{"type":"text-delta","index":0,"text":"The previous reply hit the output limit while a tool call was still streaming, so that call was discarded and no tool ran."}}} +{"type":"assistant/chunk","seq":26,"time":1786348800032,"data":{"turn":2,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"The previous reply hit the output limit while a tool call was still streaming, so that call was discarded and no tool ran."}}}} +{"type":"assistant/chunk","seq":27,"time":1786348800033,"data":{"turn":2,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":64,"outputTokens":28}}}} +{"type":"assistant/chunk","seq":28,"time":1786348800034,"data":{"turn":2,"step":1,"chunk":{"type":"finish","reason":{"kind":"stop"}}}} +{"type":"assistant/message","seq":29,"time":1786348800034,"data":{"turn":2,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"The previous reply hit the output limit while a tool call was still streaming, so that call was discarded and no tool ran."}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"7e3d9f6b-5a18-4c72-9b4e-1f8c6d2a7e05"},"usage":{"inputTokens":64,"outputTokens":28}},"sourceEventSeqs":[24,25,26,27,28],"surfaceOp":"append"} +{"type":"step/end","seq":30,"time":1786348800034,"data":{"turn":2,"step":1}} +{"type":"turn/end","seq":31,"time":1786348800034,"data":{"turn":2,"reason":{"kind":"completed"}}} diff --git a/examples/acp-agent/tests/snapshots/max-tokens-continue/stdout.expected.jsonl b/examples/acp-agent/tests/snapshots/max-tokens-continue/stdout.expected.jsonl new file mode 100644 index 0000000000..bf555a8d1c --- /dev/null +++ b/examples/acp-agent/tests/snapshots/max-tokens-continue/stdout.expected.jsonl @@ -0,0 +1,6 @@ +{"jsonrpc":"2.0","id":1,"result":{"protocolVersion":1,"agentInfo":{"name":"deepseek-harness-acp","version":"0.0.1"},"agentCapabilities":{"promptCapabilities":{"image":false,"audio":false,"embeddedContext":false}},"authMethods":[]}} +{"jsonrpc":"2.0","id":2,"result":{"sessionId":"{{sessionId}}"}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"Starting the write now."}}}} +{"jsonrpc":"2.0","id":3,"result":{"stopReason":"end_turn"}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"The previous reply hit the output limit while a tool call was still streaming, so that call was discarded and no tool ran."}}}} +{"jsonrpc":"2.0","id":4,"result":{"stopReason":"end_turn"}} diff --git a/examples/acp-agent/tests/snapshots/product-subagent-both/tool-schemas.expected.json b/examples/acp-agent/tests/snapshots/product-subagent-both/tool-schemas.expected.json index 5c65ede244..e668036737 100644 --- a/examples/acp-agent/tests/snapshots/product-subagent-both/tool-schemas.expected.json +++ b/examples/acp-agent/tests/snapshots/product-subagent-both/tool-schemas.expected.json @@ -308,7 +308,7 @@ }, { "name": "subagent_claude_code", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. Give it a complete, standalone prompt: it does not see this conversation. This call waits for the subagent and returns its result.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. Give it a complete, standalone prompt: it does not see this conversation. This call waits for the result by default. Set `run_in_background: true` to return a job id; collect with `job_output` and stop with `job_kill`.", "parameters": { "type": "object", "properties": { @@ -319,6 +319,10 @@ "prompt": { "type": "string", "description": "The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs." + }, + "run_in_background": { + "type": "boolean", + "description": "Whether to run as a background job and return its id. Defaults to false; collect with job_output or stop with job_kill." } }, "required": [ @@ -329,7 +333,7 @@ }, { "name": "subagent_codex", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. Give it a complete, standalone prompt: it does not see this conversation. This call waits for the subagent and returns its result.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. Give it a complete, standalone prompt: it does not see this conversation. This call waits for the result by default. Set `run_in_background: true` to return a job id; collect with `job_output` and stop with `job_kill`.", "parameters": { "type": "object", "properties": { @@ -340,6 +344,10 @@ "prompt": { "type": "string", "description": "The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs." + }, + "run_in_background": { + "type": "boolean", + "description": "Whether to run as a background job and return its id. Defaults to false; collect with job_output or stop with job_kill." } }, "required": [ diff --git a/examples/acp-agent/tests/snapshots/product-subagent-codex/tool-schemas.expected.json b/examples/acp-agent/tests/snapshots/product-subagent-codex/tool-schemas.expected.json index 4310ffd76e..29a85eb6b3 100644 --- a/examples/acp-agent/tests/snapshots/product-subagent-codex/tool-schemas.expected.json +++ b/examples/acp-agent/tests/snapshots/product-subagent-codex/tool-schemas.expected.json @@ -308,7 +308,7 @@ }, { "name": "subagent_codex", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. Give it a complete, standalone prompt: it does not see this conversation. This call waits for the subagent and returns its result.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. Give it a complete, standalone prompt: it does not see this conversation. This call waits for the result by default. Set `run_in_background: true` to return a job id; collect with `job_output` and stop with `job_kill`.", "parameters": { "type": "object", "properties": { @@ -319,6 +319,10 @@ "prompt": { "type": "string", "description": "The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs." + }, + "run_in_background": { + "type": "boolean", + "description": "Whether to run as a background job and return its id. Defaults to false; collect with job_output or stop with job_kill." } }, "required": [ diff --git a/examples/headless-agent/cordis.yml b/examples/headless-agent/cordis.yml index bb75f55b98..6dcde61110 100644 --- a/examples/headless-agent/cordis.yml +++ b/examples/headless-agent/cordis.yml @@ -120,7 +120,8 @@ # Fork stays one-shot because a continuable child's `report` tool and prompt # section precede the inherited history a fork reuses; `run_in_background` is off -# because this example mounts no task service. See .agents/notes/implemented/architecture/2026-08-10-fork-children-stay-one-shot.md. +# as an explicit foreground-only choice even though agent-spine-demo mounts the +# generic Job runtime. See .agents/notes/implemented/architecture/2026-08-10-fork-children-stay-one-shot.md. - id: tool-subagent-fork name: '@deepseek-ai/dsh-tool-subagent' config: diff --git a/examples/headless-agent/tests/fixtures/deepseek-defaults.cordis.yml b/examples/headless-agent/tests/fixtures/deepseek-defaults.cordis.yml index fab8ae1b7b..7f1c0b3e9e 100644 --- a/examples/headless-agent/tests/fixtures/deepseek-defaults.cordis.yml +++ b/examples/headless-agent/tests/fixtures/deepseek-defaults.cordis.yml @@ -6,7 +6,8 @@ - id: llm-deepseek config: baseURL: !!js process.env.DSH_SNAPSHOT_BASE_URL - thinking: disabled + thinking: enabled + reasoningEffort: low streamIdleTimeoutMs: 150 - id: agent-spine config: diff --git a/examples/headless-agent/tests/headless.snapshot.ts b/examples/headless-agent/tests/headless.snapshot.ts index 4f2eb28d40..d22a48a7ab 100644 --- a/examples/headless-agent/tests/headless.snapshot.ts +++ b/examples/headless-agent/tests/headless.snapshot.ts @@ -541,6 +541,7 @@ describe('headless stream-json snapshots', () => { expect(result.stderr).toBe('') expect(server.requests).toHaveLength(1) expect(server.requests[0]?.max_tokens).toBe(256_000) + expect(server.requests[0]?.reasoning_effort).toBe('low') const header = (parseJsonl(result.stdout) .map(record => record.event) .find((event): event is JsonObject => ( @@ -555,7 +556,7 @@ describe('headless stream-json snapshots', () => { "maxTokens": 256000, "model": "deepseek-v4-flash", "provider": "deepseek-official", - "reasoningEffort": "off", + "reasoningEffort": "low", } `) expect(header?.adapterDefaults).toEqual({ diff --git a/examples/headless-agent/tests/snapshots/advanced-toolchain/session.1.jsonl b/examples/headless-agent/tests/snapshots/advanced-toolchain/session.1.jsonl index dfe9a23a15..8fb937dee2 100644 --- a/examples/headless-agent/tests/snapshots/advanced-toolchain/session.1.jsonl +++ b/examples/headless-agent/tests/snapshots/advanced-toolchain/session.1.jsonl @@ -1,19 +1,19 @@ {"type":"session","version":0,"id":"22222222-2222-4222-8222-222222222222","createdAt":1783950001000,"cwd":"{{cwd}}","parentSession":"11111111-1111-4111-8111-111111111111","origin":"subagent","delegationDepth":1} -{"type":"agent/inbox/spliced","seq":0,"time":1785498583877,"data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply with exactly DIRECT_CHILD_OK and nothing else."}],"source":{"kind":"user"},"role":"user","id":"77f5992c-b7ed-4453-96de-83c51b1e8041"}]}} +{"type":"agent/inbox/spliced","seq":0,"time":1785498583877,"data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply with exactly DIRECT_CHILD_OK and nothing else."}],"source":{"kind":"user"},"role":"user","id":"c66e310e-2597-4d01-85c8-2d70a9d831c0"}]}} {"type":"turn/start","seq":1,"time":1785821454445,"data":{"turn":1}} {"type":"agent/inbox/spliced","seq":2,"time":1785821454445,"data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"subagent/descriptor","seq":3,"time":1785821454466,"data":{"version":2,"mode":"one-shot","provider":"spawn","label":"Check direct child"}} {"type":"step/start","seq":4,"time":1785730501506,"data":{"turn":1,"step":1}} -{"type":"user/message","seq":5,"time":1785730501506,"data":{"content":[{"type":"text","text":"Reply with exactly DIRECT_CHILD_OK and nothing else."}],"source":{"kind":"user"},"role":"user","id":"77f5992c-b7ed-4453-96de-83c51b1e8041"},"surfaceOp":"append"} -{"type":"user/message","seq":6,"time":1786373992181,"data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}],"source":{"kind":"plugin","plugin":"@deepseek-ai/dsh-system-prompt","form":"snapshot","sections":[{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}]},"role":"user","id":"16344357-da11-40dc-a87f-b390a2c9686d"},"surfaceOp":"append"} +{"type":"user/message","seq":5,"time":1785730501506,"data":{"content":[{"type":"text","text":"Reply with exactly DIRECT_CHILD_OK and nothing else."}],"source":{"kind":"user"},"role":"user","id":"c66e310e-2597-4d01-85c8-2d70a9d831c0"},"surfaceOp":"append"} +{"type":"user/message","seq":6,"time":1786373992181,"data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}],"source":{"kind":"plugin","plugin":"@deepseek-ai/dsh-system-prompt","form":"snapshot","sections":[{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}]},"role":"user","id":"fd0a0587-8df4-46b2-809a-317346a4c0f4"},"surfaceOp":"append"} {"type":"session/title","seq":7,"time":1786373992181,"data":{"title":"Reply with exactly DIRECT_CHILD_OK and","messageSeqs":[5],"source":{"kind":"fallback"}}} -{"type":"request/header","seq":8,"time":1785498583897,"data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"system":"You are an AI agent powered by DeepSeek Harness.\n\nYou are headless-agent, a coding assistant powered by the deepseek-v4-flash model. Your working directory is {{cwd}}.\n\nVerify your work by running the code or tests. Keep answers brief and factual.\n\n\nUse the read tool — not shell commands like cat — to inspect text files. Results include line numbers. Use offset and limit to continue reading large files.\n\nUse the write tool to create files or completely replace file contents. Existing files are overwritten, so read an existing file first (the default fs-observation-policy requires it) and prefer edit for targeted changes.\n\nUse the edit tool for targeted changes to existing UTF-8 text files. It replaces literal old_string with new_string; by default old_string must appear exactly once. If old_string appears multiple times, provide a more specific old_string or set replace_all to true. Read the file first (the default fs-observation-policy requires it), unless you just created or edited it in this session.\n\nCheck the [exit code: N] marker on every bash result; investigate failures before moving on.\n\nTrack every background job id you start. You are notified in-session when a job finishes — do not busy-poll or sleep on one; keep working on independent steps and do not duplicate a running job's work. Before giving a final answer, collect every still-relevant job with job_output (set wait: true only when you are genuinely blocked on it), and job_kill jobs that stopped mattering.\n\nUse the workflow tool ONLY when the user explicitly asks for a workflow or for large multi-agent orchestration: you write a JavaScript script (the tool description documents the exact format) that fans work out across many subagents with phases and structured results. For one or two delegations, prefer plain subagent calls.\n\n# Dynamic Cordis Plugins\n\nDynamic Cordis plugins temporarily extend the current DSH process. A Plugin uses apply(ctx) to consume Services, listen to Events, provide Services, register model Tools, or register browser UI in Slots.\n\n- Plugin and Package definitions exist only in the current process. define itself does not modify repository source, configuration, or disk, and definitions do not survive a process restart.\n- The restricted execution environment prevents accidental misuse; it is not a security boundary for malicious code. Services obtained by dynamic code connect to the real runtime.\n\n## Make the user-facing plan clear first\n\n- Dynamic Cordis Plugins are one available implementation mechanism, not the default for every request. Consider whether one could help only when the user intends to design or create something, or when a temporary interface could materially aid the current work. The presence of these instructions or Tools, and discussion of Cordis itself, do not make a request a dynamic-Plugin task.\n- When Cordis is a plausible fit, infer the intended work target and lifetime from the request and conversation. Use it only when the outcome belongs to the current running harness and should be delivered as a temporary runtime extension. If that distinction is materially ambiguous, ask at most one concise question about the intended result or lifetime. Otherwise proceed with the matching workflow; do not require the user to know or choose Cordis as an implementation mechanism.\n- Once a dynamic Plugin is appropriate, decide whether the task creates a new Plugin or modifies the Plugin named by the user with @pluginId. Proceed directly when the goal is clear; do not ask for repeated confirmation.\n- Choose Host, Client, or both from the requested outcome. Do not propose a Client/browser UI when the task does not need visible page behavior, and do not avoid Client when the requested outcome is visual, interactive, or depends on page state. Host versus Client is an implementation choice; do not make the user choose it.\n- When a design direction or a potentially useful interface would materially affect the result, ask at most one concise outcome or creative-preference question and offer a few candidate directions. Otherwise proceed directly; do not conduct a multi-round interview or a complex questionnaire.\n- cordis_define only defines and presents code; it does not run it. After definition, explain the pluginId and packageId returned by the Host and whether the next step is a run or update.\n- cordis_run may require user approval. When it returns awaiting-approval, explain that the user must allow or reject it in the UI. Do not wait, retry, or claim that it is running.\n- When it returns starting, explain that the request has entered the asynchronous flow and the Client is still activating. starting does not mean success. Wait for the system to report the final result through steering context.\n- Do not request approval again after the user rejects it. After a technical failure, fix the same Plugin from its diagnostics; do not silently create a replacement Plugin.\n\n## Recommended workflow and Tools\n\nBefore creating, modifying, or repairing a Plugin, load the cordis-plugin-development Skill. The Skill provides requirement navigation, capability composition, complete examples, and troubleshooting. Treat Inspect Provider results as the source of truth for exact APIs.\n\n1. cordis_inspect_list: discover the current Host and Client Providers and their read-only query methods.\n2. cordis_inspect_query: use the returned platform, provider, method, and schema to query exact Service, Event, Builtin, Slot, Theme token, or Tool information.\n3. cordis_inspect_self: inspect the current Session's Plugins, Packages, version pointers, source, and diagnostics. Source is returned only when both pluginId and packageId are specified.\n4. cordis_define: create the first Package for a new Plugin or append an immutable Package to an existing Plugin. It defines code but does not run it.\n5. cordis_run: activate an exact Package. Use run for the first activation, restarting current, or rollback; use update to switch versions.\n6. cordis_stop: remove the current Run and pending approval request while retaining definitions, grants, and version pointers.\n7. cordis_undefine: permanently stop and delete a Plugin and all of its Packages. Use it only after confirming that the user no longer needs them.\n\n- Inspect and Catalog data only confirm capabilities, names, signatures, types, and registration protocols before code is written; they do not replace business APIs.\n- Query Service.listService and Event.listEvents without input to choose from their compact signature directories, then query the exact service or event before using it. Exact queries return the structured contract and only its referenced types.\n- At runtime, a Plugin must call real Services or listen to real Events. Do not cache, display, or depend on Inspect results as business data.\n\n## Identity, versions, and approval\n\n- pluginId identifies a Plugin that can be modified over time. For a new Plugin, submit only a semantic idPrefix of 3–6 lowercase English letters; the Host allocates the final ID.\n- packageId identifies one immutable Host/Client source version under a Plugin. To change code, define a new Package; never overwrite an old version.\n- pluginRunId identifies one activation attempt and connects its approval, Host/Client loading, private RPC, Run card, and errors.\n- currentPackageId is the most recent fully successful Package. Stopping, starting an update, or failing an update does not clear it.\n- nextPackageId is the target awaiting approval, being attempted, awaiting Client activation, or most recently failed.\n- A single check mark authorizes only the current Package; double check marks authorize future versions of the same Plugin. A grant remains in effect after a technical failure.\n- An update stops the old Run before starting the target Package. Failure does not automatically restart the old version; retry next with update or roll back to current with run.\n\nWhen the user enters @pluginId, the system injects identity, the default base Package, version pointers, and runtime status, but not source code:\n\n1. Call cordis_inspect_self(pluginId, packageId) to read the target source.\n2. Use cordis_define in existing mode to append a Package to the same Plugin.\n3. Call cordis_run in run or update mode according to the version relationship.\n\nNever silently create another Plugin for @pluginId. If the reference is unavailable because it was removed, belongs to another Session, or was lost on process restart, tell the user directly.\n\n## High-frequency errors that must be avoided\n\n### Services: ctx.get and inject\n\n- Read an optional Service with ctx.get('serviceName') by default and handle undefined.\n- Declare inject: ['serviceName'] on the returned Plugin object only when the Service is a hard dependency and the Plugin must enter waiting until Cordis reactivates it after the Service appears.\n- Read ctx.serviceName only after declaring that Service in inject. Never access an undeclared Service as a ctx property.\n\n```js\nreturn {\n inject: ['requiredService'],\n apply(ctx) {\n ctx.requiredService.someMethod()\n const optionalService = ctx.get('optionalService')\n if (optionalService !== undefined) optionalService.someMethod()\n },\n}\n```\n\n### Code: use plain JavaScript only\n\n- Host and Client code is not transformed by TypeScript, JSX, or a bundler.\n- Do not use TypeScript types, as, decorators, import, require, or JSX.\n- Client React code must use React.createElement(...); never write .\n- Do not assume that process, Buffer, window, document, fetch, native timers, or any other global is available. Query the corresponding platform's Builtins and Services first.\n\n### Data: do not serialize live data\n\n- Services, Events, Slots, Sessions, and their derived Cordis/DSH objects are internal live data, not ordinary JSON that can be dumped.\n- Do not apply JSON.stringify, structuredClone, recursive enumeration, full copying, or whole-object display to live data.\n- Read only the leaf fields required by the task, then construct the smallest owned data object without Host references.\n\n### Lifecycle: every side effect must be reversible\n\n- Services, Events, Tools, handlers, timers, Slots, styles, and theme overrides must all belong to the current Fiber.\n- Use ctx.effect(), ctx.on(), or official APIs that return a disposer so stop, update, or undefine removes every side effect.\n- The cordis-plugin-development Skill contains complete timer, Waterfall, Slot, theme, Tool, RPC, and React examples and troubleshooting guidance.\n\n## Host and Client\n\n- Host runs in the DSH Node.js process and is appropriate for files, networking, commands, Agent/Session access, Host Events, Services, model Tools, and JSON methods callable by the Client.\n- Client runs in the browser page and is appropriate for themes, layout, current page state, Tool cards, and Slot UI.\n- Host and Client communicate through Package-private JSON methods: Host uses harness.handle(method, handler), and Client uses host.call(method, args). The direction is Client→Host, and only lossless JSON may cross it.\n- Client UI must be registered in a queried Slot; apply() cannot directly return a React Element. Query Slots.listSubTree without root to choose from the compact purpose/topology tree, then query the exact root for its full registration contract and props before writing code.\n- See the Skill and Inspect Providers for Run-specific panels and exact Slot registration patterns.\n\n## Asynchronous results and recovery\n\n- Do not wait inside a Tool for approval or browser work that can happen only after the current turn ends.\n- Asynchronous success, rejection, and runtime errors update Run state and notify you through steering context.\n- After a technical failure, use cordis_inspect_self to read the exact Package source and its message/stack. Define a corrected Package under the same Plugin and retry autonomously.\n- Use the cordis-plugin-development Skill for other failure causes, repair procedures, and complete extension patterns.\n\nUse the ralph tool ONLY when the direct human explicitly asks for a Ralph loop or fresh-agent iterative execution. Each Ralph round starts a fresh child with no conversation seed and uses the shared workspace as durable memory. Completion and blockers are worker reports, not independent evaluation. Use same-session goal tools for ordinary long-running objectives, and plain subagents or workflows for bounded delegation and fan-out.\n\nUse subagent in the background by default. Start independent delegations together in one assistant message and continue useful work while they run. Set `run_in_background: false` only when your next action depends on that subagent's result. When a background run settles, the runtime sends you a notice containing its outcome and any final assistant message.\n\n## Writing code for run_code\n\nPass `run_code` the body of an async TypeScript function (erasable syntax only — no `enum` or namespaces; type annotations are advisory, the code runs type-stripped). Inside the program:\n\n- Call tools as `await tools.name(args)` — quoted access for exotic names: `tools[\"my-tool\"](args)`. Every call resolves to the tool's typed canonical JSON value. Tool arguments must be lossless JSON.\n- A FAILED tool call rejects with `ToolCallError`, whose `toolName` identifies the failed tool and whose `message` is human-readable — `try/catch` it to handle and continue.\n- Independent read-only calls MAY overlap under `Promise.all` (safe calls run concurrently; mutating calls run alone, in submission order). Sequence dependent work with `await`.\n- Emit results with `return` and/or `console.log(...)`. ONLY what you print or return comes back to you — intermediate tool results never enter the conversation, so extract just what you need.\n\nThe available tools:\n\n```ts\ntype JsonValue = null | boolean | number | string | JsonValue[] | { [key: string]: JsonValue }\n\ninterface ToolArgsMap {\n /** Execute a bash command (`bash -c`) and return its stdout/stderr. Each call runs in a fresh shell: no state (cwd, variables, functions) persists between calls — pass `workdir` instead of using `cd`. Non-zero exits are reported as `[exit code: N]`. Current harness environment facts are exposed through managed `$DSH_*` variables; inspect them when needed. Commands may run under a file sandbox; a blocked file operation is reported as `[sandbox: file access denied under mode]` — a policy denial, not a bug in the command; do not retry another way. Long output is truncated to its tail; the full output is saved to a file whose path is reported when available. Set `run_in_background: true` for long-running commands: the call returns a job id immediately; read its output with `job_output` and stop it with `job_kill`. */\n bash: {\n /** The bash command to execute. */\n command: string;\n /** Clear, concise description of what this command does in active voice, 5-10 words (shown in the UI). Examples: \"ls\" → \"List files in current directory\"; \"git status\" → \"Show working tree status\"; \"npm install\" → \"Install package dependencies\". */\n description: string;\n /** Timeout in milliseconds. The executor applies its configured default and cap, and kills the command on expiry. */\n timeoutMs?: number;\n /** Working directory for this command. Defaults to the session workspace; a relative path is resolved against it. */\n workdir?: string;\n /** Run in the background and return a job id immediately (collect with job_output, stop with job_kill). No timeout applies. */\n run_in_background?: boolean;\n } & Record;\n /** Define an immutable Cordis Package. For a new Plugin, use kind:\"new\" and provide only a semantic prefix of 3–6 lowercase English letters; the Host returns the final pluginId and packageId. To modify an existing Plugin, use kind:\"existing\" with its exact pluginId to append a Package without overwriting older versions. Provide at least one of code.host and code.client. Each value is a plain JavaScript function body that returns a Cordis Plugin; no TypeScript, JSX, or import transformation occurs. Query Inspect before depending on a Service, Event, Builtin, Slot, or token. Define only validates parameters and syntax and records source: it does not request approval, execute apply, or change currentPackageId. On success, call cordis_run with the returned IDs. */\n cordis_define: {\n plugin: {\n kind: \"new\";\n /** Suggested semantic prefix of 3–6 lowercase English letters; the Host adds a unique numeric suffix. */\n idPrefix: string;\n } | {\n kind: \"existing\";\n /** Exact ID of an existing Plugin; the new Package is appended to that instance. */\n pluginId: string;\n };\n /** Short, readable Package name. */\n name: string;\n /** One-sentence, user-facing description of the Package purpose. */\n purpose: string;\n code: {\n /** Plain JavaScript function body that returns the Host-half Cordis Plugin. */\n host?: string;\n /** Plain JavaScript function body that returns the browser Client-half Cordis Plugin. */\n client?: string;\n };\n } & Record;\n /** List every Cordis Inspect Provider currently known to the Host, including local Host Providers and the latest manifests synchronized from the Client. Each entry includes its platform, purpose, read-only methods, and input/output schemas. Call this Tool before creating or modifying a Package, then select the provider and method for cordis_inspect_query from its result. Do not guess names or treat an Inspect method as a business Service that Plugin code can call. */\n cordis_inspect_list: Record;\n /** Run a read-only query explicitly declared by an Inspect Provider. platform, provider, and method must come from cordis_inspect_list, and input must satisfy that method's schema. Use this Tool before cordis_define to read exact Service methods, Event modes, Builtin signatures, Tool schemas, theme tokens, or live Slot trees and props. Host queries run locally. A Client query waits for the first valid page response and remains pending until a page answers or the Tool is cancelled. This Tool cannot invoke business Service methods or modify the runtime. For Service.listService and Event.listEvents, query without input to navigate the compact signature directory, then query the exact service or event for its structured contract and referenced types. For Slots.listSubTree, query without root to navigate the compact tree, then query the exact root for its complete registration contract and props. */\n cordis_inspect_query: {\n /** Runtime platform that owns the Provider. */\n platform: \"host\" | \"client\";\n /** Exact Provider ID returned by cordis_inspect_list. */\n provider: string;\n /** Exact method name declared by the Provider manifest. */\n method: string;\n /** Optional query input; it must satisfy the method input schema. */\n input?: JsonValue;\n } & Record;\n /** Inspect dynamic Cordis objects owned by the current Session at increasing levels of detail. With no IDs, list only Plugin summaries. With pluginId alone, return version pointers, the latest Run, and every Package summary. Only pluginId plus packageId returns that immutable Package's Host/Client source and runtime diagnostics. packageId cannot be supplied alone. Query an exact Package before handling @pluginId, repairing an asynchronous failure, or defining an updated version. This Tool is read-only: it neither executes code nor changes version pointers. */\n cordis_inspect_self: {\n /** Stable Plugin ID returned by cordis_define or injected by @pluginId; omit it to list every current Plugin. */\n pluginId?: string;\n /** Exact immutable Package ID owned by pluginId; when specified, source and diagnostics are returned. */\n packageId?: string;\n } & Record;\n /** Activate one exact Package of a dynamic Plugin. Use mode:\"run\" for the first activation, restarting currentPackageId, or rollback. When current exists, use mode:\"update\" to switch to a different Package, even if the Plugin is currently stopped. An unauthorized Client Package creates an approval request and returns awaiting-approval; an authorized Package returns starting and continues asynchronously in the browser. Neither result waits for the final outcome inside the Tool. currentPackageId changes only after complete success; on failure, the old current and target next remain. Asynchronous success, rejection, or technical failure is reported through state and steering. After a technical failure, read diagnostics with cordis_inspect_self, correct the same Plugin, and retry autonomously. Do not request approval again after the user rejects it. */\n cordis_run: {\n /** Stable Plugin ID returned by cordis_define. */\n pluginId: string;\n /** Exact immutable Package ID to activate under that Plugin. */\n packageId: string;\n /** Use run for the first activation, restarting current, or rollback; use update to switch from current to a different Package. */\n mode: \"run\" | \"update\";\n } & Record;\n /** Stop the current Run of a dynamic Plugin and cancel unfinished approval or activation requests. Retain the Plugin, every immutable Package, grants, currentPackageId, and nextPackageId so it can later run or update directly. Stopping an already stopped Plugin succeeds idempotently. Use this Tool to disable effects temporarily; use cordis_undefine for permanent removal. */\n cordis_stop: {\n /** Stable dynamic Plugin ID to stop. */\n pluginId: string;\n } & Record;\n /** Permanently remove a dynamic Plugin owned by the current Session. If it is running or awaiting approval, first stop it and cancel the request, then delete every Package, grant, and version pointer. After this returns, its pluginId, packageIds, @ reference, and Package business views are invalid; historical cards retain only a \"Plugin removed\" record. Do not call this Tool when versions must remain available for restart or rollback; use cordis_stop instead. */\n cordis_undefine: {\n /** Stable dynamic Plugin ID to remove permanently. */\n pluginId: string;\n } & Record;\n /** Edit an existing UTF-8 text file by replacing literal text. */\n edit: {\n /** Path to edit, resolved by the filesystem backend. */\n file_path: string;\n /** Literal text to replace. Must match exactly. */\n old_string: string;\n /** Literal replacement text. Use an empty string to delete the match. */\n new_string: string;\n /** Replace all matches. Defaults to false; when false, old_string must appear exactly once. */\n replace_all?: boolean;\n } & Record;\n /** Request cancellation of a background agent's current turn by its agent id. The target may be your direct child or a deeper agent created under you. Only the current turn stops: messages already queued for the agent stay parked until a later send_message, agents it started keep running, and the agent itself stays available for follow-ups. This call returns as soon as the stop request is accepted, so the target may keep running briefly; interrupting an agent that already finished is an accepted no-op. */\n interrupt_agent: {\n /** The agent id of the running agent to interrupt. */\n agent_id: string;\n } & Record;\n /** Request cancellation of a running background job by job id. Returns immediately; the job settles as killed once its work actually stops. */\n job_kill: {\n /** Job id returned by the tool that started the background work. */\n job_id: string;\n /** Optional short reason, recorded in the log and forwarded to the job. */\n reason?: string;\n } & Record;\n /** List your background jobs (running and finished) with their ids, kinds, and statuses. */\n job_list: Record;\n /** Read a background job. Stream jobs return only output since the previous read; final-output jobs return their result after settlement. Every response ends with `[status: ...]`. Reads are non-blocking unless `wait: true`, which waits up to the configured cap. */\n job_output: {\n /** Job id returned by the tool that started the background work. */\n job_id: string;\n /** Block until the job reaches a terminal status or the timeout expires. A timed-out wait returns [status: running] and leaves the job alive. */\n wait?: boolean;\n /** Max wait in milliseconds (only meaningful with wait: true). Defaults to the configured wait timeout; capped by the configured maximum. */\n timeout_ms?: number;\n } & Record;\n /** Run a foreground fresh-agent Ralph loop toward one immutable objective. Use only when the direct human explicitly asks for Ralph or fresh-agent iteration. Each round opens a new child with no parent conversation or prior child session; the shared workspace is long-term memory, and only a bounded structured report crosses rounds. The call returns when a worker reports completion or a concrete blocker, or at the round limit. Ordinary long-running same-session work belongs to goal tools. */\n ralph: {\n /** The immutable completion objective for every fresh Ralph round. */\n objective: string;\n /** Optional positive safe-integer round cap, bounded by the deployment ceiling. */\n maxRounds?: number;\n } & Record;\n /** Read a UTF-8 text file and return line-numbered content. */\n read: {\n /** Path to read, resolved by the filesystem backend. */\n file_path: string;\n /** 1-based first line to return. Defaults to 1. */\n offset?: number;\n /** Maximum number of lines to return. Defaults to 2000. */\n limit?: number;\n } & Record;\n /** Send a message to a background subagent by its subagent id, continuing the same conversation. It becomes the subagent's next turn: if it is still working, the message waits until its current turn finishes, so it cannot redirect work already underway. This call returns no answer from the subagent — only confirmation that the message was delivered — so use it to give it more work. A failure means the message was NOT delivered. */\n send_message: {\n /** The subagent id returned when the background subagent was started. */\n subagent_id: string;\n /** The message to deliver to the subagent. */\n message: string;\n } & Record;\n /** Load the full instructions for an available skill. Call this with the exact skill name from the session skill catalog before acting on a task that names or clearly matches that skill. */\n skill: {\n /** The exact skill name from the available skills list. */\n name: string;\n } & Record;\n /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. Give it a complete, standalone prompt: it does not see this conversation. This tool runs in the background by default, immediately returns a durable subagent id, and keeps the child conversation available for later turns. When that run settles, the runtime sends the parent a notice containing its outcome and any final assistant message; `send_message` starts a later turn in the same child conversation. Set `run_in_background: false` only when your next action depends on receiving the result. */\n subagent: {\n /** A short (3-5 word) description of the delegated task, for display. */\n description: string;\n /** The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs. */\n prompt: string;\n /** Whether to run in the background and return a durable subagent id immediately. Defaults to true. Set false to wait for the result when your next action depends on it. */\n run_in_background?: boolean;\n } & Record;\n /** Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This call waits for the subagent and returns its result. */\n subagent_fork: {\n /** A short (3-5 word) description of the delegated task, for display. */\n description: string;\n /** The task for the subagent. It already sees this conversation's completed turns, so build on them freely and state only what is new. */\n prompt: string;\n } & Record;\n /** Record and update a structured task list for the current work. Send the ENTIRE list every call — it REPLACES the previous list (there are no partial updates, no per-item edits). Use it to plan multi-step work and show progress: add one todo per concrete step before you start. Mark every todo being actively worked on `in_progress` — several at once when work genuinely runs in parallel (e.g. concurrent subagents or background commands), one for sequential work; while work remains, at least one task should be `in_progress`. Mark a todo `completed` the moment it is done (do not batch completions), and allow no `in_progress` item only once all work is complete. Skip the list for trivial single-step tasks. Statuses: `pending` (not started), `in_progress` (being worked on now), `completed` (finished). */\n todo_write: {\n /** The COMPLETE task list, replacing any previous list. */\n todos: ({\n /** What the task is — a short imperative line. */\n content: string;\n /** pending (not started) | in_progress (now) | completed (done). */\n status: \"pending\" | \"in_progress\" | \"completed\";\n })[];\n } & Record;\n /** Run a JavaScript workflow script that orchestrates subagents at scale. Use this for work that fans out across many independent pieces — an audit over many files, a migration, multi-angle research, adversarial verification of findings — where you write the orchestration as a script instead of delegating turn by turn. The workflow's identity rides the `meta` parameter as JSON: required `name` (short kebab-case) and `description` strings, optional `whenToUse` string and `phases` array (`{title, detail?, provider?, model?}`). The `script` parameter is the plain JavaScript body ONLY (NOT TypeScript, and NO `export const meta` statement — meta is a parameter, not code), running with top-level await; end with `return ` — the value must be JSON-serializable and is this tool's result. Script-body hooks: - `agent(prompt, opts?): Promise` — run one subagent to completion. Without `opts.schema` it resolves to the child's final text; with `opts.schema` (an object-rooted JSON Schema using ONLY type/properties/required/additionalProperties/items/enum/const/oneOf — no pattern/format/numeric bounds) it resolves to the validated object. Resolves `null` when the child fails (filter with `.filter(Boolean)`). Other opts: `label` (display), `phase` (progress group), and independent `provider`/`model` LLM target overrides (either may be provided alone). Anything else (`effort`/`isolation`/`agentType`) is rejected loudly. - `pipeline(items, ...stages): Promise` — run each item through the stages independently with NO barrier between stages (prefer this for multi-stage work). Each stage receives `(prev, item, index)`. An ordinary stage throw drops that ITEM to `null` and skips its remaining stages. - `parallel(thunks): Promise` — run zero-argument functions concurrently and await ALL of them (a barrier; use only when a stage genuinely needs every prior result together). A throwing thunk resolves to `null`. - `phase(title)` — start a progress phase; `log(message)` — narrate progress; `args` — the tool call's `args` input, verbatim. Misused hooks (bad arguments, unknown options, unsupported schemas, tripped caps) throw errors that ALWAYS kill the script — they never dissolve into a per-item `null`. Constraints: concurrency and total-agent caps apply; no filesystem, network, timers, or Node.js APIs are provided — the agents do the work, the script only coordinates them. The run executes in the foreground: this call returns when the whole script finishes. */\n workflow: {\n /** The plain-JS workflow script body (top-level await allowed; NO `export const meta` statement; end with `return `). */\n script: string;\n /** The workflow identity block (plain JSON — never code). */\n meta: {\n /** Short kebab-case workflow name. */\n name: string;\n /** One-line description of what the workflow does. */\n description: string;\n /** Optional guidance on when this workflow applies. */\n whenToUse?: string;\n /** Optional phase declarations matched by phase() calls. */\n phases?: ({\n /** The phase title phase() calls match by exact string. */\n title: string;\n /** Optional one-line description of the phase. */\n detail?: string;\n /** Optional provider override this phase is expected to use. */\n provider?: string;\n /** Optional model override this phase is expected to use. */\n model?: string;\n } & Record)[];\n } & Record;\n /** Optional JSON input exposed to the script as the `args` global (wrap a bare list as a field, e.g. {\"files\": [...]}). */\n args?: Record;\n } & Record;\n /** Create or fully replace a UTF-8 text file. */\n write: {\n /** Path to write, resolved by the filesystem backend. */\n file_path: string;\n /** Full UTF-8 text content to write. */\n content: string;\n } & Record;\n}\n\ninterface ToolOutputMap {\n bash: {\n kind: \"background\";\n jobId: string;\n } | {\n kind: \"foreground\";\n exitCode: number | null;\n signal: string | null;\n timedOut: boolean;\n aborted: boolean;\n timeoutMs: number;\n stdout: {\n text: string;\n truncated: boolean;\n spillPath?: string;\n };\n stderr: {\n text: string;\n truncated: boolean;\n spillPath?: string;\n };\n sandbox?: {\n mode: string;\n denied: boolean;\n enforcement?: string;\n runnerFailed?: boolean;\n };\n };\n cordis_define: {\n pluginId: string;\n packageId: string;\n name: string;\n purpose: string;\n hasHostHalf: boolean;\n hasClientHalf: boolean;\n };\n cordis_inspect_list: JsonValue;\n cordis_inspect_query: JsonValue;\n cordis_inspect_self: JsonValue;\n cordis_run: JsonValue;\n cordis_stop: {\n pluginId: string;\n };\n cordis_undefine: {\n pluginId: string;\n wasRunning: boolean;\n };\n edit: {\n path: string;\n before: string;\n after: string;\n };\n interrupt_agent: {\n accepted: boolean;\n };\n job_kill: {\n outcome: \"cancellation-requested\" | \"already-finished\";\n job: {\n id: string;\n kind: string;\n label: string;\n status: \"running\" | \"stopping\" | \"completed\" | \"killed\" | \"failed\";\n detail?: string;\n startedAt: number;\n finishedAt?: number;\n };\n };\n job_list: ({\n id: string;\n kind: string;\n label: string;\n status: \"running\" | \"stopping\" | \"completed\" | \"killed\" | \"failed\";\n detail?: string;\n startedAt: number;\n finishedAt?: number;\n })[];\n job_output: {\n text: string;\n job: {\n id: string;\n kind: string;\n label: string;\n status: \"running\" | \"stopping\" | \"completed\" | \"killed\" | \"failed\";\n detail?: string;\n startedAt: number;\n finishedAt?: number;\n };\n };\n ralph: {\n runId: string;\n agentsStarted: number;\n result: JsonValue;\n };\n read: {\n path: string;\n offset: number;\n lines: {\n number: number;\n text: string;\n }[];\n totalLines: number;\n };\n send_message: {\n messageId: string;\n };\n skill: {\n name: string;\n provider: string;\n resourceBase?: {\n kind: \"directory\";\n path: string;\n } | {\n kind: \"url\";\n url: string;\n } | {\n kind: \"opaque\";\n description: string;\n };\n content: string;\n };\n subagent: {\n kind: \"background\";\n jobId: string;\n } | {\n kind: \"continuable\";\n subagentId: string;\n } | {\n kind: \"foreground\";\n runId: string;\n output: JsonValue[];\n };\n subagent_fork: {\n kind: \"background\";\n jobId: string;\n } | {\n kind: \"continuable\";\n subagentId: string;\n } | {\n kind: \"foreground\";\n runId: string;\n output: JsonValue[];\n };\n todo_write: {\n todos: ({\n content: string;\n status: \"pending\" | \"in_progress\" | \"completed\";\n })[];\n counts: {\n pending: number;\n inProgress: number;\n completed: number;\n };\n };\n workflow: {\n runId: string;\n agentsStarted: number;\n result: JsonValue;\n };\n write: {\n path: string;\n operation: \"create\" | \"update\";\n before: string | null;\n after: string;\n };\n}\n\ntype ToolName = keyof ToolOutputMap\n\ndeclare class ToolCallError extends Error {\n readonly name: \"ToolCallError\";\n readonly toolName: ToolName;\n}\n\ndeclare const tools: {\n [K in ToolName]: (args: ToolArgsMap[K]) => Promise;\n}\n```","tools":[{"name":"bash","description":"Execute a bash command (`bash -c`) and return its stdout/stderr. Each call runs in a fresh shell: no state (cwd, variables, functions) persists between calls — pass `workdir` instead of using `cd`. Non-zero exits are reported as `[exit code: N]`. Current harness environment facts are exposed through managed `$DSH_*` variables; inspect them when needed. Commands may run under a file sandbox; a blocked file operation is reported as `[sandbox: file access denied under mode]` — a policy denial, not a bug in the command; do not retry another way. Long output is truncated to its tail; the full output is saved to a file whose path is reported when available. Set `run_in_background: true` for long-running commands: the call returns a job id immediately; read its output with `job_output` and stop it with `job_kill`.","parameters":{"type":"object","properties":{"command":{"type":"string","description":"The bash command to execute."},"description":{"type":"string","description":"Clear, concise description of what this command does in active voice, 5-10 words (shown in the UI). Examples: \"ls\" → \"List files in current directory\"; \"git status\" → \"Show working tree status\"; \"npm install\" → \"Install package dependencies\"."},"timeoutMs":{"type":"number","description":"Timeout in milliseconds. The executor applies its configured default and cap, and kills the command on expiry."},"workdir":{"type":"string","description":"Working directory for this command. Defaults to the session workspace; a relative path is resolved against it."},"run_in_background":{"type":"boolean","description":"Run in the background and return a job id immediately (collect with job_output, stop with job_kill). No timeout applies."}},"required":["command","description"]}},{"name":"cordis_define","description":"Define an immutable Cordis Package. For a new Plugin, use kind:\"new\" and provide only a semantic prefix of 3–6 lowercase English letters; the Host returns the final pluginId and packageId. To modify an existing Plugin, use kind:\"existing\" with its exact pluginId to append a Package without overwriting older versions. Provide at least one of code.host and code.client. Each value is a plain JavaScript function body that returns a Cordis Plugin; no TypeScript, JSX, or import transformation occurs. Query Inspect before depending on a Service, Event, Builtin, Slot, or token. Define only validates parameters and syntax and records source: it does not request approval, execute apply, or change currentPackageId. On success, call cordis_run with the returned IDs.","parameters":{"type":"object","properties":{"plugin":{"oneOf":[{"type":"object","additionalProperties":false,"properties":{"kind":{"type":"string","const":"new"},"idPrefix":{"type":"string","description":"Suggested semantic prefix of 3–6 lowercase English letters; the Host adds a unique numeric suffix."}},"required":["kind","idPrefix"]},{"type":"object","additionalProperties":false,"properties":{"kind":{"type":"string","const":"existing"},"pluginId":{"type":"string","description":"Exact ID of an existing Plugin; the new Package is appended to that instance."}},"required":["kind","pluginId"]}]},"name":{"type":"string","description":"Short, readable Package name."},"purpose":{"type":"string","description":"One-sentence, user-facing description of the Package purpose."},"code":{"type":"object","additionalProperties":false,"properties":{"host":{"type":"string","description":"Plain JavaScript function body that returns the Host-half Cordis Plugin."},"client":{"type":"string","description":"Plain JavaScript function body that returns the browser Client-half Cordis Plugin."}}}},"required":["plugin","name","purpose","code"]}},{"name":"cordis_inspect_list","description":"List every Cordis Inspect Provider currently known to the Host, including local Host Providers and the latest manifests synchronized from the Client. Each entry includes its platform, purpose, read-only methods, and input/output schemas. Call this Tool before creating or modifying a Package, then select the provider and method for cordis_inspect_query from its result. Do not guess names or treat an Inspect method as a business Service that Plugin code can call.","parameters":{"type":"object","properties":{}}},{"name":"cordis_inspect_query","description":"Run a read-only query explicitly declared by an Inspect Provider. platform, provider, and method must come from cordis_inspect_list, and input must satisfy that method's schema. Use this Tool before cordis_define to read exact Service methods, Event modes, Builtin signatures, Tool schemas, theme tokens, or live Slot trees and props. Host queries run locally. A Client query waits for the first valid page response and remains pending until a page answers or the Tool is cancelled. This Tool cannot invoke business Service methods or modify the runtime. For Service.listService and Event.listEvents, query without input to navigate the compact signature directory, then query the exact service or event for its structured contract and referenced types. For Slots.listSubTree, query without root to navigate the compact tree, then query the exact root for its complete registration contract and props.","parameters":{"type":"object","properties":{"platform":{"type":"string","description":"Runtime platform that owns the Provider.","enum":["host","client"]},"provider":{"type":"string","description":"Exact Provider ID returned by cordis_inspect_list."},"method":{"type":"string","description":"Exact method name declared by the Provider manifest."},"input":{"description":"Optional query input; it must satisfy the method input schema."}},"required":["platform","provider","method"]}},{"name":"cordis_inspect_self","description":"Inspect dynamic Cordis objects owned by the current Session at increasing levels of detail. With no IDs, list only Plugin summaries. With pluginId alone, return version pointers, the latest Run, and every Package summary. Only pluginId plus packageId returns that immutable Package's Host/Client source and runtime diagnostics. packageId cannot be supplied alone. Query an exact Package before handling @pluginId, repairing an asynchronous failure, or defining an updated version. This Tool is read-only: it neither executes code nor changes version pointers.","parameters":{"type":"object","properties":{"pluginId":{"type":"string","description":"Stable Plugin ID returned by cordis_define or injected by @pluginId; omit it to list every current Plugin."},"packageId":{"type":"string","description":"Exact immutable Package ID owned by pluginId; when specified, source and diagnostics are returned."}}}},{"name":"cordis_run","description":"Activate one exact Package of a dynamic Plugin. Use mode:\"run\" for the first activation, restarting currentPackageId, or rollback. When current exists, use mode:\"update\" to switch to a different Package, even if the Plugin is currently stopped. An unauthorized Client Package creates an approval request and returns awaiting-approval; an authorized Package returns starting and continues asynchronously in the browser. Neither result waits for the final outcome inside the Tool. currentPackageId changes only after complete success; on failure, the old current and target next remain. Asynchronous success, rejection, or technical failure is reported through state and steering. After a technical failure, read diagnostics with cordis_inspect_self, correct the same Plugin, and retry autonomously. Do not request approval again after the user rejects it.","parameters":{"type":"object","properties":{"pluginId":{"type":"string","description":"Stable Plugin ID returned by cordis_define."},"packageId":{"type":"string","description":"Exact immutable Package ID to activate under that Plugin."},"mode":{"type":"string","description":"Use run for the first activation, restarting current, or rollback; use update to switch from current to a different Package.","enum":["run","update"]}},"required":["pluginId","packageId","mode"]}},{"name":"cordis_stop","description":"Stop the current Run of a dynamic Plugin and cancel unfinished approval or activation requests. Retain the Plugin, every immutable Package, grants, currentPackageId, and nextPackageId so it can later run or update directly. Stopping an already stopped Plugin succeeds idempotently. Use this Tool to disable effects temporarily; use cordis_undefine for permanent removal.","parameters":{"type":"object","properties":{"pluginId":{"type":"string","description":"Stable dynamic Plugin ID to stop."}},"required":["pluginId"]}},{"name":"cordis_undefine","description":"Permanently remove a dynamic Plugin owned by the current Session. If it is running or awaiting approval, first stop it and cancel the request, then delete every Package, grant, and version pointer. After this returns, its pluginId, packageIds, @ reference, and Package business views are invalid; historical cards retain only a \"Plugin removed\" record. Do not call this Tool when versions must remain available for restart or rollback; use cordis_stop instead.","parameters":{"type":"object","properties":{"pluginId":{"type":"string","description":"Stable dynamic Plugin ID to remove permanently."}},"required":["pluginId"]}},{"name":"edit","description":"Edit an existing UTF-8 text file by replacing literal text.","parameters":{"type":"object","properties":{"file_path":{"type":"string","description":"Path to edit, resolved by the filesystem backend."},"old_string":{"type":"string","description":"Literal text to replace. Must match exactly."},"new_string":{"type":"string","description":"Literal replacement text. Use an empty string to delete the match."},"replace_all":{"type":"boolean","description":"Replace all matches. Defaults to false; when false, old_string must appear exactly once."}},"required":["file_path","old_string","new_string"]}},{"name":"interrupt_agent","description":"Request cancellation of a background agent's current turn by its agent id. The target may be your direct child or a deeper agent created under you. Only the current turn stops: messages already queued for the agent stay parked until a later send_message, agents it started keep running, and the agent itself stays available for follow-ups. This call returns as soon as the stop request is accepted, so the target may keep running briefly; interrupting an agent that already finished is an accepted no-op.","parameters":{"type":"object","properties":{"agent_id":{"type":"string","description":"The agent id of the running agent to interrupt."}},"required":["agent_id"]}},{"name":"job_kill","description":"Request cancellation of a running background job by job id. Returns immediately; the job settles as killed once its work actually stops.","parameters":{"type":"object","properties":{"job_id":{"type":"string","description":"Job id returned by the tool that started the background work."},"reason":{"type":"string","description":"Optional short reason, recorded in the log and forwarded to the job."}},"required":["job_id"]}},{"name":"job_list","description":"List your background jobs (running and finished) with their ids, kinds, and statuses.","parameters":{"type":"object","properties":{}}},{"name":"job_output","description":"Read a background job. Stream jobs return only output since the previous read; final-output jobs return their result after settlement. Every response ends with `[status: ...]`. Reads are non-blocking unless `wait: true`, which waits up to the configured cap.","parameters":{"type":"object","properties":{"job_id":{"type":"string","description":"Job id returned by the tool that started the background work."},"wait":{"type":"boolean","description":"Block until the job reaches a terminal status or the timeout expires. A timed-out wait returns [status: running] and leaves the job alive."},"timeout_ms":{"type":"number","description":"Max wait in milliseconds (only meaningful with wait: true). Defaults to the configured wait timeout; capped by the configured maximum."}},"required":["job_id"]}},{"name":"ralph","description":"Run a foreground fresh-agent Ralph loop toward one immutable objective. Use only when the direct human explicitly asks for Ralph or fresh-agent iteration. Each round opens a new child with no parent conversation or prior child session; the shared workspace is long-term memory, and only a bounded structured report crosses rounds. The call returns when a worker reports completion or a concrete blocker, or at the round limit. Ordinary long-running same-session work belongs to goal tools.","parameters":{"type":"object","properties":{"objective":{"type":"string","description":"The immutable completion objective for every fresh Ralph round."},"maxRounds":{"type":"number","description":"Optional positive safe-integer round cap, bounded by the deployment ceiling."}},"required":["objective"]}},{"name":"read","description":"Read a UTF-8 text file and return line-numbered content.","parameters":{"type":"object","properties":{"file_path":{"type":"string","description":"Path to read, resolved by the filesystem backend."},"offset":{"type":"number","description":"1-based first line to return. Defaults to 1."},"limit":{"type":"number","description":"Maximum number of lines to return. Defaults to 2000."}},"required":["file_path"]}},{"name":"run_code","description":"Execute a TypeScript program against the available tools. Write the BODY of an async function (erasable syntax only; top-level `await` and `return` work) and call tools as `await tools.name(args)` per the declarations in the system prompt. Only what you print or return comes back — curate it.","parameters":{"type":"object","properties":{"code":{"type":"string","description":"The program: the body of an async TypeScript function."},"description":{"type":"string","description":"Clear, concise description of what this program does in active voice, 5-10 words (shown in the UI). Examples: \"Count TODO markers across packages\"; \"Read failing test and its fixture\"; \"Rename config key in every cordis.yml\"."}},"required":["code","description"]}},{"name":"send_message","description":"Send a message to a background subagent by its subagent id, continuing the same conversation. It becomes the subagent's next turn: if it is still working, the message waits until its current turn finishes, so it cannot redirect work already underway. This call returns no answer from the subagent — only confirmation that the message was delivered — so use it to give it more work. A failure means the message was NOT delivered.","parameters":{"type":"object","properties":{"subagent_id":{"type":"string","description":"The subagent id returned when the background subagent was started."},"message":{"type":"string","description":"The message to deliver to the subagent."}},"required":["subagent_id","message"]}},{"name":"skill","description":"Load the full instructions for an available skill. Call this with the exact skill name from the session skill catalog before acting on a task that names or clearly matches that skill.","parameters":{"type":"object","properties":{"name":{"type":"string","description":"The exact skill name from the available skills list."}},"required":["name"]}},{"name":"subagent","description":"Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. Give it a complete, standalone prompt: it does not see this conversation. This tool runs in the background by default, immediately returns a durable subagent id, and keeps the child conversation available for later turns. When that run settles, the runtime sends the parent a notice containing its outcome and any final assistant message; `send_message` starts a later turn in the same child conversation. Set `run_in_background: false` only when your next action depends on receiving the result.","parameters":{"type":"object","properties":{"description":{"type":"string","description":"A short (3-5 word) description of the delegated task, for display."},"prompt":{"type":"string","description":"The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs."},"run_in_background":{"type":"boolean","description":"Whether to run in the background and return a durable subagent id immediately. Defaults to true. Set false to wait for the result when your next action depends on it."}},"required":["description","prompt"]}},{"name":"subagent_fork","description":"Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This call waits for the subagent and returns its result.","parameters":{"type":"object","properties":{"description":{"type":"string","description":"A short (3-5 word) description of the delegated task, for display."},"prompt":{"type":"string","description":"The task for the subagent. It already sees this conversation's completed turns, so build on them freely and state only what is new."}},"required":["description","prompt"]}},{"name":"todo_write","description":"Record and update a structured task list for the current work. Send the ENTIRE list every call — it REPLACES the previous list (there are no partial updates, no per-item edits). Use it to plan multi-step work and show progress: add one todo per concrete step before you start. Mark every todo being actively worked on `in_progress` — several at once when work genuinely runs in parallel (e.g. concurrent subagents or background commands), one for sequential work; while work remains, at least one task should be `in_progress`. Mark a todo `completed` the moment it is done (do not batch completions), and allow no `in_progress` item only once all work is complete. Skip the list for trivial single-step tasks. Statuses: `pending` (not started), `in_progress` (being worked on now), `completed` (finished).","parameters":{"type":"object","properties":{"todos":{"type":"array","description":"The COMPLETE task list, replacing any previous list.","items":{"type":"object","additionalProperties":false,"properties":{"content":{"type":"string","description":"What the task is — a short imperative line."},"status":{"type":"string","description":"pending (not started) | in_progress (now) | completed (done).","enum":["pending","in_progress","completed"]}},"required":["content","status"]}}},"required":["todos"]}},{"name":"workflow","description":"Run a JavaScript workflow script that orchestrates subagents at scale. Use this for work that fans out across many independent pieces — an audit over many files, a migration, multi-angle research, adversarial verification of findings — where you write the orchestration as a script instead of delegating turn by turn.\n\nThe workflow's identity rides the `meta` parameter as JSON: required `name` (short kebab-case) and `description` strings, optional `whenToUse` string and `phases` array (`{title, detail?, provider?, model?}`). The `script` parameter is the plain JavaScript body ONLY (NOT TypeScript, and NO `export const meta` statement — meta is a parameter, not code), running with top-level await; end with `return ` — the value must be JSON-serializable and is this tool's result.\n\nScript-body hooks:\n- `agent(prompt, opts?): Promise` — run one subagent to completion. Without `opts.schema` it resolves to the child's final text; with `opts.schema` (an object-rooted JSON Schema using ONLY type/properties/required/additionalProperties/items/enum/const/oneOf — no pattern/format/numeric bounds) it resolves to the validated object. Resolves `null` when the child fails (filter with `.filter(Boolean)`). Other opts: `label` (display), `phase` (progress group), and independent `provider`/`model` LLM target overrides (either may be provided alone). Anything else (`effort`/`isolation`/`agentType`) is rejected loudly.\n- `pipeline(items, ...stages): Promise` — run each item through the stages independently with NO barrier between stages (prefer this for multi-stage work). Each stage receives `(prev, item, index)`. An ordinary stage throw drops that ITEM to `null` and skips its remaining stages.\n- `parallel(thunks): Promise` — run zero-argument functions concurrently and await ALL of them (a barrier; use only when a stage genuinely needs every prior result together). A throwing thunk resolves to `null`.\n- `phase(title)` — start a progress phase; `log(message)` — narrate progress; `args` — the tool call's `args` input, verbatim.\n\nMisused hooks (bad arguments, unknown options, unsupported schemas, tripped caps) throw errors that ALWAYS kill the script — they never dissolve into a per-item `null`.\n\nConstraints: concurrency and total-agent caps apply; no filesystem, network, timers, or Node.js APIs are provided — the agents do the work, the script only coordinates them. The run executes in the foreground: this call returns when the whole script finishes.","parameters":{"type":"object","properties":{"script":{"type":"string","description":"The plain-JS workflow script body (top-level await allowed; NO `export const meta` statement; end with `return `)."},"meta":{"type":"object","description":"The workflow identity block (plain JSON — never code).","additionalProperties":true,"properties":{"name":{"type":"string","description":"Short kebab-case workflow name."},"description":{"type":"string","description":"One-line description of what the workflow does."},"whenToUse":{"type":"string","description":"Optional guidance on when this workflow applies."},"phases":{"type":"array","description":"Optional phase declarations matched by phase() calls.","items":{"type":"object","additionalProperties":true,"properties":{"title":{"type":"string","description":"The phase title phase() calls match by exact string."},"detail":{"type":"string","description":"Optional one-line description of the phase."},"provider":{"type":"string","description":"Optional provider override this phase is expected to use."},"model":{"type":"string","description":"Optional model override this phase is expected to use."}},"required":["title"]}}},"required":["name","description"]},"args":{"type":"object","description":"Optional JSON input exposed to the script as the `args` global (wrap a bare list as a field, e.g. {\"files\": [...]}).","additionalProperties":true}},"required":["script","meta"]}},{"name":"write","description":"Create or fully replace a UTF-8 text file.","parameters":{"type":"object","properties":{"file_path":{"type":"string","description":"Path to write, resolved by the filesystem backend."},"content":{"type":"string","description":"Full UTF-8 text content to write."}},"required":["file_path","content"]}}]},"reason":"initial"}} +{"type":"request/header","seq":8,"time":1785498583897,"data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"system":"You are an AI agent powered by DeepSeek Harness.\n\nYou are headless-agent, a coding assistant powered by the deepseek-v4-flash model. Your working directory is {{cwd}}.\n\nVerify your work by running the code or tests. Keep answers brief and factual.\n\n\nUse the read tool — not shell commands like cat — to inspect text files. Results include line numbers. Use offset and limit to continue reading large files.\n\nUse the write tool to create files or completely replace file contents. Existing files are overwritten, so read an existing file first (the default fs-observation-policy requires it) and prefer edit for targeted changes.\n\nUse the edit tool for targeted changes to existing UTF-8 text files. It replaces literal old_string with new_string; by default old_string must appear exactly once. If old_string appears multiple times, provide a more specific old_string or set replace_all to true. Read the file first (the default fs-observation-policy requires it), unless you just created or edited it in this session.\n\nCheck the [exit code: N] marker on every bash result; investigate failures before moving on.\n\nTrack every background job id you start. You are notified in-session when a job finishes — do not busy-poll or sleep on one; keep working on independent steps and do not duplicate a running job's work. Before giving a final answer, collect every still-relevant job with job_output (set wait: true only when you are genuinely blocked on it), and job_kill jobs that stopped mattering.\n\nUse the workflow tool ONLY when the user explicitly asks for a workflow or for large multi-agent orchestration: you write a JavaScript script (the tool description documents the exact format) that fans work out across many subagents with phases and structured results. For one or two delegations, prefer plain subagent calls.\n\n# Dynamic Cordis Plugins\n\nDynamic Cordis plugins temporarily extend the current DSH process. A Plugin uses apply(ctx) to consume Services, listen to Events, provide Services, register model Tools, or register browser UI in Slots.\n\n- Plugin and Package definitions exist only in the current process. define itself does not modify repository source, configuration, or disk, and definitions do not survive a process restart.\n- The restricted execution environment prevents accidental misuse; it is not a security boundary for malicious code. Services obtained by dynamic code connect to the real runtime.\n\n## Make the user-facing plan clear first\n\n- Dynamic Cordis Plugins are one available implementation mechanism, not the default for every request. Consider whether one could help only when the user intends to design or create something, or when a temporary interface could materially aid the current work. The presence of these instructions or Tools, and discussion of Cordis itself, do not make a request a dynamic-Plugin task.\n- When Cordis is a plausible fit, infer the intended work target and lifetime from the request and conversation. Use it only when the outcome belongs to the current running harness and should be delivered as a temporary runtime extension. If that distinction is materially ambiguous, ask at most one concise question about the intended result or lifetime. Otherwise proceed with the matching workflow; do not require the user to know or choose Cordis as an implementation mechanism.\n- Once a dynamic Plugin is appropriate, decide whether the task creates a new Plugin or modifies the Plugin named by the user with @pluginId. Proceed directly when the goal is clear; do not ask for repeated confirmation.\n- Choose Host, Client, or both from the requested outcome. Do not propose a Client/browser UI when the task does not need visible page behavior, and do not avoid Client when the requested outcome is visual, interactive, or depends on page state. Host versus Client is an implementation choice; do not make the user choose it.\n- When a design direction or a potentially useful interface would materially affect the result, ask at most one concise outcome or creative-preference question and offer a few candidate directions. Otherwise proceed directly; do not conduct a multi-round interview or a complex questionnaire.\n- cordis_define only defines and presents code; it does not run it. After definition, explain the pluginId and packageId returned by the Host and whether the next step is a run or update.\n- cordis_run may require user approval. When it returns awaiting-approval, explain that the user must allow or reject it in the UI. Do not wait, retry, or claim that it is running.\n- When it returns starting, explain that the request has entered the asynchronous flow and the Client is still activating. starting does not mean success. Wait for the system to report the final result through steering context.\n- Do not request approval again after the user rejects it. After a technical failure, fix the same Plugin from its diagnostics; do not silently create a replacement Plugin.\n\n## Recommended workflow and Tools\n\nBefore creating, modifying, or repairing a Plugin, load the cordis-plugin-development Skill. The Skill provides requirement navigation, capability composition, complete examples, and troubleshooting. Treat Inspect Provider results as the source of truth for exact APIs.\n\n1. cordis_inspect_list: discover the current Host and Client Providers and their read-only query methods.\n2. cordis_inspect_query: use the returned platform, provider, method, and schema to query exact Service, Event, Builtin, Slot, Theme token, or Tool information.\n3. cordis_inspect_self: inspect the current Session's Plugins, Packages, version pointers, source, and diagnostics. Source is returned only when both pluginId and packageId are specified.\n4. cordis_define: create the first Package for a new Plugin or append an immutable Package to an existing Plugin. It defines code but does not run it.\n5. cordis_run: activate an exact Package. Use run for the first activation, restarting current, or rollback; use update to switch versions.\n6. cordis_stop: remove the current Run and pending approval request while retaining definitions, grants, and version pointers.\n7. cordis_undefine: permanently stop and delete a Plugin and all of its Packages. Use it only after confirming that the user no longer needs them.\n\n- Inspect and Catalog data only confirm capabilities, names, signatures, types, and registration protocols before code is written; they do not replace business APIs.\n- Query Service.listService and Event.listEvents without input to choose from their compact signature directories, then query the exact service or event before using it. Exact queries return the structured contract and only its referenced types.\n- At runtime, a Plugin must call real Services or listen to real Events. Do not cache, display, or depend on Inspect results as business data.\n\n## Identity, versions, and approval\n\n- pluginId identifies a Plugin that can be modified over time. For a new Plugin, submit only a semantic idPrefix of 3–6 lowercase English letters; the Host allocates the final ID.\n- packageId identifies one immutable Host/Client source version under a Plugin. To change code, define a new Package; never overwrite an old version.\n- pluginRunId identifies one activation attempt and connects its approval, Host/Client loading, private RPC, Run card, and errors.\n- currentPackageId is the most recent fully successful Package. Stopping, starting an update, or failing an update does not clear it.\n- nextPackageId is the target awaiting approval, being attempted, awaiting Client activation, or most recently failed.\n- A single check mark authorizes only the current Package; double check marks authorize future versions of the same Plugin. A grant remains in effect after a technical failure.\n- An update stops the old Run before starting the target Package. Failure does not automatically restart the old version; retry next with update or roll back to current with run.\n\nWhen the user enters @pluginId, the system injects identity, the default base Package, version pointers, and runtime status, but not source code:\n\n1. Call cordis_inspect_self(pluginId, packageId) to read the target source.\n2. Use cordis_define in existing mode to append a Package to the same Plugin.\n3. Call cordis_run in run or update mode according to the version relationship.\n\nNever silently create another Plugin for @pluginId. If the reference is unavailable because it was removed, belongs to another Session, or was lost on process restart, tell the user directly.\n\n## High-frequency errors that must be avoided\n\n### Services: ctx.get and inject\n\n- Read an optional Service with ctx.get('serviceName') by default and handle undefined.\n- Declare inject: ['serviceName'] on the returned Plugin object only when the Service is a hard dependency and the Plugin must enter waiting until Cordis reactivates it after the Service appears.\n- Read ctx.serviceName only after declaring that Service in inject. Never access an undeclared Service as a ctx property.\n\n```js\nreturn {\n inject: ['requiredService'],\n apply(ctx) {\n ctx.requiredService.someMethod()\n const optionalService = ctx.get('optionalService')\n if (optionalService !== undefined) optionalService.someMethod()\n },\n}\n```\n\n### Code: use plain JavaScript only\n\n- Host and Client code is not transformed by TypeScript, JSX, or a bundler.\n- Do not use TypeScript types, as, decorators, import, require, or JSX.\n- Client React code must use React.createElement(...); never write .\n- Do not assume that process, Buffer, window, document, fetch, native timers, or any other global is available. Query the corresponding platform's Builtins and Services first.\n\n### Data: do not serialize live data\n\n- Services, Events, Slots, Sessions, and their derived Cordis/DSH objects are internal live data, not ordinary JSON that can be dumped.\n- Do not apply JSON.stringify, structuredClone, recursive enumeration, full copying, or whole-object display to live data.\n- Read only the leaf fields required by the task, then construct the smallest owned data object without Host references.\n\n### Lifecycle: every side effect must be reversible\n\n- Services, Events, Tools, handlers, timers, Slots, styles, and theme overrides must all belong to the current Fiber.\n- Use ctx.effect(), ctx.on(), or official APIs that return a disposer so stop, update, or undefine removes every side effect.\n- The cordis-plugin-development Skill contains complete timer, Waterfall, Slot, theme, Tool, RPC, and React examples and troubleshooting guidance.\n\n## Host and Client\n\n- Host runs in the DSH Node.js process and is appropriate for files, networking, commands, Agent/Session access, Host Events, Services, model Tools, and JSON methods callable by the Client.\n- Client runs in the browser page and is appropriate for themes, layout, current page state, Tool cards, and Slot UI.\n- Host and Client communicate through Package-private JSON methods: Host uses harness.handle(method, handler), and Client uses host.call(method, args). The direction is Client→Host, and only lossless JSON may cross it.\n- Client UI must be registered in a queried Slot; apply() cannot directly return a React Element. Query Slots.listSubTree without root to choose from the compact purpose/topology tree, then query the exact root for its full registration contract and props before writing code.\n- See the Skill and Inspect Providers for Run-specific panels and exact Slot registration patterns.\n\n## Asynchronous results and recovery\n\n- Do not wait inside a Tool for approval or browser work that can happen only after the current turn ends.\n- Asynchronous success, rejection, and runtime errors update Run state and notify you through steering context.\n- After a technical failure, use cordis_inspect_self to read the exact Package source and its message/stack. Define a corrected Package under the same Plugin and retry autonomously.\n- Use the cordis-plugin-development Skill for other failure causes, repair procedures, and complete extension patterns.\n\nUse the ralph tool ONLY when the direct human explicitly asks for a Ralph loop or fresh-agent iterative execution. Each Ralph round starts a fresh child with no conversation seed and uses the shared workspace as durable memory. Completion and blockers are worker reports, not independent evaluation. Use same-session goal tools for ordinary long-running objectives, and plain subagents or workflows for bounded delegation and fan-out.\n\nUse subagent in the background by default. Start independent delegations together in one assistant message and continue useful work while they run. Set `run_in_background: false` only when your next action depends on that subagent's result. When a background run settles, the runtime sends you a notice containing its outcome and any final assistant message.\n\n## Writing code for run_code\n\n`run_code` takes two required arguments: `code` — the body of an async TypeScript function (erasable syntax only — no `enum` or namespaces; type annotations are advisory, the code runs type-stripped) — and `description`, a short summary of what the program does. Inside the program:\n\n- Call tools as `await tools.name(args)` — quoted access for exotic names: `tools[\"my-tool\"](args)`. Every call resolves to the tool's typed canonical JSON value. Tool arguments must be lossless JSON.\n- A FAILED tool call rejects with `ToolCallError`, whose `toolName` identifies the failed tool and whose `message` is human-readable — `try/catch` it to handle and continue.\n- Independent read-only calls MAY overlap under `Promise.all` (safe calls run concurrently; mutating calls run alone, in submission order). Sequence dependent work with `await`.\n- Emit results with `return` and/or `console.log(...)`. ONLY what you print or return comes back to you — intermediate tool results never enter the conversation, so extract just what you need.\n\nThe available tools:\n\n```ts\ntype JsonValue = null | boolean | number | string | JsonValue[] | { [key: string]: JsonValue }\n\ninterface ToolArgsMap {\n /** Execute a bash command (`bash -c`) and return its stdout/stderr. Each call runs in a fresh shell: no state (cwd, variables, functions) persists between calls — pass `workdir` instead of using `cd`. Non-zero exits are reported as `[exit code: N]`. Current harness environment facts are exposed through managed `$DSH_*` variables; inspect them when needed. Commands may run under a file sandbox; a blocked file operation is reported as `[sandbox: file access denied under mode]` — a policy denial, not a bug in the command; do not retry another way. Long output is truncated to its tail; the full output is saved to a file whose path is reported when available. Set `run_in_background: true` for long-running commands: the call returns a job id immediately; read its output with `job_output` and stop it with `job_kill`. */\n bash: {\n /** The bash command to execute. */\n command: string;\n /** Clear, concise description of what this command does in active voice, 5-10 words (shown in the UI). Examples: \"ls\" → \"List files in current directory\"; \"git status\" → \"Show working tree status\"; \"npm install\" → \"Install package dependencies\". */\n description: string;\n /** Timeout in milliseconds. The executor applies its configured default and cap, and kills the command on expiry. */\n timeoutMs?: number;\n /** Working directory for this command. Defaults to the session workspace; a relative path is resolved against it. */\n workdir?: string;\n /** Run in the background and return a job id immediately (collect with job_output, stop with job_kill). No timeout applies. */\n run_in_background?: boolean;\n } & Record;\n /** Define an immutable Cordis Package. For a new Plugin, use kind:\"new\" and provide only a semantic prefix of 3–6 lowercase English letters; the Host returns the final pluginId and packageId. To modify an existing Plugin, use kind:\"existing\" with its exact pluginId to append a Package without overwriting older versions. Provide at least one of code.host and code.client. Each value is a plain JavaScript function body that returns a Cordis Plugin; no TypeScript, JSX, or import transformation occurs. Query Inspect before depending on a Service, Event, Builtin, Slot, or token. Define only validates parameters and syntax and records source: it does not request approval, execute apply, or change currentPackageId. On success, call cordis_run with the returned IDs. */\n cordis_define: {\n plugin: {\n kind: \"new\";\n /** Suggested semantic prefix of 3–6 lowercase English letters; the Host adds a unique numeric suffix. */\n idPrefix: string;\n } | {\n kind: \"existing\";\n /** Exact ID of an existing Plugin; the new Package is appended to that instance. */\n pluginId: string;\n };\n /** Short, readable Package name. */\n name: string;\n /** One-sentence, user-facing description of the Package purpose. */\n purpose: string;\n code: {\n /** Plain JavaScript function body that returns the Host-half Cordis Plugin. */\n host?: string;\n /** Plain JavaScript function body that returns the browser Client-half Cordis Plugin. */\n client?: string;\n };\n } & Record;\n /** List every Cordis Inspect Provider currently known to the Host, including local Host Providers and the latest manifests synchronized from the Client. Each entry includes its platform, purpose, read-only methods, and input/output schemas. Call this Tool before creating or modifying a Package, then select the provider and method for cordis_inspect_query from its result. Do not guess names or treat an Inspect method as a business Service that Plugin code can call. */\n cordis_inspect_list: Record;\n /** Run a read-only query explicitly declared by an Inspect Provider. platform, provider, and method must come from cordis_inspect_list, and input must satisfy that method's schema. Use this Tool before cordis_define to read exact Service methods, Event modes, Builtin signatures, Tool schemas, theme tokens, or live Slot trees and props. Host queries run locally. A Client query waits for the first valid page response and remains pending until a page answers or the Tool is cancelled. This Tool cannot invoke business Service methods or modify the runtime. For Service.listService and Event.listEvents, query without input to navigate the compact signature directory, then query the exact service or event for its structured contract and referenced types. For Slots.listSubTree, query without root to navigate the compact tree, then query the exact root for its complete registration contract and props. */\n cordis_inspect_query: {\n /** Runtime platform that owns the Provider. */\n platform: \"host\" | \"client\";\n /** Exact Provider ID returned by cordis_inspect_list. */\n provider: string;\n /** Exact method name declared by the Provider manifest. */\n method: string;\n /** Optional query input; it must satisfy the method input schema. */\n input?: JsonValue;\n } & Record;\n /** Inspect dynamic Cordis objects owned by the current Session at increasing levels of detail. With no IDs, list only Plugin summaries. With pluginId alone, return version pointers, the latest Run, and every Package summary. Only pluginId plus packageId returns that immutable Package's Host/Client source and runtime diagnostics. packageId cannot be supplied alone. Query an exact Package before handling @pluginId, repairing an asynchronous failure, or defining an updated version. This Tool is read-only: it neither executes code nor changes version pointers. */\n cordis_inspect_self: {\n /** Stable Plugin ID returned by cordis_define or injected by @pluginId; omit it to list every current Plugin. */\n pluginId?: string;\n /** Exact immutable Package ID owned by pluginId; when specified, source and diagnostics are returned. */\n packageId?: string;\n } & Record;\n /** Activate one exact Package of a dynamic Plugin. Use mode:\"run\" for the first activation, restarting currentPackageId, or rollback. When current exists, use mode:\"update\" to switch to a different Package, even if the Plugin is currently stopped. An unauthorized Client Package creates an approval request and returns awaiting-approval; an authorized Package returns starting and continues asynchronously in the browser. Neither result waits for the final outcome inside the Tool. currentPackageId changes only after complete success; on failure, the old current and target next remain. Asynchronous success, rejection, or technical failure is reported through state and steering. After a technical failure, read diagnostics with cordis_inspect_self, correct the same Plugin, and retry autonomously. Do not request approval again after the user rejects it. */\n cordis_run: {\n /** Stable Plugin ID returned by cordis_define. */\n pluginId: string;\n /** Exact immutable Package ID to activate under that Plugin. */\n packageId: string;\n /** Use run for the first activation, restarting current, or rollback; use update to switch from current to a different Package. */\n mode: \"run\" | \"update\";\n } & Record;\n /** Stop the current Run of a dynamic Plugin and cancel unfinished approval or activation requests. Retain the Plugin, every immutable Package, grants, currentPackageId, and nextPackageId so it can later run or update directly. Stopping an already stopped Plugin succeeds idempotently. Use this Tool to disable effects temporarily; use cordis_undefine for permanent removal. */\n cordis_stop: {\n /** Stable dynamic Plugin ID to stop. */\n pluginId: string;\n } & Record;\n /** Permanently remove a dynamic Plugin owned by the current Session. If it is running or awaiting approval, first stop it and cancel the request, then delete every Package, grant, and version pointer. After this returns, its pluginId, packageIds, @ reference, and Package business views are invalid; historical cards retain only a \"Plugin removed\" record. Do not call this Tool when versions must remain available for restart or rollback; use cordis_stop instead. */\n cordis_undefine: {\n /** Stable dynamic Plugin ID to remove permanently. */\n pluginId: string;\n } & Record;\n /** Edit an existing UTF-8 text file by replacing literal text. */\n edit: {\n /** Path to edit, resolved by the filesystem backend. */\n file_path: string;\n /** Literal text to replace. Must match exactly. */\n old_string: string;\n /** Literal replacement text. Use an empty string to delete the match. */\n new_string: string;\n /** Replace all matches. Defaults to false; when false, old_string must appear exactly once. */\n replace_all?: boolean;\n } & Record;\n /** Request cancellation of a background agent's current turn by its agent id. The target may be your direct child or a deeper agent created under you. Only the current turn stops: messages already queued for the agent stay parked until a later send_message, agents it started keep running, and the agent itself stays available for follow-ups. This call returns as soon as the stop request is accepted, so the target may keep running briefly; interrupting an agent that already finished is an accepted no-op. */\n interrupt_agent: {\n /** The agent id of the running agent to interrupt. */\n agent_id: string;\n } & Record;\n /** Request cancellation of a running background job by job id. Returns immediately; the job settles as killed once its work actually stops. */\n job_kill: {\n /** Job id returned by the tool that started the background work. */\n job_id: string;\n /** Optional short reason, recorded in the log and forwarded to the job. */\n reason?: string;\n } & Record;\n /** List your background jobs (running and finished) with their ids, kinds, and statuses. */\n job_list: Record;\n /** Read a background job. Stream jobs return only output since the previous read; final-output jobs return their result after settlement. Every response ends with `[status: ...]`. Reads are non-blocking unless `wait: true`, which waits up to the configured cap. */\n job_output: {\n /** Job id returned by the tool that started the background work. */\n job_id: string;\n /** Block until the job reaches a terminal status or the timeout expires. A timed-out wait returns [status: running] and leaves the job alive. */\n wait?: boolean;\n /** Max wait in milliseconds (only meaningful with wait: true). Defaults to the configured wait timeout; capped by the configured maximum. */\n timeout_ms?: number;\n } & Record;\n /** Run a foreground fresh-agent Ralph loop toward one immutable objective. Use only when the direct human explicitly asks for Ralph or fresh-agent iteration. Each round opens a new child with no parent conversation or prior child session; the shared workspace is long-term memory, and only a bounded structured report crosses rounds. The call returns when a worker reports completion or a concrete blocker, or at the round limit. Ordinary long-running same-session work belongs to goal tools. */\n ralph: {\n /** The immutable completion objective for every fresh Ralph round. */\n objective: string;\n /** Optional positive safe-integer round cap, bounded by the deployment ceiling. */\n maxRounds?: number;\n } & Record;\n /** Read a UTF-8 text file and return line-numbered content. */\n read: {\n /** Path to read, resolved by the filesystem backend. */\n file_path: string;\n /** 1-based first line to return. Defaults to 1. */\n offset?: number;\n /** Maximum number of lines to return. Defaults to 2000. */\n limit?: number;\n } & Record;\n /** Send a message to a background subagent by its subagent id, continuing the same conversation. It becomes the subagent's next turn: if it is still working, the message waits until its current turn finishes, so it cannot redirect work already underway. This call returns no answer from the subagent — only confirmation that the message was delivered — so use it to give it more work. A failure means the message was NOT delivered. */\n send_message: {\n /** The subagent id returned when the background subagent was started. */\n subagent_id: string;\n /** The message to deliver to the subagent. */\n message: string;\n } & Record;\n /** Load the full instructions for an available skill. Call this with the exact skill name from the session skill catalog before acting on a task that names or clearly matches that skill. */\n skill: {\n /** The exact skill name from the available skills list. */\n name: string;\n } & Record;\n /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. Give it a complete, standalone prompt: it does not see this conversation. This tool runs in the background by default, immediately returns a durable subagent id, and keeps the child conversation available for later turns. When that run settles, the runtime sends the parent a notice containing its outcome and any final assistant message; `send_message` starts a later turn in the same child conversation. Set `run_in_background: false` only when your next action depends on receiving the result. */\n subagent: {\n /** A short (3-5 word) description of the delegated task, for display. */\n description: string;\n /** The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs. */\n prompt: string;\n /** Whether to run in the background and return a durable subagent id immediately. Defaults to true. Set false to wait for the result when your next action depends on it. */\n run_in_background?: boolean;\n } & Record;\n /** Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This call waits for the subagent and returns its result. */\n subagent_fork: {\n /** A short (3-5 word) description of the delegated task, for display. */\n description: string;\n /** The task for the subagent. It already sees this conversation's completed turns, so build on them freely and state only what is new. */\n prompt: string;\n } & Record;\n /** Record and update a structured task list for the current work. Send the ENTIRE list every call — it REPLACES the previous list (there are no partial updates, no per-item edits). Use it to plan multi-step work and show progress: add one todo per concrete step before you start. Mark every todo being actively worked on `in_progress` — several at once when work genuinely runs in parallel (e.g. concurrent subagents or background commands), one for sequential work; while work remains, at least one task should be `in_progress`. Mark a todo `completed` the moment it is done (do not batch completions), and allow no `in_progress` item only once all work is complete. Skip the list for trivial single-step tasks. Statuses: `pending` (not started), `in_progress` (being worked on now), `completed` (finished). */\n todo_write: {\n /** The COMPLETE task list, replacing any previous list. */\n todos: ({\n /** What the task is — a short imperative line. */\n content: string;\n /** pending (not started) | in_progress (now) | completed (done). */\n status: \"pending\" | \"in_progress\" | \"completed\";\n })[];\n } & Record;\n /** Run a JavaScript workflow script that orchestrates subagents at scale. Use this for work that fans out across many independent pieces — an audit over many files, a migration, multi-angle research, adversarial verification of findings — where you write the orchestration as a script instead of delegating turn by turn. The workflow's identity rides the `meta` parameter as JSON: required `name` (short kebab-case) and `description` strings, optional `whenToUse` string and `phases` array (`{title, detail?, provider?, model?}`). The `script` parameter is the plain JavaScript body ONLY (NOT TypeScript, and NO `export const meta` statement — meta is a parameter, not code), running with top-level await; end with `return ` — the value must be JSON-serializable and is this tool's result. Script-body hooks: - `agent(prompt, opts?): Promise` — run one subagent to completion. Without `opts.schema` it resolves to the child's final text; with `opts.schema` (an object-rooted JSON Schema using ONLY type/properties/required/additionalProperties/items/enum/const/oneOf — no pattern/format/numeric bounds) it resolves to the validated object. Resolves `null` when the child fails (filter with `.filter(Boolean)`). Other opts: `label` (display), `phase` (progress group), and independent `provider`/`model` LLM target overrides (either may be provided alone). Anything else (`effort`/`isolation`/`agentType`) is rejected loudly. - `pipeline(items, ...stages): Promise` — run each item through the stages independently with NO barrier between stages (prefer this for multi-stage work). Each stage receives `(prev, item, index)`. An ordinary stage throw drops that ITEM to `null` and skips its remaining stages. - `parallel(thunks): Promise` — run zero-argument functions concurrently and await ALL of them (a barrier; use only when a stage genuinely needs every prior result together). A throwing thunk resolves to `null`. - `phase(title)` — start a progress phase; `log(message)` — narrate progress; `args` — the tool call's `args` input, verbatim. Misused hooks (bad arguments, unknown options, unsupported schemas, tripped caps) throw errors that ALWAYS kill the script — they never dissolve into a per-item `null`. Constraints: concurrency and total-agent caps apply; no filesystem, network, timers, or Node.js APIs are provided — the agents do the work, the script only coordinates them. The run executes in the foreground: this call returns when the whole script finishes. */\n workflow: {\n /** The plain-JS workflow script body (top-level await allowed; NO `export const meta` statement; end with `return `). */\n script: string;\n /** The workflow identity block (plain JSON — never code). */\n meta: {\n /** Short kebab-case workflow name. */\n name: string;\n /** One-line description of what the workflow does. */\n description: string;\n /** Optional guidance on when this workflow applies. */\n whenToUse?: string;\n /** Optional phase declarations matched by phase() calls. */\n phases?: ({\n /** The phase title phase() calls match by exact string. */\n title: string;\n /** Optional one-line description of the phase. */\n detail?: string;\n /** Optional provider override this phase is expected to use. */\n provider?: string;\n /** Optional model override this phase is expected to use. */\n model?: string;\n } & Record)[];\n } & Record;\n /** Optional JSON input exposed to the script as the `args` global (wrap a bare list as a field, e.g. {\"files\": [...]}). */\n args?: Record;\n } & Record;\n /** Create or fully replace a UTF-8 text file. */\n write: {\n /** Path to write, resolved by the filesystem backend. */\n file_path: string;\n /** Full UTF-8 text content to write. */\n content: string;\n } & Record;\n}\n\ninterface ToolOutputMap {\n bash: {\n kind: \"background\";\n jobId: string;\n } | {\n kind: \"foreground\";\n exitCode: number | null;\n signal: string | null;\n timedOut: boolean;\n aborted: boolean;\n timeoutMs: number;\n stdout: {\n text: string;\n truncated: boolean;\n spillPath?: string;\n };\n stderr: {\n text: string;\n truncated: boolean;\n spillPath?: string;\n };\n sandbox?: {\n mode: string;\n denied: boolean;\n enforcement?: string;\n runnerFailed?: boolean;\n };\n };\n cordis_define: {\n pluginId: string;\n packageId: string;\n name: string;\n purpose: string;\n hasHostHalf: boolean;\n hasClientHalf: boolean;\n };\n cordis_inspect_list: JsonValue;\n cordis_inspect_query: JsonValue;\n cordis_inspect_self: JsonValue;\n cordis_run: JsonValue;\n cordis_stop: {\n pluginId: string;\n };\n cordis_undefine: {\n pluginId: string;\n wasRunning: boolean;\n };\n edit: {\n path: string;\n before: string;\n after: string;\n };\n interrupt_agent: {\n accepted: boolean;\n };\n job_kill: {\n outcome: \"cancellation-requested\" | \"already-finished\";\n job: {\n id: string;\n kind: string;\n label: string;\n status: \"running\" | \"stopping\" | \"completed\" | \"killed\" | \"failed\";\n detail?: string;\n startedAt: number;\n finishedAt?: number;\n };\n };\n job_list: ({\n id: string;\n kind: string;\n label: string;\n status: \"running\" | \"stopping\" | \"completed\" | \"killed\" | \"failed\";\n detail?: string;\n startedAt: number;\n finishedAt?: number;\n })[];\n job_output: {\n text: string;\n job: {\n id: string;\n kind: string;\n label: string;\n status: \"running\" | \"stopping\" | \"completed\" | \"killed\" | \"failed\";\n detail?: string;\n startedAt: number;\n finishedAt?: number;\n };\n };\n ralph: {\n runId: string;\n agentsStarted: number;\n result: JsonValue;\n };\n read: {\n path: string;\n offset: number;\n lines: {\n number: number;\n text: string;\n }[];\n totalLines: number;\n };\n send_message: {\n messageId: string;\n };\n skill: {\n name: string;\n provider: string;\n resourceBase?: {\n kind: \"directory\";\n path: string;\n } | {\n kind: \"url\";\n url: string;\n } | {\n kind: \"opaque\";\n description: string;\n };\n content: string;\n };\n subagent: {\n kind: \"background\";\n jobId: string;\n } | {\n kind: \"continuable\";\n subagentId: string;\n } | {\n kind: \"foreground\";\n runId: string;\n output: JsonValue[];\n };\n subagent_fork: {\n kind: \"background\";\n jobId: string;\n } | {\n kind: \"continuable\";\n subagentId: string;\n } | {\n kind: \"foreground\";\n runId: string;\n output: JsonValue[];\n };\n todo_write: {\n todos: ({\n content: string;\n status: \"pending\" | \"in_progress\" | \"completed\";\n })[];\n counts: {\n pending: number;\n inProgress: number;\n completed: number;\n };\n };\n workflow: {\n runId: string;\n agentsStarted: number;\n result: JsonValue;\n };\n write: {\n path: string;\n operation: \"create\" | \"update\";\n before: string | null;\n after: string;\n };\n}\n\ntype ToolName = keyof ToolOutputMap\n\ndeclare class ToolCallError extends Error {\n readonly name: \"ToolCallError\";\n readonly toolName: ToolName;\n}\n\ndeclare const tools: {\n [K in ToolName]: (args: ToolArgsMap[K]) => Promise;\n}\n```","tools":[{"name":"bash","description":"Execute a bash command (`bash -c`) and return its stdout/stderr. Each call runs in a fresh shell: no state (cwd, variables, functions) persists between calls — pass `workdir` instead of using `cd`. Non-zero exits are reported as `[exit code: N]`. Current harness environment facts are exposed through managed `$DSH_*` variables; inspect them when needed. Commands may run under a file sandbox; a blocked file operation is reported as `[sandbox: file access denied under mode]` — a policy denial, not a bug in the command; do not retry another way. Long output is truncated to its tail; the full output is saved to a file whose path is reported when available. Set `run_in_background: true` for long-running commands: the call returns a job id immediately; read its output with `job_output` and stop it with `job_kill`.","parameters":{"type":"object","properties":{"command":{"type":"string","description":"The bash command to execute."},"description":{"type":"string","description":"Clear, concise description of what this command does in active voice, 5-10 words (shown in the UI). Examples: \"ls\" → \"List files in current directory\"; \"git status\" → \"Show working tree status\"; \"npm install\" → \"Install package dependencies\"."},"timeoutMs":{"type":"number","description":"Timeout in milliseconds. The executor applies its configured default and cap, and kills the command on expiry."},"workdir":{"type":"string","description":"Working directory for this command. Defaults to the session workspace; a relative path is resolved against it."},"run_in_background":{"type":"boolean","description":"Run in the background and return a job id immediately (collect with job_output, stop with job_kill). No timeout applies."}},"required":["command","description"]}},{"name":"cordis_define","description":"Define an immutable Cordis Package. For a new Plugin, use kind:\"new\" and provide only a semantic prefix of 3–6 lowercase English letters; the Host returns the final pluginId and packageId. To modify an existing Plugin, use kind:\"existing\" with its exact pluginId to append a Package without overwriting older versions. Provide at least one of code.host and code.client. Each value is a plain JavaScript function body that returns a Cordis Plugin; no TypeScript, JSX, or import transformation occurs. Query Inspect before depending on a Service, Event, Builtin, Slot, or token. Define only validates parameters and syntax and records source: it does not request approval, execute apply, or change currentPackageId. On success, call cordis_run with the returned IDs.","parameters":{"type":"object","properties":{"plugin":{"oneOf":[{"type":"object","additionalProperties":false,"properties":{"kind":{"type":"string","const":"new"},"idPrefix":{"type":"string","description":"Suggested semantic prefix of 3–6 lowercase English letters; the Host adds a unique numeric suffix."}},"required":["kind","idPrefix"]},{"type":"object","additionalProperties":false,"properties":{"kind":{"type":"string","const":"existing"},"pluginId":{"type":"string","description":"Exact ID of an existing Plugin; the new Package is appended to that instance."}},"required":["kind","pluginId"]}]},"name":{"type":"string","description":"Short, readable Package name."},"purpose":{"type":"string","description":"One-sentence, user-facing description of the Package purpose."},"code":{"type":"object","additionalProperties":false,"properties":{"host":{"type":"string","description":"Plain JavaScript function body that returns the Host-half Cordis Plugin."},"client":{"type":"string","description":"Plain JavaScript function body that returns the browser Client-half Cordis Plugin."}}}},"required":["plugin","name","purpose","code"]}},{"name":"cordis_inspect_list","description":"List every Cordis Inspect Provider currently known to the Host, including local Host Providers and the latest manifests synchronized from the Client. Each entry includes its platform, purpose, read-only methods, and input/output schemas. Call this Tool before creating or modifying a Package, then select the provider and method for cordis_inspect_query from its result. Do not guess names or treat an Inspect method as a business Service that Plugin code can call.","parameters":{"type":"object","properties":{}}},{"name":"cordis_inspect_query","description":"Run a read-only query explicitly declared by an Inspect Provider. platform, provider, and method must come from cordis_inspect_list, and input must satisfy that method's schema. Use this Tool before cordis_define to read exact Service methods, Event modes, Builtin signatures, Tool schemas, theme tokens, or live Slot trees and props. Host queries run locally. A Client query waits for the first valid page response and remains pending until a page answers or the Tool is cancelled. This Tool cannot invoke business Service methods or modify the runtime. For Service.listService and Event.listEvents, query without input to navigate the compact signature directory, then query the exact service or event for its structured contract and referenced types. For Slots.listSubTree, query without root to navigate the compact tree, then query the exact root for its complete registration contract and props.","parameters":{"type":"object","properties":{"platform":{"type":"string","description":"Runtime platform that owns the Provider.","enum":["host","client"]},"provider":{"type":"string","description":"Exact Provider ID returned by cordis_inspect_list."},"method":{"type":"string","description":"Exact method name declared by the Provider manifest."},"input":{"description":"Optional query input; it must satisfy the method input schema."}},"required":["platform","provider","method"]}},{"name":"cordis_inspect_self","description":"Inspect dynamic Cordis objects owned by the current Session at increasing levels of detail. With no IDs, list only Plugin summaries. With pluginId alone, return version pointers, the latest Run, and every Package summary. Only pluginId plus packageId returns that immutable Package's Host/Client source and runtime diagnostics. packageId cannot be supplied alone. Query an exact Package before handling @pluginId, repairing an asynchronous failure, or defining an updated version. This Tool is read-only: it neither executes code nor changes version pointers.","parameters":{"type":"object","properties":{"pluginId":{"type":"string","description":"Stable Plugin ID returned by cordis_define or injected by @pluginId; omit it to list every current Plugin."},"packageId":{"type":"string","description":"Exact immutable Package ID owned by pluginId; when specified, source and diagnostics are returned."}}}},{"name":"cordis_run","description":"Activate one exact Package of a dynamic Plugin. Use mode:\"run\" for the first activation, restarting currentPackageId, or rollback. When current exists, use mode:\"update\" to switch to a different Package, even if the Plugin is currently stopped. An unauthorized Client Package creates an approval request and returns awaiting-approval; an authorized Package returns starting and continues asynchronously in the browser. Neither result waits for the final outcome inside the Tool. currentPackageId changes only after complete success; on failure, the old current and target next remain. Asynchronous success, rejection, or technical failure is reported through state and steering. After a technical failure, read diagnostics with cordis_inspect_self, correct the same Plugin, and retry autonomously. Do not request approval again after the user rejects it.","parameters":{"type":"object","properties":{"pluginId":{"type":"string","description":"Stable Plugin ID returned by cordis_define."},"packageId":{"type":"string","description":"Exact immutable Package ID to activate under that Plugin."},"mode":{"type":"string","description":"Use run for the first activation, restarting current, or rollback; use update to switch from current to a different Package.","enum":["run","update"]}},"required":["pluginId","packageId","mode"]}},{"name":"cordis_stop","description":"Stop the current Run of a dynamic Plugin and cancel unfinished approval or activation requests. Retain the Plugin, every immutable Package, grants, currentPackageId, and nextPackageId so it can later run or update directly. Stopping an already stopped Plugin succeeds idempotently. Use this Tool to disable effects temporarily; use cordis_undefine for permanent removal.","parameters":{"type":"object","properties":{"pluginId":{"type":"string","description":"Stable dynamic Plugin ID to stop."}},"required":["pluginId"]}},{"name":"cordis_undefine","description":"Permanently remove a dynamic Plugin owned by the current Session. If it is running or awaiting approval, first stop it and cancel the request, then delete every Package, grant, and version pointer. After this returns, its pluginId, packageIds, @ reference, and Package business views are invalid; historical cards retain only a \"Plugin removed\" record. Do not call this Tool when versions must remain available for restart or rollback; use cordis_stop instead.","parameters":{"type":"object","properties":{"pluginId":{"type":"string","description":"Stable dynamic Plugin ID to remove permanently."}},"required":["pluginId"]}},{"name":"edit","description":"Edit an existing UTF-8 text file by replacing literal text.","parameters":{"type":"object","properties":{"file_path":{"type":"string","description":"Path to edit, resolved by the filesystem backend."},"old_string":{"type":"string","description":"Literal text to replace. Must match exactly."},"new_string":{"type":"string","description":"Literal replacement text. Use an empty string to delete the match."},"replace_all":{"type":"boolean","description":"Replace all matches. Defaults to false; when false, old_string must appear exactly once."}},"required":["file_path","old_string","new_string"]}},{"name":"interrupt_agent","description":"Request cancellation of a background agent's current turn by its agent id. The target may be your direct child or a deeper agent created under you. Only the current turn stops: messages already queued for the agent stay parked until a later send_message, agents it started keep running, and the agent itself stays available for follow-ups. This call returns as soon as the stop request is accepted, so the target may keep running briefly; interrupting an agent that already finished is an accepted no-op.","parameters":{"type":"object","properties":{"agent_id":{"type":"string","description":"The agent id of the running agent to interrupt."}},"required":["agent_id"]}},{"name":"job_kill","description":"Request cancellation of a running background job by job id. Returns immediately; the job settles as killed once its work actually stops.","parameters":{"type":"object","properties":{"job_id":{"type":"string","description":"Job id returned by the tool that started the background work."},"reason":{"type":"string","description":"Optional short reason, recorded in the log and forwarded to the job."}},"required":["job_id"]}},{"name":"job_list","description":"List your background jobs (running and finished) with their ids, kinds, and statuses.","parameters":{"type":"object","properties":{}}},{"name":"job_output","description":"Read a background job. Stream jobs return only output since the previous read; final-output jobs return their result after settlement. Every response ends with `[status: ...]`. Reads are non-blocking unless `wait: true`, which waits up to the configured cap.","parameters":{"type":"object","properties":{"job_id":{"type":"string","description":"Job id returned by the tool that started the background work."},"wait":{"type":"boolean","description":"Block until the job reaches a terminal status or the timeout expires. A timed-out wait returns [status: running] and leaves the job alive."},"timeout_ms":{"type":"number","description":"Max wait in milliseconds (only meaningful with wait: true). Defaults to the configured wait timeout; capped by the configured maximum."}},"required":["job_id"]}},{"name":"ralph","description":"Run a foreground fresh-agent Ralph loop toward one immutable objective. Use only when the direct human explicitly asks for Ralph or fresh-agent iteration. Each round opens a new child with no parent conversation or prior child session; the shared workspace is long-term memory, and only a bounded structured report crosses rounds. The call returns when a worker reports completion or a concrete blocker, or at the round limit. Ordinary long-running same-session work belongs to goal tools.","parameters":{"type":"object","properties":{"objective":{"type":"string","description":"The immutable completion objective for every fresh Ralph round."},"maxRounds":{"type":"number","description":"Optional positive safe-integer round cap, bounded by the deployment ceiling."}},"required":["objective"]}},{"name":"read","description":"Read a UTF-8 text file and return line-numbered content.","parameters":{"type":"object","properties":{"file_path":{"type":"string","description":"Path to read, resolved by the filesystem backend."},"offset":{"type":"number","description":"1-based first line to return. Defaults to 1."},"limit":{"type":"number","description":"Maximum number of lines to return. Defaults to 2000."}},"required":["file_path"]}},{"name":"run_code","description":"Execute a TypeScript program against the available tools. Takes two required arguments: `code`, the BODY of an async function (erasable syntax only; top-level `await` and `return` work), and `description`, a short summary of what the program does. Call tools as `await tools.name(args)` per the declarations in the system prompt. Only what you print or return comes back — curate it.","parameters":{"type":"object","properties":{"code":{"type":"string","description":"The program: the body of an async TypeScript function."},"description":{"type":"string","description":"Clear, concise description of what this program does in active voice, 5-10 words (shown in the UI). Examples: \"Count TODO markers across packages\"; \"Read failing test and its fixture\"; \"Rename config key in every cordis.yml\"."}},"required":["code","description"]}},{"name":"send_message","description":"Send a message to a background subagent by its subagent id, continuing the same conversation. It becomes the subagent's next turn: if it is still working, the message waits until its current turn finishes, so it cannot redirect work already underway. This call returns no answer from the subagent — only confirmation that the message was delivered — so use it to give it more work. A failure means the message was NOT delivered.","parameters":{"type":"object","properties":{"subagent_id":{"type":"string","description":"The subagent id returned when the background subagent was started."},"message":{"type":"string","description":"The message to deliver to the subagent."}},"required":["subagent_id","message"]}},{"name":"skill","description":"Load the full instructions for an available skill. Call this with the exact skill name from the session skill catalog before acting on a task that names or clearly matches that skill.","parameters":{"type":"object","properties":{"name":{"type":"string","description":"The exact skill name from the available skills list."}},"required":["name"]}},{"name":"subagent","description":"Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. Give it a complete, standalone prompt: it does not see this conversation. This tool runs in the background by default, immediately returns a durable subagent id, and keeps the child conversation available for later turns. When that run settles, the runtime sends the parent a notice containing its outcome and any final assistant message; `send_message` starts a later turn in the same child conversation. Set `run_in_background: false` only when your next action depends on receiving the result.","parameters":{"type":"object","properties":{"description":{"type":"string","description":"A short (3-5 word) description of the delegated task, for display."},"prompt":{"type":"string","description":"The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs."},"run_in_background":{"type":"boolean","description":"Whether to run in the background and return a durable subagent id immediately. Defaults to true. Set false to wait for the result when your next action depends on it."}},"required":["description","prompt"]}},{"name":"subagent_fork","description":"Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This call waits for the subagent and returns its result.","parameters":{"type":"object","properties":{"description":{"type":"string","description":"A short (3-5 word) description of the delegated task, for display."},"prompt":{"type":"string","description":"The task for the subagent. It already sees this conversation's completed turns, so build on them freely and state only what is new."}},"required":["description","prompt"]}},{"name":"todo_write","description":"Record and update a structured task list for the current work. Send the ENTIRE list every call — it REPLACES the previous list (there are no partial updates, no per-item edits). Use it to plan multi-step work and show progress: add one todo per concrete step before you start. Mark every todo being actively worked on `in_progress` — several at once when work genuinely runs in parallel (e.g. concurrent subagents or background commands), one for sequential work; while work remains, at least one task should be `in_progress`. Mark a todo `completed` the moment it is done (do not batch completions), and allow no `in_progress` item only once all work is complete. Skip the list for trivial single-step tasks. Statuses: `pending` (not started), `in_progress` (being worked on now), `completed` (finished).","parameters":{"type":"object","properties":{"todos":{"type":"array","description":"The COMPLETE task list, replacing any previous list.","items":{"type":"object","additionalProperties":false,"properties":{"content":{"type":"string","description":"What the task is — a short imperative line."},"status":{"type":"string","description":"pending (not started) | in_progress (now) | completed (done).","enum":["pending","in_progress","completed"]}},"required":["content","status"]}}},"required":["todos"]}},{"name":"workflow","description":"Run a JavaScript workflow script that orchestrates subagents at scale. Use this for work that fans out across many independent pieces — an audit over many files, a migration, multi-angle research, adversarial verification of findings — where you write the orchestration as a script instead of delegating turn by turn.\n\nThe workflow's identity rides the `meta` parameter as JSON: required `name` (short kebab-case) and `description` strings, optional `whenToUse` string and `phases` array (`{title, detail?, provider?, model?}`). The `script` parameter is the plain JavaScript body ONLY (NOT TypeScript, and NO `export const meta` statement — meta is a parameter, not code), running with top-level await; end with `return ` — the value must be JSON-serializable and is this tool's result.\n\nScript-body hooks:\n- `agent(prompt, opts?): Promise` — run one subagent to completion. Without `opts.schema` it resolves to the child's final text; with `opts.schema` (an object-rooted JSON Schema using ONLY type/properties/required/additionalProperties/items/enum/const/oneOf — no pattern/format/numeric bounds) it resolves to the validated object. Resolves `null` when the child fails (filter with `.filter(Boolean)`). Other opts: `label` (display), `phase` (progress group), and independent `provider`/`model` LLM target overrides (either may be provided alone). Anything else (`effort`/`isolation`/`agentType`) is rejected loudly.\n- `pipeline(items, ...stages): Promise` — run each item through the stages independently with NO barrier between stages (prefer this for multi-stage work). Each stage receives `(prev, item, index)`. An ordinary stage throw drops that ITEM to `null` and skips its remaining stages.\n- `parallel(thunks): Promise` — run zero-argument functions concurrently and await ALL of them (a barrier; use only when a stage genuinely needs every prior result together). A throwing thunk resolves to `null`.\n- `phase(title)` — start a progress phase; `log(message)` — narrate progress; `args` — the tool call's `args` input, verbatim.\n\nMisused hooks (bad arguments, unknown options, unsupported schemas, tripped caps) throw errors that ALWAYS kill the script — they never dissolve into a per-item `null`.\n\nConstraints: concurrency and total-agent caps apply; no filesystem, network, timers, or Node.js APIs are provided — the agents do the work, the script only coordinates them. The run executes in the foreground: this call returns when the whole script finishes.","parameters":{"type":"object","properties":{"script":{"type":"string","description":"The plain-JS workflow script body (top-level await allowed; NO `export const meta` statement; end with `return `)."},"meta":{"type":"object","description":"The workflow identity block (plain JSON — never code).","additionalProperties":true,"properties":{"name":{"type":"string","description":"Short kebab-case workflow name."},"description":{"type":"string","description":"One-line description of what the workflow does."},"whenToUse":{"type":"string","description":"Optional guidance on when this workflow applies."},"phases":{"type":"array","description":"Optional phase declarations matched by phase() calls.","items":{"type":"object","additionalProperties":true,"properties":{"title":{"type":"string","description":"The phase title phase() calls match by exact string."},"detail":{"type":"string","description":"Optional one-line description of the phase."},"provider":{"type":"string","description":"Optional provider override this phase is expected to use."},"model":{"type":"string","description":"Optional model override this phase is expected to use."}},"required":["title"]}}},"required":["name","description"]},"args":{"type":"object","description":"Optional JSON input exposed to the script as the `args` global (wrap a bare list as a field, e.g. {\"files\": [...]}).","additionalProperties":true}},"required":["script","meta"]}},{"name":"write","description":"Create or fully replace a UTF-8 text file.","parameters":{"type":"object","properties":{"file_path":{"type":"string","description":"Path to write, resolved by the filesystem backend."},"content":{"type":"string","description":"Full UTF-8 text content to write."}},"required":["file_path","content"]}}]},"reason":"initial"}} {"type":"request/context","seq":9,"time":1785730501507,"data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"assistant/chunk","seq":10,"time":1783957884564,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"text"}}} {"type":"assistant/chunk","seq":11,"time":1783957884564,"data":{"turn":1,"step":1,"chunk":{"type":"text-delta","index":0,"text":"DIRECT_CHILD_OK"}}} {"type":"assistant/chunk","seq":12,"time":1783957884564,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"DIRECT_CHILD_OK"}}}} {"type":"assistant/chunk","seq":13,"time":1785498583897,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}} {"type":"assistant/chunk","seq":14,"time":1785730501507,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"stop"}}}} -{"type":"assistant/message","seq":15,"time":1785730501507,"data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"DIRECT_CHILD_OK"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"ce699f54-ef07-41e3-86e9-ef57995549f0"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[10,11,12,13,14],"surfaceOp":"append"} +{"type":"assistant/message","seq":15,"time":1785730501507,"data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"DIRECT_CHILD_OK"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"02dd8a61-a39a-46d0-8f6f-457533271cae"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[10,11,12,13,14],"surfaceOp":"append"} {"type":"step/end","seq":16,"time":1785730501507,"data":{"turn":1,"step":1}} {"type":"turn/end","seq":17,"time":1785730501507,"data":{"turn":1,"reason":{"kind":"completed"}}} diff --git a/examples/headless-agent/tests/snapshots/advanced-toolchain/session.2.jsonl b/examples/headless-agent/tests/snapshots/advanced-toolchain/session.2.jsonl index 6d26883f39..e05489ba1f 100644 --- a/examples/headless-agent/tests/snapshots/advanced-toolchain/session.2.jsonl +++ b/examples/headless-agent/tests/snapshots/advanced-toolchain/session.2.jsonl @@ -1,19 +1,19 @@ {"type":"session","version":0,"id":"33333333-3333-4333-8333-333333333333","createdAt":1783950002000,"cwd":"{{cwd}}","parentSession":"11111111-1111-4111-8111-111111111111","origin":"subagent","delegationDepth":1} -{"type":"agent/inbox/spliced","seq":0,"time":1785498584048,"data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply with exactly WORKFLOW_CHILD_OK and nothing else."}],"source":{"kind":"user"},"role":"user","id":"893169a9-49fc-4849-96ce-18bd7132f2e3"}]}} +{"type":"agent/inbox/spliced","seq":0,"time":1785498584048,"data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply with exactly WORKFLOW_CHILD_OK and nothing else."}],"source":{"kind":"user"},"role":"user","id":"8b3cd23c-82f1-4903-8a3f-b9082059b40c"}]}} {"type":"turn/start","seq":1,"time":1785821454599,"data":{"turn":1}} {"type":"agent/inbox/spliced","seq":2,"time":1785821454599,"data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"subagent/descriptor","seq":3,"time":1785821454618,"data":{"version":2,"mode":"one-shot","provider":"spawn"}} {"type":"step/start","seq":4,"time":1785730501645,"data":{"turn":1,"step":1}} -{"type":"user/message","seq":5,"time":1785730501645,"data":{"content":[{"type":"text","text":"Reply with exactly WORKFLOW_CHILD_OK and nothing else."}],"source":{"kind":"user"},"role":"user","id":"893169a9-49fc-4849-96ce-18bd7132f2e3"},"surfaceOp":"append"} -{"type":"user/message","seq":6,"time":1786373992411,"data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}],"source":{"kind":"plugin","plugin":"@deepseek-ai/dsh-system-prompt","form":"snapshot","sections":[{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}]},"role":"user","id":"61a17dbb-19d2-4053-8251-ff867a552522"},"surfaceOp":"append"} +{"type":"user/message","seq":5,"time":1785730501645,"data":{"content":[{"type":"text","text":"Reply with exactly WORKFLOW_CHILD_OK and nothing else."}],"source":{"kind":"user"},"role":"user","id":"8b3cd23c-82f1-4903-8a3f-b9082059b40c"},"surfaceOp":"append"} +{"type":"user/message","seq":6,"time":1786373992411,"data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}],"source":{"kind":"plugin","plugin":"@deepseek-ai/dsh-system-prompt","form":"snapshot","sections":[{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}]},"role":"user","id":"823e5037-9e96-4ef5-8c5b-cbe73b993ee2"},"surfaceOp":"append"} {"type":"session/title","seq":7,"time":1786373992411,"data":{"title":"Reply with exactly WORKFLOW_CHILD_OK and","messageSeqs":[5],"source":{"kind":"fallback"}}} -{"type":"request/header","seq":8,"time":1785498584067,"data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"system":"You are an AI agent powered by DeepSeek Harness.\n\nYou are headless-agent, a coding assistant powered by the deepseek-v4-flash model. Your working directory is {{cwd}}.\n\nVerify your work by running the code or tests. Keep answers brief and factual.\n\n\nUse the read tool — not shell commands like cat — to inspect text files. Results include line numbers. Use offset and limit to continue reading large files.\n\nUse the write tool to create files or completely replace file contents. Existing files are overwritten, so read an existing file first (the default fs-observation-policy requires it) and prefer edit for targeted changes.\n\nUse the edit tool for targeted changes to existing UTF-8 text files. It replaces literal old_string with new_string; by default old_string must appear exactly once. If old_string appears multiple times, provide a more specific old_string or set replace_all to true. Read the file first (the default fs-observation-policy requires it), unless you just created or edited it in this session.\n\nCheck the [exit code: N] marker on every bash result; investigate failures before moving on.\n\nTrack every background job id you start. You are notified in-session when a job finishes — do not busy-poll or sleep on one; keep working on independent steps and do not duplicate a running job's work. Before giving a final answer, collect every still-relevant job with job_output (set wait: true only when you are genuinely blocked on it), and job_kill jobs that stopped mattering.\n\nUse the workflow tool ONLY when the user explicitly asks for a workflow or for large multi-agent orchestration: you write a JavaScript script (the tool description documents the exact format) that fans work out across many subagents with phases and structured results. For one or two delegations, prefer plain subagent calls.\n\n# Dynamic Cordis Plugins\n\nDynamic Cordis plugins temporarily extend the current DSH process. A Plugin uses apply(ctx) to consume Services, listen to Events, provide Services, register model Tools, or register browser UI in Slots.\n\n- Plugin and Package definitions exist only in the current process. define itself does not modify repository source, configuration, or disk, and definitions do not survive a process restart.\n- The restricted execution environment prevents accidental misuse; it is not a security boundary for malicious code. Services obtained by dynamic code connect to the real runtime.\n\n## Make the user-facing plan clear first\n\n- Dynamic Cordis Plugins are one available implementation mechanism, not the default for every request. Consider whether one could help only when the user intends to design or create something, or when a temporary interface could materially aid the current work. The presence of these instructions or Tools, and discussion of Cordis itself, do not make a request a dynamic-Plugin task.\n- When Cordis is a plausible fit, infer the intended work target and lifetime from the request and conversation. Use it only when the outcome belongs to the current running harness and should be delivered as a temporary runtime extension. If that distinction is materially ambiguous, ask at most one concise question about the intended result or lifetime. Otherwise proceed with the matching workflow; do not require the user to know or choose Cordis as an implementation mechanism.\n- Once a dynamic Plugin is appropriate, decide whether the task creates a new Plugin or modifies the Plugin named by the user with @pluginId. Proceed directly when the goal is clear; do not ask for repeated confirmation.\n- Choose Host, Client, or both from the requested outcome. Do not propose a Client/browser UI when the task does not need visible page behavior, and do not avoid Client when the requested outcome is visual, interactive, or depends on page state. Host versus Client is an implementation choice; do not make the user choose it.\n- When a design direction or a potentially useful interface would materially affect the result, ask at most one concise outcome or creative-preference question and offer a few candidate directions. Otherwise proceed directly; do not conduct a multi-round interview or a complex questionnaire.\n- cordis_define only defines and presents code; it does not run it. After definition, explain the pluginId and packageId returned by the Host and whether the next step is a run or update.\n- cordis_run may require user approval. When it returns awaiting-approval, explain that the user must allow or reject it in the UI. Do not wait, retry, or claim that it is running.\n- When it returns starting, explain that the request has entered the asynchronous flow and the Client is still activating. starting does not mean success. Wait for the system to report the final result through steering context.\n- Do not request approval again after the user rejects it. After a technical failure, fix the same Plugin from its diagnostics; do not silently create a replacement Plugin.\n\n## Recommended workflow and Tools\n\nBefore creating, modifying, or repairing a Plugin, load the cordis-plugin-development Skill. The Skill provides requirement navigation, capability composition, complete examples, and troubleshooting. Treat Inspect Provider results as the source of truth for exact APIs.\n\n1. cordis_inspect_list: discover the current Host and Client Providers and their read-only query methods.\n2. cordis_inspect_query: use the returned platform, provider, method, and schema to query exact Service, Event, Builtin, Slot, Theme token, or Tool information.\n3. cordis_inspect_self: inspect the current Session's Plugins, Packages, version pointers, source, and diagnostics. Source is returned only when both pluginId and packageId are specified.\n4. cordis_define: create the first Package for a new Plugin or append an immutable Package to an existing Plugin. It defines code but does not run it.\n5. cordis_run: activate an exact Package. Use run for the first activation, restarting current, or rollback; use update to switch versions.\n6. cordis_stop: remove the current Run and pending approval request while retaining definitions, grants, and version pointers.\n7. cordis_undefine: permanently stop and delete a Plugin and all of its Packages. Use it only after confirming that the user no longer needs them.\n\n- Inspect and Catalog data only confirm capabilities, names, signatures, types, and registration protocols before code is written; they do not replace business APIs.\n- Query Service.listService and Event.listEvents without input to choose from their compact signature directories, then query the exact service or event before using it. Exact queries return the structured contract and only its referenced types.\n- At runtime, a Plugin must call real Services or listen to real Events. Do not cache, display, or depend on Inspect results as business data.\n\n## Identity, versions, and approval\n\n- pluginId identifies a Plugin that can be modified over time. For a new Plugin, submit only a semantic idPrefix of 3–6 lowercase English letters; the Host allocates the final ID.\n- packageId identifies one immutable Host/Client source version under a Plugin. To change code, define a new Package; never overwrite an old version.\n- pluginRunId identifies one activation attempt and connects its approval, Host/Client loading, private RPC, Run card, and errors.\n- currentPackageId is the most recent fully successful Package. Stopping, starting an update, or failing an update does not clear it.\n- nextPackageId is the target awaiting approval, being attempted, awaiting Client activation, or most recently failed.\n- A single check mark authorizes only the current Package; double check marks authorize future versions of the same Plugin. A grant remains in effect after a technical failure.\n- An update stops the old Run before starting the target Package. Failure does not automatically restart the old version; retry next with update or roll back to current with run.\n\nWhen the user enters @pluginId, the system injects identity, the default base Package, version pointers, and runtime status, but not source code:\n\n1. Call cordis_inspect_self(pluginId, packageId) to read the target source.\n2. Use cordis_define in existing mode to append a Package to the same Plugin.\n3. Call cordis_run in run or update mode according to the version relationship.\n\nNever silently create another Plugin for @pluginId. If the reference is unavailable because it was removed, belongs to another Session, or was lost on process restart, tell the user directly.\n\n## High-frequency errors that must be avoided\n\n### Services: ctx.get and inject\n\n- Read an optional Service with ctx.get('serviceName') by default and handle undefined.\n- Declare inject: ['serviceName'] on the returned Plugin object only when the Service is a hard dependency and the Plugin must enter waiting until Cordis reactivates it after the Service appears.\n- Read ctx.serviceName only after declaring that Service in inject. Never access an undeclared Service as a ctx property.\n\n```js\nreturn {\n inject: ['requiredService'],\n apply(ctx) {\n ctx.requiredService.someMethod()\n const optionalService = ctx.get('optionalService')\n if (optionalService !== undefined) optionalService.someMethod()\n },\n}\n```\n\n### Code: use plain JavaScript only\n\n- Host and Client code is not transformed by TypeScript, JSX, or a bundler.\n- Do not use TypeScript types, as, decorators, import, require, or JSX.\n- Client React code must use React.createElement(...); never write .\n- Do not assume that process, Buffer, window, document, fetch, native timers, or any other global is available. Query the corresponding platform's Builtins and Services first.\n\n### Data: do not serialize live data\n\n- Services, Events, Slots, Sessions, and their derived Cordis/DSH objects are internal live data, not ordinary JSON that can be dumped.\n- Do not apply JSON.stringify, structuredClone, recursive enumeration, full copying, or whole-object display to live data.\n- Read only the leaf fields required by the task, then construct the smallest owned data object without Host references.\n\n### Lifecycle: every side effect must be reversible\n\n- Services, Events, Tools, handlers, timers, Slots, styles, and theme overrides must all belong to the current Fiber.\n- Use ctx.effect(), ctx.on(), or official APIs that return a disposer so stop, update, or undefine removes every side effect.\n- The cordis-plugin-development Skill contains complete timer, Waterfall, Slot, theme, Tool, RPC, and React examples and troubleshooting guidance.\n\n## Host and Client\n\n- Host runs in the DSH Node.js process and is appropriate for files, networking, commands, Agent/Session access, Host Events, Services, model Tools, and JSON methods callable by the Client.\n- Client runs in the browser page and is appropriate for themes, layout, current page state, Tool cards, and Slot UI.\n- Host and Client communicate through Package-private JSON methods: Host uses harness.handle(method, handler), and Client uses host.call(method, args). The direction is Client→Host, and only lossless JSON may cross it.\n- Client UI must be registered in a queried Slot; apply() cannot directly return a React Element. Query Slots.listSubTree without root to choose from the compact purpose/topology tree, then query the exact root for its full registration contract and props before writing code.\n- See the Skill and Inspect Providers for Run-specific panels and exact Slot registration patterns.\n\n## Asynchronous results and recovery\n\n- Do not wait inside a Tool for approval or browser work that can happen only after the current turn ends.\n- Asynchronous success, rejection, and runtime errors update Run state and notify you through steering context.\n- After a technical failure, use cordis_inspect_self to read the exact Package source and its message/stack. Define a corrected Package under the same Plugin and retry autonomously.\n- Use the cordis-plugin-development Skill for other failure causes, repair procedures, and complete extension patterns.\n\nUse the ralph tool ONLY when the direct human explicitly asks for a Ralph loop or fresh-agent iterative execution. Each Ralph round starts a fresh child with no conversation seed and uses the shared workspace as durable memory. Completion and blockers are worker reports, not independent evaluation. Use same-session goal tools for ordinary long-running objectives, and plain subagents or workflows for bounded delegation and fan-out.\n\nUse subagent in the background by default. Start independent delegations together in one assistant message and continue useful work while they run. Set `run_in_background: false` only when your next action depends on that subagent's result. When a background run settles, the runtime sends you a notice containing its outcome and any final assistant message.\n\n## Writing code for run_code\n\nPass `run_code` the body of an async TypeScript function (erasable syntax only — no `enum` or namespaces; type annotations are advisory, the code runs type-stripped). Inside the program:\n\n- Call tools as `await tools.name(args)` — quoted access for exotic names: `tools[\"my-tool\"](args)`. Every call resolves to the tool's typed canonical JSON value. Tool arguments must be lossless JSON.\n- A FAILED tool call rejects with `ToolCallError`, whose `toolName` identifies the failed tool and whose `message` is human-readable — `try/catch` it to handle and continue.\n- Independent read-only calls MAY overlap under `Promise.all` (safe calls run concurrently; mutating calls run alone, in submission order). Sequence dependent work with `await`.\n- Emit results with `return` and/or `console.log(...)`. ONLY what you print or return comes back to you — intermediate tool results never enter the conversation, so extract just what you need.\n\nThe available tools:\n\n```ts\ntype JsonValue = null | boolean | number | string | JsonValue[] | { [key: string]: JsonValue }\n\ninterface ToolArgsMap {\n /** Execute a bash command (`bash -c`) and return its stdout/stderr. Each call runs in a fresh shell: no state (cwd, variables, functions) persists between calls — pass `workdir` instead of using `cd`. Non-zero exits are reported as `[exit code: N]`. Current harness environment facts are exposed through managed `$DSH_*` variables; inspect them when needed. Commands may run under a file sandbox; a blocked file operation is reported as `[sandbox: file access denied under mode]` — a policy denial, not a bug in the command; do not retry another way. Long output is truncated to its tail; the full output is saved to a file whose path is reported when available. Set `run_in_background: true` for long-running commands: the call returns a job id immediately; read its output with `job_output` and stop it with `job_kill`. */\n bash: {\n /** The bash command to execute. */\n command: string;\n /** Clear, concise description of what this command does in active voice, 5-10 words (shown in the UI). Examples: \"ls\" → \"List files in current directory\"; \"git status\" → \"Show working tree status\"; \"npm install\" → \"Install package dependencies\". */\n description: string;\n /** Timeout in milliseconds. The executor applies its configured default and cap, and kills the command on expiry. */\n timeoutMs?: number;\n /** Working directory for this command. Defaults to the session workspace; a relative path is resolved against it. */\n workdir?: string;\n /** Run in the background and return a job id immediately (collect with job_output, stop with job_kill). No timeout applies. */\n run_in_background?: boolean;\n } & Record;\n /** Define an immutable Cordis Package. For a new Plugin, use kind:\"new\" and provide only a semantic prefix of 3–6 lowercase English letters; the Host returns the final pluginId and packageId. To modify an existing Plugin, use kind:\"existing\" with its exact pluginId to append a Package without overwriting older versions. Provide at least one of code.host and code.client. Each value is a plain JavaScript function body that returns a Cordis Plugin; no TypeScript, JSX, or import transformation occurs. Query Inspect before depending on a Service, Event, Builtin, Slot, or token. Define only validates parameters and syntax and records source: it does not request approval, execute apply, or change currentPackageId. On success, call cordis_run with the returned IDs. */\n cordis_define: {\n plugin: {\n kind: \"new\";\n /** Suggested semantic prefix of 3–6 lowercase English letters; the Host adds a unique numeric suffix. */\n idPrefix: string;\n } | {\n kind: \"existing\";\n /** Exact ID of an existing Plugin; the new Package is appended to that instance. */\n pluginId: string;\n };\n /** Short, readable Package name. */\n name: string;\n /** One-sentence, user-facing description of the Package purpose. */\n purpose: string;\n code: {\n /** Plain JavaScript function body that returns the Host-half Cordis Plugin. */\n host?: string;\n /** Plain JavaScript function body that returns the browser Client-half Cordis Plugin. */\n client?: string;\n };\n } & Record;\n /** List every Cordis Inspect Provider currently known to the Host, including local Host Providers and the latest manifests synchronized from the Client. Each entry includes its platform, purpose, read-only methods, and input/output schemas. Call this Tool before creating or modifying a Package, then select the provider and method for cordis_inspect_query from its result. Do not guess names or treat an Inspect method as a business Service that Plugin code can call. */\n cordis_inspect_list: Record;\n /** Run a read-only query explicitly declared by an Inspect Provider. platform, provider, and method must come from cordis_inspect_list, and input must satisfy that method's schema. Use this Tool before cordis_define to read exact Service methods, Event modes, Builtin signatures, Tool schemas, theme tokens, or live Slot trees and props. Host queries run locally. A Client query waits for the first valid page response and remains pending until a page answers or the Tool is cancelled. This Tool cannot invoke business Service methods or modify the runtime. For Service.listService and Event.listEvents, query without input to navigate the compact signature directory, then query the exact service or event for its structured contract and referenced types. For Slots.listSubTree, query without root to navigate the compact tree, then query the exact root for its complete registration contract and props. */\n cordis_inspect_query: {\n /** Runtime platform that owns the Provider. */\n platform: \"host\" | \"client\";\n /** Exact Provider ID returned by cordis_inspect_list. */\n provider: string;\n /** Exact method name declared by the Provider manifest. */\n method: string;\n /** Optional query input; it must satisfy the method input schema. */\n input?: JsonValue;\n } & Record;\n /** Inspect dynamic Cordis objects owned by the current Session at increasing levels of detail. With no IDs, list only Plugin summaries. With pluginId alone, return version pointers, the latest Run, and every Package summary. Only pluginId plus packageId returns that immutable Package's Host/Client source and runtime diagnostics. packageId cannot be supplied alone. Query an exact Package before handling @pluginId, repairing an asynchronous failure, or defining an updated version. This Tool is read-only: it neither executes code nor changes version pointers. */\n cordis_inspect_self: {\n /** Stable Plugin ID returned by cordis_define or injected by @pluginId; omit it to list every current Plugin. */\n pluginId?: string;\n /** Exact immutable Package ID owned by pluginId; when specified, source and diagnostics are returned. */\n packageId?: string;\n } & Record;\n /** Activate one exact Package of a dynamic Plugin. Use mode:\"run\" for the first activation, restarting currentPackageId, or rollback. When current exists, use mode:\"update\" to switch to a different Package, even if the Plugin is currently stopped. An unauthorized Client Package creates an approval request and returns awaiting-approval; an authorized Package returns starting and continues asynchronously in the browser. Neither result waits for the final outcome inside the Tool. currentPackageId changes only after complete success; on failure, the old current and target next remain. Asynchronous success, rejection, or technical failure is reported through state and steering. After a technical failure, read diagnostics with cordis_inspect_self, correct the same Plugin, and retry autonomously. Do not request approval again after the user rejects it. */\n cordis_run: {\n /** Stable Plugin ID returned by cordis_define. */\n pluginId: string;\n /** Exact immutable Package ID to activate under that Plugin. */\n packageId: string;\n /** Use run for the first activation, restarting current, or rollback; use update to switch from current to a different Package. */\n mode: \"run\" | \"update\";\n } & Record;\n /** Stop the current Run of a dynamic Plugin and cancel unfinished approval or activation requests. Retain the Plugin, every immutable Package, grants, currentPackageId, and nextPackageId so it can later run or update directly. Stopping an already stopped Plugin succeeds idempotently. Use this Tool to disable effects temporarily; use cordis_undefine for permanent removal. */\n cordis_stop: {\n /** Stable dynamic Plugin ID to stop. */\n pluginId: string;\n } & Record;\n /** Permanently remove a dynamic Plugin owned by the current Session. If it is running or awaiting approval, first stop it and cancel the request, then delete every Package, grant, and version pointer. After this returns, its pluginId, packageIds, @ reference, and Package business views are invalid; historical cards retain only a \"Plugin removed\" record. Do not call this Tool when versions must remain available for restart or rollback; use cordis_stop instead. */\n cordis_undefine: {\n /** Stable dynamic Plugin ID to remove permanently. */\n pluginId: string;\n } & Record;\n /** Edit an existing UTF-8 text file by replacing literal text. */\n edit: {\n /** Path to edit, resolved by the filesystem backend. */\n file_path: string;\n /** Literal text to replace. Must match exactly. */\n old_string: string;\n /** Literal replacement text. Use an empty string to delete the match. */\n new_string: string;\n /** Replace all matches. Defaults to false; when false, old_string must appear exactly once. */\n replace_all?: boolean;\n } & Record;\n /** Request cancellation of a background agent's current turn by its agent id. The target may be your direct child or a deeper agent created under you. Only the current turn stops: messages already queued for the agent stay parked until a later send_message, agents it started keep running, and the agent itself stays available for follow-ups. This call returns as soon as the stop request is accepted, so the target may keep running briefly; interrupting an agent that already finished is an accepted no-op. */\n interrupt_agent: {\n /** The agent id of the running agent to interrupt. */\n agent_id: string;\n } & Record;\n /** Request cancellation of a running background job by job id. Returns immediately; the job settles as killed once its work actually stops. */\n job_kill: {\n /** Job id returned by the tool that started the background work. */\n job_id: string;\n /** Optional short reason, recorded in the log and forwarded to the job. */\n reason?: string;\n } & Record;\n /** List your background jobs (running and finished) with their ids, kinds, and statuses. */\n job_list: Record;\n /** Read a background job. Stream jobs return only output since the previous read; final-output jobs return their result after settlement. Every response ends with `[status: ...]`. Reads are non-blocking unless `wait: true`, which waits up to the configured cap. */\n job_output: {\n /** Job id returned by the tool that started the background work. */\n job_id: string;\n /** Block until the job reaches a terminal status or the timeout expires. A timed-out wait returns [status: running] and leaves the job alive. */\n wait?: boolean;\n /** Max wait in milliseconds (only meaningful with wait: true). Defaults to the configured wait timeout; capped by the configured maximum. */\n timeout_ms?: number;\n } & Record;\n /** Run a foreground fresh-agent Ralph loop toward one immutable objective. Use only when the direct human explicitly asks for Ralph or fresh-agent iteration. Each round opens a new child with no parent conversation or prior child session; the shared workspace is long-term memory, and only a bounded structured report crosses rounds. The call returns when a worker reports completion or a concrete blocker, or at the round limit. Ordinary long-running same-session work belongs to goal tools. */\n ralph: {\n /** The immutable completion objective for every fresh Ralph round. */\n objective: string;\n /** Optional positive safe-integer round cap, bounded by the deployment ceiling. */\n maxRounds?: number;\n } & Record;\n /** Read a UTF-8 text file and return line-numbered content. */\n read: {\n /** Path to read, resolved by the filesystem backend. */\n file_path: string;\n /** 1-based first line to return. Defaults to 1. */\n offset?: number;\n /** Maximum number of lines to return. Defaults to 2000. */\n limit?: number;\n } & Record;\n /** Send a message to a background subagent by its subagent id, continuing the same conversation. It becomes the subagent's next turn: if it is still working, the message waits until its current turn finishes, so it cannot redirect work already underway. This call returns no answer from the subagent — only confirmation that the message was delivered — so use it to give it more work. A failure means the message was NOT delivered. */\n send_message: {\n /** The subagent id returned when the background subagent was started. */\n subagent_id: string;\n /** The message to deliver to the subagent. */\n message: string;\n } & Record;\n /** Load the full instructions for an available skill. Call this with the exact skill name from the session skill catalog before acting on a task that names or clearly matches that skill. */\n skill: {\n /** The exact skill name from the available skills list. */\n name: string;\n } & Record;\n /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. Give it a complete, standalone prompt: it does not see this conversation. This tool runs in the background by default, immediately returns a durable subagent id, and keeps the child conversation available for later turns. When that run settles, the runtime sends the parent a notice containing its outcome and any final assistant message; `send_message` starts a later turn in the same child conversation. Set `run_in_background: false` only when your next action depends on receiving the result. */\n subagent: {\n /** A short (3-5 word) description of the delegated task, for display. */\n description: string;\n /** The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs. */\n prompt: string;\n /** Whether to run in the background and return a durable subagent id immediately. Defaults to true. Set false to wait for the result when your next action depends on it. */\n run_in_background?: boolean;\n } & Record;\n /** Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This call waits for the subagent and returns its result. */\n subagent_fork: {\n /** A short (3-5 word) description of the delegated task, for display. */\n description: string;\n /** The task for the subagent. It already sees this conversation's completed turns, so build on them freely and state only what is new. */\n prompt: string;\n } & Record;\n /** Record and update a structured task list for the current work. Send the ENTIRE list every call — it REPLACES the previous list (there are no partial updates, no per-item edits). Use it to plan multi-step work and show progress: add one todo per concrete step before you start. Mark every todo being actively worked on `in_progress` — several at once when work genuinely runs in parallel (e.g. concurrent subagents or background commands), one for sequential work; while work remains, at least one task should be `in_progress`. Mark a todo `completed` the moment it is done (do not batch completions), and allow no `in_progress` item only once all work is complete. Skip the list for trivial single-step tasks. Statuses: `pending` (not started), `in_progress` (being worked on now), `completed` (finished). */\n todo_write: {\n /** The COMPLETE task list, replacing any previous list. */\n todos: ({\n /** What the task is — a short imperative line. */\n content: string;\n /** pending (not started) | in_progress (now) | completed (done). */\n status: \"pending\" | \"in_progress\" | \"completed\";\n })[];\n } & Record;\n /** Run a JavaScript workflow script that orchestrates subagents at scale. Use this for work that fans out across many independent pieces — an audit over many files, a migration, multi-angle research, adversarial verification of findings — where you write the orchestration as a script instead of delegating turn by turn. The workflow's identity rides the `meta` parameter as JSON: required `name` (short kebab-case) and `description` strings, optional `whenToUse` string and `phases` array (`{title, detail?, provider?, model?}`). The `script` parameter is the plain JavaScript body ONLY (NOT TypeScript, and NO `export const meta` statement — meta is a parameter, not code), running with top-level await; end with `return ` — the value must be JSON-serializable and is this tool's result. Script-body hooks: - `agent(prompt, opts?): Promise` — run one subagent to completion. Without `opts.schema` it resolves to the child's final text; with `opts.schema` (an object-rooted JSON Schema using ONLY type/properties/required/additionalProperties/items/enum/const/oneOf — no pattern/format/numeric bounds) it resolves to the validated object. Resolves `null` when the child fails (filter with `.filter(Boolean)`). Other opts: `label` (display), `phase` (progress group), and independent `provider`/`model` LLM target overrides (either may be provided alone). Anything else (`effort`/`isolation`/`agentType`) is rejected loudly. - `pipeline(items, ...stages): Promise` — run each item through the stages independently with NO barrier between stages (prefer this for multi-stage work). Each stage receives `(prev, item, index)`. An ordinary stage throw drops that ITEM to `null` and skips its remaining stages. - `parallel(thunks): Promise` — run zero-argument functions concurrently and await ALL of them (a barrier; use only when a stage genuinely needs every prior result together). A throwing thunk resolves to `null`. - `phase(title)` — start a progress phase; `log(message)` — narrate progress; `args` — the tool call's `args` input, verbatim. Misused hooks (bad arguments, unknown options, unsupported schemas, tripped caps) throw errors that ALWAYS kill the script — they never dissolve into a per-item `null`. Constraints: concurrency and total-agent caps apply; no filesystem, network, timers, or Node.js APIs are provided — the agents do the work, the script only coordinates them. The run executes in the foreground: this call returns when the whole script finishes. */\n workflow: {\n /** The plain-JS workflow script body (top-level await allowed; NO `export const meta` statement; end with `return `). */\n script: string;\n /** The workflow identity block (plain JSON — never code). */\n meta: {\n /** Short kebab-case workflow name. */\n name: string;\n /** One-line description of what the workflow does. */\n description: string;\n /** Optional guidance on when this workflow applies. */\n whenToUse?: string;\n /** Optional phase declarations matched by phase() calls. */\n phases?: ({\n /** The phase title phase() calls match by exact string. */\n title: string;\n /** Optional one-line description of the phase. */\n detail?: string;\n /** Optional provider override this phase is expected to use. */\n provider?: string;\n /** Optional model override this phase is expected to use. */\n model?: string;\n } & Record)[];\n } & Record;\n /** Optional JSON input exposed to the script as the `args` global (wrap a bare list as a field, e.g. {\"files\": [...]}). */\n args?: Record;\n } & Record;\n /** Create or fully replace a UTF-8 text file. */\n write: {\n /** Path to write, resolved by the filesystem backend. */\n file_path: string;\n /** Full UTF-8 text content to write. */\n content: string;\n } & Record;\n}\n\ninterface ToolOutputMap {\n bash: {\n kind: \"background\";\n jobId: string;\n } | {\n kind: \"foreground\";\n exitCode: number | null;\n signal: string | null;\n timedOut: boolean;\n aborted: boolean;\n timeoutMs: number;\n stdout: {\n text: string;\n truncated: boolean;\n spillPath?: string;\n };\n stderr: {\n text: string;\n truncated: boolean;\n spillPath?: string;\n };\n sandbox?: {\n mode: string;\n denied: boolean;\n enforcement?: string;\n runnerFailed?: boolean;\n };\n };\n cordis_define: {\n pluginId: string;\n packageId: string;\n name: string;\n purpose: string;\n hasHostHalf: boolean;\n hasClientHalf: boolean;\n };\n cordis_inspect_list: JsonValue;\n cordis_inspect_query: JsonValue;\n cordis_inspect_self: JsonValue;\n cordis_run: JsonValue;\n cordis_stop: {\n pluginId: string;\n };\n cordis_undefine: {\n pluginId: string;\n wasRunning: boolean;\n };\n edit: {\n path: string;\n before: string;\n after: string;\n };\n interrupt_agent: {\n accepted: boolean;\n };\n job_kill: {\n outcome: \"cancellation-requested\" | \"already-finished\";\n job: {\n id: string;\n kind: string;\n label: string;\n status: \"running\" | \"stopping\" | \"completed\" | \"killed\" | \"failed\";\n detail?: string;\n startedAt: number;\n finishedAt?: number;\n };\n };\n job_list: ({\n id: string;\n kind: string;\n label: string;\n status: \"running\" | \"stopping\" | \"completed\" | \"killed\" | \"failed\";\n detail?: string;\n startedAt: number;\n finishedAt?: number;\n })[];\n job_output: {\n text: string;\n job: {\n id: string;\n kind: string;\n label: string;\n status: \"running\" | \"stopping\" | \"completed\" | \"killed\" | \"failed\";\n detail?: string;\n startedAt: number;\n finishedAt?: number;\n };\n };\n ralph: {\n runId: string;\n agentsStarted: number;\n result: JsonValue;\n };\n read: {\n path: string;\n offset: number;\n lines: {\n number: number;\n text: string;\n }[];\n totalLines: number;\n };\n send_message: {\n messageId: string;\n };\n skill: {\n name: string;\n provider: string;\n resourceBase?: {\n kind: \"directory\";\n path: string;\n } | {\n kind: \"url\";\n url: string;\n } | {\n kind: \"opaque\";\n description: string;\n };\n content: string;\n };\n subagent: {\n kind: \"background\";\n jobId: string;\n } | {\n kind: \"continuable\";\n subagentId: string;\n } | {\n kind: \"foreground\";\n runId: string;\n output: JsonValue[];\n };\n subagent_fork: {\n kind: \"background\";\n jobId: string;\n } | {\n kind: \"continuable\";\n subagentId: string;\n } | {\n kind: \"foreground\";\n runId: string;\n output: JsonValue[];\n };\n todo_write: {\n todos: ({\n content: string;\n status: \"pending\" | \"in_progress\" | \"completed\";\n })[];\n counts: {\n pending: number;\n inProgress: number;\n completed: number;\n };\n };\n workflow: {\n runId: string;\n agentsStarted: number;\n result: JsonValue;\n };\n write: {\n path: string;\n operation: \"create\" | \"update\";\n before: string | null;\n after: string;\n };\n}\n\ntype ToolName = keyof ToolOutputMap\n\ndeclare class ToolCallError extends Error {\n readonly name: \"ToolCallError\";\n readonly toolName: ToolName;\n}\n\ndeclare const tools: {\n [K in ToolName]: (args: ToolArgsMap[K]) => Promise;\n}\n```","tools":[{"name":"bash","description":"Execute a bash command (`bash -c`) and return its stdout/stderr. Each call runs in a fresh shell: no state (cwd, variables, functions) persists between calls — pass `workdir` instead of using `cd`. Non-zero exits are reported as `[exit code: N]`. Current harness environment facts are exposed through managed `$DSH_*` variables; inspect them when needed. Commands may run under a file sandbox; a blocked file operation is reported as `[sandbox: file access denied under mode]` — a policy denial, not a bug in the command; do not retry another way. Long output is truncated to its tail; the full output is saved to a file whose path is reported when available. Set `run_in_background: true` for long-running commands: the call returns a job id immediately; read its output with `job_output` and stop it with `job_kill`.","parameters":{"type":"object","properties":{"command":{"type":"string","description":"The bash command to execute."},"description":{"type":"string","description":"Clear, concise description of what this command does in active voice, 5-10 words (shown in the UI). Examples: \"ls\" → \"List files in current directory\"; \"git status\" → \"Show working tree status\"; \"npm install\" → \"Install package dependencies\"."},"timeoutMs":{"type":"number","description":"Timeout in milliseconds. The executor applies its configured default and cap, and kills the command on expiry."},"workdir":{"type":"string","description":"Working directory for this command. Defaults to the session workspace; a relative path is resolved against it."},"run_in_background":{"type":"boolean","description":"Run in the background and return a job id immediately (collect with job_output, stop with job_kill). No timeout applies."}},"required":["command","description"]}},{"name":"cordis_define","description":"Define an immutable Cordis Package. For a new Plugin, use kind:\"new\" and provide only a semantic prefix of 3–6 lowercase English letters; the Host returns the final pluginId and packageId. To modify an existing Plugin, use kind:\"existing\" with its exact pluginId to append a Package without overwriting older versions. Provide at least one of code.host and code.client. Each value is a plain JavaScript function body that returns a Cordis Plugin; no TypeScript, JSX, or import transformation occurs. Query Inspect before depending on a Service, Event, Builtin, Slot, or token. Define only validates parameters and syntax and records source: it does not request approval, execute apply, or change currentPackageId. On success, call cordis_run with the returned IDs.","parameters":{"type":"object","properties":{"plugin":{"oneOf":[{"type":"object","additionalProperties":false,"properties":{"kind":{"type":"string","const":"new"},"idPrefix":{"type":"string","description":"Suggested semantic prefix of 3–6 lowercase English letters; the Host adds a unique numeric suffix."}},"required":["kind","idPrefix"]},{"type":"object","additionalProperties":false,"properties":{"kind":{"type":"string","const":"existing"},"pluginId":{"type":"string","description":"Exact ID of an existing Plugin; the new Package is appended to that instance."}},"required":["kind","pluginId"]}]},"name":{"type":"string","description":"Short, readable Package name."},"purpose":{"type":"string","description":"One-sentence, user-facing description of the Package purpose."},"code":{"type":"object","additionalProperties":false,"properties":{"host":{"type":"string","description":"Plain JavaScript function body that returns the Host-half Cordis Plugin."},"client":{"type":"string","description":"Plain JavaScript function body that returns the browser Client-half Cordis Plugin."}}}},"required":["plugin","name","purpose","code"]}},{"name":"cordis_inspect_list","description":"List every Cordis Inspect Provider currently known to the Host, including local Host Providers and the latest manifests synchronized from the Client. Each entry includes its platform, purpose, read-only methods, and input/output schemas. Call this Tool before creating or modifying a Package, then select the provider and method for cordis_inspect_query from its result. Do not guess names or treat an Inspect method as a business Service that Plugin code can call.","parameters":{"type":"object","properties":{}}},{"name":"cordis_inspect_query","description":"Run a read-only query explicitly declared by an Inspect Provider. platform, provider, and method must come from cordis_inspect_list, and input must satisfy that method's schema. Use this Tool before cordis_define to read exact Service methods, Event modes, Builtin signatures, Tool schemas, theme tokens, or live Slot trees and props. Host queries run locally. A Client query waits for the first valid page response and remains pending until a page answers or the Tool is cancelled. This Tool cannot invoke business Service methods or modify the runtime. For Service.listService and Event.listEvents, query without input to navigate the compact signature directory, then query the exact service or event for its structured contract and referenced types. For Slots.listSubTree, query without root to navigate the compact tree, then query the exact root for its complete registration contract and props.","parameters":{"type":"object","properties":{"platform":{"type":"string","description":"Runtime platform that owns the Provider.","enum":["host","client"]},"provider":{"type":"string","description":"Exact Provider ID returned by cordis_inspect_list."},"method":{"type":"string","description":"Exact method name declared by the Provider manifest."},"input":{"description":"Optional query input; it must satisfy the method input schema."}},"required":["platform","provider","method"]}},{"name":"cordis_inspect_self","description":"Inspect dynamic Cordis objects owned by the current Session at increasing levels of detail. With no IDs, list only Plugin summaries. With pluginId alone, return version pointers, the latest Run, and every Package summary. Only pluginId plus packageId returns that immutable Package's Host/Client source and runtime diagnostics. packageId cannot be supplied alone. Query an exact Package before handling @pluginId, repairing an asynchronous failure, or defining an updated version. This Tool is read-only: it neither executes code nor changes version pointers.","parameters":{"type":"object","properties":{"pluginId":{"type":"string","description":"Stable Plugin ID returned by cordis_define or injected by @pluginId; omit it to list every current Plugin."},"packageId":{"type":"string","description":"Exact immutable Package ID owned by pluginId; when specified, source and diagnostics are returned."}}}},{"name":"cordis_run","description":"Activate one exact Package of a dynamic Plugin. Use mode:\"run\" for the first activation, restarting currentPackageId, or rollback. When current exists, use mode:\"update\" to switch to a different Package, even if the Plugin is currently stopped. An unauthorized Client Package creates an approval request and returns awaiting-approval; an authorized Package returns starting and continues asynchronously in the browser. Neither result waits for the final outcome inside the Tool. currentPackageId changes only after complete success; on failure, the old current and target next remain. Asynchronous success, rejection, or technical failure is reported through state and steering. After a technical failure, read diagnostics with cordis_inspect_self, correct the same Plugin, and retry autonomously. Do not request approval again after the user rejects it.","parameters":{"type":"object","properties":{"pluginId":{"type":"string","description":"Stable Plugin ID returned by cordis_define."},"packageId":{"type":"string","description":"Exact immutable Package ID to activate under that Plugin."},"mode":{"type":"string","description":"Use run for the first activation, restarting current, or rollback; use update to switch from current to a different Package.","enum":["run","update"]}},"required":["pluginId","packageId","mode"]}},{"name":"cordis_stop","description":"Stop the current Run of a dynamic Plugin and cancel unfinished approval or activation requests. Retain the Plugin, every immutable Package, grants, currentPackageId, and nextPackageId so it can later run or update directly. Stopping an already stopped Plugin succeeds idempotently. Use this Tool to disable effects temporarily; use cordis_undefine for permanent removal.","parameters":{"type":"object","properties":{"pluginId":{"type":"string","description":"Stable dynamic Plugin ID to stop."}},"required":["pluginId"]}},{"name":"cordis_undefine","description":"Permanently remove a dynamic Plugin owned by the current Session. If it is running or awaiting approval, first stop it and cancel the request, then delete every Package, grant, and version pointer. After this returns, its pluginId, packageIds, @ reference, and Package business views are invalid; historical cards retain only a \"Plugin removed\" record. Do not call this Tool when versions must remain available for restart or rollback; use cordis_stop instead.","parameters":{"type":"object","properties":{"pluginId":{"type":"string","description":"Stable dynamic Plugin ID to remove permanently."}},"required":["pluginId"]}},{"name":"edit","description":"Edit an existing UTF-8 text file by replacing literal text.","parameters":{"type":"object","properties":{"file_path":{"type":"string","description":"Path to edit, resolved by the filesystem backend."},"old_string":{"type":"string","description":"Literal text to replace. Must match exactly."},"new_string":{"type":"string","description":"Literal replacement text. Use an empty string to delete the match."},"replace_all":{"type":"boolean","description":"Replace all matches. Defaults to false; when false, old_string must appear exactly once."}},"required":["file_path","old_string","new_string"]}},{"name":"interrupt_agent","description":"Request cancellation of a background agent's current turn by its agent id. The target may be your direct child or a deeper agent created under you. Only the current turn stops: messages already queued for the agent stay parked until a later send_message, agents it started keep running, and the agent itself stays available for follow-ups. This call returns as soon as the stop request is accepted, so the target may keep running briefly; interrupting an agent that already finished is an accepted no-op.","parameters":{"type":"object","properties":{"agent_id":{"type":"string","description":"The agent id of the running agent to interrupt."}},"required":["agent_id"]}},{"name":"job_kill","description":"Request cancellation of a running background job by job id. Returns immediately; the job settles as killed once its work actually stops.","parameters":{"type":"object","properties":{"job_id":{"type":"string","description":"Job id returned by the tool that started the background work."},"reason":{"type":"string","description":"Optional short reason, recorded in the log and forwarded to the job."}},"required":["job_id"]}},{"name":"job_list","description":"List your background jobs (running and finished) with their ids, kinds, and statuses.","parameters":{"type":"object","properties":{}}},{"name":"job_output","description":"Read a background job. Stream jobs return only output since the previous read; final-output jobs return their result after settlement. Every response ends with `[status: ...]`. Reads are non-blocking unless `wait: true`, which waits up to the configured cap.","parameters":{"type":"object","properties":{"job_id":{"type":"string","description":"Job id returned by the tool that started the background work."},"wait":{"type":"boolean","description":"Block until the job reaches a terminal status or the timeout expires. A timed-out wait returns [status: running] and leaves the job alive."},"timeout_ms":{"type":"number","description":"Max wait in milliseconds (only meaningful with wait: true). Defaults to the configured wait timeout; capped by the configured maximum."}},"required":["job_id"]}},{"name":"ralph","description":"Run a foreground fresh-agent Ralph loop toward one immutable objective. Use only when the direct human explicitly asks for Ralph or fresh-agent iteration. Each round opens a new child with no parent conversation or prior child session; the shared workspace is long-term memory, and only a bounded structured report crosses rounds. The call returns when a worker reports completion or a concrete blocker, or at the round limit. Ordinary long-running same-session work belongs to goal tools.","parameters":{"type":"object","properties":{"objective":{"type":"string","description":"The immutable completion objective for every fresh Ralph round."},"maxRounds":{"type":"number","description":"Optional positive safe-integer round cap, bounded by the deployment ceiling."}},"required":["objective"]}},{"name":"read","description":"Read a UTF-8 text file and return line-numbered content.","parameters":{"type":"object","properties":{"file_path":{"type":"string","description":"Path to read, resolved by the filesystem backend."},"offset":{"type":"number","description":"1-based first line to return. Defaults to 1."},"limit":{"type":"number","description":"Maximum number of lines to return. Defaults to 2000."}},"required":["file_path"]}},{"name":"run_code","description":"Execute a TypeScript program against the available tools. Write the BODY of an async function (erasable syntax only; top-level `await` and `return` work) and call tools as `await tools.name(args)` per the declarations in the system prompt. Only what you print or return comes back — curate it.","parameters":{"type":"object","properties":{"code":{"type":"string","description":"The program: the body of an async TypeScript function."},"description":{"type":"string","description":"Clear, concise description of what this program does in active voice, 5-10 words (shown in the UI). Examples: \"Count TODO markers across packages\"; \"Read failing test and its fixture\"; \"Rename config key in every cordis.yml\"."}},"required":["code","description"]}},{"name":"send_message","description":"Send a message to a background subagent by its subagent id, continuing the same conversation. It becomes the subagent's next turn: if it is still working, the message waits until its current turn finishes, so it cannot redirect work already underway. This call returns no answer from the subagent — only confirmation that the message was delivered — so use it to give it more work. A failure means the message was NOT delivered.","parameters":{"type":"object","properties":{"subagent_id":{"type":"string","description":"The subagent id returned when the background subagent was started."},"message":{"type":"string","description":"The message to deliver to the subagent."}},"required":["subagent_id","message"]}},{"name":"skill","description":"Load the full instructions for an available skill. Call this with the exact skill name from the session skill catalog before acting on a task that names or clearly matches that skill.","parameters":{"type":"object","properties":{"name":{"type":"string","description":"The exact skill name from the available skills list."}},"required":["name"]}},{"name":"subagent","description":"Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. Give it a complete, standalone prompt: it does not see this conversation. This tool runs in the background by default, immediately returns a durable subagent id, and keeps the child conversation available for later turns. When that run settles, the runtime sends the parent a notice containing its outcome and any final assistant message; `send_message` starts a later turn in the same child conversation. Set `run_in_background: false` only when your next action depends on receiving the result.","parameters":{"type":"object","properties":{"description":{"type":"string","description":"A short (3-5 word) description of the delegated task, for display."},"prompt":{"type":"string","description":"The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs."},"run_in_background":{"type":"boolean","description":"Whether to run in the background and return a durable subagent id immediately. Defaults to true. Set false to wait for the result when your next action depends on it."}},"required":["description","prompt"]}},{"name":"subagent_fork","description":"Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This call waits for the subagent and returns its result.","parameters":{"type":"object","properties":{"description":{"type":"string","description":"A short (3-5 word) description of the delegated task, for display."},"prompt":{"type":"string","description":"The task for the subagent. It already sees this conversation's completed turns, so build on them freely and state only what is new."}},"required":["description","prompt"]}},{"name":"todo_write","description":"Record and update a structured task list for the current work. Send the ENTIRE list every call — it REPLACES the previous list (there are no partial updates, no per-item edits). Use it to plan multi-step work and show progress: add one todo per concrete step before you start. Mark every todo being actively worked on `in_progress` — several at once when work genuinely runs in parallel (e.g. concurrent subagents or background commands), one for sequential work; while work remains, at least one task should be `in_progress`. Mark a todo `completed` the moment it is done (do not batch completions), and allow no `in_progress` item only once all work is complete. Skip the list for trivial single-step tasks. Statuses: `pending` (not started), `in_progress` (being worked on now), `completed` (finished).","parameters":{"type":"object","properties":{"todos":{"type":"array","description":"The COMPLETE task list, replacing any previous list.","items":{"type":"object","additionalProperties":false,"properties":{"content":{"type":"string","description":"What the task is — a short imperative line."},"status":{"type":"string","description":"pending (not started) | in_progress (now) | completed (done).","enum":["pending","in_progress","completed"]}},"required":["content","status"]}}},"required":["todos"]}},{"name":"workflow","description":"Run a JavaScript workflow script that orchestrates subagents at scale. Use this for work that fans out across many independent pieces — an audit over many files, a migration, multi-angle research, adversarial verification of findings — where you write the orchestration as a script instead of delegating turn by turn.\n\nThe workflow's identity rides the `meta` parameter as JSON: required `name` (short kebab-case) and `description` strings, optional `whenToUse` string and `phases` array (`{title, detail?, provider?, model?}`). The `script` parameter is the plain JavaScript body ONLY (NOT TypeScript, and NO `export const meta` statement — meta is a parameter, not code), running with top-level await; end with `return ` — the value must be JSON-serializable and is this tool's result.\n\nScript-body hooks:\n- `agent(prompt, opts?): Promise` — run one subagent to completion. Without `opts.schema` it resolves to the child's final text; with `opts.schema` (an object-rooted JSON Schema using ONLY type/properties/required/additionalProperties/items/enum/const/oneOf — no pattern/format/numeric bounds) it resolves to the validated object. Resolves `null` when the child fails (filter with `.filter(Boolean)`). Other opts: `label` (display), `phase` (progress group), and independent `provider`/`model` LLM target overrides (either may be provided alone). Anything else (`effort`/`isolation`/`agentType`) is rejected loudly.\n- `pipeline(items, ...stages): Promise` — run each item through the stages independently with NO barrier between stages (prefer this for multi-stage work). Each stage receives `(prev, item, index)`. An ordinary stage throw drops that ITEM to `null` and skips its remaining stages.\n- `parallel(thunks): Promise` — run zero-argument functions concurrently and await ALL of them (a barrier; use only when a stage genuinely needs every prior result together). A throwing thunk resolves to `null`.\n- `phase(title)` — start a progress phase; `log(message)` — narrate progress; `args` — the tool call's `args` input, verbatim.\n\nMisused hooks (bad arguments, unknown options, unsupported schemas, tripped caps) throw errors that ALWAYS kill the script — they never dissolve into a per-item `null`.\n\nConstraints: concurrency and total-agent caps apply; no filesystem, network, timers, or Node.js APIs are provided — the agents do the work, the script only coordinates them. The run executes in the foreground: this call returns when the whole script finishes.","parameters":{"type":"object","properties":{"script":{"type":"string","description":"The plain-JS workflow script body (top-level await allowed; NO `export const meta` statement; end with `return `)."},"meta":{"type":"object","description":"The workflow identity block (plain JSON — never code).","additionalProperties":true,"properties":{"name":{"type":"string","description":"Short kebab-case workflow name."},"description":{"type":"string","description":"One-line description of what the workflow does."},"whenToUse":{"type":"string","description":"Optional guidance on when this workflow applies."},"phases":{"type":"array","description":"Optional phase declarations matched by phase() calls.","items":{"type":"object","additionalProperties":true,"properties":{"title":{"type":"string","description":"The phase title phase() calls match by exact string."},"detail":{"type":"string","description":"Optional one-line description of the phase."},"provider":{"type":"string","description":"Optional provider override this phase is expected to use."},"model":{"type":"string","description":"Optional model override this phase is expected to use."}},"required":["title"]}}},"required":["name","description"]},"args":{"type":"object","description":"Optional JSON input exposed to the script as the `args` global (wrap a bare list as a field, e.g. {\"files\": [...]}).","additionalProperties":true}},"required":["script","meta"]}},{"name":"write","description":"Create or fully replace a UTF-8 text file.","parameters":{"type":"object","properties":{"file_path":{"type":"string","description":"Path to write, resolved by the filesystem backend."},"content":{"type":"string","description":"Full UTF-8 text content to write."}},"required":["file_path","content"]}}]},"reason":"initial"}} +{"type":"request/header","seq":8,"time":1785498584067,"data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"system":"You are an AI agent powered by DeepSeek Harness.\n\nYou are headless-agent, a coding assistant powered by the deepseek-v4-flash model. Your working directory is {{cwd}}.\n\nVerify your work by running the code or tests. Keep answers brief and factual.\n\n\nUse the read tool — not shell commands like cat — to inspect text files. Results include line numbers. Use offset and limit to continue reading large files.\n\nUse the write tool to create files or completely replace file contents. Existing files are overwritten, so read an existing file first (the default fs-observation-policy requires it) and prefer edit for targeted changes.\n\nUse the edit tool for targeted changes to existing UTF-8 text files. It replaces literal old_string with new_string; by default old_string must appear exactly once. If old_string appears multiple times, provide a more specific old_string or set replace_all to true. Read the file first (the default fs-observation-policy requires it), unless you just created or edited it in this session.\n\nCheck the [exit code: N] marker on every bash result; investigate failures before moving on.\n\nTrack every background job id you start. You are notified in-session when a job finishes — do not busy-poll or sleep on one; keep working on independent steps and do not duplicate a running job's work. Before giving a final answer, collect every still-relevant job with job_output (set wait: true only when you are genuinely blocked on it), and job_kill jobs that stopped mattering.\n\nUse the workflow tool ONLY when the user explicitly asks for a workflow or for large multi-agent orchestration: you write a JavaScript script (the tool description documents the exact format) that fans work out across many subagents with phases and structured results. For one or two delegations, prefer plain subagent calls.\n\n# Dynamic Cordis Plugins\n\nDynamic Cordis plugins temporarily extend the current DSH process. A Plugin uses apply(ctx) to consume Services, listen to Events, provide Services, register model Tools, or register browser UI in Slots.\n\n- Plugin and Package definitions exist only in the current process. define itself does not modify repository source, configuration, or disk, and definitions do not survive a process restart.\n- The restricted execution environment prevents accidental misuse; it is not a security boundary for malicious code. Services obtained by dynamic code connect to the real runtime.\n\n## Make the user-facing plan clear first\n\n- Dynamic Cordis Plugins are one available implementation mechanism, not the default for every request. Consider whether one could help only when the user intends to design or create something, or when a temporary interface could materially aid the current work. The presence of these instructions or Tools, and discussion of Cordis itself, do not make a request a dynamic-Plugin task.\n- When Cordis is a plausible fit, infer the intended work target and lifetime from the request and conversation. Use it only when the outcome belongs to the current running harness and should be delivered as a temporary runtime extension. If that distinction is materially ambiguous, ask at most one concise question about the intended result or lifetime. Otherwise proceed with the matching workflow; do not require the user to know or choose Cordis as an implementation mechanism.\n- Once a dynamic Plugin is appropriate, decide whether the task creates a new Plugin or modifies the Plugin named by the user with @pluginId. Proceed directly when the goal is clear; do not ask for repeated confirmation.\n- Choose Host, Client, or both from the requested outcome. Do not propose a Client/browser UI when the task does not need visible page behavior, and do not avoid Client when the requested outcome is visual, interactive, or depends on page state. Host versus Client is an implementation choice; do not make the user choose it.\n- When a design direction or a potentially useful interface would materially affect the result, ask at most one concise outcome or creative-preference question and offer a few candidate directions. Otherwise proceed directly; do not conduct a multi-round interview or a complex questionnaire.\n- cordis_define only defines and presents code; it does not run it. After definition, explain the pluginId and packageId returned by the Host and whether the next step is a run or update.\n- cordis_run may require user approval. When it returns awaiting-approval, explain that the user must allow or reject it in the UI. Do not wait, retry, or claim that it is running.\n- When it returns starting, explain that the request has entered the asynchronous flow and the Client is still activating. starting does not mean success. Wait for the system to report the final result through steering context.\n- Do not request approval again after the user rejects it. After a technical failure, fix the same Plugin from its diagnostics; do not silently create a replacement Plugin.\n\n## Recommended workflow and Tools\n\nBefore creating, modifying, or repairing a Plugin, load the cordis-plugin-development Skill. The Skill provides requirement navigation, capability composition, complete examples, and troubleshooting. Treat Inspect Provider results as the source of truth for exact APIs.\n\n1. cordis_inspect_list: discover the current Host and Client Providers and their read-only query methods.\n2. cordis_inspect_query: use the returned platform, provider, method, and schema to query exact Service, Event, Builtin, Slot, Theme token, or Tool information.\n3. cordis_inspect_self: inspect the current Session's Plugins, Packages, version pointers, source, and diagnostics. Source is returned only when both pluginId and packageId are specified.\n4. cordis_define: create the first Package for a new Plugin or append an immutable Package to an existing Plugin. It defines code but does not run it.\n5. cordis_run: activate an exact Package. Use run for the first activation, restarting current, or rollback; use update to switch versions.\n6. cordis_stop: remove the current Run and pending approval request while retaining definitions, grants, and version pointers.\n7. cordis_undefine: permanently stop and delete a Plugin and all of its Packages. Use it only after confirming that the user no longer needs them.\n\n- Inspect and Catalog data only confirm capabilities, names, signatures, types, and registration protocols before code is written; they do not replace business APIs.\n- Query Service.listService and Event.listEvents without input to choose from their compact signature directories, then query the exact service or event before using it. Exact queries return the structured contract and only its referenced types.\n- At runtime, a Plugin must call real Services or listen to real Events. Do not cache, display, or depend on Inspect results as business data.\n\n## Identity, versions, and approval\n\n- pluginId identifies a Plugin that can be modified over time. For a new Plugin, submit only a semantic idPrefix of 3–6 lowercase English letters; the Host allocates the final ID.\n- packageId identifies one immutable Host/Client source version under a Plugin. To change code, define a new Package; never overwrite an old version.\n- pluginRunId identifies one activation attempt and connects its approval, Host/Client loading, private RPC, Run card, and errors.\n- currentPackageId is the most recent fully successful Package. Stopping, starting an update, or failing an update does not clear it.\n- nextPackageId is the target awaiting approval, being attempted, awaiting Client activation, or most recently failed.\n- A single check mark authorizes only the current Package; double check marks authorize future versions of the same Plugin. A grant remains in effect after a technical failure.\n- An update stops the old Run before starting the target Package. Failure does not automatically restart the old version; retry next with update or roll back to current with run.\n\nWhen the user enters @pluginId, the system injects identity, the default base Package, version pointers, and runtime status, but not source code:\n\n1. Call cordis_inspect_self(pluginId, packageId) to read the target source.\n2. Use cordis_define in existing mode to append a Package to the same Plugin.\n3. Call cordis_run in run or update mode according to the version relationship.\n\nNever silently create another Plugin for @pluginId. If the reference is unavailable because it was removed, belongs to another Session, or was lost on process restart, tell the user directly.\n\n## High-frequency errors that must be avoided\n\n### Services: ctx.get and inject\n\n- Read an optional Service with ctx.get('serviceName') by default and handle undefined.\n- Declare inject: ['serviceName'] on the returned Plugin object only when the Service is a hard dependency and the Plugin must enter waiting until Cordis reactivates it after the Service appears.\n- Read ctx.serviceName only after declaring that Service in inject. Never access an undeclared Service as a ctx property.\n\n```js\nreturn {\n inject: ['requiredService'],\n apply(ctx) {\n ctx.requiredService.someMethod()\n const optionalService = ctx.get('optionalService')\n if (optionalService !== undefined) optionalService.someMethod()\n },\n}\n```\n\n### Code: use plain JavaScript only\n\n- Host and Client code is not transformed by TypeScript, JSX, or a bundler.\n- Do not use TypeScript types, as, decorators, import, require, or JSX.\n- Client React code must use React.createElement(...); never write .\n- Do not assume that process, Buffer, window, document, fetch, native timers, or any other global is available. Query the corresponding platform's Builtins and Services first.\n\n### Data: do not serialize live data\n\n- Services, Events, Slots, Sessions, and their derived Cordis/DSH objects are internal live data, not ordinary JSON that can be dumped.\n- Do not apply JSON.stringify, structuredClone, recursive enumeration, full copying, or whole-object display to live data.\n- Read only the leaf fields required by the task, then construct the smallest owned data object without Host references.\n\n### Lifecycle: every side effect must be reversible\n\n- Services, Events, Tools, handlers, timers, Slots, styles, and theme overrides must all belong to the current Fiber.\n- Use ctx.effect(), ctx.on(), or official APIs that return a disposer so stop, update, or undefine removes every side effect.\n- The cordis-plugin-development Skill contains complete timer, Waterfall, Slot, theme, Tool, RPC, and React examples and troubleshooting guidance.\n\n## Host and Client\n\n- Host runs in the DSH Node.js process and is appropriate for files, networking, commands, Agent/Session access, Host Events, Services, model Tools, and JSON methods callable by the Client.\n- Client runs in the browser page and is appropriate for themes, layout, current page state, Tool cards, and Slot UI.\n- Host and Client communicate through Package-private JSON methods: Host uses harness.handle(method, handler), and Client uses host.call(method, args). The direction is Client→Host, and only lossless JSON may cross it.\n- Client UI must be registered in a queried Slot; apply() cannot directly return a React Element. Query Slots.listSubTree without root to choose from the compact purpose/topology tree, then query the exact root for its full registration contract and props before writing code.\n- See the Skill and Inspect Providers for Run-specific panels and exact Slot registration patterns.\n\n## Asynchronous results and recovery\n\n- Do not wait inside a Tool for approval or browser work that can happen only after the current turn ends.\n- Asynchronous success, rejection, and runtime errors update Run state and notify you through steering context.\n- After a technical failure, use cordis_inspect_self to read the exact Package source and its message/stack. Define a corrected Package under the same Plugin and retry autonomously.\n- Use the cordis-plugin-development Skill for other failure causes, repair procedures, and complete extension patterns.\n\nUse the ralph tool ONLY when the direct human explicitly asks for a Ralph loop or fresh-agent iterative execution. Each Ralph round starts a fresh child with no conversation seed and uses the shared workspace as durable memory. Completion and blockers are worker reports, not independent evaluation. Use same-session goal tools for ordinary long-running objectives, and plain subagents or workflows for bounded delegation and fan-out.\n\nUse subagent in the background by default. Start independent delegations together in one assistant message and continue useful work while they run. Set `run_in_background: false` only when your next action depends on that subagent's result. When a background run settles, the runtime sends you a notice containing its outcome and any final assistant message.\n\n## Writing code for run_code\n\n`run_code` takes two required arguments: `code` — the body of an async TypeScript function (erasable syntax only — no `enum` or namespaces; type annotations are advisory, the code runs type-stripped) — and `description`, a short summary of what the program does. Inside the program:\n\n- Call tools as `await tools.name(args)` — quoted access for exotic names: `tools[\"my-tool\"](args)`. Every call resolves to the tool's typed canonical JSON value. Tool arguments must be lossless JSON.\n- A FAILED tool call rejects with `ToolCallError`, whose `toolName` identifies the failed tool and whose `message` is human-readable — `try/catch` it to handle and continue.\n- Independent read-only calls MAY overlap under `Promise.all` (safe calls run concurrently; mutating calls run alone, in submission order). Sequence dependent work with `await`.\n- Emit results with `return` and/or `console.log(...)`. ONLY what you print or return comes back to you — intermediate tool results never enter the conversation, so extract just what you need.\n\nThe available tools:\n\n```ts\ntype JsonValue = null | boolean | number | string | JsonValue[] | { [key: string]: JsonValue }\n\ninterface ToolArgsMap {\n /** Execute a bash command (`bash -c`) and return its stdout/stderr. Each call runs in a fresh shell: no state (cwd, variables, functions) persists between calls — pass `workdir` instead of using `cd`. Non-zero exits are reported as `[exit code: N]`. Current harness environment facts are exposed through managed `$DSH_*` variables; inspect them when needed. Commands may run under a file sandbox; a blocked file operation is reported as `[sandbox: file access denied under mode]` — a policy denial, not a bug in the command; do not retry another way. Long output is truncated to its tail; the full output is saved to a file whose path is reported when available. Set `run_in_background: true` for long-running commands: the call returns a job id immediately; read its output with `job_output` and stop it with `job_kill`. */\n bash: {\n /** The bash command to execute. */\n command: string;\n /** Clear, concise description of what this command does in active voice, 5-10 words (shown in the UI). Examples: \"ls\" → \"List files in current directory\"; \"git status\" → \"Show working tree status\"; \"npm install\" → \"Install package dependencies\". */\n description: string;\n /** Timeout in milliseconds. The executor applies its configured default and cap, and kills the command on expiry. */\n timeoutMs?: number;\n /** Working directory for this command. Defaults to the session workspace; a relative path is resolved against it. */\n workdir?: string;\n /** Run in the background and return a job id immediately (collect with job_output, stop with job_kill). No timeout applies. */\n run_in_background?: boolean;\n } & Record;\n /** Define an immutable Cordis Package. For a new Plugin, use kind:\"new\" and provide only a semantic prefix of 3–6 lowercase English letters; the Host returns the final pluginId and packageId. To modify an existing Plugin, use kind:\"existing\" with its exact pluginId to append a Package without overwriting older versions. Provide at least one of code.host and code.client. Each value is a plain JavaScript function body that returns a Cordis Plugin; no TypeScript, JSX, or import transformation occurs. Query Inspect before depending on a Service, Event, Builtin, Slot, or token. Define only validates parameters and syntax and records source: it does not request approval, execute apply, or change currentPackageId. On success, call cordis_run with the returned IDs. */\n cordis_define: {\n plugin: {\n kind: \"new\";\n /** Suggested semantic prefix of 3–6 lowercase English letters; the Host adds a unique numeric suffix. */\n idPrefix: string;\n } | {\n kind: \"existing\";\n /** Exact ID of an existing Plugin; the new Package is appended to that instance. */\n pluginId: string;\n };\n /** Short, readable Package name. */\n name: string;\n /** One-sentence, user-facing description of the Package purpose. */\n purpose: string;\n code: {\n /** Plain JavaScript function body that returns the Host-half Cordis Plugin. */\n host?: string;\n /** Plain JavaScript function body that returns the browser Client-half Cordis Plugin. */\n client?: string;\n };\n } & Record;\n /** List every Cordis Inspect Provider currently known to the Host, including local Host Providers and the latest manifests synchronized from the Client. Each entry includes its platform, purpose, read-only methods, and input/output schemas. Call this Tool before creating or modifying a Package, then select the provider and method for cordis_inspect_query from its result. Do not guess names or treat an Inspect method as a business Service that Plugin code can call. */\n cordis_inspect_list: Record;\n /** Run a read-only query explicitly declared by an Inspect Provider. platform, provider, and method must come from cordis_inspect_list, and input must satisfy that method's schema. Use this Tool before cordis_define to read exact Service methods, Event modes, Builtin signatures, Tool schemas, theme tokens, or live Slot trees and props. Host queries run locally. A Client query waits for the first valid page response and remains pending until a page answers or the Tool is cancelled. This Tool cannot invoke business Service methods or modify the runtime. For Service.listService and Event.listEvents, query without input to navigate the compact signature directory, then query the exact service or event for its structured contract and referenced types. For Slots.listSubTree, query without root to navigate the compact tree, then query the exact root for its complete registration contract and props. */\n cordis_inspect_query: {\n /** Runtime platform that owns the Provider. */\n platform: \"host\" | \"client\";\n /** Exact Provider ID returned by cordis_inspect_list. */\n provider: string;\n /** Exact method name declared by the Provider manifest. */\n method: string;\n /** Optional query input; it must satisfy the method input schema. */\n input?: JsonValue;\n } & Record;\n /** Inspect dynamic Cordis objects owned by the current Session at increasing levels of detail. With no IDs, list only Plugin summaries. With pluginId alone, return version pointers, the latest Run, and every Package summary. Only pluginId plus packageId returns that immutable Package's Host/Client source and runtime diagnostics. packageId cannot be supplied alone. Query an exact Package before handling @pluginId, repairing an asynchronous failure, or defining an updated version. This Tool is read-only: it neither executes code nor changes version pointers. */\n cordis_inspect_self: {\n /** Stable Plugin ID returned by cordis_define or injected by @pluginId; omit it to list every current Plugin. */\n pluginId?: string;\n /** Exact immutable Package ID owned by pluginId; when specified, source and diagnostics are returned. */\n packageId?: string;\n } & Record;\n /** Activate one exact Package of a dynamic Plugin. Use mode:\"run\" for the first activation, restarting currentPackageId, or rollback. When current exists, use mode:\"update\" to switch to a different Package, even if the Plugin is currently stopped. An unauthorized Client Package creates an approval request and returns awaiting-approval; an authorized Package returns starting and continues asynchronously in the browser. Neither result waits for the final outcome inside the Tool. currentPackageId changes only after complete success; on failure, the old current and target next remain. Asynchronous success, rejection, or technical failure is reported through state and steering. After a technical failure, read diagnostics with cordis_inspect_self, correct the same Plugin, and retry autonomously. Do not request approval again after the user rejects it. */\n cordis_run: {\n /** Stable Plugin ID returned by cordis_define. */\n pluginId: string;\n /** Exact immutable Package ID to activate under that Plugin. */\n packageId: string;\n /** Use run for the first activation, restarting current, or rollback; use update to switch from current to a different Package. */\n mode: \"run\" | \"update\";\n } & Record;\n /** Stop the current Run of a dynamic Plugin and cancel unfinished approval or activation requests. Retain the Plugin, every immutable Package, grants, currentPackageId, and nextPackageId so it can later run or update directly. Stopping an already stopped Plugin succeeds idempotently. Use this Tool to disable effects temporarily; use cordis_undefine for permanent removal. */\n cordis_stop: {\n /** Stable dynamic Plugin ID to stop. */\n pluginId: string;\n } & Record;\n /** Permanently remove a dynamic Plugin owned by the current Session. If it is running or awaiting approval, first stop it and cancel the request, then delete every Package, grant, and version pointer. After this returns, its pluginId, packageIds, @ reference, and Package business views are invalid; historical cards retain only a \"Plugin removed\" record. Do not call this Tool when versions must remain available for restart or rollback; use cordis_stop instead. */\n cordis_undefine: {\n /** Stable dynamic Plugin ID to remove permanently. */\n pluginId: string;\n } & Record;\n /** Edit an existing UTF-8 text file by replacing literal text. */\n edit: {\n /** Path to edit, resolved by the filesystem backend. */\n file_path: string;\n /** Literal text to replace. Must match exactly. */\n old_string: string;\n /** Literal replacement text. Use an empty string to delete the match. */\n new_string: string;\n /** Replace all matches. Defaults to false; when false, old_string must appear exactly once. */\n replace_all?: boolean;\n } & Record;\n /** Request cancellation of a background agent's current turn by its agent id. The target may be your direct child or a deeper agent created under you. Only the current turn stops: messages already queued for the agent stay parked until a later send_message, agents it started keep running, and the agent itself stays available for follow-ups. This call returns as soon as the stop request is accepted, so the target may keep running briefly; interrupting an agent that already finished is an accepted no-op. */\n interrupt_agent: {\n /** The agent id of the running agent to interrupt. */\n agent_id: string;\n } & Record;\n /** Request cancellation of a running background job by job id. Returns immediately; the job settles as killed once its work actually stops. */\n job_kill: {\n /** Job id returned by the tool that started the background work. */\n job_id: string;\n /** Optional short reason, recorded in the log and forwarded to the job. */\n reason?: string;\n } & Record;\n /** List your background jobs (running and finished) with their ids, kinds, and statuses. */\n job_list: Record;\n /** Read a background job. Stream jobs return only output since the previous read; final-output jobs return their result after settlement. Every response ends with `[status: ...]`. Reads are non-blocking unless `wait: true`, which waits up to the configured cap. */\n job_output: {\n /** Job id returned by the tool that started the background work. */\n job_id: string;\n /** Block until the job reaches a terminal status or the timeout expires. A timed-out wait returns [status: running] and leaves the job alive. */\n wait?: boolean;\n /** Max wait in milliseconds (only meaningful with wait: true). Defaults to the configured wait timeout; capped by the configured maximum. */\n timeout_ms?: number;\n } & Record;\n /** Run a foreground fresh-agent Ralph loop toward one immutable objective. Use only when the direct human explicitly asks for Ralph or fresh-agent iteration. Each round opens a new child with no parent conversation or prior child session; the shared workspace is long-term memory, and only a bounded structured report crosses rounds. The call returns when a worker reports completion or a concrete blocker, or at the round limit. Ordinary long-running same-session work belongs to goal tools. */\n ralph: {\n /** The immutable completion objective for every fresh Ralph round. */\n objective: string;\n /** Optional positive safe-integer round cap, bounded by the deployment ceiling. */\n maxRounds?: number;\n } & Record;\n /** Read a UTF-8 text file and return line-numbered content. */\n read: {\n /** Path to read, resolved by the filesystem backend. */\n file_path: string;\n /** 1-based first line to return. Defaults to 1. */\n offset?: number;\n /** Maximum number of lines to return. Defaults to 2000. */\n limit?: number;\n } & Record;\n /** Send a message to a background subagent by its subagent id, continuing the same conversation. It becomes the subagent's next turn: if it is still working, the message waits until its current turn finishes, so it cannot redirect work already underway. This call returns no answer from the subagent — only confirmation that the message was delivered — so use it to give it more work. A failure means the message was NOT delivered. */\n send_message: {\n /** The subagent id returned when the background subagent was started. */\n subagent_id: string;\n /** The message to deliver to the subagent. */\n message: string;\n } & Record;\n /** Load the full instructions for an available skill. Call this with the exact skill name from the session skill catalog before acting on a task that names or clearly matches that skill. */\n skill: {\n /** The exact skill name from the available skills list. */\n name: string;\n } & Record;\n /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. Give it a complete, standalone prompt: it does not see this conversation. This tool runs in the background by default, immediately returns a durable subagent id, and keeps the child conversation available for later turns. When that run settles, the runtime sends the parent a notice containing its outcome and any final assistant message; `send_message` starts a later turn in the same child conversation. Set `run_in_background: false` only when your next action depends on receiving the result. */\n subagent: {\n /** A short (3-5 word) description of the delegated task, for display. */\n description: string;\n /** The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs. */\n prompt: string;\n /** Whether to run in the background and return a durable subagent id immediately. Defaults to true. Set false to wait for the result when your next action depends on it. */\n run_in_background?: boolean;\n } & Record;\n /** Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This call waits for the subagent and returns its result. */\n subagent_fork: {\n /** A short (3-5 word) description of the delegated task, for display. */\n description: string;\n /** The task for the subagent. It already sees this conversation's completed turns, so build on them freely and state only what is new. */\n prompt: string;\n } & Record;\n /** Record and update a structured task list for the current work. Send the ENTIRE list every call — it REPLACES the previous list (there are no partial updates, no per-item edits). Use it to plan multi-step work and show progress: add one todo per concrete step before you start. Mark every todo being actively worked on `in_progress` — several at once when work genuinely runs in parallel (e.g. concurrent subagents or background commands), one for sequential work; while work remains, at least one task should be `in_progress`. Mark a todo `completed` the moment it is done (do not batch completions), and allow no `in_progress` item only once all work is complete. Skip the list for trivial single-step tasks. Statuses: `pending` (not started), `in_progress` (being worked on now), `completed` (finished). */\n todo_write: {\n /** The COMPLETE task list, replacing any previous list. */\n todos: ({\n /** What the task is — a short imperative line. */\n content: string;\n /** pending (not started) | in_progress (now) | completed (done). */\n status: \"pending\" | \"in_progress\" | \"completed\";\n })[];\n } & Record;\n /** Run a JavaScript workflow script that orchestrates subagents at scale. Use this for work that fans out across many independent pieces — an audit over many files, a migration, multi-angle research, adversarial verification of findings — where you write the orchestration as a script instead of delegating turn by turn. The workflow's identity rides the `meta` parameter as JSON: required `name` (short kebab-case) and `description` strings, optional `whenToUse` string and `phases` array (`{title, detail?, provider?, model?}`). The `script` parameter is the plain JavaScript body ONLY (NOT TypeScript, and NO `export const meta` statement — meta is a parameter, not code), running with top-level await; end with `return ` — the value must be JSON-serializable and is this tool's result. Script-body hooks: - `agent(prompt, opts?): Promise` — run one subagent to completion. Without `opts.schema` it resolves to the child's final text; with `opts.schema` (an object-rooted JSON Schema using ONLY type/properties/required/additionalProperties/items/enum/const/oneOf — no pattern/format/numeric bounds) it resolves to the validated object. Resolves `null` when the child fails (filter with `.filter(Boolean)`). Other opts: `label` (display), `phase` (progress group), and independent `provider`/`model` LLM target overrides (either may be provided alone). Anything else (`effort`/`isolation`/`agentType`) is rejected loudly. - `pipeline(items, ...stages): Promise` — run each item through the stages independently with NO barrier between stages (prefer this for multi-stage work). Each stage receives `(prev, item, index)`. An ordinary stage throw drops that ITEM to `null` and skips its remaining stages. - `parallel(thunks): Promise` — run zero-argument functions concurrently and await ALL of them (a barrier; use only when a stage genuinely needs every prior result together). A throwing thunk resolves to `null`. - `phase(title)` — start a progress phase; `log(message)` — narrate progress; `args` — the tool call's `args` input, verbatim. Misused hooks (bad arguments, unknown options, unsupported schemas, tripped caps) throw errors that ALWAYS kill the script — they never dissolve into a per-item `null`. Constraints: concurrency and total-agent caps apply; no filesystem, network, timers, or Node.js APIs are provided — the agents do the work, the script only coordinates them. The run executes in the foreground: this call returns when the whole script finishes. */\n workflow: {\n /** The plain-JS workflow script body (top-level await allowed; NO `export const meta` statement; end with `return `). */\n script: string;\n /** The workflow identity block (plain JSON — never code). */\n meta: {\n /** Short kebab-case workflow name. */\n name: string;\n /** One-line description of what the workflow does. */\n description: string;\n /** Optional guidance on when this workflow applies. */\n whenToUse?: string;\n /** Optional phase declarations matched by phase() calls. */\n phases?: ({\n /** The phase title phase() calls match by exact string. */\n title: string;\n /** Optional one-line description of the phase. */\n detail?: string;\n /** Optional provider override this phase is expected to use. */\n provider?: string;\n /** Optional model override this phase is expected to use. */\n model?: string;\n } & Record)[];\n } & Record;\n /** Optional JSON input exposed to the script as the `args` global (wrap a bare list as a field, e.g. {\"files\": [...]}). */\n args?: Record;\n } & Record;\n /** Create or fully replace a UTF-8 text file. */\n write: {\n /** Path to write, resolved by the filesystem backend. */\n file_path: string;\n /** Full UTF-8 text content to write. */\n content: string;\n } & Record;\n}\n\ninterface ToolOutputMap {\n bash: {\n kind: \"background\";\n jobId: string;\n } | {\n kind: \"foreground\";\n exitCode: number | null;\n signal: string | null;\n timedOut: boolean;\n aborted: boolean;\n timeoutMs: number;\n stdout: {\n text: string;\n truncated: boolean;\n spillPath?: string;\n };\n stderr: {\n text: string;\n truncated: boolean;\n spillPath?: string;\n };\n sandbox?: {\n mode: string;\n denied: boolean;\n enforcement?: string;\n runnerFailed?: boolean;\n };\n };\n cordis_define: {\n pluginId: string;\n packageId: string;\n name: string;\n purpose: string;\n hasHostHalf: boolean;\n hasClientHalf: boolean;\n };\n cordis_inspect_list: JsonValue;\n cordis_inspect_query: JsonValue;\n cordis_inspect_self: JsonValue;\n cordis_run: JsonValue;\n cordis_stop: {\n pluginId: string;\n };\n cordis_undefine: {\n pluginId: string;\n wasRunning: boolean;\n };\n edit: {\n path: string;\n before: string;\n after: string;\n };\n interrupt_agent: {\n accepted: boolean;\n };\n job_kill: {\n outcome: \"cancellation-requested\" | \"already-finished\";\n job: {\n id: string;\n kind: string;\n label: string;\n status: \"running\" | \"stopping\" | \"completed\" | \"killed\" | \"failed\";\n detail?: string;\n startedAt: number;\n finishedAt?: number;\n };\n };\n job_list: ({\n id: string;\n kind: string;\n label: string;\n status: \"running\" | \"stopping\" | \"completed\" | \"killed\" | \"failed\";\n detail?: string;\n startedAt: number;\n finishedAt?: number;\n })[];\n job_output: {\n text: string;\n job: {\n id: string;\n kind: string;\n label: string;\n status: \"running\" | \"stopping\" | \"completed\" | \"killed\" | \"failed\";\n detail?: string;\n startedAt: number;\n finishedAt?: number;\n };\n };\n ralph: {\n runId: string;\n agentsStarted: number;\n result: JsonValue;\n };\n read: {\n path: string;\n offset: number;\n lines: {\n number: number;\n text: string;\n }[];\n totalLines: number;\n };\n send_message: {\n messageId: string;\n };\n skill: {\n name: string;\n provider: string;\n resourceBase?: {\n kind: \"directory\";\n path: string;\n } | {\n kind: \"url\";\n url: string;\n } | {\n kind: \"opaque\";\n description: string;\n };\n content: string;\n };\n subagent: {\n kind: \"background\";\n jobId: string;\n } | {\n kind: \"continuable\";\n subagentId: string;\n } | {\n kind: \"foreground\";\n runId: string;\n output: JsonValue[];\n };\n subagent_fork: {\n kind: \"background\";\n jobId: string;\n } | {\n kind: \"continuable\";\n subagentId: string;\n } | {\n kind: \"foreground\";\n runId: string;\n output: JsonValue[];\n };\n todo_write: {\n todos: ({\n content: string;\n status: \"pending\" | \"in_progress\" | \"completed\";\n })[];\n counts: {\n pending: number;\n inProgress: number;\n completed: number;\n };\n };\n workflow: {\n runId: string;\n agentsStarted: number;\n result: JsonValue;\n };\n write: {\n path: string;\n operation: \"create\" | \"update\";\n before: string | null;\n after: string;\n };\n}\n\ntype ToolName = keyof ToolOutputMap\n\ndeclare class ToolCallError extends Error {\n readonly name: \"ToolCallError\";\n readonly toolName: ToolName;\n}\n\ndeclare const tools: {\n [K in ToolName]: (args: ToolArgsMap[K]) => Promise;\n}\n```","tools":[{"name":"bash","description":"Execute a bash command (`bash -c`) and return its stdout/stderr. Each call runs in a fresh shell: no state (cwd, variables, functions) persists between calls — pass `workdir` instead of using `cd`. Non-zero exits are reported as `[exit code: N]`. Current harness environment facts are exposed through managed `$DSH_*` variables; inspect them when needed. Commands may run under a file sandbox; a blocked file operation is reported as `[sandbox: file access denied under mode]` — a policy denial, not a bug in the command; do not retry another way. Long output is truncated to its tail; the full output is saved to a file whose path is reported when available. Set `run_in_background: true` for long-running commands: the call returns a job id immediately; read its output with `job_output` and stop it with `job_kill`.","parameters":{"type":"object","properties":{"command":{"type":"string","description":"The bash command to execute."},"description":{"type":"string","description":"Clear, concise description of what this command does in active voice, 5-10 words (shown in the UI). Examples: \"ls\" → \"List files in current directory\"; \"git status\" → \"Show working tree status\"; \"npm install\" → \"Install package dependencies\"."},"timeoutMs":{"type":"number","description":"Timeout in milliseconds. The executor applies its configured default and cap, and kills the command on expiry."},"workdir":{"type":"string","description":"Working directory for this command. Defaults to the session workspace; a relative path is resolved against it."},"run_in_background":{"type":"boolean","description":"Run in the background and return a job id immediately (collect with job_output, stop with job_kill). No timeout applies."}},"required":["command","description"]}},{"name":"cordis_define","description":"Define an immutable Cordis Package. For a new Plugin, use kind:\"new\" and provide only a semantic prefix of 3–6 lowercase English letters; the Host returns the final pluginId and packageId. To modify an existing Plugin, use kind:\"existing\" with its exact pluginId to append a Package without overwriting older versions. Provide at least one of code.host and code.client. Each value is a plain JavaScript function body that returns a Cordis Plugin; no TypeScript, JSX, or import transformation occurs. Query Inspect before depending on a Service, Event, Builtin, Slot, or token. Define only validates parameters and syntax and records source: it does not request approval, execute apply, or change currentPackageId. On success, call cordis_run with the returned IDs.","parameters":{"type":"object","properties":{"plugin":{"oneOf":[{"type":"object","additionalProperties":false,"properties":{"kind":{"type":"string","const":"new"},"idPrefix":{"type":"string","description":"Suggested semantic prefix of 3–6 lowercase English letters; the Host adds a unique numeric suffix."}},"required":["kind","idPrefix"]},{"type":"object","additionalProperties":false,"properties":{"kind":{"type":"string","const":"existing"},"pluginId":{"type":"string","description":"Exact ID of an existing Plugin; the new Package is appended to that instance."}},"required":["kind","pluginId"]}]},"name":{"type":"string","description":"Short, readable Package name."},"purpose":{"type":"string","description":"One-sentence, user-facing description of the Package purpose."},"code":{"type":"object","additionalProperties":false,"properties":{"host":{"type":"string","description":"Plain JavaScript function body that returns the Host-half Cordis Plugin."},"client":{"type":"string","description":"Plain JavaScript function body that returns the browser Client-half Cordis Plugin."}}}},"required":["plugin","name","purpose","code"]}},{"name":"cordis_inspect_list","description":"List every Cordis Inspect Provider currently known to the Host, including local Host Providers and the latest manifests synchronized from the Client. Each entry includes its platform, purpose, read-only methods, and input/output schemas. Call this Tool before creating or modifying a Package, then select the provider and method for cordis_inspect_query from its result. Do not guess names or treat an Inspect method as a business Service that Plugin code can call.","parameters":{"type":"object","properties":{}}},{"name":"cordis_inspect_query","description":"Run a read-only query explicitly declared by an Inspect Provider. platform, provider, and method must come from cordis_inspect_list, and input must satisfy that method's schema. Use this Tool before cordis_define to read exact Service methods, Event modes, Builtin signatures, Tool schemas, theme tokens, or live Slot trees and props. Host queries run locally. A Client query waits for the first valid page response and remains pending until a page answers or the Tool is cancelled. This Tool cannot invoke business Service methods or modify the runtime. For Service.listService and Event.listEvents, query without input to navigate the compact signature directory, then query the exact service or event for its structured contract and referenced types. For Slots.listSubTree, query without root to navigate the compact tree, then query the exact root for its complete registration contract and props.","parameters":{"type":"object","properties":{"platform":{"type":"string","description":"Runtime platform that owns the Provider.","enum":["host","client"]},"provider":{"type":"string","description":"Exact Provider ID returned by cordis_inspect_list."},"method":{"type":"string","description":"Exact method name declared by the Provider manifest."},"input":{"description":"Optional query input; it must satisfy the method input schema."}},"required":["platform","provider","method"]}},{"name":"cordis_inspect_self","description":"Inspect dynamic Cordis objects owned by the current Session at increasing levels of detail. With no IDs, list only Plugin summaries. With pluginId alone, return version pointers, the latest Run, and every Package summary. Only pluginId plus packageId returns that immutable Package's Host/Client source and runtime diagnostics. packageId cannot be supplied alone. Query an exact Package before handling @pluginId, repairing an asynchronous failure, or defining an updated version. This Tool is read-only: it neither executes code nor changes version pointers.","parameters":{"type":"object","properties":{"pluginId":{"type":"string","description":"Stable Plugin ID returned by cordis_define or injected by @pluginId; omit it to list every current Plugin."},"packageId":{"type":"string","description":"Exact immutable Package ID owned by pluginId; when specified, source and diagnostics are returned."}}}},{"name":"cordis_run","description":"Activate one exact Package of a dynamic Plugin. Use mode:\"run\" for the first activation, restarting currentPackageId, or rollback. When current exists, use mode:\"update\" to switch to a different Package, even if the Plugin is currently stopped. An unauthorized Client Package creates an approval request and returns awaiting-approval; an authorized Package returns starting and continues asynchronously in the browser. Neither result waits for the final outcome inside the Tool. currentPackageId changes only after complete success; on failure, the old current and target next remain. Asynchronous success, rejection, or technical failure is reported through state and steering. After a technical failure, read diagnostics with cordis_inspect_self, correct the same Plugin, and retry autonomously. Do not request approval again after the user rejects it.","parameters":{"type":"object","properties":{"pluginId":{"type":"string","description":"Stable Plugin ID returned by cordis_define."},"packageId":{"type":"string","description":"Exact immutable Package ID to activate under that Plugin."},"mode":{"type":"string","description":"Use run for the first activation, restarting current, or rollback; use update to switch from current to a different Package.","enum":["run","update"]}},"required":["pluginId","packageId","mode"]}},{"name":"cordis_stop","description":"Stop the current Run of a dynamic Plugin and cancel unfinished approval or activation requests. Retain the Plugin, every immutable Package, grants, currentPackageId, and nextPackageId so it can later run or update directly. Stopping an already stopped Plugin succeeds idempotently. Use this Tool to disable effects temporarily; use cordis_undefine for permanent removal.","parameters":{"type":"object","properties":{"pluginId":{"type":"string","description":"Stable dynamic Plugin ID to stop."}},"required":["pluginId"]}},{"name":"cordis_undefine","description":"Permanently remove a dynamic Plugin owned by the current Session. If it is running or awaiting approval, first stop it and cancel the request, then delete every Package, grant, and version pointer. After this returns, its pluginId, packageIds, @ reference, and Package business views are invalid; historical cards retain only a \"Plugin removed\" record. Do not call this Tool when versions must remain available for restart or rollback; use cordis_stop instead.","parameters":{"type":"object","properties":{"pluginId":{"type":"string","description":"Stable dynamic Plugin ID to remove permanently."}},"required":["pluginId"]}},{"name":"edit","description":"Edit an existing UTF-8 text file by replacing literal text.","parameters":{"type":"object","properties":{"file_path":{"type":"string","description":"Path to edit, resolved by the filesystem backend."},"old_string":{"type":"string","description":"Literal text to replace. Must match exactly."},"new_string":{"type":"string","description":"Literal replacement text. Use an empty string to delete the match."},"replace_all":{"type":"boolean","description":"Replace all matches. Defaults to false; when false, old_string must appear exactly once."}},"required":["file_path","old_string","new_string"]}},{"name":"interrupt_agent","description":"Request cancellation of a background agent's current turn by its agent id. The target may be your direct child or a deeper agent created under you. Only the current turn stops: messages already queued for the agent stay parked until a later send_message, agents it started keep running, and the agent itself stays available for follow-ups. This call returns as soon as the stop request is accepted, so the target may keep running briefly; interrupting an agent that already finished is an accepted no-op.","parameters":{"type":"object","properties":{"agent_id":{"type":"string","description":"The agent id of the running agent to interrupt."}},"required":["agent_id"]}},{"name":"job_kill","description":"Request cancellation of a running background job by job id. Returns immediately; the job settles as killed once its work actually stops.","parameters":{"type":"object","properties":{"job_id":{"type":"string","description":"Job id returned by the tool that started the background work."},"reason":{"type":"string","description":"Optional short reason, recorded in the log and forwarded to the job."}},"required":["job_id"]}},{"name":"job_list","description":"List your background jobs (running and finished) with their ids, kinds, and statuses.","parameters":{"type":"object","properties":{}}},{"name":"job_output","description":"Read a background job. Stream jobs return only output since the previous read; final-output jobs return their result after settlement. Every response ends with `[status: ...]`. Reads are non-blocking unless `wait: true`, which waits up to the configured cap.","parameters":{"type":"object","properties":{"job_id":{"type":"string","description":"Job id returned by the tool that started the background work."},"wait":{"type":"boolean","description":"Block until the job reaches a terminal status or the timeout expires. A timed-out wait returns [status: running] and leaves the job alive."},"timeout_ms":{"type":"number","description":"Max wait in milliseconds (only meaningful with wait: true). Defaults to the configured wait timeout; capped by the configured maximum."}},"required":["job_id"]}},{"name":"ralph","description":"Run a foreground fresh-agent Ralph loop toward one immutable objective. Use only when the direct human explicitly asks for Ralph or fresh-agent iteration. Each round opens a new child with no parent conversation or prior child session; the shared workspace is long-term memory, and only a bounded structured report crosses rounds. The call returns when a worker reports completion or a concrete blocker, or at the round limit. Ordinary long-running same-session work belongs to goal tools.","parameters":{"type":"object","properties":{"objective":{"type":"string","description":"The immutable completion objective for every fresh Ralph round."},"maxRounds":{"type":"number","description":"Optional positive safe-integer round cap, bounded by the deployment ceiling."}},"required":["objective"]}},{"name":"read","description":"Read a UTF-8 text file and return line-numbered content.","parameters":{"type":"object","properties":{"file_path":{"type":"string","description":"Path to read, resolved by the filesystem backend."},"offset":{"type":"number","description":"1-based first line to return. Defaults to 1."},"limit":{"type":"number","description":"Maximum number of lines to return. Defaults to 2000."}},"required":["file_path"]}},{"name":"run_code","description":"Execute a TypeScript program against the available tools. Takes two required arguments: `code`, the BODY of an async function (erasable syntax only; top-level `await` and `return` work), and `description`, a short summary of what the program does. Call tools as `await tools.name(args)` per the declarations in the system prompt. Only what you print or return comes back — curate it.","parameters":{"type":"object","properties":{"code":{"type":"string","description":"The program: the body of an async TypeScript function."},"description":{"type":"string","description":"Clear, concise description of what this program does in active voice, 5-10 words (shown in the UI). Examples: \"Count TODO markers across packages\"; \"Read failing test and its fixture\"; \"Rename config key in every cordis.yml\"."}},"required":["code","description"]}},{"name":"send_message","description":"Send a message to a background subagent by its subagent id, continuing the same conversation. It becomes the subagent's next turn: if it is still working, the message waits until its current turn finishes, so it cannot redirect work already underway. This call returns no answer from the subagent — only confirmation that the message was delivered — so use it to give it more work. A failure means the message was NOT delivered.","parameters":{"type":"object","properties":{"subagent_id":{"type":"string","description":"The subagent id returned when the background subagent was started."},"message":{"type":"string","description":"The message to deliver to the subagent."}},"required":["subagent_id","message"]}},{"name":"skill","description":"Load the full instructions for an available skill. Call this with the exact skill name from the session skill catalog before acting on a task that names or clearly matches that skill.","parameters":{"type":"object","properties":{"name":{"type":"string","description":"The exact skill name from the available skills list."}},"required":["name"]}},{"name":"subagent","description":"Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. Give it a complete, standalone prompt: it does not see this conversation. This tool runs in the background by default, immediately returns a durable subagent id, and keeps the child conversation available for later turns. When that run settles, the runtime sends the parent a notice containing its outcome and any final assistant message; `send_message` starts a later turn in the same child conversation. Set `run_in_background: false` only when your next action depends on receiving the result.","parameters":{"type":"object","properties":{"description":{"type":"string","description":"A short (3-5 word) description of the delegated task, for display."},"prompt":{"type":"string","description":"The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs."},"run_in_background":{"type":"boolean","description":"Whether to run in the background and return a durable subagent id immediately. Defaults to true. Set false to wait for the result when your next action depends on it."}},"required":["description","prompt"]}},{"name":"subagent_fork","description":"Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This call waits for the subagent and returns its result.","parameters":{"type":"object","properties":{"description":{"type":"string","description":"A short (3-5 word) description of the delegated task, for display."},"prompt":{"type":"string","description":"The task for the subagent. It already sees this conversation's completed turns, so build on them freely and state only what is new."}},"required":["description","prompt"]}},{"name":"todo_write","description":"Record and update a structured task list for the current work. Send the ENTIRE list every call — it REPLACES the previous list (there are no partial updates, no per-item edits). Use it to plan multi-step work and show progress: add one todo per concrete step before you start. Mark every todo being actively worked on `in_progress` — several at once when work genuinely runs in parallel (e.g. concurrent subagents or background commands), one for sequential work; while work remains, at least one task should be `in_progress`. Mark a todo `completed` the moment it is done (do not batch completions), and allow no `in_progress` item only once all work is complete. Skip the list for trivial single-step tasks. Statuses: `pending` (not started), `in_progress` (being worked on now), `completed` (finished).","parameters":{"type":"object","properties":{"todos":{"type":"array","description":"The COMPLETE task list, replacing any previous list.","items":{"type":"object","additionalProperties":false,"properties":{"content":{"type":"string","description":"What the task is — a short imperative line."},"status":{"type":"string","description":"pending (not started) | in_progress (now) | completed (done).","enum":["pending","in_progress","completed"]}},"required":["content","status"]}}},"required":["todos"]}},{"name":"workflow","description":"Run a JavaScript workflow script that orchestrates subagents at scale. Use this for work that fans out across many independent pieces — an audit over many files, a migration, multi-angle research, adversarial verification of findings — where you write the orchestration as a script instead of delegating turn by turn.\n\nThe workflow's identity rides the `meta` parameter as JSON: required `name` (short kebab-case) and `description` strings, optional `whenToUse` string and `phases` array (`{title, detail?, provider?, model?}`). The `script` parameter is the plain JavaScript body ONLY (NOT TypeScript, and NO `export const meta` statement — meta is a parameter, not code), running with top-level await; end with `return ` — the value must be JSON-serializable and is this tool's result.\n\nScript-body hooks:\n- `agent(prompt, opts?): Promise` — run one subagent to completion. Without `opts.schema` it resolves to the child's final text; with `opts.schema` (an object-rooted JSON Schema using ONLY type/properties/required/additionalProperties/items/enum/const/oneOf — no pattern/format/numeric bounds) it resolves to the validated object. Resolves `null` when the child fails (filter with `.filter(Boolean)`). Other opts: `label` (display), `phase` (progress group), and independent `provider`/`model` LLM target overrides (either may be provided alone). Anything else (`effort`/`isolation`/`agentType`) is rejected loudly.\n- `pipeline(items, ...stages): Promise` — run each item through the stages independently with NO barrier between stages (prefer this for multi-stage work). Each stage receives `(prev, item, index)`. An ordinary stage throw drops that ITEM to `null` and skips its remaining stages.\n- `parallel(thunks): Promise` — run zero-argument functions concurrently and await ALL of them (a barrier; use only when a stage genuinely needs every prior result together). A throwing thunk resolves to `null`.\n- `phase(title)` — start a progress phase; `log(message)` — narrate progress; `args` — the tool call's `args` input, verbatim.\n\nMisused hooks (bad arguments, unknown options, unsupported schemas, tripped caps) throw errors that ALWAYS kill the script — they never dissolve into a per-item `null`.\n\nConstraints: concurrency and total-agent caps apply; no filesystem, network, timers, or Node.js APIs are provided — the agents do the work, the script only coordinates them. The run executes in the foreground: this call returns when the whole script finishes.","parameters":{"type":"object","properties":{"script":{"type":"string","description":"The plain-JS workflow script body (top-level await allowed; NO `export const meta` statement; end with `return `)."},"meta":{"type":"object","description":"The workflow identity block (plain JSON — never code).","additionalProperties":true,"properties":{"name":{"type":"string","description":"Short kebab-case workflow name."},"description":{"type":"string","description":"One-line description of what the workflow does."},"whenToUse":{"type":"string","description":"Optional guidance on when this workflow applies."},"phases":{"type":"array","description":"Optional phase declarations matched by phase() calls.","items":{"type":"object","additionalProperties":true,"properties":{"title":{"type":"string","description":"The phase title phase() calls match by exact string."},"detail":{"type":"string","description":"Optional one-line description of the phase."},"provider":{"type":"string","description":"Optional provider override this phase is expected to use."},"model":{"type":"string","description":"Optional model override this phase is expected to use."}},"required":["title"]}}},"required":["name","description"]},"args":{"type":"object","description":"Optional JSON input exposed to the script as the `args` global (wrap a bare list as a field, e.g. {\"files\": [...]}).","additionalProperties":true}},"required":["script","meta"]}},{"name":"write","description":"Create or fully replace a UTF-8 text file.","parameters":{"type":"object","properties":{"file_path":{"type":"string","description":"Path to write, resolved by the filesystem backend."},"content":{"type":"string","description":"Full UTF-8 text content to write."}},"required":["file_path","content"]}}]},"reason":"initial"}} {"type":"request/context","seq":9,"time":1785730501646,"data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"assistant/chunk","seq":10,"time":1783957884701,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"text"}}} {"type":"assistant/chunk","seq":11,"time":1783957884701,"data":{"turn":1,"step":1,"chunk":{"type":"text-delta","index":0,"text":"WORKFLOW_CHILD_OK"}}} {"type":"assistant/chunk","seq":12,"time":1783957884701,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"WORKFLOW_CHILD_OK"}}}} {"type":"assistant/chunk","seq":13,"time":1785498584067,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}} {"type":"assistant/chunk","seq":14,"time":1785730501646,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"stop"}}}} -{"type":"assistant/message","seq":15,"time":1785730501646,"data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"WORKFLOW_CHILD_OK"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"9091fda5-4d10-4d7d-8cd2-53aa493c9dd1"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[10,11,12,13,14],"surfaceOp":"append"} +{"type":"assistant/message","seq":15,"time":1785730501646,"data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"WORKFLOW_CHILD_OK"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"cd78f077-1fad-4cdc-ab56-09d39d9095cd"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[10,11,12,13,14],"surfaceOp":"append"} {"type":"step/end","seq":16,"time":1785730501646,"data":{"turn":1,"step":1}} {"type":"turn/end","seq":17,"time":1785730501646,"data":{"turn":1,"reason":{"kind":"completed"}}} diff --git a/examples/headless-agent/tests/snapshots/advanced-toolchain/session.jsonl b/examples/headless-agent/tests/snapshots/advanced-toolchain/session.jsonl index a7183e045c..19e4ec8138 100644 --- a/examples/headless-agent/tests/snapshots/advanced-toolchain/session.jsonl +++ b/examples/headless-agent/tests/snapshots/advanced-toolchain/session.jsonl @@ -1,20 +1,20 @@ {"type":"session","version":0,"id":"11111111-1111-4111-8111-111111111111","createdAt":1783950000000,"cwd":"{{cwd}}","delegationDepth":0} -{"type":"agent/inbox/spliced","seq":0,"time":1785498583746,"data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Run this advanced flow exactly once: define a host-only dynamic Cordis Package named Snapshot Marker; run and inspect snap-1/pkg-1 through run_code; delegate once to a direct spawn child; run one workflow that delegates to another spawn child; remove snap-1; then reply with exactly ADVANCED_HEADLESS_OK."}],"source":{"kind":"user"},"role":"user","id":"eeafe3ec-26b4-4e44-ae07-96422e3691ac"}]}} +{"type":"agent/inbox/spliced","seq":0,"time":1785498583746,"data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Run this advanced flow exactly once: define a host-only dynamic Cordis Package named Snapshot Marker; run and inspect snap-1/pkg-1 through run_code; delegate once to a direct spawn child; run one workflow that delegates to another spawn child; remove snap-1; then reply with exactly ADVANCED_HEADLESS_OK."}],"source":{"kind":"user"},"role":"user","id":"8a0ac233-283c-4eb4-8bbd-5c50b7e99afe"}]}} {"type":"turn/start","seq":1,"time":1785821454304,"data":{"turn":1}} {"type":"agent/inbox/spliced","seq":2,"time":1785821454304,"data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","seq":3,"time":1783957884486,"data":{"turn":1,"step":1}} -{"type":"user/message","seq":4,"time":1785498583779,"data":{"content":[{"type":"text","text":"Run this advanced flow exactly once: define a host-only dynamic Cordis Package named Snapshot Marker; run and inspect snap-1/pkg-1 through run_code; delegate once to a direct spawn child; run one workflow that delegates to another spawn child; remove snap-1; then reply with exactly ADVANCED_HEADLESS_OK."}],"source":{"kind":"user"},"role":"user","id":"eeafe3ec-26b4-4e44-ae07-96422e3691ac"},"surfaceOp":"append"} +{"type":"user/message","seq":4,"time":1785498583779,"data":{"content":[{"type":"text","text":"Run this advanced flow exactly once: define a host-only dynamic Cordis Package named Snapshot Marker; run and inspect snap-1/pkg-1 through run_code; delegate once to a direct spawn child; run one workflow that delegates to another spawn child; remove snap-1; then reply with exactly ADVANCED_HEADLESS_OK."}],"source":{"kind":"user"},"role":"user","id":"8a0ac233-283c-4eb4-8bbd-5c50b7e99afe"},"surfaceOp":"append"} {"type":"session/title","seq":5,"time":1785498583779,"data":{"title":"Run this advanced flow exactly","messageSeqs":[4],"source":{"kind":"fallback"}}} -{"type":"request/header","seq":6,"time":1785498583782,"data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"system":"You are an AI agent powered by DeepSeek Harness.\n\nYou are headless-agent, a coding assistant powered by the deepseek-v4-flash model. Your working directory is {{cwd}}.\n\nVerify your work by running the code or tests. Keep answers brief and factual.\n\n\nUse the read tool — not shell commands like cat — to inspect text files. Results include line numbers. Use offset and limit to continue reading large files.\n\nUse the write tool to create files or completely replace file contents. Existing files are overwritten, so read an existing file first (the default fs-observation-policy requires it) and prefer edit for targeted changes.\n\nUse the edit tool for targeted changes to existing UTF-8 text files. It replaces literal old_string with new_string; by default old_string must appear exactly once. If old_string appears multiple times, provide a more specific old_string or set replace_all to true. Read the file first (the default fs-observation-policy requires it), unless you just created or edited it in this session.\n\nCheck the [exit code: N] marker on every bash result; investigate failures before moving on.\n\nTrack every background job id you start. You are notified in-session when a job finishes — do not busy-poll or sleep on one; keep working on independent steps and do not duplicate a running job's work. Before giving a final answer, collect every still-relevant job with job_output (set wait: true only when you are genuinely blocked on it), and job_kill jobs that stopped mattering.\n\nUse the workflow tool ONLY when the user explicitly asks for a workflow or for large multi-agent orchestration: you write a JavaScript script (the tool description documents the exact format) that fans work out across many subagents with phases and structured results. For one or two delegations, prefer plain subagent calls.\n\n# Dynamic Cordis Plugins\n\nDynamic Cordis plugins temporarily extend the current DSH process. A Plugin uses apply(ctx) to consume Services, listen to Events, provide Services, register model Tools, or register browser UI in Slots.\n\n- Plugin and Package definitions exist only in the current process. define itself does not modify repository source, configuration, or disk, and definitions do not survive a process restart.\n- The restricted execution environment prevents accidental misuse; it is not a security boundary for malicious code. Services obtained by dynamic code connect to the real runtime.\n\n## Make the user-facing plan clear first\n\n- Dynamic Cordis Plugins are one available implementation mechanism, not the default for every request. Consider whether one could help only when the user intends to design or create something, or when a temporary interface could materially aid the current work. The presence of these instructions or Tools, and discussion of Cordis itself, do not make a request a dynamic-Plugin task.\n- When Cordis is a plausible fit, infer the intended work target and lifetime from the request and conversation. Use it only when the outcome belongs to the current running harness and should be delivered as a temporary runtime extension. If that distinction is materially ambiguous, ask at most one concise question about the intended result or lifetime. Otherwise proceed with the matching workflow; do not require the user to know or choose Cordis as an implementation mechanism.\n- Once a dynamic Plugin is appropriate, decide whether the task creates a new Plugin or modifies the Plugin named by the user with @pluginId. Proceed directly when the goal is clear; do not ask for repeated confirmation.\n- Choose Host, Client, or both from the requested outcome. Do not propose a Client/browser UI when the task does not need visible page behavior, and do not avoid Client when the requested outcome is visual, interactive, or depends on page state. Host versus Client is an implementation choice; do not make the user choose it.\n- When a design direction or a potentially useful interface would materially affect the result, ask at most one concise outcome or creative-preference question and offer a few candidate directions. Otherwise proceed directly; do not conduct a multi-round interview or a complex questionnaire.\n- cordis_define only defines and presents code; it does not run it. After definition, explain the pluginId and packageId returned by the Host and whether the next step is a run or update.\n- cordis_run may require user approval. When it returns awaiting-approval, explain that the user must allow or reject it in the UI. Do not wait, retry, or claim that it is running.\n- When it returns starting, explain that the request has entered the asynchronous flow and the Client is still activating. starting does not mean success. Wait for the system to report the final result through steering context.\n- Do not request approval again after the user rejects it. After a technical failure, fix the same Plugin from its diagnostics; do not silently create a replacement Plugin.\n\n## Recommended workflow and Tools\n\nBefore creating, modifying, or repairing a Plugin, load the cordis-plugin-development Skill. The Skill provides requirement navigation, capability composition, complete examples, and troubleshooting. Treat Inspect Provider results as the source of truth for exact APIs.\n\n1. cordis_inspect_list: discover the current Host and Client Providers and their read-only query methods.\n2. cordis_inspect_query: use the returned platform, provider, method, and schema to query exact Service, Event, Builtin, Slot, Theme token, or Tool information.\n3. cordis_inspect_self: inspect the current Session's Plugins, Packages, version pointers, source, and diagnostics. Source is returned only when both pluginId and packageId are specified.\n4. cordis_define: create the first Package for a new Plugin or append an immutable Package to an existing Plugin. It defines code but does not run it.\n5. cordis_run: activate an exact Package. Use run for the first activation, restarting current, or rollback; use update to switch versions.\n6. cordis_stop: remove the current Run and pending approval request while retaining definitions, grants, and version pointers.\n7. cordis_undefine: permanently stop and delete a Plugin and all of its Packages. Use it only after confirming that the user no longer needs them.\n\n- Inspect and Catalog data only confirm capabilities, names, signatures, types, and registration protocols before code is written; they do not replace business APIs.\n- Query Service.listService and Event.listEvents without input to choose from their compact signature directories, then query the exact service or event before using it. Exact queries return the structured contract and only its referenced types.\n- At runtime, a Plugin must call real Services or listen to real Events. Do not cache, display, or depend on Inspect results as business data.\n\n## Identity, versions, and approval\n\n- pluginId identifies a Plugin that can be modified over time. For a new Plugin, submit only a semantic idPrefix of 3–6 lowercase English letters; the Host allocates the final ID.\n- packageId identifies one immutable Host/Client source version under a Plugin. To change code, define a new Package; never overwrite an old version.\n- pluginRunId identifies one activation attempt and connects its approval, Host/Client loading, private RPC, Run card, and errors.\n- currentPackageId is the most recent fully successful Package. Stopping, starting an update, or failing an update does not clear it.\n- nextPackageId is the target awaiting approval, being attempted, awaiting Client activation, or most recently failed.\n- A single check mark authorizes only the current Package; double check marks authorize future versions of the same Plugin. A grant remains in effect after a technical failure.\n- An update stops the old Run before starting the target Package. Failure does not automatically restart the old version; retry next with update or roll back to current with run.\n\nWhen the user enters @pluginId, the system injects identity, the default base Package, version pointers, and runtime status, but not source code:\n\n1. Call cordis_inspect_self(pluginId, packageId) to read the target source.\n2. Use cordis_define in existing mode to append a Package to the same Plugin.\n3. Call cordis_run in run or update mode according to the version relationship.\n\nNever silently create another Plugin for @pluginId. If the reference is unavailable because it was removed, belongs to another Session, or was lost on process restart, tell the user directly.\n\n## High-frequency errors that must be avoided\n\n### Services: ctx.get and inject\n\n- Read an optional Service with ctx.get('serviceName') by default and handle undefined.\n- Declare inject: ['serviceName'] on the returned Plugin object only when the Service is a hard dependency and the Plugin must enter waiting until Cordis reactivates it after the Service appears.\n- Read ctx.serviceName only after declaring that Service in inject. Never access an undeclared Service as a ctx property.\n\n```js\nreturn {\n inject: ['requiredService'],\n apply(ctx) {\n ctx.requiredService.someMethod()\n const optionalService = ctx.get('optionalService')\n if (optionalService !== undefined) optionalService.someMethod()\n },\n}\n```\n\n### Code: use plain JavaScript only\n\n- Host and Client code is not transformed by TypeScript, JSX, or a bundler.\n- Do not use TypeScript types, as, decorators, import, require, or JSX.\n- Client React code must use React.createElement(...); never write .\n- Do not assume that process, Buffer, window, document, fetch, native timers, or any other global is available. Query the corresponding platform's Builtins and Services first.\n\n### Data: do not serialize live data\n\n- Services, Events, Slots, Sessions, and their derived Cordis/DSH objects are internal live data, not ordinary JSON that can be dumped.\n- Do not apply JSON.stringify, structuredClone, recursive enumeration, full copying, or whole-object display to live data.\n- Read only the leaf fields required by the task, then construct the smallest owned data object without Host references.\n\n### Lifecycle: every side effect must be reversible\n\n- Services, Events, Tools, handlers, timers, Slots, styles, and theme overrides must all belong to the current Fiber.\n- Use ctx.effect(), ctx.on(), or official APIs that return a disposer so stop, update, or undefine removes every side effect.\n- The cordis-plugin-development Skill contains complete timer, Waterfall, Slot, theme, Tool, RPC, and React examples and troubleshooting guidance.\n\n## Host and Client\n\n- Host runs in the DSH Node.js process and is appropriate for files, networking, commands, Agent/Session access, Host Events, Services, model Tools, and JSON methods callable by the Client.\n- Client runs in the browser page and is appropriate for themes, layout, current page state, Tool cards, and Slot UI.\n- Host and Client communicate through Package-private JSON methods: Host uses harness.handle(method, handler), and Client uses host.call(method, args). The direction is Client→Host, and only lossless JSON may cross it.\n- Client UI must be registered in a queried Slot; apply() cannot directly return a React Element. Query Slots.listSubTree without root to choose from the compact purpose/topology tree, then query the exact root for its full registration contract and props before writing code.\n- See the Skill and Inspect Providers for Run-specific panels and exact Slot registration patterns.\n\n## Asynchronous results and recovery\n\n- Do not wait inside a Tool for approval or browser work that can happen only after the current turn ends.\n- Asynchronous success, rejection, and runtime errors update Run state and notify you through steering context.\n- After a technical failure, use cordis_inspect_self to read the exact Package source and its message/stack. Define a corrected Package under the same Plugin and retry autonomously.\n- Use the cordis-plugin-development Skill for other failure causes, repair procedures, and complete extension patterns.\n\nUse the ralph tool ONLY when the direct human explicitly asks for a Ralph loop or fresh-agent iterative execution. Each Ralph round starts a fresh child with no conversation seed and uses the shared workspace as durable memory. Completion and blockers are worker reports, not independent evaluation. Use same-session goal tools for ordinary long-running objectives, and plain subagents or workflows for bounded delegation and fan-out.\n\nUse subagent in the background by default. Start independent delegations together in one assistant message and continue useful work while they run. Set `run_in_background: false` only when your next action depends on that subagent's result. When a background run settles, the runtime sends you a notice containing its outcome and any final assistant message.\n\n## Writing code for run_code\n\nPass `run_code` the body of an async TypeScript function (erasable syntax only — no `enum` or namespaces; type annotations are advisory, the code runs type-stripped). Inside the program:\n\n- Call tools as `await tools.name(args)` — quoted access for exotic names: `tools[\"my-tool\"](args)`. Every call resolves to the tool's typed canonical JSON value. Tool arguments must be lossless JSON.\n- A FAILED tool call rejects with `ToolCallError`, whose `toolName` identifies the failed tool and whose `message` is human-readable — `try/catch` it to handle and continue.\n- Independent read-only calls MAY overlap under `Promise.all` (safe calls run concurrently; mutating calls run alone, in submission order). Sequence dependent work with `await`.\n- Emit results with `return` and/or `console.log(...)`. ONLY what you print or return comes back to you — intermediate tool results never enter the conversation, so extract just what you need.\n\nThe available tools:\n\n```ts\ntype JsonValue = null | boolean | number | string | JsonValue[] | { [key: string]: JsonValue }\n\ninterface ToolArgsMap {\n /** Execute a bash command (`bash -c`) and return its stdout/stderr. Each call runs in a fresh shell: no state (cwd, variables, functions) persists between calls — pass `workdir` instead of using `cd`. Non-zero exits are reported as `[exit code: N]`. Current harness environment facts are exposed through managed `$DSH_*` variables; inspect them when needed. Commands may run under a file sandbox; a blocked file operation is reported as `[sandbox: file access denied under mode]` — a policy denial, not a bug in the command; do not retry another way. Long output is truncated to its tail; the full output is saved to a file whose path is reported when available. Set `run_in_background: true` for long-running commands: the call returns a job id immediately; read its output with `job_output` and stop it with `job_kill`. */\n bash: {\n /** The bash command to execute. */\n command: string;\n /** Clear, concise description of what this command does in active voice, 5-10 words (shown in the UI). Examples: \"ls\" → \"List files in current directory\"; \"git status\" → \"Show working tree status\"; \"npm install\" → \"Install package dependencies\". */\n description: string;\n /** Timeout in milliseconds. The executor applies its configured default and cap, and kills the command on expiry. */\n timeoutMs?: number;\n /** Working directory for this command. Defaults to the session workspace; a relative path is resolved against it. */\n workdir?: string;\n /** Run in the background and return a job id immediately (collect with job_output, stop with job_kill). No timeout applies. */\n run_in_background?: boolean;\n } & Record;\n /** Define an immutable Cordis Package. For a new Plugin, use kind:\"new\" and provide only a semantic prefix of 3–6 lowercase English letters; the Host returns the final pluginId and packageId. To modify an existing Plugin, use kind:\"existing\" with its exact pluginId to append a Package without overwriting older versions. Provide at least one of code.host and code.client. Each value is a plain JavaScript function body that returns a Cordis Plugin; no TypeScript, JSX, or import transformation occurs. Query Inspect before depending on a Service, Event, Builtin, Slot, or token. Define only validates parameters and syntax and records source: it does not request approval, execute apply, or change currentPackageId. On success, call cordis_run with the returned IDs. */\n cordis_define: {\n plugin: {\n kind: \"new\";\n /** Suggested semantic prefix of 3–6 lowercase English letters; the Host adds a unique numeric suffix. */\n idPrefix: string;\n } | {\n kind: \"existing\";\n /** Exact ID of an existing Plugin; the new Package is appended to that instance. */\n pluginId: string;\n };\n /** Short, readable Package name. */\n name: string;\n /** One-sentence, user-facing description of the Package purpose. */\n purpose: string;\n code: {\n /** Plain JavaScript function body that returns the Host-half Cordis Plugin. */\n host?: string;\n /** Plain JavaScript function body that returns the browser Client-half Cordis Plugin. */\n client?: string;\n };\n } & Record;\n /** List every Cordis Inspect Provider currently known to the Host, including local Host Providers and the latest manifests synchronized from the Client. Each entry includes its platform, purpose, read-only methods, and input/output schemas. Call this Tool before creating or modifying a Package, then select the provider and method for cordis_inspect_query from its result. Do not guess names or treat an Inspect method as a business Service that Plugin code can call. */\n cordis_inspect_list: Record;\n /** Run a read-only query explicitly declared by an Inspect Provider. platform, provider, and method must come from cordis_inspect_list, and input must satisfy that method's schema. Use this Tool before cordis_define to read exact Service methods, Event modes, Builtin signatures, Tool schemas, theme tokens, or live Slot trees and props. Host queries run locally. A Client query waits for the first valid page response and remains pending until a page answers or the Tool is cancelled. This Tool cannot invoke business Service methods or modify the runtime. For Service.listService and Event.listEvents, query without input to navigate the compact signature directory, then query the exact service or event for its structured contract and referenced types. For Slots.listSubTree, query without root to navigate the compact tree, then query the exact root for its complete registration contract and props. */\n cordis_inspect_query: {\n /** Runtime platform that owns the Provider. */\n platform: \"host\" | \"client\";\n /** Exact Provider ID returned by cordis_inspect_list. */\n provider: string;\n /** Exact method name declared by the Provider manifest. */\n method: string;\n /** Optional query input; it must satisfy the method input schema. */\n input?: JsonValue;\n } & Record;\n /** Inspect dynamic Cordis objects owned by the current Session at increasing levels of detail. With no IDs, list only Plugin summaries. With pluginId alone, return version pointers, the latest Run, and every Package summary. Only pluginId plus packageId returns that immutable Package's Host/Client source and runtime diagnostics. packageId cannot be supplied alone. Query an exact Package before handling @pluginId, repairing an asynchronous failure, or defining an updated version. This Tool is read-only: it neither executes code nor changes version pointers. */\n cordis_inspect_self: {\n /** Stable Plugin ID returned by cordis_define or injected by @pluginId; omit it to list every current Plugin. */\n pluginId?: string;\n /** Exact immutable Package ID owned by pluginId; when specified, source and diagnostics are returned. */\n packageId?: string;\n } & Record;\n /** Activate one exact Package of a dynamic Plugin. Use mode:\"run\" for the first activation, restarting currentPackageId, or rollback. When current exists, use mode:\"update\" to switch to a different Package, even if the Plugin is currently stopped. An unauthorized Client Package creates an approval request and returns awaiting-approval; an authorized Package returns starting and continues asynchronously in the browser. Neither result waits for the final outcome inside the Tool. currentPackageId changes only after complete success; on failure, the old current and target next remain. Asynchronous success, rejection, or technical failure is reported through state and steering. After a technical failure, read diagnostics with cordis_inspect_self, correct the same Plugin, and retry autonomously. Do not request approval again after the user rejects it. */\n cordis_run: {\n /** Stable Plugin ID returned by cordis_define. */\n pluginId: string;\n /** Exact immutable Package ID to activate under that Plugin. */\n packageId: string;\n /** Use run for the first activation, restarting current, or rollback; use update to switch from current to a different Package. */\n mode: \"run\" | \"update\";\n } & Record;\n /** Stop the current Run of a dynamic Plugin and cancel unfinished approval or activation requests. Retain the Plugin, every immutable Package, grants, currentPackageId, and nextPackageId so it can later run or update directly. Stopping an already stopped Plugin succeeds idempotently. Use this Tool to disable effects temporarily; use cordis_undefine for permanent removal. */\n cordis_stop: {\n /** Stable dynamic Plugin ID to stop. */\n pluginId: string;\n } & Record;\n /** Permanently remove a dynamic Plugin owned by the current Session. If it is running or awaiting approval, first stop it and cancel the request, then delete every Package, grant, and version pointer. After this returns, its pluginId, packageIds, @ reference, and Package business views are invalid; historical cards retain only a \"Plugin removed\" record. Do not call this Tool when versions must remain available for restart or rollback; use cordis_stop instead. */\n cordis_undefine: {\n /** Stable dynamic Plugin ID to remove permanently. */\n pluginId: string;\n } & Record;\n /** Edit an existing UTF-8 text file by replacing literal text. */\n edit: {\n /** Path to edit, resolved by the filesystem backend. */\n file_path: string;\n /** Literal text to replace. Must match exactly. */\n old_string: string;\n /** Literal replacement text. Use an empty string to delete the match. */\n new_string: string;\n /** Replace all matches. Defaults to false; when false, old_string must appear exactly once. */\n replace_all?: boolean;\n } & Record;\n /** Request cancellation of a background agent's current turn by its agent id. The target may be your direct child or a deeper agent created under you. Only the current turn stops: messages already queued for the agent stay parked until a later send_message, agents it started keep running, and the agent itself stays available for follow-ups. This call returns as soon as the stop request is accepted, so the target may keep running briefly; interrupting an agent that already finished is an accepted no-op. */\n interrupt_agent: {\n /** The agent id of the running agent to interrupt. */\n agent_id: string;\n } & Record;\n /** Request cancellation of a running background job by job id. Returns immediately; the job settles as killed once its work actually stops. */\n job_kill: {\n /** Job id returned by the tool that started the background work. */\n job_id: string;\n /** Optional short reason, recorded in the log and forwarded to the job. */\n reason?: string;\n } & Record;\n /** List your background jobs (running and finished) with their ids, kinds, and statuses. */\n job_list: Record;\n /** Read a background job. Stream jobs return only output since the previous read; final-output jobs return their result after settlement. Every response ends with `[status: ...]`. Reads are non-blocking unless `wait: true`, which waits up to the configured cap. */\n job_output: {\n /** Job id returned by the tool that started the background work. */\n job_id: string;\n /** Block until the job reaches a terminal status or the timeout expires. A timed-out wait returns [status: running] and leaves the job alive. */\n wait?: boolean;\n /** Max wait in milliseconds (only meaningful with wait: true). Defaults to the configured wait timeout; capped by the configured maximum. */\n timeout_ms?: number;\n } & Record;\n /** Run a foreground fresh-agent Ralph loop toward one immutable objective. Use only when the direct human explicitly asks for Ralph or fresh-agent iteration. Each round opens a new child with no parent conversation or prior child session; the shared workspace is long-term memory, and only a bounded structured report crosses rounds. The call returns when a worker reports completion or a concrete blocker, or at the round limit. Ordinary long-running same-session work belongs to goal tools. */\n ralph: {\n /** The immutable completion objective for every fresh Ralph round. */\n objective: string;\n /** Optional positive safe-integer round cap, bounded by the deployment ceiling. */\n maxRounds?: number;\n } & Record;\n /** Read a UTF-8 text file and return line-numbered content. */\n read: {\n /** Path to read, resolved by the filesystem backend. */\n file_path: string;\n /** 1-based first line to return. Defaults to 1. */\n offset?: number;\n /** Maximum number of lines to return. Defaults to 2000. */\n limit?: number;\n } & Record;\n /** Send a message to a background subagent by its subagent id, continuing the same conversation. It becomes the subagent's next turn: if it is still working, the message waits until its current turn finishes, so it cannot redirect work already underway. This call returns no answer from the subagent — only confirmation that the message was delivered — so use it to give it more work. A failure means the message was NOT delivered. */\n send_message: {\n /** The subagent id returned when the background subagent was started. */\n subagent_id: string;\n /** The message to deliver to the subagent. */\n message: string;\n } & Record;\n /** Load the full instructions for an available skill. Call this with the exact skill name from the session skill catalog before acting on a task that names or clearly matches that skill. */\n skill: {\n /** The exact skill name from the available skills list. */\n name: string;\n } & Record;\n /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. Give it a complete, standalone prompt: it does not see this conversation. This tool runs in the background by default, immediately returns a durable subagent id, and keeps the child conversation available for later turns. When that run settles, the runtime sends the parent a notice containing its outcome and any final assistant message; `send_message` starts a later turn in the same child conversation. Set `run_in_background: false` only when your next action depends on receiving the result. */\n subagent: {\n /** A short (3-5 word) description of the delegated task, for display. */\n description: string;\n /** The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs. */\n prompt: string;\n /** Whether to run in the background and return a durable subagent id immediately. Defaults to true. Set false to wait for the result when your next action depends on it. */\n run_in_background?: boolean;\n } & Record;\n /** Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This call waits for the subagent and returns its result. */\n subagent_fork: {\n /** A short (3-5 word) description of the delegated task, for display. */\n description: string;\n /** The task for the subagent. It already sees this conversation's completed turns, so build on them freely and state only what is new. */\n prompt: string;\n } & Record;\n /** Record and update a structured task list for the current work. Send the ENTIRE list every call — it REPLACES the previous list (there are no partial updates, no per-item edits). Use it to plan multi-step work and show progress: add one todo per concrete step before you start. Mark every todo being actively worked on `in_progress` — several at once when work genuinely runs in parallel (e.g. concurrent subagents or background commands), one for sequential work; while work remains, at least one task should be `in_progress`. Mark a todo `completed` the moment it is done (do not batch completions), and allow no `in_progress` item only once all work is complete. Skip the list for trivial single-step tasks. Statuses: `pending` (not started), `in_progress` (being worked on now), `completed` (finished). */\n todo_write: {\n /** The COMPLETE task list, replacing any previous list. */\n todos: ({\n /** What the task is — a short imperative line. */\n content: string;\n /** pending (not started) | in_progress (now) | completed (done). */\n status: \"pending\" | \"in_progress\" | \"completed\";\n })[];\n } & Record;\n /** Run a JavaScript workflow script that orchestrates subagents at scale. Use this for work that fans out across many independent pieces — an audit over many files, a migration, multi-angle research, adversarial verification of findings — where you write the orchestration as a script instead of delegating turn by turn. The workflow's identity rides the `meta` parameter as JSON: required `name` (short kebab-case) and `description` strings, optional `whenToUse` string and `phases` array (`{title, detail?, provider?, model?}`). The `script` parameter is the plain JavaScript body ONLY (NOT TypeScript, and NO `export const meta` statement — meta is a parameter, not code), running with top-level await; end with `return ` — the value must be JSON-serializable and is this tool's result. Script-body hooks: - `agent(prompt, opts?): Promise` — run one subagent to completion. Without `opts.schema` it resolves to the child's final text; with `opts.schema` (an object-rooted JSON Schema using ONLY type/properties/required/additionalProperties/items/enum/const/oneOf — no pattern/format/numeric bounds) it resolves to the validated object. Resolves `null` when the child fails (filter with `.filter(Boolean)`). Other opts: `label` (display), `phase` (progress group), and independent `provider`/`model` LLM target overrides (either may be provided alone). Anything else (`effort`/`isolation`/`agentType`) is rejected loudly. - `pipeline(items, ...stages): Promise` — run each item through the stages independently with NO barrier between stages (prefer this for multi-stage work). Each stage receives `(prev, item, index)`. An ordinary stage throw drops that ITEM to `null` and skips its remaining stages. - `parallel(thunks): Promise` — run zero-argument functions concurrently and await ALL of them (a barrier; use only when a stage genuinely needs every prior result together). A throwing thunk resolves to `null`. - `phase(title)` — start a progress phase; `log(message)` — narrate progress; `args` — the tool call's `args` input, verbatim. Misused hooks (bad arguments, unknown options, unsupported schemas, tripped caps) throw errors that ALWAYS kill the script — they never dissolve into a per-item `null`. Constraints: concurrency and total-agent caps apply; no filesystem, network, timers, or Node.js APIs are provided — the agents do the work, the script only coordinates them. The run executes in the foreground: this call returns when the whole script finishes. */\n workflow: {\n /** The plain-JS workflow script body (top-level await allowed; NO `export const meta` statement; end with `return `). */\n script: string;\n /** The workflow identity block (plain JSON — never code). */\n meta: {\n /** Short kebab-case workflow name. */\n name: string;\n /** One-line description of what the workflow does. */\n description: string;\n /** Optional guidance on when this workflow applies. */\n whenToUse?: string;\n /** Optional phase declarations matched by phase() calls. */\n phases?: ({\n /** The phase title phase() calls match by exact string. */\n title: string;\n /** Optional one-line description of the phase. */\n detail?: string;\n /** Optional provider override this phase is expected to use. */\n provider?: string;\n /** Optional model override this phase is expected to use. */\n model?: string;\n } & Record)[];\n } & Record;\n /** Optional JSON input exposed to the script as the `args` global (wrap a bare list as a field, e.g. {\"files\": [...]}). */\n args?: Record;\n } & Record;\n /** Create or fully replace a UTF-8 text file. */\n write: {\n /** Path to write, resolved by the filesystem backend. */\n file_path: string;\n /** Full UTF-8 text content to write. */\n content: string;\n } & Record;\n}\n\ninterface ToolOutputMap {\n bash: {\n kind: \"background\";\n jobId: string;\n } | {\n kind: \"foreground\";\n exitCode: number | null;\n signal: string | null;\n timedOut: boolean;\n aborted: boolean;\n timeoutMs: number;\n stdout: {\n text: string;\n truncated: boolean;\n spillPath?: string;\n };\n stderr: {\n text: string;\n truncated: boolean;\n spillPath?: string;\n };\n sandbox?: {\n mode: string;\n denied: boolean;\n enforcement?: string;\n runnerFailed?: boolean;\n };\n };\n cordis_define: {\n pluginId: string;\n packageId: string;\n name: string;\n purpose: string;\n hasHostHalf: boolean;\n hasClientHalf: boolean;\n };\n cordis_inspect_list: JsonValue;\n cordis_inspect_query: JsonValue;\n cordis_inspect_self: JsonValue;\n cordis_run: JsonValue;\n cordis_stop: {\n pluginId: string;\n };\n cordis_undefine: {\n pluginId: string;\n wasRunning: boolean;\n };\n edit: {\n path: string;\n before: string;\n after: string;\n };\n interrupt_agent: {\n accepted: boolean;\n };\n job_kill: {\n outcome: \"cancellation-requested\" | \"already-finished\";\n job: {\n id: string;\n kind: string;\n label: string;\n status: \"running\" | \"stopping\" | \"completed\" | \"killed\" | \"failed\";\n detail?: string;\n startedAt: number;\n finishedAt?: number;\n };\n };\n job_list: ({\n id: string;\n kind: string;\n label: string;\n status: \"running\" | \"stopping\" | \"completed\" | \"killed\" | \"failed\";\n detail?: string;\n startedAt: number;\n finishedAt?: number;\n })[];\n job_output: {\n text: string;\n job: {\n id: string;\n kind: string;\n label: string;\n status: \"running\" | \"stopping\" | \"completed\" | \"killed\" | \"failed\";\n detail?: string;\n startedAt: number;\n finishedAt?: number;\n };\n };\n ralph: {\n runId: string;\n agentsStarted: number;\n result: JsonValue;\n };\n read: {\n path: string;\n offset: number;\n lines: {\n number: number;\n text: string;\n }[];\n totalLines: number;\n };\n send_message: {\n messageId: string;\n };\n skill: {\n name: string;\n provider: string;\n resourceBase?: {\n kind: \"directory\";\n path: string;\n } | {\n kind: \"url\";\n url: string;\n } | {\n kind: \"opaque\";\n description: string;\n };\n content: string;\n };\n subagent: {\n kind: \"background\";\n jobId: string;\n } | {\n kind: \"continuable\";\n subagentId: string;\n } | {\n kind: \"foreground\";\n runId: string;\n output: JsonValue[];\n };\n subagent_fork: {\n kind: \"background\";\n jobId: string;\n } | {\n kind: \"continuable\";\n subagentId: string;\n } | {\n kind: \"foreground\";\n runId: string;\n output: JsonValue[];\n };\n todo_write: {\n todos: ({\n content: string;\n status: \"pending\" | \"in_progress\" | \"completed\";\n })[];\n counts: {\n pending: number;\n inProgress: number;\n completed: number;\n };\n };\n workflow: {\n runId: string;\n agentsStarted: number;\n result: JsonValue;\n };\n write: {\n path: string;\n operation: \"create\" | \"update\";\n before: string | null;\n after: string;\n };\n}\n\ntype ToolName = keyof ToolOutputMap\n\ndeclare class ToolCallError extends Error {\n readonly name: \"ToolCallError\";\n readonly toolName: ToolName;\n}\n\ndeclare const tools: {\n [K in ToolName]: (args: ToolArgsMap[K]) => Promise;\n}\n```","tools":[{"name":"bash","description":"Execute a bash command (`bash -c`) and return its stdout/stderr. Each call runs in a fresh shell: no state (cwd, variables, functions) persists between calls — pass `workdir` instead of using `cd`. Non-zero exits are reported as `[exit code: N]`. Current harness environment facts are exposed through managed `$DSH_*` variables; inspect them when needed. Commands may run under a file sandbox; a blocked file operation is reported as `[sandbox: file access denied under mode]` — a policy denial, not a bug in the command; do not retry another way. Long output is truncated to its tail; the full output is saved to a file whose path is reported when available. Set `run_in_background: true` for long-running commands: the call returns a job id immediately; read its output with `job_output` and stop it with `job_kill`.","parameters":{"type":"object","properties":{"command":{"type":"string","description":"The bash command to execute."},"description":{"type":"string","description":"Clear, concise description of what this command does in active voice, 5-10 words (shown in the UI). Examples: \"ls\" → \"List files in current directory\"; \"git status\" → \"Show working tree status\"; \"npm install\" → \"Install package dependencies\"."},"timeoutMs":{"type":"number","description":"Timeout in milliseconds. The executor applies its configured default and cap, and kills the command on expiry."},"workdir":{"type":"string","description":"Working directory for this command. Defaults to the session workspace; a relative path is resolved against it."},"run_in_background":{"type":"boolean","description":"Run in the background and return a job id immediately (collect with job_output, stop with job_kill). No timeout applies."}},"required":["command","description"]}},{"name":"cordis_define","description":"Define an immutable Cordis Package. For a new Plugin, use kind:\"new\" and provide only a semantic prefix of 3–6 lowercase English letters; the Host returns the final pluginId and packageId. To modify an existing Plugin, use kind:\"existing\" with its exact pluginId to append a Package without overwriting older versions. Provide at least one of code.host and code.client. Each value is a plain JavaScript function body that returns a Cordis Plugin; no TypeScript, JSX, or import transformation occurs. Query Inspect before depending on a Service, Event, Builtin, Slot, or token. Define only validates parameters and syntax and records source: it does not request approval, execute apply, or change currentPackageId. On success, call cordis_run with the returned IDs.","parameters":{"type":"object","properties":{"plugin":{"oneOf":[{"type":"object","additionalProperties":false,"properties":{"kind":{"type":"string","const":"new"},"idPrefix":{"type":"string","description":"Suggested semantic prefix of 3–6 lowercase English letters; the Host adds a unique numeric suffix."}},"required":["kind","idPrefix"]},{"type":"object","additionalProperties":false,"properties":{"kind":{"type":"string","const":"existing"},"pluginId":{"type":"string","description":"Exact ID of an existing Plugin; the new Package is appended to that instance."}},"required":["kind","pluginId"]}]},"name":{"type":"string","description":"Short, readable Package name."},"purpose":{"type":"string","description":"One-sentence, user-facing description of the Package purpose."},"code":{"type":"object","additionalProperties":false,"properties":{"host":{"type":"string","description":"Plain JavaScript function body that returns the Host-half Cordis Plugin."},"client":{"type":"string","description":"Plain JavaScript function body that returns the browser Client-half Cordis Plugin."}}}},"required":["plugin","name","purpose","code"]}},{"name":"cordis_inspect_list","description":"List every Cordis Inspect Provider currently known to the Host, including local Host Providers and the latest manifests synchronized from the Client. Each entry includes its platform, purpose, read-only methods, and input/output schemas. Call this Tool before creating or modifying a Package, then select the provider and method for cordis_inspect_query from its result. Do not guess names or treat an Inspect method as a business Service that Plugin code can call.","parameters":{"type":"object","properties":{}}},{"name":"cordis_inspect_query","description":"Run a read-only query explicitly declared by an Inspect Provider. platform, provider, and method must come from cordis_inspect_list, and input must satisfy that method's schema. Use this Tool before cordis_define to read exact Service methods, Event modes, Builtin signatures, Tool schemas, theme tokens, or live Slot trees and props. Host queries run locally. A Client query waits for the first valid page response and remains pending until a page answers or the Tool is cancelled. This Tool cannot invoke business Service methods or modify the runtime. For Service.listService and Event.listEvents, query without input to navigate the compact signature directory, then query the exact service or event for its structured contract and referenced types. For Slots.listSubTree, query without root to navigate the compact tree, then query the exact root for its complete registration contract and props.","parameters":{"type":"object","properties":{"platform":{"type":"string","description":"Runtime platform that owns the Provider.","enum":["host","client"]},"provider":{"type":"string","description":"Exact Provider ID returned by cordis_inspect_list."},"method":{"type":"string","description":"Exact method name declared by the Provider manifest."},"input":{"description":"Optional query input; it must satisfy the method input schema."}},"required":["platform","provider","method"]}},{"name":"cordis_inspect_self","description":"Inspect dynamic Cordis objects owned by the current Session at increasing levels of detail. With no IDs, list only Plugin summaries. With pluginId alone, return version pointers, the latest Run, and every Package summary. Only pluginId plus packageId returns that immutable Package's Host/Client source and runtime diagnostics. packageId cannot be supplied alone. Query an exact Package before handling @pluginId, repairing an asynchronous failure, or defining an updated version. This Tool is read-only: it neither executes code nor changes version pointers.","parameters":{"type":"object","properties":{"pluginId":{"type":"string","description":"Stable Plugin ID returned by cordis_define or injected by @pluginId; omit it to list every current Plugin."},"packageId":{"type":"string","description":"Exact immutable Package ID owned by pluginId; when specified, source and diagnostics are returned."}}}},{"name":"cordis_run","description":"Activate one exact Package of a dynamic Plugin. Use mode:\"run\" for the first activation, restarting currentPackageId, or rollback. When current exists, use mode:\"update\" to switch to a different Package, even if the Plugin is currently stopped. An unauthorized Client Package creates an approval request and returns awaiting-approval; an authorized Package returns starting and continues asynchronously in the browser. Neither result waits for the final outcome inside the Tool. currentPackageId changes only after complete success; on failure, the old current and target next remain. Asynchronous success, rejection, or technical failure is reported through state and steering. After a technical failure, read diagnostics with cordis_inspect_self, correct the same Plugin, and retry autonomously. Do not request approval again after the user rejects it.","parameters":{"type":"object","properties":{"pluginId":{"type":"string","description":"Stable Plugin ID returned by cordis_define."},"packageId":{"type":"string","description":"Exact immutable Package ID to activate under that Plugin."},"mode":{"type":"string","description":"Use run for the first activation, restarting current, or rollback; use update to switch from current to a different Package.","enum":["run","update"]}},"required":["pluginId","packageId","mode"]}},{"name":"cordis_stop","description":"Stop the current Run of a dynamic Plugin and cancel unfinished approval or activation requests. Retain the Plugin, every immutable Package, grants, currentPackageId, and nextPackageId so it can later run or update directly. Stopping an already stopped Plugin succeeds idempotently. Use this Tool to disable effects temporarily; use cordis_undefine for permanent removal.","parameters":{"type":"object","properties":{"pluginId":{"type":"string","description":"Stable dynamic Plugin ID to stop."}},"required":["pluginId"]}},{"name":"cordis_undefine","description":"Permanently remove a dynamic Plugin owned by the current Session. If it is running or awaiting approval, first stop it and cancel the request, then delete every Package, grant, and version pointer. After this returns, its pluginId, packageIds, @ reference, and Package business views are invalid; historical cards retain only a \"Plugin removed\" record. Do not call this Tool when versions must remain available for restart or rollback; use cordis_stop instead.","parameters":{"type":"object","properties":{"pluginId":{"type":"string","description":"Stable dynamic Plugin ID to remove permanently."}},"required":["pluginId"]}},{"name":"edit","description":"Edit an existing UTF-8 text file by replacing literal text.","parameters":{"type":"object","properties":{"file_path":{"type":"string","description":"Path to edit, resolved by the filesystem backend."},"old_string":{"type":"string","description":"Literal text to replace. Must match exactly."},"new_string":{"type":"string","description":"Literal replacement text. Use an empty string to delete the match."},"replace_all":{"type":"boolean","description":"Replace all matches. Defaults to false; when false, old_string must appear exactly once."}},"required":["file_path","old_string","new_string"]}},{"name":"interrupt_agent","description":"Request cancellation of a background agent's current turn by its agent id. The target may be your direct child or a deeper agent created under you. Only the current turn stops: messages already queued for the agent stay parked until a later send_message, agents it started keep running, and the agent itself stays available for follow-ups. This call returns as soon as the stop request is accepted, so the target may keep running briefly; interrupting an agent that already finished is an accepted no-op.","parameters":{"type":"object","properties":{"agent_id":{"type":"string","description":"The agent id of the running agent to interrupt."}},"required":["agent_id"]}},{"name":"job_kill","description":"Request cancellation of a running background job by job id. Returns immediately; the job settles as killed once its work actually stops.","parameters":{"type":"object","properties":{"job_id":{"type":"string","description":"Job id returned by the tool that started the background work."},"reason":{"type":"string","description":"Optional short reason, recorded in the log and forwarded to the job."}},"required":["job_id"]}},{"name":"job_list","description":"List your background jobs (running and finished) with their ids, kinds, and statuses.","parameters":{"type":"object","properties":{}}},{"name":"job_output","description":"Read a background job. Stream jobs return only output since the previous read; final-output jobs return their result after settlement. Every response ends with `[status: ...]`. Reads are non-blocking unless `wait: true`, which waits up to the configured cap.","parameters":{"type":"object","properties":{"job_id":{"type":"string","description":"Job id returned by the tool that started the background work."},"wait":{"type":"boolean","description":"Block until the job reaches a terminal status or the timeout expires. A timed-out wait returns [status: running] and leaves the job alive."},"timeout_ms":{"type":"number","description":"Max wait in milliseconds (only meaningful with wait: true). Defaults to the configured wait timeout; capped by the configured maximum."}},"required":["job_id"]}},{"name":"ralph","description":"Run a foreground fresh-agent Ralph loop toward one immutable objective. Use only when the direct human explicitly asks for Ralph or fresh-agent iteration. Each round opens a new child with no parent conversation or prior child session; the shared workspace is long-term memory, and only a bounded structured report crosses rounds. The call returns when a worker reports completion or a concrete blocker, or at the round limit. Ordinary long-running same-session work belongs to goal tools.","parameters":{"type":"object","properties":{"objective":{"type":"string","description":"The immutable completion objective for every fresh Ralph round."},"maxRounds":{"type":"number","description":"Optional positive safe-integer round cap, bounded by the deployment ceiling."}},"required":["objective"]}},{"name":"read","description":"Read a UTF-8 text file and return line-numbered content.","parameters":{"type":"object","properties":{"file_path":{"type":"string","description":"Path to read, resolved by the filesystem backend."},"offset":{"type":"number","description":"1-based first line to return. Defaults to 1."},"limit":{"type":"number","description":"Maximum number of lines to return. Defaults to 2000."}},"required":["file_path"]}},{"name":"run_code","description":"Execute a TypeScript program against the available tools. Write the BODY of an async function (erasable syntax only; top-level `await` and `return` work) and call tools as `await tools.name(args)` per the declarations in the system prompt. Only what you print or return comes back — curate it.","parameters":{"type":"object","properties":{"code":{"type":"string","description":"The program: the body of an async TypeScript function."},"description":{"type":"string","description":"Clear, concise description of what this program does in active voice, 5-10 words (shown in the UI). Examples: \"Count TODO markers across packages\"; \"Read failing test and its fixture\"; \"Rename config key in every cordis.yml\"."}},"required":["code","description"]}},{"name":"send_message","description":"Send a message to a background subagent by its subagent id, continuing the same conversation. It becomes the subagent's next turn: if it is still working, the message waits until its current turn finishes, so it cannot redirect work already underway. This call returns no answer from the subagent — only confirmation that the message was delivered — so use it to give it more work. A failure means the message was NOT delivered.","parameters":{"type":"object","properties":{"subagent_id":{"type":"string","description":"The subagent id returned when the background subagent was started."},"message":{"type":"string","description":"The message to deliver to the subagent."}},"required":["subagent_id","message"]}},{"name":"skill","description":"Load the full instructions for an available skill. Call this with the exact skill name from the session skill catalog before acting on a task that names or clearly matches that skill.","parameters":{"type":"object","properties":{"name":{"type":"string","description":"The exact skill name from the available skills list."}},"required":["name"]}},{"name":"subagent","description":"Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. Give it a complete, standalone prompt: it does not see this conversation. This tool runs in the background by default, immediately returns a durable subagent id, and keeps the child conversation available for later turns. When that run settles, the runtime sends the parent a notice containing its outcome and any final assistant message; `send_message` starts a later turn in the same child conversation. Set `run_in_background: false` only when your next action depends on receiving the result.","parameters":{"type":"object","properties":{"description":{"type":"string","description":"A short (3-5 word) description of the delegated task, for display."},"prompt":{"type":"string","description":"The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs."},"run_in_background":{"type":"boolean","description":"Whether to run in the background and return a durable subagent id immediately. Defaults to true. Set false to wait for the result when your next action depends on it."}},"required":["description","prompt"]}},{"name":"subagent_fork","description":"Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This call waits for the subagent and returns its result.","parameters":{"type":"object","properties":{"description":{"type":"string","description":"A short (3-5 word) description of the delegated task, for display."},"prompt":{"type":"string","description":"The task for the subagent. It already sees this conversation's completed turns, so build on them freely and state only what is new."}},"required":["description","prompt"]}},{"name":"todo_write","description":"Record and update a structured task list for the current work. Send the ENTIRE list every call — it REPLACES the previous list (there are no partial updates, no per-item edits). Use it to plan multi-step work and show progress: add one todo per concrete step before you start. Mark every todo being actively worked on `in_progress` — several at once when work genuinely runs in parallel (e.g. concurrent subagents or background commands), one for sequential work; while work remains, at least one task should be `in_progress`. Mark a todo `completed` the moment it is done (do not batch completions), and allow no `in_progress` item only once all work is complete. Skip the list for trivial single-step tasks. Statuses: `pending` (not started), `in_progress` (being worked on now), `completed` (finished).","parameters":{"type":"object","properties":{"todos":{"type":"array","description":"The COMPLETE task list, replacing any previous list.","items":{"type":"object","additionalProperties":false,"properties":{"content":{"type":"string","description":"What the task is — a short imperative line."},"status":{"type":"string","description":"pending (not started) | in_progress (now) | completed (done).","enum":["pending","in_progress","completed"]}},"required":["content","status"]}}},"required":["todos"]}},{"name":"workflow","description":"Run a JavaScript workflow script that orchestrates subagents at scale. Use this for work that fans out across many independent pieces — an audit over many files, a migration, multi-angle research, adversarial verification of findings — where you write the orchestration as a script instead of delegating turn by turn.\n\nThe workflow's identity rides the `meta` parameter as JSON: required `name` (short kebab-case) and `description` strings, optional `whenToUse` string and `phases` array (`{title, detail?, provider?, model?}`). The `script` parameter is the plain JavaScript body ONLY (NOT TypeScript, and NO `export const meta` statement — meta is a parameter, not code), running with top-level await; end with `return ` — the value must be JSON-serializable and is this tool's result.\n\nScript-body hooks:\n- `agent(prompt, opts?): Promise` — run one subagent to completion. Without `opts.schema` it resolves to the child's final text; with `opts.schema` (an object-rooted JSON Schema using ONLY type/properties/required/additionalProperties/items/enum/const/oneOf — no pattern/format/numeric bounds) it resolves to the validated object. Resolves `null` when the child fails (filter with `.filter(Boolean)`). Other opts: `label` (display), `phase` (progress group), and independent `provider`/`model` LLM target overrides (either may be provided alone). Anything else (`effort`/`isolation`/`agentType`) is rejected loudly.\n- `pipeline(items, ...stages): Promise` — run each item through the stages independently with NO barrier between stages (prefer this for multi-stage work). Each stage receives `(prev, item, index)`. An ordinary stage throw drops that ITEM to `null` and skips its remaining stages.\n- `parallel(thunks): Promise` — run zero-argument functions concurrently and await ALL of them (a barrier; use only when a stage genuinely needs every prior result together). A throwing thunk resolves to `null`.\n- `phase(title)` — start a progress phase; `log(message)` — narrate progress; `args` — the tool call's `args` input, verbatim.\n\nMisused hooks (bad arguments, unknown options, unsupported schemas, tripped caps) throw errors that ALWAYS kill the script — they never dissolve into a per-item `null`.\n\nConstraints: concurrency and total-agent caps apply; no filesystem, network, timers, or Node.js APIs are provided — the agents do the work, the script only coordinates them. The run executes in the foreground: this call returns when the whole script finishes.","parameters":{"type":"object","properties":{"script":{"type":"string","description":"The plain-JS workflow script body (top-level await allowed; NO `export const meta` statement; end with `return `)."},"meta":{"type":"object","description":"The workflow identity block (plain JSON — never code).","additionalProperties":true,"properties":{"name":{"type":"string","description":"Short kebab-case workflow name."},"description":{"type":"string","description":"One-line description of what the workflow does."},"whenToUse":{"type":"string","description":"Optional guidance on when this workflow applies."},"phases":{"type":"array","description":"Optional phase declarations matched by phase() calls.","items":{"type":"object","additionalProperties":true,"properties":{"title":{"type":"string","description":"The phase title phase() calls match by exact string."},"detail":{"type":"string","description":"Optional one-line description of the phase."},"provider":{"type":"string","description":"Optional provider override this phase is expected to use."},"model":{"type":"string","description":"Optional model override this phase is expected to use."}},"required":["title"]}}},"required":["name","description"]},"args":{"type":"object","description":"Optional JSON input exposed to the script as the `args` global (wrap a bare list as a field, e.g. {\"files\": [...]}).","additionalProperties":true}},"required":["script","meta"]}},{"name":"write","description":"Create or fully replace a UTF-8 text file.","parameters":{"type":"object","properties":{"file_path":{"type":"string","description":"Path to write, resolved by the filesystem backend."},"content":{"type":"string","description":"Full UTF-8 text content to write."}},"required":["file_path","content"]}}]},"reason":"initial"}} +{"type":"request/header","seq":6,"time":1785498583782,"data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"system":"You are an AI agent powered by DeepSeek Harness.\n\nYou are headless-agent, a coding assistant powered by the deepseek-v4-flash model. Your working directory is {{cwd}}.\n\nVerify your work by running the code or tests. Keep answers brief and factual.\n\n\nUse the read tool — not shell commands like cat — to inspect text files. Results include line numbers. Use offset and limit to continue reading large files.\n\nUse the write tool to create files or completely replace file contents. Existing files are overwritten, so read an existing file first (the default fs-observation-policy requires it) and prefer edit for targeted changes.\n\nUse the edit tool for targeted changes to existing UTF-8 text files. It replaces literal old_string with new_string; by default old_string must appear exactly once. If old_string appears multiple times, provide a more specific old_string or set replace_all to true. Read the file first (the default fs-observation-policy requires it), unless you just created or edited it in this session.\n\nCheck the [exit code: N] marker on every bash result; investigate failures before moving on.\n\nTrack every background job id you start. You are notified in-session when a job finishes — do not busy-poll or sleep on one; keep working on independent steps and do not duplicate a running job's work. Before giving a final answer, collect every still-relevant job with job_output (set wait: true only when you are genuinely blocked on it), and job_kill jobs that stopped mattering.\n\nUse the workflow tool ONLY when the user explicitly asks for a workflow or for large multi-agent orchestration: you write a JavaScript script (the tool description documents the exact format) that fans work out across many subagents with phases and structured results. For one or two delegations, prefer plain subagent calls.\n\n# Dynamic Cordis Plugins\n\nDynamic Cordis plugins temporarily extend the current DSH process. A Plugin uses apply(ctx) to consume Services, listen to Events, provide Services, register model Tools, or register browser UI in Slots.\n\n- Plugin and Package definitions exist only in the current process. define itself does not modify repository source, configuration, or disk, and definitions do not survive a process restart.\n- The restricted execution environment prevents accidental misuse; it is not a security boundary for malicious code. Services obtained by dynamic code connect to the real runtime.\n\n## Make the user-facing plan clear first\n\n- Dynamic Cordis Plugins are one available implementation mechanism, not the default for every request. Consider whether one could help only when the user intends to design or create something, or when a temporary interface could materially aid the current work. The presence of these instructions or Tools, and discussion of Cordis itself, do not make a request a dynamic-Plugin task.\n- When Cordis is a plausible fit, infer the intended work target and lifetime from the request and conversation. Use it only when the outcome belongs to the current running harness and should be delivered as a temporary runtime extension. If that distinction is materially ambiguous, ask at most one concise question about the intended result or lifetime. Otherwise proceed with the matching workflow; do not require the user to know or choose Cordis as an implementation mechanism.\n- Once a dynamic Plugin is appropriate, decide whether the task creates a new Plugin or modifies the Plugin named by the user with @pluginId. Proceed directly when the goal is clear; do not ask for repeated confirmation.\n- Choose Host, Client, or both from the requested outcome. Do not propose a Client/browser UI when the task does not need visible page behavior, and do not avoid Client when the requested outcome is visual, interactive, or depends on page state. Host versus Client is an implementation choice; do not make the user choose it.\n- When a design direction or a potentially useful interface would materially affect the result, ask at most one concise outcome or creative-preference question and offer a few candidate directions. Otherwise proceed directly; do not conduct a multi-round interview or a complex questionnaire.\n- cordis_define only defines and presents code; it does not run it. After definition, explain the pluginId and packageId returned by the Host and whether the next step is a run or update.\n- cordis_run may require user approval. When it returns awaiting-approval, explain that the user must allow or reject it in the UI. Do not wait, retry, or claim that it is running.\n- When it returns starting, explain that the request has entered the asynchronous flow and the Client is still activating. starting does not mean success. Wait for the system to report the final result through steering context.\n- Do not request approval again after the user rejects it. After a technical failure, fix the same Plugin from its diagnostics; do not silently create a replacement Plugin.\n\n## Recommended workflow and Tools\n\nBefore creating, modifying, or repairing a Plugin, load the cordis-plugin-development Skill. The Skill provides requirement navigation, capability composition, complete examples, and troubleshooting. Treat Inspect Provider results as the source of truth for exact APIs.\n\n1. cordis_inspect_list: discover the current Host and Client Providers and their read-only query methods.\n2. cordis_inspect_query: use the returned platform, provider, method, and schema to query exact Service, Event, Builtin, Slot, Theme token, or Tool information.\n3. cordis_inspect_self: inspect the current Session's Plugins, Packages, version pointers, source, and diagnostics. Source is returned only when both pluginId and packageId are specified.\n4. cordis_define: create the first Package for a new Plugin or append an immutable Package to an existing Plugin. It defines code but does not run it.\n5. cordis_run: activate an exact Package. Use run for the first activation, restarting current, or rollback; use update to switch versions.\n6. cordis_stop: remove the current Run and pending approval request while retaining definitions, grants, and version pointers.\n7. cordis_undefine: permanently stop and delete a Plugin and all of its Packages. Use it only after confirming that the user no longer needs them.\n\n- Inspect and Catalog data only confirm capabilities, names, signatures, types, and registration protocols before code is written; they do not replace business APIs.\n- Query Service.listService and Event.listEvents without input to choose from their compact signature directories, then query the exact service or event before using it. Exact queries return the structured contract and only its referenced types.\n- At runtime, a Plugin must call real Services or listen to real Events. Do not cache, display, or depend on Inspect results as business data.\n\n## Identity, versions, and approval\n\n- pluginId identifies a Plugin that can be modified over time. For a new Plugin, submit only a semantic idPrefix of 3–6 lowercase English letters; the Host allocates the final ID.\n- packageId identifies one immutable Host/Client source version under a Plugin. To change code, define a new Package; never overwrite an old version.\n- pluginRunId identifies one activation attempt and connects its approval, Host/Client loading, private RPC, Run card, and errors.\n- currentPackageId is the most recent fully successful Package. Stopping, starting an update, or failing an update does not clear it.\n- nextPackageId is the target awaiting approval, being attempted, awaiting Client activation, or most recently failed.\n- A single check mark authorizes only the current Package; double check marks authorize future versions of the same Plugin. A grant remains in effect after a technical failure.\n- An update stops the old Run before starting the target Package. Failure does not automatically restart the old version; retry next with update or roll back to current with run.\n\nWhen the user enters @pluginId, the system injects identity, the default base Package, version pointers, and runtime status, but not source code:\n\n1. Call cordis_inspect_self(pluginId, packageId) to read the target source.\n2. Use cordis_define in existing mode to append a Package to the same Plugin.\n3. Call cordis_run in run or update mode according to the version relationship.\n\nNever silently create another Plugin for @pluginId. If the reference is unavailable because it was removed, belongs to another Session, or was lost on process restart, tell the user directly.\n\n## High-frequency errors that must be avoided\n\n### Services: ctx.get and inject\n\n- Read an optional Service with ctx.get('serviceName') by default and handle undefined.\n- Declare inject: ['serviceName'] on the returned Plugin object only when the Service is a hard dependency and the Plugin must enter waiting until Cordis reactivates it after the Service appears.\n- Read ctx.serviceName only after declaring that Service in inject. Never access an undeclared Service as a ctx property.\n\n```js\nreturn {\n inject: ['requiredService'],\n apply(ctx) {\n ctx.requiredService.someMethod()\n const optionalService = ctx.get('optionalService')\n if (optionalService !== undefined) optionalService.someMethod()\n },\n}\n```\n\n### Code: use plain JavaScript only\n\n- Host and Client code is not transformed by TypeScript, JSX, or a bundler.\n- Do not use TypeScript types, as, decorators, import, require, or JSX.\n- Client React code must use React.createElement(...); never write .\n- Do not assume that process, Buffer, window, document, fetch, native timers, or any other global is available. Query the corresponding platform's Builtins and Services first.\n\n### Data: do not serialize live data\n\n- Services, Events, Slots, Sessions, and their derived Cordis/DSH objects are internal live data, not ordinary JSON that can be dumped.\n- Do not apply JSON.stringify, structuredClone, recursive enumeration, full copying, or whole-object display to live data.\n- Read only the leaf fields required by the task, then construct the smallest owned data object without Host references.\n\n### Lifecycle: every side effect must be reversible\n\n- Services, Events, Tools, handlers, timers, Slots, styles, and theme overrides must all belong to the current Fiber.\n- Use ctx.effect(), ctx.on(), or official APIs that return a disposer so stop, update, or undefine removes every side effect.\n- The cordis-plugin-development Skill contains complete timer, Waterfall, Slot, theme, Tool, RPC, and React examples and troubleshooting guidance.\n\n## Host and Client\n\n- Host runs in the DSH Node.js process and is appropriate for files, networking, commands, Agent/Session access, Host Events, Services, model Tools, and JSON methods callable by the Client.\n- Client runs in the browser page and is appropriate for themes, layout, current page state, Tool cards, and Slot UI.\n- Host and Client communicate through Package-private JSON methods: Host uses harness.handle(method, handler), and Client uses host.call(method, args). The direction is Client→Host, and only lossless JSON may cross it.\n- Client UI must be registered in a queried Slot; apply() cannot directly return a React Element. Query Slots.listSubTree without root to choose from the compact purpose/topology tree, then query the exact root for its full registration contract and props before writing code.\n- See the Skill and Inspect Providers for Run-specific panels and exact Slot registration patterns.\n\n## Asynchronous results and recovery\n\n- Do not wait inside a Tool for approval or browser work that can happen only after the current turn ends.\n- Asynchronous success, rejection, and runtime errors update Run state and notify you through steering context.\n- After a technical failure, use cordis_inspect_self to read the exact Package source and its message/stack. Define a corrected Package under the same Plugin and retry autonomously.\n- Use the cordis-plugin-development Skill for other failure causes, repair procedures, and complete extension patterns.\n\nUse the ralph tool ONLY when the direct human explicitly asks for a Ralph loop or fresh-agent iterative execution. Each Ralph round starts a fresh child with no conversation seed and uses the shared workspace as durable memory. Completion and blockers are worker reports, not independent evaluation. Use same-session goal tools for ordinary long-running objectives, and plain subagents or workflows for bounded delegation and fan-out.\n\nUse subagent in the background by default. Start independent delegations together in one assistant message and continue useful work while they run. Set `run_in_background: false` only when your next action depends on that subagent's result. When a background run settles, the runtime sends you a notice containing its outcome and any final assistant message.\n\n## Writing code for run_code\n\n`run_code` takes two required arguments: `code` — the body of an async TypeScript function (erasable syntax only — no `enum` or namespaces; type annotations are advisory, the code runs type-stripped) — and `description`, a short summary of what the program does. Inside the program:\n\n- Call tools as `await tools.name(args)` — quoted access for exotic names: `tools[\"my-tool\"](args)`. Every call resolves to the tool's typed canonical JSON value. Tool arguments must be lossless JSON.\n- A FAILED tool call rejects with `ToolCallError`, whose `toolName` identifies the failed tool and whose `message` is human-readable — `try/catch` it to handle and continue.\n- Independent read-only calls MAY overlap under `Promise.all` (safe calls run concurrently; mutating calls run alone, in submission order). Sequence dependent work with `await`.\n- Emit results with `return` and/or `console.log(...)`. ONLY what you print or return comes back to you — intermediate tool results never enter the conversation, so extract just what you need.\n\nThe available tools:\n\n```ts\ntype JsonValue = null | boolean | number | string | JsonValue[] | { [key: string]: JsonValue }\n\ninterface ToolArgsMap {\n /** Execute a bash command (`bash -c`) and return its stdout/stderr. Each call runs in a fresh shell: no state (cwd, variables, functions) persists between calls — pass `workdir` instead of using `cd`. Non-zero exits are reported as `[exit code: N]`. Current harness environment facts are exposed through managed `$DSH_*` variables; inspect them when needed. Commands may run under a file sandbox; a blocked file operation is reported as `[sandbox: file access denied under mode]` — a policy denial, not a bug in the command; do not retry another way. Long output is truncated to its tail; the full output is saved to a file whose path is reported when available. Set `run_in_background: true` for long-running commands: the call returns a job id immediately; read its output with `job_output` and stop it with `job_kill`. */\n bash: {\n /** The bash command to execute. */\n command: string;\n /** Clear, concise description of what this command does in active voice, 5-10 words (shown in the UI). Examples: \"ls\" → \"List files in current directory\"; \"git status\" → \"Show working tree status\"; \"npm install\" → \"Install package dependencies\". */\n description: string;\n /** Timeout in milliseconds. The executor applies its configured default and cap, and kills the command on expiry. */\n timeoutMs?: number;\n /** Working directory for this command. Defaults to the session workspace; a relative path is resolved against it. */\n workdir?: string;\n /** Run in the background and return a job id immediately (collect with job_output, stop with job_kill). No timeout applies. */\n run_in_background?: boolean;\n } & Record;\n /** Define an immutable Cordis Package. For a new Plugin, use kind:\"new\" and provide only a semantic prefix of 3–6 lowercase English letters; the Host returns the final pluginId and packageId. To modify an existing Plugin, use kind:\"existing\" with its exact pluginId to append a Package without overwriting older versions. Provide at least one of code.host and code.client. Each value is a plain JavaScript function body that returns a Cordis Plugin; no TypeScript, JSX, or import transformation occurs. Query Inspect before depending on a Service, Event, Builtin, Slot, or token. Define only validates parameters and syntax and records source: it does not request approval, execute apply, or change currentPackageId. On success, call cordis_run with the returned IDs. */\n cordis_define: {\n plugin: {\n kind: \"new\";\n /** Suggested semantic prefix of 3–6 lowercase English letters; the Host adds a unique numeric suffix. */\n idPrefix: string;\n } | {\n kind: \"existing\";\n /** Exact ID of an existing Plugin; the new Package is appended to that instance. */\n pluginId: string;\n };\n /** Short, readable Package name. */\n name: string;\n /** One-sentence, user-facing description of the Package purpose. */\n purpose: string;\n code: {\n /** Plain JavaScript function body that returns the Host-half Cordis Plugin. */\n host?: string;\n /** Plain JavaScript function body that returns the browser Client-half Cordis Plugin. */\n client?: string;\n };\n } & Record;\n /** List every Cordis Inspect Provider currently known to the Host, including local Host Providers and the latest manifests synchronized from the Client. Each entry includes its platform, purpose, read-only methods, and input/output schemas. Call this Tool before creating or modifying a Package, then select the provider and method for cordis_inspect_query from its result. Do not guess names or treat an Inspect method as a business Service that Plugin code can call. */\n cordis_inspect_list: Record;\n /** Run a read-only query explicitly declared by an Inspect Provider. platform, provider, and method must come from cordis_inspect_list, and input must satisfy that method's schema. Use this Tool before cordis_define to read exact Service methods, Event modes, Builtin signatures, Tool schemas, theme tokens, or live Slot trees and props. Host queries run locally. A Client query waits for the first valid page response and remains pending until a page answers or the Tool is cancelled. This Tool cannot invoke business Service methods or modify the runtime. For Service.listService and Event.listEvents, query without input to navigate the compact signature directory, then query the exact service or event for its structured contract and referenced types. For Slots.listSubTree, query without root to navigate the compact tree, then query the exact root for its complete registration contract and props. */\n cordis_inspect_query: {\n /** Runtime platform that owns the Provider. */\n platform: \"host\" | \"client\";\n /** Exact Provider ID returned by cordis_inspect_list. */\n provider: string;\n /** Exact method name declared by the Provider manifest. */\n method: string;\n /** Optional query input; it must satisfy the method input schema. */\n input?: JsonValue;\n } & Record;\n /** Inspect dynamic Cordis objects owned by the current Session at increasing levels of detail. With no IDs, list only Plugin summaries. With pluginId alone, return version pointers, the latest Run, and every Package summary. Only pluginId plus packageId returns that immutable Package's Host/Client source and runtime diagnostics. packageId cannot be supplied alone. Query an exact Package before handling @pluginId, repairing an asynchronous failure, or defining an updated version. This Tool is read-only: it neither executes code nor changes version pointers. */\n cordis_inspect_self: {\n /** Stable Plugin ID returned by cordis_define or injected by @pluginId; omit it to list every current Plugin. */\n pluginId?: string;\n /** Exact immutable Package ID owned by pluginId; when specified, source and diagnostics are returned. */\n packageId?: string;\n } & Record;\n /** Activate one exact Package of a dynamic Plugin. Use mode:\"run\" for the first activation, restarting currentPackageId, or rollback. When current exists, use mode:\"update\" to switch to a different Package, even if the Plugin is currently stopped. An unauthorized Client Package creates an approval request and returns awaiting-approval; an authorized Package returns starting and continues asynchronously in the browser. Neither result waits for the final outcome inside the Tool. currentPackageId changes only after complete success; on failure, the old current and target next remain. Asynchronous success, rejection, or technical failure is reported through state and steering. After a technical failure, read diagnostics with cordis_inspect_self, correct the same Plugin, and retry autonomously. Do not request approval again after the user rejects it. */\n cordis_run: {\n /** Stable Plugin ID returned by cordis_define. */\n pluginId: string;\n /** Exact immutable Package ID to activate under that Plugin. */\n packageId: string;\n /** Use run for the first activation, restarting current, or rollback; use update to switch from current to a different Package. */\n mode: \"run\" | \"update\";\n } & Record;\n /** Stop the current Run of a dynamic Plugin and cancel unfinished approval or activation requests. Retain the Plugin, every immutable Package, grants, currentPackageId, and nextPackageId so it can later run or update directly. Stopping an already stopped Plugin succeeds idempotently. Use this Tool to disable effects temporarily; use cordis_undefine for permanent removal. */\n cordis_stop: {\n /** Stable dynamic Plugin ID to stop. */\n pluginId: string;\n } & Record;\n /** Permanently remove a dynamic Plugin owned by the current Session. If it is running or awaiting approval, first stop it and cancel the request, then delete every Package, grant, and version pointer. After this returns, its pluginId, packageIds, @ reference, and Package business views are invalid; historical cards retain only a \"Plugin removed\" record. Do not call this Tool when versions must remain available for restart or rollback; use cordis_stop instead. */\n cordis_undefine: {\n /** Stable dynamic Plugin ID to remove permanently. */\n pluginId: string;\n } & Record;\n /** Edit an existing UTF-8 text file by replacing literal text. */\n edit: {\n /** Path to edit, resolved by the filesystem backend. */\n file_path: string;\n /** Literal text to replace. Must match exactly. */\n old_string: string;\n /** Literal replacement text. Use an empty string to delete the match. */\n new_string: string;\n /** Replace all matches. Defaults to false; when false, old_string must appear exactly once. */\n replace_all?: boolean;\n } & Record;\n /** Request cancellation of a background agent's current turn by its agent id. The target may be your direct child or a deeper agent created under you. Only the current turn stops: messages already queued for the agent stay parked until a later send_message, agents it started keep running, and the agent itself stays available for follow-ups. This call returns as soon as the stop request is accepted, so the target may keep running briefly; interrupting an agent that already finished is an accepted no-op. */\n interrupt_agent: {\n /** The agent id of the running agent to interrupt. */\n agent_id: string;\n } & Record;\n /** Request cancellation of a running background job by job id. Returns immediately; the job settles as killed once its work actually stops. */\n job_kill: {\n /** Job id returned by the tool that started the background work. */\n job_id: string;\n /** Optional short reason, recorded in the log and forwarded to the job. */\n reason?: string;\n } & Record;\n /** List your background jobs (running and finished) with their ids, kinds, and statuses. */\n job_list: Record;\n /** Read a background job. Stream jobs return only output since the previous read; final-output jobs return their result after settlement. Every response ends with `[status: ...]`. Reads are non-blocking unless `wait: true`, which waits up to the configured cap. */\n job_output: {\n /** Job id returned by the tool that started the background work. */\n job_id: string;\n /** Block until the job reaches a terminal status or the timeout expires. A timed-out wait returns [status: running] and leaves the job alive. */\n wait?: boolean;\n /** Max wait in milliseconds (only meaningful with wait: true). Defaults to the configured wait timeout; capped by the configured maximum. */\n timeout_ms?: number;\n } & Record;\n /** Run a foreground fresh-agent Ralph loop toward one immutable objective. Use only when the direct human explicitly asks for Ralph or fresh-agent iteration. Each round opens a new child with no parent conversation or prior child session; the shared workspace is long-term memory, and only a bounded structured report crosses rounds. The call returns when a worker reports completion or a concrete blocker, or at the round limit. Ordinary long-running same-session work belongs to goal tools. */\n ralph: {\n /** The immutable completion objective for every fresh Ralph round. */\n objective: string;\n /** Optional positive safe-integer round cap, bounded by the deployment ceiling. */\n maxRounds?: number;\n } & Record;\n /** Read a UTF-8 text file and return line-numbered content. */\n read: {\n /** Path to read, resolved by the filesystem backend. */\n file_path: string;\n /** 1-based first line to return. Defaults to 1. */\n offset?: number;\n /** Maximum number of lines to return. Defaults to 2000. */\n limit?: number;\n } & Record;\n /** Send a message to a background subagent by its subagent id, continuing the same conversation. It becomes the subagent's next turn: if it is still working, the message waits until its current turn finishes, so it cannot redirect work already underway. This call returns no answer from the subagent — only confirmation that the message was delivered — so use it to give it more work. A failure means the message was NOT delivered. */\n send_message: {\n /** The subagent id returned when the background subagent was started. */\n subagent_id: string;\n /** The message to deliver to the subagent. */\n message: string;\n } & Record;\n /** Load the full instructions for an available skill. Call this with the exact skill name from the session skill catalog before acting on a task that names or clearly matches that skill. */\n skill: {\n /** The exact skill name from the available skills list. */\n name: string;\n } & Record;\n /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. Give it a complete, standalone prompt: it does not see this conversation. This tool runs in the background by default, immediately returns a durable subagent id, and keeps the child conversation available for later turns. When that run settles, the runtime sends the parent a notice containing its outcome and any final assistant message; `send_message` starts a later turn in the same child conversation. Set `run_in_background: false` only when your next action depends on receiving the result. */\n subagent: {\n /** A short (3-5 word) description of the delegated task, for display. */\n description: string;\n /** The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs. */\n prompt: string;\n /** Whether to run in the background and return a durable subagent id immediately. Defaults to true. Set false to wait for the result when your next action depends on it. */\n run_in_background?: boolean;\n } & Record;\n /** Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This call waits for the subagent and returns its result. */\n subagent_fork: {\n /** A short (3-5 word) description of the delegated task, for display. */\n description: string;\n /** The task for the subagent. It already sees this conversation's completed turns, so build on them freely and state only what is new. */\n prompt: string;\n } & Record;\n /** Record and update a structured task list for the current work. Send the ENTIRE list every call — it REPLACES the previous list (there are no partial updates, no per-item edits). Use it to plan multi-step work and show progress: add one todo per concrete step before you start. Mark every todo being actively worked on `in_progress` — several at once when work genuinely runs in parallel (e.g. concurrent subagents or background commands), one for sequential work; while work remains, at least one task should be `in_progress`. Mark a todo `completed` the moment it is done (do not batch completions), and allow no `in_progress` item only once all work is complete. Skip the list for trivial single-step tasks. Statuses: `pending` (not started), `in_progress` (being worked on now), `completed` (finished). */\n todo_write: {\n /** The COMPLETE task list, replacing any previous list. */\n todos: ({\n /** What the task is — a short imperative line. */\n content: string;\n /** pending (not started) | in_progress (now) | completed (done). */\n status: \"pending\" | \"in_progress\" | \"completed\";\n })[];\n } & Record;\n /** Run a JavaScript workflow script that orchestrates subagents at scale. Use this for work that fans out across many independent pieces — an audit over many files, a migration, multi-angle research, adversarial verification of findings — where you write the orchestration as a script instead of delegating turn by turn. The workflow's identity rides the `meta` parameter as JSON: required `name` (short kebab-case) and `description` strings, optional `whenToUse` string and `phases` array (`{title, detail?, provider?, model?}`). The `script` parameter is the plain JavaScript body ONLY (NOT TypeScript, and NO `export const meta` statement — meta is a parameter, not code), running with top-level await; end with `return ` — the value must be JSON-serializable and is this tool's result. Script-body hooks: - `agent(prompt, opts?): Promise` — run one subagent to completion. Without `opts.schema` it resolves to the child's final text; with `opts.schema` (an object-rooted JSON Schema using ONLY type/properties/required/additionalProperties/items/enum/const/oneOf — no pattern/format/numeric bounds) it resolves to the validated object. Resolves `null` when the child fails (filter with `.filter(Boolean)`). Other opts: `label` (display), `phase` (progress group), and independent `provider`/`model` LLM target overrides (either may be provided alone). Anything else (`effort`/`isolation`/`agentType`) is rejected loudly. - `pipeline(items, ...stages): Promise` — run each item through the stages independently with NO barrier between stages (prefer this for multi-stage work). Each stage receives `(prev, item, index)`. An ordinary stage throw drops that ITEM to `null` and skips its remaining stages. - `parallel(thunks): Promise` — run zero-argument functions concurrently and await ALL of them (a barrier; use only when a stage genuinely needs every prior result together). A throwing thunk resolves to `null`. - `phase(title)` — start a progress phase; `log(message)` — narrate progress; `args` — the tool call's `args` input, verbatim. Misused hooks (bad arguments, unknown options, unsupported schemas, tripped caps) throw errors that ALWAYS kill the script — they never dissolve into a per-item `null`. Constraints: concurrency and total-agent caps apply; no filesystem, network, timers, or Node.js APIs are provided — the agents do the work, the script only coordinates them. The run executes in the foreground: this call returns when the whole script finishes. */\n workflow: {\n /** The plain-JS workflow script body (top-level await allowed; NO `export const meta` statement; end with `return `). */\n script: string;\n /** The workflow identity block (plain JSON — never code). */\n meta: {\n /** Short kebab-case workflow name. */\n name: string;\n /** One-line description of what the workflow does. */\n description: string;\n /** Optional guidance on when this workflow applies. */\n whenToUse?: string;\n /** Optional phase declarations matched by phase() calls. */\n phases?: ({\n /** The phase title phase() calls match by exact string. */\n title: string;\n /** Optional one-line description of the phase. */\n detail?: string;\n /** Optional provider override this phase is expected to use. */\n provider?: string;\n /** Optional model override this phase is expected to use. */\n model?: string;\n } & Record)[];\n } & Record;\n /** Optional JSON input exposed to the script as the `args` global (wrap a bare list as a field, e.g. {\"files\": [...]}). */\n args?: Record;\n } & Record;\n /** Create or fully replace a UTF-8 text file. */\n write: {\n /** Path to write, resolved by the filesystem backend. */\n file_path: string;\n /** Full UTF-8 text content to write. */\n content: string;\n } & Record;\n}\n\ninterface ToolOutputMap {\n bash: {\n kind: \"background\";\n jobId: string;\n } | {\n kind: \"foreground\";\n exitCode: number | null;\n signal: string | null;\n timedOut: boolean;\n aborted: boolean;\n timeoutMs: number;\n stdout: {\n text: string;\n truncated: boolean;\n spillPath?: string;\n };\n stderr: {\n text: string;\n truncated: boolean;\n spillPath?: string;\n };\n sandbox?: {\n mode: string;\n denied: boolean;\n enforcement?: string;\n runnerFailed?: boolean;\n };\n };\n cordis_define: {\n pluginId: string;\n packageId: string;\n name: string;\n purpose: string;\n hasHostHalf: boolean;\n hasClientHalf: boolean;\n };\n cordis_inspect_list: JsonValue;\n cordis_inspect_query: JsonValue;\n cordis_inspect_self: JsonValue;\n cordis_run: JsonValue;\n cordis_stop: {\n pluginId: string;\n };\n cordis_undefine: {\n pluginId: string;\n wasRunning: boolean;\n };\n edit: {\n path: string;\n before: string;\n after: string;\n };\n interrupt_agent: {\n accepted: boolean;\n };\n job_kill: {\n outcome: \"cancellation-requested\" | \"already-finished\";\n job: {\n id: string;\n kind: string;\n label: string;\n status: \"running\" | \"stopping\" | \"completed\" | \"killed\" | \"failed\";\n detail?: string;\n startedAt: number;\n finishedAt?: number;\n };\n };\n job_list: ({\n id: string;\n kind: string;\n label: string;\n status: \"running\" | \"stopping\" | \"completed\" | \"killed\" | \"failed\";\n detail?: string;\n startedAt: number;\n finishedAt?: number;\n })[];\n job_output: {\n text: string;\n job: {\n id: string;\n kind: string;\n label: string;\n status: \"running\" | \"stopping\" | \"completed\" | \"killed\" | \"failed\";\n detail?: string;\n startedAt: number;\n finishedAt?: number;\n };\n };\n ralph: {\n runId: string;\n agentsStarted: number;\n result: JsonValue;\n };\n read: {\n path: string;\n offset: number;\n lines: {\n number: number;\n text: string;\n }[];\n totalLines: number;\n };\n send_message: {\n messageId: string;\n };\n skill: {\n name: string;\n provider: string;\n resourceBase?: {\n kind: \"directory\";\n path: string;\n } | {\n kind: \"url\";\n url: string;\n } | {\n kind: \"opaque\";\n description: string;\n };\n content: string;\n };\n subagent: {\n kind: \"background\";\n jobId: string;\n } | {\n kind: \"continuable\";\n subagentId: string;\n } | {\n kind: \"foreground\";\n runId: string;\n output: JsonValue[];\n };\n subagent_fork: {\n kind: \"background\";\n jobId: string;\n } | {\n kind: \"continuable\";\n subagentId: string;\n } | {\n kind: \"foreground\";\n runId: string;\n output: JsonValue[];\n };\n todo_write: {\n todos: ({\n content: string;\n status: \"pending\" | \"in_progress\" | \"completed\";\n })[];\n counts: {\n pending: number;\n inProgress: number;\n completed: number;\n };\n };\n workflow: {\n runId: string;\n agentsStarted: number;\n result: JsonValue;\n };\n write: {\n path: string;\n operation: \"create\" | \"update\";\n before: string | null;\n after: string;\n };\n}\n\ntype ToolName = keyof ToolOutputMap\n\ndeclare class ToolCallError extends Error {\n readonly name: \"ToolCallError\";\n readonly toolName: ToolName;\n}\n\ndeclare const tools: {\n [K in ToolName]: (args: ToolArgsMap[K]) => Promise;\n}\n```","tools":[{"name":"bash","description":"Execute a bash command (`bash -c`) and return its stdout/stderr. Each call runs in a fresh shell: no state (cwd, variables, functions) persists between calls — pass `workdir` instead of using `cd`. Non-zero exits are reported as `[exit code: N]`. Current harness environment facts are exposed through managed `$DSH_*` variables; inspect them when needed. Commands may run under a file sandbox; a blocked file operation is reported as `[sandbox: file access denied under mode]` — a policy denial, not a bug in the command; do not retry another way. Long output is truncated to its tail; the full output is saved to a file whose path is reported when available. Set `run_in_background: true` for long-running commands: the call returns a job id immediately; read its output with `job_output` and stop it with `job_kill`.","parameters":{"type":"object","properties":{"command":{"type":"string","description":"The bash command to execute."},"description":{"type":"string","description":"Clear, concise description of what this command does in active voice, 5-10 words (shown in the UI). Examples: \"ls\" → \"List files in current directory\"; \"git status\" → \"Show working tree status\"; \"npm install\" → \"Install package dependencies\"."},"timeoutMs":{"type":"number","description":"Timeout in milliseconds. The executor applies its configured default and cap, and kills the command on expiry."},"workdir":{"type":"string","description":"Working directory for this command. Defaults to the session workspace; a relative path is resolved against it."},"run_in_background":{"type":"boolean","description":"Run in the background and return a job id immediately (collect with job_output, stop with job_kill). No timeout applies."}},"required":["command","description"]}},{"name":"cordis_define","description":"Define an immutable Cordis Package. For a new Plugin, use kind:\"new\" and provide only a semantic prefix of 3–6 lowercase English letters; the Host returns the final pluginId and packageId. To modify an existing Plugin, use kind:\"existing\" with its exact pluginId to append a Package without overwriting older versions. Provide at least one of code.host and code.client. Each value is a plain JavaScript function body that returns a Cordis Plugin; no TypeScript, JSX, or import transformation occurs. Query Inspect before depending on a Service, Event, Builtin, Slot, or token. Define only validates parameters and syntax and records source: it does not request approval, execute apply, or change currentPackageId. On success, call cordis_run with the returned IDs.","parameters":{"type":"object","properties":{"plugin":{"oneOf":[{"type":"object","additionalProperties":false,"properties":{"kind":{"type":"string","const":"new"},"idPrefix":{"type":"string","description":"Suggested semantic prefix of 3–6 lowercase English letters; the Host adds a unique numeric suffix."}},"required":["kind","idPrefix"]},{"type":"object","additionalProperties":false,"properties":{"kind":{"type":"string","const":"existing"},"pluginId":{"type":"string","description":"Exact ID of an existing Plugin; the new Package is appended to that instance."}},"required":["kind","pluginId"]}]},"name":{"type":"string","description":"Short, readable Package name."},"purpose":{"type":"string","description":"One-sentence, user-facing description of the Package purpose."},"code":{"type":"object","additionalProperties":false,"properties":{"host":{"type":"string","description":"Plain JavaScript function body that returns the Host-half Cordis Plugin."},"client":{"type":"string","description":"Plain JavaScript function body that returns the browser Client-half Cordis Plugin."}}}},"required":["plugin","name","purpose","code"]}},{"name":"cordis_inspect_list","description":"List every Cordis Inspect Provider currently known to the Host, including local Host Providers and the latest manifests synchronized from the Client. Each entry includes its platform, purpose, read-only methods, and input/output schemas. Call this Tool before creating or modifying a Package, then select the provider and method for cordis_inspect_query from its result. Do not guess names or treat an Inspect method as a business Service that Plugin code can call.","parameters":{"type":"object","properties":{}}},{"name":"cordis_inspect_query","description":"Run a read-only query explicitly declared by an Inspect Provider. platform, provider, and method must come from cordis_inspect_list, and input must satisfy that method's schema. Use this Tool before cordis_define to read exact Service methods, Event modes, Builtin signatures, Tool schemas, theme tokens, or live Slot trees and props. Host queries run locally. A Client query waits for the first valid page response and remains pending until a page answers or the Tool is cancelled. This Tool cannot invoke business Service methods or modify the runtime. For Service.listService and Event.listEvents, query without input to navigate the compact signature directory, then query the exact service or event for its structured contract and referenced types. For Slots.listSubTree, query without root to navigate the compact tree, then query the exact root for its complete registration contract and props.","parameters":{"type":"object","properties":{"platform":{"type":"string","description":"Runtime platform that owns the Provider.","enum":["host","client"]},"provider":{"type":"string","description":"Exact Provider ID returned by cordis_inspect_list."},"method":{"type":"string","description":"Exact method name declared by the Provider manifest."},"input":{"description":"Optional query input; it must satisfy the method input schema."}},"required":["platform","provider","method"]}},{"name":"cordis_inspect_self","description":"Inspect dynamic Cordis objects owned by the current Session at increasing levels of detail. With no IDs, list only Plugin summaries. With pluginId alone, return version pointers, the latest Run, and every Package summary. Only pluginId plus packageId returns that immutable Package's Host/Client source and runtime diagnostics. packageId cannot be supplied alone. Query an exact Package before handling @pluginId, repairing an asynchronous failure, or defining an updated version. This Tool is read-only: it neither executes code nor changes version pointers.","parameters":{"type":"object","properties":{"pluginId":{"type":"string","description":"Stable Plugin ID returned by cordis_define or injected by @pluginId; omit it to list every current Plugin."},"packageId":{"type":"string","description":"Exact immutable Package ID owned by pluginId; when specified, source and diagnostics are returned."}}}},{"name":"cordis_run","description":"Activate one exact Package of a dynamic Plugin. Use mode:\"run\" for the first activation, restarting currentPackageId, or rollback. When current exists, use mode:\"update\" to switch to a different Package, even if the Plugin is currently stopped. An unauthorized Client Package creates an approval request and returns awaiting-approval; an authorized Package returns starting and continues asynchronously in the browser. Neither result waits for the final outcome inside the Tool. currentPackageId changes only after complete success; on failure, the old current and target next remain. Asynchronous success, rejection, or technical failure is reported through state and steering. After a technical failure, read diagnostics with cordis_inspect_self, correct the same Plugin, and retry autonomously. Do not request approval again after the user rejects it.","parameters":{"type":"object","properties":{"pluginId":{"type":"string","description":"Stable Plugin ID returned by cordis_define."},"packageId":{"type":"string","description":"Exact immutable Package ID to activate under that Plugin."},"mode":{"type":"string","description":"Use run for the first activation, restarting current, or rollback; use update to switch from current to a different Package.","enum":["run","update"]}},"required":["pluginId","packageId","mode"]}},{"name":"cordis_stop","description":"Stop the current Run of a dynamic Plugin and cancel unfinished approval or activation requests. Retain the Plugin, every immutable Package, grants, currentPackageId, and nextPackageId so it can later run or update directly. Stopping an already stopped Plugin succeeds idempotently. Use this Tool to disable effects temporarily; use cordis_undefine for permanent removal.","parameters":{"type":"object","properties":{"pluginId":{"type":"string","description":"Stable dynamic Plugin ID to stop."}},"required":["pluginId"]}},{"name":"cordis_undefine","description":"Permanently remove a dynamic Plugin owned by the current Session. If it is running or awaiting approval, first stop it and cancel the request, then delete every Package, grant, and version pointer. After this returns, its pluginId, packageIds, @ reference, and Package business views are invalid; historical cards retain only a \"Plugin removed\" record. Do not call this Tool when versions must remain available for restart or rollback; use cordis_stop instead.","parameters":{"type":"object","properties":{"pluginId":{"type":"string","description":"Stable dynamic Plugin ID to remove permanently."}},"required":["pluginId"]}},{"name":"edit","description":"Edit an existing UTF-8 text file by replacing literal text.","parameters":{"type":"object","properties":{"file_path":{"type":"string","description":"Path to edit, resolved by the filesystem backend."},"old_string":{"type":"string","description":"Literal text to replace. Must match exactly."},"new_string":{"type":"string","description":"Literal replacement text. Use an empty string to delete the match."},"replace_all":{"type":"boolean","description":"Replace all matches. Defaults to false; when false, old_string must appear exactly once."}},"required":["file_path","old_string","new_string"]}},{"name":"interrupt_agent","description":"Request cancellation of a background agent's current turn by its agent id. The target may be your direct child or a deeper agent created under you. Only the current turn stops: messages already queued for the agent stay parked until a later send_message, agents it started keep running, and the agent itself stays available for follow-ups. This call returns as soon as the stop request is accepted, so the target may keep running briefly; interrupting an agent that already finished is an accepted no-op.","parameters":{"type":"object","properties":{"agent_id":{"type":"string","description":"The agent id of the running agent to interrupt."}},"required":["agent_id"]}},{"name":"job_kill","description":"Request cancellation of a running background job by job id. Returns immediately; the job settles as killed once its work actually stops.","parameters":{"type":"object","properties":{"job_id":{"type":"string","description":"Job id returned by the tool that started the background work."},"reason":{"type":"string","description":"Optional short reason, recorded in the log and forwarded to the job."}},"required":["job_id"]}},{"name":"job_list","description":"List your background jobs (running and finished) with their ids, kinds, and statuses.","parameters":{"type":"object","properties":{}}},{"name":"job_output","description":"Read a background job. Stream jobs return only output since the previous read; final-output jobs return their result after settlement. Every response ends with `[status: ...]`. Reads are non-blocking unless `wait: true`, which waits up to the configured cap.","parameters":{"type":"object","properties":{"job_id":{"type":"string","description":"Job id returned by the tool that started the background work."},"wait":{"type":"boolean","description":"Block until the job reaches a terminal status or the timeout expires. A timed-out wait returns [status: running] and leaves the job alive."},"timeout_ms":{"type":"number","description":"Max wait in milliseconds (only meaningful with wait: true). Defaults to the configured wait timeout; capped by the configured maximum."}},"required":["job_id"]}},{"name":"ralph","description":"Run a foreground fresh-agent Ralph loop toward one immutable objective. Use only when the direct human explicitly asks for Ralph or fresh-agent iteration. Each round opens a new child with no parent conversation or prior child session; the shared workspace is long-term memory, and only a bounded structured report crosses rounds. The call returns when a worker reports completion or a concrete blocker, or at the round limit. Ordinary long-running same-session work belongs to goal tools.","parameters":{"type":"object","properties":{"objective":{"type":"string","description":"The immutable completion objective for every fresh Ralph round."},"maxRounds":{"type":"number","description":"Optional positive safe-integer round cap, bounded by the deployment ceiling."}},"required":["objective"]}},{"name":"read","description":"Read a UTF-8 text file and return line-numbered content.","parameters":{"type":"object","properties":{"file_path":{"type":"string","description":"Path to read, resolved by the filesystem backend."},"offset":{"type":"number","description":"1-based first line to return. Defaults to 1."},"limit":{"type":"number","description":"Maximum number of lines to return. Defaults to 2000."}},"required":["file_path"]}},{"name":"run_code","description":"Execute a TypeScript program against the available tools. Takes two required arguments: `code`, the BODY of an async function (erasable syntax only; top-level `await` and `return` work), and `description`, a short summary of what the program does. Call tools as `await tools.name(args)` per the declarations in the system prompt. Only what you print or return comes back — curate it.","parameters":{"type":"object","properties":{"code":{"type":"string","description":"The program: the body of an async TypeScript function."},"description":{"type":"string","description":"Clear, concise description of what this program does in active voice, 5-10 words (shown in the UI). Examples: \"Count TODO markers across packages\"; \"Read failing test and its fixture\"; \"Rename config key in every cordis.yml\"."}},"required":["code","description"]}},{"name":"send_message","description":"Send a message to a background subagent by its subagent id, continuing the same conversation. It becomes the subagent's next turn: if it is still working, the message waits until its current turn finishes, so it cannot redirect work already underway. This call returns no answer from the subagent — only confirmation that the message was delivered — so use it to give it more work. A failure means the message was NOT delivered.","parameters":{"type":"object","properties":{"subagent_id":{"type":"string","description":"The subagent id returned when the background subagent was started."},"message":{"type":"string","description":"The message to deliver to the subagent."}},"required":["subagent_id","message"]}},{"name":"skill","description":"Load the full instructions for an available skill. Call this with the exact skill name from the session skill catalog before acting on a task that names or clearly matches that skill.","parameters":{"type":"object","properties":{"name":{"type":"string","description":"The exact skill name from the available skills list."}},"required":["name"]}},{"name":"subagent","description":"Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. Give it a complete, standalone prompt: it does not see this conversation. This tool runs in the background by default, immediately returns a durable subagent id, and keeps the child conversation available for later turns. When that run settles, the runtime sends the parent a notice containing its outcome and any final assistant message; `send_message` starts a later turn in the same child conversation. Set `run_in_background: false` only when your next action depends on receiving the result.","parameters":{"type":"object","properties":{"description":{"type":"string","description":"A short (3-5 word) description of the delegated task, for display."},"prompt":{"type":"string","description":"The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs."},"run_in_background":{"type":"boolean","description":"Whether to run in the background and return a durable subagent id immediately. Defaults to true. Set false to wait for the result when your next action depends on it."}},"required":["description","prompt"]}},{"name":"subagent_fork","description":"Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This call waits for the subagent and returns its result.","parameters":{"type":"object","properties":{"description":{"type":"string","description":"A short (3-5 word) description of the delegated task, for display."},"prompt":{"type":"string","description":"The task for the subagent. It already sees this conversation's completed turns, so build on them freely and state only what is new."}},"required":["description","prompt"]}},{"name":"todo_write","description":"Record and update a structured task list for the current work. Send the ENTIRE list every call — it REPLACES the previous list (there are no partial updates, no per-item edits). Use it to plan multi-step work and show progress: add one todo per concrete step before you start. Mark every todo being actively worked on `in_progress` — several at once when work genuinely runs in parallel (e.g. concurrent subagents or background commands), one for sequential work; while work remains, at least one task should be `in_progress`. Mark a todo `completed` the moment it is done (do not batch completions), and allow no `in_progress` item only once all work is complete. Skip the list for trivial single-step tasks. Statuses: `pending` (not started), `in_progress` (being worked on now), `completed` (finished).","parameters":{"type":"object","properties":{"todos":{"type":"array","description":"The COMPLETE task list, replacing any previous list.","items":{"type":"object","additionalProperties":false,"properties":{"content":{"type":"string","description":"What the task is — a short imperative line."},"status":{"type":"string","description":"pending (not started) | in_progress (now) | completed (done).","enum":["pending","in_progress","completed"]}},"required":["content","status"]}}},"required":["todos"]}},{"name":"workflow","description":"Run a JavaScript workflow script that orchestrates subagents at scale. Use this for work that fans out across many independent pieces — an audit over many files, a migration, multi-angle research, adversarial verification of findings — where you write the orchestration as a script instead of delegating turn by turn.\n\nThe workflow's identity rides the `meta` parameter as JSON: required `name` (short kebab-case) and `description` strings, optional `whenToUse` string and `phases` array (`{title, detail?, provider?, model?}`). The `script` parameter is the plain JavaScript body ONLY (NOT TypeScript, and NO `export const meta` statement — meta is a parameter, not code), running with top-level await; end with `return ` — the value must be JSON-serializable and is this tool's result.\n\nScript-body hooks:\n- `agent(prompt, opts?): Promise` — run one subagent to completion. Without `opts.schema` it resolves to the child's final text; with `opts.schema` (an object-rooted JSON Schema using ONLY type/properties/required/additionalProperties/items/enum/const/oneOf — no pattern/format/numeric bounds) it resolves to the validated object. Resolves `null` when the child fails (filter with `.filter(Boolean)`). Other opts: `label` (display), `phase` (progress group), and independent `provider`/`model` LLM target overrides (either may be provided alone). Anything else (`effort`/`isolation`/`agentType`) is rejected loudly.\n- `pipeline(items, ...stages): Promise` — run each item through the stages independently with NO barrier between stages (prefer this for multi-stage work). Each stage receives `(prev, item, index)`. An ordinary stage throw drops that ITEM to `null` and skips its remaining stages.\n- `parallel(thunks): Promise` — run zero-argument functions concurrently and await ALL of them (a barrier; use only when a stage genuinely needs every prior result together). A throwing thunk resolves to `null`.\n- `phase(title)` — start a progress phase; `log(message)` — narrate progress; `args` — the tool call's `args` input, verbatim.\n\nMisused hooks (bad arguments, unknown options, unsupported schemas, tripped caps) throw errors that ALWAYS kill the script — they never dissolve into a per-item `null`.\n\nConstraints: concurrency and total-agent caps apply; no filesystem, network, timers, or Node.js APIs are provided — the agents do the work, the script only coordinates them. The run executes in the foreground: this call returns when the whole script finishes.","parameters":{"type":"object","properties":{"script":{"type":"string","description":"The plain-JS workflow script body (top-level await allowed; NO `export const meta` statement; end with `return `)."},"meta":{"type":"object","description":"The workflow identity block (plain JSON — never code).","additionalProperties":true,"properties":{"name":{"type":"string","description":"Short kebab-case workflow name."},"description":{"type":"string","description":"One-line description of what the workflow does."},"whenToUse":{"type":"string","description":"Optional guidance on when this workflow applies."},"phases":{"type":"array","description":"Optional phase declarations matched by phase() calls.","items":{"type":"object","additionalProperties":true,"properties":{"title":{"type":"string","description":"The phase title phase() calls match by exact string."},"detail":{"type":"string","description":"Optional one-line description of the phase."},"provider":{"type":"string","description":"Optional provider override this phase is expected to use."},"model":{"type":"string","description":"Optional model override this phase is expected to use."}},"required":["title"]}}},"required":["name","description"]},"args":{"type":"object","description":"Optional JSON input exposed to the script as the `args` global (wrap a bare list as a field, e.g. {\"files\": [...]}).","additionalProperties":true}},"required":["script","meta"]}},{"name":"write","description":"Create or fully replace a UTF-8 text file.","parameters":{"type":"object","properties":{"file_path":{"type":"string","description":"Path to write, resolved by the filesystem backend."},"content":{"type":"string","description":"Full UTF-8 text content to write."}},"required":["file_path","content"]}}]},"reason":"initial"}} {"type":"request/context","seq":7,"time":1785730501403,"data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"assistant/chunk","seq":8,"time":1783950000007,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}} {"type":"assistant/chunk","seq":9,"time":1783950000008,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":0,"id":"advanced-define","name":"cordis_define","argumentsDelta":"{\"plugin\":{\"kind\":\"new\",\"idPrefix\":\"snap\"},\"name\":\"Snapshot Marker\",\"purpose\":\"Exercise the dynamic Cordis Package lifecycle in the snapshot.\",\"code\":{\"host\":\"return { apply() {} }\"}}"}}} {"type":"assistant/chunk","seq":10,"time":1783950000009,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"advanced-define","name":"cordis_define","arguments":"{\"plugin\":{\"kind\":\"new\",\"idPrefix\":\"snap\"},\"name\":\"Snapshot Marker\",\"purpose\":\"Exercise the dynamic Cordis Package lifecycle in the snapshot.\",\"code\":{\"host\":\"return { apply() {} }\"}}"}}}} {"type":"assistant/chunk","seq":11,"time":1785498583784,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}} {"type":"assistant/chunk","seq":12,"time":1785730501404,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}} -{"type":"assistant/message","seq":13,"time":1785730501404,"data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"advanced-define","name":"cordis_define","arguments":"{\"plugin\":{\"kind\":\"new\",\"idPrefix\":\"snap\"},\"name\":\"Snapshot Marker\",\"purpose\":\"Exercise the dynamic Cordis Package lifecycle in the snapshot.\",\"code\":{\"host\":\"return { apply() {} }\"}}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"79c1bd38-584a-4756-8854-211919937987"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[8,9,10,11,12],"surfaceOp":"append"} +{"type":"assistant/message","seq":13,"time":1785730501404,"data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"advanced-define","name":"cordis_define","arguments":"{\"plugin\":{\"kind\":\"new\",\"idPrefix\":\"snap\"},\"name\":\"Snapshot Marker\",\"purpose\":\"Exercise the dynamic Cordis Package lifecycle in the snapshot.\",\"code\":{\"host\":\"return { apply() {} }\"}}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"e0351488-7bca-48d6-b7af-87d533858f47"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[8,9,10,11,12],"surfaceOp":"append"} {"type":"tool/call","seq":14,"time":1785730501404,"data":{"turn":1,"step":1,"callId":"advanced-define","name":"cordis_define","arguments":"{\"plugin\":{\"kind\":\"new\",\"idPrefix\":\"snap\"},\"name\":\"Snapshot Marker\",\"purpose\":\"Exercise the dynamic Cordis Package lifecycle in the snapshot.\",\"code\":{\"host\":\"return { apply() {} }\"}}"}} -{"type":"tool/result","seq":15,"time":1785730501413,"data":{"turn":1,"step":1,"message":{"source":{"kind":"tool","callId":"advanced-define"},"content":[{"type":"tool-result","toolCallId":"advanced-define","content":[{"type":"text","text":"Defined snap-1/pkg-1 (Snapshot Marker); it is not running yet. Use cordis_run to activate this Package."}],"isError":false}],"role":"user","id":"8255947c-3d5d-4872-8359-914555595bd3"},"meta":{"pluginId":"snap-1","packageId":"pkg-1"}},"sourceEventSeqs":[14],"surfaceOp":"append"} +{"type":"tool/result","seq":15,"time":1785730501413,"data":{"turn":1,"step":1,"message":{"source":{"kind":"tool","callId":"advanced-define"},"content":[{"type":"tool-result","toolCallId":"advanced-define","content":[{"type":"text","text":"Defined snap-1/pkg-1 (Snapshot Marker); it is not running yet. Use cordis_run to activate this Package."}],"isError":false}],"role":"user","id":"9fd9ba62-1b6d-4bb7-98c6-97815e983026"},"meta":{"pluginId":"snap-1","packageId":"pkg-1"}},"sourceEventSeqs":[14],"surfaceOp":"append"} {"type":"step/end","seq":16,"time":1785730501413,"data":{"turn":1,"step":1}} {"type":"step/start","seq":17,"time":1785730501423,"data":{"turn":1,"step":2}} {"type":"assistant/chunk","seq":18,"time":1783950000017,"data":{"turn":1,"step":2,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}} @@ -22,13 +22,13 @@ {"type":"assistant/chunk","seq":20,"time":1783950000019,"data":{"turn":1,"step":2,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"advanced-code","name":"run_code","arguments":"{\"code\":\"const run = await tools.cordis_run({ pluginId: 'snap-1', packageId: 'pkg-1', mode: 'run' });\\nconst inspected = await tools.cordis_inspect_self({ pluginId: 'snap-1' });\\nreturn { run, inspected };\",\"description\":\"Run and inspect the dynamic Cordis Package\"}"}}}} {"type":"assistant/chunk","seq":21,"time":1785498583804,"data":{"turn":1,"step":2,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}} {"type":"assistant/chunk","seq":22,"time":1785730501424,"data":{"turn":1,"step":2,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}} -{"type":"assistant/message","seq":23,"time":1785730501424,"data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"tool-call","id":"advanced-code","name":"run_code","arguments":"{\"code\":\"const run = await tools.cordis_run({ pluginId: 'snap-1', packageId: 'pkg-1', mode: 'run' });\\nconst inspected = await tools.cordis_inspect_self({ pluginId: 'snap-1' });\\nreturn { run, inspected };\",\"description\":\"Run and inspect the dynamic Cordis Package\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"e73246e2-257d-4d38-a8cd-5e5f713d4ad3"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[18,19,20,21,22],"surfaceOp":"append"} +{"type":"assistant/message","seq":23,"time":1785730501424,"data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"tool-call","id":"advanced-code","name":"run_code","arguments":"{\"code\":\"const run = await tools.cordis_run({ pluginId: 'snap-1', packageId: 'pkg-1', mode: 'run' });\\nconst inspected = await tools.cordis_inspect_self({ pluginId: 'snap-1' });\\nreturn { run, inspected };\",\"description\":\"Run and inspect the dynamic Cordis Package\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"6f6c3cc3-350b-4afb-a3d1-8f91b9494628"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[18,19,20,21,22],"surfaceOp":"append"} {"type":"tool/call","seq":24,"time":1785730501424,"data":{"turn":1,"step":2,"callId":"advanced-code","name":"run_code","arguments":"{\"code\":\"const run = await tools.cordis_run({ pluginId: 'snap-1', packageId: 'pkg-1', mode: 'run' });\\nconst inspected = await tools.cordis_inspect_self({ pluginId: 'snap-1' });\\nreturn { run, inspected };\",\"description\":\"Run and inspect the dynamic Cordis Package\"}"}} {"type":"tool/code-dispatch-start","seq":25,"time":1785730501473,"data":{"rootCallId":"advanced-code","parentCallId":"advanced-code","subCallId":"advanced-code:code:1","name":"cordis_run","arguments":{"pluginId":"snap-1","packageId":"pkg-1","mode":"run"}}} {"type":"tool/code-dispatch","seq":26,"time":1785730501474,"data":{"rootCallId":"advanced-code","parentCallId":"advanced-code","subCallId":"advanced-code:code:1","name":"cordis_run","arguments":{"pluginId":"snap-1","packageId":"pkg-1","mode":"run"},"isError":false,"content":[{"type":"text","text":"snap-1/pkg-1 is running (run-1)."}]}} {"type":"tool/code-dispatch-start","seq":27,"time":1786558903189,"data":{"rootCallId":"advanced-code","parentCallId":"advanced-code","subCallId":"advanced-code:code:2","name":"cordis_inspect_self","arguments":{"pluginId":"snap-1"}}} {"type":"tool/code-dispatch","seq":28,"time":1786558903189,"data":{"rootCallId":"advanced-code","parentCallId":"advanced-code","subCallId":"advanced-code:code:2","name":"cordis_inspect_self","arguments":{"pluginId":"snap-1"},"isError":false,"content":[{"type":"text","text":"{\n \"mode\": \"plugin\",\n \"pluginId\": \"snap-1\",\n \"name\": \"Snapshot Marker\",\n \"packageCount\": 1,\n \"state\": \"running\",\n \"currentPackageId\": \"pkg-1\",\n \"activeRun\": {\n \"pluginRunId\": \"run-1\",\n \"packageId\": \"pkg-1\"\n },\n \"packages\": [\n {\n \"packageId\": \"pkg-1\",\n \"name\": \"Snapshot Marker\",\n \"purpose\": \"Exercise the dynamic Cordis Package lifecycle in the snapshot.\",\n \"hasHostHalf\": true,\n \"hasClientHalf\": false,\n \"isCurrent\": true,\n \"isNext\": false\n }\n ]\n}"}]}} -{"type":"tool/result","seq":29,"time":1786558903193,"data":{"turn":1,"step":2,"message":{"source":{"kind":"tool","callId":"advanced-code"},"content":[{"type":"tool-result","toolCallId":"advanced-code","content":[{"type":"text","text":"{\n \"run\": {\n \"status\": \"running\",\n \"pluginId\": \"snap-1\",\n \"packageId\": \"pkg-1\",\n \"pluginRunId\": \"run-1\",\n \"currentPackageId\": \"pkg-1\",\n \"host\": {\n \"status\": \"running\",\n \"provides\": [],\n \"waitingFor\": []\n },\n \"client\": {\n \"status\": \"absent\",\n \"waitingFor\": []\n }\n },\n \"inspected\": {\n \"mode\": \"plugin\",\n \"pluginId\": \"snap-1\",\n \"name\": \"Snapshot Marker\",\n \"packageCount\": 1,\n \"state\": \"running\",\n \"currentPackageId\": \"pkg-1\",\n \"activeRun\": {\n \"pluginRunId\": \"run-1\",\n \"packageId\": \"pkg-1\"\n },\n \"packages\": [\n {\n \"packageId\": \"pkg-1\",\n \"name\": \"Snapshot Marker\",\n \"purpose\": \"Exercise the dynamic Cordis Package lifecycle in the snapshot.\",\n \"hasHostHalf\": true,\n \"hasClientHalf\": false,\n \"isCurrent\": true,\n \"isNext\": false\n }\n ]\n }\n}"}],"isError":false}],"role":"user","id":"acb0a833-2535-41ff-9e1d-926c092329b6"}},"sourceEventSeqs":[24],"surfaceOp":"append"} +{"type":"tool/result","seq":29,"time":1786558903193,"data":{"turn":1,"step":2,"message":{"source":{"kind":"tool","callId":"advanced-code"},"content":[{"type":"tool-result","toolCallId":"advanced-code","content":[{"type":"text","text":"{\n \"run\": {\n \"status\": \"running\",\n \"pluginId\": \"snap-1\",\n \"packageId\": \"pkg-1\",\n \"pluginRunId\": \"run-1\",\n \"currentPackageId\": \"pkg-1\",\n \"host\": {\n \"status\": \"running\",\n \"provides\": [],\n \"waitingFor\": []\n },\n \"client\": {\n \"status\": \"absent\",\n \"waitingFor\": []\n }\n },\n \"inspected\": {\n \"mode\": \"plugin\",\n \"pluginId\": \"snap-1\",\n \"name\": \"Snapshot Marker\",\n \"packageCount\": 1,\n \"state\": \"running\",\n \"currentPackageId\": \"pkg-1\",\n \"activeRun\": {\n \"pluginRunId\": \"run-1\",\n \"packageId\": \"pkg-1\"\n },\n \"packages\": [\n {\n \"packageId\": \"pkg-1\",\n \"name\": \"Snapshot Marker\",\n \"purpose\": \"Exercise the dynamic Cordis Package lifecycle in the snapshot.\",\n \"hasHostHalf\": true,\n \"hasClientHalf\": false,\n \"isCurrent\": true,\n \"isNext\": false\n }\n ]\n }\n}"}],"isError":false}],"role":"user","id":"40a17cbf-a853-4813-bbb5-7970cfbc7010"}},"sourceEventSeqs":[24],"surfaceOp":"append"} {"type":"step/end","seq":30,"time":1786558903193,"data":{"turn":1,"step":2}} {"type":"step/start","seq":31,"time":1786558903203,"data":{"turn":1,"step":3}} {"type":"assistant/chunk","seq":32,"time":1785037378923,"data":{"turn":1,"step":3,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}} @@ -36,9 +36,9 @@ {"type":"assistant/chunk","seq":34,"time":1785730501484,"data":{"turn":1,"step":3,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"advanced-direct-child","name":"subagent","arguments":"{\"description\":\"Check direct child\",\"prompt\":\"Reply with exactly DIRECT_CHILD_OK and nothing else.\",\"run_in_background\":false}"}}}} {"type":"assistant/chunk","seq":35,"time":1786558903204,"data":{"turn":1,"step":3,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}} {"type":"assistant/chunk","seq":36,"time":1786558903204,"data":{"turn":1,"step":3,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}} -{"type":"assistant/message","seq":37,"time":1786558903204,"data":{"turn":1,"step":3,"message":{"role":"assistant","content":[{"type":"tool-call","id":"advanced-direct-child","name":"subagent","arguments":"{\"description\":\"Check direct child\",\"prompt\":\"Reply with exactly DIRECT_CHILD_OK and nothing else.\",\"run_in_background\":false}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"32da94eb-ef97-4929-8dec-dea761506e90"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[32,33,34,35,36],"surfaceOp":"append"} +{"type":"assistant/message","seq":37,"time":1786558903204,"data":{"turn":1,"step":3,"message":{"role":"assistant","content":[{"type":"tool-call","id":"advanced-direct-child","name":"subagent","arguments":"{\"description\":\"Check direct child\",\"prompt\":\"Reply with exactly DIRECT_CHILD_OK and nothing else.\",\"run_in_background\":false}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"8bdea090-4a9a-451f-bb21-459af50472fa"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[32,33,34,35,36],"surfaceOp":"append"} {"type":"tool/call","seq":38,"time":1786558903205,"data":{"turn":1,"step":3,"callId":"advanced-direct-child","name":"subagent","arguments":"{\"description\":\"Check direct child\",\"prompt\":\"Reply with exactly DIRECT_CHILD_OK and nothing else.\",\"run_in_background\":false}"}} -{"type":"tool/result","seq":39,"time":1786558903240,"data":{"turn":1,"step":3,"message":{"source":{"kind":"tool","callId":"advanced-direct-child"},"content":[{"type":"tool-result","toolCallId":"advanced-direct-child","content":[{"type":"text","text":"DIRECT_CHILD_OK"}],"isError":false}],"role":"user","id":"29fcc9e2-dee3-4bf7-b3a9-e167c00a755b"}},"sourceEventSeqs":[38],"surfaceOp":"append"} +{"type":"tool/result","seq":39,"time":1786558903240,"data":{"turn":1,"step":3,"message":{"source":{"kind":"tool","callId":"advanced-direct-child"},"content":[{"type":"tool-result","toolCallId":"advanced-direct-child","content":[{"type":"text","text":"DIRECT_CHILD_OK"}],"isError":false}],"role":"user","id":"c978c208-8ebd-4dd6-b997-606ca7de787e"}},"sourceEventSeqs":[38],"surfaceOp":"append"} {"type":"step/end","seq":40,"time":1786558903240,"data":{"turn":1,"step":3}} {"type":"step/start","seq":41,"time":1786558903249,"data":{"turn":1,"step":4}} {"type":"assistant/chunk","seq":42,"time":1785037378946,"data":{"turn":1,"step":4,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}} @@ -46,13 +46,13 @@ {"type":"assistant/chunk","seq":44,"time":1785730501522,"data":{"turn":1,"step":4,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"advanced-workflow","name":"workflow","arguments":"{\"script\":\"phase('Delegate')\\nconst reply = await agent('Reply with exactly WORKFLOW_CHILD_OK and nothing else.', { label: 'workflow-child' })\\nreturn { reply }\",\"meta\":{\"name\":\"advanced-headless-snapshot\",\"description\":\"exercise one workflow child through the headless agent\"}}"}}}} {"type":"assistant/chunk","seq":45,"time":1786558903250,"data":{"turn":1,"step":4,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}} {"type":"assistant/chunk","seq":46,"time":1786558903250,"data":{"turn":1,"step":4,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}} -{"type":"assistant/message","seq":47,"time":1786558903250,"data":{"turn":1,"step":4,"message":{"role":"assistant","content":[{"type":"tool-call","id":"advanced-workflow","name":"workflow","arguments":"{\"script\":\"phase('Delegate')\\nconst reply = await agent('Reply with exactly WORKFLOW_CHILD_OK and nothing else.', { label: 'workflow-child' })\\nreturn { reply }\",\"meta\":{\"name\":\"advanced-headless-snapshot\",\"description\":\"exercise one workflow child through the headless agent\"}}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"6fff1bc7-3e35-415b-ae02-e018d360fe09"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[42,43,44,45,46],"surfaceOp":"append"} +{"type":"assistant/message","seq":47,"time":1786558903250,"data":{"turn":1,"step":4,"message":{"role":"assistant","content":[{"type":"tool-call","id":"advanced-workflow","name":"workflow","arguments":"{\"script\":\"phase('Delegate')\\nconst reply = await agent('Reply with exactly WORKFLOW_CHILD_OK and nothing else.', { label: 'workflow-child' })\\nreturn { reply }\",\"meta\":{\"name\":\"advanced-headless-snapshot\",\"description\":\"exercise one workflow child through the headless agent\"}}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"e55b2b2e-497c-45d2-8115-16f317ae573f"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[42,43,44,45,46],"surfaceOp":"append"} {"type":"tool/call","seq":48,"time":1786558903250,"data":{"turn":1,"step":4,"callId":"advanced-workflow","name":"workflow","arguments":"{\"script\":\"phase('Delegate')\\nconst reply = await agent('Reply with exactly WORKFLOW_CHILD_OK and nothing else.', { label: 'workflow-child' })\\nreturn { reply }\",\"meta\":{\"name\":\"advanced-headless-snapshot\",\"description\":\"exercise one workflow child through the headless agent\"}}"}} {"type":"tool-workflow/run-start","seq":49,"time":1786558903255,"data":{"runId":"cd3d2666-94a1-4285-804e-c99630bc7b51","name":"advanced-headless-snapshot"}} {"type":"tool-workflow/agent-start","seq":50,"time":1786558903485,"data":{"runId":"cd3d2666-94a1-4285-804e-c99630bc7b51","seq":1,"label":"workflow-child","phase":"Delegate","childId":"33333333-3333-4333-8333-333333333333"}} {"type":"tool-workflow/agent-end","seq":51,"time":1786558903518,"data":{"runId":"cd3d2666-94a1-4285-804e-c99630bc7b51","seq":1,"outcome":"completed"}} {"type":"tool-workflow/run-end","seq":52,"time":1786558903521,"data":{"runId":"cd3d2666-94a1-4285-804e-c99630bc7b51","stopReason":"completed"}} -{"type":"tool/result","seq":53,"time":1786558903521,"data":{"turn":1,"step":4,"message":{"source":{"kind":"tool","callId":"advanced-workflow"},"content":[{"type":"tool-result","toolCallId":"advanced-workflow","content":[{"type":"text","text":"workflow \"advanced-headless-snapshot\" completed (1 agent).\nReturn value:\n{\n \"reply\": \"WORKFLOW_CHILD_OK\"\n}"}],"isError":false}],"role":"user","id":"82895074-35a8-470a-a622-b951d2fc2665"}},"sourceEventSeqs":[48],"surfaceOp":"append"} +{"type":"tool/result","seq":53,"time":1786558903521,"data":{"turn":1,"step":4,"message":{"source":{"kind":"tool","callId":"advanced-workflow"},"content":[{"type":"tool-result","toolCallId":"advanced-workflow","content":[{"type":"text","text":"workflow \"advanced-headless-snapshot\" completed (1 agent).\nReturn value:\n{\n \"reply\": \"WORKFLOW_CHILD_OK\"\n}"}],"isError":false}],"role":"user","id":"f85f58fc-8d7e-4c9f-a0fe-caff480a9fec"}},"sourceEventSeqs":[48],"surfaceOp":"append"} {"type":"step/end","seq":54,"time":1786558903521,"data":{"turn":1,"step":4}} {"type":"step/start","seq":55,"time":1786558903530,"data":{"turn":1,"step":5}} {"type":"assistant/chunk","seq":56,"time":1786359174239,"data":{"turn":1,"step":5,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}} @@ -60,9 +60,9 @@ {"type":"assistant/chunk","seq":58,"time":1786359174239,"data":{"turn":1,"step":5,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"advanced-undefine","name":"cordis_undefine","arguments":"{\"pluginId\":\"snap-1\"}"}}}} {"type":"assistant/chunk","seq":59,"time":1786558903530,"data":{"turn":1,"step":5,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}} {"type":"assistant/chunk","seq":60,"time":1786558903530,"data":{"turn":1,"step":5,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}} -{"type":"assistant/message","seq":61,"time":1786558903530,"data":{"turn":1,"step":5,"message":{"role":"assistant","content":[{"type":"tool-call","id":"advanced-undefine","name":"cordis_undefine","arguments":"{\"pluginId\":\"snap-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"b1219ecf-66a4-4de1-b822-a39b6651bd90"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[56,57,58,59,60],"surfaceOp":"append"} +{"type":"assistant/message","seq":61,"time":1786558903530,"data":{"turn":1,"step":5,"message":{"role":"assistant","content":[{"type":"tool-call","id":"advanced-undefine","name":"cordis_undefine","arguments":"{\"pluginId\":\"snap-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"68bd993f-a0bd-4ea8-ad16-6b1a19e09bd3"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[56,57,58,59,60],"surfaceOp":"append"} {"type":"tool/call","seq":62,"time":1786558903531,"data":{"turn":1,"step":5,"callId":"advanced-undefine","name":"cordis_undefine","arguments":"{\"pluginId\":\"snap-1\"}"}} -{"type":"tool/result","seq":63,"time":1786558903537,"data":{"turn":1,"step":5,"message":{"source":{"kind":"tool","callId":"advanced-undefine"},"content":[{"type":"tool-result","toolCallId":"advanced-undefine","content":[{"type":"text","text":"Removed dynamic Plugin snap-1 and all of its Packages."}],"isError":false}],"role":"user","id":"30c8e3bb-2ada-4576-9764-6e87f5b8fc94"}},"sourceEventSeqs":[62],"surfaceOp":"append"} +{"type":"tool/result","seq":63,"time":1786558903537,"data":{"turn":1,"step":5,"message":{"source":{"kind":"tool","callId":"advanced-undefine"},"content":[{"type":"tool-result","toolCallId":"advanced-undefine","content":[{"type":"text","text":"Removed dynamic Plugin snap-1 and all of its Packages."}],"isError":false}],"role":"user","id":"2d90e3b5-2a4c-4408-a1a0-3d009786a07b"}},"sourceEventSeqs":[62],"surfaceOp":"append"} {"type":"step/end","seq":64,"time":1786558903537,"data":{"turn":1,"step":5}} {"type":"step/start","seq":65,"time":1786558903547,"data":{"turn":1,"step":6}} {"type":"assistant/chunk","seq":66,"time":1786359174249,"data":{"turn":1,"step":6,"chunk":{"type":"block-start","index":0,"blockType":"text"}}} @@ -70,6 +70,6 @@ {"type":"assistant/chunk","seq":68,"time":1786359174249,"data":{"turn":1,"step":6,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"ADVANCED_HEADLESS_OK"}}}} {"type":"assistant/chunk","seq":69,"time":1786558903548,"data":{"turn":1,"step":6,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}} {"type":"assistant/chunk","seq":70,"time":1786558903548,"data":{"turn":1,"step":6,"chunk":{"type":"finish","reason":{"kind":"stop"}}}} -{"type":"assistant/message","seq":71,"time":1786558903548,"data":{"turn":1,"step":6,"message":{"role":"assistant","content":[{"type":"text","text":"ADVANCED_HEADLESS_OK"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"9b46dd3a-e3ea-4f25-a246-814f31826e9e"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[66,67,68,69,70],"surfaceOp":"append"} +{"type":"assistant/message","seq":71,"time":1786558903548,"data":{"turn":1,"step":6,"message":{"role":"assistant","content":[{"type":"text","text":"ADVANCED_HEADLESS_OK"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"f3823367-2e25-43d2-a129-70dc492b2a90"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[66,67,68,69,70],"surfaceOp":"append"} {"type":"step/end","seq":72,"time":1786558903549,"data":{"turn":1,"step":6}} {"type":"turn/end","seq":73,"time":1786558903549,"data":{"turn":1,"reason":{"kind":"completed"}}} diff --git a/examples/jsonrpc-agent/README.i18n.yaml b/examples/jsonrpc-agent/README.i18n.yaml index b8cf6969df..78a96ee6ac 100644 --- a/examples/jsonrpc-agent/README.i18n.yaml +++ b/examples/jsonrpc-agent/README.i18n.yaml @@ -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 examples/jsonrpc-agent/README.md -README.md: 5166d94e92e2e4bcdda5026fa65ba6b77b87fe40 -README.zh.md: f84ab95132e820cf0fcf45bff4ae30d9bccb55c1 +README.md: ec94fa7ceec5a51585241851eaee2cfcf938738f +README.zh.md: 64a5e607bd37e97b60cb0a4f6ee89a7c766d7464 diff --git a/examples/jsonrpc-agent/README.md b/examples/jsonrpc-agent/README.md index 5166d94e92..ec94fa7cee 100644 --- a/examples/jsonrpc-agent/README.md +++ b/examples/jsonrpc-agent/README.md @@ -30,7 +30,7 @@ Pass the config path through the Python SDK's `cordis` option or `DSH_CORDIS_CON ## Minimal variant -[`minimal.cordis.yml`](minimal.cordis.yml) is the complete standalone counterpart of the Web `minimal` preset. `DSH_SYSTEM_PROMPT` selects its system prompt, with `You are a helpful software engineer assistant.` as the fallback, and no context-compaction plugin is mounted. Its model-facing tools are exactly: +[`minimal.cordis.yml`](minimal.cordis.yml) is the complete standalone counterpart of the Web `minimal` preset. `DSH_SYSTEM_PROMPT` selects its system prompt, with `You are a helpful software engineer assistant.` as the fallback. It suppresses every system-prompt runtime-context contribution for fresh sessions and mounts no context-compaction plugin. Its model-facing tools are exactly: - owner-scoped persistent `bash` - `str_replace_editor` with `view`, `create`, `str_replace`, and `insert` diff --git a/examples/jsonrpc-agent/README.zh.md b/examples/jsonrpc-agent/README.zh.md index f84ab95132..64a5e607bd 100644 --- a/examples/jsonrpc-agent/README.zh.md +++ b/examples/jsonrpc-agent/README.zh.md @@ -30,7 +30,7 @@ ## 极简变体 -[`minimal.cordis.yml`](minimal.cordis.yml) 是 Web `minimal` preset 的完整独立版本。`DSH_SYSTEM_PROMPT` 选择它的系统提示词,未设置时使用 `You are a helpful software engineer assistant.`,且不挂载上下文压缩插件。面向模型的工具严格只有: +[`minimal.cordis.yml`](minimal.cordis.yml) 是 Web `minimal` preset 的完整独立版本。`DSH_SYSTEM_PROMPT` 选择它的系统提示词,未设置时使用 `You are a helpful software engineer assistant.`。它为新建会话抑制每个 system-prompt runtime-context 贡献,且不挂载上下文压缩插件。面向模型的工具严格只有: - 所有者作用域内持久化的 `bash` - 提供 `view`、`create`、`str_replace` 与 `insert` 的 `str_replace_editor` diff --git a/examples/jsonrpc-agent/minimal.cordis.yml b/examples/jsonrpc-agent/minimal.cordis.yml index 8d6e9b8181..e23d52a866 100644 --- a/examples/jsonrpc-agent/minimal.cordis.yml +++ b/examples/jsonrpc-agent/minimal.cordis.yml @@ -1,6 +1,7 @@ # Complete unattended minimal-agent composition for the Python SDK. The model # sees one deployment-selected system prompt and only the owner-scoped -# persistent Bash and string-replace editor tools. Context compaction is absent. +# persistent Bash and string-replace editor tools. Runtime-context injection and +# context compaction are absent. - id: sdk-jsonrpc-server name: '@deepseek-ai/dsh-sdk-jsonrpc-server' @@ -47,6 +48,7 @@ name: '@deepseek-ai/dsh-agent-spine-demo' config: includeHarnessIdentity: false + includeRuntimeContext: false persona: !!js process.env.DSH_SYSTEM_PROMPT ?? 'You are a helpful software engineer assistant.' workspaceContext: false skills: diff --git a/examples/jsonrpc-agent/tests/sdk.snapshot.ts b/examples/jsonrpc-agent/tests/sdk.snapshot.ts index 85667cf64d..9b45292df5 100644 --- a/examples/jsonrpc-agent/tests/sdk.snapshot.ts +++ b/examples/jsonrpc-agent/tests/sdk.snapshot.ts @@ -77,8 +77,8 @@ interface SdkScenario { expectedSystem?: string /** Exact model-facing descriptions for selected tools. */ expectedToolDescriptions?: Readonly> - /** Stable policy-context clauses the real assembled request must include or omit. */ - policyContext?: { includes: readonly string[]; excludes: readonly string[] } + /** Expected runtime-context state in the real assembled request. */ + runtimeContext?: false | { includes: readonly string[]; excludes: readonly string[] } } const SCENARIOS: SdkScenario[] = [ @@ -111,10 +111,7 @@ const SCENARIOS: SdkScenario[] = [ expectedTools: { bash: ['command'], str_replace_editor: ['command', 'path'] }, expectedSystem: MINIMAL_SYSTEM_PROMPT, expectedToolDescriptions: { bash: MINIMAL_BASH_DESCRIPTION }, - policyContext: { - includes: ['Current DSH file policy: danger-full-access.', 'file modifications by available operations'], - excludes: ['write and edit tools', 'terminal sessions', 'one-shot bash commands'], - }, + runtimeContext: false, }, ] @@ -182,8 +179,8 @@ function assembledSystem(log: PersistedLog): string { return system } -function assembledPolicyContext(log: PersistedLog): string { - const contexts = log.content.trimEnd().split('\n').flatMap((line) => { +function assembledRuntimeContexts(log: PersistedLog): string[] { + return log.content.trimEnd().split('\n').flatMap((line) => { const event = JSON.parse(line) as { type?: string data?: { source?: { kind?: string; plugin?: string }; content?: Array<{ type?: string; text?: unknown }> } @@ -193,8 +190,6 @@ function assembledPolicyContext(log: PersistedLog): string { || event.data.source.plugin !== '@deepseek-ai/dsh-system-prompt') return [] return event.data.content?.flatMap(block => block.type === 'text' && typeof block.text === 'string' ? [block.text] : []) ?? [] }) - if (contexts.length !== 1) throw new Error(`session log has ${String(contexts.length)} runtime-context snapshots; expected one`) - return contexts[0] as string } function contextOf(logs: readonly { content: string; header: Record }[], cwd: string): NormalizeContext { @@ -447,14 +442,20 @@ describe('TypeScript SDK snapshots over the jsonrpc runtime', () => { if (parent === undefined) throw new Error(`${scenario.name} has no parent session log`) expect(assembledToolDescriptions(parent)).toMatchObject(scenario.expectedToolDescriptions) } - if (scenario.policyContext !== undefined) { + if (scenario.runtimeContext !== undefined) { const parent = ordered[0] if (parent === undefined) throw new Error(`${scenario.name} has no parent session log`) - const context = assembledPolicyContext(parent) - for (const clause of scenario.policyContext.includes) expect(context).toContain(clause) - for (const clause of scenario.policyContext.excludes) expect(context).not.toContain(clause) - const system = assembledSystem(parent) - for (const clause of scenario.policyContext.includes) expect(system).not.toContain(clause) + const contexts = assembledRuntimeContexts(parent) + if (scenario.runtimeContext === false) { + expect(contexts).toEqual([]) + } else { + expect(contexts).toHaveLength(1) + const context = contexts[0] as string + for (const clause of scenario.runtimeContext.includes) expect(context).toContain(clause) + for (const clause of scenario.runtimeContext.excludes) expect(context).not.toContain(clause) + const system = assembledSystem(parent) + for (const clause of scenario.runtimeContext.includes) expect(system).not.toContain(clause) + } } if (scenario.children > 0) { expect(notifications.some(n => n.method === 'subagent.started')).toBe(true) diff --git a/examples/jsonrpc-agent/tests/snapshots/persistent-tools/notifications.expected.jsonl b/examples/jsonrpc-agent/tests/snapshots/persistent-tools/notifications.expected.jsonl index ea8f220308..550d3495f9 100644 --- a/examples/jsonrpc-agent/tests/snapshots/persistent-tools/notifications.expected.jsonl +++ b/examples/jsonrpc-agent/tests/snapshots/persistent-tools/notifications.expected.jsonl @@ -4,76 +4,75 @@ {"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"agent/inbox/spliced","seq":2,"time":0,"data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}}}} {"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/start","seq":3,"time":0,"data":{"turn":1,"step":1}}}} {"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"user/message","seq":4,"time":0,"data":{"content":[{"type":"text","text":"Prove that bash state persists. Then create {{cwd}}/note.txt with a tab-indented line, view it, replace that literal tab-indented line, and make the persistent shell exit with code 9."}],"source":{"kind":"user"},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"user/message","seq":5,"time":0,"data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."}],"source":{"kind":"plugin","plugin":"@deepseek-ai/dsh-system-prompt","form":"snapshot","sections":[{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."}]},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"session/title","seq":6,"time":0,"data":{"title":"Prove that bash state persists.","messageSeqs":[4],"source":{"kind":"fallback"}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"request/header","seq":7,"time":0,"data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"system":"{{system}}","tools":"{{tools}}"},"reason":"initial"}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"request/context","seq":8,"time":0,"data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":9,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":10,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":0,"id":"bash-1","name":"bash","argumentsDelta":"{\"command\":\"cd /tmp && export DSH_EXAMPLE_COUNT=1 && printf \\\"COUNT=%s CWD=%s\\\\n\\\" \\\"$DSH_EXAMPLE_COUNT\\\" \\\"$PWD\\\"\"}"}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":11,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"bash-1","name":"bash","arguments":"{\"command\":\"cd /tmp && export DSH_EXAMPLE_COUNT=1 && printf \\\"COUNT=%s CWD=%s\\\\n\\\" \\\"$DSH_EXAMPLE_COUNT\\\" \\\"$PWD\\\"\"}"}}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":12,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":13,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/message","seq":14,"time":0,"data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"bash-1","name":"bash","arguments":"{\"command\":\"cd /tmp && export DSH_EXAMPLE_COUNT=1 && printf \\\"COUNT=%s CWD=%s\\\\n\\\" \\\"$DSH_EXAMPLE_COUNT\\\" \\\"$PWD\\\"\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{sessionId}}"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[9,10,11,12,13],"surfaceOp":"append"}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/call","seq":15,"time":0,"data":{"turn":1,"step":1,"callId":"bash-1","name":"bash","arguments":"{\"command\":\"cd /tmp && export DSH_EXAMPLE_COUNT=1 && printf \\\"COUNT=%s CWD=%s\\\\n\\\" \\\"$DSH_EXAMPLE_COUNT\\\" \\\"$PWD\\\"\"}"}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/result","seq":16,"time":0,"data":{"turn":1,"step":1,"message":{"source":{"kind":"tool","callId":"bash-1"},"content":[{"type":"tool-result","toolCallId":"bash-1","content":[{"type":"text","text":"COUNT=1 CWD=/tmp"}],"isError":false}],"role":"user","id":"{{sessionId}}"}},"sourceEventSeqs":[15],"surfaceOp":"append"}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/end","seq":17,"time":0,"data":{"turn":1,"step":1}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/start","seq":18,"time":0,"data":{"turn":1,"step":2}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":19,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":20,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":0,"id":"bash-2","name":"bash","argumentsDelta":"{\"command\":\"DSH_EXAMPLE_COUNT=$((DSH_EXAMPLE_COUNT + 1)); printf \\\"COUNT=%s CWD=%s\\\\n\\\" \\\"$DSH_EXAMPLE_COUNT\\\" \\\"$PWD\\\"\"}"}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":21,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"bash-2","name":"bash","arguments":"{\"command\":\"DSH_EXAMPLE_COUNT=$((DSH_EXAMPLE_COUNT + 1)); printf \\\"COUNT=%s CWD=%s\\\\n\\\" \\\"$DSH_EXAMPLE_COUNT\\\" \\\"$PWD\\\"\"}"}}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":22,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":23,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/message","seq":24,"time":0,"data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"tool-call","id":"bash-2","name":"bash","arguments":"{\"command\":\"DSH_EXAMPLE_COUNT=$((DSH_EXAMPLE_COUNT + 1)); printf \\\"COUNT=%s CWD=%s\\\\n\\\" \\\"$DSH_EXAMPLE_COUNT\\\" \\\"$PWD\\\"\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{sessionId}}"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[19,20,21,22,23],"surfaceOp":"append"}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/call","seq":25,"time":0,"data":{"turn":1,"step":2,"callId":"bash-2","name":"bash","arguments":"{\"command\":\"DSH_EXAMPLE_COUNT=$((DSH_EXAMPLE_COUNT + 1)); printf \\\"COUNT=%s CWD=%s\\\\n\\\" \\\"$DSH_EXAMPLE_COUNT\\\" \\\"$PWD\\\"\"}"}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/result","seq":26,"time":0,"data":{"turn":1,"step":2,"message":{"source":{"kind":"tool","callId":"bash-2"},"content":[{"type":"tool-result","toolCallId":"bash-2","content":[{"type":"text","text":"COUNT=2 CWD=/tmp"}],"isError":false}],"role":"user","id":"{{sessionId}}"}},"sourceEventSeqs":[25],"surfaceOp":"append"}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/end","seq":27,"time":0,"data":{"turn":1,"step":2}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/start","seq":28,"time":0,"data":{"turn":1,"step":3}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":29,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":30,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":0,"id":"editor-create","name":"str_replace_editor","argumentsDelta":"{\"command\":\"create\",\"path\":\"{{cwd}}/note.txt\",\"file_text\":\"target:\\n\\told\\n\"}"}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":31,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"editor-create","name":"str_replace_editor","arguments":"{\"command\":\"create\",\"path\":\"{{cwd}}/note.txt\",\"file_text\":\"target:\\n\\told\\n\"}"}}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":32,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":33,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/message","seq":34,"time":0,"data":{"turn":1,"step":3,"message":{"role":"assistant","content":[{"type":"tool-call","id":"editor-create","name":"str_replace_editor","arguments":"{\"command\":\"create\",\"path\":\"{{cwd}}/note.txt\",\"file_text\":\"target:\\n\\told\\n\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{sessionId}}"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[29,30,31,32,33],"surfaceOp":"append"}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/call","seq":35,"time":0,"data":{"turn":1,"step":3,"callId":"editor-create","name":"str_replace_editor","arguments":"{\"command\":\"create\",\"path\":\"{{cwd}}/note.txt\",\"file_text\":\"target:\\n\\told\\n\"}"}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/result","seq":36,"time":0,"data":{"turn":1,"step":3,"message":{"source":{"kind":"tool","callId":"editor-create"},"content":[{"type":"tool-result","toolCallId":"editor-create","content":[{"type":"text","text":"New file created successfully at: {{cwd}}/note.txt"}],"isError":false}],"role":"user","id":"{{sessionId}}"}},"sourceEventSeqs":[35],"surfaceOp":"append"}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/end","seq":37,"time":0,"data":{"turn":1,"step":3}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/start","seq":38,"time":0,"data":{"turn":1,"step":4}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":39,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":40,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"tool-call-delta","index":0,"id":"editor-view","name":"str_replace_editor","argumentsDelta":"{\"command\":\"view\",\"path\":\"{{cwd}}/note.txt\"}"}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":41,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"editor-view","name":"str_replace_editor","arguments":"{\"command\":\"view\",\"path\":\"{{cwd}}/note.txt\"}"}}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":42,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":43,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/message","seq":44,"time":0,"data":{"turn":1,"step":4,"message":{"role":"assistant","content":[{"type":"tool-call","id":"editor-view","name":"str_replace_editor","arguments":"{\"command\":\"view\",\"path\":\"{{cwd}}/note.txt\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{sessionId}}"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[39,40,41,42,43],"surfaceOp":"append"}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/call","seq":45,"time":0,"data":{"turn":1,"step":4,"callId":"editor-view","name":"str_replace_editor","arguments":"{\"command\":\"view\",\"path\":\"{{cwd}}/note.txt\"}"}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/result","seq":46,"time":0,"data":{"turn":1,"step":4,"message":{"source":{"kind":"tool","callId":"editor-view"},"content":[{"type":"tool-result","toolCallId":"editor-view","content":[{"type":"text","text":"Here's the content of {{cwd}}/note.txt with line numbers (which has a total of 3 lines):\n 1 target:\n 2 \told\n 3 \n"}],"isError":false}],"role":"user","id":"{{sessionId}}"}},"sourceEventSeqs":[45],"surfaceOp":"append"}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/end","seq":47,"time":0,"data":{"turn":1,"step":4}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/start","seq":48,"time":0,"data":{"turn":1,"step":5}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":49,"time":0,"data":{"turn":1,"step":5,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":50,"time":0,"data":{"turn":1,"step":5,"chunk":{"type":"tool-call-delta","index":0,"id":"editor-replace","name":"str_replace_editor","argumentsDelta":"{\"command\":\"str_replace\",\"path\":\"{{cwd}}/note.txt\",\"old_str\":\"\\told\",\"new_str\":\"\\tnew\"}"}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":51,"time":0,"data":{"turn":1,"step":5,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"editor-replace","name":"str_replace_editor","arguments":"{\"command\":\"str_replace\",\"path\":\"{{cwd}}/note.txt\",\"old_str\":\"\\told\",\"new_str\":\"\\tnew\"}"}}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":52,"time":0,"data":{"turn":1,"step":5,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":53,"time":0,"data":{"turn":1,"step":5,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/message","seq":54,"time":0,"data":{"turn":1,"step":5,"message":{"role":"assistant","content":[{"type":"tool-call","id":"editor-replace","name":"str_replace_editor","arguments":"{\"command\":\"str_replace\",\"path\":\"{{cwd}}/note.txt\",\"old_str\":\"\\told\",\"new_str\":\"\\tnew\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{sessionId}}"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[49,50,51,52,53],"surfaceOp":"append"}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/call","seq":55,"time":0,"data":{"turn":1,"step":5,"callId":"editor-replace","name":"str_replace_editor","arguments":"{\"command\":\"str_replace\",\"path\":\"{{cwd}}/note.txt\",\"old_str\":\"\\told\",\"new_str\":\"\\tnew\"}"}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/result","seq":56,"time":0,"data":{"turn":1,"step":5,"message":{"source":{"kind":"tool","callId":"editor-replace"},"content":[{"type":"tool-result","toolCallId":"editor-replace","content":[{"type":"text","text":"The file {{cwd}}/note.txt has been edited successfully."}],"isError":false}],"role":"user","id":"{{sessionId}}"}},"sourceEventSeqs":[55],"surfaceOp":"append"}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/end","seq":57,"time":0,"data":{"turn":1,"step":5}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/start","seq":58,"time":0,"data":{"turn":1,"step":6}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":59,"time":0,"data":{"turn":1,"step":6,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":60,"time":0,"data":{"turn":1,"step":6,"chunk":{"type":"tool-call-delta","index":0,"id":"bash-exit","name":"bash","argumentsDelta":"{\"command\":\"exit 9\"}"}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":61,"time":0,"data":{"turn":1,"step":6,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"bash-exit","name":"bash","arguments":"{\"command\":\"exit 9\"}"}}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":62,"time":0,"data":{"turn":1,"step":6,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":63,"time":0,"data":{"turn":1,"step":6,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/message","seq":64,"time":0,"data":{"turn":1,"step":6,"message":{"role":"assistant","content":[{"type":"tool-call","id":"bash-exit","name":"bash","arguments":"{\"command\":\"exit 9\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{sessionId}}"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[59,60,61,62,63],"surfaceOp":"append"}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/call","seq":65,"time":0,"data":{"turn":1,"step":6,"callId":"bash-exit","name":"bash","arguments":"{\"command\":\"exit 9\"}"}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/result","seq":66,"time":0,"data":{"turn":1,"step":6,"message":{"source":{"kind":"tool","callId":"bash-exit"},"content":[{"type":"tool-result","toolCallId":"bash-exit","content":[{"type":"text","text":"exit\n[shell exited: code 9]\nThe persistent bash shell was reset; the next bash call starts from the workspace with a fresh current directory and environment."}],"isError":false}],"role":"user","id":"{{sessionId}}"}},"sourceEventSeqs":[65],"surfaceOp":"append"}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/end","seq":67,"time":0,"data":{"turn":1,"step":6}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/start","seq":68,"time":0,"data":{"turn":1,"step":7}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":69,"time":0,"data":{"turn":1,"step":7,"chunk":{"type":"block-start","index":0,"blockType":"text"}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":70,"time":0,"data":{"turn":1,"step":7,"chunk":{"type":"text-delta","index":0,"text":"PERSISTENT_TOOLS_OK"}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":71,"time":0,"data":{"turn":1,"step":7,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"PERSISTENT_TOOLS_OK"}}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":72,"time":0,"data":{"turn":1,"step":7,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":73,"time":0,"data":{"turn":1,"step":7,"chunk":{"type":"finish","reason":{"kind":"stop"}}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/message","seq":74,"time":0,"data":{"turn":1,"step":7,"message":{"role":"assistant","content":[{"type":"text","text":"PERSISTENT_TOOLS_OK"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{sessionId}}"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[69,70,71,72,73],"surfaceOp":"append"}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/end","seq":75,"time":0,"data":{"turn":1,"step":7}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"turn/end","seq":76,"time":0,"data":{"turn":1,"reason":{"kind":"completed"}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"session/title","seq":5,"time":0,"data":{"title":"Prove that bash state persists.","messageSeqs":[4],"source":{"kind":"fallback"}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"request/header","seq":6,"time":0,"data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"system":"{{system}}","tools":"{{tools}}"},"reason":"initial"}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"request/context","seq":7,"time":0,"data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":8,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":9,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":0,"id":"bash-1","name":"bash","argumentsDelta":"{\"command\":\"cd /tmp && export DSH_EXAMPLE_COUNT=1 && printf \\\"COUNT=%s CWD=%s\\\\n\\\" \\\"$DSH_EXAMPLE_COUNT\\\" \\\"$PWD\\\"\"}"}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":10,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"bash-1","name":"bash","arguments":"{\"command\":\"cd /tmp && export DSH_EXAMPLE_COUNT=1 && printf \\\"COUNT=%s CWD=%s\\\\n\\\" \\\"$DSH_EXAMPLE_COUNT\\\" \\\"$PWD\\\"\"}"}}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":11,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":12,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/message","seq":13,"time":0,"data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"bash-1","name":"bash","arguments":"{\"command\":\"cd /tmp && export DSH_EXAMPLE_COUNT=1 && printf \\\"COUNT=%s CWD=%s\\\\n\\\" \\\"$DSH_EXAMPLE_COUNT\\\" \\\"$PWD\\\"\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{sessionId}}"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[8,9,10,11,12],"surfaceOp":"append"}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/call","seq":14,"time":0,"data":{"turn":1,"step":1,"callId":"bash-1","name":"bash","arguments":"{\"command\":\"cd /tmp && export DSH_EXAMPLE_COUNT=1 && printf \\\"COUNT=%s CWD=%s\\\\n\\\" \\\"$DSH_EXAMPLE_COUNT\\\" \\\"$PWD\\\"\"}"}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/result","seq":15,"time":0,"data":{"turn":1,"step":1,"message":{"source":{"kind":"tool","callId":"bash-1"},"content":[{"type":"tool-result","toolCallId":"bash-1","content":[{"type":"text","text":"COUNT=1 CWD=/tmp"}],"isError":false}],"role":"user","id":"{{sessionId}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/end","seq":16,"time":0,"data":{"turn":1,"step":1}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/start","seq":17,"time":0,"data":{"turn":1,"step":2}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":18,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":19,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":0,"id":"bash-2","name":"bash","argumentsDelta":"{\"command\":\"DSH_EXAMPLE_COUNT=$((DSH_EXAMPLE_COUNT + 1)); printf \\\"COUNT=%s CWD=%s\\\\n\\\" \\\"$DSH_EXAMPLE_COUNT\\\" \\\"$PWD\\\"\"}"}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":20,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"bash-2","name":"bash","arguments":"{\"command\":\"DSH_EXAMPLE_COUNT=$((DSH_EXAMPLE_COUNT + 1)); printf \\\"COUNT=%s CWD=%s\\\\n\\\" \\\"$DSH_EXAMPLE_COUNT\\\" \\\"$PWD\\\"\"}"}}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":21,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":22,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/message","seq":23,"time":0,"data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"tool-call","id":"bash-2","name":"bash","arguments":"{\"command\":\"DSH_EXAMPLE_COUNT=$((DSH_EXAMPLE_COUNT + 1)); printf \\\"COUNT=%s CWD=%s\\\\n\\\" \\\"$DSH_EXAMPLE_COUNT\\\" \\\"$PWD\\\"\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{sessionId}}"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[18,19,20,21,22],"surfaceOp":"append"}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/call","seq":24,"time":0,"data":{"turn":1,"step":2,"callId":"bash-2","name":"bash","arguments":"{\"command\":\"DSH_EXAMPLE_COUNT=$((DSH_EXAMPLE_COUNT + 1)); printf \\\"COUNT=%s CWD=%s\\\\n\\\" \\\"$DSH_EXAMPLE_COUNT\\\" \\\"$PWD\\\"\"}"}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/result","seq":25,"time":0,"data":{"turn":1,"step":2,"message":{"source":{"kind":"tool","callId":"bash-2"},"content":[{"type":"tool-result","toolCallId":"bash-2","content":[{"type":"text","text":"COUNT=2 CWD=/tmp"}],"isError":false}],"role":"user","id":"{{sessionId}}"}},"sourceEventSeqs":[24],"surfaceOp":"append"}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/end","seq":26,"time":0,"data":{"turn":1,"step":2}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/start","seq":27,"time":0,"data":{"turn":1,"step":3}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":28,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":29,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":0,"id":"editor-create","name":"str_replace_editor","argumentsDelta":"{\"command\":\"create\",\"path\":\"{{cwd}}/note.txt\",\"file_text\":\"target:\\n\\told\\n\"}"}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":30,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"editor-create","name":"str_replace_editor","arguments":"{\"command\":\"create\",\"path\":\"{{cwd}}/note.txt\",\"file_text\":\"target:\\n\\told\\n\"}"}}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":31,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":32,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/message","seq":33,"time":0,"data":{"turn":1,"step":3,"message":{"role":"assistant","content":[{"type":"tool-call","id":"editor-create","name":"str_replace_editor","arguments":"{\"command\":\"create\",\"path\":\"{{cwd}}/note.txt\",\"file_text\":\"target:\\n\\told\\n\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{sessionId}}"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[28,29,30,31,32],"surfaceOp":"append"}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/call","seq":34,"time":0,"data":{"turn":1,"step":3,"callId":"editor-create","name":"str_replace_editor","arguments":"{\"command\":\"create\",\"path\":\"{{cwd}}/note.txt\",\"file_text\":\"target:\\n\\told\\n\"}"}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/result","seq":35,"time":0,"data":{"turn":1,"step":3,"message":{"source":{"kind":"tool","callId":"editor-create"},"content":[{"type":"tool-result","toolCallId":"editor-create","content":[{"type":"text","text":"New file created successfully at: {{cwd}}/note.txt"}],"isError":false}],"role":"user","id":"{{sessionId}}"}},"sourceEventSeqs":[34],"surfaceOp":"append"}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/end","seq":36,"time":0,"data":{"turn":1,"step":3}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/start","seq":37,"time":0,"data":{"turn":1,"step":4}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":38,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":39,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"tool-call-delta","index":0,"id":"editor-view","name":"str_replace_editor","argumentsDelta":"{\"command\":\"view\",\"path\":\"{{cwd}}/note.txt\"}"}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":40,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"editor-view","name":"str_replace_editor","arguments":"{\"command\":\"view\",\"path\":\"{{cwd}}/note.txt\"}"}}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":41,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":42,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/message","seq":43,"time":0,"data":{"turn":1,"step":4,"message":{"role":"assistant","content":[{"type":"tool-call","id":"editor-view","name":"str_replace_editor","arguments":"{\"command\":\"view\",\"path\":\"{{cwd}}/note.txt\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{sessionId}}"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[38,39,40,41,42],"surfaceOp":"append"}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/call","seq":44,"time":0,"data":{"turn":1,"step":4,"callId":"editor-view","name":"str_replace_editor","arguments":"{\"command\":\"view\",\"path\":\"{{cwd}}/note.txt\"}"}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/result","seq":45,"time":0,"data":{"turn":1,"step":4,"message":{"source":{"kind":"tool","callId":"editor-view"},"content":[{"type":"tool-result","toolCallId":"editor-view","content":[{"type":"text","text":"Here's the content of {{cwd}}/note.txt with line numbers (which has a total of 3 lines):\n 1 target:\n 2 \told\n 3 \n"}],"isError":false}],"role":"user","id":"{{sessionId}}"}},"sourceEventSeqs":[44],"surfaceOp":"append"}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/end","seq":46,"time":0,"data":{"turn":1,"step":4}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/start","seq":47,"time":0,"data":{"turn":1,"step":5}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":48,"time":0,"data":{"turn":1,"step":5,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":49,"time":0,"data":{"turn":1,"step":5,"chunk":{"type":"tool-call-delta","index":0,"id":"editor-replace","name":"str_replace_editor","argumentsDelta":"{\"command\":\"str_replace\",\"path\":\"{{cwd}}/note.txt\",\"old_str\":\"\\told\",\"new_str\":\"\\tnew\"}"}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":50,"time":0,"data":{"turn":1,"step":5,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"editor-replace","name":"str_replace_editor","arguments":"{\"command\":\"str_replace\",\"path\":\"{{cwd}}/note.txt\",\"old_str\":\"\\told\",\"new_str\":\"\\tnew\"}"}}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":51,"time":0,"data":{"turn":1,"step":5,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":52,"time":0,"data":{"turn":1,"step":5,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/message","seq":53,"time":0,"data":{"turn":1,"step":5,"message":{"role":"assistant","content":[{"type":"tool-call","id":"editor-replace","name":"str_replace_editor","arguments":"{\"command\":\"str_replace\",\"path\":\"{{cwd}}/note.txt\",\"old_str\":\"\\told\",\"new_str\":\"\\tnew\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{sessionId}}"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[48,49,50,51,52],"surfaceOp":"append"}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/call","seq":54,"time":0,"data":{"turn":1,"step":5,"callId":"editor-replace","name":"str_replace_editor","arguments":"{\"command\":\"str_replace\",\"path\":\"{{cwd}}/note.txt\",\"old_str\":\"\\told\",\"new_str\":\"\\tnew\"}"}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/result","seq":55,"time":0,"data":{"turn":1,"step":5,"message":{"source":{"kind":"tool","callId":"editor-replace"},"content":[{"type":"tool-result","toolCallId":"editor-replace","content":[{"type":"text","text":"The file {{cwd}}/note.txt has been edited successfully."}],"isError":false}],"role":"user","id":"{{sessionId}}"}},"sourceEventSeqs":[54],"surfaceOp":"append"}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/end","seq":56,"time":0,"data":{"turn":1,"step":5}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/start","seq":57,"time":0,"data":{"turn":1,"step":6}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":58,"time":0,"data":{"turn":1,"step":6,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":59,"time":0,"data":{"turn":1,"step":6,"chunk":{"type":"tool-call-delta","index":0,"id":"bash-exit","name":"bash","argumentsDelta":"{\"command\":\"exit 9\"}"}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":60,"time":0,"data":{"turn":1,"step":6,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"bash-exit","name":"bash","arguments":"{\"command\":\"exit 9\"}"}}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":61,"time":0,"data":{"turn":1,"step":6,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":62,"time":0,"data":{"turn":1,"step":6,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/message","seq":63,"time":0,"data":{"turn":1,"step":6,"message":{"role":"assistant","content":[{"type":"tool-call","id":"bash-exit","name":"bash","arguments":"{\"command\":\"exit 9\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{sessionId}}"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[58,59,60,61,62],"surfaceOp":"append"}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/call","seq":64,"time":0,"data":{"turn":1,"step":6,"callId":"bash-exit","name":"bash","arguments":"{\"command\":\"exit 9\"}"}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/result","seq":65,"time":0,"data":{"turn":1,"step":6,"message":{"source":{"kind":"tool","callId":"bash-exit"},"content":[{"type":"tool-result","toolCallId":"bash-exit","content":[{"type":"text","text":"exit\n[shell exited: code 9]\nThe persistent bash shell was reset; the next bash call starts from the workspace with a fresh current directory and environment."}],"isError":false}],"role":"user","id":"{{sessionId}}"}},"sourceEventSeqs":[64],"surfaceOp":"append"}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/end","seq":66,"time":0,"data":{"turn":1,"step":6}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/start","seq":67,"time":0,"data":{"turn":1,"step":7}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":68,"time":0,"data":{"turn":1,"step":7,"chunk":{"type":"block-start","index":0,"blockType":"text"}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":69,"time":0,"data":{"turn":1,"step":7,"chunk":{"type":"text-delta","index":0,"text":"PERSISTENT_TOOLS_OK"}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":70,"time":0,"data":{"turn":1,"step":7,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"PERSISTENT_TOOLS_OK"}}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":71,"time":0,"data":{"turn":1,"step":7,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":72,"time":0,"data":{"turn":1,"step":7,"chunk":{"type":"finish","reason":{"kind":"stop"}}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/message","seq":73,"time":0,"data":{"turn":1,"step":7,"message":{"role":"assistant","content":[{"type":"text","text":"PERSISTENT_TOOLS_OK"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{sessionId}}"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[68,69,70,71,72],"surfaceOp":"append"}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/end","seq":74,"time":0,"data":{"turn":1,"step":7}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"turn/end","seq":75,"time":0,"data":{"turn":1,"reason":{"kind":"completed"}}}}} {"method":"session.status","params":{"sessionId":"{{sessionId}}","status":"idle"}} diff --git a/examples/jsonrpc-agent/tests/snapshots/persistent-tools/session.jsonl b/examples/jsonrpc-agent/tests/snapshots/persistent-tools/session.jsonl index be559eeb9a..77fe6f03a6 100644 --- a/examples/jsonrpc-agent/tests/snapshots/persistent-tools/session.jsonl +++ b/examples/jsonrpc-agent/tests/snapshots/persistent-tools/session.jsonl @@ -4,75 +4,74 @@ {"type":"agent/inbox/spliced","seq":2,"time":1785821461907,"data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","seq":3,"time":1785331618312,"data":{"turn":1,"step":1}} {"type":"user/message","seq":4,"time":1785498592368,"data":{"content":[{"type":"text","text":"Prove that bash state persists. Then create {{cwd}}/note.txt with a tab-indented line, view it, replace that literal tab-indented line, and make the persistent shell exit with code 9."}],"source":{"kind":"user"},"role":"user","id":"9a08e199-69d7-4b85-bfa4-27b41a92672a"},"surfaceOp":"append"} -{"type":"user/message","seq":5,"time":1785730508088,"data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."}],"source":{"kind":"plugin","plugin":"@deepseek-ai/dsh-system-prompt","form":"snapshot","sections":[{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."}]},"role":"user","id":"bb38bdc2-276e-46ec-87a1-089732acbc8d"},"surfaceOp":"append"} -{"type":"session/title","seq":6,"time":1785730508088,"data":{"title":"Prove that bash state persists.","messageSeqs":[4],"source":{"kind":"fallback"}}} -{"type":"request/header","seq":7,"time":1785498592370,"data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"system":"{{system}}","tools":"{{tools}}"},"reason":"initial"}} -{"type":"request/context","seq":8,"time":1785730508089,"data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} -{"type":"assistant/chunk","seq":9,"time":1785331618326,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}} -{"type":"assistant/chunk","seq":10,"time":1785331618326,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":0,"id":"bash-1","name":"bash","argumentsDelta":"{\"command\":\"cd /tmp && export DSH_EXAMPLE_COUNT=1 && printf \\\"COUNT=%s CWD=%s\\\\n\\\" \\\"$DSH_EXAMPLE_COUNT\\\" \\\"$PWD\\\"\"}"}}} -{"type":"assistant/chunk","seq":11,"time":1785331618326,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"bash-1","name":"bash","arguments":"{\"command\":\"cd /tmp && export DSH_EXAMPLE_COUNT=1 && printf \\\"COUNT=%s CWD=%s\\\\n\\\" \\\"$DSH_EXAMPLE_COUNT\\\" \\\"$PWD\\\"\"}"}}}} -{"type":"assistant/chunk","seq":12,"time":1785498592372,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}} -{"type":"assistant/chunk","seq":13,"time":1785730508090,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}} -{"type":"assistant/message","seq":14,"time":1785730508090,"data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"bash-1","name":"bash","arguments":"{\"command\":\"cd /tmp && export DSH_EXAMPLE_COUNT=1 && printf \\\"COUNT=%s CWD=%s\\\\n\\\" \\\"$DSH_EXAMPLE_COUNT\\\" \\\"$PWD\\\"\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"0d064526-8eff-482d-8525-ac478e1d1791"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[9,10,11,12,13],"surfaceOp":"append"} -{"type":"tool/call","seq":15,"time":1785730508090,"data":{"turn":1,"step":1,"callId":"bash-1","name":"bash","arguments":"{\"command\":\"cd /tmp && export DSH_EXAMPLE_COUNT=1 && printf \\\"COUNT=%s CWD=%s\\\\n\\\" \\\"$DSH_EXAMPLE_COUNT\\\" \\\"$PWD\\\"\"}"}} -{"type":"tool/result","seq":16,"time":1785730508425,"data":{"turn":1,"step":1,"message":{"source":{"kind":"tool","callId":"bash-1"},"content":[{"type":"tool-result","toolCallId":"bash-1","content":[{"type":"text","text":"COUNT=1 CWD=/tmp"}],"isError":false}],"role":"user","id":"2c01f81a-01ea-47e2-bf92-f7825b7cc69f"}},"sourceEventSeqs":[15],"surfaceOp":"append"} -{"type":"step/end","seq":17,"time":1785730508425,"data":{"turn":1,"step":1}} -{"type":"step/start","seq":18,"time":1785730508425,"data":{"turn":1,"step":2}} -{"type":"assistant/chunk","seq":19,"time":1785331618652,"data":{"turn":1,"step":2,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}} -{"type":"assistant/chunk","seq":20,"time":1785331618652,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":0,"id":"bash-2","name":"bash","argumentsDelta":"{\"command\":\"DSH_EXAMPLE_COUNT=$((DSH_EXAMPLE_COUNT + 1)); printf \\\"COUNT=%s CWD=%s\\\\n\\\" \\\"$DSH_EXAMPLE_COUNT\\\" \\\"$PWD\\\"\"}"}}} -{"type":"assistant/chunk","seq":21,"time":1785331618652,"data":{"turn":1,"step":2,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"bash-2","name":"bash","arguments":"{\"command\":\"DSH_EXAMPLE_COUNT=$((DSH_EXAMPLE_COUNT + 1)); printf \\\"COUNT=%s CWD=%s\\\\n\\\" \\\"$DSH_EXAMPLE_COUNT\\\" \\\"$PWD\\\"\"}"}}}} -{"type":"assistant/chunk","seq":22,"time":1785498592702,"data":{"turn":1,"step":2,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}} -{"type":"assistant/chunk","seq":23,"time":1785730508426,"data":{"turn":1,"step":2,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}} -{"type":"assistant/message","seq":24,"time":1785730508426,"data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"tool-call","id":"bash-2","name":"bash","arguments":"{\"command\":\"DSH_EXAMPLE_COUNT=$((DSH_EXAMPLE_COUNT + 1)); printf \\\"COUNT=%s CWD=%s\\\\n\\\" \\\"$DSH_EXAMPLE_COUNT\\\" \\\"$PWD\\\"\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"ba4078ce-0e18-419a-b720-339918aecf26"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[19,20,21,22,23],"surfaceOp":"append"} -{"type":"tool/call","seq":25,"time":1785730508426,"data":{"turn":1,"step":2,"callId":"bash-2","name":"bash","arguments":"{\"command\":\"DSH_EXAMPLE_COUNT=$((DSH_EXAMPLE_COUNT + 1)); printf \\\"COUNT=%s CWD=%s\\\\n\\\" \\\"$DSH_EXAMPLE_COUNT\\\" \\\"$PWD\\\"\"}"}} -{"type":"tool/result","seq":26,"time":1785730508537,"data":{"turn":1,"step":2,"message":{"source":{"kind":"tool","callId":"bash-2"},"content":[{"type":"tool-result","toolCallId":"bash-2","content":[{"type":"text","text":"COUNT=2 CWD=/tmp"}],"isError":false}],"role":"user","id":"6e3ad5e1-1149-44d5-bd20-d9cc0139c747"}},"sourceEventSeqs":[25],"surfaceOp":"append"} -{"type":"step/end","seq":27,"time":1785730508537,"data":{"turn":1,"step":2}} -{"type":"step/start","seq":28,"time":1785730508537,"data":{"turn":1,"step":3}} -{"type":"assistant/chunk","seq":29,"time":1785331618762,"data":{"turn":1,"step":3,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}} -{"type":"assistant/chunk","seq":30,"time":1785331618762,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":0,"id":"editor-create","name":"str_replace_editor","argumentsDelta":"{\"command\":\"create\",\"path\":\"{{cwd}}/note.txt\",\"file_text\":\"target:\\n\\told\\n\"}"}}} -{"type":"assistant/chunk","seq":31,"time":1785331618762,"data":{"turn":1,"step":3,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"editor-create","name":"str_replace_editor","arguments":"{\"command\":\"create\",\"path\":\"{{cwd}}/note.txt\",\"file_text\":\"target:\\n\\told\\n\"}"}}}} -{"type":"assistant/chunk","seq":32,"time":1785498592812,"data":{"turn":1,"step":3,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}} -{"type":"assistant/chunk","seq":33,"time":1785730508538,"data":{"turn":1,"step":3,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}} -{"type":"assistant/message","seq":34,"time":1785730508538,"data":{"turn":1,"step":3,"message":{"role":"assistant","content":[{"type":"tool-call","id":"editor-create","name":"str_replace_editor","arguments":"{\"command\":\"create\",\"path\":\"{{cwd}}/note.txt\",\"file_text\":\"target:\\n\\told\\n\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"e5769b2d-ea91-42fe-a78f-2f7f408f545e"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[29,30,31,32,33],"surfaceOp":"append"} -{"type":"tool/call","seq":35,"time":1785730508538,"data":{"turn":1,"step":3,"callId":"editor-create","name":"str_replace_editor","arguments":"{\"command\":\"create\",\"path\":\"{{cwd}}/note.txt\",\"file_text\":\"target:\\n\\told\\n\"}"}} -{"type":"tool/result","seq":36,"time":1785730508551,"data":{"turn":1,"step":3,"message":{"source":{"kind":"tool","callId":"editor-create"},"content":[{"type":"tool-result","toolCallId":"editor-create","content":[{"type":"text","text":"New file created successfully at: {{cwd}}/note.txt"}],"isError":false}],"role":"user","id":"af41060c-7007-4ada-89d6-8b15a0e8be7c"}},"sourceEventSeqs":[35],"surfaceOp":"append"} -{"type":"step/end","seq":37,"time":1785730508551,"data":{"turn":1,"step":3}} -{"type":"step/start","seq":38,"time":1785730508552,"data":{"turn":1,"step":4}} -{"type":"assistant/chunk","seq":39,"time":1785331618784,"data":{"turn":1,"step":4,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}} -{"type":"assistant/chunk","seq":40,"time":1785331618784,"data":{"turn":1,"step":4,"chunk":{"type":"tool-call-delta","index":0,"id":"editor-view","name":"str_replace_editor","argumentsDelta":"{\"command\":\"view\",\"path\":\"{{cwd}}/note.txt\"}"}}} -{"type":"assistant/chunk","seq":41,"time":1785331618784,"data":{"turn":1,"step":4,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"editor-view","name":"str_replace_editor","arguments":"{\"command\":\"view\",\"path\":\"{{cwd}}/note.txt\"}"}}}} -{"type":"assistant/chunk","seq":42,"time":1785498592825,"data":{"turn":1,"step":4,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}} -{"type":"assistant/chunk","seq":43,"time":1785730508552,"data":{"turn":1,"step":4,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}} -{"type":"assistant/message","seq":44,"time":1785730508552,"data":{"turn":1,"step":4,"message":{"role":"assistant","content":[{"type":"tool-call","id":"editor-view","name":"str_replace_editor","arguments":"{\"command\":\"view\",\"path\":\"{{cwd}}/note.txt\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"0e9afabb-10a6-444c-ae22-fcdbb5e14695"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[39,40,41,42,43],"surfaceOp":"append"} -{"type":"tool/call","seq":45,"time":1785730508553,"data":{"turn":1,"step":4,"callId":"editor-view","name":"str_replace_editor","arguments":"{\"command\":\"view\",\"path\":\"{{cwd}}/note.txt\"}"}} -{"type":"tool/result","seq":46,"time":1785730508554,"data":{"turn":1,"step":4,"message":{"source":{"kind":"tool","callId":"editor-view"},"content":[{"type":"tool-result","toolCallId":"editor-view","content":[{"type":"text","text":"Here's the content of {{cwd}}/note.txt with line numbers (which has a total of 3 lines):\n 1 target:\n 2 \told\n 3 \n"}],"isError":false}],"role":"user","id":"a4472b37-6311-4880-bce2-cc369f9bc34b"}},"sourceEventSeqs":[45],"surfaceOp":"append"} -{"type":"step/end","seq":47,"time":1785730508554,"data":{"turn":1,"step":4}} -{"type":"step/start","seq":48,"time":1785730508554,"data":{"turn":1,"step":5}} -{"type":"assistant/chunk","seq":49,"time":1785331618801,"data":{"turn":1,"step":5,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}} -{"type":"assistant/chunk","seq":50,"time":1785331618801,"data":{"turn":1,"step":5,"chunk":{"type":"tool-call-delta","index":0,"id":"editor-replace","name":"str_replace_editor","argumentsDelta":"{\"command\":\"str_replace\",\"path\":\"{{cwd}}/note.txt\",\"old_str\":\"\\told\",\"new_str\":\"\\tnew\"}"}}} -{"type":"assistant/chunk","seq":51,"time":1785331618801,"data":{"turn":1,"step":5,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"editor-replace","name":"str_replace_editor","arguments":"{\"command\":\"str_replace\",\"path\":\"{{cwd}}/note.txt\",\"old_str\":\"\\told\",\"new_str\":\"\\tnew\"}"}}}} -{"type":"assistant/chunk","seq":52,"time":1785498592826,"data":{"turn":1,"step":5,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}} -{"type":"assistant/chunk","seq":53,"time":1785730508555,"data":{"turn":1,"step":5,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}} -{"type":"assistant/message","seq":54,"time":1785730508555,"data":{"turn":1,"step":5,"message":{"role":"assistant","content":[{"type":"tool-call","id":"editor-replace","name":"str_replace_editor","arguments":"{\"command\":\"str_replace\",\"path\":\"{{cwd}}/note.txt\",\"old_str\":\"\\told\",\"new_str\":\"\\tnew\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"ba189070-d46e-461e-969b-9bca032bb154"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[49,50,51,52,53],"surfaceOp":"append"} -{"type":"tool/call","seq":55,"time":1785730508555,"data":{"turn":1,"step":5,"callId":"editor-replace","name":"str_replace_editor","arguments":"{\"command\":\"str_replace\",\"path\":\"{{cwd}}/note.txt\",\"old_str\":\"\\told\",\"new_str\":\"\\tnew\"}"}} -{"type":"tool/result","seq":56,"time":1785730508564,"data":{"turn":1,"step":5,"message":{"source":{"kind":"tool","callId":"editor-replace"},"content":[{"type":"tool-result","toolCallId":"editor-replace","content":[{"type":"text","text":"The file {{cwd}}/note.txt has been edited successfully."}],"isError":false}],"role":"user","id":"17331db9-174b-4699-9c9e-3140921956c4"}},"sourceEventSeqs":[55],"surfaceOp":"append"} -{"type":"step/end","seq":57,"time":1785730508564,"data":{"turn":1,"step":5}} -{"type":"step/start","seq":58,"time":1785730508565,"data":{"turn":1,"step":6}} -{"type":"assistant/chunk","seq":59,"time":1785331618804,"data":{"turn":1,"step":6,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}} -{"type":"assistant/chunk","seq":60,"time":1785331618804,"data":{"turn":1,"step":6,"chunk":{"type":"tool-call-delta","index":0,"id":"bash-exit","name":"bash","argumentsDelta":"{\"command\":\"exit 9\"}"}}} -{"type":"assistant/chunk","seq":61,"time":1785331618804,"data":{"turn":1,"step":6,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"bash-exit","name":"bash","arguments":"{\"command\":\"exit 9\"}"}}}} -{"type":"assistant/chunk","seq":62,"time":1785498592838,"data":{"turn":1,"step":6,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}} -{"type":"assistant/chunk","seq":63,"time":1785730508565,"data":{"turn":1,"step":6,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}} -{"type":"assistant/message","seq":64,"time":1785730508565,"data":{"turn":1,"step":6,"message":{"role":"assistant","content":[{"type":"tool-call","id":"bash-exit","name":"bash","arguments":"{\"command\":\"exit 9\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"7fa07d0f-e70a-460d-b685-bf8a63b6a8a0"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[59,60,61,62,63],"surfaceOp":"append"} -{"type":"tool/call","seq":65,"time":1785730508565,"data":{"turn":1,"step":6,"callId":"bash-exit","name":"bash","arguments":"{\"command\":\"exit 9\"}"}} -{"type":"tool/result","seq":66,"time":1785730508641,"data":{"turn":1,"step":6,"message":{"source":{"kind":"tool","callId":"bash-exit"},"content":[{"type":"tool-result","toolCallId":"bash-exit","content":[{"type":"text","text":"exit\n[shell exited: code 9]\nThe persistent bash shell was reset; the next bash call starts from the workspace with a fresh current directory and environment."}],"isError":false}],"role":"user","id":"ccb91a28-4034-49bf-967d-450f68f7f9b8"}},"sourceEventSeqs":[65],"surfaceOp":"append"} -{"type":"step/end","seq":67,"time":1785730508641,"data":{"turn":1,"step":6}} -{"type":"step/start","seq":68,"time":1785730508642,"data":{"turn":1,"step":7}} -{"type":"assistant/chunk","seq":69,"time":1785331618807,"data":{"turn":1,"step":7,"chunk":{"type":"block-start","index":0,"blockType":"text"}}} -{"type":"assistant/chunk","seq":70,"time":1785331618807,"data":{"turn":1,"step":7,"chunk":{"type":"text-delta","index":0,"text":"PERSISTENT_TOOLS_OK"}}} -{"type":"assistant/chunk","seq":71,"time":1785331618807,"data":{"turn":1,"step":7,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"PERSISTENT_TOOLS_OK"}}}} -{"type":"assistant/chunk","seq":72,"time":1785498592934,"data":{"turn":1,"step":7,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}} -{"type":"assistant/chunk","seq":73,"time":1785730508642,"data":{"turn":1,"step":7,"chunk":{"type":"finish","reason":{"kind":"stop"}}}} -{"type":"assistant/message","seq":74,"time":1785730508642,"data":{"turn":1,"step":7,"message":{"role":"assistant","content":[{"type":"text","text":"PERSISTENT_TOOLS_OK"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"43efc58a-46a1-4813-995f-1dc489438942"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[69,70,71,72,73],"surfaceOp":"append"} -{"type":"step/end","seq":75,"time":1785730508642,"data":{"turn":1,"step":7}} -{"type":"turn/end","seq":76,"time":1785730508642,"data":{"turn":1,"reason":{"kind":"completed"}}} +{"type":"session/title","seq":5,"time":1785498592368,"data":{"title":"Prove that bash state persists.","messageSeqs":[4],"source":{"kind":"fallback"}}} +{"type":"request/header","seq":6,"time":1786547087174,"data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"system":"{{system}}","tools":"{{tools}}"},"reason":"initial"}} +{"type":"request/context","seq":7,"time":1786547087175,"data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} +{"type":"assistant/chunk","seq":8,"time":1786547087175,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}} +{"type":"assistant/chunk","seq":9,"time":1786547087175,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":0,"id":"bash-1","name":"bash","argumentsDelta":"{\"command\":\"cd /tmp && export DSH_EXAMPLE_COUNT=1 && printf \\\"COUNT=%s CWD=%s\\\\n\\\" \\\"$DSH_EXAMPLE_COUNT\\\" \\\"$PWD\\\"\"}"}}} +{"type":"assistant/chunk","seq":10,"time":1785331618326,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"bash-1","name":"bash","arguments":"{\"command\":\"cd /tmp && export DSH_EXAMPLE_COUNT=1 && printf \\\"COUNT=%s CWD=%s\\\\n\\\" \\\"$DSH_EXAMPLE_COUNT\\\" \\\"$PWD\\\"\"}"}}}} +{"type":"assistant/chunk","seq":11,"time":1785331618326,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}} +{"type":"assistant/chunk","seq":12,"time":1785331618326,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}} +{"type":"assistant/message","seq":13,"time":1786547087175,"data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"bash-1","name":"bash","arguments":"{\"command\":\"cd /tmp && export DSH_EXAMPLE_COUNT=1 && printf \\\"COUNT=%s CWD=%s\\\\n\\\" \\\"$DSH_EXAMPLE_COUNT\\\" \\\"$PWD\\\"\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"0d064526-8eff-482d-8525-ac478e1d1791"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[8,9,10,11,12],"surfaceOp":"append"} +{"type":"tool/call","seq":14,"time":1786547087176,"data":{"turn":1,"step":1,"callId":"bash-1","name":"bash","arguments":"{\"command\":\"cd /tmp && export DSH_EXAMPLE_COUNT=1 && printf \\\"COUNT=%s CWD=%s\\\\n\\\" \\\"$DSH_EXAMPLE_COUNT\\\" \\\"$PWD\\\"\"}"}} +{"type":"tool/result","seq":15,"time":1786547094340,"data":{"turn":1,"step":1,"message":{"source":{"kind":"tool","callId":"bash-1"},"content":[{"type":"tool-result","toolCallId":"bash-1","content":[{"type":"text","text":"COUNT=1 CWD=/tmp"}],"isError":false}],"role":"user","id":"2c01f81a-01ea-47e2-bf92-f7825b7cc69f"}},"sourceEventSeqs":[14],"surfaceOp":"append"} +{"type":"step/end","seq":16,"time":1786547094340,"data":{"turn":1,"step":1}} +{"type":"step/start","seq":17,"time":1786547094341,"data":{"turn":1,"step":2}} +{"type":"assistant/chunk","seq":18,"time":1786547094341,"data":{"turn":1,"step":2,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}} +{"type":"assistant/chunk","seq":19,"time":1786547094341,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":0,"id":"bash-2","name":"bash","argumentsDelta":"{\"command\":\"DSH_EXAMPLE_COUNT=$((DSH_EXAMPLE_COUNT + 1)); printf \\\"COUNT=%s CWD=%s\\\\n\\\" \\\"$DSH_EXAMPLE_COUNT\\\" \\\"$PWD\\\"\"}"}}} +{"type":"assistant/chunk","seq":20,"time":1785331618652,"data":{"turn":1,"step":2,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"bash-2","name":"bash","arguments":"{\"command\":\"DSH_EXAMPLE_COUNT=$((DSH_EXAMPLE_COUNT + 1)); printf \\\"COUNT=%s CWD=%s\\\\n\\\" \\\"$DSH_EXAMPLE_COUNT\\\" \\\"$PWD\\\"\"}"}}}} +{"type":"assistant/chunk","seq":21,"time":1785331618652,"data":{"turn":1,"step":2,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}} +{"type":"assistant/chunk","seq":22,"time":1785331618652,"data":{"turn":1,"step":2,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}} +{"type":"assistant/message","seq":23,"time":1786547094341,"data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"tool-call","id":"bash-2","name":"bash","arguments":"{\"command\":\"DSH_EXAMPLE_COUNT=$((DSH_EXAMPLE_COUNT + 1)); printf \\\"COUNT=%s CWD=%s\\\\n\\\" \\\"$DSH_EXAMPLE_COUNT\\\" \\\"$PWD\\\"\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"ba4078ce-0e18-419a-b720-339918aecf26"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[18,19,20,21,22],"surfaceOp":"append"} +{"type":"tool/call","seq":24,"time":1786547094341,"data":{"turn":1,"step":2,"callId":"bash-2","name":"bash","arguments":"{\"command\":\"DSH_EXAMPLE_COUNT=$((DSH_EXAMPLE_COUNT + 1)); printf \\\"COUNT=%s CWD=%s\\\\n\\\" \\\"$DSH_EXAMPLE_COUNT\\\" \\\"$PWD\\\"\"}"}} +{"type":"tool/result","seq":25,"time":1786547097878,"data":{"turn":1,"step":2,"message":{"source":{"kind":"tool","callId":"bash-2"},"content":[{"type":"tool-result","toolCallId":"bash-2","content":[{"type":"text","text":"COUNT=2 CWD=/tmp"}],"isError":false}],"role":"user","id":"6e3ad5e1-1149-44d5-bd20-d9cc0139c747"}},"sourceEventSeqs":[24],"surfaceOp":"append"} +{"type":"step/end","seq":26,"time":1786547097878,"data":{"turn":1,"step":2}} +{"type":"step/start","seq":27,"time":1786547097878,"data":{"turn":1,"step":3}} +{"type":"assistant/chunk","seq":28,"time":1786547097878,"data":{"turn":1,"step":3,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}} +{"type":"assistant/chunk","seq":29,"time":1786547097878,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":0,"id":"editor-create","name":"str_replace_editor","argumentsDelta":"{\"command\":\"create\",\"path\":\"{{cwd}}/note.txt\",\"file_text\":\"target:\\n\\told\\n\"}"}}} +{"type":"assistant/chunk","seq":30,"time":1785331618762,"data":{"turn":1,"step":3,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"editor-create","name":"str_replace_editor","arguments":"{\"command\":\"create\",\"path\":\"{{cwd}}/note.txt\",\"file_text\":\"target:\\n\\told\\n\"}"}}}} +{"type":"assistant/chunk","seq":31,"time":1785331618762,"data":{"turn":1,"step":3,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}} +{"type":"assistant/chunk","seq":32,"time":1785331618762,"data":{"turn":1,"step":3,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}} +{"type":"assistant/message","seq":33,"time":1786547097878,"data":{"turn":1,"step":3,"message":{"role":"assistant","content":[{"type":"tool-call","id":"editor-create","name":"str_replace_editor","arguments":"{\"command\":\"create\",\"path\":\"{{cwd}}/note.txt\",\"file_text\":\"target:\\n\\told\\n\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"e5769b2d-ea91-42fe-a78f-2f7f408f545e"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[28,29,30,31,32],"surfaceOp":"append"} +{"type":"tool/call","seq":34,"time":1786547097879,"data":{"turn":1,"step":3,"callId":"editor-create","name":"str_replace_editor","arguments":"{\"command\":\"create\",\"path\":\"{{cwd}}/note.txt\",\"file_text\":\"target:\\n\\told\\n\"}"}} +{"type":"tool/result","seq":35,"time":1786547097885,"data":{"turn":1,"step":3,"message":{"source":{"kind":"tool","callId":"editor-create"},"content":[{"type":"tool-result","toolCallId":"editor-create","content":[{"type":"text","text":"New file created successfully at: {{cwd}}/note.txt"}],"isError":false}],"role":"user","id":"af41060c-7007-4ada-89d6-8b15a0e8be7c"}},"sourceEventSeqs":[34],"surfaceOp":"append"} +{"type":"step/end","seq":36,"time":1786547097885,"data":{"turn":1,"step":3}} +{"type":"step/start","seq":37,"time":1786547097885,"data":{"turn":1,"step":4}} +{"type":"assistant/chunk","seq":38,"time":1786547097886,"data":{"turn":1,"step":4,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}} +{"type":"assistant/chunk","seq":39,"time":1786547097886,"data":{"turn":1,"step":4,"chunk":{"type":"tool-call-delta","index":0,"id":"editor-view","name":"str_replace_editor","argumentsDelta":"{\"command\":\"view\",\"path\":\"{{cwd}}/note.txt\"}"}}} +{"type":"assistant/chunk","seq":40,"time":1785331618784,"data":{"turn":1,"step":4,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"editor-view","name":"str_replace_editor","arguments":"{\"command\":\"view\",\"path\":\"{{cwd}}/note.txt\"}"}}}} +{"type":"assistant/chunk","seq":41,"time":1785331618784,"data":{"turn":1,"step":4,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}} +{"type":"assistant/chunk","seq":42,"time":1785331618784,"data":{"turn":1,"step":4,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}} +{"type":"assistant/message","seq":43,"time":1786547097886,"data":{"turn":1,"step":4,"message":{"role":"assistant","content":[{"type":"tool-call","id":"editor-view","name":"str_replace_editor","arguments":"{\"command\":\"view\",\"path\":\"{{cwd}}/note.txt\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"0e9afabb-10a6-444c-ae22-fcdbb5e14695"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[38,39,40,41,42],"surfaceOp":"append"} +{"type":"tool/call","seq":44,"time":1786547097886,"data":{"turn":1,"step":4,"callId":"editor-view","name":"str_replace_editor","arguments":"{\"command\":\"view\",\"path\":\"{{cwd}}/note.txt\"}"}} +{"type":"tool/result","seq":45,"time":1786547097887,"data":{"turn":1,"step":4,"message":{"source":{"kind":"tool","callId":"editor-view"},"content":[{"type":"tool-result","toolCallId":"editor-view","content":[{"type":"text","text":"Here's the content of {{cwd}}/note.txt with line numbers (which has a total of 3 lines):\n 1 target:\n 2 \told\n 3 \n"}],"isError":false}],"role":"user","id":"a4472b37-6311-4880-bce2-cc369f9bc34b"}},"sourceEventSeqs":[44],"surfaceOp":"append"} +{"type":"step/end","seq":46,"time":1786547097887,"data":{"turn":1,"step":4}} +{"type":"step/start","seq":47,"time":1786547097887,"data":{"turn":1,"step":5}} +{"type":"assistant/chunk","seq":48,"time":1786547097887,"data":{"turn":1,"step":5,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}} +{"type":"assistant/chunk","seq":49,"time":1786547097887,"data":{"turn":1,"step":5,"chunk":{"type":"tool-call-delta","index":0,"id":"editor-replace","name":"str_replace_editor","argumentsDelta":"{\"command\":\"str_replace\",\"path\":\"{{cwd}}/note.txt\",\"old_str\":\"\\told\",\"new_str\":\"\\tnew\"}"}}} +{"type":"assistant/chunk","seq":50,"time":1785331618801,"data":{"turn":1,"step":5,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"editor-replace","name":"str_replace_editor","arguments":"{\"command\":\"str_replace\",\"path\":\"{{cwd}}/note.txt\",\"old_str\":\"\\told\",\"new_str\":\"\\tnew\"}"}}}} +{"type":"assistant/chunk","seq":51,"time":1785331618801,"data":{"turn":1,"step":5,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}} +{"type":"assistant/chunk","seq":52,"time":1785331618801,"data":{"turn":1,"step":5,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}} +{"type":"assistant/message","seq":53,"time":1786547097887,"data":{"turn":1,"step":5,"message":{"role":"assistant","content":[{"type":"tool-call","id":"editor-replace","name":"str_replace_editor","arguments":"{\"command\":\"str_replace\",\"path\":\"{{cwd}}/note.txt\",\"old_str\":\"\\told\",\"new_str\":\"\\tnew\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"ba189070-d46e-461e-969b-9bca032bb154"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[48,49,50,51,52],"surfaceOp":"append"} +{"type":"tool/call","seq":54,"time":1786547097887,"data":{"turn":1,"step":5,"callId":"editor-replace","name":"str_replace_editor","arguments":"{\"command\":\"str_replace\",\"path\":\"{{cwd}}/note.txt\",\"old_str\":\"\\told\",\"new_str\":\"\\tnew\"}"}} +{"type":"tool/result","seq":55,"time":1786547097892,"data":{"turn":1,"step":5,"message":{"source":{"kind":"tool","callId":"editor-replace"},"content":[{"type":"tool-result","toolCallId":"editor-replace","content":[{"type":"text","text":"The file {{cwd}}/note.txt has been edited successfully."}],"isError":false}],"role":"user","id":"17331db9-174b-4699-9c9e-3140921956c4"}},"sourceEventSeqs":[54],"surfaceOp":"append"} +{"type":"step/end","seq":56,"time":1786547097892,"data":{"turn":1,"step":5}} +{"type":"step/start","seq":57,"time":1786547097892,"data":{"turn":1,"step":6}} +{"type":"assistant/chunk","seq":58,"time":1786547097893,"data":{"turn":1,"step":6,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}} +{"type":"assistant/chunk","seq":59,"time":1786547097893,"data":{"turn":1,"step":6,"chunk":{"type":"tool-call-delta","index":0,"id":"bash-exit","name":"bash","argumentsDelta":"{\"command\":\"exit 9\"}"}}} +{"type":"assistant/chunk","seq":60,"time":1785331618804,"data":{"turn":1,"step":6,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"bash-exit","name":"bash","arguments":"{\"command\":\"exit 9\"}"}}}} +{"type":"assistant/chunk","seq":61,"time":1785331618804,"data":{"turn":1,"step":6,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}} +{"type":"assistant/chunk","seq":62,"time":1785331618804,"data":{"turn":1,"step":6,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}} +{"type":"assistant/message","seq":63,"time":1786547097893,"data":{"turn":1,"step":6,"message":{"role":"assistant","content":[{"type":"tool-call","id":"bash-exit","name":"bash","arguments":"{\"command\":\"exit 9\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"7fa07d0f-e70a-460d-b685-bf8a63b6a8a0"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[58,59,60,61,62],"surfaceOp":"append"} +{"type":"tool/call","seq":64,"time":1786547097893,"data":{"turn":1,"step":6,"callId":"bash-exit","name":"bash","arguments":"{\"command\":\"exit 9\"}"}} +{"type":"tool/result","seq":65,"time":1786547098003,"data":{"turn":1,"step":6,"message":{"source":{"kind":"tool","callId":"bash-exit"},"content":[{"type":"tool-result","toolCallId":"bash-exit","content":[{"type":"text","text":"exit\n[shell exited: code 9]\nThe persistent bash shell was reset; the next bash call starts from the workspace with a fresh current directory and environment."}],"isError":false}],"role":"user","id":"ccb91a28-4034-49bf-967d-450f68f7f9b8"}},"sourceEventSeqs":[64],"surfaceOp":"append"} +{"type":"step/end","seq":66,"time":1786547098003,"data":{"turn":1,"step":6}} +{"type":"step/start","seq":67,"time":1786547098003,"data":{"turn":1,"step":7}} +{"type":"assistant/chunk","seq":68,"time":1786547098003,"data":{"turn":1,"step":7,"chunk":{"type":"block-start","index":0,"blockType":"text"}}} +{"type":"assistant/chunk","seq":69,"time":1786547098003,"data":{"turn":1,"step":7,"chunk":{"type":"text-delta","index":0,"text":"PERSISTENT_TOOLS_OK"}}} +{"type":"assistant/chunk","seq":70,"time":1785331618807,"data":{"turn":1,"step":7,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"PERSISTENT_TOOLS_OK"}}}} +{"type":"assistant/chunk","seq":71,"time":1785331618807,"data":{"turn":1,"step":7,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}} +{"type":"assistant/chunk","seq":72,"time":1785331618807,"data":{"turn":1,"step":7,"chunk":{"type":"finish","reason":{"kind":"stop"}}}} +{"type":"assistant/message","seq":73,"time":1786547098003,"data":{"turn":1,"step":7,"message":{"role":"assistant","content":[{"type":"text","text":"PERSISTENT_TOOLS_OK"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"43efc58a-46a1-4813-995f-1dc489438942"},"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[68,69,70,71,72],"surfaceOp":"append"} +{"type":"step/end","seq":74,"time":1786547098003,"data":{"turn":1,"step":7}} +{"type":"turn/end","seq":75,"time":1786547098004,"data":{"turn":1,"reason":{"kind":"completed"}}} diff --git a/knip.json b/knip.json index e06fa48220..3017292382 100644 --- a/knip.json +++ b/knip.json @@ -9,6 +9,7 @@ "musl-gcc", "python3", "sandbox-exec", + "tar", "taskkill", "where.exe" ], diff --git a/native/landlock-run/package.json b/native/landlock-run/package.json index 0fb9b3ddfb..be0ca9732d 100644 --- a/native/landlock-run/package.json +++ b/native/landlock-run/package.json @@ -1,6 +1,6 @@ { "name": "@deepseek-ai/node-addon-landlock-run-workspace", - "version": "0.0.1", + "version": "0.1.1", "private": true, "type": "module", "license": "BSD-3-Clause", @@ -19,6 +19,7 @@ "release:assemble-prebuilds": "node ./scripts/assemble-prebuilds.mjs", "release:verify": "node ./scripts/verify-release.mjs", "release:pack": "node ./scripts/pack-release.mjs", + "release:publish": "node ./scripts/publish-release.mjs", "release:verify-packed-install": "node ./scripts/verify-packed-install.mjs" }, "devDependencies": { diff --git a/native/landlock-run/packages/entry/package.json b/native/landlock-run/packages/entry/package.json index b3384a58c0..5e34cf96f0 100644 --- a/native/landlock-run/packages/entry/package.json +++ b/native/landlock-run/packages/entry/package.json @@ -1,6 +1,6 @@ { "name": "@deepseek-ai/node-addon-landlock-run", - "version": "0.0.1", + "version": "0.1.1", "type": "module", "description": "Landlock self-restrict-then-exec launcher for sandboxing subprocesses on Linux: per-platform prebuilt static binaries plus the JS seam that resolves, probes, and speaks their CLI contract", "repository": { @@ -32,7 +32,7 @@ }, "license": "BSD-3-Clause", "publishConfig": { - "access": "restricted" + "access": "public" }, "optionalDependencies": { "@deepseek-ai/node-addon-landlock-run-linux-arm64": "workspace:*", diff --git a/native/landlock-run/packages/linux-arm64/package.json b/native/landlock-run/packages/linux-arm64/package.json index 11d9384c87..8e6affec6a 100644 --- a/native/landlock-run/packages/linux-arm64/package.json +++ b/native/landlock-run/packages/linux-arm64/package.json @@ -1,6 +1,6 @@ { "name": "@deepseek-ai/node-addon-landlock-run-linux-arm64", - "version": "0.0.1", + "version": "0.1.1", "description": "Prebuilt landlock-run Landlock launcher binary for linux-arm64 (static musl) — resolved as a file path by @deepseek-ai/node-addon-landlock-run, never imported", "repository": { "type": "git", @@ -26,6 +26,6 @@ }, "license": "BSD-3-Clause", "publishConfig": { - "access": "restricted" + "access": "public" } } diff --git a/native/landlock-run/packages/linux-x64/package.json b/native/landlock-run/packages/linux-x64/package.json index 6e3ad395e6..7e9cab7a1a 100644 --- a/native/landlock-run/packages/linux-x64/package.json +++ b/native/landlock-run/packages/linux-x64/package.json @@ -1,6 +1,6 @@ { "name": "@deepseek-ai/node-addon-landlock-run-linux-x64", - "version": "0.0.1", + "version": "0.1.1", "description": "Prebuilt landlock-run Landlock launcher binary for linux-x64 (static musl) — resolved as a file path by @deepseek-ai/node-addon-landlock-run, never imported", "repository": { "type": "git", @@ -26,6 +26,6 @@ }, "license": "BSD-3-Clause", "publishConfig": { - "access": "restricted" + "access": "public" } } diff --git a/native/landlock-run/scripts/publish-release.mjs b/native/landlock-run/scripts/publish-release.mjs new file mode 100644 index 0000000000..76c875b8d3 --- /dev/null +++ b/native/landlock-run/scripts/publish-release.mjs @@ -0,0 +1,165 @@ +#!/usr/bin/env node +/** + * Publish the packed launcher family from the tarballs `pack-release.mjs` + * produced, in `publish-order.txt` order. + * + * What goes out is decided per package against the registry, never from the + * order file alone: a version the registry lacks is published, a version whose + * published tarball has the same integrity is skipped, and a version whose + * published tarball differs fails the run — that last case means the content + * changed without a version bump. Skipping on identical integrity is what makes + * re-running the publish step over the same artifact safe, which matters here + * because a partial publication used to leave no way forward: republishing an + * existing version fails permanently. + * + * Usage: `node scripts/publish-release.mjs [packed dir]`. + */ + +import fs from 'node:fs'; +import path from 'node:path'; +import crypto from 'node:crypto'; +import { spawnSync } from 'node:child_process'; +import { setTimeout as sleep } from 'node:timers/promises'; +import { root } from './repo.mjs'; + +/** + * Registry codes that answer a write which did not settle, rather than a + * rejection of what was sent. `E409 Failed to save packument` is the one this + * sequence actually hits: publishing the platform packages and the entry back + * to back can outrun the registry's own processing. A rejected payload (`E403` + * over an existing version, a malformed manifest) never clears on a retry. + */ +const TRANSIENT_PUBLISH_CODES = ['E409', 'E429', 'E500', 'E502', 'E503', 'E504', 'ETIMEDOUT', 'ECONNRESET', 'EAI_AGAIN']; + +/** How many times one tarball's publish is attempted before the run fails. */ +const PUBLISH_ATTEMPTS = 4; + +/** + * Shortest gap between two publishes, and the first retry backoff. The registry + * needs a moment to commit a packument before the next write; back to back + * publishes are what produce `E409`. + */ +const PUBLISH_SPACING_MS = 2_000; + +const destination = path.resolve(process.argv.slice(2).find((arg) => !arg.startsWith('--')) || path.join(root, 'dist', 'npm')); + +/** + * @param {string} output Combined npm output. + * @returns {boolean} True when the registry reported a write it did not commit. + */ +function isTransientFailure(output) { + return TRANSIENT_PUBLISH_CODES.some((code) => output.includes(`code ${code}`)); +} + +/** + * @param {string} tarball Absolute tarball path. + * @returns {string} The `sha512-` integrity npm records for it. + */ +function integrityOf(tarball) { + return `sha512-${crypto.createHash('sha512').update(fs.readFileSync(tarball)).digest('base64')}`; +} + +/** + * @param {string} tarball Absolute tarball path. + * @returns {{name: string, version: string}} What the packed manifest declares. + */ +function packedIdentity(tarball) { + const result = spawnSync('tar', ['-xOzf', tarball, 'package/package.json'], { encoding: 'utf8' }); + if (result.status !== 0) throw new Error(`cannot read the manifest inside ${tarball}:\n${result.stderr}`); + const manifest = JSON.parse(result.stdout); + if (typeof manifest.name !== 'string' || typeof manifest.version !== 'string') { + throw new Error(`${tarball} manifest lacks name/version`); + } + return { name: manifest.name, version: manifest.version }; +} + +/** + * Ask the registry whether a version exists, and with what integrity. + * @param {string} name Package name. + * @param {string} version Package version. + * @returns {{kind: 'absent'} | {kind: 'present', integrity: string}} Registry state. + */ +function registryState(name, version) { + const result = spawnSync('npm', ['view', `${name}@${version}`, 'dist.integrity', '--json'], { encoding: 'utf8' }); + if (result.status !== 0) { + const output = `${result.stdout}${result.stderr}`; + if (output.includes('E404') || output.includes('404 Not Found')) return { kind: 'absent' }; + throw new Error(`npm view ${name}@${version} failed:\n${output}`); + } + const parsed = JSON.parse(result.stdout); + if (typeof parsed !== 'string' || parsed === '') { + throw new Error(`registry reported no dist.integrity for ${name}@${version}`); + } + return { kind: 'present', integrity: parsed }; +} + +/** + * Publish one tarball, retrying a registry write that did not settle. + * + * Every retry re-reads the registry first, because `E409` can answer a write + * that landed anyway: republishing a version that now exists fails permanently, + * so the same integrity appearing under the failed attempt counts as success. + * @param {string} tarball Absolute tarball path. + * @param {string} name Package name the tarball declares. + * @param {string} version Package version the tarball declares. + */ +async function publishTarball(tarball, name, version) { + // A prerelease version never takes the latest dist-tag. + const tagArgs = version.includes('-') ? ['--tag', 'next'] : []; + for (let tries = 1; tries <= PUBLISH_ATTEMPTS; tries += 1) { + // No --access: publishConfig.access in each manifest decides, and a + // command-line flag would override it. + const result = spawnSync('npm', ['publish', tarball, ...tagArgs], { encoding: 'utf8' }); + const output = `${result.stdout}${result.stderr}`; + if (result.status === 0) return; + + const settled = registryState(name, version); + if (settled.kind === 'present' && settled.integrity === integrityOf(tarball)) { + console.log(`landlock publish: ${name}@${version} landed despite a reported failure, continuing`); + return; + } + if (tries === PUBLISH_ATTEMPTS || !isTransientFailure(output)) { + throw new Error(`npm publish ${name}@${version} failed:\n${output}`); + } + const backoff = PUBLISH_SPACING_MS * 2 ** (tries - 1); + console.log( + `landlock publish: ${name}@${version} hit a transient registry failure` + + ` (attempt ${tries} of ${PUBLISH_ATTEMPTS}), retrying in ${backoff}ms`, + ); + await sleep(backoff); + } +} + +const order = fs + .readFileSync(path.join(destination, 'publish-order.txt'), 'utf8') + .split('\n') + .filter((line) => line !== ''); + +let published = 0; +let skipped = 0; +for (const filename of order) { + const tarball = path.join(destination, filename); + const { name, version } = packedIdentity(tarball); + const state = registryState(name, version); + if (state.kind === 'present') { + const local = integrityOf(tarball); + if (state.integrity !== local) { + throw new Error( + `${name}@${version} is already published with different content` + + `\n registry: ${state.integrity}\n packed: ${local}` + + '\nBump the version, or investigate why the build is not reproducible.', + ); + } + console.log(`landlock publish: ${name}@${version} already published, skipping`); + skipped += 1; + continue; + } + // Space out the writes: the gap belongs between publishes, so a run that only + // skips does not wait at all. + if (published > 0) await sleep(PUBLISH_SPACING_MS); + await publishTarball(tarball, name, version); + console.log(`landlock publish: ${name}@${version} published`); + published += 1; +} + +console.log(`landlock publish: ${published} published, ${skipped} already present`); diff --git a/package.json b/package.json index edfec2bae8..517d0c56d1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,7 @@ { "name": "@deepseek-ai/dsh-root", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", + "license": "MIT", "private": true, "type": "module", "packageManager": "pnpm@11.7.0", @@ -65,9 +66,11 @@ "doc-typecheck:contracts-ready": "tsx scripts/doc-typecheck.ts", "verify-md-wrap": "tsx scripts/verify-md-wrap.ts", "verify-md-links": "tsx scripts/verify-md-links.ts", + "verify-doc-site-fragments": "tsx scripts/verify-doc-site-fragments.ts", "verify-public-repository-links": "tsx scripts/verify-public-repository-links.ts", "verify-doc-refs": "tsx scripts/verify-doc-refs.ts", "verify-package-paths": "tsx scripts/verify-package-paths.ts", + "verify-dsh-package-licenses": "tsx scripts/verify-dsh-package-licenses.ts", "verify-config-source-ownership": "tsx scripts/verify-config-source-ownership.ts", "verify-package-invariants": "tsx scripts/verify-package-invariants.ts", "verify-built-package-invariants": "node scripts/verify-built-package-invariants.mjs", @@ -84,14 +87,15 @@ "gen-translation-brief": "tsx scripts/gen-translation-brief.ts", "verify-doc-budgets": "tsx scripts/verify-doc-budgets.ts", "docs:dev": "pnpm --filter @deepseek-ai/website run dev", - "docs:build": "pnpm --filter @deepseek-ai/website run build", - "docs:build:mpa": "pnpm --filter @deepseek-ai/website exec vitepress build . --mpa", + "docs:build": "pnpm --filter @deepseek-ai/website run build && pnpm run verify-doc-site-fragments", + "docs:build:mpa": "pnpm --filter @deepseek-ai/website exec vitepress build . --mpa && pnpm run verify-doc-site-fragments", "docs:preview": "pnpm --filter @deepseek-ai/website run preview", - "docs:check": "pnpm exec vitest run scripts/project-doc-site.spec.ts && pnpm run docs:build", + "docs:check": "pnpm exec vitest run scripts/project-doc-site.spec.ts scripts/verify-doc-site-fragments.spec.ts && pnpm run docs:build", "website:dev": "pnpm run docs:dev", "website:build": "pnpm run docs:build", "verify-package-readme-limitations": "tsx scripts/verify-package-readme-limitations.ts", "verify-node-next-types": "tsx scripts/verify-node-next-types.ts", + "verify-optional-dependency-imports": "tsx scripts/verify-optional-dependency-imports.ts", "verify-runtime-closure": "tsx scripts/verify-runtime-closure.ts", "verify-vendored-links": "tsx scripts/verify-vendored-links.ts", "verify-cordis-config": "tsx scripts/verify-cordis-config.ts", @@ -122,7 +126,7 @@ "verify-module-graph": "tsx scripts/gen-module-graph.ts --check", "constraints": "tsx scripts/check-workspace-constraints.ts", "doc-sync": "tsx scripts/run-gates.ts doc-sync", - "hygiene": "pnpm run rescope-vendor:check && pnpm run knip && pnpm run publint && pnpm run constraints && pnpm run verify-package-invariants && pnpm run verify-built-package-invariants && pnpm run verify-cordis-config && pnpm run verify-node-next-types && pnpm run verify-runtime-closure && pnpm run verify-vendored-links", + "hygiene": "pnpm run rescope-vendor:check && pnpm run knip && pnpm run publint && pnpm run constraints && pnpm run verify-dsh-package-licenses && pnpm run verify-package-invariants && pnpm run verify-built-package-invariants && pnpm run verify-cordis-config && pnpm run verify-node-next-types && pnpm run verify-optional-dependency-imports && pnpm run verify-runtime-closure && pnpm run verify-vendored-links", "publish:npm-baseline": "tsx scripts/publish-npm-baseline.ts", "release:dsh": "tsx scripts/release/bump.ts --family dsh", "release:vendor": "tsx scripts/release/bump.ts --family vendor", diff --git a/packages/README.i18n.yaml b/packages/README.i18n.yaml index 856b455103..cdc5428234 100644 --- a/packages/README.i18n.yaml +++ b/packages/README.i18n.yaml @@ -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/README.md -README.md: 2e28b190378ed8ca25102d6311bd8a2c8d5e1c58 -README.zh.md: e0e1973d146c241d4846c4c237ed0e5f6a0d7b8a +README.md: 7904ec1fea8dbab361fcd90b2b32f1c743ce5537 +README.zh.md: c39b65dad7e9c277779a85d7327982597628e007 diff --git a/packages/README.md b/packages/README.md index 2e28b19037..7904ec1fea 100644 --- a/packages/README.md +++ b/packages/README.md @@ -64,6 +64,6 @@ New packages join existing groups; new groups update their README and this table The dependency graph is generated: [docs/module-graph.md](../docs/module-graph.md) (`pnpm run gen-module-graph`, freshness-gated in CI). -**Extension plugins depend on Service Definitions, never concrete providers.** `dsh-agent-loop` is swappable; UI, hook, and tool plugins use `dsh-agent`. Composition bundles, including `dsh-agent-spine-demo`, may depend on spine plugins. Capabilities separate Service Definition / Service provider / Consumer roles when they evolve independently; see [capability seams](../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md). +**Extension plugins depend on Service Definitions, never concrete providers.** `dsh-agent-loop` is swappable; UI, hook, and tool plugins use `dsh-agent`. Composition bundles, including `dsh-agent-spine-demo`, may depend on spine plugins. Capabilities separate Service Definition / Service Provider / Consumer roles when they evolve independently; see [capability seams](../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md). Package READMEs cover purpose, APIs, extension points, and [Model Experience](../docs/cookbook/adding-a-package.md#4-write-the-package-readme) unless on the model-agnostic [omission allowlist](../scripts/verify-package-readme-model-experience.ts). They also carry `## Known Limitations and Deferred Work` or use its [allowlist](../scripts/verify-package-readme-limitations.ts). diff --git a/packages/README.zh.md b/packages/README.zh.md index e0e1973d14..c39b65dad7 100644 --- a/packages/README.zh.md +++ b/packages/README.zh.md @@ -10,53 +10,53 @@ npm scope 为 `@deepseek-ai/dsh-*`;Cordis `Service` 子类和函数插件通 | 组 | 职责 | 发布预期 | |---|---|---| -| [`core/`](core/README.md) | 产品 API 主干:会话、提示词、工具、agent(智能体)服务与具体循环 | 产品:稳定接口 | -| [`api/`](api/README.md) | Remote BFF 装配与 Typert RPC Gateway | 产品:稳定接口 | -| [`typert/`](typert/README.md) | 类型图生成、产物加载与运行时注册表 | 产品:稳定接口 | -| [`goal/`](goal/README.md) | 同会话 goal 的持久化与生命周期 | 产品:稳定接口 | -| [`schedule/`](schedule/README.md) | 仅限会话内的定时后续轮次 | 产品:稳定接口 | -| [`feedback/`](feedback/README.md) | 人类反馈 | 产品:稳定接口 | -| [`identity/`](identity/README.md) | 共享匿名身份 | 产品:稳定接口 | -| [`llm/`](llm/README.md) | LLM(大语言模型)能力系列:抽象服务 + 提供方适配器 | 产品:稳定接口 | +| [`core/`](core/README.md) | 产品 API 主干:会话、提示词、工具、agent(智能体)服务与具体循环 | 产品:稳定 API | +| [`api/`](api/README.md) | Remote BFF 装配与 Typert RPC 网关 | 产品:稳定 API | +| [`typert/`](typert/README.md) | 类型图生成、产物加载与运行时注册表 | 产品:稳定 API | +| [`goal/`](goal/README.md) | 同会话 goal 的持久化与生命周期 | 产品:稳定 API | +| [`schedule/`](schedule/README.md) | 仅限会话内的定时后续操作 | 产品:稳定 API | +| [`feedback/`](feedback/README.md) | 人类反馈 | 产品:稳定 API | +| [`identity/`](identity/README.md) | 共享匿名身份 | 产品:稳定 API | +| [`llm/`](llm/README.md) | LLM(大语言模型)能力系列:抽象服务 + 提供方适配器 | 产品:稳定 API | | [`e2b/`](e2b/README.md) | E2B 提供方 | POC | -| [`subprocess/`](subprocess/README.md) | 子进程能力系列:Service Definition + 本地进程树提供方 | 产品:稳定接口 | -| [`shell/`](shell/README.md) | Bash 能力系列:执行器 seam、本地实现、面向模型的工具 | 产品:稳定接口 | -| [`terminal/`](terminal/README.md) | 持久 PTY 能力系列:按所有者隔离的会话、本地实现和面向模型的工具 | 产品:稳定接口 | -| [`code-runtime/`](code-runtime/README.md) | 代码执行能力系列:Service Definition + worker 线程提供方 + Code Mode Consumer | 产品:稳定接口 | -| [`sandbox/`](sandbox/README.md) | 进程限制 seam;bwrap/Landlock/Seatbelt 后端 | 产品:稳定接口 | -| [`fs/`](fs/README.md) | 文件系统能力系列:seam、本地实现、面向模型的文件工具、由 bash 支持的发现工具 | 产品:稳定接口 | -| [`lsp/`](lsp/README.md) | LSP 能力系列:seam、通用 stdio 提供方和 `lsp` 工具 | 产品:稳定接口 | -| [`skill/`](skill/README.md) | skill(技能)能力系列:提供方注册表、本地提供方和面向模型的目录/loader | 产品:稳定接口 | -| [`compaction/`](compaction/README.md) | 压缩(compaction)能力系列:Service Definition + 基础提供方 + 命令 Consumer | 产品:稳定接口 | -| [`context/`](context/README.md) | 模型可见请求上下文,包括 workspace 指令和时间上下文 | 产品:稳定接口 | -| [`subagent/`](subagent/README.md) | subagent 能力系列:提供方注册表约定和面向模型的委托工具 | 产品:稳定接口 | -| [`jobs/`](jobs/README.md) | 通用后台任务运行时和面向模型的 `job_*` 控制工具 | 产品:稳定接口 | -| [`workflow/`](workflow/README.md) | 工作流 seam、worker 线程引擎和面向模型的 `workflow`/`ralph` 工具 | 产品:稳定接口 | -| [`web/`](web/README.md) | Web 能力系列:seam、搜索/获取提供方实现和面向模型的 Web 工具 | 产品:稳定接口 | -| [`attachment/`](attachment/README.md) | 持久附件标识、校验、本地内容寻址存储 | 产品:稳定接口 | -| [`spill/`](spill/README.md) | spill 能力系列:存储 seam、本地实现、工具结果 spill 策略 | 产品:稳定接口 | -| [`todo/`](todo/README.md) | 面向模型的 `todo_write` 工具 | 产品:稳定接口 | -| [`plan/`](plan/README.md) | Plan 协作状态,提供直接进入命令与经评审的退出 | 产品:稳定接口 | -| [`preset/`](preset/README.md) | 由 preset `cordis.yml` 按会话组装 agent | 产品:稳定接口 | -| [`guard/`](guard/README.md) | 循环卫生守卫:建议性重复调用提醒 + `tools/execute` 截止时间强制执行器 | 产品:稳定接口 | -| [`bundle/`](bundle/README.md) | 可安装的 `dsh --profile` 补丁层 | 产品:稳定接口 | -| [`extensions/`](extensions/README.md) | agent 运行时自修改:实时插件/服务检查和模型所写插件挂载/卸载([设计](../.agents/notes/implemented/feature/2026-07-08-self-referential-cordis-toolset.md)) | 产品:稳定接口 | -| [`hooks/`](hooks/README.md) | 钩子桥接 + 共享 Claude Code/Codex 协议格式库 | 产品:稳定接口 | -| [`session/`](session/README.md) | 持久会话数据平面:持久化 seam + JSONL/SQLite 后端、投影 seam、基于日志的标题、会话上报 | 产品:稳定接口 | -| [`session-query/`](session-query/README.md) | 会话检索系列:逻辑语料库、有界读取、血缘、事件关系、语义过滤和 SQLite 全文搜索 | 产品:稳定接口 | -| [`settings/`](settings/README.md) | 用户设置 seam + 基于文件的提供方 | 产品:稳定接口 | -| [`credentials/`](credentials/README.md) | 凭据引用 seam + 环境变量优先于 `.env` 的提供方 | 产品:稳定接口 | -| [`storage/`](storage/README.md) | 非会话存储中枢 + 后端 + 领域形式 | 产品:稳定接口 | -| [`workspace/`](workspace/README.md) | Workspace 实体 | 产品:稳定接口 | -| [`sdk/`](sdk/README.md) | 进程外运行时 SDK:JSON-RPC 协议、TypeScript 客户端和服务器插件 | 产品:稳定接口 | -| [`acp/`](acp/README.md) | 仅面向自动化的 ACP(Agent Client Protocol)服务器 | 产品:稳定接口 | -| [`interaction/`](interaction/README.md) | 人机协作平面:批准/交互 seam、权限预设、命令、询问用户的工具 | 产品:稳定接口 | -| [`boot/`](boot/README.md) | 共享的 app bin 启动粘合层 | 产品:稳定接口 | -| [`host/`](host/README.md) | web GUI 宿主半侧:API 网关 + HTTP 路由服务器 | 产品:稳定接口 | -| [`client/`](client/README.md) | web GUI 浏览器半侧:shell、协议层、对象服务、slot、`ui-*` 插件 | 产品:稳定接口 | +| [`subprocess/`](subprocess/README.md) | 子进程能力系列:Service Definition + 本地进程树提供方 | 产品:稳定 API | +| [`shell/`](shell/README.md) | Bash 能力系列:执行器 seam、本地实现、面向模型的工具 | 产品:稳定 API | +| [`terminal/`](terminal/README.md) | 持久 PTY 能力系列:限定所有者范围的会话、本地实现和面向模型的工具 | 产品:稳定 API | +| [`code-runtime/`](code-runtime/README.md) | 代码执行能力系列:Service Definition + worker 线程提供方 + Code Mode Consumer | 产品:稳定 API | +| [`sandbox/`](sandbox/README.md) | 进程限制 seam;bwrap/Landlock/Seatbelt 后端 | 产品:稳定 API | +| [`fs/`](fs/README.md) | 文件系统能力系列:seam、本地实现、面向模型的文件工具、由 bash 支持的发现工具 | 产品:稳定 API | +| [`lsp/`](lsp/README.md) | LSP 能力系列:seam、通用 stdio 提供方和 `lsp` 工具 | 产品:稳定 API | +| [`skill/`](skill/README.md) | skill(技能)能力系列:提供方注册表、本地提供方和面向模型的目录/loader | 产品:稳定 API | +| [`compaction/`](compaction/README.md) | 压缩(compaction)能力系列:Service Definition + 基础提供方 + 命令 Consumer | 产品:稳定 API | +| [`context/`](context/README.md) | 模型可见请求上下文,包括 workspace 指令和时间上下文 | 产品:稳定 API | +| [`subagent/`](subagent/README.md) | subagent 能力系列:提供方注册表约定和面向模型的委托工具 | 产品:稳定 API | +| [`jobs/`](jobs/README.md) | 通用后台任务运行时和面向模型的 `job_*` 控制工具 | 产品:稳定 API | +| [`workflow/`](workflow/README.md) | 工作流 seam、worker 线程引擎和面向模型的 `workflow`/`ralph` 工具 | 产品:稳定 API | +| [`web/`](web/README.md) | Web 能力系列:seam、搜索/获取提供方实现和面向模型的 Web 工具 | 产品:稳定 API | +| [`attachment/`](attachment/README.md) | 持久附件标识、校验、本地内容寻址存储 | 产品:稳定 API | +| [`spill/`](spill/README.md) | spill 能力系列:存储 seam、本地实现、工具结果 spill 策略 | 产品:稳定 API | +| [`todo/`](todo/README.md) | 面向模型的 `todo_write` 工具 | 产品:稳定 API | +| [`plan/`](plan/README.md) | Plan 协作状态,提供直接进入命令与经评审的退出 | 产品:稳定 API | +| [`preset/`](preset/README.md) | 由 preset `cordis.yml` 按会话组装 agent | 产品:稳定 API | +| [`guard/`](guard/README.md) | 循环卫生守卫:建议性重复调用提醒 + `tools/execute` 截止时间强制执行器 | 产品:稳定 API | +| [`bundle/`](bundle/README.md) | 可安装的 `dsh --profile` 补丁层 | 产品:稳定 API | +| [`extensions/`](extensions/README.md) | agent 运行时自修改:实时插件/服务检查和模型所写插件挂载/卸载([设计](../.agents/notes/implemented/feature/2026-07-08-self-referential-cordis-toolset.md)) | 产品:稳定 API | +| [`hooks/`](hooks/README.md) | 钩子桥接 + 共享的 Claude Code/Codex 线协议库 | 产品:稳定 API | +| [`session/`](session/README.md) | 持久会话数据平面:持久化 seam + JSONL/SQLite 后端、投影 seam、基于日志的标题、会话上报 | 产品:稳定 API | +| [`session-query/`](session-query/README.md) | 会话检索系列:逻辑语料库、有界读取、血缘、事件关系、语义过滤和 SQLite 全文搜索 | 产品:稳定 API | +| [`settings/`](settings/README.md) | 用户设置 seam + 基于文件的提供方 | 产品:稳定 API | +| [`credentials/`](credentials/README.md) | 凭据引用 seam + 环境变量优先于 `.env` 的提供方 | 产品:稳定 API | +| [`storage/`](storage/README.md) | 非会话存储中枢 + 后端 + 领域形式 | 产品:稳定 API | +| [`workspace/`](workspace/README.md) | Workspace 实体 | 产品:稳定 API | +| [`sdk/`](sdk/README.md) | 进程外运行时 SDK:JSON-RPC 协议、TypeScript 客户端和服务器插件 | 产品:稳定 API | +| [`acp/`](acp/README.md) | 仅面向自动化的 ACP(Agent Client Protocol)服务器 | 产品:稳定 API | +| [`interaction/`](interaction/README.md) | 人机协作平面:批准/交互 seam、权限预设、命令、询问用户的工具 | 产品:稳定 API | +| [`boot/`](boot/README.md) | 共享的 app bin 启动粘合层 | 产品:稳定 API | +| [`host/`](host/README.md) | web GUI 宿主半侧:API 网关 + HTTP 路由服务器 | 产品:稳定 API | +| [`client/`](client/README.md) | web GUI 浏览器半侧:shell、协议层、对象服务、slot、`ui-*` 插件 | 产品:稳定 API | | [`examples/`](examples/README.md) | 演示组合包(agent-spine + CLI(命令行界面)/ACP/JSON-RPC bin),由叶节点加载 | 支持:示例基础设施 | | [`test-support/`](test-support/README.md) | 支持基础设施(testkit、不变式、回放、Loader 冒烟测试) | 支持:兼容性预期较低 | -| [`util/`](util/README.md) | 组间共享的低层零依赖工具(`Branded`、Harness home/路径辅助函数、超时、保留策略) | 支持:小型、稳定、无 harness 依赖 | +| [`util/`](util/README.md) | 组间共享的低层零依赖工具(`Branded`、Harness home/路径辅助函数、超时、留存) | 支持:小型、稳定、无 harness 依赖 | 新包加入现有组;新组更新其 README 和此表。 @@ -64,6 +64,6 @@ npm scope 为 `@deepseek-ai/dsh-*`;Cordis `Service` 子类和函数插件通 依赖图由工具生成:[docs/module-graph.md](../docs/module-graph.md)(`pnpm run gen-module-graph`,CI 中有新鲜度门禁)。 -**扩展插件依赖 Service Definition,绝不依赖具体提供方。** `dsh-agent-loop` 可替换;UI、钩子和工具插件使用 `dsh-agent`。包括 `dsh-agent-spine-demo` 在内的组合包可以依赖主干插件。能力在 Service Definition/Service provider/Consumer 角色需要独立演进时将其分离;详见[能力 seam](../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md)。 +**扩展插件依赖 Service Definition,绝不依赖具体提供方。** `dsh-agent-loop` 可替换;UI、钩子和工具插件使用 `dsh-agent`。包括 `dsh-agent-spine-demo` 在内的组合包可以依赖主干插件。能力会将需要独立演进的 Service Definition/Service Provider/Consumer 角色分离;详见[能力 seam](../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md)。 包 README 覆盖用途、API、扩展点和[模型体验](../docs/cookbook/adding-a-package.md#4-write-the-package-readme);列入模型无关[省略允许清单](../scripts/verify-package-readme-model-experience.ts)的包除外。它们还要包含 `## Known Limitations and Deferred Work`,或列入其[允许清单](../scripts/verify-package-readme-limitations.ts)。 diff --git a/packages/acp/acp/package.json b/packages/acp/acp/package.json index 5aedb8fd5b..d5f08d2028 100644 --- a/packages/acp/acp/package.json +++ b/packages/acp/acp/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-acp", "description": "Automation-only Agent Client Protocol server for driving DeepSeek Harness agents over JSON-RPC stdio", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "@agentclientprotocol/sdk": "0.25.1", "@deepseek-ai/schemastery": "workspace:^" diff --git a/packages/api/gateway/package.json b/packages/api/gateway/package.json index 66c34a9b1f..9d128595d8 100644 --- a/packages/api/gateway/package.json +++ b/packages/api/gateway/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-api-gateway", "description": "Typert Remote Host dispatcher and Client API endpoint", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -54,7 +54,7 @@ "lib/types/**/*.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "@deepseek-ai/dsh-typert-protocol": "workspace:^" }, diff --git a/packages/api/remotes/package.json b/packages/api/remotes/package.json index ae2f56dd0c..edc6d65704 100644 --- a/packages/api/remotes/package.json +++ b/packages/api/remotes/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-api-remotes", "description": "Remote BFF assembly and Host Agent/Session lookup policy", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -46,7 +46,7 @@ "bundle": "tsdown", "watch": "tsdown --watch" }, - "license": "BSD-3-Clause", + "license": "MIT", "files": [ "lib/index.js", "lib/invariant.js", diff --git a/packages/attachment/attachment-local/package.json b/packages/attachment/attachment-local/package.json index bc350a8106..844479fc40 100644 --- a/packages/attachment/attachment-local/package.json +++ b/packages/attachment/attachment-local/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-attachment-local", "description": "Private content-addressed DSH_HOME attachment storage", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -20,7 +20,7 @@ "./package.json": "./package.json" }, "files": ["lib/index.js", "lib/invariant.js", "lib/types/**/*.d.ts"], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-attachment": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/attachment/attachment/package.json b/packages/attachment/attachment/package.json index 4819bd7674..3f11676e71 100644 --- a/packages/attachment/attachment/package.json +++ b/packages/attachment/attachment/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-attachment", "description": "Durable immutable attachment storage seam for the DeepSeek Harness", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -20,7 +20,7 @@ "./package.json": "./package.json" }, "files": ["lib/index.js", "lib/invariant.js", "lib/types/**/*.d.ts"], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-brand": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/boot/app-boot/package.json b/packages/boot/app-boot/package.json index cafa235de1..c602dc9399 100644 --- a/packages/boot/app-boot/package.json +++ b/packages/boot/app-boot/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-app-boot", "description": "Shared boot glue for the app bins: .env loading, fail-loud Loader guards, snapshot-aware config resolution, and the Loader boot sequence", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "js-yaml": "^4.2.0" }, diff --git a/packages/boot/app-boot/src/profile.ts b/packages/boot/app-boot/src/profile.ts index 59dac77d69..8f982bed80 100644 --- a/packages/boot/app-boot/src/profile.ts +++ b/packages/boot/app-boot/src/profile.ts @@ -24,7 +24,7 @@ import { createRequire } from 'node:module' import { - existsSync, lstatSync, mkdirSync, readFileSync, readlinkSync, rmSync, symlinkSync, writeFileSync, + existsSync, lstatSync, mkdirSync, readFileSync, readlinkSync, symlinkSync, unlinkSync, writeFileSync, } from 'node:fs' import { basename, dirname, join } from 'node:path' import type { EntryOptions } from '@deepseek-ai/cordis-plugin-loader' @@ -182,7 +182,9 @@ function ensureSymlink(link: string, target: string): void { throw new Error(`dsh: ${link} exists and is not a symlink; remove it so dsh can manage the installation fallback`) } if (readlinkSync(link) === target) return - rmSync(link) + // unlink deletes the reparse point itself on Windows too; rmSync treats a + // junction as a directory and throws EISDIR unless recursive. + unlinkSync(link) } try { symlinkSync(target, link, 'junction') @@ -209,7 +211,7 @@ function ensureSymlink(link: string, target: string): void { * installation" contract. The closure (not just direct dependencies) is * required for out-of-tree plugins: their peer dependencies name Service * Definition packages (`dsh-compaction`, `dsh-invariants`, ...) that the app - * reaches only through its Service provider packages. Symlinked packages + * reaches only through its Service Provider packages. Symlinked packages * resolve their own dependencies from their real directories (Node's default * symlink-following), so each package needs only its one flat link. * Idempotent: correct links are kept and moved installations are diff --git a/packages/boot/app-boot/tests/hmr-config.spec.ts b/packages/boot/app-boot/tests/hmr-config.spec.ts index c248643130..5f52ab5e2a 100644 --- a/packages/boot/app-boot/tests/hmr-config.spec.ts +++ b/packages/boot/app-boot/tests/hmr-config.spec.ts @@ -62,7 +62,7 @@ describe('HMR exact config paths', () => { expect(cacheHas).toHaveBeenCalledWith(expected) } finally { await ctx.fiber.dispose() - rmSync(alias, { force: true }) + unlinkSync(alias) rmSync(target, { recursive: true, force: true }) } }) @@ -78,7 +78,7 @@ describe('HMR exact config paths', () => { .rejects.toThrow('config path already registered') } finally { await ctx.fiber.dispose() - rmSync(alias, { force: true }) + unlinkSync(alias) rmSync(target, { recursive: true, force: true }) } }) diff --git a/packages/boot/cmdline/package.json b/packages/boot/cmdline/package.json index a679d4e3fe..a91d6b8cd2 100644 --- a/packages/boot/cmdline/package.json +++ b/packages/boot/cmdline/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-cmdline", "description": "Immutable command-line handoff from a dsh launcher to any app plugin that injects cmdlineArgs", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -30,7 +30,7 @@ "lib/invariant.js", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis-plugin-loader": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/bundle/base/README.i18n.yaml b/packages/bundle/base/README.i18n.yaml index cae813eb1d..483784e547 100644 --- a/packages/bundle/base/README.i18n.yaml +++ b/packages/bundle/base/README.i18n.yaml @@ -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/bundle/base/README.md -README.md: bd38f39f58ee1f765ff34d40cf57cc6daed2b32b -README.zh.md: bcf4463587f42a245126f87388f3c0a4e57f0976 +README.md: 00a177d4dd65de8706aa0e27a79d06a9a50eb55a +README.zh.md: ad70fc16035d3dd70b04e78c31aea90acf61119b diff --git a/packages/bundle/base/README.md b/packages/bundle/base/README.md index bd38f39f58..00a177d4dd 100644 --- a/packages/bundle/base/README.md +++ b/packages/bundle/base/README.md @@ -2,7 +2,7 @@ English | [中文](README.zh.md) -The shared dsh core as a profile bundle: [`cordis.patch.yml`](cordis.patch.yml) inserts every base plugin row — model adapters, the shared [`agent-default-model`](../../core/agent-default-model/README.md) selection, tools, persistence, policy, settings/credentials, telemetry, and host-level subagent providers — over the empty profile root, as the first layer of every profile's `dsh.profile.bundles` list. Codex and Claude Code providers load dormant; Agent Presets independently decide whether their agent contributes either model-facing delegation tool. Later bundle layers (e.g. [`dsh-web-app`](../web-app/README.md)) and the user's profile `cordis.patch.yml` override these rows by id; a patch replaces a row's whole `config`, so mode-specific values live in mode bundles, not here. The package has no runtime API; the profile composer resolves the patch through the `dsh.bundle.patch` manifest field, never through code. +The shared dsh core as a profile bundle: [`cordis.patch.yml`](cordis.patch.yml) inserts every base plugin row — model adapters, the shared [`agent-default-model`](../../core/agent-default-model/README.md) selection, tools, persistence, policy, settings/credentials, telemetry, and host-level subagent providers — over the empty profile root, as the first layer of every profile's `dsh.profile.bundles` list. This bundle neither depends on nor mounts the optional Codex and Claude Code providers; an opting-in Profile installs and mounts the selected provider once on the host plane, while Agent Presets decide whether their agents receive the corresponding model-facing delegation tools. Later bundle layers (e.g. [`dsh-web-app`](../web-app/README.md)) and the user's profile `cordis.patch.yml` override these rows by id; a patch replaces a row's whole `config`, so mode-specific values live in mode bundles, not here. The package has no runtime API; the profile composer resolves the patch through the `dsh.bundle.patch` manifest field, never through code. The patch gates both shell stacks by platform on its own rows: `bash-sandbox`/`tool-bash` carry `disabled: !!js process.platform === 'win32'` (bash has no Windows runner), and their twins `pwsh-sandbox`/`tool-pwsh` mount on win32 only with the inverted expression — one shared patch file, exactly one shell stack per host. The permission surface stays exactly as on POSIX: `sandbox`/`sandbox-policy` enforce the file-effect policy through the Windows ACL restricted-token runner (the win32 chain of `dsh-sandbox-local` → `@deepseek-ai/dsh-sandbox-windows-acl`), the permission switcher and the approval service run unchanged, and `fs-sandbox` keeps fencing `ctx.fs` writes — mounting `dsh-fs-local` alongside it would double-register `ctx.fs` and fail the load. A Windows host that prefers the unconfined local pwsh executor or full access overrides these rows through its profile or home `cordis.patch.yml` (the bash-restore recipe must be complete: disable `pwsh-sandbox`/`tool-pwsh` AND re-enable `bash-sandbox`/`tool-bash` — both executor families register the same `bash` service, so an incomplete recipe fails loud at load). POSIX hosts see the pwsh rows disabled. @@ -19,5 +19,4 @@ None directly; each inserted row's package owns its effect. ## Known Limitations and Deferred Work - **A patch replaces whole row configs** — profile overrides must restate every field a row keeps; there is no deep-merge layer. -- **Claude's SDK platform CLI remains in the Profile install closure** — the base bundle depends on the Claude provider, whose production path resolves the host `claude`; removing the SDK's unused optional payload is deferred to the product installation-closure follow-up. - **The Windows temp grant is a private per-session subdirectory** — `workspace-write` confines writes to the workspace plus the session's own temp subdirectory (`\dsh-`, TMP/TEMP rewritten for confined children); `read-only` grants nothing. See `@deepseek-ai/dsh-sandbox-windows-acl`. diff --git a/packages/bundle/base/README.zh.md b/packages/bundle/base/README.zh.md index bcf4463587..ad70fc1603 100644 --- a/packages/bundle/base/README.zh.md +++ b/packages/bundle/base/README.zh.md @@ -2,7 +2,7 @@ [English](README.md) | 中文 -以 profile 组合包形式交付的共享 dsh 核心:[`cordis.patch.yml`](cordis.patch.yml) 在空的 profile 根之上插入全部基础插件行——模型适配器、共享的 [`agent-default-model`](../../core/agent-default-model/README.md) 选择、工具、持久化、策略、settings/credentials、遥测与宿主级 subagent provider——作为每个 profile 的 `dsh.profile.bundles` 列表中的第一层。Codex 与 Claude Code provider 以休眠状态加载;Agent Preset 分别决定自己的 agent 是否贡献任一面向模型的委派工具。后续的组合包层(例如 [`dsh-web-app`](../web-app/README.md))和用户 profile 的 `cordis.patch.yml` 按 id 覆盖这些行;patch 会替换目标行的整个 `config`,因此模式专属的值放在各模式组合包中,而不是这里。该包没有运行时 API;profile 组合器通过 manifest(元数据清单)的 `dsh.bundle.patch` 字段解析 patch,绝不通过代码。 +以 profile 组合包形式交付的共享 dsh 核心:[`cordis.patch.yml`](cordis.patch.yml) 在空的 profile 根之上插入全部基础插件行——模型适配器、共享的 [`agent-default-model`](../../core/agent-default-model/README.md) 选择、工具、持久化、策略、settings/credentials、遥测与宿主级 subagent provider——作为每个 profile 的 `dsh.profile.bundles` 列表中的第一层。这个 bundle 既不依赖也不挂载可选的 Codex 与 Claude Code provider;选择产品集成的 Profile 会安装目标 provider 并在 host plane(宿主平面)挂载一次,Agent Preset 则决定自己的 agent 是否获得对应的面向模型委派工具。后续的组合包层(例如 [`dsh-web-app`](../web-app/README.md))和用户 profile 的 `cordis.patch.yml` 按 id 覆盖这些行;patch 会替换目标行的整个 `config`,因此模式专属的值放在各模式组合包中,而不是这里。该包没有运行时 API;profile 组合器通过 manifest(元数据清单)的 `dsh.bundle.patch` 字段解析 patch,绝不通过代码。 patch 在自身上按平台门控两个 shell 栈:`bash-sandbox`/`tool-bash` 携带 `disabled: !!js process.platform === 'win32'`(bash 没有 Windows runner),它们的孪生行 `pwsh-sandbox`/`tool-pwsh` 以取反的表达式仅在 win32 挂载——同一份 patch 文件,每个宿主恰好挂载一个 shell 栈。权限面与 POSIX 完全一致:`sandbox`/`sandbox-policy` 通过 Windows ACL 受限令牌 runner(`dsh-sandbox-local` 的 win32 链 → `@deepseek-ai/dsh-sandbox-windows-acl`)执行文件效果策略,权限切换器与 approval 服务原样运行,`fs-sandbox` 继续围栏 `ctx.fs` 写入——在其旁再挂载 `dsh-fs-local` 会重复注册 `ctx.fs` 并在加载时失败。偏好不受沙盒约束的本地 pwsh 执行器或完整访问的 Windows 主机通过其 profile 或 home 的 `cordis.patch.yml` 覆盖这些行(bash 恢复配方必须完整:禁用 `pwsh-sandbox`/`tool-pwsh` 并重新启用 `bash-sandbox`/`tool-bash`——两个执行器家族注册同一个 `bash` 服务,配方不完整会在加载时直接报错)。POSIX 主机看到的是被禁用的 pwsh 行。 @@ -19,5 +19,4 @@ patch 在自身上按平台门控两个 shell 栈:`bash-sandbox`/`tool-bash` ## 已知限制与暂缓事项 - **patch 会替换整行 `config`**:profile 覆盖必须重述该行需要保留的每个字段;不存在深度合并层。 -- **Claude SDK 的平台 CLI(命令行界面)仍在 Profile 安装闭包中**:base 组合包依赖 Claude 提供方,其生产路径解析宿主提供的 `claude`;移除 SDK 中未使用的可选载荷,推迟到产品安装闭包后续项处理。 - **Windows 的临时目录授权是按会话的私有子目录**——`workspace-write` 把写入限制在工作区与会话自己的 temp 子目录(`\dsh-`,受限子进程的 TMP/TEMP 被改写);`read-only` 不授予任何临时目录写入权限。见 `@deepseek-ai/dsh-sandbox-windows-acl`。 diff --git a/packages/bundle/base/cordis.patch.yml b/packages/bundle/base/cordis.patch.yml index 2f5b5c6a12..e9567d9206 100644 --- a/packages/bundle/base/cordis.patch.yml +++ b/packages/bundle/base/cordis.patch.yml @@ -106,13 +106,19 @@ - id: attachment-local name: '@deepseek-ai/dsh-attachment-local' - # Raw configs can supply a process-local path or disable this shared session - # capability. The neutral default is process-local and opens only when used. + # Full-text session search is opt-in. `openAt: never` keeps + # ctx.sessionQuery mounted — exact reads, titles, and lineage traces + # (session export, subagent-fork Workspace inheritance) stay available — + # while search calls fail with SESSION_QUERY_SEARCH_DISABLED and SQLite is + # never opened; the Web sidebar search matches titles and workspace names + # only. Deployments enabling content search override `openAt` to + # `first-search` or `startup` in a later patch layer (profile + # cordis.patch.yml or a --patch overlay), typically with a durable `path`. - id: session-query-sqlite name: '@deepseek-ai/dsh-session-query-sqlite' config: path: ':memory:' - openAt: first-search + openAt: never # Shared projection registry: subagent catalog identity (mode/label) folds # through its registered units, so the `list_agents` surface below fails @@ -296,15 +302,6 @@ config: providerName: fork - # Product providers stay on the host plane because the registry is a - # process singleton. Agent presets decide whether their own model sees the - # matching delegation tools; loading either provider starts no product. - - id: subagent-codex - name: '@deepseek-ai/dsh-subagent-codex' - - - id: subagent-claude-code - name: '@deepseek-ai/dsh-subagent-claude-code' - # Continuable background children are selected per delegation tool. The # separately loaded follow-up tool registers the one global `send_message`. - id: tool-subagent-control diff --git a/packages/bundle/base/package.json b/packages/bundle/base/package.json index 392a6f63d5..9351c491a9 100644 --- a/packages/bundle/base/package.json +++ b/packages/bundle/base/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-base", "description": "The shared dsh core as a profile bundle: every profile's first patch layer, inserting the base plugin rows over the empty profile root", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -32,7 +32,7 @@ "cordis.patch.yml", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "dsh": { "bundle": { "patch": "./cordis.patch.yml" @@ -85,8 +85,6 @@ "@deepseek-ai/dsh-spill-local": "workspace:^", "@deepseek-ai/dsh-spill-policy": "workspace:^", "@deepseek-ai/dsh-subagent": "workspace:^", - "@deepseek-ai/dsh-subagent-claude-code": "workspace:^", - "@deepseek-ai/dsh-subagent-codex": "workspace:^", "@deepseek-ai/dsh-subagent-fork-in-process": "workspace:^", "@deepseek-ai/dsh-subagent-spawn-in-process": "workspace:^", "@deepseek-ai/dsh-subprocess-local": "workspace:^", diff --git a/packages/bundle/base/tests/base.spec.ts b/packages/bundle/base/tests/base.spec.ts index 8f904ac60b..e70bc0ff74 100644 --- a/packages/bundle/base/tests/base.spec.ts +++ b/packages/bundle/base/tests/base.spec.ts @@ -35,12 +35,10 @@ describe('dsh-base bundle', () => { expect(rows.find(row => row.id === 'session-telemetry-otel')?.config?.['mode']).toEqual({ __jsExpr: "process.env.DSH_TELEMETRY_MODE || 'DISABLED'", }) - expect(rows.filter(row => row.id === 'subagent-codex')).toHaveLength(1) - expect(rows.filter(row => row.id === 'subagent-claude-code')).toHaveLength(1) - expect(manifest.dependencies).toMatchObject({ - '@deepseek-ai/dsh-subagent-codex': 'workspace:^', - '@deepseek-ai/dsh-subagent-claude-code': 'workspace:^', - }) + expect(rows.filter(row => row.id === 'subagent-codex')).toHaveLength(0) + expect(rows.filter(row => row.id === 'subagent-claude-code')).toHaveLength(0) + expect(manifest.dependencies).not.toHaveProperty('@deepseek-ai/dsh-subagent-codex') + expect(manifest.dependencies).not.toHaveProperty('@deepseek-ai/dsh-subagent-claude-code') }) it('gates each shell stack by platform with a symmetric disabled expression', () => { diff --git a/packages/bundle/headless/package.json b/packages/bundle/headless/package.json index 652c5802da..886fdc593e 100644 --- a/packages/bundle/headless/package.json +++ b/packages/bundle/headless/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-headless", "description": "The dsh one-shot bundle: a direct core Agent/Session runner over dsh-base with no Host, HTTP, or browser layer", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -37,7 +37,7 @@ "cordis.patch.yml", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "dsh": { "bundle": { "patch": "./cordis.patch.yml" diff --git a/packages/bundle/web-app/README.i18n.yaml b/packages/bundle/web-app/README.i18n.yaml index 45da05fcf3..220b4d78ff 100644 --- a/packages/bundle/web-app/README.i18n.yaml +++ b/packages/bundle/web-app/README.i18n.yaml @@ -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/bundle/web-app/README.md -README.md: 3f7fbe7bbbeba2ee753ab2dfa8c945e798dd6a02 -README.zh.md: 357ca9946ed7fef1bf4c691c6666156bb293b5e0 +README.md: 90d1566b5a7a25f6a827079c4a8ab776e05cc7a3 +README.zh.md: b7156bcab66b53964bb2f0e1c87d9e9a806e3f75 diff --git a/packages/bundle/web-app/README.md b/packages/bundle/web-app/README.md index 3f7fbe7bbb..90d1566b5a 100644 --- a/packages/bundle/web-app/README.md +++ b/packages/bundle/web-app/README.md @@ -2,7 +2,7 @@ English | [中文](README.zh.md) -The dsh browser-surface bundle. [`cordis.patch.yml`](cordis.patch.yml) rides over [`dsh-base`](../base/README.md): it sets the coding persona, inserts the Web host rows (webserver, API gateway, workspace, projection cache, storage) and the browser plugin roster, the always-on client-plugin reload chain ([`dsh-client-hmr`](../../client/hmr/README.md), idle until a rebuild watcher rewrites client bundles), and mounts this package's `web-runtime` glue plugin (config `{printUrl, surfaceContext, trustedHosts}`). That plugin resolves the built frontend dist through `@deepseek-ai/dsh-web-frontend`'s exports, samples bind-dependent LAN trust once, provides it as `webRuntime` to the browser-trust fence and client roster, mounts the [`frontend-static`](../../host/frontend-static/README.md) fallback owner, registers the harness-source and web-surface prompt sections plus the bash-visible `DSH_WEB_URL` runtime variable when `surfaceContext` is true, and prints the `dsh web:` URL line when `printUrl` is true, after its Loader tree settles so a sibling failure cannot announce a dead app. This bundle also owns the app command line: the ordinary `web-startup` provider ([`src/startup.ts`](src/startup.ts)) injects `ctx.cmdlineArgs` ([`dsh-cmdline`](../../boot/cmdline/README.md)), parses `--host`, `--port`, repeatable `--trusted-host`, and the app's `--help`, then provides `webStartup`. Flag-configured rows inject that service and read it directly from lazy config, so nothing binds a port before argument resolution and `dsh --profile web --help` starts no server. [`dsh-headless`](../headless/README.md) is a sibling surface over the same base and does not mount this bundle. +The dsh browser-surface bundle. [`cordis.patch.yml`](cordis.patch.yml) rides over [`dsh-base`](../base/README.md): it sets the coding persona, inserts the Web host rows (webserver, API gateway, workspace, projection cache, storage) and the browser plugin roster, the always-on client-plugin reload chain ([`dsh-client-hmr`](../../client/hmr/README.md), idle until a rebuild watcher rewrites client bundles), and mounts this package's `web-runtime` glue plugin (config `{printUrl, surfaceContext, trustedHosts}`). That plugin resolves the built frontend dist through `@deepseek-ai/dsh-web-frontend`'s exports, samples bind-dependent LAN trust once, provides it as `webRuntime` to the browser-trust fence and client roster, mounts the [`frontend-static`](../../host/frontend-static/README.md) fallback owner, registers the harness-source and web-surface prompt sections plus the bash-visible `DSH_WEB_URL` runtime variable when `surfaceContext` is true, and prints the `dsh web:` URL line when `printUrl` is true, after its Loader tree settles so a sibling failure cannot announce a dead app. This bundle also owns the app command line: the ordinary `web-startup` provider ([`src/startup.ts`](src/startup.ts)) injects `ctx.cmdlineArgs` ([`dsh-cmdline`](../../boot/cmdline/README.md)), parses `--host`, `--port`, repeatable `--trusted-host`, and the app's `--help`, then provides `webStartup`. It rejects `--host 0.0.0.0` before publishing that service because the CLI intentionally does not support all-interfaces binding yet. Flag-configured rows inject the service and read it directly from lazy config, so nothing binds a port before argument resolution and `dsh --profile web --help` starts no server. [`dsh-headless`](../headless/README.md) is a sibling surface over the same base and does not mount this bundle. ## Model Experience diff --git a/packages/bundle/web-app/README.zh.md b/packages/bundle/web-app/README.zh.md index 357ca9946e..b7156bcab6 100644 --- a/packages/bundle/web-app/README.zh.md +++ b/packages/bundle/web-app/README.zh.md @@ -2,7 +2,7 @@ [English](README.md) | 中文 -dsh 浏览器表层组合包。[`cordis.patch.yml`](cordis.patch.yml) 叠加在 [`dsh-base`](../base/README.md) 之上:设置 coding persona,插入 Web 宿主行(webserver、API 网关、workspace、投影缓存、存储)、浏览器插件名录与始终挂载的客户端插件重载链([`dsh-client-hmr`](../../client/hmr/README.md),在重建 watcher 改写客户端 bundle 之前保持空闲),并挂载本包的 `web-runtime` 粘合插件(配置为 `{printUrl, surfaceContext, trustedHosts}`)。该插件通过 `@deepseek-ai/dsh-web-frontend` 的 exports 解析已构建的前端 dist,只采样一次依赖 bind 的 LAN 信任信息并将其作为 `webRuntime` 提供给浏览器信任栅栏和客户端名录,挂载 [`frontend-static`](../../host/frontend-static/README.md) 回退席位所有者,在 `surfaceContext` 为 true 时注册 Harness 源码与 Web 表层提示词段落,以及 bash 可见的 `DSH_WEB_URL` 运行时变量,并在 `printUrl` 为 true 时等自身的 Loader 配置树结算后再打印 `dsh web:` URL 行,避免兄弟行失败时公告一个已失效的应用。本组合包还持有应用命令行:普通 `web-startup` 提供方([`src/startup.ts`](src/startup.ts))注入 `ctx.cmdlineArgs`([`dsh-cmdline`](../../boot/cmdline/README.md)),解析 `--host`、`--port`、可重复的 `--trusted-host` 以及应用自己的 `--help`,再提供 `webStartup`。由 flag 配置的行会注入该服务,并在惰性配置中直接读取它,因此参数解析完成前不会有任何东西绑定端口,`dsh --profile web --help` 也不会启动服务器。[`dsh-headless`](../headless/README.md) 是同一 base 之上的同级表层,不挂载本组合包。 +dsh 浏览器表层组合包。[`cordis.patch.yml`](cordis.patch.yml) 叠加在 [`dsh-base`](../base/README.md) 之上:设置 coding persona,插入 Web 宿主行(webserver、API 网关、workspace、投影缓存、存储)、浏览器插件名录与始终挂载的客户端插件重载链([`dsh-client-hmr`](../../client/hmr/README.md),在重建 watcher 改写客户端 bundle 之前保持空闲),并挂载本包的 `web-runtime` 粘合插件(配置为 `{printUrl, surfaceContext, trustedHosts}`)。该插件通过 `@deepseek-ai/dsh-web-frontend` 的 exports 解析已构建的前端 dist,只采样一次依赖 bind 的 LAN 信任信息并将其作为 `webRuntime` 提供给浏览器信任栅栏和客户端名录,挂载 [`frontend-static`](../../host/frontend-static/README.md) 回退席位所有者,在 `surfaceContext` 为 true 时注册 Harness 源码与 Web 表层提示词段落,以及 bash 可见的 `DSH_WEB_URL` 运行时变量,并在 `printUrl` 为 true 时等自身的 Loader 配置树结算后再打印 `dsh web:` URL 行,避免兄弟行失败时公告一个已失效的应用。本组合包还持有应用命令行:普通 `web-startup` 提供方([`src/startup.ts`](src/startup.ts))注入 `ctx.cmdlineArgs`([`dsh-cmdline`](../../boot/cmdline/README.md)),解析 `--host`、`--port`、可重复的 `--trusted-host` 以及应用自己的 `--help`,再提供 `webStartup`。它会在发布该服务前拒绝 `--host 0.0.0.0`,因为 CLI 目前有意不支持绑定所有网络接口。由 flag 配置的行会注入该服务,并在惰性配置中直接读取它,因此参数解析完成前不会有任何东西绑定端口,`dsh --profile web --help` 也不会启动服务器。[`dsh-headless`](../headless/README.md) 是同一 base 之上的同级表层,不挂载本组合包。 ## 模型体验 diff --git a/packages/bundle/web-app/cordis.patch.yml b/packages/bundle/web-app/cordis.patch.yml index d8922fdfd1..b06e63b54f 100644 --- a/packages/bundle/web-app/cordis.patch.yml +++ b/packages/bundle/web-app/cordis.patch.yml @@ -22,14 +22,15 @@ - id: hmr disabled: true -# Web content search runs on an ephemeral in-memory index. The service -# activates at boot, while first-search defers the node:sqlite import and -# in-memory handle so Node 22 startup stays quiet until content search -# actually uses SQLite. That search then reconciles this boot's sources. +# Full-text session search is opt-in (the base row's `openAt: never`). This +# restatement keeps the Web values on one ephemeral in-memory index; a +# deployment enabling content search overrides `openAt` to `first-search` in a +# later patch layer, which defers the node:sqlite import and in-memory handle +# to the first search so Node 22 startup stays quiet. - id: session-query-sqlite config: path: ':memory:' - openAt: first-search + openAt: never - id: tools config: diff --git a/packages/bundle/web-app/package.json b/packages/bundle/web-app/package.json index 227f0b5dfb..13ca525731 100644 --- a/packages/bundle/web-app/package.json +++ b/packages/bundle/web-app/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-web-app", "description": "The dsh browser-surface bundle: the web patch layer over dsh-base plus the runtime glue plugin (frontend dist serving, web-surface prompt, bash runtime variables, URL line)", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -37,7 +37,7 @@ "cordis.patch.yml", "lib/types/**/*.d.ts" ], - "license": "BSD-3-Clause", + "license": "MIT", "dsh": { "bundle": { "patch": "./cordis.patch.yml" diff --git a/packages/bundle/web-app/src/startup.ts b/packages/bundle/web-app/src/startup.ts index 2aaf89a742..af6997cff7 100644 --- a/packages/bundle/web-app/src/startup.ts +++ b/packages/bundle/web-app/src/startup.ts @@ -45,28 +45,30 @@ function webCommand(): Command { .name('dsh --profile web') .description('Serve the DeepSeek Harness browser UI.') .helpOption('-h, --help', 'show this help') - .option('--host ', 'bind host; pass 0.0.0.0 to reach it from another machine') + .option('--host ', 'bind host') .option('--port ', 'listen port; pass 0 to let the OS pick a free one') .option('--trusted-host ', 'extra authority the /api browser-trust fence accepts (host or host:port; repeatable)') .addHelpText('after', ` Examples: dsh --profile web serve on the composed host and port dsh --profile web --port 8080 serve on another port - dsh --profile web --host 0.0.0.0 reach it from another machine on the LAN `) } /** * Parse and provide the Web invocation as an ordinary Cordis service. The - * command's action publishes the flags this invocation named; a non-numeric - * `--port` is a usage error, so on rejection (and on `--help`) nothing is - * provided. + * command's action publishes the flags this invocation named; `--host 0.0.0.0` + * or a non-numeric `--port` is a usage error, so on rejection (and on `--help`) + * nothing is provided. * @param ctx - plugin context carrying the command line. */ export function apply(ctx: Context): void { const program = webCommand() program.action(() => { const options = program.opts() + if (options.host === '0.0.0.0') { + program.error('error: --host 0.0.0.0 is intentionally not supported yet for safety: it would expose remote code execution to the network; use 127.0.0.1 instead') + } if (options.port !== undefined && !/^\d+$/.test(options.port)) { program.error(`error: --port must be a number, got ${JSON.stringify(options.port)}`) } diff --git a/packages/bundle/web-app/tests/startup.spec.ts b/packages/bundle/web-app/tests/startup.spec.ts index a00405378a..26e347a503 100644 --- a/packages/bundle/web-app/tests/startup.spec.ts +++ b/packages/bundle/web-app/tests/startup.spec.ts @@ -88,13 +88,13 @@ export const apply = ctx => globalThis.__webStartupApply(ctx) describe('web command-line provider', () => { it('publishes each flag and releases direct service expressions', async () => { const { values, observed } = await bootProvider([ - '--host', '0.0.0.0', + '--host', '127.0.0.1', '--port', '8080', '--trusted-host', 'lab.internal', 'lab-2.internal', '--trusted-host', '10.0.0.9', ]) expect(values).toEqual({ - host: '0.0.0.0', + host: '127.0.0.1', port: 8080, trustedHosts: ['lab.internal', 'lab-2.internal', '10.0.0.9'], }) @@ -128,4 +128,12 @@ describe('web command-line provider', () => { expect(observed.readerConfig).toBeUndefined() expect(observed.exits).toEqual([1]) }) + + it('rejects the intentionally unsupported all-interfaces host before the consumer activates', async () => { + const { values, observed } = await bootProvider(['--host', '0.0.0.0']) + expect(observed.out).toContain('--host 0.0.0.0 is intentionally not supported yet for safety: it would expose remote code execution to the network; use 127.0.0.1 instead') + expect(values).toBeUndefined() + expect(observed.readerConfig).toBeUndefined() + expect(observed.exits).toEqual([1]) + }) }) diff --git a/packages/client/connection/README.i18n.yaml b/packages/client/connection/README.i18n.yaml index 38c31ad05c..4745644cc5 100644 --- a/packages/client/connection/README.i18n.yaml +++ b/packages/client/connection/README.i18n.yaml @@ -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/client/connection/README.md -README.md: 3315552dd0400697d5a96639598c5f5bb2bb4f5b -README.zh.md: 0dc251f1e5410bd0d74ef450c6d8df3dc9cdab81 +README.md: f0a707cc5f3a962c7852f7323c727d0a39a57b10 +README.zh.md: b529eebf9af93e36b6b92c19964678b7f5a04ea1 diff --git a/packages/client/connection/README.md b/packages/client/connection/README.md index 3315552dd0..f0a707cc5f 100644 --- a/packages/client/connection/README.md +++ b/packages/client/connection/README.md @@ -6,7 +6,7 @@ Wire consumer layer: the client plugin's apply mounts `ctx.connection` (shared a ## /api browser-trust fence -The node half guards every entry under `/api` before bridging or upgrading (`src/api-request-trust.ts`). Every request — browser-marked or not — must present a `Host` that is a loopback authority or matches a `trustedHosts` entry: exact on `host:port` entries, any port on port-less entries, both sides compared through WHATWG normalization (DNS-rebinding defense). There is deliberately no shortcut for unmarked HTTP requests: over plain HTTP a browser attaches neither `Origin` nor Fetch-Metadata to image and navigation reads, so an unmarked request may still be a rebound browser read with a readable response, and Host is the one header rebinding cannot forge; a browser WebSocket handshake carries `Origin` and passes the same comparison. Non-browser clients pass the same fence via loopback, the CLI-derived LAN IP literals, or a declared authority. When markers are present, an attached `Origin` must equal the Host authority, and an explicit `sec-fetch-site: cross-site` marker is refused. A `trustedHosts` entry that is not a bare, canonical `host[:port]` authority — one WHATWG parsing reads back exactly as written — fails the plugin load loudly: parsing would otherwise quietly authorize the hostname inside `harness.internal/path`, or broaden a dangling-colon or zero-padded port to an any-port grant. HTTP failures answer plain 403 before any RPC dispatch; upgrade failures reject the handshake before any event stream starts. A non-loopback (`--host 0.0.0.0`) deployment therefore needs its serving authorities trusted: the dsh CLI derives the machine's LAN IP literals itself and its `--trusted-host` flag declares named ones, so `trustedHosts` in cordis.yml is for compositions the CLI does not boot. The fence is a reachability policy, not authentication; the Web carrier provides no authentication layer. Decision record: [the api browser-trust boundary Agent Note](../../../.agents/notes/implemented/architecture/2026-07-28-api-browser-trust-boundary.md). +The node half guards every entry under `/api` before bridging or upgrading (`src/api-request-trust.ts`). Every request — browser-marked or not — must present a `Host` that is a loopback authority or matches a `trustedHosts` entry: exact on `host:port` entries, any port on port-less entries, both sides compared through WHATWG normalization (DNS-rebinding defense). There is deliberately no shortcut for unmarked HTTP requests: over plain HTTP a browser attaches neither `Origin` nor Fetch-Metadata to image and navigation reads, so an unmarked request may still be a rebound browser read with a readable response, and Host is the one header rebinding cannot forge; a browser WebSocket handshake carries `Origin` and passes the same comparison. Non-browser clients pass the same fence via loopback, deployment-derived LAN IP literals, or a declared authority. When markers are present, an attached `Origin` must equal the Host authority, and an explicit `sec-fetch-site: cross-site` marker is refused. A `trustedHosts` entry that is not a bare, canonical `host[:port]` authority — one WHATWG parsing reads back exactly as written — fails the plugin load loudly: parsing would otherwise quietly authorize the hostname inside `harness.internal/path`, or broaden a dangling-colon or zero-padded port to an any-port grant. HTTP failures answer plain 403 before any RPC dispatch; upgrade failures reject the handshake before any event stream starts. Non-loopback compositions must trust their serving authorities explicitly: the Web runtime derives LAN IP literals from an all-interfaces server config, while `trustedHosts` in cordis.yml and the CLI's `--trusted-host` flag declare named authorities. `dsh web --host 0.0.0.0` is intentionally unsupported until remote access has an authentication layer. The fence is a reachability policy, not authentication; the Web carrier provides no authentication layer. Decision record: [the api browser-trust boundary Agent Note](../../../.agents/notes/implemented/architecture/2026-07-28-api-browser-trust-boundary.md). ## `/api` WebSocket downlinks diff --git a/packages/client/connection/README.zh.md b/packages/client/connection/README.zh.md index 0dc251f1e5..b529eebf9a 100644 --- a/packages/client/connection/README.zh.md +++ b/packages/client/connection/README.zh.md @@ -6,7 +6,7 @@ ## /api 浏览器信任栅栏 -node 半侧在桥接或 upgrade 前守卫 `/api` 下的每个入口(`src/api-request-trust.ts`)。每个请求——无论是否带浏览器标记——`Host` 都必须是回环地址权威,或与某个 `trustedHosts` 条目匹配:带端口的 `host:port` 条目精确匹配,不带端口的条目匹配任意端口,两侧均经 WHATWG 归一化后比较(DNS rebinding 防御)。刻意不为无浏览器标记的 HTTP 请求开捷径:明文 HTTP 下浏览器的图片与导航读取既不带 `Origin` 也不带 Fetch-Metadata,因此无标记请求仍可能是被重绑页面发起的、响应可被读走的读取,而 Host 是重绑唯一伪造不了的请求头;WebSocket 浏览器握手会带 `Origin` 并通过同一道比较。非浏览器客户端经由回环地址、CLI(命令行界面)推导的 LAN IP 字面量或已声明的权威通过同一道栅栏。当标记存在时,如附带 `Origin`,则它必须与 Host 权威完全一致;显式的 `sec-fetch-site: cross-site` 标记一律拒绝。不是纯的、规范形 `host[:port]` 权威的 `trustedHosts` 条目——即 WHATWG 解析读回后与原文不完全一致的——会让插件加载明确报错:否则解析会悄悄授权 `harness.internal/path` 这类笔误里的 hostname,或把悬空冒号、补零端口放大成任意端口授权。HTTP 失败在任何 RPC 分发之前以纯 403 应答,upgrade 失败在启动任何事件流前拒绝握手。因此非回环(`--host 0.0.0.0`)部署需要让自己的服务权威被信任:dsh CLI 会自行推导本机的 LAN IP 字面量,其 `--trusted-host` flag 用于声明具名权威,所以 cordis.yml 中的 `trustedHosts` 面向 CLI 不参与引导的组合。这道栅栏是可达性策略,而不是认证;Web 载体不提供认证层。决策记录:[api 浏览器信任边界 Agent Note](../../../.agents/notes/implemented/architecture/2026-07-28-api-browser-trust-boundary.md)。 +node 半侧在桥接或 upgrade 前守卫 `/api` 下的每个入口(`src/api-request-trust.ts`)。每个请求——无论是否带浏览器标记——`Host` 都必须是回环地址权威,或与某个 `trustedHosts` 条目匹配:带端口的 `host:port` 条目精确匹配,不带端口的条目匹配任意端口,两侧均经 WHATWG 归一化后比较(DNS rebinding 防御)。刻意不为无浏览器标记的 HTTP 请求开捷径:明文 HTTP 下浏览器的图片与导航读取既不带 `Origin` 也不带 Fetch-Metadata,因此无标记请求仍可能是被重绑页面发起的、响应可被读走的读取,而 Host 是重绑唯一伪造不了的请求头;WebSocket 浏览器握手会带 `Origin` 并通过同一道比较。非浏览器客户端经由回环地址、部署推导的 LAN IP 字面量或已声明的权威通过同一道栅栏。当标记存在时,如附带 `Origin`,则它必须与 Host 权威完全一致;显式的 `sec-fetch-site: cross-site` 标记一律拒绝。不是纯的、规范形 `host[:port]` 权威的 `trustedHosts` 条目——即 WHATWG 解析读回后与原文不完全一致的——会让插件加载明确报错:否则解析会悄悄授权 `harness.internal/path` 这类笔误里的 hostname,或把悬空冒号、补零端口放大成任意端口授权。HTTP 失败在任何 RPC 分发之前以纯 403 应答,upgrade 失败在启动任何事件流前拒绝握手。非回环组合必须显式信任其服务权威:Web 运行时从全接口服务器配置推导 LAN IP 字面量,cordis.yml 中的 `trustedHosts` 与 CLI(命令行界面)的 `--trusted-host` flag 则声明具名权威。`dsh web --host 0.0.0.0` 在远程访问具备认证层之前有意不受支持。这道栅栏是可达性策略,而不是认证;Web 载体不提供认证层。决策记录:[api 浏览器信任边界 Agent Note](../../../.agents/notes/implemented/architecture/2026-07-28-api-browser-trust-boundary.md)。 ## `/api` WebSocket 下行 diff --git a/packages/client/connection/package.json b/packages/client/connection/package.json index 537e3817cd..00d4e6da21 100644 --- a/packages/client/connection/package.json +++ b/packages/client/connection/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-client-connection", "description": "Wire consumer layer: HTTP-up/WebSocket-down client, ConnectionController dual streams with reconnect, and fixture api", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -36,7 +36,7 @@ "immediately": true } }, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "@deepseek-ai/dsh-attachment": "workspace:^", "@deepseek-ai/dsh-host-apiproxy": "workspace:^", diff --git a/packages/client/connection/src/api-request-trust.ts b/packages/client/connection/src/api-request-trust.ts index 141092c63b..ea8914ccc6 100644 --- a/packages/client/connection/src/api-request-trust.ts +++ b/packages/client/connection/src/api-request-trust.ts @@ -7,8 +7,8 @@ * nor Fetch-Metadata to reads (images and navigations — those * headers go only to trustworthy destinations), so an unmarked request may * still be a rebound browser read and Host is the one header rebinding cannot - * forge. Non-browser and remote clients pass the same fence via loopback, the - * CLI-derived LAN IP literals, or a declared `trustedHosts` authority. + * forge. Non-browser and remote clients pass the same fence via loopback, + * deployment-derived LAN IP literals, or a declared `trustedHosts` authority. * Network reachability and authentication stay out of scope: binding policy * belongs to the webserver config, and this fence is not an auth layer. */ diff --git a/packages/client/connection/tests/node-half.host.spec.ts b/packages/client/connection/tests/node-half.host.spec.ts index 6c8b42b5ab..0b30ce6520 100644 --- a/packages/client/connection/tests/node-half.host.spec.ts +++ b/packages/client/connection/tests/node-half.host.spec.ts @@ -199,8 +199,8 @@ describe('connection node half', () => { const loopback = fakeResponse() await routes[0]!.handler(fakeRequest({ host: '127.0.0.1:3080' }), loopback.response) expect(loopback.state.status).toBe(404) - // LAN authority declared as a port-less IP literal — the shape the CLI - // derives for `--host 0.0.0.0` — passes markerless curl on any port. + // An all-interfaces composition derives port-less LAN IP literals, which + // pass markerless curl on any port. const lan = fakeResponse() await routes[0]!.handler(fakeRequest({ host: '192.168.1.5:3080' }), lan.response) expect(lan.state.status).toBe(404) diff --git a/packages/client/hmr/package.json b/packages/client/hmr/package.json index 4190458443..f1ab0c4044 100644 --- a/packages/client/hmr/package.json +++ b/packages/client/hmr/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-client-hmr", "description": "Dev-only hot-reload driver for script-loaded client entries: SSE rebuilt frames → invalidate/prefetch → fiber swap through the vendored Loader entry", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -36,7 +36,7 @@ "immediately": true } }, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "workspace:^" }, diff --git a/packages/client/locale/package.json b/packages/client/locale/package.json index 4aa1561131..0184f72d18 100644 --- a/packages/client/locale/package.json +++ b/packages/client/locale/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-client-locale", "description": "Locale plugin: Host-backed zh/en preference, browser-derived fallback, locale snapshots, and typed namespace dictionaries", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -41,7 +41,7 @@ "immediately": true } }, - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "workspace:^", "@deepseek-ai/dsh-api-remotes": "workspace:^", diff --git a/packages/client/modules/package.json b/packages/client/modules/package.json index a18247368f..dd45276a7a 100644 --- a/packages/client/modules/package.json +++ b/packages/client/modules/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-client-modules", "description": "Client module system, dual-face: node half composes the __DSH_BOOT__ entry graph (incremental dsh.client scan, bundle route, index tap, webPlugins service); browser half is the lazy-CJS module table the vendored cordis Loader consumes as its internal seam", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -40,7 +40,7 @@ "bundle": "tsdown", "watch": "tsdown --watch" }, - "license": "BSD-3-Clause", + "license": "MIT", "devDependencies": { "@deepseek-ai/cordis-plugin-loader": "workspace:^", "@deepseek-ai/dsh-host-webserver": "workspace:^", diff --git a/packages/client/runtime/package.json b/packages/client/runtime/package.json index 36aeaa4bf2..1da3ac6428 100644 --- a/packages/client/runtime/package.json +++ b/packages/client/runtime/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-client-runtime", "description": "Client core services: SlotRegistry, SessionRuntime (scope tree + object layer)", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -40,7 +40,7 @@ "immediately": true } }, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "@deepseek-ai/dsh-agent": "workspace:^", "@deepseek-ai/dsh-attachment": "workspace:^", diff --git a/packages/client/schema-form/package.json b/packages/client/schema-form/package.json index fca815aae0..e8e3a0228a 100644 --- a/packages/client/schema-form/package.json +++ b/packages/client/schema-form/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-client-schema-form", "description": "Schema/draft model layer for settings editors: rehydrates a serialized schemastery schema, validates drafts, and edits them immutably by path", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -25,7 +25,7 @@ "./src/*": "./src/*", "./package.json": "./package.json" }, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "workspace:^" }, diff --git a/packages/client/ui-agent-preset/package.json b/packages/client/ui-agent-preset/package.json index 418e6642e7..f705158d1e 100644 --- a/packages/client/ui-agent-preset/package.json +++ b/packages/client/ui-agent-preset/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-client-ui-agent-preset", "description": "Agent-preset surfaces: the default for later sessions, this session's seat, and the composition editor", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -46,7 +46,7 @@ "bundle": "tsdown", "watch": "tsdown --watch" }, - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "workspace:^", "@deepseek-ai/dsh-api-remotes": "workspace:^", diff --git a/packages/client/ui-agent-preset/src/client/locales.ts b/packages/client/ui-agent-preset/src/client/locales.ts index 54acc298a1..de19803a29 100644 --- a/packages/client/ui-agent-preset/src/client/locales.ts +++ b/packages/client/ui-agent-preset/src/client/locales.ts @@ -37,7 +37,7 @@ export const en: Record = { presetStandardName: 'Standard mode', presetStandardDescription: 'Full coding agent with file editing, shell, file and web search, skills, planning, goals, subagents, and workflows.', - presetCodeName: 'Code mode', + presetCodeName: 'PTC mode', presetCodeDescription: 'All Standard mode capabilities, with tools exposed through the Code Mode SDK so the model can combine multi-step operations in one TypeScript program.', presetMinimalName: 'Minimal mode', diff --git a/packages/client/ui-agent-preset/src/client/settings-store.ts b/packages/client/ui-agent-preset/src/client/settings-store.ts index 4f4e26bdf8..9589d5c2bb 100644 --- a/packages/client/ui-agent-preset/src/client/settings-store.ts +++ b/packages/client/ui-agent-preset/src/client/settings-store.ts @@ -216,7 +216,7 @@ export class AgentPresetSettingsController { // The roster says what may be chosen; `settings.describe` says whether // this browser may write the choice down. A non-loopback browser reaches // neither method, so a refused describe leaves the row read-only rather - // than offering a control whose write answers `settings-not-exposed`. + // than offering a control whose write the Host would refuse. const described = await this.api.settings.describe({}) this.set({ status: 'ready', diff --git a/packages/client/ui-agent-preset/tests/settings-store.client.spec.ts b/packages/client/ui-agent-preset/tests/settings-store.client.spec.ts index 0a98138233..54fd600a60 100644 --- a/packages/client/ui-agent-preset/tests/settings-store.client.spec.ts +++ b/packages/client/ui-agent-preset/tests/settings-store.client.spec.ts @@ -67,8 +67,8 @@ describe('the agent-preset settings controller', () => { await controller.load() // `settings.describe` is loopback-only and reports a read-only provider; - // offering a control whose write answers `settings-not-exposed` would - // promise a switch the host refuses. + // offering a control whose write answers `settings-rejected` would promise + // a switch the host refuses. expect(controller.store.getSnapshot().writable).toBe(false) expect(controller.store.getSnapshot().currentValue).toBe('standard') }) diff --git a/packages/client/ui-attachment/package.json b/packages/client/ui-attachment/package.json index 837353dc5b..c257166e2a 100644 --- a/packages/client/ui-attachment/package.json +++ b/packages/client/ui-attachment/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-client-ui-attachment", "description": "Pure React attachment atoms for the dsh web UI: draft-image rail, message image gallery, and original-image lightbox (zero cordis)", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -25,7 +25,7 @@ "./src/*": "./src/*", "./package.json": "./package.json" }, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "@deepseek-ai/dsh-attachment": "workspace:^", "@deepseek-ai/dsh-client-ui-primitives": "workspace:^", diff --git a/packages/client/ui-commands/package.json b/packages/client/ui-commands/package.json index 9b55563f85..cf80e20f3f 100644 --- a/packages/client/ui-commands/package.json +++ b/packages/client/ui-commands/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-client-ui-commands", "description": "Client command surface: global directory cache, '/' source, three command UI kinds, popupSelect registry", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -45,7 +45,7 @@ "bundle": "tsdown", "watch": "tsdown --watch" }, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "clsx": "^2.0.0" }, diff --git a/packages/client/ui-conversation/README.i18n.yaml b/packages/client/ui-conversation/README.i18n.yaml index 954ba5d7af..6d866e05e7 100644 --- a/packages/client/ui-conversation/README.i18n.yaml +++ b/packages/client/ui-conversation/README.i18n.yaml @@ -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/client/ui-conversation/README.md -README.md: ecf463da619662fe158511079e7773ee3c627ac8 -README.zh.md: f8922b160cdc6feca94dea998163c25d803a5535 +README.md: d1a265b5789d9f1d9b5e630e0548ae5f619eebbf +README.zh.md: 3f303391d39bc040b4a6a5a2d1f6a34fe8891919 diff --git a/packages/client/ui-conversation/README.md b/packages/client/ui-conversation/README.md index ecf463da61..d1a265b578 100644 --- a/packages/client/ui-conversation/README.md +++ b/packages/client/ui-conversation/README.md @@ -6,7 +6,7 @@ Conversation domain: skeleton (header/tabs/composer/empty state), chat view (gro Compaction renders as one collapsed row at the checkpoint's flow position without replacing the transcript above it. Automatic compaction uses the context-compacted title. Every completed marker with a loaded `compaction/summary` event shows the replaced-item and estimated-token counts and discloses the summary on click. Manual `/compact` starts as a running `compact` row; on successful settlement its explicit summary-event reference folds that command into the checkpoint row under the same React key. A completed checkpoint keeps the context-compaction icon at rest and replaces it with the collapsed or expanded disclosure only on hover or keyboard focus. Input rejection, no compactable history, cancellation, and failure retain the generic command row and its handler-authored text. Pairing never depends on adjacency because durable context may be injected while compaction is running. The framed checkpoint payload is model-facing and never renders; when the cited `compaction/summary` event is outside the loaded window, the checkpoint remains visible but non-expandable. -The resident conversation shell survives no-session and session transitions. Without a current session it locks message actions and presents the whole dashed composer card as a trigger for the root-scoped `conversation.hero.workspace` Workspace picker; the textarea remains read-only and keyboard-accessible. Selecting a Workspace connects or reuses its Host-owned blank session and opens that session without replacing the shell. The root always owns the same scrollport and Hero/composer subtree; separate strict-session header and body outlets fill their regions when the first Session arrives, so the Workspace picker, scroll body, composer seat, and textarea retain their React and DOM identity. Blank sessions render the same composer body as active sessions, while the InputHub carries drafts across Workspace switches and mirrors them into the session store. In the active phase the session header shows only the current session title and view tabs as ordinary column chrome; fork lineage remains session data and is not projected into the header. Beneath it the scrollport (`data-conversation-scroll`) holds the flowing views and the sticky composer stack (stats dock + input docks + bar). That scrollport reserves its scrollbar gutter unconditionally, and a view opting into a composer overlay leaves it a scroll container, so the input card keeps one horizontal position whether or not the transcript scrolls and whichever view tab is shown ([decision](../../../.agents/notes/implemented/bug-fix/2026-08-04-composer-tab-gutter-reservation.md)). Wheel over the textarea chains: the capped draft scrolls locally until its edge, then forwards to that host. +The resident conversation shell survives no-session and session transitions. Without a current session it locks message actions and presents the whole dashed composer card as a trigger for the root-scoped `conversation.hero.workspace` Workspace picker; the textarea remains read-only and keyboard-accessible. Selecting a Workspace connects or reuses its Host-owned blank session and opens that session without replacing the shell. The root always owns the same scrollport and Hero/composer subtree; separate strict-session header and body outlets fill their regions when the first Session arrives, so the Workspace picker, scroll body, composer seat, and textarea retain their React and DOM identity. Blank sessions render the same composer body as active sessions, while the InputHub carries drafts across Workspace switches and mirrors them into the session store. In the active phase the session header shows only the current session title and view tabs as ordinary column chrome; fork lineage remains session data and is not projected into the header. Beneath it the scrollport (`data-conversation-scroll`) holds the flowing views and the sticky composer stack (stats dock + input docks + bar). That scrollport reserves its scrollbar gutter unconditionally, and a view opting into a composer overlay leaves it a scroll container, so the input card keeps one horizontal position whether or not the transcript scrolls and whichever view tab is shown ([decision](../../../.agents/notes/implemented/bug-fix/2026-08-04-composer-tab-gutter-reservation.md)). Wheel over the textarea chains: the capped draft scrolls locally until its edge, then forwards to that host. Safari alone receives a pre-paint recovery when a native edit shortens the draft and leaves stale soft-wrap overflow; draft growth, programmatic updates, and other browsers never read layout for that recovery ([decision](../../../.agents/notes/implemented/bug-fix/2026-08-13-safari-textarea-soft-wrap-reflow.md)). Another plugin can make one session's composer inert through `ctx.conversation.blocks`: it sets a block carrying its own localized reason, and the bar renders the same disabled textarea with that reason as the placeholder — the no-workspace posture, reused. The push direction is the constraint, not a preference: the plugins that know a session cannot send (ui-model-selection, when no adapter serves its route) already depend on this package, so this package cannot read them. The model seat is the one control a block leaves live — every block this contract has is cleared by choosing a model, so locking it too would leave the composer asking for the only thing it prevents. A block is an affordance only; the Host refuses a prompt it cannot route regardless of what any client disables. The no-workspace state wins when both hold, because picking a workspace is the earlier prerequisite. diff --git a/packages/client/ui-conversation/README.zh.md b/packages/client/ui-conversation/README.zh.md index f8922b160c..3f303391d3 100644 --- a/packages/client/ui-conversation/README.zh.md +++ b/packages/client/ui-conversation/README.zh.md @@ -6,7 +6,7 @@ 压缩(compaction)在检查点自身的消息流位置渲染为一行折叠标记,不替换其上方的 transcript(文本记录)。自动压缩使用「上下文已压缩」标题。每个已加载对应 `compaction/summary` 事件的完成标记都会显示被替换条目数量和估算 token 数量,并可点击展开摘要。手动 `/compact` 开始时显示为运行中的 `compact` 行;成功结算后,其显式摘要事件引用会在保持同一 React key 的前提下把该命令折叠进检查点行。完成的检查点静止时保留上下文压缩(context compaction)图标,仅在悬停或键盘聚焦时将其替换为收起/展开指示图标。输入被拒绝、没有可压缩历史、取消和失败时仍使用通用命令行及处理器撰写的文本。配对绝不依赖相邻关系,因为压缩运行期间可能注入持久上下文。面向模型的带框检查点载荷绝不渲染;被引用的 `compaction/summary` 事件位于已加载窗口之外时,检查点仍然可见但不可展开。 -常驻会话壳会跨无会话与会话状态切换而保留。没有当前会话时,它会锁定消息操作,并让整张虚线编辑器卡片成为根作用域 `conversation.hero.workspace` Workspace picker 的入口;textarea 保持只读且支持键盘操作。选择 Workspace 会连接或复用由 Host 拥有的空白会话,并在不替换会话壳的情况下打开该会话。根组件始终拥有同一个滚动容器与 Hero/编辑器子树;首个会话到达时,彼此独立的严格会话页头和主体 outlet 只填入各自区域,因此 Workspace picker、滚动主体、编辑器 seat 与 textarea 都保留原有 React 和 DOM identity。空白会话与活跃会话渲染相同的输入区主体;InputHub 则在 Workspace 切换间携带草稿,并将草稿镜像到会话 store。活跃阶段,会话标题栏作为普通列 chrome,仅显示当前会话标题和视图标签;fork 谱系仍保留为会话数据,不投影到标题栏。其下滚动容器(`data-conversation-scroll`)承载流动排版的各视图与 sticky 编辑器栈(统计 dock+输入区 dock+输入栏)。该滚动容器无条件预留自己的滚动条槽,选用编辑器 overlay 的视图也仍把它保留为滚动容器,因此无论对话记录是否滚动、无论展示哪个视图标签,输入卡片都保持同一个横向位置([决策](../../../.agents/notes/implemented/bug-fix/2026-08-04-composer-tab-gutter-reservation.md))。textarea 上的滚轮会链式处理:限高草稿先在本地滚动,到达边缘后再转交给该宿主。 +常驻会话壳会跨无会话与会话状态切换而保留。没有当前会话时,它会锁定消息操作,并让整张虚线编辑器卡片成为根作用域 `conversation.hero.workspace` Workspace picker 的入口;textarea 保持只读且支持键盘操作。选择 Workspace 会连接或复用由 Host 拥有的空白会话,并在不替换会话壳的情况下打开该会话。根组件始终拥有同一个滚动容器与 Hero/编辑器子树;首个会话到达时,彼此独立的严格会话页头和主体 outlet 只填入各自区域,因此 Workspace picker、滚动主体、编辑器 seat 与 textarea 都保留原有 React 和 DOM identity。空白会话与活跃会话渲染相同的输入区主体;InputHub 则在 Workspace 切换间携带草稿,并将草稿镜像到会话 store。活跃阶段,会话标题栏作为普通列 chrome,仅显示当前会话标题和视图标签;fork 谱系仍保留为会话数据,不投影到标题栏。其下滚动容器(`data-conversation-scroll`)承载流动排版的各视图与 sticky 编辑器栈(统计 dock+输入区 dock+输入栏)。该滚动容器无条件预留自己的滚动条槽,选用编辑器 overlay 的视图也仍把它保留为滚动容器,因此无论对话记录是否滚动、无论展示哪个视图标签,输入卡片都保持同一个横向位置([决策](../../../.agents/notes/implemented/bug-fix/2026-08-04-composer-tab-gutter-reservation.md))。textarea 上的滚轮会链式处理:限高草稿先在本地滚动,到达边缘后再转交给该宿主。只有 Safari 会在原生编辑缩短草稿并留下陈旧软换行溢出时执行绘制前恢复;草稿增长、程序化更新与其他浏览器都不会为这项恢复读取布局([决策](../../../.agents/notes/implemented/bug-fix/2026-08-13-safari-textarea-soft-wrap-reflow.md))。 别的插件可以经 `ctx.conversation.blocks` 让某个会话的编辑器变为惰性:它设置一个携带自己本地化理由的 block,输入栏就渲染同一个禁用的 textarea,并把该理由作为 placeholder——复用无 Workspace 时的那套姿态。推送方向是约束而非偏好:知道某会话发不出消息的插件(ui-model-selection,在没有适配器服务其路由时)本就依赖本包,因此本包读不到它们。模型 seat 是 block 唯一保留可用的控件——这份约定里的每个 block 都靠选模型来解除,把它一起锁上会让编辑器索要它自己拦下的那件事。block 只是提示性设计;无论客户端禁用了什么,宿主都会拒绝一个它无法路由的提示词。两者同时成立时以无 Workspace 姿态为准,因为选 Workspace 是更靠前的前提。 diff --git a/packages/client/ui-conversation/package.json b/packages/client/ui-conversation/package.json index 608817a1e8..2fc12605c1 100644 --- a/packages/client/ui-conversation/package.json +++ b/packages/client/ui-conversation/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-client-ui-conversation", "description": "Conversation domain: skeleton, ordered chat flow, composer with the Host-backed busy-Enter preference, and details host", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -46,7 +46,7 @@ "bundle": "tsdown", "watch": "tsdown --watch" }, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "@deepseek-ai/dsh-settings": "workspace:^", "clsx": "^2.0.0", diff --git a/packages/client/ui-conversation/src/client/skeleton/ConversationRoot.module.css b/packages/client/ui-conversation/src/client/skeleton/ConversationRoot.module.css index 6a8eb15559..6146d42810 100644 --- a/packages/client/ui-conversation/src/client/skeleton/ConversationRoot.module.css +++ b/packages/client/ui-conversation/src/client/skeleton/ConversationRoot.module.css @@ -272,12 +272,17 @@ .scrollBody:has([data-conversation-composer-overlay]) { position: relative; /* A clipping box nothing scrolls out of, stated as a scroll container on both - axes rather than `overflow: hidden`: WebKit honours the reservation above - only in the `overflow-y: auto` form, and a single-axis scroller computes - the other axis to `auto` - ([decision](../../../../../../.agents/notes/implemented/bug-fix/2026-08-04-composer-tab-gutter-reservation.md)). */ + axes rather than `overflow: hidden`: a single-axis scroller computes the + other axis to `auto`, and the seat's absolute positioning below needs the + box to stay a containing block in every engine. */ overflow-x: hidden; overflow-y: auto; + /* The view owns its own scrollers (the trajectory ledger scrolls inside the + view), so this box never scrolls here; reserving a gutter would only + narrow the view's content by the bar's width. Chat keeps the reservation + on the same element, so the seat below compensates with the bar's width + ([decision](../../../../../../.agents/notes/implemented/bug-fix/2026-08-04-composer-tab-gutter-reservation.md)). */ + scrollbar-gutter: auto; } .scrollBody:has([data-conversation-composer-overlay]) > :global([data-slot='conversation.session']) > .viewArea { @@ -288,7 +293,15 @@ .scrollBody:has([data-conversation-composer-overlay]) > .composerSeat { position: absolute; - right: 0; + /* Chat's seat rides this box's content box, which its own scrolling shortens + by the bar's width; the overlay seat is against the padding box, so it + must give back the same width to keep the input card in place across + tabs. Reads ui-theme's --dsh-scrollbar-width, which mirrors the WebKit + bar's layout width. Chat reserves the engine-resolved width, so on an + engine where the resolved width differs from this fixed 8px the card + drifts by half the difference — accepted residual risk, recorded in + ([decision](../../../../../../.agents/notes/implemented/bug-fix/2026-08-12-composer-overlay-seat-width-compensation.md)). */ + right: var(--dsh-scrollbar-width); bottom: 0; left: 0; } diff --git a/packages/client/ui-conversation/src/client/skeleton/InputBar.tsx b/packages/client/ui-conversation/src/client/skeleton/InputBar.tsx index 9585677ae3..000174f513 100644 --- a/packages/client/ui-conversation/src/client/skeleton/InputBar.tsx +++ b/packages/client/ui-conversation/src/client/skeleton/InputBar.tsx @@ -6,7 +6,7 @@ * region-slot content) ride the owner props. Session facts * (running/removed/promptError) are self-selected via useSession. */ -import { useCallback, useEffect, useMemo, useRef, useState } from 'react' +import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react' import type { ChangeEvent, KeyboardEvent, MouseEvent, ReactNode } from 'react' import clsx from 'clsx' import { @@ -31,6 +31,7 @@ import { } from '../image-labels.ts' import { ContextMeter } from './ContextMeter.tsx' import { PermissionSelect } from './PermissionSelect.tsx' +import { isSafariBrowser, repairSafariTextareaLayout } from './safari.ts' import css from './InputBar.module.css' /** Decoration product of the no-session state (no machine, empty draft). */ @@ -106,6 +107,8 @@ export function InputBar({ const dragDepthRef = useRef(0) const scrollRef = useRef(null) const mirrorRef = useRef(null) + const safari = useMemo(() => isSafariBrowser(navigator), []) + const safariNativeShrinkRef = useRef(false) // IME guard: composition Enter picks a candidate, it must not send. The ref outlives renders; // clearing is deferred one tick because Safari delivers the closing keydown AFTER compositionend. const composingRef = useRef(false) @@ -154,6 +157,18 @@ export function InputBar({ } }, [attachments, input?.imageIds, inputActions]) + // A native Safari edit that shortens the draft may leave the previous + // soft-wrap layout behind after the mirror shrinks. The native-change signal + // keeps ordinary typing and programmatic draft updates from reading layout; + // the helper then repairs only measured overflow before paint while + // preserving native editing state. See + // .agents/notes/implemented/bug-fix/2026-08-13-safari-textarea-soft-wrap-reflow.md. + useLayoutEffect(() => { + const nativeShrink = safariNativeShrinkRef.current + safariNativeShrinkRef.current = false + if (safari && nativeShrink) repairSafariTextareaLayout(inputRef.current) + }, [draft, safari]) + useEffect(() => { if (preview !== null && !attachments.some(attachment => attachment.id === preview.id)) setPreview(null) }, [attachments, preview]) @@ -343,6 +358,7 @@ export function InputBar({ if (keyboard === undefined || locked) return // disabled/read-only states cannot edit the draft if (machineBusy) return // submitting is the read-only span; adjudicating holds the pending lock const next = e.target.value + safariNativeShrinkRef.current = safari && next.length < draft.length keyboard.setDraft(next) // selectionStart is number|null in lib.dom; the type-aware lint program narrows it. // oxlint-disable-next-line typescript/no-unnecessary-condition diff --git a/packages/client/ui-conversation/src/client/skeleton/safari.ts b/packages/client/ui-conversation/src/client/skeleton/safari.ts new file mode 100644 index 0000000000..d563b25e6c --- /dev/null +++ b/packages/client/ui-conversation/src/client/skeleton/safari.ts @@ -0,0 +1,42 @@ +/** Safari-specific textarea layout recovery for the conversation composer. */ + +/** Browser identity fields needed to distinguish Safari from other WebKit-based browsers. */ +export interface BrowserIdentity { + readonly userAgent: string + readonly vendor: string +} + +const ALTERNATE_IOS_BROWSER = /\b(?:CriOS|FxiOS|EdgiOS|OPiOS|OPT|DuckDuckGo|Brave)(?:\/|\b)/ + +/** + * Detect Safari's `Version/... Safari/...` form while excluding known alternate iOS browser tokens. + * @param identity - Browser user-agent and vendor values. + * @returns Whether the identity should use the Safari-specific recovery. + */ +export function isSafariBrowser(identity: BrowserIdentity): boolean { + return identity.vendor === 'Apple Computer, Inc.' + && /\bVersion\/[\d.]+.*\bSafari\/[\d.]+/.test(identity.userAgent) + && !ALTERNATE_IOS_BROWSER.test(identity.userAgent) +} + +/** + * Repair Safari's stale native textarea layout and the scrollport auto height it can contaminate. + * @param input - Composer textarea whose own scrollable overflow must stay zero. + */ +export function repairSafariTextareaLayout(input: HTMLTextAreaElement | null): void { + if (input === null || input.scrollHeight <= input.clientHeight) return + const scrollport = input.closest('[data-input-scroll]') + if (scrollport === null) return + + const inputHeight = input.style.height + input.style.height = `${String(input.clientHeight + 1)}px` + void input.offsetHeight + input.style.height = inputHeight + void input.offsetHeight + + const scrollportHeight = scrollport.style.height + scrollport.style.height = `${String(scrollport.clientHeight + 1)}px` + void scrollport.offsetHeight + scrollport.style.height = scrollportHeight + void scrollport.offsetHeight +} diff --git a/packages/client/ui-conversation/tests/input-bar.client.spec.tsx b/packages/client/ui-conversation/tests/input-bar.client.spec.tsx index 94354bd316..f7d5e02a7f 100644 --- a/packages/client/ui-conversation/tests/input-bar.client.spec.tsx +++ b/packages/client/ui-conversation/tests/input-bar.client.spec.tsx @@ -824,6 +824,116 @@ describe('running and lock semantics', () => { expect(backdrop.textContent).toBe('line\n'.repeat(40)) }) + it('repairs Safari native overflow after the mirror shrinks the draft', () => { + const vendor = vi.spyOn(window.navigator, 'vendor', 'get').mockReturnValue('Apple Computer, Inc.') + const userAgent = vi.spyOn(window.navigator, 'userAgent', 'get').mockReturnValue( + 'Mozilla/5.0 (Macintosh) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.5 Safari/605.1.15', + ) + onTestFinished(() => { + vendor.mockRestore() + userAgent.mockRestore() + }) + const { textarea } = bench({ draft: 'two wrapped lines' }) + const scrollport = textarea.closest('[data-input-scroll]')! + let inputRepaired = false + let scrollportRepaired = false + const inputLayouts: string[] = [] + const scrollportLayouts: string[] = [] + Object.defineProperty(textarea, 'clientHeight', { + configurable: true, + get: () => textarea.style.height === '29px' ? 29 : 28, + }) + Object.defineProperty(textarea, 'scrollHeight', { + configurable: true, + get: () => inputRepaired ? 28 : 52, + }) + Object.defineProperty(textarea, 'offsetHeight', { + configurable: true, + get: () => { + inputLayouts.push(textarea.style.height) + if (textarea.style.height === '') inputRepaired = true + return textarea.clientHeight + }, + }) + Object.defineProperty(scrollport, 'clientHeight', { + configurable: true, + get: () => { + if (scrollport.style.height === '53px') return 53 + if (inputRepaired && !scrollportRepaired) return 52 + return 28 + }, + }) + Object.defineProperty(scrollport, 'offsetHeight', { + configurable: true, + get: () => { + scrollportLayouts.push(scrollport.style.height) + if (scrollport.style.height === '') scrollportRepaired = true + return scrollport.clientHeight + }, + }) + textarea.setSelectionRange(5, 5) + + fireEvent.change(textarea, { target: { value: 'one line' } }) + + expect(inputLayouts).toEqual(['29px', '']) + expect(scrollportLayouts).toEqual(['53px', '']) + expect(textarea.style.height).toBe('') + expect(scrollport.style.height).toBe('') + expect(textarea.scrollHeight).toBe(textarea.clientHeight) + expect(scrollport.clientHeight).toBe(28) + }) + + it('does not force the Safari recovery for another iOS browser', () => { + const vendor = vi.spyOn(window.navigator, 'vendor', 'get').mockReturnValue('Apple Computer, Inc.') + const userAgent = vi.spyOn(window.navigator, 'userAgent', 'get').mockReturnValue( + 'Mozilla/5.0 (iPhone) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/140.0.0.0 Mobile/15E148 Safari/604.1', + ) + onTestFinished(() => { + vendor.mockRestore() + userAgent.mockRestore() + }) + const { textarea } = bench({ draft: 'two wrapped lines' }) + const scrollport = textarea.closest('[data-input-scroll]')! + Object.defineProperty(textarea, 'clientHeight', { configurable: true, value: 28 }) + Object.defineProperty(textarea, 'scrollHeight', { configurable: true, value: 52 }) + Object.defineProperty(textarea, 'offsetHeight', { + configurable: true, + get: () => { throw new Error('non-Safari browser must not force textarea layout') }, + }) + Object.defineProperty(scrollport, 'offsetHeight', { + configurable: true, + get: () => { throw new Error('non-Safari browser must not force scrollport layout') }, + }) + + fireEvent.change(textarea, { target: { value: 'one line' } }) + + expect(scrollport.style.height).toBe('') + }) + + it('does not read Safari layout while a native edit grows the draft', () => { + const vendor = vi.spyOn(window.navigator, 'vendor', 'get').mockReturnValue('Apple Computer, Inc.') + const userAgent = vi.spyOn(window.navigator, 'userAgent', 'get').mockReturnValue( + 'Mozilla/5.0 (Macintosh) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.5 Safari/605.1.15', + ) + onTestFinished(() => { + vendor.mockRestore() + userAgent.mockRestore() + }) + const { textarea, shell } = bench({ draft: 'one line' }) + Object.defineProperty(textarea, 'clientHeight', { + configurable: true, + get: () => { throw new Error('growing Safari input must not read layout') }, + }) + Object.defineProperty(textarea, 'scrollHeight', { + configurable: true, + get: () => { throw new Error('growing Safari input must not read layout') }, + }) + + fireEvent.change(textarea, { target: { value: 'one line grows' } }) + + expect(shell.snapshot.draft).toBe('one line grows') + }) + it('an edit the composer performs itself scrolls the caret back into view', async () => { // Paste and cut suppress the native edit, so no engine reveals the caret // for them. jsdom has no layout: the rects are stubbed, diff --git a/packages/client/ui-conversation/tests/safari.client.spec.ts b/packages/client/ui-conversation/tests/safari.client.spec.ts new file mode 100644 index 0000000000..895680d693 --- /dev/null +++ b/packages/client/ui-conversation/tests/safari.client.spec.ts @@ -0,0 +1,131 @@ +// @vitest-environment jsdom + +import { describe, expect, it } from 'vitest' +import { isSafariBrowser, repairSafariTextareaLayout } from '../src/client/skeleton/safari.ts' + +describe('Safari browser detection', () => { + it.each([ + { + name: 'desktop Safari', + vendor: 'Apple Computer, Inc.', + userAgent: 'Mozilla/5.0 (Macintosh) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.5 Safari/605.1.15', + expected: true, + }, + { + name: 'mobile Safari', + vendor: 'Apple Computer, Inc.', + userAgent: 'Mozilla/5.0 (iPhone) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1', + expected: true, + }, + { + name: 'desktop Chromium', + vendor: 'Google Inc.', + userAgent: 'Mozilla/5.0 (Macintosh) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36', + expected: false, + }, + { + name: 'Chrome on iOS', + vendor: 'Apple Computer, Inc.', + userAgent: 'Mozilla/5.0 (iPhone) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/140.0.0.0 Mobile/15E148 Safari/604.1', + expected: false, + }, + { + name: 'Edge on iOS with Safari tokens', + vendor: 'Apple Computer, Inc.', + userAgent: 'Mozilla/5.0 (iPhone) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 EdgiOS/140.0 Mobile/15E148 Safari/604.1', + expected: false, + }, + { + name: 'Opera on iOS with Safari tokens', + vendor: 'Apple Computer, Inc.', + userAgent: 'Mozilla/5.0 (iPhone) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 OPiOS/6.0 Mobile/15E148 Safari/604.1', + expected: false, + }, + { + name: 'Apple web view', + vendor: 'Apple Computer, Inc.', + userAgent: 'Mozilla/5.0 (iPhone) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148', + expected: false, + }, + ])('identifies $name', ({ vendor, userAgent, expected }) => { + expect(isSafariBrowser({ vendor, userAgent })).toBe(expected) + }) +}) + +describe('Safari textarea layout recovery', () => { + it('does nothing while the textarea owns no scrollable overflow', () => { + const input = document.createElement('textarea') + Object.defineProperty(input, 'clientHeight', { value: 28 }) + Object.defineProperty(input, 'scrollHeight', { value: 28 }) + + repairSafariTextareaLayout(input) + + expect(input.style.height).toBe('') + }) + + it('invalidates a stale native layout and restores the owned height', () => { + const input = document.createElement('textarea') + const scrollport = document.createElement('div') + scrollport.setAttribute('data-input-scroll', '') + scrollport.appendChild(input) + input.value = 'abcdef' + input.setSelectionRange(3, 3) + input.style.height = '100%' + scrollport.style.height = '100%' + let inputRepaired = false + let scrollportRepaired = false + const inputLayouts: string[] = [] + const scrollportLayouts: string[] = [] + Object.defineProperty(input, 'clientHeight', { + get: () => input.style.height === '29px' ? 29 : 28, + }) + Object.defineProperty(input, 'scrollHeight', { + get: () => inputRepaired ? 28 : 52, + }) + Object.defineProperty(input, 'offsetHeight', { + get: () => { + inputLayouts.push(input.style.height) + if (input.style.height === '100%') inputRepaired = true + return input.clientHeight + }, + }) + Object.defineProperty(scrollport, 'clientHeight', { + get: () => { + if (scrollport.style.height === '53px') return 53 + if (inputRepaired && !scrollportRepaired) return 52 + return 28 + }, + }) + Object.defineProperty(scrollport, 'offsetHeight', { + get: () => { + scrollportLayouts.push(scrollport.style.height) + if (scrollport.style.height === '100%') scrollportRepaired = true + return scrollport.clientHeight + }, + }) + + repairSafariTextareaLayout(input) + + expect(inputLayouts).toEqual(['29px', '100%']) + expect(scrollportLayouts).toEqual(['53px', '100%']) + expect(input.style.height).toBe('100%') + expect(scrollport.style.height).toBe('100%') + expect(input.scrollHeight).toBe(input.clientHeight) + expect(scrollport.clientHeight).toBe(28) + expect([input.selectionStart, input.selectionEnd]).toEqual([3, 3]) + }) + + it('does nothing outside the composer scrollport', () => { + const input = document.createElement('textarea') + Object.defineProperty(input, 'clientHeight', { value: 28 }) + Object.defineProperty(input, 'scrollHeight', { value: 52 }) + + repairSafariTextareaLayout(input) + + expect(input.style.height).toBe('') + }) + + it('accepts an absent textarea during teardown', () => { + expect(() => { repairSafariTextareaLayout(null) }).not.toThrow() + }) +}) diff --git a/packages/client/ui-deliverables/package.json b/packages/client/ui-deliverables/package.json index ecac18c55f..ac7f264f62 100644 --- a/packages/client/ui-deliverables/package.json +++ b/packages/client/ui-deliverables/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-client-ui-deliverables", "description": "Produced-files turn tail and clickable final-response file references for Web", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -44,7 +44,7 @@ "bundle": "tsdown", "watch": "tsdown --watch" }, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "react": "^18.2.0" }, diff --git a/packages/client/ui-directory-picker-browse/package.json b/packages/client/ui-directory-picker-browse/package.json index a63fe3038a..0cc14700fc 100644 --- a/packages/client/ui-directory-picker-browse/package.json +++ b/packages/client/ui-directory-picker-browse/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-client-ui-directory-picker-browse", "description": "In-app directory browsing surface: the workspace directory-flow owner rendering the host's listing and creation primitives", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -43,7 +43,7 @@ "bundle": "tsdown", "watch": "tsdown --watch" }, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "clsx": "^2.0.0" }, diff --git a/packages/client/ui-directory-picker-native/package.json b/packages/client/ui-directory-picker-native/package.json index 73e8646f14..74b8e7845b 100644 --- a/packages/client/ui-directory-picker-native/package.json +++ b/packages/client/ui-directory-picker-native/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-client-ui-directory-picker-native", "description": "Native directory-picker surface: the renderless workspace directory-flow occupant driving the host's OS chooser", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -42,7 +42,7 @@ "bundle": "tsdown", "watch": "tsdown --watch" }, - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-client-runtime": "workspace:^", "@deepseek-ai/dsh-client-ui-slots": "workspace:^", diff --git a/packages/client/ui-goal/package.json b/packages/client/ui-goal/package.json index acea46c02c..6076aab741 100644 --- a/packages/client/ui-goal/package.json +++ b/packages/client/ui-goal/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-client-ui-goal", "description": "Session goal surface: GoalBar docked above the composer, read from the goal session projection", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -44,7 +44,7 @@ "bundle": "tsdown", "watch": "tsdown --watch" }, - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-client-locale": "workspace:^", "@deepseek-ai/dsh-api-remotes": "workspace:^", diff --git a/packages/client/ui-input-trigger/package.json b/packages/client/ui-input-trigger/package.json index f9b10d5975..a4ca2afe84 100644 --- a/packages/client/ui-input-trigger/package.json +++ b/packages/client/ui-input-trigger/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-client-ui-input-trigger", "description": "Input trigger pipeline: '/' and '@' detection, candidate menu, pick routing to registered sources", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -42,7 +42,7 @@ "bundle": "tsdown", "watch": "tsdown --watch" }, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "clsx": "^2.0.0" }, diff --git a/packages/client/ui-jobs/package.json b/packages/client/ui-jobs/package.json index 92be42fbce..a59d064dda 100644 --- a/packages/client/ui-jobs/package.json +++ b/packages/client/ui-jobs/package.json @@ -1,7 +1,7 @@ { "name": "@deepseek-ai/dsh-client-ui-jobs", "description": "Session-header background-job list: live registry state mirrored from session/jobs frames", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "type": "module", "main": "lib/index.js", "types": "lib/types/index.d.ts", @@ -36,14 +36,14 @@ "bundle": "tsdown", "watch": "tsdown --watch" }, - "license": "BSD-3-Clause", + "license": "MIT", "repository": { "type": "git", "url": "git+https://github.com/deepseek-ai/deepseek-harness.git", "directory": "packages/client/ui-jobs" }, "publishConfig": { - "access": "restricted" + "access": "public" }, "dependencies": { "react": "^18.2.0" diff --git a/packages/client/ui-jobs/src/client/JobListAction.tsx b/packages/client/ui-jobs/src/client/JobListAction.tsx index b4cd08c56d..8834abf82b 100644 --- a/packages/client/ui-jobs/src/client/JobListAction.tsx +++ b/packages/client/ui-jobs/src/client/JobListAction.tsx @@ -1,6 +1,6 @@ import { useEffect, useMemo, useRef, useState, type KeyboardEvent } from 'react' import type { JobView } from '@deepseek-ai/dsh-client-runtime/client' -import { IconChevronDownOutline14, StateDot, type StateDotState } from '@deepseek-ai/dsh-client-ui-primitives' +import { IconChevronDownOutline14, StateDot, useDismissOnOutsidePointer, type StateDotState } from '@deepseek-ai/dsh-client-ui-primitives' import type { PropsLocale, PropsRuntime, TranslateNS } from '@deepseek-ai/dsh-client-ui-slots' import { NS } from './locales.ts' import type {} from '@deepseek-ai/dsh-client-ui-conversation/client' @@ -101,16 +101,7 @@ export function JobListAction({ sessionId, useSessions, t }: JobListActionProps) const rows = useMemo(() => ordered(jobs), [jobs]) const liveCount = useMemo(() => jobs.filter(isLive).length, [jobs]) - useEffect(() => { - if (!open) return - const closeOutside = (event: PointerEvent): void => { - if (event.target instanceof Node && !rootRef.current?.contains(event.target)) { - setOpen(false) - } - } - document.addEventListener('pointerdown', closeOutside) - return () => { document.removeEventListener('pointerdown', closeOutside) } - }, [open]) + useDismissOnOutsidePointer(rootRef, open, setOpen) // The clock only runs while an open list is showing something that moves. useEffect(() => { diff --git a/packages/client/ui-layout/package.json b/packages/client/ui-layout/package.json index d600913ce9..d3ab329297 100644 --- a/packages/client/ui-layout/package.json +++ b/packages/client/ui-layout/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-client-ui-layout", "description": "Shell plugin: three-column AppFrame with drag handles, ctx.layout viewing-state service (navigation + panels)", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -42,7 +42,7 @@ "bundle": "tsdown", "watch": "tsdown --watch" }, - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-client-runtime": "workspace:^", "@deepseek-ai/dsh-client-ui-slots": "workspace:^", diff --git a/packages/client/ui-message-feedback/package.json b/packages/client/ui-message-feedback/package.json index f59a70fe1d..481d02aa03 100644 --- a/packages/client/ui-message-feedback/package.json +++ b/packages/client/ui-message-feedback/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-client-ui-message-feedback", "description": "Per-message feedback controls contributed to the assistant-message action strip, backed by the messageFeedback Host Remote", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -44,7 +44,7 @@ "bundle": "tsdown", "watch": "tsdown --watch" }, - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-api-remotes": "workspace:^", "@deepseek-ai/dsh-client-connection": "workspace:^", diff --git a/packages/client/ui-model-selection/package.json b/packages/client/ui-model-selection/package.json index 1e85054714..298fd8b133 100644 --- a/packages/client/ui-model-selection/package.json +++ b/packages/client/ui-model-selection/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-client-ui-model-selection", "description": "Model selection: the /model popupSelect over session.models / session.selectModel", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -44,7 +44,7 @@ "bundle": "tsdown", "watch": "tsdown --watch" }, - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-api-remotes": "workspace:^", "@deepseek-ai/dsh-client-connection": "workspace:^", diff --git a/packages/client/ui-permission-presets/package.json b/packages/client/ui-permission-presets/package.json index 89b3de4ca2..62f03cbd07 100644 --- a/packages/client/ui-permission-presets/package.json +++ b/packages/client/ui-permission-presets/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-client-ui-permission-presets", "description": "Permission surfaces: a new-session default in General settings and a current-session /permission popup over the permissions projection", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -46,7 +46,7 @@ "bundle": "tsdown", "watch": "tsdown --watch" }, - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "workspace:^", "@deepseek-ai/dsh-api-remotes": "workspace:^", diff --git a/packages/client/ui-plan/package.json b/packages/client/ui-plan/package.json index c06c45ca13..233a8a72fe 100644 --- a/packages/client/ui-plan/package.json +++ b/packages/client/ui-plan/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-client-ui-plan", "description": "Plan-mode composer control: the conversation.input.plan seat over the plan projection and the /plan command channel", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -43,7 +43,7 @@ "bundle": "tsdown", "watch": "tsdown --watch" }, - "license": "BSD-3-Clause", + "license": "MIT", "peerDependencies": { "@deepseek-ai/dsh-api-remotes": "workspace:^", "@deepseek-ai/dsh-client-locale": "workspace:^", diff --git a/packages/client/ui-primitives/package.json b/packages/client/ui-primitives/package.json index 0000405054..b6e01b4f5a 100644 --- a/packages/client/ui-primitives/package.json +++ b/packages/client/ui-primitives/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-client-ui-primitives", "description": "Pure React atoms for the dsh web UI: controls, icons, markdown, and JSON inspectors (zero cordis)", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -25,7 +25,7 @@ "./src/*": "./src/*", "./package.json": "./package.json" }, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "@shikijs/langs": "^4.3.1", "@types/mdast": "^4.0.4", diff --git a/packages/client/ui-primitives/src/index.ts b/packages/client/ui-primitives/src/index.ts index 05baf26f8d..1e8c3e576d 100644 --- a/packages/client/ui-primitives/src/index.ts +++ b/packages/client/ui-primitives/src/index.ts @@ -13,6 +13,7 @@ export { Input } from './Input.tsx' export { Menu } from './Menu.tsx' export type { MenuEntry, MenuItem, MenuSeparator, MenuLabel } from './Menu.tsx' export { useAnchoredMaxHeight } from './useAnchoredMaxHeight.ts' +export { useDismissOnOutsidePointer } from './useDismissOnOutsidePointer.ts' export { HoverCard } from './HoverCard.tsx' export { Modal } from './Modal.tsx' export { OnboardingSurface } from './OnboardingSurface.tsx' diff --git a/packages/client/ui-primitives/src/useDismissOnOutsidePointer.ts b/packages/client/ui-primitives/src/useDismissOnOutsidePointer.ts new file mode 100644 index 0000000000..3706d13bfc --- /dev/null +++ b/packages/client/ui-primitives/src/useDismissOnOutsidePointer.ts @@ -0,0 +1,29 @@ +/** + * Outside-pointer dismissal for trigger-owned popovers (jobs list, Cordis + * panel): while the surface is open, a pointerdown outside the root closes it. + */ +import { useEffect } from 'react' +import type { RefObject } from 'react' + +/** + * Close an open popover when a pointerdown lands outside its root element. + * @param root - element containing both the trigger and the open surface. + * @param open - whether the surface is showing; false detaches the listener. + * @param setOpen - state setter invoked with false on an outside pointerdown. + */ +export function useDismissOnOutsidePointer( + root: RefObject, + open: boolean, + setOpen: (open: boolean) => void, +): void { + useEffect(() => { + if (!open) return + const closeOutside = (event: PointerEvent): void => { + if (event.target instanceof Node && !root.current?.contains(event.target)) { + setOpen(false) + } + } + document.addEventListener('pointerdown', closeOutside) + return () => { document.removeEventListener('pointerdown', closeOutside) } + }, [root, open, setOpen]) +} diff --git a/packages/client/ui-settings-general/README.i18n.yaml b/packages/client/ui-settings-general/README.i18n.yaml index 3a0fae8d41..77b5c4e2d3 100644 --- a/packages/client/ui-settings-general/README.i18n.yaml +++ b/packages/client/ui-settings-general/README.i18n.yaml @@ -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/client/ui-settings-general/README.md -README.md: d02230d281482d03545a7dd9bb06fd5f1085d017 -README.zh.md: 9e2011902227c8d656f57813d4ecec92147d0f6f +README.md: c59b77617cfd5848553ba340e97bafe37b7b2a2f +README.zh.md: ea4896284b677a7b430cceb949b53aa6e3a5a242 diff --git a/packages/client/ui-settings-general/README.md b/packages/client/ui-settings-general/README.md index d02230d281..c59b77617c 100644 --- a/packages/client/ui-settings-general/README.md +++ b/packages/client/ui-settings-general/README.md @@ -2,13 +2,13 @@ English | [中文](README.zh.md) -Settings shell, ownerless-copy, and product-onboarding plugin. It occupies `sidebar.settings` with the trigger chrome and modal settings panel, projects the `settings.section` ledger into the navigation and the `settings.onboarding` ledger into one mounted page at a time, and registers everything on the Settings pages that belongs to no single feature — the trigger/header/close chrome content, the local configuration-file action, the General section and its `settings.general.item` slot, the `settings` dictionaries, and the first ordered welcome step. The slot types it renders into belong to ui-settings, the settings domain base; only the shell's own contract types live here, because they reference ui-sidebar's slot type and the base layer must depend on no `ui-*` package. Feature-owned rows (Permission, Language, Appearance), sections (Models), and conditional onboarding steps stay with their feature packages. +Settings shell, ownerless copy, and durable product-onboarding namespace. It occupies `sidebar.settings` with the trigger chrome and modal settings panel, projects the `settings.section` ledger into the navigation and the `settings.onboarding` ledger into one mounted step at a time, and registers everything on the Settings pages that belongs to no single feature — the trigger/header/close chrome content, the local configuration-file action, the General section and its `settings.general.item` slot, and the `settings` dictionaries. The slot types it renders into belong to ui-settings, the settings domain base; only the shell's own contract types live here, because they reference ui-sidebar's slot type and the base layer must depend on no `ui-*` package. Feature-owned rows (Permission, Language, Appearance), sections (Models), and conditional onboarding steps stay with their feature packages. -The shell ships no copy of its own — all text arrives from registrants. Nav labels may be locale-following thunks, so the nav projection resolves them through `resolveSlotLabel` and re-renders on the section ledger bump or the locale revision (an optional `ctx.get('locale')` read; no hard locale dependency). The onboarding ledger projects in ascending order and mounts exactly one page at a time; the takeover chrome (body-level stage, mask, app-root `inert`) belongs to the step itself through ui-primitives' `OnboardingSurface`, so a mounted step still resolving its private facts renders null and neither paints nor blocks anything — the shell shows no empty stage while a step decides. The active registrant receives its id, `complete()`, and an `openSection(id)` callback; completing or skipping transfers ownership to the next entry. Registrants own durable completion, capability readiness, copy, mutations, and the surface wrap, so independently registered flows cannot stack and the shell does not become a second configuration fact source. +The shell ships no onboarding copy of its own — all text arrives from registrants. Nav labels may be locale-following thunks, so the nav projection resolves them through `resolveSlotLabel` and re-renders on the section ledger bump or the locale revision (an optional `ctx.get('locale')` read; no hard locale dependency). The onboarding ledger projects in ascending order and mounts exactly one step at a time. Visible steps own their dialog chrome and app-root `inert` lifecycle; a mounted step still resolving private facts renders null, so nothing paints or blocks while it decides. The active registrant receives its id, `complete()`, and an `openSection(id)` callback; completing or skipping transfers ownership to the next entry. Registrants own durable completion, capability readiness, copy, mutations, and their visible wrapper, so independently registered flows cannot stack and the shell does not become a second configuration fact source. A loopback browser loads the provider's `hasDocument` capability through `settings.describe` and renders **Open configuration file** only when the Host confirms that a provider-owned local document can be prepared. The action sends the pathless, loopback-only `settings.openDocument` request; the Host resolves the provider path again, materializes an absent document, and hands it to a native text editor (`open -t` on macOS, bypassing a browser file association; the desktop file association on Linux and Windows; Windows association after `wslpath -w` translation on WSL). Open failures keep the action available and render a localized error. Reopening the dialog or reconnecting refreshes availability after a transient read failure or Host topology change. Remote browsers never register the action and never issue the privileged settings read. -`src/onboarding-copy.ts` is the single editable owner of the complete notice plus `WELCOME_NOTICE_VERSION`; both supported GUI locales intentionally render the same Chinese copy. The Host half registers `ui-onboarding` in the user-settings seam. A loopback browser compares `welcomeNoticeVersion` for exact equality and writes the current value only after Continue succeeds. The path mutation is idempotent across tabs and preserves sibling settings, while `host/settings-changed` makes an externally acknowledged notice advance without a reload. A non-loopback browser cannot access the privileged settings API: it still presents the notice, but Continue advances only the current browser process and a reload presents the notice again. A different version deliberately presents the notice again. The welcome page preserves every authored paragraph, gives the requested clause in the final paragraph the sole emphasis, initially focuses the title, and has no close, Escape, mask-click, or secondary path. None of its copy or acknowledgement enters a Session log or model request. The notice states that session telemetry is disabled by default, names the `FEEDBACK_ONLY` and `FULL` opt-in modes, and discloses that `FULL` also enables dsh-sdk command telemetry. +The Host half registers `ui-onboarding` in the user-settings seam. The welcome step contributed by `ui-settings-models` reads and writes its `welcomeNoticeVersion` through the existing public settings boundary; the shell itself remains policy-free. ## Model Experience diff --git a/packages/client/ui-settings-general/README.zh.md b/packages/client/ui-settings-general/README.zh.md index 9e20119022..ea4896284b 100644 --- a/packages/client/ui-settings-general/README.zh.md +++ b/packages/client/ui-settings-general/README.zh.md @@ -2,13 +2,13 @@ [English](README.md) | 中文 -设置外壳、无特定功能归属文案与产品引导插件。它以触发控件和模态设置面板占用 `sidebar.settings`,把 `settings.section` 账本投影成导航、把 `settings.onboarding` 账本投影成每次只挂载一页的引导流程,并在设置页面上注册所有不属于单一功能的内容:触发器、标题栏与关闭控件内容、本地配置文件操作,「通用」分区及其 `settings.general.item` slot、`settings` 字典,以及第一个有序欢迎步骤。它渲染进的那些 slot 类型归 ui-settings——设置领域底座——所有;只有外壳自身的契约类型放在这里,因为它们引用 ui-sidebar 的 slot 类型,而底座不得依赖任何 `ui-*` 包。归具体功能所有的行(「权限」、「语言」、「外观」)、分区(「模型」)和条件式首次使用引导步骤仍由各自的功能包提供。 +设置外壳、无特定功能归属文案与持久化产品引导 namespace。它以触发控件和模态设置面板占用 `sidebar.settings`,把 `settings.section` 账本投影成导航、把 `settings.onboarding` 账本投影成每次只挂载一个步骤的引导流程,并在设置页面上注册所有不属于单一功能的内容:触发器、标题栏与关闭控件内容、本地配置文件操作,「通用」分区及其 `settings.general.item` slot,以及 `settings` 字典。它渲染进的那些 slot 类型归 ui-settings——设置领域底座——所有;只有外壳自身的契约类型放在这里,因为它们引用 ui-sidebar 的 slot 类型,而底座不得依赖任何 `ui-*` 包。归具体功能所有的行(「权限」、「语言」、「外观」)、分区(「模型」)和条件式首次使用引导步骤仍由各自的功能包提供。 -外壳不自带文案:所有文本都来自注册方。导航 label 可以是跟随语言的 thunk,因此导航投影经 `resolveSlotLabel` 解析,并在分区账本更新或 locale revision 变化时重新渲染(`ctx.get('locale')` 可选读取,无硬 locale 依赖)。首次使用引导记录按升序投影,每次只挂载一个页面;接管界面框架(body 层级的展示层、遮罩、应用根节点 `inert`)经 ui-primitives 的 `OnboardingSurface` 由步骤自身持有,因此已挂载但仍在判定私有事实的步骤渲染 null 时不绘制也不阻塞任何内容——步骤判定期间外壳不会露出空白展示层。当前注册方会收到该条目的 id、`complete()` 和 `openSection(id)` 回调;完成或跳过当前页面后,所有权转交给下一项。持久化完成状态、能力就绪状态、文案、变更操作以及展示层包装均由注册方持有,因此独立注册的流程无法堆叠,外壳也不会成为第二个配置事实来源。 +外壳不自带引导文案:所有文本都来自注册方。导航 label 可以是跟随语言的 thunk,因此导航投影经 `resolveSlotLabel` 解析,并在分区账本更新或 locale revision 变化时重新渲染(`ctx.get('locale')` 可选读取,无硬 locale 依赖)。首次使用引导记录按升序投影,每次只挂载一个步骤;可见步骤自行持有弹窗框架和应用根节点 `inert` 生命周期。已挂载但仍在判定私有事实的步骤渲染 null,因此判定期间不绘制也不阻塞任何内容。当前注册方会收到该条目的 id、`complete()` 和 `openSection(id)` 回调;完成或跳过当前步骤后,所有权转交给下一项。持久化完成状态、能力就绪状态、文案、变更操作以及可见包装均由注册方持有,因此独立注册的流程无法堆叠,外壳也不会成为第二个配置事实来源。 回环浏览器通过 `settings.describe` 加载提供方的 `hasDocument` 能力,且只有在 Host 确认可准备好一份由提供方持有的本地文档时才渲染**打开配置文件**。该操作发送无路径参数且仅限回环访问的 `settings.openDocument` 请求;Host 会再次解析提供方路径、在文档缺失时将其创建出来,并交给原生文本编辑器(macOS 上使用 `open -t`,绕过浏览器文件关联;Linux 和 Windows 上使用桌面文件关联;WSL 上经 `wslpath -w` 转换后使用 Windows 文件关联)。打开失败时该操作仍可使用,并渲染本地化错误。临时读取失败或 Host 拓扑变化后,重新打开对话框或重新连接会刷新可用性。远程浏览器从不注册该操作,也从不发起这项特权设置读取。 -`src/onboarding-copy.ts` 是完整通知文案和 `WELCOME_NOTICE_VERSION` 的唯一可编辑来源;GUI 支持的两种 locale 都有意渲染同一份中文文案。宿主端在用户设置 seam 中注册 `ui-onboarding`。回环浏览器会比较 `welcomeNoticeVersion` 是否精确相等,仅在「继续」操作成功后写入当前值。该路径变更在不同标签页间幂等,并会保留同级设置;`host/settings-changed` 则让页面在通知被外部确认后,无需重新加载即可推进。非回环浏览器不能访问受保护的设置 API:它仍会显示通知,但「继续」只推进当前浏览器进程,重新加载后会再次显示通知。版本不同时,系统也会有意重新显示通知。欢迎页保留原文的每个段落,仅强调最后一段中指定的句段,初始焦点落在标题上,并且没有关闭操作、Escape、点击遮罩或次要操作路径。其文案和确认状态均不会进入会话日志或模型请求。通知说明会话遥测默认禁用,列出 `FEEDBACK_ONLY` 和 `FULL` 两种显式启用模式,并披露 `FULL` 同时会启用 dsh-sdk 命令遥测。 +宿主端在用户设置 seam 中注册 `ui-onboarding`。`ui-settings-models` 提供的欢迎步骤通过既有公开 settings 边界读写其中的 `welcomeNoticeVersion`;外壳本身仍不持有产品策略。 ## 模型体验 diff --git a/packages/client/ui-settings-general/package.json b/packages/client/ui-settings-general/package.json index 3da8aff119..c5207dfc9d 100644 --- a/packages/client/ui-settings-general/package.json +++ b/packages/client/ui-settings-general/package.json @@ -1,9 +1,9 @@ { "name": "@deepseek-ai/dsh-client-ui-settings-general", "description": "Settings ownerless-copy and product onboarding plugin: the General section, shell trigger/header chrome content, settings dictionaries, and the versioned welcome notice", - "version": "0.0.1-rc.5", + "version": "0.1.0-rc.6", "publishConfig": { - "access": "restricted" + "access": "public" }, "repository": { "type": "git", @@ -46,7 +46,7 @@ "bundle": "tsdown", "watch": "tsdown --watch" }, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { "@deepseek-ai/dsh-settings": "workspace:^", "@deepseek-ai/schemastery": "workspace:^", diff --git a/packages/client/ui-settings-general/src/client/SettingsRoot.module.css b/packages/client/ui-settings-general/src/client/SettingsRoot.module.css index 060e8d115b..03e0f6372c 100644 --- a/packages/client/ui-settings-general/src/client/SettingsRoot.module.css +++ b/packages/client/ui-settings-general/src/client/SettingsRoot.module.css @@ -1,19 +1,19 @@ /* Settings shell (figma 501:29904 mask context / 501:29947 panel): sidebar foot trigger row + centered 1080x700 modal panel. The trigger uses the - sidebar's 34px compact row / 36px rail circle rhythm; the + sidebar foot's 42px row / 36px rail circle rhythm; the panel is a two-column layout — 188px nav rail + content column with a 54px header and the 24px-padded options area. */ -/* Trigger row: match the other wide sidebar controls' compact vertical rhythm. */ +/* Trigger row: the 42px foot-row box shared with the Cordis footer action. */ .trigger { flex: none; display: flex; align-items: center; gap: 8px; - width: calc(100% + 8px); - height: 34px; - margin: 4px -4px 4px; - padding: 6px 2px 6px 10px; + width: calc(100% + 4px); + height: 42px; + margin: 4px -2px; + padding: 0 10px 0 8px; box-sizing: border-box; border: none; border-radius: 12px; diff --git a/packages/client/ui-settings-general/src/client/SettingsRoot.tsx b/packages/client/ui-settings-general/src/client/SettingsRoot.tsx index fb14059f05..762747500d 100644 --- a/packages/client/ui-settings-general/src/client/SettingsRoot.tsx +++ b/packages/client/ui-settings-general/src/client/SettingsRoot.tsx @@ -7,9 +7,8 @@ * aria-labelledby the title node; close: visually-hidden slot text). Modal * open state and the active section id are component-local viewing state; * the onboarding coordinator mounts exactly one ordered registrant while the - * sessions-derived empty-Hero fact is active — the takeover chrome - * (OnboardingSurface) belongs to the step, so a mounted-but-deciding step - * paints nothing here. + * sessions-derived empty-Hero fact is active. Visible dialog chrome belongs + * to the step, so a mounted-but-deciding step paints nothing here. */ import { useCallback, useEffect, useId, useRef, useState } from 'react' import clsx from 'clsx' @@ -160,10 +159,9 @@ export function SettingsRoot(props: SettingsRootComponentProps) { onClose={close} /> )} - {/* The takeover chrome (OnboardingSurface: mask, opaque stage, `#root` - inert) lives inside the step component, wrapped around its visible - content — a step still deciding (private facts loading) renders - null, so nothing paints or blocks while it decides. */} + {/* Dialog chrome and `#root` inert ownership live inside each step's + visible branch. A step still deciding (private facts loading) + renders null, so nothing paints or blocks while it decides. */} {onboardingStep !== undefined && renderSlot('settings.onboarding', { stepId: onboardingStep.id, complete: () => { completeOnboardingStep(onboardingStep.id) }, diff --git a/packages/client/ui-settings-general/src/client/WelcomeNotice.module.css b/packages/client/ui-settings-general/src/client/WelcomeNotice.module.css deleted file mode 100644 index a1727b8033..0000000000 --- a/packages/client/ui-settings-general/src/client/WelcomeNotice.module.css +++ /dev/null @@ -1,155 +0,0 @@ -.page { - position: relative; - z-index: 1; - width: min(640px, calc(100vw - 64px)); - max-height: 100vh; - padding: clamp(64px, 9vh, 104px) 0 40px; - box-sizing: border-box; - overflow-y: auto; - color: var(--dsw-alias-label-primary); - --welcome-ease-out: cubic-bezier(0.23, 1, 0.32, 1); -} - -.brand { - display: flex; - align-items: center; - margin-bottom: 42px; - color: var(--dsw-alias-label-primary); -} - -.title { - margin: 0; - font-size: 28px; - line-height: 36px; - font-weight: 600; - letter-spacing: -0.02em; - outline: none; -} - -.opening, -.reflection, -.feedback, -.error { - margin: 0; -} - -.opening { - margin-top: 30px; -} - -.reflection { - margin-top: 36px; - padding: 0; -} - -.feedback { - margin-top: 30px; -} - -.opening, -.reflection, -.feedback { - font-size: 16px; - line-height: 28px; - color: var(--dsw-alias-label-secondary); -} - -.feedback strong { - color: inherit; - font-weight: 500; -} - -.footer { - display: flex; - justify-content: flex-end; - margin-top: 32px; -} - -.error { - margin-top: 20px; - font-size: 14px; - line-height: 22px; - color: var(--dsw-alias-state-error-primary); -} - -.primary { - min-width: 120px; - transition: transform 140ms var(--welcome-ease-out); -} - -.primary:active:not(:disabled) { - transform: scale(0.97); -} - -.brand, -.title, -.opening, -.reflection, -.feedback, -.footer { - animation: welcome-enter 280ms var(--welcome-ease-out) both; -} - -.title { animation-delay: 40ms; } -.opening { animation-delay: 80ms; } -.reflection { animation-delay: 120ms; } -.feedback { animation-delay: 160ms; } -.footer { animation-delay: 200ms; } - -@keyframes welcome-enter { - from { - opacity: 0; - transform: translateY(8px); - } - - to { - opacity: 1; - transform: translateY(0); - } -} - -@media (prefers-reduced-motion: reduce) { - .brand, - .title, - .opening, - .reflection, - .feedback, - .footer { - animation: none; - } - - .primary { - transition: none; - } -} - -@media (max-width: 560px) { - .page { - width: calc(100vw - 40px); - padding-top: 38px; - } - - .brand { - margin-bottom: 30px; - } - - .opening { - margin-top: 24px; - } - - .reflection { - margin-top: 28px; - } - - .feedback { - margin-top: 28px; - } - - .footer { - margin-top: 30px; - } - - .primary { - width: 100%; - } -} diff --git a/packages/client/ui-settings-general/src/client/WelcomeNotice.tsx b/packages/client/ui-settings-general/src/client/WelcomeNotice.tsx deleted file mode 100644 index 34187073a1..0000000000 --- a/packages/client/ui-settings-general/src/client/WelcomeNotice.tsx +++ /dev/null @@ -1,91 +0,0 @@ -/** Product-wide, versioned first-run welcome step. */ - -import { useCallback, useEffect, useRef } from 'react' -import type { ReactNode } from 'react' -import type { PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots' -import { BrandWordmark, Button, OnboardingSurface } from '@deepseek-ai/dsh-client-ui-primitives' -import type { SnapshotSelectorHook } from '@deepseek-ai/dsh-client-web-react' -import type { WelcomeNoticeState, WelcomeNoticeStore } from './welcome-store.ts' -import css from './WelcomeNotice.module.css' - -function emphasizedFeedback(paragraph: string, emphasis: string): ReactNode { - const index = paragraph.indexOf(emphasis) - /* v8 ignore next -- both locale values derive from one owner object that contains the emphasis */ - if (index < 0) return paragraph - return ( - <> - {paragraph.slice(0, index)} - {emphasis} - {paragraph.slice(index + emphasis.length)} - - ) -} - -/** Registrant-owned dependencies of {@link WelcomeNotice}. */ -export interface WelcomeNoticeInjected { - controller: WelcomeNoticeStore - useSnapshot: SnapshotSelectorHook -} - -/** Coordinator owner props plus the welcome step's injected face. */ -export type WelcomeNoticeProps = - PropsRuntime<'settings.onboarding'> & PropsLocale<'settings'> & WelcomeNoticeInjected - -/** Render the mandatory notice until its current version is acknowledged. */ -export function WelcomeNotice(props: WelcomeNoticeProps): ReactNode { - const { complete, controller, useSnapshot, t } = props - const state = useSnapshot(snapshot => snapshot) - const finished = useRef(false) - const titleRef = useRef(null) - const finish = useCallback((): void => { - if (finished.current) return - finished.current = true - complete() - }, [complete]) - - useEffect(() => { - if (state.status === 'idle') void controller.load() - }, [controller, state.status]) - - useEffect(() => { - if (state.acknowledged) finish() - }, [finish, state.acknowledged]) - - useEffect(() => { - if (state.status === 'ready' && !state.acknowledged) titleRef.current?.focus() - }, [state.acknowledged, state.status]) - - // Null while the acknowledgement fact is still loading (or already given): - // the takeover chrome below is part of THIS render, so deciding not to - // show paints and blocks nothing. - if (state.status === 'idle' || state.status === 'loading' || state.acknowledged) return null - - const acknowledge = async (): Promise => { - if (await controller.acknowledge()) finish() - } - - return ( - -