feat: add Pi subagent scheduler and child runtime

This commit is contained in:
2026-08-23 12:40:22 +08:00
parent b806c78139
commit f1c7cd8ad4
21 changed files with 1986 additions and 53 deletions

View File

@@ -0,0 +1,136 @@
# Task: Implement PI-080 child workers and subagent runtime
## Identity
- Task ID: 20260823-pi-child-workers-5c8e2a71
- Mode: Feature
- Branch: codex/20260823-pi-child-workers-5c8e2a71-pi-child-workers
- Worktree: D:\Datas\OthersProjects\makelore-pi-child-workers-5c8e2a71
- Base commit: b806c78139aa11e338c680d4c3fa92e076901aa2
- Owner: codex
- Status: Implementation complete; planner review pending
## Scope
- Implement `PI-080 — Subagent scheduler and nested protocol` on top of the
cumulative PI-070 baseline `b806c78139aa11e338c680d4c3fa92e076901aa2`.
- Own the Main-private child scheduler/supervisor, managed ephemeral child Pi
opener, parent-child lifecycle registry, global child concurrency limit, and
strict `subagent.v1` validation/projection.
- Extend the single managed Makelore Pi extension and its authenticated Main
bridge only as needed to dispatch `single`, `parallel`, and `chain` child
work and stream stable product details back to the parent tool.
- Add fake scheduler integration coverage, real Pi child process smoke,
process/semaphore leak coverage, bridge identity/abort coverage, and
same-project parent/child write-lease coverage. Renderer/Host product routes
and final nested UI remain owned by later tickets.
## Intent And Constraints
- Follow planner task `20260822-pi-runtime-spec-b6e2c9a4`, ticket `PI-080`,
Spec `UX-041` through `UX-044`, `EXT-001` through `EXT-006`, and section 9.4.
- A dispatch accepts exactly one mode, contains at most eight bounded tasks,
and resolves only through Makelore-owned `subagent.v1`; unknown schema or raw
Pi/example details never enter product state or diagnostics.
- Every child owns an independent ephemeral Pi process/context and uses an
enabled project Agent's managed prompt, skills, model, credentials, and one
exact `read-only` or `coding` tool profile. Child sessions are not persisted
as recoverable user Conversations and children cannot recursively dispatch
more subagents.
- Reuse the same application `PiProcessBudget` as parent workers for the locked
parent/child soft cap of eight and enforce one global FIFO maximum of four
running children across all parents. Do not add a competing process counter.
- Reuse PI-070's single project mutation lease. A coding child loads the same
managed extension lease hooks as its parent; read-only children receive no
mutation tools. Do not introduce child worktrees or a second mutation lock.
- Parent abort/crash/recover/dispose, stale generation/run identity, bridge
disconnect, and host shutdown cancel unfinished children and release every
child/process permit. Parallel failures preserve sibling results; chain
failure marks the remaining tasks skipped.
- Keep Provider credentials in the child environment/redaction set only. Real
external Provider validation remains **Explicitly Waived / Accepted Risk**
with `realTurnVerified=false`; macOS x64/arm64 remains deferred to mandatory
PI-150. Neither is a Pass.
- Keep the change surgical: no dual runtime, generic plugin/permission system,
project/user Pi discovery, Renderer wire changes, Host product routes,
OpenCode refactor, or canonical project-memory edits.
## Outcome
- Added the Main-private `PiSubagentScheduler` with strict one-to-eight task
validation, single/parallel/chain execution, one FIFO four-child semaphore,
a parent/run dispatch registry, shared `PiProcessBudget` acquisition, idle
parent reclamation when the eight-process budget is full, and deterministic
abort/error/skipped projection without raw child errors.
- Added the managed ephemeral child opener. It resolves only enabled,
unarchived project Agents from `.niancode/project.json`, materializes their
exact model/prompt/skills, keeps credentials in the child environment and
redaction set, selects the exact read-only or coding tools, uses
`--no-session`, and returns bounded public summary/usage data.
- Upgraded the single materialized Makelore extension bundle to v2. Parent
workers expose `ask_user` and `subagent`; child workers expose neither and
retain only the shared mutation-lease hooks required by coding tools. The
authenticated loopback bridge streams only NDJSON `subagent.v1` details and
rejects recursive child dispatch and stale identities.
- Connected subagent dispatches to PI-070 generation resource cancellation so
parent abort/crash/recover/dispose and bridge disconnect stop unfinished
children and release child/process permits. Coding children join the same
project write lease as their parent.
- Added vendor-neutral strict `subagent.v1` projection for live events, durable
session hydration, and reducer validation. Unknown versions render one fixed
unavailable message and never copy their raw payload into product state.
- `PiConversationRuntime` now configures the scheduler/bridge against the
existing pool generation tracker. Final product cutover and nested Renderer
presentation remain outside this ticket.
## Verification
- Focused scheduler, managed-child, bridge, bundle, projector, session, process
and contract tests passed, including: 1/4/8 task coverage and ninth-task
rejection; two-parent global child concurrency of four; full-budget idle
parent reclamation; parallel sibling preservation; chain skip/abort rules;
parent generation cancellation with no orphan and zero leaked permits;
recursive child rejection; parent/child same-project write-lease queuing;
and unknown schema/version raw-payload suppression.
- Locked real Pi 0.84.2 smoke passed for both the parent worker and an
ephemeral read-only child launched through Electron Node with the child
extension role and `--no-session`: 2/2 tests passed. This smoke performs
`get_state` and clean stdin shutdown only; it does not call an external
Provider.
- All cumulative Pi tests passed: 22 files, 106 tests.
- `pnpm run typecheck`: passed.
- `pnpm run lint:check`: passed with 0 errors and 6 pre-existing frontend
warnings outside this task.
- `pnpm run build:vite`: passed for Renderer, Main, Preload, and utility
worker bundles; existing chunk-size/dynamic-import warnings remain.
- First full-suite run, executed concurrently with the build, passed 2208/2209
and hit the known Windows temporary JSON `rename` `EPERM` in the unchanged
conversation store. The failing test passed in isolation, then the serial
full-suite rerun passed: 202 files, 2209 tests.
- Real external Provider validation remains **Explicitly Waived / Accepted
Risk** with `realTurnVerified=false`. Provider concurrency, credential
isolation, protocol compatibility, and image-path risk are accepted rather
than marked Pass. macOS x64/arm64 validation was not run and remains deferred
to mandatory PI-150; it is not marked Pass.
## Follow-ups
- PI-130 owns the final nested Renderer execution graph and user-facing child
error/abort presentation.
- PI-150 owns final packaged provider-shaped subagent smoke and mandatory
macOS x64/arm64 validation.
## Promotion Candidates
- Target canonical document: Pi runtime process/concurrency architecture.
Proposal: record that child budget acquisition must reclaim an idle parent
worker when the shared eight-process budget is full; otherwise the supported
shape of four running parents plus four warm-idle parents can deadlock while
the running parents wait on children. Evidence: the focused full-budget
scheduler regression test and the shared-budget implementation in PI-080.
Future impact: any final Main composition must pass one `PiProcessBudget` to
both the parent pool and child scheduler and wire the scheduler's capacity
reclaimer to `PiWorkerPool.reclaimIdleWorker`. Semantic conflicts: none with
the accepted PI runtime specification; this makes its parent/child cap
executable. Human confirmation required: no, unless integration changes the
accepted process-cap policy.