fix review findings: sync stale v1/removed-event doc references

Codex's re-confirmation pass verified both blocker fixes correct but found
doc/comment drift the fix commit missed:

- session/index.ts + session/README.md: "minimal v1 header" → "minimal header
  (stamped with the current SESSION_FORMAT_VERSION)" — the version is 0, not 1.
- session/index.ts deriveMessages comment listed "usage, and errors" as trace
  data — those standalone events no longer exist; only boundaries + chunks are.
- session-persistence RFC: "no v1 migration" → the pinned-v0 pre-release stance.
- collapse-trace-only RFC format-version note: reframed off the "bump the
  version and reject" wording (which now reads as the OTHER AGENTS.md stance)
  onto the pinned-0 unstable stance the session log actually uses.
- agent-loop/loop.ts finishError JSDoc: "with a logged `error` event" → the
  failure is recorded on turn/end.reason (no standalone error event).
- acp/acp-feature-support.md (two spots): usage is recorded on assistant/message
  now, not as standalone internal usage events.
- Regenerate the cordis catalog (finishError JSDoc line shift).
This commit is contained in:
Tianyi Cui
2026-06-21 11:33:41 +08:00
parent b0422f2a50
commit 2eb6ad3260
6 changed files with 12 additions and 12 deletions

View File

@@ -38,8 +38,8 @@ function toError(error: unknown): CodedError {
* caller's try/catch), OR end the stream with a finish-error/aborted chunk
* (the only option for adapters that can't throw mid-stream, e.g.
* library-backed ones). This translates the latter into a thrown step error
* so the turn ends error/aborted with a logged `error` event, never as a
* normal `completed` assistant message.
* so the turn ends error/aborted (the failure recorded on `turn/end.reason`),
* never as a normal `completed` assistant message.
*
* `FinishReason` is merge-extensible (plugins/adapters can add `kind`s), so
* the switch handles the known terminal-failure kinds and treats every other

View File

@@ -37,7 +37,7 @@ Plain class (not a Cordis Service). Create via `ctx.sessions.create()`.
- `session.append(type, data): SessionEvent` — synchronous, never blocks on I/O. **Throws** if `data` is not losslessly JSON-serializable (BigInt, function, symbol, undefined, non-finite number, circular ref, or an exotic object like Map/Set/Date) — the event log is the durable source of truth, so this invariant is enforced at the source (exported as `isJsonValue` for backends to reuse on their replay/fork entry points).
- `session.deriveMessages(): Message[]` — derive the LLM message history from the event log. Raw `assistant/chunk` events are skipped; `context/message` and `steering/message` render as tagged synthetic user messages.
- `session.events`, `session.seq`, `session.id`
- `session.header: SessionHeader` — immutable creation metadata (`version`, `id`, `createdAt`, optional `cwd`/`parentSession`). Kept out of the event log (a storage concern, not replayable state); a minimal v1 header is synthesized for bare `Session` construction.
- `session.header: SessionHeader` — immutable creation metadata (`version`, `id`, `createdAt`, optional `cwd`/`parentSession`). Kept out of the event log (a storage concern, not replayable state); a minimal header (stamped with the current `SESSION_FORMAT_VERSION`) is synthesized for bare `Session` construction.
### Metadata types (`types.ts`)

View File

@@ -79,9 +79,10 @@ export class Session {
/**
* Immutable creation metadata (format version, cwd, lineage). Supplied by
* the store via `ctx.sessions.create()`. When a `Session` is constructed
* bare (tests, ad-hoc replay), a minimal v1 header is synthesized so
* `session.header` is always present. Kept out of the event log — it is a
* storage concern, not replayable conversation state.
* bare (tests, ad-hoc replay), a minimal header is synthesized (stamped with
* the current {@link SESSION_FORMAT_VERSION}) so `session.header` is always
* present. Kept out of the event log — it is a storage concern, not
* replayable conversation state.
*/
readonly header: SessionHeader
@@ -180,8 +181,7 @@ export class Session {
const messages: Message[] = []
for (const event of this.log) {
// Intentionally non-exhaustive: only message-producing events derive
// history; turn/step boundaries, chunks, usage, and errors are
// trace/replay data.
// history; turn/step boundaries and chunks are trace/replay data.
// eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
switch (event.type) {
case 'user/message': {

View File

@@ -87,7 +87,7 @@ These are capabilities the bridge would *drive* on the editor. The harness runs
| `available_commands_update` | S | ❌ | ✅ | ✅ | No slash commands advertised. |
| `current_mode_update` | S | ❌ | ✅ | ✅ | No session modes. |
| `config_option_update` | S | ❌ | ✅ | ✅ | No config options. |
| `usage_update` | S | ❌ | ✅ | ✅ | Token/cost reporting not surfaced (the harness HAS usage events internally). |
| `usage_update` | S | ❌ | ✅ | ✅ | Token/cost reporting not surfaced (the harness records token usage internally on `assistant/message`). |
| `session_info_update` | S | ❌ | ⚠️ | ⚠️ | Session title/metadata not pushed. |
## 5. Tool-call rendering
@@ -148,7 +148,7 @@ Ranked by how commonly the reference adapters ship them and how much UX they unl
6. **MCP passthrough** (`mcpServers` on `session/new` + `mcpCapabilities`).
7. **Richer prompt content** — image / embedded `resource` blocks (needs a multimodal model path).
8. **Diff + location tool rendering**`diff` content and `locations` for edit tools.
9. **Usage reporting** (`usage_update`) — the harness already has the internal usage events.
9. **Usage reporting** (`usage_update`) — the harness already records token usage internally (on `assistant/message`).
10. **Editor filesystem delegation** (`fs/read_text_file` / `fs/write_text_file`) — lets the agent see unsaved buffers; lower priority since the harness has direct disk access.
## Out of scope