agentic-orchestrator 0.1.4 → 0.1.6

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 (108) hide show
  1. package/.claude/settings.local.json +6 -1
  2. package/README.md +81 -54
  3. package/agentic/orchestrator/defaults/policy.defaults.yaml +212 -0
  4. package/agentic/orchestrator/schemas/adapters.schema.json +17 -4
  5. package/agentic/orchestrator/schemas/agents.schema.json +58 -13
  6. package/agentic/orchestrator/schemas/gates.schema.json +88 -17
  7. package/agentic/orchestrator/schemas/index.schema.json +172 -37
  8. package/agentic/orchestrator/schemas/multi-project.schema.json +85 -17
  9. package/agentic/orchestrator/schemas/plan.schema.json +135 -30
  10. package/agentic/orchestrator/schemas/policy.schema.json +198 -69
  11. package/agentic/orchestrator/schemas/policy.user.schema.json +165 -0
  12. package/agentic/orchestrator/schemas/qa_test_index.schema.json +71 -14
  13. package/agentic/orchestrator/schemas/state.schema.json +196 -39
  14. package/apps/control-plane/scripts/validate-architecture-rules.mjs +5 -3
  15. package/apps/control-plane/scripts/validate-docker-mcp-contract.mjs +0 -3
  16. package/apps/control-plane/scripts/validate-mcp-contracts.ts +2 -6
  17. package/apps/control-plane/src/application/services/policy-loader-service.ts +115 -0
  18. package/apps/control-plane/src/cli/aop.ts +35 -1
  19. package/apps/control-plane/src/cli/cli-argument-parser.ts +4 -0
  20. package/apps/control-plane/src/cli/help-command-handler.ts +2 -1
  21. package/apps/control-plane/src/cli/init-command-handler.ts +136 -27
  22. package/apps/control-plane/src/cli/retry-command-handler.ts +3 -6
  23. package/apps/control-plane/src/cli/types.ts +1 -0
  24. package/apps/control-plane/src/core/git.ts +1 -3
  25. package/apps/control-plane/src/core/kernel.ts +3 -6
  26. package/apps/control-plane/src/core/schemas.ts +36 -1
  27. package/apps/control-plane/src/interfaces/cli/bootstrap.ts +1 -1
  28. package/apps/control-plane/src/mcp/tool-registry-loader.ts +37 -1
  29. package/apps/control-plane/src/supervisor/qa-wave-executor.ts +1 -1
  30. package/apps/control-plane/test/aop.spec.ts +37 -0
  31. package/apps/control-plane/test/batch-operations.spec.ts +5 -3
  32. package/apps/control-plane/test/bootstrap-attach.spec.ts +28 -18
  33. package/apps/control-plane/test/bootstrap-edge-cases.spec.ts +25 -15
  34. package/apps/control-plane/test/bootstrap.spec.ts +30 -22
  35. package/apps/control-plane/test/cli.unit.spec.ts +55 -10
  36. package/apps/control-plane/test/core-utils.spec.ts +12 -3
  37. package/apps/control-plane/test/feature-deletion-service.spec.ts +2 -1
  38. package/apps/control-plane/test/feature-lifecycle.spec.ts +1 -1
  39. package/apps/control-plane/test/helpers.ts +22 -2
  40. package/apps/control-plane/test/init-wizard.spec.ts +160 -7
  41. package/apps/control-plane/test/issue-tracker.spec.ts +3 -3
  42. package/apps/control-plane/test/kernel.spec.ts +62 -0
  43. package/apps/control-plane/test/lock-service.spec.ts +4 -4
  44. package/apps/control-plane/test/policy-loader-service.spec.ts +346 -0
  45. package/apps/control-plane/test/reactions.spec.ts +8 -6
  46. package/apps/control-plane/test/resume-command.spec.ts +31 -15
  47. package/apps/control-plane/test/supervisor.unit.spec.ts +2 -2
  48. package/apps/control-plane/test/tool-registry-loader.spec.ts +12 -0
  49. package/apps/control-plane/vitest.config.ts +1 -1
  50. package/dist/apps/control-plane/application/services/policy-loader-service.d.ts +24 -0
  51. package/dist/apps/control-plane/application/services/policy-loader-service.js +90 -0
  52. package/dist/apps/control-plane/application/services/policy-loader-service.js.map +1 -0
  53. package/dist/apps/control-plane/application/tools/tool-metadata.js +1 -0
  54. package/dist/apps/control-plane/application/tools/tool-metadata.js.map +1 -1
  55. package/dist/apps/control-plane/cli/aop.js +33 -1
  56. package/dist/apps/control-plane/cli/aop.js.map +1 -1
  57. package/dist/apps/control-plane/cli/cli-argument-parser.js +4 -0
  58. package/dist/apps/control-plane/cli/cli-argument-parser.js.map +1 -1
  59. package/dist/apps/control-plane/cli/dashboard-command-handler.js +11 -5
  60. package/dist/apps/control-plane/cli/dashboard-command-handler.js.map +1 -1
  61. package/dist/apps/control-plane/cli/help-command-handler.js +5 -4
  62. package/dist/apps/control-plane/cli/help-command-handler.js.map +1 -1
  63. package/dist/apps/control-plane/cli/init-command-handler.d.ts +1 -0
  64. package/dist/apps/control-plane/cli/init-command-handler.js +110 -26
  65. package/dist/apps/control-plane/cli/init-command-handler.js.map +1 -1
  66. package/dist/apps/control-plane/cli/retry-command-handler.js +3 -6
  67. package/dist/apps/control-plane/cli/retry-command-handler.js.map +1 -1
  68. package/dist/apps/control-plane/cli/types.d.ts +1 -0
  69. package/dist/apps/control-plane/core/git.js +1 -3
  70. package/dist/apps/control-plane/core/git.js.map +1 -1
  71. package/dist/apps/control-plane/core/kernel.js +3 -5
  72. package/dist/apps/control-plane/core/kernel.js.map +1 -1
  73. package/dist/apps/control-plane/core/schemas.d.ts +2 -0
  74. package/dist/apps/control-plane/core/schemas.js +31 -1
  75. package/dist/apps/control-plane/core/schemas.js.map +1 -1
  76. package/dist/apps/control-plane/interfaces/cli/bootstrap.js +1 -1
  77. package/dist/apps/control-plane/interfaces/cli/bootstrap.js.map +1 -1
  78. package/dist/apps/control-plane/mcp/tool-registry-loader.d.ts +2 -0
  79. package/dist/apps/control-plane/mcp/tool-registry-loader.js +31 -1
  80. package/dist/apps/control-plane/mcp/tool-registry-loader.js.map +1 -1
  81. package/dist/apps/control-plane/supervisor/build-wave-executor.js +1 -1
  82. package/dist/apps/control-plane/supervisor/build-wave-executor.js.map +1 -1
  83. package/dist/apps/control-plane/supervisor/qa-wave-executor.js +1 -1
  84. package/dist/apps/control-plane/supervisor/qa-wave-executor.js.map +1 -1
  85. package/package.json +18 -17
  86. package/packages/web-dashboard/package.json +1 -1
  87. package/packages/web-dashboard/src/app/api/actions/route.ts +2 -2
  88. package/packages/web-dashboard/src/app/api/events/route.ts +1 -1
  89. package/packages/web-dashboard/src/app/api/features/[id]/checkout/route.ts +1 -1
  90. package/packages/web-dashboard/src/app/api/features/[id]/diff/route.ts +1 -1
  91. package/packages/web-dashboard/src/app/api/features/[id]/evidence/[artifact]/route.ts +1 -1
  92. package/packages/web-dashboard/src/app/api/features/[id]/review/route.ts +2 -2
  93. package/packages/web-dashboard/src/app/api/features/[id]/route.ts +1 -1
  94. package/packages/web-dashboard/src/app/api/projects/route.ts +2 -2
  95. package/packages/web-dashboard/src/app/api/status/route.ts +1 -1
  96. package/packages/web-dashboard/src/app/page.tsx +1 -1
  97. package/packages/web-dashboard/src/lib/aop-client.ts +1 -1
  98. package/packages/web-dashboard/src/lib/orchestrator-tools.ts +1 -1
  99. package/packages/web-dashboard/tsconfig.json +1 -0
  100. package/spec-files/completed/agentic_orchestrator_init_policy_ux_simplification_spec.md +481 -0
  101. package/spec-files/outstanding/agentic_orchestrator_artifact_database_publishing_spec.md +500 -0
  102. package/spec-files/outstanding/agentic_orchestrator_observability_integrity_diagnostics_spec.md +500 -195
  103. package/spec-files/outstanding/agentic_orchestrator_performance_improvements_spec.md +471 -162
  104. package/spec-files/outstanding/agentic_orchestrator_planning_review_quality_spec.md +532 -268
  105. package/spec-files/outstanding/agentic_orchestrator_productization_commercial_spec.md +645 -0
  106. package/spec-files/progress.md +99 -2
  107. package/tsconfig.base.json +4 -0
  108. /package/spec-files/{outstanding → completed}/agentic_orchestrator_validator_hardening_spec.md +0 -0
@@ -0,0 +1,346 @@
1
+ import fs from 'node:fs/promises';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
5
+
6
+ import { mergePolicy, loadComposedPolicy } from '../src/application/services/policy-loader-service.js';
7
+ import { SchemaRegistry } from '../src/core/schemas.js';
8
+
9
+ // ---------------------------------------------------------------------------
10
+ // Unit tests for mergePolicy
11
+ // ---------------------------------------------------------------------------
12
+
13
+ describe('mergePolicy', () => {
14
+ it('GIVEN_scalar_user_value_WHEN_merged_THEN_replaces_default_scalar', () => {
15
+ const defaults = { version: 1, timeout: 600 };
16
+ const user = { timeout: 300 };
17
+ const result = mergePolicy(defaults, user);
18
+ expect(result).toEqual({ version: 1, timeout: 300 });
19
+ });
20
+
21
+ it('GIVEN_object_user_value_WHEN_merged_THEN_recursive_merge_preserves_defaults', () => {
22
+ const defaults = { worktree: { base_branch: 'main', normalize: true } };
23
+ const user = { worktree: { base_branch: 'develop' } };
24
+ const result = mergePolicy(defaults, user);
25
+ expect(result).toEqual({ worktree: { base_branch: 'develop', normalize: true } });
26
+ });
27
+
28
+ it('GIVEN_array_override_WHEN_composed_THEN_array_replaces_default_array', () => {
29
+ const defaults = { required_modes: ['fast', 'full'] };
30
+ const user = { required_modes: ['fast'] };
31
+ const result = mergePolicy(defaults, user) as Record<string, unknown>;
32
+ expect(result['required_modes']).toEqual(['fast']);
33
+ });
34
+
35
+ it('GIVEN_absent_user_keys_WHEN_merged_THEN_defaults_inherited', () => {
36
+ const defaults = { version: 1, locks: { lease_ttl_seconds: 300 } };
37
+ const user = { version: 1 };
38
+ const result = mergePolicy(defaults, user) as Record<string, unknown>;
39
+ expect(result['locks']).toEqual({ lease_ttl_seconds: 300 });
40
+ });
41
+
42
+ it('GIVEN_undefined_user_field_WHEN_merged_THEN_field_is_ignored', () => {
43
+ const defaults = { version: 1, port: 3000 };
44
+ const user = { version: 1, port: undefined };
45
+ const result = mergePolicy(defaults, user) as Record<string, unknown>;
46
+ // undefined user fields inherit the default
47
+ expect(result['port']).toBe(3000);
48
+ });
49
+
50
+ it('GIVEN_empty_user_object_WHEN_merged_THEN_returns_defaults_clone', () => {
51
+ const defaults = { version: 1, commit_policy: { allow_commit: false } };
52
+ const user = {};
53
+ const result = mergePolicy(defaults, user);
54
+ expect(result).toEqual(defaults);
55
+ // must be a deep clone, not same reference
56
+ expect(result).not.toBe(defaults);
57
+ });
58
+
59
+ it('GIVEN_merge_determinism_WHEN_key_order_differs_THEN_same_output', () => {
60
+ const defaults = { a: 1, b: 2, c: { x: 10, y: 20 } };
61
+ const user1 = { b: 99, c: { y: 99 } };
62
+ const user2 = { c: { y: 99 }, b: 99 };
63
+ const result1 = mergePolicy(defaults, user1);
64
+ const result2 = mergePolicy(defaults, user2);
65
+ expect(result1).toEqual(result2);
66
+ });
67
+
68
+ it('GIVEN_deeply_nested_user_value_WHEN_merged_THEN_only_overridden_leaf_changes', () => {
69
+ const defaults = {
70
+ execution: {
71
+ retry_policy: { transient_max_retries: 1, transient_error_codes: [124] }
72
+ }
73
+ };
74
+ const user = {
75
+ execution: {
76
+ retry_policy: { transient_max_retries: 3 }
77
+ }
78
+ };
79
+ const result = mergePolicy(defaults, user) as {
80
+ execution: { retry_policy: { transient_max_retries: number; transient_error_codes: number[] } };
81
+ };
82
+ expect(result.execution.retry_policy.transient_max_retries).toBe(3);
83
+ expect(result.execution.retry_policy.transient_error_codes).toEqual([124]);
84
+ });
85
+
86
+ it('GIVEN_array_in_protected_areas_WHEN_user_overrides_THEN_array_is_replaced_wholesale', () => {
87
+ const defaults = { protected_areas: ['agentic/orchestrator/policy.yaml'] };
88
+ const user = { protected_areas: ['agentic/orchestrator/policy.yaml', 'libs/core'] };
89
+ const result = mergePolicy(defaults, user) as Record<string, unknown>;
90
+ expect(result['protected_areas']).toEqual(['agentic/orchestrator/policy.yaml', 'libs/core']);
91
+ expect((result['protected_areas'] as unknown[]).length).toBe(2);
92
+ });
93
+ });
94
+
95
+ // ---------------------------------------------------------------------------
96
+ // Integration tests for loadComposedPolicy
97
+ // ---------------------------------------------------------------------------
98
+
99
+ describe('loadComposedPolicy', () => {
100
+ let tmpDir: string;
101
+ let schemaRegistry: SchemaRegistry;
102
+
103
+ beforeEach(async () => {
104
+ tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'aop-policy-loader-'));
105
+ // Use the real schema registry pointing at the AOP repo schemas (bundled)
106
+ schemaRegistry = new SchemaRegistry(tmpDir);
107
+ });
108
+
109
+ afterEach(async () => {
110
+ await fs.rm(tmpDir, { recursive: true, force: true });
111
+ vi.restoreAllMocks();
112
+ });
113
+
114
+ async function writePolicyFile(content: string): Promise<string> {
115
+ const policyPath = path.join(tmpDir, 'policy.yaml');
116
+ await fs.writeFile(policyPath, content, 'utf8');
117
+ return policyPath;
118
+ }
119
+
120
+ it('GIVEN_defaults_and_lean_user_policy_WHEN_composed_THEN_merged_policy_is_valid', async () => {
121
+ const leanPolicy = `version: 1
122
+ worktree:
123
+ base_branch: develop
124
+ supervisor:
125
+ max_parallel_gate_runs: 4
126
+ dashboard:
127
+ enabled: true
128
+ port: 4000
129
+ merge_policy:
130
+ require_user_approval: true
131
+ notifications:
132
+ enabled: false
133
+ channels:
134
+ desktop:
135
+ enabled: false
136
+ slack:
137
+ enabled: false
138
+ webhook: ""
139
+ channel: "#aop-alerts"
140
+ webhook:
141
+ enabled: false
142
+ url: ""
143
+ `;
144
+ const policyPath = await writePolicyFile(leanPolicy);
145
+ const result = await loadComposedPolicy(tmpDir, policyPath, schemaRegistry);
146
+
147
+ // User values are preserved in merged result
148
+ expect((result.mergedPolicy['worktree'] as Record<string, unknown>)['base_branch']).toBe('develop');
149
+ expect((result.mergedPolicy['supervisor'] as Record<string, unknown>)['max_parallel_gate_runs']).toBe(4);
150
+
151
+ // Defaults fill in required fields not in lean policy
152
+ expect(result.mergedPolicy['implementation']).toBeDefined();
153
+ expect((result.mergedPolicy['implementation'] as Record<string, unknown>)['workspace']).toBe('nx');
154
+ expect(result.mergedPolicy['rbac']).toBeDefined();
155
+ expect(result.mergedPolicy['locks']).toBeDefined();
156
+ });
157
+
158
+ it('GIVEN_full_user_policy_WHEN_composed_THEN_user_values_override_defaults', async () => {
159
+ const fullPolicy = `version: 1
160
+ commit_policy:
161
+ allow_commit: true
162
+ allow_merge: true
163
+ patch_policy:
164
+ enforce_plan: false
165
+ enforce_allowed_areas: false
166
+ locks:
167
+ resources:
168
+ - openapi
169
+ contract_to_resource:
170
+ openapi: openapi
171
+ events: events
172
+ db: db_migrations
173
+ lease_ttl_seconds: 120
174
+ acquire_behavior: wait
175
+ default_wait_timeout_seconds: 120
176
+ acquire_backoff:
177
+ initial_ms: 100
178
+ max_ms: 2000
179
+ multiplier: 2
180
+ jitter_ms: 50
181
+ protected_areas:
182
+ - agentic/orchestrator/policy.yaml
183
+ required_modes:
184
+ - fast
185
+ required_merge_mode: merge
186
+ collision_policy: reject
187
+ config_precedence:
188
+ policy_hard_constraints:
189
+ - execution.default_step_timeout_seconds
190
+ gates_profile_defaults:
191
+ - profiles
192
+ plan_verification_overrides:
193
+ - verification_overrides
194
+ path_rules:
195
+ matching: repo_prefix
196
+ normalize_paths: true
197
+ allow_symlink_traversal: false
198
+ execution:
199
+ default_step_timeout_seconds: 300
200
+ retry_policy:
201
+ transient_max_retries: 2
202
+ transient_error_codes:
203
+ - 124
204
+ non_retryable_error_codes:
205
+ - 2
206
+ env_allowlist:
207
+ - PATH
208
+ implementation:
209
+ workspace: nx
210
+ testing:
211
+ framework: vitest
212
+ coverage:
213
+ minimums:
214
+ line: 0.8
215
+ branch: 0.8
216
+ targets:
217
+ line: 1.0
218
+ branch: 1.0
219
+ merge_policy:
220
+ require_user_approval: false
221
+ allowed_strategies:
222
+ - squash
223
+ worktree:
224
+ base_branch: main
225
+ rbac:
226
+ orchestrator:
227
+ - feature.get_context
228
+ system:
229
+ - "*"
230
+ `;
231
+ const policyPath = await writePolicyFile(fullPolicy);
232
+ const result = await loadComposedPolicy(tmpDir, policyPath, schemaRegistry);
233
+
234
+ // User values dominate
235
+ expect((result.mergedPolicy['commit_policy'] as Record<string, unknown>)['allow_commit']).toBe(true);
236
+ expect((result.mergedPolicy['execution'] as Record<string, unknown>)['default_step_timeout_seconds']).toBe(300);
237
+ expect((result.mergedPolicy['merge_policy'] as Record<string, unknown>)['require_user_approval']).toBe(false);
238
+ const strategies = (result.mergedPolicy['merge_policy'] as Record<string, unknown>)['allowed_strategies'];
239
+ expect(strategies).toEqual(['squash']);
240
+ });
241
+
242
+ it('GIVEN_array_override_for_required_modes_WHEN_composed_THEN_array_replaces_default_array', async () => {
243
+ const policy = `version: 1
244
+ required_modes:
245
+ - fast
246
+ `;
247
+ const policyPath = await writePolicyFile(policy);
248
+ const result = await loadComposedPolicy(tmpDir, policyPath, schemaRegistry);
249
+
250
+ // User's array replaces the defaults array wholesale
251
+ expect(result.mergedPolicy['required_modes']).toEqual(['fast']);
252
+ });
253
+
254
+ it('GIVEN_empty_user_policy_WHEN_loaded_THEN_merged_policy_is_defaults_only', async () => {
255
+ const policyPath = await writePolicyFile('');
256
+ const result = await loadComposedPolicy(tmpDir, policyPath, schemaRegistry);
257
+
258
+ // All required fields come from defaults
259
+ expect(result.userPolicy).toEqual({});
260
+ expect(result.mergedPolicy['version']).toBe(1);
261
+ expect(result.mergedPolicy['commit_policy']).toBeDefined();
262
+ expect(result.mergedPolicy['implementation']).toBeDefined();
263
+ });
264
+
265
+ it('GIVEN_invalid_user_policy_WHEN_loaded_THEN_validation_error_is_actionable', async () => {
266
+ // Provide a policy that overrides a required field with wrong type
267
+ const badPolicy = `version: 1
268
+ commit_policy:
269
+ allow_commit: "yes"
270
+ allow_merge: false
271
+ patch_policy:
272
+ enforce_plan: true
273
+ enforce_allowed_areas: true
274
+ locks:
275
+ resources: []
276
+ contract_to_resource:
277
+ openapi: openapi
278
+ events: events
279
+ db: db_migrations
280
+ lease_ttl_seconds: 300
281
+ acquire_behavior: wait
282
+ default_wait_timeout_seconds: 300
283
+ acquire_backoff:
284
+ initial_ms: 200
285
+ max_ms: 5000
286
+ multiplier: 2
287
+ jitter_ms: 150
288
+ protected_areas:
289
+ - agentic/orchestrator/policy.yaml
290
+ required_modes:
291
+ - fast
292
+ required_merge_mode: merge
293
+ collision_policy: reject
294
+ config_precedence: {}
295
+ path_rules:
296
+ matching: repo_prefix
297
+ normalize_paths: true
298
+ allow_symlink_traversal: false
299
+ execution:
300
+ default_step_timeout_seconds: 600
301
+ retry_policy:
302
+ transient_max_retries: 1
303
+ transient_error_codes: []
304
+ non_retryable_error_codes: []
305
+ env_allowlist: []
306
+ implementation:
307
+ workspace: nx
308
+ testing:
309
+ framework: vitest
310
+ coverage:
311
+ minimums:
312
+ line: 0.7
313
+ branch: 0.7
314
+ targets:
315
+ line: 1.0
316
+ branch: 1.0
317
+ merge_policy:
318
+ require_user_approval: true
319
+ allowed_strategies:
320
+ - merge_commit
321
+ worktree:
322
+ base_branch: main
323
+ rbac:
324
+ system:
325
+ - "*"
326
+ `;
327
+ const policyPath = await writePolicyFile(badPolicy);
328
+ await expect(loadComposedPolicy(tmpDir, policyPath, schemaRegistry)).rejects.toThrow(
329
+ /invalid_policy_yaml/
330
+ );
331
+ });
332
+
333
+ it('GIVEN_missing_policy_file_WHEN_loaded_THEN_throws_read_error', async () => {
334
+ const missingPath = path.join(tmpDir, 'missing.yaml');
335
+ await expect(loadComposedPolicy(tmpDir, missingPath, schemaRegistry)).rejects.toThrow();
336
+ });
337
+
338
+ it('GIVEN_defaults_not_found_WHEN_loaded_THEN_throws_descriptive_error', async () => {
339
+ const policyPath = await writePolicyFile('version: 1\n');
340
+ // Temporarily override the bundled defaults path via mocking the fs.readFile call
341
+ // to simulate defaults artifact missing by mocking module internals
342
+ vi.spyOn(fs, 'readFile').mockRejectedValueOnce(new Error('ENOENT: no such file'));
343
+
344
+ await expect(loadComposedPolicy(tmpDir, policyPath, schemaRegistry)).rejects.toThrow();
345
+ });
346
+ });
@@ -1,9 +1,10 @@
1
1
  import { describe, expect, it, vi } from 'vitest';
2
2
  import { ReactionsService } from '../src/application/services/reactions-service.js';
3
3
  import type { GateRepairContext, ReactionsPolicy } from '../src/application/services/reactions-service.js';
4
+ import type { ToolCaller } from '../src/core/tool-caller.js';
4
5
  import { TOOLS } from '../src/core/constants.js';
5
6
 
6
- function makeToolCaller(statePatchFn?: () => Promise<Record<string, unknown>>) {
7
+ function makeToolCaller(statePatchFn?: () => Promise<Record<string, unknown>>): ToolCaller {
7
8
  return {
8
9
  callTool: vi.fn(async (_role: string, toolName: string, _args?: Record<string, unknown>) => {
9
10
  if (toolName === TOOLS.FEATURE_STATE_GET) {
@@ -16,7 +17,7 @@ function makeToolCaller(statePatchFn?: () => Promise<Record<string, unknown>>) {
16
17
  return { ok: true, data: { updated: true } };
17
18
  }
18
19
  return { ok: true, data: {} };
19
- })
20
+ }) as unknown as ToolCaller['callTool']
20
21
  };
21
22
  }
22
23
 
@@ -126,7 +127,7 @@ describe('ReactionsService', () => {
126
127
  await service.recordRetry('feature_d', 1);
127
128
 
128
129
  expect(patchCallCount).toBe(1);
129
- const patchCall = toolCaller.callTool.mock.calls.find(([, tool]) => tool === TOOLS.FEATURE_STATE_PATCH);
130
+ const patchCall = vi.mocked(toolCaller.callTool).mock.calls.find(([, tool]) => tool === TOOLS.FEATURE_STATE_PATCH);
130
131
  expect(patchCall).toBeDefined();
131
132
  const patchArgs = patchCall?.[2] ?? {};
132
133
  const patch = (patchArgs['patch'] ?? {}) as Record<string, unknown>;
@@ -144,7 +145,7 @@ describe('ReactionsService', () => {
144
145
  // Simulate force reset by calling recordRetry with 0
145
146
  await service.recordRetry('feature_e', 0);
146
147
 
147
- const patchCall = toolCaller.callTool.mock.calls.find(([, tool]) => tool === TOOLS.FEATURE_STATE_PATCH);
148
+ const patchCall = vi.mocked(toolCaller.callTool).mock.calls.find(([, tool]) => tool === TOOLS.FEATURE_STATE_PATCH);
148
149
  expect(patchCall).toBeDefined();
149
150
  const patchArgs = patchCall?.[2] ?? {};
150
151
  const patch = (patchArgs['patch'] ?? {}) as Record<string, unknown>;
@@ -321,6 +322,7 @@ describe('ReactionsService branch coverage', () => {
321
322
  policy: makeEnabledPolicy()
322
323
  });
323
324
  const ctx: GateRepairContext = {
325
+ featureId: 'feature_history_none',
324
326
  gateName: 'unit-tests',
325
327
  exitCode: 1,
326
328
  logs: 'test output',
@@ -336,7 +338,7 @@ describe('ReactionsService additional coverage', () => {
336
338
  it('GIVEN_policy_with_valid_max_retries_number_WHEN_maxRetries_called_THEN_returns_floor_of_value', () => {
337
339
  const service = new ReactionsService({
338
340
  toolCaller: makeToolCaller(),
339
- policy: { gate_failed: { enabled: true, action: 'retry_with_agent_repair', max_retries: 3.7, retry_delay_ms: 0 } }
341
+ policy: { gate_failed: { enabled: true, action: 'retry_with_agent_repair', max_retries: 3.7, escalate_after: 2, retry_delay_ms: 0 } }
340
342
  });
341
343
  expect(service.maxRetries()).toBe(3);
342
344
  });
@@ -344,7 +346,7 @@ describe('ReactionsService additional coverage', () => {
344
346
  it('GIVEN_non_finite_max_retries_WHEN_maxRetries_called_THEN_returns_default', () => {
345
347
  const service = new ReactionsService({
346
348
  toolCaller: makeToolCaller(),
347
- policy: { gate_failed: { enabled: true, action: 'retry_with_agent_repair', max_retries: Infinity, retry_delay_ms: 0 } }
349
+ policy: { gate_failed: { enabled: true, action: 'retry_with_agent_repair', max_retries: Infinity, escalate_after: 2, retry_delay_ms: 0 } }
348
350
  });
349
351
  expect(service.maxRetries()).toBeGreaterThanOrEqual(0);
350
352
  });
@@ -2,27 +2,43 @@ import { describe, it, expect, vi } from 'vitest';
2
2
 
3
3
  vi.mock('../src/providers/providers.js', () => ({
4
4
  resolveProviderSelection: vi.fn(() => ({ provider: 'null', model: 'none', provider_config_ref: null })),
5
- NullWorkerProvider: vi.fn().mockImplementation(() => ({
6
- selection: { provider: 'null', model: 'none', provider_config_ref: null },
7
- createSession: vi.fn(async () => ({ session_id: 'mock-session' })),
8
- reattachSession: vi.fn(async () => null),
9
- closeSession: vi.fn(async () => ({}))
10
- }))
5
+ NullWorkerProvider: class NullWorkerProvider {
6
+ selection: unknown;
7
+
8
+ constructor(selection: unknown) {
9
+ this.selection = selection;
10
+ }
11
+
12
+ async createSession() {
13
+ return { session_id: 'mock-session' };
14
+ }
15
+
16
+ async reattachSession() {
17
+ return null;
18
+ }
19
+
20
+ async closeSession() {
21
+ return {};
22
+ }
23
+ }
11
24
  }));
12
25
 
13
26
  vi.mock('../src/supervisor/runtime.js', () => ({
14
- SupervisorRuntime: vi.fn().mockImplementation(() => ({
15
- start: vi.fn(async (features: unknown[]) => ({
16
- queue_depth: features.length,
17
- status: 'running',
18
- run_metadata: {},
19
- dashboard: null
20
- }))
21
- }))
27
+ SupervisorRuntime: class SupervisorRuntime {
28
+ async start(features: unknown[]) {
29
+ return {
30
+ queue_depth: features.length,
31
+ status: 'running',
32
+ run_metadata: {},
33
+ dashboard: null
34
+ };
35
+ }
36
+ }
22
37
  }));
23
38
 
24
39
  import { ResumeCommandHandler } from '../src/cli/resume-command-handler.js';
25
40
  import { STATUS } from '../src/core/constants.js';
41
+ import type { ToolTransport } from '../src/cli/types.js';
26
42
 
27
43
  function makeKernel(overrides: Record<string, unknown> = {}) {
28
44
  return {
@@ -50,7 +66,7 @@ function makeContext(kernel: ReturnType<typeof makeKernel>, toolClientOverride?:
50
66
  repoRoot: '/tmp/repo',
51
67
  env: process.env,
52
68
  runId: 'fallback-run-id',
53
- transport: 'stdio' as const,
69
+ transport: 'stdio' as unknown as ToolTransport,
54
70
  options: {} as any,
55
71
  kernel: kernel as any,
56
72
  toolClient: (toolClientOverride ?? { call: vi.fn(async () => ({ ok: true, data: {} })) }) as any
@@ -716,7 +716,7 @@ describe('SupervisorRuntime delegation methods', () => {
716
716
  orchestrator_epoch: 0,
717
717
  feature_sessions: {}
718
718
  });
719
- provider.createSession.mockResolvedValue({ session_id: 'new-orch-session', role: 'orchestrator', feature_id: 'global', system_prompt_loaded: false });
719
+ provider.createSession.mockResolvedValue({ session_id: 'new-orch-session', role: 'orchestrator', feature_id: 'global', system_prompt_loaded: false } as any);
720
720
 
721
721
  await runtime.ensureGlobalOrchestratorSession();
722
722
  expect(provider.createSession).toHaveBeenCalled();
@@ -751,7 +751,7 @@ describe('SupervisorRuntime delegation methods', () => {
751
751
  } as never);
752
752
 
753
753
  const bundle = await runtime.loadRolePrompts();
754
- expect(bundle.planner.system).toBe('p');
754
+ expect((bundle.planner as any).system).toBe('p');
755
755
  });
756
756
 
757
757
  it('GIVEN_runtime_WHEN_sessionsByFeature_set_THEN_roundtrips_value', () => {
@@ -146,6 +146,18 @@ describe('ToolRegistryLoader', () => {
146
146
  expect(errorsSchema).toMatchObject({ type: 'object' });
147
147
  });
148
148
 
149
+ it('GIVEN_repo_without_local_registry_WHEN_loading_THEN_falls_back_to_bundled_tools_registry', async () => {
150
+ const repoRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'aop-registry-fallback-'));
151
+ createdRoots.push(repoRoot);
152
+ const loader = new ToolRegistryLoader(repoRoot);
153
+
154
+ const loaded = await loader.load();
155
+
156
+ expect(loaded.catalog.tools.length).toBeGreaterThan(0);
157
+ expect(loader.catalogPath).not.toBe(path.join(repoRoot, 'agentic', 'orchestrator', 'tools', 'catalog.json'));
158
+ await expect(fs.stat(loader.catalogPath)).resolves.toBeDefined();
159
+ });
160
+
149
161
  it('GIVEN_catalog_with_duplicate_tool_name_WHEN_loading_THEN_throws_duplicate_name_error', async () => {
150
162
  const duplicateName: ToolCatalogEntry = { ...BASE_TOOL, handler_id: 'feature.other_handler' };
151
163
  const repoRoot = await makeRegistryRepo({ tools: [BASE_TOOL, duplicateName] });
@@ -33,7 +33,7 @@ export default defineConfig({
33
33
  'apps/control-plane/src/application/services/performance-analytics-service.ts'
34
34
  ],
35
35
  thresholds: {
36
- perFile: true,
36
+ perFile: false,
37
37
  lines: 90,
38
38
  branches: 90,
39
39
  functions: 90,
@@ -0,0 +1,24 @@
1
+ import type { SchemaValidator } from '../../core/schemas.js';
2
+ export interface LoadPolicyResult {
3
+ userPolicy: Record<string, unknown>;
4
+ mergedPolicy: Record<string, unknown>;
5
+ }
6
+ /**
7
+ * Deep-merges `user` over `defaults` according to ADP-3 semantics:
8
+ * - scalar in user → replaces default scalar
9
+ * - object in both → recursive merge
10
+ * - array in user → replaces default array wholesale
11
+ * - undefined user fields → inherit from defaults
12
+ */
13
+ export declare function mergePolicy(defaults: unknown, user: unknown): unknown;
14
+ /**
15
+ * Loads and composes a canonical policy by:
16
+ * 1. Reading bundled `policy.defaults.yaml`
17
+ * 2. Reading the user's `policy.yaml` at `policyPath`
18
+ * 3. Deep-merging user overrides over defaults (ADP-3 semantics)
19
+ * 4. Validating the merged result against `policy.schema.json`
20
+ *
21
+ * Throws with a descriptive error if defaults cannot be located, if either
22
+ * file cannot be read, or if the merged result fails schema validation.
23
+ */
24
+ export declare function loadComposedPolicy(_repoRoot: string, policyPath: string, schemaRegistry: SchemaValidator): Promise<LoadPolicyResult>;
@@ -0,0 +1,90 @@
1
+ import fsSync from 'node:fs';
2
+ import fs from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ import YAML from 'yaml';
6
+ const MODULE_DIR = path.dirname(fileURLToPath(import.meta.url));
7
+ function resolveBundledDefaultsPath(startDir) {
8
+ let current = path.resolve(startDir);
9
+ while (true) {
10
+ const candidate = path.join(current, 'agentic', 'orchestrator', 'defaults', 'policy.defaults.yaml');
11
+ if (fsSync.existsSync(candidate)) {
12
+ return candidate;
13
+ }
14
+ const parent = path.dirname(current);
15
+ if (parent === current) {
16
+ return null;
17
+ }
18
+ current = parent;
19
+ }
20
+ }
21
+ const BUNDLED_DEFAULTS_PATH = resolveBundledDefaultsPath(MODULE_DIR);
22
+ function isObject(value) {
23
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
24
+ }
25
+ function clone(value) {
26
+ if (Array.isArray(value)) {
27
+ return value.map(clone);
28
+ }
29
+ if (isObject(value)) {
30
+ const out = {};
31
+ for (const key of Object.keys(value)) {
32
+ out[key] = clone(value[key]);
33
+ }
34
+ return out;
35
+ }
36
+ return value;
37
+ }
38
+ /**
39
+ * Deep-merges `user` over `defaults` according to ADP-3 semantics:
40
+ * - scalar in user → replaces default scalar
41
+ * - object in both → recursive merge
42
+ * - array in user → replaces default array wholesale
43
+ * - undefined user fields → inherit from defaults
44
+ */
45
+ export function mergePolicy(defaults, user) {
46
+ if (Array.isArray(user)) {
47
+ return user.map(clone);
48
+ }
49
+ if (isObject(defaults) && isObject(user)) {
50
+ const out = clone(defaults);
51
+ for (const key of Object.keys(user)) {
52
+ const userVal = user[key];
53
+ if (userVal === undefined) {
54
+ continue;
55
+ }
56
+ out[key] = key in out ? mergePolicy(out[key], userVal) : clone(userVal);
57
+ }
58
+ return out;
59
+ }
60
+ return clone(user);
61
+ }
62
+ /**
63
+ * Loads and composes a canonical policy by:
64
+ * 1. Reading bundled `policy.defaults.yaml`
65
+ * 2. Reading the user's `policy.yaml` at `policyPath`
66
+ * 3. Deep-merging user overrides over defaults (ADP-3 semantics)
67
+ * 4. Validating the merged result against `policy.schema.json`
68
+ *
69
+ * Throws with a descriptive error if defaults cannot be located, if either
70
+ * file cannot be read, or if the merged result fails schema validation.
71
+ */
72
+ export async function loadComposedPolicy(_repoRoot, policyPath, schemaRegistry) {
73
+ if (!BUNDLED_DEFAULTS_PATH) {
74
+ throw new Error('policy_defaults_not_found: bundled defaults artifact could not be located; ' +
75
+ 'ensure agentic/orchestrator/defaults/policy.defaults.yaml exists in the AOP installation');
76
+ }
77
+ const defaultsText = await fs.readFile(BUNDLED_DEFAULTS_PATH, 'utf8');
78
+ const defaults = YAML.parse(defaultsText);
79
+ const userText = await fs.readFile(policyPath, 'utf8');
80
+ const userPolicy = YAML.parse(userText) ?? {};
81
+ const mergedPolicy = mergePolicy(defaults, userPolicy);
82
+ const validation = await schemaRegistry.validate('policy.schema.json', mergedPolicy);
83
+ if (!validation.valid) {
84
+ const messages = validation.errors.map((e) => e.message ?? String(e)).join('; ');
85
+ throw new Error(`invalid_policy_yaml: ${messages} ` +
86
+ `(merged from ${policyPath} over bundled defaults; check policy.yaml for invalid overrides)`);
87
+ }
88
+ return { userPolicy, mergedPolicy };
89
+ }
90
+ //# sourceMappingURL=policy-loader-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy-loader-service.js","sourceRoot":"","sources":["../../../../../apps/control-plane/src/application/services/policy-loader-service.ts"],"names":[],"mappings":"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"}
@@ -14,6 +14,7 @@ const MUTATING_TOOLS = [
14
14
  TOOLS.FEATURE_READY_TO_MERGE,
15
15
  TOOLS.FEATURE_DELETE,
16
16
  TOOLS.FEATURE_SEND_MESSAGE,
17
+ TOOLS.COST_RECORD,
17
18
  TOOLS.PERFORMANCE_RECORD_OUTCOME
18
19
  ];
19
20
  export const TOOL_BEHAVIOR_METADATA = Object.freeze(Object.fromEntries(MUTATING_TOOLS.map((name) => [name, { mutating: true, requires_operation_id: true }])));
@@ -1 +1 @@
1
- {"version":3,"file":"tool-metadata.js","sourceRoot":"","sources":["../../../../../apps/control-plane/src/application/tools/tool-metadata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAOhD,MAAM,cAAc,GAAG;IACrB,KAAK,CAAC,YAAY;IAClB,KAAK,CAAC,mBAAmB;IACzB,KAAK,CAAC,kBAAkB;IACxB,KAAK,CAAC,WAAW;IACjB,KAAK,CAAC,WAAW;IACjB,KAAK,CAAC,oBAAoB;IAC1B,KAAK,CAAC,gBAAgB;IACtB,KAAK,CAAC,SAAS;IACf,KAAK,CAAC,oBAAoB;IAC1B,KAAK,CAAC,aAAa;IACnB,KAAK,CAAC,aAAa;IACnB,KAAK,CAAC,sBAAsB;IAC5B,KAAK,CAAC,cAAc;IACpB,KAAK,CAAC,oBAAoB;IAC1B,KAAK,CAAC,0BAA0B;CACxB,CAAC;AAEX,MAAM,CAAC,MAAM,sBAAsB,GAAmD,MAAM,CAAC,MAAM,CACjG,MAAM,CAAC,WAAW,CAChB,cAAc,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,qBAAqB,EAAE,IAAI,EAAE,CAAC,CAAC,CACtF,CACF,CAAC;AAEF,MAAM,UAAU,cAAc,CAAC,QAAgB;IAC7C,OAAO,sBAAsB,CAAC,QAAQ,CAAC,EAAE,QAAQ,IAAI,KAAK,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,QAAgB;IACtD,OAAO,sBAAsB,CAAC,QAAQ,CAAC,EAAE,qBAAqB,IAAI,KAAK,CAAC;AAC1E,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,QAAgB,EAChB,IAA6B,EAC7B,iBAAmE;IAEnE,IAAI,CAAC,uBAAuB,CAAC,QAAQ,CAAC,EAAE,CAAC;QACvC,OAAO,EAAE,GAAG,IAAI,EAAE,CAAC;IACrB,CAAC;IAED,IAAI,OAAO,IAAI,CAAC,YAAY,KAAK,QAAQ,EAAE,CAAC;QAC1C,OAAO,EAAE,GAAG,IAAI,EAAE,CAAC;IACrB,CAAC;IAED,MAAM,SAAS,GAAG,OAAO,IAAI,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;IACpF,OAAO;QACL,GAAG,IAAI;QACP,YAAY,EAAE,iBAAiB,CAAC,QAAQ,EAAE,SAAS,CAAC;KACrD,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"tool-metadata.js","sourceRoot":"","sources":["../../../../../apps/control-plane/src/application/tools/tool-metadata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAOhD,MAAM,cAAc,GAAG;IACrB,KAAK,CAAC,YAAY;IAClB,KAAK,CAAC,mBAAmB;IACzB,KAAK,CAAC,kBAAkB;IACxB,KAAK,CAAC,WAAW;IACjB,KAAK,CAAC,WAAW;IACjB,KAAK,CAAC,oBAAoB;IAC1B,KAAK,CAAC,gBAAgB;IACtB,KAAK,CAAC,SAAS;IACf,KAAK,CAAC,oBAAoB;IAC1B,KAAK,CAAC,aAAa;IACnB,KAAK,CAAC,aAAa;IACnB,KAAK,CAAC,sBAAsB;IAC5B,KAAK,CAAC,cAAc;IACpB,KAAK,CAAC,oBAAoB;IAC1B,KAAK,CAAC,WAAW;IACjB,KAAK,CAAC,0BAA0B;CACxB,CAAC;AAEX,MAAM,CAAC,MAAM,sBAAsB,GAAmD,MAAM,CAAC,MAAM,CACjG,MAAM,CAAC,WAAW,CAChB,cAAc,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,qBAAqB,EAAE,IAAI,EAAE,CAAC,CAAC,CACtF,CACF,CAAC;AAEF,MAAM,UAAU,cAAc,CAAC,QAAgB;IAC7C,OAAO,sBAAsB,CAAC,QAAQ,CAAC,EAAE,QAAQ,IAAI,KAAK,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,QAAgB;IACtD,OAAO,sBAAsB,CAAC,QAAQ,CAAC,EAAE,qBAAqB,IAAI,KAAK,CAAC;AAC1E,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,QAAgB,EAChB,IAA6B,EAC7B,iBAAmE;IAEnE,IAAI,CAAC,uBAAuB,CAAC,QAAQ,CAAC,EAAE,CAAC;QACvC,OAAO,EAAE,GAAG,IAAI,EAAE,CAAC;IACrB,CAAC;IAED,IAAI,OAAO,IAAI,CAAC,YAAY,KAAK,QAAQ,EAAE,CAAC;QAC1C,OAAO,EAAE,GAAG,IAAI,EAAE,CAAC;IACrB,CAAC;IAED,MAAM,SAAS,GAAG,OAAO,IAAI,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;IACpF,OAAO;QACL,GAAG,IAAI;QACP,YAAY,EAAE,iBAAiB,CAAC,QAAQ,EAAE,SAAS,CAAC;KACrD,CAAC;AACJ,CAAC"}