@renseiai/agentfactory 0.8.18 → 0.8.20

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 (117) hide show
  1. package/dist/src/config/repository-config.d.ts +7 -0
  2. package/dist/src/config/repository-config.d.ts.map +1 -1
  3. package/dist/src/config/repository-config.js +15 -1
  4. package/dist/src/config/repository-config.test.js +1 -1
  5. package/dist/src/governor/decision-engine-adapter.d.ts +43 -0
  6. package/dist/src/governor/decision-engine-adapter.d.ts.map +1 -0
  7. package/dist/src/governor/decision-engine-adapter.js +417 -0
  8. package/dist/src/governor/decision-engine-adapter.test.d.ts +2 -0
  9. package/dist/src/governor/decision-engine-adapter.test.d.ts.map +1 -0
  10. package/dist/src/governor/decision-engine-adapter.test.js +362 -0
  11. package/dist/src/governor/decision-engine.js +3 -7
  12. package/dist/src/governor/decision-engine.test.js +5 -5
  13. package/dist/src/governor/index.d.ts +1 -0
  14. package/dist/src/governor/index.d.ts.map +1 -1
  15. package/dist/src/governor/index.js +1 -0
  16. package/dist/src/index.d.ts +1 -0
  17. package/dist/src/index.d.ts.map +1 -1
  18. package/dist/src/index.js +1 -0
  19. package/dist/src/manifest/route-manifest.d.ts.map +1 -1
  20. package/dist/src/manifest/route-manifest.js +4 -0
  21. package/dist/src/merge-queue/adapters/local.d.ts +68 -0
  22. package/dist/src/merge-queue/adapters/local.d.ts.map +1 -0
  23. package/dist/src/merge-queue/adapters/local.js +136 -0
  24. package/dist/src/merge-queue/adapters/local.test.d.ts +2 -0
  25. package/dist/src/merge-queue/adapters/local.test.d.ts.map +1 -0
  26. package/dist/src/merge-queue/adapters/local.test.js +176 -0
  27. package/dist/src/merge-queue/index.d.ts +13 -5
  28. package/dist/src/merge-queue/index.d.ts.map +1 -1
  29. package/dist/src/merge-queue/index.js +13 -6
  30. package/dist/src/merge-queue/merge-queue.integration.test.js +19 -0
  31. package/dist/src/merge-queue/merge-worker.d.ts.map +1 -1
  32. package/dist/src/merge-queue/merge-worker.js +29 -0
  33. package/dist/src/merge-queue/types.d.ts +1 -1
  34. package/dist/src/merge-queue/types.d.ts.map +1 -1
  35. package/dist/src/orchestrator/index.d.ts +4 -0
  36. package/dist/src/orchestrator/index.d.ts.map +1 -1
  37. package/dist/src/orchestrator/index.js +3 -0
  38. package/dist/src/orchestrator/orchestrator.d.ts +58 -0
  39. package/dist/src/orchestrator/orchestrator.d.ts.map +1 -1
  40. package/dist/src/orchestrator/orchestrator.js +552 -97
  41. package/dist/src/orchestrator/parse-work-result.d.ts.map +1 -1
  42. package/dist/src/orchestrator/parse-work-result.js +3 -1
  43. package/dist/src/orchestrator/parse-work-result.test.js +6 -0
  44. package/dist/src/orchestrator/quality-baseline.d.ts +83 -0
  45. package/dist/src/orchestrator/quality-baseline.d.ts.map +1 -0
  46. package/dist/src/orchestrator/quality-baseline.js +313 -0
  47. package/dist/src/orchestrator/quality-baseline.test.d.ts +2 -0
  48. package/dist/src/orchestrator/quality-baseline.test.d.ts.map +1 -0
  49. package/dist/src/orchestrator/quality-baseline.test.js +448 -0
  50. package/dist/src/orchestrator/quality-ratchet.d.ts +70 -0
  51. package/dist/src/orchestrator/quality-ratchet.d.ts.map +1 -0
  52. package/dist/src/orchestrator/quality-ratchet.js +162 -0
  53. package/dist/src/orchestrator/quality-ratchet.test.d.ts +2 -0
  54. package/dist/src/orchestrator/quality-ratchet.test.d.ts.map +1 -0
  55. package/dist/src/orchestrator/quality-ratchet.test.js +335 -0
  56. package/dist/src/orchestrator/types.d.ts +2 -0
  57. package/dist/src/orchestrator/types.d.ts.map +1 -1
  58. package/dist/src/providers/claude-provider.d.ts.map +1 -1
  59. package/dist/src/providers/claude-provider.js +11 -0
  60. package/dist/src/providers/codex-app-server-provider.d.ts +237 -0
  61. package/dist/src/providers/codex-app-server-provider.d.ts.map +1 -0
  62. package/dist/src/providers/codex-app-server-provider.js +1041 -0
  63. package/dist/src/providers/codex-app-server-provider.test.d.ts +2 -0
  64. package/dist/src/providers/codex-app-server-provider.test.d.ts.map +1 -0
  65. package/dist/src/providers/codex-app-server-provider.test.js +589 -0
  66. package/dist/src/providers/codex-approval-bridge.d.ts +49 -0
  67. package/dist/src/providers/codex-approval-bridge.d.ts.map +1 -0
  68. package/dist/src/providers/codex-approval-bridge.js +117 -0
  69. package/dist/src/providers/codex-approval-bridge.test.d.ts +2 -0
  70. package/dist/src/providers/codex-approval-bridge.test.d.ts.map +1 -0
  71. package/dist/src/providers/codex-approval-bridge.test.js +188 -0
  72. package/dist/src/providers/codex-provider.d.ts +24 -4
  73. package/dist/src/providers/codex-provider.d.ts.map +1 -1
  74. package/dist/src/providers/codex-provider.js +58 -6
  75. package/dist/src/providers/index.d.ts +1 -0
  76. package/dist/src/providers/index.d.ts.map +1 -1
  77. package/dist/src/providers/index.js +1 -0
  78. package/dist/src/providers/types.d.ts +25 -0
  79. package/dist/src/providers/types.d.ts.map +1 -1
  80. package/dist/src/routing/observation-recorder.test.js +1 -1
  81. package/dist/src/routing/observation-store.d.ts +15 -1
  82. package/dist/src/routing/observation-store.d.ts.map +1 -1
  83. package/dist/src/routing/observation-store.test.js +17 -11
  84. package/dist/src/routing/types.d.ts +1 -1
  85. package/dist/src/templates/adapters.d.ts +25 -0
  86. package/dist/src/templates/adapters.d.ts.map +1 -1
  87. package/dist/src/templates/adapters.js +70 -0
  88. package/dist/src/templates/adapters.test.js +49 -0
  89. package/dist/src/templates/index.d.ts +3 -1
  90. package/dist/src/templates/index.d.ts.map +1 -1
  91. package/dist/src/templates/index.js +1 -0
  92. package/dist/src/templates/registry.d.ts +31 -0
  93. package/dist/src/templates/registry.d.ts.map +1 -1
  94. package/dist/src/templates/registry.js +91 -0
  95. package/dist/src/templates/schema.d.ts +31 -0
  96. package/dist/src/templates/schema.d.ts.map +1 -0
  97. package/dist/src/templates/schema.js +139 -0
  98. package/dist/src/templates/schema.test.d.ts +2 -0
  99. package/dist/src/templates/schema.test.d.ts.map +1 -0
  100. package/dist/src/templates/schema.test.js +215 -0
  101. package/dist/src/templates/types.d.ts +22 -0
  102. package/dist/src/templates/types.d.ts.map +1 -1
  103. package/dist/src/templates/types.js +12 -0
  104. package/dist/src/tools/index.d.ts +2 -0
  105. package/dist/src/tools/index.d.ts.map +1 -1
  106. package/dist/src/tools/index.js +1 -0
  107. package/dist/src/tools/registry.d.ts +9 -1
  108. package/dist/src/tools/registry.d.ts.map +1 -1
  109. package/dist/src/tools/registry.js +13 -1
  110. package/dist/src/tools/stdio-server-entry.d.ts +25 -0
  111. package/dist/src/tools/stdio-server-entry.d.ts.map +1 -0
  112. package/dist/src/tools/stdio-server-entry.js +205 -0
  113. package/dist/src/tools/stdio-server.d.ts +87 -0
  114. package/dist/src/tools/stdio-server.d.ts.map +1 -0
  115. package/dist/src/tools/stdio-server.js +138 -0
  116. package/dist/src/workflow/workflow-types.d.ts +3 -3
  117. package/package.json +3 -2
@@ -121,6 +121,7 @@ export declare const RepositoryConfigSchema: z.ZodObject<{
121
121
  mergeQueue: z.ZodOptional<z.ZodObject<{
122
122
  provider: z.ZodDefault<z.ZodEnum<{
123
123
  "github-native": "github-native";
124
+ local: "local";
124
125
  mergify: "mergify";
125
126
  trunk: "trunk";
126
127
  }>>;
@@ -159,6 +160,12 @@ export declare const RepositoryConfigSchema: z.ZodObject<{
159
160
  default: "default";
160
161
  mergiraf: "mergiraf";
161
162
  }>>;
163
+ quality: z.ZodOptional<z.ZodObject<{
164
+ baselineEnabled: z.ZodDefault<z.ZodBoolean>;
165
+ ratchetEnabled: z.ZodDefault<z.ZodBoolean>;
166
+ boyscoutRule: z.ZodDefault<z.ZodBoolean>;
167
+ tddWorkflow: z.ZodDefault<z.ZodBoolean>;
168
+ }, z.core.$strip>>;
162
169
  }, z.core.$strip>;
163
170
  export type RepositoryConfig = z.infer<typeof RepositoryConfigSchema>;
164
171
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"repository-config.d.ts","sourceRoot":"","sources":["../../../src/config/repository-config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAC5D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAMxD,qEAAqE;AACrE,eAAO,MAAM,mBAAmB;;;;;;;;;;;;iBAW9B,CAAA;AAEF,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAW/D,uCAAuC;AACvC,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;iBAOhC,CAAA;AAEF,6DAA6D;AAC7D,eAAO,MAAM,0BAA0B;;;;;;;iBAarC,CAAA;AAEF,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA8GlC,CAAA;AAMD,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAA;AAMrE;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,EAAE,GAAG,SAAS,CAK1F;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAepG;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAKhG;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,gBAAgB,GAAG,eAAe,GAAG,SAAS,CAExF;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,GAAG,aAAa,GAAG,SAAS,CAEpF;AAMD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAQ7E"}
1
+ {"version":3,"file":"repository-config.d.ts","sourceRoot":"","sources":["../../../src/config/repository-config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAC5D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAMxD,qEAAqE;AACrE,eAAO,MAAM,mBAAmB;;;;;;;;;;;;iBAW9B,CAAA;AAEF,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAW/D,uCAAuC;AACvC,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;iBAOhC,CAAA;AAEF,6DAA6D;AAC7D,eAAO,MAAM,0BAA0B;;;;;;;iBAarC,CAAA;AAEF,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA4HlC,CAAA;AAMD,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAA;AAMrE;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,EAAE,GAAG,SAAS,CAK1F;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAepG;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAKhG;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,gBAAgB,GAAG,eAAe,GAAG,SAAS,CAExF;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,GAAG,aAAa,GAAG,SAAS,CAEpF;AAMD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAQ7E"}
@@ -116,7 +116,7 @@ export const RepositoryConfigSchema = z.object({
116
116
  */
117
117
  mergeQueue: z.object({
118
118
  /** Merge queue provider to use */
119
- provider: z.enum(['github-native', 'mergify', 'trunk']).default('github-native'),
119
+ provider: z.enum(['github-native', 'local', 'mergify', 'trunk']).default('local'),
120
120
  /** Whether merge queue integration is enabled */
121
121
  enabled: z.boolean().default(false),
122
122
  /** Automatically add approved PRs to merge queue */
@@ -164,6 +164,20 @@ export const RepositoryConfigSchema = z.object({
164
164
  * Defaults to 'default' (standard git line-based merge).
165
165
  */
166
166
  mergeDriver: z.enum(['mergiraf', 'default']).optional(),
167
+ /**
168
+ * Quality gate configuration.
169
+ * Controls baseline-diff quality checks and ratchet enforcement.
170
+ */
171
+ quality: z.object({
172
+ /** Enable quality baseline capture at worktree creation and post-session delta check */
173
+ baselineEnabled: z.boolean().default(false),
174
+ /** Enable quality ratchet enforcement in merge queue and CI */
175
+ ratchetEnabled: z.boolean().default(false),
176
+ /** Include boy scout rule instructions in agent prompts */
177
+ boyscoutRule: z.boolean().default(true),
178
+ /** Include TDD workflow instructions in agent prompts */
179
+ tddWorkflow: z.boolean().default(true),
180
+ }).optional(),
167
181
  }).refine((data) => !(data.allowedProjects && data.projectPaths), { message: 'allowedProjects and projectPaths are mutually exclusive — use one or the other' });
168
182
  // ---------------------------------------------------------------------------
169
183
  // Helpers
@@ -695,7 +695,7 @@ describe('RepositoryConfigSchema mergeQueue — Refinery fields', () => {
695
695
  mergeQueue: { enabled: true },
696
696
  });
697
697
  expect(result.mergeQueue).toBeDefined();
698
- expect(result.mergeQueue.provider).toBe('github-native');
698
+ expect(result.mergeQueue.provider).toBe('local');
699
699
  expect(result.mergeQueue.enabled).toBe(true);
700
700
  expect(result.mergeQueue.autoMerge).toBe(true);
701
701
  expect(result.mergeQueue.requiredChecks).toBeUndefined();
@@ -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,417 @@
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
+ // Always trigger QA for functional validation — merge queue handles git
339
+ // mechanics at merge time, not as a QA bypass.
340
+ // The includeMergeQueue flag is preserved for the adapter signature but the
341
+ // Finished node no longer short-circuits to trigger-merge.
342
+ void includeMergeQueue;
343
+ steps.push({
344
+ id: 'dispatch-qa',
345
+ action: 'trigger-qa',
346
+ when: '{{ config.enableAutoQA }}',
347
+ with: {
348
+ reason: 'Issue {{ issue.identifier }} is in Finished — triggering QA',
349
+ },
350
+ });
351
+ return {
352
+ name: 'route-finished',
353
+ description: 'Finished → trigger-qa (with escalation/merge-queue checks)',
354
+ provider: 'agent',
355
+ when: "{{ issue.status == 'Finished' }}",
356
+ steps,
357
+ };
358
+ }
359
+ function buildDeliveredNode(config) {
360
+ return {
361
+ name: 'route-delivered',
362
+ description: 'Delivered → trigger-acceptance (if enabled)',
363
+ provider: 'agent',
364
+ when: "{{ issue.status == 'Delivered' }}",
365
+ steps: [
366
+ {
367
+ id: 'check-enabled',
368
+ action: 'none',
369
+ when: '{{ !config.enableAutoAcceptance }}',
370
+ with: {
371
+ reason: 'Auto-acceptance is disabled for {{ issue.identifier }}',
372
+ },
373
+ },
374
+ {
375
+ id: 'dispatch',
376
+ action: 'trigger-acceptance',
377
+ when: '{{ config.enableAutoAcceptance }}',
378
+ with: {
379
+ reason: 'Issue {{ issue.identifier }} is in Delivered — triggering acceptance',
380
+ },
381
+ },
382
+ ],
383
+ };
384
+ }
385
+ function buildRejectedNode() {
386
+ return {
387
+ name: 'route-rejected',
388
+ description: 'Rejected → trigger-refinement (with escalation checks)',
389
+ provider: 'agent',
390
+ when: "{{ issue.status == 'Rejected' }}",
391
+ steps: [
392
+ {
393
+ id: 'check-escalate-human',
394
+ action: 'escalate-human',
395
+ when: "{{ workflowStrategy == 'escalate-human' }}",
396
+ with: {
397
+ reason: 'Issue {{ issue.identifier }} is Rejected with escalate-human strategy — needs human intervention',
398
+ },
399
+ },
400
+ {
401
+ id: 'check-decompose',
402
+ action: 'decompose',
403
+ when: "{{ workflowStrategy == 'decompose' }}",
404
+ with: {
405
+ reason: 'Issue {{ issue.identifier }} is Rejected with decompose strategy — triggering decomposition',
406
+ },
407
+ },
408
+ {
409
+ id: 'dispatch-refinement',
410
+ action: 'trigger-refinement',
411
+ with: {
412
+ reason: 'Issue {{ issue.identifier }} is Rejected — triggering refinement',
413
+ },
414
+ },
415
+ ],
416
+ };
417
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=decision-engine-adapter.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decision-engine-adapter.test.d.ts","sourceRoot":"","sources":["../../../src/governor/decision-engine-adapter.test.ts"],"names":[],"mappings":""}