@hasna/loops 0.3.60 → 0.4.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/CHANGELOG.md +265 -0
- package/LICENSE +197 -13
- package/README.md +95 -85
- package/dist/api/index.d.ts +11 -0
- package/dist/api/index.js +333 -0
- package/dist/cli/index.js +8013 -6659
- package/dist/daemon/control.d.ts +21 -1
- package/dist/daemon/daemon.d.ts +5 -0
- package/dist/daemon/index.js +2836 -1222
- package/dist/daemon/install.d.ts +1 -1
- package/dist/index.d.ts +23 -8
- package/dist/index.js +5715 -4541
- package/dist/lib/accounts.d.ts +6 -1
- package/dist/lib/agent-adapter.d.ts +74 -0
- package/dist/lib/backup.d.ts +25 -0
- package/dist/lib/errors.d.ts +21 -0
- package/dist/lib/executor.d.ts +10 -1
- package/dist/lib/goal/metadata.d.ts +16 -0
- package/dist/lib/goal/model-factory.d.ts +1 -0
- package/dist/lib/goal/prompts.d.ts +3 -1
- package/dist/lib/goal/types.d.ts +3 -0
- package/dist/lib/health.d.ts +1 -1
- package/dist/lib/ids.d.ts +8 -1
- package/dist/lib/machines.d.ts +6 -0
- package/dist/lib/mode.d.ts +48 -0
- package/dist/lib/mode.js +260 -0
- package/dist/lib/process-identity.d.ts +16 -0
- package/dist/lib/{schedule.d.ts → recurrence.d.ts} +1 -0
- package/dist/lib/redact.d.ts +21 -0
- package/dist/lib/route/cursors.d.ts +18 -0
- package/dist/lib/route/drain.d.ts +6 -0
- package/dist/lib/route/fields.d.ts +27 -0
- package/dist/lib/route/gates.d.ts +26 -0
- package/dist/lib/route/index.d.ts +18 -0
- package/dist/lib/route/options.d.ts +31 -0
- package/dist/lib/route/parse.d.ts +8 -0
- package/dist/lib/route/pr-review.d.ts +11 -0
- package/dist/lib/route/provider.d.ts +41 -0
- package/dist/lib/route/route-event.d.ts +23 -0
- package/dist/lib/route/route-tasks.d.ts +75 -0
- package/dist/lib/route/throttle.d.ts +47 -0
- package/dist/lib/route/todos-cli.d.ts +21 -0
- package/dist/lib/route/types.d.ts +88 -0
- package/dist/lib/run-artifacts.d.ts +17 -2
- package/dist/lib/run-envelope.d.ts +41 -0
- package/dist/lib/scheduler.d.ts +78 -2
- package/dist/lib/store.d.ts +63 -0
- package/dist/lib/store.js +1007 -287
- package/dist/lib/template-kit.d.ts +70 -0
- package/dist/lib/templates-custom.d.ts +34 -0
- package/dist/lib/templates.d.ts +13 -81
- package/dist/lib/workflow-runner.d.ts +2 -0
- package/dist/mcp/index.d.ts +3 -0
- package/dist/mcp/index.js +3231 -1382
- package/dist/runner/index.d.ts +9 -0
- package/dist/runner/index.js +295 -0
- package/dist/sdk/index.d.ts +29 -3
- package/dist/sdk/index.js +2743 -1044
- package/dist/test-helpers.d.ts +37 -0
- package/dist/types.d.ts +3 -1
- package/docs/DEPLOYMENT_MODES.md +140 -0
- package/docs/USAGE.md +102 -46
- package/package.json +23 -5
package/README.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
OpenLoops is a local CLI and daemon for persistent loops and workflows: scheduled or recurring work that survives process restarts and records every run.
|
|
4
4
|
|
|
5
|
+
Naming: the product is **OpenLoops**, published on npm as
|
|
6
|
+
[`@hasna/loops`](https://www.npmjs.com/package/@hasna/loops) and developed in the
|
|
7
|
+
[`hasna/loops`](https://github.com/hasna/loops) repository. The installed
|
|
8
|
+
binaries are `loops`, `loops-daemon`, `loops-api`, `loops-runner`, and
|
|
9
|
+
`loops-mcp`.
|
|
10
|
+
|
|
5
11
|
It supports deterministic command loops, JSON-defined workflows, and guarded CLI adapters for headless coding agents:
|
|
6
12
|
|
|
7
13
|
- `claude`
|
|
@@ -11,9 +17,49 @@ It supports deterministic command loops, JSON-defined workflows, and guarded CLI
|
|
|
11
17
|
- `opencode run`
|
|
12
18
|
- `codex exec`
|
|
13
19
|
|
|
20
|
+
## Deployment Modes
|
|
21
|
+
|
|
22
|
+
OpenLoops has three deployment modes:
|
|
23
|
+
|
|
24
|
+
- `local`: SQLite in `LOOPS_DATA_DIR` is authoritative and `loops-daemon` executes scheduled work.
|
|
25
|
+
- `self_hosted`: a user-operated `loops-api` control plane contract. This release exposes status/API/runner foundations; claim protocol and non-local execution are follow-up work.
|
|
26
|
+
- `cloud`: a hosted control-plane contract. This release exposes client/runner status only; hosted tenant auth and infrastructure live outside this package.
|
|
27
|
+
|
|
28
|
+
`local` is the default and requires no network, token, Postgres, or hosted
|
|
29
|
+
service. Set `LOOPS_MODE` or `HASNA_LOOPS_MODE` to `local`, `self_hosted`, or
|
|
30
|
+
`cloud` to choose explicitly. Without an explicit mode, `LOOPS_CLOUD_API_URL`
|
|
31
|
+
selects `cloud`, while `LOOPS_API_URL` or `LOOPS_DATABASE_URL` selects
|
|
32
|
+
`self_hosted`.
|
|
33
|
+
|
|
34
|
+
The public `@hasna/loops` package owns the local runtime, mode resolver,
|
|
35
|
+
self-hosted API contract, runner contract, SDK, MCP server, and CLI. Hosted
|
|
36
|
+
tenant auth, account administration, and infrastructure live outside this
|
|
37
|
+
package. Cloud mode is a public contract until a cloud-specific hosted URL and
|
|
38
|
+
cloud token are configured through `LOOPS_CLOUD_API_URL` plus
|
|
39
|
+
`LOOPS_CLOUD_TOKEN` or `HASNA_LOOPS_CLOUD_TOKEN`.
|
|
40
|
+
|
|
41
|
+
Useful status commands:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
loops mode
|
|
45
|
+
loops --json mode
|
|
46
|
+
loops self-hosted status
|
|
47
|
+
loops cloud status
|
|
48
|
+
loops-api status
|
|
49
|
+
loops-runner status
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
See [Deployment Modes](docs/DEPLOYMENT_MODES.md) for the full package boundary
|
|
53
|
+
and machine-placement contract.
|
|
54
|
+
|
|
14
55
|
## Install
|
|
15
56
|
|
|
16
|
-
|
|
57
|
+
**OpenLoops requires the [Bun](https://bun.sh) runtime (`bun >= 1.0`).** The
|
|
58
|
+
`loops`, `loops-daemon`, `loops-api`, `loops-runner`, and `loops-mcp` binaries
|
|
59
|
+
run with a `#!/usr/bin/env bun` shebang, so Bun must be on `PATH` even when the
|
|
60
|
+
package is installed with npm. Node.js is not a supported runtime.
|
|
61
|
+
|
|
62
|
+
From npm (with Bun installed):
|
|
17
63
|
|
|
18
64
|
```bash
|
|
19
65
|
npm install -g @hasna/loops
|
|
@@ -57,8 +103,9 @@ The package also exports the server factory for embedded hosts:
|
|
|
57
103
|
import { createLoopsMcpServer } from "@hasna/loops/mcp";
|
|
58
104
|
```
|
|
59
105
|
|
|
60
|
-
Available read tools include `loops_list`, `loops_show`, `
|
|
61
|
-
`loops_doctor`, `
|
|
106
|
+
Available read tools include `loops_list`, `loops_show`, `loops_runs`,
|
|
107
|
+
`loops_doctor`, `loops_workflows_list`, `loops_workflow_read`, and
|
|
108
|
+
`loops_workflow_validate`.
|
|
62
109
|
Resources are available at `loops://runtime` and `loops://tools`.
|
|
63
110
|
Those tools use the same `Store`, public redaction helpers, and workflow parser
|
|
64
111
|
as the CLI and SDK, so read output and validation behavior stay aligned across
|
|
@@ -66,15 +113,19 @@ surfaces.
|
|
|
66
113
|
|
|
67
114
|
Mutation tools are disabled by default. Start the server with
|
|
68
115
|
`LOOPS_MCP_ALLOW_MUTATIONS=true` only for a trusted local MCP host that should be
|
|
69
|
-
allowed to change loop state.
|
|
70
|
-
|
|
71
|
-
`
|
|
72
|
-
|
|
116
|
+
allowed to change loop state. The guarded mutation tools use canonical names:
|
|
117
|
+
`loops_pause`, `loops_resume`, `loops_stop`, `loops_run_now`, `loops_archive`,
|
|
118
|
+
`loops_unarchive`, `loops_create_command`, and `loops_create_workflow`.
|
|
119
|
+
Deprecated `loop_*` aliases are still registered where compatibility needs them,
|
|
120
|
+
but callers should use the `loops_*` names. Mutation tools do not require or
|
|
121
|
+
accept confirmation-string parameters; the server-side environment opt-in is the
|
|
122
|
+
gate. MCP `loops_run_now` schedules the loop for immediate daemon pickup; inline
|
|
123
|
+
execution remains CLI-only.
|
|
73
124
|
|
|
74
125
|
Keep host-affecting or long-running operations on the CLI: daemon
|
|
75
|
-
start/stop/install/logs, inline `run-now`, `tick`, loop
|
|
76
|
-
|
|
77
|
-
|
|
126
|
+
start/stop/install/logs, inline `run-now`, `tick`, loop deletion, workflow
|
|
127
|
+
create/migrate/cancel/recover, agent loop creation, template materialization,
|
|
128
|
+
and event-route drains.
|
|
78
129
|
|
|
79
130
|
## Create Loops
|
|
80
131
|
|
|
@@ -197,7 +248,9 @@ non-secret routing/configuration data.
|
|
|
197
248
|
|
|
198
249
|
## Goals
|
|
199
250
|
|
|
200
|
-
Add `--goal` to wrap a command, agent, or workflow loop in an AI-SDK orchestration layer. OpenLoops asks the configured model to create a flat DAG plan, executes ready nodes by
|
|
251
|
+
Add `--goal` to wrap a command, agent, or workflow loop in an AI-SDK orchestration layer. OpenLoops asks the configured model to create a flat DAG plan, then executes ready plan nodes by re-running the underlying target once per node. Each node run is parameterized with that node's objective: agent prompts get the goal and node objective appended, and every wrapped process receives `LOOPS_GOAL_NODE_KEY` and `LOOPS_GOAL_NODE_OBJECTIVE` in its environment. An adversarial achievement audit runs before the goal is marked complete.
|
|
252
|
+
|
|
253
|
+
The goal `autoExecute` mode is honored: `off` plans and persists the DAG without executing any nodes (the run reports the persisted plan), while `readyOnly` (the default) and `aiDirected` run the dependency-driven execution loop over ready nodes.
|
|
201
254
|
|
|
202
255
|
```bash
|
|
203
256
|
export OPENROUTER_API_KEY=...
|
|
@@ -213,7 +266,7 @@ loops create agent repo-fixer \
|
|
|
213
266
|
--goal-max-turns 5
|
|
214
267
|
```
|
|
215
268
|
|
|
216
|
-
Goal planning and validation use the Vercel AI SDK with `@openrouter/ai-sdk-provider`. Set `OPENROUTER_API_KEY`; optionally set `LOOPS_GOAL_BASE_URL` to point at a local gateway compatible with OpenRouter. Goal context is passed to wrapped commands and agents as `LOOPS_GOAL_ID`, `LOOPS_GOAL_OBJECTIVE`, and `
|
|
269
|
+
Goal planning and validation use the Vercel AI SDK with `@openrouter/ai-sdk-provider`. Set `OPENROUTER_API_KEY`; optionally set `LOOPS_GOAL_BASE_URL` to point at a local gateway compatible with OpenRouter. Goal context is passed to wrapped commands and agents as `LOOPS_GOAL_ID`, `LOOPS_GOAL_OBJECTIVE`, `LOOPS_GOAL_NODE_KEY`, and `LOOPS_GOAL_NODE_OBJECTIVE`.
|
|
217
270
|
|
|
218
271
|
If a resumed goal plan has no runnable nodes, failed run output includes a
|
|
219
272
|
structured `diagnostics` object with the concrete blocker and `owner`
|
|
@@ -224,7 +277,7 @@ Inspect configured and runtime goal state:
|
|
|
224
277
|
|
|
225
278
|
```bash
|
|
226
279
|
loops goal show <loop-or-goal-id>
|
|
227
|
-
loops goal
|
|
280
|
+
loops goal show <goal-run-id-or-loop-run-id>
|
|
228
281
|
```
|
|
229
282
|
|
|
230
283
|
Workflow JSON can also embed goals at the workflow or step level:
|
|
@@ -327,11 +380,11 @@ loops templates render todos-task-worker-verifier \
|
|
|
327
380
|
--var taskTitle="Fix parser" \
|
|
328
381
|
--var projectPath=/path/to/repo \
|
|
329
382
|
--var provider=codewith \
|
|
330
|
-
--var authProfilePool=
|
|
383
|
+
--var authProfilePool=account001,account002,account003 \
|
|
331
384
|
--var sandbox=workspace-write \
|
|
332
385
|
--var todosProjectPath=$HOME/.hasna/loops \
|
|
333
386
|
--var addDirs=$HOME/.hasna/todos,$HOME/.hasna/loops
|
|
334
|
-
loops
|
|
387
|
+
loops workflows create --template todos-task-worker-verifier \
|
|
335
388
|
--var taskId=<task-id> \
|
|
336
389
|
--var projectPath=/path/to/repo
|
|
337
390
|
loops templates render event-worker-verifier \
|
|
@@ -344,7 +397,7 @@ loops templates render bounded-agent-worker-verifier \
|
|
|
344
397
|
--var objective="Check docs drift and queue tasks for gaps" \
|
|
345
398
|
--var projectPath=/path/to/repo \
|
|
346
399
|
--var provider=codewith \
|
|
347
|
-
--var authProfilePool=
|
|
400
|
+
--var authProfilePool=account001,account002 \
|
|
348
401
|
--var sandbox=workspace-write \
|
|
349
402
|
--var worktreeMode=required
|
|
350
403
|
loops templates render pr-review \
|
|
@@ -429,30 +482,31 @@ loops templates show custom-report
|
|
|
429
482
|
loops templates render custom-report \
|
|
430
483
|
--var objective="Check docs drift" \
|
|
431
484
|
--var projectPath=/path/to/repo
|
|
432
|
-
loops
|
|
485
|
+
loops workflows create --template custom-report \
|
|
433
486
|
--var objective="Check docs drift" \
|
|
434
487
|
--var projectPath=/path/to/repo
|
|
435
488
|
```
|
|
436
489
|
|
|
437
490
|
Use `--source builtin`, `--source custom`, or `--source all` on
|
|
438
|
-
`list`, `show`, `render`, and
|
|
439
|
-
|
|
491
|
+
`templates list`, `templates show`, `templates render`, and
|
|
492
|
+
`workflows create --template` when automation needs an explicit source. Custom
|
|
493
|
+
template ids and names cannot override built-ins.
|
|
440
494
|
Custom templates fail closed for `danger-full-access`, dangerous passthrough
|
|
441
495
|
arguments, and implicit Codewith/Codex full-access defaults. If a custom
|
|
442
496
|
Codewith/Codex template uses `permissionMode: "bypass"`, it must also set
|
|
443
497
|
`sandbox` to `workspace-write` or `read-only`. Use built-in templates with
|
|
444
498
|
explicit break-glass handling for emergency workflows that need full access.
|
|
445
499
|
|
|
446
|
-
For event-driven task automation, `loops
|
|
500
|
+
For event-driven task automation, `loops routes create todos-task` reads a
|
|
447
501
|
Hasna event envelope from stdin or `HASNA_EVENT_JSON`, records a
|
|
448
502
|
`WorkflowInvocation`, upserts an admission work item, and admits that work item
|
|
449
503
|
into a deduped one-shot workflow loop when route capacity allows:
|
|
450
504
|
|
|
451
505
|
```bash
|
|
452
|
-
cat task-created-event.json | loops
|
|
506
|
+
cat task-created-event.json | loops routes create todos-task \
|
|
453
507
|
--template task-lifecycle \
|
|
454
508
|
--provider codewith \
|
|
455
|
-
--auth-profile-pool
|
|
509
|
+
--auth-profile-pool account001,account002,account003 \
|
|
456
510
|
--permission-mode bypass \
|
|
457
511
|
--sandbox workspace-write \
|
|
458
512
|
--todos-project "$HOME/.hasna/loops" \
|
|
@@ -485,7 +539,7 @@ selected.
|
|
|
485
539
|
loops routes drain todos-task \
|
|
486
540
|
--dry-run \
|
|
487
541
|
--provider-rule area=frontend:claude:claude-ui-a,claude-ui-b \
|
|
488
|
-
--provider-rule area=backend:codewith:
|
|
542
|
+
--provider-rule area=backend:codewith:account001,account002 \
|
|
489
543
|
--worktree-mode required
|
|
490
544
|
```
|
|
491
545
|
|
|
@@ -522,9 +576,9 @@ For other Hasna apps that expose `@hasna/events` webhooks, use the generic
|
|
|
522
576
|
handler:
|
|
523
577
|
|
|
524
578
|
```bash
|
|
525
|
-
cat event.json | loops
|
|
579
|
+
cat event.json | loops routes create generic \
|
|
526
580
|
--provider codewith \
|
|
527
|
-
--auth-profile-pool
|
|
581
|
+
--auth-profile-pool account001,account002,account003 \
|
|
528
582
|
--permission-mode bypass \
|
|
529
583
|
--sandbox workspace-write \
|
|
530
584
|
--project-path /path/to/repo \
|
|
@@ -567,7 +621,7 @@ loops routes requeue <work-item-id> --reason "fixed upstream blocker"
|
|
|
567
621
|
loops routes invocations
|
|
568
622
|
```
|
|
569
623
|
|
|
570
|
-
For
|
|
624
|
+
For OSS task-created routing, use a deterministic drain instead of tmux
|
|
571
625
|
dispatch:
|
|
572
626
|
|
|
573
627
|
```bash
|
|
@@ -575,10 +629,10 @@ loops routes schedule todos-task oss-task-route-drain \
|
|
|
575
629
|
--every 5m \
|
|
576
630
|
--todos-project "$HOME/.hasna/loops" \
|
|
577
631
|
--template task-lifecycle \
|
|
578
|
-
--project-path-prefix /
|
|
632
|
+
--project-path-prefix "$HOME/workspace/example/opensource" \
|
|
579
633
|
--tags auto:route \
|
|
580
634
|
--provider codewith \
|
|
581
|
-
--auth-profile-pool
|
|
635
|
+
--auth-profile-pool account001,account002,account003 \
|
|
582
636
|
--add-dir "$HOME/.hasna/todos,$HOME/.hasna/loops" \
|
|
583
637
|
--project-group oss \
|
|
584
638
|
--max-dispatch 2 \
|
|
@@ -621,7 +675,7 @@ import { openAutomationsRuntimeBinding } from "@hasna/loops";
|
|
|
621
675
|
|
|
622
676
|
const binding = openAutomationsRuntimeBinding();
|
|
623
677
|
console.log(binding.handoff); // "claim-queue"
|
|
624
|
-
console.log(binding.eventHandoff.handlerCommand); // "loops
|
|
678
|
+
console.log(binding.eventHandoff.handlerCommand); // "loops routes create generic"
|
|
625
679
|
```
|
|
626
680
|
|
|
627
681
|
The claim-queue handoff uses the OpenAutomations CLI or SDK:
|
|
@@ -634,18 +688,18 @@ automations queue fail <action-id> --runner open-loops:<worker-id> --code <code>
|
|
|
634
688
|
|
|
635
689
|
For explicit event workflow routing, OpenAutomations can export the normalized
|
|
636
690
|
event envelope and OpenLoops can consume it through the existing generic event
|
|
637
|
-
|
|
691
|
+
route:
|
|
638
692
|
|
|
639
693
|
```bash
|
|
640
694
|
automations --json webhooks event <route> --body-json '<json>' \
|
|
641
|
-
| loops --json
|
|
695
|
+
| loops --json routes create generic
|
|
642
696
|
```
|
|
643
697
|
|
|
644
698
|
This is not automation materialization in OpenLoops. It is an explicit
|
|
645
699
|
event-envelope workflow handoff: OpenAutomations owns deterministic automation
|
|
646
700
|
specs, webhook normalization, queue state, approvals, DLQ, and replay; OpenLoops
|
|
647
701
|
owns agent workflow invocation after the operator routes the envelope to
|
|
648
|
-
`loops
|
|
702
|
+
`loops routes create generic`.
|
|
649
703
|
|
|
650
704
|
Do not store automation specs in OpenLoops, infer automation triggers from event
|
|
651
705
|
transport alone, or replace the OpenAutomations queue with loop/workflow rows.
|
|
@@ -660,59 +714,15 @@ write OpenLoops SQLite rows directly. The stable contract should be an
|
|
|
660
714
|
idempotent CLI/SDK upsert that accepts a fully rendered one-shot workflow loop
|
|
661
715
|
request and returns durable refs.
|
|
662
716
|
|
|
663
|
-
|
|
717
|
+
The canonical `WorkflowUpsertRequest` / `WorkflowUpsertResult` shapes and their
|
|
718
|
+
required semantics (dry-run/preflight/commit modes, `idempotencyKey` +
|
|
719
|
+
`specHash` idempotency, dispatch behavior, and redaction-before-persistence)
|
|
720
|
+
are specified in `docs/AUTOMATION_RUNTIME_DESIGN.md`; this README intentionally
|
|
721
|
+
does not duplicate that spec.
|
|
664
722
|
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
source: { kind: "action" | "automation" | "event"; id: string; dedupeKey?: string };
|
|
669
|
-
subject: { kind: "repo" | "task" | "pr" | "run"; id?: string; path?: string; url?: string };
|
|
670
|
-
workflow: { name: string; description?: string; steps: WorkflowStepInput[] };
|
|
671
|
-
loop: { name: string; schedule: { type: "once"; at: string }; machine?: LoopMachineRef };
|
|
672
|
-
route?: { projectPath?: string; projectGroup?: string; concurrencyGroup?: string };
|
|
673
|
-
execution?: AutomationExecutionPolicy;
|
|
674
|
-
mode?: "dry-run" | "preflight" | "commit";
|
|
675
|
-
dispatch?: "schedule" | "run-now" | "none";
|
|
676
|
-
};
|
|
677
|
-
|
|
678
|
-
type WorkflowUpsertResult = {
|
|
679
|
-
ok: boolean;
|
|
680
|
-
dryRun: boolean;
|
|
681
|
-
idempotencyKey: string;
|
|
682
|
-
specHash: string;
|
|
683
|
-
refs: {
|
|
684
|
-
workflowId?: string;
|
|
685
|
-
loopId?: string;
|
|
686
|
-
invocationId?: string;
|
|
687
|
-
workItemId?: string;
|
|
688
|
-
runId?: string;
|
|
689
|
-
manifestPath?: string;
|
|
690
|
-
};
|
|
691
|
-
action: "created" | "updated" | "reused" | "rejected";
|
|
692
|
-
preflight?: { ok: boolean; checks: unknown[]; error?: string };
|
|
693
|
-
};
|
|
694
|
-
```
|
|
695
|
-
|
|
696
|
-
Required semantics:
|
|
697
|
-
|
|
698
|
-
- `mode="dry-run"` validates, canonicalizes, hashes, and returns the same JSON
|
|
699
|
-
shape without mutating OpenLoops state.
|
|
700
|
-
- `mode="preflight"` additionally checks provider binaries, machine routing,
|
|
701
|
-
accounts/auth profiles, prompt files, and workflow target compatibility before
|
|
702
|
-
commit.
|
|
703
|
-
- `mode="commit"` is idempotent on `idempotencyKey` plus `specHash`: identical
|
|
704
|
-
requests return existing refs; changed specs create a new workflow version or
|
|
705
|
-
one-shot loop while preserving previous run history.
|
|
706
|
-
- `dispatch="schedule"` stores a one-shot loop for the daemon; `run-now` claims
|
|
707
|
-
an immediate manual slot; `none` only materializes refs for another owner to
|
|
708
|
-
trigger later.
|
|
709
|
-
- All persisted output is redacted before storage, and returned refs are enough
|
|
710
|
-
for the caller to inspect, cancel, replay, or resolve the run without querying
|
|
711
|
-
SQLite directly.
|
|
712
|
-
|
|
713
|
-
See `docs/AUTOMATION_RUNTIME_DESIGN.md` for the planned DLQ/dead-letter
|
|
714
|
-
lifecycle, including `loops dlq list/show/replay/resolve`, idempotent replay
|
|
715
|
-
keys, and compatibility rules for `@hasna/actions`.
|
|
723
|
+
The same design doc covers the planned DLQ/dead-letter lifecycle, including
|
|
724
|
+
`loops dlq list/show/replay/resolve`, idempotent replay keys, and compatibility
|
|
725
|
+
rules for `@hasna/actions`.
|
|
716
726
|
|
|
717
727
|
The same design doc also defines the planned strict automation execution mode:
|
|
718
728
|
minimal env inheritance, scoped secret refs, enforced allowlists,
|
|
@@ -879,4 +889,4 @@ The adapters intentionally use provider command surfaces instead of pretending e
|
|
|
879
889
|
- `--variant` is provider-specific reasoning/model effort. Claude maps it to `--effort`, Codewith/Codex map it to `model_reasoning_effort`, and OpenCode/AICopilot pass `--variant`.
|
|
880
890
|
- Daemon and scheduled runs prepend common user executable directories such as `~/.local/bin` and `~/.bun/bin` before resolving provider CLIs.
|
|
881
891
|
|
|
882
|
-
For production loops that can mutate repos,
|
|
892
|
+
For production loops that can mutate repos, use disposable worktrees (`--worktree-mode required` / `worktreeMode=required`) and explicit prompts that name allowed write scope. Worktrees are executor-enforced: when a target carries worktree metadata, the executor prepares and enters the git worktree before spawning the child process, records the worktree it entered, and with `mode=required` fails the run closed instead of falling back to the original checkout when preparation fails. Remote machine runs with a required worktree are verified fail-closed on the remote side before the target executes.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
export declare function apiStatus(): {
|
|
3
|
+
ok: boolean;
|
|
4
|
+
service: string;
|
|
5
|
+
status: import("../index.js").LoopDeploymentStatus;
|
|
6
|
+
};
|
|
7
|
+
export declare function createLoopsApiServer(opts?: {
|
|
8
|
+
host?: string;
|
|
9
|
+
port?: number;
|
|
10
|
+
}): Bun.Server<undefined>;
|
|
11
|
+
export declare function main(argv?: string[]): Promise<void>;
|