@trevonistrevon/pi-loop 0.5.8 → 0.6.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.
Files changed (127) hide show
  1. package/.release-please-manifest.json +3 -0
  2. package/AGENTS.md +52 -12
  3. package/CHANGELOG.md +59 -0
  4. package/CONTRIBUTING.md +13 -3
  5. package/Dockerfile +17 -0
  6. package/README.md +47 -0
  7. package/coverage/coverage-final.json +35 -31
  8. package/coverage/index.html +64 -49
  9. package/coverage/src/api.ts.html +193 -0
  10. package/coverage/src/commands/index.html +32 -32
  11. package/coverage/src/commands/loop-command.ts.html +170 -170
  12. package/coverage/src/commands/tasks-command.ts.html +135 -135
  13. package/coverage/src/coordinator.ts.html +26 -26
  14. package/coverage/src/index.html +61 -106
  15. package/coverage/src/index.ts.html +280 -94
  16. package/coverage/src/loop-parse.ts.html +90 -57
  17. package/coverage/src/loop-reducer.ts.html +25 -25
  18. package/coverage/src/monitor-completion-coordinator.ts.html +1 -1
  19. package/coverage/src/monitor-manager.ts.html +95 -71
  20. package/coverage/src/monitor-reducer.ts.html +15 -15
  21. package/coverage/src/notification-reducer.ts.html +7 -7
  22. package/coverage/src/reducer-backed-store.ts.html +57 -57
  23. package/coverage/src/rpc/channels.ts.html +376 -0
  24. package/coverage/src/rpc/cross-extension-rpc.ts.html +541 -0
  25. package/coverage/src/rpc/index.html +131 -0
  26. package/coverage/src/runtime/index.html +89 -29
  27. package/coverage/src/{goal-coordinator.ts.html → runtime/loop-events.ts.html} +79 -73
  28. package/coverage/src/runtime/monitor-ondone-runtime.ts.html +5 -5
  29. package/coverage/src/runtime/native-task-rpc.ts.html +502 -0
  30. package/coverage/src/runtime/notification-runtime.ts.html +14 -14
  31. package/coverage/src/runtime/scope.ts.html +17 -17
  32. package/coverage/src/runtime/session-runtime.ts.html +40 -40
  33. package/coverage/src/runtime/task-backlog-runtime.ts.html +66 -24
  34. package/coverage/src/runtime/task-events.ts.html +208 -0
  35. package/coverage/src/runtime/task-mutations.ts.html +394 -0
  36. package/coverage/src/runtime/task-rpc.ts.html +106 -118
  37. package/coverage/src/scheduler.ts.html +12 -12
  38. package/coverage/src/store.ts.html +20 -20
  39. package/coverage/src/task-backlog-coordinator.ts.html +8 -8
  40. package/coverage/src/task-reducer.ts.html +42 -42
  41. package/coverage/src/task-store.ts.html +49 -49
  42. package/coverage/src/tools/index.html +39 -24
  43. package/coverage/src/tools/loop-tools.ts.html +12 -21
  44. package/coverage/src/tools/monitor-tools.ts.html +12 -21
  45. package/coverage/src/tools/native-task-tools.ts.html +52 -94
  46. package/coverage/src/tools/tool-result.ts.html +97 -0
  47. package/coverage/src/trigger-system.ts.html +12 -12
  48. package/coverage/src/ui/index.html +1 -1
  49. package/coverage/src/ui/widget.ts.html +23 -23
  50. package/dist/api.d.ts +11 -0
  51. package/dist/api.js +10 -0
  52. package/dist/commands/loop-command.js +2 -2
  53. package/dist/commands/tasks-command.js +3 -3
  54. package/dist/coordinator.d.ts +1 -1
  55. package/dist/index.js +80 -20
  56. package/dist/loop-parse.js +14 -5
  57. package/dist/monitor-manager.d.ts +4 -1
  58. package/dist/monitor-manager.js +5 -3
  59. package/dist/reducer-backed-store.d.ts +1 -1
  60. package/dist/reducer-backed-store.js +1 -1
  61. package/dist/rpc/channels.d.ts +73 -0
  62. package/dist/rpc/channels.js +30 -0
  63. package/dist/rpc/cross-extension-rpc.d.ts +59 -0
  64. package/dist/rpc/cross-extension-rpc.js +117 -0
  65. package/dist/runtime/loop-events.d.ts +26 -0
  66. package/dist/runtime/loop-events.js +26 -0
  67. package/dist/runtime/native-task-rpc.d.ts +22 -0
  68. package/dist/runtime/native-task-rpc.js +50 -0
  69. package/dist/runtime/task-backlog-runtime.d.ts +3 -0
  70. package/dist/runtime/task-backlog-runtime.js +4 -1
  71. package/dist/runtime/task-mutations.d.ts +39 -0
  72. package/dist/runtime/task-mutations.js +68 -0
  73. package/dist/runtime/task-rpc.d.ts +4 -0
  74. package/dist/runtime/task-rpc.js +40 -58
  75. package/dist/scheduler.js +1 -1
  76. package/dist/tools/loop-tools.js +1 -3
  77. package/dist/tools/monitor-tools.js +1 -3
  78. package/dist/tools/native-task-tools.d.ts +2 -6
  79. package/dist/tools/native-task-tools.js +25 -55
  80. package/dist/tools/tool-result.d.ts +8 -0
  81. package/dist/tools/tool-result.js +4 -0
  82. package/docker-compose.yml +12 -0
  83. package/docs/architecture/state-machine-migration.md +0 -44
  84. package/docs/architecture/state-machine-reducer-event-model.md +2 -3
  85. package/package.json +6 -1
  86. package/release-please-config.json +9 -0
  87. package/src/api.ts +36 -0
  88. package/src/commands/loop-command.ts +2 -2
  89. package/src/commands/tasks-command.ts +3 -3
  90. package/src/coordinator.ts +1 -1
  91. package/src/index.ts +84 -22
  92. package/src/loop-parse.ts +18 -7
  93. package/src/monitor-manager.ts +11 -3
  94. package/src/reducer-backed-store.ts +3 -3
  95. package/src/rpc/channels.ts +97 -0
  96. package/src/rpc/cross-extension-rpc.ts +152 -0
  97. package/src/runtime/loop-events.ts +60 -0
  98. package/src/runtime/native-task-rpc.ts +139 -0
  99. package/src/runtime/task-backlog-runtime.ts +14 -0
  100. package/src/runtime/task-mutations.ts +103 -0
  101. package/src/runtime/task-rpc.ts +48 -54
  102. package/src/scheduler.ts +1 -1
  103. package/src/tools/loop-tools.ts +1 -4
  104. package/src/tools/monitor-tools.ts +1 -4
  105. package/src/tools/native-task-tools.ts +31 -52
  106. package/src/tools/tool-result.ts +4 -0
  107. package/src/trigger-system.ts +4 -4
  108. package/vitest.config.ts +11 -7
  109. package/coverage/src/goal-reducer.ts.html +0 -982
  110. package/coverage/src/goal-store.ts.html +0 -742
  111. package/coverage/src/goal-verifier.ts.html +0 -808
  112. package/dist/goal-coordinator.d.ts +0 -22
  113. package/dist/goal-coordinator.js +0 -28
  114. package/dist/goal-reducer.d.ts +0 -98
  115. package/dist/goal-reducer.js +0 -190
  116. package/dist/goal-store.d.ts +0 -22
  117. package/dist/goal-store.js +0 -188
  118. package/dist/goal-types.d.ts +0 -82
  119. package/dist/goal-types.js +0 -1
  120. package/dist/goal-verifier.d.ts +0 -20
  121. package/dist/goal-verifier.js +0 -198
  122. package/docs/architecture/goal-state-schema.md +0 -505
  123. package/src/goal-coordinator.ts +0 -58
  124. package/src/goal-reducer.ts +0 -299
  125. package/src/goal-store.ts +0 -219
  126. package/src/goal-types.ts +0 -104
  127. package/src/goal-verifier.ts +0 -241
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "0.6.0"
3
+ }
package/AGENTS.md CHANGED
@@ -13,17 +13,60 @@
13
13
  ## Architecture
14
14
  ```
15
15
  src/
16
- ├── index.ts # Extension entry: 6 tools + /loop /loops commands + widget
17
- ├── types.ts # LoopKind, Trigger spec, LoopEntry, MonitorEntry, LoopConfig
18
- ├── store.ts # File-backed CRUD (.pi/loops/loops.json) with file locking
19
- ├── scheduler.ts # Timer-based cron scheduler with jitter + 7-day expiry
20
- ├── trigger-system.ts # Unified trigger engine: cron timers + pi event subscriptions + hybrid
21
- ├── monitor-manager.ts # ChildProcess tracking, output buffering, event emission, stop
22
- ├── loop-parse.ts # Human interval cron expression, next-fire computation, jitter
16
+ ├── index.ts # Extension entry: tool/command registration, session wiring, native task fallback timer
17
+ ├── api.ts # Public subpath (@trevonistrevon/pi-loop/api): RPC channels/DTOs, TaskStore, scope resolvers
18
+ ├── types.ts # LoopKind, Trigger spec, LoopEntry, MonitorEntry, LoopConfig
19
+ ├── task-types.ts # TaskEntry, TaskStatus, TaskStoreData
20
+ ├── store.ts # File-backed CRUD (.pi/loops/loops.json) with file locking
21
+ ├── task-store.ts # File-backed CRUD for native fallback tasks (.pi/tasks/tasks.json)
22
+ ├── reducer-backed-store.ts # Shared atomic-write + pid-lock persistence layer for reducer-driven stores
23
+ ├── coordinator.ts # ReducerSource/ReducerEvent/ReducerEffect plumbing shared by *-reducer/*-coordinator modules
24
+ ├── loop-reducer.ts # Pure loop state transitions, incl. maxFires/expiry checks
25
+ ├── monitor-reducer.ts # Pure monitor state transitions
26
+ ├── notification-reducer.ts # Pure pending-notification state transitions
27
+ ├── task-reducer.ts # Pure native task state transitions
28
+ ├── monitor-completion-coordinator.ts # Reduces monitor "onDone" completion into a fire effect
29
+ ├── task-backlog-coordinator.ts # Reduces pending-task counts into auto-create/auto-clean effects
30
+ ├── scheduler.ts # Timer-based cron scheduler with jitter + 7-day expiry
31
+ ├── trigger-system.ts # Unified trigger engine: cron timers + pi event subscriptions + hybrid
32
+ ├── monitor-manager.ts # ChildProcess tracking, output buffering, event emission, stop
33
+ ├── loop-parse.ts # Human interval → cron expression, next-fire computation, jitter
34
+ ├── rpc/ # VENDORED — canonical copy shared verbatim with pi-orca; see "Cross-extension RPC" below
35
+ │ ├── channels.ts # TASKS_RPC/SUBAGENTS_RPC/TASK_EVENTS channel constants + wire DTOs
36
+ │ └── cross-extension-rpc.ts # rpcCall (client), rpcProbe (detection), handleRpc (server), PROTOCOL_VERSION, RpcError
37
+ ├── runtime/ # Extension-init-time wiring, one module per concern
38
+ │ ├── loop-events.ts # Auto-delete payload types for backlog-drained loops
39
+ │ ├── monitor-ondone-runtime.ts # Coordinator wiring for MonitorCreate's onDone → loop fire
40
+ │ ├── native-task-rpc.ts # tasks:rpc:* server: ping/pending/create/clean/update over the native TaskStore
41
+ │ ├── notification-runtime.ts # Pending-notification buffering + idle-driven delivery
42
+ │ ├── scope.ts # PI_LOOP_SCOPE → loop/task store path resolution
43
+ │ ├── session-runtime.ts # Session-switch hooks, store (re)binding
44
+ │ ├── task-backlog-runtime.ts # Auto-create/auto-clean backlog worker evaluation
45
+ │ ├── task-events.ts # emitNativeTaskEvent: tasks:created/started/completed/reopened/updated/deleted
46
+ │ ├── task-mutations.ts # Shared mutation service: mutate → emit event → widget → backlog, used by RPC server and tools
47
+ │ └── task-rpc.ts # Client bridge: probes pi-tasks, falls back to native TaskStore for autoTask/pending/clean
48
+ ├── tools/ # Tool implementations
49
+ │ ├── loop-tools.ts # LoopCreate/LoopList/LoopDelete
50
+ │ ├── monitor-tools.ts # MonitorCreate/MonitorList/MonitorStop
51
+ │ ├── native-task-tools.ts # TaskCreate/TaskList/TaskUpdate/TaskDelete (fallback only)
52
+ │ └── tool-result.ts # textResult() helper
53
+ ├── commands/
54
+ │ ├── loop-command.ts # /loop interactive loop creation
55
+ │ └── tasks-command.ts # /tasks native task viewer/manager
23
56
  └── ui/
24
- └── widget.ts # Persistent widget: active loops + monitors
57
+ └── widget.ts # Persistent widget: active loops + monitors + task summary
25
58
  ```
26
59
 
60
+ ## Cross-extension RPC
61
+ `src/rpc/` is a **vendored** module: the canonical copy is maintained here and copied verbatim into the sibling `pi-orca` repo. If you edit `channels.ts` or `cross-extension-rpc.ts`, copy the change to `pi-orca` and bump the `VENDOR_REV` comment at the top of both files in both repos — the two copies must never drift.
62
+
63
+ The wire contract is request/reply over `pi.events`: a caller emits `{ requestId, ...params }` on a channel (e.g. `tasks:rpc:create`), the server replies on `<channel>:reply:<requestId>` with an envelope, `{success:true,data}` or `{success:false,error}`. `rpcCall` resolves/rejects that promise, `rpcProbe` swallows the rejection into `undefined` for presence detection, `handleRpc` is the server-side helper that turns a handler function into a channel subscription with automatic envelope wrapping. `PROTOCOL_VERSION` (currently `2`) is returned in ping replies so callers can gate on server capability.
64
+
65
+ `pi-loop`'s native tasks RPC server (`src/runtime/native-task-rpc.ts`) registers at extension init — not behind the native-tool-registration fallback timer — so early cross-extension calls never race it. It stands down (silent no-op via `isEnabled`) once an external `pi-tasks` is detected.
66
+
67
+ ## Public API surface
68
+ External consumers must import `@trevonistrevon/pi-loop/api` (`src/api.ts`), never a deep `src/...` path. The package `exports` map in `package.json` enforces this — deep imports fail to resolve. `src/api.ts` re-exports the RPC channel constants/DTOs, `rpcCall`/`rpcProbe`/`handleRpc`/`RpcError`/`PROTOCOL_VERSION`, `TaskStore`, `TaskEntry`/`TaskStatus`, `resolveLoopStorePath`/`resolveTaskStorePath`, and `NATIVE_TASKS_PROVIDER`. Anything not re-exported there is internal and may change without notice.
69
+
27
70
  ## Conventions (mirror pi-tasks)
28
71
  - No comments unless answering "why", never "what"
29
72
  - `debug(...)` helper gated on `PI_LOOP_DEBUG` env var, logs to stderr
@@ -61,10 +104,7 @@ All loops are idle-driven. Cron and hybrid loops track their next fire time but
61
104
  Monitor stdout/stderr lines are emitted as `pi.events("monitor:output", { monitorId, line, timestamp })`. Tool consumers subscribe to these events. Completion emits `"monitor:done"` / `"monitor:error"`.
62
105
 
63
106
  ## pi-tasks Integration
64
- When `@tintinweb/pi-tasks` is present, `LoopCreate` with `autoTask: true` fires an RPC to create a task. Communication via `pi.events`:
65
- - `tasks:rpc:ping` on init → detect pi-tasks presence
66
- - `tasks:ready` listener → late-binding detection
67
- - `tasks:rpc:create` → auto-create task when loop fires (if `autoTask: true`)
107
+ `pi-loop` probes for `@tintinweb/pi-tasks` at init via `tasks:rpc:ping` (see "Cross-extension RPC" above) and again on a `tasks:ready` listener for late binding. When an external provider answers, `LoopCreate` with `autoTask: true` calls `tasks:rpc:create` to create a tracked task on fire. When no external provider answers, `pi-loop`'s own native RPC server (`src/runtime/native-task-rpc.ts`) serves all five verbs — `ping`/`pending`/`create`/`clean`/`update` — against the native `TaskStore`, and `autoTask: true` creates a native task directly instead of over RPC.
68
108
 
69
109
  ## /loop Self-Paced Mode
70
110
  When no interval is specified in `/loop prompt`, the loop runs in self-paced mode. The agent receives the prompt, acts on it, and uses `LoopCreate`/`LoopUpdate` to schedule the next iteration. The loop fires once, then the agent decides the next interval dynamically (matching Claude Code's dynamic interval behavior).
package/CHANGELOG.md CHANGED
@@ -1,5 +1,64 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.6.0](https://github.com/trvon/pi-loop/compare/pi-loop-v0.5.8...pi-loop-v0.6.0) (2026-07-02)
4
+
5
+
6
+ ### ⚠ BREAKING CHANGES
7
+
8
+ * package exports map blocks deep src/ imports — consumers must use @trevonistrevon/pi-loop/api. tasks:updated now reports previousStatus at edit time, not pre-transition.
9
+
10
+ ### Features
11
+
12
+ * add maxFires for self-limiting loops, event-driven prompt steering ([52b50f0](https://github.com/trvon/pi-loop/commit/52b50f0d2b8c0b1df6aa74b09a8561807b549fe6))
13
+ * add native task fallback and compact task tracker ([6b5b6ff](https://github.com/trvon/pi-loop/commit/6b5b6fff53cc7810242e4f9081fe6d21b318c654))
14
+ * add task decomposition guidance to TaskCreate prompt ([4c51e72](https://github.com/trvon/pi-loop/commit/4c51e72a7317e1433cdb5bed6cfc9dfa521b5bfb))
15
+ * add tasks:rpc:clean RPC for sweeping done tasks ([73812ed](https://github.com/trvon/pi-loop/commit/73812ed4c3efeb08e97908e6de6435f65c768440))
16
+ * auto-create task worker loop at backlog threshold ([430663a](https://github.com/trvon/pi-loop/commit/430663a8042560688e08bd08129ea57b190ccecc))
17
+ * canonical rpc module + init-time task server ([7335eff](https://github.com/trvon/pi-loop/commit/7335eff6440452178ae9db3cb22a49098ad3953d))
18
+ * generalize task backlog loop cleanup ([9132948](https://github.com/trvon/pi-loop/commit/9132948dc9e22cda32adf6e8c5e13a7203f9c864))
19
+ * goal prompt and loading refinements ([b31df23](https://github.com/trvon/pi-loop/commit/b31df23c240f0bde7fb69fb8ea702429576276c7))
20
+ * prune completed tasks after successful git commit ([cba120b](https://github.com/trvon/pi-loop/commit/cba120be3a7fcdf71b7f7649b414577412d26a94))
21
+ * refining monitor interface ([66a6007](https://github.com/trvon/pi-loop/commit/66a60077093f40c258efeeb971f6f8db74e24f83))
22
+ * show worker-loop hint when pending tasks reach 5+ ([74dbf2c](https://github.com/trvon/pi-loop/commit/74dbf2cbf7f55a4206762eee3731798527537ab5))
23
+ * skip loop fires when autoTask loop has no pending tasks ([f2feb07](https://github.com/trvon/pi-loop/commit/f2feb079d5b520ed4c4dd0dc85d5b385efc45c45))
24
+ * **tasks:** add native rpc update and backlog signals ([31d06f6](https://github.com/trvon/pi-loop/commit/31d06f61fce1333c359f0d38def7406474144f8b))
25
+ * **tasks:** emit native task events with previousStatus tracking ([61b49ea](https://github.com/trvon/pi-loop/commit/61b49ea5703597b02754998269edfdc5b2018ebb))
26
+
27
+
28
+ ### Bug Fixes
29
+
30
+ * add trigger validation, readOnly flag, and edge-case tests ([91baa07](https://github.com/trvon/pi-loop/commit/91baa07884bc20d760c7a3642c3ec462997fc0d3))
31
+ * auto-delete worker loop when task backlog clears ([502fa10](https://github.com/trvon/pi-loop/commit/502fa106b8862c06648e6be373e5980d2af18f6f))
32
+ * auto-expire monitor:done loops, buffer output, show completed monitors ([a3ec5de](https://github.com/trvon/pi-loop/commit/a3ec5de5847d67bddee9c572079b559b03e35f3f))
33
+ * deduplicate loop follow-up messages to prevent flood ([1613511](https://github.com/trvon/pi-loop/commit/1613511a2453d346edb59919beed2bdb18c05f63))
34
+ * delete done loops/monitors immediately instead of marking expired ([43f5220](https://github.com/trvon/pi-loop/commit/43f5220a3e6d807234e4bdb7611e44c0fa7468ec))
35
+ * delete event maxFires loops immediately ([12335e7](https://github.com/trvon/pi-loop/commit/12335e75dcf8d17a2c887966cae180d2b2f848da))
36
+ * deliver monitor onDone wakes without event dependency ([79d6a8b](https://github.com/trvon/pi-loop/commit/79d6a8b925aa98e8de0ea1b12addd5e0d2db0c47))
37
+ * derive jitter ceiling from cron step, delete expired event loops ([6d13935](https://github.com/trvon/pi-loop/commit/6d13935e79d2367072bec027d5ef2cb430eff44a))
38
+ * flush buffered worker wakes on agent end ([7a7dedf](https://github.com/trvon/pi-loop/commit/7a7dedf3ec7f16eb63edbfaf93e5dae9ed7a8f25))
39
+ * harden TaskUpdate prompt to prevent taskId alias errors ([5dfefd9](https://github.com/trvon/pi-loop/commit/5dfefd96bb08c29d192de472c6224ac434394b6f))
40
+ * **injection:** use before_agent_start message, not tool_result ([99a6317](https://github.com/trvon/pi-loop/commit/99a6317aabde8ce9d4f9e0c3065f42b6c6111259))
41
+ * loop trigger fix ([619f32c](https://github.com/trvon/pi-loop/commit/619f32c48134d9cc1376a89a62a7c8d729321143))
42
+ * **monitor:** make MonitorManager spawn-injectable, fix CI test timeouts ([f277646](https://github.com/trvon/pi-loop/commit/f277646b95369b43508fbbc8cc7eef5e37580781))
43
+ * **monitor:** prune stopped/timed-out monitors ([a46f6e8](https://github.com/trvon/pi-loop/commit/a46f6e8f2b99fa39bd11ff22d1a34999e1ac4434))
44
+ * only dedup recurring loop fires, always deliver one-shot events ([352e50e](https://github.com/trvon/pi-loop/commit/352e50e1de14ecd8d884b18a8e72572270ca90e9))
45
+ * **persist:** expire event loops on session start, clean stale monitors ([7f0876d](https://github.com/trvon/pi-loop/commit/7f0876d821e93e663f43ec2d5351bc9a37223b4b))
46
+ * recommend 5m default interval in LoopCreate task-continuation prompt ([1af3bcd](https://github.com/trvon/pi-loop/commit/1af3bcd35a2782f9fc333559d293c665db76c234))
47
+ * release please fix ([16e2304](https://github.com/trvon/pi-loop/commit/16e2304ea3112664c12c65b4e098e04d390f93f0))
48
+ * **reminders:** make loop reminder directive, not informational ([e21174d](https://github.com/trvon/pi-loop/commit/e21174df3d1d9403684e094f5763db33ed9cb732))
49
+ * repair native task fallback compilation ([a8cef04](https://github.com/trvon/pi-loop/commit/a8cef04eabd8a8af404d27ffa756266ee6a188ec))
50
+ * **runtime:** unref retention timer, swallow heartbeat pump errors ([602816b](https://github.com/trvon/pi-loop/commit/602816b3abb06859a0268c02119cc753de03decb))
51
+ * scope native task files by session, prevent cross-session leakage ([0436710](https://github.com/trvon/pi-loop/commit/04367102414dd56f7668e1522b91c6f089490979))
52
+ * **tasks:** gate late native RPC probes ([c97f4ad](https://github.com/trvon/pi-loop/commit/c97f4ad6800c00b9858c1a8e640f13e699e0c26a))
53
+ * **tasks:** guard native fallback registration ([7d3b74a](https://github.com/trvon/pi-loop/commit/7d3b74abfa637bbe370ae232b8067e7bc5205ea1))
54
+ * **trigger:** auto-expire non-recurring event loops ([178f9fd](https://github.com/trvon/pi-loop/commit/178f9fd6a6548a04307f3ed83935068a235c24d3))
55
+ * use pi.hasPendingMessages() instead of bespoke tracking Set ([dab60d4](https://github.com/trvon/pi-loop/commit/dab60d46340fab04ae74b80044ad03b6b0ca9fe8))
56
+
57
+
58
+ ### Performance Improvements
59
+
60
+ * **test:** replace real 6.1s waits with fake-timer advance in onDone tests ([c713ad3](https://github.com/trvon/pi-loop/commit/c713ad36f958d53e75c4c7d7fd723c06ee420543))
61
+
3
62
  ## [0.1.2]
4
63
 
5
64
  - Added `onDone` parameter to `MonitorCreate` — auto-creates a completion loop so the agent is notified when a background process finishes, no polling needed
package/CONTRIBUTING.md CHANGED
@@ -19,19 +19,22 @@ npm install
19
19
  | `npm run lint:fix` | Auto-fix lint issues |
20
20
  | `npm test` | Run tests (`vitest run`) |
21
21
  | `npm run test:watch` | Watch mode |
22
+ | `npm run test:coverage` | Run tests with coverage (used in CI) |
23
+ | `npm run test:e2e` | Run `test/e2e/reminder-injection.sh` (self-skips without a local llama server) |
22
24
  | `npm run build` | Compile TypeScript |
23
25
 
24
26
  ## Architecture
25
27
 
26
- See `AGENTS.md` for the full architecture overview. Key modules:
28
+ See `AGENTS.md` for the full architecture overview and directory tree, including `src/rpc/` (vendored cross-extension RPC) and `src/api.ts` (public `@trevonistrevon/pi-loop/api` subpath — the only supported import path for external consumers). Key modules:
27
29
 
28
- - **`src/index.ts`** — Extension entry: registers 6 tools + `/loop` `/loops` commands + widget lifecycle
30
+ - **`src/index.ts`** — Extension entry: registers tools, `/loop` `/tasks` commands, widget lifecycle, cross-extension RPC server
29
31
  - **`src/types.ts`** — Core types: `LoopEntry`, `MonitorEntry`, `Trigger` variants
30
32
  - **`src/store.ts`** — File-backed CRUD with pid-based file locking (atomic write → rename)
31
33
  - **`src/scheduler.ts`** — Timer-based cron scheduler with per-loop jitter and 7-day expiry
32
34
  - **`src/trigger-system.ts`** — Unified engine: cron timers + pi event subscriptions + hybrid debounce
33
35
  - **`src/monitor-manager.ts`** — `ChildProcess` wrapper: stdout/stderr streaming as pi events
34
36
  - **`src/loop-parse.ts`** — Human interval parsing (`5m` → cron), cron matching, next-fire computation
37
+ - **`src/runtime/native-task-rpc.ts`** — `tasks:rpc:*` server for the native fallback task store
35
38
  - **`src/ui/widget.ts`** — TUI widget rendering active loops + monitors above the editor
36
39
 
37
40
  ## Conventions
@@ -58,12 +61,19 @@ npm test # Run once
58
61
  npm run test:watch # Watch mode
59
62
  ```
60
63
 
64
+ ### Manual fixtures (not run in CI)
65
+
66
+ - `benchmarks/experiment-sim.js` — synthetic monitor fixture: prints periodic `iteration N/M, loss=...` lines and handles `SIGTERM` with a checkpoint message. Used to manually exercise `MonitorCreate` streaming, `onDone`, and stop handling. Run with `node benchmarks/experiment-sim.js`. Not wired into CI by design — it's a fixture, not an assertion.
67
+ - `test/e2e/reminder-injection.sh` (`npm run test:e2e`) — drives a real `pi` session against a local llama server to validate loop/reminder injection end to end. Requires a model server reachable at `localhost:2276`; the script checks for it and self-skips (exit 0) when absent. Never runs in CI — there is no llama server in the CI environment.
68
+
61
69
  ## Pull Request Workflow
62
70
 
63
71
  1. Fork, branch, implement
64
- 2. Ensure `npm run typecheck`, `npm run lint`, and `npm test` all pass
72
+ 2. Ensure `npm run lint`, `npm run typecheck`, and `npm run test:coverage` all pass, then `npm run build`
65
73
  3. Open PR against `main`
66
74
 
75
+ CI (`.github/workflows/ci.yml`) runs the same validation in this order on Node 20.x and 22.x: `lint` → `typecheck` → `test:coverage` → `build`.
76
+
67
77
  ## License
68
78
 
69
79
  By contributing, you agree that your contributions will be licensed under the MIT License.
package/Dockerfile ADDED
@@ -0,0 +1,17 @@
1
+ FROM node:22-alpine AS base
2
+ WORKDIR /app
3
+ COPY package.json package-lock.json ./
4
+ RUN npm ci
5
+ COPY . .
6
+
7
+ FROM node:20-alpine AS node20
8
+ WORKDIR /app
9
+ COPY package.json package-lock.json ./
10
+ RUN npm ci
11
+ COPY . .
12
+
13
+ FROM node:22-alpine AS node22
14
+ WORKDIR /app
15
+ COPY package.json package-lock.json ./
16
+ RUN npm ci
17
+ COPY . .
package/README.md CHANGED
@@ -81,9 +81,56 @@ If `pi-tasks` does not respond during startup detection, `pi-loop` registers a n
81
81
  - `TaskCreate`, `TaskList`, `TaskUpdate`, `TaskDelete`
82
82
  - `/tasks` interactive viewer
83
83
  - compact status-line task tracking
84
+ - native task RPC replies on `tasks:rpc:ping`, `tasks:rpc:create`, `tasks:rpc:pending`, `tasks:rpc:clean`, and `tasks:rpc:update`
84
85
 
85
86
  This fallback is session-sticky: `pi-loop` decides once at startup whether `pi-tasks` or native tasks own task management for that session.
86
87
 
88
+ ### Task and backlog events
89
+
90
+ `pi-loop` emits native task lifecycle events that other extensions can consume directly:
91
+
92
+ - `tasks:created`
93
+ - `tasks:started`
94
+ - `tasks:completed`
95
+ - `tasks:reopened`
96
+ - `tasks:updated`
97
+ - `tasks:deleted`
98
+
99
+ Payloads carry `previousStatus`. Transition events (`tasks:started` /
100
+ `tasks:completed` / `tasks:reopened`) report the status before the transition;
101
+ `tasks:updated` (a details edit) reports the status current at edit time — so a
102
+ combined status+details update never fabricates a second transition. (Changed
103
+ in 0.6.0: the tool path previously reused the pre-transition status.)
104
+ - `tasks:backlog_empty` — emitted when a task-backlog worker observes zero pending tasks and is about to auto-delete
105
+ - `loops:autodeleted` — emitted for each loop that `pi-loop` auto-deletes, including backlog workers removed because the task queue drained
106
+
107
+ ### Cross-extension task RPC
108
+
109
+ Other extensions can create and manage native tasks without importing `pi-loop` internals. `pi-loop` answers `ping` over `pi.events` from extension init; the other verbs unlock once the pi-tasks detection probe settles (a few seconds at most, immediate when no provider replies race it). The whole server stands down (silent no-op) once an external `pi-tasks` is detected:
110
+
111
+ | Channel | Request | Reply |
112
+ |---|---|---|
113
+ | `tasks:rpc:ping` | `{}` | `{ version, provider }` |
114
+ | `tasks:rpc:pending` | `{}` | `{ pending }` |
115
+ | `tasks:rpc:create` | `{ subject, description, metadata? }` | `{ id, task }` |
116
+ | `tasks:rpc:clean` | `{}` | `{ pruned }` |
117
+ | `tasks:rpc:update` | `{ id, status?, subject?, description? }` | `{ task }` |
118
+
119
+ Every request/reply pair follows the same contract: emit `{ requestId, ...params }` on the channel, receive an envelope on `<channel>:reply:<requestId>` — `{ success: true, data }` or `{ success: false, error }`.
120
+
121
+ `@trevonistrevon/pi-loop/api` exports typed channel constants and a client helper so consumers don't hand-roll the envelope:
122
+
123
+ ```ts
124
+ import { TASKS_RPC, rpcCall } from "@trevonistrevon/pi-loop/api";
125
+
126
+ const { id, task } = await rpcCall(pi.events, TASKS_RPC.create, {
127
+ subject: "Fix deploy polling",
128
+ description: "Switch deploy check to event-driven loop",
129
+ });
130
+ ```
131
+
132
+ `rpcCall` rejects on failure or timeout instead of returning a sentinel; wrap it in `try/catch` if you want fallback behavior. Import only from `@trevonistrevon/pi-loop/api` — the package's `exports` map blocks deep `src/` imports.
133
+
87
134
  ## Status line
88
135
 
89
136
  `pi-loop` keeps a compact persistent status line in the TUI.