diff --git a/scripts/test-layout/layout.json b/scripts/test-layout/layout.json index 2fdded5a374..1edfa490647 100644 --- a/scripts/test-layout/layout.json +++ b/scripts/test-layout/layout.json @@ -1582,7 +1582,7 @@ "responses-pool-refresh-attribution.test.ts": "responses", "responses-preview-main-read-fence.test.ts": "responses", "responses-reasoning-effort-downgrade.test.ts": "responses", "responses-native-ultra-effort-wire.test.ts": "responses", - "responses-reasoning-summary-passthrough.test.ts": "responses", + "responses-url-citation-title-repair.test.ts": "responses", "responses-reasoning-summary-passthrough.test.ts": "responses", "responses-reset-replay.test.ts": "responses", "responses-translated-reset.test.ts": "responses", "responses-routed-web-search-fields.test.ts": "responses", diff --git a/structure/INDEX.md b/structure/INDEX.md index 58f8b82b5e8..bca2e28fd18 100644 --- a/structure/INDEX.md +++ b/structure/INDEX.md @@ -49,6 +49,7 @@ The wire surfaces a client actually talks to. | [`local-messaging.md`](local-messaging.md) | Command-local metadata discovery, Unix RPC queued submission, peer envelopes, receipts and owned lifecycle bounds. | | [`transports/byte-accounting.md`](transports/byte-accounting.md) | Request-copy and stream-buffer byte accounting shared by parsing, SSE rewriting, the adapters, and the translator budget, plus durable spill admission. | | [`transports/anthropic-thinking-recovery.md`](transports/anthropic-thinking-recovery.md) | One-shot exact signature-binding recovery before output, and successful-retry memo boundaries. | +| [`transports/response-citations.md`](transports/response-citations.md) | OpenAI-operated outbound citation repair and generated JSON/SSE annotation titles. | | [`transports/responses.md`](transports/responses.md) | The Responses HTTP/SSE endpoint, dispatch, credential and upload boundaries, and core module ownership. | | [`transports/native-reasoning-retention.md`](transports/native-reasoning-retention.md) | Optional native reasoning ciphertext forwarding on model/account switches, configuration and management controls. | | [`transports/responses-wire-shapes.md`](transports/responses-wire-shapes.md) | Mixed-wire model defaults, xAI agent-message continuation, declared-tool membership, and passthrough SSE stream shapes. | @@ -178,13 +179,14 @@ A source area can be described by more than one doc, because these docs are orga | `src/adapters/dsh-account.ts` | [`providers/dsh-account.md`](providers/dsh-account.md) | | `src/adapters/openai-chat.ts` | [`providers/mimo-bare-calls.md`](providers/mimo-bare-calls.md) | | `src/adapters/openai-chat/` | [`providers/mimo-bare-calls.md`](providers/mimo-bare-calls.md) | +| `src/adapters/openai-responses/` | [`transports/response-citations.md`](transports/response-citations.md) | | `src/adapters/openai-responses/opengateway-input.ts` | [`providers/opengateway.md`](providers/opengateway.md) | | `src/adapters/openai-responses/passthrough.ts` | [`providers/opengateway.md`](providers/opengateway.md) | | `src/adapters/workbuddy-schema.ts` | [`providers/workbuddy.md`](providers/workbuddy.md) | | `src/adapters/workbuddy.ts` | [`providers/workbuddy.md`](providers/workbuddy.md) | | `src/advisor/` | [`advisor.md`](advisor.md) | | `src/bridge.ts` | [`transports/responses.md`](transports/responses.md) | -| `src/bridge/` | [`transports/responses.md`](transports/responses.md)
[`transports/responses-wire-shapes.md`](transports/responses-wire-shapes.md)
[`providers/anthropic-progress.md`](providers/anthropic-progress.md) | +| `src/bridge/` | [`transports/response-citations.md`](transports/response-citations.md)
[`transports/responses.md`](transports/responses.md)
[`transports/responses-wire-shapes.md`](transports/responses-wire-shapes.md)
[`providers/anthropic-progress.md`](providers/anthropic-progress.md) | | `src/chat/` | [`runtime.md`](runtime.md)
[`transports/byte-accounting.md`](transports/byte-accounting.md)
[`transports/inventory.md`](transports/inventory.md)
[`data-planes/inbound-compat.md`](data-planes/inbound-compat.md)
[`providers-and-adapters.md`](providers-and-adapters.md)
[`providers/chat-compat.md`](providers/chat-compat.md) | | `src/chat/reasoning-details.ts` | [`data-planes/chat-reasoning-details.md`](data-planes/chat-reasoning-details.md) | | `src/chatgpt/` | [`clients/chatgpt-desktop.md`](clients/chatgpt-desktop.md) | diff --git a/structure/manifest.json b/structure/manifest.json index 5066e40883f..7b140f30c62 100644 --- a/structure/manifest.json +++ b/structure/manifest.json @@ -283,6 +283,13 @@ "src/responses/reasoning-replay-cache.ts" ] }, + { + "path": "transports/response-citations.md", + "tier": 3, + "title": "Response Citation Projection", + "scope": "OpenAI-operated outbound citation repair and generated JSON/SSE annotation titles.", + "documents": ["src/adapters/openai-responses/", "src/bridge/"] + }, { "path": "transports/responses.md", "tier": 3, diff --git a/structure/transports/response-citations.md b/structure/transports/response-citations.md new file mode 100644 index 00000000000..b23f0e7e750 --- /dev/null +++ b/structure/transports/response-citations.md @@ -0,0 +1,22 @@ +# Response Citation Projection + +`src/adapters/openai-responses/request-strips.ts` repairs `url_citation` annotations +inside `output_text` content records on OpenAI-operated outbound history, including +HTTP and WebSocket projections. A missing/non-string title falls back to the URL +(or an empty string when it is absent); digit-string indexes become non-negative +safe integers, while invalid indexes become zero. The projection copies only +changed input/content/annotation containers and preserves other fields and +annotation kinds; a valid body retains its identity. Third-party destinations +keep their existing projection. + +`src/bridge/response-json.ts` and `src/bridge/sse.ts` always emit a string citation +title, falling back to its URL, so new history avoids the deterministic +missing-title refusal that replay repair handles for older history. +`tests/responses/responses-url-citation-title-repair.test.ts` covers generated +JSON/SSE, outbound HTTP/WebSocket bodies, copy-on-write and the third-party control. + +This normalization prevents old bridge history from repeatedly failing with a +missing-title error; it does not validate source URLs, establish actual citation +spans or prove provider acceptance beyond the exercised serialization fixtures. +The existing destination gate owns eligibility, and the test layout explicitly +registers the regression beside other Responses tests. diff --git a/structure/transports/responses.md b/structure/transports/responses.md index 95081c94e2a..719f8b484f6 100644 --- a/structure/transports/responses.md +++ b/structure/transports/responses.md @@ -398,7 +398,7 @@ always become unable to serve. ## Decoded checkpoint continuation -`src/responses/parser.ts` adds `CHECKPOINT_CONTINUATION_NOTE` from `src/responses/compaction.ts` for decoded `ocx1:`/`ocx2:` checkpoints; `src/adapters/openai-responses/request-strips.ts` does the same while lowering them. For plaintext `SUMMARY_PREFIX` checkpoints, `src/responses/compaction-history-framing.ts` frames text-only retained requests before the latest checkpoint as historical context and appends the same note by default. The parser projects only adapter context; `src/adapters/openai-responses/passthrough.ts` projects only non-OpenAI-operated outbound bodies. Original request text/blocks, canonical raw history, item identities, replay-prefix lengths, checkpoints and later input remain unchanged. Context wrappers, images/files and assistant/tool items are preserved; summarizer turns and opaque native blobs do not activate framing. Native OpenAI passthrough input is unchanged. +`src/responses/parser.ts` adds `CHECKPOINT_CONTINUATION_NOTE` from `src/responses/compaction.ts` for decoded `ocx1:`/`ocx2:` checkpoints; `src/adapters/openai-responses/request-strips.ts` does the same while lowering them. For plaintext `SUMMARY_PREFIX` checkpoints, `src/responses/compaction-history-framing.ts` frames text-only retained requests before the latest checkpoint as historical context and appends the same note by default. The parser projects only adapter context; `src/adapters/openai-responses/passthrough.ts` projects only non-OpenAI-operated outbound bodies. Original request text/blocks, canonical raw history, item identities, replay-prefix lengths, checkpoints and later input remain unchanged. Context wrappers, images/files and assistant/tool items are preserved; summarizer turns and opaque native blobs do not activate framing. Native OpenAI passthrough input is unchanged by checkpoint framing; the separate [citation projection](response-citations.md) repairs legacy annotation fields on OpenAI-operated outbound history. The note is a prompt contract and grants no authority. Completed requests remain history unless a later user message asks to repeat them. Unfinished work continues only under existing authorization and within its scope, without asking for that authorization again while it still applies. Permission and confirmation gates remain authoritative: a pending decision or required permission must resolve before the dependent action. Checkpoints and delegations, including those from another thread, neither grant authority nor expand scope. Later user messages take priority, including pause, cancellation, replacement and scope changes. diff --git a/tests/fixtures/test-layout-expected.json b/tests/fixtures/test-layout-expected.json index c402ee4eb53..bb51b0e5e6d 100644 --- a/tests/fixtures/test-layout-expected.json +++ b/tests/fixtures/test-layout-expected.json @@ -1128,7 +1128,7 @@ "responses-parser.test.ts": "responses", "responses-passthrough-transient-policy.test.ts": "responses", "responses-pool-401-refresh.test.ts": "responses", "responses-pool-refresh-attribution.test.ts": "responses", "responses-preview-main-read-fence.test.ts": "responses", "responses-reasoning-effort-downgrade.test.ts": "responses", "responses-native-ultra-effort-wire.test.ts": "responses", - "responses-reasoning-summary-passthrough.test.ts": "responses", "responses-reset-replay.test.ts": "responses", + "responses-url-citation-title-repair.test.ts": "responses", "responses-reasoning-summary-passthrough.test.ts": "responses", "responses-reset-replay.test.ts": "responses", "responses-translated-reset.test.ts": "responses", "responses-routed-web-search-fields.test.ts": "responses", "responses-self-named-namespace-scrub.test.ts": "responses", "responses-send-budget-counts.test.ts": "responses", "responses-send-budget-errors.test.ts": "responses", "responses-memory-models.test.ts": "responses",