@volter/supercode-frontend-vscode 0.1.63 → 0.1.64

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -180,7 +180,9 @@ default is never stored as a choice (a pick equal to the default follows the def
180
180
  changes), and an Auto approve is never stored for a conversation that cannot answer. Conversations opened before 0.1.36 saved their picker's
181
181
  **Ask** when opened and keep it. Auto approve approves the requests the harness would ask you about, including requests to run
182
182
  outside its sandbox (Codex's approval requests are its sandbox escalations); the harness's deny
183
- rules still apply. Each request it answers is noted in the turn ("auto-approved: …"). A turn
183
+ rules still apply. A request it answers adds no line of its own: the call's row is the record (Code-OSS also says
184
+ "Auto approved" on that row, which the extension API cannot); a card already shown gets its answer as a line beneath
185
+ it, and an approval it could not answer has its card drawn again for the person to answer. A turn
184
186
  re-joined after a page reload (the conversation's active response) is answered the same way. Unsupported modes are refused. Unanswerable
185
187
  harnesses show **Harness permissions**. Previously answered requests cannot affect another
186
188
  connection. Native command-button fallback limitations are documented below.
@@ -296,7 +298,7 @@ Fresh snapshots also restore retained `history_events` before replay at the
296
298
  runtime's cursor. Their original sequences and payloads are preserved. Recovered
297
299
  unseen events reach existing response listeners, and an authoritative idle
298
300
  snapshot releases a restored response even when its terminal event is no longer
299
- retained. Chat states when older events are outside the bounded display window.
301
+ retained.
300
302
  An unavailable saved runtime returns an error in Chat instead of a blank draft.
301
303
  These are implemented source paths; real editor recovery and pending approval
302
304
  interaction remain unqualified.
@@ -322,53 +324,66 @@ request), and each part declares its own fallback.
322
324
  | `defaultChatParticipant` | `isDefault` — Volter Harness answers the Chat view with no `@` mention | the ordinary `@supercode` participant; a mention is required |
323
325
  | `chatParticipantAdditions` | `ChatToolInvocationPart` (with its terminal, todo-list and subagent data), `ChatResponseConfirmationPart`, `ChatResponseWarningPart`, `codeblockUri`, `ChatResponseThinkingProgressPart`, `ChatResponseHookPart`, `questionCarousel` | progress lines, labeled Markdown results, typed replies, plain fenced diffs, blockquoted reasoning, quoted hook lines, answer buttons |
324
326
  | `chatSessionsProvider` | the runtime's sessions in the Chat view's session picker, each reopening with its history | the participant still attaches; there is no session list |
325
- | `chatParticipantPrivate` | dynamic participant identity with the harness and provider icon | static participant identity |
327
+ | `chatParticipantPrivate` | dynamic participant identity with the harness and provider icon; an interrupted turn's error at warning level | static participant identity; the interruption is an ordinary error |
326
328
  | `chatProvider` | native fixed-model identity and provider icon | host new-chat configuration |
327
329
 
328
- ### Parity with Code-OSS's own chat parts
329
-
330
- Every chat response part and tool-row kind the pinned Code-OSS (`4a7cd45`, `src/vscode-dts`) offers an extension,
331
- and what this frontend does with it. **Native**: the harness's event is drawn as VS Code draws its own.
332
- **Fallback**: drawn, but with a plainer part than VS Code's own (why given). **Not used**: no harness event this
333
- frontend receives carries what the part shows. **Gap**: the event exists and the native part is not built yet.
334
- This count is the measure of done; a change that moves a row says so here.
335
-
336
- | Part / tool data | Status | What draws it, or why not |
337
- |---|---|---|
338
- | `ChatResponseMarkdownPart` | native | the agent's text |
339
- | `ChatResponseProgressPart` | native | status lines; a finished subagent task as one line |
340
- | `ChatResponseWarningPart` | native | warnings, failed turns, usage limits |
341
- | `ChatResponseThinkingProgressPart` | native | the agent's reasoning (a subagent's is not shown, as VS Code shows none) |
342
- | `ChatResponseReferencePart` | native | each file a Codex diff names |
343
- | `ChatResponseCommandButtonPart` | native | approval answers; Stop for a background task |
344
- | `ChatToolInvocationPart` | native | every tool call, updated in place with its result |
345
- | ↳ terminal data | native | shell calls: command and output |
346
- | ↳ todo-list data | native | Claude Code's TodoWrite and its task tools (TaskCreate, TaskUpdate, TaskList), and supercode's own `update_plan`, shown in VS Code's todo list. Codex app-server's plan (`turn/plan/updated`, not a tool call) is still a status line: fallback |
347
- | ↳ subagent data, `subAgentInvocationId` | native | Claude Code's Agent/Task call is the subagent row; its own calls are grouped under it (`parent_tool_use_id`) |
348
- | ↳ simple input/output data | native | any other finished call |
349
- | ↳ MCP data | fallback | an MCP call's result arrives as text, so it is the simple input/output |
350
- | ↳ resources data | not used | no tool event lists resources as such |
351
- | `ChatResponseHookPart` | native | a blocked prompt, a blocked tool call, a hook that failed (Claude Code). The extension API cannot place a hook inside a subagent row |
352
- | `ChatResponseQuestionCarouselPart` | native | an elicitation of questions (`ask_user`, Claude Code's AskUserQuestion) on a turn this window runs; command buttons on a re-joined response, where the pinned host never delivers the carousel's answer |
353
- | `ChatResponseConfirmationPart` | native / fallback | approvals, where the host advertises in-turn approval cards; command buttons otherwise (a stock confirmation answers with a new request) |
354
- | `ChatResponseCodeblockUriPart` | fallback | a Codex diff: `codeblockUri` with a fenced diff, not an edit (see *Why `diff_updated` is not an edit part*) |
355
- | `ChatResponseTextEditPart`, `ChatResponseNotebookEditPart`, `ChatResponseWorkspaceEditPart`, `ChatResponseMultiDiffPart`, `ChatResponseExternalEditPart` | **gap (known)** | native file edits with Keep/Undo and the multi-file diff: the harness has already written the files, and no event carries the before/after the editor needs |
356
- | `ChatResponseAnchorPart` | not used | no event names a location inline in text |
357
- | `ChatResponseFileTreePart` | not used | no event lists a file tree |
358
- | `ChatResponseMarkdownWithVulnerabilitiesPart` | not used | no harness reports vulnerabilities |
359
- | `ChatResponseCodeCitationPart` | not used | no harness reports a licensed citation |
360
- | `ChatResponseMovePart` | not used | no event moves a range |
361
- | `ChatResponseExtensionsPart` | not used | no harness recommends extensions |
362
- | `ChatResponsePullRequestPart` | not used | no structured event announces a pull request |
363
- | `ChatResponseInfoPart` | not used | informational records are warnings or are dropped as telemetry |
364
- | `ChatResponseAutoModeResolutionPart` | not used | the harness's model is the one chosen; there is no automatic routing to report |
365
- | `ChatResponseProgressPart2`, `ChatResponseReferencePart2` | not used | no event carries a resolvable task or a reference status |
366
- | `ChatResponseVoiceProgressPart` (`chatParticipantPrivate`) | not used | voice is not a harness event |
367
- | `stream.usage` | gap | token counts are dropped from the transcript; VS Code's own context indicator could show them and does not yet |
368
-
369
- Count, by row: 14 native (the confirmation card only where the host advertises it), 2 fallback (and Codex's plan
370
- inside the todo-list row), 12 not used, 2 gaps — native edits (the known gap, five parts in one row) and
371
- `stream.usage`.
330
+ ### Parity with Code-OSS's own chat
331
+
332
+ The measure is the event, not the API part: **does this event look as the pinned Code-OSS (`4a7cd45`, the fork
333
+ this product ships) draws its own equivalent event?** Using a native part for something VS Code never draws is not
334
+ parity. Each row names what Code-OSS itself draws, with its source, and what this frontend draws on the product's
335
+ host (all five proposals granted). **Native**: drawn as Code-OSS draws it. **Fallback**: drawn, but plainer than
336
+ Code-OSS's own (why given). **Gap (API)**: Code-OSS's own drawing is not reachable through the extension API at the
337
+ pin; the row names the fork change that would reach it. **Gap**: reachable, not built. This count is the measure of
338
+ done; a change that moves a row says so here. Paths are under `src/vs/` unless they start with `src/vscode-dts`.
339
+
340
+ | Event | Code-OSS draws its own as | This frontend | Status |
341
+ |---|---|---|---|
342
+ | The agent's text | markdown (`chatMarkdownContentPart.ts`) | `ChatResponseMarkdownPart`; a subagent's own text is not shown | native |
343
+ | The agent's reasoning, live and saved | thinking (`chatThinkingContentPart.ts`) | `ChatResponseThinkingProgressPart`, in history too | native |
344
+ | A tool call, started then finished | one tool row updated in place (`chatToolInvocationPart.ts`) | `ChatToolInvocationPart` with `enablePartialUpdate` | native |
345
+ | A shell call | the terminal row: command and output (`chatTerminalToolProgressPart.ts`) | terminal tool data | native |
346
+ | A call's work left running in the background (a background Bash, a Monitor, a subagent sent to the background) | Code-OSS's own Claude host (`platform/agentHost/node/claude/claudeToolDisplay.ts` `TOOL_ROWS`, lines 100-102) sets no `isBackground`: a background `Bash` is a terminal row that completes with its launch result; `BashOutput` ("Reading shell output") and `KillBash` ("Kill shell command") are terminal rows of their own. The person stops a task by asking the agent; current Claude Code (2.1.312) then calls `TaskStop` (which still answers to the old names `KillShell` and `KillBash`), which Code-OSS's table does not list, so it is an ordinary tool row there and here | the same: the Bash row completes with its launch result, and BashOutput and KillBash are terminal rows with Code-OSS's titles; the harness's listing of its background tasks draws nothing | native |
347
+ | Output a background-status call drained (`background_output`) | that call's own row (`get_terminal_output`'s row) | nothing more: the status call's row result already carries it | native |
348
+ | A plan (TodoWrite, the task tools, `update_plan`) | the todo list (`chatTodoListWidget.ts`) | todo-list tool data | native |
349
+ | Codex's plan (`turn/plan/updated`, not a call) | the todo list | a status line | fallback: no call carries it, and a todo list is a tool row |
350
+ | A subagent and its calls | the subagent row with its calls grouped under it (`chatSubagentContentPart.ts`) | subagent tool data, `subAgentInvocationId` | native |
351
+ | A hook that blocked or warned | the hook row (`chatHookContentPart.ts`) | `ChatResponseHookPart` | native; **gap (API)** inside a subagent: the part carries no subagent id |
352
+ | An approval | the confirmation card, answered in the running turn (`chatConfirmationContentPart.ts`; the fork's `volter.chat.inTurnApprovalCapability`, `volterHarness/volterChat.ts`) | `ChatResponseConfirmationPart` where the host advertises in-turn cards (this product's host does); command buttons on a stock host, whose confirmation answers with a new request | native; fallback on a stock host |
353
+ | A harness's questions | the question carousel (`chatQuestionCarouselPart.ts`) | the carousel on a turn this window runs; `Answer…` buttons on a re-joined response | native; **gap (API)** on a re-joined response: its stream has a resolver map no answer reaches (`extHostChatSessions.ts`). Fork: route `$handleQuestionCarouselAnswer` to the session's active-response stream |
354
+ | A request answered through its own card in this window | the card or carousel shows what was chosen (`chatConfirmationContentPart.ts`, `chatQuestionCarouselPart.ts`); the call's row carries on or ends denied | the same; a stock host's buttons stay, inert, and the status bar says what was sent | native |
355
+ | A request answered any other way (another window, Auto approve turned on after its card showed, a typed reply) | the card retires itself with the answer | its card stays live; one plain line beneath it says the answer | **gap (API)**: an extension cannot retire a confirmation or carousel it pushed. Fork: let a pushed `ChatResponseConfirmationPart` or question carousel be resolved by the extension (marked used with the chosen answer) |
356
+ | An approval answered automatically (Auto approve) | the call's row says "Auto approved …" (`chatToolPartUtilities.ts` `getApprovalMessageFromReason`, lines 58-80) | the call's row alone; an answer that fails or does not settle draws the approval's card again, as the one still waiting | **gap (API)**: `ChatToolInvocationPart` carries no confirmation reason. Fork: a proposed approval message (or reason) on `ChatToolInvocationPart`, passed through `extHostTypeConverters.ts` to the invocation's confirmed reason |
357
+ | A request this window cannot answer (another client holds it) | no read-only confirmation: another client's call is its row, "Running {0} on another client…", with a cancel action (`stateToProgressAdapter.ts` `toolCallStateToInvocation`) | its title and summary as words, no controls; its answer as a line beneath it | fallback: the extension API cannot draw another client's call |
358
+ | A turn that failed | the response's error (`agentHostSessionHandler.ts` `_getTurnErrorDetails`, `errorDetails`) | the request handler's `ChatResult.errorDetails` | native on a turn this window runs; **gap (API)** on a re-joined response and in history, which show VS Code's warning part with the error's words: the ext host ignores what `activeResponseCallback` returns (`extHostChatSessions.ts`) and `convertResponseTurn` drops `result.errorDetails`. Fork: let `activeResponseCallback` resolve a `ChatResult` whose `errorDetails` the main thread sets on the response (`response.setResult`, as `agentHostSessionHandler.ts` does), and pass `turn.result.errorDetails` through `convertResponseTurn` |
359
+ | A turn interrupted from elsewhere | the response's warning-level, expected error (`_getTurnErrorDetails`, `executionInterrupted`) | `errorDetails` with `level: Warning`, `isExpectedError` | native on a turn this window runs; **gap (API)** elsewhere, as above |
360
+ | A turn the person stopped | VS Code marks the response stopped | nothing more | native |
361
+ | A request Chat cannot run (no sign-in, no runtime, a refused send) | the request's error | a thrown error, which the workbench writes as the response's error | native |
362
+ | A transport or stream error while a turn may still run (`stream_error`, `transport_error`, `watch_error`, `runtime_disconnected`; a re-joined stream that fails; a conversation that cannot be recovered) | the response's error | VS Code's warning part with the error's words | fallback: the turn may still be running, so it is not ended with an error; a saved response cannot carry one (above) |
363
+ | A harness warning (`cache_warning`, `warning`, a usage limit) | the warning part (`chatErrorContentPart.ts`, warning level) | `ChatResponseWarningPart` | native |
364
+ | A harness record that is not the person's words (a background task's notification, live or saved; an interruption record) | a system notification row (`stateToProgressAdapter.ts` `systemNotificationToChatPart`; `claudeReplayMapper.ts` keeps `compact_boundary` and `notification`) | the notice's own words as a plain line, once per task (Claude Code reports a finished task both as `system/task_notification` and as the user-role record that wakes the agent; the saved transcript keeps only the latter, a `queued_command` attachment); not a progress part, which Code-OSS hides once any other part follows it (`chatProgressContentPart.ts`) | **gap (API)**: the extension API has no system-notification part. Fork: a proposed `ChatResponseSystemNotificationPart` converted to `{kind: 'systemNotification'}` in `extHostTypeConverters.ts` |
365
+ | A status line (`status`) | the progress message, hidden once another part follows (`chatProgressContentPart.ts`) | `ChatResponseProgressPart` | native |
366
+ | Input arriving from elsewhere while a turn runs | a request turn of its own (`agentHostSessionHandler.ts`, server-initiated turns) | **Additional input** and the words, inside the running response | **gap (API)**: an extension cannot add a request turn to an open session. Fork: let a session's provider append a request turn (end the active response and open the next with that prompt) |
367
+ | A prompt the runtime's scheduler starts | a request turn of its own | a plain line, "Scheduled prompt: …" | **gap (API)**, as above |
368
+ | A Codex diff | file edits with Keep/Undo and the multi-file diff (`chatTextEditContentPart.ts`, `chatMultiDiffContentPart.ts`) | `codeblockUri` with a fenced diff, plus one reference per file | **gap (known)**: the harness has already written the files and no event carries the before/after the editor needs (see *Why `diff_updated` is not an edit part*) |
369
+ | An MCP call | the MCP input/output row | the simple input/output row | fallback: its result arrives as text |
370
+ | Token usage | the context-window indicator (`stream.usage`) | not shown | **gap** |
371
+ | A protocol record (`native_event`, a kind this version does not know, a malformed request) | nothing | nothing; an unknown kind and a malformed request go to the output channel | native |
372
+ | Saved history | the same parts a live response draws | the same converter: tool rows, hooks, warnings, reasoning | native |
373
+ | History past its bound | left out without a word; a turn without its request gets "Message content could not be retrieved" (`claudeReplayMapper.ts` `missingPromptPlaceholder`) | the same | native |
374
+ | A call waiting on approval in re-joined history | its row, with its card on the active response | the same | native |
375
+
376
+ Count, by row (33): 22 native on this product's host, of which three (the questions, a failed turn, an interrupted
377
+ turn) are native only on a turn this window runs and an API gap on a re-joined response, and one (hooks) is an API gap
378
+ inside a subagent; 4 fallback; 5 API gaps (a request answered elsewhere, an automatic approval, harness records,
379
+ input from elsewhere, a scheduled prompt); 1 known gap (native edits); 1 gap not built (`stream.usage`). The fork
380
+ changes named above would close every API gap; none is made yet.
381
+
382
+ Parts the extension API offers that no harness event this frontend receives carries, so not used:
383
+ `ChatResponseAnchorPart`, `ChatResponseFileTreePart`, `ChatResponseMarkdownWithVulnerabilitiesPart`,
384
+ `ChatResponseCodeCitationPart`, `ChatResponseMovePart`, `ChatResponseExtensionsPart`, `ChatResponsePullRequestPart`,
385
+ `ChatResponseInfoPart`, `ChatResponseAutoModeResolutionPart`, `ChatResponseProgressPart2`,
386
+ `ChatResponseReferencePart2`, `ChatResponseVoiceProgressPart`, and the resources tool data.
372
387
 
373
388
  The session participant uses the exact session type id (`supercode`). With
374
389
  `chatParticipantPrivate`, the extension registers its dynamic identity directly and keeps
@@ -402,24 +417,25 @@ it needs and the fallback it degrades to. Each arm names the producer it reads.
402
417
  | Event kind | Producer | Rendered as |
403
418
  |---|---|---|
404
419
  | `text_delta` | `crates/runtime/src/event.rs` `AgentEvent::TextDelta` | `response.markdown` (streamed) |
405
- | `user_message` | `sdk/interchange/agent-runtime-host.mjs` accepted-turn projection; `runtime-native-projection.mjs` `claudeBlocks` for Claude's own user-role records (`source: harness`) | the request turn in history; dropped live (VS Code already shows it); a harness record shows its `notice` or nothing |
420
+ | `user_message` | `sdk/interchange/agent-runtime-host.mjs` accepted-turn projection; `runtime-native-projection.mjs` `claudeBlocks` for Claude's own user-role records (`source: harness`) | the request turn in history; dropped live (VS Code already shows it); a harness record shows its `notice` as a plain line, or nothing |
406
421
  | `turn_started` / `turn_completed` / `turn_succeeded` | `submit_claimed`; `AgentEvent::TurnCompleted` | lifecycle only — the handler resolves, nothing renders |
407
- | `turn_interrupted` | `submit_claimed` | an italic notice |
408
- | `turn_failed` | `submit_claimed` | `ChatResponseWarningPart` → blockquote |
422
+ | `turn_interrupted` | `submit_claimed` | the request handler's result: `errorDetails` at warning level; elsewhere `ChatResponseWarningPart` → its words |
423
+ | `turn_failed` | `submit_claimed` | the request handler's result: `errorDetails`; elsewhere `ChatResponseWarningPart` → blockquote |
409
424
  | `tool_call_started` / `tool_call_completed` | `AgentEvent::ToolCallStarted` / `ToolCallCompleted` | one `ChatToolInvocationPart` per call, updated in place with its result (`enablePartialUpdate`) → a progress line plus a labeled Markdown result |
410
425
  | `diff_updated` | `crates/codex-frontend/src/codex_app_server_v0_144.rs` (stock Codex `turn/diff/updated`) | `codeblockUri` + a fenced `diff` block, plus one stable `reference` per file the diff names → the fenced block alone |
411
- | `request` | `sdk/interchange/frontend-request-bridge.mjs` request publication | a titled markdown block plus one **command button per answer** — stable API, no proposal |
426
+ | `request` | `sdk/interchange/frontend-request-bridge.mjs` request publication | `ChatResponseConfirmationPart` where the host advertises in-turn cards, the question carousel for questions; else a titled markdown block plus one **command button per answer**. Read-only (title and summary) for a request this window cannot answer |
427
+ | `request_resolved` | `FrontendRequestBroker::respond` | nothing for a card answered through itself in this window; else one plain line beneath the card naming the answer |
412
428
  | `cache_warning` | `AgentEvent::CacheWarning` | `ChatResponseWarningPart` → blockquote |
413
429
  | `hook` | `runtime-native-projection.mjs` from Claude Code's failed `hook_response`, its blocked-prompt `informational` record, and a tool result in its own `PreToolUse:<tool> hook error:` words | `ChatResponseHookPart` ("Blocked by" / "Warning from" the hook) → blockquote |
414
- | `background_tasks` | `runtime-native-projection.mjs` from Claude Code's `background_tasks_changed` | nothing in the transcript: the turn lists them with a Stop each |
430
+ | `background_tasks` | `runtime-native-projection.mjs` from Claude Code's `background_tasks_changed` | nothing: a background command is its call's row, as in Code-OSS's own Claude host |
415
431
  | any event with `parent_id` | `runtime-native-projection.mjs` from Claude Code's `parent_tool_use_id` | a subagent's calls are grouped under its call; its own text, reasoning and input are not shown |
416
- | `usage` | `AgentEvent::Usage` | a progress line |
417
- | `background_output` | `AgentEvent::BackgroundOutput` | a fenced block, saying so when the runtime stopped retaining |
418
- | `scheduled_prompt_started` / `_deferred` / `_completed` | declared by `frontend_descriptor`'s `display.event_kinds` | a progress line |
419
- | `scheduler_error` | same | `ChatResponseWarningPart` → blockquote |
432
+ | `usage` | `AgentEvent::Usage` | nothing (see `stream.usage` in the parity table) |
433
+ | `background_output` | `sdk/interchange/agent-background.mjs` `status` | nothing: the status call's own row carries the output |
434
+ | `scheduled_prompt_started` / `_deferred` / `_completed` | declared by `agent-runtime-host.mjs` `displayKinds`; no producer here | started: a plain line, "Scheduled prompt: …"; deferred and completed: lifecycle only |
435
+ | `scheduler_error` | same | `ChatResponseWarningPart` with its words → blockquote |
420
436
  | `reasoning` / `thinking` | no producer in this repository; read because `sdk/interchange/frontend-transcript.mjs` reads them | `ChatResponseThinkingProgressPart` → blockquote |
421
- | `stream_error` / `transport_error` / `watch_error` / `runtime_disconnected` | `crates/opencode-frontend/src/server.rs`; `crates/interchange/src/watch.rs`; synthesized by a frontend (`sdk/interchange/frontend-app.mjs`); `stream_error` has no producer here | `ChatResponseWarningPart` → blockquote |
422
- | anything else | opaque by contract | one **bounded** markdown cell that names the kind and shows the payload — never dropped |
437
+ | `stream_error` / `transport_error` / `watch_error` / `runtime_disconnected` | `crates/opencode-frontend/src/server.rs`; `crates/interchange/src/watch.rs`; synthesized by a frontend (`sdk/interchange/frontend-app.mjs`); `stream_error` has no producer here | `ChatResponseWarningPart` with its words → blockquote |
438
+ | anything else | opaque by contract | nothing in the transcript; written to the output channel |
423
439
 
424
440
  **Why `diff_updated` is not an edit part.** Measured: the payload carries one unified-diff *string*
425
441
  and nothing else. `ChatResponseTextEditPart` wants ranges and the runtime has already written the
@@ -446,7 +462,7 @@ invisible is one nobody can trust. A pushed command button cannot be withdrawn
446
462
  enables on `!isStale` and carries no used-state, and only `confirmation`, `mcpAuthenticationRequired`,
447
463
  `planReview` and `questionCarousel` have one — so the buttons stay visible after the answer. They are
448
464
  inert: the command refuses a request the runtime no longer holds and says "already resolved", and the
449
- resolution sentence lands directly beneath them. An elicitation that carries a `requested_schema` gets an
465
+ status bar says what was sent. An elicitation that carries a `requested_schema` gets an
450
466
  `Answer…` button that asks for the value first; a request still pending while the session is idle
451
467
  can also be answered by typing.
452
468
 
@@ -488,14 +504,16 @@ own envelope, which for Claude Code is `{behavior:'allow'}` / `{behavior:'deny',
488
504
  request states which decisions its harness protocol actually carries, so this view offers exactly
489
505
  those and no button the runtime would refuse — Claude Code has an allow and a deny and no
490
506
  always-allow *behavior* at all, so it gets two. A harness with no translation keeps
491
- `actions.respond: false`, and then the request is rendered as an observation naming who answers it,
492
- because a control appears only for an action the descriptor advertises. Tool completions name only
507
+ `actions.respond: false`, and then the request is drawn read-only, its title and summary with no controls,
508
+ because a control appears only for an action the descriptor advertises; Code-OSS likewise draws another
509
+ client's pending call for every observer. Tool completions name only
493
510
  the call they answer (Claude Code's `tool_result` block carries just a `tool_use_id`), so an unnamed
494
511
  completion keeps the name the start stated rather than becoming a tool called `tool`.
495
512
 
496
513
  **Bounds.** The projection is bounded like `@volter/supercode-frontend-browser`'s: 64 KiB per
497
- part, 256 characters per title, 2 KiB for an opaque payload, 500 history turns. When turns are
498
- omitted the view says so; the runtime's own history is unchanged and authoritative. Terminal control
514
+ part, 256 characters per title, 2 KiB for an opaque payload, 500 history turns. Turns past the bound are
515
+ left out without a word, as VS Code's own agent host shows a transcript its harness truncated; the
516
+ runtime's own history is unchanged and authoritative. Terminal control
499
517
  characters never reach a rendered part.
500
518
 
501
519
  **The turn.** A chat request submits through `frontend.v2.send_input` and resolves on the first
@@ -527,7 +545,7 @@ create no person-message bubble, live or restored; ordinary quoted text
527
545
  without those flags stays a person message. A task notification becomes a
528
546
  short background-task notice, and Claude's unmarked, exact interruption
529
547
  records (`[Request interrupted by user]`, `… for tool use]`) a short turn
530
- interruption notice. The native transcript remains authoritative and unchanged.
548
+ interruption notice, each a plain line of its own words (see the parity table's harness-record row). The native transcript remains authoritative and unchanged.
531
549
  [Source evidence and remaining qualification](../../docs/evidence/chat-native-notices-20261013.md).
532
550
 
533
551
  **Session times are real or nothing.** `frontend.v2` carries no session timestamp, and the editor's
@@ -541,8 +559,9 @@ not supported by native history rendering. A saved call is labeled neutrally bec
541
559
  a recorded invocation does not prove that permission was granted. VS Code's chat history is request/response **pairs** and drops a response turn with no
542
560
  request before it. A runtime transcript legitimately opens with assistant or system content — the
543
561
  runtime compacts, so its canonical history can begin `[earlier conversation compacted: N messages]`
544
- with no user turn left. Rather than drop it, the projection pairs it with a marker turn,
545
- `⟨supercode runtime history⟩`, which names itself: nothing is presented as a person's words.
562
+ with no user turn left. Rather than drop it, the projection pairs it with a marker turn whose prompt is
563
+ Code-OSS's own for a turn whose request is missing, "Message content could not be retrieved"
564
+ (`claudeReplayMapper.ts` `missingPromptPlaceholder`): nothing is presented as a person's words.
546
565
 
547
566
  ## Building and packaging
548
567