@renseiai/agentfactory 0.8.17 → 0.8.19
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/dist/src/governor/decision-engine-adapter.d.ts +43 -0
- package/dist/src/governor/decision-engine-adapter.d.ts.map +1 -0
- package/dist/src/governor/decision-engine-adapter.js +422 -0
- package/dist/src/governor/decision-engine-adapter.test.d.ts +2 -0
- package/dist/src/governor/decision-engine-adapter.test.d.ts.map +1 -0
- package/dist/src/governor/decision-engine-adapter.test.js +363 -0
- package/dist/src/governor/index.d.ts +1 -0
- package/dist/src/governor/index.d.ts.map +1 -1
- package/dist/src/governor/index.js +1 -0
- package/dist/src/manifest/route-manifest.d.ts.map +1 -1
- package/dist/src/manifest/route-manifest.js +4 -0
- package/dist/src/merge-queue/adapters/github-native.d.ts +8 -0
- package/dist/src/merge-queue/adapters/github-native.d.ts.map +1 -1
- package/dist/src/merge-queue/adapters/github-native.js +37 -7
- package/dist/src/merge-queue/adapters/github-native.test.js +71 -42
- package/dist/src/orchestrator/activity-emitter.d.ts +7 -0
- package/dist/src/orchestrator/activity-emitter.d.ts.map +1 -1
- package/dist/src/orchestrator/activity-emitter.js +19 -1
- package/dist/src/orchestrator/api-activity-emitter.d.ts +6 -0
- package/dist/src/orchestrator/api-activity-emitter.d.ts.map +1 -1
- package/dist/src/orchestrator/api-activity-emitter.js +35 -0
- package/dist/src/orchestrator/index.d.ts +2 -0
- package/dist/src/orchestrator/index.d.ts.map +1 -1
- package/dist/src/orchestrator/index.js +1 -0
- package/dist/src/orchestrator/issue-tracker-client.d.ts +2 -1
- package/dist/src/orchestrator/issue-tracker-client.d.ts.map +1 -1
- package/dist/src/orchestrator/orchestrator.d.ts +27 -0
- package/dist/src/orchestrator/orchestrator.d.ts.map +1 -1
- package/dist/src/orchestrator/orchestrator.js +331 -86
- package/dist/src/orchestrator/security-scan-event.d.ts +57 -0
- package/dist/src/orchestrator/security-scan-event.d.ts.map +1 -0
- package/dist/src/orchestrator/security-scan-event.js +192 -0
- package/dist/src/orchestrator/security-scan-event.test.d.ts +2 -0
- package/dist/src/orchestrator/security-scan-event.test.d.ts.map +1 -0
- package/dist/src/orchestrator/security-scan-event.test.js +219 -0
- package/dist/src/orchestrator/state-recovery.d.ts.map +1 -1
- package/dist/src/orchestrator/state-recovery.js +1 -0
- package/dist/src/orchestrator/work-types.d.ts +1 -1
- package/dist/src/orchestrator/work-types.d.ts.map +1 -1
- package/dist/src/providers/claude-provider.d.ts.map +1 -1
- package/dist/src/providers/claude-provider.js +11 -0
- package/dist/src/providers/codex-app-server-provider.d.ts +201 -0
- package/dist/src/providers/codex-app-server-provider.d.ts.map +1 -0
- package/dist/src/providers/codex-app-server-provider.js +786 -0
- package/dist/src/providers/codex-app-server-provider.test.d.ts +2 -0
- package/dist/src/providers/codex-app-server-provider.test.d.ts.map +1 -0
- package/dist/src/providers/codex-app-server-provider.test.js +529 -0
- package/dist/src/providers/codex-provider.d.ts +24 -4
- package/dist/src/providers/codex-provider.d.ts.map +1 -1
- package/dist/src/providers/codex-provider.js +58 -6
- package/dist/src/providers/index.d.ts +1 -0
- package/dist/src/providers/index.d.ts.map +1 -1
- package/dist/src/providers/index.js +1 -0
- package/dist/src/providers/types.d.ts +1 -0
- package/dist/src/providers/types.d.ts.map +1 -1
- package/dist/src/routing/observation-recorder.test.js +1 -1
- package/dist/src/routing/observation-store.d.ts +15 -1
- package/dist/src/routing/observation-store.d.ts.map +1 -1
- package/dist/src/routing/observation-store.test.js +17 -11
- package/dist/src/templates/index.d.ts +2 -1
- package/dist/src/templates/index.d.ts.map +1 -1
- package/dist/src/templates/index.js +1 -0
- package/dist/src/templates/registry.d.ts +23 -0
- package/dist/src/templates/registry.d.ts.map +1 -1
- package/dist/src/templates/registry.js +80 -0
- package/dist/src/templates/registry.test.js +3 -2
- package/dist/src/templates/schema.d.ts +31 -0
- package/dist/src/templates/schema.d.ts.map +1 -0
- package/dist/src/templates/schema.js +139 -0
- package/dist/src/templates/schema.test.d.ts +2 -0
- package/dist/src/templates/schema.test.d.ts.map +1 -0
- package/dist/src/templates/schema.test.js +215 -0
- package/dist/src/templates/types.d.ts +2 -0
- package/dist/src/templates/types.d.ts.map +1 -1
- package/dist/src/templates/types.js +1 -0
- package/dist/src/tools/index.d.ts +2 -0
- package/dist/src/tools/index.d.ts.map +1 -1
- package/dist/src/tools/index.js +1 -0
- package/dist/src/tools/tool-category.d.ts +16 -0
- package/dist/src/tools/tool-category.d.ts.map +1 -0
- package/dist/src/tools/tool-category.js +58 -0
- package/package.json +2 -2
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decision Engine Adapter
|
|
3
|
+
*
|
|
4
|
+
* Translates the full `decideAction()` decision context into a
|
|
5
|
+
* WorkflowDefinition v2 YAML equivalent. Each decision point in the
|
|
6
|
+
* engine becomes a condition node or action node in the v2 graph.
|
|
7
|
+
*
|
|
8
|
+
* This adapter enables the platform to replace the legacy decision engine
|
|
9
|
+
* with a declarative workflow while preserving identical behavior.
|
|
10
|
+
*
|
|
11
|
+
* @see SUP-1757
|
|
12
|
+
*/
|
|
13
|
+
import type { GovernorConfig } from './governor-types.js';
|
|
14
|
+
import type { WorkflowDefinitionV2 } from '../workflow/workflow-types.js';
|
|
15
|
+
export interface DecisionEngineAdapterConfig {
|
|
16
|
+
/** Governor configuration to derive workflow from */
|
|
17
|
+
governorConfig?: GovernorConfig;
|
|
18
|
+
/** Workflow name (default: "governor-decision-engine") */
|
|
19
|
+
workflowName?: string;
|
|
20
|
+
/** Whether to include top-of-funnel nodes (Icebox handling) */
|
|
21
|
+
includeTopOfFunnel?: boolean;
|
|
22
|
+
/** Whether to include merge queue handling */
|
|
23
|
+
includeMergeQueue?: boolean;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Converts the Governor's `decideAction()` logic into a WorkflowDefinition v2.
|
|
27
|
+
*
|
|
28
|
+
* The generated workflow mirrors the decision tree exactly:
|
|
29
|
+
*
|
|
30
|
+
* 1. Universal guards: active-session, cooldown, hold, gates, circuit-breaker
|
|
31
|
+
* 2. Terminal statuses: Accepted, Canceled, Duplicate
|
|
32
|
+
* 3. Sub-issue guard
|
|
33
|
+
* 4. Status-specific routing: Icebox, Backlog, Started, Finished, Delivered, Rejected
|
|
34
|
+
* 5. Escalation strategy overrides (decompose, escalate-human)
|
|
35
|
+
* 6. Merge queue handling
|
|
36
|
+
*/
|
|
37
|
+
export declare class DecisionEngineAdapter {
|
|
38
|
+
/**
|
|
39
|
+
* Generate a WorkflowDefinition v2 that replicates the full decision engine.
|
|
40
|
+
*/
|
|
41
|
+
static toWorkflowDefinition(config?: DecisionEngineAdapterConfig): WorkflowDefinitionV2;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=decision-engine-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decision-engine-adapter.d.ts","sourceRoot":"","sources":["../../../src/governor/decision-engine-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAEzD,OAAO,KAAK,EACV,oBAAoB,EAKrB,MAAM,+BAA+B,CAAA;AAOtC,MAAM,WAAW,2BAA2B;IAC1C,qDAAqD;IACrD,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,0DAA0D;IAC1D,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,+DAA+D;IAC/D,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,8CAA8C;IAC9C,iBAAiB,CAAC,EAAE,OAAO,CAAA;CAC5B;AAMD;;;;;;;;;;;GAWG;AACH,qBAAa,qBAAqB;IAChC;;OAEG;IACH,MAAM,CAAC,oBAAoB,CACzB,MAAM,GAAE,2BAAgC,GACvC,oBAAoB;CAgCxB"}
|
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decision Engine Adapter
|
|
3
|
+
*
|
|
4
|
+
* Translates the full `decideAction()` decision context into a
|
|
5
|
+
* WorkflowDefinition v2 YAML equivalent. Each decision point in the
|
|
6
|
+
* engine becomes a condition node or action node in the v2 graph.
|
|
7
|
+
*
|
|
8
|
+
* This adapter enables the platform to replace the legacy decision engine
|
|
9
|
+
* with a declarative workflow while preserving identical behavior.
|
|
10
|
+
*
|
|
11
|
+
* @see SUP-1757
|
|
12
|
+
*/
|
|
13
|
+
import { DEFAULT_GOVERNOR_CONFIG } from './governor-types.js';
|
|
14
|
+
import { MAX_SESSION_ATTEMPTS } from './decision-engine.js';
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
// Adapter
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
/**
|
|
19
|
+
* Converts the Governor's `decideAction()` logic into a WorkflowDefinition v2.
|
|
20
|
+
*
|
|
21
|
+
* The generated workflow mirrors the decision tree exactly:
|
|
22
|
+
*
|
|
23
|
+
* 1. Universal guards: active-session, cooldown, hold, gates, circuit-breaker
|
|
24
|
+
* 2. Terminal statuses: Accepted, Canceled, Duplicate
|
|
25
|
+
* 3. Sub-issue guard
|
|
26
|
+
* 4. Status-specific routing: Icebox, Backlog, Started, Finished, Delivered, Rejected
|
|
27
|
+
* 5. Escalation strategy overrides (decompose, escalate-human)
|
|
28
|
+
* 6. Merge queue handling
|
|
29
|
+
*/
|
|
30
|
+
export class DecisionEngineAdapter {
|
|
31
|
+
/**
|
|
32
|
+
* Generate a WorkflowDefinition v2 that replicates the full decision engine.
|
|
33
|
+
*/
|
|
34
|
+
static toWorkflowDefinition(config = {}) {
|
|
35
|
+
const govConfig = config.governorConfig ?? DEFAULT_GOVERNOR_CONFIG;
|
|
36
|
+
const workflowName = config.workflowName ?? 'governor-decision-engine';
|
|
37
|
+
const includeTopOfFunnel = config.includeTopOfFunnel ?? true;
|
|
38
|
+
const includeMergeQueue = config.includeMergeQueue ?? false;
|
|
39
|
+
const triggers = buildTriggers();
|
|
40
|
+
const providers = buildProviders();
|
|
41
|
+
const nodes = buildNodes(govConfig, includeTopOfFunnel, includeMergeQueue);
|
|
42
|
+
return {
|
|
43
|
+
apiVersion: 'v2',
|
|
44
|
+
kind: 'WorkflowDefinition',
|
|
45
|
+
metadata: {
|
|
46
|
+
name: workflowName,
|
|
47
|
+
description: 'Auto-generated from Governor DecisionEngine. ' +
|
|
48
|
+
'Replicates the full decideAction() decision tree as v2 workflow nodes.',
|
|
49
|
+
},
|
|
50
|
+
triggers,
|
|
51
|
+
providers,
|
|
52
|
+
config: {
|
|
53
|
+
maxSessionAttempts: MAX_SESSION_ATTEMPTS,
|
|
54
|
+
enableAutoDevelopment: govConfig.enableAutoDevelopment,
|
|
55
|
+
enableAutoQA: govConfig.enableAutoQA,
|
|
56
|
+
enableAutoAcceptance: govConfig.enableAutoAcceptance,
|
|
57
|
+
enableAutoResearch: govConfig.enableAutoResearch,
|
|
58
|
+
enableAutoBacklogCreation: govConfig.enableAutoBacklogCreation,
|
|
59
|
+
},
|
|
60
|
+
nodes,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
// Trigger builders
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
function buildTriggers() {
|
|
68
|
+
return [
|
|
69
|
+
{
|
|
70
|
+
name: 'issue-status-change',
|
|
71
|
+
type: 'webhook',
|
|
72
|
+
source: 'linear',
|
|
73
|
+
event: 'issue.status_changed',
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
name: 'governor-scan',
|
|
77
|
+
type: 'schedule',
|
|
78
|
+
schedule: '*/1 * * * *', // Every minute
|
|
79
|
+
},
|
|
80
|
+
];
|
|
81
|
+
}
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
// Provider builders
|
|
84
|
+
// ---------------------------------------------------------------------------
|
|
85
|
+
function buildProviders() {
|
|
86
|
+
return [
|
|
87
|
+
{ name: 'linear', type: 'linear' },
|
|
88
|
+
{ name: 'agent', type: 'agent-provider' },
|
|
89
|
+
];
|
|
90
|
+
}
|
|
91
|
+
// ---------------------------------------------------------------------------
|
|
92
|
+
// Node builders
|
|
93
|
+
// ---------------------------------------------------------------------------
|
|
94
|
+
function buildNodes(config, includeTopOfFunnel, includeMergeQueue) {
|
|
95
|
+
const nodes = [];
|
|
96
|
+
// --- Universal guard nodes ---
|
|
97
|
+
nodes.push(buildActiveSessionGuard());
|
|
98
|
+
nodes.push(buildCooldownGuard());
|
|
99
|
+
nodes.push(buildHoldGuard());
|
|
100
|
+
nodes.push(buildGateGuard());
|
|
101
|
+
nodes.push(buildCircuitBreakerGuard());
|
|
102
|
+
nodes.push(buildTerminalStatusGuard());
|
|
103
|
+
nodes.push(buildSubIssueGuard());
|
|
104
|
+
// --- Status-specific routing nodes ---
|
|
105
|
+
if (includeTopOfFunnel) {
|
|
106
|
+
nodes.push(buildIceboxResearchNode(config));
|
|
107
|
+
nodes.push(buildIceboxBacklogCreationNode(config));
|
|
108
|
+
}
|
|
109
|
+
nodes.push(buildBacklogNode(config));
|
|
110
|
+
nodes.push(buildStartedNode());
|
|
111
|
+
nodes.push(buildFinishedNode(config, includeMergeQueue));
|
|
112
|
+
nodes.push(buildDeliveredNode(config));
|
|
113
|
+
nodes.push(buildRejectedNode());
|
|
114
|
+
return nodes;
|
|
115
|
+
}
|
|
116
|
+
// ---------------------------------------------------------------------------
|
|
117
|
+
// Guard nodes
|
|
118
|
+
// ---------------------------------------------------------------------------
|
|
119
|
+
function buildActiveSessionGuard() {
|
|
120
|
+
return {
|
|
121
|
+
name: 'guard-active-session',
|
|
122
|
+
description: 'Skip if issue already has an active agent session',
|
|
123
|
+
when: '{{ hasActiveSession }}',
|
|
124
|
+
steps: [
|
|
125
|
+
{
|
|
126
|
+
id: 'skip',
|
|
127
|
+
action: 'none',
|
|
128
|
+
with: {
|
|
129
|
+
reason: 'Issue {{ issue.identifier }} already has an active agent session',
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
],
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
function buildCooldownGuard() {
|
|
136
|
+
return {
|
|
137
|
+
name: 'guard-cooldown',
|
|
138
|
+
description: 'Skip if issue is within cooldown period',
|
|
139
|
+
when: '{{ isWithinCooldown }}',
|
|
140
|
+
steps: [
|
|
141
|
+
{
|
|
142
|
+
id: 'skip',
|
|
143
|
+
action: 'none',
|
|
144
|
+
with: {
|
|
145
|
+
reason: 'Issue {{ issue.identifier }} is within cooldown period',
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
],
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
function buildHoldGuard() {
|
|
152
|
+
return {
|
|
153
|
+
name: 'guard-hold',
|
|
154
|
+
description: 'Skip if HOLD override is active',
|
|
155
|
+
when: '{{ isHeld }}',
|
|
156
|
+
steps: [
|
|
157
|
+
{
|
|
158
|
+
id: 'skip',
|
|
159
|
+
action: 'none',
|
|
160
|
+
with: {
|
|
161
|
+
reason: 'Issue {{ issue.identifier }} is held (HOLD override active)',
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
],
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
function buildGateGuard() {
|
|
168
|
+
return {
|
|
169
|
+
name: 'guard-gates',
|
|
170
|
+
description: 'Block when gates are unsatisfied (Phase 4 gate evaluation)',
|
|
171
|
+
when: '{{ gateEvaluation && !gateEvaluation.allSatisfied }}',
|
|
172
|
+
steps: [
|
|
173
|
+
{
|
|
174
|
+
id: 'block',
|
|
175
|
+
action: 'none',
|
|
176
|
+
with: {
|
|
177
|
+
reason: 'Issue {{ issue.identifier }} has unsatisfied gates',
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
],
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
function buildCircuitBreakerGuard() {
|
|
184
|
+
return {
|
|
185
|
+
name: 'guard-circuit-breaker',
|
|
186
|
+
description: `Trip circuit breaker when session count >= ${MAX_SESSION_ATTEMPTS}`,
|
|
187
|
+
when: `{{ completedSessionCount >= ${MAX_SESSION_ATTEMPTS} }}`,
|
|
188
|
+
steps: [
|
|
189
|
+
{
|
|
190
|
+
id: 'trip',
|
|
191
|
+
action: 'none',
|
|
192
|
+
with: {
|
|
193
|
+
reason: `Issue {{ issue.identifier }} has had {{ completedSessionCount }} agent sessions — circuit breaker tripped (max ${MAX_SESSION_ATTEMPTS})`,
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
],
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
function buildTerminalStatusGuard() {
|
|
200
|
+
return {
|
|
201
|
+
name: 'guard-terminal-status',
|
|
202
|
+
description: 'No action for terminal statuses (Accepted, Canceled, Duplicate)',
|
|
203
|
+
when: "{{ issue.status == 'Accepted' || issue.status == 'Canceled' || issue.status == 'Duplicate' }}",
|
|
204
|
+
steps: [
|
|
205
|
+
{
|
|
206
|
+
id: 'skip',
|
|
207
|
+
action: 'none',
|
|
208
|
+
with: {
|
|
209
|
+
reason: 'Issue {{ issue.identifier }} is in terminal status: {{ issue.status }}',
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
],
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
function buildSubIssueGuard() {
|
|
216
|
+
return {
|
|
217
|
+
name: 'guard-sub-issue',
|
|
218
|
+
description: 'Sub-issues managed by coordinator via parent — skip direct dispatch',
|
|
219
|
+
when: '{{ issue.parentId != undefined }}',
|
|
220
|
+
steps: [
|
|
221
|
+
{
|
|
222
|
+
id: 'skip',
|
|
223
|
+
action: 'none',
|
|
224
|
+
with: {
|
|
225
|
+
reason: 'Sub-issue {{ issue.identifier }} skipped — coordinator manages sub-issues via parent',
|
|
226
|
+
},
|
|
227
|
+
},
|
|
228
|
+
],
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
// ---------------------------------------------------------------------------
|
|
232
|
+
// Status-specific routing nodes
|
|
233
|
+
// ---------------------------------------------------------------------------
|
|
234
|
+
function buildIceboxResearchNode(config) {
|
|
235
|
+
return {
|
|
236
|
+
name: 'icebox-research',
|
|
237
|
+
description: 'Trigger research for sparse Icebox issues (top-of-funnel)',
|
|
238
|
+
provider: 'agent',
|
|
239
|
+
when: `{{ issue.status == 'Icebox' && config.enableAutoResearch && !researchCompleted && !isParentIssue }}`,
|
|
240
|
+
steps: [
|
|
241
|
+
{
|
|
242
|
+
id: 'evaluate',
|
|
243
|
+
action: 'trigger-research',
|
|
244
|
+
with: {
|
|
245
|
+
enableAutoResearch: config.enableAutoResearch,
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
],
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
function buildIceboxBacklogCreationNode(config) {
|
|
252
|
+
return {
|
|
253
|
+
name: 'icebox-backlog-creation',
|
|
254
|
+
description: 'Trigger backlog creation for well-researched Icebox issues',
|
|
255
|
+
provider: 'agent',
|
|
256
|
+
when: `{{ issue.status == 'Icebox' && config.enableAutoBacklogCreation && !backlogCreationCompleted && !isParentIssue }}`,
|
|
257
|
+
steps: [
|
|
258
|
+
{
|
|
259
|
+
id: 'evaluate',
|
|
260
|
+
action: 'trigger-backlog-creation',
|
|
261
|
+
with: {
|
|
262
|
+
enableAutoBacklogCreation: config.enableAutoBacklogCreation,
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
],
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
function buildBacklogNode(config) {
|
|
269
|
+
return {
|
|
270
|
+
name: 'route-backlog',
|
|
271
|
+
description: 'Backlog → trigger-development (if enabled)',
|
|
272
|
+
provider: 'agent',
|
|
273
|
+
when: "{{ issue.status == 'Backlog' }}",
|
|
274
|
+
steps: [
|
|
275
|
+
{
|
|
276
|
+
id: 'check-enabled',
|
|
277
|
+
action: 'none',
|
|
278
|
+
when: `{{ !config.enableAutoDevelopment }}`,
|
|
279
|
+
with: {
|
|
280
|
+
reason: 'Auto-development is disabled for {{ issue.identifier }}',
|
|
281
|
+
},
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
id: 'dispatch',
|
|
285
|
+
action: 'trigger-development',
|
|
286
|
+
when: `{{ config.enableAutoDevelopment }}`,
|
|
287
|
+
with: {
|
|
288
|
+
isParentIssue: '{{ isParentIssue }}',
|
|
289
|
+
reason: '{{ isParentIssue ? "Parent issue" : "Issue" }} {{ issue.identifier }} is in Backlog — triggering {{ isParentIssue ? "coordination " : "" }}development',
|
|
290
|
+
},
|
|
291
|
+
},
|
|
292
|
+
],
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
function buildStartedNode() {
|
|
296
|
+
return {
|
|
297
|
+
name: 'route-started',
|
|
298
|
+
description: 'Started → none (agent already working)',
|
|
299
|
+
when: "{{ issue.status == 'Started' }}",
|
|
300
|
+
steps: [
|
|
301
|
+
{
|
|
302
|
+
id: 'skip',
|
|
303
|
+
action: 'none',
|
|
304
|
+
with: {
|
|
305
|
+
reason: 'Issue {{ issue.identifier }} is in Started status (agent already working)',
|
|
306
|
+
},
|
|
307
|
+
},
|
|
308
|
+
],
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
function buildFinishedNode(config, includeMergeQueue) {
|
|
312
|
+
const steps = [
|
|
313
|
+
{
|
|
314
|
+
id: 'check-enabled',
|
|
315
|
+
action: 'none',
|
|
316
|
+
when: '{{ !config.enableAutoQA }}',
|
|
317
|
+
with: {
|
|
318
|
+
reason: 'Auto-QA is disabled for {{ issue.identifier }}',
|
|
319
|
+
},
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
id: 'check-escalate-human',
|
|
323
|
+
action: 'escalate-human',
|
|
324
|
+
when: "{{ workflowStrategy == 'escalate-human' }}",
|
|
325
|
+
with: {
|
|
326
|
+
reason: 'Issue {{ issue.identifier }} is in Finished with escalate-human strategy — needs human review',
|
|
327
|
+
},
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
id: 'check-decompose',
|
|
331
|
+
action: 'decompose',
|
|
332
|
+
when: "{{ workflowStrategy == 'decompose' }}",
|
|
333
|
+
with: {
|
|
334
|
+
reason: 'Issue {{ issue.identifier }} is in Finished with decompose strategy — triggering decomposition',
|
|
335
|
+
},
|
|
336
|
+
},
|
|
337
|
+
];
|
|
338
|
+
if (includeMergeQueue) {
|
|
339
|
+
steps.push({
|
|
340
|
+
id: 'check-merge-queue',
|
|
341
|
+
action: 'trigger-merge',
|
|
342
|
+
when: '{{ mergeQueueEnabled }}',
|
|
343
|
+
with: {
|
|
344
|
+
reason: 'Issue {{ issue.identifier }} is in Finished — enqueuing to merge queue',
|
|
345
|
+
},
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
steps.push({
|
|
349
|
+
id: 'dispatch-qa',
|
|
350
|
+
action: 'trigger-qa',
|
|
351
|
+
when: '{{ config.enableAutoQA }}',
|
|
352
|
+
with: {
|
|
353
|
+
reason: 'Issue {{ issue.identifier }} is in Finished — triggering QA',
|
|
354
|
+
},
|
|
355
|
+
});
|
|
356
|
+
return {
|
|
357
|
+
name: 'route-finished',
|
|
358
|
+
description: 'Finished → trigger-qa (with escalation/merge-queue checks)',
|
|
359
|
+
provider: 'agent',
|
|
360
|
+
when: "{{ issue.status == 'Finished' }}",
|
|
361
|
+
steps,
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
function buildDeliveredNode(config) {
|
|
365
|
+
return {
|
|
366
|
+
name: 'route-delivered',
|
|
367
|
+
description: 'Delivered → trigger-acceptance (if enabled)',
|
|
368
|
+
provider: 'agent',
|
|
369
|
+
when: "{{ issue.status == 'Delivered' }}",
|
|
370
|
+
steps: [
|
|
371
|
+
{
|
|
372
|
+
id: 'check-enabled',
|
|
373
|
+
action: 'none',
|
|
374
|
+
when: '{{ !config.enableAutoAcceptance }}',
|
|
375
|
+
with: {
|
|
376
|
+
reason: 'Auto-acceptance is disabled for {{ issue.identifier }}',
|
|
377
|
+
},
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
id: 'dispatch',
|
|
381
|
+
action: 'trigger-acceptance',
|
|
382
|
+
when: '{{ config.enableAutoAcceptance }}',
|
|
383
|
+
with: {
|
|
384
|
+
reason: 'Issue {{ issue.identifier }} is in Delivered — triggering acceptance',
|
|
385
|
+
},
|
|
386
|
+
},
|
|
387
|
+
],
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
function buildRejectedNode() {
|
|
391
|
+
return {
|
|
392
|
+
name: 'route-rejected',
|
|
393
|
+
description: 'Rejected → trigger-refinement (with escalation checks)',
|
|
394
|
+
provider: 'agent',
|
|
395
|
+
when: "{{ issue.status == 'Rejected' }}",
|
|
396
|
+
steps: [
|
|
397
|
+
{
|
|
398
|
+
id: 'check-escalate-human',
|
|
399
|
+
action: 'escalate-human',
|
|
400
|
+
when: "{{ workflowStrategy == 'escalate-human' }}",
|
|
401
|
+
with: {
|
|
402
|
+
reason: 'Issue {{ issue.identifier }} is Rejected with escalate-human strategy — needs human intervention',
|
|
403
|
+
},
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
id: 'check-decompose',
|
|
407
|
+
action: 'decompose',
|
|
408
|
+
when: "{{ workflowStrategy == 'decompose' }}",
|
|
409
|
+
with: {
|
|
410
|
+
reason: 'Issue {{ issue.identifier }} is Rejected with decompose strategy — triggering decomposition',
|
|
411
|
+
},
|
|
412
|
+
},
|
|
413
|
+
{
|
|
414
|
+
id: 'dispatch-refinement',
|
|
415
|
+
action: 'trigger-refinement',
|
|
416
|
+
with: {
|
|
417
|
+
reason: 'Issue {{ issue.identifier }} is Rejected — triggering refinement',
|
|
418
|
+
},
|
|
419
|
+
},
|
|
420
|
+
],
|
|
421
|
+
};
|
|
422
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decision-engine-adapter.test.d.ts","sourceRoot":"","sources":["../../../src/governor/decision-engine-adapter.test.ts"],"names":[],"mappings":""}
|