delegation-layer 0.2.0 → 0.3.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.
Files changed (31) hide show
  1. package/README.md +7 -0
  2. package/docs/assets/delegation-layer-hero.jpg +0 -0
  3. package/package.json +1 -1
  4. package/plugins/delegation-layer/.claude-plugin/plugin.json +1 -1
  5. package/plugins/delegation-layer/.codex-plugin/plugin.json +1 -1
  6. package/plugins/delegation-layer/skills/agent-integration/SKILL.md +16 -8
  7. package/plugins/delegation-layer/skills/agent-integration/evals/evals.json +23 -3
  8. package/plugins/delegation-layer/skills/agent-integration/examples/json-results.md +5 -2
  9. package/plugins/delegation-layer/skills/agent-integration/examples/managed-workspace.md +50 -17
  10. package/plugins/delegation-layer/skills/agent-integration/examples/read-only-task.md +3 -1
  11. package/plugins/delegation-layer/skills/agent-integration/references/ccr.md +7 -3
  12. package/plugins/delegation-layer/skills/agent-integration/references/collaboration.md +2 -2
  13. package/plugins/delegation-layer/skills/agent-integration/references/command-reference.md +152 -47
  14. package/plugins/delegation-layer/skills/agent-integration/references/continuation.md +7 -4
  15. package/plugins/delegation-layer/skills/agent-integration/references/interaction.md +6 -5
  16. package/plugins/delegation-layer/skills/agent-integration/references/result-handling.md +66 -3
  17. package/plugins/delegation-layer/skills/agent-integration/references/routing-rule.json +1 -1
  18. package/plugins/delegation-layer/skills/agent-integration/references/workspaces.md +18 -14
  19. package/skills/agent-integration/SKILL.md +16 -8
  20. package/skills/agent-integration/evals/evals.json +23 -3
  21. package/skills/agent-integration/examples/json-results.md +5 -2
  22. package/skills/agent-integration/examples/managed-workspace.md +50 -17
  23. package/skills/agent-integration/examples/read-only-task.md +3 -1
  24. package/skills/agent-integration/references/ccr.md +7 -3
  25. package/skills/agent-integration/references/collaboration.md +2 -2
  26. package/skills/agent-integration/references/command-reference.md +152 -47
  27. package/skills/agent-integration/references/continuation.md +7 -4
  28. package/skills/agent-integration/references/interaction.md +6 -5
  29. package/skills/agent-integration/references/result-handling.md +66 -3
  30. package/skills/agent-integration/references/routing-rule.json +1 -1
  31. package/skills/agent-integration/references/workspaces.md +18 -14
@@ -10,7 +10,7 @@
10
10
  {
11
11
  "name": "normal-dispatch",
12
12
  "prompt": "Run one bounded task through the available agent provider.",
13
- "expected": ["dispatch --auto", "--json", "save task_id", "status", "collect"]
13
+ "expected": ["dispatch --auto", "omit --root on ordinary commands", "--json", "save task_id", "status", "collect"]
14
14
  },
15
15
  {
16
16
  "name": "model-discovery-when-needed",
@@ -68,9 +68,29 @@
68
68
  "expected": ["use status with returned task_id", "read saved dispatch response if needed", "do not dispatch again to print an exit code", "exactly one admitted task for the assignment"]
69
69
  },
70
70
  {
71
- "name": "supplied-root-across-shell-calls",
71
+ "name": "ambient-root-ignored-across-shell-calls",
72
72
  "prompt": "DELEGATE_ROOT is already set. Consult a separate external agent and answer its questions; each shell tool call starts a new shell.",
73
- "expected": ["use supplied DELEGATE_ROOT on dispatch, status, collect, reply, steer, and continue", "resolve the same root in each shell call", "no invented task-specific root"]
73
+ "expected": ["omit --root on dispatch, status, collect, reply, steer, and continue", "ambient DELEGATE_ROOT has no root-selection authority", "CLI resolves its default in the same user/configuration context", "no assembled default, shell fallback, sample path, or per-task root"]
74
+ },
75
+ {
76
+ "name": "ordinary-root-from-another-project",
77
+ "prompt": "DELEGATE_ROOT is unset. An admitted task was dispatched without --root in project A. Observe and continue it from project B in the same user/configuration context.",
78
+ "expected": ["omit --root on status, collect, and continue", "use the recorded task ID", "CLI default is independent of project cwd", "no path guessed from project A or B", "no search across roots"]
79
+ },
80
+ {
81
+ "name": "explicit-root-across-shell-calls",
82
+ "prompt": "For this isolated test, I explicitly choose the state root /state/custom with spaces. Consult a separate external agent and answer its questions; each shell tool call starts a new shell.",
83
+ "expected": ["pass --root with the exact single argument /state/custom with spaces on dispatch, status, collect, reply, steer, and continue", "quote the root in shell commands", "save and reassign absolute brief and response paths in each needed shell invocation", "no ambient variable or fallback overrides the explicit choice"]
84
+ },
85
+ {
86
+ "name": "historical-root-continuation",
87
+ "prompt": "An eligible predecessor task has recorded historical root /state/legacy with spaces. Continue that exact task and collect its successor. The current CLI default is different.",
88
+ "expected": ["pass the exact recorded --root argument /state/legacy with spaces on continue, status, and collect", "use the exact predecessor and returned successor IDs", "no fresh dispatch", "do not move or search for the task in the default root"]
89
+ },
90
+ {
91
+ "name": "ordinary-schedule-root",
92
+ "prompt": "Create a recurring task in this project, then inspect its definition, history, and execution from another project in the same user/configuration context. No custom state root was requested.",
93
+ "expected": ["omit --root on schedule create, list, show, history, and execution", "keep the definition's own project --cwd", "no per-project root", "do not start a persistent scheduler inside the agent task", "forward any returned scheduler.serve_command argv intact"]
74
94
  },
75
95
  {
76
96
  "name": "pending-without-questions",
@@ -1,8 +1,11 @@
1
1
  # JSON decision sketch
2
2
 
3
+ Use the created task's exact ID as `TASK_ID` and follow the main skill's
4
+ [root rule](../SKILL.md#3-prepare-separate-paths-and-a-finite-brief).
5
+
3
6
  ```sh
4
- delegate --root "${DELEGATE_ROOT:-$HOME/delegation-state}" status "$TASK_ID" --json
5
- delegate --root "${DELEGATE_ROOT:-$HOME/delegation-state}" collect "$TASK_ID" --watch 5s --json
7
+ delegate status TASK_ID --json
8
+ delegate collect TASK_ID --watch 5s --json
6
9
  ```
7
10
 
8
11
  Apply [result handling](../references/result-handling.md) to each response and
@@ -3,14 +3,18 @@
3
3
  Use this example for independent write work that should be isolated in a
4
4
  retained Git worktree. The source must be a Git checkout and the state root
5
5
  must remain outside provider-writable workspaces.
6
+ Commands use the CLI default under the main skill's
7
+ [root rule](../SKILL.md#3-prepare-separate-paths-and-a-finite-brief); preserve any
8
+ explicit custom or recorded historical root on all related commands.
6
9
 
7
10
  ```sh
8
11
  SOURCE="$PWD"
9
- BRIEF="$(mktemp)"
10
- RESPONSE="$(mktemp)"
12
+ BRIEF="$(mktemp)" || exit 1
13
+ RESPONSE="$(mktemp)" || exit 1
11
14
  printf '%s\n' 'Implement the requested change and report the files changed.' >"$BRIEF"
15
+ printf 'Saved response: %s\n' "$RESPONSE"
12
16
 
13
- if delegate --root "${DELEGATE_ROOT:-$HOME/delegation-state}" dispatch --auto \
17
+ if delegate dispatch --auto \
14
18
  --brief "$BRIEF" --cwd "$SOURCE" \
15
19
  --permission workspace-write --isolation git-worktree \
16
20
  --base HEAD --workspace-budget 5m --budget 30m --json >"$RESPONSE"; then
@@ -26,28 +30,51 @@ Read the saved JSON before running another command. When
26
30
  `task_record: "created"`, use its `task_id` as `TASK_ID` below. When no task
27
31
  was created, follow the [result decisions](../references/result-handling.md#managed-workspace-results);
28
32
  do not run task status or collection against that nonexistent record.
33
+ Each later block is a separate shell invocation. Replace `ABS_SAVED_RESPONSE`
34
+ with the printed absolute response path and the ID placeholders with the actual
35
+ returned IDs; reassign the path in each invocation.
29
36
 
30
37
  ```sh
31
- if delegate --root "${DELEGATE_ROOT:-$HOME/delegation-state}" status TASK_ID --json >"$RESPONSE.status"; then
38
+ RESPONSE="ABS_SAVED_RESPONSE"
39
+ if delegate status TASK_ID --json >"$RESPONSE.status"; then
32
40
  status_exit=0
33
41
  else
34
42
  status_exit=$?
35
43
  fi
36
44
  printf '%s\n' "$status_exit" >"$RESPONSE.status.exit"
37
- if delegate --root "${DELEGATE_ROOT:-$HOME/delegation-state}" collect TASK_ID --watch 5s --json >"$RESPONSE.collect"; then
45
+ cat "$RESPONSE.status"
46
+ ```
47
+
48
+ Read the saved status JSON and apply
49
+ [Observe and collect](../references/result-handling.md#observe-and-collect)
50
+ before running another command. Run the collection below only when that
51
+ guidance calls for it.
52
+
53
+ ```sh
54
+ RESPONSE="ABS_SAVED_RESPONSE"
55
+ if delegate collect TASK_ID --watch 5s --json >"$RESPONSE.collect"; then
38
56
  collect_exit=0
39
57
  else
40
58
  collect_exit=$?
41
59
  fi
42
60
  printf '%s\n' "$collect_exit" >"$RESPONSE.collect.exit"
61
+ cat "$RESPONSE.collect"
43
62
  ```
44
63
 
45
- Continue observing that created task when collection exits `3`. Wait for the
46
- workspace to return to `state: retained` and inspect its final capture. Only
47
- after the Lead explicitly chooses release, run:
64
+ Apply that same decision order to the collection JSON before treating exit `3`
65
+ as pending. Cancellation, `failure.code: "task_cancelled"` or
66
+ `failure.next_action: "stop_and_report"` ends pending polling; do not continue
67
+ the task or dispatch a replacement. Bounded
68
+ [failure diagnosis](../references/result-handling.md#failure-diagnosis)
69
+ remains available. Keep observing the same task with a finite watch only when
70
+ the canonical guidance calls for it.
71
+
72
+ Before release, wait for the workspace to return to `state: retained` and inspect
73
+ its final capture. Only after the Lead explicitly chooses release, run:
48
74
 
49
75
  ```sh
50
- if delegate --root "${DELEGATE_ROOT:-$HOME/delegation-state}" workspace release WORKSPACE_ID \
76
+ RESPONSE="ABS_SAVED_RESPONSE"
77
+ if delegate workspace release WORKSPACE_ID \
51
78
  --budget 5m --json >"$RESPONSE.release"; then
52
79
  release_exit=0
53
80
  else
@@ -62,10 +89,11 @@ Follow the same result decisions rather than assuming either response is
62
89
  completed cleanup.
63
90
 
64
91
  Save each response and exit code once. A created task is observed with
65
- `status` first and collected in the foreground. Exit `3` means pending, not
66
- success; continue observing the same task. The Lead reviews the capture and
67
- owns landing any changes. `workspace release` is explicit; no automatic
68
- apply, commit, branch merge, TTL eviction, or provider-CLI fallback occurs.
92
+ `status` first and collected in the foreground, following the canonical
93
+ observation decisions before each next step. Exit `3` alone is not a reason
94
+ to keep polling. The Lead reviews the capture and owns landing any changes.
95
+ `workspace release` is explicit; no automatic apply, commit, branch merge,
96
+ TTL eviction, or provider-CLI fallback occurs.
69
97
 
70
98
  ## Fork from a checkpoint
71
99
 
@@ -77,8 +105,9 @@ owns every response decision.
77
105
 
78
106
  ```sh
79
107
  SOURCE="$PWD"
80
- RESPONSE="$(mktemp)"
81
- if delegate --root "${DELEGATE_ROOT:-$HOME/delegation-state}" checkpoint create \
108
+ RESPONSE="$(mktemp)" || exit 1
109
+ printf 'Saved response: %s\n' "$RESPONSE"
110
+ if delegate checkpoint create \
82
111
  --cwd "$SOURCE" --budget 5m --json >"$RESPONSE.checkpoint"; then
83
112
  checkpoint_exit=0
84
113
  else
@@ -91,9 +120,12 @@ cat "$RESPONSE.checkpoint"
91
120
  Exit `3` with `checkpoint.id` and `next_action: "watch_checkpoint"` means the
92
121
  request was accepted, not captured. Use that `checkpoint.id` as
93
122
  `CHECKPOINT_ID`. Do not run `create` again.
123
+ For the later checkpoint blocks, replace `ABS_SAVED_RESPONSE` with the absolute
124
+ response path printed by this checkpoint invocation.
94
125
 
95
126
  ```sh
96
- if delegate --root "${DELEGATE_ROOT:-$HOME/delegation-state}" checkpoint status CHECKPOINT_ID \
127
+ RESPONSE="ABS_SAVED_RESPONSE"
128
+ if delegate checkpoint status CHECKPOINT_ID \
97
129
  --watch 30s --json >"$RESPONSE.checkpoint.status"; then
98
130
  checkpoint_status_exit=0
99
131
  else
@@ -112,7 +144,8 @@ dispatch example, replacing `--base HEAD` with `--base COMMIT_OID`. Report a
112
144
  When the Lead no longer needs the checkpoint, remove it explicitly:
113
145
 
114
146
  ```sh
115
- if delegate --root "${DELEGATE_ROOT:-$HOME/delegation-state}" checkpoint remove CHECKPOINT_ID \
147
+ RESPONSE="ABS_SAVED_RESPONSE"
148
+ if delegate checkpoint remove CHECKPOINT_ID \
116
149
  --budget 5m --json >"$RESPONSE.checkpoint.remove"; then
117
150
  checkpoint_remove_exit=0
118
151
  else
@@ -2,6 +2,8 @@
2
2
 
3
3
  Run from the intended workspace, outside Delegate's private state root.
4
4
  Use a catalog provider ID in place of `--auto` when a destination was named.
5
+ This example uses the CLI default under the main skill's
6
+ [root rule](../SKILL.md#3-prepare-separate-paths-and-a-finite-brief).
5
7
  Prepare paths and dispatch in this same shell invocation:
6
8
 
7
9
  ```sh
@@ -13,7 +15,7 @@ Inspect the workspace and summarize the current test failures. Do not edit files
13
15
  You are the assigned worker; perform this task without delegating it.
14
16
  EOF
15
17
  printf 'Saved response: %s\n' "$RESPONSE"
16
- if delegate --root "${DELEGATE_ROOT:-$HOME/delegation-state}" dispatch --auto \
18
+ if delegate dispatch --auto \
17
19
  --brief "$BRIEF" --cwd "$WORKSPACE" \
18
20
  --permission read-only --budget 30m --json >"$RESPONSE"; then
19
21
  dispatch_exit=0
@@ -3,6 +3,9 @@
3
3
  Use this reference when asked to consult Claude Code Router (CCR), use one of
4
4
  its configured model aliases, or compare its models with other harnesses.
5
5
  CCR runs Claude Code against a configured third-party or local provider.
6
+ Use the CLI default under the main skill's
7
+ [root rule](../SKILL.md#3-prepare-separate-paths-and-a-finite-brief); preserve any
8
+ explicit custom or recorded historical root for model discovery and dispatch.
6
9
 
7
10
  1. Resolve CCR through `delegate providers --json`; its profile is `ccr:print`.
8
11
  2. Preserve an explicitly requested CCR alias as `--model ALIAS`. Do not replace
@@ -12,9 +15,10 @@ CCR runs Claude Code against a configured third-party or local provider.
12
15
  Choose a suitable configured alias from the available metadata and report
13
16
  the choice. Clarify when the intended model remains ambiguous. If discovery
14
17
  is unavailable and no alias is known, report the blocker; do not guess.
15
- 4. Dispatch through Delegate with `--provider ccr:print --model ALIAS`, the brief,
16
- workspace, permission, finite budget, and `--json`. Use the normal status,
17
- collect, and continuation procedure from the main skill.
18
+ 4. Dispatch through Delegate with
19
+ `--provider ccr:print --model ALIAS`, the brief, workspace, permission, finite
20
+ budget, and `--json`. Use the normal status, collect, and continuation procedure
21
+ from the main skill.
18
22
 
19
23
  CCR requires an explicit alias. Unspecified external collaboration still uses
20
24
  `dispatch --auto`; do not prefer CCR unless the request calls for it. Multiple
@@ -45,7 +45,7 @@ RECEIPTS="$(mktemp -d)" || exit 1
45
45
  # Set these absolute paths and catalog IDs in this same tool invocation.
46
46
  # BRIEF_A and BRIEF_B contain the real independent assignments.
47
47
  (
48
- if delegate --root "${DELEGATE_ROOT:-$HOME/delegation-state}" dispatch --provider "$PROVIDER_A" \
48
+ if delegate dispatch --provider "$PROVIDER_A" \
49
49
  --brief "$BRIEF_A" --cwd "$WORKSPACE_A" \
50
50
  --permission read-only --budget 30m --json \
51
51
  >"$RECEIPTS/review-a.json" 2>"$RECEIPTS/review-a.stderr"; then
@@ -56,7 +56,7 @@ RECEIPTS="$(mktemp -d)" || exit 1
56
56
  printf '%s\n' "$dispatch_exit" >"$RECEIPTS/review-a.exit"
57
57
  ) &
58
58
  (
59
- if delegate --root "${DELEGATE_ROOT:-$HOME/delegation-state}" dispatch --provider "$PROVIDER_B" \
59
+ if delegate dispatch --provider "$PROVIDER_B" \
60
60
  --brief "$BRIEF_B" --cwd "$WORKSPACE_B" \
61
61
  --permission read-only --budget 30m --json \
62
62
  >"$RECEIPTS/review-b.json" 2>"$RECEIPTS/review-b.stderr"; then
@@ -22,15 +22,17 @@ The main skill owns [root selection](../SKILL.md#3-prepare-separate-paths-and-a-
22
22
  | `workspace`, `checkpoint` | [Git resources](workspaces.md) | Helpers, not provider turns |
23
23
  | `teams` | [Optional configuration and Member selection](#teams) | None |
24
24
  | `schedule` | [Recurring definitions](#schedules), [history and execution evidence](#schedule-history-and-execution) | None |
25
- | `scheduler run` | [Independent scheduler](#scheduler-runtime) | Admits due occurrences through normal dispatch |
25
+ | `scheduler serve/status/stop` (when supported), `scheduler run` | [User-started host and compatibility runtime](#scheduler-runtime) | Due occurrences use normal dispatch; status/stop do not launch providers |
26
26
 
27
- Prefix every task command with `delegate --root ROOT`, using the same
28
- explicit root across invocations.
27
+ The commands below use the CLI default and omit `--root`. The advanced override
28
+ syntax is `delegate --root ABS COMMAND ...`; use it only for an explicitly
29
+ supplied or already recorded custom or historical root, preserved exactly under
30
+ the main skill's [root rule](../SKILL.md#3-prepare-separate-paths-and-a-finite-brief).
29
31
 
30
32
  ## Dispatch
31
33
 
32
34
  ```text
33
- delegate --root ROOT dispatch [--auto | --provider ID] --brief FILE \
35
+ delegate dispatch [--auto | --provider ID] --brief FILE \
34
36
  --cwd ABS [--id TASK_ID] [--permission MODE] [--budget DURATION] \
35
37
  [--model MODEL] [--effort EFFORT] [--native-timeout DURATION] \
36
38
  [--interactive] [--review-target TARGET] [--resume-task TASK_ID] \
@@ -170,8 +172,8 @@ setup, even when there is no matching Team or project default.
170
172
  After a task record is created, inspect the same ID and root:
171
173
 
172
174
  ```sh
173
- delegate --root "${DELEGATE_ROOT:-$HOME/delegation-state}" status TASK_ID --json
174
- delegate --root "${DELEGATE_ROOT:-$HOME/delegation-state}" collect TASK_ID --watch 5s --json
175
+ delegate status TASK_ID --json
176
+ delegate collect TASK_ID --watch 5s --json
175
177
  ```
176
178
 
177
179
  Dispatch/status/collect optionally expose top-level `team`, the admitted
@@ -186,23 +188,30 @@ not prove admission, provider readiness or successful publication.
186
188
 
187
189
  ## Schedules
188
190
 
189
- The management commands below save and inspect definitions. They do not start
190
- a scheduler, launch a provider, or prove that a task ran. Start the
191
- [scheduler](#scheduler-runtime) separately to execute due occurrences.
191
+ The management commands below save and inspect definitions; they do not start a
192
+ scheduler, launch a provider themselves, or prove that a task ran. On builds with
193
+ [host controls](#scheduler-runtime), create/resume check for a compatible live
194
+ host after saving. When a response includes `scheduler.serve_command`, retain
195
+ the saved ID and give that argv array intact to the user for an independent
196
+ terminal or tmux pane. For run-only builds, use the
197
+ [compatibility instructions](#scheduler-runtime); do not expect those host fields.
198
+ Never start a persistent scheduler inside the agent's bounded task or submit
199
+ another create to obtain a running scheduler.
200
+ See [definition and host results](result-handling.md#schedule-definition-and-host-results).
192
201
 
193
202
  ```text
194
- delegate --root ROOT schedule create --brief FILE --cwd ABS \
203
+ delegate schedule create --brief FILE --cwd ABS \
195
204
  [--auto | --provider ID] --cron 'MIN HOUR DOM MONTH DOW' \
196
205
  [--timezone ZONE] [--id SCHEDULE_ID] [--model MODEL] [--effort EFFORT] \
197
206
  [--permission MODE] [--budget DURATION] [--native-timeout DURATION] \
198
207
  [--review-target TARGET] \
199
208
  [--team-scope user|project --team TEAM_ID --member MEMBER_ID] \
200
209
  [--project-root ABS] --json
201
- delegate --root ROOT schedule list [--after SCHEDULE_ID] [--limit N] --json
202
- delegate --root ROOT schedule show SCHEDULE_ID --json
203
- delegate --root ROOT schedule pause SCHEDULE_ID --json
204
- delegate --root ROOT schedule resume SCHEDULE_ID --json
205
- delegate --root ROOT schedule delete SCHEDULE_ID --json
210
+ delegate schedule list [--after SCHEDULE_ID] [--limit N] --json
211
+ delegate schedule show SCHEDULE_ID --json
212
+ delegate schedule pause SCHEDULE_ID --json
213
+ delegate schedule resume SCHEDULE_ID --json
214
+ delegate schedule delete SCHEDULE_ID --json
206
215
  ```
207
216
 
208
217
  - Requested provider options remain as supplied, including omissions. Creation
@@ -235,17 +244,23 @@ delegate --root ROOT schedule delete SCHEDULE_ID --json
235
244
  - Definitions are immutable. Pause blocks future admissions; resume skips the
236
245
  interval from the stored cursor through now without catch-up. A clock behind
237
246
  the cursor leaves that cursor unchanged. Delete is terminal and retains
238
- history. Pause/delete do not cancel an active occurrence.
239
- - Only create initializes absent schedule storage. An absent store lists as
240
- empty; show/state commands report not found. List defaults to 50 rows, at most
241
- 100, including paused/deleted definitions. Use the returned cursor to page.
247
+ history. Pause/delete do not cancel an active occurrence or require a live
248
+ host. Create/resume preserve the saved definition even when the host is
249
+ absent, starting, in backoff or otherwise not confirmed ready.
250
+ - Among schedule management commands, only create initializes absent storage.
251
+ An absent store lists as empty; show/state commands report not found. List
252
+ defaults to 50 rows, at most 100, including paused/deleted definitions. Use the
253
+ returned cursor to page.
242
254
  - Create/state responses are compact. Show returns saved requested choices and
243
255
  brief metadata, not brief contents, with a 2 MiB response limit. Keep the ID
244
256
  when output or storage reports uncertainty; inspect it with show rather than
245
257
  submitting another create. Reusing an existing ID conflicts.
246
258
 
247
- Handler results use exit `0` for success/advisory warnings, `2` for invalid
248
- input/state transitions and `1` for not-found, conflicts or operational failures.
259
+ Handler results use exit `0` for confirmed completion/advisory warnings, `2` for
260
+ invalid input/state transitions and `1` for not-found, conflicts or operational
261
+ failures. On builds with host controls, create/resume also use exit `3` for saved
262
+ definitions needing user host start or pending host readiness; keep the same ID
263
+ and follow [result handling](result-handling.md#schedule-definition-and-host-results).
249
264
  `--json` applies to handler responses; argument/usage errors retain the CLI's
250
265
  normal stderr behavior. A valid rule with no future occurrence in the supported
251
266
  timestamp range has a distinct range error, not a claim of permanent invalidity.
@@ -253,8 +268,8 @@ timestamp range has a distinct range error, not a claim of permanent invalidity.
253
268
  ### Schedule history and execution
254
269
 
255
270
  ```text
256
- delegate --root ROOT schedule history SCHEDULE_ID [--before RFC3339Nano] [--limit N] --json
257
- delegate --root ROOT schedule execution TASK_ID --json
271
+ delegate schedule history SCHEDULE_ID [--before RFC3339Nano] [--limit N] --json
272
+ delegate schedule execution TASK_ID --json
258
273
  ```
259
274
 
260
275
  `history` returns occurrence summaries and compact skipped intervals together,
@@ -282,31 +297,121 @@ for freshness, no-result states, response bounds, exit codes and recovery.
282
297
 
283
298
  ## Scheduler runtime
284
299
 
300
+ Check `delegate help` for the installed build's command surface. Use `serve`,
301
+ `status` and `stop` only when that help advertises them; prefer `serve` for managed
302
+ recovery. The signatures below describe the current command surface. They use
303
+ the same CLI default as ordinary schedule commands; preserve an explicit custom
304
+ or historical root when the schedule is bound to one.
305
+
285
306
  ```text
286
- delegate --root ROOT scheduler run [--pueue-config ABS] [--json]
307
+ delegate scheduler serve
308
+ delegate scheduler status
309
+ delegate scheduler stop
310
+ delegate scheduler run [--pueue-config ABS] [--json]
287
311
  ```
288
312
 
289
- The scheduler requires the automatic managed worker. Use colocated `delegate`
313
+ If installed help offers only `scheduler run`, the user runs
314
+ `delegate scheduler run` in an independent terminal or tmux pane and
315
+ leaves it in the foreground. Ctrl-C in its original pane stops it; it has no
316
+ automatic child restart. Keep the saved schedule ID and inspect
317
+ [history and execution](#schedule-history-and-execution) for actual occurrences.
318
+ Do not issue unsupported `scheduler status` or `scheduler stop` commands, or
319
+ expect `start_required` or `scheduler.serve_command` fields from that build.
320
+ The managed-host controls and response fields below apply only when installed
321
+ help supports them.
322
+
323
+ The user starts one foreground `serve` host per canonical execution root in an
324
+ independent terminal or tmux pane and leaves it running. It manages every saved
325
+ schedule in that root. When returned, agents give the exact
326
+ `scheduler.serve_command` argv array to the user. Agents must not start either
327
+ persistent scheduler command inside their own bounded task. The guard recognizes
328
+ an explicit Delegate task-scope marker and, on Linux, native Delegate
329
+ cgroup membership. It does not reconstruct guardian ownership or detect every
330
+ enclosing ancestor. A successful check or missing marker does not prove
331
+ independent placement; independent user launch remains required. Delegate
332
+ installs no OS service, enables no reboot/login startup and
333
+ does not automatically launch a detached host.
334
+
335
+ When present, `scheduler.serve_command` preserves spaces and shell metacharacters
336
+ as separate arguments. Human output also prints JSON argv, not an unquoted shell string.
337
+ Preserve those boundaries; see the [scheduler response fields](result-handling.md#schedule-definition-and-host-results).
338
+
339
+ Explicit `serve` may initialize absent scheduler storage through the same
340
+ scheduler owner lease used by `schedule create`. It can become ready with no
341
+ definitions; later creates reach that running host without a restart. Existing
342
+ root identity and data stay in place; invalid existing storage fails explicitly.
343
+ Passive reads and low-level `run` do not initialize absent storage. A second host
344
+ or competing `run` cannot acquire the same root's ownership. The host uses its
345
+ retained launch context and the saved requested provider choices. For
346
+ Team-targeted schedules, new occurrences read the pinned catalog's latest Member
347
+ defaults through normal admission; existing task IDs retain saved settings. Use
348
+ the intended user configuration context, or a different catalog instance fails
349
+ admission even when Team/Member IDs match. Context changes require completed stop
350
+ and a fresh user start; full launch environments are not persisted.
351
+
352
+ While the host lives, it restarts its scheduler child after an unexpected exit,
353
+ including a clean exit while running is still desired. A successful Start needs
354
+ its exact child Wait before replacement; a definitively failed Start that
355
+ created no child may retry without Wait. Retry delays are 1, 2, 4, 8, 16, 30, 60,
356
+ 120 and 300 seconds, capped at five minutes indefinitely. Five continuous healthy
357
+ minutes reset the policy;
358
+ elapsed healthy time and delays use monotonic timing. Create/resume/status do not
359
+ reset cooldown. A live but unready child or uncertain launch is not replaced.
360
+ Before the child reports Ready or scans for due work, the application's
361
+ before-Ready check validates every current saved definition. An incompatible
362
+ definition leaves the host degraded and stops automatic child restart for that
363
+ incompatibility; it does not enter an endless crash/retry loop. Preserve the
364
+ saved definitions and report the compatibility fault.
365
+ If the host, terminal/tmux pane or machine stops, automatic recovery ends; the
366
+ user must run serve again.
367
+
368
+ `scheduler status` is passive: it does not start, migrate, repair or clean
369
+ anything. It observes starting, ready, backoff, degraded, stopping or stopped
370
+ state, or a compatibility runtime's `foreground` generation, and available
371
+ attempt, bounded diagnostic and retry information. Optional
372
+ `scheduler.fault: true` is the host owner's permanent fault decision; degraded state or
373
+ `last_error` alone is not that decision. After a definition is saved,
374
+ transport-only unreachability returns pending exit `3` without a top-level
375
+ `error`; a permanent host fault returns exit `1`, retaining
376
+ `schedule.saved: true` and the same ID.
377
+
378
+ `scheduler stop` persists a stopped fence, interrupts backoff, ends admission and
379
+ joins accepted controls, GoCron shutdown and child Wait. The host remains
380
+ responsive to authenticated status/stop while joining its child or waiting for a
381
+ prior execution owner. Under host ownership, it writes a closure witness once
382
+ execution ownership is free. Completed stop requires that witness and exact
383
+ host absence; acceptance, timeout or host death alone is not completion.
384
+ Authenticated acceptance remains visible even if later readback fails; concrete
385
+ faults remain visible too. SIGINT, SIGTERM and SIGHUP use the same fenced shutdown
386
+ path. Independently admitted tasks retain their own supervisors and budgets.
387
+ See [host result decisions](result-handling.md#schedule-definition-and-host-results).
388
+
389
+ `scheduler run` runs the foreground runtime directly and remains a compatibility
390
+ path without automatic child restart. On builds with host controls, it shares
391
+ root ownership with serve and announces its current foreground generation,
392
+ which an older managed-host stop
393
+ receipt cannot hide. Status reports `scheduler.state: foreground`.
394
+ `scheduler stop` does not terminate the raw invocation: it returns
395
+ `stop_accepted: false` and `next_action: stop_foreground_runtime`. The user ends
396
+ it with Ctrl-C in its original pane; prefer `scheduler serve` for managed
397
+ recovery. The existing manual OS-service hosting option is separate from the new
398
+ foreground host path; see [operator hosting](https://github.com/hishamkaram/delegation-layer/blob/main/docs/cli-reference.md#scheduler-hosting).
399
+
400
+ Serve and run require the automatic managed worker. Use colocated `delegate`
290
401
  and `delegate-run` binaries from the same build and omit the advanced `--runner`
291
402
  override. An override selects custom ownership even when it names the bundled
292
- worker; startup rejects it with exit `2` before opening storage or acquiring a
293
- lease. Ordinary explicit custom-runner dispatch and continuation retain their
403
+ worker. `scheduler run` rejects it with exit `2` before opening storage or
404
+ acquiring a lease. `scheduler serve` checks existing state and schedule storage
405
+ before rejecting the override with exit `2`, so a storage error can take
406
+ precedence. Ordinary explicit custom-runner dispatch and continuation retain their
294
407
  existing compatibility rules. Historical custom-runner claims are not
295
408
  automatically repaired or released.
296
409
 
297
- This foreground command requires existing schedule storage. One process owns
298
- each root; a second fails busy. It uses the service launch environment and the
299
- saved requested provider choices. Saving a definition never starts the service.
300
- For Team-targeted schedules, new occurrences read the pinned catalog's latest
301
- Member defaults through normal admission; existing task IDs retain saved settings.
302
- Use the same intended user configuration context as creation, or a different
303
- catalog instance fails admission even when Team/Member IDs match.
304
- See [operator hosting](https://github.com/hishamkaram/delegation-layer/blob/main/docs/cli-reference.md#scheduler-hosting).
305
-
306
410
  Startup skips past appointments. Expired, overlapping or capacity-limited
307
411
  appointments are skipped with a recorded reason; no catch-up queue or automatic
308
- retry/continuation is added. Pause/delete prevent new claims, without canceling
309
- already claimed tasks. Use [history and execution](#schedule-history-and-execution)
412
+ provider retry/continuation is added. Downtime is recorded in compact skipped
413
+ intervals, never replayed minute by minute. Pause/delete prevent new claims,
414
+ without canceling already claimed tasks. Use [history and execution](#schedule-history-and-execution)
310
415
  to inspect recorded work, and [result handling](result-handling.md#scheduled-execution-results)
311
416
  to collect its answer. Schedule reservation release is separate from result
312
417
  publication.
@@ -317,12 +422,12 @@ Delegate workers keep their own budgets; provider-native in-session subagents do
317
422
  not acquire independent Delegate lifetimes. The workflow owns saved progress,
318
423
  worker IDs and deduplication; unknown acknowledgment is not permission to resend.
319
424
 
320
- Interrupting the service joins its admission/control work before releasing its
321
- owner lease. Accepted lifecycle calls settle independently of the stop signal;
425
+ Interrupting the compatibility runtime joins its admission/control work before
426
+ releasing its owner lease. Accepted lifecycle calls settle independently of the stop signal;
322
427
  there is no shutdown-time guarantee. Already admitted tasks continue under their
323
- own supervisors. The
324
- service reports bounded identifiers/codes on stderr; `--json` selects the final
325
- command response, not an event stream or daemon-control protocol. Uncertain task
428
+ own supervisors. The compatibility command reports bounded identifiers/codes on
429
+ stderr; `--json` selects the final command response, not an event stream or
430
+ daemon-control protocol. Uncertain task
326
431
  evidence blocks only its schedule until the existing owners can prove closure.
327
432
 
328
433
  ## Codex review
@@ -355,8 +460,8 @@ A checkpoint is Git-content evidence, not a provider outcome.
355
460
  ## Providers and capabilities
356
461
 
357
462
  ```sh
358
- delegate --root "${DELEGATE_ROOT:-$HOME/delegation-state}" providers --json
359
- delegate --root "${DELEGATE_ROOT:-$HOME/delegation-state}" capabilities --provider PROVIDER_ID --json
463
+ delegate providers --json
464
+ delegate capabilities --provider PROVIDER_ID --json
360
465
  ```
361
466
 
362
467
  `providers` returns `schema_version: 1` and a sorted `providers` array.
@@ -393,7 +498,7 @@ them. Keep defaults when no explicit choice is needed. Resolve a natural-languag
393
498
  name through native discovery:
394
499
 
395
500
  ```sh
396
- delegate --root "${DELEGATE_ROOT:-$HOME/delegation-state}" models \
501
+ delegate models \
397
502
  --provider PROVIDER_ID --cwd ABSOLUTE_WORKSPACE --json
398
503
  ```
399
504
 
@@ -436,7 +541,7 @@ reason codes and return no model facts.
436
541
  Use static preflight when readiness was requested, not before every task:
437
542
 
438
543
  ```sh
439
- delegate --root "${DELEGATE_ROOT:-$HOME/delegation-state}" preflight \
544
+ delegate preflight \
440
545
  --provider PROVIDER_ID --cwd ABSOLUTE_WORKSPACE \
441
546
  --permission REQUESTED_MODE --json
442
547
  ```
@@ -22,7 +22,7 @@ When `status` or `collect` reports a timed-out turn with:
22
22
  run:
23
23
 
24
24
  ```sh
25
- delegate --root "${DELEGATE_ROOT:-$HOME/delegation-state}" continue \
25
+ delegate continue \
26
26
  --task PREDECESSOR_TASK_ID \
27
27
  --brief FOLLOW_UP_BRIEF \
28
28
  --budget 30m \
@@ -35,8 +35,11 @@ indefinitely for a publication that the interrupted turn cannot complete.
35
35
 
36
36
  The follow-up brief is optional. If it is omitted, Delegation Layer reuses the
37
37
  validated predecessor brief. A successful continuation returns a new task ID
38
- and links it to the predecessor. Observe and collect the new ID separately. Always retain the original state
39
- root, even if a returned command hint omits it. Permission is inherited; do not
38
+ and links it to the predecessor. Observe and collect the new ID separately.
39
+ Follow the main skill's [root rule](../SKILL.md#3-prepare-separate-paths-and-a-finite-brief):
40
+ ordinary continuation omits `--root` in the same user/configuration context;
41
+ an explicit custom or recorded historical root must be retained exactly, even
42
+ if a returned command hint omits it. Permission is inherited; do not
40
43
  add `--permission` to `continue`. Apply
41
44
  [task creation](result-handling.md#task-creation) before retrying or observing.
42
45
  Any authorized admission retry remains the argv-equivalent `continue`;
@@ -85,7 +88,7 @@ observe that successor instead; if its creation is uncertain, follow the
85
88
  `workspace.id` from the task response; never guess an ID or path:
86
89
 
87
90
  ```sh
88
- delegate --root "${DELEGATE_ROOT:-$HOME/delegation-state}" workspace status \
91
+ delegate workspace status \
89
92
  WORKSPACE_ID --watch 30s --json
90
93
  ```
91
94
 
@@ -62,7 +62,7 @@ question. A printed question alone is not a pending reply request.
62
62
  together with the exact answers. Submit the reply:
63
63
 
64
64
  ```sh
65
- delegate --root "${DELEGATE_ROOT:-$HOME/delegation-state}" reply "$task_id" \
65
+ delegate reply "$task_id" \
66
66
  --request "$request_id" --answers "$answers_file" \
67
67
  --id "$message_id" --json
68
68
  ```
@@ -70,9 +70,10 @@ question. A printed question alone is not a pending reply request.
70
70
  6. Keep collecting. A receipt is not task completion. Only the task's
71
71
  authoritative `outcome` establishes the final result.
72
72
 
73
- Use the same root expression for dispatch, collection, reply, and steering.
74
- If the user explicitly chose another root, use that exact path for all of
75
- them. The other variables stand for actual values saved from this task;
73
+ Follow the main skill's [root rule](../SKILL.md#3-prepare-separate-paths-and-a-finite-brief)
74
+ for dispatch, collection, reply, and steering. The examples use the CLI default;
75
+ preserve an explicit custom or recorded historical root for all of them.
76
+ The variables stand for actual values saved from this task;
76
77
  reassign them in each shell invocation if your tool does not preserve variables.
77
78
  A pending response without questions means keep collecting, not inspect OS
78
79
  processes or dispatch a replacement task.
@@ -86,7 +87,7 @@ reply IDs and earlier steering IDs. Submit it; for a lost response, follow the
86
87
  [delivery rules](#interpret-delivery-precisely) with the same ID and content:
87
88
 
88
89
  ```sh
89
- delegate --root "${DELEGATE_ROOT:-$HOME/delegation-state}" steer "$task_id" \
90
+ delegate steer "$task_id" \
90
91
  --brief "$guidance_file" --id "$steering_message_id" --json
91
92
  ```
92
93