pi-background-tasks 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/PUBLISHING.md CHANGED
@@ -32,8 +32,8 @@ npm publish --access public
32
32
  Pi install smoke after publish:
33
33
 
34
34
  ```bash
35
- pi -e npm:pi-background-tasks@0.2.0 --offline --no-tools --no-session -p "/jobs"
36
- pi install npm:pi-background-tasks@0.2.0
35
+ pi -e npm:pi-background-tasks@0.4.0 --offline --no-tools --no-session -p "/jobs"
36
+ pi install npm:pi-background-tasks@0.4.0
37
37
  ```
38
38
 
39
39
  ## Publish to git
@@ -48,15 +48,15 @@ git commit -m "Release pi-background-tasks"
48
48
  git branch -M main
49
49
  git remote add origin git@github.com:ismailsaleekh/pi-background-tasks.git
50
50
  git push -u origin main
51
- git tag v0.2.0
52
- git push origin v0.2.0
51
+ git tag v0.4.0
52
+ git push origin v0.4.0
53
53
  ```
54
54
 
55
55
  Pi install smoke after git tag:
56
56
 
57
57
  ```bash
58
- pi -e git:github.com/ismailsaleekh/pi-background-tasks@v0.2.0 --offline --no-tools --no-session -p "/jobs"
59
- pi install git:github.com/ismailsaleekh/pi-background-tasks@v0.2.0
58
+ pi -e git:github.com/ismailsaleekh/pi-background-tasks@v0.4.0 --offline --no-tools --no-session -p "/jobs"
59
+ pi install git:github.com/ismailsaleekh/pi-background-tasks@v0.4.0
60
60
  ```
61
61
 
62
62
  ## pi.dev/packages
package/README.md CHANGED
@@ -2,35 +2,37 @@
2
2
 
3
3
  Claude-Code-like explicit background shell task manager for [Pi](https://pi.dev/).
4
4
 
5
- This package adds named, tracked background shell jobs with durable output files, bounded log reads, kill/timeout safety, task-owned context-window telemetry, a focused footer-dock task manager, `/tasks` fallback UI, and completion notifications that can wake the agent when LLM-launched work finishes.
5
+ This package adds named, tracked background shell jobs with durable output files, bounded log reads, kill/timeout safety, task-owned context-window/token/tool-use/model telemetry, explicit Pi-agent telemetry wrapping for tasks marked as agents, a focused footer-dock task manager, `/tasks` fallback UI, and completion notifications that can wake the agent when LLM-launched work finishes.
6
6
 
7
7
  ## Install
8
8
 
9
9
  From npm after publish:
10
10
 
11
11
  ```bash
12
- pi install npm:pi-background-tasks@0.2.0
12
+ pi install npm:pi-background-tasks@0.4.0
13
13
  ```
14
14
 
15
15
  From git after pushing this package to its standalone repository and tagging:
16
16
 
17
17
  ```bash
18
- pi install git:github.com/ismailsaleekh/pi-background-tasks@v0.2.0
18
+ pi install git:github.com/ismailsaleekh/pi-background-tasks@v0.4.0
19
19
  ```
20
20
 
21
21
  For project-local install:
22
22
 
23
23
  ```bash
24
- pi install -l npm:pi-background-tasks@0.2.0
24
+ pi install -l npm:pi-background-tasks@0.4.0
25
25
  ```
26
26
 
27
27
  ## Commands
28
28
 
29
- - `/bg [--name "Task name"] <command>` — start a named tracked background shell command.
29
+ - `/bg [--agent] [--name "Task name"] <command>` — start a named tracked background shell command. Use `--agent` only when the command launches an LLM/agent.
30
30
  - `/jobs` — list running and recent completed/failed/killed tasks.
31
31
  - `/logs <id> [maxBytes]` — show bounded tail output and full output path.
32
32
  - `/kill <id>` — stop a running task.
33
33
  - `/tasks` or `/bg-tasks` — fallback command to open the task manager UI.
34
+ - `/bg-clear` — clear finished background-task footer notices.
35
+ - `/bg-update` — print update instructions when a newer published version exists (instruct-only; never self-installs).
34
36
 
35
37
  ## Footer dock UX
36
38
 
@@ -38,18 +40,21 @@ When tasks are active or unseen completions/failures exist, Pi shows a compact f
38
40
 
39
41
  ```text
40
42
  bg 2 running · Shift↓
41
- bg 1 running · 1 failed · Shift↓
42
- bg 2 done · Shift↓
43
+ bg 1 running · 1 failed · Shift↓ · /bg-clear
44
+ bg 2 done · Shift↓ · /bg-clear
43
45
  ```
44
46
 
45
- Press `Shift+Down` to open the focused bottom dock. Arrow keys are captured only while the dock is focused. Each task row shows context-window usage reported by that specific background task, for example `ctx 21.0%/200k`; tasks that do not report their own context show `ctx —` rather than the parent Pi session's usage. Finished-task badges intentionally remain visible until acknowledged; press uppercase `C` (`Shift+C`) from the main UI to clear finished background-task notices without opening the dock.
47
+ Press `Shift+Down` to open the focused bottom dock. Arrow keys are captured only while the dock is focused. Each task row shows the latest context-window usage reported by that specific background task, for example `ctx 21.0%/200k`; tasks that do not report their own context show `ctx —` rather than the parent Pi session's usage. Background Pi-agent tasks also surface the LLM model they ran (`model gpt-5.5` in the compact row, fully-qualified such as `openai-codex/gpt-5.5` in the detail view), cumulative token usage (`tok 1.6k`), and tool-use counts (`tools 2/1 failed`) in the dock and detail view; missing model/token/tool telemetry is omitted in rows and shown as “not reported by this background task” in details. When a background command is explicitly marked as an agent and invokes a print/json child agent such as `pi -p ...` through the normal shell command name, the extension wraps that child Pi process with `--mode json`, parses real assistant usage/tool execution events, and emits task-owned telemetry automatically including the model reported by the child assistant turns.
48
+
49
+ Finished-task badges intentionally remain visible until acknowledged. The reliable clear path is `/bg-clear`, which works in every terminal and clears finished background-task footer notices without opening the dock. `Ctrl+Alt+C` is still registered as an optional terminal-dependent fallback shortcut, but the footer advertises `/bg-clear` because some macOS terminals do not transmit `Ctrl+Alt+C` distinctly.
46
50
 
47
51
  Dock controls:
48
52
 
49
53
  | Key | Action |
50
54
  |---|---|
51
55
  | `Shift+Down` | Open focused background-task dock |
52
- | `C` / `Shift+C` | Clear finished-task footer notices from the main UI |
56
+ | `/bg-clear` | Clear finished-task footer notices from the main UI |
57
+ | `Ctrl+Alt+C` | Optional terminal-dependent shortcut for `/bg-clear` |
53
58
  | `↑` / `↓` | Select task |
54
59
  | `PageUp` / `PageDown` | Page task list |
55
60
  | `Enter` / `→` | Inspect logs/details |
@@ -61,6 +66,19 @@ Dock controls:
61
66
  | `R` | Rerun selected command |
62
67
  | `c` | Show copyable output path |
63
68
  | `x` / `Esc` / `q` | Close dock |
69
+ | `/bg-update` | Print update instructions when a newer version is published |
70
+
71
+ ### Update-available notice
72
+
73
+ When a newer version of `pi-background-tasks` has been published to npm, the footer appends a compact, instruct-only segment after the entry hint:
74
+
75
+ ```text
76
+ bg 1 running · 1 failed · Shift↓ · /bg-clear · ⬆ v0.5.0 /bg-update
77
+ ```
78
+
79
+ When no tasks are active, the notice still appears on its own (`bg ⬆ v0.5.0 /bg-update`) so the update hint is visible. The segment is rendered only when a strictly newer published version exists; `/bg-update` prints the npm and git update commands and never installs or self-updates.
80
+
81
+ The lookup runs at most once per session on `session_start`, is time-boxed, and is fully offline-safe: it never blocks or errors the footer/session, and on an offline or failed lookup it simply renders no segment (it never pins a misleading version). The check is skipped entirely when `PI_OFFLINE=1`, and can be disabled explicitly with `PI_BG_DISABLE_UPDATE_CHECK=1`. Set `PI_BG_REGISTRY_URL` to point the check at a registry mirror instead of `https://registry.npmjs.org`.
64
82
 
65
83
  ## LLM tools
66
84
 
@@ -69,7 +87,7 @@ Dock controls:
69
87
  - `bg_logs` — read bounded task output.
70
88
  - `bg_kill` — stop a running task.
71
89
 
72
- `bg_run` requires a concise `name` for the footer dock, plus the shell `command`. It defaults to `triggerOnCompletion: true`, so completion notifications trigger a follow-up agent turn. User-launched `/bg` jobs and UI reruns are display-only by default.
90
+ `bg_run` requires a concise `name` for the footer dock, the shell `command`, and required `isAgent: boolean`. Set `isAgent: true` only when the background task launches an LLM/agent process (for example `pi -p ...` or `pi --mode json ...`); set `isAgent: false` for scripts, tests, dev servers, sleeps, and ordinary shell commands. It defaults to `triggerOnCompletion: true`, so completion notifications trigger a follow-up agent turn. Tasks marked with `isAgent: true` that launch print/json child Pi agents through the normal shell command name are telemetry-wrapped; set `PI_BG_DISABLE_PI_TELEMETRY=1` only when raw Pi stdout is required. The task snapshot and metadata expose `isAgent`, `contextUsage` (latest reported child assistant turn), cumulative `tokenUsage` (`input`, `output`, `cacheRead`, `cacheWrite`, `totalTokens`), cumulative `toolUsage` (`total`, `failed`, `byName`), and `model` (the LLM identifier reported by the child assistant turns, preferring the fully-qualified `provider/model` form) when reported by the child task. User-launched `/bg` jobs are display-only by default unless `--agent` is provided; UI reruns preserve the original task's `isAgent` value.
73
91
 
74
92
  ## Runtime files
75
93
 
@@ -112,9 +130,9 @@ Full interactive QA gate:
112
130
  npm run test:full
113
131
  ```
114
132
 
115
- The suite includes typecheck, unit, SDK, RPC, component, package, and PTY/TUI coverage for the focused dock and `Shift+Down` shortcut.
133
+ The suite includes typecheck, unit, SDK, RPC, component, package, PTY/TUI, and scripted-provider coverage for the focused dock, lifecycle safety, and completion follow-up behavior.
116
134
 
117
- Note: the repo QA standard now requires exhaustive coverage of every public behavior and plausible edge case. This package passes the current baseline gates, but `TEST_PLAN.md` tracks remaining exhaustive-coverage work for restart/rerun, all dock keys, command/tool edge cases, lifecycle safety paths, notification follow-up, footer badges, package distribution edge cases, and cross-platform mocks.
135
+ Note: the repo QA standard requires exhaustive coverage of every public behavior and plausible edge case. `TEST_PLAN.md` tracks the current coverage matrix and any future edge-case additions.
118
136
 
119
137
  This package follows the repo-wide Pi extension QA standard documented in:
120
138
 
package/TESTING.md CHANGED
@@ -35,6 +35,7 @@ This runs the default gate plus:
35
35
 
36
36
  ```bash
37
37
  npm run test:pty
38
+ npm run test:agent-loop
38
39
  ```
39
40
 
40
41
  Smoke/release checks:
@@ -69,19 +70,32 @@ Tests must not use the user's real `~/.pi/agent`.
69
70
 
70
71
  Implemented coverage includes:
71
72
 
72
- - tools: `bg_run`, `bg_status`, `bg_logs`, `bg_kill`, including unknown/ambiguous IDs, completed-kill failure, legacy no-name preparation, head/tail truncation, and notification on/off behavior
73
- - commands: `/bg`, `/jobs`, `/logs`, `/kill`, `/tasks`, `/bg-tasks` discovery, happy paths, malformed `/bg`, unknown/ambiguous IDs, completed-task `/kill`, byte-limit normalization, and RPC no-hang fallback behavior
74
- - shortcut/UI: component coverage for focused dock list/detail/key handling, empty/history/unread states, paging, close aliases, stop/stop-all/rerun/path actions, missing output files; SDK coverage for explicit `Shift+C` finished-notice clearing; and PTY coverage for `/tasks`, real `Shift+Down`, detail/back/history/stop/close
75
- - runtime files: output and metadata files under `.pi/tasks/`, task-owned context-window telemetry snapshots, metadata after completion/failure, local tarball install contents
76
- - safety: kill, already-finished kill failure, timeout failure, spawn failure, low output-cap failure, multi-task shutdown cleanup
73
+ - tools: `bg_run`, `bg_status`, `bg_logs`, `bg_kill`, including required `isAgent` schema/runtime validation, unknown/ambiguous IDs, completed-kill failure, legacy no-name preparation, head/tail truncation, and notification on/off behavior
74
+ - commands: `/bg`, `/jobs`, `/logs`, `/kill`, `/tasks`, `/bg-tasks`, `/bg-clear`, `/bg-update` discovery, happy paths, `/bg --agent` parsing, finished-notice clearing, malformed `/bg`, unknown/ambiguous IDs, completed-task `/kill`, byte-limit normalization, and RPC no-hang fallback behavior
75
+ - update-available notice: semver parse/compare/precedence, `formatUpdateSegment`, npm/`package.json` payload narrowing, and injected-fetch success/404/throw/timeout (unit); localhost-registry footer segment (idle + appended to an active footer), `/bg-update` non-installing instructions, and opt-out/offline/already-current/registry-failure no-segment-and-no-throw paths (SDK); `/bg-update` discovery and offline instructions (RPC). The check is one-shot on `session_start`, time-boxed, offline-safe, gated by `PI_OFFLINE`/`PI_BG_DISABLE_UPDATE_CHECK`, and `PI_BG_REGISTRY_URL` overrides the registry endpoint
76
+ - shortcut/UI: component coverage for focused dock list/detail/key handling, empty/history/unread states, paging, close aliases, stop/stop-all/rerun/path actions, missing output files; SDK coverage for explicit `/bg-clear` finished-notice clearing, `/bg-clear` footer hinting, optional `Ctrl+Alt+C` fallback shortcut registration, and mixed failed/stopped/done/focused footer status; RPC coverage that `/bg-clear` works as a terminal-independent clear path; and PTY coverage for `/tasks`, `/bg-tasks`, real `Shift+Down`, arrows, page keys, detail/back/history/stop/stop-all/rerun/path/close, failed unread badges, and running/completed/failed/killed rerun paths
77
+ - runtime files: output and metadata files under `.pi/tasks/`, persisted `isAgent` classification, task-owned context-window telemetry snapshots, cumulative background Pi-agent token usage, tool-use counts, agent model identifier (preferring the fully-qualified `provider/model` form), explicit `isAgent:true` telemetry wrapping for background `pi` agents, `isAgent:false` non-wrapping for scripts, real child `pi --mode json` tool-event parsing, split/large telemetry ingestion, metadata after completion/failure, local tarball install contents
78
+ - safety: kill, already-finished kill failure, timeout failure, spawn failure, low output-cap failure, multi-task shutdown cleanup, process-group kill fallback, Windows child-kill behavior, SIGKILL escalation, duplicate finalization/notification races, metadata/notification failure handling, and pruning
79
+ - agent loop: deterministic scripted-provider coverage for actual `bg_run` completion follow-up turns, `/bg` display-only behavior, `notifyOnCompletion:false`, and failed-task notification error fields
77
80
  - package: manifest, docs, `pi.extensions`, peer dependency/import parity, packed runtime files, tarball-install smoke, and artifact exclusion
78
81
 
79
82
  ## PTY notes
80
83
 
81
84
  `test:pty` uses `/usr/bin/expect` to drive a real pseudo-terminal. It verifies:
82
85
 
83
- - `/tasks` opens the focused dock and closes with `x`.
86
+ - `/tasks` and `/bg-tasks` open the focused dock and close with `x`.
84
87
  - A named `/bg` task appears in the dock when opened with xterm `Shift+Down` (`ESC [ 1 ; 2 B`).
88
+ - Secondary dock keys work in a real TUI: arrows, page keys, detail/back, history, stop selected, stop-all confirmation, rerun, output path, and failed/unread history surfacing.
89
+
90
+ The detail-view `Model:` line and the compact `model <id>` dock row are also exercised deterministically by the component layer (`tests/component/background-tasks-manager.test.ts`), which is the lowest reliable layer for dock rendering.
91
+
92
+ ### Terminal keyboard-protocol negotiation
93
+
94
+ `pi` enables the Kitty keyboard protocol at startup by emitting `ESC[>7u ESC[?u ESC[c` and briefly intercepts stdin until that negotiation completes. The expect harness therefore must not key on a bare `>` (which matches the `ESC[>7u` push instantly and fires input before pi is listening); instead it waits for the steady-state status marker `(auto)`, answers the keyboard-protocol query (`ESC[?0u`, i.e. legacy keyboard) and the device-attributes query (`ESC[?1;2c`), and settles briefly before sending keys. This makes legacy keystrokes reach pi deterministically rather than racing the 150 ms negotiation fallback.
95
+
96
+ ### Interactive-stdin capability probe
97
+
98
+ `test:pty` begins with a one-shot probe (`ptyInputSupported()`) that spawns a minimal raw-mode Node stdin reader under the same `/usr/bin/expect` driver and checks that a sent byte is received. Some hosts cannot deliver stdin to a raw-mode Node TUI through expect (a plain `cat` receives input but Node `process.stdin` does not). On such hosts every PTY case is skipped with a loud reason instead of failing; where stdin is deliverable the full interactive dock scenarios run for real. The deterministic SDK/RPC/component layers remain the authoritative gates in `npm run test` either way.
85
99
 
86
100
  ## Artifact policy
87
101
 
@@ -100,4 +114,4 @@ Normalize volatile values before snapshotting: task IDs, session IDs, PIDs, time
100
114
 
101
115
  ## Remaining full exhaustive coverage work
102
116
 
103
- The package now has expanded edge-case coverage across the default and full gates. Remaining hardening items tracked in [`TEST_PLAN.md`](TEST_PLAN.md) are narrower: deeper registry extraction/race unit tests, scripted-provider validation of actual follow-up agent turns, exhaustive real-PTY coverage for every secondary dock key (`a`/`K`, `R`, `c`, page keys), process-tree kill fallback mocking, pruning, and Windows-specific shell/path/kill mocks.
117
+ The Lane A residual hardening items and the explicit `isAgent` agent-vs-script classification are now covered by default unit/SDK gates plus full PTY and scripted-provider gates. `TEST_PLAN.md` remains the source of truth for future edge-case additions, especially any new telemetry surfaces added after this baseline.
package/TEST_PLAN.md CHANGED
@@ -12,9 +12,9 @@ This package follows:
12
12
  |---|---|
13
13
  | Package | `pi-background-tasks` |
14
14
  | Extension entrypoint | `extensions/background-tasks.ts` |
15
- | Public commands | `/bg`, `/jobs`, `/logs`, `/kill`, `/tasks`, `/bg-tasks` |
15
+ | Public commands | `/bg`, `/jobs`, `/logs`, `/kill`, `/tasks`, `/bg-tasks`, `/bg-clear`, `/bg-update` |
16
16
  | Public tools | `bg_run`, `bg_status`, `bg_logs`, `bg_kill` |
17
- | Shortcuts | `Shift+Down`, `Shift+C` |
17
+ | Shortcuts | `Shift+Down`; optional fallback `Ctrl+Alt+C` |
18
18
  | Custom UI | footer status + focused bottom dock overlay |
19
19
  | Custom provider | no |
20
20
  | Runtime files/state | `.pi/tasks/<session-id>-<pid>/<task-id>.output`, `.pi/tasks/<session-id>-<pid>/<task-id>.json` |
@@ -29,7 +29,8 @@ This package follows:
29
29
  | RPC | `npm run test:rpc` | yes | implemented |
30
30
  | Component | `npm run test:component` | yes | implemented |
31
31
  | Package | `npm run test:package` | yes | implemented |
32
- | PTY/TUI | `npm run test:pty` | full gate | implemented |
32
+ | PTY/TUI | `npm run test:pty` | full gate | implemented (answers pi's Kitty keyboard-protocol negotiation; auto-skips with a loud reason on hosts that cannot deliver raw-mode Node stdin via `/usr/bin/expect`) |
33
+ | Scripted provider | `npm run test:agent-loop` | full gate | implemented |
33
34
  | Pack dry run | `npm run pack:dry-run` | release gate | implemented |
34
35
  | Smoke | `npm run smoke` | no | implemented; load-only |
35
36
 
@@ -37,55 +38,62 @@ This package follows:
37
38
 
38
39
  | Feature | Public surface | Unit | SDK | RPC | Component | PTY | Package | Scripted provider | Notes |
39
40
  |---|---|---:|---:|---:|---:|---:|---:|---:|---|
40
- | Start background command from UI command | `/bg` | yes | | yes | | yes | | | Unit covers `--name`; RPC/PTY start real processes. |
41
+ | Start background command from UI command | `/bg` | yes | | yes | | yes | | | Unit covers `--name` and `--agent`; RPC/PTY start real processes. |
41
42
  | List tasks | `/jobs` | | | yes | | | | | RPC asserts running and killed task rows. |
42
43
  | Show bounded logs | `/logs <id> [maxBytes]` | yes | | yes | | | | | Unit covers bounded reads; RPC verifies output/path. |
43
44
  | Kill running task | `/kill <id>` | | yes | yes | | | | | SDK tool and RPC slash command. |
44
- | Open task manager fallback | `/tasks`, `/bg-tasks` | | | discovery | yes | yes | | | Component covers dock; PTY covers `/tasks`. |
45
- | Start background command from LLM tool | `bg_run` | yes | yes | | | | | optional | SDK starts named commands. |
45
+ | Open task manager fallback | `/tasks`, `/bg-tasks` | | | discovery | yes | yes | | | Component covers dock; PTY covers `/tasks` and `/bg-tasks`. |
46
+ | Start background command from LLM tool | `bg_run` | yes | yes | | | | | yes | SDK starts named commands, verifies required `isAgent` schema/runtime behavior, and scripted provider verifies agent-loop tool calls with `isAgent:false` for scripts. |
46
47
  | Inspect task status | `bg_status` | | yes | | | | | | SDK polls exact IDs and validates shutdown state. |
47
48
  | Read task logs | `bg_logs` | yes | yes | | | | | | SDK verifies content. |
48
49
  | Stop task from LLM tool | `bg_kill` | | yes | | | | | | Covers running kill and already-finished loud failure. |
49
- | Completion notification | custom message `background-task-notification` | | manual/runtime | | renderer via typecheck | | | optional | Live runtime smoke previously verified; scripted-provider follow-up remains optional hardening. |
50
- | Footer status | `ctx.ui.setStatus` | | load path + clear shortcut | | render semantics | yes | | | SDK verifies `C clear` persistence/clear; PTY verifies Shift+Down dock path after footer-visible task. |
51
- | Per-task context usage | task row/detail + metadata | | yes | | yes | | | | SDK verifies task-owned telemetry is captured and parent `ctx.getContextUsage()` is not used; component verifies list/detail rendering plus `ctx —` placeholder. |
52
- | Focused dock list | overlay component | | | | yes | yes | | | Selection/actions/history tested. |
50
+ | Completion notification | custom message `background-task-notification` | yes | yes | | renderer via typecheck | | | yes | Unit covers duplicate/failing notification paths; SDK verifies XML/details; scripted provider verifies real follow-up turns, display-only `/bg`, `notifyOnCompletion:false`, and failed-task error fields. |
51
+ | Footer status | `ctx.ui.setStatus` | | load path + clear command/shortcut + mixed states/focused label | | render semantics | yes | | | SDK verifies `/bg-clear` hint, failed/stopped/done combinations, running combinations, and focused label; PTY verifies Shift+Down dock path after footer-visible task. |
52
+ | Explicit agent classification | required `bg_run.isAgent`, `/bg --agent`, task metadata | yes | yes | | | | | yes | `isAgent:true` is required only for LLM/agent tasks and enables Pi-agent telemetry wrapping when the command invokes plain `pi`; `isAgent:false` is required for scripts/non-agents and prevents wrapping even if the command text looks like `pi -p ...`. |
53
+ | Per-task context usage | task row/detail + `bg_status`/metadata/notification snapshots | yes | yes | | yes | | | | SDK verifies task-owned telemetry is captured, explicitly marked background `pi` invocations are wrapped to emit telemetry, and parent `ctx.getContextUsage()` is not used; component verifies list/detail rendering plus `ctx —` placeholder. |
54
+ | Per-task token usage | background Pi-agent telemetry + `bg_status`/metadata/dock row/detail | yes | yes | | yes | | | | SDK verifies cumulative input/output/cache read/cache write/total token usage from explicit telemetry, fake `isAgent:true` wrapped child events, and real child `pi --mode json` with scripted provider; component verifies row/detail rendering. |
55
+ | Per-task tool-use counts | background Pi-agent telemetry + `bg_status`/metadata/dock row/detail | yes | yes | | yes | | | | SDK verifies total/failed/by-name tool counts from fake and real child Pi `tool_execution_start/end` events, including failed tools; component verifies row/detail rendering. |
56
+ | Per-task agent model | background Pi-agent telemetry + `bg_status`/metadata/dock row/detail | yes | yes | | yes | | | | Unit verifies `formatModelSummary`/snapshot-list rendering and telemetry ingestion of `model`; SDK verifies the model is captured from explicit telemetry, fake `isAgent:true` wrapped child `message_end` events (qualified `provider/model`), and a real child `pi --mode json` run (bare child model re-qualified from `--model`), plus that non-agent tasks report no model; component verifies compact `model <id>` row, fully-qualified `Model:` detail, and the “not reported by this background task” placeholder. |
57
+ | Focused dock list | overlay component | | | | yes | yes | | | Selection/actions/history tested; PTY covers arrows, page keys, ordering with multiple tasks, failed/unread badges, and `/bg-tasks` fallback. |
53
58
  | Focused dock detail | overlay component | | | | yes | | | | Tail read, output box, return-to-list tested. |
54
59
  | Dock stop selected | `k` | | | | yes | | | | Component. |
55
- | Dock stop all | `a`/`K` | | | | yes | | | | Component confirmation. |
56
- | Dock rerun | `R` | | | | yes | | | | Component. |
60
+ | Dock stop all | `a`/`K` | | | | yes | yes | | | Component and PTY confirmation. |
61
+ | Dock rerun | `R` | | | | yes | yes | | | Component plus PTY running/completed/failed/killed rerun paths. |
57
62
  | Dock close | `x`/`Esc`/`q` | | | | yes | yes | | | Component + PTY. |
58
63
  | Shortcut opens dock | `Shift+Down` | | registration | | | yes | | | PTY sends xterm `ESC [ 1 ; 2 B`. |
59
- | Shortcut clears finished notices | `Shift+C` / `C` | | yes | | | | | | SDK invokes registered shortcut and asserts finished notices remain until explicit clear. |
64
+ | Clear finished notices | `/bg-clear`, optional `Ctrl+Alt+C` fallback | | yes | yes | | | | | `/bg-clear` is the canonical terminal-independent path and is advertised in the footer. SDK invokes the slash-command handler and verifies fallback shortcut registration; RPC verifies `/bg-clear` clears finished notices; finished notices remain until explicit clear. |
65
+ | Update-available footer notice | `⬆ v<latest> /bg-update` footer segment + `/bg-update` command | yes | yes | yes | | | | | Unit covers semver parse/compare/precedence, `isNewerVersion`, `formatUpdateSegment`, npm/`package.json` payload narrowing, injected-fetch success/404/throw/timeout, and `package.json` read/degrade. SDK uses a localhost registry to verify the idle and append-to-active footer segment, `/bg-update` non-installing instructions, and that opt-out (`PI_BG_DISABLE_UPDATE_CHECK=1`), offline (`PI_OFFLINE=1`), already-current, and registry-failure paths render no segment and never throw. RPC verifies `/bg-update` discovery and offline non-installing instructions. The check is one-shot per `session_start`, time-boxed, offline-safe, and never runs on the status tick. |
60
66
  | Runtime output files | `.pi/tasks/...output` | yes | yes | | | | | | SDK asserts existence. |
61
- | Runtime metadata files | `.pi/tasks/...json` | | yes | | | | | | SDK asserts shape/status/name/context usage. |
67
+ | Runtime metadata files | `.pi/tasks/...json` | yes | yes | | | | | | SDK asserts shape/status/name/context usage; registry unit tests cover metadata failure/update ordering. |
62
68
  | Timeout kills task | `timeoutSeconds` | | yes | | | | | | SDK. |
63
69
  | Output cap kills task | `PI_BG_MAX_OUTPUT_BYTES` | | | yes | | | | | RPC runs with a low cap and asserts failed status/log notice. |
64
- | Shutdown cleanup | `session_shutdown` | | yes | | | | | | SDK asserts multiple running tasks become killed. |
70
+ | Shutdown cleanup | `session_shutdown` | yes | yes | | | | | | SDK asserts multiple running tasks become killed; registry tests cover shared stop/wait behavior. |
71
+ | Process lifecycle/races | registry core | yes | yes | yes | | yes | | yes | Unit tests cover process-group fallback, Windows fallback, SIGKILL escalation, duplicate finalization/notification races, notification/metadata failures, pruning, malformed telemetry, split telemetry chunks, and large telemetry records above the old 16KiB buffer; SDK/RPC cover runtime spawn/timeout/output-cap/shutdown; scripted provider covers wakeup integration. |
65
72
  | Package manifest | `package.json` | | | | | | yes | | Keywords, `pi.extensions`, files. |
66
73
  | Pack contents | `npm pack --dry-run` | | | | | | yes | | Runtime files included. |
67
74
 
68
- ## Remaining hardening coverage
75
+ ## Residual hardening coverage
69
76
 
70
- The expanded suite now covers the major public command/tool/UI/package edge cases. The rows below are the residual hardening items that still require deeper extraction, mocks, or scripted-provider infrastructure before the package can be called exhaustively complete under the strictest interpretation of the repo QA standard.
77
+ Lane A residual hardening is now covered by automated tests. No remaining hardening-only gaps are intentionally left open in this plan. Future feature work should add new rows instead of weakening these gates.
71
78
 
72
- | Gap | Owner | Date | Reason | Planned fix |
73
- |---|---|---|---|---|
74
- | Process registry still mostly lives in `src/extension.ts` | package maintainer | 2026-05-27 | UI was extracted; deeper registry extraction remains | Move process lifecycle into `src/core/registry.ts` and unit-test state transitions/races directly. |
75
- | Restart/rerun not exhaustively tested in live PTY | package maintainer | 2026-05-27 | Component covers `R` from list/detail; PTY currently covers detail/back/history/stop/close but not real rerun | Add PTY cases for `R` from completed/killed/failed tasks, inherited fields, new ID, and display-only notification defaults. |
76
- | Dock key map not exhaustively covered in PTY | package maintainer | 2026-05-27 | Component covers full key map; PTY covers `/tasks`, `Shift+Down`, `Enter`, `←`, `h`, `k`, `r`, `x` | Add PTY cases for `↑/↓`, page keys, `a`/`K`, `R`, `c`, failed/unseen/done badges, ordering, and multiple running tasks. |
77
- | Process lifecycle/safety edge cases incomplete | package maintainer | 2026-05-27 | Timeout/shutdown/kill/spawn-failure/output-cap covered; lower-level races need extraction/mocks | Add tests for process-tree fallback where mockable, duplicate finalization prevention, duplicate notification prevention under races, metadata-after-notification ordering under write failures, and pruning old tasks. |
78
- | Completion follow-up turn not deterministic | package maintainer | 2026-05-27 | SDK now verifies custom message XML/details and `notifyOnCompletion:false`; live runtime smoke verified wakeups | Add scripted-provider tests for `/bg` display-only default, `bg_run` wakeup default, failed notification error fields, and actual follow-up trigger behavior. |
79
- | Footer/status behavior could be deeper | package maintainer | 2026-05-27 | SDK covers explicit clear and running/done persistence; component covers seen-state behavior and PTY observes dock path; full status protocol assertions are still thin | Add RPC/SDK assertions for failed/stopped count combinations and focused label. |
80
- | Cross-platform behavior not covered | package maintainer | 2026-05-27 | Current tests run on local POSIX/macOS | Add unit/mocked coverage for Windows shell invocation, path separator handling, and kill fallback semantics. |
79
+ | Hardened area | Coverage |
80
+ |---|---|
81
+ | Extracted process registry | `src/core/registry.ts` has direct unit coverage for state transitions and injected spawn/kill/platform behavior. |
82
+ | Agent/script classification | Unit tests cover `isAgent:true` wrapping, `isAgent:false` non-wrapping, `PI_BG_DISABLE_PI_TELEMETRY`, and non-interceptable path-qualified `pi`; SDK verifies required tool schema/runtime validation and real marked Pi telemetry. |
83
+ | Process lifecycle/races | Unit tests cover duplicate error/close finalization, output-cap races, duplicate-notification prevention, waiter resolution via stop paths, metadata failure logging, and notification failure reset. |
84
+ | Process-tree kill safety | Unit tests cover POSIX process-group kill, child fallback, both-fail loud errors, SIGTERM idempotency, SIGKILL escalation, and Windows child-kill/shell invocation. |
85
+ | Pruning | Unit tests cover oldest-finished pruning while preserving running tasks. |
86
+ | Completion follow-up turns | `test:agent-loop` registers a deterministic scripted provider and verifies `bg_run` wakeup default, `/bg` display-only default, `notifyOnCompletion:false`, failed notification error fields, and real follow-up provider calls. |
87
+ | PTY secondary keys | `test:pty` covers arrows, page keys, `a`/`K`, `R`, `c`, `/bg-tasks`, failed/unread badges, multiple-task ordering, and rerun paths for running/completed/failed/killed tasks. |
88
+ | Footer/status combinations | SDK tests cover failed/stopped/done/running combinations, explicit clear, and focused label. |
81
89
 
82
90
  ## Acceptance checklist
83
91
 
84
92
  - [x] `npm run test` passes offline in isolated temp dirs.
85
93
  - [x] `npm run test:full` validates baseline real TUI/PTY behavior.
86
94
  - [x] `npm run pack:dry-run` passes.
87
- - [ ] README claims and all plausible edge cases are exhaustively mapped in this test plan.
88
- - [ ] Every listed edge case has automated coverage at the lowest reliable layer.
95
+ - [x] README claims and all plausible edge cases are exhaustively mapped in this test plan.
96
+ - [x] Every listed edge case has automated coverage at the lowest reliable layer.
89
97
  - [x] No real LLM/API/network dependency in default tests.
90
98
  - [x] No dependency on user/global `~/.pi/agent` for SDK/RPC/PTY tests.
91
99
  - [x] Volatile output is normalized in snapshot-style assertions where applicable.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-background-tasks",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "Claude-Code-like named background shell task manager for Pi: bg_run tools, /bg commands, Shift+Down footer dock, bounded logs, kill/timeout safety, and completion wakeups.",
5
5
  "type": "module",
6
6
  "license": "ISC",
@@ -36,14 +36,16 @@
36
36
  ],
37
37
  "scripts": {
38
38
  "typecheck": "tsc --noEmit",
39
+ "test:type-safety": "tsx --test tests/package/type-safety.test.ts",
39
40
  "test:unit": "tsx --test tests/unit/**/*.test.ts",
40
41
  "test:sdk": "tsx --test tests/sdk/**/*.test.ts",
41
42
  "test:rpc": "tsx --test tests/rpc/**/*.test.ts",
42
43
  "test:component": "tsx --test tests/component/**/*.test.ts",
43
44
  "test:package": "tsx --test tests/package/**/*.test.ts",
44
- "test": "npm run typecheck && npm run test:unit && npm run test:sdk && npm run test:rpc && npm run test:component && npm run test:package",
45
+ "test": "npm run typecheck && npm run test:type-safety && npm run test:unit && npm run test:sdk && npm run test:rpc && npm run test:component && npm run test:package",
45
46
  "test:pty": "tsx --test tests/pty/**/*.test.ts",
46
- "test:full": "npm run test && npm run test:pty",
47
+ "test:agent-loop": "tsx --test tests/scripted-provider/**/*.test.ts",
48
+ "test:full": "npm run test && npm run test:pty && npm run test:agent-loop",
47
49
  "smoke": "pi --no-extensions -e ./extensions/background-tasks.ts --offline --no-tools --no-session -p \"/jobs\"",
48
50
  "pack:dry-run": "npm pack --dry-run"
49
51
  },
@@ -58,6 +60,7 @@
58
60
  "typebox": "*"
59
61
  },
60
62
  "devDependencies": {
63
+ "@earendil-works/pi-ai": "^0.75.5",
61
64
  "@earendil-works/pi-coding-agent": "^0.75.5",
62
65
  "@earendil-works/pi-tui": "^0.75.5",
63
66
  "@types/node": "^24.0.0",