218 lines
13 KiB
Markdown
218 lines
13 KiB
Markdown
# Task: Fix Pi worker exit terminalization and thinking contract
|
|
|
|
## Identity
|
|
|
|
- Task ID: 20260825-pi-worker-exit-thinking-5e7c2a91
|
|
- Mode: Feature
|
|
- Branch: codex/20260825-pi-worker-exit-thinking-5e7c2a91-pi-worker-exit-thinking
|
|
- Worktree: D:\Datas\OthersProjects\makelore-pi-worker-exit-thinking-5e7c2a91
|
|
- Base commit: 274187e3cfe2ae6cb97f2b4bcb422b3fdf06fbf2
|
|
- Owner: codex-root
|
|
- Status: Completed
|
|
|
|
## Scope
|
|
|
|
- Fix the installed Windows Pi Conversation lifecycle so an accepted run whose
|
|
matching worker generation exits or is protocol-invalidated converges within
|
|
a bounded time to a recoverable terminal failure instead of remaining
|
|
`running` or `aborting`.
|
|
- Make abort-after-exit and crash/abort/`agent_settled` ordering monotonic on
|
|
the target Conversation projection chain while preserving target isolation,
|
|
the original session binding, and no replay of an uncertain prompt.
|
|
- Add Main-only worker lifecycle forensics that distinguish unexpected exit,
|
|
protocol invalidation, and intentional stop with a required finite reason,
|
|
generation, stage, code/signal, and bounded redacted stderr.
|
|
- Persist and display only the thinking level Pi actually supports and accepts,
|
|
and derive managed custom-model reasoning compatibility from the authoritative
|
|
capability data without implicitly replacing a worker generation.
|
|
- Add focused, Host/SSE/Renderer, Windows Electron, and final packaged fault-
|
|
injection regressions; build and verify a new Windows x64 NSIS installer.
|
|
|
|
## Intent And Constraints
|
|
|
|
- Keep the Pi hard cutover. Do not add an OpenCode fallback, compatibility
|
|
layer, generic Provider watchdog, feature flag, or uncertain prompt replay.
|
|
- Serialize crash, abort, and settled handling by Conversation + generation.
|
|
A terminal run is monotonic; a stale generation cannot modify the active
|
|
Conversation; one crash cannot affect another Conversation.
|
|
- On crash/protocol invalidation, finally settle the target run and converge
|
|
its queue permit, process lease, pending interaction, extension run, child
|
|
worker, and project write lease. Normal live-worker abort continues to wait
|
|
for authoritative `agent_settled`.
|
|
- Thinking changes and same-account model changes must not restart a normally
|
|
running worker. Provider/resource/credential revisions rebuild only after the
|
|
accepted run settles, with an explicit generation-replacement reason.
|
|
- Every Main-initiated stop must use a bounded reason enum covering application
|
|
shutdown, idle eviction, stale-resource rebuild, recover, dispose, fork
|
|
replacement, protocol invalidation, and test injection or their exact current
|
|
implementation equivalents. Do not log prompt/response/tool/header/token,
|
|
expose stderr to Renderer, or write credentials into diagnostics.
|
|
- Preserve direct API-key, OAuth, local Provider, existing session persistence,
|
|
fork/recover behavior, and the user's installed application under
|
|
`D:\Tools\泥土\niancode\Makelore`.
|
|
- Use pinned pnpm `10.33.4`, frozen install semantics, focused/full verification,
|
|
formal Windows packaging, final artifact/runtime closure checks, and isolated
|
|
packaged product fault injection with zero residual proof processes.
|
|
- Real external Provider verification remains `Explicitly Waived / Accepted
|
|
Risk` with `realTurnVerified=false`; loopback/fault injection is not a real
|
|
Provider Pass. macOS and native non-WSL Linux status is unchanged.
|
|
|
|
## Project Context Loaded
|
|
|
|
- Concurrent Task Gate passed in the isolated worktree owned by `codex-root`;
|
|
task identity, branch, worktree, base, and task record match the registry.
|
|
- Planning Gate passed after reading project entry/memory/current-state,
|
|
architecture/domain/decision/evidence/reflection/commitment/stale records,
|
|
the Pi hard-cutover runtime/ticket constraints, both cumulative Windows Pi
|
|
hotfix records, the read-only stuck-processing diagnosis, and all active peer
|
|
task scopes.
|
|
- Base `274187e3cfe2ae6cb97f2b4bcb422b3fdf06fbf2` contains the earlier proxy-token
|
|
and persisted-session reopen delivery. The diagnosis worktree is read-only;
|
|
dirty `main` and all other task worktrees remain untouched.
|
|
- Shared canonical architecture/current-state files predate the Pi delivery.
|
|
The current source, Pi cutover contract, cumulative task records, and the
|
|
accepted diagnostic evidence are authoritative for this repair.
|
|
- The active peer tasks are older, unrelated, test-only, or read-only. The one
|
|
main-worktree OpenCode integration task explicitly does not package; no
|
|
unresolved semantic conflict changes this plan.
|
|
- Eleven copied-session packaged loopback cases settled normally, so Provider
|
|
SSE, session corruption, and `task_state` are not established causes. The
|
|
incident trigger remains unknown until the replacement artifact records the
|
|
bounded exit/stop classification.
|
|
- No subagents are used, per user direction and repository policy.
|
|
- The committed planning supplement
|
|
`2d9d8274d77986fe96e88f02ccba2b5389d2e696` is a direct child of this
|
|
task's base and identifies this executor task as `PI-R001`. Its
|
|
`RES-INV-001..009`, `RES-ACC-001..016`, release blockers, Main-only privacy
|
|
boundary, and final packaged fault-injection matrix are additional acceptance
|
|
contracts for this implementation. The content first entered as the
|
|
conflict-free cherry-pick `2b13454`; the exact source commit `2d9d827` was
|
|
then retained as a merge parent, so planning and implementation share one
|
|
history without rewriting either line of work. At the executor tip the
|
|
specification is materialized under the task-owned path
|
|
`20260825-pi-worker-exit-thinking-5e7c2a91__pi-runtime-resilience-hardening.md`;
|
|
the planner task record remains available in the original commit history
|
|
instead of violating feature-task document ownership.
|
|
|
|
## Plan
|
|
|
|
1. Inspect runtime, pool, process/RPC, extension/child/lease, model capability,
|
|
Host/SSE, Renderer, E2E, and packaged proof seams; map all worker stop callers
|
|
and generation-replacement reasons before changing contracts.
|
|
2. Add focused red regressions for active accepted-run exit, abort-after-exit,
|
|
exit/abort/settled ordering, target isolation and resource convergence;
|
|
unexpected/protocol/intentional diagnostics and redaction; effective
|
|
thinking persistence and no worker replacement.
|
|
3. Implement the smallest lifecycle, diagnostics, and capability changes that
|
|
satisfy the existing Pi contracts, retaining the original error category
|
|
and session binding through recover.
|
|
4. Extend Host SSE/Renderer unlock-and-recover and Windows packaged deterministic
|
|
fault-injection proof for running exit, abort-after-exit, settled-before-close,
|
|
strict JSONL invalidation, deliberate stop, isolation, no prompt replay, no
|
|
unexplained generation replacement, and zero residual processes.
|
|
5. Run frozen install, focused tests, typecheck, lint, full unit, `build:vite`,
|
|
Windows Electron E2E, formal `package:win`, artifact/runtime/closure
|
|
verification, and final packaged proofs from a clean committed candidate.
|
|
6. Record exact commits, changed files, verification results, structured
|
|
packaged evidence, installer size/SHA-256, accepted/deferred risks, clean git
|
|
state, and complete the Task Documentation Gate.
|
|
|
|
## Outcome
|
|
|
|
- Implemented matching-generation worker crash/protocol terminalization on the
|
|
per-Conversation projection chain. An accepted run now reaches recoverable
|
|
`error` without overriding an earlier terminal `agent_settled`; abort after
|
|
exit cannot restore `running`.
|
|
- Generation invalidation now cancels command, interaction, child/dispatch,
|
|
extension-run, process-permit, and write-lease resources for only the target
|
|
Conversation. Recover reopens the same persisted Pi binding and never
|
|
replays the uncertain accepted prompt.
|
|
- Added finite, required Main stop/replacement reasons and separate structured
|
|
lifecycle classification for unexpected exit, strict protocol invalidation,
|
|
and intentional stop. `PI_RPC_EXITED` retains bounded stderr after token,
|
|
header, credential, and managed-path redaction; prompt/response/tool content
|
|
is not copied into lifecycle diagnostics or Renderer state.
|
|
- Same-account model and thinking changes no longer replace the worker.
|
|
Hydration and mutations query Pi capabilities/state and persist/project only
|
|
the effective level. The managed `deepseek-v4-pro` profile now derives its
|
|
reasoning, DeepSeek compatibility, context/output limits, and supported
|
|
product thinking level from the imported authoritative capability profile;
|
|
unsupported levels reject instead of presenting false success.
|
|
- Renderer error state displays `本地 Agent 已中断,原请求未自动重发。`,
|
|
leaves the Composer editable, exposes recovery, and does not remain in
|
|
processing/recovering. The packaged proof now drives the real final-ASAR Main
|
|
composition through target exit, abort-after-exit, protocol invalidation,
|
|
settled-before-close, target recovery, sibling isolation, child/write-lease
|
|
cleanup, explicit deliberate stop, redacted lifecycle evidence, and clean
|
|
process exit.
|
|
- Concurrent packaged workers exposed a reachable Windows rename collision
|
|
while materializing the same managed extension. Materialization is now
|
|
single-flight per extensions directory; eight concurrent registrations share
|
|
one atomic result without changing the extension contract.
|
|
- Formal Windows `package:win` completed from the clean code candidate, including
|
|
pinned Python/uv acquisition, Vite production build, Pi runtime bundling, and
|
|
NSIS generation. The final product verifiers and the final-ASAR resilience
|
|
proof pass. Real Provider verification is not claimed.
|
|
|
|
## Verification
|
|
|
|
- `corepack pnpm install --frozen-lockfile` — pass with pinned pnpm `10.33.4`.
|
|
- Focused Pi/runtime/pool/RPC/extension/subagent/UI regressions — pass, including
|
|
6 files / 60 tests for the lifecycle contract and 2 files / 9 tests after the
|
|
extension materialization concurrency repair.
|
|
- `corepack pnpm run typecheck` — pass.
|
|
- `corepack pnpm run lint:check` — pass with 0 errors and 5 pre-existing
|
|
warnings in unrelated `Home`/`Makelore` files.
|
|
- `corepack pnpm test` — pass: 178 files / 1520 passed / 2 skipped, plus the
|
|
isolated pressure file 1/1 passed.
|
|
- `corepack pnpm run build:vite` — pass for Renderer, Main, Preload, and utility
|
|
bundles; existing dynamic-import and chunk-size warnings remain non-blocking.
|
|
- `corepack pnpm run test:electron:windows` — pass: 2 files / 4 tests.
|
|
- `corepack pnpm run package:win` — pass from the clean `7aa9f79` product-code
|
|
candidate. Two earlier attempts were blocked only by a transient GitHub uv
|
|
0.10.0 download timeout; the final formal command downloaded both x64/arm64
|
|
archives and completed without staging reuse.
|
|
- `corepack pnpm run verify:artifact:win` — pass: final `app.asar`, Electron
|
|
`43.4.0`, Node `24.18.1`, bundled Python/pip/sqlite/SSL, uv `0.10.0`, npm
|
|
`11.6.2`, required native modules/assets, and NSIS validated. The pre-task-doc
|
|
candidate installer was `211912226` bytes with SHA-256
|
|
`54559D5ADEFAF84F3F124A535A811778E2A347E1B5247F43C0D5A31BBDFC6C0D`;
|
|
the post-documentation clean-HEAD artifact metadata is reported in the final
|
|
handoff rather than being recursively embedded into the artifact-producing
|
|
commit.
|
|
- `corepack pnpm run verify:artifact:pi` — pass: Pi `0.84.2`, final
|
|
`resources/pi-runtime/dist/cli.js`, 130 production packages, 6 runtime assets,
|
|
5 native assets outside asar, managed Skills, and materialized
|
|
extension/subagent closure all present and executable.
|
|
- `corepack pnpm run verify:publish-runtime` — pass with npm `11.6.2`.
|
|
- `corepack pnpm run test:pi-subagent:packaged` — pass against the real final-ASAR
|
|
Main composition. Target worker exit and strict protocol invalidation reached
|
|
bounded recoverable terminal states; abort-after-exit did not restore
|
|
`running`; settled-before-close stayed terminal; sibling Conversation kept
|
|
running; recover reused the same binding and did not replay the uncertain
|
|
prompt. Lifecycle classifications and all stop/replacement reasons were
|
|
present and redacted, Renderer was unlocked with recovery available, all
|
|
pool/subagent/extension/write-lease counters returned to zero, and no tracked
|
|
Electron/Pi process lingered after exit. `realTurnVerified=false`.
|
|
- The first final proof attempt selected the still-running isolation Conversation
|
|
after reload, and the next locator matched both sidebar and header controls.
|
|
The harness now selects the fault-target sidebar entry deterministically and
|
|
emits Main/UI state on failure; no product assertion, timeout, or lifecycle
|
|
contract was relaxed.
|
|
|
|
## Follow-ups
|
|
|
|
- Later soak and any new real-external-Provider occurrence may use the new
|
|
bounded diagnostics to identify the initiating exit class. They are not
|
|
substitutes for this task's required deterministic convergence proof.
|
|
- Real Provider protocol/concurrency/credential-isolation verification remains
|
|
explicitly waived accepted risk and must continue to report
|
|
`realTurnVerified=false`.
|
|
- `PI-R002` loopback soak and field incident classification start only after
|
|
`PI-R001` is delivered. They do not block this repair or broaden its current
|
|
implementation scope.
|
|
|
|
## Promotion Candidates
|
|
|
|
- None recorded.
|