omp packages

@qcts33/pi-herdr-tasks0.3.0

Run one external command per Herdr pane as a Command task and deliver its Task outcome back to a pi conversation

qcts33 Published 11 hours ago MIT ~179 downloads/mo

Untested on omp

This is a pi package. No one has reported whether it works on omp yet. If you try it, add your result below.

Did it work for you?

Result

One report per person. A new report replaces your old one.

Reports 0

No reports yet.

Readme

@qcts33/pi-herdr-tasks

Run one external command per herdr pane as a Command task, watch it in its own herdr tab, and get its outcome back in the pi conversation when it ends. The task tool returns as soon as the command is admitted, so a build, a test suite, a batch job, or a training run is not tied to the turn that started it. POSIX only in this version.

How it works

task starts a Command task: one external command on the raw terminal surface of a herdr pane, with no Pi child runtime and no agent lifecycle. The tool creates a Task run directory under the OS temporary directory, writes a generated Task launcher there, and opens a Task pane in a new herdr tab in the parent runtime's workspace, without stealing focus. The launch returns a report once the launcher has written its start record — normally immediately — and watches from the parent process from then on.

Inside the Task pane the launcher:

  • runs the caller's command verbatim, so the command text is never subject to shell quoting or escaping;
  • redirects the command's stdin from the null device, so a command that waits for input fails instead of hanging;
  • pipes stdout and stderr through tee, so the Task pane and the Task log carry the same bytes;
  • records the command's pid, traps INT and TERM, and writes the Task completion record when the command ends, with its status, exit code or signal, and start and end times.

The extension reads that record; it never reads the pane for a result. A human's Ctrl+C in the pane therefore still produces a terminal record rather than missing evidence. The watch polls the record once a second, and when the command has ended it reads the log tail, closes the Task pane, and delivers exactly one Task outcome message. The outcome carries the Task status, exit code or signal, elapsed time, the Task log path, a Task failure category when the task failed, and the last 50 lines of the log (ANSI escapes stripped, capped at about 8 KB). The message arrives through Pi's custom-message API as a steer with a turn trigger; a long tail or log path stays readable with the usual expand key.

The Task log is the complete output, not a terminal window: it stays in the Task run directory after the task ends, so a result can be read the next day. The reasoning behind the result channel is ADR-0001 in this package's docs/adr/.

A line above the editor spins a count of running Command tasks — ⠹ 2 tasks — and disappears when the last outcome is claimed. Names, logs, and elapsed times stay in the task_inventory report and the Task outcome. The extension sends nothing to the model while a task runs and nothing to a phone when it ends.

Install

Install the package from npm:

pi install npm:@qcts33/pi-herdr-tasks

Start herdr, then run pi inside it:

herdr
pi

The extension requires HERDR_ENV=1, the herdr CLI on PATH, and the workspace id herdr exposes to the session. A missing CLI refuses every task tool with one line telling you to start pi inside herdr; a herdr below the floor is refused with the runtime-window line in Requirements.

Requirements

  • pi — the coding agent, 1.x (floor 1.0.0, tested on 1.2.0); update with pi update self
  • herdr — the required terminal workspace, 0.8.2 or newer (tested on 0.9.5); update with herdr update

Outside that window, a session shows one warning at session start, and every herdr-backed tool refuses with the same line the warning carried. The check is runtime-compat.ts, generated from shared/runtime-compat.template.ts and probed once per process, so a herdr below the floor or a server the running client cannot talk to fails a tool call with an instruction instead of a raw herdr error. The decision is ADR-0009 in the repository root.

Tools

task

Start one Command task and return its Task launch report.

Parameter Type Default Description
command string required The command to run. It is written verbatim into the Task launcher, so quotes and shell metacharacters behave as in a shell; do not quote it for the tool.
name string a label derived from the command Display name used in the report, the outcome, and the inventory.
cwd string the parent runtime's directory Working directory for the command.

The tool always returns a launch report, never the outcome. Its text says the task is running in the background in its own herdr tab, that the outcome arrives as one message and starts the next turn, that the turn ends when nothing else is left to do, and where the Task log is. The tool also carries one prompt guideline, which the host renders into the system prompt's rules section: end the turn when the next step needs a Task outcome or nothing else is left to do, because the outcome starts the next turn.

Its details name the run id, name, command, cwd, tab id, pane id, Task run directory, and running as the status. There is no foreground mode (ADR-0002), and there is no env parameter, tool-level timeout, or concurrency cap.

A launch that fails before the command is admitted is reported synchronously in this tool result, its Task pane is reclaimed, and no Task outcome is delivered. That covers a tab that cannot be created, a launcher that cannot be started, and a launcher that never writes its start record inside the 30-second startup window. A refused platform, a missing herdr CLI, and a runtime outside the support window are reported the same way.

task_cancel

Cancel one running Command task, by exact id or exact name.

Parameter Type Description
id string Exact run id; tried first.
name string Exact display name; used when no id is given.

A missing target, an unknown id or name, and an ambiguous name are each reported precisely, with the matching candidates for an ambiguity. A task that is already cancelling reports that instead of receiving a second request, and a task that is already finalizing its outcome is left alone.

Cancellation is applied to the Task pane, never directly to the command process, and in two levels: the extension writes a cancellation request, interrupts the Task pane's foreground process group, and — only if the command's own pid is still alive after a 5-second grace period polled every 100 ms — closes the Task pane. The Task completion record still decides how the task ended. A command that detached into its own session survives both levels; the result says so instead of implying the machine is idle. The design and the measured reason both levels exist are ADR-0003.

A cancellation you request delivers a cancelled Task outcome. A cancellation the extension performs internally is control flow and delivers nothing. A manual Ctrl+C in the Task pane is a cancellation too: the launcher records it and the outcome is delivered.

task_inventory

Report the Command tasks this session still owns. It takes no parameters, is read-only, is derived at call time from the running task registry, and keeps no history: a finished task is absent. Each entry names the task, its command, its running status, elapsed time, tab id, pane id, and Task run directory. It needs no herdr call and reports nothing about tasks started by another session or by a parent process that has ended.

Statuses and failure categories

A Task status is running while the command executes, and otherwise how it ended: completed, failed, or cancelled. A Task failure category is the stable machine-readable reason on a failed outcome:

  • no-completion-record — the Task pane disappeared before a completion record existed; the log is delivered as it stood;
  • invalid-completion-record — the record was there but unusable;
  • supervision-error — the extension could not supervise the task.

completed outcomes and command-exit failed outcomes carry an exit code; cancelled outcomes carry a signal name; a failed outcome with a failure category has neither.

Lifecycle

A Command task's lifecycle belongs to herdr, not to the parent runtime (ADR-0002):

  • Quitting or restarting Pi leaves running Command tasks running in their panes. Their outcomes are dropped; the Task log stays in the Task run directory.
  • /reload continues the same parent runtime: the running registry and its watchers are preserved, and outcomes keep arriving.
  • No other shutdown is a cancellation. Every shutdown reason except a reload stops watching and drops the outcome without cancelling anything.
  • A new parent process does not re-adopt, resume, or recover tasks. Use task_inventory (or herdr tab list) to see what a previous session left running.
  • A Command task started by a Subagent keeps it alive: the child's Completion evidence waits for the Task outcome, so the outcome reaches the session that asked for it. A cancelled child ends its own tasks as control flow, and a Task still outlives a child runtime that a cancellation or a parent exit ends, with the Task log left in the Task run directory.

Task run directory

Each Command task gets one private directory under the OS temporary directory, named by its run id (herdr-tasks/<run id>/). It holds the launcher, the Task log, the start record, the Task completion record, the command pid, the cancellation request, and an owner record naming the creating process.

The directory outlives the task, because the Task log is the delivered evidence. A bounded sweep keeps the storage from growing forever: every allocation sweeps the run root (at most 100 entries per pass) and deletes a run directory only when its owner process is gone and nothing has written to it for seven days. A directory whose owner is still alive, or that was written recently, is left alone; one whose owner record is unreadable is decided by age alone.

Platform limit

Command tasks are POSIX only in this version. Starting a task on Windows is refused with one message naming the limit, both in the tool result and once at session start when the session has a UI:

Command tasks are POSIX only and cannot start on Windows. Run the command with the built-in bash tool instead.

The limit exists because the Task launcher is a POSIX sh script run by path inside the pane. Windows support, including its test matrix, is out of scope for this version.

Development

Run the unit tests, lint, and typecheck locally:

npm test
npm run lint
npm run typecheck

The unit suite is node --test files named after the module they cover; no build step is involved. The end-to-end suite (test/integration/, run from the repo root as npm run test:integration:tasks) drives a real parent Pi session inside herdr and uses the same PI_TEST_* environment contract as the subagents suite, documented in packages/pi-herdr-subagents/README.md in the repository. It skips itself unless HERDR_ENV=1 and herdr is on PATH.

License

MIT