@rse/ase 1.0.7 → 2.0.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 (279) hide show
  1. package/dst/ase-agent-definition-api.d.ts +184 -0
  2. package/dst/ase-agent-definition-api.js +6 -0
  3. package/dst/ase-agent-definition-builtin/condenser.js +42 -0
  4. package/dst/ase-agent-definition-builtin/editor.js +45 -0
  5. package/dst/ase-agent-definition-builtin/estimator.js +98 -0
  6. package/dst/ase-agent-definition-builtin/implementer.js +121 -0
  7. package/dst/ase-agent-definition-builtin/integrator.js +56 -0
  8. package/dst/ase-agent-definition-builtin/qualifier.js +61 -0
  9. package/dst/ase-agent-definition-builtin/rebooter.js +41 -0
  10. package/dst/ase-agent-definition-builtin/researcher.js +77 -0
  11. package/dst/ase-agent-definition-core.js +827 -0
  12. package/dst/ase-agent-fleet.js +772 -0
  13. package/dst/ase-agent-process.js +232 -0
  14. package/dst/ase-agent-relay-client.js +509 -0
  15. package/dst/ase-agent-relay-core.js +213 -0
  16. package/dst/ase-agent-relay-server-bind.js +242 -0
  17. package/dst/ase-agent-relay-server-cli.js +50 -0
  18. package/dst/ase-agent-runtime-claim.js +189 -0
  19. package/dst/ase-agent-runtime-engine.js +1100 -0
  20. package/dst/ase-agent-runtime-exec.js +275 -0
  21. package/dst/ase-agent-runtime-phase.js +581 -0
  22. package/dst/ase-agent-runtime-request.js +272 -0
  23. package/dst/ase-agent-runtime-tool.js +207 -0
  24. package/dst/ase-agent-runtime.js +1316 -0
  25. package/dst/ase-agent.js +65 -0
  26. package/dst/ase-artifact.js +6 -5
  27. package/dst/ase-config-core.js +465 -0
  28. package/dst/ase-config-schema.js +357 -0
  29. package/dst/ase-config-scope.js +172 -0
  30. package/dst/ase-config.js +25 -585
  31. package/dst/ase-hook.js +228 -111
  32. package/dst/ase-lib-daemon-cli.js +130 -0
  33. package/dst/ase-lib-hash.js +20 -0
  34. package/dst/{ase-log.js → ase-lib-log.js} +40 -7
  35. package/dst/ase-lib-server-bind.js +115 -0
  36. package/dst/ase-lib-server-cli.js +474 -0
  37. package/dst/{ase-table.js → ase-lib-table.js} +1 -1
  38. package/dst/{ase-version.js → ase-lib-version.js} +8 -1
  39. package/dst/ase-man.js +96 -0
  40. package/dst/ase-mcp.js +166 -13
  41. package/dst/{ase-getopt.js → ase-service-getopt.js} +82 -80
  42. package/dst/{ase-markdown.js → ase-service-markdown.js} +18 -11
  43. package/dst/ase-service-otel.js +1246 -0
  44. package/dst/{ase-skills.js → ase-service-skills.js} +29 -64
  45. package/dst/ase-service-state.js +101 -0
  46. package/dst/ase-service.js +269 -81
  47. package/dst/ase-setup-common.js +141 -0
  48. package/dst/ase-setup-mcp.js +359 -0
  49. package/dst/ase-setup-settings.js +837 -0
  50. package/dst/ase-setup.js +113 -869
  51. package/dst/ase-spec.js +31 -19
  52. package/dst/ase-statusline.js +108 -43
  53. package/dst/ase-task-board-core.js +739 -0
  54. package/dst/ase-task-board-filter.js +127 -0
  55. package/dst/ase-task-board-flow.js +237 -0
  56. package/dst/ase-task-board-graph.js +497 -0
  57. package/dst/ase-task-board-stats.js +263 -0
  58. package/dst/ase-task-board-tui-control.js +775 -0
  59. package/dst/ase-task-board-tui-model.js +1008 -0
  60. package/dst/ase-task-board-tui-popup.js +626 -0
  61. package/dst/ase-task-board-tui-style.js +106 -0
  62. package/dst/ase-task-board-tui-view.js +847 -0
  63. package/dst/ase-task-board-tui.js +189 -0
  64. package/dst/ase-task-board-web-client.css +1 -0
  65. package/dst/ase-task-board-web-client.html +20 -0
  66. package/dst/ase-task-board-web-client.js +81 -0
  67. package/dst/ase-task-board-web-server.js +823 -0
  68. package/dst/ase-task-board.js +134 -0
  69. package/dst/ase-task-format.js +757 -0
  70. package/dst/ase-task-request.js +208 -0
  71. package/dst/ase-task-store-client.js +495 -0
  72. package/dst/ase-task-store-core.js +804 -0
  73. package/dst/ase-task-store-issues.js +237 -0
  74. package/dst/ase-task-store-plugin-api.js +6 -0
  75. package/dst/ase-task-store-plugin-ase.js +484 -0
  76. package/dst/ase-task-store-plugin-delegate.js +137 -0
  77. package/dst/ase-task-store-plugin-gitea.js +666 -0
  78. package/dst/ase-task-store-plugin-github.js +696 -0
  79. package/dst/ase-task-store-plugin-gitlab.js +668 -0
  80. package/dst/ase-task-store-server-bind.js +538 -0
  81. package/dst/ase-task-store-server-cli.js +154 -0
  82. package/dst/ase-task.js +1335 -357
  83. package/dst/{ase-compat.js → ase-util-compat.js} +2 -2
  84. package/dst/{ase-diagram.js → ase-util-diagram.js} +107 -32
  85. package/dst/{ase-meta.js → ase-util-meta.js} +2 -2
  86. package/dst/{ase-metric.js → ase-util-metric.js} +2 -2
  87. package/dst/{ase-mint.js → ase-util-mint.js} +19 -12
  88. package/dst/{ase-worktree.js → ase-util-worktree.js} +30 -19
  89. package/dst/ase-util.js +20 -0
  90. package/dst/ase.js +108 -32
  91. package/dst/man/ase-agent-adhoc.1 +515 -0
  92. package/dst/man/ase-agent-condenser.1 +193 -0
  93. package/dst/man/ase-agent-editor.1 +212 -0
  94. package/dst/man/ase-agent-estimator.1 +214 -0
  95. package/dst/man/ase-agent-fleet.1 +185 -0
  96. package/dst/man/ase-agent-implementer.1 +233 -0
  97. package/dst/man/ase-agent-integrator.1 +213 -0
  98. package/dst/man/ase-agent-qualifier.1 +214 -0
  99. package/dst/man/ase-agent-rebooter.1 +193 -0
  100. package/dst/man/ase-agent-relay.1 +128 -0
  101. package/dst/man/ase-agent-researcher.1 +217 -0
  102. package/dst/man/ase-agent.1 +264 -0
  103. package/dst/man/ase-artifact-list.1 +38 -0
  104. package/dst/man/ase-artifact-name.1 +39 -0
  105. package/dst/man/ase-artifact.1 +56 -0
  106. package/dst/man/ase-config-delete.1 +45 -0
  107. package/dst/man/ase-config-edit.1 +48 -0
  108. package/dst/man/ase-config-get.1 +46 -0
  109. package/dst/man/ase-config-init.1 +60 -0
  110. package/dst/man/ase-config-list.1 +42 -0
  111. package/dst/man/ase-config-set.1 +52 -0
  112. package/dst/man/ase-config.1 +231 -0
  113. package/dst/man/ase-hook-permission-request.1 +36 -0
  114. package/dst/man/ase-hook-pre-tool-use.1 +59 -0
  115. package/dst/man/ase-hook-session-end.1 +47 -0
  116. package/dst/man/ase-hook-session-persona.1 +37 -0
  117. package/dst/man/ase-hook-session-start.1 +81 -0
  118. package/dst/man/ase-hook-stop.1 +34 -0
  119. package/dst/man/ase-hook-user-prompt-submit.1 +34 -0
  120. package/dst/man/ase-hook.1 +51 -0
  121. package/dst/man/ase-man.1 +67 -0
  122. package/dst/man/ase-mcp.1 +61 -0
  123. package/dst/man/ase-service-log.1 +43 -0
  124. package/dst/man/ase-service-send.1 +47 -0
  125. package/dst/man/ase-service-start.1 +54 -0
  126. package/dst/man/ase-service-status.1 +46 -0
  127. package/dst/man/ase-service-stop.1 +37 -0
  128. package/dst/man/ase-service.1 +85 -0
  129. package/dst/man/ase-setup-disable.1 +44 -0
  130. package/dst/man/ase-setup-enable.1 +45 -0
  131. package/dst/man/ase-setup-install.1 +73 -0
  132. package/dst/man/ase-setup-mcp.1 +124 -0
  133. package/dst/man/ase-setup-status.1 +60 -0
  134. package/dst/man/ase-setup-statusline.1 +92 -0
  135. package/dst/man/ase-setup-telemetry.1 +92 -0
  136. package/dst/man/ase-setup-uninstall.1 +59 -0
  137. package/dst/man/ase-setup-update.1 +64 -0
  138. package/dst/man/ase-setup.1 +93 -0
  139. package/dst/man/ase-spec-export.1 +62 -0
  140. package/dst/man/ase-spec-lint.1 +40 -0
  141. package/dst/man/ase-spec-preview.1 +40 -0
  142. package/dst/man/ase-spec.1 +46 -0
  143. package/dst/man/ase-statusline.1 +189 -0
  144. package/dst/man/ase-task-assign.1 +71 -0
  145. package/dst/man/ase-task-board.1 +384 -0
  146. package/dst/man/ase-task-delete.1 +35 -0
  147. package/dst/man/ase-task-edit.1 +46 -0
  148. package/dst/man/ase-task-idscheme.1 +65 -0
  149. package/dst/man/ase-task-lifecycle.1 +57 -0
  150. package/dst/man/ase-task-list.1 +47 -0
  151. package/dst/man/ase-task-load.1 +36 -0
  152. package/dst/man/ase-task-newid.1 +61 -0
  153. package/dst/man/ase-task-purge.1 +37 -0
  154. package/dst/man/ase-task-rename.1 +44 -0
  155. package/dst/man/ase-task-request.1 +61 -0
  156. package/dst/man/ase-task-save.1 +48 -0
  157. package/dst/man/ase-task-status.1 +55 -0
  158. package/dst/man/ase-task-store.1 +194 -0
  159. package/dst/man/ase-task-view.1 +40 -0
  160. package/dst/man/ase-task.1 +160 -0
  161. package/dst/man/ase-util-compat.1 +25 -0
  162. package/dst/man/ase-util-diagram.1 +76 -0
  163. package/dst/man/ase-util-meta.1 +45 -0
  164. package/dst/man/ase-util-metric.1 +54 -0
  165. package/dst/man/ase-util-mint.1 +59 -0
  166. package/dst/man/ase-util-worktree.1 +72 -0
  167. package/dst/man/ase-util.1 +50 -0
  168. package/dst/man/ase.1 +124 -0
  169. package/package.json +81 -21
  170. package/plugin/.claude-plugin/plugin.json +1 -1
  171. package/plugin/.codex-plugin/plugin.json +1 -1
  172. package/plugin/.github/plugin/plugin.json +1 -1
  173. package/plugin/agents/ase-meta-diagram.md +12 -8
  174. package/plugin/agents/ase-repo-review.md +322 -0
  175. package/plugin/hooks/hooks-codex.json +5 -0
  176. package/plugin/hooks/hooks-copilot.json +5 -0
  177. package/plugin/hooks/hooks.json +8 -0
  178. package/plugin/meta/ase-common-approach.md +117 -0
  179. package/plugin/meta/ase-common-changeset.md +256 -0
  180. package/plugin/meta/ase-common-code.md +10 -173
  181. package/plugin/meta/ase-common-grill.md +317 -0
  182. package/plugin/meta/ase-common-resolve.md +305 -0
  183. package/plugin/meta/ase-common-task.md +83 -4
  184. package/plugin/meta/ase-constitution.md +0 -2
  185. package/plugin/meta/ase-format-specbook.md +208 -25
  186. package/plugin/meta/ase-format-specbook.yaml +242 -851
  187. package/plugin/meta/ase-format-task.md +669 -125
  188. package/plugin/meta/ase-persona.md +3 -4
  189. package/plugin/meta/ase-skill.md +9 -0
  190. package/plugin/mods/ase-mods.ts +409 -0
  191. package/plugin/mods/claude-code.d.ts +13417 -0
  192. package/plugin/skills/ase-arch-analyze/SKILL.md +1 -1
  193. package/plugin/skills/ase-arch-analyze/help.md +2 -2
  194. package/plugin/skills/ase-code-analyze/SKILL.md +59 -8
  195. package/plugin/skills/ase-code-analyze/help.md +29 -4
  196. package/plugin/skills/ase-code-edit/SKILL.md +107 -181
  197. package/plugin/skills/ase-code-edit/help.md +118 -31
  198. package/plugin/skills/ase-code-lint/SKILL.md +64 -13
  199. package/plugin/skills/ase-code-lint/help.md +32 -2
  200. package/plugin/skills/ase-docs-proofread/SKILL.md +4 -4
  201. package/plugin/skills/ase-docs-proofread/help.md +1 -1
  202. package/plugin/skills/ase-docs-refine/SKILL.md +4 -4
  203. package/plugin/skills/ase-docs-shorten/SKILL.md +4 -4
  204. package/plugin/skills/ase-help-intent/data.md +2164 -1087
  205. package/plugin/skills/ase-help-intent/help.md +1 -1
  206. package/plugin/skills/ase-help-skill/catalog.md +12 -9
  207. package/plugin/skills/ase-meta-brainstorm/SKILL.md +1 -1
  208. package/plugin/skills/ase-meta-config/SKILL.md +3 -4
  209. package/plugin/skills/ase-meta-config/help.md +31 -10
  210. package/plugin/skills/ase-meta-mint/SKILL.md +5 -5
  211. package/plugin/skills/ase-meta-mint/help.md +10 -5
  212. package/plugin/skills/ase-meta-why/help.md +1 -1
  213. package/plugin/skills/ase-meta-workflow/SKILL.md +7 -7
  214. package/plugin/skills/ase-meta-workflow/help.md +4 -4
  215. package/plugin/skills/ase-meta-workflow/sample.md +3 -3
  216. package/plugin/skills/ase-meta-workflow/workflow.txt +22 -18
  217. package/plugin/skills/{ase-meta-changelog → ase-repo-changelog}/SKILL.md +4 -3
  218. package/plugin/skills/{ase-meta-changelog → ase-repo-changelog}/help.md +5 -5
  219. package/plugin/skills/{ase-meta-commit → ase-repo-commit}/SKILL.md +6 -6
  220. package/plugin/skills/{ase-meta-commit → ase-repo-commit}/help.md +5 -5
  221. package/plugin/skills/{ase-meta-diff → ase-repo-diff}/SKILL.md +6 -6
  222. package/plugin/skills/{ase-meta-diff → ase-repo-diff}/help.md +8 -8
  223. package/plugin/skills/{ase-code-dissect → ase-repo-dissect}/SKILL.md +19 -19
  224. package/plugin/skills/{ase-code-dissect → ase-repo-dissect}/help.md +10 -12
  225. package/plugin/skills/ase-repo-merge/SKILL.md +346 -0
  226. package/plugin/skills/ase-repo-merge/help.md +107 -0
  227. package/plugin/skills/ase-repo-resolve/SKILL.md +158 -0
  228. package/plugin/skills/ase-repo-resolve/help.md +102 -0
  229. package/plugin/skills/ase-repo-review/SKILL.md +406 -0
  230. package/plugin/skills/ase-repo-review/help.md +181 -0
  231. package/plugin/skills/ase-spec-edit/SKILL.md +117 -183
  232. package/plugin/skills/ase-spec-edit/help.md +107 -26
  233. package/plugin/skills/ase-sync-reconcile/help.md +1 -1
  234. package/plugin/skills/ase-task-assign/SKILL.md +111 -0
  235. package/plugin/skills/ase-task-assign/help.md +119 -0
  236. package/plugin/skills/ase-task-condense/SKILL.md +21 -21
  237. package/plugin/skills/ase-task-condense/help.md +12 -10
  238. package/plugin/skills/ase-task-delete/SKILL.md +1 -1
  239. package/plugin/skills/ase-task-dissect/SKILL.md +71 -48
  240. package/plugin/skills/ase-task-dissect/help.md +10 -9
  241. package/plugin/skills/ase-task-edit/SKILL.md +379 -94
  242. package/plugin/skills/ase-task-edit/help.md +95 -22
  243. package/plugin/skills/ase-task-estimate/SKILL.md +492 -0
  244. package/plugin/skills/ase-task-estimate/help.md +158 -0
  245. package/plugin/skills/ase-task-grill/SKILL.md +246 -138
  246. package/plugin/skills/ase-task-grill/help.md +129 -26
  247. package/plugin/skills/ase-task-id/SKILL.md +8 -1
  248. package/plugin/skills/ase-task-id/help.md +6 -3
  249. package/plugin/skills/ase-task-implement/SKILL.md +535 -145
  250. package/plugin/skills/ase-task-implement/help.md +138 -47
  251. package/plugin/skills/ase-task-integrate/SKILL.md +549 -0
  252. package/plugin/skills/ase-task-integrate/help.md +187 -0
  253. package/plugin/skills/ase-task-list/SKILL.md +55 -23
  254. package/plugin/skills/ase-task-list/help.md +45 -21
  255. package/plugin/skills/ase-task-reboot/SKILL.md +84 -43
  256. package/plugin/skills/ase-task-reboot/help.md +28 -8
  257. package/plugin/skills/ase-task-rename/SKILL.md +10 -2
  258. package/plugin/skills/ase-task-research/SKILL.md +386 -0
  259. package/plugin/skills/ase-task-research/help.md +102 -0
  260. package/plugin/skills/ase-task-status/SKILL.md +137 -0
  261. package/plugin/skills/ase-task-status/help.md +80 -0
  262. package/plugin/skills/ase-task-view/SKILL.md +49 -24
  263. package/plugin/skills/ase-task-view/help.md +19 -9
  264. package/plugin/agents/ase-meta-review.md +0 -187
  265. package/plugin/skills/ase-code-craft/SKILL.md +0 -264
  266. package/plugin/skills/ase-code-craft/help.md +0 -122
  267. package/plugin/skills/ase-code-refactor/SKILL.md +0 -232
  268. package/plugin/skills/ase-code-refactor/help.md +0 -109
  269. package/plugin/skills/ase-code-resolve/SKILL.md +0 -289
  270. package/plugin/skills/ase-code-resolve/help.md +0 -116
  271. package/plugin/skills/ase-meta-review/SKILL.md +0 -210
  272. package/plugin/skills/ase-meta-review/help.md +0 -96
  273. package/plugin/skills/ase-task-preflight/SKILL.md +0 -166
  274. package/plugin/skills/ase-task-preflight/help.md +0 -82
  275. /package/dst/{ase-ignore.js → ase-lib-ignore.js} +0 -0
  276. /package/dst/{ase-stdio.js → ase-lib-stdio.js} +0 -0
  277. /package/dst/{ase-kv.js → ase-service-kv.js} +0 -0
  278. /package/dst/{ase-sleep.js → ase-service-sleep.js} +0 -0
  279. /package/dst/{ase-timestamp.js → ase-service-timestamp.js} +0 -0
@@ -0,0 +1,184 @@
1
+ type Many<T> = T | T[];
2
+ export type AgentType = "phase" | "request";
3
+ export type AgentWorkdir = "project" | "source" | "changeset" | "changeset-read" | "target";
4
+ export type AgentCriterion = "exit" | "clean" | "changed" | "verdict" | "attachment" | "status";
5
+ export interface AgentParam {
6
+ desc?: string;
7
+ default?: string | number | boolean;
8
+ required?: boolean;
9
+ allow?: Many<string>;
10
+ }
11
+ export interface AgentDefinition {
12
+ definition?: string;
13
+ title?: string;
14
+ description?: string;
15
+ params?: Record<string, AgentParam | string | number | boolean>;
16
+ type?: AgentType;
17
+ workdir?: AgentWorkdir;
18
+ lifecycle?: Many<string>;
19
+ serial?: boolean;
20
+ unclaimed?: boolean;
21
+ state?: {
22
+ incoming?: Many<string>;
23
+ activity?: string;
24
+ success?: string;
25
+ failure?: string;
26
+ phase?: string;
27
+ passed?: string;
28
+ verdict?: Many<string>;
29
+ };
30
+ tag?: {
31
+ name?: string;
32
+ success?: string;
33
+ failure?: string;
34
+ require?: Many<string>;
35
+ exclude?: Many<string>;
36
+ retry?: boolean;
37
+ };
38
+ assign?: {
39
+ name?: string;
40
+ required?: boolean;
41
+ success?: string;
42
+ failure?: string;
43
+ };
44
+ request?: {
45
+ name?: string;
46
+ done?: string;
47
+ };
48
+ prompt?: {
49
+ skill?: string;
50
+ args?: string;
51
+ text?: string;
52
+ file?: string;
53
+ };
54
+ prepare?: {
55
+ run?: Many<string>;
56
+ };
57
+ success?: {
58
+ criterion?: Many<AgentCriterion>;
59
+ match?: Many<string>;
60
+ };
61
+ verdict?: {
62
+ label?: string;
63
+ allow?: Many<string>;
64
+ };
65
+ attach?: {
66
+ output?: string;
67
+ expect?: string;
68
+ skip?: string;
69
+ changeset?: string;
70
+ };
71
+ finish?: {
72
+ commit?: boolean;
73
+ success?: string;
74
+ failure?: string;
75
+ };
76
+ hooks?: AgentHooks;
77
+ }
78
+ export type AgentDefinitionExport = AgentDefinition | (() => AgentDefinition | Promise<AgentDefinition>);
79
+ export interface AgentHookTask {
80
+ readonly id: string;
81
+ readonly title: string;
82
+ readonly status: string;
83
+ readonly keys: Readonly<Record<string, string>>;
84
+ readonly tags: readonly string[];
85
+ }
86
+ export interface AgentHookFlow {
87
+ readonly type: string;
88
+ readonly name: string;
89
+ }
90
+ export interface AgentHookAttachment {
91
+ readonly type: string;
92
+ readonly desc: string;
93
+ readonly data?: string;
94
+ }
95
+ export type AgentHookLevel = "error" | "warning" | "info";
96
+ export interface AgentHookExec {
97
+ readonly code: number;
98
+ readonly stdout: string;
99
+ readonly stderr: string;
100
+ }
101
+ export interface AgentHookAttach {
102
+ readonly kind: string;
103
+ readonly mime?: string;
104
+ readonly desc?: string;
105
+ readonly data: string;
106
+ readonly replace?: boolean;
107
+ }
108
+ export interface AgentHookUpdate {
109
+ keys?: Readonly<Record<string, string | null>>;
110
+ tags?: {
111
+ readonly add?: readonly string[];
112
+ readonly remove?: readonly string[];
113
+ };
114
+ attach?: readonly AgentHookAttach[];
115
+ }
116
+ export interface AgentHookContext {
117
+ readonly agent: {
118
+ readonly name: string;
119
+ readonly kind: string;
120
+ readonly mode: string;
121
+ readonly tag: string;
122
+ };
123
+ readonly params: Readonly<Record<string, string>>;
124
+ readonly lifecycle: {
125
+ readonly name: string;
126
+ readonly states: readonly string[];
127
+ };
128
+ readonly signal: AbortSignal;
129
+ flow(task: AgentHookTask, key: "Source" | "Changeset" | "Target"): AgentHookFlow | null;
130
+ attachments(task: AgentHookTask | string): Promise<readonly AgentHookAttachment[]>;
131
+ plan(task: AgentHookTask | string): Promise<string | null>;
132
+ task(id: string): Promise<AgentHookTask | null>;
133
+ tasks(): Promise<readonly AgentHookTask[]>;
134
+ update(task: AgentHookTask | string, change: AgentHookUpdate): Promise<boolean>;
135
+ exec(cmd: string, args?: readonly string[], options?: {
136
+ readonly cwd?: string;
137
+ readonly env?: Readonly<Record<string, string>>;
138
+ readonly input?: string;
139
+ }): Promise<AgentHookExec>;
140
+ log(level: AgentHookLevel, message: string): void;
141
+ }
142
+ export interface AgentHookJob {
143
+ readonly dir: string;
144
+ readonly dirs: readonly string[];
145
+ readonly sourceDir: string;
146
+ readonly changesetWorktree: string;
147
+ readonly request: string;
148
+ }
149
+ export type AgentHookPrompt = {
150
+ readonly skill: string;
151
+ readonly args: string;
152
+ } | {
153
+ readonly text: string;
154
+ };
155
+ export interface AgentHookResult {
156
+ readonly ok: boolean;
157
+ readonly output: readonly string[];
158
+ readonly verdict: string;
159
+ }
160
+ export interface AgentHookOutcome {
161
+ readonly success: boolean;
162
+ readonly reasons: readonly string[];
163
+ readonly result: AgentHookResult;
164
+ }
165
+ export interface AgentHookSettlement {
166
+ readonly state?: string;
167
+ readonly tag?: string | null;
168
+ readonly assignee?: string;
169
+ }
170
+ type Async<T> = T | Promise<T>;
171
+ export interface AgentHooks {
172
+ start?: (ctx: AgentHookContext) => Async<void>;
173
+ order?: (tasks: readonly AgentHookTask[], ctx: AgentHookContext) => Async<readonly (AgentHookTask | string)[]>;
174
+ passes?: (pred: AgentHookTask, succ: AgentHookTask, ctx: AgentHookContext) => boolean | undefined;
175
+ ready?: (task: AgentHookTask, ctx: AgentHookContext) => Async<boolean | string>;
176
+ prepare?: (task: AgentHookTask, job: AgentHookJob, ctx: AgentHookContext) => Async<void>;
177
+ prompt?: (task: AgentHookTask, prompt: AgentHookPrompt, job: AgentHookJob, ctx: AgentHookContext) => Async<AgentHookPrompt | string | undefined>;
178
+ verdict?: (task: AgentHookTask, result: AgentHookResult, ctx: AgentHookContext) => Async<string | undefined>;
179
+ success?: (task: AgentHookTask, result: AgentHookResult, ctx: AgentHookContext) => Async<boolean | string>;
180
+ settle?: (task: AgentHookTask, outcome: AgentHookOutcome, ctx: AgentHookContext) => Async<AgentHookSettlement | undefined>;
181
+ finish?: (task: AgentHookTask, outcome: AgentHookOutcome, job: AgentHookJob, ctx: AgentHookContext) => Async<void>;
182
+ stop?: (ctx: AgentHookContext) => Async<void>;
183
+ }
184
+ export {};
@@ -0,0 +1,6 @@
1
+ /*
2
+ ** Agentic Software Engineering (ASE)
3
+ ** Copyright (c) 2025-2026 Dr. Ralf S. Engelschall <rse@engelschall.com>
4
+ ** Licensed under Apache 2.0 <https://spdx.org/licenses/Apache-2.0>
5
+ */
6
+ export {};
@@ -0,0 +1,42 @@
1
+ /*
2
+ ** Agentic Software Engineering (ASE)
3
+ ** Copyright (c) 2025-2026 Dr. Ralf S. Engelschall <rse@engelschall.com>
4
+ ** Licensed under Apache 2.0 <https://spdx.org/licenses/Apache-2.0>
5
+ */
6
+ /* agent "ase agent condenser", processing a plan only on explicit request,
7
+ i.e., once a human assigned the task to the condenser (by its name) */
8
+ export default {
9
+ kind: "condenser",
10
+ description: "Condense the plans of tasks in the \"Planning\" phase of the \"enterprise\" task lifecycle " +
11
+ "model on explicit request: claim every \"DRAFTED\" task explicitly assigned to the " +
12
+ "condenser (by its name) into \"PLANNING\", " +
13
+ "compress the wording of its plan via the headless agent tool and the \"ase-task-condense\" " +
14
+ "skill, and put it back into \"DRAFTED\" and unassign it (or put it back into \"DRAFTED\" " +
15
+ "with its previous assignee on interrupt), logging to stdout and to the \"agent\" " +
16
+ "attachment of the task",
17
+ modeDesc: "",
18
+ mode: "condense",
19
+ modes: {
20
+ /* compress the wording of the plan of a task, where the skill leaves the task in
21
+ "PLANNING", so the agent puts it back into "DRAFTED", and where the task is untagged
22
+ and unassigned afterwards, so it is guarded by its assignment only and hence condensed
23
+ again once a human assigns it to the condenser again, and where the processing
24
+ succeeded only if the agent tool succeeded and the skill reported no error (as the
25
+ agent tool still exits successfully then), including on an already condensed plan, and
26
+ where the task waits for no predecessors (see the rebooter) */
27
+ condense: {
28
+ title: "Condense the plans of assigned tasks",
29
+ description: "Claims every DRAFTED task explicitly assigned to the condenser into PLANNING. Compresses " +
30
+ "the wording of its plan via the ase-task-condense skill, puts it back into DRAFTED, and " +
31
+ "unassigns it, so assigning it to the condenser again requests another condensing.",
32
+ type: "phase",
33
+ lifecycle: "enterprise",
34
+ workdir: "project",
35
+ state: { incoming: "DRAFTED", activity: "PLANNING", success: "DRAFTED", failure: "DRAFTED" },
36
+ tag: { success: "none", failure: "none" },
37
+ assign: { required: true },
38
+ prompt: { skill: "ase-task-condense", args: "--next DONE {id}" },
39
+ success: { criterion: ["exit", "clean"] }
40
+ }
41
+ }
42
+ };
@@ -0,0 +1,45 @@
1
+ /*
2
+ ** Agentic Software Engineering (ASE)
3
+ ** Copyright (c) 2025-2026 Dr. Ralf S. Engelschall <rse@engelschall.com>
4
+ ** Licensed under Apache 2.0 <https://spdx.org/licenses/Apache-2.0>
5
+ */
6
+ /* agent "ase agent editor" */
7
+ export default {
8
+ kind: "editor",
9
+ description: "Process the edit requests of tasks in any task lifecycle model, as requested with key " +
10
+ "\"E\" on the task board: claim every task tagged with \"ase-agent-editor:pending\" " +
11
+ "(except in an activity status, until it changes) by turning its oldest \"edit\" " +
12
+ "attachment into \"edit-running\" and assigning the task to the agent (keeping all " +
13
+ "other agents off it), edit its plan by the prompt of the request via the headless " +
14
+ "agent tool and the \"ase-task-edit\" skill (grounded in its \"Source:\", a " +
15
+ "\"branch:\" one checked out in a temporary Git worktree, and saved only if not " +
16
+ "changed meanwhile), restore its previous assignee, and remove the request if the plan " +
17
+ "was changed (else turn it into \"edit-failed\", or back into \"edit\" on interrupt), " +
18
+ "logging to stdout and to the \"agent\" attachment of the task",
19
+ modeDesc: "",
20
+ mode: "edit",
21
+ modes: {
22
+ /* edit the plan of the task by the prompt of the request in the working copy,
23
+ grounded in the "Source:" of the task: a "worktree" one in the working copy
24
+ itself, and a "branch:" one in a temporary, detached Git worktree of the
25
+ branch (passed to the skill and the agent tool), which is removed afterwards,
26
+ where the processing succeeded only if the plan content changed since the
27
+ claim and the skill reported no error */
28
+ edit: {
29
+ title: "Edit task plans by the prompts of edit requests",
30
+ description: "Claims every task with a pending edit request (requested with key E on the task boards) " +
31
+ "in any task lifecycle model and in any status except an activity one. Edits its plan by " +
32
+ "the prompt of the request via the ase-task-edit skill (grounded in the Source: of the " +
33
+ "task), restores its previous assignee, and removes the request if the plan was changed, " +
34
+ "else marks the request as failed.",
35
+ type: "request",
36
+ workdir: "source",
37
+ request: { name: "edit", done: "edited" },
38
+ prompt: {
39
+ skill: "ase-task-edit",
40
+ args: "--plan REFINE --next DONE{?source-dir: --int-source-dir \"{source-dir}\"} {id}: {prompt}"
41
+ },
42
+ success: { criterion: ["clean", "changed"] }
43
+ }
44
+ }
45
+ };
@@ -0,0 +1,98 @@
1
+ /*
2
+ ** Agentic Software Engineering (ASE)
3
+ ** Copyright (c) 2025-2026 Dr. Ralf S. Engelschall <rse@engelschall.com>
4
+ ** Licensed under Apache 2.0 <https://spdx.org/licenses/Apache-2.0>
5
+ */
6
+ import { parseEffort } from "../ase-task-format.js";
7
+ /* whether a task carries a valid effort estimation (its "Effort" key), as the task store
8
+ drops a stale one (whose content hash no longer matches the plan body) on loading
9
+ and listing, so a loaded task carries a well-formed one only if it is valid */
10
+ const estimated = (task) => parseEffort(task.keys.Effort ?? "") !== null;
11
+ /* whether a task awaits its effort estimation: it carries no valid effort estimation yet,
12
+ it is no explicit epic (a task being its own group, whose effort is the sum of its
13
+ members), and its plan is not empty (as both are skipped by the skill), where this is
14
+ also the condition the implementer waits on (see its parameter "effort-wait") */
15
+ export const estimable = async (task, ctx) => !estimated(task) && (task.keys.Group ?? "").trim() !== task.id
16
+ && ((await ctx.plan(task)) ?? "").trim() !== "";
17
+ /* the estimation succeeded only once the task carries a valid effort
18
+ estimation, as the skill reports a failed estimation without an error */
19
+ const succeeded = async (task, ctx) => {
20
+ const current = await ctx.task(task.id);
21
+ return current !== null && estimated(current) ? true : "task carries no valid \"Effort\" key";
22
+ };
23
+ /* agent "ase agent estimator" */
24
+ export default {
25
+ kind: "estimator",
26
+ description: "Estimate the effort of tasks in any task lifecycle model: pick every task in \"PLANNED\" " +
27
+ "(adapted onto the task lifecycle model, i.e., \"PLANNING\" for \"team\" and \"OPEN\" for " +
28
+ "\"solo\"), without tag \"ase-agent-estimator\", without a valid \"Effort\" key, with a " +
29
+ "non-empty plan, and which is no explicit epic, without claiming it (so its status and its " +
30
+ "assignee are never changed and no other agent is kept off it), estimate its effort via the " +
31
+ "headless agent tool and the \"ase-task-estimate\" skill (which writes just its \"Effort\" key " +
32
+ "in a conditional save), and tag it with \"ase-agent-estimator\" only if it carries no valid " +
33
+ "\"Effort\" key afterwards (so it is not picked again) (\"--mode phase\", intended for the " +
34
+ "final estimation of the planned tasks), or process the \"estimate\" requests of tasks in any " +
35
+ "unfinished status (e.g. \"DRAFTED\"), as requested with key \"R\" on the task board, by " +
36
+ "claiming the task like the editor agent and re-estimating its effort even if it carries a " +
37
+ "valid one (\"--mode request\", intended for dry-runs, i.e., provisional estimations of plans " +
38
+ "still in progress), logging to stdout and to the \"agent\" attachment of the task",
39
+ modeDesc: "\"phase\" for the final estimation of the unestimated tasks in \"PLANNED\" automatically, or " +
40
+ "\"request\" for dry-runs, (re-)estimating the tasks in any unfinished status on request",
41
+ mode: "phase",
42
+ modes: {
43
+ /* estimate the effort of the task in the project root, where the task is processed
44
+ unclaimed, as the skill saves just the "Effort" key conditionally (retried on a
45
+ concurrent change, e.g. by a claim of another agent), and where an estimated task
46
+ is left untagged, as its valid "Effort" key itself guards it (see the hook "ready"),
47
+ so it is estimated again once its plan content changed (as the task store drops its
48
+ then stale "Effort" key), while a task not estimated is tagged, so it is not picked
49
+ again and again */
50
+ phase: {
51
+ title: "Estimate the effort of unestimated planned tasks",
52
+ description: "Picks every PLANNED task without a valid Effort: key, with a non-empty plan, and which is " +
53
+ "no explicit epic, without claiming it (so its status and its assignee stay untouched). " +
54
+ "Estimates its effort as a T-shirt size via the ase-task-estimate skill, which stores just " +
55
+ "its Effort: key, and tags it only if it is still unestimated afterwards, so it is not " +
56
+ "picked again. Intended for the final estimation of the planned tasks.",
57
+ type: "phase",
58
+ unclaimed: true,
59
+ workdir: "project",
60
+ state: { incoming: "PLANNED" },
61
+ tag: { name: "ase-agent-estimator", success: "none" },
62
+ prompt: { skill: "ase-task-estimate", args: "{id}" },
63
+ success: { criterion: ["exit", "clean"] },
64
+ hooks: {
65
+ /* estimate only a task awaiting its effort estimation */
66
+ ready: (task, ctx) => estimable(task, ctx),
67
+ /* the estimation succeeded only with a valid effort estimation */
68
+ success: (task, _result, ctx) => succeeded(task, ctx)
69
+ }
70
+ },
71
+ /* estimate the effort of the task of an "estimate" request in the project root, in
72
+ any unfinished status (e.g. "DRAFTED", where the phase mode never picks it), where
73
+ the task is claimed like by the editor agent, and where the estimation is forced,
74
+ as the request explicitly asks for it even if the task carries a valid one, and
75
+ where the prompt of the request is ignored (and the criterion "changed" is not
76
+ used, as a re-estimation of the same size leaves the plan content unchanged),
77
+ and where the success additionally requires the reported status of a stored
78
+ estimation, as the hook "success" alone also passes on the old, still valid
79
+ effort estimation left untouched by a failed re-estimation */
80
+ request: {
81
+ title: "Re-estimate the effort of tasks on request",
82
+ description: "Claims every task with a pending estimate request (requested with key R on the task " +
83
+ "boards) in any unfinished status. Re-estimates its effort as a T-shirt size via the " +
84
+ "ase-task-estimate skill, even if it already carries a valid Effort: key (ignoring the " +
85
+ "prompt of the request), restores its previous assignee, and removes the request on success. " +
86
+ "Intended for dry-runs, i.e., provisional estimations of plans still in progress.",
87
+ type: "request",
88
+ workdir: "project",
89
+ request: { name: "estimate", done: "estimated" },
90
+ prompt: { skill: "ase-task-estimate", args: "--force {id}" },
91
+ success: { criterion: ["exit", "clean"], match: ["status:\\W*effort estimated\\b"] },
92
+ hooks: {
93
+ /* the estimation succeeded only with a valid effort estimation */
94
+ success: (task, _result, ctx) => succeeded(task, ctx)
95
+ }
96
+ }
97
+ }
98
+ };
@@ -0,0 +1,121 @@
1
+ /*
2
+ ** Agentic Software Engineering (ASE)
3
+ ** Copyright (c) 2025-2026 Dr. Ralf S. Engelschall <rse@engelschall.com>
4
+ ** Licensed under Apache 2.0 <https://spdx.org/licenses/Apache-2.0>
5
+ */
6
+ import { estimable } from "./estimator.js";
7
+ /* the parameters of the implementer: whether a task is claimed only once the estimator
8
+ is done with it (default), to be disabled when no estimator agent is used */
9
+ const params = {
10
+ "effort-wait": {
11
+ desc: "whether to wait for the effort estimation of a task by the agent \"estimator\"",
12
+ default: "true",
13
+ allow: ["true", "false"]
14
+ }
15
+ };
16
+ /* with the parameter "effort-wait", a task is claimed only once the estimator is done
17
+ with it, i.e., once it no longer awaits its effort estimation, or once the estimator
18
+ failed on it (and hence tagged it, so it is not estimated again), as the estimator
19
+ processes the "PLANNED" tasks unclaimed and would else race against the implementer,
20
+ which, if claiming a task first, would keep it from being estimated at all */
21
+ const ready = async (task, ctx) => ctx.params["effort-wait"] !== "true"
22
+ || task.tags.some((tag) => tag === "ase-agent-estimator" || tag.startsWith("ase-agent-estimator:"))
23
+ || !(await estimable(task, ctx))
24
+ || "its effort estimation by the agent \"estimator\"";
25
+ /* a predecessor passed the implementation phase for its successor only once its change
26
+ set is contained in the "Source:" of the successor, from which the successor is
27
+ implemented resp. drafted, i.e., once integrated (and its integrated target branch
28
+ published, i.e., not still held by the integrator or failed there), or, for a
29
+ successor stacked onto it (with the "branch:" changeset of the predecessor as its
30
+ "Source:"), already once implemented (and its changeset branch committed and
31
+ published, i.e., not still held by the implementer or failed there), where an
32
+ invalid "Source:" or "Changeset:" value never stacks, and where the implementer is
33
+ recognized by the tag <implementer> (default: the tag of the agent itself, so the
34
+ definition reused under another tag recognizes its own implementing), while the
35
+ integrator is recognized by the tag of the built-in integrator by convention */
36
+ const passes = (implementer) => (pred, succ, ctx) => {
37
+ const held = (tag) => pred.tags.includes(`${tag}:active`) || pred.tags.includes(`${tag}:failed`);
38
+ const changeset = ctx.flow(pred, "Changeset");
39
+ const source = ctx.flow(succ, "Source");
40
+ const stacked = changeset?.type === "branch" && source?.type === "branch" && changeset.name === source.name;
41
+ const states = ctx.lifecycle.states;
42
+ if (stacked)
43
+ return states.indexOf(pred.status) >= states.indexOf("IMPLEMENTED")
44
+ && !(pred.status === "IMPLEMENTED" && held(implementer ?? ctx.agent.tag));
45
+ else
46
+ return pred.status === "INTEGRATED" && !held("ase-agent-integrator");
47
+ };
48
+ /* agent "ase agent implementer" */
49
+ export default {
50
+ kind: "implementer",
51
+ description: "Drive the \"Implementation\" phase of the \"enterprise\" task lifecycle model: claim " +
52
+ "every \"PLANNED\" task unassigned or assigned to the implementer, not yet tagged " +
53
+ "\"ase-agent-implementer\", and with integrated \"After:\" predecessors (or implemented ones, " +
54
+ "if stacked onto their \"branch:\" changeset by its \"Source:\") into " +
55
+ "\"IMPLEMENTING\", implement it from its \"Source:\" into its \"Changeset:\" via the " +
56
+ "\"ase-task-implement\" skill (in a Git worktree where needed), tag it, and put it into " +
57
+ "\"STALLED\" unless it became \"IMPLEMENTED\" (tagged \"ase-agent-implementer:failed\" " +
58
+ "if its branch could not be published), or, with \"--mode draft\", only draft the " +
59
+ "implementation of tasks without a draft yet into their \"draft\" attachment and put " +
60
+ "them back into \"PLANNED\", logging to stdout and to the \"agent\" " +
61
+ "attachment of the task",
62
+ modeDesc: "\"implement\" to implement the task into its changeset, or \"draft\" " +
63
+ "to just draft its implementation into its \"draft\" attachment",
64
+ mode: "implement",
65
+ modes: {
66
+ /* implement the task from its source into its changeset, which the skill itself puts
67
+ into "IMPLEMENTED" on success (else it is stalled), where a "branch:" changeset is
68
+ implemented in place in the worktree carrying its branch, while the "Source:" of the
69
+ plan stays in effect, the change set snapshot is attached by the agent itself, based
70
+ on the fork point of the branch from its source (and hence shows the entire branch,
71
+ also on a re-run of a declined task), and the work on it is afterwards committed onto
72
+ it and published */
73
+ implement: {
74
+ title: "Implement planned tasks into their changesets",
75
+ description: "Claims every PLANNED task unassigned or assigned to the implementer, not yet implemented, " +
76
+ "and with integrated After: predecessors into IMPLEMENTING. Implements its plan from its " +
77
+ "Source: into its Changeset: via the ase-task-implement skill (in a Git worktree where " +
78
+ "needed), commits and publishes a branch: changeset, attaches a snapshot of the change " +
79
+ "set, and puts it into IMPLEMENTED on success, else into STALLED.",
80
+ params,
81
+ type: "phase",
82
+ lifecycle: "enterprise",
83
+ workdir: "changeset",
84
+ state: { incoming: "PLANNED", activity: "IMPLEMENTING", success: "IMPLEMENTED", failure: "STALLED", passed: "IMPLEMENTED" },
85
+ tag: { name: "ase-agent-implementer" },
86
+ prompt: {
87
+ skill: "ase-task-implement",
88
+ args: "--next DONE{?changeset-type=branch: --changeset worktree}" +
89
+ "{?changeset-worktree: --worktree {changeset-worktree}} {id}"
90
+ },
91
+ success: { criterion: ["status"] },
92
+ attach: { changeset: "changeset" },
93
+ finish: { commit: true },
94
+ hooks: { passes: passes(), ready }
95
+ },
96
+ /* draft the implementation of the task into its "draft" attachment only (in a temporary
97
+ worktree of the skill, from the source commit, without uncommitted changes, so the
98
+ working copy is used as-is and the drafts are parallel-safe), where the skill leaves
99
+ the task status untouched, so it is put back into "PLANNED" in any case, untagged
100
+ if drafted (as its draft attachment itself keeps it from being drafted again), and
101
+ else tagged with a tag separate from the one of the implementing, so a drafted task
102
+ is still implemented later */
103
+ draft: {
104
+ title: "Draft the implementation of planned tasks",
105
+ description: "Claims every PLANNED task without an implementation draft yet into IMPLEMENTING. Drafts " +
106
+ "its implementation via the ase-task-implement skill into its draft attachment only (in a " +
107
+ "temporary worktree, leaving the working copy untouched), and puts it back into PLANNED in " +
108
+ "any case, so it can still be implemented later.",
109
+ params,
110
+ type: "phase",
111
+ lifecycle: "enterprise",
112
+ workdir: "source",
113
+ state: { incoming: "PLANNED", activity: "IMPLEMENTING", success: "PLANNED", failure: "PLANNED", phase: "IMPLEMENTED", passed: "IMPLEMENTED" },
114
+ tag: { name: "ase-agent-implementer-draft", success: "none" },
115
+ attach: { skip: "text/x-diff;draft", expect: "text/x-diff;draft" },
116
+ prompt: { skill: "ase-task-implement", args: "--next DONE --draft --stateless {id}" },
117
+ success: { criterion: ["exit", "attachment"] },
118
+ hooks: { passes: passes("ase-agent-implementer"), ready }
119
+ }
120
+ }
121
+ };
@@ -0,0 +1,56 @@
1
+ /*
2
+ ** Agentic Software Engineering (ASE)
3
+ ** Copyright (c) 2025-2026 Dr. Ralf S. Engelschall <rse@engelschall.com>
4
+ ** Licensed under Apache 2.0 <https://spdx.org/licenses/Apache-2.0>
5
+ */
6
+ /* integrate the changeset of the task into its target by the Git operation <mode> (described
7
+ as <how>), where the skill itself puts the task into "INTEGRATED" on success, so the task counts as
8
+ integrated on the "plan integrated" status of the skill only (else it is deferred), where
9
+ the agent itself attaches the change set snapshot of the change set which finally landed
10
+ on the target, and where the tasks are processed serially only, as merges into the same
11
+ target branch cannot run concurrently */
12
+ const integrate = (mode, how) => ({
13
+ title: `Integrate qualified tasks by ${how}`,
14
+ description: "Claims every QUALIFIED task unassigned or assigned to the integrator, not yet integrated, " +
15
+ "and with integrated After: predecessors into INTEGRATING, one task at a time. Integrates " +
16
+ `its Changeset: into its Target: by ${how} via the ase-task-integrate skill, attaches a ` +
17
+ "snapshot of the landed change set, and puts it into INTEGRATED on success, else into DEFERRED.",
18
+ type: "phase",
19
+ lifecycle: "enterprise",
20
+ serial: true,
21
+ workdir: "target",
22
+ state: { incoming: "QUALIFIED", activity: "INTEGRATING", success: "INTEGRATED", failure: "DEFERRED", passed: "INTEGRATED" },
23
+ tag: { name: "ase-agent-integrator" },
24
+ prompt: {
25
+ skill: "ase-task-integrate",
26
+ args: `--next DONE --mode ${mode}{?changeset-worktree: --worktree {changeset-worktree}} {id}`
27
+ },
28
+ success: { criterion: ["exit"], match: ["status:\\W*plan integrated\\b"] },
29
+ attach: { changeset: "changeset" }
30
+ });
31
+ /* agent "ase agent integrator" */
32
+ export default {
33
+ kind: "integrator",
34
+ description: "Drive the \"Integration\" phase of the \"enterprise\" task lifecycle model: claim every " +
35
+ "\"QUALIFIED\" task unassigned or assigned to the integrator (by its name), without tag " +
36
+ "\"ase-agent-integrator\", and with integrated \"After:\" predecessors into " +
37
+ "\"INTEGRATING\", integrate its \"Changeset:\" into its \"Target:\" (a \"branch:\" " +
38
+ "target not checked out yet in a temporary Git worktree) via the headless agent tool and " +
39
+ "the \"ase-task-integrate\" skill (by a merge, rebase, or squash after \"--mode\"), tag " +
40
+ "it with \"ase-agent-integrator\", and put it into \"INTEGRATED\" if integrated, or into " +
41
+ "\"DEFERRED\" otherwise (or \"QUALIFIED\" untagged on interrupt, or left \"INTEGRATED\" " +
42
+ "with tag \"ase-agent-integrator:failed\" if its integrated target branch could not be " +
43
+ "published), processing the tasks serially (ignoring \"--parallel\") and logging to " +
44
+ "stdout and to the \"agent\" attachment of the task",
45
+ modeDesc: "\"merge\", \"rebase\", or \"squash\" to integrate the changeset " +
46
+ "into the target by a merge commit, a rebase with fast-forward, or a squash commit",
47
+ mode: "squash",
48
+ modes: {
49
+ /* create a merge commit */
50
+ merge: integrate("merge", "a merge commit"),
51
+ /* rebase the changeset onto the target and fast-forward the target */
52
+ rebase: integrate("rebase", "a rebase with fast-forward"),
53
+ /* combine the changeset into one new commit on the target */
54
+ squash: integrate("squash", "a squash commit")
55
+ }
56
+ };
@@ -0,0 +1,61 @@
1
+ /*
2
+ ** Agentic Software Engineering (ASE)
3
+ ** Copyright (c) 2025-2026 Dr. Ralf S. Engelschall <rse@engelschall.com>
4
+ ** Licensed under Apache 2.0 <https://spdx.org/licenses/Apache-2.0>
5
+ */
6
+ /* review the changeset of the task (a "worktree" one staged, a "branch:" one against its
7
+ base, an "attachment:" one staged in a temporary Git worktree) and tag the task with the
8
+ verdict "APPROVE" resp. "REJECT" of the review (or plain without a verdict, e.g. on a
9
+ failed or skipped review), where the task is put back into "IMPLEMENTED" for a human
10
+ decision, except where the verdict decides on its resulting status */
11
+ const review = (verdicts) => ({
12
+ type: "phase",
13
+ lifecycle: "enterprise",
14
+ workdir: "changeset-read",
15
+ state: {
16
+ incoming: "IMPLEMENTED", activity: "QUALIFYING", success: "IMPLEMENTED", failure: "IMPLEMENTED",
17
+ phase: "QUALIFIED", passed: "QUALIFIED", verdict: verdicts
18
+ },
19
+ tag: { name: "ase-agent-qualifier" },
20
+ prompt: { skill: "ase-repo-review", args: "{?changeset-type=branch:--branch {changeset-name}}" },
21
+ verdict: { label: "REVIEW VERDICT", allow: ["APPROVE", "REJECT"] },
22
+ success: { criterion: ["exit", "verdict"] }
23
+ });
24
+ /* agent "ase agent qualifier" */
25
+ export default {
26
+ kind: "qualifier",
27
+ description: "Drive the \"Qualification\" phase of the \"enterprise\" task lifecycle model: " +
28
+ "claim every \"IMPLEMENTED\" task unassigned or assigned to the qualifier (by its name), without tag " +
29
+ "\"ase-agent-qualifier\" (i.e., without its verdict yet), and with qualified \"After:\" predecessors into " +
30
+ "\"QUALIFYING\", review its \"Changeset:\" (a \"worktree\" one staged, a \"branch:\" one " +
31
+ "against its base, an \"attachment:\" one staged in a temporary Git worktree) via the headless " +
32
+ "agent tool and the \"ase-repo-review\" skill, tag it with its verdict \"ase-agent-qualifier:approve\" " +
33
+ "or \"ase-agent-qualifier:reject\" (or plain \"ase-agent-qualifier\" without a verdict), and put it back " +
34
+ "into \"IMPLEMENTED\" for a human decision (\"--mode judge\"), or into \"QUALIFIED\" resp. \"DECLINED\" by " +
35
+ "its verdict (\"--mode qualify\", and back into \"IMPLEMENTED\" without a verdict), " +
36
+ "untagged into \"IMPLEMENTED\" on interrupt, " +
37
+ "logging to stdout and to the \"agent\" attachment of the task",
38
+ modeDesc: "\"judge\" to just add the verdict tag, or \"qualify\" to additionally " +
39
+ "qualify resp. decline the task by its verdict",
40
+ mode: "judge",
41
+ modes: {
42
+ /* just add the verdict */
43
+ judge: {
44
+ ...review([]),
45
+ title: "Review implemented tasks and tag their verdict",
46
+ description: "Claims every IMPLEMENTED task unassigned or assigned to the qualifier, without a verdict " +
47
+ "yet, and with qualified After: predecessors into QUALIFYING. Reviews its Changeset: via the " +
48
+ "ase-repo-review skill, tags it with its verdict (approve or reject), and puts it back into " +
49
+ "IMPLEMENTED for the final decision by a human."
50
+ },
51
+ /* additionally decide on the resulting task status by the verdict */
52
+ qualify: {
53
+ ...review(["APPROVE=QUALIFIED", "REJECT=DECLINED"]),
54
+ title: "Review implemented tasks and decide by verdict",
55
+ description: "Claims every IMPLEMENTED task unassigned or assigned to the qualifier, without a verdict " +
56
+ "yet, and with qualified After: predecessors into QUALIFYING. Reviews its Changeset: via the " +
57
+ "ase-repo-review skill, tags it with its verdict (approve or reject), and puts it into " +
58
+ "QUALIFIED resp. DECLINED by its verdict, or back into IMPLEMENTED without any verdict."
59
+ }
60
+ }
61
+ };