fix(pi): keep active runs alive during background sleep
This commit is contained in:
@@ -0,0 +1,184 @@
|
||||
# Task: Prevent background sleep from terminating active Pi runs
|
||||
|
||||
## Identity
|
||||
|
||||
- Task ID: 20260825-pi-background-run-lease-6a4e2c91
|
||||
- Mode: Feature
|
||||
- Branch: codex/20260825-pi-background-run-lease-6a4e2c91-pi-background-run-lease
|
||||
- Worktree: D:\Datas\OthersProjects\makelore-pi-background-run-lease-6a4e2c91
|
||||
- Base commit: 92f4c91088e79252aca76af3279b184da68e1eb7
|
||||
- Owner: codex-root
|
||||
- Status: Ready for integration
|
||||
|
||||
## Scope
|
||||
|
||||
- Add a Main-owned authoritative background lease for every queued or accepted
|
||||
top-level Pi Conversation run, acquired before mutation queueing and held
|
||||
through parent/child work until authoritative terminal cleanup.
|
||||
- Close the `BackgroundLifecycleController.sleepIfIdle()` in-flight race so a
|
||||
lease acquired while `onSleep` is awaiting prevents the later runtime stop,
|
||||
while preserving hidden-idle warm-worker eviction after all runs settle.
|
||||
- Terminalize supported intentional disposal of an active target Conversation
|
||||
before runtime projection state is removed, without replaying an accepted or
|
||||
uncertain mutation or affecting sibling Conversations.
|
||||
- Replace ambiguous Main stop reason `dispose` at supported callers with a
|
||||
bounded caller-specific reason, and retain content-free lifecycle evidence.
|
||||
- Extend focused Main/runtime/Renderer tests, Windows Electron E2E, final-ASAR
|
||||
packaged proof, and formal Windows NSIS/artifact verification.
|
||||
|
||||
## Intent And Constraints
|
||||
|
||||
- Preserve the Pi hard cutover and exact Pi `0.84.2`; do not add OpenCode
|
||||
fallback, a Provider watchdog, automatic mutation replay, a global daemon,
|
||||
schema migration, feature flag, compatibility track, or Pi upgrade.
|
||||
- The authoritative lease is Main-owned. Renderer visibility or IPC lease
|
||||
delivery must not own run liveness. Acquire synchronously before a top-level
|
||||
mutation can be queued/accepted; a parent lease covers its child/subagent.
|
||||
- Release the lease exactly once only after authoritative settle, definite
|
||||
pre-accept rejection, terminal crash/protocol failure, completed cancel,
|
||||
explicit dispose cleanup, or application shutdown cleanup. Generation or
|
||||
resource replacement for the same logical run must not release it early.
|
||||
- Preserve target isolation, the existing same-session recover contract, and
|
||||
no-replay semantics. Intentional termination while the UI remains alive must
|
||||
project a recoverable terminal state; it must not fabricate success.
|
||||
- Keep stop reasons finite and content-free. Diagnostics may retain only safe
|
||||
lifecycle classification, reason, redacted identifiers, generation,
|
||||
code/signal, stage, and duration; no prompt/tool/header/token/session text or
|
||||
complete project path may enter logs or Renderer DTOs.
|
||||
- Do not edit the read-only diagnosis task or overwrite the user's installed
|
||||
Makelore. Do not push or publish. Real Provider remains Explicitly Waived /
|
||||
Accepted Risk (`realTurnVerified=false`); macOS/native Linux gates are out.
|
||||
|
||||
## Project Context Loaded
|
||||
|
||||
- Concurrent Task Gate passed with isolated ownership of this task, branch,
|
||||
and worktree at base `92f4c91088e79252aca76af3279b184da68e1eb7`.
|
||||
- Diagnosis commit `dc820b2` is a docs-only sibling based on `941b015`, not an
|
||||
ancestor of the cumulative product HEAD; its task record was read-only and
|
||||
is not used as the implementation base.
|
||||
- Shared canonical memory remains OpenCode-stale relative to the cumulative Pi
|
||||
product. Current source, the Pi resilience contract, cumulative Pi task
|
||||
records, and the read-only output-stall diagnosis are authoritative here.
|
||||
- Eleven non-ready peer records were inspected. One owns an old main/OpenCode
|
||||
integration and the others are unrelated or placeholder scopes; no known
|
||||
peer owns Pi background lifecycle, runtime disposal, or packaged proof
|
||||
semantics. Placeholder scopes remain unknown coordination state but expose
|
||||
no semantic conflict that changes this isolated plan.
|
||||
- Relevant constraints are Main-owned run liveness, target-scoped monotonic
|
||||
terminalization, same-binding recovery, bounded stop reasons, no mutation
|
||||
replay, and final Windows packaged proof with zero residual resources.
|
||||
- Planning Gate result: Passed.
|
||||
|
||||
## Plan
|
||||
|
||||
1. Trace actual background lifecycle, Pi mutation/dispose, composition, and
|
||||
stop-reason callers; build a deterministic combined red test for the exact
|
||||
hidden-active-run failure and the in-flight sleep race.
|
||||
2. Add the narrow Main-owned lease dependency, acquire before top-level
|
||||
queue/acceptance, and release exactly once across settle/reject/crash/
|
||||
protocol/abort/dispose/shutdown paths.
|
||||
3. Reuse the existing Conversation projection chain to terminalize active
|
||||
intentional disposal before state removal, and pass caller-specific bounded
|
||||
reasons without changing settled runs or sibling Conversations.
|
||||
4. Extend Renderer/Host/Windows E2E and final packaged proof for hidden active
|
||||
completion, later idle stop, explicit-dispose unlock/recover/isolation, no
|
||||
replay, safe diagnostics, and zero resource/process residue.
|
||||
5. Run focused tests, typecheck, lint, full unit, build, Windows Electron E2E,
|
||||
then commit a clean candidate and run formal `package:win`, Windows/Pi
|
||||
closure verification, packaged proof, artifact fingerprinting, and the Task
|
||||
Documentation Gate.
|
||||
|
||||
## Outcome
|
||||
|
||||
- Implemented a Main-owned per-Conversation top-level run lease in the Pi
|
||||
runtime. Prompt and compact acquire before optimistic/queue acceptance;
|
||||
steer/follow-up reuse the parent run lease. Settle, definite rejection,
|
||||
crash, protocol invalidation, abort convergence, explicit recovery,
|
||||
intentional disposal, and shutdown release through an idempotent owner map.
|
||||
- Closed both background-stop races: the lifecycle controller rechecks
|
||||
visibility and leases after asynchronous sleep preparation, and the Pi pool
|
||||
rechecks the target's authoritative active-work predicate after pending
|
||||
prepare/rebuild work and immediately before worker cancellation.
|
||||
- Background sleep now refuses the entire coding-runtime sleep while any run
|
||||
is queued or active, while settled hidden workers remain eligible for normal
|
||||
eviction. A parent lease remains held while child/subagent resources finish.
|
||||
- Active intentional disposal projects the existing safe recoverable terminal
|
||||
failure on the target Conversation chain before cleanup/removal, preserves
|
||||
the durable session binding, does not replay the accepted prompt, and leaves
|
||||
sibling Conversations unchanged.
|
||||
- Replaced the ambiguous `dispose` worker stop reason with caller-owned finite
|
||||
reasons for background sleep, project deactivation/removal, Conversation
|
||||
deletion, auth cleanup, model reconfiguration, fork cleanup, app shutdown,
|
||||
and existing internal replacement/cleanup paths.
|
||||
- Extended the final-ASAR resilience proof to use the real Main composition for
|
||||
hidden active-run survival, settled idle eviction, intentional-dispose UI
|
||||
unlock/recover/isolation, safe lifecycle reason evidence, background lease
|
||||
counts, and zero residual resource/process verification.
|
||||
- The clean implementation candidate completed Windows NSIS creation, both
|
||||
artifact/closure verifiers, and the final packaged Main/UI/fault proof. The
|
||||
task record is amended into the cumulative delivery commit before the formal
|
||||
commands are rerun for the returned artifact.
|
||||
|
||||
## Verification
|
||||
|
||||
- `pnpm install --frozen-lockfile` — passed with package-manager-pinned pnpm
|
||||
`10.33.4` and locked Pi `0.84.2`.
|
||||
- Red phase: the new background lifecycle in-flight test observed one unwanted
|
||||
`onStopRuntime` call; the real Pi-runtime/lifecycle combination observed zero
|
||||
Main run leases after prompt acceptance.
|
||||
- Focused regression gate — passed: 8 files / 106 tests, covering lifecycle,
|
||||
running+queued Pi work, parent/child lease retention, exactly-once release,
|
||||
crash/protocol/abort/recover, forced disposal, worker reason diagnostics,
|
||||
project/auth callers, and packaged proof wiring.
|
||||
- `pnpm run typecheck` — passed.
|
||||
- `pnpm run lint:check` — passed with 5 pre-existing warnings and zero errors.
|
||||
- `pnpm test` — passed: 182 files, 1529 tests passed, 2 skipped.
|
||||
- `pnpm run build:vite` — passed for Renderer, Main, Preload, and utility
|
||||
bundles; only existing dynamic-import/chunk-size warnings were emitted.
|
||||
- `pnpm run test:electron:windows` — passed: 2 files / 4 tests.
|
||||
- Clean-candidate `pnpm run package:win` — passed; generated the Windows x64
|
||||
NSIS without overwriting an installed Makelore directory.
|
||||
- `pnpm run verify:artifact:win` — passed for NSIS/unpacked Electron, app.asar,
|
||||
bundled Python/uv/npm, and Windows native modules; verifier HEAD matched the
|
||||
clean implementation candidate.
|
||||
- `pnpm run verify:artifact:pi` — passed: exact Pi `0.84.2`, 130 production
|
||||
packages, 6 asset groups, zero missing/relocated package or asset, 5 native
|
||||
assets outside ASAR, managed Skills, and materialized extension/subagent.
|
||||
- `pnpm run test:pi-subagent:packaged` — passed from packaged app.asar Main:
|
||||
two UI/Main runs retained 2 background leases and 2 worker processes while
|
||||
hidden past grace; both settled, released leases, then warm idle workers
|
||||
stopped with reason `background_sleep`. Controlled intentional disposal
|
||||
projected `CODING_RUNTIME_START_FAILED` as recoverable, kept the sibling
|
||||
running and both bindings intact, and did not change Provider request counts.
|
||||
Recover reused the binding without mutation replay. Final workers, Pi
|
||||
processes, process leases, run permits, child permits/dispatches, extension
|
||||
registrations, write leases, and background leases all reached zero.
|
||||
- Packaged proof clean exit — passed with zero lingering tracked Electron/Pi
|
||||
PIDs. Lifecycle evidence distinguished unexpected exit, protocol
|
||||
invalidation, and intentional stop; every stop/replacement had a reason and
|
||||
redaction/content-free checks passed.
|
||||
- Authenticode inspection — `NotSigned`; no signing identity was available.
|
||||
- The returned installer is rebuilt and reverified from the amended cumulative
|
||||
clean HEAD; its exact path, size, SHA-256, and signing state are reported in
|
||||
the delivery response.
|
||||
|
||||
## Follow-ups
|
||||
|
||||
- PI-R002 soak/field attribution remains a separate follow-up and is not a
|
||||
blocker for this deterministic failure-convergence hotfix.
|
||||
- Real external Provider concurrency, credential isolation, and protocol
|
||||
compatibility remain Explicitly Waived / Accepted Risk with
|
||||
`realTurnVerified=false`; loopback/fault injection is not a Provider Pass.
|
||||
- macOS and native non-WSL Linux gate status is unchanged and not promoted.
|
||||
|
||||
## Promotion Candidates
|
||||
|
||||
- Target canonical document: Pi runtime architecture/resilience documentation.
|
||||
Proposal: record Main-owned top-level run leases, post-`onSleep` activity
|
||||
recheck, terminal-before-dispose monotonicity, and finite caller-owned stop
|
||||
reasons as accepted invariants. Evidence: focused lifecycle/runtime tests,
|
||||
Windows Electron E2E, final-ASAR hidden-run/idle-eviction/intentional-dispose
|
||||
proof, and zero-resource shutdown. Future impact: new Pi mutation or stop
|
||||
callers must join these seams rather than relying on Renderer visibility.
|
||||
Semantic conflicts: none known with the accepted Pi hard cutover/resilience
|
||||
plan. Human confirmation required: yes, during Integration Gate.
|
||||
Reference in New Issue
Block a user