docs: complete PI-010 conversation contracts

This commit is contained in:
2026-08-22 19:15:35 +08:00
parent 4deba3a68b
commit b6f693048d

View File

@@ -0,0 +1,84 @@
# Task: Implement PI-010 Conversation contracts and reducer
## Identity
- Task ID: 20260822-pi-conversation-contracts-b72c4e19
- Mode: Feature
- Branch: codex/20260822-pi-conversation-contracts-b72c4e19-pi-conversation-contracts
- Worktree: D:\Datas\OthersProjects\makelore-pi-conversation-contracts-b72c4e19
- Base commit: 72f7a26ca9554fb4e4e97067c0c5eb084514481a
- Owner: codex
- Status: Completed
## Scope
- Implement `PI-010 Conversation contracts and reducer` from the merged Pi cutover Spec/ticket graph.
- Add the vendor-neutral `CodingConversationRuntime` Interface and product DTOs under `electron/coding-runtime`.
- Add one strict Snapshot/Patch reducer for both hydrated and live product fixtures.
- Add an `InMemoryConversationRuntime` Implementation for later Host/Renderer product tests.
- Add focused fixtures/tests for mixed messages, thinking, tools, queue, interactions, compaction, subagents, generation/sequence handling, reconciliation, and fail-closed unknown input.
- Do not change Host routes, Renderer stores/components, Pi process/RPC wiring, project schema/migration, OpenCode behavior, or final packaging in this ticket.
## Intent And Constraints
- The external seam is the small product-owned `CodingConversationRuntime` Interface. Pi/OpenCode types, enums, paths, CLI options, provider details, and raw events must not cross it.
- Keep UI node IDs distinct from durable `sourceEntryId`; reconcile optimistic user nodes by `clientRequestId` without replacing UI identity.
- Enforce exact `schemaVersion`, worker generation, and per-Conversation sequence. Unknown schema/op or a sequence gap invalidates only that reducer state until a fresh Snapshot replaces it; stale generations are ignored.
- Treat tool output as cumulative replacement and attach tool results to the existing tool node; never create a tool-result message.
- `agent_end` is not idle. Only the product fixture projected from `agent_settled` may transition the run to idle.
- Use one in-process reducer Module and one InMemory Implementation. Do not add speculative ports, adapters, compatibility layers, vendor aliases, or unrelated refactors.
- Preserve the hard cutover and the explicit PI-000 waivers: they unlock this ticket but do not convert real Provider or macOS evidence into Pass.
## Project Context Loaded
- Planning commit `a8c0806` and PI-000 implementation commit `2bc423e` are part of the registered base commit `72f7a26`, so Spec, tickets, evidence, and implementation share one Git history without appearing as PI-010 drift.
- The first PI-010 registration used `2bc423e` as its base and correctly failed the Task Documentation Gate after the planner merge appeared as foreign documentation. Its code-only checkpoint was re-applied here as `4deba3a`; the old task registration was released, not completed.
- The current canonical application still runs OpenCode; this ticket only introduces the vendor-neutral product seam that later tickets will consume.
- `maintain-project-docs` Concurrent Task Gate and Planning Gate passed in this corrected worktree. Relevant peers are ready for integration and have no write overlap with this task.
- `codebase-design` directs the Interface to stay small while reducer/runtime behavior remains behind it; internal test seams are not exposed as public adapters. The user-prohibited parallel-subagent design path is not used.
- The canonical project-positioning record remains a placeholder; repository guidance, current state, and the merged Pi Spec/tickets are authoritative for this task.
## Plan
1. Define the vendor-neutral runtime Interface and all PI-010 product DTOs.
2. Implement strict Snapshot replacement and ordered Patch reduction with stable identity reconciliation.
3. Implement the InMemory runtime against the same Interface and product envelopes.
4. Add locked-version product fixtures and focused acceptance tests, including no-vendor-import assertions.
5. Run focused tests, typecheck, scoped/full lint, full unit, production compile, and project-documentation gates.
## Outcome
- Added the vendor-neutral `CodingConversationRuntime` Interface and product-owned Snapshot/Patch, node, run, queue, context, interaction, model, worker, usage, error, input, and acceptance DTOs.
- Added one strict reducer Module for Snapshot replacement and ordered live envelopes. It drops stale generations/duplicate sequence, invalidates only the target Conversation on future generation, sequence gap, unknown schema/op, malformed payload, explicit invalidation, or missing delta target, and resumes only after a valid Snapshot replacement.
- Kept live UI identity stable while reconciling durable `sourceEntryId` and optimistic `clientRequestId`; cumulative tool updates replace output, and tool results remain attached to tool nodes.
- Added `InMemoryConversationRuntime` as the second Implementation of the product Interface, with deterministic injected clock/id seams, idempotent prompt/queue acceptance, target abort, model/thinking updates, compaction, fork, recovery generation, disposal, and patch subscription.
- Added locked `@earendil-works/pi-coding-agent@0.84.2` fixture provenance whose projected values are product DTOs only. Fixtures cover text/thinking, parallel tools, tool error, cumulative output, retry, queue, interaction, compaction `willRetry`, subagent, hidden custom input, `agent_end` checkpoint, and authoritative `agent_settled` idle.
- No Host route, Renderer store/component, project schema, Pi process/RPC implementation, OpenCode behavior, or packaging path changed.
## Verification
- Installed the merged frozen lockfile in this corrected worktree with the exact repository-pinned `pnpm@10.33.4`; 1,018 packages were reused from the local store.
- `pnpm exec vitest run tests/unit/coding-conversation-contracts.test.ts`: 14 tests passed.
- `pnpm run typecheck`: passed.
- Scoped ESLint for the three runtime files, fixture, and focused test: passed.
- `pnpm run lint:check`: passed with zero errors and six pre-existing React warnings outside this ticket.
- `pnpm test`: 179 files / 2,097 tests passed.
- `pnpm run build:vite`: Renderer, Main, Preload, and utility production builds passed; existing mixed-import/chunk-size warnings remain outside this ticket.
- Scoped vendor scan over `electron/coding-runtime`: no `OpenCode` or Pi package import/reference found (`rg` exit 1 / zero matches).
- Acceptance audit passed: snapshot/live equivalence, target-only gap invalidation, stale generation discard, stable optimistic/durable identity, cumulative tool replacement, no tool-result message, retry/compaction behavior, `agent_end` non-idle, `agent_settled` idle, and unknown fail-closed behavior all have focused assertions.
- Task Documentation Gate passed: required project-doc files exist, ownership/doc-drift boundaries are clean, `git diff --check` passed, and the scoped trailing-whitespace scan returned zero matches.
## Follow-ups
- `PI-050`, `PI-060`, and `PI-110` should consume this Interface/reducer directly. If their real implementation exposes a missing product capability, amend this upstream contract with focused equivalence tests rather than passing vendor wire through a caller.
- `PI-060` owns actual Pi live/hydrated event projection. It must preserve the locked fixture boundary established here and keep hidden/unknown raw events out of product state.
- `PI-110` owns the Renderer store; it must maintain one reducer state per Conversation so a gap cannot invalidate unrelated Conversations.
## Promotion Candidates
- Target: canonical Pi cutover architecture after Integration Gate.
Proposal: record `CodingConversationRuntime` plus the Snapshot/Patch reducer as the product-owned seam shared by Main orchestration, Renderer state, and tests; Pi/OpenCode wire remains implementation-private.
Evidence: `electron/coding-runtime/contracts.ts`, `conversation-reducer.ts`, `in-memory-conversation-runtime.ts`, and 14 focused acceptance tests.
Future impact: later worker/event/Renderer tickets can vary their Implementation without widening the Interface or duplicating normalization logic.
Semantic conflicts: none with the merged Spec/ticket graph; the current OpenCode runtime is unchanged until the hard-cutover release unit completes.
Human confirmation required: no; the planning session already authorized and merged this ticket's scope.