docs: diagnose Pi branch creation failure

This commit is contained in:
2026-08-25 17:08:09 +08:00
parent 45d933732a
commit 941b015330

View File

@@ -0,0 +1,72 @@
# Task: Diagnose branch creation runtime unavailable
## Identity
- Task ID: 20260825-fork-runtime-unavailable-8e7c4a21
- Mode: Feature
- Branch: codex/20260825-fork-runtime-unavailable-8e7c4a21-fork-runtime-unavailable
- Worktree: D:\Datas\OthersProjects\makelore-fork-runtime-unavailable-8e7c4a21
- Base commit: 45d933732a8fbc0dadb07a4a4d65f0d12000c2ea
- Owner: codex-root
- Status: Done
## Scope
- Diagnose the installed Windows client's `从这里创建新对话分支` action returning `本地编程运行时暂时不可用。` from the exact packaged product source `45d9337`.
- Build a deterministic regression at the Renderer → Host → Pi runtime fork seam, identify the first failing ownership/runtime boundary, and report the verified cause.
- Do not change product code unless the user subsequently authorizes implementation; diagnostic fixtures or instrumentation must remain task-scoped and be removed before completion unless promoted into an approved regression test.
## Intent And Constraints
- Preserve Main-owned `/api/coding/*`, per-Conversation worker/session ownership, mutation no-replay semantics, and safe fixed error projection.
- Use installed-client logs only after redacting credentials, headers, prompts, project absolute paths, and user content. Do not expose or persist secrets.
- Do not infer the cause from the generic user-facing error: distinguish request/selection errors, missing or stale worker ownership, fork RPC failure, session persistence failure, and packaging/runtime resolution.
- Do not create subagents.
## Project Context Loaded
- Task ID: `20260825-fork-runtime-unavailable-8e7c4a21`
- Mode: Feature
- Branch: `codex/20260825-fork-runtime-unavailable-8e7c4a21-fork-runtime-unavailable`
- Worktree: `D:\Datas\OthersProjects\makelore-fork-runtime-unavailable-8e7c4a21`
- Base commit: `45d933732a8fbc0dadb07a4a4d65f0d12000c2ea`
- Other active local tasks: eleven planning/integration records were inspected; none owns the current Pi fork route/runtime path. The main-worktree integration record concerns the superseded OpenCode model-switch path.
- Overlap or semantic-conflict assessment: no blocking peer overlap. Canonical current-state/architecture documents are OpenCode-stale relative to the installed Pi product, so current Pi source and completed Pi task records are authoritative for this diagnosis.
- Read: project entry/gate/index files, task record, positioning/current state, decision and architecture indexes, module/data-flow and domain/success documents, evidence/reflection/commitment/stale indexes, and all active peer task scopes.
- Relevant understanding: the failing feature belongs to the Pi Conversation product chain and must retain Conversation-scoped ownership and no mutation replay. The packaged Windows artifact already passed Pi closure/load checks, which makes a total missing runtime less likely but does not prove the fork operation.
- Gate result: Passed.
## Plan
1. Locate the exact UI string, fork route, safe error mapper, runtime method, and existing fork tests from the fixed package source.
2. Construct and run the smallest unattended test that drives the same fork path and asserts the reported generic runtime-unavailable outcome.
3. Inspect redacted installed-product diagnostics and persisted Conversation/session metadata only as needed to distinguish the ranked hypotheses.
4. Minimize the failing state and state the verified cause, affected files, and an in-scope repair/verification proposal; do not implement without user authorization.
## Outcome
- Confirmed the reported message is caused by an invalid product-to-Pi fork entry, not by the Pi runtime being globally absent or crashed.
- `CodingConversationTimeline` currently renders `从这里创建新对话分支` for every durable message with a `sourceEntryId`, including assistant messages (`src/pages/Chat/CodingConversationTimeline.tsx:190`). The existing PI-130 fixture explicitly asserts this assistant-message behavior.
- The normative Pi cutover Spec assigns `/api/coding/conversations/:id/fork` to a **user entry**. A real pinned Pi `0.84.2` RPC experiment proved that the same persisted session accepts its user entry and deterministically rejects its assistant entry with `Invalid entry ID for forking`.
- `createPiManagedWorkerOpener` forwards the Renderer-selected entry unchanged as Pi RPC `{ type: 'fork', entryId }` after opening the target worker (`electron/coding-runtime/pi/runtime.ts:292`). `PiRpcClient` converts the rejection to `PI_RPC_RESPONSE_ERROR`; because that error has no product `publicError`, `CodingConversationService.runtimeError` maps it to `503 CODING_RUNTIME_UNAVAILABLE`, whose fixed Chinese message is exactly `本地编程运行时暂时不可用。`.
- The installed log did not provide a trustworthy click correlation: the observed `open_failure` timestamps overlap the automated package verifier. Those lines were excluded from the causal proof.
- No product source was changed. Temporary diagnostic tests were removed after the reproduction.
## Verification
- `corepack pnpm install --frozen-lockfile` — passed with pnpm `10.33.4` and pinned Pi `0.84.2`.
- Red-capable Renderer regression, run as `corepack pnpm exec vitest run tests/unit/coding-conversation-timeline.test.tsx` — failed deterministically in 18 ms because an assistant entry incorrectly rendered the fork button; the other four tests passed. The temporary assertion was then removed.
- Real Pi `0.84.2` diagnostic through Electron Node and `PiWorkerProcess` — passed: a synthetic persisted session was CLI-forked, Pi RPC accepted the user entry and rejected the assistant entry with `Invalid entry ID for forking`; stderr remained empty. This distinguishes an RPC contract rejection from worker crash/startup failure. The temporary diagnostic file and scratch sessions were removed.
- Static error-chain confirmation — `PI_RPC_RESPONSE_ERROR` has no product `publicError`, so the service maps it to `CODING_RUNTIME_UNAVAILABLE` and the Host route emits the exact reported Chinese message.
- Diagnostic cleanup — no product/test diff remains; only this task record is task-owned output.
## Follow-ups
- Recommended implementation task: render/enable fork only for durable **user** message entries, and validate the same invariant in Main before creating target metadata or spawning a target worker. Invalid/stale source entries should return `400 CODING_CONVERSATION_REQUEST_INVALID`, not a misleading runtime-unavailable response.
- Preserve the existing mutation no-replay rule. Do not retry fork automatically after timeout or an uncertain response.
- Add three permanent regressions: Renderer hides assistant-entry fork actions and still submits user entries; Main rejects assistant/unknown entry ids before target creation; real Pi `0.84.2` user-entry fork succeeds through the managed opener/final packaged seam.
- After implementation, run focused Timeline/Conversation service/Pi real-worker tests, typecheck, lint, full unit suite, `build:vite`, a real Electron branch-creation E2E, then rebuild and verify the Windows installer.
## Promotion Candidates
- None recorded.