docs: classify consumer-owned model effects as indirect
This commit is contained in:
@@ -68,7 +68,7 @@ Long stable prompt or schema description, copied exactly from source.
|
||||
|
||||
Fill Model Experience from the implementation. Direct, multi-surface, conditional, capped, or lifetime effects use one H3 block per context surface; each block has the exact bold-led `What the model sees` and `Token effect` fields shown above. Quote short stable model-visible source literals verbatim in inline code, using named placeholders such as `<mode>` only for interpolated values. Put a long stable prompt or schema description under the optional exact `### Verbatim model-visible text` heading: give each literal an H4 title and its own `markdown` fence, then link it from the relevant context surface. Summarize only data-dependent payloads, provider-owned text, or schemas too large to reproduce, and identify their exact shape and renderer. Do not infer prompt visibility from tool-schema visibility because independently registered guidance can remain after a scoped tool restriction.
|
||||
|
||||
An audited package with no context effect or one simple consumer-owned path joins [`SENTENCE_MODEL_EXPERIENCE`](../../scripts/verify-package-readme-model-experience.ts) and replaces the structured blocks with one line beginning `None, as ` or `Indirectly, through `. Every package outside that allowlist keeps one or more context-surface blocks; the verifier gates their H3 headings, field labels, spacing, and the optional verbatim appendix's H4-plus-`markdown`-fence shape. A package with genuinely no limitations joins the separate allowlist in [`verify-readme-limitations.ts`](../../scripts/verify-readme-limitations.ts) and ends after Model Experience. The [Model Experience RFC](../rfc/implemented/process/2026-07-12-package-model-experience-contract.md) records the rationale.
|
||||
An audited package with no context effect or one simple consumer-owned path belongs in [`SENTENCE_MODEL_EXPERIENCE`](../../scripts/verify-package-readme-model-experience.ts) and uses one line beginning `None, as ` or `Indirectly, through `. A provider backend whose single context path is formatted and inserted entirely by a named consumer uses the indirect sentence even when it caps or filters data before returning it; do not give it a structured block describing the consumer's work. Packages that register model input themselves, invoke a model, or own multiple context paths keep context-surface blocks; the verifier gates their H3 headings, field labels, spacing, and the optional verbatim appendix's H4-plus-`markdown`-fence shape. A package with genuinely no limitations joins the separate allowlist in [`verify-readme-limitations.ts`](../../scripts/verify-readme-limitations.ts) and ends after Model Experience. The [Model Experience RFC](../rfc/implemented/process/2026-07-12-package-model-experience-contract.md) records the rationale.
|
||||
|
||||
## 5. Verify
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ A package README can explain APIs and runtime mechanics without answering the qu
|
||||
|
||||
Every workspace package README ends with the canonical [Model Experience section](../../../cookbook/adding-a-package.md#4-write-the-package-readme), immediately before `## Known Limitations and Deferred Work`; a package on the no-limitations allowlist ends with Model Experience itself. Packages with direct, multi-surface, conditional, capped, or lifetime effects use one H3 block per context surface. Each block says what the relevant model literally receives and when under `**What the model sees**:`, then classifies the token effect under `**Token effect**:`. Short stable source literals are quoted verbatim in the first field, with named placeholders only for interpolated values. Long stable prompts or schema descriptions live in a `### Verbatim model-visible text` appendix after the context surfaces, one titled `markdown` fence per literal, and the relevant surface links to them. Summaries are reserved for data-dependent payloads, provider-owned text, or schemas too large to reproduce. The default subject is the conversation model; a package that invokes an auxiliary model, such as a summarizer or search provider, names that request separately. Agent-scoped visibility is stated where it changes which agent receives a contribution. Prompt text and tool schemas are described separately whenever configuration or scoping can hide one without the other.
|
||||
|
||||
Every package participates. A package with no model-context effect, or one simple effect rendered entirely by another package, can join the verifier's audited sentence allowlist. It then uses exactly one sentence beginning `None, as ` or `Indirectly, through ` instead of expanding a negative fact into a structured block. Implementations that shape results, caps, history, lifetimes, or more than one request surface keep the context-surface blocks even when they add zero direct prompt tokens.
|
||||
Every package participates. A package with no model-context effect, or one simple effect rendered entirely by another package, uses the verifier's audited sentence allowlist. It carries exactly one sentence beginning `None, as ` or `Indirectly, through ` instead of expanding a negative fact into a structured block. A provider backend whose single context path is formatted and inserted entirely by a named consumer uses the indirect sentence even when it caps or filters data before returning it. Packages that register model input themselves, invoke a model, or own multiple context paths keep the context-surface blocks even when they add zero direct prompt tokens.
|
||||
|
||||
`verify-package-readme-model-experience` discovers packages from `packages/*/*/package.json`, requires one sibling README and the canonical final-section order, and validates one of two package-classified bodies. An allowlisted package carries exactly one sentence with its assigned prefix; every other package carries at least one H3 context surface with the two exact, non-empty fields and one blank line between each element. Optional long literals follow the structured blocks under the exact appendix heading, with each H4 title paired to one non-empty `markdown` fence and linked from a model-view field. It runs in `doc-sync` and the parallel gate runner. The check owns package classification, structural presence, block and appendix shape, and order; implementation review owns coverage and the truth of the prose.
|
||||
|
||||
|
||||
@@ -27,11 +27,7 @@ Design surveyed against the bash tools of Claude Code, OpenCode, Codex, and pi;
|
||||
|
||||
## Model Experience
|
||||
|
||||
### Bash tool results, indirectly
|
||||
|
||||
**What the model sees**: Through `dsh-tool-bash`, the conversation model sees the data-dependent stdout and stderr tail inside that consumer's exact result wrappers, exit and timeout markers, background-task state, and a spill-file path when full output is available. This backend adds no prompt or schema itself. An unknown task becomes exactly `Error: unknown bash task "<taskId>"`; a pre-spawn cancellation becomes `Error: aborted before spawn: <reason>`.
|
||||
|
||||
**Token effect**: Zero tokens until a bash tool runs. Foreground output is bounded per stream by `maxOutputBytes`; background reads return only new output, so polling does not repeat already-delivered text. Results remain in history until compaction.
|
||||
Indirectly, through `dsh-tool-bash`, which renders this executor's bounded stdout/stderr tails, background-task deltas and state, spill-file path, exact `Error: unknown bash task "<taskId>"` and `Error: aborted before spawn: <reason>` failures, and retains each resulting tool message until compaction.
|
||||
|
||||
## Known Limitations and Deferred Work
|
||||
|
||||
|
||||
@@ -33,11 +33,7 @@ Every field is validated (positive numbers) and defaulted; there are no other tu
|
||||
|
||||
## Model Experience
|
||||
|
||||
### `run_code` result, indirectly
|
||||
|
||||
**What the model sees**: Through Code Mode in `dsh-tools`, the conversation model sees only what the program prints or returns. A log cap emits exactly `[dsh-code-runtime-worker] log capture truncated at <maxLogBytes> bytes`; an oversized or non-transferable return rendered as text ends exactly `… [truncated]`. Worker failures become `Error: code run failed (<kind>): <message>`; this backend's stable messages include `compute budget exhausted (<computeMs>ms busy)`, `wall-clock ceiling reached (<maxWallMs>ms)`, `worker error: <message>`, and `worker exited with code <code> before completing`. Binding-call traffic and worker internals stay outside context.
|
||||
|
||||
**Token effect**: Zero tokens until Code Mode executes a program. `maxLogBytes` and `maxValueBytes` cap the model-visible result, which then remains in tool history until compaction.
|
||||
Indirectly, through Code Mode in `dsh-tools`, which renders this worker's capped printed or returned data, exact `[dsh-code-runtime-worker] log capture truncated at <maxLogBytes> bytes` and `… [truncated]` markers, and `Error: code run failed (<kind>): <message>` failures into a retained `run_code` result while keeping binding traffic and worker internals outside context.
|
||||
|
||||
## Known Limitations and Deferred Work
|
||||
|
||||
|
||||
@@ -23,11 +23,7 @@ The raw I/O lives in `src/fsio.ts` (Cordis-free, independently unit-tested); `sr
|
||||
|
||||
## Model Experience
|
||||
|
||||
### Filesystem tool results, indirectly
|
||||
|
||||
**What the model sees**: Through `dsh-tool-fs`, the model sees line-windowed UTF-8 file content or mutation acknowledgements. This backend's stable failures are normalized as `Error: <message>`; messages include `cannot read "<path>": binary file`, `cannot <read-or-edit> "<path>": invalid UTF-8 text`, `cannot write "<path>": not a regular file`, `cannot write "<path>": file no longer exists`, `cannot <write-or-edit> "<path>": file changed since it was read`, `cannot overwrite existing "<path>" without reading it first`, `cannot edit "<path>": binary file`, `old_string must be a non-empty string`, `old_string was not found in "<path>"`, and `old_string matched <count> times in "<path>"; provide a more specific old_string or set replace_all to true`. Real paths, versions, atomic-write mechanics, and directory metadata remain internal unless a consumer renders them.
|
||||
|
||||
**Token effect**: Zero direct tokens. Read tokens are bounded by the tool's line, line-length, and byte caps; mutation results or errors remain in history until compaction.
|
||||
Indirectly, through `dsh-tool-fs`, which renders this provider's line-windowed UTF-8 content, mutation acknowledgements, and exact provider messages under `Error: <message>` into capped retained tool results while versions, atomic-write mechanics, and directory metadata remain internal.
|
||||
|
||||
## Known Limitations and Deferred Work
|
||||
|
||||
|
||||
@@ -19,11 +19,7 @@ Consumers: [`@deepseek-ai/dsh-bash-sandbox`](../../bash/bash-sandbox/); see [`ex
|
||||
|
||||
## Model Experience
|
||||
|
||||
### Sandbox result facts, indirectly
|
||||
|
||||
**What the model sees**: This provider adds no prompt or tool. It supplies the selected enforcement and denial dialect to `dsh-bash-sandbox`, which can become that consumer's exact `[sandbox: file access denied under <mode> mode]` marker. If no local runner can confine the command, the model instead receives the exact `SANDBOX_UNAVAILABLE` text quoted in [`dsh-sandbox`](../sandbox/README.md). Runner selection and profiles are not shown.
|
||||
|
||||
**Token effect**: Zero direct tokens; only the conditional marker or error reaches context through the bash consumer.
|
||||
Indirectly, through `dsh-bash-sandbox` and `dsh-tool-bash`, which render this provider's enforcement dialect as the exact `[sandbox: file access denied under <mode> mode]` marker or the [`dsh-sandbox`](../sandbox/README.md) `SANDBOX_UNAVAILABLE` text while keeping runner selection and profiles outside context.
|
||||
|
||||
## Known Limitations and Deferred Work
|
||||
|
||||
|
||||
@@ -12,11 +12,7 @@ Implementations: [`@deepseek-ai/dsh-sandbox-local`](../sandbox-local/) (Linux: `
|
||||
|
||||
## Model Experience
|
||||
|
||||
### Sandbox result, indirectly
|
||||
|
||||
**What the model sees**: Through `dsh-bash-sandbox` and `dsh-tool-bash`, enforcement facts may become that consumer's exact denial marker. `SandboxUnavailableError` becomes exactly `Error: sandbox mode "<mode>" is requested but no sandbox backend is usable on this host; refusing to run the command unconfined. Install bubblewrap or run a Landlock-enforcing kernel (Linux), ensure sandbox-exec is usable (macOS) — Windows has no confinement backend yet — or switch the consumer to danger-full-access.`, optionally followed by ` Runner failure: <detail>`.
|
||||
|
||||
**Token effect**: This package adds no prompt or schema. Only a denial or failed confinement adds retained result tokens.
|
||||
Indirectly, through [`dsh-bash-sandbox`](../../bash/bash-sandbox/README.md) and `dsh-tool-bash`, which render this seam's enforcement facts as the exact denial or `SandboxUnavailableError` text documented by the consumer, with retained tokens added only for a denial or failed confinement.
|
||||
|
||||
## Known Limitations and Deferred Work
|
||||
|
||||
|
||||
@@ -38,11 +38,7 @@ Skills can be single-level directory bundles (`<name>/SKILL.md`) or flat Markdow
|
||||
|
||||
## Model Experience
|
||||
|
||||
### Skill catalog and loaded body, indirectly
|
||||
|
||||
**What the model sees**: When `dsh-tool-skill` is visible, discovered model-invocable skill names and descriptions enter its session-prefix catalog; a `skill` call returns the selected instructions and resource-base guidance. Paths, provider ranks, and disabled skills stay out of the catalog.
|
||||
|
||||
**Token effect**: Zero direct tokens from this provider. Catalog cost scales with discovered entries under the consumer's per-description cap; a full body is added only after selection and remains in tool history.
|
||||
Indirectly, through `dsh-tool-skill`, which renders this provider's invocable names and capped descriptions into the session-prefix catalog and a selected instruction body plus resource-base guidance into retained tool history while paths, provider ranks, and disabled skills remain hidden.
|
||||
|
||||
## Known Limitations and Deferred Work
|
||||
|
||||
|
||||
@@ -62,11 +62,7 @@ The current model-facing tool collects synchronously: it awaits the child result
|
||||
|
||||
## Model Experience
|
||||
|
||||
### Delegation result, indirectly
|
||||
|
||||
**What the model sees**: Through `dsh-tool-subagent`, registered providers create child contexts and return data-dependent final output. A missing provider or unsupported requested capability becomes exactly `Error: no subagent provider registered for "<name>"` or `Error: subagent provider "<name>" does not support the "<capability>" capability`. Provider-specific start errors receive the same `Error: <message>` wrapper.
|
||||
|
||||
**Token effect**: This seam adds no parent schema itself. The parent retains only the final output or start error; child working tokens remain in the child.
|
||||
Indirectly, through `dsh-tool-subagent`, which retains only a provider's data-dependent final output or exact `Error: no subagent provider registered for "<name>"`, `Error: subagent provider "<name>" does not support the "<capability>" capability`, and `Error: <message>` start failures in the parent while child working tokens remain child-only.
|
||||
|
||||
## Known Limitations and Deferred Work
|
||||
|
||||
|
||||
@@ -25,11 +25,7 @@ This is the interface package. Model-facing consumers such as `@deepseek-ai/dsh-
|
||||
|
||||
## Model Experience
|
||||
|
||||
### Human-answer result, indirectly
|
||||
|
||||
**What the model sees**: Through `dsh-tool-ask-user`, a successful provider answer becomes that consumer's exact compact JSON result. Seam-level failures become exactly `Error: ask_user_question was aborted before the user answered`, `Error: ask_user_question requires at least one question`, or `Error: no user-interaction provider is registered`; provider-owned failures receive the same `Error: <message>` wrapper.
|
||||
|
||||
**Token effect**: This seam adds no prompt or schema. Only the consumer's completed or failed tool call adds retained tokens; waiting for the human adds none.
|
||||
Indirectly, through `dsh-tool-ask-user`, which retains a successful provider answer as compact JSON or the exact `Error: ask_user_question was aborted before the user answered`, `Error: ask_user_question requires at least one question`, `Error: no user-interaction provider is registered`, and `Error: <message>` failures while waiting for the human adds no tokens.
|
||||
|
||||
## Known Limitations and Deferred Work
|
||||
|
||||
|
||||
@@ -35,11 +35,7 @@ The numeric limits are validated at plugin construction: every cap except `maxRe
|
||||
|
||||
## Model Experience
|
||||
|
||||
### Web fetch result, indirectly
|
||||
|
||||
**What the model sees**: Through `dsh-tool-web`, the conversation model sees that consumer's exact fetch header plus the data-dependent decoded text or markdown-shaped HTML. This provider's stable failures become `Error: <message>`; messages include `web fetch aborted`, `web fetch timed out`, `web fetch failed: <error>`, `exceeded the maximum of <count> redirects`, `redirect response (HTTP <status>) without a Location header`, `invalid redirect Location "<location>"`, `cross-origin redirect to <origin> is not followed automatically; retry against that URL directly`, `unsupported content type "<type>"`, `response exceeds the maximum of <bytes> bytes`, `URL exceeds the maximum length of <chars>`, `invalid URL: <url>`, `unsupported URL scheme "<scheme>" (only http and https are allowed)`, `credentials in URLs are not allowed`, and `unsupported charset "<charset>"`. Redirects, headers, and transport mechanics are otherwise absent.
|
||||
|
||||
**Token effect**: Zero direct tokens. `maxBodyChars` bounds decoded result length before the tool records it; the retained result or error is resent until compaction.
|
||||
Indirectly, through `dsh-tool-web`, which renders this provider's `maxBodyChars`-bounded decoded text or markdown-shaped HTML under the exact fetch header and its stable failures under `Error: <message>` into retained tool history while redirects, headers, and transport mechanics remain hidden.
|
||||
|
||||
## Known Limitations and Deferred Work
|
||||
|
||||
|
||||
@@ -27,11 +27,7 @@ Exa returns a flat `results[]` and no generated answer, so `content` is omitted.
|
||||
|
||||
## Model Experience
|
||||
|
||||
### Web search result, indirectly
|
||||
|
||||
**What the model sees**: Through `dsh-tool-web`, the conversation model sees Exa result URLs, titles, first highlight snippets, and publication dates. No generated answer or provider-private response fields enter the tool result. Failures become `Error: Exa search aborted`, `Error: Exa search request failed: <error>`, or `Error: Exa returned an unprocessable response body: <error>`; HTTP failures pass through their provider message after `Error:`.
|
||||
|
||||
**Token effect**: Zero direct harness-model tokens. Result size scales with the bounded source list and snippets; the seam enforces `maxResults`, and retained results or errors remain until compaction.
|
||||
Indirectly, through `dsh-tool-web`, which retains this provider's `maxResults`-bounded URLs, titles, first highlights, and publication dates or exact `Error: Exa search aborted`, `Error: Exa search request failed: <error>`, and `Error: Exa returned an unprocessable response body: <error>` failures while generated answers and provider-private fields remain outside context.
|
||||
|
||||
## Known Limitations and Deferred Work
|
||||
|
||||
|
||||
@@ -45,11 +45,7 @@ The failure branches throw `WebError`, whose structured code (plus message detai
|
||||
|
||||
## Model Experience
|
||||
|
||||
### Search or fetch result, indirectly
|
||||
|
||||
**What the model sees**: Through `dsh-tool-web`, the model sees bounded normalized provider data. Selection failures become exactly `Error: configured web provider "<id>" is not registered`, `Error: configured web provider "<id>" is registered but unavailable`, `Error: no usable web provider is registered`, or `Error: multiple usable web providers are registered (<ids>); configure one explicitly`; provider failures use the same `Error: <message>` wrapper.
|
||||
|
||||
**Token effect**: This seam adds no prompt or schema. Only a call result or error adds retained tokens; source caps bound search output.
|
||||
Indirectly, through `dsh-tool-web`, which retains bounded normalized provider data or the exact configured-provider, unavailable-provider, no-provider, multiple-provider, and `Error: <message>` failures while this registry contributes no prompt or schema itself.
|
||||
|
||||
## Known Limitations and Deferred Work
|
||||
|
||||
|
||||
@@ -33,16 +33,27 @@ interface SentenceContract {
|
||||
*/
|
||||
const SENTENCE_MODEL_EXPERIENCE: Readonly<Record<string, SentenceContract>> = {
|
||||
'packages/bash/bash': { kind: 'indirect', reason: 'The service interface delegates all model rendering to dsh-tool-bash.' },
|
||||
'packages/bash/bash-local': { kind: 'indirect', reason: 'The executor backend delegates model rendering to dsh-tool-bash.' },
|
||||
'packages/code-runtime/code-runtime': { kind: 'indirect', reason: 'The service interface delegates model rendering to Code Mode in dsh-tools.' },
|
||||
'packages/code-runtime/code-runtime-worker': { kind: 'indirect', reason: 'The worker backend delegates model rendering to Code Mode in dsh-tools.' },
|
||||
'packages/fs/fs': { kind: 'indirect', reason: 'The service interface delegates model rendering to dsh-tool-fs.' },
|
||||
'packages/fs/fs-local': { kind: 'indirect', reason: 'The provider backend delegates model rendering to dsh-tool-fs.' },
|
||||
'packages/hooks/hook-protocol': { kind: 'indirect', reason: 'Only the hook bridge plugins render decoded hook output to a model.' },
|
||||
'packages/sandbox/sandbox': { kind: 'indirect', reason: 'Sandbox consumers render enforcement and availability facts.' },
|
||||
'packages/sandbox/sandbox-local': { kind: 'indirect', reason: 'The provider backend delegates model rendering to dsh-bash-sandbox and dsh-tool-bash.' },
|
||||
'packages/skill/skill': { kind: 'indirect', reason: 'The provider registry delegates model rendering to dsh-tool-skill.' },
|
||||
'packages/skill/skill-local': { kind: 'indirect', reason: 'The provider backend delegates model rendering to dsh-tool-skill.' },
|
||||
'packages/subagent/subagent': { kind: 'indirect', reason: 'The provider registry delegates parent-model rendering to dsh-tool-subagent.' },
|
||||
'packages/subagent/subagent-subprocess': { kind: 'indirect', reason: 'Only process-based subagent backends compose a child model request.' },
|
||||
'packages/support/acp-snapshot': { kind: 'none', reason: 'The test harness observes and normalizes transcripts without changing live requests.' },
|
||||
'packages/support/invariants': { kind: 'none', reason: 'The observer validates requests but never rewrites their context.' },
|
||||
'packages/ui/app-boot': { kind: 'indirect', reason: 'Only the loaded plugin tree contributes model context.' },
|
||||
'packages/ui/user-interaction': { kind: 'indirect', reason: 'Model-facing consumers render provider answers and seam errors.' },
|
||||
'packages/util/brand': { kind: 'none', reason: 'The type-only primitive is erased at compile time.' },
|
||||
'packages/util/timeout': { kind: 'indirect', reason: 'Only timeout consumers render timeout outcomes.' },
|
||||
'packages/web/web': { kind: 'indirect', reason: 'The provider registry delegates model rendering to dsh-tool-web.' },
|
||||
'packages/web/web-fetch-local': { kind: 'indirect', reason: 'The provider backend delegates model rendering to dsh-tool-web.' },
|
||||
'packages/web/web-search-exa': { kind: 'indirect', reason: 'The provider backend delegates model rendering to dsh-tool-web.' },
|
||||
'packages/workflow/workflow': { kind: 'indirect', reason: 'The service delegates parent and child model rendering to its consumer and engine.' },
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user