@sgtbeatdown/pi-tasks 0.1.0 → 0.1.1

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/README.md CHANGED
@@ -1,502 +1,89 @@
1
1
  # pi-tasks
2
2
 
3
- Structured task communication for Pi agents.
3
+ `pi-tasks` is a Pi extension client for the Wolfpack task gateway. Wolfpack owns task state in its machine-global `~/.wolfpack/tasks` store; this package does not create task files or write assignments to terminals. Read Wolfpack's [task gateway guide](https://github.com/almogdepaz/wolfpack/blob/main/docs/task-gateway.md) for the canonical route and operational contract.
4
4
 
5
- `pi-tasks` lets one Pi session hand work to another agent, session, process, or
6
- worker and get durable structured results back. The core model is transport- and
7
- runner-neutral: local sessions, HTTP workers, queues, hosted control planes, and
8
- terminal multiplexers can all implement the same task lifecycle.
5
+ ## requirements and trust boundary
9
6
 
10
- ## what this is
7
+ - a reachable local Wolfpack v1 task gateway on every participating machine;
8
+ - this package loaded in every participating Pi process;
9
+ - `WOLFPACK_SESSION_NAME` set by Wolfpack so the local gateway can resolve the caller to a stable broker ID; and
10
+ - `WOLFPACK_PORT` when the local control port is not the default `18790`.
11
11
 
12
- A task lifecycle and communication layer:
12
+ The boundary is trusted local processes and trusted Tailnet machines. Pi only calls its own local gateway. The gateways perform direct fetch federation; Pi never fetches a peer directly. v1 adds no task capability authentication. Normal Wolfpack global JWT behavior is not bypassed, and JWT federation is unsupported: peer delivery fails clearly when credentials would be required.
13
13
 
14
- 1. create a structured assignment
15
- 2. persist task state in a store
16
- 3. dispatch the assignment through a transport
17
- 4. let the sender keep working
18
- 5. record status/results in structured files/data, not terminal prose
19
- 6. require the assignee to finish through the task protocol
14
+ ## task address and send
20
15
 
21
- ## what this is not
22
-
23
- This is **not** a subagent spawner. Use any process manager, terminal/session
24
- manager, HTTP worker pool, queue, cron job, or custom runner to create/host
25
- agents. `pi-tasks` only gives those agents a shared task protocol.
26
-
27
- ## mental model
28
-
29
- ```text
30
- parent pi session
31
- agent_task_send
32
- ↓
33
- TaskStore creates task + durable refs
34
- TaskTransport delivers assignment text to target
35
- ↓
36
- target runner/session/worker
37
- receives pi.task.assignment.v1
38
- does work
39
- completes task through agent_task_done or equivalent store/server completion API
40
- ↓
41
- parent pi session
42
- agent_task_status / agent_task_wait / agent_task_inbox
43
- ```
44
-
45
- The `to` field is transport-specific:
46
-
47
- - session name
48
- - worker id
49
- - queue/topic name
50
- - tmux pane
51
- - process id
52
- - service-specific address
53
-
54
- ## requirements for any runner
55
-
56
- For task communication to work, you need exactly these pieces:
57
-
58
- 1. **running target** — an already-open Pi session, worker, process, or service.
59
- `pi-tasks` does not open or close it.
60
- 2. **transport** — code that delivers the assignment text to that target. This
61
- can be `tmux paste-buffer`, HTTP POST, queue publish, file write, ssh, etc.
62
- 3. **reachable task store** — parent and target must read/write the same task
63
- state. With `createFilesystemTaskStore`, that means the same cwd and shared
64
- `.pi/tasks` directory. For multi-host setups without shared disk, implement a
65
- remote `TaskStore`.
66
- 4. **completion capability** — Pi targets need this extension loaded so they have
67
- `agent_task_done`. Non-Pi workers need an equivalent completion API/store
68
- write.
69
- 5. **preserved task id** — the target must complete the exact `taskId` from the
70
- `pi.task.assignment.v1` assignment.
71
-
72
- If those are true, session lifecycle is irrelevant. Open agents with tmux,
73
- screen, ssh, a process manager, or manually; `pi-tasks` only handles the task
74
- protocol once the agents exist.
75
-
76
- ## install
77
-
78
- Install locally into Pi:
79
-
80
- ```bash
81
- pi install npm:@sgtbeatdown/pi-tasks
82
- ```
83
-
84
- Temporary one-off run:
85
-
86
- ```bash
87
- pi -e npm:@sgtbeatdown/pi-tasks
88
- ```
89
-
90
- Every participating Pi session must load this extension. If a target Pi session
91
- does not have `agent_task_done`, the sender can still create/dispatch the task,
92
- but it will remain non-terminal until timeout or cancellation.
93
-
94
- ## quick start: local/custom transport
95
-
96
- Most integrations reuse the filesystem store and provide only a transport:
97
-
98
- ```ts
99
- import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
100
- import { registerAgentTaskTools } from "@sgtbeatdown/pi-tasks/src/extension";
101
- import { createFilesystemTaskStore } from "@sgtbeatdown/pi-tasks/src/stores/filesystem";
102
- import type { TaskTransport } from "@sgtbeatdown/pi-tasks/src/task-communication";
103
-
104
- function createCliTransport(pi: ExtensionAPI): TaskTransport {
105
- return {
106
- name: "local-cli",
107
- getCurrentSessionName(env) {
108
- return env.PI_TASK_SESSION ?? env.USER ?? "unknown-session";
109
- },
110
- async dispatchTask({ target, assignment, signal }) {
111
- const result = await pi.exec("my-session-send", [target, assignment], { signal });
112
- if (result.code === 0) return { ok: true };
113
- return {
114
- ok: false,
115
- message: result.stderr || result.stdout || "my-session-send failed",
116
- retryable: true,
117
- };
118
- },
119
- };
120
- }
121
-
122
- export default function extension(pi: ExtensionAPI): void {
123
- registerAgentTaskTools(pi, {
124
- store: createFilesystemTaskStore({ tasksDir: ".pi/tasks" }),
125
- transport: createCliTransport(pi),
126
- });
127
- }
128
- ```
129
-
130
- Then call `agent_task_send` from the parent session:
16
+ A target is always `{ machine, sessionId }`, where `sessionId` is the stable opaque broker ID returned by Wolfpack session control. Use `machine: "local"` for same-machine work. For a peer, use the receiver's canonical HTTPS Tailnet origin, for example `https://worker.example.ts.net`; do not supply a hostname label, path, query, fragment, credentials, unexpected port, or arbitrary HTTPS URL.
131
17
 
132
18
  ```json
133
19
  {
134
- "to": "worker-a",
135
- "task": "inspect the auth middleware and report risks",
136
- "timeoutMs": 1800000
137
- }
138
- ```
139
-
140
- The parent should keep working and later use `agent_task_status`,
141
- `agent_task_wait`, or `agent_task_inbox`. Do **not** infer completion from
142
- terminal output.
143
-
144
- ## tmux recipe: already-open pi agents
145
-
146
- Use this when you manually open Pi agents in tmux panes and only need task
147
- communication between them.
148
-
149
- ### 1. create a tmux transport extension
150
-
151
- Create `.pi/extensions/pi-tasks-tmux.ts` in the project:
152
-
153
- ```ts
154
- import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
155
- import { registerAgentTaskTools } from "@sgtbeatdown/pi-tasks/src/extension";
156
- import { createFilesystemTaskStore } from "@sgtbeatdown/pi-tasks/src/stores/filesystem";
157
- import type { TaskTransport } from "@sgtbeatdown/pi-tasks/src/task-communication";
158
-
159
- function createTmuxTransport(pi: ExtensionAPI): TaskTransport {
160
- return {
161
- name: "tmux",
162
- getCurrentSessionName(env) {
163
- return env.PI_TASK_SESSION ?? env.TMUX_PANE ?? `pid-${process.pid}`;
164
- },
165
- async dispatchTask({ target, assignment, task, signal }) {
166
- const bufferName = `pi-task-${task.id}`;
167
- const setBuffer = await pi.exec("tmux", ["set-buffer", "-b", bufferName, assignment], { signal });
168
- if (setBuffer.code !== 0) {
169
- return {
170
- ok: false,
171
- message: setBuffer.stderr || setBuffer.stdout || "tmux set-buffer failed",
172
- retryable: true,
173
- };
174
- }
175
-
176
- const paste = await pi.exec("tmux", ["paste-buffer", "-d", "-b", bufferName, "-t", target], { signal });
177
- if (paste.code !== 0) {
178
- return {
179
- ok: false,
180
- message: paste.stderr || paste.stdout || "tmux paste-buffer failed",
181
- retryable: true,
182
- };
183
- }
184
-
185
- const enter = await pi.exec("tmux", ["send-keys", "-t", target, "Enter"], { signal });
186
- if (enter.code !== 0) {
187
- return {
188
- ok: false,
189
- message: enter.stderr || enter.stdout || "tmux send-keys failed",
190
- retryable: true,
191
- };
192
- }
193
-
194
- return { ok: true };
195
- },
196
- };
197
- }
198
-
199
- export default function extension(pi: ExtensionAPI): void {
200
- registerAgentTaskTools(pi, {
201
- // All tmux panes must run in the same project cwd so they share .pi/tasks.
202
- store: createFilesystemTaskStore({ tasksDir: ".pi/tasks" }),
203
- transport: createTmuxTransport(pi),
204
- });
205
- }
206
- ```
207
-
208
- This transport does not open panes. It only pastes assignment text into an
209
- already-running pane and presses Enter.
210
-
211
- ### 2. open the agents yourself
212
-
213
- Start each Pi agent in the same repo/cwd and load the extension. Give each one a
214
- stable session name:
215
-
216
- ```bash
217
- # pane 1
218
- PI_TASK_SESSION=parent pi -e ./.pi/extensions/pi-tasks-tmux.ts
219
-
220
- # pane 2
221
- PI_TASK_SESSION=worker-a pi -e ./.pi/extensions/pi-tasks-tmux.ts
222
- ```
223
-
224
- If the extension is installed with `pi install`, you can omit `-e`; the important
225
- parts are same cwd, same `.pi/tasks`, and distinct `PI_TASK_SESSION` values.
226
-
227
- ### 3. find the target pane id
228
-
229
- From inside tmux:
230
-
231
- ```bash
232
- tmux list-panes -a -F '#{pane_id} #{pane_current_path} #{pane_title}'
233
- ```
234
-
235
- Pane ids look like `%12`. Use that pane id as `agent_task_send.to`.
236
-
237
- ### 4. send a task
238
-
239
- From the parent Pi session, call:
240
-
241
- ```json
242
- {
243
- "to": "%12",
244
- "task": "inspect the auth middleware and report risks",
245
- "timeoutMs": 1800000
246
- }
247
- ```
248
-
249
- Expected flow:
250
-
251
- 1. parent creates `.pi/tasks/<taskId>/...`
252
- 2. tmux transport pastes the assignment into pane `%12`
253
- 3. worker receives `pi.task.assignment.v1`
254
- 4. worker does the work
255
- 5. worker calls `agent_task_done` with that `taskId`
256
- 6. parent reads the result via `agent_task_status`, `agent_task_wait`, or
257
- `agent_task_inbox`
258
-
259
- ### tmux troubleshooting
260
-
261
- - If the target cannot complete the task, confirm it loaded the extension and has
262
- `agent_task_done` available.
263
- - If status never changes, confirm parent and worker are in the same cwd and both
264
- can see the same `.pi/tasks/<taskId>` directory.
265
- - If dispatch fails, run `tmux paste-buffer` manually against the same target id;
266
- the pane id may be stale.
267
- - Do not use terminal output as the source of truth. The task result is the store
268
- state, not visible prose in the pane.
269
-
270
- ## using with non-pi workers
271
-
272
- A non-Pi worker can participate if it implements the same lifecycle:
273
-
274
- 1. receive `pi.task.assignment.v1`
275
- 2. do the assigned work
276
- 3. write/report a terminal result with the same status and payload semantics
277
- 4. never overwrite an already-terminal task
278
-
279
- Example HTTP transport from a Pi extension:
280
-
281
- ```ts
282
- import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
283
- import { registerAgentTaskTools } from "@sgtbeatdown/pi-tasks/src/extension";
284
- import { createFilesystemTaskStore } from "@sgtbeatdown/pi-tasks/src/stores/filesystem";
285
- import type { TaskTransport } from "@sgtbeatdown/pi-tasks/src/task-communication";
286
-
287
- const httpTransport: TaskTransport = {
288
- name: "http",
289
- getCurrentSessionName(env) {
290
- return env.PI_TASK_SESSION ?? "unknown-session";
291
- },
292
- async dispatchTask({ target, assignment, task, signal }) {
293
- const response = await fetch(`https://tasks.example/sessions/${target}/assignments`, {
294
- method: "POST",
295
- headers: { "content-type": "application/json" },
296
- body: JSON.stringify({ taskId: task.id, assignment }),
297
- signal,
298
- });
299
-
300
- if (response.ok) return { ok: true };
301
-
302
- return {
303
- ok: false,
304
- message: await response.text(),
305
- retryable: response.status >= 500,
306
- };
20
+ "to": { "machine": "local", "sessionId": "receiver-broker-id" },
21
+ "task": "implement the narrow change and run focused tests",
22
+ "context": {
23
+ "summary": "## constraints and preferences\n- keep scope narrow\n## key decisions\n- preserve the public contract",
24
+ "refs": [{ "path": "src/extension.ts", "purpose": "affected tool wiring" }]
307
25
  },
308
- };
309
-
310
- export default function extension(pi: ExtensionAPI): void {
311
- registerAgentTaskTools(pi, {
312
- store: createFilesystemTaskStore({ tasksDir: ".pi/tasks" }),
313
- transport: httpTransport,
314
- });
26
+ "metadata": { "phaseId": "phase-1", "issueId": "task-3", "verificationTier": "focused" },
27
+ "onCompletePrompt": "review the receiver diff before reporting completion",
28
+ "timeoutMs": 1800000
315
29
  }
316
30
  ```
317
31
 
318
- For non-Pi workers, expose a completion endpoint or let workers use your store
319
- implementation directly. The worker should report a terminal result equivalent
320
- to:
32
+ Remote addressing changes only `to.machine`:
321
33
 
322
34
  ```json
323
- {
324
- "taskId": "task_...",
325
- "status": "completed",
326
- "summary": "finished the assigned work",
327
- "result": {}
328
- }
35
+ { "to": { "machine": "https://worker.example.ts.net", "sessionId": "receiver-broker-id" }, "task": "review the cited diff" }
329
36
  ```
330
37
 
331
- ## file inbox / polling workers
332
-
333
- A pushed message is not required. A transport can durably drop assignments into a
334
- file inbox or queue and return success once the assignment is written.
335
-
336
- One simple design:
337
-
338
- - store tasks in `.pi/tasks`
339
- - transport writes assignment text to `.pi/task-inbox/<target>/<taskId>.txt`
340
- - worker watches its inbox directory
341
- - worker reads the assignment, does the work, then completes through a store API
342
- or by invoking a Pi session that has `agent_task_done`
343
-
344
- Completion is separate from dispatch. Dispatch means “assignment delivered,” not
345
- “work finished.”
346
-
347
- ## when to implement a custom store
38
+ Context is optional, curated Markdown plus deliberately selected ref metadata. The extension renders refs but never reads or copies their contents. Relative refs resolve in the receiver project; absolute refs are same-machine only and must remain inside the authoritative parent or receiver project root. Missing refs are warnings, not copied content or transcript transfer.
348
39
 
349
- Do **not** implement a custom store just because you have a new dispatch
350
- mechanism. Implement `TaskStore` only when task state itself must be somewhere
351
- else:
40
+ Initial limits are 16 KiB UTF-8 each for task instructions and context summary, 48 KiB for the assignment envelope, and 64 KiB for an HTTP request body. The initial size limits require representative payload benchmarking before adjustment.
352
41
 
353
- - central HTTP service
354
- - Redis/Postgres/SQLite shared by multiple machines
355
- - multi-host queue system
356
- - hosted control plane
42
+ `agent_task_send` waits for durable gateway receipt, not task execution. A remote initial send has one initial attempt: the receiver persists a provisional receipt, then receives sender confirmation before Pi can see the assignment. Later peer confirmation, messages, terminal updates, cancellation, delivery notices, and parent acknowledgment have four total attempts: the initial attempt plus retries around 1, 2, and 4 seconds with jitter. Exhaustion is a visible local delivery failure, not a background queue or offline dispatch promise.
357
43
 
358
- If only delivery changes, keep the filesystem store.
44
+ Normal delegation is fire-and-forget. Use `agent_task_wait` only when the user explicitly asks to block.
359
45
 
360
- ## included wolfpack transport
361
-
362
- This package includes a Wolfpack transport for convenience. It is only a delivery
363
- adapter:
364
-
365
- ```bash
366
- wolfpack session send <target-session> <assignment>
367
- ```
368
-
369
- It does not own storage. The default exported extension uses the generic
370
- filesystem store at `.pi/tasks/` plus the included Wolfpack transport.
371
-
372
- If you are using Wolfpack, install this extension in every participating Pi
373
- session and target a session name/id with `agent_task_send`.
374
-
375
- If you are not using Wolfpack, register the tools with your own `{ store,
376
- transport }` composition.
377
-
378
- ## tools
46
+ ## tools, messages, and acknowledgment
379
47
 
380
48
  | tool | purpose |
381
49
  | --- | --- |
382
- | `agent_task_send` | create a task and dispatch it through the configured transport |
383
- | `agent_task_status` | read compact structured status for one task |
384
- | `agent_task_wait` | wait in tool code for a terminal result when the user wants it now |
385
- | `agent_task_inbox` | list terminal tasks for the current parent session |
386
- | `agent_task_cancel` | cancel a non-terminal task |
387
- | `agent_task_done` | assignee-side structured completion; terminates the target response |
50
+ | `agent_task_send` | create a durable gateway assignment |
51
+ | `agent_task_status` | read task state, history, result, and warnings |
52
+ | `agent_task_wait` | explicitly poll a task until terminal or timeout |
53
+ | `agent_task_inbox` | read task events; `ack: true` starts terminal parent acknowledgment |
54
+ | `agent_task_message` | send a durable `question`, `answer`, or `information` event |
55
+ | `agent_task_cancel` | request cancellation |
56
+ | `agent_task_done` | receiver-only terminal completion; terminates the tool turn |
388
57
 
389
- ### completion contract
58
+ Use `agent_task_message` for clarification instead of terminal prose. Only one question can be unresolved per task; answers link to that question. Information is durable and does not change task state. An accepted receiver question terminates that receiver turn; a parent question does not.
390
59
 
391
- Assigned Pi agents must call `agent_task_done` as their final action:
60
+ The sender gateway owns canonical event order, timeout, and terminal state. The first accepted terminal event wins. Sender timeout triggers best-effort remote cancellation; late terminals remain diagnostics. After independently verifying a terminal result, call `agent_task_inbox({ ack: true })`. Remote acknowledgment is two-phase: the receiver durably confirms pending acknowledgment before the sender records final parent acknowledgment. If that delivery fails, the task remains visible and a later explicit acknowledgment repairs it with the same event ID.
392
61
 
393
- ```json
394
- {
395
- "taskId": "task_...",
396
- "status": "completed",
397
- "summary": "inspected auth middleware; no bypass found",
398
- "result": {
399
- "filesReviewed": ["src/auth.ts"]
400
- }
401
- }
402
- ```
62
+ ## structured delivery and replay
403
63
 
404
- Non-Pi workers should complete through an equivalent store/server API with the
405
- same terminal status and payload semantics.
64
+ The extension polls the local gateway every five seconds and only injects events when Pi is idle with no pending messages. It uses Pi structured custom messages with `{ taskId, eventId }` details, so task context participates in the session without parsing prose.
406
65
 
407
- Valid terminal statuses:
66
+ On start or resume it rebuilds incorporated IDs from those custom-message details. A session gets only missing events; a new Pi session in the same Wolfpack PTY gets complete active history. The receiver records gateway delivery only after the structured insertion exists. A restart after insertion and before acknowledgment therefore acknowledges the existing entry without duplicate injection. Gateway delivery is at-least-once; this does not claim exactly-once model execution.
408
67
 
409
- - `completed`
410
- - `failed`
411
- - `cancelled`
412
- - `timed_out`
413
- - `rejected`
68
+ ## parent workflow
414
69
 
415
- Terminal completion is first-writer-wins.
70
+ 1. create or select a Wolfpack Pi session with the canonical session-control workflow and retain its stable broker ID.
71
+ 2. check the target's local gateway/package requirements, then send compact instructions with curated context and selected refs only when they save receiver investigation.
72
+ 3. keep working; use `agent_task_status` or `agent_task_inbox` for structured follow-up, and `agent_task_message` for questions, answers, and decisions.
73
+ 4. verify cited files, diffs, tests, and paths-only artifact metadata independently before reporting success.
74
+ 5. acknowledge the accepted terminal result, then clean up only sessions this parent spawned. Keep a reusable implementer alive while review or correction remains possible; never make workers close their own sessions.
416
75
 
417
- ## task protocol
76
+ A real second peer is not currently available for live operational verification. The protocol has isolated two-server coverage, but that does not prove a particular remote Wolfpack deployment is reachable. Do not overstate remote availability or use direct peer URLs from Pi.
418
77
 
419
- Assignments are delivered as human-readable text plus a structured envelope with:
78
+ See `skills/wolfpack-pi-task-delegation/SKILL.md` for the operational workflow and `skills/task-context-summary/SKILL.md` for recovery/reuse summaries.
420
79
 
421
- - `type: "pi.task.assignment.v1"`
422
- - `taskId`
423
- - `fromSession`
424
- - `instructions`
425
- - protocol requirements telling the assignee to use `agent_task_done`
80
+ ## deferred follow-up
426
81
 
427
- Task state includes:
82
+ These are documented operational debt, not production TODOs: exact Pi runtime registration and heartbeat/capability leases; durable offline initial dispatch; JWT/authenticated peer federation; artifact byte transfer and retention; representative payload benchmarking; automated recovery summaries; and summary caching only after measured repeated-generation waste. v1 has no queue, scheduler, artifact transfer, or transcript transfer.
428
83
 
429
- - `pending`
430
- - `dispatched`
431
- - `running`
432
- - terminal status
433
- - assignment/result refs
434
- - event history
435
- - optional result payload/artifacts/error
436
-
437
- Filesystem layout:
438
-
439
- ```text
440
- <tasksDir>/<taskId>/
441
- ├── task.json
442
- ├── assignment.json
443
- ├── events.jsonl
444
- └── result.json
445
- ```
84
+ ## legacy historical metrics
446
85
 
447
- Generic filesystem storage defaults to `.pi/tasks/` when used directly.
448
-
449
- ## architecture
450
-
451
- `pi-tasks` separates storage from delivery:
452
-
453
- ```ts
454
- interface TaskStore {
455
- createOrReuseDispatchedTask(...): Promise<...>;
456
- readTask(...): Promise<...>;
457
- readTaskResult(...): Promise<...>;
458
- expireTaskIfOverdue(...): Promise<...>;
459
- waitForTask(...): Promise<...>;
460
- listInbox(...): Promise<...>;
461
- ackTask(...): Promise<...>;
462
- cancelTask(...): Promise<...>;
463
- completeTask(...): Promise<...>;
464
- }
465
-
466
- interface TaskTransport {
467
- getCurrentSessionName(env): string;
468
- dispatchTask(input): Promise<DispatchTaskResult>;
469
- }
470
- ```
471
-
472
- Registration composes both:
473
-
474
- ```ts
475
- registerAgentTaskTools(pi, {
476
- store: createFilesystemTaskStore({ tasksDir: ".pi/tasks" }),
477
- transport: myTransport,
478
- });
479
- ```
480
-
481
- ## exported building blocks
482
-
483
- - `src/extension.ts`
484
- - `registerAgentTaskTools`
485
- - `createDefaultTaskCommunicationLayer`
486
- - `src/task-communication.ts`
487
- - `TaskStore`
488
- - `TaskTransport`
489
- - `TaskCommunicationLayer`
490
- - `src/stores/filesystem.ts`
491
- - `createFilesystemTaskStore`
492
- - `src/transports/wolfpack.ts`
493
- - `createWolfpackTaskTransport`
494
- - `src/protocol.ts`
495
- - `buildAssignment`
496
- - `compactTaskResult`
497
- - `src/store.ts`
498
- - low-level filesystem store functions, if you need finer control than
499
- `createFilesystemTaskStore`
86
+ `task-metrics` and the task board remain read-only analyzers for already-existing historical `.pi/tasks` directories. They are not part of the runtime task protocol and must not create, mutate, or deliver v1 gateway tasks. Replacing or retiring that historical reporting surface requires a product decision about gateway-wide query/metrics ownership.
500
87
 
501
88
  ## development
502
89
 
@@ -505,10 +92,3 @@ bun install
505
92
  bun test
506
93
  bun run typecheck
507
94
  ```
508
-
509
- ## current limitations
510
-
511
- - no built-in HTTP/Redis transport yet
512
- - no runtime transport selector yet; compose a store/transport in an extension
513
- - default extension uses the generic filesystem store plus the included Wolfpack transport
514
- - package is source-first; install with `pi install npm:@sgtbeatdown/pi-tasks`
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@sgtbeatdown/pi-tasks",
3
- "version": "0.1.0",
4
- "description": "Structured task communication for Pi agents with pluggable stores and transports.",
3
+ "version": "0.1.1",
4
+ "description": "Durable Pi agent delegation through the Wolfpack task gateway.",
5
5
  "module": "src/extension.ts",
6
6
  "repository": {
7
7
  "type": "git",
8
- "url": "https://github.com/almogdepaz/pi-tasks.git"
8
+ "url": "git+https://github.com/almogdepaz/pi-tasks.git"
9
9
  },
10
10
  "keywords": [
11
11
  "pi-package",
@@ -46,6 +46,7 @@
46
46
  },
47
47
  "scripts": {
48
48
  "test": "bun test",
49
+ "task-metrics": "bun src/metrics-cli.ts",
49
50
  "typecheck": "tsc --noEmit"
50
51
  },
51
52
  "type": "module"
@@ -0,0 +1,34 @@
1
+ ---
2
+ name: task-context-summary
3
+ description: Recover or reuse a bounded Wolfpack task context summary when the parent needs to reconstruct handoff context without copying a transcript.
4
+ ---
5
+
6
+ # task context summary
7
+
8
+ parent authors normal summaries. use this skill only for recovery or reuse when the parent lacks enough already-loaded context.
9
+
10
+ ## evidence order
11
+
12
+ 1. inspect relevant docs/code first.
13
+ 2. use an existing session summary next, if one exists.
14
+ 3. inspect only the selective recent transcript needed to resolve remaining gaps.
15
+
16
+ do not copy a full transcript, infer unseen file contents, or automatically cache generated summaries. when evidence disagrees, state the disagreement explicitly instead of silently choosing a version.
17
+
18
+ ## output
19
+
20
+ return concise Markdown, under 16KiB UTF-8, using any useful subset:
21
+
22
+ ```md
23
+ ## constraints and preferences
24
+ ## progress
25
+ ### done
26
+ ### in progress
27
+ ### blocked
28
+ ## key decisions
29
+ ## critical context
30
+ ## failed approaches
31
+ ## open questions
32
+ ```
33
+
34
+ include selected refs separately in the task request. mention a ref's path, selector, and purpose only; do not read or duplicate ref contents merely to populate the summary.