11 KiB
11 KiB
Task: Implement PI-120 core chat and first-conversation UX
Identity
- Task ID: 20260823-pi-chat-timeline-c8f31a62
- Mode: Feature
- Branch: codex/20260823-pi-chat-timeline-c8f31a62-pi-chat-timeline
- Worktree: D:\Datas\OthersProjects\makelore-pi-chat-timeline-c8f31a62
- Base commit:
54d8bb2e4a - Owner: codex-root
- Status: In Progress
Scope
- Implement
PI-120 — Core Chat and first-Conversation UXon cumulative PI-110 delivery HEAD54d8bb2. - Add a vendor-neutral
CodingChatPanelcomposition, first-Conversation metadata selection/creation, core Composer, and memoized timeline renderers for message/thinking/tool/compaction/boundary nodes. - Bind the page exclusively to
/api/coding/*Renderer facades and the PI-110 Conversation store, including optimistic prompt acceptance, preparing/queued/running/error/recovery states, draft continuity, and hidden-Conversation render isolation. - Add focused component/performance coverage and the first-prompt Electron E2E. Do not implement PI-130 feature-complete controls or PI-140 legacy removal.
Intent And Constraints
- The exact Ready Frontier is
{PI-120}. PI-110 is Done at audit HEAD934ba02and cumulative delivery HEAD54d8bb2; PI-130 remains locked until this ticket is accepted. - Textarea editability depends only on an active project, an enabled Agent, and the absence of a project destruction/migration transition. It never depends on worker/runtime/metadata loading, provider latency, diagnostics, another Conversation, or the current Conversation run state.
- Conversation creation is local metadata only. Snapshot/prewarm is lazy and Conversation-scoped; preparation beyond ten seconds becomes a recoverable error while the draft stays editable.
- A send immediately creates one stable optimistic user node. HTTP 202 is only acceptance; later provider/tool failure never removes the accepted user message, and uncertain delivery is never silently resent.
- Renderer components must use granular PI-110 selectors and memoized blocks. Hidden Conversation streaming cannot rerender the selected timeline; cumulative tool output replaces rather than appends duplicate content.
- Do not read
src/stores/opencode.ts, call/api/opencode, import Pi/OpenCode wire types, or mechanically rename the legacy 4k-line panel. The old panel remains only as PI-140 removal residue after the new page composition takes ownership. - PI-130 still owns model/thinking controls, steer/follow-up queue controls, compaction/retry/context actions, interactions, subagent graph, changes/files/ browser/skills/commands, and Conversation archive/fork/title/unread UI.
- The planner amended the attachment contract:
POST /api/coding/attachmentsaccepts one bounded image binary and returns only{attachmentId,mime,byteLength}; authenticatedGET /api/coding/attachments/:id/contentreturns raw bytes. Upload happens only on Send, each local variant has one in-flight/result, and Renderer state/protocol keep references rather than base64. - The planner selected public
patch-batchdelivery only. Main retains private single-patch envelopes and original seq, batches per Conversation/generation for 16–33 ms with bounded early flush, and cancels an old generation's pending batch. Renderer validates the full batch and folds it in one Zustand transaction; malformed/gapped batches recover only their target. - Real Provider remains Explicitly Waived / Accepted Risk with
realTurnVerified=false. macOS x64/arm64 remains deferred to mandatory PI-150. Neither is Pass evidence. No subagents are authorized.
Project Context Loaded
- Task identity:
20260823-pi-chat-timeline-c8f31a62, feature mode, isolated branch/worktree above, exact base54d8bb2e4a6f1a7dd857827659e60d1b4a1fb6f5. - Concurrent Task Gate passed. The only semantically adjacent planning task,
20260820-partner-create-model-parity-c83d, still has undefined scope and no claimed files. The canonical main integration task is Blocked and is not a write target; all other planning owners are unrelated Canvas/Robot/Learning or read-only scopes. - Planning Gate inputs read: memory index, active task record, project
positioning/current state/decision/system/architecture/domain documents,
PI-100/105/110 completion records, exact PI-120 ticket and PI-130 boundary,
and relevant
UX-*,REN-*, API, performance and recovery Spec sections. - Canonical positioning and project-level success fields are placeholders and the integrated memory still describes the legacy OpenCode UI. Repository guidance plus the planner-owned Pi Spec/tickets and reviewed cumulative code are authoritative for this feature branch.
- Confirmed seams: schema-v2 project/config/Conversation routes already provide
local-only metadata; PI-110 provides the typed Snapshot/prompt/SSE facade,
shared reducer, per-Conversation store, optimistic identity, target-only
recovery, and granular selectors. The current Chat page still imports the
legacy
OpencodeChatPaneland is the cutover seam. - No accepted ADR conflicts with this ticket. The attachment transport gap is recorded above and has been escalated to the planner instead of silently inventing a route.
- Gate result: Passed.
Plan
- Add the minimal vendor-neutral project/config/Conversation Renderer facade and metadata store needed to load the active project, enabled Agents and Conversations without touching the legacy OpenCode store.
- Build a small
CodingChatPanelcomposition and switch the Chat page to it; make first-Conversation selection/creation local-only and keep Textarea readiness independent of snapshot/runtime preparation. - Implement focused Composer submission/recovery UI over the PI-110 draft and optimistic request lifecycle, including preparing/queued/running/error status without a page-wide loading gate.
- Implement memoized/windowed message, thinking, tool, compaction and boundary blocks that update only the selected target and keep large/cumulative output bounded; apply the planner's attachment ruling without expanding PI-130.
- Add red-capable first-Conversation, core Chat, optimistic failure, hidden-Conversation/render-count and 100 KB performance fixtures, plus the first-prompt Electron E2E; then run focused/full validation, build, documentation gates and planner review.
Outcome
- Replaced the Chat page composition with a vendor-neutral
CodingChatPanelbacked only by/api/coding/*facades. It loads active project/config/local Conversation metadata, auto-creates the first local Conversation, and keeps the Composer editable while runtime Snapshot preparation is held. - Added text/image Composer behavior, stable optimistic user nodes, distinct preparing/accepted/running/uncertain/error/recovery feedback, Enter/Shift+Enter and IME handling, Send-time single-flight image upload, and authenticated object-URL previews without base64 state or protocol payloads.
- Added a memoized/windowed timeline for message, Markdown, thinking, tool, compaction, boundary and notice nodes. Hidden Conversation batches leave the selected timeline selector stable; cumulative tool output is replaced rather than duplicated.
- Added Main-owned attachment binary routes/IPC transport and public Snapshot +
patch-batchSSE delivery. Main batches at 24 ms by default with item/byte early-flush bounds; Renderer atomically rejects malformed/gapped batches, buffers during target recovery, trims Snapshot-covered items and replays only a strict continuous tail. - Fixed a supported concurrency defect exposed by the full suite: the Pi Session Registry now reuses one Conversation store per project, serializing simultaneous first bindings instead of racing writes to the same metadata file.
- Synchronized
README.mdwith the current Pi core Chat, first-Conversation, batch and attachment behavior. PI-130 feature controls and PI-140 legacy removal remain outside this task.
Verification
pnpm exec vitest run tests/unit/coding-workspace-store.test.ts tests/unit/coding-projects-facade.test.ts tests/unit/coding-attachments-facade.test.ts tests/unit/coding-attachments-routes.test.ts tests/unit/coding-chat-panel.test.tsx tests/unit/coding-conversation-timeline.test.tsx tests/unit/coding-conversations-store.test.tsx tests/unit/coding-core-routes.test.ts tests/unit/host-api.test.ts tests/unit/host-api-proxy.test.ts: passed, 10 files / 68 tests before the final malformed-batch and Session Registry regression additions.pnpm exec vitest run tests/unit/pi-session-registry.test.ts tests/unit/pi-conversation-runtime.test.ts tests/unit/coding-conversations-store.test.tsx tests/unit/coding-chat-panel.test.tsx: passed, 4 files / 25 tests.pnpm test: passed, 217 files / 2303 passed / 2 skipped. The final run is green after fixing the same-project parallel Session Registry write race and stabilizing the AI Hardware async query at its actual loading boundary.pnpm run typecheck: passed.pnpm run lint:check: passed with 0 errors and six unchanged warnings inExecutionGraphCard,Home, andMakelore.pnpm run build:vite: passed; existing Vite dynamic-import and chunk-size warnings remain.pnpm exec playwright test tests/e2e/pi-coding-first-chat.spec.ts: passed, 1/1.pnpm exec playwright test tests/e2e/pi-coding-first-chat.spec.ts --repeat-each=20 --workers=1: passed, 20/20 fresh-userData runs. Every sample asserted Composer editability below 500 ms while runtime Snapshot was held, so the measured sample p95 is below the locked 500 ms budget; the same fixture verifies optimistic prompt visibility and HTTP 202 acceptance without a real Provider.git diff --check: passed; only repository line-ending conversion notices were printed.- Real Provider remains Explicitly Waived / Accepted Risk with
realTurnVerified=false; no Provider Account, credential isolation, protocol-specific endpoint, rate-limit or real concurrency behavior is claimed as Pass. - macOS x64/arm64 execution remains user-deferred to mandatory
PI-150; no macOS Pass is claimed.
Follow-ups
- PI-130 owns Conversation model/thinking controls, steer/follow-up queue, compaction/retry/context controls, interactions, subagents, changes/files, browser, skills/commands, and archive/fork/title/unread UI.
- PI-140 owns removal of legacy OpenCode runtime/routes/dependencies/UI/tests and migration notice.
- PI-150 must run final packaged cross-platform proof, including the deferred macOS x64/arm64 matrix. Real Provider qualification remains explicitly waived unless the user changes that decision.
Promotion Candidates
- Preserve the public Snapshot +
patch-batchhard-cut contract and the target-only recovery semantics in the planner-owned Pi Spec/tickets after implementation review. - Preserve the explicit attachment upload/read Host contract, Send-time single-flight rule, and reference-only Renderer state in the planner-owned Pi Spec/tickets after implementation review.