All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
-
Supervisor status injection during an in-flight tool call wedged the interactive session (#621): On batch phase transitions the supervisor injects display banners via
pi.sendMessage(customEntry, {triggerTurn:false}), which appends the entry (renderedrole:"user") at the current session leaf. If the interactive agent had an assistanttool_useappended but itstool_resulthad not yet landed (tool still executing), the banner spliced between them. On the next request Anthropic hard-rejected the conversation (400 ... unexpected tool_use_id ... in tool_result blocks; each tool_result must have a corresponding tool_use block in the previous message), permanently wedging the session — every retry re-sent the same broken ordering. Recovery previously required hand-editing the session.jsonl.Fixed with a two-layer defense:
- Prevention — a
SupervisorNoticeGateroutes the batch-end epilogue through an idleness check: it runs immediately when the agent is idle, otherwise defers the whole epilogue to the nextagent_settledboundary (the first lifecycle point at which all tool results, retries, compaction, and queued continuations have finished). A monotonic batch generation tag lets a newer batch — started via/orchor/orch-resume— supersede stale deferred work. - Defense-in-depth — a
contextevent handler (repairToolResultOrdering) reorders every outgoing provider request so eachtool_useis immediately followed by its matchingtool_result(s), relocating any spliced-in message after the tool-result group. This covers the other backgroundsendMessagesites (heartbeat, routing, integration progress) without gating each one, and only transforms the per-request context — the persisted session tree is untouched, so it self-corrects across reloads. Hardened (per Sage review) to preserve duplicate results, track emitted messages by identity, and repair result-before-assistant ordering without ever dropping atool_result.
Behavior note: when a batch completes while the interactive agent is mid-turn, auto-integration (supervised/auto modes) now starts at the next
agent_settledboundary rather than instantly — a small, bounded latency introduced deliberately to guarantee the epilogue can never split atool_use/tool_resultpair. This is distinct from #597 (a stale-ctx heartbeat crash); thesafeSendMessageFromTimerwrapper from #597 does not prevent #621 because the send succeeds — it just lands in the wrong place. - Prevention — a
-
Supervisor heartbeat timer crashed pi with stale extension ctx (#597, reported by @beettlle): Pi throws
"This extension ctx is stale after session replacement or reload"from itsassertActiveguard when an extension uses a capturedpi: ExtensionAPIhandle afterctx.newSession(),ctx.fork(),ctx.switchSession(), orctx.reload(). Two background timers insupervisor.ts(startHeartbeattakeover-detection branch,startEventTailer.notifycallback) capturedpiin their closures and calledpi.sendMessage()at arbitrary times — when the captured handle went stale between ticks, the throw became a process-fataluncaughtExceptionthat killed the entire Pi process during normal batch startup, taking the operator's supervisor UI and monitoring down with it.Fix introduces two helpers (
isStaleExtensionCtxandsafeSendMessageFromTimer) and rewires threepi.sendMessagecall sites through the never-throw wrapper: the two known timer-context sites pluspresentBatchSummary(reachable indirectly viastartHeartbeat → deactivateSupervisor → presentBatchSummarywhenstate.pendingSummaryDepsis set — caught by Sage's code review as a blocking gap in the initial fix). Also adds defensive timer teardown at the top ofactivateSupervisorso re-activation paths can't orphan timers holding stalepireferences. 9 new regression tests insupervisor.test.tsincluding a behavioral test (8.22) that mutation-verifies it actually catches regressions in the indirect path.
- Pi GitHub URL sweep + install tutorial PATH co-location (#604): Five
references to the legacy
https://github.com/badlogic/pi-monoURL inREADME.md,CONTRIBUTING.md,docs/specifications/cli/CLI-SPEC.md, anddocs/tutorials/install.mdupdated to Pi's canonical repo athttps://github.com/earendil-works/pi. Install tutorial's Option A also gains the PATH-setup snippets (bash/zsh + PowerShell) co-located with the install command, so users hit the complete unified-update recipe (pi install→ add bin dir to PATH →pi updateis the single source of truth) at the natural decision point rather than only in the later 'taskplane not on PATH' troubleshooting section. @mariozechner/*stale-references follow-up sweep (#605): Pi was renamed from@mariozechner/pi-coding-agentto@earendil-works/pi-coding-agentat Pi v0.74.0 (issue #560). TP-191's tsconfig modernization was supposed to refresh related stale references but several were overlooked. This sweep updates the truly stale items (theextensions/tsconfig.json// NOTEcomment that thecode-quality-gates.mdspec explicitly flagged as awaiting refresh, the CLI-SPEC peerDependencies examples, and threenpm install -g @mariozechner/pi-coding-agentinstall commands in the framework spec) while preserving accurate descriptions of back-compat behavior in maintainer docs (the test loader genuinely still aliases@mariozechner/*because Taskplane source code still imports under those names — Pi maintains both scope aliases at runtime).
taskplane --versiondisplayed "vundefined, initialized unknown" placeholders for.pi/taskplane.jsonfiles lackingversion/installedAtfields: Reproducible in any repo where.pi/taskplane.jsonexists for a non-init purpose (e.g. taskplane's own source repo, where the file carries only migration history).cmdVersion()now defensively renders only the fields that are actually present and non-empty; falls through to(metadata only)when neither field is set. Cosmetic but operator-visible.
taskplane doctordetects duplicate Pi-private / npm-global installs: Pi 0.75.0 (2026-05-17) moved user-scoped pi extensions from npm's global root to~/.pi/agent/npm/node_modules/. Operators who had previously installed vianpm install -g taskplanenow have two on-disk copies that drift independently:pi updaterefreshes only the Pi-private one, so the system-wide CLI silently runs stale code. The newdetectDuplicateTaskplaneInstall()helper incmdDoctoridentifies this state (both copies present + versions differ) and emits a WARN with both paths, both versions, and a platform-aware remediation (PowerShell snippet on Windows, bash form on Linux/macOS, both inline on either). Same-version pairs are silently tolerated. Best-effort: 5s timeout onnpm root -g, silently returns null on errors so doctor never crashes on this side check. Doctor's failure-summary line is also context-aware now: when duplication is the issue it points atnpm uninstall -g taskplaneinstead of the generictaskplane init(which was actively misleading remediation for this case).
README.mdInstallation section: documents the PATH requirement for Pi 0.75.0+ (bash/zsh + PowerShell snippets) so thetaskplaneCLI is callable on the shell afterpi install npm:taskplane. Adds a duplication-caveat note for users who previously rannpm install -g taskplaneunder older docs.docs/tutorials/install.md: Reframes Option A (Global install) to explicitly steer users away fromnpm install -g taskplaneas the primary install command, citing the Pi 0.75.0 install-location change and the duplication caveat. Expands the "taskplane not on PATH" troubleshooting section into three labeled options (npx, direct bin invocation, PATH addition) with platform-specific snippets for each.
-
Pi CLI resolution fails on NVM-Windows and non-canonical installs (#598, #519):
resolvePiCliPath()ignoredprocess.argv[1]and relied entirely onnpm root -gplus a small static fallback list. That stranded NVM-on-Windows users (child processes inherit a stripped PATH, sonpm root -greturns empty and the fallback list doesn't include NVM-versioned dirs) and Nix users (Pi lives at/nix/store/..., outside any npm prefix). The fix addsprocess.argv[1]as the authoritative candidate 0 — when Taskplane runs as a Pi extension, the parent process IS Pi and Node setsprocess.argv[1]to Pi'scli.jsdirectly. Two sanity guards (endsWith('cli.js')+existsSync()) keep wrappers and test runners from being mistaken for Pi. Defense in depth: two additional env-var-driven bases ($NVM_SYMLINK\node_modulesfor NVM-for-Windows,dirname($NVM_BIN)/../lib/node_modulesfor NVM-for-Unix) cover the same NVM scenarios in environments whereargv[1]isn't available. 6 new regression tests inpath-resolver-pi-scope.test.ts. Apologies to@chenxin-yanwhose PR #520 (closed 2026-05-25) proposed exactly this fix forresolvePiCliPath7 weeks ago — it was incorrectly closed as already-fixed becauseprocess.argv[1]had been added to the siblingresolveTaskplanePackageFileresolver, but not toresolvePiCliPathitself. -
Dashboard merge agent telemetry missing for some waves (#509): Merge snapshot files were keyed on disk by
mergeNumberalone (merge-{N}.json), andmergeNumberis derived fromlane.laneNumber. Because lane numbers reset every wave, wave N+1's lane-1 merge silently overwrote wave N's lane-1 terminal snapshot before the dashboard could read it — surfacing as—in the merge telemetry column for any wave whose lane numbers were reused by a subsequent wave. The fix namespaces the filename per wave (merge-w{waveIndex}-{mergeNumber}.json) and updates the dashboard server's intermediate map key to a composite (w{waveIndex}-{mergeNumber}) so collisions can't reappear at read time. Filename filter remains permissive so legacy snapshots from pre-fix batches still load for back-compat. 4 new regression tests inprocess-registry.test.ts(7.4–7.7) pin the cross-wave invariants. -
Dashboard briefly flips to history view at batch startup (#507): A single missed SSE poll during
batch-state.jsonwrite at startup triggered the no-batch handler inapp.js, which closes the viewer and renders the history panel before the next poll picked up the new batch. The user-visible effect was a flash of stale history between two live batches. The fix adds a 3-consecutive-miss debounce on the no-batch transition (~6s with the 2sPOLL_INTERVAL) — well past the sub-secondbatch-state.jsonwrite window while still cleaning up promptly when a batch genuinely ends. -
Wave-merge counter
(N/3)overflow past wave 3 (#562): In polyrepo batches where task-level waves expand into segment-level merge rounds (3 task waves → 6 segment rounds in the reporter's case), the merge_success alert's(X/Y)counter overflowed its denominator:(1/3),(2/3),(3/3), then(4/3),(5/3),(6/3). The supervisor formatter's(X/Y)rendering paired a segment-round numerator with a task-level denominator fromtaskLevelWaveCount. The fix swaps the event emission'stotalWavessource fromtaskLevelWaveCounttobatchState.totalWaves(the segment-expanded round count), so numerator and denominator share units. Purely cosmetic — functionality was correct. Regression test 5.8a insupervisor.test.ts.
- Administrative closeouts for already-shipped fixes: Closed five stale
open issues whose fixes had already shipped in earlier releases but were
never marked complete: #557 (Pi
@earendil-worksrename — fixed by34b303a4in v0.29.0), #538 / #539 / #540 (supervisor recovery cluster — all three fixed by TP-187 in v0.29.0), and #519 (Nix CLI resolution — NOW fixed in v0.30.2; the closeout in May was incorrect). Open issue queue dropped from 16 to 7 across this release cycle.
-
Dashboard segment-level progress indicators (TP-197, #464): Multi-segment task rows now show a horizontal pill row of per-segment status badges — one pill per segment with a status icon (✅ succeeded · ⏳ running · ⬚ pending · ❌ failed · ⏸ stalled · ↷ skipped) plus the segment’s repo ID. The currently-executing segment is visually emphasized. This closes the operator-visibility gap introduced by TP-145’s
.DONEsuppression for non-final segments: previously, multi-segment lanes sat “running” with no segment-level signal during the suppression window, which made wave 2+ batches where all tasks were mid-segment appear stuck. With the pill row in place, operators can see at a glance which segments have finished, which is running, and which remain. The progress bar itself is unchanged — TP-174 already made it segment-scoped via the V2 lane snapshot’s per-segment counts; the new pill row provides the missing context that makes the existing bar legible as “current segment’s progress.”Backwards-compatibility: single-segment tasks render an empty pill row (auto-collapsed grid sub-row), so the DOM and visual layout for non-segmented batches are identical to before. The pill row lives in a new grid row 3 of
.task-row(cols 3–7), mirroring thetask-title-subtitlepattern from TP-485, and is intentionally placed outside the.task-stepcell so the existing@media (max-width: 900px)rule that hides.task-stepdoes not hide segment context on narrow viewports. Nodashboard/server.cjschange was required — the existing API response already exposedbatch.segments[],task.segmentIds, andruntimeLaneSnapshots[*].segmentId.
-
Multi-segment engine hardening (TP-196, #462 + #502 + #503 + #508): closes four follow-up issues from the multi-repo task execution rollout with a single coherent hardening pass against the multi-segment engine.
-
.DONEauthority guards (#462) — three defense-in-depth checks now refuse to honor a stale or premature.DONEin multi-segment tasks: (a)resolveTaskMonitorState(execution.ts) accepts an optionalmultiSegmentContext: { isFinalSegment, segmentId }parameter; whenisFinalSegment === falseand.DONEis present, Priority 1 is skipped and a WARN is logged viaexecLog;monitorLanespopulates this context fromtask.segmentIds+task.activeSegmentId. (b)collectDoneTaskIdsForResume(resume.ts) now refuses to add a taskId to the done set when persisted segment records exist AND any segment is notsucceeded/skipped— the task re-reconciles instead of silently being marked complete. (c) A new exportedcheckDoneAuthoritySafeguardhelper (discovery.ts) emits a doctor-styleconsole.warnwhen.DONEcoexists with unchecked STATUS.md checkboxes during area scans. The pre-existing TP-135 "keeps .DONE authoritative even when segment frontier is incomplete" test was updated to assert the inverted (post-#462) contract. -
SegmentScopeMode unification (#502 + #503) — promotes the FULL_TASK / SEGMENT_SCOPED decision to a first-class
SegmentScopeMode = "FULL_TASK" | "SEGMENT_SCOPED"type intypes.tsplus acomputeSegmentScopeMode(stepSegmentMap, repoStepNumbers, currentRepoId, currentStepNumber)helper inlane-runner.ts. The iteration loop now derives both the authoritativesegmentScopeModeand the legacyisSegmentScopedboolean alias from one call, and the segment-prompt injection block is gated onisSegmentScopedinstead of the previous scatteredstepSegmentMap && currentRepoId && repoStepNumbers && remainingSteps.length > 0composite. New behavioural regression suite (extensions/tests/segment-scope-mode-prompt.test.ts, 9 tests across 4 describe blocks) mocksspawnAgentto capture the worker prompt + env + system prompt and verifies the FULL_TASK, SEGMENT_SCOPED, polyrepo single-segment, and legacy/partial-marker contracts end-to-end. -
Wasted-iteration elimination (#508) — lane-runner now performs an explicit pre-spawn segment-completion check between the existing
remainingSteps.length === 0guard and thetotalIterations++increment, delegating to a new pure helpershouldSkipSpawnForCompleteSegment(statusContent, repoStepNumbers, currentRepoId). When every segment-scoped step for the active repo is already complete, the loop logs"Pre-spawn segment-completion check"and breaks before incurring a worker spawn. Behavioural test (extensions/tests/early-exit-segment-spawn-skip.test.ts) mocksagent-host.spawnAgentviamock.moduleand assertsspawnAgentCallCount === 0for a fixture worktree whose checkboxes are pre-checked. -
Validation: typecheck / lint / format:check all exit 0. Fast test suite passes at 3678 / 0 fail / 1 skip — net +51 new tests spread across 3 new test files plus targeted updates to
segment-scoped-lane-runner.test.ts,resume-segment-frontier.test.ts, andengine-runtime-v2-routing.test.ts(slice-window widening for the longerresolveTaskMonitorStatebody).
-
- Preflight cleanup feature now actually runs (TP-195):
runOrchBatchinextensions/taskplane/engine.tsreferencedsweepStaleArtifacts,formatPreflightSweep,rotateSupervisorLogs, andformatLogRotationinside the preflight-cleanup try-block, but those identifiers were never imported from./cleanup.ts. At runtime the first reference threw a ReferenceError that the enclosing catch-all swallowed, so Layers 2–5 of preflight cleanup (age-based artifact sweep, supervisor log rotation, telemetry size cap, prior-batch artifact cleanup) had been silently a no-op since TP-065 / #221 (․2024-09). The missing imports were uncovered by the TP-191 typecheck script; this fix adds them so the advertised cleanup runs on every batch. Regression test:tests/lane-runner-v2.test.ts 3.10asserts the four helpers are imported from./cleanup.ts. max_worker_minutesconfig field is honored (TP-195): Lane-runner config inexecuteLaneV2(extensions/taskplane/execution.ts) was reading a non-existentconfig.failure?.maxWorkerMinutescamelCase alias — always undefined — silently ignoring any operator-set value onOrchestratorConfig.failure.max_worker_minutesand always falling through to the hard-coded120-minute default. Fixed to read the canonical snake_case field. Operators withmax_worker_minutesconfigured in.pi/taskplane-config.jsonwill now have their configured limit honored; default of 120 preserved when the field is unset. Regression test:tests/lane-runner-v2.test.ts 3.9asserts the corrected accessor and absence of the typo.- Resume’s failed-task supervisor-alert path no longer crashes
(TP-195): When
/orch-resumeencountered a failed task during a wave, the supervisor-alert emission block inresume.tscalledbatchState.tasks.find(…), butOrchBatchRuntimeStatehas notasksfield (onlyPersistedBatchStatedoes). The runtime call would throwTypeError: undefined.find is not a function. The failed-task path was never covered by tests, so the crash never surfaced. Replaced with a lookup againstlaneForTask?.tasks.find (…)?.task— the lane-allocatedParsedTaskpayload carries the samesegmentIds/activeSegmentIddata the alert needs. Regression test:tests/resume-bug-fixes.test.ts 4.1.
-
Code-quality gates active (TP-194)
The final task packet implementing the code-quality-gates spec (
docs/specifications/taskplane/code-quality-gates.md, section 6.4). Flips three static-analysis checks from advisory to required CI gates:Typecheck(new —tsc --noEmitagainstextensions/tsconfig.ci.json),Lint (Biome)(was already wired but ran withcontinue-on-error: trueuntil now), andFormat check (Biome)(new —biome format --no-errors-on-unmatched .)..github/workflows/ci.ymlruns the three steps in order before the existingRun testsstep inside the singlecijob, so any failure short-circuits the rest of the pipeline. The existing requiredcibranch-protection context already covers the new gates because a step failure fails the whole job.Reviewer-agent activation: the TP-188 quality-check verification section in
templates/agents/task-reviewer.mdis now fully active. The temporary activation note added in TP-191 (which previously surfaced quality-check failures as Issues Found without downgrading the verdict) is removed; failing typecheck/lint/format:check now unconditionally downgrades APPROVE → REVISE during code review. Documentation updates:AGENTS.mdadds the three commands to the validation checklist;docs/maintainers/release-process.mdadds them to the pre-release checks and pre-release checklist;docs/maintainers/development-setup.mdgets a new "Code-quality gates (required for every PR)" section. The long-missinglint:fixnpm script (referenced by these docs) is added topackage.json.Operator handoff (verification-only): no branch-protection changes are required. After this PR merges, verify via
gh api repos/HenryLach/taskplane/branches/main/protectionthatrequired_status_checks.contextsstill containsci(it does today). If at some future point per-gate visibility in branch protection is desirable, the follow-up is to split the gates into separate jobs inci.yml— out of scope for TP-194 per the spec's Tier-1.5 follow-up list. -
Code-quality typecheck cleanup (TP-195): Fourth of four sequenced packets implementing the code-quality-gates spec (
docs/specifications/taskplane/code-quality-gates.md). Cleaned up the 264 typecheck errors that TP-191 surfaced when it first madenpm run typecheckrunnable, so TP-194’s gate flip can promote typecheck from advisory to a CI gate. Final state:npm run typecheckexits 0 againstextensions/tsconfig.ci.jsonat the current strictness (strict: false,noImplicitAny: false). Per-category breakdown of fixes (top categories at task start): TS2339 (63) — property-not-exist; TS2741 (52) — mock-object missing required fields; TS2345 (30) — caller-shape mismatch; TS2554 (23) — signature drift; TS2367 (21) — unintentional comparison; TS2322 (19) — assignment mismatch; TS2739 (12) — type missing properties; plus smaller TS2769/TS2353/TS2352/TS2559/TS2347/TS2578/TS2304/TS2871/ TS2694 counts. Source-side highlights: 4 latent bugs uncovered and fixed (preflight-cleanup-feature no-op,max_worker_minutestypo, resume failed-task crash, plus an extension.ts dashboard change-detection that was reading non-existent fields and only ever refreshing oncurrentTaskId— dropped the dead comparisons, observable behavior unchanged); widenedexecLog’sextraparameter fromRecord<string, string\|number\|boolean>toRecord<string, unknown>(callers were already passing arrays/ objects; template-string stringification preserved); re-exportedRuntimeRegistryfromprocess-registry.ts; documented optionalbatchId?field onOrchestratorConfig.orchestrator; addedEXEC_MISSING_TASK_FOLDERtoExecutionErrorCode; fixed discriminated-union narrowing under non-strict mode by addingreason?: undefined/error?: undefinedto success branches; switchedloadProjectOverrides/migrateProjectOverrides/loadJsonConfig/mergeProjectOverridestoDeepPartial<TaskplaneConfig>; changedspawnMergeAgentV2return type toPromise<void>(fire-and-forget). Test-side highlights: introduced sharedtests/helpers/mock-orchestrator-config.tsfactories (makeOrchestratorConfig/makeTaskRunnerConfig) that wrapDEFAULT_*_CONFIGdefaults fromtypes.tsso test mocks stay in sync with the runtime schema; addedexpect.unreachable()and optional 2ndmessagearg toexpect()(Vitest-compat surface that ~190 sites already relied on); fixed phase-narrowing in 9.x launch-window suite via typedOrchBatchPhasecasts; updatedLaneRunnerConfig/PersistedTaskRecord/MergeResult/BatchSummaryData/MinimalBatchState/WorkspaceRoutingConfigfixtures to match current schemas; replaced legacyRuntimeAgentStatus"complete"with canonical"exited"; convertedit(name, fn, 30000)calls toit(name, { timeout: 30000 }, fn)for node:test compatibility; declaredmock.fn<(…args: any[]) => any>()somockImplementationaccepts non-undefined returns. Anti-shortcut policy enforced: zero newas anycasts; zero@ts-expect-erroradded (the 3 unused-directive errors were removed); only legitimate 2-stepas unknown as Xwidenings with justifying comments; no garbage default values — every mock-object missing-field fix uses a schema-defined value. Pi-shim extendedExtensionContextfromanyto a structural interface soctx.ui.custom<T>()typechecks at 4 settings-tui.ts call sites;uileft optional so thin test mocks (e.g.,{ model: null }) still satisfy the type. After the pass:npm run typecheckexits 0;npm run lint/npm run format:checkunchanged from baseline; test suite 3627 passing / 1 skipped / 0 failed (TP-191 baseline 3624 + 3 new TP-195 regression tests for the fix-the-bug paths). Strict mode remains out of scope — the strictness ratchet (enablingstrict: true/noImplicitAny: true) is a separate post-TP-194 follow-up. With this packet merged, TP-194’s typecheck-gate flip CRITICAL pre-condition (“npm run typecheckexits 0 onmain”) is satisfied. -
Code-quality formatter adoption (TP-193): Third of four sequenced packets implementing the code-quality-gates spec (
docs/specifications/taskplane/code-quality-gates.mdsection 6.3). Enabled the Biome formatter and applied it once across the entire codebase in a single mechanical commit. Formatter rules pinned inbiome.jsonper spec section 6.3.1:indentStyle: "tab",indentWidth: 1,lineWidth: 100,lineEnding: "lf",quoteStyle: "double",trailingCommas: "all",semicolons: "always",arrowParentheses: "always". Format pass touched 161 files (every TS/MJS file in scope) with cosmetic-only changes — line wrapping, trailing-comma insertions, single-param arrow parens, and a small number of quote-style switches where Biome's smart-quote rule picked the alternative quote when the primary was inside the string. No semantic changes. Test resilience prep preceded the format pass in a separate commit: introducedexpect().toContainNormalized()(whitespace + bracket-padding + trailing-comma normalized substring match) and updated 22 distinct source-grep test assertions across ~20 test files to use the helper or pre-normalize source before matching; bumped fixed-size source-slice windows in retry-matrix, spawn-failure-visibility, supervisor-recovery-flows, and tier0-watchdog tests so vertically-rewrapped multi-arg calls don't push expected needles outside the inspected window.tmux-reference-audit.mjswas extended to skip strict-mode functional-usage detection inside test files, because Biome's quote-style switch unmasked literal assertion strings like"execSync('tmux list-sessions"that would otherwise flag the audit..git-blame-ignore-revsadded at the repo root listing the format-adoption commit SHA sogit blamedoesn't bottom out on the bulk reformat; per-developer one-time setup (git config blame.ignoreRevsFile .git-blame-ignore-revs) documented indocs/maintainers/development-setup.md. After the pass:npm run format:checkexits 0;npm run lintexits 0 (TP-192 cleanup preserved); test suite unchanged at 3624 passing / 1 skipped / 0 failed. Theformat:checkgate flip is TP-194's scope. -
Code-quality lint cleanup (TP-192): Second of four sequenced packets implementing the code-quality-gates spec (
docs/specifications/taskplane/code-quality-gates.mdsection 6.2). Fixed all 9 pre-existing Biome lint errors inmainso TP-194 can promotenpm run lintfrom advisory to a CI gate without breaking the build. Errors fixed by category:noImplicitAnyLet× 5 — added explicit type annotations to regex-exec loop variables (let m: RegExpExecArray | null;) inlane-runner.tsandtask-executor-core.ts(3 sites), and to areaddirSyncresult (let entries: Dirent[];) inmerge.ts(added matchingtype Direntto the existingnode:fsimport).noControlCharactersInRegex× 1 — inverification.ts, convertedANSI_REGEXfrom a regex literal containing\u001b\u009bescapes tonew RegExp("...", "g")with an escaped string body; runtime behavior is identical (the rule only inspects regex literals, not constructor strings). The stale// eslint-disable-next-line no-control-regexcomment was dropped (this repo has no ESLint).noRedeclare× 2 — inwaves.ts, removedAllocateLanesResultfrom the type-import on line 10 (it was not actually exported from./types.ts; the localexport interface AllocateLanesResultat line 1072 is the canonical declaration); intests/orch-state-persistence.test.ts, renamed the duplicateresolveRepoRoottest helper in section 8.1 toresolveRepoRootMixedRepoand updated its 14 in-section callers (bodies are functionally identical, so behavior is preserved; the section-7 helper at line 4226 keeps its original name).noUnsafeFinally× 1 — inextension.tswithPreservedBatchHistory, invertedif (!snapshot) return;(early-return inside afinallyblock) toif (snapshot) { ... }(conditional execution); same observable behavior, noreturninfinally. No suppressions added — every error received a real fix. Affected files: 7 source files (extension.ts,lane-runner.ts,merge.ts,task-executor-core.ts,verification.ts,waves.ts) plus 1 test file (orch-state-persistence.test.ts). After cleanup:npm run lintexits 0 (was: 9 errors); typecheck dropped from 267 to 264 errors (incidental, from explicit regex-exec type annotations — new TP-194 baseline); test suite unchanged at 3624 passing / 1 skipped / 0 failed. -
Code-quality prep — scripts, tool pinning, pi-shims (TP-191): First of four sequenced packets implementing the code-quality-gates spec (
docs/specifications/taskplane/code-quality-gates.md). This packet is prep only — no gating changes, no behavior changes, no lint cleanup. (1) Scripts — added a rootpackage.jsonscriptsblock withtypecheck(tsc --project extensions/tsconfig.ci.json --noEmit),lint(biome lint .),format(biome format --write .), andformat:check(biome format .). Names match the reviewer-agent's TP-188 discovery list verbatim. (2) Tool pinning — added@biomejs/biome@2.4.15,typescript@5.6.3, and@types/node@22to rootdevDependencies, removing thenpx ...@latestdrift from CI. (3) Pi-shims — newextensions/types/pi-shims.d.tsdeclares minimal type stubs for both@earendil-works/*AND@mariozechner/*Pi packages (pi-coding-agent, pi-ai, pi-tui) so headlesstsc --noEmitresolves imports without the actual pi packages installed locally. (4) CI tsconfig — newextensions/tsconfig.ci.jsonextends the editor-facingtsconfig.json(untouched) with comprehensiveinclude,pathsmapping pi specifiers to the shim, andtypeRootspointing to root@types/node.tsconfig.test.jsonupdated to add@earendil-works/*mappings alongside legacy@mariozechner/*(back-compat preserved). (5) Biome modernized —biome.json$schemaURL updated to2.4.15, deprecatedexperimentalScannerIgnoresmigrated to negation patterns insideincludes(Biome 2.2+ canonical syntax), scope expanded to coverbin/**/*.mjs,scripts/**/*.mjs, andextensions/**/*.tsx; tests now in scope (sage's recommendation per spec section 7.2);dashboard/public,extensions/types,.pi,.worktreesexcluded; formatter still disabled (TP-193 enables). (6) Reviewer discoverability —.pi/taskplane-config.jsontaskRunner.testing.commandsnow declarestypecheck,lint,format:check(and the existingtest);templates/agents/task-reviewer.mdcarries a temporary activation note explaining that typecheck/lint/format:check failures surface as Issues Found but do NOT downgrade APPROVE→REVISE until TP-194 lands (note removed in TP-194). (7) CI workflow —.github/workflows/ci.ymllint step now runsnpm run lint(stillcontinue-on-error: trueuntil TP-194); addedInstall root dev dependenciesstep before lint and updated the Node setup-action cache-dependency-path to include both root and extensions lockfiles. Captured baselines for TP-194's gating decision: 267 typecheck errors and 9 lint errors / 277 warnings / 660 infos across 175 files. All 3624 tests still pass (1 skipped, 0 failed) — zero behavior changes.
-
Migrate
peerDependenciesfrom@mariozechner/*to@earendil-works/*and mark them optional: everypi updatewas printing fournpm warn deprecatedlines (one for each@mariozechner/pi-*package the new pi packages tell npm they are deprecating). Pi v0.74.0+ ships under the@earendil-worksscope; the legacy@mariozechnerpeer-dep entries in taskplane'spackage.jsonmade npm resolve the deprecated packages and surface the warnings on every install. Fix: switch the four pi-related entries inpeerDependenciesto@earendil-works/pi-coding-agent,@earendil-works/pi-tui,@earendil-works/pi-ai(kept@sinclair/typeboxunchanged — not pi-managed); add apeerDependenciesMetablock marking all three pi packagesoptional: trueso npm doesn't generate unmet-peer warnings for users in transitional setups, and so we don't tell users they MUST have pi globally installed at npm-install time (pi is the runtime, not a strict install-time peer).No source-code changes. The
importstatements inextensions/*.tscontinue to reference@mariozechner/*because Pi's runtime extension loader (<pi>/dist/core/extensions/loader.js) bundles aliases for BOTH scopes — imports resolve identically regardless of which scope name is used. Changing the import statements would break compat for users still on Pi < v0.74.0 (the alias map was added in v0.74.0). ThepeerDependenciesdeclaration is informational only; the runtime resolution is unaffected by either approach.No tests changed; no behavior changed. Tests pass at the v0.29.1 baseline (3624 passing / 1 skipped / 0 failed).
-
Runtime V2 spawn failures now visible (TP-190, #561): Previously, when a Runtime V2 lane spawn failed at the very first call site (Pi CLI not findable, worktree provisioning error, branch collision), the lane was not transitioned to
failed. The engine continued polling indefinitely, the dashboard showed green/running lanes that had no actual worker process,orch_status()reportedexecuting, and no supervisor alert fired. Recovery required the operator to manuallytailengine-worker stderr — not in any documented diagnostic place. This bug masked the operator-side impact of #559 (orchestrator IPC crash) and #560 (@earendil-worksrename), making both look like hangs rather than immediate spawn errors. Fix has four parts: (1) State transition — the existing per-task try/catch inexecuteLaneV2now tags the failedLaneTaskOutcomewithexitDiagnostic.classification = "spawn_failure"(a newExitClassificationvalue alongsideprocess_crash,stall_timeout, etc.) and writes a synthetic terminalRuntimeLaneSnapshotsomonitorLanesresolves the lane to terminal state instead of looping forever on the never-written snapshot file (the actual root cause of the silent hang). (2) No-retry policy —spawn_failureis intentionally NOT inTIER0_RETRYABLE_CLASSIFICATIONSbecause spawn-stage errors are never transient; a defense-in-depth early return inattemptWorkerCrashRetryproduces an operator-friendly log line. (3) IPC alert — thetask-failuresupervisor alert payload now carriescontext.exitCategory(and a "Spawn failure: … escalate immediately" summary line when applicable) so the supervisor playbook can branch on spawn-stage failures and escalate without retrying. The same wiring is mirrored inresume.tsfor/orch-resumeparity. (4) Phase transition — when every task in a wave fails withclassification === "spawn_failure",batchState.phasetransitions from"executing"to"failed"(not"paused", because the operator cannot un-stick spawn failures without changing something external). Validation: 33 new behavioral + helper tests inextensions/tests/spawn-failure-visibility.test.ts; full fast suite 3620 pass / 1 skipped / 0 failed (+33 from baseline 3587); cross-platform Node 24 CI.Sage post-merge fold: two important correctness issues caught by sage's review of the merged TP-190 work, both folded before public release. (a) Residual hang on snapshot-write failure: the spawn- failure catch's
writeLaneSnapshot()is best-effort, but the original comment claimed a 30-second staleness fallback would recover — not true whensnap == null(no file at all), becausesnap?.updatedAtisundefinedsostaleMs == 0and the 30-second check never fires. Snapshot-write failure (disk full, permission, transient I/O) would have leftsessionAlive = trueindefinitely, reintroducing the same #561 hang. Fix: added a null-snapshot tracker-age fallback inresolveTaskMonitorState— whensnap == nullAND the tracker has observed the task for ≥ 60s (past startup grace), consult the registry liveness check instead of defaulting to alive. (b) Multi-segment edge inisAllLanesSpawnFailedWave: thesucceededTaskIds.length !== 0gate was the terminal completion projection, populated only when a multi-segment task reaches its final segment. A wave with a multi-segment task succeeding on segment 1 (with continuation scheduled) plus a single-segment task spawn-failing would have falsely tripped phase=failed, burying real progress. Fix: the helper now optionally acceptslaneResultsand scans per-task outcomes for anystatus === "succeeded". 4 new sage-fold tests inspawn-failure-visibility.test.tscover both edge cases. Final test count: 3624 passing (+4 over the 3620 worker-batch baseline).Polyrepo end-to-end verified by operator in
C:/dev/tp-test-workspace. The bug class that previously left lanes silently "running" forever now surfaces immediately as a visible failure with a meaningfulphase=failedandtask-failureIPC alert.
supervisor_takeover(reason)tool (TP-187, #538): Non-destructive escape hatch for misbehaving batches. Pauses the running wave, drains every per-agent on-disk outbox for the current batch, and marks all active lanes as terminated so any in-transit zombie alerts are dropped before they reach the supervisor's user-message queue. Worktrees, branches, batch state, and sessions are all preserved — distinct fromorch_abort, which kills sessions and deletes state. Use this when the batch is producing alert spam or has hit a death-spiral pattern but you may still want to resume the same batch. After takeover, callorch_status()to inspect, then eitherorch_resume(force=true)to continue (alert suppression is lifted automatically on resume) ororch_abort()to escalate to destructive shutdown. Documented intemplates/agents/supervisor.mdalongside the existing orch_* tool surface, plus a new section codifying the lane-runner's text-reply parser semantics (close keywordsskip/let it fail/close/abort/stopare only treated as session-close directives when they appear in a reply under 30 characters; longer messages are always treated as instructional re-prompts).
-
Zombie supervisor alerts after lane termination (TP-187, #538): Previously, when a worker lane was killed (no-progress threshold or hard-fail), 3–5 "wants to exit" alerts that the worker emitted before termination remained in the supervisor's user-message queue and the agent's on-disk outbox, where they could be re-discovered later. None of the documented operator responses (
steer,skip,let it fail,orch_abort,orch_skip_task) reliably drained either path. Fix has three parts: (1) at every lane-termination decision point (no-progress kill inlane-runner.ts, hard-fail inengine.ts), the agent's outbox is now synchronously drained — pending*.msg.jsonfiles are moved tooutbox/processed/and other pending files (e.g.,segment-expansion-*.json) are renamed to.drainedso they are invisible to subsequent discovery scans; (2) the engine emits a newlane-terminatedIPC message to the supervisor process, which keys a per-batch suppression filter (terminatedLanes/terminatedAgentsMaps) that drops any subsequent supervisor-alert whosecontext.laneNumberorcontext.agentIdmatches before it reachespi.sendUserMessage; (3) the engine emits a complementarylane-respawnedIPC at the start of eachexecuteLaneV2invocation so a fresh task on a re-allocated lane number lifts the suppression. The filter is also cleared onorch_resume(), on a new batch start, and onsupervisor_takeover()-then-resume. Implementation: newdrainAgentOutboxhelper inmailbox.ts,LaneTerminatedInfo/LaneTerminatedCallbacktypes intypes.ts, callback threading throughengine.ts/execution.ts/resume.ts/engine-worker.ts, and IPC + filter wiring inextension.ts. -
orch_resume(force=true)cannot reattach afterorch_abort()(TP-187, #539):executeAbort()deletes.pi/batch-state.jsonto enforce its destructive contract, but the runtime registry, per-agent manifests, lane snapshots, worktrees, and branches all survive. With no batch-state.json,loadBatchState()returned null and force-resume returned the generic "no batch found" error, forcing operators into ~15 minutes of manual git surgery (fast-forward feature branches, push, remove worktrees, edit STATUS, re-orch_start) just to do what force-resume should have done. Fix adds a smallbatch-meta.jsonruntime artifact written at batch-start to.pi/runtime/<batchId>/batch-meta.jsoncapturing the wave plan and the few non-recoverable scalars (baseBranch, orchBranch, mode, startedAt, totalWaves). On force-resume after abort, whenloadBatchState()returns null, the newreconstructBatchStateFromRuntime()helper deterministically rebuilds a validator-compliantPersistedBatchStatefrom the surviving artifacts: most-recent batch dir wins by mtime (lex tiebreak),batch-meta.jsonprovides wave topology and orchBranch, worker manifests provide per-lane allocation, and the existing reconciliation pass re-detects succeeded tasks via.DONEmarkers and STATUS.md. When required artifacts are missing or validation fails, force-resume fails loud with a newresumeNoStateAfterAbortmessage that names the missing artifact and recommendsorch_start <PROMPT.md>as the recovery path. The non-forceorch_resume()path is unchanged.orch_abortitself remains semantically destructive — only force-resume reads from the surviving runtime artifacts. -
Worker said:is empty in early no-progress alerts (TP-187, #540): When a worker exits an iteration without producing a visible assistant message (a known failure mode in the death-spiral pattern), the worker-exit-intercept alert sent to the supervisor showedWorker said: ""— leaving the supervisor with no signal about why the worker is stuck on the iterations where intervention could still help. By the time the field has content, the worker is already at no-progress count 3 (kill threshold). Fix has two parts: (1)templates/agents/task-worker.mdnow requires a one-sentence reason before any silent exit-with-no-progress, with concrete examples; (2)lane-runner.tsfalls back to walking the worker'sevents.jsonlbackward to find the most recent non-emptyassistant_messagepayload when the current turn produced no visible output, and tags the alert with which source (current-turn,events-jsonl-fallback, orempty-sentinel) produced theWorker said:field. The 500-character truncation invariant is preserved. -
taskplane doctorno longer shows empty parens forpi installed ()(TP-189-C / TP-185 follow-up): pi prints its--versionoutput to stderr, butbin/taskplane.mjs'sgetVersion()only captured stdout viaexecSync(... { stdio: 'pipe' }), so the doctor display was✅ pi installed ()with empty parens. The fix extractsgetVersiontobin/get-version.mjs(testable ESM helper) and switches it tospawnSyncwithstdio: ['ignore', 'pipe', 'pipe']. The new logic prefers stdout but falls back to stderr when stdout is empty, and preserves the prior fail-safe contract (returnsnullon subprocess failure or non-zero exit — critical so shell error text isn't surfaced as a fake version string). Manual verification:taskplane doctornow shows✅ pi installed (0.73.0). 7 new behavioral tests inextensions/tests/cli-doctor-version-capture.test.tscover the stdout-precedence, stderr-fallback, trim, and null-on-failure cases. -
isStepMarkedCompletedeath-spiral guard now skips fenced code blocks (TP-189-A3 / TP-186 follow-up): the helper that powers thereview_stepREFUSED guard scanned STATUS.md line-by-line for the literal**Status:** ✅ Completepattern. If a step's body documented that pattern inside a fenced code block (legitimate authoring of the format itself), the guard would false-positive and refuse a legitimate code review. The helper now uses CommonMark-aware fence tracking: recognizes both ``` and ~~~ fences, tracks the opener char + length, and only closes on a matching delimiter (same char, length ≥ opener length, no trailing non-whitespace text). Mixed-delimiter examples andclose it. Step-heading detection is gated on being outside a fence so a `### Step N:` line inside a code-block sample is treated as content rather than a step boundary. 6 new unit tests cover the edge cases.
templates/agents/task-worker.mdreconciled with TP-186's Order of Operations rule (TP-189-E): two older sections were ambiguous when read alongside the new review-gated step-completion contract from TP-186. (1) Resume Algorithm step 6 ("all items checked → proceed to next step") now splits behavior by Review Level: 0/1 may proceed, but 2/3 must commit the implementation, callreview_step(type="code"), and only flip the per-step**Status:**heading after APPROVE — with a cross-reference to the Order of Operations section. (2) The Checkpoint Discipline / Git commits example commit message changed fromfeat(TASK-ID): complete Step N — descriptiontofeat(TASK-ID): step N implementation, plus explicit Level 0/1 vs Level 2/3 paragraphs and a separatechore(TASK-ID): step N complete (code review APPROVE)example for the post-APPROVE status-flip commit. Both edits reuse canonical wording from the Order of Operations + Recovery Recipe sections so the existing source-pattern tests inextensions/tests/worker-step-completion-protocol.test.tscontinue to pass; a new test 1.4b regression-guards the Resume Algorithm wording.skills/create-taskplane-task/SKILL.mdComplexity Assessment augmented with Per-Step Reviews vs. Consolidated Reviews (Checkpoint Markers) sub-section (TP-189-E): the existing rubric documents Review Levels 0–3 but not the second axis — how many reviews fire for a given level. PROMPT authors had been discovering this empirically (e.g., TP-186 fired only 2 reviews via checkpoint markers vs the default ~8 it would have fired without them). The new sub-section makes the choice explicit: per-step is the default and right for independent multi-feature work; consolidation via**Plan-review checkpoint**/**Code review checkpoint**markers is appropriate for single-deliverable tasks where the steps are mechanical applications of one design. TP-186 is referenced as the canonical consolidation example.
DEFAULT_WORKER_USER_TOOLSmigrated to a shared lightweight constants module (TP-189-B / TP-184 follow-up): the literal"read,write,edit,bash,grep,find,ls"was duplicated acrossextensions/taskplane/agent-host.ts(canonical),config-schema.ts(×2), andtypes.ts(×1), withNOTE (TP-184)comments pointing at the canonical source. The duplication existed becauseagent-host.tsimportschild_process/fs, and pulling those into the schema/types layer would either be circular (types.ts is the import root for agent-host.ts) or pollute pure-data files with subprocess plumbing. Sage flagged this as a future cleanup target. Fix: newextensions/taskplane/tool-allowlist-constants.tsis a deliberately import-free leaf module that owns the literal.agent-host.tsnow re-exportsDEFAULT_WORKER_USER_TOOLSfrom the new module so existing internal callers (execution.ts,worker-tools-allowlist.test.ts) continue to work unchanged.config-schema.tsandtypes.tsnow import directly from the new module. Verified no circular imports via a Node import probe; existing 16-testworker-tools-allowlist.test.tssuite still passes (constant value is unchanged, only its source module moved).ENGINE_BRIDGE_TOOLSandbuildWorkerToolsAllowlist()deliberately stay inagent-host.ts— they have no duplication problem and live next to their consumers.- Architectural regression guard for the worker tool allowlist
spawn-site wiring (TP-189-A1 / TP-184 follow-up): new
extensions/tests/lane-runner-spawn-wiring.test.ts(4 source-pattern tests) asserts thatlane-runner.tsimportsbuildWorkerToolsAllowlistfromagent-hostand calls it astools: buildWorkerToolsAllowlist(config.workerTools)at the worker spawn site, with explicit guards against passingconfig.workerToolsdirectly (which would silently drop engine bridge tools and re-introduce issue #530). The call site is also bounded to within ~80 lines of the surroundingagentId:field, sanity-checking the call lives inside the AgentHostOptions object literal. - Runtime test of the
review_stepdeath-spiral guard's REFUSED path (TP-189-A2 / TP-186 follow-up): newextensions/tests/review-step-guard-runtime.test.ts(5 tests) exercises the actualreview_steptool handler end-to-end via the bridge-extension's tool registration. Confirmstype='code'(andtype='test') on a step marked**Status:** ✅ Completereturns the documented REFUSED prose without spawning a reviewer subprocess and without incrementing the Review Counter;type='plan'is exempt even on a Complete step;type='code'on an In-Progress step proceeds normally. Mocking strategy uses the barechild_processspecifier for portability across Node 22 and Node 24 (matches thewindows-worktree-cleanup-fallback.test.tsrationale). - Behavioral tests for
removeWorktree()Windows MAX_PATH fallback (TP-189-A4 / TP-188 follow-up): newextensions/tests/windows-worktree-cleanup-behavioral.test.ts(3 tests) augments the existing source-pattern suite with end-to-end decision-branch coverage. Uses a singlechild_processmock that dispatches on the spawned command (git vs cmd) plus real on-disk temp directories so the post-removalexistsSyncverification passes for real. Covers: win32 + "Filename too long" stderr →cmd /c rd /s /qfallback fires, prune-after-rd ordering verified, removed:true; win32- non-MAX_PATH error → fallback skipped,
WORKTREE_REMOVE_FAILEDthrown with the original stderr; non-win32 + MAX_PATH text → platform guard inisWindowsMaxPathErrorcorrectly skips the fallback.
- non-MAX_PATH error → fallback skipped,
-
Orchestrator parent crashes on first IPC frame from engine-worker (#559):
ReferenceError: batchState is not definedthrown fromipcBatchIdMatchesin the supervisor IPC closure crashed the orchestrator parent process the moment any engine-worker emitted its firstlane-terminatedorlane-respawnedmessage. Affected every batch — the batch state file was left inphase=executingwith 0 progress, and git worktrees /task/...branches were orphaned. Root cause: TP-187's batchId-gating helper (added to fold sage's post-integration finding) referencedbatchState.batchId5 times, butbatchStateis NOT bound in the supervisor IPC closure — onlyorchBatchStateandsupervisorStateare. The crash slipped through because (1)node --experimental-strip-typesperforms no name-resolution checks, only strips type annotations; (2) TP-187's in-batch tests mock IPC handlers at a different layer (engine-worker → supervisor callbacks viaexecuteOrchBatch'sdepsparameter), bypassing the actual extension closure under fault. Fix: switched 5 sites frombatchState.batchIdtoorchBatchState.batchId(NOTsupervisorState.batchId— sage's post-mortem on the first attempted fix flagged thatsupervisorState.batchIdis only populated when the supervisor activates, so for batches where the supervisor never activates the gate would never fire and the zombie-alert filter would be defeated).orchBatchState.batchIdis the canonical live runtime batch ID for the extension closure: declared next tosupervisorState, populated reliably via state-sync IPC. Regression test inextensions/tests/extension-ipc-batchid-scope.test.ts(4 tests) asserts via source-pattern that the supervisor IPC closure region contains zero references tobatchState.batchIdand at least one reference toorchBatchState.batchId. Comments are stripped before the check so documentation-of-the-bug doesn't trigger false positives. -
Pi CLI path resolution broken after
@mariozechner→@earendil-worksrename (#560): Pi v0.74.0 republished under the@earendil-worksnpm scope. Taskplane's Runtime V2 spawn pathway resolves Pi's CLI on disk viapath-resolver.ts:resolvePiCliPath(), which hardcoded@mariozechneras the only scope to search undernpm root -g. Result: every Runtime V2 spawn (workers, reviewers, mergers) failed immediately withCannot find Pi CLI entrypointon any system whose only globally-installed Pi was the new scope. Critically, Pi's own extension loader bundles aliases for BOTH scopes at runtime (<pi>/dist/core/extensions/loader.jslines 41-45), so all of taskplane'simport type { ExtensionAPI } from "@mariozechner/pi-coding-agent"andimport { Type } from "@mariozechner/pi-ai"sites continue to resolve correctly via Pi's in-process aliasing — the rename only breaks disk-side lookup for child-process spawning. Fix is therefore narrowly scoped topath-resolver.ts: refactoredresolvePiCliPath()to walk the cross product of base directories × scopes, with@earendil-workschecked first and@mariozechnersecond within each base directory. Operators with EITHER scope installed get a working Pi resolution; operators with BOTH installed (e.g., during a transition window) pick up@earendil-works. The error message and theworktree.tsinstall hint now name both scopes for diagnosability. Other ~10 files that reference@mariozechner(TypeScript imports, test mocks, peerDependencies, docs) deliberately left as-is because Pi's bundled-alias handling makes them work at runtime regardless of scope, and updating them risks breaking compat for users on Pi versions older than v0.74.0 (which don't have the alias map). Regression test inextensions/tests/path-resolver-pi-scope.test.ts(4 tests) sets up temp directories with each scope combination and asserts the resolver behaves correctly via realchild_processprobes.
- Dashboard: task title row widened to span cols 3–6 (#485 follow-up): The task title subtitle introduced in v0.28.7 was constrained to the 100px-wide task-id column, which truncated most realistic titles ('Reviewer runs typec...') after just a few words. Restructured the task-row grid to two rows: row 1 holds the primary cells (icon, actions, task-id, status, duration, progress, step+telemetry), row 2 holds the optional task-title-subtitle spanning cols 3–6 (~486px combined width vs. the previous 100px). Stops before col 7 (task-step + telemetry) so step info and worker stats stay visible alongside the title. Auto row 2 collapses to 0 height when no subtitle exists, so tasks with null taskTitle look identical to the v0.28.7 single-line layout. Display-only change — cannot affect orchestrator correctness.
- Code reviewer now runs project quality checks (typecheck/lint/format)
before deciding (TP-188, #541): Previously, the reviewer agent spawned
via
review_step(type="code")evaluated changes through behavioural inspection only. It did NOT runnpm run typecheck/npm run lint/npm run format:check, so code with TypeScript strict-mode errors or lint failures could receive APPROVE — those issues then surfaced at the worker's Testing & Verification step, blocking the entire batch. In one observed production batch, acodereview returned APPROVE for a step that subsequently failednpm run typecheckwith 5 strict-mode errors in the test code the reviewer had just signed off on. Cost of catching these earlier: one extra typecheck per code review. Cost of NOT catching them: the entire investment in the affected step plus all dependents. Fix is a prompt-only change totemplates/agents/task-reviewer.md: a new Quality-check verification section (between How You Work and Verdict Criteria) instructs the reviewer to (1) discover commands by reading.pi/taskplane-config.jsontaskRunner.testing.commandsfirst, then fall back topackage.jsonscriptsfortypecheck/lint/format:check; (2) run any matching commands using its existingbashtool (no allowlist change required —bashis already in the default reviewer tool list); (3) surface failures as Issues Found with severityimportant; (4) downgrade an otherwise-APPROVE verdict to REVISE when any quality check fails. Plan reviews skip the section entirely (no code exists yet to typecheck). Skip-silently rule: if neither config norpackage.jsonyields a relevant command, the reviewer notes the skip in the Summary and proceeds normally rather than blocking on absent infrastructure. 10 new source-pattern tests inextensions/tests/reviewer-quality-checks.test.tslock the section shape, the hybrid discovery wording, and the verdict-downgrade rule. - Windows worktree cleanup falls back to
cmd rd /s /qwhen git hits MAX_PATH (TP-188, #543): On Windows with defaultcore.longpaths = false,git worktree remove --forcefails witherror: failed to delete '<path>': Filename too longwhen the worktree contains a deepnode_modulestree (most non-trivial Node projects). Previously the orchestrator surfaced cleanup-incomplete via the post-integration banner but didn't recover — the operator had to runcmd /c "rd /s /q <path>"manually. Observed twice during a single recovery flow on the user's Windows machine working with emailgistics-astro (700+ npm deps). Fix adds two new exported helpers inextensions/taskplane/worktree.ts:isWindowsMaxPathError(stderr)(returns true only on win32 +/filename too long/i) andrunWindowsCmdRd(absolutePath)(invokesexecFileSync("cmd", ["/c", "rd", "/s", "/q", winPath])with forward slashes normalized to backslashes for native Windows path semantics). The fallback fires insideremoveWorktree's retry loop when the predicate matches, prunes git's bookkeeping on success so post-removal verification passes, and falls through to the existing terminal/retry classification on failure (with both git's stderr and cmd's stderr enriched into the thrown error so operators can diagnose). Other error classes (lock errors, permission denied, generic git errors) are unaffected. INFO-level logs viaexecLog("cleanup", "worktree", ...)make the rescue path visible in operator-facing output. 17 new tests inextensions/tests/windows-worktree-cleanup-fallback.test.tscover the source-pattern wiring (helpers exist;removeWorktreecalls them;git worktree pruneruns on fallback success; failure path enriches the error), platform guard (returns false on linux/macOS), regex case-insensitivity, andrunWindowsCmdRd's mocked invocation. Tests are platform-agnostic viachild_processmocking so the suite passes on every CI runner.
- CI workflow upgraded to Node 24 LTS:
.github/workflows/ci.ymlwas on Node 22;release.ymlhad moved to Node 24 LTS during the v0.28.5 release work but ci.yml was not aligned. Two motivations converged: the Node 22 / Node 24mock.module()semantics divergence caused TP-188'srunWindowsCmdRdunit tests to fail on Node 22 CI while passing locally on Node 24 (Node 24 aliases barechild_processandnode:child_process; Node 22 treats them as separate modules). Bumping ci.yml to Node 24 fixes the test mock portability AND completes TP-189's Cluster D ahead of schedule.
- Dashboard: lane parallelization visible in wave indicator chips (#484):
Wave chips at the top of the dashboard now group tasks by lane within each
wave, joining same-lane tasks with
→(serial) and different-lane tasks with|(parallel). For example,W1 [TP-165, TP-166, TP-168, TP-167]now readsW1 [TP-165 → TP-166 | TP-168 | TP-167], immediately revealing that TP-165→TP-166 are serialized on lane 1 while TP-168 and TP-167 run in parallel on lanes 2 and 3. Within each lane, tasks render in execution order (perlane.taskIds). Hover tooltip on the chip exposes the expanded multi-line lane breakdown. Future waves with no lane assignment data fall back to the previous flat comma-separated display — no regression for unprovisioned waves. - Dashboard: task title under task ID in lane view (#485): The lane
view now renders the human-readable task title (extracted from PROMPT.md's
# Task: <ID> - <title>first-line heading) as a smaller muted subtitle beneath the task ID. Operator no longer needs to remember what each TP-XXX is. The title is read once from PROMPT.md and cached for the server's lifetime (PROMPT.md is immutable above the---divider). Surfaced via a newtaskTitlefield on/api/statetask records; frontend falls back gracefully when the field is null.
- Worker death-spiral when code review returns REVISE on a step already
marked Complete in STATUS (TP-186, #537, #542): Previously, if a worker
set a step's
**Status:** ✅ Completeheading in STATUS.md before callingreview_step(type="code"), and the reviewer returnedREVISE, the worker was caught in a state contradiction (STATUS says done, reviewer says not) with no recovery recipe in the prompt. The worker would loop through 3 no-progress iterations and the orch's safety mechanism would kill the lane — the entire batch was a write-off, requiring ~15 min of manual git surgery per occurrence. The fix is structural: (1) the base worker prompt (templates/agents/task-worker.md) now contains an explicit Order of Operations rule that mandates code review BEFORE marking a step Complete, a Recovery Recipe for the case when the rule is accidentally violated (revert STATUS → commit → handle REVISE through the normal flow), and a Forbidden callout naming the death-spiral anti-pattern alongside the existing "NEVER add, remove, or renumber steps" family of MUST-NOT rules; (2) the engine-sidereview_steptool now refuses to run on a step already marked**Status:** ✅ Complete, returning aREFUSEDverdict that points the worker at the Recovery Recipe (the refusal applies tocodeandtestreview types only — plan reviews fire pre-implementation and are correctly exempt). Until this fix shipped, Review Level ≥ 2 was effectively unsafe in production. 14 new tests inworker-step-completion-protocol.test.ts. Supersedes the partial diagnosis in #510. Thanks to the production batch20260506T105850againstemailgistics-astrofor surfacing the reproducer.
- Pi no longer hard-blocks startup with a red error when run in directories
that aren't configured for Taskplane (TP-183, #523): Previously, launching
pi in any non-git directory (or any directory without
.pi/taskplane-workspace.yaml/taskplane-config.json) raised a verbose redWORKSPACE_SETUP_REQUIREDnotification at session_start. For users who only want Taskplane in some projects, this was wrong UX. The orchestrator now soft-fails theWORKSPACE_SETUP_REQUIREDcase specifically: no error notification, status line shows the quiet🔀 Orchestrator · disabled (no taskplane config in workspace)indicator, orchestrator commands stay gracefully disabled (and still explain why if invoked, via the existingrequireExecCtxguard). Configuration errors in workspaces that ARE set up —WORKSPACE_FILE_PARSE_ERROR,WORKSPACE_SCHEMA_INVALID,WORKSPACE_REPO_PATH_NOT_FOUND, and every otherWorkspaceConfigErrorCode— still surface loudly with the existing red notify and❌ startup failed (workspace config error)status line, so real misconfigurations remain visible. Throw behavior ofbuildExecutionContextis unchanged — only the display inextension.tschanges. 6 new tests inorchestrator-startup-uxv2.test.ts(3 scenarios, 6 fine-grained checks). Thanks to @mwickens for the report. - Workers can now invoke
review_step,notify_supervisor,escalate_to_supervisor, andrequest_segment_expansion(TP-184, #530): Previously these engine-internal coordination tools were missing from the worker's hardcoded--toolsallowlist, so pi's tool gate filtered them out at the worker. The visible symptom: plan/code/test reviews silently never fired at Review Level >= 1, supervisor steering replies were impossible, and multi-repo segment-expansion requests were unreachable. The bridge tools are now always appended to the worker allowlist regardless oftaskRunner.worker.toolsconfig; the user-tools default is unchanged. Introduces three new exports inagent-host.ts:ENGINE_BRIDGE_TOOLS(canonical list of engine-internal tools),DEFAULT_WORKER_USER_TOOLS(the user-tools default literal), andbuildWorkerToolsAllowlist()(combines user portion with bridge tools, deduplicated). Called exactly once at the lane-runner spawn site. Defense-in-depth: lane-runner now warns (vialogExecution) if any bridge tool is missing from the final allowlist. 14 new tests inworker-tools-allowlist.test.ts. - Preflight
picheck no longer misreports cold-start timeouts as "Pi not found" (TP-185):execChecknow classifies failures by mode (not-found,timeout,exit-code,signal,unknown) instead of treating every failure as missing-binary. Thepipreflight now uses a 30s timeout (up from 10s) and retries once on timeout to absorb cold-start variance — mise shim resolution, Node bootstrap, AV process-launch scanning, and pi's own startup can together exceed 10s on a fresh first run, especially on Windows. Failure messages and hints are now tailored to the actual error kind (e.g. timeouts say "Pi did not respond within 30s" + diagnostic guidance, rather than the misleading "Install pi" hint). Detects missing binaries on both POSIX (ENOENT/exit 127) and Windows (cmd.exe"is not recognized") shells. 9 new tests inexec-check-error-classification.test.tscovering every classification path including regression guards against the original bug. Backward compatible: existing callers reading{ ok, stdout }are unaffected. - Worker model/thinking/tools from preferences now flow through to spawned
workers (TP-181, #522):
taskRunner.worker.{model,thinking,tools}inpreferences.json(and project config) are now threaded fromTaskRunnerConfigthroughexecuteWave→executeLaneV2to the worker subprocess viaTASKPLANE_WORKER_{MODEL,THINKING,TOOLS}env vars. PreviouslyLaneRunnerConfig.workerModelwas hardcoded to""and the user-configured worker model was silently ignored. Mirrors the existing reviewer pipeline established in TP-160. NewbuildWorkerEnv()helper, plumbed throughengine.ts,execution.ts, andresume.ts. 11 new tests inworker-model.test.ts. Thanks to @NerfEko.
- Settings TUI: Agent Extensions description: Shows "Toggle extensions per agent type" instead of generic "Read-only collection/record fields" label.
- Forward project and global extensions to spawned agents (#511, #513):
Third-party pi extensions installed via
.pi/settings.json(project-level or global) are now forwarded to worker, reviewer, and merge agents as explicit-eflags. Previously,--no-extensionsblocked all auto-discovered packages from loading in spawned subprocesses.- New
settings-loader.tsreads and merges packages from project and global settings files, deduplicates, and filters out taskplane itself. - Per-agent-type exclusions via
excludeExtensionsconfig arrays ontaskRunner.worker,taskRunner.reviewer, andorchestrator.merge. - New Agent Extensions submenu in
/taskplane-settingsTUI — toggle extensions on/off per agent type with auto-discovered package list. - All three spawn points wired: worker (lane-runner), reviewer (agent-bridge-extension), merge agent (merge.ts).
- Exclusions threaded through engine retry paths (crash retry, model fallback, stale worktree recovery) and resume flows.
- 27 new tests covering settings loading, exclusion filtering, and spawn arg injection.
- New
- Taskplane exclusion filter tightened: Extension filter now uses exact
package name matching instead of substring. Packages like
npm:taskplane-utilsare no longer incorrectly filtered out.
- Added hybrid IPC architecture specification (
docs/specifications/taskplane/). - Updated
docs/how-to/configure-task-runner.mdwithexcludeExtensionsconfig.
- Dashboard: split
useV2intouseV2Progress/useV2Step: Fixes edge case where step label and progress bar could reference stale data from different render cycles. - Dashboard: segmented bar isDone excludes merge phase: Progress bar no longer shows "complete" prematurely during wave merging.
- Dashboard: running task with 0 total shows "executing...": Instead of displaying 0/0 (0%), shows a descriptive status while checkboxes are being discovered.
buildCiDepsacceptsstateRootparam: Fixes workspace-mode path resolution for CI dependency checking during PR lifecycle.
- Dashboard: stale STATUS.md viewer across batches (#487): Viewer clears when a new batch starts instead of showing previous batch's content.
- Dashboard: lane step label never updates (#488): Step name re-read from sidecar on every poll instead of caching the initial value.
- Dashboard: succeeded tasks show 0% progress (#491): Override to 100% and "Complete" when task status is succeeded.
- Dashboard: wave indicators flash green during merge (#493): Only completed waves show green during merge phase; merging wave shows pulse.
- Dashboard: no progress for non-final segments (#494): Segment-scoped progress displayed during execution.
- Dashboard: merge telemetry duplicated across waves (#498): Merge agent telemetry associated with correct wave via waveIndex.
- Dashboard: supervisor actions lack descriptions (#497): Context/detail fields from JSONL now displayed in recovery actions table.
- orch-integrate doesn't set integratedAt (#499): Integration timestamp written to batch history before cleanup. Dashboard correctly transitions completed batches to history view in workspace mode.
- Dependency parser: Task: format (#486): Parser now matches both
**Requires:**and**Task:**label formats from the skill template.
-
Phase A: Segment-aware steps (TP-173, TP-174, TP-175, TP-176, TP-177): Multi-repo polyrepo tasks now support
#### Segment: <repoId>markers in PROMPT.md steps. Workers only see checkboxes for their current segment.- Discovery parser extracts step-segment mappings from PROMPT.md
- Lane-runner filters iteration prompt, progress tracking, and stall detection to the current segment's checkboxes
- Workers exit cleanly when their segment's checkboxes are complete
- Dashboard shows segment-scoped progress bars and STATUS.md viewer
- create-taskplane-task skill generates segment markers for multi-repo tasks
- Worker prompt template updated with multi-segment guidance
- Single-segment tasks completely unaffected (backward compatible)
-
Hard mode separation for worker prompts: Two separate prompt files (
task-worker.mdfor full-task,task-worker-segment.mdfor segment-scoped) instead of conditional prose in one prompt. In FULL_TASK mode, all segment signals are stripped: no segment env vars, no segment ID in prompt, no segment tools. Workers cannot self-scope on signals that don't exist.
-
Monitor STATUS.md path resolution (#501): Monitor poll was re-resolving STATUS.md path with
isWorkspaceMode=false, reading stale files from the main checkout instead of the worktree. AddedparseStatusMdAtPath()that reads directly from the authoritative path. Fixes 0% progress display for all workspace-mode tasks. -
Worker self-scoping in workspace mode: Workers exited after one step because: (a) multi-segment rules applied to all tasks, (b) segment ID metadata triggered self-scoping behavior, (c) discovery fallback created stepSegmentMap entries without explicit markers. Fixed by hard mode separation and
hasExplicitMarkersgate. -
Segment env var inheritance:
TASKPLANE_ACTIVE_SEGMENT_IDandTASKPLANE_SEGMENT_IDhard-cleared to empty string in FULL_TASK mode to prevent parent process env inheritance from leaking segment cues.
- Segment-aware steps specification updated to v4 (Phase A fully specified, Phases B-F strategy outlined with Sage architectural review findings)
- Worker prompt rewritten: workers must not exit voluntarily between steps. Workers that previously exited after partial progress may now behave differently (they keep working instead of stopping).
- Supervisor-in-the-loop exit interception (TP-172): When a worker exits without progress, the lane-runner holds the session alive and escalates to the supervisor. The supervisor can send targeted instructions to continue the worker's session with full conversation context preserved.
- Soft progress detection: Stall detector checks
git difffor uncommitted source changes before counting an iteration as stalled. Workers editing code but not yet checking boxes get credit for progress. - Corrective re-spawn prompt: When a worker is re-spawned after no-progress exit, the iteration prompt explicitly warns about the previous failure pattern and demands action.
- Worker exit contract: Worker prompt rewritten with "Do NOT Exit — Keep Working Until Done" and "Never Narrate What You Plan To Do" sections, addressing the #1 failure mode of workers saying "Now let me fix this:" and then stopping.
- Segment .DONE guard (TP-165, #457):
.DONEis no longer created after the first segment of a multi-segment task. The lane-runner checks for pending expansion requests in the worker outbox before creating.DONE. - Expansion consumption (TP-165, #452): Engine correctly resolves worker
agent IDs for outbox lookup in workspace mode.
.DONEremoval path now usesresolveCanonicalTaskPathswith worktree-relative paths. - Wave planner phantom waves (TP-166, #454): Wave count matches the actual
dependency graph depth. Operator-facing displays use
taskLevelWaveCount. - Global lane cap (TP-166, #451):
enforceGlobalLaneCapis wired into the workspace execution path.maxLanesis now a global cap, not per-repo. - Init Windows backslash (TP-167, #446):
taskplane initnormalizes all paths to forward slashes before writing to YAML and JSON config files. - Artifact cleanup (TP-168, #296): Telemetry age sweep reduced from 7 to 3 days. Verification, conversation, and lane-state files included in sweep. Telemetry directory size cap (500MB) with oldest-first eviction.
- Resume crash after expansion (TP-169, #441):
taskFolderpopulated for dynamically-added segments during resume reconstruction. - Workspace orch branch (TP-169, #458): All workspace repos get an orch branch at batch start. Missing branch on resume is now fatal (throws) instead of warning-and-continue.
- CLI widget session-dead (TP-170, #425): Widget is wave-aware — completed lanes from prior waves show succeeded, active lanes show progress. Session name reconciliation fixed.
- Skipped task progress (TP-171, #453): STATUS.md and worker commits from
skipped tasks are cherry-picked to the orch branch via isolated worktree.
.DONEexcluded from skipped staging. - Batch history gap (TP-171, #455): All wave-planned tasks recorded in batch history including skipped, failed, and never-started tasks.
- Close-directive parser: Long supervisor instructions (>30 chars) starting with "stop" are no longer misinterpreted as close directives.
- Skipped artifact paths (Sage):
taskFolderresolved against lane worktree path in workspace mode for correct cross-repo artifact staging.
- Segment-aware steps specification (draft v4) for multi-repo task execution
- Supervisor primer: Section 13c for worker exit interception alerts
orch-integratedetects already-merged orch branch and runs cleanup only- Supervisor primer: always call
orch_integrate()after manual merge - Dashboard: human-readable labels for supervisor recovery actions
- Broken link to deleted
task-runner.tsin spec doc
- task-runner.ts deleted — The original
/taskcommand extension (2,784 lines) has been removed entirely./task,/task-status,/task-pause, and/task-resumeno longer exist. Use/orchfor all task execution.
sidecar-telemetry.ts— New canonical module for sidecar JSONL tailing utilities (extracted from task-runner.ts).context-window.ts— New canonical module for context window resolution (extracted from task-runner.ts).loadConfig,_resetPointerWarning— Moved toconfig-loader.ts.loadAgentDef— Exported fromexecution.ts.
- TP-163 (#471): ENOENT crash when task folders are uncommitted at batch start — orch branch now fast-forwarded after staging commit.
- TP-164 (#465): Live merge agent telemetry in dashboard — merge agents show tool calls, cost, context %, elapsed during merge phase.
- Reviewer model threading (TP-160): Configured reviewer model/thinking/tools now correctly passed to reviewer subprocess on all execution paths (initial waves, resume, retries).
- Ghost worker detection (TP-159 #461): Orphaned workers detected within one poll cycle and marked crashed immediately.
- Config reload on /orch start (TP-158 #460): Config changes take effect without restarting pi.
- Path resolver consolidation (TP-157): All npm/package path resolution centralized in
path-resolver.ts, fixing macOS Homebrew/nvm failures. - Supervisor hang fix:
/orchno longer hangs the terminal on activation. - Settings live reload:
/taskplane-settingschanges apply immediately without restart.
- TP-145: Multi-segment .DONE timing + expansion edge validation — Four-layer defense against premature .DONE: pre-segment deletion, worker prompt rule, post-segment deletion, expansion deletion. Edge validation accepts anchor-repo references.
- TP-146: Missing orch branch investigation — Root cause identified (
resolveBaseBranchfallback), diagnostic logging added. - TP-147: Skipped task branch preservation + batch history completeness — Partial work saved as
saved/*refs. All wave plan tasks recorded in history. - TP-148: Wave display, global maxLanes cap, session naming — Dashboard shows segment context in waves. Global lane cap across repos. Lane-number fallback for widget liveness.
- TP-149: Supervisor integration ordering — Tries FF first, merge second, PR only when protected + diverged + remotes exist.
- Local build script —
node scripts/local-build.mjscopies dev files to global install for testing without npm publish.
- Dashboard messages no longer truncated — Removed 120-char JS truncation, CSS wrapping enabled.
- Premature .DONE deletion gated on actual insertion — No-op expansion mutations no longer reopen completed tasks.
- Batch history deduplication — Gap-fill loop updates covered set after each push.
- Integration plan tries FF before PR for protected branches — Tests updated.
- maxLanes warning when repos exceed global cap.
- resolveBaseBranch log prefix consistency.
- Segment expansion requests not consumed by engine (#452) — Post-wave processing used stale
task.activeSegmentId(already null for completed single-segment tasks). Now usesoutcome.segmentIdfrom task outcome. Same fix applied to failed task path. - Workspace config resolution short-circuit (#424) —
hasConfigFiles()no longer countstaskplane-workspace.yamlas a project config file. - Workspace init doubled config repo name — Tasks directory path no longer doubled when config repo prefix matches.
taskplane initwritestask_packet_repo— Eliminates compatibility warnings on workspace startup.- Windows backslashes in init paths (#446) — All path inputs normalized to forward slashes.
- Workspace config resolution short-circuit (#424) —
hasConfigFiles()countedtaskplane-workspace.yamlas a project config, causing the pointer-resolved config root to be skipped. Task areas were empty, discovery found no tasks. Fix: workspace YAML excluded from config file detection.
- Workspace init doubled config repo name in tasks directory —
shared-libs/shared-libs/task-management/...now correctly resolves toshared-libs/task-management/....
taskplane initwritestask_packet_repoin workspace YAML — Eliminates compatibility warnings on workspace startup.
- Windows backslashes in
taskplane initpaths (#446) — All path inputs normalized to forward slashes before writing to YAML/JSON config. Fixes YAML parse error on Windows.
- Safety-net auto-commit for uncommitted worker artifacts — Before the merge phase, each merge-candidate lane worktree is checked for uncommitted changes. If found, auto-committed with a safety-net message. Prevents permanent loss of worker-created files when workers forget to commit.
- Sage review remediations for segment expansion — merge.ts taskFolder guard (#441), resume segments carry-forward, segment metadata rehydration, topo-sort failure rollback, requestedRepoIds uniqueness validation.
- Merge agent auth failure — v0.24.21's
PI_CODING_AGENT_DIRisolation cut off API credentials (auth.jsonwas empty in the isolated dir). Merge agents silently failed to authenticate, producing zero tool calls. Removed process-level isolation; test-level isolation inproject-config-loader.test.tsis sufficient.
- TP-142: Segment expansion tool + file IPC —
request_segment_expansionRPC tool for workers to request new segments at runtime. SegmentId extended with sequence suffix (::2) for repeat-repo segments. Non-autonomous guard rejects in supervised/interactive mode. - TP-143: Engine segment graph mutation — Engine consumes expansion requests at segment boundaries. DAG mutation with formal successor rewiring (roots/sinks algorithm). Repeat-repo segments, cycle detection, idempotency guard. Persisted to batch state for resume.
- TP-144: Segment expansion acceptance tests — Unit test coverage for expansion tool, engine mutation, frontier reconstruction, and resume. Live e2e deferred due to merge thinking issue.
- Resume crash after segment expansion (#441) —
resolve(allocTask.task.taskFolder)guarded for missing/empty taskFolder. Persisted segments carried forward on resume. Segment metadata (segmentIds, activeSegmentId, packetRepoId, packetTaskPath) rehydrated into discovered tasks. - Topo-sort failure rejects expansion — Was falling back to append-order which could violate dependency semantics. Now fully rolls back to pre-mutation state.
- Engine-side requestedRepoIds uniqueness — Duplicate repo IDs in expansion request now rejected at engine validation.
- TP-140: Global preferences architecture — Config precedence flipped: schema → global prefs → project overrides. "User preferences" renamed to "global preferences" throughout. Project config is sparse (only overrides). Settings TUI defaults to saving to global. Source badges:
(global)and(project). - TP-141: First-install bootstrap + cross-provider guidance — Global prefs bootstrapped from schema defaults on first install. Thinking defaults to
highfor worker/reviewer. Firsttaskplane initguides cross-provider reviewer/merger model selection. Thinking picker shows all pi levels (off through xhigh).
- Merge agent thinking defaults to
off(#439) — Thinking caused merge agent to spend 70 min reasoning without calling any tools. Merge is mechanical; thinking is counterproductive. - Deprecated
/taskcommands removed —/task,/task-status,/task-pause,/task-resumeno longer registered./orchis the only execution path. Spawn Mode setting removed from TUI.
- Test and merge agent isolation from user preferences —
project-config-loader.test.tsisolatesPI_CODING_AGENT_DIRper test. Merge agent spawns with isolated agent dir. Prevents stale user prefs from contaminating verification tests. - Enum settings use picker instead of toggle — Integration and Autonomy Level now open a scrollable picker on Enter (was unintuitive ←/→ cycling).
- TP-138: Inherit defaults + thinking picker — Worker thinking and reviewer model now default to inherit (empty string). "inherit" string alias normalized to empty. Thinking picker (inherit/on/off) in
/taskplane-settingswith model-change suggestion. Runtime fallbacks audited — no--thinking/--modelflag passed when empty. - TP-139: Init model picker + global defaults — Interactive provider → model → thinking selection during
taskplane init.taskplane config --save-as-defaultssaves agent settings to user preferences for future inits. Model registry queried viapi --list-models.
generateProjectConfig()in CLI now uses inherit defaults (was hardcodingworker.thinking: "off"andreviewer.model: "openai/gpt-5.3-codex").qualityGate.reviewModelnow normalized —"inherit"no longer passed as literal--model inherit.sanitizeInitAgentConfignormalizes"inherit"in model fields from saved preferences.
- Merge thinking user prefs silently dropped —
mergeThinkingwas referenced in settings TUI but not wired throughUserPreferencesinterface, extraction, or application. Saving merge thinking to user prefs was a no-op.
- Merge agent thinking config —
MergeConfignow has athinkingfield (empty = inherit session). Available in/taskplane-settingsunder Merge section.
- Interactive model picker in
/taskplane-settings— Model selection now uses a two-level provider → model picker instead of free-text input. First option is "inherit (use current session model)". Current model marked with ✓. Falls back to manual input if no models available.
- Batch history persistence (TP-137) — Batch history now survives
orch_integrate. The parent process writes history after engine completion, and integration preserves.pi/batch-history.jsonacross merges. Fixes #423.
- Wave transition false-failure from stale lane snapshots — Stale lane snapshot files from prior waves are now cleared before launching new wave workers. Added 60-second tracker-age grace period so newly-started tasks aren't marked failed during worker startup. Fixes TP-005 being falsely marked failed at wave 2 start in workspace mode.
- Same-repo segment packet paths resolve inside worktree — When packet home repo equals execution repo, packet paths now resolve inside the worktree instead of using absolute paths to the original repo. Fixes
.DONEbeing written outside the worktree (monitor couldn't find it → false task failure while worker completed successfully).
- Missing
runGitimport in waves.ts —resolveBaseBranchcalledrunGit()butwaves.tsonly importedgetCurrentBranchfromgit.ts. In the jiti-compiled engine-worker context, this threwReferenceError: runGit is not defined, silently falling back to the repo HEAD branch. Root cause of persistent wave 2 worktree base branch failures.
- Wave 2+ worktree base branch (v0.24.10 regression) — The orch branch existence check used
check.statusinstead ofcheck.ok(runGitreturns{ ok }not{ status }). The check always failed, so worktrees were still branched from develop instead of the orch branch.
- Merge result path on Windows — Normalize backslash paths to forward slashes in merge request text. Prevents LLM from converting to MSYS-style
/c/dev/...which Node.js misresolves toC:\c\dev\...on Windows.
- Workspace wave 2+ worktree base branch — Worktrees now branch from the orch branch (which has prior wave merged work) instead of the repo's HEAD. Fixes wave 2 workers not finding wave 1 artifacts in polyrepo mode.
- Cross-repo segment execution: packet path resolution —
packetTaskPathis now resolved to an absolute path using the workspace root. Previously stored as a relative path, which broke when a segment executed in a different repo's worktree (lane-runner couldn't find PROMPT.md/STATUS.md/.DONE to create completion markers). First polyrepo segment test surfaced this.
- Multi-repo segment execution MVP (TP-132–136) — Full segment-based execution for workspace/polyrepo mode:
- TP-132: Spec aligned to Runtime V2 contracts
- TP-133: Engine segment frontier — consumes segment plans, executes segments sequentially per-task, packet-home
.DONEauthority - TP-134: Segment-aware lane execution — segmentId in snapshots/outcomes, separate execution cwd from packet paths, segment context in worker prompts
- TP-135: Segment persistence + resume —
segments[]populated in batch state, resume reconstructs segment frontier from persisted state - TP-136: Segment observability — dashboard shows active segment per lane, supervisor alerts include segment context
- Supervisor alert on engine crash — Error IPC handler now emits
onSupervisorAlert(was only callingctx.ui.notify). The supervisor is now notified of engine crashes. - Disk persistence on engine crash — Parent process persists
batch-state.jsonwithphase: "failed"when engine crashes. Fixes #421.
- Crash fix: onTelemetry guard — The
onTelemetrycall added in v0.24.6 for immediate context % refresh was missing the optional callback guard. Crashed the engine whenspawnAgentwas called withoutonTelemetry(merge agent, reviewer). First real-world validation of TP-130’suncaughtExceptiondiagnostic pipeline.
- Live context % refresh (TP-129) —
get_session_statsrequested periodically (every 5 assistant messages) instead of one-shot. Context % emitted immediately onresponseevent for true live dashboard updates. - Engine worker diagnostics (TP-130) —
uncaughtException/unhandledRejectionhandlers send stack trace via IPC before exit. Stderr captured to.pi/telemetry/{batchId}-engine-worker-stderr.logwith tail included in supervisor alerts. Snapshot failure counter auto-disables reviewer refresh after 5 consecutive failures. - TMUX naming cleanup (TP-131) — Dashboard
tmuxSessions→sessions,.tmux-*CSS →.session-*, server stubs cleaned,/api/pane/*removed, audit expanded toskills/. - Reviewer telemetry parity — Dashboard reviewer sub-row shows elapsed, tools, context %, token summary, and last tool (matching worker badges).
- Duplicate crash alerts suppressed — When engine-worker sends error via IPC before exiting, the parent no longer fires a second alert on the exit event.
- Stderr capture flush safety — Stream flushed before log rotation, error handler added, in-memory tail preferred over disk file for freshest data.
- Dashboard version skew — Frontend reads
sessions ?? tmuxSessionsfor backward compat.
- Checkbox discipline reinforcement — RULE #1 added to top of worker template: check off each checkbox immediately after completing it, not at step end. Also added explicit reminder in the lane-runner worker prompt.
- Stall timeout: 30 → 60 minutes — Prevents false stall kills during long steps where STATUS.md isn't updated until step completion.
- Full-package TMUX extrication (TP-128) — Removed TMUX from task-runner.ts (-1755 lines), CLI doctor/install checks (-295 lines), supervisor templates, and expanded audit script scope. 15 reviews. Net -5876 lines across 35 files.
- Engine crash prevention —
emitSnapshot()is now non-throwing by contract. ThereviewerRefreshinterval andonTelemetrycallbacks are wrapped in try/catch. PreventsuncaughtException→process.exit(1)from file I/O errors in telemetry paths. Root cause of engine-worker crashes during long-running batches.
- Worker timeout default: 30 → 120 minutes — Persistent worker sessions handle multiple steps; 30 min was from the legacy single-step TMUX era.
- Context window: auto-detect from model — Default
workerContextWindow: 0means inherit from the model's context window size. The previous hardcoded 200K was a poor fit for models with 1M+ context.
- Reviewer dashboard visibility (TP-121) — Reviewer sub-row appears in the dashboard during reviews, showing live telemetry (elapsed, tools, context%, cost, last tool). Bridge extension writes
.reviewer-state.json, lane-runner reads it into lane snapshot. Includes review type and step number labels. - TMUX extrication tasks (TP-122–126) — Reference baseline/guardrails, operator messaging de-TMUX, comment/type doc sweep, centralized legacy compat shim, final compat removal.
- TP-127: Wave transition fix — Monitor no longer reports tasks as "failed" during multi-wave batch transitions (stale snapshot detection + 30s registry fallback).
- Config auto-migration — Legacy
tmuxPrefixandspawnMode: "tmux"fields are now silently migrated tosessionPrefix/"subprocess"instead of crashing. Config files updated on disk atomically (tmp+rename). Users updating from pre-v0.24.0 no longer hit a startup crash. - Wave transition stale snapshot (TP-127) — Monitor no longer reports tasks as "failed" during multi-wave batch transitions. Stale snapshot from previous task detected via taskId mismatch, with 30s timeout fallback to registry check.
- Dead TMUX functions removed —
buildLaneEnvVars,pollUntilTaskComplete,resolveRpcWrapperPath,generateTelemetryPathsremoved from execution.ts (-459 lines).
- TMUX extrication complete (orch runtime) — 9 tasks (TP-117–126) removed all functional TMUX code from the orchestrator runtime. 427 → 80 references (81% reduction). Remaining refs are migration compat, error guards, and comments.
review_steptool for V2 workers (v0.23.15) — Workers spawn reviewer agents at step boundaries via bridge extension.- Worker system prompt fix (v0.23.14) — Workers receive full 362-line base template with checkpoint discipline.
- Outcome-embedded telemetry (TP-116) — Telemetry in LaneTaskOutcome, no fragile key matching.
- Dashboard batch transition (v0.23.12) — No page reload when new batch starts.
- Review level scoring reinforcement (v0.23.16) — Task creation skill warns against defaulting to Level 0.
- Batch history token zeros — Multiple fixes for V2 telemetry pipeline (v0.23.1–0.23.11).
- Monitor startup race (v0.23.4) — Assume alive before first snapshot.
- Agent ID naming (v0.23.3) — Registry keys aligned with monitor lookups.
- Dashboard V2 native (v0.23.2) — Server reads V2 snapshots without legacy shim.
- jiti cache (v0.23.8) — Engine-worker purges stale jiti cache on fork.
- Config rename:
tmux_prefix→sessionPrefix,spawn_mode: "tmux"→ throws error. Old field names in project config cause hard failures with migration guidance. tmuxSessionName→laneSessionIdin persisted state. Old field read via backward-compat shim (tmux-compat.ts).
- Task creation skill: review level reinforcement — Step 2 now includes inline scoring rubric and explicit warning against defaulting to Level 0. Prompt template adds pre-creation validation reminder.
- V2
review_steptool — Workers can now spawn reviewer agents at step boundaries via the bridge extension. Generates review requests, spawns a reviewer Pi subprocess, waits for completion, and returns APPROVE/REVISE/RETHINK verdict. Works with the Review Level instructions in the base worker template.
- V2 worker system prompt — Workers now receive the full 362-line base template (
templates/agents/task-worker.md) composed with project-specific guidance, matching legacy task-runner behavior. Previously V2 workers got a 1-sentence default, causing them to skip checkpoint discipline (no incremental STATUS.md checkbox updates) and ignore review level instructions. Root cause of zero progress visibility during execution.
- Outcome-embedded telemetry (TP-116) —
LaneTaskOutcomenow carrieslaneNumberandtelemetryfields populated by the lane-runner at task completion. Batch history reads telemetry directly from outcomes instead of reconstructing it via fragile lane-snapshot key lookups. Legacy snapshot fallback preserved for pre-V2 batches.
- Dashboard batch transition — When a new batch starts while viewing history, the dashboard now transitions inline instead of calling
location.reload(). Eliminates the hanging loading indicator in the browser tab.
- Batch history token lookup — V2 laneTokens now keyed by
lane-N(from snapshot) and looked up by lane number. Previous approach relied onbatchState.lanes(undefined) and sessionName (mismatched suffix).
- Batch history token zeros —
batchState.laneswas undefined when the batch history writer ran, causing a silent TypeError in the V2 lane snapshot reader. Guarded with(batchState.lanes || []). Dashboard history view now shows real token/cost data.
- Batch history token lookup — V2 task outcomes have
-workersuffix on sessionName but laneTokens was keyed without suffix. Now strips suffix as fallback. Dashboard summary page shows real token/cost data. - Merge agent "killed" → "exited" — After successful merge, registry manifest updated to "exited" instead of "killed". Dashboard agents panel shows correct status.
- jiti cache option — v0.23.7-8 used wrong option name (
fsCacheinstead ofcache). Now correct.
- After
npm update, clear stale jiti cache:rm -rf "$TEMP/jiti"then restart Pi.
- jiti cache option name — v0.23.7 used
fsCache: false(silently ignored by jiti v2). Correct option iscache: false. Stale compiled code at$TEMP/jiti/was the root cause of telemetry zeros after npm update.
- jiti cache causing stale engine code — Disabled filesystem caching in
engine-worker-entry.mjs. Afternpm update, jiti was serving old compiled code from its cache, causing telemetry zeros and other regressions. Engine-worker now compiles fresh each batch.
- Supervisor summary cost — The concise batch summary message now reads V2 lane snapshot cost (was bypassing the
collectBatchSummaryDatafix and always showing "not tracked").
- Batch history token counts — History writer now reads V2 lane snapshots (
.pi/runtime/{batchId}/lanes/*.json) instead of legacy sidecar files. Token counts and cost are no longer all-zero for V2 batches. - Supervisor summary cost —
collectBatchSummaryDatacomputes cost from V2 lane snapshots whendiagnostics.batchCostis zero. Summary now shows real cost instead of "not tracked".
- Monitor startup race — First monitor poll could fire before lane-runner wrote its initial snapshot, causing the task to be cached as "failed" in
terminalTasksfor the entire execution. Now assumes alive during startup grace window. Root cause of CLI widget showing "✗ failed" despite task succeeding.
- Agent ID naming alignment —
executeLaneV2()now usesresolveOperatorId()(same as wave planner) instead of hardcoded"op"fallback. Fixes monitor always reporting V2 tasks as "failed" due to registry key mismatch. - Snapshot-based V2 liveness — Monitor reads lane snapshot file (
status: "running") instead of PID probing for V2 liveness. More resilient, aligns with spec §5. - Flaky exitDiagnostic test — Fixed
Date.now()drift causing intermittent CI failures.
- Dashboard reads V2 lane snapshots natively — Server synthesizes
laneStatesfrom.pi/runtime/{batchId}/lanes/*.jsondirectly. No legacylane-state-*.jsonsidecar files needed for V2 batches. Dashboard and CLI widget now show live worker stats, telemetry, and progress during V2 execution. - Removed legacy lane-state shim — V2 lane-runner writes only to
.pi/runtime/(no TMUX-era files).
- Lane snapshot telemetry zeros — Terminal snapshots now populated from
AgentHostResultwith real tokens, cost, tool count, and elapsed time. - Dashboard V2 status mapping — V2 agent status (
exited/crashed/killed) mapped to legacy dashboard strings (done/error) so worker stats render. - Batch ID propagation — V2 lane snapshots include
batchIdso dashboard batch-filtering doesn't drop them. - Telemetry snapshot scope — Reviewer fix for snapshot aggregation correctness.
- Runtime V2 is now the default backend — All batches (repo mode and workspace mode) use direct process hosting instead of TMUX. TMUX is no longer required for execution correctness. Legacy TMUX paths are retained as fallback only.
/taskfully deprecated —/orchis the single execution path for both single-task and batch execution.- Merge strategy changed from squash-first to merge-first —
mergePr()in/orch-integrate --prnow tries regular merge first (preserves per-commit history), squash as fallback. GitHub repo settingrequired_linear_historymust be disabled for merge commits.
- Runtime V2 architecture (TP-100–TP-112) — Complete replacement of the TMUX-based control plane:
- Direct agent hosting (TP-104) —
agent-host.tsspawnspi --mode rpcas direct child processes withshell: false. Process registry tracks all agents. - Task executor core (TP-103) — 15 pure functions extracted from
task-runner.tsintotask-executor-core.tsfor headless execution. - Headless lane-runner (TP-105) —
lane-runner.tsmanages worker iteration loops, context pressure, stall detection, and.DONEcreation without TMUX. - Batch execution cutover (TP-108) — All repo-mode batches use
executeLaneV2. Merge agents spawn viaspawnMergeAgentV2(direct agent-host, not TMUX). - Workspace packet-home authority (TP-109) — Resume checks worktree-relative
.DONEpaths. Workspace mode enabled on V2. - Resume/monitor de-TMUX (TP-112) — Resume uses process registry for liveness. Monitor uses registry-based agent liveness. Stall kill uses PID SIGTERM. Reconnect follows detect+terminate+rehydrate.
- Direct agent hosting (TP-104) —
- Mailbox steering system (TP-089–TP-092) — File-based cross-agent messaging:
send_agent_message— Steer running agents via mailboxread_agent_replies— Non-consuming, durable outbox history (pending + acked)broadcast_message— Send to all agents (all-or-none rate limiting)notify_supervisor/escalate_to_supervisor— Agent bridge tools- Rate limiting: 30s per-agent window with audit events
- Dashboard Runtime V2 (TP-107, TP-093) — New panels and data sources:
- Agents panel — Registry-backed agent grid with role, status, lane, elapsed
- Messages panel — Event-authoritative mailbox timeline (sent/delivered/replied/rate-limited)
- V2 conversation viewer — Reads normalized agent events instead of TMUX pane capture
- V2 lane snapshot precedence over legacy lane states
- Conversation event fidelity (TP-111) — Agent-host emits
prompt_sent,assistant_message, enrichedtool_call(with path), andtool_result(with summary). All payloads bounded to prevent log growth. - Supervisor tools reference — AGENTS.md now documents all 16 supervisor tools with usage examples.
orch_startaccepts PROMPT.md paths —targetparameter now documented to accept single or multiple PROMPT.md paths for targeted execution.
- Merge V2 liveness —
waitForMergeResultis backend-aware: V2 uses process handle liveness, not TMUX session checks. - Merge error/retry cleanup — V2 merge agents killed before respawn to prevent orphans.
- Abort kills V2 agents —
killAllMergeAgentsV2()called alongside TMUX session cleanup. - Resume TDZ bug —
resumeBackenddeclaration moved before all uses. - Session identity mapping — V2
aliveSessionsstrips role suffix for reconciliation matching. - Dashboard outbox read test — Made deterministic for same-millisecond writes.
extractAssistantTextnull safety — Handles null/malformed content block arrays without throwing.- Tool event payload bounding —
tool_callemits boundedargsPreviewinstead of raw args.
- Skill refresh (TP-101) —
create-taskplane-taskskill updated for/orchexecution, JSON config precedence, no TMUX, noPROGRESS.mdrequirement. - Runtime V2 specs — 9 architecture documents under
docs/specifications/framework/taskplane-runtime-v2/. - Rollout docs — Phases F.1–F.3 marked implemented in migration plan.
- Process registry (TP-104) —
process-registry.tswith manifest CRUD, registry snapshots, orphan detection. - ExecutionUnit + PacketPaths contracts (TP-102) — Type-safe launch contracts for Runtime V2.
- Agent bridge extension —
agent-bridge-extension.tsfor worker→supervisor communication. - Test suite growth — 3406 tests (up from ~3100 at v0.22.18).
- Lane sessions pass
--no-extensionsto pi — Root cause of telemetry freeze. Pi auto-discoveredtask-runner.tsfrom the worktree CWD AND loaded it via explicit-eflag, resulting in two competing extension copies. The second copy generated timestamp-based sidecar paths, overriding TP-097's stable paths. Also explains worker startup crashes — two copies competing to spawn tmux sessions.
- TP-097: Stable sidecar identity and TMUX lifecycle — Sidecar path is now deterministic per session (not per spawn attempt), fixing telemetry freeze after crash recovery (#354, root cause of #333/#334). Orphan rpc-wrapper processes cleaned up via PID file on task end (#242). Spawn retry budget increased 2→5 with progressive delay (#335).
- TP-098: Dashboard duplicate log fix — Execution log entries no longer render twice (#348). All
.wiggum-wrap-uplegacy references removed (#251). - TP-099: Integration STATUS.md preservation — STATUS.md, .DONE, and .reviews/ files now survive through squash merge integration (#356). Root cause was artifact staging overwriting lane-merged content.
- Artifact staging allowlist expanded to include
.reviews/**directory tree — review outputs now preserved through merge. - Worker prompt cleaned of legacy dual wrap-up signal references.
- Wave start message reports post-affinity lane count (#346).
- TP-094: Context pressure fix — pi sends
contextUsage.percentbut code checkedpercentUsed(always undefined). Context pressure thresholds (85% wrap-up, 95% kill) now work correctly. Manual token-based fallback removed. Context % snapshots written at worker iteration boundaries for post-batch analysis. - TP-095: Crash recovery and spawn reliability — Worker spawn verification with retry after tmux session creation (#335). Lane-state reset on worker restart so dashboard reflects correct state (#333). Telemetry accumulation across worker restarts (#334). Lane session stderr captured to log file for crash diagnosis (#339).
- TP-096: Dashboard merge telemetry and supervisor tools — Merge agent telemetry in dashboard with full parity (#328). Four new supervisor recovery tools:
read_agent_status,trigger_wrap_up,read_lane_logs,list_active_agents.
- Wave start message reports post-affinity lane count — previously showed
min(tasks, maxLanes)ignoring file-scope grouping (#346).
- TP-081: State Schema v4 — persisted-state contracts for segment execution. v1→v2→v3→v4 migration chain, 806 lines of new tests.
- TP-089: Agent Mailbox — cross-agent steering protocol. Supervisor can send messages to any running agent (worker, reviewer, merger) via
send_agent_messagetool. rpc-wrapper checks inbox on every turn and injects via pi'ssteerRPC command. Non-blocking, guaranteed delivery. 633 lines of tests. - Agent mailbox steering spec — full protocol design at
docs/specifications/taskplane/agent-mailbox-steering.md.
- ORCH_BATCH_ID now reaches lane sessions — was never populated, causing dashboard batch filtering to fail and stale telemetry to display.
- Sidecar JSONL ~99% size reduction — rpc-wrapper now only writes telemetry-relevant events. Merge agents previously produced 42MB+ sidecar files from streaming deltas.
- REQUEST CHANGES → REVISE verdict mapping — reviewers using GitHub PR terminology now correctly trigger the REVISE flow.
- Worker template: plan review before implementation — explicit CRITICAL section prohibiting implement-then-plan-review sequence.
- Merger template: use verification commands from merge request — no longer suggests
npm testas fallback.
- TP-080 segment inference completeness — segment planning now accepts workspace repo IDs during wave computation so single-task, cross-repo
File Scopehints are inferred correctly (e.g.,api/...+web/...now yields two inferred segments instead of collapsing to one when only one repo was present in pending task routing signals). - Planning wiring —
/orch-plannow passes workspace repo IDs intocomputeWaveAssignments(...)for deterministic, workspace-aware segment inference. - Regression coverage — added tests for workspace-hinted cross-repo inference in
segment-model.test.tsandwaves-repo-scoped.test.ts.
0.20.0 - 2026-03-26
- Node.js native test runner (TP-074, TP-075) — migrated all 2690 tests from vitest to
node:test. Tests run in 10 seconds (was 156 seconds with vitest). vitest, vite, and esbuild removed from devDependencies. Customexpect()compatibility wrapper preserves assertion syntax. - Artifact cleanup and log rotation (TP-065) — 3-layer defense against unbounded disk growth: post-integrate cleanup, 7-day age-based sweep, 5MB log rotation.
- Additive upgrade migrations (TP-063, #211) —
/orchpreflight auto-creates missing scaffold files afterpi update. No more manualtaskplane initafter upgrades. - Dashboard light mode (TP-072) — sun/moon toggle in header, project-level theme persistence in
.pi/dashboard-preferences.json. - Taskplane logo — dashboard header now shows the Taskplane word mark.
- orch_start tool (TP-061, #183) — supervisor can start batches programmatically.
- Targeted test execution (TP-060, #200) — worker template instructs
--changedtests during steps, full suite only at the gate.
- Context pressure safety net (#223, TP-066) — context % calculation now includes cache read tokens. Workers no longer silently exhaust context without wrap-up signals.
- Persistent reviewer reliability (#225, TP-068) — early-exit detection, verdict tolerance for non-standard formats, graceful skip on double failure.
- Merge telemetry in dashboard (#215, TP-067) — telemetry key derived from lane session naming.
- Dashboard telemetry crash (#213, TP-064) — reads capped at 10MB per tick, skip-to-tail on fresh start.
- Dashboard bug fixes (TP-059) — merge message shows actual orch branch (#201), merge agents section populates (#202), test failures fixed (#193).
- STATUS.md step display (#198, TP-062) — only current step shows "In Progress".
- Supervisor template pattern (#135, TP-058) — composable base+local template, same as worker/reviewer/merger.
- Supervisor event visibility (#214) —
setStatusfor immediate footer rendering. - Worker premature exit — template instructs always ending with tool call, not text-only response.
- Worker incomplete exit nudge (TP-073) — subsequent iterations get explicit nudge listing remaining steps.
- Stale retrying badge (#189) —
retryActivecleared onmessage_end. - .DONE checkbox removed — task-runner creates it automatically, workers no longer checkpoint a redundant item.
- Engine worker thread (TP-071, #199) — engine runs in a
worker_thread, supervisor main thread stays responsive. - Async I/O (TP-070, #199) — all polling loops use async I/O, no more
spawnSync("tmux")blocking the event loop. - Test optimization —
--pool=threads, integration test separation, barrel import removal.
0.19.0 - 2026-03-25
- Persistent reviewer reliability (#225, TP-068) — three-layer defense against reviewer model incompatibility:
- Better prompting — reviewer template explicitly states
wait_for_reviewis a registered tool, not a bash command - Early-exit detection — if reviewer exits within 30 seconds with no verdict, triggers immediate fallback instead of waiting for 30-minute timeout
- Verdict tolerance —
extractVerdictnow recognizes non-standard formats ("Changes requested" → REVISE, "Needs revision" → REVISE) - Graceful skip — double failure (persistent + fallback) continues task with operator notification instead of blocking
- Better prompting — reviewer template explicitly states
- Reviewer template updated with explicit tool usage instructions for persistent mode
- 156 new tests for persistent reviewer reliability scenarios
0.18.1 - 2026-03-25
- Merge agent telemetry in dashboard (#215, TP-067) — telemetry key now derived from lane session naming pattern, matching actual tmux session names. Dashboard merge section shows token/cost data during merges.
0.18.0 - 2026-03-25
- Context pressure safety net (#223, TP-066) — context percentage calculation now includes cache read tokens. Previously, workers with heavy cache usage (reading large files) showed artificially low context % and never triggered the 85% wrap-up signal or 95% kill. Workers could silently exhaust their entire context window without any safety net firing.
- Worker file reading guidance (TP-066) — worker template now instructs agents to use
grep+readwith offset/limit for large files instead of reading entire files. Prevents unnecessary context bloat. - 246 new context pressure tests — validates cache-inclusive calculation with threshold triggers.
0.17.0 - 2026-03-25
- Artifact cleanup and log rotation (TP-065) — 3-layer defense against unbounded disk growth:
- Layer 1: Post-integrate cleanup deletes batch-specific telemetry and merge result files
- Layer 2: Age-based sweep on
/orchpreflight removes artifacts older than 7 days - Layer 3: Size-capped rotation for
events.jsonlandactions.jsonlat 5MB threshold - All cleanup is non-fatal — failures warn and continue
- Dashboard telemetry crash (#213, TP-064) —
tailJsonlFile()capped at 10MB per read tick. Fresh dashboard start on large files skips to tail instead of reading from offset 0. No moreERR_STRING_TOO_LONGcrashes.
0.16.0 - 2026-03-25
- Additive upgrade migrations (TP-063, #211) — when users run
/orchafter api update, newly introduced scaffold files are created automatically. No more manualtaskplane initafter upgrades. Migration state tracked in.pi/taskplane.jsonso each migration runs once per repo. First migration: auto-create missing.pi/agents/supervisor.md.
0.15.0 - 2026-03-25
- Targeted test execution (TP-060, #200) — worker template now instructs targeted tests (
--changed) during implementation steps and full suite only in the Testing & Verification step. PROMPT template and create-taskplane-task skill updated to reflect the strategy. Reduces test time by ~60% per task. - orch_start tool (TP-061, #183) — supervisor can now start batches programmatically via
orch_start(target). Shared helper used by both/orchcommand and tool. Guards prevent starting when a batch is already running.
- STATUS.md step display (#198) — only the current step shows "🟨 In Progress". Future steps correctly show "⬜ Not Started" instead of all being marked in-progress.
0.14.1 - 2026-03-25
- Merge message says "into develop" (#201) — now shows the actual orch branch name.
- Dashboard merge agents section empty during merge (#202) — session filter updated to match
orch-{operatorId}-merge-{N}naming pattern. Telemetry lookups also fixed. - Two pre-existing test failures (#193) —
supervisor-merge-monitoring.test.tstests 9.3 and 10.5 updated to match current implementation.
0.14.0 - 2026-03-25
- Supervisor template pattern (TP-058, #135) — the supervisor agent now follows the same composable template pattern as workers, reviewers, and mergers. Base template (
templates/agents/supervisor.md) ships with npm and auto-updates. Local override (.pi/agents/supervisor.md) enables project-specific customization without editing extension source. - Routing template —
templates/agents/supervisor-routing.mdfor onboarding/no-batch mode. - Init copies supervisor template —
taskplane initnow creates.pi/agents/supervisor.mdalongside other agent templates.
buildSupervisorSystemPrompt()andbuildRoutingSystemPrompt()load templates with{{placeholder}}variable injection instead of inline string construction. Falls back to inline prompt when templates are missing.
0.13.0 - 2026-03-24
- Persistent reviewer context (TP-057, #146) — one reviewer per task instead of per review. The reviewer stays alive across all
review_stepcalls via await_for_reviewblocking tool, maintaining full context about the task and previous reviews. ~50-60% reduction in reviewer token cost. Falls back to fresh spawn if the persistent reviewer crashes or hits the context limit. - New file:
extensions/reviewer-extension.ts— registers thewait_for_reviewtool for persistent reviewer mode. Signal protocol uses numbered files (.review-signal-{NNN}) for request coordination and.review-shutdownfor clean exit.
- Reviewer template updated — supports both persistent mode (with
wait_for_reviewtool) and fallback fresh-spawn mode. Cross-step awareness: reviewer references previous findings when reviewing later steps.
0.12.0 - 2026-03-24
- Supervisor merge monitoring (TP-056, #145) — the supervisor actively monitors merge agent health during the merge phase. Detects dead sessions (tmux died, no result file) within 2-3 minutes instead of waiting for the 90-minute timeout. Escalation tiers: healthy → possibly stalled (10 min) → dead → stuck (20 min). 763 new tests.
- Stale retrying badge (#189) — the dashboard telemetry accumulator never cleared
retryActivewhen a retry resolved viamessage_end. Stale retry state from previous batches persisted, causing a permanently flashing "retrying" badge. Server-side fix: clearretryActiveon every successfulmessage_end.
0.11.0 - 2026-03-24
/taskdeprecation (TP-054, #164) —/task,/task-status,/task-pause,/task-resumenow show deprecation warnings recommending/orch. Commands still work (soft deprecation). Docs updated.- Runtime model fallback (TP-055, #134) — when a configured agent model becomes unavailable mid-batch (rate limit, API key expired, model deprecated), tasks fall back to the session model instead of failing. Configurable via
modelFallback: "inherit"(default) or"fail". Newmodel_access_errorexit classification. 509 new tests.
0.10.2 - 2026-03-24
- Dashboard rendering crash — PR #175 introduced a TDZ (Temporal Dead Zone) crash:
reviewerActiveused before itsconstdeclaration. Dashboard showed empty lanes section.
0.10.1 - 2026-03-24
- macOS path resolution (#177) — workers crashed immediately on Homebrew/nvm npm installs because
rpc-wrapper.mjsandtask-runner.tscouldn't be found. Resolution now usesnpm root -gas the primary dynamic lookup, covering all npm setups. Added/opt/homebrewstatic fallback.
0.10.0 - 2026-03-24
- Supervisor orchestrator tools (TP-053) — the supervisor agent can now invoke
orch_resume,orch_integrate,orch_pause,orch_abort, andorch_statusas extension tools. No more asking the user to type slash commands — the supervisor acts autonomously. - Shared command/tool helpers — orchestrator command logic extracted into shared internal functions called by both slash commands and tools. Ensures behavior parity.
- Retrying badge during reviews (#174) — dashboard no longer shows a flashing "retrying" badge during
review_steptool calls.
- execution-model.md — rewritten for persistent-context + worker-driven inline reviews.
- review-loop.md — rewritten for
review_steptool model. - README.md — updated key features, single-task guidance, architecture description.
0.9.3 - 2026-03-24
- State persistence log spam (issue #166) —
endTimefor completed/failed tasks was set tolastPollTimeon every poll tick, causingchanged=true→ persist → log every few seconds. Now freezes once set. Eliminates the[orch] state/...: persisted: task-transitionflood in the supervisor session. - Reviewer sub-row scoped to active task — reviewer activity row in the dashboard now only appears under the task being reviewed, not under all tasks in the lane.
0.9.2 - 2026-03-24
- Stale branches after integrate (TP-051, issue #142) —
/orch-integratenow deletestask/*andsaved/task/*branches from the integrated batch. Also cleans orphaned branches from previous batches. Preservesorch/*in PR mode and partial-progresssaved/*refs. - Task startedAt timing (TP-051, issue #19) — task start times now use actual execution timestamps instead of STATUS.md file mtime. Fixes incorrect timing in dashboard and batch history.
- Integrate guidance after batch completion (TP-052, issue #99) — clear, prominent message shows exact
/orch-integrateand--prcommands after every batch completion. Appears in engine output and supervisor routing. - Branch protection detection (TP-052, issue #100) —
/orch-integratechecks for branch protection viagh apibefore attempting merge. Warns and suggests--prwhen protection detected. Graceful degradation whenghunavailable. - Post-batch prompt visibility (TP-052, issue #88) — supervisor sends a clear conversational message when transitioning to routing mode after batch completion, ensuring the user sees an active input prompt.
0.9.1 - 2026-03-24
- Code review baseline —
review_steptool now acceptsbaselineparameter so workers pass the pre-step HEAD SHA. Reviewer sees only the step's changes instead of an empty diff. - Reviewer model inheritance — all reviewer model fallbacks changed from hardcoded
openai/gpt-5.3-codexto session model inheritance. Config default is now empty (triggers inheritance chain). - Dead code removed —
resolveExtensionPath()andisWorkerToolMode()(19 lines, never called).
0.9.0 - 2026-03-24
- Worker-driven inline reviews (TP-050) — workers now drive the review process via a
review_stepextension tool, preserving their full context across reviews. Reviewers spawn in named tmux sessions with RPC wrapper telemetry. REVISE feedback is addressed inline by the worker in the same context. - Dashboard reviewer sub-row — live reviewer activity (elapsed, tools, last tool, cost, context%) displayed as a sub-row under the worker row during reviews. Dashboard no longer appears frozen during review phases.
- Review protocol in worker template — worker agent template includes review level interpretation (0-3), skip rules for low-risk steps, and verdict handling instructions.
- Review architecture — reviews moved from outer-loop deferred model (post-worker-exit) to worker-driven inline model (mid-execution via tool call). Review level scoring (0-3) still determines which reviews run.
- Lane-state sidecar — extended with reviewer metrics:
reviewerSessionName,reviewerType,reviewerStep,reviewerElapsed,reviewerContextPct,reviewerLastTool,reviewerToolCount,reviewerCostUsd,reviewerInputTokens,reviewerOutputTokens.
0.8.2 - 2026-03-24
- Telemetry temp file leak — lane prompt files now written to
.pi/telemetry/instead of system tmpdir, cleaned up with batch artifacts. - Telemetry filename accuracy —
generateTelemetryPaths()accepts actualbatchIdandrepoIdinstead of hardcoding timestamp and "default". Filenames now correlate correctly across agents in a batch. - Shared opId resolution — extracted
resolveTelemOpId()helper to prevent divergence between lane and merge telemetry naming. - Merge agent crash on fresh projects —
spawnMergeAgent()now checks.pi/agents/task-merger.mdexistence before passing--system-prompt-file. Falls back gracefully when agent definition is missing.
0.8.1 - 2026-03-24
- RPC telemetry for all orchestrator agents (TP-049, issue #139) — lane workers, merge agents, and reviewers now spawn through the RPC wrapper during
/orchbatches, producing.pi/telemetry/*.jsonlsidecar files and exit summaries. The dashboard consumes these for accurate per-agent tokens, cost, context%, and tool call metrics.
0.8.0 - 2026-03-23
- Persistent worker context (TP-048, issue #140) — workers now spawn once per task instead of once per step. The worker handles all remaining steps in a single context window, committing at each step boundary. If context runs out mid-task, the next iteration picks up from the last completed step. Typical tasks complete in a single iteration.
- Context window auto-detect (TP-047, issue #140) —
worker_context_windowis now auto-detected from pi's model registry instead of hardcoded at 200K. Claude 4.6 Opus correctly uses its 1M context window. Explicit config overrides still take precedence. - Updated context defaults —
warn_percentraised from 70% to 85%,kill_percentfrom 85% to 95%, maximizing useful context utilization.
- Model pre-flight display — worker/reviewer models now read from the full unified config (including user preferences), not the stripped orchestrator config. Previously always showed "inherit" regardless of
/settings. - Dashboard NaN heartbeat (issue #129) —
relativeTime()now handles ISO string timestamps from the supervisor lockfile. - Lockfile batchId stuck (issue #130) — heartbeat tick refreshes batchId from live batch state when it was initially "(initializing)".
- Dashboard shows wrong batch (issue #20) — after batch completion, dashboard now shows the just-finished batch instead of the previous one. Fixed async race between history fetch and view rendering.
- Onboarding task area registration (issue #138) — supervisor onboarding script now explicitly requires registering task areas in config, with example JSON and verification step.
- Merge timeout default — increased from 10 to 90 minutes to accommodate large batches with tests.
0.7.2 - 2026-03-23
- Model availability pre-flight check —
/orchvalidates all configured agent models (worker, reviewer, merger, supervisor) against the pi model registry before starting a batch. Misconfigured models block with a clear error instead of failing hours into a run. - Unified supervisor mode (issue #128) — routing-mode supervisor can now start batches via
/orch all. Batch completion transitions back to conversational mode instead of deactivating. Enables continuous workflow:/orch→ conversation → run tasks → complete → conversation continues. - Async merge polling (TP-046, issue #136) —
waitForMergeResultconverted from synchronoussleepSyncto asyncsleepAsync. Supervisor, heartbeat, and user input remain responsive during the merge phase. - Dashboard wave bar fix (TP-045, issue #101) — completed wave segments now render green instead of black in the progress bar.
- Agent model defaults — removed hardcoded
openai/gpt-5.3-codexfrom reviewer template and model-specific comments from local templates. All agents default to inheriting the session model. resolveConfigRootexport — fixed/orchcrash (resolveConfigRoot is not a function) caused by missing re-export from config barrel.- Supervisor session cleanup — extension deactivates supervisor on
session_endto clean heartbeat/lock in normal shutdown paths. - Merge result schema tolerance — parser accepts
source/sourceBranch/source_branchand equivalent variants. Merge request includes explicit JSON schema guidance.
- Updated commands reference for unified supervisor mode.
0.7.0 - 2026-03-23
- Resume coherence and merge-retry recovery (TP-037) — resume now checks wave merge outcomes (not just task
.DONE) so completed-task waves with missing/failed merges are retried instead of skipped; stale pending-task session allocations are cleared to avoid false failure classification on resume. - Merge-timeout resilience (TP-038) — merge timeout handling now checks for a written result file before killing the session, supports timeout retries with exponential backoff, and re-reads config on retry so updated
merge.timeoutMinutesis respected without restarting. - Tier 0 watchdog integration (TP-039) — deterministic recovery paths are wired into the engine loop with retry budgets, recovery/exhaustion/escalation event emission, and pause-on-exhaustion behavior for operator visibility.
- Non-blocking orchestration runtime (TP-040) —
/orchand/orch-resumenow return control immediately while batch execution continues asynchronously; engine lifecycle events are persisted to.pi/supervisor/events.jsonlfor live supervision and dashboard consumption. - Supervisor agent (TP-041) — added
extensions/taskplane/supervisor.tswith dynamic supervisor prompt injection, lockfile + heartbeat ownership (.pi/supervisor/lock.json), startup takeover recovery,/orch-takeover, autonomy-level behavior controls, and structured action audit logging. - Universal
/orchrouting and onboarding flows (TP-042) —/orchwith no args now routes by detected project state (active batch, pending integration, no config, pending tasks, no tasks) and launches supervisor-led onboarding/returning-user conversational flows. - Supervisor-managed integration + batch summaries (TP-043) — supervised/auto integration modes now run from terminal batch callbacks, detect branch protection, execute PR/CI lifecycle flows, and generate structured supervisor batch summaries.
- Dashboard supervisor panel (TP-044) — dashboard now surfaces supervisor status, recovery timelines, event context, conversation stream data (when available), and summary content with graceful degradation for pre-supervisor batches.
- Merge result schema compatibility hardening — merge result parsing now tolerates known key variants (
source_branch/sourceBranch/source,target_*,merge_commit/mergeCommit) and normalizes verification payload variants to prevent false merge hangs/timeouts when agents produce non-canonical keys. - Merger prompt schema precision — merge request generation now embeds an explicit required snake_case JSON schema to reduce model drift in merge result files.
- Supervisor shutdown cleanup — extension now deactivates supervisor on session end to clean heartbeat/lock ownership in normal shutdown paths.
- Task status artifact reconciliation — TP-037..TP-044
STATUS.mdfiles were reconciled after batch completion so staged task records no longer incorrectly show "Not Started".
- Updated architecture, command reference, settings reference, first-run orchestration tutorial, and dashboard tutorial for non-blocking engine + supervisor-led workflows.
- Watchdog/supervisor specification docs were finalized and synchronized ahead of implementation.
- Added extensive deterministic regression coverage for resume bugs, timeout resilience, watchdog behavior, non-blocking engine flow, supervisor routing/behavior, auto-integration, and merge-result schema compatibility.
- Test suite expanded to 51 files / 2151 tests at release cut.
- Skip reviews for low-risk steps (TP-036) — Step 0 (Preflight) and the final step (Documentation & Delivery) now skip plan and code reviews regardless of review level. Saves ~4 review agent invocations per task (~25-30% faster for M-sized tasks). Middle implementation steps are unaffected.
- Supervisor-led onboarding scripts added to watchdog spec — 8 conversational scripts for project setup, task area design, git branching, batch planning, health checks, and post-batch retrospectives.
- RPC wrapper & structured diagnostics (TP-025) —
bin/rpc-wrapper.mjswrapspi --mode rpcto capture telemetry from worker/reviewer sessions.TaskExitDiagnosticinterface with 9-way exit classification (completed,api_error,context_overflow,process_crash, etc.). Sidecar JSONL files for real-time telemetry with secret redaction. - Task-runner RPC integration (TP-026) —
spawnAgentTmux()uses the RPC wrapper for/tasktmux sessions. Sidecar tailing during poll loop provides live token counts and cost. Structured exit diagnostics replace free-textexitReason./orchsubprocess path unchanged. - Dashboard real-time telemetry (TP-027) — Dashboard displays per-lane token counts, cost, context utilization %, last tool call, retry status, and batch total cost. Graceful degradation for pre-RPC sessions.
- Partial progress preservation (TP-028) — Failed tasks with lane branch commits get saved branches (
saved/{opId}-{taskId}-{batchId}). Commit count and branch name recorded in task outcome. Works in single-repo and workspace mode. - Cleanup resilience & post-merge gate (TP-029) — Fixes issue #93: lane worktrees and branches cleaned up in ALL workspace repos per wave (not just last-wave repos). Force cleanup fallback (
rm -rf+git worktree prune). Post-merge cleanup gate blocks next wave if cleanup fails. Polyrepo acceptance criteria validated after/orch-integrate. - State schema v3 & migration (TP-030) —
batch-state.jsonschema v3 withresilience(retry counters, repair history, failure classification) anddiagnostics(per-task exit summaries, batch cost) sections. Auto-migration from v1/v2 with conservative defaults. Corrupt state enterspaused(never auto-deleted). Unknown fields preserved on roundtrip. - Force-resume & diagnostic reports (TP-031) —
/orch-resume --forceforfailed/stoppedphases with pre-resume diagnostics. Merge failure defaults topaused(notfailed). Structured diagnostic reports (JSONL event log + human-readable summary) emitted on batch completion/failure. - Verification baseline & fingerprinting (TP-032) — Pre-merge verification baselines per repo. Normalized test output fingerprinting.
newFailures = postMerge - baseline— pre-existing failures no longer block valid merges. Flaky test handling (re-run once). Strict/permissive modes. Opt-in viaverification.enabled. - Transactional merge & retry matrix (TP-033) — Merge transaction envelope (capture pre/post refs, rollback on failure, safe-stop if rollback fails). Retry policy matrix with persisted counters scoped by
(repoId, wave, lane). Cooldown delays, max attempts, wave gate on cleanup failure. - Quality gate structured review (TP-034) — Opt-in post-completion quality gate. Cross-model structured review with JSON verdict (PASS/NEEDS_FIXES). Severity-classified findings.
.DONEonly created after PASS when enabled. Remediation cycle (max 2 reviews). Configurable viaquality_gate.enabled. - STATUS.md reconciliation & artifact staging scope (TP-035) — Automatic STATUS.md checkbox correction from quality gate review findings. Artifact staging restricted to task-owned paths only. System-owned template checkboxes removed.
- Supervisor primer —
extensions/taskplane/supervisor-primer.mdships with npm package. Operational runbook for the future supervisor agent covering architecture, recovery patterns, git operations, and batch state management.
- Reviewer APPROVE threshold raised — REVISE now means "will fail without fixes", not "I found something". Minor findings go to Suggestions (no checkboxes), not Issues Found.
- Worker prompt updated — Issues Found items create mandatory checkboxes, Suggestions logged in Notes only.
docs/specifications/— moved from.pi/local/docs/to git-tracked location for worktree accessibilitydocs/explanation/waves-lanes-and-worktrees.md— comprehensive rewrite covering orch branch model, file-scope affinity, batch-scoped worktrees, per-repo merge, integration flowdocs/explanation/architecture.md— updated for JSON config, orch branch flow- "Repo mode" renamed to "single-repo mode" across all docs
- Watchdog & recovery tiers specification (v2) — interactive supervisor architecture
- AGENTS.md — added JSON config precedence rule (invariant #6)
- Cross-repo TASK_AUTOSTART path resolution — workspace mode now uses absolute paths for task PROMPT.md so workers in api-service/web-client worktrees can find tasks that live in shared-libs.
.DONEfiles missing after/orch-integrate— artifact staging was deleting.DONEfiles from the working tree after copying to the merge worktree. After ff integration, they weren't restored. Now.DONEfiles are preserved in the working tree (the stash in/orch-integratehandles them)..worktrees/directory excluded from artifact staging — prevents worktree internals from being committed to the orch branch.- Test isolation — config loader tests no longer break when user preferences override reviewer model.
/orch-integrateblocked by dirty STATUS.md files — workspace mode preserves STATUS.md in the working tree for dashboard visibility, but these dirty files blockedgit merge --ff-only. Now auto-stashes before integration and pops after.- Batch completion message unclear — simplified to two options: "Apply now (recommended)" and "Push & open PR for review". Removed
--mergefrom default display (shown in ff error fallback). Added "Your branch was not modified" reassurance.
- Dashboard wave progress bar stale — STATUS.md was reverted in develop's working tree after artifact staging, causing the dashboard to show partial checkbox counts for completed waves. Now only .DONE files are removed; STATUS.md modifications are preserved for dashboard visibility.
/orch-integratecommit count always 0 — count was measured after fast-forward when HEAD already equals orch tip. Now measured before.
/orch-integrateonly integrated default repo — in workspace mode, now loops over all repos that have the orch branch and integrates each one.
- Task artifacts committed to develop instead of orch branch —
.DONEandSTATUS.mdfiles are now staged into the merge worktree (on the orch branch) instead of committed directly to develop. This prevents branch divergence that blocked/orch-integratefast-forward.
- Orch branch only created in default repo — workspace mode now creates the orch branch in every repo at batch start. Merges target the orch branch directly instead of the repo's current branch, so
/orch-integratehas actual commits to apply.
- Dashboard missing merge sub-rows for single-repo waves — Wave 3 merge showed "succeeded" but no lane details when only one repo was involved. Threshold changed from 2+ to 1+ repo results.
- Workspace task artifacts not committed before merge — workers wrote
.DONEandSTATUS.mdto the canonical task folder (shared-libs) via absolute paths, leaving them as uncommitted working tree changes. NewcommitWorkspaceTaskArtifacts()runs after each wave before the merge step, committing task artifacts to the task-area repo so they appear in the orch branch and don't block/orch-integrate.
- Task completion not detected in workspace mode — orchestrator polled for
.DONEinside lane worktrees, but in workspace mode workers write.DONEto the canonical task folder (shared-libs). Now resolves.DONEandSTATUS.mdfrom the absolute task folder path in workspace mode. Also fixes dashboard STATUS.md monitoring for cross-repo tasks.
- Cross-repo TASK_AUTOSTART path resolution — workspace mode now uses absolute paths for task PROMPT.md so workers in api-service/web-client worktrees can find tasks that live in shared-libs.
- TASKPLANE_WORKSPACE_ROOT not set for lane sessions — env var condition was always false in workspace mode. Lane sessions couldn't find config, showing "0 areas".
- Lane sessions couldn't find task-runner extension — lane tmux sessions hardcoded
{repoRoot}/extensions/task-runner.tswhich only exists in the taskplane dev repo. Now searches npm global install paths. This was a critical bug preventing workspace/polyrepo mode from working for any project other than taskplane itself. - Batch completion message missing integration instructions — now shows orch branch name and
/orch-integratecommand options. - Batch state deleted on clean completion — state is now preserved when an orch branch exists so
/orch-integratecan find it.
- Orchestrator-managed branch model (issue #24) —
/orchnow creates an ephemeralorch/{opId}-{batchId}branch and does all work there. User's HEAD is never touched during batch execution. VS Code stays on whatever branch the user is working on. /orch-integratecommand — integrates completed batch work into your working branch. Three modes: fast-forward (default),--merge(real merge),--pr(push and open GitHub PR). Includes branch safety check (warns if current branch differs from batch origin).- Batch-scoped worktree containers — worktree paths changed from
{prefix}-{opId}-{N}to{basePath}/{opId}-{batchId}/lane-{N}. Prevents directory collisions between concurrent batches. Merge worktree is inside the container. - Auto-integration config —
integrationsetting ("manual"default,"auto"opt-in). Manual = user runs/orch-integrate. Auto = fast-forward on completion. - Settings reference doc —
docs/reference/configuration/taskplane-settings.mddocuments every setting with types, defaults, options, and descriptions. - 86 new tests (828 total across 22 test files), including new
orch-integrate.test.ts.
- Wave merges use
git update-refinstead ofgit merge --ff-onlyin the main repo — no longer touches the working tree. - Stash/pop logic removed from merge flow (no longer needed since orch branch is never checked out in main repo).
- Post-merge worktree reset targets orch branch HEAD instead of user's branch.
- Batch completion message shows orch branch name and
/orch-integrateinstructions.
- Settings TUI input fields freeze terminal (issue #57) — replaced inline submenu with single-value cycling pattern that exits TUI, then prompts via
ctx.ui.input(). Works on all platforms. - Renamed
/settingsto/taskplane-settingsto avoid collision with pi's built-in/settingscommand. - Protected branch blindness —
/orchon a protected branch no longer wastes hours before failing at merge time.
- Orchestrator
spawn_modesetting removed from/taskplane-settingsTUI —/orchalways requires tmux, making the setting misleading. The worker-level Spawn Mode (controls/taskbehavior) remains.
/taskplane-settingsTUI command — interactive config editor with section navigation, source indicators (project/user/default), type-specific controls, and validation. Primary config interface — users rarely need to edit files directly.- JSON config schema — unified
taskplane-config.jsonreplaces both YAML files. Unified loader with YAML fallback for backward compatibility. taskplane initv2 — auto-detects repo vs workspace mode (no--workspaceflag needed). Enforces selective gitignore entries. Detects and offers to untrack accidentally committed runtime artifacts. Defaultsspawn_modeto"tmux"when available.- Pointer file resolution — workspace mode uses
taskplane-pointer.jsonto locate config, agents, and state in the designated config repo. All subsystems (task-runner, orchestrator, dashboard, merge agent) follow the pointer. - User preferences —
~/.pi/agent/taskplane/preferences.jsonfor personal settings (operator ID, models, tmux prefix, dashboard port). Merged with project config at load time. - Doctor enhancements — gitignore validation, tracked artifact detection, workspace pointer chain validation, config repo default branch check, legacy YAML migration warning, tmux vs
spawn_modemismatch detection. - Configurable merge agent timeout (
merge.timeout_minutes, default: 10 min, was hardcoded 5 min). Exposed in/taskplane-settingsTUI.
- Per-step git commits replace per-checkbox commits — reduces git overhead by ~70-80% without losing recovery capability. STATUS.md is still updated after each checkbox.
- CHANGELOG.md mandatory in release process (AGENTS.md pre-release checklist added).
- Agent prompt inheritance — base prompts ship in package and auto-update on
pi update. Local.pi/agents/*.mdfiles are thin project-specific overrides composed at runtime.standalone: trueopts out. taskplane initnow scaffolds thin local agent files instead of full copies.
- Node.js minimum raised to 22 (was 20). All CLI commands fail fast with a clear error on older versions. CI updated to Node 22.
taskplane install-tmux— automated tmux installation for Git Bash on Windows. Downloads from MSYS2 mirrors, no admin rights needed.--checkfor status,--forceto reinstall/upgrade.- tmux documented as strongly recommended prerequisite across all public-facing docs.
taskplane doctorsuggestsinstall-tmuxwhen tmux is missing on Windows.
taskplane install-tmuxcommand (same as v0.3.0 — released before the Node.js bump).
- Dashboard STATUS.md eye icon resolves paths correctly in workspace mode (was double-pathing repo prefix).
- State/sidecar files (batch-state.json, lane-state, merge results) now write to workspace root's
.pi/instead of repo root's.pi/in workspace mode. Fixes dashboard not showing batch progress.
- Tolerate flat
verification_passed/verification_commandsfields in merge result JSON (merge agents may write flat fields instead of nestedverificationobject).
- Normalize merge result
statusfield to uppercase before validation. Merge agents may write lowercase ("success"vs"SUCCESS").
- Worktree base branch resolved from current HEAD instead of
default_branchin workspace config. Was causing worktrees to branch fromdevelopinstead of the user's feature branch.
- Thread
TASKPLANE_WORKSPACE_ROOTenv var to lane sessions so task-runner can find.pi/task-runner.yamlin workspace mode.
- Discovery resolves task area paths from workspace root (not repo root) in workspace mode.
- Preflight
git worktree listcheck runs from repo root in workspace mode (workspace root is not a git repo).
- Polyrepo workspace mode — multi-repository orchestration with per-repo lanes, merges, and resume.
- Workspace config (
.pi/taskplane-workspace.yaml) with repo definitions, routing, and strict mode. - Task repo routing via
## Execution Targetin PROMPT.md. - Repo-scoped lane allocation with global lane numbering.
- Repo-scoped merge sequencing with partial-success reporting.
- Operator-scoped naming for sessions, worktrees, branches, and merge artifacts (collision resistance).
- Schema v2 persistence with repo-aware task/lane records and v1→v2 auto-upconversion.
- Resume reconciliation across repos.
- Dashboard repo filter, badges, and per-repo merge sub-rows.
- Strict routing enforcement (
routing.strict: true). - 398 tests across 15 test files.
- Rebalanced hydration philosophy — outcome-level checkboxes (2-5 per step) replace exhaustive implementation scripts (15+ micro-checkboxes).
- Updated task-worker and task-reviewer agent prompts with "Adaptive Planning, Not Exhaustive Scripting" guidance.
- Dashboard eye icon contrast improved — higher opacity, accent color on hover/active states, box-shadow ring for on/off distinction.
- Minor bug fixes and stability improvements.
- Minor bug fixes and stability improvements.
0.1.14 - 2026-03-15
taskplane doctornow parses task-areacontext:paths only from thetask_areasblock, preventing false-positive CONTEXT warnings from unrelated YAML sections.
0.1.13 - 2026-03-15
taskplane init --tasks-root <relative-path>to target an existing task directory (for exampledocs/task-management) instead of creating an alternate task area path.
- When
--tasks-rootis provided, sample task packets are skipped by default; pass--include-examplesto scaffold examples intentionally into that directory.
0.1.12 - 2026-03-15
taskplane uninstallCLI command with project cleanup + optional package uninstall scopes (--package,--package-only,--local,--global,--remove-tasks,--all,--dry-run).- Dynamic example scaffolding in
taskplane init: alltemplates/tasks/EXAMPLE-*packets are now discovered and generated. - Second default example task packet:
EXAMPLE-002-parallel-smoke. - GitHub governance baseline for OSS collaboration:
- CI workflow (
.github/workflows/ci.yml) - Dependabot config
- CODEOWNERS
- Docs improvement issue form + issue template config
- CI workflow (
- Onboarding is now orchestrator-first (
/orch-plan all+/orch all+ dashboard), with/taskdocumented as explicit single-task mode. - Docs now explicitly clarify
/taskruns in current branch/worktree while/orchuses isolated worktrees (recommended default even for single-task isolation). AGENTS.mdnow includes branching/PR workflow and release-playbook guidance for coding agents.- Maintainer documentation expanded with repository governance and release mapping between GitHub releases and npm publish.
- CI baseline now avoids peer-dependency import failures from extension runtime-only modules in this repo context.
- Branch protection/check naming documentation aligned with the required GitHub check context (
ci).
0.1.11 - 2026-03-14
- Taskplane CLI package entrypoint (
taskplane) with init/doctor/version/dashboard commands - Web dashboard packaging under
dashboard/with CLI launch support - Project scaffolding via
taskplane init(configs, agents, task templates) - Dependency-aware parallel orchestration commands (
/orch*) - Batch persistence and resume foundations (
/orch-resume, persisted batch state)
- Package layout aligned for pi package distribution (
extensions/,skills/,templates/,dashboard/) - Documentation strategy shifted to phased, public open-source structure
- Dashboard root resolution based on runtime
--rootinstead of hardcoded repo path