Files
makelore/.project-docs/30-worklog/tasks/20260825-pi-user-entry-fork-4a7d9c21.md

13 KiB

Task: Fix Pi user-entry conversation fork

Identity

  • Task ID: 20260825-pi-user-entry-fork-4a7d9c21
  • Mode: Feature
  • Branch: codex/20260825-pi-user-entry-fork-4a7d9c21-pi-user-entry-fork
  • Worktree: D:\Datas\OthersProjects\makelore-pi-user-entry-fork-4a7d9c21
  • Base commit: 941b015330
  • Owner: codex-root
  • Status: Done

Scope

  • Restrict the Renderer fork action to durable user messages on the active Conversation path.
  • Validate the same invariant in CodingConversationService.fork before any target Conversation metadata, worker, session binding, archive, or cleanup resource can be created.
  • Preserve the existing real Pi 0.84.2 fork RPC for a valid user entry and prove the resulting target binding/hydration through unit, managed runtime, Windows Electron, and final packaged-product seams.
  • Produce and verify a new Windows x64 NSIS without modifying the user's installed application.

Intent And Constraints

  • Keep the Pi hard cutover and current project/Agent/Conversation ownership. Do not add an OpenCode fallback, runtime restart control, compatibility layer, schema migration, feature flag, Pi upgrade, or Provider/worker-pool redesign.
  • A valid source is a message node on the source Snapshot's current active path with the exact sourceEntryId, role === 'user', and non-optimistic durable state. Missing, assistant, unknown, stale, abandoned-path, or optimistic sources fail before target creation.
  • Invalid input returns existing 400 CODING_CONVERSATION_REQUEST_INVALID through the fixed safe Chinese route projection. Pi's raw rejection, stderr, session paths, prompts, credentials, and provider data must not reach Renderer or proof reports.
  • Keep fork mutation no-replay: a timeout or uncertain result is never automatically submitted again. A valid fork retains the existing source session and hydrates a distinct target binding under the same Agent.
  • Preserve cumulative base 941b015330206af648f944183846ac2857468847, including product parent 45d933732a8fbc0dadb07a4a4d65f0d12000c2ea and its Agent-owned Conversation hierarchy. Do not touch dirty main, the diagnosis worktree/record, previous packaging worktrees, or user install.
  • Real external Provider remains Explicitly Waived / Accepted Risk with realTurnVerified=false; macOS/native Linux status is unchanged and is not Pass evidence. Do not create subagents, push, or publish.

Project Context Loaded

Task context:

  • Task ID: 20260825-pi-user-entry-fork-4a7d9c21
  • Mode: feature
  • Branch: codex/20260825-pi-user-entry-fork-4a7d9c21-pi-user-entry-fork
  • Worktree: D:\Datas\OthersProjects\makelore-pi-user-entry-fork-4a7d9c21
  • Base commit: 941b015330206af648f944183846ac2857468847
  • Other active local tasks: eleven non-ready owner records were inspected. One AI Design E2E task has a narrow unrelated test-only scope; the occupied main integration task owns historical OpenCode model-switch integration. The remaining older planning records still contain undefined placeholder scopes.
  • Overlap or semantic-conflict assessment: no known peer owns Pi fork, CodingConversationTimeline, CodingConversationService, or packaged Pi fork proof semantics. Placeholder scopes remain unknown coordination state, but their stated titles and isolated worktrees expose no semantic conflict that changes this plan.

Read:

  • .project-docs/05-agent-entry/read-before-planning.md
  • .project-docs/05-agent-entry/memory-index.md
  • .project-docs/05-agent-entry/planning-gate.md
  • this active task record
  • project positioning, current state, decision index, system overview, module map, data flow, business rules, success criteria, glossary, evidence, reflection, commitments, and stale-item indexes
  • diagnosis task 20260825-fork-runtime-unavailable-8e7c4a21
  • Pi cutover Spec and the relevant PI-050/060/100/130/150 ticket sections
  • PI Conversation contracts, Renderer store, Host cutover, and cumulative Agent→Conversation hierarchy task records
  • every non-ready peer's Scope, Intent And Constraints, and Promotion Candidates sections

Relevant understanding:

  • Project goal: Makelore Code exposes a vendor-neutral, local project-scoped Conversation product while Electron Main exclusively owns Pi runtime, sessions, credentials, files, and recovery.
  • Current integrated focus: shared canonical memory is OpenCode-stale relative to the cumulative Pi product. Current source, the Pi Spec/task chain, and the committed diagnosis are authoritative for this repair.
  • Active task scope: correct the supported fork source and error boundary only; do not reinterpret a deterministic Pi entry rejection as runtime failure.
  • Active constraints: target validation precedes metadata/resource creation; valid user fork semantics and no-replay remain unchanged; the Agent-owned Conversation hierarchy from 45d9337 must remain intact.
  • Decisions affecting this task: Spec route /api/coding/conversations/:id/fork is explicitly from a user entry; hydrated Snapshot nodes contain only the active path and expose durable sourceEntryId without leaking Pi wire.
  • Evidence, reflections, or commitments affecting this task: real pinned Pi accepted the persisted user entry and rejected the assistant entry with empty stderr. Windows formal packaging must retain artifact/runtime closure; real Provider and non-Windows platform gates remain out of scope.
  • Files or modules likely involved: Timeline and Chat E2E, shared/facade fork types, conversation-service.ts, focused Host/runtime tests, Pi packaged release proof, packaged smoke runner, and Windows artifact reports.
  • Unknowns, stale docs, or conflicts: canonical positioning is a placeholder and architecture/data-flow are OpenCode-stale. Several peer task scopes are placeholders, but no known decision conflicts with the precise Pi repair.

Gate result:

  • Passed.

Plan

  1. Add failing Renderer and Main regressions for user-only visibility, exact callback identity, invalid active-path rejection, and zero target-side effects; verify they fail on the diagnosed behavior.
  2. Implement the smallest product-contract correction: user-only durable UI action and service-owned active-Snapshot validation before target create.
  3. Add valid user fork coverage through the real pinned Pi managed opener and service seam, checking distinct target binding, Pi session identity, hydrated Snapshot, source isolation, and clean worker shutdown.
  4. Extend Windows Electron E2E and final packaged Main/UI proof so assistant has no action, the user action creates/selects a same-Agent branch, the original remains unchanged, and no runtime-unavailable state or process residue appears.
  5. Run frozen install, focused tests, typecheck, lint, full unit, production build, Windows Electron E2E, then commit a clean candidate and run formal package:win, Windows/Pi closure verifiers, packaged proof, signing/hash, documentation drift, registry completion, and final clean-state checks.

Outcome

  • Renderer now exposes the fork action only on non-optimistic user message nodes with a durable sourceEntryId; assistant and non-persisted nodes do not expose the action.
  • CodingConversationService.fork now resolves the source Conversation's authoritative hydrated Snapshot and rejects missing, assistant, unknown, stale, or abandoned-path entries with 400 CODING_CONVERSATION_REQUEST_INVALID before target metadata creation. The Host keeps its fixed safe Chinese projection and never exposes Pi's raw Invalid entry ID for forking response.
  • A valid user entry still reaches the locked Pi fork RPC. The permanent real Pi 0.84.2 regression proves source hydration, a same-Agent target with a distinct Pi session binding, correct before-entry target hydration, source isolation, and clean shutdown of both workers.
  • Windows Electron coverage now proves one user fork action for a history that also contains an assistant entry, exact sourceEntryId submission, target selection under the same Agent, preserved source history, and absence of the runtime-unavailable banner.
  • The final packaged proxy proof now performs the user-entry fork through the real packaged Main composition and UI after a settled controlled turn. It checks distinct bindings, correct target hydrate, source preservation, zero prompt replay, user/assistant action visibility, process cleanup, and the existing credential/role-contract boundaries.
  • README.md now states that only persisted user messages are fork sources. No Provider, worker-pool, schema, compatibility, or fallback architecture changed.

Verification

  • corepack pnpm install --frozen-lockfile — passed with package-manager pinned pnpm 10.33.4 and Pi 0.84.2.
  • Red phase — the focused Timeline/Main tests failed as expected: assistant exposed a second fork action, and invalid entries reached target creation.
  • Focused green — 4 files / 29 tests passed, including the real managed Pi service fork and release-proof wiring.
  • corepack pnpm run typecheck — passed.
  • corepack pnpm run lint:check — passed with the existing five warnings and no errors.
  • corepack pnpm test — passed: 180 files / 1525 tests plus the isolated pressure test; 2 pre-existing skips.
  • corepack pnpm run build:vite — passed for Renderer, Main, Preload, and release utility worker.
  • Focused Windows Electron Playwright — passed: 2 tests, including the same-Agent user-entry branch flow and source isolation.
  • corepack pnpm run test:electron:windows — passed: 2 files / 4 tests.
  • corepack pnpm run package:win — passed from clean code/proof candidate 5031979ca9c46ed00597a36f6412e321f6fdcdcf. Three earlier attempts stopped only at GitHub's fixed uv download with UND_ERR_CONNECT_TIMEOUT; the successful formal run downloaded both Windows architectures, rebuilt Vite, staged 130 Pi production packages and 6 assets, and generated a new x64 NSIS without reusing an old installer.
  • corepack pnpm run verify:publish-runtime — passed with npm 11.6.2.
  • corepack pnpm run verify:artifact:win — passed and bound the artifact to clean verification HEAD 5031979; Electron 43.4.0, Node 24.18.1, Python/pip/sqlite/SSL, uv 0.10.0, npm, msgpackr, Canvas native assets, and Unicode copy all loaded from the final product. The repository does not embed the optional buildCommit package field, so binding uses the verifier's clean verificationHead contract rather than a fabricated packaged field.
  • corepack pnpm run verify:artifact:pi -- --samples 2 — passed: final app.asar, Pi 0.84.2 CLI, all expected production packages/assets, five unpacked native assets, four managed Skills, extension/subagent markers, session persistence, local isolation, exit, and performance budgets were verified. Its nested matrix correctly remains partial-pass for waived real Provider and deferred non-Windows evidence.
  • corepack pnpm run test:pi-subagent:packaged — passed against the real final app.asar Main and Renderer. The first proof attempt correctly found no fork action on the just-settled live projection because it did not yet have a durable source id; the harness now restarts the isolated product and rehydrates the persisted binding before the installed-history action. Final evidence: source + target count 2, same Agent, distinct target piSessionId/sessionKey, target worker ready / run idle, target hydrate before the selected user entry, source unchanged, no prompt replay, one user fork action, no assistant action, selected target, no runtime-unavailable or permanent-recovering UI, and all worker/process/resource counters released. The broader existing crash/protocol/resilience proof also remained green.
  • Pre-documentation installer evidence from 5031979: 211891212 bytes, SHA-256 DE51AABA5A0F36810CE451328B45ACB7A03469E634DCBCCF52A8FA0608AA01BC; app.asar SHA-256 4488C8C0F8653CE61438012A47BFCB9C7B8282967735AFA70C03EC45DE04674C. The post-documentation clean-HEAD artifact is rebuilt and fingerprinted in the final handoff so generated evidence is not recursively embedded into the artifact-producing commit.
  • Authenticode status is NotSigned; no signed publisher claim is made.
  • Final packaged proof tracked process residue was empty, and an independent Windows process query found no Electron/Pi process associated with this worktree.

Follow-ups

  • Real external Provider execution remains explicitly waived and is not proof for this fix (realTurnVerified=false). macOS and native non-WSL Linux states remain unchanged.

Promotion Candidates

  • None. The current Pi Spec already states that fork is from a user entry; the product README and this task-owned record now match that existing decision.