@hasna/loops 0.3.14 → 0.3.16

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/docs/USAGE.md CHANGED
@@ -94,6 +94,23 @@ loops create agent supply-chain-watch \
94
94
  --prompt "Check for suspicious dependency or supply-chain changes. Report only concrete findings."
95
95
  ```
96
96
 
97
+ Agent loops can also carry advisory per-session allowlist metadata:
98
+
99
+ ```bash
100
+ loops create agent repo-check \
101
+ --provider codewith \
102
+ --every 15m \
103
+ --cwd /path/to/repo \
104
+ --prompt "Check the repo and report concrete failures." \
105
+ --allow-tool functions.exec_command \
106
+ --allow-command git,bun
107
+ ```
108
+
109
+ These fields are stored on the loop target and exposed to the run environment
110
+ as `LOOPS_AGENT_ALLOWED_TOOLS`, `LOOPS_AGENT_ALLOWED_COMMANDS`, and
111
+ `LOOPS_AGENT_ALLOWLIST_ENFORCEMENT=metadata_only`. They are not enforced by
112
+ OpenLoops yet; provider-native enforcement will be added separately.
113
+
97
114
  For `codewith` and `aicopilot` account isolation, register matching OpenAccounts tools first if they are not built in on the machine:
98
115
 
99
116
  ```bash
@@ -176,7 +193,7 @@ loops templates render todos-task-worker-verifier \
176
193
  --var taskTitle="Fix parser" \
177
194
  --var projectPath=/path/to/repo \
178
195
  --var provider=codewith \
179
- --var authProfile=account005 \
196
+ --var authProfilePool=account004,account005,account006 \
180
197
  --var sandbox=danger-full-access
181
198
  loops templates create-workflow todos-task-worker-verifier \
182
199
  --var taskId=<task-id> \
@@ -196,18 +213,26 @@ schedules a deduped one-shot workflow loop:
196
213
  ```bash
197
214
  cat task-created-event.json | loops events handle todos-task \
198
215
  --provider codewith \
199
- --auth-profile account005 \
216
+ --auth-profile-pool account004,account005,account006 \
200
217
  --permission-mode bypass \
201
218
  --sandbox danger-full-access
202
219
  ```
203
220
 
221
+ Task routing is explicit opt-in. The handler skips the event without creating a
222
+ workflow unless the event data or metadata has `route_enabled=true`,
223
+ `automation.allowed=true`, or a task tag containing `auto:route`. It also skips
224
+ blocked, completed/done, cancelled/canceled, failed, archived, manual,
225
+ approval-required, or `no-auto` tasks. This guard exists even when the upstream
226
+ `@hasna/events` webhook filter is misconfigured, so task existence alone is not
227
+ permission to execute agent work.
228
+
204
229
  For other Hasna apps that expose `@hasna/events` webhooks, use the generic
205
230
  handler:
206
231
 
207
232
  ```bash
208
233
  cat event.json | loops events handle generic \
209
234
  --provider codewith \
210
- --auth-profile account005 \
235
+ --auth-profile-pool account004,account005,account006 \
211
236
  --permission-mode bypass \
212
237
  --sandbox danger-full-access \
213
238
  --project-path /path/to/repo
@@ -215,9 +240,11 @@ cat event.json | loops events handle generic \
215
240
 
216
241
  This is the intended deterministic-to-agentic path: a producer creates a todos
217
242
  task, `@hasna/events` delivers `task.created`, OpenLoops creates a worker and a
218
- verifier workflow, and the workflow updates todos with evidence. Use
219
- `--dry-run` to inspect the rendered workflow and loop input without storing
220
- anything.
243
+ verifier workflow, and the workflow updates todos with evidence. Use account
244
+ pools so worker and verifier steps do not burn the same profile; OpenLoops picks
245
+ deterministically and uses a different verifier profile when the pool has at
246
+ least two entries. Use `--dry-run` to inspect the rendered workflow and loop
247
+ input without storing anything.
221
248
 
222
249
  ## Transcript-Driven Loops
223
250
 
@@ -240,12 +267,45 @@ loops runs <id-or-name>
240
267
  loops pause <id-or-name>
241
268
  loops resume <id-or-name>
242
269
  loops stop <id-or-name>
270
+ loops archive <id-or-name>
271
+ loops unarchive <id-or-name>
243
272
  loops remove <id-or-name>
244
273
  loops run-now <id-or-name>
245
274
  ```
246
275
 
247
276
  Use `--json` for machine-readable output. Prompt bodies and run stdout/stderr are redacted by default in status output. `loops run-now` exits non-zero when the recorded run fails or times out.
248
277
 
278
+ ## Health And Expectations
279
+
280
+ `loops health --json` summarizes the latest run for each loop and classifies
281
+ agent-run failures for default-loop SLOs:
282
+
283
+ ```bash
284
+ loops health --json
285
+ loops expectations <loop-id-or-name> --json
286
+ ```
287
+
288
+ The JSON contains the expectation result, bounded error/stdout/stderr evidence,
289
+ a stable failure fingerprint, route metadata, and recommended task fields.
290
+ OpenLoops does not mutate Todos from these commands. Until Todos has a native
291
+ upsert command, consumers can use the included compatibility fallback:
292
+ `todos search <dedupe-key>`, then `todos add ...` or `todos comment ...`.
293
+ The planned native integration is represented in `futureNativeUpsert`.
294
+
295
+ Failure classifications are: `rate_limit`, `auth`, `model_not_found`,
296
+ `context_length`, `schema_response_format`, `node_init`, `timeout`, `sigsegv`,
297
+ `skipped_previous_active`, and `unknown`.
298
+
299
+ Archive loops when retiring old automation but preserving history:
300
+
301
+ ```bash
302
+ loops archive <id-or-name>
303
+ loops list --archived
304
+ loops list --all
305
+ ```
306
+
307
+ Archived loops are hidden from the default `loops list`, excluded from daemon scheduling and doctor preflight, and cannot be run manually until restored with `loops unarchive`. `loops remove` deletes the loop record; prefer `archive` for superseded loops that may need audit history.
308
+
249
309
  `loops run-now` reports the manual run source:
250
310
 
251
311
  - `source=ad_hoc`: the loop was not due yet, so OpenLoops created a one-off manual slot. This is a single immediate attempt and does not schedule retries or consume the future scheduled slot.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/loops",
3
- "version": "0.3.14",
3
+ "version": "0.3.16",
4
4
  "description": "Persistent local loop and workflow runner for deterministic commands and headless AI coding agents",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",