@cleocode/mcp-server 0.86.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 (374) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +306 -0
  3. package/dist/domains/index.d.ts +16 -0
  4. package/dist/domains/index.d.ts.map +1 -0
  5. package/dist/domains/index.js +16 -0
  6. package/dist/domains/index.js.map +1 -0
  7. package/dist/domains/lifecycle.d.ts +147 -0
  8. package/dist/domains/lifecycle.d.ts.map +1 -0
  9. package/dist/domains/lifecycle.js +452 -0
  10. package/dist/domains/lifecycle.js.map +1 -0
  11. package/dist/domains/orchestrate.d.ts +133 -0
  12. package/dist/domains/orchestrate.d.ts.map +1 -0
  13. package/dist/domains/orchestrate.js +465 -0
  14. package/dist/domains/orchestrate.js.map +1 -0
  15. package/dist/domains/release.d.ts +109 -0
  16. package/dist/domains/release.d.ts.map +1 -0
  17. package/dist/domains/release.js +400 -0
  18. package/dist/domains/release.js.map +1 -0
  19. package/dist/domains/research.d.ts +139 -0
  20. package/dist/domains/research.d.ts.map +1 -0
  21. package/dist/domains/research.js +606 -0
  22. package/dist/domains/research.js.map +1 -0
  23. package/dist/domains/session.d.ts +129 -0
  24. package/dist/domains/session.d.ts.map +1 -0
  25. package/dist/domains/session.js +433 -0
  26. package/dist/domains/session.js.map +1 -0
  27. package/dist/domains/system.d.ts +92 -0
  28. package/dist/domains/system.d.ts.map +1 -0
  29. package/dist/domains/system.js +473 -0
  30. package/dist/domains/system.js.map +1 -0
  31. package/dist/domains/tasks.d.ts +180 -0
  32. package/dist/domains/tasks.d.ts.map +1 -0
  33. package/dist/domains/tasks.js +704 -0
  34. package/dist/domains/tasks.js.map +1 -0
  35. package/dist/domains/validate.d.ts +150 -0
  36. package/dist/domains/validate.d.ts.map +1 -0
  37. package/dist/domains/validate.js +568 -0
  38. package/dist/domains/validate.js.map +1 -0
  39. package/dist/gateways/mutate.d.ts +100 -0
  40. package/dist/gateways/mutate.d.ts.map +1 -0
  41. package/dist/gateways/mutate.js +937 -0
  42. package/dist/gateways/mutate.js.map +1 -0
  43. package/dist/gateways/query.d.ts +91 -0
  44. package/dist/gateways/query.d.ts.map +1 -0
  45. package/dist/gateways/query.js +245 -0
  46. package/dist/gateways/query.js.map +1 -0
  47. package/dist/index.d.ts +21 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +299 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/lib/audit.d.ts +118 -0
  52. package/dist/lib/audit.d.ts.map +1 -0
  53. package/dist/lib/audit.js +311 -0
  54. package/dist/lib/audit.js.map +1 -0
  55. package/dist/lib/background-jobs.d.ts +86 -0
  56. package/dist/lib/background-jobs.d.ts.map +1 -0
  57. package/dist/lib/background-jobs.js +183 -0
  58. package/dist/lib/background-jobs.js.map +1 -0
  59. package/dist/lib/cache.d.ts +78 -0
  60. package/dist/lib/cache.d.ts.map +1 -0
  61. package/dist/lib/cache.js +204 -0
  62. package/dist/lib/cache.js.map +1 -0
  63. package/dist/lib/command-builder.d.ts +52 -0
  64. package/dist/lib/command-builder.d.ts.map +1 -0
  65. package/dist/lib/command-builder.js +280 -0
  66. package/dist/lib/command-builder.js.map +1 -0
  67. package/dist/lib/config.d.ts +42 -0
  68. package/dist/lib/config.d.ts.map +1 -0
  69. package/dist/lib/config.js +248 -0
  70. package/dist/lib/config.js.map +1 -0
  71. package/dist/lib/defaults.d.ts +115 -0
  72. package/dist/lib/defaults.d.ts.map +1 -0
  73. package/dist/lib/defaults.js +61 -0
  74. package/dist/lib/defaults.js.map +1 -0
  75. package/dist/lib/error-handler.d.ts +101 -0
  76. package/dist/lib/error-handler.d.ts.map +1 -0
  77. package/dist/lib/error-handler.js +277 -0
  78. package/dist/lib/error-handler.js.map +1 -0
  79. package/dist/lib/executor.d.ts +110 -0
  80. package/dist/lib/executor.d.ts.map +1 -0
  81. package/dist/lib/executor.js +362 -0
  82. package/dist/lib/executor.js.map +1 -0
  83. package/dist/lib/exit-codes.d.ts +190 -0
  84. package/dist/lib/exit-codes.d.ts.map +1 -0
  85. package/dist/lib/exit-codes.js +1027 -0
  86. package/dist/lib/exit-codes.js.map +1 -0
  87. package/dist/lib/formatter.d.ts +196 -0
  88. package/dist/lib/formatter.d.ts.map +1 -0
  89. package/dist/lib/formatter.js +260 -0
  90. package/dist/lib/formatter.js.map +1 -0
  91. package/dist/lib/gate-validators.d.ts +103 -0
  92. package/dist/lib/gate-validators.d.ts.map +1 -0
  93. package/dist/lib/gate-validators.js +689 -0
  94. package/dist/lib/gate-validators.js.map +1 -0
  95. package/dist/lib/manifest-parser.d.ts +61 -0
  96. package/dist/lib/manifest-parser.d.ts.map +1 -0
  97. package/dist/lib/manifest-parser.js +338 -0
  98. package/dist/lib/manifest-parser.js.map +1 -0
  99. package/dist/lib/manifest.d.ts +177 -0
  100. package/dist/lib/manifest.d.ts.map +1 -0
  101. package/dist/lib/manifest.js +301 -0
  102. package/dist/lib/manifest.js.map +1 -0
  103. package/dist/lib/protocol-enforcement.d.ts +105 -0
  104. package/dist/lib/protocol-enforcement.d.ts.map +1 -0
  105. package/dist/lib/protocol-enforcement.js +331 -0
  106. package/dist/lib/protocol-enforcement.js.map +1 -0
  107. package/dist/lib/protocol-rules.d.ts +55 -0
  108. package/dist/lib/protocol-rules.d.ts.map +1 -0
  109. package/dist/lib/protocol-rules.js +760 -0
  110. package/dist/lib/protocol-rules.js.map +1 -0
  111. package/dist/lib/rate-limiter.d.ts +110 -0
  112. package/dist/lib/rate-limiter.d.ts.map +1 -0
  113. package/dist/lib/rate-limiter.js +208 -0
  114. package/dist/lib/rate-limiter.js.map +1 -0
  115. package/dist/lib/router.d.ts +126 -0
  116. package/dist/lib/router.d.ts.map +1 -0
  117. package/dist/lib/router.js +276 -0
  118. package/dist/lib/router.js.map +1 -0
  119. package/dist/lib/schema.d.ts +55 -0
  120. package/dist/lib/schema.d.ts.map +1 -0
  121. package/dist/lib/schema.js +70 -0
  122. package/dist/lib/schema.js.map +1 -0
  123. package/dist/lib/security.d.ts +156 -0
  124. package/dist/lib/security.d.ts.map +1 -0
  125. package/dist/lib/security.js +347 -0
  126. package/dist/lib/security.js.map +1 -0
  127. package/dist/lib/verification-gates.d.ts +287 -0
  128. package/dist/lib/verification-gates.d.ts.map +1 -0
  129. package/dist/lib/verification-gates.js +548 -0
  130. package/dist/lib/verification-gates.js.map +1 -0
  131. package/dist/types/domain.d.ts +29 -0
  132. package/dist/types/domain.d.ts.map +1 -0
  133. package/dist/types/domain.js +7 -0
  134. package/dist/types/domain.js.map +1 -0
  135. package/dist/types/error.d.ts +101 -0
  136. package/dist/types/error.d.ts.map +1 -0
  137. package/dist/types/error.js +61 -0
  138. package/dist/types/error.js.map +1 -0
  139. package/dist/types/gateway.d.ts +78 -0
  140. package/dist/types/gateway.d.ts.map +1 -0
  141. package/dist/types/gateway.js +7 -0
  142. package/dist/types/gateway.js.map +1 -0
  143. package/dist/types/index.d.ts +21 -0
  144. package/dist/types/index.d.ts.map +1 -0
  145. package/dist/types/index.js +11 -0
  146. package/dist/types/index.js.map +1 -0
  147. package/dist/types/operations/lifecycle.d.ts +140 -0
  148. package/dist/types/operations/lifecycle.d.ts.map +1 -0
  149. package/dist/types/operations/lifecycle.js +8 -0
  150. package/dist/types/operations/lifecycle.js.map +1 -0
  151. package/dist/types/operations/orchestrate.d.ts +140 -0
  152. package/dist/types/operations/orchestrate.d.ts.map +1 -0
  153. package/dist/types/operations/orchestrate.js +8 -0
  154. package/dist/types/operations/orchestrate.js.map +1 -0
  155. package/dist/types/operations/release.d.ts +97 -0
  156. package/dist/types/operations/release.d.ts.map +1 -0
  157. package/dist/types/operations/release.js +7 -0
  158. package/dist/types/operations/release.js.map +1 -0
  159. package/dist/types/operations/research.d.ts +122 -0
  160. package/dist/types/operations/research.d.ts.map +1 -0
  161. package/dist/types/operations/research.js +8 -0
  162. package/dist/types/operations/research.js.map +1 -0
  163. package/dist/types/operations/session.d.ts +108 -0
  164. package/dist/types/operations/session.d.ts.map +1 -0
  165. package/dist/types/operations/session.js +8 -0
  166. package/dist/types/operations/session.js.map +1 -0
  167. package/dist/types/operations/system.d.ts +147 -0
  168. package/dist/types/operations/system.d.ts.map +1 -0
  169. package/dist/types/operations/system.js +8 -0
  170. package/dist/types/operations/system.js.map +1 -0
  171. package/dist/types/operations/tasks.d.ts +186 -0
  172. package/dist/types/operations/tasks.d.ts.map +1 -0
  173. package/dist/types/operations/tasks.js +8 -0
  174. package/dist/types/operations/tasks.js.map +1 -0
  175. package/dist/types/operations/validate.d.ts +170 -0
  176. package/dist/types/operations/validate.d.ts.map +1 -0
  177. package/dist/types/operations/validate.js +8 -0
  178. package/dist/types/operations/validate.js.map +1 -0
  179. package/package.json +67 -0
  180. package/schemas/IMPLEMENTATION-SUMMARY.md +250 -0
  181. package/schemas/README.md +284 -0
  182. package/schemas/common/error.schema.json +54 -0
  183. package/schemas/common/meta.schema.json +39 -0
  184. package/schemas/common/pagination.schema.json +32 -0
  185. package/schemas/index.json +159 -0
  186. package/schemas/requests/lifecycle/check.schema.json +20 -0
  187. package/schemas/requests/lifecycle/gate.fail.schema.json +25 -0
  188. package/schemas/requests/lifecycle/gate.pass.schema.json +28 -0
  189. package/schemas/requests/lifecycle/gates.schema.json +15 -0
  190. package/schemas/requests/lifecycle/history.schema.json +15 -0
  191. package/schemas/requests/lifecycle/prerequisites.schema.json +15 -0
  192. package/schemas/requests/lifecycle/progress.schema.json +29 -0
  193. package/schemas/requests/lifecycle/reset.schema.json +25 -0
  194. package/schemas/requests/lifecycle/skip.schema.json +25 -0
  195. package/schemas/requests/lifecycle/status.schema.json +23 -0
  196. package/schemas/requests/orchestrate/analyze.schema.json +15 -0
  197. package/schemas/requests/orchestrate/context.schema.json +13 -0
  198. package/schemas/requests/orchestrate/next.schema.json +15 -0
  199. package/schemas/requests/orchestrate/parallel.end.schema.json +20 -0
  200. package/schemas/requests/orchestrate/parallel.start.schema.json +20 -0
  201. package/schemas/requests/orchestrate/ready.schema.json +15 -0
  202. package/schemas/requests/orchestrate/skill.list.schema.json +13 -0
  203. package/schemas/requests/orchestrate/spawn.schema.json +25 -0
  204. package/schemas/requests/orchestrate/startup.schema.json +15 -0
  205. package/schemas/requests/orchestrate/status.schema.json +15 -0
  206. package/schemas/requests/orchestrate/validate.schema.json +15 -0
  207. package/schemas/requests/orchestrate/waves.schema.json +15 -0
  208. package/schemas/requests/release/changelog.schema.json +23 -0
  209. package/schemas/requests/release/commit.schema.json +22 -0
  210. package/schemas/requests/release/gates.run.schema.json +17 -0
  211. package/schemas/requests/release/prepare.schema.json +20 -0
  212. package/schemas/requests/release/push.schema.json +20 -0
  213. package/schemas/requests/release/rollback.schema.json +20 -0
  214. package/schemas/requests/release/tag.schema.json +19 -0
  215. package/schemas/requests/research/inject.schema.json +24 -0
  216. package/schemas/requests/research/link.schema.json +25 -0
  217. package/schemas/requests/research/list.schema.json +19 -0
  218. package/schemas/requests/research/manifest.append.schema.json +20 -0
  219. package/schemas/requests/research/manifest.archive.schema.json +19 -0
  220. package/schemas/requests/research/manifest.read.schema.json +21 -0
  221. package/schemas/requests/research/pending.schema.json +14 -0
  222. package/schemas/requests/research/query.schema.json +21 -0
  223. package/schemas/requests/research/show.schema.json +14 -0
  224. package/schemas/requests/research/stats.schema.json +14 -0
  225. package/schemas/requests/session/end.schema.json +13 -0
  226. package/schemas/requests/session/focus.clear.schema.json +7 -0
  227. package/schemas/requests/session/focus.get.schema.json +7 -0
  228. package/schemas/requests/session/focus.set.schema.json +15 -0
  229. package/schemas/requests/session/gc.schema.json +14 -0
  230. package/schemas/requests/session/history.schema.json +16 -0
  231. package/schemas/requests/session/list.schema.json +13 -0
  232. package/schemas/requests/session/resume.schema.json +14 -0
  233. package/schemas/requests/session/show.schema.json +14 -0
  234. package/schemas/requests/session/start.schema.json +23 -0
  235. package/schemas/requests/session/status.schema.json +7 -0
  236. package/schemas/requests/session/suspend.schema.json +13 -0
  237. package/schemas/requests/system/backup.schema.json +19 -0
  238. package/schemas/requests/system/cleanup.schema.json +20 -0
  239. package/schemas/requests/system/config.get.schema.json +14 -0
  240. package/schemas/requests/system/config.set.schema.json +24 -0
  241. package/schemas/requests/system/context.schema.json +7 -0
  242. package/schemas/requests/system/doctor.schema.json +7 -0
  243. package/schemas/requests/system/init.schema.json +18 -0
  244. package/schemas/requests/system/migrate.schema.json +19 -0
  245. package/schemas/requests/system/restore.schema.json +14 -0
  246. package/schemas/requests/system/stats.schema.json +7 -0
  247. package/schemas/requests/system/sync.schema.json +15 -0
  248. package/schemas/requests/system/version.schema.json +7 -0
  249. package/schemas/requests/tasks/analyze.schema.json +14 -0
  250. package/schemas/requests/tasks/archive.schema.json +19 -0
  251. package/schemas/requests/tasks/blockers.schema.json +15 -0
  252. package/schemas/requests/tasks/complete.schema.json +24 -0
  253. package/schemas/requests/tasks/create.schema.json +48 -0
  254. package/schemas/requests/tasks/delete.schema.json +20 -0
  255. package/schemas/requests/tasks/deps.schema.json +21 -0
  256. package/schemas/requests/tasks/exists.schema.json +15 -0
  257. package/schemas/requests/tasks/find.schema.json +22 -0
  258. package/schemas/requests/tasks/get.schema.json +15 -0
  259. package/schemas/requests/tasks/list.schema.json +26 -0
  260. package/schemas/requests/tasks/next.schema.json +21 -0
  261. package/schemas/requests/tasks/promote.schema.json +15 -0
  262. package/schemas/requests/tasks/reopen.schema.json +15 -0
  263. package/schemas/requests/tasks/reorder.schema.json +20 -0
  264. package/schemas/requests/tasks/reparent.schema.json +20 -0
  265. package/schemas/requests/tasks/tree.schema.json +21 -0
  266. package/schemas/requests/tasks/unarchive.schema.json +15 -0
  267. package/schemas/requests/tasks/update.schema.json +41 -0
  268. package/schemas/requests/validate/compliance.record.schema.json +20 -0
  269. package/schemas/requests/validate/compliance.summary.schema.json +18 -0
  270. package/schemas/requests/validate/compliance.violations.schema.json +19 -0
  271. package/schemas/requests/validate/manifest.schema.json +23 -0
  272. package/schemas/requests/validate/output.schema.json +19 -0
  273. package/schemas/requests/validate/protocol.schema.json +20 -0
  274. package/schemas/requests/validate/schema.schema.json +19 -0
  275. package/schemas/requests/validate/task.schema.json +21 -0
  276. package/schemas/requests/validate/test.coverage.schema.json +14 -0
  277. package/schemas/requests/validate/test.run.schema.json +22 -0
  278. package/schemas/requests/validate/test.status.schema.json +14 -0
  279. package/schemas/responses/common-error.schema.json +20 -0
  280. package/schemas/responses/common-success.schema.json +21 -0
  281. package/schemas/responses/lifecycle/check.schema.json +18 -0
  282. package/schemas/responses/lifecycle/gate.fail.schema.json +18 -0
  283. package/schemas/responses/lifecycle/gate.pass.schema.json +18 -0
  284. package/schemas/responses/lifecycle/gates.schema.json +18 -0
  285. package/schemas/responses/lifecycle/history.schema.json +18 -0
  286. package/schemas/responses/lifecycle/prerequisites.schema.json +18 -0
  287. package/schemas/responses/lifecycle/progress.schema.json +18 -0
  288. package/schemas/responses/lifecycle/reset.schema.json +18 -0
  289. package/schemas/responses/lifecycle/skip.schema.json +18 -0
  290. package/schemas/responses/lifecycle/status.schema.json +18 -0
  291. package/schemas/responses/orchestrate/analyze.schema.json +18 -0
  292. package/schemas/responses/orchestrate/context.schema.json +18 -0
  293. package/schemas/responses/orchestrate/next.schema.json +18 -0
  294. package/schemas/responses/orchestrate/parallel.end.schema.json +18 -0
  295. package/schemas/responses/orchestrate/parallel.start.schema.json +18 -0
  296. package/schemas/responses/orchestrate/ready.schema.json +18 -0
  297. package/schemas/responses/orchestrate/skill.list.schema.json +18 -0
  298. package/schemas/responses/orchestrate/spawn.schema.json +18 -0
  299. package/schemas/responses/orchestrate/startup.schema.json +18 -0
  300. package/schemas/responses/orchestrate/status.schema.json +18 -0
  301. package/schemas/responses/orchestrate/validate.schema.json +18 -0
  302. package/schemas/responses/orchestrate/waves.schema.json +18 -0
  303. package/schemas/responses/release/changelog.schema.json +18 -0
  304. package/schemas/responses/release/commit.schema.json +18 -0
  305. package/schemas/responses/release/gates.run.schema.json +18 -0
  306. package/schemas/responses/release/prepare.schema.json +18 -0
  307. package/schemas/responses/release/push.schema.json +18 -0
  308. package/schemas/responses/release/rollback.schema.json +18 -0
  309. package/schemas/responses/release/tag.schema.json +18 -0
  310. package/schemas/responses/research/inject.schema.json +18 -0
  311. package/schemas/responses/research/link.schema.json +18 -0
  312. package/schemas/responses/research/list.schema.json +18 -0
  313. package/schemas/responses/research/manifest.append.schema.json +18 -0
  314. package/schemas/responses/research/manifest.archive.schema.json +18 -0
  315. package/schemas/responses/research/manifest.read.schema.json +18 -0
  316. package/schemas/responses/research/pending.schema.json +18 -0
  317. package/schemas/responses/research/query.schema.json +18 -0
  318. package/schemas/responses/research/show.schema.json +18 -0
  319. package/schemas/responses/research/stats.schema.json +18 -0
  320. package/schemas/responses/session/end.schema.json +18 -0
  321. package/schemas/responses/session/focus.clear.schema.json +18 -0
  322. package/schemas/responses/session/focus.get.schema.json +18 -0
  323. package/schemas/responses/session/focus.set.schema.json +18 -0
  324. package/schemas/responses/session/gc.schema.json +18 -0
  325. package/schemas/responses/session/history.schema.json +18 -0
  326. package/schemas/responses/session/list.schema.json +18 -0
  327. package/schemas/responses/session/resume.schema.json +18 -0
  328. package/schemas/responses/session/show.schema.json +18 -0
  329. package/schemas/responses/session/start.schema.json +18 -0
  330. package/schemas/responses/session/status.schema.json +18 -0
  331. package/schemas/responses/session/suspend.schema.json +18 -0
  332. package/schemas/responses/system/backup.schema.json +18 -0
  333. package/schemas/responses/system/cleanup.schema.json +18 -0
  334. package/schemas/responses/system/config.get.schema.json +18 -0
  335. package/schemas/responses/system/config.set.schema.json +18 -0
  336. package/schemas/responses/system/context.schema.json +18 -0
  337. package/schemas/responses/system/doctor.schema.json +18 -0
  338. package/schemas/responses/system/init.schema.json +18 -0
  339. package/schemas/responses/system/migrate.schema.json +18 -0
  340. package/schemas/responses/system/restore.schema.json +18 -0
  341. package/schemas/responses/system/stats.schema.json +18 -0
  342. package/schemas/responses/system/sync.schema.json +18 -0
  343. package/schemas/responses/system/version.schema.json +18 -0
  344. package/schemas/responses/tasks/analyze.schema.json +18 -0
  345. package/schemas/responses/tasks/archive.schema.json +18 -0
  346. package/schemas/responses/tasks/blockers.schema.json +18 -0
  347. package/schemas/responses/tasks/complete.schema.json +18 -0
  348. package/schemas/responses/tasks/create.schema.json +18 -0
  349. package/schemas/responses/tasks/delete.schema.json +18 -0
  350. package/schemas/responses/tasks/deps.schema.json +18 -0
  351. package/schemas/responses/tasks/exists.schema.json +18 -0
  352. package/schemas/responses/tasks/find.schema.json +18 -0
  353. package/schemas/responses/tasks/get.schema.json +87 -0
  354. package/schemas/responses/tasks/list.schema.json +18 -0
  355. package/schemas/responses/tasks/next.schema.json +18 -0
  356. package/schemas/responses/tasks/promote.schema.json +18 -0
  357. package/schemas/responses/tasks/reopen.schema.json +18 -0
  358. package/schemas/responses/tasks/reorder.schema.json +18 -0
  359. package/schemas/responses/tasks/reparent.schema.json +18 -0
  360. package/schemas/responses/tasks/tree.schema.json +18 -0
  361. package/schemas/responses/tasks/unarchive.schema.json +18 -0
  362. package/schemas/responses/tasks/update.schema.json +18 -0
  363. package/schemas/responses/validate/compliance.record.schema.json +18 -0
  364. package/schemas/responses/validate/compliance.summary.schema.json +18 -0
  365. package/schemas/responses/validate/compliance.violations.schema.json +18 -0
  366. package/schemas/responses/validate/manifest.schema.json +18 -0
  367. package/schemas/responses/validate/output.schema.json +18 -0
  368. package/schemas/responses/validate/protocol.schema.json +18 -0
  369. package/schemas/responses/validate/schema.schema.json +18 -0
  370. package/schemas/responses/validate/task.schema.json +18 -0
  371. package/schemas/responses/validate/test.coverage.schema.json +18 -0
  372. package/schemas/responses/validate/test.run.schema.json +18 -0
  373. package/schemas/responses/validate/test.status.schema.json +18 -0
  374. package/server.json +53 -0
@@ -0,0 +1,689 @@
1
+ /**
2
+ * Gate Validators for 4-Layer Verification System
3
+ *
4
+ * @task T2936
5
+ * @task T3138
6
+ * @epic T2908
7
+ *
8
+ * Individual validator functions for each gate layer:
9
+ * - Layer 1: Schema validation (JSON Schema, format constraints)
10
+ * - Layer 2: Semantic validation (business rules, anti-hallucination)
11
+ * - Layer 3: Referential validation (cross-entity integrity)
12
+ * - Layer 4: Protocol validation (RCSD-IVTR lifecycle)
13
+ *
14
+ * Reference: docs/specs/MCP-SERVER-SPECIFICATION.md Section 8
15
+ */
16
+ import { GateLayer, GateStatus, WORKFLOW_GATE_SEQUENCE, isValidWorkflowGateName, } from './verification-gates.js';
17
+ import { ErrorSeverity } from './exit-codes.js';
18
+ /**
19
+ * Layer 1: Schema Validation
20
+ *
21
+ * Validates operation parameters against JSON Schema definitions.
22
+ * Checks required fields, data types, and format constraints.
23
+ */
24
+ export async function validateLayer1Schema(context) {
25
+ const violations = [];
26
+ // Task ID validation (if present)
27
+ if (context.params?.taskId) {
28
+ const taskId = context.params.taskId;
29
+ if (!taskId.match(/^T[0-9]+$/)) {
30
+ violations.push({
31
+ layer: GateLayer.SCHEMA,
32
+ severity: ErrorSeverity.ERROR,
33
+ code: 'E_INVALID_TASK_ID',
34
+ message: `Invalid task ID format: ${taskId}`,
35
+ field: 'taskId',
36
+ value: taskId,
37
+ constraint: 'Must match pattern ^T[0-9]+$',
38
+ fix: 'Use format T followed by digits (e.g., T1234)',
39
+ });
40
+ }
41
+ }
42
+ // Title validation (for create/update operations)
43
+ if (context.params?.title !== undefined) {
44
+ const title = context.params.title;
45
+ if (typeof title !== 'string' || title.length < 5 || title.length > 100) {
46
+ violations.push({
47
+ layer: GateLayer.SCHEMA,
48
+ severity: ErrorSeverity.ERROR,
49
+ code: 'E_INVALID_TITLE',
50
+ message: 'Title must be 5-100 characters',
51
+ field: 'title',
52
+ value: title,
53
+ constraint: 'length: 5-100',
54
+ fix: 'Provide a title between 5 and 100 characters',
55
+ });
56
+ }
57
+ }
58
+ // Description validation (Section 8.1: 10-1000 characters)
59
+ if (context.params?.description !== undefined) {
60
+ const description = context.params.description;
61
+ if (typeof description !== 'string' || description.length < 10 || description.length > 1000) {
62
+ violations.push({
63
+ layer: GateLayer.SCHEMA,
64
+ severity: ErrorSeverity.ERROR,
65
+ code: 'E_INVALID_DESCRIPTION',
66
+ message: 'Description must be 10-1000 characters',
67
+ field: 'description',
68
+ value: typeof description === 'string' ? `${description.substring(0, 50)}...` : description,
69
+ constraint: 'length: 10-1000',
70
+ fix: 'Provide a description between 10 and 1000 characters',
71
+ });
72
+ }
73
+ }
74
+ // Manifest ID format validation (Section 8.2: ^T\d{3,}-[a-z0-9-]+$)
75
+ if (context.params?.manifestEntry) {
76
+ const entry = context.params.manifestEntry;
77
+ if (entry.id) {
78
+ const manifestId = entry.id;
79
+ if (!manifestId.match(/^T\d{3,}-[a-z0-9-]+$/)) {
80
+ violations.push({
81
+ layer: GateLayer.SCHEMA,
82
+ severity: ErrorSeverity.ERROR,
83
+ code: 'E_INVALID_MANIFEST_ID',
84
+ message: `Invalid manifest ID format: ${manifestId}`,
85
+ field: 'manifestEntry.id',
86
+ value: manifestId,
87
+ constraint: 'Must match ^T\\d{3,}-[a-z0-9-]+$',
88
+ fix: 'Use format T####-slug (e.g., T1234-research-output)',
89
+ });
90
+ }
91
+ }
92
+ // Date format validation (Section 8.2: ISO 8601 YYYY-MM-DD)
93
+ if (entry.date) {
94
+ const date = entry.date;
95
+ if (!date.match(/^\d{4}-\d{2}-\d{2}$/)) {
96
+ violations.push({
97
+ layer: GateLayer.SCHEMA,
98
+ severity: ErrorSeverity.ERROR,
99
+ code: 'E_INVALID_DATE_FORMAT',
100
+ message: `Invalid date format: ${date}`,
101
+ field: 'manifestEntry.date',
102
+ value: date,
103
+ constraint: 'Must be ISO 8601 YYYY-MM-DD',
104
+ fix: 'Use date format YYYY-MM-DD (e.g., 2026-02-06)',
105
+ });
106
+ }
107
+ }
108
+ // Agent type validation (Section 8.2: known protocol type)
109
+ if (entry.agent_type) {
110
+ const agentType = entry.agent_type;
111
+ const validAgentTypes = [
112
+ 'research', 'analysis', 'specification', 'implementation',
113
+ 'testing', 'validation', 'documentation', 'release',
114
+ ];
115
+ if (!validAgentTypes.includes(agentType)) {
116
+ violations.push({
117
+ layer: GateLayer.SCHEMA,
118
+ severity: ErrorSeverity.ERROR,
119
+ code: 'E_INVALID_AGENT_TYPE',
120
+ message: `Invalid agent type: ${agentType}`,
121
+ field: 'manifestEntry.agent_type',
122
+ value: agentType,
123
+ constraint: `Must be one of: ${validAgentTypes.join(', ')}`,
124
+ fix: `Use one of: ${validAgentTypes.join(', ')}`,
125
+ });
126
+ }
127
+ }
128
+ }
129
+ // Status validation
130
+ if (context.params?.status) {
131
+ const status = context.params.status;
132
+ const validStatuses = ['pending', 'active', 'blocked', 'done'];
133
+ if (!validStatuses.includes(status)) {
134
+ violations.push({
135
+ layer: GateLayer.SCHEMA,
136
+ severity: ErrorSeverity.ERROR,
137
+ code: 'E_INVALID_STATUS',
138
+ message: `Invalid status: ${status}`,
139
+ field: 'status',
140
+ value: status,
141
+ constraint: `Must be one of: ${validStatuses.join(', ')}`,
142
+ fix: `Use one of: ${validStatuses.join(', ')}`,
143
+ });
144
+ }
145
+ }
146
+ // Priority validation
147
+ if (context.params?.priority !== undefined) {
148
+ const priority = context.params.priority;
149
+ if (typeof priority !== 'number' || priority < 1 || priority > 9) {
150
+ violations.push({
151
+ layer: GateLayer.SCHEMA,
152
+ severity: ErrorSeverity.ERROR,
153
+ code: 'E_INVALID_PRIORITY',
154
+ message: 'Priority must be 1-9',
155
+ field: 'priority',
156
+ value: priority,
157
+ constraint: 'range: 1-9',
158
+ fix: 'Set priority between 1 (highest) and 9 (lowest)',
159
+ });
160
+ }
161
+ }
162
+ return {
163
+ layer: GateLayer.SCHEMA,
164
+ status: violations.length > 0 ? GateStatus.FAILED : GateStatus.PASSED,
165
+ passed: violations.length === 0,
166
+ violations,
167
+ duration_ms: 0,
168
+ };
169
+ }
170
+ /**
171
+ * Layer 2: Semantic Validation
172
+ *
173
+ * Validates business rules and logical constraints.
174
+ * Checks hierarchy depth, sibling limits, title/description uniqueness.
175
+ */
176
+ export async function validateLayer2Semantic(context) {
177
+ const violations = [];
178
+ // Title and description must be different (anti-hallucination)
179
+ if (context.params?.title && context.params?.description) {
180
+ const title = context.params.title;
181
+ const description = context.params.description;
182
+ if (title === description) {
183
+ violations.push({
184
+ layer: GateLayer.SEMANTIC,
185
+ severity: ErrorSeverity.ERROR,
186
+ code: 'E_TITLE_DESCRIPTION_SAME',
187
+ message: 'Title and description must be different',
188
+ field: 'description',
189
+ constraint: 'must differ from title',
190
+ fix: 'Provide a unique description that explains the task',
191
+ });
192
+ }
193
+ }
194
+ // No future timestamps (Section 8.1: created/updated <= now)
195
+ if (context.params?.created || context.params?.updated) {
196
+ const now = new Date();
197
+ for (const field of ['created', 'updated']) {
198
+ const value = context.params?.[field];
199
+ if (value) {
200
+ const timestamp = new Date(value);
201
+ if (!isNaN(timestamp.getTime()) && timestamp > now) {
202
+ violations.push({
203
+ layer: GateLayer.SEMANTIC,
204
+ severity: ErrorSeverity.ERROR,
205
+ code: 'E_FUTURE_TIMESTAMP',
206
+ message: `Timestamp ${field} cannot be in the future: ${value}`,
207
+ field,
208
+ value,
209
+ constraint: `${field} <= current time`,
210
+ fix: `Set ${field} to current or past timestamp`,
211
+ });
212
+ }
213
+ }
214
+ }
215
+ }
216
+ // Manifest date must not be future (Section 8.1)
217
+ if (context.params?.manifestEntry) {
218
+ const entry = context.params.manifestEntry;
219
+ if (entry.date) {
220
+ const dateStr = entry.date;
221
+ const today = new Date().toISOString().split('T')[0];
222
+ if (dateStr > today) {
223
+ violations.push({
224
+ layer: GateLayer.SEMANTIC,
225
+ severity: ErrorSeverity.ERROR,
226
+ code: 'E_FUTURE_TIMESTAMP',
227
+ message: `Manifest date cannot be in the future: ${dateStr}`,
228
+ field: 'manifestEntry.date',
229
+ value: dateStr,
230
+ constraint: 'date <= today',
231
+ fix: 'Set date to today or earlier',
232
+ });
233
+ }
234
+ }
235
+ }
236
+ // Circular dependency check (if depends specified)
237
+ if (context.params?.depends) {
238
+ const depends = context.params.depends;
239
+ const taskId = context.params?.taskId;
240
+ if (taskId && depends.includes(taskId)) {
241
+ violations.push({
242
+ layer: GateLayer.SEMANTIC,
243
+ severity: ErrorSeverity.ERROR,
244
+ code: 'E_CIRCULAR_DEPENDENCY',
245
+ message: 'Task cannot depend on itself',
246
+ field: 'depends',
247
+ constraint: 'no self-reference',
248
+ fix: 'Remove self-reference from dependencies',
249
+ });
250
+ }
251
+ }
252
+ // Session scope validation
253
+ if (context.domain === 'session' && context.operation === 'start') {
254
+ const scope = context.params?.scope;
255
+ if (scope && !scope.match(/^(epic|task|global):/)) {
256
+ violations.push({
257
+ layer: GateLayer.SEMANTIC,
258
+ severity: ErrorSeverity.ERROR,
259
+ code: 'E_INVALID_SCOPE',
260
+ message: `Invalid session scope format: ${scope}`,
261
+ field: 'scope',
262
+ constraint: 'Must be epic:<id>, task:<id>, or global',
263
+ fix: 'Use format: epic:T1234, task:T5678, or global',
264
+ });
265
+ }
266
+ }
267
+ // Notes required for completion (if configured)
268
+ if (context.operation === 'complete' && context.params?.notes === undefined) {
269
+ violations.push({
270
+ layer: GateLayer.SEMANTIC,
271
+ severity: ErrorSeverity.WARNING,
272
+ code: 'E_NOTES_RECOMMENDED',
273
+ message: 'Completion notes are recommended',
274
+ field: 'notes',
275
+ constraint: 'should be present',
276
+ fix: 'Add --notes "..." to document completion',
277
+ });
278
+ }
279
+ return {
280
+ layer: GateLayer.SEMANTIC,
281
+ status: violations.filter((v) => v.severity === ErrorSeverity.ERROR).length > 0
282
+ ? GateStatus.FAILED
283
+ : GateStatus.PASSED,
284
+ passed: violations.filter((v) => v.severity === ErrorSeverity.ERROR).length === 0,
285
+ violations,
286
+ duration_ms: 0,
287
+ };
288
+ }
289
+ /**
290
+ * Layer 3: Referential Validation
291
+ *
292
+ * Validates cross-entity references and relationships.
293
+ * Checks task existence, parent/child relationships, dependencies.
294
+ */
295
+ export async function validateLayer3Referential(context) {
296
+ const violations = [];
297
+ // Parent task validation (if specified)
298
+ if (context.params?.parent) {
299
+ const parent = context.params.parent;
300
+ // Note: In production, this would call CLIExecutor to check existence
301
+ // For now, we validate format
302
+ if (!parent.match(/^T[0-9]+$/)) {
303
+ violations.push({
304
+ layer: GateLayer.REFERENTIAL,
305
+ severity: ErrorSeverity.ERROR,
306
+ code: 'E_INVALID_PARENT_REF',
307
+ message: `Invalid parent reference: ${parent}`,
308
+ field: 'parent',
309
+ value: parent,
310
+ constraint: 'Must be valid task ID',
311
+ fix: 'Verify parent task exists with: cleo exists <id>',
312
+ });
313
+ }
314
+ }
315
+ // Dependency validation
316
+ if (context.params?.depends) {
317
+ const depends = context.params.depends;
318
+ for (const depId of depends) {
319
+ if (!depId.match(/^T[0-9]+$/)) {
320
+ violations.push({
321
+ layer: GateLayer.REFERENTIAL,
322
+ severity: ErrorSeverity.ERROR,
323
+ code: 'E_INVALID_DEPENDENCY_REF',
324
+ message: `Invalid dependency reference: ${depId}`,
325
+ field: 'depends',
326
+ value: depId,
327
+ constraint: 'Must be valid task ID',
328
+ fix: 'Verify dependency exists with: cleo find --id <id>',
329
+ });
330
+ }
331
+ }
332
+ }
333
+ // Task existence validation (for update/complete/delete operations)
334
+ if (['update', 'complete', 'delete', 'archive', 'reopen'].includes(context.operation)) {
335
+ const taskId = context.params?.taskId;
336
+ if (!taskId) {
337
+ violations.push({
338
+ layer: GateLayer.REFERENTIAL,
339
+ severity: ErrorSeverity.ERROR,
340
+ code: 'E_TASK_ID_REQUIRED',
341
+ message: 'Task ID is required for this operation',
342
+ field: 'taskId',
343
+ constraint: 'required',
344
+ fix: 'Provide task ID with --taskId T####',
345
+ });
346
+ }
347
+ }
348
+ // Session validation (for focus operations)
349
+ if (context.domain === 'session' && context.operation === 'focus.set') {
350
+ const taskId = context.params?.taskId;
351
+ if (taskId && !taskId.match(/^T[0-9]+$/)) {
352
+ violations.push({
353
+ layer: GateLayer.REFERENTIAL,
354
+ severity: ErrorSeverity.ERROR,
355
+ code: 'E_INVALID_FOCUS_REF',
356
+ message: `Invalid focus task reference: ${taskId}`,
357
+ field: 'taskId',
358
+ value: taskId,
359
+ constraint: 'Must be valid task ID',
360
+ fix: 'Use valid task ID format: T####',
361
+ });
362
+ }
363
+ }
364
+ // Hierarchy depth validation (Section 8.1: max 3 levels)
365
+ if (context.params?.depth !== undefined) {
366
+ const depth = context.params.depth;
367
+ if (typeof depth === 'number' && depth > VALIDATION_RULES.MAX_DEPTH) {
368
+ violations.push({
369
+ layer: GateLayer.REFERENTIAL,
370
+ severity: ErrorSeverity.ERROR,
371
+ code: 'E_DEPTH_EXCEEDED',
372
+ message: `Hierarchy depth ${depth} exceeds maximum of ${VALIDATION_RULES.MAX_DEPTH}`,
373
+ field: 'depth',
374
+ value: depth,
375
+ constraint: `max depth: ${VALIDATION_RULES.MAX_DEPTH}`,
376
+ fix: 'Flatten hierarchy to max 3 levels (epic -> task -> subtask)',
377
+ });
378
+ }
379
+ }
380
+ // Sibling limit validation (Section 8.1: max 7 per parent)
381
+ if (context.params?.siblingCount !== undefined) {
382
+ const siblingCount = context.params.siblingCount;
383
+ if (typeof siblingCount === 'number' && siblingCount >= VALIDATION_RULES.MAX_SIBLINGS) {
384
+ violations.push({
385
+ layer: GateLayer.REFERENTIAL,
386
+ severity: ErrorSeverity.ERROR,
387
+ code: 'E_SIBLING_LIMIT',
388
+ message: `Parent already has ${siblingCount} children (max ${VALIDATION_RULES.MAX_SIBLINGS})`,
389
+ field: 'siblingCount',
390
+ value: siblingCount,
391
+ constraint: `max siblings: ${VALIDATION_RULES.MAX_SIBLINGS}`,
392
+ fix: 'Create a new parent to group related tasks',
393
+ });
394
+ }
395
+ }
396
+ // Manifest file reference validation (Section 8.2: referenced file readable)
397
+ if (context.params?.manifestEntry) {
398
+ const entry = context.params.manifestEntry;
399
+ if (typeof entry.file === 'string' && entry.file.length === 0) {
400
+ violations.push({
401
+ layer: GateLayer.REFERENTIAL,
402
+ severity: ErrorSeverity.ERROR,
403
+ code: 'E_EMPTY_FILE_REF',
404
+ message: 'Manifest entry file reference cannot be empty',
405
+ field: 'manifestEntry.file',
406
+ value: entry.file,
407
+ constraint: 'must be non-empty file path',
408
+ fix: 'Provide a valid file path in manifest entry',
409
+ });
410
+ }
411
+ }
412
+ return {
413
+ layer: GateLayer.REFERENTIAL,
414
+ status: violations.length > 0 ? GateStatus.FAILED : GateStatus.PASSED,
415
+ passed: violations.length === 0,
416
+ violations,
417
+ duration_ms: 0,
418
+ };
419
+ }
420
+ /**
421
+ * Layer 4: Protocol Validation
422
+ *
423
+ * Validates RCSD-IVTR lifecycle compliance and protocol requirements.
424
+ * Checks lifecycle gates, protocol-specific rules, provenance tags.
425
+ */
426
+ export async function validateLayer4Protocol(context, enforcer) {
427
+ const violations = [];
428
+ // Skip protocol validation for non-protocol operations
429
+ if (!context.protocolType) {
430
+ return {
431
+ layer: GateLayer.PROTOCOL,
432
+ status: GateStatus.SKIPPED,
433
+ passed: true,
434
+ violations: [],
435
+ duration_ms: 0,
436
+ };
437
+ }
438
+ // Lifecycle gate validation (for spawn/complete operations)
439
+ if (context.operation === 'spawn' || context.operation === 'complete') {
440
+ const taskId = context.params?.taskId;
441
+ const protocolType = context.protocolType;
442
+ // Check lifecycle prerequisites
443
+ const lifecycleGates = {
444
+ research: [],
445
+ consensus: ['research'],
446
+ specification: ['research', 'consensus'],
447
+ decomposition: ['research', 'consensus', 'specification'],
448
+ implementation: ['research', 'consensus', 'specification', 'decomposition'],
449
+ validation: ['implementation'],
450
+ testing: ['implementation', 'validation'],
451
+ release: ['implementation', 'validation', 'testing'],
452
+ };
453
+ const requiredGates = lifecycleGates[protocolType] || [];
454
+ if (requiredGates.length > 0) {
455
+ // Note: In production, check actual gate status via CLIExecutor
456
+ // For now, we document the requirement
457
+ violations.push({
458
+ layer: GateLayer.PROTOCOL,
459
+ severity: ErrorSeverity.INFO,
460
+ code: 'E_LIFECYCLE_PREREQUISITES',
461
+ message: `This operation requires prior stages: ${requiredGates.join(', ')}`,
462
+ field: 'lifecycle',
463
+ constraint: `prerequisites: ${requiredGates.join(', ')}`,
464
+ fix: 'Ensure prior lifecycle stages are complete',
465
+ });
466
+ }
467
+ }
468
+ // Manifest validation (for complete operations)
469
+ if (context.operation === 'complete') {
470
+ const manifestEntry = context.params?.manifestEntry;
471
+ if (manifestEntry) {
472
+ // Required manifest fields
473
+ const requiredFields = ['id', 'file', 'title', 'date', 'status', 'agent_type'];
474
+ for (const field of requiredFields) {
475
+ if (!manifestEntry[field]) {
476
+ violations.push({
477
+ layer: GateLayer.PROTOCOL,
478
+ severity: ErrorSeverity.ERROR,
479
+ code: 'E_MANIFEST_FIELD_MISSING',
480
+ message: `Manifest entry missing required field: ${field}`,
481
+ field: `manifestEntry.${field}`,
482
+ constraint: 'required',
483
+ fix: `Add ${field} to manifest entry`,
484
+ });
485
+ }
486
+ }
487
+ // Status enum validation
488
+ const status = manifestEntry.status;
489
+ if (!['complete', 'partial', 'blocked'].includes(status)) {
490
+ violations.push({
491
+ layer: GateLayer.PROTOCOL,
492
+ severity: ErrorSeverity.ERROR,
493
+ code: 'E_INVALID_MANIFEST_STATUS',
494
+ message: `Invalid manifest status: ${status}`,
495
+ field: 'manifestEntry.status',
496
+ value: status,
497
+ constraint: 'Must be: complete, partial, or blocked',
498
+ fix: 'Set status to complete, partial, or blocked',
499
+ });
500
+ }
501
+ }
502
+ }
503
+ // Key findings validation for research protocol (Section 8.2: 3-7 items)
504
+ if (context.protocolType === 'research' && context.operation === 'complete') {
505
+ const manifestEntry = context.params?.manifestEntry;
506
+ if (manifestEntry?.key_findings) {
507
+ const findings = manifestEntry.key_findings;
508
+ if (!Array.isArray(findings) || findings.length < VALIDATION_RULES.KEY_FINDINGS_MIN || findings.length > VALIDATION_RULES.KEY_FINDINGS_MAX) {
509
+ violations.push({
510
+ layer: GateLayer.PROTOCOL,
511
+ severity: ErrorSeverity.ERROR,
512
+ code: 'E_KEY_FINDINGS_COUNT',
513
+ message: `Research must have ${VALIDATION_RULES.KEY_FINDINGS_MIN}-${VALIDATION_RULES.KEY_FINDINGS_MAX} key findings, got ${Array.isArray(findings) ? findings.length : 0}`,
514
+ field: 'manifestEntry.key_findings',
515
+ value: Array.isArray(findings) ? findings.length : findings,
516
+ constraint: `count: ${VALIDATION_RULES.KEY_FINDINGS_MIN}-${VALIDATION_RULES.KEY_FINDINGS_MAX}`,
517
+ fix: 'Adjust key findings to have 3-7 items',
518
+ });
519
+ }
520
+ }
521
+ }
522
+ // Provenance validation (for implementation protocol)
523
+ if (context.protocolType === 'implementation') {
524
+ const files = context.params?.files;
525
+ if (files && files.length > 0) {
526
+ violations.push({
527
+ layer: GateLayer.PROTOCOL,
528
+ severity: ErrorSeverity.WARNING,
529
+ code: 'E_PROVENANCE_CHECK',
530
+ message: 'Implementation files should include @task provenance tags',
531
+ field: 'files',
532
+ constraint: 'should include @task comments',
533
+ fix: 'Add @task T#### comments to new functions/classes',
534
+ });
535
+ }
536
+ }
537
+ return {
538
+ layer: GateLayer.PROTOCOL,
539
+ status: violations.filter((v) => v.severity === ErrorSeverity.ERROR).length > 0
540
+ ? GateStatus.FAILED
541
+ : GateStatus.PASSED,
542
+ passed: violations.filter((v) => v.severity === ErrorSeverity.ERROR).length === 0,
543
+ violations,
544
+ duration_ms: 0,
545
+ };
546
+ }
547
+ /**
548
+ * Validation rule definitions for reuse
549
+ */
550
+ export const VALIDATION_RULES = {
551
+ TASK_ID_PATTERN: /^T[0-9]+$/,
552
+ MANIFEST_ID_PATTERN: /^T\d{3,}-[a-z0-9-]+$/,
553
+ DATE_FORMAT_PATTERN: /^\d{4}-\d{2}-\d{2}$/,
554
+ TITLE_MIN_LENGTH: 5,
555
+ TITLE_MAX_LENGTH: 100,
556
+ DESCRIPTION_MIN_LENGTH: 10,
557
+ DESCRIPTION_MAX_LENGTH: 1000,
558
+ VALID_STATUSES: ['pending', 'active', 'blocked', 'done'],
559
+ VALID_MANIFEST_STATUSES: ['complete', 'partial', 'blocked'],
560
+ VALID_AGENT_TYPES: [
561
+ 'research', 'analysis', 'specification', 'implementation',
562
+ 'testing', 'validation', 'documentation', 'release',
563
+ ],
564
+ PRIORITY_MIN: 1,
565
+ PRIORITY_MAX: 9,
566
+ MAX_DEPTH: 3,
567
+ MAX_SIBLINGS: 7,
568
+ KEY_FINDINGS_MIN: 3,
569
+ KEY_FINDINGS_MAX: 7,
570
+ };
571
+ /**
572
+ * Helper to check if a field is required for an operation
573
+ */
574
+ export function isFieldRequired(domain, operation, field) {
575
+ const requirements = {
576
+ tasks: {
577
+ create: ['title', 'description'],
578
+ update: ['taskId'],
579
+ complete: ['taskId'],
580
+ delete: ['taskId'],
581
+ },
582
+ session: {
583
+ start: ['scope'],
584
+ 'focus.set': ['taskId'],
585
+ },
586
+ };
587
+ return requirements[domain]?.[operation]?.includes(field) ?? false;
588
+ }
589
+ // ============================================================================
590
+ // Section 7: Workflow Gate Validators
591
+ // ============================================================================
592
+ /**
593
+ * Valid workflow gate agent names per Section 7.2
594
+ */
595
+ export const VALID_WORKFLOW_AGENTS = ['coder', 'testing', 'qa', 'cleanup', 'security', 'docs'];
596
+ /**
597
+ * Valid workflow gate status values per Section 7.3
598
+ */
599
+ export const VALID_WORKFLOW_GATE_STATUSES = [null, 'passed', 'failed', 'blocked'];
600
+ /**
601
+ * Validate a workflow gate name
602
+ *
603
+ * @task T3141
604
+ */
605
+ export function validateWorkflowGateName(name) {
606
+ return isValidWorkflowGateName(name);
607
+ }
608
+ /**
609
+ * Validate a workflow gate status value per Section 7.3
610
+ *
611
+ * @task T3141
612
+ */
613
+ export function validateWorkflowGateStatus(status) {
614
+ return status === null || status === 'passed' || status === 'failed' || status === 'blocked';
615
+ }
616
+ /**
617
+ * Validate a gate update operation.
618
+ *
619
+ * Checks that:
620
+ * - Gate name is valid
621
+ * - Status value is valid
622
+ * - Agent matches expected agent for the gate
623
+ * - Dependencies are met for pass operations
624
+ *
625
+ * @task T3141
626
+ */
627
+ export function validateWorkflowGateUpdate(gateName, status, agent, tracker) {
628
+ const violations = [];
629
+ // Validate gate name
630
+ if (!isValidWorkflowGateName(gateName)) {
631
+ violations.push({
632
+ layer: GateLayer.PROTOCOL,
633
+ severity: ErrorSeverity.ERROR,
634
+ code: 'E_INVALID_GATE',
635
+ message: `Invalid workflow gate name: ${gateName}`,
636
+ field: 'gateName',
637
+ value: gateName,
638
+ constraint: `Must be one of: ${WORKFLOW_GATE_SEQUENCE.join(', ')}`,
639
+ fix: `Use a valid gate name: ${WORKFLOW_GATE_SEQUENCE.join(', ')}`,
640
+ });
641
+ return violations;
642
+ }
643
+ // Validate status
644
+ if (status !== 'passed' && status !== 'failed') {
645
+ violations.push({
646
+ layer: GateLayer.PROTOCOL,
647
+ severity: ErrorSeverity.ERROR,
648
+ code: 'E_INVALID_GATE_STATUS',
649
+ message: `Invalid gate status for update: ${status}`,
650
+ field: 'status',
651
+ value: status,
652
+ constraint: 'Must be "passed" or "failed" for update operations',
653
+ fix: 'Use status "passed" or "failed"',
654
+ });
655
+ }
656
+ // Validate agent match (if tracker provided for context)
657
+ if (agent && tracker) {
658
+ const gateState = tracker.getGateState(gateName);
659
+ if (gateState && agent !== gateState.agent) {
660
+ violations.push({
661
+ layer: GateLayer.PROTOCOL,
662
+ severity: ErrorSeverity.ERROR,
663
+ code: 'E_INVALID_AGENT',
664
+ message: `Agent "${agent}" is not authorized for gate "${gateName}" (expected: ${gateState.agent})`,
665
+ field: 'agent',
666
+ value: agent,
667
+ constraint: `Must be agent: ${gateState.agent}`,
668
+ fix: `Use the correct agent: ${gateState.agent}`,
669
+ });
670
+ }
671
+ }
672
+ // Validate dependencies are met for pass operations
673
+ if (status === 'passed' && tracker) {
674
+ if (!tracker.canAttempt(gateName)) {
675
+ violations.push({
676
+ layer: GateLayer.PROTOCOL,
677
+ severity: ErrorSeverity.ERROR,
678
+ code: 'E_GATE_DEPENDENCY',
679
+ message: `Cannot pass gate "${gateName}": dependencies not met`,
680
+ field: 'gateName',
681
+ value: gateName,
682
+ constraint: 'All dependency gates must be passed first',
683
+ fix: 'Pass all prerequisite gates first',
684
+ });
685
+ }
686
+ }
687
+ return violations;
688
+ }
689
+ //# sourceMappingURL=gate-validators.js.map