8.2 KiB
8.2 KiB
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:
72f7a26ca9 - Owner: codex
- Status: Completed
Scope
- Implement
PI-010 Conversation contracts and reducerfrom the merged Pi cutover Spec/ticket graph. - Add the vendor-neutral
CodingConversationRuntimeInterface and product DTOs underelectron/coding-runtime. - Add one strict Snapshot/Patch reducer for both hydrated and live product fixtures.
- Add an
InMemoryConversationRuntimeImplementation 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
CodingConversationRuntimeInterface. 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 byclientRequestIdwithout 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_endis not idle. Only the product fixture projected fromagent_settledmay 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
a8c0806and PI-000 implementation commit2bc423eare part of the registered base commit72f7a26, so Spec, tickets, evidence, and implementation share one Git history without appearing as PI-010 drift. - The first PI-010 registration used
2bc423eas 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 as4deba3a; 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-docsConcurrent 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-designdirects 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
- Define the vendor-neutral runtime Interface and all PI-010 product DTOs.
- Implement strict Snapshot replacement and ordered Patch reduction with stable identity reconciliation.
- Implement the InMemory runtime against the same Interface and product envelopes.
- Add locked-version product fixtures and focused acceptance tests, including no-vendor-import assertions.
- Run focused tests, typecheck, scoped/full lint, full unit, production compile, and project-documentation gates.
Outcome
- Added the vendor-neutral
CodingConversationRuntimeInterface 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
sourceEntryIdand optimisticclientRequestId; cumulative tool updates replace output, and tool results remain attached to tool nodes. - Added
InMemoryConversationRuntimeas 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.2fixture provenance whose projected values are product DTOs only. Fixtures cover text/thinking, parallel tools, tool error, cumulative output, retry, queue, interaction, compactionwillRetry, subagent, hidden custom input,agent_endcheckpoint, and authoritativeagent_settledidle. - 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: noOpenCodeor Pi package import/reference found (rgexit 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_endnon-idle,agent_settledidle, 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 --checkpassed, and the scoped trailing-whitespace scan returned zero matches.
Follow-ups
PI-050,PI-060, andPI-110should 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-060owns 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-110owns 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
CodingConversationRuntimeplus 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.