From 23850b4ad9e90dac72e358578587684ac93be2c1 Mon Sep 17 00:00:00 2001 From: Tianyi Cui <53024+tianyicui@users.noreply.github.com> Date: Sun, 12 Jul 2026 23:59:05 +0800 Subject: [PATCH] docs: align model experience with scoped runtime --- docs/AGENTS.md | 10 +++++----- packages/core/agent-loop/README.md | 2 +- packages/core/scope/README.md | 2 +- packages/core/system-prompt/README.md | 2 +- packages/core/tools/README.md | 4 ++-- packages/subagent/subagent-acp/README.md | 2 +- packages/subagent/subagent-fork/README.md | 2 +- packages/subagent/subagent-inprocess/README.md | 2 +- packages/subagent/subagent-spawn/README.md | 2 +- packages/subagent/tool-subagent/README.md | 2 +- 10 files changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/AGENTS.md b/docs/AGENTS.md index ad592333d5..90b5b7354f 100644 --- a/docs/AGENTS.md +++ b/docs/AGENTS.md @@ -1,10 +1,10 @@ # AGENTS.md — The documentation standard -This file is the contract for every Markdown files in the repo: each tier's job, the writing rules, and the word budgets that `verify-doc-budgets` enforces. The audit/apply workflow is the [dsh-doc-standards](../.agents/skills/dsh-doc-standards/SKILL.md) skill; the decision record is [the doc-tiers-and-budgets RFC](rfc/implemented/process/2026-07-04-doc-tiers-and-budgets.md). +This is the repo's Markdown placement, writing, and budget contract. Use [dsh-doc-standards](../.agents/skills/dsh-doc-standards/SKILL.md) to apply it; the [doc-tiers-and-budgets RFC](rfc/implemented/process/2026-07-04-doc-tiers-and-budgets.md) records the rationale. ## The tier taxonomy: one home per fact -Every fact has exactly one home — the tier whose job it is — and every other place that needs it links there instead of restating it. A rule restated in two files drifts word-by-word until the copies disagree; a link cannot drift, and `verify-md-links` keeps it resolving. +Each fact has one owning tier; other tiers link to it. Restated rules drift, while `verify-md-links` keeps links resolving. | Tier | Job | Does NOT belong there | |---|---|---| @@ -20,7 +20,7 @@ Every fact has exactly one home — the tier whose job it is — and every other | Generated catalogs: [cordis events](cordis-catalog/events.md), [cordis services](cordis-catalog/services.md), [tool-catalog](tool-catalog.md), [config-catalog](config-catalog.md), [persistence-catalog](persistence-catalog.md), [module-graph.md](module-graph.md) | Exhaustive enumerations regenerated from source, freshness-gated | Hand edits of any kind | | Skills (`.agents/skills/`) | Workflows: how to carry out a recurring task against the contracts | The contracts themselves (→ docs) | -Placement test: a story about a bug → postmortem. Why we chose X → RFC. How to do task Y → cookbook. What type Z looks like → core-data-structures. What package P promises → its README. A rule every agent must always obey → root AGENTS.md, one line, linking the home that holds the why. +Placement: bugs → postmortems; rationale → RFCs; procedures → cookbooks; type shapes → core data; package promises → READMEs; standing orders → root `AGENTS.md` with a link to their rationale. ## Writing rules @@ -35,12 +35,12 @@ Placement test: a story about a bug → postmortem. Why we chose X → RFC. How ## Package Model Experience -Every package README ends with this table followed by `## Known Limitations and Deferred Work`; [allowlisted packages](../scripts/verify-readme-limitations.ts) end after the table: +Every package README ends with this table immediately before `## Known Limitations and Deferred Work`; [allowlisted packages](../scripts/verify-readme-limitations.ts) end after it: | Context surface | What the model sees | Token effect | |---|---|---| -Rows name request surface, condition, and agent scope, then classify tokens as fixed per request, conditional per call, retained, replaced, capped, or zero-direct. Separate conversation and auxiliary calls; zero-direct rows name the indirect path. `verify-package-readme-model-experience` enforces shape and order; review owns accuracy. +Rows state what reaches which model and classify token cost or lifetime; zero-direct rows name the indirect path. `verify-package-readme-model-experience` gates shape and order, while review owns accuracy ([rationale](rfc/implemented/process/2026-07-12-package-model-experience-contract.md)). ## Wordcount Budgets diff --git a/packages/core/agent-loop/README.md b/packages/core/agent-loop/README.md index 981c13e656..b5d2a5f441 100644 --- a/packages/core/agent-loop/README.md +++ b/packages/core/agent-loop/README.md @@ -111,7 +111,7 @@ Everything that goes beyond "call the model, run the tools, repeat" belongs to p | Context surface | What the model sees | Token effect | |---|---|---| -| Complete conversation request | For each step, the loop sends the rendered per-agent system prompt, visible tool schemas, the frozen session prefix, and the session's derived messages. It supplies `model` and `cwd` variable values but no additional fixed prose. | System text, schemas, and prefix are paid again on every step. Per-agent scoping can substitute or remove individual contributions. | +| Complete conversation request | For each step, the loop sends the rendered per-agent system prompt, visible tool schemas, the frozen session prefix, and the session's derived messages. It supplies `model` and `cwd` variable values but no additional fixed prose. | System text, schemas, and prefix are paid again on every step. Per-agent scoping can substitute or remove ordinary contributions; owner-final protocol contributions retain their canonical state. | | Retained message history | Accepted user messages, assistant messages, tool calls and results, injected context, and steering are logged and sent on later steps. Raw stream chunks, lifecycle boundaries, and other log-only events are excluded. | Input grows with every surface message until a compaction replacement shadows older nodes; a multi-step tool turn resends the accumulated prefix and history each step. | ## Known Limitations and Deferred Work diff --git a/packages/core/scope/README.md b/packages/core/scope/README.md index bb8189e037..64e2df91ea 100644 --- a/packages/core/scope/README.md +++ b/packages/core/scope/README.md @@ -23,7 +23,7 @@ Handing out a scoped context hands out the minting plugin's service-resolution s | Context surface | What the model sees | Token effect | |---|---|---| -| Per-agent visibility control | This package emits no text or schema. It decides whether agent-scoped prompt sections, variables, tools, restrictions, and listeners apply to one agent, can shadow same-named global contributions, and removes them with that agent. | Zero direct tokens. It can add, replace, or remove whole contributions for one agent without changing another agent's request. | +| Per-agent visibility control | This package emits no text or schema. It routes scoped prompt sections, variables, tools, restrictions, and listeners to one agent: scoped registrations can shadow same-named globals, while restrictions filter global tools before scope-local tools are merged. All disappear with that agent. This is request composition, not authority confinement. | Zero direct tokens. It can add, replace, or remove whole contributions for one agent without changing another agent's request. | ## Known Limitations and Deferred Work diff --git a/packages/core/system-prompt/README.md b/packages/core/system-prompt/README.md index d7f5abcb0a..e17c72ba20 100644 --- a/packages/core/system-prompt/README.md +++ b/packages/core/system-prompt/README.md @@ -45,7 +45,7 @@ Design rationale: [the prompt-variables RFC](../../../docs/rfc/implemented/archi | Context surface | What the model sees | Token effect | |---|---|---| -| System prompt | Every assembly starts with `You are an AI agent powered by the DeepSeek Harness SDK.`, then the configured persona and ordered plugin sections after strict variable interpolation. Empty sections disappear; scoped sections and variables can shadow globals for one agent. | Identity is a fixed per-request cost. Persona and plugin text are repeated per request and scale with their rendered content. | +| System prompt | Every assembly starts with `You are an AI agent powered by the DeepSeek Harness SDK.`, then the configured persona and ordered plugin sections after strict variable interpolation. Empty sections disappear; ordinary scoped sections and variables can shadow globals for one agent, while owner-final contributions return to their canonical presence and definition after assembly interception. | Identity is a fixed per-request cost. Persona and plugin text are repeated per request and scale with their rendered content. | | Tool schemas | The model receives the collected, per-agent-visible tool names, descriptions, and JSON schemas in configured or lexicographic order after restrictions and assembly interception. | Schema tokens repeat on every request. Restricting a tool removes its entire schema cost for that agent; reordering changes cache shape but not semantic content. | ## Known Limitations and Deferred Work diff --git a/packages/core/tools/README.md b/packages/core/tools/README.md index 5a6f3da04c..04949af9a6 100644 --- a/packages/core/tools/README.md +++ b/packages/core/tools/README.md @@ -132,7 +132,7 @@ const bash = defineTool({ Under `mode: code` (or `both`) the registry turns the tool surface into a programming API, per the [Code Mode RFC](../../../docs/rfc/implemented/feature/2026-06-15-code-mode.md): the model writes a TypeScript program (the body of an async function) and passes it to the reserved wire transport `run_code`; the program runs in `ctx.codeRuntime` (the [code-execution seam](../../code-runtime/README.md) — the shipped backend is a worker thread) with one async binding per visible end-capability tool (`await tools.bash({...})`), and ONLY what it prints or returns re-enters the model's context. Scope restrictions change those SDK bindings but cannot remove or replace the transport itself. -- **The SDK section** (`tools:sdk`, order 150): a lazy prompt section regenerating, at each assembly, a `declare const tools: {...}` TypeScript declaration of the calling scope's visible end capabilities (exotic names via quoted keys), plus fixed usage instructions. The registry protects this section and the `run_code` wire schema after the assembly waterfall, so Code Mode cannot silently lose either half of its transport. Deterministic — lexicographic tool order, byte-identical text for an unchanged tool set (prefix-cache-friendly). The codegen (`jsonSchemaToTs`, exported) is total: constructs outside the `defineTool` subset degrade to `unknown`, never throw. +- **The SDK section** (`tools:sdk`, order 150): a lazy prompt section regenerating, at each assembly, a `declare const tools: {...}` TypeScript declaration of the calling scope's visible end capabilities (exotic names via quoted keys), plus fixed usage instructions. The registry marks this section and the `run_code` wire schema owner-final, so Code Mode cannot silently lose either half of its transport during assembly. Deterministic — lexicographic tool order, byte-identical text for an unchanged tool set (prefix-cache-friendly). The codegen (`jsonSchemaToTs`, exported) is total: constructs outside the `defineTool` subset degrade to `unknown`, never throw. - **The dispatch bridge** (`run_code`'s execute): every binding call is JSON-normalized before dispatch (a value that does not survive — `BigInt`, circulars — rejects that one call, so the dispatched form and logged form are the same JSON value by construction), serialized through a per-run queue (even `Promise.all` executes underlying calls one at a time in submission order), given the outer execution's opaque token as `parent`, and run through the complete pre-execute → guards → execute → post-execute → result pipeline. A denial reaches the program as a binding rejection, and each sub-call is logged as a `tool/code-dispatch` session event with deterministic id `:code:`; `deriveMessages()` does not surface that event. Token correlation lets commit-style observers defer an inner success until the final `run_code` result without exposing the live outer execution; ordinary tool side effects are not rolled back. A sub-call's `additionalContext` is deliberately dropped because inserting it inside a running parent call would break tool-call/result adjacency. - **Settlement discipline**: the bridge owns a run-scoped abort that follows the outer signal in and fires when the run settles for any reason, so a budget expiry aborts an in-flight sub-tool instead of orphaning it; the bridge then drains its queue BEFORE returning, so every `tool/code-dispatch` lands inside the open turn. A failed run throws `CodeRunFailedError` (`code: 'CODE_RUN_FAILED'`, message = the failure kind + captured logs), which the pipeline converts to a structured `isError` the model self-corrects from. @@ -142,7 +142,7 @@ The wire collapse is the registry's own contribution (`systemPrompt.tools()` is | Context surface | What the model sees | Token effect | |---|---|---| -| Tool schemas and Code Mode SDK | In normal mode the model sees each visible definition's name, description, and JSON schema. Code Mode instead protects one `run_code` wire schema and adds a generated TypeScript `tools` SDK section; `both` exposes both forms. Agent-scoped restrictions and shadows change that agent's set. | Fixed per-request cost proportional to the visible definitions. Code Mode trades end-tool schemas for generated SDK text plus one transport schema rather than promising a universal reduction. | +| Tool schemas and Code Mode SDK | In normal mode the model sees each visible definition's name, description, and JSON schema. Code Mode instead contributes one owner-final `run_code` wire schema and a generated owner-final TypeScript `tools` SDK section; `both` exposes both forms. Agent-scoped restrictions and shadows change that agent's end-tool set but cannot remove or replace the transport. | Fixed per-request cost proportional to the visible definitions. Code Mode trades end-tool schemas for generated SDK text plus one transport schema rather than promising a universal reduction. | | Tool-call history and results | The loop retains model-emitted arguments and the registry's final normalized content or structured error. Post-execute listeners may append source-attributed context after the result. Code Mode exposes only the outer program's printed or returned value; inner dispatch events stay log-only. | Arguments, results, and additional context are data-dependent and resent until compaction. Restrictions that hide tools also remove their schemas before the model can call them. | ## Known Limitations and Deferred Work diff --git a/packages/subagent/subagent-acp/README.md b/packages/subagent/subagent-acp/README.md index 5f5fbf8d2f..06c8180f88 100644 --- a/packages/subagent/subagent-acp/README.md +++ b/packages/subagent/subagent-acp/README.md @@ -61,7 +61,7 @@ Keyless tests drive a scripted ACP subprocess over real stdio. The with-key e2e | Context surface | What the model sees | Token effect | |---|---|---| -| Child-agent request | The remote child receives the standalone task through ACP plus its own process's configured system prompt, tools, and fresh session. It receives no parent conversation and cannot enforce the parent's scoped persona or tool filter. | The child pays for an independent full context and its own multi-step history. These tokens never enter the parent's context. | +| Child-agent request | The remote child receives the standalone task through ACP plus its own process's configured system prompt, tools, and fresh session. It receives no parent conversation. This provider advertises no optional start-time capabilities, so the local service rejects requests for persona, tool filtering, depth enforcement, or structured output instead of silently omitting them. | The child pays for an independent full context and its own multi-step history. These tokens never enter the parent's context. | | Parent tool result, indirectly | Through `dsh-tool-subagent`, the parent receives only the child's final streamed assistant text or a stop-reason error, not intermediate messages or tool traffic. | Parent input grows only by the final result, which is data-dependent and retained until compaction. This provider adds no parent schema itself. | ## Known Limitations and Deferred Work diff --git a/packages/subagent/subagent-fork/README.md b/packages/subagent/subagent-fork/README.md index b0d925689c..930c50836b 100644 --- a/packages/subagent/subagent-fork/README.md +++ b/packages/subagent/subagent-fork/README.md @@ -27,7 +27,7 @@ See [`dsh-subagent-spawn`](../subagent-spawn/README.md) for the run lifecycle, m | Context surface | What the model sees | Token effect | |---|---|---| -| Child-agent history | The child receives the parent's balanced completed-turn surface prefix, then the new task, along with its own scoped persona, tool filter, and optional structured-output contract. The parent's current in-flight turn is excluded. | Forking duplicates the retained completed history into a separate child's requests; the child then accumulates its own tokens independently. A first-turn fork has no inherited history. | +| Child-agent history | The child receives the parent's balanced completed-turn surface prefix, then the new task. Configured persona and tool restrictions compose only in the child's fresh scope; the parent's tool view and authority are not inherited. An optional structured-output request adds its child-only contract. The parent's current in-flight turn is excluded. | Forking duplicates the retained completed history into a separate child's requests; the child then accumulates its own tokens independently. A first-turn fork has no inherited history. | | Parent tool result, indirectly | The parent receives only the child's own final output through `dsh-tool-subagent`, not the inherited prefix or intermediate work. | Parent input grows by one data-dependent final result retained until compaction. | ## Known Limitations and Deferred Work diff --git a/packages/subagent/subagent-inprocess/README.md b/packages/subagent/subagent-inprocess/README.md index 7aa8dcab19..9d8eea23e4 100644 --- a/packages/subagent/subagent-inprocess/README.md +++ b/packages/subagent/subagent-inprocess/README.md @@ -44,7 +44,7 @@ A clean turn that never commits the required structured value reports `error`; t | Context surface | What the model sees | Token effect | |---|---|---| -| Child-agent request | The shared driver sends the task as the child's user message and composes per-child scoped persona and tool restrictions. Structured runs add a scoped instruction plus `structured_output` in the visible schema or Code Mode SDK, then stop after a committed capture. Spawn supplies no history; fork supplies its balanced seed. | Child input is isolated from the parent and grows through the child's own steps. Structured output adds fixed instruction and capability tokens only to that child for that run. | +| Child-agent request | The shared driver sends the task as the child's user message and, when requested, composes persona and global-tool restrictions in the unpublished child's fresh scope; parent restrictions are not inherited. Structured runs add an owner-final scoped instruction plus `structured_output` in the visible schema or Code Mode SDK, then stop after a committed capture. Spawn supplies no history; fork supplies its balanced seed. | Child input is isolated from the parent and grows through the child's own steps. Optional persona, filtering, and structured-output changes affect only that child; structured output adds fixed instruction and capability tokens for the run. | | Parent result, indirectly | The driver extracts only the child's own last assistant output or captured structured value; seeded parent messages and intermediate child work do not become the result. | The parent receives one data-dependent result through the consumer; all other child tokens stay in the child session. | ## Known Limitations and Deferred Work diff --git a/packages/subagent/subagent-spawn/README.md b/packages/subagent/subagent-spawn/README.md index 27e7f0a270..8ad605d68b 100644 --- a/packages/subagent/subagent-spawn/README.md +++ b/packages/subagent/subagent-spawn/README.md @@ -22,7 +22,7 @@ Spawn advertises `{ outputSchema: true, depthLimit: true, toolFilter: true, pers | Context surface | What the model sees | Token effect | |---|---|---| -| Child-agent request | The fresh child receives the standalone task, inherits the parent model and workspace by default, and sees the globally composed prompt and tools after its scoped persona and tool filter. It receives zero parent conversation messages. | The child pays for a new independent context and history; no parent-history tokens are duplicated. | +| Child-agent request | The fresh child receives the standalone task, inherits the parent model and workspace by default, and sees the globally composed prompt and tools after any configured child-scoped persona shadow and global-tool restriction. It receives zero parent conversation messages; the filter is visibility/composition, not an authority grant inherited from the parent. | The child pays for a new independent context and history; no parent-history tokens are duplicated. Persona or filtering changes only this child's repeated prompt/schema cost. | | Parent tool result, indirectly | Through `dsh-tool-subagent`, the parent receives only the child's final output or stop-reason error. | Parent input grows by one data-dependent result retained until compaction. | ## Known Limitations and Deferred Work diff --git a/packages/subagent/tool-subagent/README.md b/packages/subagent/tool-subagent/README.md index 58bea7cd2a..94b4df9f99 100644 --- a/packages/subagent/tool-subagent/README.md +++ b/packages/subagent/tool-subagent/README.md @@ -31,7 +31,7 @@ A non-`completed` stop reason becomes an `isError` tool result; partial child ou | Context surface | What the model sees | Token effect | |---|---|---| -| Tool schema | While the configured provider exists, the parent model sees one `{ description, prompt }` tool under `toolName`. Its description explicitly says whether the child inherits completed turns or needs a standalone prompt; persona, model, filter, depth, and provider choice remain deployment config. | Fixed schema cost per parent request while mounted. Removing the provider removes the whole schema; exposing multiple providers adds one independently named schema per load. | +| Tool schema | While the configured provider exists, the parent model sees one `{ description, prompt }` tool under `toolName`. Its description explicitly says whether the child inherits completed turns or needs a standalone prompt; persona, model, filter, depth, and provider choice remain deployment config. The filter changes the child's visible global tools, not an inherited authority ceiling. | Fixed schema cost per parent request while mounted. Removing the provider removes the whole schema; exposing multiple providers adds one independently named schema per load. | | Tool-call history and result | The task description and full prompt remain in the parent assistant tool call. The result contains only the child's final text or a stop-reason error, never intermediate child steps. | Prompt and final output are data-dependent retained tokens. All child working context is paid in the child and omitted from the parent. | ## Known Limitations and Deferred Work