@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.
- package/dst/ase-agent-definition-api.d.ts +184 -0
- package/dst/ase-agent-definition-api.js +6 -0
- package/dst/ase-agent-definition-builtin/condenser.js +42 -0
- package/dst/ase-agent-definition-builtin/editor.js +45 -0
- package/dst/ase-agent-definition-builtin/estimator.js +98 -0
- package/dst/ase-agent-definition-builtin/implementer.js +121 -0
- package/dst/ase-agent-definition-builtin/integrator.js +56 -0
- package/dst/ase-agent-definition-builtin/qualifier.js +61 -0
- package/dst/ase-agent-definition-builtin/rebooter.js +41 -0
- package/dst/ase-agent-definition-builtin/researcher.js +77 -0
- package/dst/ase-agent-definition-core.js +827 -0
- package/dst/ase-agent-fleet.js +772 -0
- package/dst/ase-agent-process.js +232 -0
- package/dst/ase-agent-relay-client.js +509 -0
- package/dst/ase-agent-relay-core.js +213 -0
- package/dst/ase-agent-relay-server-bind.js +242 -0
- package/dst/ase-agent-relay-server-cli.js +50 -0
- package/dst/ase-agent-runtime-claim.js +189 -0
- package/dst/ase-agent-runtime-engine.js +1100 -0
- package/dst/ase-agent-runtime-exec.js +275 -0
- package/dst/ase-agent-runtime-phase.js +581 -0
- package/dst/ase-agent-runtime-request.js +272 -0
- package/dst/ase-agent-runtime-tool.js +207 -0
- package/dst/ase-agent-runtime.js +1316 -0
- package/dst/ase-agent.js +65 -0
- package/dst/ase-artifact.js +6 -5
- package/dst/ase-config-core.js +465 -0
- package/dst/ase-config-schema.js +357 -0
- package/dst/ase-config-scope.js +172 -0
- package/dst/ase-config.js +25 -585
- package/dst/ase-hook.js +228 -111
- package/dst/ase-lib-daemon-cli.js +130 -0
- package/dst/ase-lib-hash.js +20 -0
- package/dst/{ase-log.js → ase-lib-log.js} +40 -7
- package/dst/ase-lib-server-bind.js +115 -0
- package/dst/ase-lib-server-cli.js +474 -0
- package/dst/{ase-table.js → ase-lib-table.js} +1 -1
- package/dst/{ase-version.js → ase-lib-version.js} +8 -1
- package/dst/ase-man.js +96 -0
- package/dst/ase-mcp.js +166 -13
- package/dst/{ase-getopt.js → ase-service-getopt.js} +82 -80
- package/dst/{ase-markdown.js → ase-service-markdown.js} +18 -11
- package/dst/ase-service-otel.js +1246 -0
- package/dst/{ase-skills.js → ase-service-skills.js} +29 -64
- package/dst/ase-service-state.js +101 -0
- package/dst/ase-service.js +269 -81
- package/dst/ase-setup-common.js +141 -0
- package/dst/ase-setup-mcp.js +359 -0
- package/dst/ase-setup-settings.js +837 -0
- package/dst/ase-setup.js +113 -869
- package/dst/ase-spec.js +31 -19
- package/dst/ase-statusline.js +108 -43
- package/dst/ase-task-board-core.js +739 -0
- package/dst/ase-task-board-filter.js +127 -0
- package/dst/ase-task-board-flow.js +237 -0
- package/dst/ase-task-board-graph.js +497 -0
- package/dst/ase-task-board-stats.js +263 -0
- package/dst/ase-task-board-tui-control.js +775 -0
- package/dst/ase-task-board-tui-model.js +1008 -0
- package/dst/ase-task-board-tui-popup.js +626 -0
- package/dst/ase-task-board-tui-style.js +106 -0
- package/dst/ase-task-board-tui-view.js +847 -0
- package/dst/ase-task-board-tui.js +189 -0
- package/dst/ase-task-board-web-client.css +1 -0
- package/dst/ase-task-board-web-client.html +20 -0
- package/dst/ase-task-board-web-client.js +81 -0
- package/dst/ase-task-board-web-server.js +823 -0
- package/dst/ase-task-board.js +134 -0
- package/dst/ase-task-format.js +757 -0
- package/dst/ase-task-request.js +208 -0
- package/dst/ase-task-store-client.js +495 -0
- package/dst/ase-task-store-core.js +804 -0
- package/dst/ase-task-store-issues.js +237 -0
- package/dst/ase-task-store-plugin-api.js +6 -0
- package/dst/ase-task-store-plugin-ase.js +484 -0
- package/dst/ase-task-store-plugin-delegate.js +137 -0
- package/dst/ase-task-store-plugin-gitea.js +666 -0
- package/dst/ase-task-store-plugin-github.js +696 -0
- package/dst/ase-task-store-plugin-gitlab.js +668 -0
- package/dst/ase-task-store-server-bind.js +538 -0
- package/dst/ase-task-store-server-cli.js +154 -0
- package/dst/ase-task.js +1335 -357
- package/dst/{ase-compat.js → ase-util-compat.js} +2 -2
- package/dst/{ase-diagram.js → ase-util-diagram.js} +107 -32
- package/dst/{ase-meta.js → ase-util-meta.js} +2 -2
- package/dst/{ase-metric.js → ase-util-metric.js} +2 -2
- package/dst/{ase-mint.js → ase-util-mint.js} +19 -12
- package/dst/{ase-worktree.js → ase-util-worktree.js} +30 -19
- package/dst/ase-util.js +20 -0
- package/dst/ase.js +108 -32
- package/dst/man/ase-agent-adhoc.1 +515 -0
- package/dst/man/ase-agent-condenser.1 +193 -0
- package/dst/man/ase-agent-editor.1 +212 -0
- package/dst/man/ase-agent-estimator.1 +214 -0
- package/dst/man/ase-agent-fleet.1 +185 -0
- package/dst/man/ase-agent-implementer.1 +233 -0
- package/dst/man/ase-agent-integrator.1 +213 -0
- package/dst/man/ase-agent-qualifier.1 +214 -0
- package/dst/man/ase-agent-rebooter.1 +193 -0
- package/dst/man/ase-agent-relay.1 +128 -0
- package/dst/man/ase-agent-researcher.1 +217 -0
- package/dst/man/ase-agent.1 +264 -0
- package/dst/man/ase-artifact-list.1 +38 -0
- package/dst/man/ase-artifact-name.1 +39 -0
- package/dst/man/ase-artifact.1 +56 -0
- package/dst/man/ase-config-delete.1 +45 -0
- package/dst/man/ase-config-edit.1 +48 -0
- package/dst/man/ase-config-get.1 +46 -0
- package/dst/man/ase-config-init.1 +60 -0
- package/dst/man/ase-config-list.1 +42 -0
- package/dst/man/ase-config-set.1 +52 -0
- package/dst/man/ase-config.1 +231 -0
- package/dst/man/ase-hook-permission-request.1 +36 -0
- package/dst/man/ase-hook-pre-tool-use.1 +59 -0
- package/dst/man/ase-hook-session-end.1 +47 -0
- package/dst/man/ase-hook-session-persona.1 +37 -0
- package/dst/man/ase-hook-session-start.1 +81 -0
- package/dst/man/ase-hook-stop.1 +34 -0
- package/dst/man/ase-hook-user-prompt-submit.1 +34 -0
- package/dst/man/ase-hook.1 +51 -0
- package/dst/man/ase-man.1 +67 -0
- package/dst/man/ase-mcp.1 +61 -0
- package/dst/man/ase-service-log.1 +43 -0
- package/dst/man/ase-service-send.1 +47 -0
- package/dst/man/ase-service-start.1 +54 -0
- package/dst/man/ase-service-status.1 +46 -0
- package/dst/man/ase-service-stop.1 +37 -0
- package/dst/man/ase-service.1 +85 -0
- package/dst/man/ase-setup-disable.1 +44 -0
- package/dst/man/ase-setup-enable.1 +45 -0
- package/dst/man/ase-setup-install.1 +73 -0
- package/dst/man/ase-setup-mcp.1 +124 -0
- package/dst/man/ase-setup-status.1 +60 -0
- package/dst/man/ase-setup-statusline.1 +92 -0
- package/dst/man/ase-setup-telemetry.1 +92 -0
- package/dst/man/ase-setup-uninstall.1 +59 -0
- package/dst/man/ase-setup-update.1 +64 -0
- package/dst/man/ase-setup.1 +93 -0
- package/dst/man/ase-spec-export.1 +62 -0
- package/dst/man/ase-spec-lint.1 +40 -0
- package/dst/man/ase-spec-preview.1 +40 -0
- package/dst/man/ase-spec.1 +46 -0
- package/dst/man/ase-statusline.1 +189 -0
- package/dst/man/ase-task-assign.1 +71 -0
- package/dst/man/ase-task-board.1 +384 -0
- package/dst/man/ase-task-delete.1 +35 -0
- package/dst/man/ase-task-edit.1 +46 -0
- package/dst/man/ase-task-idscheme.1 +65 -0
- package/dst/man/ase-task-lifecycle.1 +57 -0
- package/dst/man/ase-task-list.1 +47 -0
- package/dst/man/ase-task-load.1 +36 -0
- package/dst/man/ase-task-newid.1 +61 -0
- package/dst/man/ase-task-purge.1 +37 -0
- package/dst/man/ase-task-rename.1 +44 -0
- package/dst/man/ase-task-request.1 +61 -0
- package/dst/man/ase-task-save.1 +48 -0
- package/dst/man/ase-task-status.1 +55 -0
- package/dst/man/ase-task-store.1 +194 -0
- package/dst/man/ase-task-view.1 +40 -0
- package/dst/man/ase-task.1 +160 -0
- package/dst/man/ase-util-compat.1 +25 -0
- package/dst/man/ase-util-diagram.1 +76 -0
- package/dst/man/ase-util-meta.1 +45 -0
- package/dst/man/ase-util-metric.1 +54 -0
- package/dst/man/ase-util-mint.1 +59 -0
- package/dst/man/ase-util-worktree.1 +72 -0
- package/dst/man/ase-util.1 +50 -0
- package/dst/man/ase.1 +124 -0
- package/package.json +81 -21
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/.github/plugin/plugin.json +1 -1
- package/plugin/agents/ase-meta-diagram.md +12 -8
- package/plugin/agents/ase-repo-review.md +322 -0
- package/plugin/hooks/hooks-codex.json +5 -0
- package/plugin/hooks/hooks-copilot.json +5 -0
- package/plugin/hooks/hooks.json +8 -0
- package/plugin/meta/ase-common-approach.md +117 -0
- package/plugin/meta/ase-common-changeset.md +256 -0
- package/plugin/meta/ase-common-code.md +10 -173
- package/plugin/meta/ase-common-grill.md +317 -0
- package/plugin/meta/ase-common-resolve.md +305 -0
- package/plugin/meta/ase-common-task.md +83 -4
- package/plugin/meta/ase-constitution.md +0 -2
- package/plugin/meta/ase-format-specbook.md +208 -25
- package/plugin/meta/ase-format-specbook.yaml +242 -851
- package/plugin/meta/ase-format-task.md +669 -125
- package/plugin/meta/ase-persona.md +3 -4
- package/plugin/meta/ase-skill.md +9 -0
- package/plugin/mods/ase-mods.ts +409 -0
- package/plugin/mods/claude-code.d.ts +13417 -0
- package/plugin/skills/ase-arch-analyze/SKILL.md +1 -1
- package/plugin/skills/ase-arch-analyze/help.md +2 -2
- package/plugin/skills/ase-code-analyze/SKILL.md +59 -8
- package/plugin/skills/ase-code-analyze/help.md +29 -4
- package/plugin/skills/ase-code-edit/SKILL.md +107 -181
- package/plugin/skills/ase-code-edit/help.md +118 -31
- package/plugin/skills/ase-code-lint/SKILL.md +64 -13
- package/plugin/skills/ase-code-lint/help.md +32 -2
- package/plugin/skills/ase-docs-proofread/SKILL.md +4 -4
- package/plugin/skills/ase-docs-proofread/help.md +1 -1
- package/plugin/skills/ase-docs-refine/SKILL.md +4 -4
- package/plugin/skills/ase-docs-shorten/SKILL.md +4 -4
- package/plugin/skills/ase-help-intent/data.md +2164 -1087
- package/plugin/skills/ase-help-intent/help.md +1 -1
- package/plugin/skills/ase-help-skill/catalog.md +12 -9
- package/plugin/skills/ase-meta-brainstorm/SKILL.md +1 -1
- package/plugin/skills/ase-meta-config/SKILL.md +3 -4
- package/plugin/skills/ase-meta-config/help.md +31 -10
- package/plugin/skills/ase-meta-mint/SKILL.md +5 -5
- package/plugin/skills/ase-meta-mint/help.md +10 -5
- package/plugin/skills/ase-meta-why/help.md +1 -1
- package/plugin/skills/ase-meta-workflow/SKILL.md +7 -7
- package/plugin/skills/ase-meta-workflow/help.md +4 -4
- package/plugin/skills/ase-meta-workflow/sample.md +3 -3
- package/plugin/skills/ase-meta-workflow/workflow.txt +22 -18
- package/plugin/skills/{ase-meta-changelog → ase-repo-changelog}/SKILL.md +4 -3
- package/plugin/skills/{ase-meta-changelog → ase-repo-changelog}/help.md +5 -5
- package/plugin/skills/{ase-meta-commit → ase-repo-commit}/SKILL.md +6 -6
- package/plugin/skills/{ase-meta-commit → ase-repo-commit}/help.md +5 -5
- package/plugin/skills/{ase-meta-diff → ase-repo-diff}/SKILL.md +6 -6
- package/plugin/skills/{ase-meta-diff → ase-repo-diff}/help.md +8 -8
- package/plugin/skills/{ase-code-dissect → ase-repo-dissect}/SKILL.md +19 -19
- package/plugin/skills/{ase-code-dissect → ase-repo-dissect}/help.md +10 -12
- package/plugin/skills/ase-repo-merge/SKILL.md +346 -0
- package/plugin/skills/ase-repo-merge/help.md +107 -0
- package/plugin/skills/ase-repo-resolve/SKILL.md +158 -0
- package/plugin/skills/ase-repo-resolve/help.md +102 -0
- package/plugin/skills/ase-repo-review/SKILL.md +406 -0
- package/plugin/skills/ase-repo-review/help.md +181 -0
- package/plugin/skills/ase-spec-edit/SKILL.md +117 -183
- package/plugin/skills/ase-spec-edit/help.md +107 -26
- package/plugin/skills/ase-sync-reconcile/help.md +1 -1
- package/plugin/skills/ase-task-assign/SKILL.md +111 -0
- package/plugin/skills/ase-task-assign/help.md +119 -0
- package/plugin/skills/ase-task-condense/SKILL.md +21 -21
- package/plugin/skills/ase-task-condense/help.md +12 -10
- package/plugin/skills/ase-task-delete/SKILL.md +1 -1
- package/plugin/skills/ase-task-dissect/SKILL.md +71 -48
- package/plugin/skills/ase-task-dissect/help.md +10 -9
- package/plugin/skills/ase-task-edit/SKILL.md +379 -94
- package/plugin/skills/ase-task-edit/help.md +95 -22
- package/plugin/skills/ase-task-estimate/SKILL.md +492 -0
- package/plugin/skills/ase-task-estimate/help.md +158 -0
- package/plugin/skills/ase-task-grill/SKILL.md +246 -138
- package/plugin/skills/ase-task-grill/help.md +129 -26
- package/plugin/skills/ase-task-id/SKILL.md +8 -1
- package/plugin/skills/ase-task-id/help.md +6 -3
- package/plugin/skills/ase-task-implement/SKILL.md +535 -145
- package/plugin/skills/ase-task-implement/help.md +138 -47
- package/plugin/skills/ase-task-integrate/SKILL.md +549 -0
- package/plugin/skills/ase-task-integrate/help.md +187 -0
- package/plugin/skills/ase-task-list/SKILL.md +55 -23
- package/plugin/skills/ase-task-list/help.md +45 -21
- package/plugin/skills/ase-task-reboot/SKILL.md +84 -43
- package/plugin/skills/ase-task-reboot/help.md +28 -8
- package/plugin/skills/ase-task-rename/SKILL.md +10 -2
- package/plugin/skills/ase-task-research/SKILL.md +386 -0
- package/plugin/skills/ase-task-research/help.md +102 -0
- package/plugin/skills/ase-task-status/SKILL.md +137 -0
- package/plugin/skills/ase-task-status/help.md +80 -0
- package/plugin/skills/ase-task-view/SKILL.md +49 -24
- package/plugin/skills/ase-task-view/help.md +19 -9
- package/plugin/agents/ase-meta-review.md +0 -187
- package/plugin/skills/ase-code-craft/SKILL.md +0 -264
- package/plugin/skills/ase-code-craft/help.md +0 -122
- package/plugin/skills/ase-code-refactor/SKILL.md +0 -232
- package/plugin/skills/ase-code-refactor/help.md +0 -109
- package/plugin/skills/ase-code-resolve/SKILL.md +0 -289
- package/plugin/skills/ase-code-resolve/help.md +0 -116
- package/plugin/skills/ase-meta-review/SKILL.md +0 -210
- package/plugin/skills/ase-meta-review/help.md +0 -96
- package/plugin/skills/ase-task-preflight/SKILL.md +0 -166
- package/plugin/skills/ase-task-preflight/help.md +0 -82
- /package/dst/{ase-ignore.js → ase-lib-ignore.js} +0 -0
- /package/dst/{ase-stdio.js → ase-lib-stdio.js} +0 -0
- /package/dst/{ase-kv.js → ase-service-kv.js} +0 -0
- /package/dst/{ase-sleep.js → ase-service-sleep.js} +0 -0
- /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,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
|
+
};
|