234 lines
14 KiB
Markdown
234 lines
14 KiB
Markdown
# 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.
|