From 3567d000c4516879d4359a13769174732968251b Mon Sep 17 00:00:00 2001 From: Tianyi Cui <53024+tianyicui@users.noreply.github.com> Date: Sat, 4 Jul 2026 17:50:50 +0800 Subject: [PATCH 1/3] =?UTF-8?q?refactor(vocab):=20prune=20producer-less=20?= =?UTF-8?q?variants=20=E2=80=94=20cache=20hints,=20agent=20source,=20conti?= =?UTF-8?q?nuation=20trigger?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The vocabulary maps grow by declaration merging, and the admission policy stated on TurnEndReasonMap is that a variant lands with its first emitter. Three declared items had no producer and no consumer: - CacheHint and the cache?: CacheHint fields on TextBlock/ToolResultBlock: nothing constructs a block with cache:, and neither adapter reads .cache — DeepSeek prompt caching is automatic (hints map OUT of responses, never IN). - MessageSourceMap.agent: zero constructors; the subagent backends send the parent prompt with no source (logs as user), and the envelope renderer interpolates source.kind without routing on it. - TurnTriggerMap.continuation: the loop structurally cannot emit it — continuation is further steps within a turn, never a new turn — and its only writer was an llm-replay test fixture that needed any non-message trigger (now an injection trigger). Each variant returns the day it gains a real producer, via the same merge-extensible maps. Docs updated in the same change: the MessageSourceMap paste in core.md, the TurnTriggerMap paste in session.md (manifest untouched — both symbols survive), the content-block vocabulary RFC's cache-hints consequence line, and the RFC moved to implemented/ and amended to shipped reality (the image block's own cache field had already left with the drop-image RFC). --- docs/core-data-structures/core.md | 1 - docs/core-data-structures/session.md | 1 - docs/rfc/README.md | 2 +- .../2026-06-11-content-block-vocabulary.md | 2 +- ...-prune-producerless-vocabulary-variants.md | 31 +++++++++++++++++++ ...-prune-producerless-vocabulary-variants.md | 31 ------------------- packages/core/session/src/types.ts | 1 - packages/llm/llm/src/types.ts | 6 ---- .../llm-replay/tests/llm-replay.spec.ts | 2 +- 9 files changed, 34 insertions(+), 43 deletions(-) create mode 100644 docs/rfc/implemented/simplification/2026-07-04-prune-producerless-vocabulary-variants.md delete mode 100644 docs/rfc/proposed/simplification/2026-07-04-prune-producerless-vocabulary-variants.md diff --git a/docs/core-data-structures/core.md b/docs/core-data-structures/core.md index e2f3cd35f5..e8f5c05f10 100644 --- a/docs/core-data-structures/core.md +++ b/docs/core-data-structures/core.md @@ -107,7 +107,6 @@ Where a message came from is itself a merge-extensible sum type: interface MessageSourceMap { user: { kind: 'user' } plugin: { kind: 'plugin'; plugin: string } - agent: { kind: 'agent'; agentId: string } } ``` diff --git a/docs/core-data-structures/session.md b/docs/core-data-structures/session.md index 900fdc54fa..2ef01596d4 100644 --- a/docs/core-data-structures/session.md +++ b/docs/core-data-structures/session.md @@ -164,7 +164,6 @@ Everything else (`turn/*`, `step/*`) is structural and does not project into a m ```ts type-equiv interface TurnTriggerMap { message: { kind: 'message'; source: MessageSource } - continuation: { kind: 'continuation' } /** * An out-of-band context injection (`agent.inject()`) made while the agent * was idle. The loop wraps the injected `context/message` in a one-shot turn diff --git a/docs/rfc/README.md b/docs/rfc/README.md index f0987d2e65..0c6944bf40 100644 --- a/docs/rfc/README.md +++ b/docs/rfc/README.md @@ -56,7 +56,6 @@ Do NOT write one for a mechanical or local choice (a variable name, a one-file r | [Drop the unconsumed web observation surface — the `providers-change` event and the status methods](proposed/simplification/2026-07-04-drop-unconsumed-web-observation-surface.md) | 2026-07-04 | | [Fold the stdio UI helper into the stdio app](proposed/simplification/2026-07-04-fold-stdio-ui-helper.md) | 2026-07-04 | | [Prune dead core-spine surface — `SurfaceManager.invalidate()`, the loop-internal exports, `ToolExecutionResult.callId`](proposed/simplification/2026-07-04-prune-dead-core-spine-surface.md) | 2026-07-04 | -| [Prune producer-less vocabulary variants (block cache hints, the `agent` message source, the `continuation` turn trigger)](proposed/simplification/2026-07-04-prune-producerless-vocabulary-variants.md) | 2026-07-04 | | [Prune write-only fields and a dead routing knob from the fs seam](proposed/simplification/2026-07-04-prune-write-only-fs-surface.md) | 2026-07-04 | | [Remove the `agent/steering` mirror emit](proposed/simplification/2026-07-04-remove-agent-steering-mirror.md) | 2026-07-04 | | [Share the app bins' boot glue instead of maintaining twin copies](proposed/simplification/2026-07-04-share-app-bin-boot-glue.md) | 2026-07-04 | @@ -120,6 +119,7 @@ Do NOT write one for a mechanical or local choice (a variable name, a one-file r | [Split the filesystem seam — provider text mutations plus the `dsh-fs-policy` plugin](implemented/simplification/2026-06-26-fsspec-style-fs-seam.md) | 2026-06-26 | | [Stop mirroring the token stream as an agent event](implemented/simplification/2026-07-02-remove-stream-chunk-mirror.md) | 2026-07-02 | | [Drop the `image` content block until a path can honor it](implemented/simplification/2026-07-04-drop-image-content-block.md) | 2026-07-04 | +| [Prune producer-less vocabulary variants (block cache hints, the `agent` message source, the `continuation` turn trigger)](implemented/simplification/2026-07-04-prune-producerless-vocabulary-variants.md) | 2026-07-04 | ### Architecture diff --git a/docs/rfc/implemented/architecture/2026-06-11-content-block-vocabulary.md b/docs/rfc/implemented/architecture/2026-06-11-content-block-vocabulary.md index d2d2162588..619ada6f13 100644 --- a/docs/rfc/implemented/architecture/2026-06-11-content-block-vocabulary.md +++ b/docs/rfc/implemented/architecture/2026-06-11-content-block-vocabulary.md @@ -16,6 +16,6 @@ In-session context injection (`context/message`, `steering/message`) renders as ## Consequences -- Reasoning, prefill, and cache hints have a home without provider contortions. Multimodal content deliberately has NO core block type: the core set is limited to blocks every shipping path honors, and a multimodal feature adds its block type through the merge-extensible map in the same coordinated change that maps it in the adapters, surfaces it in the UI bridges, and prices it in compaction — see [the drop-image RFC](../simplification/2026-07-04-drop-image-content-block.md). +- Reasoning and prefill have a home without provider contortions. Multimodal content deliberately has NO core block type: the core set is limited to blocks every shipping path honors, and a multimodal feature adds its block type through the merge-extensible map in the same coordinated change that maps it in the adapters, surfaces it in the UI bridges, and prices it in compaction — see [the drop-image RFC](../simplification/2026-07-04-drop-image-content-block.md). Block cache hints likewise have no core field: DeepSeek prompt caching is automatic, so no shipping adapter can transmit a hint; a caching feature adds a `cache` field together with the adapter that honors it — see [the producer-less-variants RFC](../simplification/2026-07-04-prune-producerless-vocabulary-variants.md). - Every adapter pays a translation cost; the first real adapters have since validated the streaming protocol, and new adapters should continue proving their provider-specific mapping in adapter-local tests. - IDs that cross package boundaries are branded (`CallId`, `SessionId`, `AgentId`) — nominal typing at zero runtime cost. diff --git a/docs/rfc/implemented/simplification/2026-07-04-prune-producerless-vocabulary-variants.md b/docs/rfc/implemented/simplification/2026-07-04-prune-producerless-vocabulary-variants.md new file mode 100644 index 0000000000..b0fedc990e --- /dev/null +++ b/docs/rfc/implemented/simplification/2026-07-04-prune-producerless-vocabulary-variants.md @@ -0,0 +1,31 @@ +# RFC: Prune producer-less vocabulary variants (block cache hints, the `agent` message source, the `continuation` turn trigger) + +Status: implemented (proposed and accepted 2026-07-04) + +## Problem + +The merge-extensible vocabulary maps are designed to grow by declaration merging, and the codebase already states the admission policy on `TurnEndReasonMap` (`packages/core/session/src/types.ts`): a variant like `refusal` is "deliberately omitted until" an adapter or loop first emits it. Three declared vocabulary items violated that policy — each had no producer and no consumer, and two had not even a test: + +- **`CacheHint` and its `cache?: CacheHint` block fields** on `TextBlock`/`ToolResultBlock` (`packages/llm/llm/src/types.ts`; the image block carried a third such field, which left with it — see [the drop-image RFC](2026-07-04-drop-image-content-block.md)). Nothing constructed a block with `cache:` anywhere — src, tests, and doc pastes all came up empty — and neither adapter read `.cache`: DeepSeek prompt caching is automatic, so the adapters map `prompt_cache_hit_tokens` OUT of responses without ever sending a hint IN. This was Anthropic-style `cache_control` surface with no provider that could honor it. +- **`MessageSourceMap.agent`** (`{ kind: 'agent'; agentId: string }`, same file). Zero constructors, tests included. Its intended producer shipped without it: the subagent backends send the parent's prompt to the child with no `source`, so it logs as `{ kind: 'user' }`, and the generic envelope renderer interpolates `source.kind` without ever routing on it. +- **`TurnTriggerMap.continuation`** (`packages/core/session/src/types.ts`). The loop structurally cannot emit it — continuation happens *within* a turn as further steps, never as a new turn — and it constructs only `message` and `injection` triggers. The only writer was one hand-built test fixture needing an arbitrary non-message trigger (`packages/support/llm-replay/tests/llm-replay.spec.ts`), which an `injection` trigger serves equally; the only production trigger reader, the ACP bridge, filters on `kind === 'message'`. + +## Decision + +`CacheHint` with both `cache?` fields, the `agent` message-source variant, and the `continuation` turn-trigger variant are deleted. The llm-replay fixture uses an `injection` trigger (any non-`message` trigger serves its purpose). Updated in the same change: the type-equiv pastes in [core.md](../../../core-data-structures/core.md) and [session.md](../../../core-data-structures/session.md) (`scripts/type-equiv.manifest.json` is untouched — both pasted symbols survive, each minus a member), and the [content-block vocabulary RFC](../architecture/2026-06-11-content-block-vocabulary.md)'s consequence line that had named cache hints as having a home, per [implemented/AGENTS.md](../AGENTS.md). + +Each variant returns the day it gains a real producer, exactly as the maps are designed to grow: a caching feature re-adds `cache` together with the adapter that transmits it; subagent attribution re-adds `agent` together with the backend that stamps it and a consumer that routes on it; an auto-continue feature that genuinely starts new turns re-adds `continuation` with the plugin that emits it. + +## Why not keep them? + +The [content-block vocabulary RFC](../architecture/2026-06-11-content-block-vocabulary.md) listed "cache hints … have a home" as a design consequence, and reserved slots do advertise intent. But an empty slot is contract surface every implementation and consumer must consider (must my adapter honor `cache`? must my renderer route `agent` sources?), and the sibling map's own JSDoc already rejects reservation-without-emitter — `refusal` and `max_turn_requests` are named as variants to add *when something first emits them*, not declared in advance. Holding already-declared dead variants to the same standard makes the vocabulary mean something: if it is in the map, something produces it. + +## Acceptance criteria + +- `rg` for `CacheHint`, the `agent` message-source spelling, and the `continuation` trigger spelling returns only RFC records (this one, and [the drop-image RFC](2026-07-04-drop-image-content-block.md)'s account of the image block's own `cache` field). +- The core-data-structures pastes and the type-equiv manifest are in sync (`pnpm run doc-sync` green). +- The fixture asserts the same replay behavior with an `injection` trigger; the suite is green. + +## Risks + +None operational — nothing could construct these values. The mirror-event removals (recorded in [the boundary-mirror RFC](2026-06-20-remove-agent-boundary-mirror-events.md) and [the stream-chunk RFC](2026-07-02-remove-stream-chunk-mirror.md)) touch only transient `agent/*` events, never the durable vocabulary, so there is no collision. Elsewhere in the vocabulary the admission policy already holds: `rejected`, `prompt/blocked`, and `hook/invoked`/`hook/result` each have live producers — this RFC extends the same bar to the three variants that lacked one. [The image-block removal](2026-07-04-drop-image-content-block.md) shipped first, taking the image block's `cache?` field with it; this change removed the two that remained. diff --git a/docs/rfc/proposed/simplification/2026-07-04-prune-producerless-vocabulary-variants.md b/docs/rfc/proposed/simplification/2026-07-04-prune-producerless-vocabulary-variants.md deleted file mode 100644 index 38565c9214..0000000000 --- a/docs/rfc/proposed/simplification/2026-07-04-prune-producerless-vocabulary-variants.md +++ /dev/null @@ -1,31 +0,0 @@ -# RFC: Prune producer-less vocabulary variants (block cache hints, the `agent` message source, the `continuation` turn trigger) - -Status: proposed - -## Problem - -The merge-extensible vocabulary maps are designed to grow by declaration merging, and the codebase already states the admission policy on `TurnEndReasonMap` (`packages/core/session/src/types.ts`): a variant like `refusal` is "deliberately omitted until" an adapter or loop first emits it. Three declared vocabulary items violate that policy — each has no producer and no consumer, and two have not even a test: - -- **`CacheHint` and the three `cache?: CacheHint` fields** on `TextBlock`/`ToolResultBlock`/`ImageBlock` (`packages/llm/llm/src/types.ts`). Nothing constructs a block with `cache:` anywhere — src, tests, and doc pastes all come up empty — and neither adapter reads `.cache`: DeepSeek prompt caching is automatic, so the adapters map `prompt_cache_hit_tokens` OUT of responses without ever sending a hint IN. This is Anthropic-style `cache_control` surface with no provider that can honor it. -- **`MessageSourceMap.agent`** (`{ kind: 'agent'; agentId: string }`, same file). Zero constructors, tests included. Its intended producer shipped without it: the subagent backends send the parent's prompt to the child with no `source`, so it logs as `{ kind: 'user' }`, and the generic envelope renderer interpolates `source.kind` without ever routing on it. The variant is pasted into [core.md](../../../core-data-structures/core.md). -- **`TurnTriggerMap.continuation`** (`packages/core/session/src/types.ts`). The loop structurally cannot emit it — continuation happens *within* a turn as further steps, never as a new turn — and it constructs only `message` and `injection` triggers. The only writer is one hand-built test fixture that needs an arbitrary non-message trigger (`packages/support/llm-replay/tests/llm-replay.spec.ts`); the only production trigger reader, the ACP bridge, filters on `kind === 'message'`. The variant is pasted into [session.md](../../../core-data-structures/session.md). - -## Proposal - -Delete `CacheHint` with its three `cache?` fields, the `agent` message-source variant, and the `continuation` turn-trigger variant. Switch the llm-replay fixture to an `injection` trigger (any non-`message` trigger serves its purpose). Update the type-equiv pastes in [core.md](../../../core-data-structures/core.md) and [session.md](../../../core-data-structures/session.md) (and `scripts/type-equiv.manifest.json` where block identity shifts) in the same change, and amend the [content-block vocabulary RFC](../../implemented/architecture/2026-06-11-content-block-vocabulary.md)'s consequence line naming cache hints as having a home, per [implemented/AGENTS.md](../../implemented/AGENTS.md). - -Each variant returns the day it gains a real producer, exactly as the maps are designed to grow: a caching feature re-adds `cache` together with the adapter that transmits it; subagent attribution re-adds `agent` together with the backend that stamps it and a consumer that routes on it; an auto-continue feature that genuinely starts new turns re-adds `continuation` with the plugin that emits it. - -## Why not keep them? - -The [content-block vocabulary RFC](../../implemented/architecture/2026-06-11-content-block-vocabulary.md) lists "cache hints … have a home" as a design consequence, and reserved slots do advertise intent. But an empty slot is contract surface every implementation and consumer must consider (must my adapter honor `cache`? must my renderer route `agent` sources?), and the sibling map's own JSDoc already rejects reservation-without-emitter — `refusal` and `max_turn_requests` are named as variants to add *when something first emits them*, not declared in advance. Holding already-declared dead variants to the same standard makes the vocabulary mean something: if it is in the map, something produces it. - -## Acceptance criteria - -- `rg` for `CacheHint`, the `agent` message-source spelling, and the `continuation` trigger spelling returns only this RFC. -- The core-data-structures pastes and the type-equiv manifest are in sync (`pnpm run doc-sync` green). -- The fixture asserts the same replay behavior with an `injection` trigger; the suite is green. - -## Risks - -None operational — nothing can construct these values today. The mirror-event removals (recorded in [the boundary-mirror RFC](../../implemented/simplification/2026-06-20-remove-agent-boundary-mirror-events.md) and [the stream-chunk RFC](../../implemented/simplification/2026-07-02-remove-stream-chunk-mirror.md)) touch only transient `agent/*` events, never the durable vocabulary, so there is no collision. Elsewhere in the vocabulary the admission policy already holds: `rejected`, `prompt/blocked`, and `hook/invoked`/`hook/result` each have live producers — this RFC extends the same bar to the three variants that lack one. If the [image-block RFC](../../implemented/simplification/2026-07-04-drop-image-content-block.md) ships first, one of the three `cache?` fields leaves with it; the two proposals are independent and compose in either order. diff --git a/packages/core/session/src/types.ts b/packages/core/session/src/types.ts index b9a4c3b89b..27aaf580bc 100644 --- a/packages/core/session/src/types.ts +++ b/packages/core/session/src/types.ts @@ -91,7 +91,6 @@ export interface CreateSessionOptions { */ export interface TurnTriggerMap { message: { kind: 'message'; source: MessageSource } - continuation: { kind: 'continuation' } /** * An out-of-band context injection (`agent.inject()`) made while the agent * was idle. The loop wraps the injected `context/message` in a one-shot turn diff --git a/packages/llm/llm/src/types.ts b/packages/llm/llm/src/types.ts index fbfc7eb523..61d4769ffa 100644 --- a/packages/llm/llm/src/types.ts +++ b/packages/llm/llm/src/types.ts @@ -22,14 +22,10 @@ import type { Branded } from '@deepseek-ai/dsh-brand' import type { CallId } from './brand.ts' -/** Cache hint attached to a content block (provider-interpreted). */ -export type CacheHint = 'ephemeral' - /** Plain text visible to the end user. */ export interface TextBlock { type: 'text' text: string - cache?: CacheHint } /** Reasoning / thinking content, distinct from visible text. */ @@ -54,7 +50,6 @@ export interface ToolResultBlock { toolCallId: CallId content: ContentBlock[] isError?: boolean - cache?: CacheHint } /** @@ -91,7 +86,6 @@ export interface Message { export interface MessageSourceMap { user: { kind: 'user' } plugin: { kind: 'plugin'; plugin: string } - agent: { kind: 'agent'; agentId: string } } export type MessageSource = MessageSourceMap[keyof MessageSourceMap] diff --git a/packages/support/llm-replay/tests/llm-replay.spec.ts b/packages/support/llm-replay/tests/llm-replay.spec.ts index 2dd8357cc7..87cc62d165 100644 --- a/packages/support/llm-replay/tests/llm-replay.spec.ts +++ b/packages/support/llm-replay/tests/llm-replay.spec.ts @@ -118,7 +118,7 @@ describe('deriveReplayScript', () => { it('ignores non-assistant/chunk events', () => { let seq = 1 const events: SessionEvent[] = [ - { type: 'turn/start', seq: seq++, time: 0, data: { turn: 1, trigger: { kind: 'continuation' } } }, + { type: 'turn/start', seq: seq++, time: 0, data: { turn: 1, trigger: { kind: 'injection', source: { kind: 'user' } } } }, ...TEXT_CHUNKS.map(c => chunkEvent(seq++, 1, 1, c)), { type: 'turn/end', seq: seq++, time: 0, data: { turn: 1, reason: { kind: 'completed' } } }, ] From 75b97e7463496ea148308997a0723b0f1c03d509 Mon Sep 17 00:00:00 2001 From: Tianyi Cui <53024+tianyicui@users.noreply.github.com> Date: Sat, 4 Jul 2026 18:04:26 +0800 Subject: [PATCH 2/3] docs(rfc): state the pruned-vocabulary RFC as current facts, not patch mechanics The Decision and Risks paragraphs described the change relative to the patch that landed it (what was updated together, what another change took first). An implemented RFC reads as standing truth: the pastes match the pruned maps, the manifest rows remain because the symbols survive, and the image block's cache field belongs to the drop-image RFC's record. --- ...4-prune-producerless-vocabulary-variants.md | 4 ++-- verdict | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 verdict diff --git a/docs/rfc/implemented/simplification/2026-07-04-prune-producerless-vocabulary-variants.md b/docs/rfc/implemented/simplification/2026-07-04-prune-producerless-vocabulary-variants.md index b0fedc990e..d938f3eafb 100644 --- a/docs/rfc/implemented/simplification/2026-07-04-prune-producerless-vocabulary-variants.md +++ b/docs/rfc/implemented/simplification/2026-07-04-prune-producerless-vocabulary-variants.md @@ -12,7 +12,7 @@ The merge-extensible vocabulary maps are designed to grow by declaration merging ## Decision -`CacheHint` with both `cache?` fields, the `agent` message-source variant, and the `continuation` turn-trigger variant are deleted. The llm-replay fixture uses an `injection` trigger (any non-`message` trigger serves its purpose). Updated in the same change: the type-equiv pastes in [core.md](../../../core-data-structures/core.md) and [session.md](../../../core-data-structures/session.md) (`scripts/type-equiv.manifest.json` is untouched — both pasted symbols survive, each minus a member), and the [content-block vocabulary RFC](../architecture/2026-06-11-content-block-vocabulary.md)'s consequence line that had named cache hints as having a home, per [implemented/AGENTS.md](../AGENTS.md). +`CacheHint`, its `cache?` block fields, the `agent` message-source variant, and the `continuation` turn-trigger variant are deleted: the shipped vocabulary carries none of them. The llm-replay fixture uses an `injection` trigger (any non-`message` trigger serves its purpose). The type-equiv pastes in [core.md](../../../core-data-structures/core.md) and [session.md](../../../core-data-structures/session.md) match the pruned maps — both symbols keep their rows in `scripts/type-equiv.manifest.json`, since each map survives minus a member — and the [content-block vocabulary RFC](../architecture/2026-06-11-content-block-vocabulary.md)'s consequences record cache hints as producer-gated rather than as having a home, per [implemented/AGENTS.md](../AGENTS.md). Each variant returns the day it gains a real producer, exactly as the maps are designed to grow: a caching feature re-adds `cache` together with the adapter that transmits it; subagent attribution re-adds `agent` together with the backend that stamps it and a consumer that routes on it; an auto-continue feature that genuinely starts new turns re-adds `continuation` with the plugin that emits it. @@ -28,4 +28,4 @@ The [content-block vocabulary RFC](../architecture/2026-06-11-content-block-voca ## Risks -None operational — nothing could construct these values. The mirror-event removals (recorded in [the boundary-mirror RFC](2026-06-20-remove-agent-boundary-mirror-events.md) and [the stream-chunk RFC](2026-07-02-remove-stream-chunk-mirror.md)) touch only transient `agent/*` events, never the durable vocabulary, so there is no collision. Elsewhere in the vocabulary the admission policy already holds: `rejected`, `prompt/blocked`, and `hook/invoked`/`hook/result` each have live producers — this RFC extends the same bar to the three variants that lacked one. [The image-block removal](2026-07-04-drop-image-content-block.md) shipped first, taking the image block's `cache?` field with it; this change removed the two that remained. +None operational — nothing could construct these values. The mirror-event removals (recorded in [the boundary-mirror RFC](2026-06-20-remove-agent-boundary-mirror-events.md) and [the stream-chunk RFC](2026-07-02-remove-stream-chunk-mirror.md)) touch only transient `agent/*` events, never the durable vocabulary, so there is no collision. Elsewhere in the vocabulary the admission policy already holds: `rejected`, `prompt/blocked`, and `hook/invoked`/`hook/result` each have live producers — this RFC extends the same bar to the three variants that lacked one. The image block's own `cache?` field belongs to [the drop-image RFC](2026-07-04-drop-image-content-block.md), which removed it together with the block; this RFC covers the two fields on the block types that remain. diff --git a/verdict b/verdict new file mode 100644 index 0000000000..d43803f7a9 --- /dev/null +++ b/verdict @@ -0,0 +1,18 @@ +(A) merge-blocker +- `docs/rfc/implemented/simplification/2026-07-04-prune-producerless-vocabulary-variants.md:15` and `docs/rfc/implemented/simplification/2026-07-04-prune-producerless-vocabulary-variants.md:31` still narrate this PR/change history instead of just the shipped/current state: "Updated in the same change", "`scripts/type-equiv.manifest.json` is untouched", "shipped first", and "this change removed". The review spec asks for current-state prose only, and the house rules prohibit process narration in docs/comments. Reword these as present facts about the live vocabulary/catalogs rather than mechanics of this patch. + +(B) non-blocking +- None. + +(C) nitpick +- None. + +Evidence checked +- Producer-less claims are accurate: exact `cache:` block constructors are gone except this RFC record (`rg "\bcache\s*:"`), exact `{ kind: 'agent' }` constructors are gone (`rg "\{\s*kind:\s*['\"]agent['\"]\s*[,}]"`), and exact `{ kind: 'continuation' }` constructors are gone (`rg "\{\s*kind:\s*['\"]continuation['\"]\s*[,}]"`). +- The loop constructs `message` at `packages/core/agent-loop/src/loop.ts:284` and `injection` at `packages/core/agent-loop/src/agent.ts:145`; production `trigger.kind` readers are the ACP message filters at `packages/ui/acp/src/index.ts:352` and `packages/ui/acp/src/index.ts:385`. +- The subagent prompt path sends without a source at `packages/subagent/subagent-inprocess/src/index.ts:155`, and missing sources default to `{ kind: 'user' }` at `packages/core/agent-loop/src/agent.ts:103`. +- The core-data-structures pastes no longer include the removed variants: `docs/core-data-structures/core.md:107` and `docs/core-data-structures/session.md:165`. +- The llm-replay fixture still proves `deriveReplayScript` ignores non-`assistant/chunk` events: the test includes `turn/start`/`turn/end` around chunks at `packages/support/llm-replay/tests/llm-replay.spec.ts:118`, while the implementation skips all non-chunk events at `packages/support/llm-replay/src/index.ts:195`. +- Checks run: `pnpm exec vitest run packages/support/llm-replay/tests/llm-replay.spec.ts` (51 passed), `pnpm run doc-sync` (passed), `git diff --check origin/simpl-a1-drop-image...HEAD` (passed), precise EOF check on touched files (passed), and `pnpm run typecheck` (passed). + +Verdict: NO-SHIP as it stands, due to the implemented RFC process-narration blocker above. From 2825aa6fdc0ab6232417c3002a76bfe0688fc271 Mon Sep 17 00:00:00 2001 From: Tianyi Cui <53024+tianyicui@users.noreply.github.com> Date: Sat, 4 Jul 2026 18:06:30 +0800 Subject: [PATCH 3/3] chore: drop a stray review scratch file A reviewer's working notes (an untracked 'verdict' file at the repo root) were swept into the previous commit by a blanket git add; the file is no part of the change. --- verdict | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 verdict diff --git a/verdict b/verdict deleted file mode 100644 index d43803f7a9..0000000000 --- a/verdict +++ /dev/null @@ -1,18 +0,0 @@ -(A) merge-blocker -- `docs/rfc/implemented/simplification/2026-07-04-prune-producerless-vocabulary-variants.md:15` and `docs/rfc/implemented/simplification/2026-07-04-prune-producerless-vocabulary-variants.md:31` still narrate this PR/change history instead of just the shipped/current state: "Updated in the same change", "`scripts/type-equiv.manifest.json` is untouched", "shipped first", and "this change removed". The review spec asks for current-state prose only, and the house rules prohibit process narration in docs/comments. Reword these as present facts about the live vocabulary/catalogs rather than mechanics of this patch. - -(B) non-blocking -- None. - -(C) nitpick -- None. - -Evidence checked -- Producer-less claims are accurate: exact `cache:` block constructors are gone except this RFC record (`rg "\bcache\s*:"`), exact `{ kind: 'agent' }` constructors are gone (`rg "\{\s*kind:\s*['\"]agent['\"]\s*[,}]"`), and exact `{ kind: 'continuation' }` constructors are gone (`rg "\{\s*kind:\s*['\"]continuation['\"]\s*[,}]"`). -- The loop constructs `message` at `packages/core/agent-loop/src/loop.ts:284` and `injection` at `packages/core/agent-loop/src/agent.ts:145`; production `trigger.kind` readers are the ACP message filters at `packages/ui/acp/src/index.ts:352` and `packages/ui/acp/src/index.ts:385`. -- The subagent prompt path sends without a source at `packages/subagent/subagent-inprocess/src/index.ts:155`, and missing sources default to `{ kind: 'user' }` at `packages/core/agent-loop/src/agent.ts:103`. -- The core-data-structures pastes no longer include the removed variants: `docs/core-data-structures/core.md:107` and `docs/core-data-structures/session.md:165`. -- The llm-replay fixture still proves `deriveReplayScript` ignores non-`assistant/chunk` events: the test includes `turn/start`/`turn/end` around chunks at `packages/support/llm-replay/tests/llm-replay.spec.ts:118`, while the implementation skips all non-chunk events at `packages/support/llm-replay/src/index.ts:195`. -- Checks run: `pnpm exec vitest run packages/support/llm-replay/tests/llm-replay.spec.ts` (51 passed), `pnpm run doc-sync` (passed), `git diff --check origin/simpl-a1-drop-image...HEAD` (passed), precise EOF check on touched files (passed), and `pnpm run typecheck` (passed). - -Verdict: NO-SHIP as it stands, due to the implemented RFC process-narration blocker above.