@rse/ase 2.0.3 → 2.0.5

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 (198) hide show
  1. package/dst/ase-hook.js +13 -4
  2. package/dst/ase-lib-version.js +14 -5
  3. package/dst/ase-man-catalog.js +229 -0
  4. package/dst/ase-man-render.js +278 -0
  5. package/dst/ase-man-tui.js +636 -0
  6. package/dst/ase-man.js +33 -27
  7. package/dst/ase-setup.js +2 -2
  8. package/dst/ase-spec.js +103 -20
  9. package/dst/ase-task-board-filter.js +5 -4
  10. package/dst/ase-task-board-web-client.js +26 -26
  11. package/dst/man/ase-agent-adhoc.md +1165 -0
  12. package/dst/man/ase-agent-condenser.md +383 -0
  13. package/dst/man/ase-agent-editor.md +441 -0
  14. package/dst/man/ase-agent-estimator.md +477 -0
  15. package/dst/man/ase-agent-fleet.md +358 -0
  16. package/dst/man/ase-agent-implementer.md +521 -0
  17. package/dst/man/ase-agent-integrator.md +449 -0
  18. package/dst/man/ase-agent-qualifier.md +426 -0
  19. package/dst/man/ase-agent-rebooter.md +384 -0
  20. package/dst/man/ase-agent-relay.md +262 -0
  21. package/dst/man/ase-agent-researcher.md +478 -0
  22. package/dst/man/ase-agent.md +628 -0
  23. package/dst/man/ase-artifact-list.md +57 -0
  24. package/dst/man/ase-artifact-name.md +56 -0
  25. package/dst/man/ase-artifact.md +92 -0
  26. package/dst/man/ase-config-delete.md +74 -0
  27. package/dst/man/ase-config-edit.md +83 -0
  28. package/dst/man/ase-config-get.md +70 -0
  29. package/dst/man/ase-config-init.md +110 -0
  30. package/dst/man/ase-config-list.md +68 -0
  31. package/dst/man/ase-config-set.md +92 -0
  32. package/dst/man/ase-config.md +426 -0
  33. package/dst/man/ase-hook-permission-request.md +61 -0
  34. package/dst/man/ase-hook-pre-tool-use.md +96 -0
  35. package/dst/man/ase-hook-session-end.md +71 -0
  36. package/dst/man/ase-hook-session-persona.md +65 -0
  37. package/dst/man/ase-hook-session-start.md +184 -0
  38. package/dst/man/ase-hook-stop.md +52 -0
  39. package/dst/man/ase-hook-user-prompt-submit.md +54 -0
  40. package/dst/man/ase-hook.md +93 -0
  41. package/dst/man/ase-man.md +195 -0
  42. package/dst/man/ase-mcp.md +102 -0
  43. package/dst/man/ase-service-log.md +59 -0
  44. package/dst/man/ase-service-send.md +60 -0
  45. package/dst/man/ase-service-start.md +93 -0
  46. package/dst/man/ase-service-status.md +58 -0
  47. package/dst/man/ase-service-stop.md +52 -0
  48. package/dst/man/ase-service.md +124 -0
  49. package/dst/man/ase-setup-disable.md +67 -0
  50. package/dst/man/ase-setup-enable.md +66 -0
  51. package/dst/man/ase-setup-install.md +116 -0
  52. package/dst/man/ase-setup-mcp.md +213 -0
  53. package/dst/man/ase-setup-status.md +101 -0
  54. package/dst/man/ase-setup-statusline.md +162 -0
  55. package/dst/man/ase-setup-telemetry.md +166 -0
  56. package/dst/man/ase-setup-uninstall.md +85 -0
  57. package/dst/man/ase-setup-update.md +117 -0
  58. package/dst/man/ase-setup.md +156 -0
  59. package/dst/man/ase-spec-export.md +99 -0
  60. package/dst/man/ase-spec-init.md +57 -0
  61. package/dst/man/ase-spec-lint.md +74 -0
  62. package/dst/man/ase-spec-preview.md +57 -0
  63. package/dst/man/ase-spec.md +85 -0
  64. package/dst/man/ase-statusline.md +330 -0
  65. package/dst/man/ase-task-assign.md +138 -0
  66. package/dst/man/ase-task-board.md +651 -0
  67. package/dst/man/ase-task-delete.md +46 -0
  68. package/dst/man/ase-task-edit.md +73 -0
  69. package/dst/man/ase-task-idscheme.md +92 -0
  70. package/dst/man/ase-task-lifecycle.md +92 -0
  71. package/dst/man/ase-task-list.md +86 -0
  72. package/dst/man/ase-task-load.md +48 -0
  73. package/dst/man/ase-task-newid.md +100 -0
  74. package/dst/man/ase-task-purge.md +49 -0
  75. package/dst/man/ase-task-rename.md +69 -0
  76. package/dst/man/ase-task-request.md +108 -0
  77. package/dst/man/ase-task-save.md +78 -0
  78. package/dst/man/ase-task-status.md +79 -0
  79. package/dst/man/ase-task-store.md +377 -0
  80. package/dst/man/ase-task-view.md +50 -0
  81. package/dst/man/ase-task.md +335 -0
  82. package/dst/man/ase-util-compat.md +38 -0
  83. package/dst/man/ase-util-diagram.md +140 -0
  84. package/dst/man/ase-util-meta.md +68 -0
  85. package/dst/man/ase-util-metric.md +74 -0
  86. package/dst/man/ase-util-mint.md +85 -0
  87. package/dst/man/ase-util-worktree.md +109 -0
  88. package/dst/man/ase-util.md +81 -0
  89. package/dst/man/ase.md +228 -0
  90. package/package.json +16 -21
  91. package/plugin/.claude-plugin/plugin.json +1 -1
  92. package/plugin/.codex-plugin/plugin.json +1 -1
  93. package/plugin/.github/plugin/plugin.json +1 -1
  94. package/plugin/agents/ase-code-lint.md +3 -3
  95. package/plugin/agents/ase-docs-proofread.md +3 -3
  96. package/plugin/agents/ase-docs-refine.md +3 -3
  97. package/plugin/agents/ase-spec-lint.md +338 -0
  98. package/plugin/mods/ase-mods-common.ts +444 -0
  99. package/plugin/mods/ase-mods-grill.ts +312 -0
  100. package/plugin/mods/ase-mods-help-browse.ts +405 -0
  101. package/plugin/mods/ase-mods-help-compose.ts +561 -0
  102. package/plugin/mods/ase-mods-help-find.ts +426 -0
  103. package/plugin/mods/ase-mods-help-hint.ts +134 -0
  104. package/plugin/mods/ase-mods-help-show.ts +142 -0
  105. package/plugin/mods/ase-mods.ts +214 -381
  106. package/plugin/mods/claude-code.d.ts +26 -3
  107. package/plugin/skills/ase-code-lint/SKILL.md +15 -15
  108. package/plugin/skills/ase-code-lint/help.md +21 -8
  109. package/plugin/skills/ase-help-intent/SKILL.md +2 -1
  110. package/plugin/skills/ase-help-intent/data.md +214 -9
  111. package/plugin/skills/ase-help-skill/catalog.md +1 -0
  112. package/plugin/skills/ase-meta-workflow/workflow.txt +2 -0
  113. package/plugin/skills/ase-repo-commit/SKILL.md +1 -0
  114. package/plugin/skills/ase-repo-merge/SKILL.md +1 -0
  115. package/plugin/skills/ase-spec-edit/SKILL.md +3 -3
  116. package/plugin/skills/ase-spec-edit/help.md +1 -1
  117. package/plugin/skills/ase-spec-lint/SKILL.md +695 -0
  118. package/plugin/skills/ase-spec-lint/help.md +184 -0
  119. package/plugin/skills/ase-task-implement/SKILL.md +24 -6
  120. package/plugin/skills/ase-task-implement/help.md +11 -1
  121. package/dst/man/ase-agent-adhoc.1 +0 -515
  122. package/dst/man/ase-agent-condenser.1 +0 -193
  123. package/dst/man/ase-agent-editor.1 +0 -212
  124. package/dst/man/ase-agent-estimator.1 +0 -214
  125. package/dst/man/ase-agent-fleet.1 +0 -185
  126. package/dst/man/ase-agent-implementer.1 +0 -233
  127. package/dst/man/ase-agent-integrator.1 +0 -213
  128. package/dst/man/ase-agent-qualifier.1 +0 -214
  129. package/dst/man/ase-agent-rebooter.1 +0 -193
  130. package/dst/man/ase-agent-relay.1 +0 -128
  131. package/dst/man/ase-agent-researcher.1 +0 -217
  132. package/dst/man/ase-agent.1 +0 -264
  133. package/dst/man/ase-artifact-list.1 +0 -38
  134. package/dst/man/ase-artifact-name.1 +0 -39
  135. package/dst/man/ase-artifact.1 +0 -56
  136. package/dst/man/ase-config-delete.1 +0 -45
  137. package/dst/man/ase-config-edit.1 +0 -48
  138. package/dst/man/ase-config-get.1 +0 -46
  139. package/dst/man/ase-config-init.1 +0 -60
  140. package/dst/man/ase-config-list.1 +0 -42
  141. package/dst/man/ase-config-set.1 +0 -52
  142. package/dst/man/ase-config.1 +0 -231
  143. package/dst/man/ase-hook-permission-request.1 +0 -36
  144. package/dst/man/ase-hook-pre-tool-use.1 +0 -59
  145. package/dst/man/ase-hook-session-end.1 +0 -47
  146. package/dst/man/ase-hook-session-persona.1 +0 -37
  147. package/dst/man/ase-hook-session-start.1 +0 -81
  148. package/dst/man/ase-hook-stop.1 +0 -34
  149. package/dst/man/ase-hook-user-prompt-submit.1 +0 -34
  150. package/dst/man/ase-hook.1 +0 -51
  151. package/dst/man/ase-man.1 +0 -67
  152. package/dst/man/ase-mcp.1 +0 -61
  153. package/dst/man/ase-service-log.1 +0 -43
  154. package/dst/man/ase-service-send.1 +0 -47
  155. package/dst/man/ase-service-start.1 +0 -54
  156. package/dst/man/ase-service-status.1 +0 -46
  157. package/dst/man/ase-service-stop.1 +0 -37
  158. package/dst/man/ase-service.1 +0 -85
  159. package/dst/man/ase-setup-disable.1 +0 -44
  160. package/dst/man/ase-setup-enable.1 +0 -45
  161. package/dst/man/ase-setup-install.1 +0 -73
  162. package/dst/man/ase-setup-mcp.1 +0 -124
  163. package/dst/man/ase-setup-status.1 +0 -60
  164. package/dst/man/ase-setup-statusline.1 +0 -92
  165. package/dst/man/ase-setup-telemetry.1 +0 -92
  166. package/dst/man/ase-setup-uninstall.1 +0 -59
  167. package/dst/man/ase-setup-update.1 +0 -64
  168. package/dst/man/ase-setup.1 +0 -93
  169. package/dst/man/ase-spec-export.1 +0 -62
  170. package/dst/man/ase-spec-lint.1 +0 -40
  171. package/dst/man/ase-spec-preview.1 +0 -40
  172. package/dst/man/ase-spec.1 +0 -46
  173. package/dst/man/ase-statusline.1 +0 -189
  174. package/dst/man/ase-task-assign.1 +0 -71
  175. package/dst/man/ase-task-board.1 +0 -384
  176. package/dst/man/ase-task-delete.1 +0 -35
  177. package/dst/man/ase-task-edit.1 +0 -46
  178. package/dst/man/ase-task-idscheme.1 +0 -65
  179. package/dst/man/ase-task-lifecycle.1 +0 -57
  180. package/dst/man/ase-task-list.1 +0 -47
  181. package/dst/man/ase-task-load.1 +0 -36
  182. package/dst/man/ase-task-newid.1 +0 -61
  183. package/dst/man/ase-task-purge.1 +0 -37
  184. package/dst/man/ase-task-rename.1 +0 -44
  185. package/dst/man/ase-task-request.1 +0 -61
  186. package/dst/man/ase-task-save.1 +0 -48
  187. package/dst/man/ase-task-status.1 +0 -55
  188. package/dst/man/ase-task-store.1 +0 -194
  189. package/dst/man/ase-task-view.1 +0 -40
  190. package/dst/man/ase-task.1 +0 -160
  191. package/dst/man/ase-util-compat.1 +0 -25
  192. package/dst/man/ase-util-diagram.1 +0 -76
  193. package/dst/man/ase-util-meta.1 +0 -45
  194. package/dst/man/ase-util-metric.1 +0 -54
  195. package/dst/man/ase-util-mint.1 +0 -59
  196. package/dst/man/ase-util-worktree.1 +0 -72
  197. package/dst/man/ase-util.1 +0 -50
  198. package/dst/man/ase.1 +0 -124
@@ -0,0 +1,1165 @@
1
+ # ase-agent-adhoc(1) -- Run an Ad-Hoc Agent of a Definition Given by Options
2
+
3
+ ## SYNOPSIS
4
+
5
+ `ase agent adhoc start`
6
+ \[`-n`|`--name` *name*\]
7
+ \[`-t`|`--tool` *tool*\]
8
+ \[`-p`|`--parallel` *num*\]
9
+ \[`-T`|`--timeout` *duration*\]
10
+ \[`-o`|`--one-shot`\]
11
+ \[`--agent-relay` *url*\]
12
+ \[`-r`|`--repo` *url*\]
13
+ \[`-d`|`--tempdir` *dir*\]
14
+ \[`-D`|`--definition` *file*|`builtin:`*kind*\[`-`*mode*\]\]
15
+ \[`--title` *text*\]
16
+ \[`--description` *text*\]
17
+ \[`--type` `phase`|`request`\]
18
+ \[`--workdir` *kind*\]
19
+ \[`--lifecycle` *model*\]
20
+ \[`--serial`\]
21
+ \[`--unclaimed`\]
22
+ \[`--params` *name*`=`*value*\]
23
+ \[`--state-`*item* *state*\]
24
+ \[`--tag-`*item* *tag*\]
25
+ \[`--assign-`*item* *who*\]
26
+ \[`--request-`*item* *value*\]
27
+ \[`--prompt-`*item* *value*\]
28
+ \[`--prepare-run` *cmd*\]
29
+ \[`--success-`*item* *value*\]
30
+ \[`--verdict-`*item* *value*\]
31
+ \[`--attach-`*item* *value*\]
32
+ \[`--finish-`*item* \[*cmd*\]\]
33
+ \[`-f`|`--foreground`\]
34
+
35
+ `ase agent adhoc status`
36
+ \[`-n`|`--name` *name*\]
37
+
38
+ `ase agent adhoc log`
39
+ \[`-f`|`--follow`\]
40
+ \[`-n`|`--lines` *n*\]
41
+ \[`--name` *name*\]
42
+
43
+ `ase agent adhoc stop`
44
+ \[`-n`|`--name` *name*\]
45
+
46
+ `ase agent` *kind* `start`|`status`|`log`|`stop` \[...\]
47
+
48
+ ## DESCRIPTION
49
+
50
+ `ase agent adhoc` runs an *ad-hoc agent*: an autonomous agent whose
51
+ *entire* behavior is given by its command-line options (optionally
52
+ based on the definition file or the built-in definition of
53
+ `--definition`), instead of by a definition file of its own. This
54
+ manual page is also the authoritative reference of the *agent
55
+ definitions* in general, i.e., of the options `--`*group*`-`*item*,
56
+ of the definition files, of the prompt templates, and of the hooks.
57
+
58
+ An agent definition configures the behavior of an agent declaratively.
59
+ All agents of **ase** are agents of a definition, run by the same
60
+ agent engine:
61
+
62
+ - *built-in agents* (`ase agent rebooter`, `condenser`, `implementer`,
63
+ `qualifier`, `integrator`, `editor`, `estimator`, and `researcher`):
64
+ each mode of them is a built-in definition, which can be referenced as
65
+ `builtin:`*kind*`-`*mode* (resp. `builtin:`*kind* for its default
66
+ mode): `builtin:rebooter-reboot`, `builtin:condenser-condense`,
67
+ `builtin:implementer-implement`, `builtin:implementer-draft`,
68
+ `builtin:qualifier-judge`, `builtin:qualifier-qualify`,
69
+ `builtin:integrator-merge`, `builtin:integrator-rebase`,
70
+ `builtin:integrator-squash`, `builtin:editor-edit`,
71
+ `builtin:estimator-phase`, `builtin:estimator-request`,
72
+ `builtin:researcher-phase`, and `builtin:researcher-request`.
73
+
74
+ All options `--`*group*`-`*item* below are also accepted by the
75
+ built-in agents, where they override the built-in definition (see
76
+ `ase-agent-rebooter`(1) etc.).
77
+
78
+ - *definition kinds* (`ase agent` *kind*): an agent kind of its own,
79
+ discovered from the definition file *kind*`.`*ext* of the project
80
+ (`.ase/agents/`, intended to be versioned) or of the user (*per-user
81
+ configuration directory*`/agents/`). A definition kind of the project
82
+ shadows one of the user, and both shadow a built-in agent kind of the
83
+ same name (whose `--mode` then no longer exists).
84
+
85
+ For example, `.ase/agents/reviewer.mts` yields the commands
86
+ `ase agent reviewer start|status|log|stop`, which take exactly the same
87
+ options as `ase agent adhoc` described here, except `--definition` (as
88
+ the definition file of the kind takes its place), and where the given
89
+ options override the definition file.
90
+
91
+ The definition files are discovered only on the commands `ase agent`
92
+ ..., where a file of an invalid kind name (other than up to 64 letters,
93
+ digits, underscores, and dashes, starting with a letter or digit), of
94
+ the reserved kind names `adhoc`, `relay`, or `fleet`, or of an already
95
+ discovered kind name in the same directory (by the precedence of the
96
+ extensions `.yaml`, `.yml`, `.ts`, `.mts`, `.js`, `.mjs`, and `.cjs`,
97
+ in this order) is skipped with a warning.
98
+
99
+ - *ad-hoc agents* (`ase agent adhoc`): an agent without a definition
100
+ file of its own, e.g., for a one-off agent, or for an agent defined
101
+ inline in a fleet (see `ase-agent-fleet`(1)).
102
+
103
+ Each agent runs in its own process, in the background (logging into
104
+ `.ase/agent/`*name*`.log`) or with `--foreground` in the current
105
+ process (logging to the terminal). Several agents are best run
106
+ together as a fleet (see `ase-agent-fleet`(1)).
107
+
108
+ With `--type phase` (default), an agent claims tasks by their
109
+ *lifecycle status*, like the built-in phase agents: it observes the
110
+ task store for the tasks in the state of `--state-incoming` which do
111
+ not carry its tag (see `--tag-name`), whose `Assignee:` is empty or
112
+ its own assignee name (see `--assign-name`), and whose predecessors
113
+ (the tasks of the `After:` key, and, for an explicit epic, the other
114
+ tasks of its `Group:`) all passed its phase (see `--state-passed` and
115
+ the hook `passes`).
116
+
117
+ It claims each such task (in natural task id order, or in the order of
118
+ the hook `order`) in a single conditional save, which moves it into the
119
+ state of `--state-activity`, tags it with the tag value `active` (as
120
+ `<tag-name>:active`), and assigns it to the agent.
121
+
122
+ It then processes the task through the headless agent tool of `--tool`
123
+ with the prompt of `--prompt-skill`, `--prompt-text`, or `--prompt-file`,
124
+ checks the success criteria, and finally, again in a single conditional
125
+ save, settles the task: it tags it according to `--tag-success` resp.
126
+ `--tag-failure` (or with the found verdict as the tag value), hands it
127
+ over to the assignee of `--assign-success` resp. `--assign-failure`, and
128
+ moves it into the state of `--state-success` resp. `--state-failure` (or
129
+ of `--state-verdict`), where `previous` restores the incoming state the
130
+ task was claimed from.
131
+
132
+ A task whose status the skill itself moved elsewhere is tagged, too, and
133
+ left in that state, except that for a `previous` success or failure
134
+ state, a task the skill itself moved back into one of the incoming
135
+ states (e.g., `ase-task-reboot`, which resets it into its default
136
+ state) is still settled as above. An interrupted processing puts the task back,
137
+ untagged and with its previous assignee, into the incoming state it was
138
+ claimed from.
139
+
140
+ With `--type phase` and `--unclaimed`, an agent instead processes the
141
+ tasks *unclaimed*, like the built-in `estimator` agent: it observes the
142
+ tasks in one of the states of `--state-incoming` (each adapted onto the
143
+ task lifecycle model of the project, e.g., `PLANNED` as `PLANNING` for
144
+ `team` and as `OPEN` for `solo`, so it supports all models) which do
145
+ not carry its tag, independent of their `Assignee:` and their
146
+ predecessors. It processes each such task without any change of it
147
+ (neither moving it into an activity state, nor tagging it as active,
148
+ nor assigning it), so it keeps no other agent off the task, and the
149
+ skill itself has to save its result conditionally (as another agent can
150
+ claim and change the task meanwhile). Finally, it settles the task by
151
+ its tag only (according to `--tag-success` resp. `--tag-failure`),
152
+ without ever changing its status or its assignee. An interrupted
153
+ processing leaves the task untouched.
154
+
155
+ With `--type request`, an agent processes the *prompt requests*
156
+ attached to tasks in any lifecycle status (see `ase task request` in
157
+ `ase-task-request`(1), or key `R` of the task boards), like the
158
+ built-in `editor` agent: it observes the tasks with pending requests
159
+ of the request name of `--request-name` (attachments of type
160
+ `text/plain; charset=utf-8; kind="<name>"`, mirrored in the tag
161
+ `ase-agent-<name>:pending`), claims the oldest request of such a task
162
+ by turning it into `kind="<name>-running"` and assigning the task to
163
+ the agent (remembering its previous assignee), processes it with the
164
+ request prompt available as `{prompt}`, and finally removes the
165
+ request on success, or turns it into `kind="<name>-failed"` (with the
166
+ reason of the failure as its description) on failure, resp. back into
167
+ `kind="<name>"` on interrupt, where the task keeps its status and its
168
+ tags (except the request state tag) and, by default, gets its previous
169
+ assignee back. An agent consumes the request prompts if its prompt
170
+ template references `{prompt}` (except within the conditional
171
+ `{?prompt:`*text*`}` only, which makes the prompt *optional*) or it
172
+ has a hook `prepare`, `prompt`, or `finish` (which receive the request
173
+ prompt in their *job*), where it then refuses a request with an empty
174
+ prompt as failed, else it accepts requests with an empty prompt (which
175
+ an agent with an optional prompt still passes on if non-empty), and
176
+ announces this to the agent relay, so the task boards accept an empty
177
+ prompt for its requests, too.
178
+
179
+ Only the prompt (and `--state-incoming` for `--type phase`) is
180
+ mandatory, while all other options default to the safe *annotate*
181
+ behavior: a `phase` task returns into its incoming state, tagged with
182
+ the plain tag `ase-agent-<name>` and unassigned, while a `request` task
183
+ keeps its status and tags and gets its previous assignee back. The
184
+ options are validated on the start (also before detaching the agent),
185
+ where an error names the offending option.
186
+
187
+ ## COMMANDS
188
+
189
+ - `ase agent adhoc start` \[*options*\]:
190
+ Start the ad-hoc agent named by `--name` in the background (spawning
191
+ a detached process logging into `.ase/agent/`*name*`.log`), or with
192
+ `--foreground` in the current process. The agent is validated and
193
+ initialized (e.g., its agent tool is looked up and the task lifecycle
194
+ model is checked against `--lifecycle`) before the command returns,
195
+ so a failing agent is reported together with the tail of its log
196
+ (waiting up to 30 seconds for its startup).
197
+
198
+ An agent of the same name already running is left alone (and is an error
199
+ with `--foreground`). All options are described under **OPTIONS** below.
200
+
201
+ - `ase agent adhoc status` \[`-n`|`--name` *name*\]:
202
+ Report whether the agent named *name* (default: `adhoc`) is running,
203
+ as `agent` *name*`: running (pid` *pid*`)` resp. `agent` *name*`: not
204
+ running`. Exits with status 1 if it is not running.
205
+
206
+ - `ase agent adhoc log` \[`-f`|`--follow`\] \[`-n`|`--lines` *n*\] \[`--name` *name*\]:
207
+ Show the log `.ase/agent/`*name*`.log` of the agent named *name*
208
+ (default: `adhoc`) run in the background (where an agent run in the
209
+ foreground logs to the terminal, and an agent of a fleet into the log
210
+ of the fleet instead, see `ase-agent-fleet`(1)).
211
+
212
+ With `-n`|`--lines` *n*, only the last *n* lines are shown (default:
213
+ all). With `-f`|`--follow`, the last *n* lines (default: 10) are shown
214
+ and then, in the style of `tail -f`, all newly appended lines are
215
+ followed until interrupted. As `-n` is the number of lines, the name is
216
+ given via the long option `--name` only. If no log file exists, this is
217
+ just reported (at log level `info`).
218
+
219
+ - `ase agent adhoc stop` \[`-n`|`--name` *name*\]:
220
+ Stop the agent named *name* (default: `adhoc`) by sending it
221
+ `SIGTERM`, and wait (up to 5 minutes) until it aborted its running
222
+ processings and put their tasks back. A not running agent is reported
223
+ as such, without an error.
224
+
225
+ - `ase agent` *kind* `start`|`status`|`log`|`stop` \[...\]:
226
+ The same commands for an agent of the definition kind *kind* (see
227
+ **DESCRIPTION**), with the same options (except `--definition`),
228
+ where the name defaults to *kind*.
229
+
230
+ ## OPTIONS
231
+
232
+ ### Agent Options
233
+
234
+ The following options are shared by all agents (see also
235
+ `ase-agent`(1)):
236
+
237
+ - \[`-n`|`--name` *name*\]:
238
+ The name of the agent (default: its kind, i.e., `adhoc`, resp. the
239
+ definition kind *kind*), at most 64 letters, digits, underscores, and
240
+ dashes, starting with a letter or digit, and neither the name of
241
+ another agent kind, nor `relay` or `fleet`.
242
+
243
+ It names the agent in its log lines (also in the shared processing
244
+ log attachment `agent`), the `Assignee:` of the tasks it
245
+ processes (see `--assign-name`), its default tag `ase-agent-`*name*
246
+ (lower-cased, see `--tag-name`), its default request name (see
247
+ `--request-name`), its temporary directory, and its process files
248
+ `.ase/agent/`*name*`.yaml` and `.ase/agent/`*name*`.log`. Hence,
249
+ multiple ad-hoc agents are started under different names.
250
+
251
+ - \[`-t`|`--tool` *tool*\]:
252
+ The agent tool processing the tasks: `claude`, `copilot`, or `codex`
253
+ (default: `$ASE_TOOL`, else `claude`). It is run headless (with
254
+ `ASE_HEADLESS=true`), i.e., via `claude -p`, `copilot -p`, resp.
255
+ `codex exec` (see `ase-agent`(1)), and has to be found in `$PATH`.
256
+
257
+ - \[`-p`|`--parallel` *num*\]:
258
+ The maximum number of tasks processed in parallel, a positive
259
+ integer (default: `1`). Ignored (with a warning) with `--serial`.
260
+
261
+ - \[`-T`|`--timeout` *duration*\]:
262
+ The maximum duration of processing a task, as *number* *unit* with
263
+ *unit* `s`, `m`, or `h` (default: `60m`), where a processing
264
+ exceeding it fails. The preparing and the finishing of a processing
265
+ are each limited to a fixed duration of 240 seconds in addition.
266
+
267
+ - \[`-o`|`--one-shot`\]:
268
+ Terminate the agent, instead of observing for further tasks, once a
269
+ check of the task store finds no dispatchable task while it
270
+ processes no task anymore. Intended for CI contexts. Not allowed in
271
+ a fleet. A failed check of the task store is retried after a growing
272
+ delay, where `--one-shot` gives up after three failures in a row and
273
+ terminates with a non-zero exit status.
274
+
275
+ - \[`--agent-relay` *url*\]:
276
+ The agent relay to pass the live presence of the agent to, as
277
+ `ase://`*addr*`:`*port*\[`/`*token*\] (HTTP) or
278
+ `ases://`*addr*`:`*port*\[`/`*token*\]\[`?insecure`\] (HTTPS,
279
+ optionally without certificate verification) (default: the
280
+ configured `project.relay.url`, else none). See `ase-agent-relay`(1).
281
+
282
+ - \[`-r`|`--repo` *url*\]:
283
+ The Git repository to clone temporarily into the temporary directory
284
+ of the agent, for processing every task without a `worktree` flow
285
+ value in a temporary Git worktree of this clone (default: the Git
286
+ working copy the agent is started in). Requires a task store not
287
+ located in the working copy (i.e., not a local `ase:`*path* one).
288
+ Silently ignored with `--workdir project`.
289
+
290
+ - \[`-d`|`--tempdir` *dir*\]:
291
+ The directory whose sub-directory *name* holds the temporary files
292
+ of the agent, like the clone of `--repo`, where `%p` in *dir* is
293
+ expanded to the process id of the agent, `%h` to a hash value unique
294
+ to the process, and `%%` to `%` (default: a fresh, private directory
295
+ below the system temporary directory).
296
+
297
+ A missing *dir* is created private to the current user, while an
298
+ existing *dir* has to be a directory (no symbolic link) owned by the
299
+ current user. Silently ignored with `--workdir project`.
300
+
301
+ - \[`-f`|`--foreground`\]:
302
+ Run the agent in the current process, logging to the terminal, until
303
+ it is interrupted or stopped, instead of detaching it.
304
+
305
+ - \[`-h`|`--help`\]:
306
+ Show the usage information of the command and exit.
307
+
308
+ ### Definition Options
309
+
310
+ The following options form the *definition* of an agent. Each one is
311
+ a flat long option `--`*group*`-`*item* (except the ungrouped ones),
312
+ accepted by all agents (including the built-in ones), where the given
313
+ options override the definition of the agent (see `--definition` and
314
+ **DEFINITION FILES**). A *repeatable* option can be given multiple
315
+ times, each time adding a value.
316
+
317
+ A given option also replaces its mutually exclusive alternatives of the
318
+ definition: `--prompt-skill` replaces `--prompt-text` and
319
+ `--prompt-file`, `--prompt-text` and `--prompt-file` replace each other
320
+ and `--prompt-skill` with `--prompt-args`, and `--tag-retry` and
321
+ `--tag-failure` replace each other.
322
+
323
+ #### Ungrouped
324
+
325
+ - \[`-D`|`--definition` *file*|`builtin:`*kind*\[`-`*mode*\]\]:
326
+ (`ase agent adhoc` only) The definition to base the agent on: a
327
+ definition file (see **DEFINITION FILES**), or, as
328
+ `builtin:`*kind*`-`*mode* (resp. `builtin:`*kind* for its default
329
+ mode), the definition of a built-in agent (see **DESCRIPTION**),
330
+ where all other given options override it. Example: `ase agent adhoc
331
+ start -n reviewer -D builtin:qualifier-qualify --tag-name
332
+ ase-agent-reviewer`.
333
+
334
+ - \[`--title` *text*\]:
335
+ The one-line title of the operation of the agent (at most 80
336
+ characters), shown on the task boards: in the information line of the
337
+ agent logs view and above the description in its pane `Operation`
338
+ (default: none).
339
+
340
+ - \[`--description` *text*\]:
341
+ The brief description of the operation of the agent (about 3-6 lines,
342
+ at most 600 characters, with its whitespace collapsed), shown on the
343
+ task boards in the pane `Operation` of the agent logs view, word-wrapped
344
+ onto its width (default: none).
345
+
346
+ - \[`--type` *type*\]:
347
+ The processing type: `phase` (default) to claim tasks by their
348
+ lifecycle status, or `request` to process the prompt requests
349
+ attached to tasks (see **DESCRIPTION**). The options `--unclaimed`,
350
+ `--state-`\*, `--tag-success`, `--tag-failure`, `--tag-retry`,
351
+ `--assign-required`, and `--attach-skip` are allowed for `phase`
352
+ only, the options `--request-`\* for `request` only.
353
+
354
+ - \[`--workdir` *kind*\]:
355
+ The working directory of the processing (default: `project`), which
356
+ determines the working directory of the agent tool, the directories
357
+ granted to it (via `--add-dir`), the holds and deferrals of the
358
+ tasks, and the values of the placeholders `{workdir}`, `{source-dir}`,
359
+ and `{changeset-worktree}`.
360
+
361
+ The temporary worktrees the agent creates itself are named
362
+ *id*`-`*assign-name* resp. *id*`-`*changeset-name*`-`*assign-name*
363
+ (with every `#` of the task id replaced by `_`), so they equal those
364
+ of the built-in agents if `--assign-name` is set to the built-in
365
+ kind, while the worktree of a `branch:` changeset is named after the
366
+ branch (with every character other than letters, digits, `_`, and
367
+ `-` replaced by `-`, runs of `-` reduced to one, and leading and
368
+ trailing `-` and `_` removed), like by the skills:
369
+ - `project`: the project root. `--repo` and `--tempdir` are
370
+ silently ignored.
371
+ - `source`: the working copy holding the `Source:` (the project
372
+ root, or with `--repo` a worktree of its temporary clone), where a
373
+ `branch:` source is additionally checked out in a temporary
374
+ detached worktree *id*`-`*assign-name* (as `{source-dir}`,
375
+ granted to the agent tool) only if the prompt template references
376
+ `{source-dir}` (like `editor`).
377
+ - `changeset` (*write* access, like `implementer`): a `worktree`
378
+ changeset in the project root, which, processed serially, is
379
+ held, deferred until free of uncommitted changes, and switched
380
+ onto a `branch:` source, and, processed in parallel, yields the
381
+ ASE worktree id of the task (created by the skill) as
382
+ `{changeset-worktree}`; a `branch:` changeset is held and checked
383
+ out in the agent worktree named after the branch (created from the
384
+ source if missing, refused if its directory already exists, else
385
+ reused if already checked out, but then required free of
386
+ uncommitted changes), yielding its ASE worktree
387
+ id (unless the project root) as `{changeset-worktree}`, and
388
+ removed afterwards only if clean (else preserved); an
389
+ `attachment:` changeset is left to the skill.
390
+ - `changeset-read` (*review* access, like `qualifier`): a `worktree`
391
+ changeset staged in its context worktree, which becomes the
392
+ working directory; a `branch:` changeset left in place (to be
393
+ addressed via `{changeset-name}`); an `attachment:` changeset
394
+ applied staged in the temporary worktree
395
+ *id*`-`*changeset-name*`-`*assign-name*, detached at its base
396
+ commit, which becomes the working directory.
397
+ - `target` (*integration* access, like `integrator`): the project
398
+ root, with access granted to the context worktree of a `worktree`
399
+ changeset (whose ASE worktree id becomes `{changeset-worktree}`)
400
+ and to the worktree of a `branch:` changeset, where a `branch:`
401
+ target is checked out in the temporary worktree
402
+ *id*`-`*assign-name* unless checked out already, published
403
+ afterwards if moved (or rescued if not publishable), and the
404
+ merged `branch:` changeset is deleted from the origin.
405
+
406
+ - \[`--lifecycle` *model*\]:
407
+ (repeatable) A supported task lifecycle model, `solo`, `team`, or
408
+ `enterprise` (default: every model containing all given states, resp.
409
+ all models for `request` and with `--unclaimed`). The agent refuses
410
+ to start for a project of any other model. All given states have to
411
+ exist in all supported models (except with `--unclaimed`, whose
412
+ incoming states are adapted onto the model of the project).
413
+
414
+ - \[`--serial`\]:
415
+ Process the tasks serially only, ignoring `--parallel`. A fleet
416
+ refuses two serially processing agents of the same tag.
417
+
418
+ - \[`--unclaimed`\]:
419
+ (`phase` only) Process the tasks *unclaimed* (see **DESCRIPTION**):
420
+ every task in one of the states of `--state-incoming` (each adapted
421
+ onto the task lifecycle model of the project) which does not carry
422
+ the tag, independent of its assignee and its predecessors, without
423
+ claiming it, and without ever changing its status and its assignee
424
+ (the tag options still apply). An agent of the same kind on the same
425
+ host does not pick up a task already processed by another one.
426
+
427
+ Not allowed together with `--state-activity`, `--state-success`,
428
+ `--state-failure`, `--state-phase`, `--state-passed`,
429
+ `--state-verdict`, `--assign-required`, `--assign-success`,
430
+ `--assign-failure`, the success criterion `status`, the hook
431
+ `passes`, and `--workdir changeset` resp. `target` (as the task can
432
+ be claimed by another agent meanwhile).
433
+
434
+ - \[`--params` *name*`=`*value*\]:
435
+ (repeatable) The value of the parameter *name* declared by the
436
+ definition (see **PARAMETERS**), where a later value of the same
437
+ name wins. An undeclared *name* is refused.
438
+
439
+ #### State (`--type phase` only)
440
+
441
+ All states are case-insensitive (upper-cased), have to exist in the
442
+ supported task lifecycle models, and the transitions from the incoming
443
+ into the activity state, back (on interrupt), and from the activity
444
+ state into all target states have to be reachable in these models.
445
+ With `--unclaimed`, only `--state-incoming` is allowed instead, whose
446
+ states have to exist in any task lifecycle model only.
447
+
448
+ - \[`--state-incoming` *state*\]:
449
+ The state of the tasks to claim. Mandatory for `phase`. Repeatable
450
+ with `--unclaimed`, where each state is adapted onto the task
451
+ lifecycle model of the project (a state of the model is kept, any
452
+ other one is mapped onto its counterpart, e.g., `PLANNED` onto
453
+ `PLANNING` for `team` and onto `OPEN` for `solo`), and with an
454
+ explicit `--state-activity`, where a task is claimed from any of the
455
+ states (e.g., `DRAFTED` and `PLANNING` into `PLANNING`).
456
+
457
+ - \[`--state-activity` *state*\]:
458
+ The state of a task during its processing (default: the first
459
+ incoming state, i.e., the claim is marked by the `:active` tag value
460
+ only).
461
+
462
+ - \[`--state-success` *state*\]:
463
+ The target state on success, or `previous` for the incoming state
464
+ the task was claimed from (default: the first incoming state).
465
+
466
+ - \[`--state-failure` *state*\]:
467
+ The target state on failure, or `previous` for the incoming state
468
+ the task was claimed from (default: the first incoming state).
469
+
470
+ - \[`--state-phase` *state*\]:
471
+ The *phase success state*, decoupled from the target state: a task
472
+ the skill itself moves there counts as processed (see the success
473
+ criterion `status`), and a task there carrying the tag counts as
474
+ having passed the phase for its `After:` successors (default: the
475
+ success state, resp. the activity state for a `previous` success
476
+ state).
477
+
478
+ - \[`--state-passed` *state*\]:
479
+ The first state of the lifecycle model from which on a task has
480
+ passed the phase for its `After:` successors (default: the phase
481
+ state).
482
+
483
+ - \[`--state-verdict` *VERDICT*`=`*STATE*\]:
484
+ (repeatable) The target state per verdict (both upper-case words),
485
+ overriding the success target state, but never the failure target
486
+ state of a failed processing. Requires `--verdict-label` (or the hook
487
+ `verdict`), and every verdict has to be accepted by `--verdict-allow`
488
+ (if given).
489
+
490
+ #### Tag
491
+
492
+ - \[`--tag-name` *tag*\]:
493
+ The tag of the processed tasks, of the form `ase-agent-`*word* in
494
+ lower-case and without `:` (default: `ase-agent-`*name*, hence no
495
+ sharing between differently named agents). It guards the tasks
496
+ against a repeated processing: a task carrying it (plain or with any
497
+ value) is not claimed again. For `request`, it is always the request
498
+ state tag `ase-agent-`*request-name* (resp. `ase-agent-editor` for the
499
+ request name `edit`), and any other value is refused.
500
+
501
+ - \[`--tag-success` *tag*\]:
502
+ (`phase` only) The tag set on success: *tag-name* (default, the
503
+ plain tag), *tag-name*`:`*value* (a lower-case *value* other than
504
+ `active`), or `none` to untag the task. A foreign tag is refused, as
505
+ the agent would claim the task again. `none` is refused if a task
506
+ returns into an incoming state on success (unless guarded by
507
+ `--attach-skip`, by the hook `ready` of a definition which itself
508
+ declares `tag-success: none`, like the built-in `estimator`, as a hook
509
+ `ready` inherited from a definition without it, like the one of the
510
+ built-in `implementer`, does not guard against claiming the untagged
511
+ task again, or by `--assign-required` with an `--assign-success`
512
+ handing the task over to somebody else, like the built-in
513
+ `rebooter`), e.g., always with `--unclaimed`. A found verdict is
514
+ stored as the tag value instead.
515
+
516
+ - \[`--tag-failure` *tag*\]:
517
+ (`phase` only) The tag set on failure, like `--tag-success` (default:
518
+ *tag-name*), e.g., *tag-name*`:failed` to tell failures apart.
519
+
520
+ - \[`--tag-require` *tag*\]:
521
+ (repeatable) A tag a claimable task has to carry, where a plain tag
522
+ also matches the tag with any value.
523
+
524
+ - \[`--tag-exclude` *tag*\]:
525
+ (repeatable) A tag a claimable task must not carry, where a plain tag
526
+ also matches the tag with any value.
527
+
528
+ - \[`--tag-retry`\]:
529
+ (`phase` only) A shorthand for `--tag-failure none` (not allowed
530
+ together with it): a failed task returning into the incoming state is
531
+ claimed again, but held off by the agent process for an exponentially
532
+ growing delay from 1 minute up to 1 hour.
533
+
534
+ The tag options never apply to an interrupted task (released untagged)
535
+ or to a task left for a manual intervention (tagged
536
+ *tag-name*`:failed`, e.g., after a failed finishing or an unreachable
537
+ resulting state), which does not count as passed for its successors.
538
+
539
+ #### Assign
540
+
541
+ - \[`--assign-name` *who*\]:
542
+ The assignee under which the agent claims, holds, recognizes, and
543
+ releases the tasks, and which names its agent-owned worktrees and its
544
+ mode as announced to the agent relay (default: the agent name), a
545
+ name of letters, digits, `_`, `.`, `@`, and `-`, starting with a
546
+ letter or digit. So a configured agent can act as, e.g., `rebooter`,
547
+ although its agent name must not clash with a built-in kind.
548
+
549
+ - \[`--assign-required`\]:
550
+ (`phase` only) Claim only the tasks explicitly assigned to *who* of
551
+ `--assign-name` (like `rebooter`), instead of the unassigned ones,
552
+ too.
553
+
554
+ - \[`--assign-success` *who*\]:
555
+ The assignee to hand a task over to after its successful processing:
556
+ a name, `none` to unassign it, or `previous` for the assignee before
557
+ the claim (default: `none` for `phase`, `previous` for `request`).
558
+ Applied only while the task is still assigned to the agent.
559
+
560
+ - \[`--assign-failure` *who*\]:
561
+ The assignee to hand a task over to after its failed processing,
562
+ like `--assign-success` (same defaults). An interrupted task always
563
+ gets its previous assignee back, and a task left for a manual
564
+ intervention is always unassigned.
565
+
566
+ #### Request (`--type request` only)
567
+
568
+ - \[`--request-name` *name*\]:
569
+ The name of the processed requests, i.e., of the attachments
570
+ `kind="<name>"`, `kind="<name>-running"`, and `kind="<name>-failed"`
571
+ (default: the agent name), a lower-case word of letters, digits, and
572
+ dashes, not ending in `-running` or `-failed`, and none of the
573
+ built-in agent kinds. The name `edit` processes the edit requests of
574
+ key `E` of the task boards.
575
+
576
+ - \[`--request-done` *word*\]:
577
+ The word naming a processed task in the log lines (default:
578
+ `processed`, e.g., `edited`).
579
+
580
+ #### Prompt
581
+
582
+ Exactly one of `--prompt-skill`, `--prompt-text`, or `--prompt-file`
583
+ is required. Flags of the skills like `--next DONE` are never added
584
+ implicitly, but always have to be given explicitly.
585
+
586
+ - \[`--prompt-skill` *name*\]:
587
+ The skill to invoke, as *skill* or *plugin*`:`*skill* (letters,
588
+ digits, `_`, `.`, and `-`).
589
+
590
+ It is invoked like the built-in agents do, i.e., as `/`*skill*
591
+ (`claude` and `copilot`) resp. `$`*skill* (`codex`), followed by a
592
+ single space and the rendered arguments of `--prompt-args` only if
593
+ these are non-empty, where an un-namespaced ASE skill (`ase-*`) gets
594
+ the plugin namespace `ase:` for `claude` only, a *plugin*`:`*skill*
595
+ stays verbatim, and any other name (e.g., a project skill generated by
596
+ `ase-meta-workflow`) stays un-namespaced.
597
+
598
+ - \[`--prompt-args` *template*\]:
599
+ The arguments of the skill, as a template (see **TEMPLATES**)
600
+ (default: `{id}` for `phase`, `{id}: {prompt}` for `request`).
601
+ Allowed with `--prompt-skill` only.
602
+
603
+ - \[`--prompt-text` *template*\]:
604
+ The prompt text to pass as-is to the agent tool (instead of a skill),
605
+ as a template (see **TEMPLATES**).
606
+
607
+ - \[`--prompt-file` *file*\]:
608
+ A file with the prompt text (instead of a skill), whose content is a
609
+ template (see **TEMPLATES**). It is read and validated on the start.
610
+ In a definition file, a relative *file* is relative to the
611
+ definition file.
612
+
613
+ #### Prepare
614
+
615
+ - \[`--prepare-run` *cmd*\]:
616
+ (repeatable) A shell command run in the working directory before the
617
+ prompt (e.g., `npm ci`), where a failing command fails the processing
618
+ without running the prompt.
619
+
620
+ It gets the environment variables `ASE_TASK_ID`, `ASE_TASK_TITLE`,
621
+ `ASE_TASK_SOURCE`, `ASE_TASK_CHANGESET`, `ASE_TASK_TARGET` (the raw
622
+ flow values or their configured defaults), `ASE_AGENT_NAME`,
623
+ `ASE_AGENT_WORKDIR`, and `ASE_AGENT_PARAM_`*NAME* per parameter (see
624
+ **PARAMETERS**). Empty commands are refused.
625
+
626
+ #### Success
627
+
628
+ - \[`--success-criterion` *criterion*\]:
629
+ (repeatable) A success criterion, where all given criteria have to
630
+ hold, replacing the default `exit` and `clean` for `phase`, resp.
631
+ `clean` and `changed` for `request`:
632
+ - `exit`: an exit code 0 of the agent tool without timeout or
633
+ interrupt.
634
+ - `clean`: no output line reporting an error of the skill (a line
635
+ starting with `ERROR:` or containing `▶ ERROR:`).
636
+ - `changed`: (`request` only) a plan content changed since the
637
+ claim, hence also succeeding on an interrupt after the plan was
638
+ saved (like `editor`).
639
+ - `verdict`: a found verdict. Requires `--verdict-label` (or the
640
+ hook `verdict`).
641
+ - `attachment`: an attachment of `--attach-expect` created or
642
+ changed by the processing (a leftover of an earlier processing
643
+ does not count). Requires `--attach-expect`.
644
+ - `status`: (`phase` only) the move into the phase success state
645
+ (see `--state-phase`) by the skill itself.
646
+
647
+ - \[`--success-match` *regex*\]:
648
+ (repeatable) A regular expression (JavaScript syntax) an output line
649
+ has to match, e.g., `status:\W*plan integrated\b`.
650
+
651
+ An unmet criterion is logged, and a failed request is described in its
652
+ `<name>-failed` attachment by the first applicable reason: a failed
653
+ preparing or finishing command, `skill reported an error`, `agent tool
654
+ failed`, else the reason of the first unmet criterion (e.g., `plan not
655
+ changed`, `no verdict`, `no new or changed attachment "<spec>"`, or
656
+ `no output line matching "<regex>"`).
657
+
658
+ #### Verdict
659
+
660
+ - \[`--verdict-label` *label*\]:
661
+ The label after which the verdict is given in the output of a
662
+ successfully exited agent tool: the verdict is the upper-case word
663
+ following the label (after any non-word characters) on the last
664
+ output line carrying it, e.g., `APPROVE` for the label `REVIEW VERDICT`
665
+ and the line `**REVIEW VERDICT**: **APPROVE**`. The hook `verdict` can
666
+ determine it instead.
667
+
668
+ A verdict is stored lower-cased as the tag value (e.g.,
669
+ `ase-agent-qualifier:approve`, instead of `--tag-success`) and mapped to
670
+ a target state via `--state-verdict`. It is honored on success only: on
671
+ a failed processing, the task is settled by `--tag-failure` and
672
+ `--state-failure` instead.
673
+
674
+ - \[`--verdict-allow` *VERDICT*\]:
675
+ (repeatable) An accepted verdict, an upper-case word (default: the
676
+ verdicts of `--state-verdict`, else any). A verdict not accepted
677
+ counts as none. Requires `--verdict-label` (or the hook `verdict`).
678
+
679
+ #### Attach
680
+
681
+ An attachment *spec* is *kind* or *mime-type*`;`*kind* (e.g.,
682
+ `text/x-diff;draft`), matching the `kind` parameter of the attachment
683
+ type exactly and, if given, its MIME type.
684
+
685
+ - \[`--attach-output` *kind*\]:
686
+ Store the output lines of the prompt as the task attachment of type
687
+ `text/plain; charset=utf-8; kind="<kind>"`, replacing the one of an
688
+ earlier processing.
689
+
690
+ - \[`--attach-expect` *spec*\]:
691
+ The attachment the success criterion `attachment` requires, which
692
+ must not match the attachment of `--attach-output` (as this one is
693
+ always created).
694
+
695
+ - \[`--attach-skip` *spec*\]:
696
+ (`phase` only) Leave every task already carrying such an attachment
697
+ unclaimed (e.g., a task already carrying a draft).
698
+
699
+ - \[`--attach-changeset` *kind*\]:
700
+ (with `--workdir changeset` or `target` only) Store the *change set
701
+ snapshot* -- the view-only, text-only unified diff of the change set
702
+ (without the `.ase` directory) -- as the task attachment of type
703
+ `text/x-diff; charset=utf-8; kind="<kind>"`, captured by the agent
704
+ itself after the processing (before `--finish-commit`) and replacing
705
+ the one of an earlier processing in place (keeping its `Created:`
706
+ key), like `implementer` and `integrator` with the kind `changeset`.
707
+
708
+ With `--workdir changeset`, it covers the change set of a `worktree`
709
+ or `branch:` changeset from its fork point from the `Source:` on, with
710
+ `base` *commit* (plus `, partial` unless the task reached
711
+ `--state-phase`) in its `Desc:` key, while an `attachment:` changeset
712
+ other than `attachment:`*kind* removes it as obsolete.
713
+
714
+ With `--workdir target`, it covers the change of the target branch by
715
+ the integration of a `worktree` or `branch:` changeset, with `base`
716
+ *commit*`, merged` *commit* in its `Desc:` key, unless the task did
717
+ not reach `--state-phase` or the content of the target did not change.
718
+ Without a change set, the task stays untouched.
719
+
720
+ #### Finish
721
+
722
+ - \[`--finish-commit`\]:
723
+ (with `--workdir changeset` only) Commit the work onto a `branch:`
724
+ changeset with the message *Kind*`:` *title* `(`*id*`)` and publish
725
+ it, rescuing a branch which could not be published, like
726
+ `implementer`.
727
+
728
+ - \[`--finish-success` *cmd*\]:
729
+ A shell command run in the working directory after a successful
730
+ processing, with the environment variables of `--prepare-run` plus
731
+ `ASE_TASK_STATUS`, where a failing command fails the finishing.
732
+
733
+ - \[`--finish-failure` *cmd*\]:
734
+ A shell command run in the working directory after a failed
735
+ processing, with the same environment variables, where a failing
736
+ command is only reported.
737
+
738
+ The preparing and finishing commands are limited by the fixed duration
739
+ of 240 seconds of the preparing resp. finishing of a processing.
740
+
741
+ ## TEMPLATES
742
+
743
+ The templates of `--prompt-args`, `--prompt-text`, and `--prompt-file`
744
+ expand the following placeholders:
745
+
746
+ - `{id}`, `{title}`:
747
+ The id and the title of the task.
748
+
749
+ - `{prompt}`:
750
+ The request prompt, with its whitespace collapsed into single spaces
751
+ (`request` only).
752
+
753
+ - `{source}`, `{changeset}`, `{target}`:
754
+ The raw flow values of the frontmatter keys `Source:`, `Changeset:`,
755
+ and `Target:`, or their configured defaults
756
+ `project.task.default.*`, with their placeholder `{id}` replaced by
757
+ the task id (with every character other than letters, digits, `_`,
758
+ and `-` replaced by `-`, runs of `-` reduced to one, and leading and
759
+ trailing `-` and `_` removed, e.g., `12` for `#12` and `FOO-12` for
760
+ `FOO#12`).
761
+
762
+ - `{source-type}`, `{source-name}`, `{changeset-type}`, `{changeset-name}`, `{target-type}`, `{target-name}`:
763
+ The parsed flow values: the type `worktree`, `branch`, or
764
+ `attachment`, and the branch resp. attachment name, else empty, where
765
+ a `Target:` of `source` reads as the `Source:`.
766
+
767
+ - `{workdir}`:
768
+ The working directory of the processing (see `--workdir`).
769
+
770
+ - `{source-dir}`:
771
+ The temporary worktree of a `branch:` source, else empty.
772
+
773
+ - `{changeset-worktree}`:
774
+ The ASE worktree id under which the skill finds the changeset, else
775
+ empty.
776
+
777
+ - `{key:`*Header*`}`:
778
+ A frontmatter key *Header* of the task.
779
+
780
+ - `{param:`*name*`}`:
781
+ The value of the parameter *name* declared by the definition (see
782
+ **PARAMETERS**).
783
+
784
+ - `{?`*cond*`:`*text*`}`:
785
+ A conditional, which emits *text* (with placeholders, but without
786
+ nested conditionals) only if *cond* holds, either *placeholder* (the
787
+ placeholder is non-empty) or *placeholder*`=`*value* (the placeholder
788
+ equals *value*), e.g., `{?source-dir: --int-source-dir
789
+ "{source-dir}"}` or `{?changeset-type=branch:--branch
790
+ {changeset-name}}`. A `{prompt}` used only within `{?prompt:`*text*`}`
791
+ makes the prompt of the requests optional, e.g., `{id}:{?prompt:
792
+ {prompt}}`.
793
+
794
+ All other text, including whitespace, is kept verbatim, `{{` and `}}`
795
+ yield literal braces, and an unknown placeholder (or a malformed or
796
+ unbalanced one) fails the start.
797
+
798
+ ## DEFINITION FILES
799
+
800
+ A definition file carries the same keys as the definition options
801
+ above (without the leading `--`), either flat (`state-incoming:
802
+ PLANNED`) or nested by group (`state: { incoming: PLANNED }`), where a
803
+ key must not be given both flat and nested, a list value repeats a
804
+ repeatable option, a flag takes a boolean, and a relative
805
+ `prompt-file` is relative to the definition file. A definition file is
806
+ either:
807
+
808
+ - a YAML file (`.yaml` or `.yml`), declarative only, or
809
+
810
+ - a TypeScript file (`.ts` or `.mts`, run via the type stripping of
811
+ Node.js) or a JavaScript file (`.js`, `.mjs`, or `.cjs`), whose
812
+ default export is the definition object or a (possibly asynchronous)
813
+ function returning it, where `.mts` resp. `.mjs` avoid the reparsing
814
+ warning of Node.js outside of a package of `"type": "module"`.
815
+
816
+ It is typed via the type `AgentDefinition` of the package `@rse/ase`
817
+ (`import type { AgentDefinition } from "@rse/ase"` and
818
+ `export default { ... } satisfies AgentDefinition`, with `@rse/ase`
819
+ as a development dependency for the editor only, as the type import is
820
+ erased). Only such a file can additionally carry *hooks* (its key
821
+ `hooks`, see **HOOKS**).
822
+
823
+ Every definition file can additionally declare *parameters* (its key
824
+ `params`, see **PARAMETERS**).
825
+
826
+ A definition file can extend a *base definition* via its key
827
+ `definition`: a further definition file (relative to the definition
828
+ file) or, as `builtin:`*kind*`-`*mode* (resp. `builtin:`*kind*), the
829
+ definition of a built-in agent.
830
+
831
+ Its options override those of the base definition (also replacing their
832
+ mutually exclusive alternatives, and with a false flag unsetting the
833
+ flag of the base definition), its parameter declarations extend those
834
+ of the same name of the base definition field-wise (e.g.,
835
+ `params: { severity: LOW }` changes just the default value), and its
836
+ hooks replace those of the same name of the base definition. Base
837
+ definitions can be chained arbitrarily deep, but never cyclic.
838
+
839
+ For example, a `.ase/agents/implementer.mts` of
840
+ `definition: "builtin:implementer-implement"` plus a `ready` hook shadows
841
+ the built-in `implementer` while keeping its definition and its `passes`
842
+ hook, and a `.ase/agents/reviewer.yaml` of
843
+ `definition: builtin:qualifier-judge` plus its own
844
+ `tag: { name: ase-agent-reviewer }` runs a further judging agent of its
845
+ own tag.
846
+
847
+ ## PARAMETERS
848
+
849
+ A definition can declare *parameters* (its key `params`, typed via
850
+ `AgentParam` of the package `@rse/ase`): custom options of the agent,
851
+ whose values are given on its start via `--params` *name*`=`*value*
852
+ (resp. via the map `params` of its section of a fleet configuration,
853
+ see `ase-agent-fleet`(1)). A parameter *name* consists of up to 64
854
+ letters, digits, underscores, and dashes, starting with a letter, and
855
+ is declared by an object of the optional fields:
856
+
857
+ - `desc`:
858
+ The description of the parameter, cited in its errors.
859
+
860
+ - `default`:
861
+ The default value of the parameter (else empty).
862
+
863
+ - `required`:
864
+ Whether a non-empty value is required (default: `false`).
865
+
866
+ - `allow`:
867
+ The allowed values (a single value or a list), where an empty value
868
+ is always allowed unless `required`.
869
+
870
+ A plain scalar instead of the object declares just the default value
871
+ (e.g., `params: { severity: HIGH }`). The values of all parameters are
872
+ validated on the start, where an undeclared parameter, a missing
873
+ required value, and a value not allowed are refused. Each declared
874
+ parameter provides its value (empty if neither given nor defaulted) as:
875
+
876
+ - the placeholder `{param:`*name*`}` of the templates (see **TEMPLATES**),
877
+ also usable in a conditional like `{?param:`*name*`:`*text*`}`;
878
+
879
+ - `ctx.params.`*name* (resp. `ctx.params["`*name*`"]`) of the hooks (see
880
+ **HOOKS**);
881
+
882
+ - the environment variable `ASE_AGENT_PARAM_`*NAME* of the commands of
883
+ `--prepare-run`, `--finish-success`, and `--finish-failure`, with
884
+ *NAME* the upper-cased *name* with every `-` replaced by `_`, where
885
+ two parameters of the same such variable are refused.
886
+
887
+ ## HOOKS
888
+
889
+ The *hooks* of a TypeScript or JavaScript definition file (its key
890
+ `hooks`, typed via `AgentHooks` of the package `@rse/ase`) are the
891
+ code-based extensions beyond the declarative options, which not only gate,
892
+ but also shape the processing. A thrown error never terminates a running
893
+ agent, but counts like a negative result with the error as its reason.
894
+
895
+ The hooks receive the *task* (its `id`, `title`, `status` adapted to the
896
+ task lifecycle model of the project, its flattened frontmatter `keys`,
897
+ and its `tags`) and a context *ctx*, which provides:
898
+
899
+ - `agent` and `lifecycle`:
900
+ The agent (its `name`, `kind`, `mode`, and `tag`) and the task
901
+ lifecycle model of the project (its `name` and its `states`).
902
+
903
+ - `params`:
904
+ The values of all declared parameters, by their names (see
905
+ **PARAMETERS**).
906
+
907
+ - `signal`:
908
+ An `AbortSignal`, aborted on the interrupt of the agent (and, within
909
+ the hooks of a job, on the timeout of its preparing resp. finishing),
910
+ which a long-running hook should honor.
911
+
912
+ - `flow(task, key)`:
913
+ The parsed `Source`, `Changeset`, or `Target` flow value (`type` and
914
+ `name`) of the task, or its configured default (where a `Target:` of
915
+ `source` reads as the `Source:`), else `null` if invalid.
916
+
917
+ - `attachments(task)`, `plan(task)`, `task(id)`, `tasks()`:
918
+ The attachments of a task (their `type`, `desc`, and inline `data`),
919
+ the plan body of a task (else `null`), a task by its id (else
920
+ `null`), and all tasks, where *task* is a task or its id.
921
+
922
+ - `update(task, change)`:
923
+ A change of a task in a single conditional update (retried on a
924
+ concurrent change, resolving to `false` if the task vanished): `keys`
925
+ to set (or to remove with `null`), except `Status`, `Assignee`,
926
+ `Tags`, and `Modified`; `tags` to `add` (*tag* or *tag*`:`*value*,
927
+ replacing the other occurrences of *tag*) and to `remove` (*tag* with
928
+ any value, or exactly *tag*`:`*value*), except the tag of the agent
929
+ itself; and `attach` attachments (`kind`, `mime` (default:
930
+ `text/plain`), `desc`, `data`, replacing those of the same kind unless
931
+ `replace: false`), except the processing logs and the processed
932
+ requests of the agent.
933
+
934
+ - `exec(cmd, args, options)`:
935
+ The run of a command without a shell (within the hooks of a job in
936
+ the working directory of the job, else in the current directory, or
937
+ in `options.cwd`, with the additional environment variables
938
+ `options.env` and the standard input `options.input`), limited to 240
939
+ seconds and cancelled by `signal`, resolving to its exit `code` (or
940
+ `-1` if it did not exit regularly), `stdout`, and `stderr`.
941
+
942
+ - `log(level, message)`:
943
+ A log line of level `error`, `warning`, or `info` (within the hooks of
944
+ a job into the processing log of the task, else into the log of the
945
+ agent).
946
+
947
+ The hooks of a job additionally receive the *job*: its working
948
+ directory `dir`, the additional directories `dirs` granted to the agent
949
+ tool, the temporary worktree `sourceDir` of a `branch:` source, the ASE
950
+ worktree id `changesetWorktree` of the changeset, and, for `request`,
951
+ the raw `request` prompt. The hooks are, in the order of their
952
+ invocation:
953
+
954
+ - `start(ctx)`:
955
+ The initialization of the agent (e.g., opening a connection) on its
956
+ start, where a thrown error refuses the start.
957
+
958
+ - `order(tasks, ctx)`:
959
+ The prioritization of the dispatchable tasks (given in natural id
960
+ order) on each dispatching: the tasks (or their ids) in the order to
961
+ claim them, where an omitted task is not claimed this time (a failed
962
+ hook keeps the natural id order and is warned about once per change).
963
+
964
+ - `passes(pred, succ, ctx)`:
965
+ (`phase` without `--unclaimed` only, synchronous) Whether the
966
+ predecessor *pred* passed the phase of the agent for its successor
967
+ *succ*, or `undefined` for the default decision by `--state-phase`
968
+ and `--state-passed` (a failed hook lets the successor wait and is
969
+ warned about once).
970
+
971
+ - `ready(task, ctx)`:
972
+ Whether a dispatchable task is claimed now, checked right before its
973
+ claim (after `--attach-skip`): `true` to claim it, `false` to
974
+ silently skip it (e.g., as the result of an earlier processing
975
+ already guards it, like the valid `Effort:` key for `estimator`), or
976
+ the reason to wait for (reported once per change of it).
977
+
978
+ - `prepare(task, job, ctx)`:
979
+ The preparing of the job in its working directory, after the commands
980
+ of `--prepare-run`, where a thrown error fails the processing without
981
+ invoking the agent tool.
982
+
983
+ - `prompt(task, prompt, job, ctx)`:
984
+ The prompt of the job, given the configured *prompt* rendered from
985
+ its template (`{ skill, args }` or `{ text }`): `{ skill, args }`,
986
+ `{ text }`, a plain prompt text, or `undefined` to keep the
987
+ configured one, where a thrown error fails the processing.
988
+
989
+ - `verdict(task, result, ctx)`:
990
+ (after a successful agent tool only) The verdict of the result (an
991
+ upper-case word, accepted only if listed by `--verdict-allow`), an
992
+ empty string for none, or `undefined` to keep the one found after
993
+ `--verdict-label` (if any). This hook can stand in for
994
+ `--verdict-label` (also for the criterion `verdict` and for
995
+ `--state-verdict`).
996
+
997
+ - `success(task, result, ctx)`:
998
+ An additional success criterion after all others (where *result*
999
+ carries `ok`, the `output` lines, and the found `verdict`): `true` if
1000
+ met, else `false` or the reason why it is not met.
1001
+
1002
+ - `settle(task, outcome, ctx)`:
1003
+ The settling of the processed task (where *outcome* carries its
1004
+ `success`, the `reasons` of the unmet success criteria, and the
1005
+ `result`), overriding the configured one: its target `state` (`phase`
1006
+ without `--unclaimed` only, still required to be reachable from the
1007
+ activity state), the value of its `tag` (`phase` only, a lower-case
1008
+ value, or `null` to untag it, refused if the task would return into
1009
+ an incoming state unguarded by `--attach-skip`, the hook `ready`, or
1010
+ the handover of a required assignment, see `--tag-success`),
1011
+ and its `assignee` (a name, `none`, or `previous`, but not with
1012
+ `--unclaimed`), where an omitted field (or `undefined` for all) keeps
1013
+ the configured settling, and a failed hook keeps the configured
1014
+ settling (and is warned about).
1015
+
1016
+ - `finish(task, outcome, job, ctx)`:
1017
+ The finishing of the job in its working directory, after the
1018
+ finishing of its work (e.g., the commit of `--finish-commit`) and
1019
+ before `--finish-success` resp. `--finish-failure`, where a thrown
1020
+ error fails the finishing of a successful processing (like a failed
1021
+ `--finish-success`), but is only reported for a failed one.
1022
+
1023
+ - `stop(ctx)`:
1024
+ The teardown of the agent (e.g., closing a connection) on its
1025
+ termination, with a fresh `signal` (a failed hook is only reported).
1026
+
1027
+ ## AGENT RELAY AND RUNS
1028
+
1029
+ An agent of a definition kind resp. an ad-hoc agent announces itself
1030
+ to the agent relay (see `ase-agent-relay`(1)) with its kind (resp.
1031
+ `adhoc`), its `--assign-name` as its mode, and, for `request`, its
1032
+ request name (suggested by key `R` of the task boards). Its runs are
1033
+ recorded per tag (below `agent-tag-`*word*`/`*store-hash* of the
1034
+ *per-user state directory* for the tag `ase-agent-`*word*), so the
1035
+ recoveries of differently configured agents never affect each other.
1036
+
1037
+ ## ENVIRONMENT
1038
+
1039
+ - `ASE_TOOL`:
1040
+ The default of `--tool`.
1041
+
1042
+ - `ASE_AGENT_RELAY_TOKEN`:
1043
+ The bearer token of the agent relay, if not embedded in its URL.
1044
+
1045
+ - `ASE_HEADLESS`:
1046
+ Set to `true` for the agent tool processes spawned by the agent.
1047
+
1048
+ - `ASE_TASK_ID`, `ASE_TASK_TITLE`, `ASE_TASK_SOURCE`, `ASE_TASK_CHANGESET`, `ASE_TASK_TARGET`, `ASE_AGENT_NAME`, `ASE_AGENT_WORKDIR`, `ASE_AGENT_PARAM_`*NAME*, `ASE_TASK_STATUS`:
1049
+ Set for the commands of `--prepare-run`, `--finish-success`, and
1050
+ `--finish-failure` (the latter only for the finishing commands).
1051
+
1052
+ ## FILES
1053
+
1054
+ - `.ase/agents/`*kind*`.`*ext*:
1055
+ The definition files of the definition kinds of the project.
1056
+
1057
+ - *per-user configuration directory*`/agents/`*kind*`.`*ext*:
1058
+ The definition files of the definition kinds of the user.
1059
+
1060
+ - `.ase/agent/`*name*`.yaml`:
1061
+ The process state (process id and process start time) of the agent
1062
+ named *name*, existing while the agent runs.
1063
+
1064
+ - `.ase/agent/`*name*`.log`:
1065
+ The log of the agent named *name* run in the background.
1066
+
1067
+ - *per-user state directory*`/agent-tag-`*word*`/`*store-hash*`/`*run-id*`.lock` and `.json`:
1068
+ The run lock and run record of each agent process of the tag
1069
+ `ase-agent-`*word*, used to recover the tasks of terminated agent
1070
+ processes.
1071
+
1072
+ ## EXIT STATUS
1073
+
1074
+ `start` and `stop` exit with status 0 on success (also for an agent
1075
+ already running resp. not running) and 1 on any error. `status` exits
1076
+ with status 1 if the agent is not running. `log` exits with status 0.
1077
+
1078
+ ## EXAMPLES
1079
+
1080
+ ```sh
1081
+ # a qualification agent deciding on the task status by its verdict
1082
+ $ ase agent adhoc start -n reviewer --state-incoming IMPLEMENTED \
1083
+ --state-activity QUALIFYING --state-phase QUALIFIED --workdir changeset-read \
1084
+ --prompt-skill ase-repo-review --prompt-args "{?changeset-type=branch:--branch {changeset-name}}" \
1085
+ --verdict-label "REVIEW VERDICT" --state-verdict APPROVE=QUALIFIED --state-verdict REJECT=DECLINED \
1086
+ --success-criterion exit --success-criterion verdict
1087
+
1088
+ # a request agent attaching a lint report (requested via "ase task request <id> lint <prompt>")
1089
+ $ ase agent adhoc start -n linter --type request --request-name lint --workdir source \
1090
+ --prompt-text "Lint the source code changed by task {id} with focus on: {prompt}" \
1091
+ --success-criterion exit --success-criterion clean --attach-output lint-report
1092
+
1093
+ # an agent running a project skill generated by "ase-meta-workflow" on the planned tasks
1094
+ $ ase agent adhoc start -n workflow --state-incoming PLANNED --tag-require workflow \
1095
+ --prompt-skill my-workflow --prompt-args "{id}"
1096
+
1097
+ # a further qualification agent of its own tag, based on a built-in definition
1098
+ $ ase agent adhoc start -n reviewer -D builtin:qualifier-qualify --tag-name ase-agent-reviewer
1099
+
1100
+ # an agent of a definition kind of the project (see .ase/agents/reviewer.mts below)
1101
+ $ ase agent reviewer start -p 2
1102
+ $ ase agent reviewer log -f
1103
+ ```
1104
+
1105
+ A YAML definition file `.ase/agents/linter.yaml`, yielding the
1106
+ definition kind `linter`:
1107
+
1108
+ ```yaml
1109
+ type: request
1110
+ workdir: source
1111
+ request:
1112
+ name: lint
1113
+ prompt:
1114
+ text: "Lint the source code changed by task {id} with focus on: {prompt}"
1115
+ success:
1116
+ criterion: [ exit, clean ]
1117
+ attach:
1118
+ output: lint-report
1119
+ ```
1120
+
1121
+ A TypeScript definition file `.ase/agents/reviewer.mts` with hooks,
1122
+ yielding the definition kind `reviewer`:
1123
+
1124
+ ```ts
1125
+ import type { AgentDefinition } from "@rse/ase"
1126
+ export default {
1127
+ type: "phase",
1128
+ lifecycle: "enterprise",
1129
+ workdir: "changeset-read",
1130
+ state: { incoming: "IMPLEMENTED", activity: "QUALIFYING", phase: "QUALIFIED" },
1131
+ tag: { name: "ase-agent-reviewer", require: "security" },
1132
+ prompt: { skill: "ase-repo-review", args: "{?changeset-type=branch:--branch {changeset-name}}" },
1133
+ verdict: { label: "REVIEW VERDICT", allow: [ "APPROVE", "REJECT" ] },
1134
+ success: { criterion: [ "exit", "verdict" ] },
1135
+ params: {
1136
+ severity: { desc: "severity of the findings a rejecting review has to cite", default: "HIGH", allow: [ "LOW", "MEDIUM", "HIGH" ] }
1137
+ },
1138
+ hooks: {
1139
+ /* review a task only once its changeset is a branch */
1140
+ ready: (task, ctx) =>
1141
+ ctx.flow(task, "Changeset")?.type === "branch" ? true : "a \"branch:\" changeset",
1142
+
1143
+ /* require a rejecting review to cite at least one finding of the configured severity */
1144
+ success: (_task, result, ctx) =>
1145
+ result.verdict !== "REJECT" || result.output.some((line) => new RegExp(`\\b${ctx.params.severity}\\b`).test(line)) ||
1146
+ `rejecting review without ${ctx.params.severity} findings`
1147
+ }
1148
+ } satisfies AgentDefinition
1149
+ ```
1150
+
1151
+ Started via `ase agent reviewer start --params severity=MEDIUM` (resp. with
1152
+ `params: { severity: MEDIUM }` in its section of a fleet configuration).
1153
+
1154
+ ## SEE ALSO
1155
+
1156
+ `ase`(1), `ase-agent`(1), `ase-agent-rebooter`(1),
1157
+ `ase-agent-condenser`(1), `ase-agent-researcher`(1),
1158
+ `ase-agent-implementer`(1), `ase-agent-qualifier`(1),
1159
+ `ase-agent-integrator`(1), `ase-agent-editor`(1),
1160
+ `ase-agent-estimator`(1), `ase-agent-relay`(1), `ase-agent-fleet`(1),
1161
+ `ase-task-request`(1), `ase-task-board`(1).
1162
+
1163
+ ## AUTHOR
1164
+
1165
+ Dr. Ralf S. Engelschall <rse@engelschall.com>