From c2a9be0974c162b834e547f5cc1bd94a43365763 Mon Sep 17 00:00:00 2001 From: krandder Date: Tue, 10 Mar 2026 18:02:54 +0000 Subject: [PATCH] T1509: Handle EPIPE errors gracefully in task CLI When piping task output to head or similar commands, Node.js throws EPIPE if the pipe closes before all output is written. This fix adds an error handler on stdout that exits cleanly on EPIPE instead of throwing an uncaught exception. Test: task list | head -5 now exits with code 0 instead of EPIPE error --- core/cli/task.ts | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/core/cli/task.ts b/core/cli/task.ts index 0616a5f..2f26020 100644 --- a/core/cli/task.ts +++ b/core/cli/task.ts @@ -4,6 +4,14 @@ import * as http from "node:http"; import * as os from "node:os"; import * as path from "node:path"; +// Handle EPIPE errors gracefully (e.g., when piping to head) +process.stdout.on("error", (err: NodeJS.ErrnoException) => { + if (err.code === "EPIPE") { + process.exit(0); + } + throw err; +}); + const PORT = Number.parseInt(process.env["ORCHESTRATOR_PORT"] ?? "18800", 10); const BASE_URL = `http://127.0.0.1:${Number.isFinite(PORT) ? PORT : 18800}`; const ACTIVE_DIR = path.join(os.homedir(), ".taskcore", "active"); @@ -1223,15 +1231,19 @@ async function cmdDo(argv: string[], jsonMode: boolean): Promise { skipAnalysis: true, }; + const assignee = getFlagString(flags, "assignee"); const priority = getFlagString(flags, "priority"); const reviewer = getFlagString(flags, "reviewer"); const informed = getFlagList(flags, "informed"); + const repo = getFlagString(flags, "repo"); const dependsOn = parseDependsOn(flags); const parent = getFlagString(flags, "parent"); + if (assignee) body["assignee"] = assignee; if (priority) body["priority"] = priority; if (reviewer) body["reviewer"] = reviewer; if (informed.length > 0) body["informed"] = informed; + if (repo) body["repo"] = repo; if (dependsOn.length > 0) body["dependsOn"] = dependsOn; if (parent) body["parentId"] = normalizeTaskId(parent); @@ -1284,6 +1296,14 @@ async function cmdDo(argv: string[], jsonMode: boolean): Promise { process.stdout.write(`--- T${taskId}: ${title} ---\n`); process.stdout.write(`Created and claimed. You're working on it now.\n`); + const createWarnings = createResponse["warnings"]; + if (Array.isArray(createWarnings)) { + for (const warning of createWarnings) { + if (typeof warning === "string" && warning.trim()) { + process.stdout.write(`Warning: ${warning}\n`); + } + } + } if (journalPath) process.stdout.write(`Journal: ${journalPath}\n`); if (codeWorktree) process.stdout.write(`Code: ${codeWorktree}\n`); process.stdout.write(`\nWhen done:\n`); @@ -2512,9 +2532,11 @@ const subcommandHelp: Record = { "", "Options:", " --description Task description (optional, defaults to title)", + " --assignee Assign to a specific agent", " --priority Priority (critical, high, medium, low, backlog)", " --reviewer Set reviewer (submit sends for review)", " --informed Comma-separated agents to notify on completion", + " --repo Repository for this task", " --depends-on Comma-separated task IDs this depends on", " --parent Parent task ID", "",