Files
makelore/.project-docs/30-worklog/tasks/20260824-pi-runtime-unavailable-hotfix-4e9c7a31.md

11 KiB

Task: Fix packaged Pi proxy token initialization and recovery

Identity

  • Task ID: 20260824-pi-runtime-unavailable-hotfix-4e9c7a31
  • Mode: Feature
  • Branch: codex/20260824-pi-runtime-unavailable-hotfix-4e9c7a31-pi-runtime-unavailable-hotfix
  • Worktree: D:\Datas\OthersProjects\makelore-pi-runtime-unavailable-hotfix-4e9c7a31
  • Base commit: fa510c4976
  • Owner: codex-root
  • Status: Ready for Integration

Scope

  • Fix the Windows packaged Pi startup failure for the works_square_ai_gateway_proxy account without changing the OpenCode-to-Pi architecture or starting PI-160.
  • Resolve the Main Host API credential lazily for persistent parent open, rebuild/recover, and ephemeral child open; preserve Main ownership and prove token rotation does not reuse a captured value.
  • Map Pi's typed PROVIDER_AUTH_REQUIRED failure through the existing single refresh/reopen boundary, and make Renderer Conversation recovery failure leave recovering for a retryable per-Conversation error without losing user state.
  • Produce and verify a Windows x64 NSIS installer from the final clean candidate, including a real packaged Main-composition proxy first- Conversation proof and token non-disclosure checks.

Intent And Constraints

  • Base exactly on fa510c49761485cbd323801923dbe2472d6981bb, which is the common HEAD of the PI-150 release-proof and diagnostic worktrees and contains code candidate 09841c8; do not rewrite or drop cumulative PI-150 history.
  • Do not modify the old PI-150 worktree, diagnostic worktree, occupied/dirty main, or the user's installed application under D:\Tools\泥土\niancode\Makelore.
  • Keep the Host token Main-owned and memory-only. Never write it to argv, models.json, logs, diagnostics, task evidence, or Renderer state.
  • Do not upgrade Pi, add a fallback/compatibility layer, refactor Host auth, or change direct API-key, OAuth, or local Provider behavior.
  • Real Provider verification remains Explicitly Waived / Accepted Risk with realTurnVerified=false; macOS and native non-WSL Linux gate status is unchanged.
  • Use the exact package-manager version pinned by packageManager, frozen install semantics, focused regressions, full repository verification, and the formal Windows packaging path.

Project Context Loaded

  • Concurrent Task Gate: Passed in the isolated worktree above; ownership is codex-root, feature mode, and the task record matches the registry.
  • Planning Gate: Passed after reading the diagnostic record, PI-150 source record, memory index, positioning/current-state/decision/architecture/domain/ evidence/reflection/commitment/stale records, and all active peer scopes.
  • The shared canonical snapshot is older than the Pi feature chain. The diagnostic record, cumulative PI-150 source record, current source, and the delegated repair boundary are authoritative for this task.
  • Other active tasks use separate worktrees. The main-worktree integration task concerns the older OpenCode model-switch path and explicitly does not package; no semantic conflict requires changing this hotfix plan.
  • No subagents are used by explicit user direction.

Plan

  1. Inspect the exact composition, opener, auth-classifier, recovery-store, test, Windows Electron E2E, and packaged proof seams; identify the smallest production and test surface.
  2. Add red-capable focused regressions for lazy/current token reads across parent/rebuild/recover/child, typed auth mapping and bounded refresh, recovery failure/retry, and unaffected direct/OAuth/local Provider paths.
  3. Implement the lazy Main-owned credential getter, typed error classification, and retryable recovery-state transition with surgical changes only.
  4. Run focused tests, typecheck, lint, the full unit suite, production build, and Windows Electron E2E; fix only failures caused by this hotfix.
  5. Commit the clean implementation candidate, run formal package:win, execute Windows artifact/runtime closure checks, and run a final packaged Main- composition proxy first-Conversation proof including token-secrecy and clean process-exit assertions.
  6. Record exact commits, changed files, verification results, NSIS size/hash, structured packaged evidence and unchanged release waivers; pass the Task Documentation Gate and mark the task ready for integration.

Outcome

  • Implemented a lazy getLocalProxyCredential seam from Electron Main through the single coding composition. Composition construction no longer reads or captures the pre-server token; persistent parent first-open, recover/rebuild, and ephemeral child open all resolve the getter at the worker-open boundary.
  • Extended the existing typed Provider-auth classifier to recognize only PiProviderConfigError.code === PROVIDER_AUTH_REQUIRED. Initial prepare and prompt authentication failures now use the existing maximum-one refresh and reopen coordinator and project as CODING_PROVIDER_AUTH_REQUIRED.
  • Made Renderer recovery failures leave recovering for the target Conversation's retryable error state while preserving the selected Conversation, last good Snapshot, draft, and attachments; a later retry can recover normally.
  • Added focused rotation/non-disclosure regressions for parent first-open, recover, rebuild, and child open while retaining the pre-existing direct API-key/OAuth/local credential coverage.
  • Extended the final packaged proof entry so the actual global Main composition can exercise works_square_ai_gateway_proxy through the current authenticated Host proxy, create the first Conversation from the real UI, establish a Pi binding, accept input, dispatch a real packaged parent and child, and verify argv/models/log/diagnostic token non-disclosure. Its upstream is controlled loopback and the report remains realTurnVerified=false.
  • The first packaged proxy run additionally proved that Host authentication was accepted but exposed a second Windows release blocker: Pi's Node fetch adds sec-fetch-mode: cors, and forwarding that transport-owned header into Electron net.fetch fails with net::ERR_INVALID_ARGUMENT before the upstream receives the request. The Host proxy now drops only that header; direct API-key/OAuth/local Provider behavior and the no-mutation-replay rule are unchanged.
  • Generated and verified the final Windows x64 NSIS from clean candidate 34a4434cfb3b6d083259f27dde065e78d4e0054f. The final packaged global-Main proxy proof passed and all proof Electron/Pi processes exited.

Commits

  • f902edefd0026fc8b003d4769c4eb1c064243880 — lazy Main Host token, typed Provider auth mapping, retryable recovery state, focused regressions, and the packaged global-Main proxy proof path.
  • 34a4434cfb3b6d083259f27dde065e78d4e0054f — drop Pi/Undici's sec-fetch-mode transport header before Electron upstream forwarding and use an actionable real-UI send in the packaged proof harness.

Changed Files

  • .project-docs/30-worklog/tasks/20260824-pi-runtime-unavailable-hotfix-4e9c7a31.md
  • electron/api/coding-composition.ts
  • electron/api/coding-provider-auth.ts
  • electron/api/routes/ai-proxy.ts
  • electron/coding-runtime/pi/release-proof.ts
  • electron/main/index.ts
  • scripts/run-pi-subagent-packaged-smoke.mjs
  • src/stores/coding-conversations.ts
  • tests/unit/ai-proxy-routes.test.ts
  • tests/unit/coding-conversations-store.test.tsx
  • tests/unit/coding-core-routes.test.ts
  • tests/unit/coding-provider-auth.test.ts
  • tests/unit/pi-managed-worker-opener.test.ts
  • tests/unit/pi-runtime-auth-recovery.test.ts
  • tests/unit/pi-subagent-child.test.ts

Verification

  • corepack pnpm install --frozen-lockfile with pinned pnpm 10.33.4: passed, 997 packages linked from the existing store and the lockfile remained unchanged.
  • Focused Vitest run for proxy forwarding, composition, auth, Renderer recovery, parent opener, child opener, and auth recovery: 7 files / 66 tests passed. The initial hotfix red run failed exactly on typed auth classification, auth-required projection, and permanent recovering state.
  • corepack pnpm run typecheck: passed after the final proof changes.
  • corepack pnpm run lint:check: passed with 0 errors and 5 pre-existing React warnings in src/pages/Home/index.tsx and src/pages/Makelore/index.tsx.
  • corepack pnpm test: passed; primary run 178 files / 1512 passed / 2 skipped, serialized pressure run 1 file / 1 passed.
  • corepack pnpm run build:vite: passed; Renderer, Main, Preload, and release utility bundles built. Existing dynamic-import and large-chunk warnings remain.
  • corepack pnpm run test:electron:windows: passed; 2 files / 4 tests.
  • corepack pnpm run package:win: passed from clean candidate 34a4434cfb3b6d083259f27dde065e78d4e0054f; produced Makelore-2.0.0-win-x64.exe, 211,888,141 bytes, SHA-256 3A1335A6DEFDEBE53A84EA558E6A000DBD538C568EB9AFB202893AA4D82858B2.
  • corepack pnpm run verify:artifact:win: passed. The unpacked product runs Electron 43.4.0 / Node 24.18.1; bundled Python, pip, sqlite3, SSL, uv 0.10.0, npm 11.6.2, msgpackr, and x64 canvas load from the product.
  • corepack pnpm run verify:artifact:pi -- --samples 2: passed. Final app.asar, Pi 0.84.2 CLI, all 130 expected production packages, 6 runtime assets, 5 native assets outside ASAR, 4 managed Skills, and the materialized extension/subagent contract are present and executable. The nested runtime report remains partial-pass only for the pre-existing explicit real- Provider/macOS/Linux waivers; the artifact verifier result is pass.
  • corepack pnpm run test:pi-subagent:packaged: passed against the final unpacked executable. The actual packaged app.asar Main composition used works_square_ai_gateway_proxy, created exactly one first Conversation, established its Pi binding, projected the submitted user input and REAL_PARENT_COMPLETE, and settled at worker ready / run idle. Parent and child each reached the controlled upstream through the current authenticated Host proxy; the token was absent from argv, models.json, logs, and diagnostics. The UI remained editable with neither runtime- unavailable nor permanent-recovering state. Cleanup reported zero retained workers, and an independent Windows process query found zero proof Electron/ Pi processes.
  • Pre-final packaged attempts were not counted as passes: the first used an unsupported optional embedded-commit assertion, and the real proxy run then failed on net::ERR_INVALID_ARGUMENT; that failure directly produced the sec-fetch-mode regression and the final package/proof rerun above.

Follow-ups

  • Real external Provider turn verification remains explicitly waived and its concurrency, credential-isolation, and protocol-compatibility risk remains accepted; the loopback Host-proxy proof must not be reported as a real Provider pass.
  • macOS and native non-WSL Linux release gates remain unchanged by this Windows hotfix.

Promotion Candidates

  • None. This feature task records the hotfix and evidence locally; it does not promote stale shared OpenCode-era canonical documents.