@the-open-engine/zeroshot 5.4.0

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 (295) hide show
  1. package/CHANGELOG.md +539 -0
  2. package/LICENSE +21 -0
  3. package/README.md +508 -0
  4. package/cli/commands/inspect-render.js +135 -0
  5. package/cli/commands/inspect.js +294 -0
  6. package/cli/commands/providers.js +149 -0
  7. package/cli/index.js +5431 -0
  8. package/cli/lib/first-run.js +211 -0
  9. package/cli/lib/update-checker.js +281 -0
  10. package/cli/message-formatter-utils.js +75 -0
  11. package/cli/message-formatters-normal.js +275 -0
  12. package/cli/message-formatters-watch.js +185 -0
  13. package/cluster-templates/base-templates/debug-workflow.json +422 -0
  14. package/cluster-templates/base-templates/full-workflow.json +727 -0
  15. package/cluster-templates/base-templates/heavy-validation.json +272 -0
  16. package/cluster-templates/base-templates/quick-validation.json +285 -0
  17. package/cluster-templates/base-templates/single-worker.json +71 -0
  18. package/cluster-templates/base-templates/worker-validator.json +230 -0
  19. package/cluster-templates/conductor-bootstrap.json +130 -0
  20. package/docker/zeroshot-cluster/Dockerfile +153 -0
  21. package/docker/zeroshot-cluster/pre-baked-deps.json +28 -0
  22. package/lib/agent-cli-provider/adapters/claude-parser.d.ts +3 -0
  23. package/lib/agent-cli-provider/adapters/claude-parser.d.ts.map +1 -0
  24. package/lib/agent-cli-provider/adapters/claude-parser.js +122 -0
  25. package/lib/agent-cli-provider/adapters/claude-parser.js.map +1 -0
  26. package/lib/agent-cli-provider/adapters/claude-recovery.d.ts +15 -0
  27. package/lib/agent-cli-provider/adapters/claude-recovery.d.ts.map +1 -0
  28. package/lib/agent-cli-provider/adapters/claude-recovery.js +165 -0
  29. package/lib/agent-cli-provider/adapters/claude-recovery.js.map +1 -0
  30. package/lib/agent-cli-provider/adapters/claude.d.ts +3 -0
  31. package/lib/agent-cli-provider/adapters/claude.d.ts.map +1 -0
  32. package/lib/agent-cli-provider/adapters/claude.js +181 -0
  33. package/lib/agent-cli-provider/adapters/claude.js.map +1 -0
  34. package/lib/agent-cli-provider/adapters/codex-parser.d.ts +3 -0
  35. package/lib/agent-cli-provider/adapters/codex-parser.d.ts.map +1 -0
  36. package/lib/agent-cli-provider/adapters/codex-parser.js +192 -0
  37. package/lib/agent-cli-provider/adapters/codex-parser.js.map +1 -0
  38. package/lib/agent-cli-provider/adapters/codex.d.ts +3 -0
  39. package/lib/agent-cli-provider/adapters/codex.d.ts.map +1 -0
  40. package/lib/agent-cli-provider/adapters/codex.js +151 -0
  41. package/lib/agent-cli-provider/adapters/codex.js.map +1 -0
  42. package/lib/agent-cli-provider/adapters/common.d.ts +28 -0
  43. package/lib/agent-cli-provider/adapters/common.d.ts.map +1 -0
  44. package/lib/agent-cli-provider/adapters/common.js +71 -0
  45. package/lib/agent-cli-provider/adapters/common.js.map +1 -0
  46. package/lib/agent-cli-provider/adapters/gemini.d.ts +3 -0
  47. package/lib/agent-cli-provider/adapters/gemini.d.ts.map +1 -0
  48. package/lib/agent-cli-provider/adapters/gemini.js +176 -0
  49. package/lib/agent-cli-provider/adapters/gemini.js.map +1 -0
  50. package/lib/agent-cli-provider/adapters/index.d.ts +9 -0
  51. package/lib/agent-cli-provider/adapters/index.d.ts.map +1 -0
  52. package/lib/agent-cli-provider/adapters/index.js +95 -0
  53. package/lib/agent-cli-provider/adapters/index.js.map +1 -0
  54. package/lib/agent-cli-provider/adapters/opencode.d.ts +3 -0
  55. package/lib/agent-cli-provider/adapters/opencode.d.ts.map +1 -0
  56. package/lib/agent-cli-provider/adapters/opencode.js +228 -0
  57. package/lib/agent-cli-provider/adapters/opencode.js.map +1 -0
  58. package/lib/agent-cli-provider/contract-actions.d.ts +5 -0
  59. package/lib/agent-cli-provider/contract-actions.d.ts.map +1 -0
  60. package/lib/agent-cli-provider/contract-actions.js +140 -0
  61. package/lib/agent-cli-provider/contract-actions.js.map +1 -0
  62. package/lib/agent-cli-provider/contract-env.d.ts +11 -0
  63. package/lib/agent-cli-provider/contract-env.d.ts.map +1 -0
  64. package/lib/agent-cli-provider/contract-env.js +113 -0
  65. package/lib/agent-cli-provider/contract-env.js.map +1 -0
  66. package/lib/agent-cli-provider/contract-envelope.d.ts +49 -0
  67. package/lib/agent-cli-provider/contract-envelope.d.ts.map +1 -0
  68. package/lib/agent-cli-provider/contract-envelope.js +52 -0
  69. package/lib/agent-cli-provider/contract-envelope.js.map +1 -0
  70. package/lib/agent-cli-provider/contract-errors.d.ts +22 -0
  71. package/lib/agent-cli-provider/contract-errors.d.ts.map +1 -0
  72. package/lib/agent-cli-provider/contract-errors.js +71 -0
  73. package/lib/agent-cli-provider/contract-errors.js.map +1 -0
  74. package/lib/agent-cli-provider/contract-fallback.d.ts +7 -0
  75. package/lib/agent-cli-provider/contract-fallback.d.ts.map +1 -0
  76. package/lib/agent-cli-provider/contract-fallback.js +102 -0
  77. package/lib/agent-cli-provider/contract-fallback.js.map +1 -0
  78. package/lib/agent-cli-provider/contract-invoke.d.ts +5 -0
  79. package/lib/agent-cli-provider/contract-invoke.d.ts.map +1 -0
  80. package/lib/agent-cli-provider/contract-invoke.js +89 -0
  81. package/lib/agent-cli-provider/contract-invoke.js.map +1 -0
  82. package/lib/agent-cli-provider/contract-options.d.ts +3 -0
  83. package/lib/agent-cli-provider/contract-options.d.ts.map +1 -0
  84. package/lib/agent-cli-provider/contract-options.js +140 -0
  85. package/lib/agent-cli-provider/contract-options.js.map +1 -0
  86. package/lib/agent-cli-provider/contract-parse.d.ts +15 -0
  87. package/lib/agent-cli-provider/contract-parse.d.ts.map +1 -0
  88. package/lib/agent-cli-provider/contract-parse.js +81 -0
  89. package/lib/agent-cli-provider/contract-parse.js.map +1 -0
  90. package/lib/agent-cli-provider/contract-support.d.ts +18 -0
  91. package/lib/agent-cli-provider/contract-support.d.ts.map +1 -0
  92. package/lib/agent-cli-provider/contract-support.js +154 -0
  93. package/lib/agent-cli-provider/contract-support.js.map +1 -0
  94. package/lib/agent-cli-provider/contract.d.ts +13 -0
  95. package/lib/agent-cli-provider/contract.d.ts.map +1 -0
  96. package/lib/agent-cli-provider/contract.js +30 -0
  97. package/lib/agent-cli-provider/contract.js.map +1 -0
  98. package/lib/agent-cli-provider/env-safety.d.ts +11 -0
  99. package/lib/agent-cli-provider/env-safety.d.ts.map +1 -0
  100. package/lib/agent-cli-provider/env-safety.js +83 -0
  101. package/lib/agent-cli-provider/env-safety.js.map +1 -0
  102. package/lib/agent-cli-provider/errors.d.ts +5 -0
  103. package/lib/agent-cli-provider/errors.d.ts.map +1 -0
  104. package/lib/agent-cli-provider/errors.js +115 -0
  105. package/lib/agent-cli-provider/errors.js.map +1 -0
  106. package/lib/agent-cli-provider/executable.d.ts +3 -0
  107. package/lib/agent-cli-provider/executable.d.ts.map +1 -0
  108. package/lib/agent-cli-provider/executable.js +24 -0
  109. package/lib/agent-cli-provider/executable.js.map +1 -0
  110. package/lib/agent-cli-provider/index.d.ts +8 -0
  111. package/lib/agent-cli-provider/index.d.ts.map +1 -0
  112. package/lib/agent-cli-provider/index.js +31 -0
  113. package/lib/agent-cli-provider/index.js.map +1 -0
  114. package/lib/agent-cli-provider/invoke-evidence.d.ts +4 -0
  115. package/lib/agent-cli-provider/invoke-evidence.d.ts.map +1 -0
  116. package/lib/agent-cli-provider/invoke-evidence.js +17 -0
  117. package/lib/agent-cli-provider/invoke-evidence.js.map +1 -0
  118. package/lib/agent-cli-provider/json.d.ts +16 -0
  119. package/lib/agent-cli-provider/json.d.ts.map +1 -0
  120. package/lib/agent-cli-provider/json.js +110 -0
  121. package/lib/agent-cli-provider/json.js.map +1 -0
  122. package/lib/agent-cli-provider/log-prefix.d.ts +2 -0
  123. package/lib/agent-cli-provider/log-prefix.d.ts.map +1 -0
  124. package/lib/agent-cli-provider/log-prefix.js +22 -0
  125. package/lib/agent-cli-provider/log-prefix.js.map +1 -0
  126. package/lib/agent-cli-provider/process-runner.d.ts +17 -0
  127. package/lib/agent-cli-provider/process-runner.d.ts.map +1 -0
  128. package/lib/agent-cli-provider/process-runner.js +89 -0
  129. package/lib/agent-cli-provider/process-runner.js.map +1 -0
  130. package/lib/agent-cli-provider/redaction.d.ts +9 -0
  131. package/lib/agent-cli-provider/redaction.d.ts.map +1 -0
  132. package/lib/agent-cli-provider/redaction.js +227 -0
  133. package/lib/agent-cli-provider/redaction.js.map +1 -0
  134. package/lib/agent-cli-provider/schema.d.ts +5 -0
  135. package/lib/agent-cli-provider/schema.d.ts.map +1 -0
  136. package/lib/agent-cli-provider/schema.js +136 -0
  137. package/lib/agent-cli-provider/schema.js.map +1 -0
  138. package/lib/agent-cli-provider/single-agent-runtime.d.ts +15 -0
  139. package/lib/agent-cli-provider/single-agent-runtime.d.ts.map +1 -0
  140. package/lib/agent-cli-provider/single-agent-runtime.js +228 -0
  141. package/lib/agent-cli-provider/single-agent-runtime.js.map +1 -0
  142. package/lib/agent-cli-provider/types.d.ts +194 -0
  143. package/lib/agent-cli-provider/types.d.ts.map +1 -0
  144. package/lib/agent-cli-provider/types.js +12 -0
  145. package/lib/agent-cli-provider/types.js.map +1 -0
  146. package/lib/completion.js +174 -0
  147. package/lib/detached-startup.js +220 -0
  148. package/lib/docker-config.js +220 -0
  149. package/lib/git-remote-utils.js +165 -0
  150. package/lib/id-detector.js +55 -0
  151. package/lib/provider-defaults.js +62 -0
  152. package/lib/provider-detection.js +59 -0
  153. package/lib/provider-names.js +57 -0
  154. package/lib/repo-settings.js +69 -0
  155. package/lib/settings/claude-auth.js +78 -0
  156. package/lib/settings.js +542 -0
  157. package/lib/start-cluster.js +321 -0
  158. package/lib/stream-json-parser.js +67 -0
  159. package/package.json +162 -0
  160. package/scripts/fix-node-pty-permissions.js +75 -0
  161. package/scripts/record-demo.sh +279 -0
  162. package/scripts/setup-merge-queue.sh +170 -0
  163. package/scripts/test-install.sh +40 -0
  164. package/scripts/validate-templates.js +107 -0
  165. package/src/agent/agent-config.js +266 -0
  166. package/src/agent/agent-context-builder.js +189 -0
  167. package/src/agent/agent-context-sections.js +338 -0
  168. package/src/agent/agent-context-sources.js +147 -0
  169. package/src/agent/agent-hook-executor.js +721 -0
  170. package/src/agent/agent-input-injector.js +141 -0
  171. package/src/agent/agent-lifecycle.js +982 -0
  172. package/src/agent/agent-quality-gate-schema.js +93 -0
  173. package/src/agent/agent-quality-gates-context.js +51 -0
  174. package/src/agent/agent-stuck-detector.js +256 -0
  175. package/src/agent/agent-task-executor.js +2028 -0
  176. package/src/agent/agent-trigger-evaluator.js +67 -0
  177. package/src/agent/context-metrics.js +160 -0
  178. package/src/agent/context-pack-builder.js +367 -0
  179. package/src/agent/context-replay-policy.js +51 -0
  180. package/src/agent/guidance-queue.js +77 -0
  181. package/src/agent/output-extraction.js +367 -0
  182. package/src/agent/output-reformatter.js +175 -0
  183. package/src/agent/pr-verification.js +653 -0
  184. package/src/agent/rate-limit-backoff.js +82 -0
  185. package/src/agent/schema-utils.js +146 -0
  186. package/src/agent/validation-platform.js +35 -0
  187. package/src/agent-cli-provider/adapters/claude-parser.ts +133 -0
  188. package/src/agent-cli-provider/adapters/claude-recovery.ts +203 -0
  189. package/src/agent-cli-provider/adapters/claude.ts +247 -0
  190. package/src/agent-cli-provider/adapters/codex-parser.ts +211 -0
  191. package/src/agent-cli-provider/adapters/codex.ts +217 -0
  192. package/src/agent-cli-provider/adapters/common.ts +124 -0
  193. package/src/agent-cli-provider/adapters/gemini.ts +243 -0
  194. package/src/agent-cli-provider/adapters/index.ts +126 -0
  195. package/src/agent-cli-provider/adapters/opencode.ts +286 -0
  196. package/src/agent-cli-provider/contract-actions.ts +150 -0
  197. package/src/agent-cli-provider/contract-env.ts +111 -0
  198. package/src/agent-cli-provider/contract-envelope.ts +110 -0
  199. package/src/agent-cli-provider/contract-errors.ts +66 -0
  200. package/src/agent-cli-provider/contract-fallback.ts +121 -0
  201. package/src/agent-cli-provider/contract-invoke.ts +104 -0
  202. package/src/agent-cli-provider/contract-options.ts +173 -0
  203. package/src/agent-cli-provider/contract-parse.ts +94 -0
  204. package/src/agent-cli-provider/contract-support.ts +167 -0
  205. package/src/agent-cli-provider/contract.ts +56 -0
  206. package/src/agent-cli-provider/env-safety.ts +82 -0
  207. package/src/agent-cli-provider/errors.ts +122 -0
  208. package/src/agent-cli-provider/executable.ts +24 -0
  209. package/src/agent-cli-provider/index.ts +83 -0
  210. package/src/agent-cli-provider/invoke-evidence.ts +18 -0
  211. package/src/agent-cli-provider/json.ts +114 -0
  212. package/src/agent-cli-provider/log-prefix.ts +20 -0
  213. package/src/agent-cli-provider/process-runner.ts +145 -0
  214. package/src/agent-cli-provider/redaction.ts +282 -0
  215. package/src/agent-cli-provider/schema.ts +115 -0
  216. package/src/agent-cli-provider/single-agent-runtime.ts +311 -0
  217. package/src/agent-cli-provider/types.ts +237 -0
  218. package/src/agent-wrapper.js +615 -0
  219. package/src/agents/git-pusher-template.js +705 -0
  220. package/src/attach/attach-client.js +438 -0
  221. package/src/attach/attach-server.js +543 -0
  222. package/src/attach/index.js +37 -0
  223. package/src/attach/protocol.js +220 -0
  224. package/src/attach/ring-buffer.js +121 -0
  225. package/src/attach/send-input.js +88 -0
  226. package/src/attach/socket-discovery.js +267 -0
  227. package/src/claude-task-runner.js +661 -0
  228. package/src/config-router.js +89 -0
  229. package/src/config-validator.js +2202 -0
  230. package/src/copy-worker.js +43 -0
  231. package/src/guidance-topics.js +10 -0
  232. package/src/input-helpers.js +65 -0
  233. package/src/isolation-manager.js +1734 -0
  234. package/src/issue-providers/README.md +305 -0
  235. package/src/issue-providers/azure-devops-provider.js +307 -0
  236. package/src/issue-providers/base-provider.js +232 -0
  237. package/src/issue-providers/github-provider.js +210 -0
  238. package/src/issue-providers/gitlab-provider.js +262 -0
  239. package/src/issue-providers/index.js +196 -0
  240. package/src/issue-providers/jira-provider.js +260 -0
  241. package/src/ledger.js +692 -0
  242. package/src/lib/gc.js +232 -0
  243. package/src/lib/safe-exec.js +88 -0
  244. package/src/logic-engine.js +201 -0
  245. package/src/message-buffer.js +81 -0
  246. package/src/message-bus-bridge.js +144 -0
  247. package/src/message-bus.js +256 -0
  248. package/src/name-generator.js +232 -0
  249. package/src/orchestrator.js +3924 -0
  250. package/src/preflight.js +712 -0
  251. package/src/process-metrics.js +608 -0
  252. package/src/providers/anthropic/index.js +3 -0
  253. package/src/providers/base-provider.js +355 -0
  254. package/src/providers/capabilities.js +60 -0
  255. package/src/providers/google/index.js +3 -0
  256. package/src/providers/index.js +293 -0
  257. package/src/providers/openai/index.js +3 -0
  258. package/src/providers/opencode/index.js +3 -0
  259. package/src/quality-gates.js +143 -0
  260. package/src/schemas/sub-cluster.js +208 -0
  261. package/src/state-snapshot.js +398 -0
  262. package/src/state-snapshotter.js +142 -0
  263. package/src/status-footer.js +1026 -0
  264. package/src/sub-cluster-wrapper.js +693 -0
  265. package/src/task-runner.js +30 -0
  266. package/src/template-resolver.js +425 -0
  267. package/src/template-validation/index.js +338 -0
  268. package/src/template-validation/simulate-consensus-gates.js +324 -0
  269. package/src/template-validation/simulate-random-topology.js +541 -0
  270. package/src/template-validation/simulate-two-stage-validation.js +270 -0
  271. package/src/worktree-claude-config.js +135 -0
  272. package/src/worktree-tooling-env.js +150 -0
  273. package/task-lib/attachable-watcher.js +381 -0
  274. package/task-lib/commands/clean.js +50 -0
  275. package/task-lib/commands/episodes.js +105 -0
  276. package/task-lib/commands/get-log-path.js +23 -0
  277. package/task-lib/commands/kill.js +32 -0
  278. package/task-lib/commands/list.js +105 -0
  279. package/task-lib/commands/logs.js +439 -0
  280. package/task-lib/commands/resume.js +42 -0
  281. package/task-lib/commands/run.js +57 -0
  282. package/task-lib/commands/schedule.js +105 -0
  283. package/task-lib/commands/scheduler-cmd.js +96 -0
  284. package/task-lib/commands/schedules.js +148 -0
  285. package/task-lib/commands/status.js +44 -0
  286. package/task-lib/commands/unschedule.js +16 -0
  287. package/task-lib/completion.js +9 -0
  288. package/task-lib/config.js +11 -0
  289. package/task-lib/name-generator.js +230 -0
  290. package/task-lib/package.json +3 -0
  291. package/task-lib/provider-helper-runtime.js +29 -0
  292. package/task-lib/runner.js +190 -0
  293. package/task-lib/scheduler.js +252 -0
  294. package/task-lib/store.js +529 -0
  295. package/task-lib/watcher.js +305 -0
@@ -0,0 +1,3 @@
1
+ const { createProviderClass } = require('..');
2
+
3
+ module.exports = createProviderClass('opencode');
@@ -0,0 +1,143 @@
1
+ const { readRepoSettings } = require('../lib/repo-settings');
2
+
3
+ function hasOwn(value, key) {
4
+ return Object.prototype.hasOwnProperty.call(value || {}, key);
5
+ }
6
+
7
+ function hasDefinedOwn(value, key) {
8
+ return hasOwn(value, key) && value[key] !== undefined;
9
+ }
10
+
11
+ function getGateId(gate) {
12
+ if (typeof gate.id === 'string' && gate.id.trim()) {
13
+ return gate.id.trim();
14
+ }
15
+
16
+ if (typeof gate.name === 'string' && gate.name.trim()) {
17
+ return gate.name.trim();
18
+ }
19
+
20
+ return null;
21
+ }
22
+
23
+ function normalizeStringGate(gate) {
24
+ const id = gate.trim();
25
+ return id ? { id } : null;
26
+ }
27
+
28
+ function setOptionalString(target, source, key) {
29
+ if (typeof source[key] === 'string' && source[key].trim()) {
30
+ target[key] = source[key].trim();
31
+ }
32
+ }
33
+
34
+ function normalizeObjectGate(gate) {
35
+ if (!gate || typeof gate !== 'object') {
36
+ return null;
37
+ }
38
+
39
+ const id = getGateId(gate);
40
+ if (!id) {
41
+ return null;
42
+ }
43
+
44
+ const normalized = { id };
45
+ setOptionalString(normalized, gate, 'scope');
46
+ setOptionalString(normalized, gate, 'description');
47
+ setOptionalString(normalized, gate, 'command');
48
+ return normalized;
49
+ }
50
+
51
+ function normalizeRequiredQualityGates(value) {
52
+ if (!Array.isArray(value)) {
53
+ return [];
54
+ }
55
+
56
+ return value
57
+ .map((gate) => {
58
+ if (typeof gate === 'string') {
59
+ return normalizeStringGate(gate);
60
+ }
61
+ return normalizeObjectGate(gate);
62
+ })
63
+ .filter(Boolean);
64
+ }
65
+
66
+ function getRequiredQualityGateSource(options, repoSettings) {
67
+ if (hasDefinedOwn(options, 'requiredQualityGates')) {
68
+ return options.requiredQualityGates;
69
+ }
70
+
71
+ if (
72
+ options.ship &&
73
+ typeof options.ship === 'object' &&
74
+ hasDefinedOwn(options.ship, 'requiredQualityGates')
75
+ ) {
76
+ return options.ship.requiredQualityGates;
77
+ }
78
+
79
+ const settingsShip = repoSettings?.ship;
80
+ if (
81
+ settingsShip &&
82
+ typeof settingsShip === 'object' &&
83
+ hasOwn(settingsShip, 'requiredQualityGates')
84
+ ) {
85
+ return settingsShip.requiredQualityGates;
86
+ }
87
+
88
+ if (hasOwn(repoSettings, 'requiredQualityGates')) {
89
+ return repoSettings.requiredQualityGates;
90
+ }
91
+
92
+ return [];
93
+ }
94
+
95
+ function resolveRequiredQualityGates(options = {}) {
96
+ const repoSettingsResult = readRepoSettings(options.cwd || process.cwd());
97
+ const repoSettings = repoSettingsResult.settings || {};
98
+ const source = getRequiredQualityGateSource(options, repoSettings);
99
+ return normalizeRequiredQualityGates(source);
100
+ }
101
+
102
+ function getClusterRequiredQualityGateSource(config, options) {
103
+ if (hasDefinedOwn(options, 'requiredQualityGates')) {
104
+ return options.requiredQualityGates;
105
+ }
106
+
107
+ if (
108
+ options.ship &&
109
+ typeof options.ship === 'object' &&
110
+ hasDefinedOwn(options.ship, 'requiredQualityGates')
111
+ ) {
112
+ return options.ship.requiredQualityGates;
113
+ }
114
+
115
+ if (
116
+ config?.ship &&
117
+ typeof config.ship === 'object' &&
118
+ hasDefinedOwn(config.ship, 'requiredQualityGates')
119
+ ) {
120
+ return config.ship.requiredQualityGates;
121
+ }
122
+
123
+ if (hasDefinedOwn(config, 'requiredQualityGates')) {
124
+ return config.requiredQualityGates;
125
+ }
126
+
127
+ return undefined;
128
+ }
129
+
130
+ function resolveClusterRequiredQualityGates(config = {}, options = {}) {
131
+ const configuredSource = getClusterRequiredQualityGateSource(config, options);
132
+ if (configuredSource !== undefined) {
133
+ return normalizeRequiredQualityGates(configuredSource);
134
+ }
135
+
136
+ return resolveRequiredQualityGates({ ...options, cwd: options.cwd || process.cwd() });
137
+ }
138
+
139
+ module.exports = {
140
+ normalizeRequiredQualityGates,
141
+ resolveRequiredQualityGates,
142
+ resolveClusterRequiredQualityGates,
143
+ };
@@ -0,0 +1,208 @@
1
+ /**
2
+ * Sub-Cluster Schema
3
+ *
4
+ * Defines the structure for nested clusters where an agent can be replaced
5
+ * with an entire cluster configuration, enabling recursive composition.
6
+ *
7
+ * Example:
8
+ * {
9
+ * "id": "implementation-cluster",
10
+ * "type": "subcluster",
11
+ * "config": {
12
+ * "agents": [
13
+ * { "id": "worker", "role": "implementation", ... },
14
+ * { "id": "validator", "role": "validator", ... }
15
+ * ]
16
+ * },
17
+ * "triggers": [{ "topic": "PLAN_READY" }],
18
+ * "hooks": {
19
+ * "onComplete": {
20
+ * "action": "publish_message",
21
+ * "config": { "topic": "IMPLEMENTATION_COMPLETE" }
22
+ * }
23
+ * }
24
+ * }
25
+ */
26
+
27
+ /**
28
+ * Validate sub-cluster agent configuration
29
+ * @param {Object} agentConfig - Agent config with type: 'subcluster'
30
+ * @param {Number} depth - Current nesting depth (for recursion limit)
31
+ * @returns {{ valid: boolean, errors: string[], warnings: string[] }}
32
+ */
33
+ const MAX_SUBCLUSTER_DEPTH = 5;
34
+
35
+ function validateSubCluster(agentConfig, depth = 0) {
36
+ const errors = [];
37
+ const warnings = [];
38
+
39
+ // Max nesting depth to prevent infinite recursion
40
+ if (depth > MAX_SUBCLUSTER_DEPTH) {
41
+ errors.push(
42
+ `Sub-cluster '${agentConfig.id}' exceeds max nesting depth (${MAX_SUBCLUSTER_DEPTH})`
43
+ );
44
+ return buildValidationResult(errors, warnings);
45
+ }
46
+
47
+ // Validate required fields
48
+ if (agentConfig.type !== 'subcluster') {
49
+ errors.push(`Agent '${agentConfig.id}' must have type: 'subcluster'`);
50
+ }
51
+
52
+ if (!validateSubClusterConfig(agentConfig, depth, errors, warnings)) {
53
+ return buildValidationResult(errors, warnings);
54
+ }
55
+
56
+ // Validate triggers (sub-cluster must have triggers to activate)
57
+ validateSubClusterTriggers(agentConfig, errors);
58
+
59
+ // Validate hooks structure
60
+ validateSubClusterHooks(agentConfig, errors);
61
+
62
+ // Check for context bridging configuration
63
+ validateContextStrategy(agentConfig, errors);
64
+
65
+ return buildValidationResult(errors, warnings);
66
+ }
67
+
68
+ function buildValidationResult(errors, warnings) {
69
+ return {
70
+ valid: errors.length === 0,
71
+ errors,
72
+ warnings,
73
+ };
74
+ }
75
+
76
+ function validateSubClusterConfig(agentConfig, depth, errors, warnings) {
77
+ if (!agentConfig.config) {
78
+ errors.push(`Sub-cluster '${agentConfig.id}' missing config field`);
79
+ return false;
80
+ }
81
+
82
+ if (!agentConfig.config.agents || !Array.isArray(agentConfig.config.agents)) {
83
+ errors.push(`Sub-cluster '${agentConfig.id}' config.agents must be an array`);
84
+ return false;
85
+ }
86
+
87
+ if (agentConfig.config.agents.length === 0) {
88
+ errors.push(`Sub-cluster '${agentConfig.id}' config.agents cannot be empty`);
89
+ return false;
90
+ }
91
+
92
+ // Recursively validate nested cluster config
93
+ const configValidator = require('../config-validator');
94
+ const childValidation = configValidator.validateConfig(agentConfig.config, depth + 1);
95
+
96
+ if (!childValidation.valid) {
97
+ errors.push(...childValidation.errors.map((e) => `Sub-cluster '${agentConfig.id}': ${e}`));
98
+ }
99
+
100
+ warnings.push(...childValidation.warnings.map((w) => `Sub-cluster '${agentConfig.id}': ${w}`));
101
+ return true;
102
+ }
103
+
104
+ function validateSubClusterTriggers(agentConfig, errors) {
105
+ if (!agentConfig.triggers || agentConfig.triggers.length === 0) {
106
+ errors.push(`Sub-cluster '${agentConfig.id}' must have triggers to activate`);
107
+ }
108
+ }
109
+
110
+ function validateSubClusterHooks(agentConfig, errors) {
111
+ if (!agentConfig.hooks?.onComplete) {
112
+ return;
113
+ }
114
+
115
+ const hook = agentConfig.hooks.onComplete;
116
+ if (!hook.action) {
117
+ errors.push(`Sub-cluster '${agentConfig.id}' onComplete hook missing action`);
118
+ }
119
+ if (hook.action === 'publish_message' && !hook.config?.topic) {
120
+ errors.push(`Sub-cluster '${agentConfig.id}' onComplete hook missing config.topic`);
121
+ }
122
+ }
123
+
124
+ function validateContextStrategy(agentConfig, errors) {
125
+ const parentTopics = agentConfig.contextStrategy?.parentTopics;
126
+ if (!parentTopics) {
127
+ return;
128
+ }
129
+
130
+ if (!Array.isArray(parentTopics)) {
131
+ errors.push(`Sub-cluster '${agentConfig.id}' contextStrategy.parentTopics must be an array`);
132
+ return;
133
+ }
134
+
135
+ // Validate each parent topic entry
136
+ for (const entry of parentTopics) {
137
+ if (typeof entry === 'string') {
138
+ continue;
139
+ }
140
+
141
+ if (!entry || typeof entry !== 'object') {
142
+ errors.push(
143
+ `Sub-cluster '${agentConfig.id}' parentTopics must contain strings or objects, got ${typeof entry}`
144
+ );
145
+ continue;
146
+ }
147
+
148
+ if (typeof entry.topic !== 'string') {
149
+ errors.push(`Sub-cluster '${agentConfig.id}' parentTopics entry must include a string topic`);
150
+ }
151
+
152
+ if (entry.strategy && !['latest', 'all', 'oldest'].includes(entry.strategy)) {
153
+ errors.push(
154
+ `Sub-cluster '${agentConfig.id}' parentTopics entry has invalid strategy '${entry.strategy}'`
155
+ );
156
+ }
157
+
158
+ if (entry.amount !== undefined && !Number.isFinite(entry.amount)) {
159
+ errors.push(`Sub-cluster '${agentConfig.id}' parentTopics entry amount must be a number`);
160
+ }
161
+
162
+ if (entry.limit !== undefined && !Number.isFinite(entry.limit)) {
163
+ errors.push(`Sub-cluster '${agentConfig.id}' parentTopics entry limit must be a number`);
164
+ }
165
+ }
166
+ }
167
+
168
+ /**
169
+ * Get default sub-cluster template
170
+ * @returns {Object} Default sub-cluster configuration
171
+ */
172
+ function getDefaultSubCluster() {
173
+ return {
174
+ id: 'example-subcluster',
175
+ type: 'subcluster',
176
+ role: 'orchestrator',
177
+ config: {
178
+ agents: [
179
+ {
180
+ id: 'worker',
181
+ role: 'implementation',
182
+ triggers: [{ topic: 'PARENT_TRIGGER' }],
183
+ hooks: {
184
+ onComplete: {
185
+ action: 'publish_message',
186
+ config: { topic: 'WORK_COMPLETE' },
187
+ },
188
+ },
189
+ },
190
+ ],
191
+ },
192
+ triggers: [{ topic: 'START_WORK' }],
193
+ hooks: {
194
+ onComplete: {
195
+ action: 'publish_message',
196
+ config: { topic: 'SUBCLUSTER_COMPLETE' },
197
+ },
198
+ },
199
+ contextStrategy: {
200
+ parentTopics: ['ISSUE_OPENED', 'PLAN_READY'],
201
+ },
202
+ };
203
+ }
204
+
205
+ module.exports = {
206
+ validateSubCluster,
207
+ getDefaultSubCluster,
208
+ };