docs(rfc): propose nine simplification RFCs from a five-domain survey

Survey of master for surface area whose consumers are tests/docs only,
classified per candidate (production vs non-production corpus, rg + call-site
reads). New proposed/simplification RFCs:

- prune-producerless-vocabulary-variants: CacheHint/cache? fields,
  MessageSource 'agent', TurnTrigger 'continuation' (the TurnEndReasonMap
  omitted-until-emitted policy, applied)
- drop-inert-request-knobs: GenerateOptions.prefill (both adapters throw
  UNSUPPORTED), ToolSchema.strict (zero setters; beta-URL-only feature)
- drop-web-providers-change-event: the llm/adapter-change precedent replayed
- drop-image-content-block: no producer; every consumer silently drops it
- prune-write-only-fs-surface: fs-local STREAM_MIN_SIZE/streamMinSize,
  FsTarget.inputPath, FsEditOutcome.replacements/replaceAll,
  FileReadOutcome.limit/version
- prune-unimplemented-subagent-vocabulary: outputSchema/structured,
  toolFilter, sendMessage/resume (depthLimit stays)
- trim-acp-bridge-unreachable-surface: agentName/agentVersion knobs
  (resolves TODO(double-default)), toolKindFor name-sniffing
- prune-dead-core-spine-surface: SurfaceManager.invalidate(), runLoop/Inbox
  exports, ToolExecutionResult.callId
- share-app-bin-boot-glue: the twin coverage-exempt bin helpers

Also supplements three existing proposed RFCs with survey evidence: the bash
seam consumption census (generic-long-running-tool-runtime), three more
static inventories (discover-package-inventory), and the bridge's already-1:1
id usage (unify-agent-and-session-id).
This commit is contained in:
Tianyi Cui
2026-07-04 03:00:25 +08:00
parent b735c766c6
commit e13bbcb5d5
13 changed files with 284 additions and 2 deletions

View File

@@ -0,0 +1,33 @@
# RFC: Drop `GenerateOptions.prefill` and `ToolSchema.strict` — request knobs with no working end-to-end path
Status: proposed
## Problem
Two request-contract knobs ride the whole request pipeline, yet neither can do anything today:
- **`prefill`** (`packages/llm/llm/src/types.ts`) has no production setter — the loop assembles `model`/`system`/`tools`/`messages` plus `sessionId`/`signal`, and the compaction backend adds only `maxTokens` — and BOTH adapters reject it: `packages/llm/llm-deepseek/src/serialize.ts` and `packages/llm/llm-pi-ai/src/adapter.ts` each throw `LlmError('UNSUPPORTED')` on a non-undefined `prefill`. The field's entire observable behavior is two throws, each pinned by one adapter test. DeepSeek's chat-prefix completion is a Beta feature on a base URL neither adapter targets.
- **`strict`** (`ToolSchema`, same file) is threaded through `DefineToolOptions`/`defineTool` (`packages/core/tools/src/schema.ts`), the registry's `schemas()` allowlist (`packages/core/tools/src/index.ts`), the deepseek wire mapping (`packages/llm/llm-deepseek/src/serialize.ts`, whose wire-type note records that strict mode requires the `/beta` base URL the adapter does not use), and a per-tool payload-patching pass in `packages/llm/llm-pi-ai/src/adapter.ts`. No shipped tool sets it — `rg` across every `tool-*` package src and `examples/` finds zero `strict:` producers; the only setters are dsh-tools unit tests.
Both knobs are adapter-symmetric, so removal sheds them from both twins together — the [twin-adapter design](../../implemented/architecture/2026-06-13-twin-llm-adapters.md) is untouched.
## Proposal
- Remove `prefill` from `GenerateOptions`, both adapters' UNSUPPORTED guards, the tests pinning the throws, the paste lines in [core.md](../../../core-data-structures/core.md), and the adapter README rows documenting the rejection.
- Remove `strict` from `ToolSchema`, `DefineToolOptions`, `defineTool`, and the `schemas()` allowlist; drop the deepseek serializer branch; simplify the pi-ai payload fixup to the unconditional scrub of pi-ai's own strict default (that half exists for wire parity with the hand-rolled twin and survives); drop the setter tests and the core.md paste line.
This RFC deliberately does NOT touch `temperature`, `stop`, or `maxTokens`: those are honored end-to-end by both adapters and are the natural first targets of a request-mutating hook plugin on `agent/request`.
## Why not keep them?
"An explicit UNSUPPORTED throw is honest contract behavior" — but a knob whose only implementation across both twins is rejection promises nothing, and deleting it upgrades the failure mode: an accidental setter becomes a compile error instead of a runtime throw. "Strict schema adherence is an officially documented provider feature with complete plumbing" — but a knob is not product surface until a shipped tool sets it AND an endpoint honors it; today neither is true. Each returns with its first real producer: `prefill` together with an adapter that implements chat-prefix completion (and a stated policy for adapters that do not), `strict` together with a tool that wants it and a beta-endpoint story.
## Acceptance criteria
- `rg prefill` and a tool-schema-scoped `rg strict` return only this RFC (and unrelated prose such as `strictEqual`).
- Both adapters compile and their contract tests pass without the guards; the pi-ai fixup still scrubs the library's strict default (wire parity pinned by its serializer tests).
- Doc pastes and the type-equiv manifest in sync; `pnpm run doc-sync` green.
## Risks
A hooks/config plugin arriving via the interception seams may want to set request fields — it will reach for `temperature`/`stop` (kept, working), not a field adapters reject. If chat-prefix completion or strict mode become product features, the re-add lands with the adapter/endpoint work, where the contract can say what actually happens rather than "everyone throws".