feat: reduce task management friction across 14 real-session pain points#2
Open
vsumner wants to merge 11 commits intotintinweb:masterfrom
Open
feat: reduce task management friction across 14 real-session pain points#2vsumner wants to merge 11 commits intotintinweb:masterfrom
vsumner wants to merge 11 commits intotintinweb:masterfrom
Conversation
…test coverage - Replace busy-wait with Atomics.wait, hoist SharedArrayBuffer outside loop - Cap process output buffer at 1MB with FIFO eviction - Guard proc.pid undefined with -1 sentinel - Store kill signal from close event - Harden load() to re-throw non-ENOENT/non-SyntaxError errors - Atomic file writes with temp file cleanup on failure - Single-pass clearCompleted() - Cache widget task list, avoid disk I/O on animation frames - Pin typebox version, add engines field - Add dispose() for extension cleanup (event listeners, timers, widget) - Self-remove subagents:ready listener to prevent leak - Accept AbortSignal in spawnSubagent with proper cleanup - Track in-flight spawn RPC listeners for dispose cleanup - Replace global cascadeConfig singleton with per-task Map - Add ProcessTracker.remove() for memory cleanup - Fix appendOutput byte accounting to use chunk.length - Add 11 new tests (130 total): buffer cap, oversized chunk, pid=-1, remove(), ENOENT/corrupt JSON handling, dispose, AbortSignal
Implements friction-reducing improvements identified from 8 real sessions: - Skipped status for tasks (type, icon, unblocking behavior) - Nudge suppression when tasks are in_progress - Configurable nudge interval and auto-clear settings - TaskCreateMany for batch task creation - Enhanced TaskCreate with blockedBy/blocks/status/clearCompleted - formatTaskDetail helper (DRY across TaskCreate/TaskGet) - Collapse completed tasks in widget (3+ active) - Budget/timeout display in widget - Orphaned task detection on session resume - Cycle detection via DFS in task-store - Status-at-creation support in store Review fixes applied: - Bug: widget totalShown now uses visibleTasks.length (fixes "and N more") - DRY: createSingleTask helper shared by TaskCreate/TaskCreateMany - DRY: isTerminalStatus helper for blocker resolution checks - Simplify: orphan state collapsed to single pendingOrphanReminder - Simplify: settings-menu if/else if chain with hoisted saveTasksConfig 157 tests passing, typecheck clean.
Thread model parameter through to spawnSubagent() for both initial execution and auto-cascade — was accepted in schema but never forwarded to spawn options. Timeout handler now emits subagents:rpc:stop with the agent ID as a best-effort cancellation request. Previously it only marked the task completed locally without attempting to stop the running agent. Update README to reflect current API surface: - 8 tools (was 7, missing TaskCreateMany) - Document TaskCreateMany with parameter table - Add missing TaskCreate params (blockedBy, blocks, status, clearCompleted) - Add skipped to TaskUpdate status enum - Add token_budget and timeout_ms to TaskExecute table - 4 persisted settings (was 2) - 165 tests (was 116)
Replace Atomics.wait in file lock with bounded spin-sleep (10ms × 50 retries = 500ms max, down from 50ms × 100 = 5s). Eliminates SharedArrayBuffer dependency and reduces worst-case event loop stall by 10×. Lock path only fires for project-scoped stores. Add 50ms read cache TTL to TaskStore — coalesces rapid get()/list() calls within the same event loop tick. withLock() force-reads to ensure consistency under mutation. save() updates timestamp to avoid stale reads after writes. Add shape validation to JSON.parse in task-store load() and tasks-config loadTasksConfig(). Rejects structurally invalid files (wrong types, missing fields) instead of trusting blindly. Move TaskBudget interface from closure-scoped inline definition in index.ts to types.ts for testability and reuse. Improve empty catch blocks: distinguish ENOENT (expected) from EACCES (surprising) in lock release and file cleanup. Document expected error codes in process-tracker kill catches. Add isolatedModules to tsconfig for type-strip compatibility. Bump engines.node from >=18 to >=22 (pi's actual floor). Document session_switch type cast with TODO for upstream fix.
Adds ping, createMany, and update RPC handlers on pi.events, following the same scoped request/reply pattern as pi-subagents. Enables extensions like plan-executor to create and update tasks programmatically without going through the LLM tool layer. Channels: tasks:rpc:ping, tasks:rpc:createMany, tasks:rpc:update Broadcasts tasks:ready on init for late-loading extensions.
Add missing TaskStatus import — typecheck was broken on HEAD. Revert spin-sleep to Atomics.wait in file lock. The spin-loop replacement burned CPU while still blocking the event loop; Atomics.wait blocks without CPU cost. Keep the reduced budget (10ms × 50 = 500ms max, down from 5s). Move tasks:ready broadcast after all RPC handlers are registered so consumers that react to ready can immediately call any RPC. Add payload validation to tasks:rpc:createMany and tasks:rpc:update — silently ignore malformed events instead of crashing on destructure. Return partialIds in createMany error replies for partial mutation visibility. Add 10 tests for tasks:rpc:* handlers: ping reply, createMany with deps and clearCompleted, update success/failure, malformed payload rejection, and ready-ordering guarantee.
Treat missing blockers as resolved (deleted = done) in TaskExecute, auto-cascade, and TaskList display. Previously TaskExecute treated a missing blocker as unresolved, which permanently blocked tasks when clearCompleted removed the referenced task in the same TaskCreateMany call. All three code paths now use the same semantic: if the blocker no longer exists in the store, the dependency is satisfied. Surface dependency warnings (dangling refs, cycles) from createSingleTask in TaskCreate, TaskCreateMany, and the tasks:rpc:createMany handler. Previously these warnings were silently dropped.
Completed/skipped tasks now auto-clear when new tasks are created via TaskCreate or TaskCreateMany. Matches Claude Code's TodoWrite pattern where the agent sends an empty list after finishing work. Users who want to preserve completed tasks across batches can set autoClearCompleted: false in .pi/tasks-config.json or pass clearCompleted: false explicitly.
TaskCreate now accepts either single-task params ({subject,
description, ...}) or a tasks array for batch mode. Removes
TaskCreateMany as a separate tool, reducing the API surface
from 8 tools to 7 — matching Claude Code's tool set.
Batch mode preserves all existing functionality: sequential
IDs, intra-batch dependency wiring via blockedBy/blocks,
clearCompleted, and warning surfacing.
Single mode returns an error if neither subject nor tasks
array is provided.
Return 'Created 0 task(s).' for TaskCreate({ tasks: [] }) instead
of falling through to the confusing single-mode error message.
Update README test count to 181+ (was stale at 165).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
After analyzing 8 real coding sessions (2026-03-17), we identified 14 recurring friction points in task management workflows. This PR addresses all of them.
Why
Tasks are the primary coordination mechanism between agents and humans. In practice, sessions were losing time to: excessive tool round-trips when creating task lists, missing status transitions (no way to skip irrelevant tasks), noisy nudge reminders during active work, and lack of visibility into agent budget/progress. On resume, orphaned in_progress tasks went unnoticed.
What changed
Workflow efficiency
TaskCreateManyfor batch creation with intra-batch dependencies — eliminates repeated TaskCreate + TaskUpdate round-tripsTaskCreatewithblockedBy/blocks/status/clearCompletedin a single callskippedtask status (⊘) that unblocks dependents without marking work "completed"Signal-to-noise
in_progress— no reminders during focused workVisibility
Settings
/taskssettings menuTest plan
npm run typecheckclean