Files
makelore/.project-docs/30-worklog/tasks/20260823-pi-chat-timeline-c8f31a62.md
T

234 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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: 54d8bb2e4a6f1a7dd857827659e60d1b4a1fb6f5
- Owner: codex-root
- Status: Ready for Integration
## Scope
- Implement `PI-120 — Core Chat and first-Conversation UX` on cumulative
PI-110 delivery HEAD `54d8bb2`.
- Add a vendor-neutral `CodingChatPanel` composition, 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 HEAD
`934ba02` and cumulative delivery HEAD `54d8bb2`; 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/attachments`
accepts one bounded image binary and returns only `{attachmentId,mime,byteLength}`;
authenticated `GET /api/coding/attachments/:id/content` returns 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-batch` delivery 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 base
`54d8bb2e4a6f1a7dd857827659e60d1b4a1fb6f5`.
- 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 `OpencodeChatPanel` and 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
1. 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.
2. Build a small `CodingChatPanel` composition and switch the Chat page to it;
make first-Conversation selection/creation local-only and keep Textarea
readiness independent of snapshot/runtime preparation.
3. 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.
4. 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.
5. 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 `CodingChatPanel`
backed 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-batch` SSE 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 and Coding Project Service now receive the same project-
scoped Conversation store provider, so runtime bindings and metadata writes
serialize through one mutation queue instead of racing the same file.
- Closed the first planner review findings after candidate `612135f`: the
authenticated Host server now admits only the exact image-binary upload
exception; empty/invalid/oversize/not-found attachments have stable typed
errors and supported image signatures are checked before disk writes.
- Made active target ownership atomic across Agent switches. An old or archived
Conversation cannot supply the visible draft/timeline/prompt target, and a
slow automatic or explicit create completion only selects when its captured
project and Agent are still active. Submission flights and errors are scoped
per Conversation, so one pending/rejected target does not disable another.
- Bounded each message to 16 local images and four concurrent uploads. A real
Electron image fixture now traverses the Renderer facade, IPC channel and
authenticated Host server, reads the stored bytes back for the optimistic
timeline preview, observes one upload, and verifies the prompt contains only
attachment ids rather than base64.
- Extended target-only gap recovery: when the first recovery Snapshot remains
behind a buffered continuous tail, Renderer requests one fresh target
Snapshot; a repeated identical stale response becomes a retryable error
instead of remaining in an infinite recovering state.
- Closed the incremental planner review findings after `bec93d0`: attachment
editing is locked for the originating Conversation until upload and HTTP 202
acceptance settle, so removal or a next-message paste cannot mutate the
captured image set. Attachment preparation failures now remain local to the
Composer, restore the draft, permit direct retry without runtime recovery,
retain already uploaded variants for reuse, and wait for every concurrent
upload flight to settle before releasing the edit lock. Attachment route failures use
only registered `CODING_ATTACHMENT_INVALID`, `CODING_ATTACHMENT_NOT_FOUND`,
and `CODING_STORAGE_WRITE_FAILED` codes while preserving 413/404 status.
- Synchronized `README.md` with 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
- First implementation candidate `612135f` received planner review result
**Standards Needs Fix / Spec Needs Fix**. PI-120 remained the unique Ready
Frontier; the findings above were treated as blocking rather than advancing
PI-130.
- The correction candidate `bec93d0` received incremental planner review result
**Standards PASS / Spec Needs Fix**. Its three remaining attachment-state and
typed-error findings were implemented and kept PI-130 locked pending another
planner review.
- Final candidate `1fe8863` received planner code review result
**Standards PASS / Spec PASS**. The planner confirmed the all-settled upload
semantics, held-sibling regression, direct attachment retry, registered error
codes, and absence of duplicate-upload or cross-Conversation lock leakage.
- Post-review focused suites passed: attachment Host routes, stale recovery,
shared ProjectService/Registry mutation queue, slow Agent switch, cross-
Conversation submission isolation, attachment count/concurrency and pressure
tests all pass. The consolidated focused run covered 3 files / 30 tests, and
`coding-chat-panel.test.tsx` covered 6/6 behavior tests.
- `REN-008` actual-path fixture passed with 100 runtime patch items, 20 public
patch batches, 21 SSE frames including Snapshot, 20 Renderer transactions,
20 React commits, 131,148 wire bytes, and measured Main-to-React p95
`35.995 ms` against the `<=50 ms` budget. It includes mixed message blocks,
4 KiB tool output and more than 100 KiB of cumulative thinking output.
- Latest attachment-state focused run passed: 3 files / 39 tests, including
delayed upload/removal, delayed HTTP 202/next-image isolation, local
preparation failure/direct retry, uploaded-variant reuse, and registered
Host error codes.
- `pnpm test`: passed, 218 files / 2321 passed / 2 skipped.
- `pnpm run typecheck`: passed.
- `pnpm run lint:check`: passed with 0 errors and six unchanged warnings in
`ExecutionGraphCard`, `Home`, and `Makelore`.
- `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. The post-review real-image fixture also passed 5/5 fresh-userData repeats
with one upload, Host readback preview, optimistic message, HTTP 202 and no
base64 in later payloads. The earlier text-only first-Conversation fixture
passed 20/20 fresh-userData runs below the 500 ms editability budget.
- `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-batch` hard-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.