@mcoda/core 0.1.8 → 0.1.11

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 (216) hide show
  1. package/CHANGELOG.md +3 -0
  2. package/README.md +2 -2
  3. package/dist/api/AgentsApi.d.ts +9 -1
  4. package/dist/api/AgentsApi.d.ts.map +1 -1
  5. package/dist/api/AgentsApi.js +201 -6
  6. package/dist/api/QaTasksApi.d.ts.map +1 -1
  7. package/dist/api/QaTasksApi.js +6 -0
  8. package/dist/api/TasksApi.d.ts.map +1 -1
  9. package/dist/api/TasksApi.js +1 -0
  10. package/dist/index.d.ts +4 -0
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +4 -0
  13. package/dist/prompts/PdrPrompts.d.ts.map +1 -1
  14. package/dist/prompts/PdrPrompts.js +9 -1
  15. package/dist/prompts/SdsPrompts.d.ts.map +1 -1
  16. package/dist/prompts/SdsPrompts.js +9 -0
  17. package/dist/services/agents/AgentRatingFormula.d.ts +27 -0
  18. package/dist/services/agents/AgentRatingFormula.d.ts.map +1 -0
  19. package/dist/services/agents/AgentRatingFormula.js +45 -0
  20. package/dist/services/agents/AgentRatingService.d.ts +60 -0
  21. package/dist/services/agents/AgentRatingService.d.ts.map +1 -0
  22. package/dist/services/agents/AgentRatingService.js +363 -0
  23. package/dist/services/agents/GatewayAgentService.d.ts +11 -0
  24. package/dist/services/agents/GatewayAgentService.d.ts.map +1 -1
  25. package/dist/services/agents/GatewayAgentService.js +525 -84
  26. package/dist/services/agents/GatewayHandoff.d.ts +11 -0
  27. package/dist/services/agents/GatewayHandoff.d.ts.map +1 -0
  28. package/dist/services/agents/GatewayHandoff.js +141 -0
  29. package/dist/services/agents/RoutingService.d.ts +1 -0
  30. package/dist/services/agents/RoutingService.d.ts.map +1 -1
  31. package/dist/services/agents/RoutingService.js +4 -4
  32. package/dist/services/backlog/BacklogService.d.ts +23 -0
  33. package/dist/services/backlog/BacklogService.d.ts.map +1 -1
  34. package/dist/services/backlog/BacklogService.js +62 -7
  35. package/dist/services/backlog/TaskOrderingHeuristics.d.ts +12 -0
  36. package/dist/services/backlog/TaskOrderingHeuristics.d.ts.map +1 -0
  37. package/dist/services/backlog/TaskOrderingHeuristics.js +56 -0
  38. package/dist/services/backlog/TaskOrderingService.d.ts +17 -4
  39. package/dist/services/backlog/TaskOrderingService.d.ts.map +1 -1
  40. package/dist/services/backlog/TaskOrderingService.js +538 -79
  41. package/dist/services/docs/DocInventory.d.ts +11 -0
  42. package/dist/services/docs/DocInventory.d.ts.map +1 -0
  43. package/dist/services/docs/DocInventory.js +230 -0
  44. package/dist/services/docs/DocgenRunContext.d.ts +59 -0
  45. package/dist/services/docs/DocgenRunContext.d.ts.map +1 -0
  46. package/dist/services/docs/DocgenRunContext.js +4 -0
  47. package/dist/services/docs/DocsService.d.ts +70 -3
  48. package/dist/services/docs/DocsService.d.ts.map +1 -1
  49. package/dist/services/docs/DocsService.js +1930 -89
  50. package/dist/services/docs/alignment/DocAlignmentGraph.d.ts +23 -0
  51. package/dist/services/docs/alignment/DocAlignmentGraph.d.ts.map +1 -0
  52. package/dist/services/docs/alignment/DocAlignmentGraph.js +78 -0
  53. package/dist/services/docs/alignment/DocAlignmentPatcher.d.ts +19 -0
  54. package/dist/services/docs/alignment/DocAlignmentPatcher.d.ts.map +1 -0
  55. package/dist/services/docs/alignment/DocAlignmentPatcher.js +222 -0
  56. package/dist/services/docs/patch/DocPatchEngine.d.ts +57 -0
  57. package/dist/services/docs/patch/DocPatchEngine.d.ts.map +1 -0
  58. package/dist/services/docs/patch/DocPatchEngine.js +331 -0
  59. package/dist/services/docs/review/Glossary.d.ts +16 -0
  60. package/dist/services/docs/review/Glossary.d.ts.map +1 -0
  61. package/dist/services/docs/review/Glossary.js +47 -0
  62. package/dist/services/docs/review/ReviewReportRenderer.d.ts +3 -0
  63. package/dist/services/docs/review/ReviewReportRenderer.d.ts.map +1 -0
  64. package/dist/services/docs/review/ReviewReportRenderer.js +133 -0
  65. package/dist/services/docs/review/ReviewReportSchema.d.ts +39 -0
  66. package/dist/services/docs/review/ReviewReportSchema.d.ts.map +1 -0
  67. package/dist/services/docs/review/ReviewReportSchema.js +47 -0
  68. package/dist/services/docs/review/ReviewTypes.d.ts +76 -0
  69. package/dist/services/docs/review/ReviewTypes.d.ts.map +1 -0
  70. package/dist/services/docs/review/ReviewTypes.js +94 -0
  71. package/dist/services/docs/review/gates/AdminOpenApiSpecGate.d.ts +7 -0
  72. package/dist/services/docs/review/gates/AdminOpenApiSpecGate.d.ts.map +1 -0
  73. package/dist/services/docs/review/gates/AdminOpenApiSpecGate.js +93 -0
  74. package/dist/services/docs/review/gates/ApiPathConsistencyGate.d.ts +7 -0
  75. package/dist/services/docs/review/gates/ApiPathConsistencyGate.d.ts.map +1 -0
  76. package/dist/services/docs/review/gates/ApiPathConsistencyGate.js +308 -0
  77. package/dist/services/docs/review/gates/BuildReadyCompletenessGate.d.ts +8 -0
  78. package/dist/services/docs/review/gates/BuildReadyCompletenessGate.d.ts.map +1 -0
  79. package/dist/services/docs/review/gates/BuildReadyCompletenessGate.js +278 -0
  80. package/dist/services/docs/review/gates/DeploymentBlueprintGate.d.ts +8 -0
  81. package/dist/services/docs/review/gates/DeploymentBlueprintGate.d.ts.map +1 -0
  82. package/dist/services/docs/review/gates/DeploymentBlueprintGate.js +487 -0
  83. package/dist/services/docs/review/gates/NoMaybesGate.d.ts +8 -0
  84. package/dist/services/docs/review/gates/NoMaybesGate.d.ts.map +1 -0
  85. package/dist/services/docs/review/gates/NoMaybesGate.js +145 -0
  86. package/dist/services/docs/review/gates/OpenApiCoverageGate.d.ts +7 -0
  87. package/dist/services/docs/review/gates/OpenApiCoverageGate.d.ts.map +1 -0
  88. package/dist/services/docs/review/gates/OpenApiCoverageGate.js +266 -0
  89. package/dist/services/docs/review/gates/OpenApiSchemaSanityGate.d.ts +7 -0
  90. package/dist/services/docs/review/gates/OpenApiSchemaSanityGate.d.ts.map +1 -0
  91. package/dist/services/docs/review/gates/OpenApiSchemaSanityGate.js +59 -0
  92. package/dist/services/docs/review/gates/OpenQuestionsGate.d.ts +7 -0
  93. package/dist/services/docs/review/gates/OpenQuestionsGate.d.ts.map +1 -0
  94. package/dist/services/docs/review/gates/OpenQuestionsGate.js +200 -0
  95. package/dist/services/docs/review/gates/PdrInterfacesGate.d.ts +7 -0
  96. package/dist/services/docs/review/gates/PdrInterfacesGate.d.ts.map +1 -0
  97. package/dist/services/docs/review/gates/PdrInterfacesGate.js +159 -0
  98. package/dist/services/docs/review/gates/PdrOpenQuestionsGate.d.ts +8 -0
  99. package/dist/services/docs/review/gates/PdrOpenQuestionsGate.d.ts.map +1 -0
  100. package/dist/services/docs/review/gates/PdrOpenQuestionsGate.js +129 -0
  101. package/dist/services/docs/review/gates/PdrOwnershipGate.d.ts +7 -0
  102. package/dist/services/docs/review/gates/PdrOwnershipGate.d.ts.map +1 -0
  103. package/dist/services/docs/review/gates/PdrOwnershipGate.js +169 -0
  104. package/dist/services/docs/review/gates/PlaceholderArtifactGate.d.ts +10 -0
  105. package/dist/services/docs/review/gates/PlaceholderArtifactGate.d.ts.map +1 -0
  106. package/dist/services/docs/review/gates/PlaceholderArtifactGate.js +261 -0
  107. package/dist/services/docs/review/gates/RfpConsentGate.d.ts +6 -0
  108. package/dist/services/docs/review/gates/RfpConsentGate.d.ts.map +1 -0
  109. package/dist/services/docs/review/gates/RfpConsentGate.js +127 -0
  110. package/dist/services/docs/review/gates/RfpDefinitionGate.d.ts +7 -0
  111. package/dist/services/docs/review/gates/RfpDefinitionGate.d.ts.map +1 -0
  112. package/dist/services/docs/review/gates/RfpDefinitionGate.js +173 -0
  113. package/dist/services/docs/review/gates/SdsAdaptersGate.d.ts +7 -0
  114. package/dist/services/docs/review/gates/SdsAdaptersGate.d.ts.map +1 -0
  115. package/dist/services/docs/review/gates/SdsAdaptersGate.js +196 -0
  116. package/dist/services/docs/review/gates/SdsDecisionsGate.d.ts +7 -0
  117. package/dist/services/docs/review/gates/SdsDecisionsGate.d.ts.map +1 -0
  118. package/dist/services/docs/review/gates/SdsDecisionsGate.js +89 -0
  119. package/dist/services/docs/review/gates/SdsOpsGate.d.ts +7 -0
  120. package/dist/services/docs/review/gates/SdsOpsGate.d.ts.map +1 -0
  121. package/dist/services/docs/review/gates/SdsOpsGate.js +162 -0
  122. package/dist/services/docs/review/gates/SdsPolicyTelemetryGate.d.ts +7 -0
  123. package/dist/services/docs/review/gates/SdsPolicyTelemetryGate.d.ts.map +1 -0
  124. package/dist/services/docs/review/gates/SdsPolicyTelemetryGate.js +166 -0
  125. package/dist/services/docs/review/gates/SqlRequiredTablesGate.d.ts +7 -0
  126. package/dist/services/docs/review/gates/SqlRequiredTablesGate.d.ts.map +1 -0
  127. package/dist/services/docs/review/gates/SqlRequiredTablesGate.js +273 -0
  128. package/dist/services/docs/review/gates/SqlSyntaxGate.d.ts +7 -0
  129. package/dist/services/docs/review/gates/SqlSyntaxGate.d.ts.map +1 -0
  130. package/dist/services/docs/review/gates/SqlSyntaxGate.js +203 -0
  131. package/dist/services/docs/review/gates/TerminologyNormalizationGate.d.ts +9 -0
  132. package/dist/services/docs/review/gates/TerminologyNormalizationGate.d.ts.map +1 -0
  133. package/dist/services/docs/review/gates/TerminologyNormalizationGate.js +217 -0
  134. package/dist/services/docs/review/glossary.json +47 -0
  135. package/dist/services/estimate/EstimateService.d.ts +2 -0
  136. package/dist/services/estimate/EstimateService.d.ts.map +1 -1
  137. package/dist/services/estimate/EstimateService.js +66 -18
  138. package/dist/services/estimate/VelocityService.d.ts +4 -0
  139. package/dist/services/estimate/VelocityService.d.ts.map +1 -1
  140. package/dist/services/estimate/VelocityService.js +179 -36
  141. package/dist/services/estimate/types.d.ts +1 -0
  142. package/dist/services/estimate/types.d.ts.map +1 -1
  143. package/dist/services/execution/GatewayTrioService.d.ts +200 -0
  144. package/dist/services/execution/GatewayTrioService.d.ts.map +1 -0
  145. package/dist/services/execution/GatewayTrioService.js +2492 -0
  146. package/dist/services/execution/QaApiRunner.d.ts +30 -0
  147. package/dist/services/execution/QaApiRunner.d.ts.map +1 -0
  148. package/dist/services/execution/QaApiRunner.js +881 -0
  149. package/dist/services/execution/QaFollowupService.d.ts +2 -0
  150. package/dist/services/execution/QaFollowupService.d.ts.map +1 -1
  151. package/dist/services/execution/QaFollowupService.js +9 -2
  152. package/dist/services/execution/QaPlanValidator.d.ts +10 -0
  153. package/dist/services/execution/QaPlanValidator.d.ts.map +1 -0
  154. package/dist/services/execution/QaPlanValidator.js +128 -0
  155. package/dist/services/execution/QaProfileService.d.ts +27 -1
  156. package/dist/services/execution/QaProfileService.d.ts.map +1 -1
  157. package/dist/services/execution/QaProfileService.js +354 -7
  158. package/dist/services/execution/QaTasksService.d.ts +59 -1
  159. package/dist/services/execution/QaTasksService.d.ts.map +1 -1
  160. package/dist/services/execution/QaTasksService.js +3347 -318
  161. package/dist/services/execution/QaTestCommandBuilder.d.ts +51 -0
  162. package/dist/services/execution/QaTestCommandBuilder.d.ts.map +1 -0
  163. package/dist/services/execution/QaTestCommandBuilder.js +495 -0
  164. package/dist/services/execution/TaskSelectionService.d.ts +4 -2
  165. package/dist/services/execution/TaskSelectionService.d.ts.map +1 -1
  166. package/dist/services/execution/TaskSelectionService.js +144 -28
  167. package/dist/services/execution/TaskStateService.d.ts +19 -6
  168. package/dist/services/execution/TaskStateService.d.ts.map +1 -1
  169. package/dist/services/execution/TaskStateService.js +128 -13
  170. package/dist/services/execution/WorkOnTasksService.d.ts +32 -1
  171. package/dist/services/execution/WorkOnTasksService.d.ts.map +1 -1
  172. package/dist/services/execution/WorkOnTasksService.js +4667 -722
  173. package/dist/services/jobs/JobInsightsService.d.ts +4 -0
  174. package/dist/services/jobs/JobInsightsService.d.ts.map +1 -1
  175. package/dist/services/jobs/JobInsightsService.js +51 -5
  176. package/dist/services/jobs/JobResumeService.d.ts.map +1 -1
  177. package/dist/services/jobs/JobResumeService.js +23 -10
  178. package/dist/services/jobs/JobService.d.ts +56 -4
  179. package/dist/services/jobs/JobService.d.ts.map +1 -1
  180. package/dist/services/jobs/JobService.js +232 -1
  181. package/dist/services/openapi/OpenApiService.d.ts +51 -0
  182. package/dist/services/openapi/OpenApiService.d.ts.map +1 -1
  183. package/dist/services/openapi/OpenApiService.js +953 -106
  184. package/dist/services/planning/CreateTasksService.d.ts +21 -0
  185. package/dist/services/planning/CreateTasksService.d.ts.map +1 -1
  186. package/dist/services/planning/CreateTasksService.js +569 -31
  187. package/dist/services/planning/RefineTasksService.d.ts +9 -0
  188. package/dist/services/planning/RefineTasksService.d.ts.map +1 -1
  189. package/dist/services/planning/RefineTasksService.js +409 -59
  190. package/dist/services/review/CodeReviewService.d.ts +18 -0
  191. package/dist/services/review/CodeReviewService.d.ts.map +1 -1
  192. package/dist/services/review/CodeReviewService.js +1309 -167
  193. package/dist/services/review/ReviewNormalizer.d.ts +9 -0
  194. package/dist/services/review/ReviewNormalizer.d.ts.map +1 -0
  195. package/dist/services/review/ReviewNormalizer.js +147 -0
  196. package/dist/services/shared/AuthErrors.d.ts +3 -0
  197. package/dist/services/shared/AuthErrors.d.ts.map +1 -0
  198. package/dist/services/shared/AuthErrors.js +17 -0
  199. package/dist/services/shared/DocdexGuidance.d.ts +7 -0
  200. package/dist/services/shared/DocdexGuidance.d.ts.map +1 -0
  201. package/dist/services/shared/DocdexGuidance.js +12 -0
  202. package/dist/services/shared/ProjectGuidance.d.ts +17 -0
  203. package/dist/services/shared/ProjectGuidance.d.ts.map +1 -0
  204. package/dist/services/shared/ProjectGuidance.js +78 -0
  205. package/dist/services/system/ToolDenylist.d.ts +13 -0
  206. package/dist/services/system/ToolDenylist.d.ts.map +1 -0
  207. package/dist/services/system/ToolDenylist.js +85 -0
  208. package/dist/services/tasks/TaskCommentFormatter.d.ts +20 -0
  209. package/dist/services/tasks/TaskCommentFormatter.d.ts.map +1 -0
  210. package/dist/services/tasks/TaskCommentFormatter.js +54 -0
  211. package/dist/services/telemetry/TelemetryService.d.ts.map +1 -1
  212. package/dist/services/telemetry/TelemetryService.js +39 -7
  213. package/dist/workspace/WorkspaceManager.d.ts +26 -0
  214. package/dist/workspace/WorkspaceManager.d.ts.map +1 -1
  215. package/dist/workspace/WorkspaceManager.js +206 -32
  216. package/package.json +6 -5
@@ -0,0 +1,51 @@
1
+ import { TaskRow } from '@mcoda/db';
2
+ import { type QaTestCategory, type QaTechStackId } from '@mcoda/shared';
3
+ export type QaTestCommandPlan = {
4
+ commands: string[];
5
+ source: 'override' | 'plan' | 'metadata' | 'profile' | 'stack' | 'fallback' | 'none';
6
+ categories: QaTestCategory[];
7
+ stack?: QaTechStackId;
8
+ };
9
+ export type QaTestCommandBuildInput = {
10
+ task: TaskRow & {
11
+ metadata?: any;
12
+ };
13
+ planCommands?: string[];
14
+ cliOverride?: string;
15
+ profileCommand?: string;
16
+ };
17
+ export declare class QaTestCommandBuilder {
18
+ private workspaceRoot;
19
+ constructor(workspaceRoot: string);
20
+ build(input: QaTestCommandBuildInput): Promise<QaTestCommandPlan>;
21
+ private buildStackCommands;
22
+ private buildNodeCategoryCommands;
23
+ private buildPythonCategoryCommands;
24
+ private buildDotnetCategoryCommands;
25
+ private buildJavaCategoryCommands;
26
+ private buildFlutterCategoryCommands;
27
+ private buildGoCategoryCommands;
28
+ private buildPhpCategoryCommands;
29
+ private buildRubyCategoryCommands;
30
+ private collectPackageDeps;
31
+ private hasPackageDep;
32
+ private detectViteUsage;
33
+ private resolveNodeRunner;
34
+ private buildNodeRunnerCommand;
35
+ private resolvePythonRunner;
36
+ private resolveJavaBuildTool;
37
+ private findFileByExtensionInDir;
38
+ private buildMinitestCommand;
39
+ private resolveFallbackCommand;
40
+ private detectPrimaryStack;
41
+ private detectStackFromPaths;
42
+ private readPackageJson;
43
+ private detectPackageManager;
44
+ private buildScriptCommand;
45
+ private buildPathCategoryCommands;
46
+ private findCategoryDir;
47
+ private toRelativePath;
48
+ private pathExists;
49
+ private findFileByExtension;
50
+ }
51
+ //# sourceMappingURL=QaTestCommandBuilder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QaTestCommandBuilder.d.ts","sourceRoot":"","sources":["../../../src/services/execution/QaTestCommandBuilder.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,eAAe,CAAC;AASvB,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,EAAE,UAAU,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,UAAU,GAAG,MAAM,CAAC;IACrF,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,IAAI,EAAE,OAAO,GAAG;QAAE,QAAQ,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC;IACnC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAqCF,qBAAa,oBAAoB;IACnB,OAAO,CAAC,aAAa;gBAAb,aAAa,EAAE,MAAM;IAEnC,KAAK,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,iBAAiB,CAAC;YA+DzD,kBAAkB;YAkBlB,yBAAyB;YA8BzB,2BAA2B;YAQ3B,2BAA2B;YAa3B,yBAAyB;YAoBzB,4BAA4B;YAc5B,uBAAuB;YAIvB,wBAAwB;YAYxB,yBAAyB;IAmBvC,OAAO,CAAC,kBAAkB;IAQ1B,OAAO,CAAC,aAAa;YAIP,eAAe;YASf,iBAAiB;IAU/B,OAAO,CAAC,sBAAsB;YAWhB,mBAAmB;YAUnB,oBAAoB;YAYpB,wBAAwB;IAkBtC,OAAO,CAAC,oBAAoB;YAKd,sBAAsB;YAgCtB,kBAAkB;IAyDhC,OAAO,CAAC,oBAAoB;YA4Bd,eAAe;YAUf,oBAAoB;IAUlC,OAAO,CAAC,kBAAkB;YAMZ,yBAAyB;YAazB,eAAe;IAa7B,OAAO,CAAC,cAAc;YAIR,UAAU;YASV,mBAAmB;CAQlC"}
@@ -0,0 +1,495 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { QA_TEST_CATEGORY_ORDER, } from '@mcoda/shared';
4
+ const normalizeStringArray = (value) => {
5
+ if (!Array.isArray(value))
6
+ return [];
7
+ return value
8
+ .filter((item) => typeof item === 'string')
9
+ .map((item) => item.trim())
10
+ .filter(Boolean);
11
+ };
12
+ const normalizeTestRequirements = (value) => {
13
+ const raw = value && typeof value === 'object' ? value : {};
14
+ return {
15
+ unit: normalizeStringArray(raw.unit),
16
+ component: normalizeStringArray(raw.component),
17
+ integration: normalizeStringArray(raw.integration),
18
+ api: normalizeStringArray(raw.api),
19
+ };
20
+ };
21
+ const normalizeTestCommands = (value) => {
22
+ if (typeof value === 'string') {
23
+ const trimmed = value.trim();
24
+ return trimmed ? [trimmed] : [];
25
+ }
26
+ return normalizeStringArray(value);
27
+ };
28
+ const hasRequirements = (requirements) => requirements.unit.length > 0 ||
29
+ requirements.component.length > 0 ||
30
+ requirements.integration.length > 0 ||
31
+ requirements.api.length > 0;
32
+ const normalizeCommands = (commands) => (commands ?? []).map((cmd) => cmd.trim()).filter(Boolean);
33
+ export class QaTestCommandBuilder {
34
+ constructor(workspaceRoot) {
35
+ this.workspaceRoot = workspaceRoot;
36
+ }
37
+ async build(input) {
38
+ if (input.cliOverride) {
39
+ return {
40
+ commands: [input.cliOverride],
41
+ source: 'override',
42
+ categories: [],
43
+ };
44
+ }
45
+ const planCommands = normalizeCommands(input.planCommands);
46
+ if (planCommands.length) {
47
+ return {
48
+ commands: planCommands,
49
+ source: 'plan',
50
+ categories: [],
51
+ };
52
+ }
53
+ const metadata = input.task.metadata ?? {};
54
+ const metadataCommands = normalizeTestCommands(metadata.tests ?? metadata.testCommands);
55
+ if (metadataCommands.length) {
56
+ return {
57
+ commands: metadataCommands,
58
+ source: 'metadata',
59
+ categories: [],
60
+ };
61
+ }
62
+ const profileCommand = input.profileCommand?.trim();
63
+ if (profileCommand) {
64
+ return {
65
+ commands: [profileCommand],
66
+ source: 'profile',
67
+ categories: [],
68
+ };
69
+ }
70
+ const requirements = normalizeTestRequirements(metadata.test_requirements ?? metadata.testRequirements);
71
+ const categories = QA_TEST_CATEGORY_ORDER.filter((category) => requirements[category].length > 0);
72
+ const stack = await this.detectPrimaryStack(input.task);
73
+ const commands = await this.buildStackCommands(stack, categories);
74
+ if (commands.length) {
75
+ return { commands, source: 'stack', categories, stack };
76
+ }
77
+ const fallback = await this.resolveFallbackCommand(stack);
78
+ if (fallback) {
79
+ return {
80
+ commands: [fallback],
81
+ source: 'fallback',
82
+ categories,
83
+ stack,
84
+ };
85
+ }
86
+ return { commands: [], source: 'none', categories, stack };
87
+ }
88
+ async buildStackCommands(stack, categories) {
89
+ if (!stack || categories.length === 0)
90
+ return [];
91
+ if (stack === 'node' || stack === 'react-native') {
92
+ return this.buildNodeCategoryCommands(categories);
93
+ }
94
+ if (stack === 'python')
95
+ return this.buildPythonCategoryCommands(categories);
96
+ if (stack === 'dotnet')
97
+ return this.buildDotnetCategoryCommands(categories);
98
+ if (stack === 'java')
99
+ return this.buildJavaCategoryCommands(categories);
100
+ if (stack === 'go')
101
+ return this.buildGoCategoryCommands(categories);
102
+ if (stack === 'php')
103
+ return this.buildPhpCategoryCommands(categories);
104
+ if (stack === 'ruby')
105
+ return this.buildRubyCategoryCommands(categories);
106
+ if (stack === 'flutter')
107
+ return this.buildFlutterCategoryCommands(categories);
108
+ return [];
109
+ }
110
+ async buildNodeCategoryCommands(categories) {
111
+ const pkg = await this.readPackageJson();
112
+ if (!pkg)
113
+ return [];
114
+ const pm = (await this.detectPackageManager()) ?? 'npm';
115
+ const scripts = (pkg.scripts ?? {});
116
+ const deps = this.collectPackageDeps(pkg);
117
+ const runner = await this.resolveNodeRunner(deps);
118
+ const scriptMap = {
119
+ unit: ['test:unit', 'unit'],
120
+ component: ['test:component', 'component', 'test:ui'],
121
+ integration: ['test:integration', 'integration', 'test:int'],
122
+ api: ['test:api', 'api'],
123
+ };
124
+ const commands = [];
125
+ for (const category of categories) {
126
+ const candidate = scriptMap[category].find((script) => typeof scripts[script] === 'string');
127
+ if (candidate) {
128
+ commands.push(this.buildScriptCommand(pm, candidate));
129
+ continue;
130
+ }
131
+ if (runner) {
132
+ const dir = await this.findCategoryDir(category, ['tests', 'test']);
133
+ if (dir) {
134
+ commands.push(this.buildNodeRunnerCommand(pm, runner, dir));
135
+ }
136
+ }
137
+ }
138
+ return commands;
139
+ }
140
+ async buildPythonCategoryCommands(categories) {
141
+ const runner = await this.resolvePythonRunner();
142
+ return this.buildPathCategoryCommands(categories, ['tests', 'test'], (dir) => {
143
+ if (runner === 'nose2')
144
+ return `nose2 -s ${dir}`;
145
+ return `pytest ${dir}`;
146
+ });
147
+ }
148
+ async buildDotnetCategoryCommands(categories) {
149
+ const commands = [];
150
+ for (const category of categories) {
151
+ const dir = await this.findCategoryDir(category, ['tests', 'test']);
152
+ if (!dir)
153
+ continue;
154
+ const absDir = path.join(this.workspaceRoot, dir);
155
+ const csproj = await this.findFileByExtensionInDir(absDir, '.csproj');
156
+ const target = csproj ? this.toRelativePath(csproj) : dir;
157
+ commands.push(`dotnet test ${target}`);
158
+ }
159
+ return commands;
160
+ }
161
+ async buildJavaCategoryCommands(categories) {
162
+ const buildTool = await this.resolveJavaBuildTool();
163
+ if (!buildTool)
164
+ return [];
165
+ const commands = [];
166
+ for (const category of categories) {
167
+ const dir = await this.findCategoryDir(category, ['src/test/java', 'src/test/kotlin']);
168
+ if (!dir)
169
+ continue;
170
+ const filter = `*${category}*`;
171
+ if (buildTool === 'maven') {
172
+ commands.push(`mvn -Dtest=${filter} test`);
173
+ continue;
174
+ }
175
+ const gradleBin = (await this.pathExists(path.join(this.workspaceRoot, 'gradlew')))
176
+ ? './gradlew'
177
+ : 'gradle';
178
+ commands.push(`${gradleBin} test --tests "${filter}"`);
179
+ }
180
+ return commands;
181
+ }
182
+ async buildFlutterCategoryCommands(categories) {
183
+ const commands = [];
184
+ for (const category of categories) {
185
+ if (category === 'integration') {
186
+ if (await this.pathExists(path.join(this.workspaceRoot, 'integration_test'))) {
187
+ commands.push('flutter test integration_test');
188
+ }
189
+ }
190
+ else if (category === 'unit') {
191
+ commands.push('flutter test');
192
+ }
193
+ }
194
+ return commands;
195
+ }
196
+ async buildGoCategoryCommands(categories) {
197
+ return this.buildPathCategoryCommands(categories, ['tests', 'test'], (dir) => `go test ./${dir}`);
198
+ }
199
+ async buildPhpCategoryCommands(categories) {
200
+ const vendorDir = path.join(this.workspaceRoot, 'vendor', 'bin');
201
+ const pestBin = path.join(vendorDir, 'pest');
202
+ const phpunitBin = path.join(vendorDir, 'phpunit');
203
+ const runner = (await this.pathExists(pestBin))
204
+ ? 'vendor/bin/pest'
205
+ : (await this.pathExists(phpunitBin))
206
+ ? 'vendor/bin/phpunit'
207
+ : 'phpunit';
208
+ return this.buildPathCategoryCommands(categories, ['tests', 'test'], (dir) => `${runner} ${dir}`);
209
+ }
210
+ async buildRubyCategoryCommands(categories) {
211
+ const commands = [];
212
+ const hasRakefile = await this.pathExists(path.join(this.workspaceRoot, 'Rakefile'));
213
+ for (const category of categories) {
214
+ const specDir = await this.findCategoryDir(category, ['spec']);
215
+ if (specDir) {
216
+ commands.push(`bundle exec rspec ${specDir}`);
217
+ continue;
218
+ }
219
+ const testDir = await this.findCategoryDir(category, ['test']);
220
+ if (testDir && hasRakefile) {
221
+ commands.push(`bundle exec rake test TEST=${testDir}`);
222
+ }
223
+ else if (testDir) {
224
+ commands.push(this.buildMinitestCommand(testDir));
225
+ }
226
+ }
227
+ return commands;
228
+ }
229
+ collectPackageDeps(pkg) {
230
+ return {
231
+ ...(pkg.dependencies ?? {}),
232
+ ...(pkg.devDependencies ?? {}),
233
+ ...(pkg.peerDependencies ?? {}),
234
+ };
235
+ }
236
+ hasPackageDep(deps, name) {
237
+ return typeof deps[name] === 'string';
238
+ }
239
+ async detectViteUsage(deps) {
240
+ if (this.hasPackageDep(deps, 'vite'))
241
+ return true;
242
+ return ((await this.pathExists(path.join(this.workspaceRoot, 'vite.config.ts'))) ||
243
+ (await this.pathExists(path.join(this.workspaceRoot, 'vite.config.js'))) ||
244
+ (await this.pathExists(path.join(this.workspaceRoot, 'vite.config.mjs'))));
245
+ }
246
+ async resolveNodeRunner(deps) {
247
+ const runners = ['vitest', 'jest', 'mocha', 'ava'];
248
+ const existing = runners.find((runner) => this.hasPackageDep(deps, runner));
249
+ if (existing)
250
+ return existing;
251
+ if (await this.detectViteUsage(deps))
252
+ return 'vitest';
253
+ return 'jest';
254
+ }
255
+ buildNodeRunnerCommand(pm, runner, dir) {
256
+ const args = runner === 'vitest' ? `run ${dir}` : dir;
257
+ if (pm === 'pnpm')
258
+ return `pnpm ${runner} ${args}`;
259
+ if (pm === 'yarn')
260
+ return `yarn ${runner} ${args}`;
261
+ return `npx ${runner} ${args}`;
262
+ }
263
+ async resolvePythonRunner() {
264
+ if ((await this.pathExists(path.join(this.workspaceRoot, 'nose2.cfg'))) ||
265
+ (await this.pathExists(path.join(this.workspaceRoot, 'nose2.conf')))) {
266
+ return 'nose2';
267
+ }
268
+ return 'pytest';
269
+ }
270
+ async resolveJavaBuildTool() {
271
+ if (await this.pathExists(path.join(this.workspaceRoot, 'pom.xml')))
272
+ return 'maven';
273
+ if ((await this.pathExists(path.join(this.workspaceRoot, 'gradlew'))) ||
274
+ (await this.pathExists(path.join(this.workspaceRoot, 'build.gradle'))) ||
275
+ (await this.pathExists(path.join(this.workspaceRoot, 'build.gradle.kts')))) {
276
+ return 'gradle';
277
+ }
278
+ return undefined;
279
+ }
280
+ async findFileByExtensionInDir(dir, extension) {
281
+ try {
282
+ const entries = await fs.promises.readdir(dir, { withFileTypes: true });
283
+ for (const entry of entries) {
284
+ if (!entry.isFile())
285
+ continue;
286
+ if (entry.name.toLowerCase().endsWith(extension)) {
287
+ return path.join(dir, entry.name);
288
+ }
289
+ }
290
+ }
291
+ catch {
292
+ return undefined;
293
+ }
294
+ return undefined;
295
+ }
296
+ buildMinitestCommand(dir) {
297
+ const pattern = `${dir.replace(/\/$/, '')}/**/*_test.rb`;
298
+ return `bundle exec ruby -I test -e "Dir['${pattern}'].each { |f| require f }"`;
299
+ }
300
+ async resolveFallbackCommand(stack) {
301
+ if (await this.pathExists(path.join(this.workspaceRoot, 'tests', 'all.js'))) {
302
+ return 'node tests/all.js';
303
+ }
304
+ if (stack === 'node' || stack === 'react-native') {
305
+ const pkg = await this.readPackageJson();
306
+ if (pkg?.scripts?.test) {
307
+ const pm = (await this.detectPackageManager()) ?? 'npm';
308
+ return `${pm} test`;
309
+ }
310
+ }
311
+ if (stack === 'python')
312
+ return 'pytest';
313
+ if (stack === 'dotnet')
314
+ return 'dotnet test';
315
+ if (stack === 'java') {
316
+ if (await this.pathExists(path.join(this.workspaceRoot, 'pom.xml')))
317
+ return 'mvn test';
318
+ const gradlew = path.join(this.workspaceRoot, 'gradlew');
319
+ return (await this.pathExists(gradlew)) ? './gradlew test' : 'gradle test';
320
+ }
321
+ if (stack === 'go')
322
+ return 'go test ./...';
323
+ if (stack === 'php') {
324
+ const vendorBin = path.join(this.workspaceRoot, 'vendor', 'bin', 'phpunit');
325
+ return (await this.pathExists(vendorBin)) ? 'vendor/bin/phpunit' : 'phpunit';
326
+ }
327
+ if (stack === 'ruby')
328
+ return 'bundle exec rspec';
329
+ if (stack === 'flutter')
330
+ return 'flutter test';
331
+ if (stack === 'ios')
332
+ return 'xcodebuild test';
333
+ if (stack === 'android')
334
+ return './gradlew test';
335
+ return undefined;
336
+ }
337
+ async detectPrimaryStack(task) {
338
+ const metadata = task.metadata ?? {};
339
+ const files = normalizeStringArray(metadata.files);
340
+ const reviewFiles = normalizeStringArray(metadata.last_review_changed_paths);
341
+ const combined = [...files, ...reviewFiles];
342
+ const fromFiles = this.detectStackFromPaths(combined);
343
+ if (fromFiles)
344
+ return fromFiles;
345
+ if (await this.pathExists(path.join(this.workspaceRoot, 'package.json'))) {
346
+ const pkg = await this.readPackageJson();
347
+ const deps = {
348
+ ...(pkg?.dependencies ?? {}),
349
+ ...(pkg?.devDependencies ?? {}),
350
+ ...(pkg?.peerDependencies ?? {}),
351
+ };
352
+ if (typeof deps['react-native'] === 'string' || typeof deps.expo === 'string') {
353
+ return 'react-native';
354
+ }
355
+ return 'node';
356
+ }
357
+ if ((await this.pathExists(path.join(this.workspaceRoot, 'pyproject.toml'))) ||
358
+ (await this.pathExists(path.join(this.workspaceRoot, 'requirements.txt'))) ||
359
+ (await this.pathExists(path.join(this.workspaceRoot, 'Pipfile')))) {
360
+ return 'python';
361
+ }
362
+ if (await this.findFileByExtension('.csproj'))
363
+ return 'dotnet';
364
+ if ((await this.pathExists(path.join(this.workspaceRoot, 'pom.xml'))) ||
365
+ (await this.pathExists(path.join(this.workspaceRoot, 'gradlew'))) ||
366
+ (await this.pathExists(path.join(this.workspaceRoot, 'build.gradle'))) ||
367
+ (await this.pathExists(path.join(this.workspaceRoot, 'build.gradle.kts')))) {
368
+ return 'java';
369
+ }
370
+ if (await this.pathExists(path.join(this.workspaceRoot, 'go.mod')))
371
+ return 'go';
372
+ if (await this.pathExists(path.join(this.workspaceRoot, 'composer.json')))
373
+ return 'php';
374
+ if (await this.pathExists(path.join(this.workspaceRoot, 'Gemfile')))
375
+ return 'ruby';
376
+ if (await this.pathExists(path.join(this.workspaceRoot, 'pubspec.yaml')))
377
+ return 'flutter';
378
+ if ((await this.pathExists(path.join(this.workspaceRoot, 'ios', 'Podfile'))) ||
379
+ (await this.pathExists(path.join(this.workspaceRoot, 'Package.swift')))) {
380
+ return 'ios';
381
+ }
382
+ if ((await this.pathExists(path.join(this.workspaceRoot, 'android', 'build.gradle'))) ||
383
+ (await this.pathExists(path.join(this.workspaceRoot, 'android', 'build.gradle.kts')))) {
384
+ return 'android';
385
+ }
386
+ return undefined;
387
+ }
388
+ detectStackFromPaths(paths) {
389
+ for (const raw of paths) {
390
+ const value = raw.toLowerCase();
391
+ if (value.includes('/android/'))
392
+ return 'android';
393
+ if (value.includes('/ios/'))
394
+ return 'ios';
395
+ if (value.endsWith('.dart'))
396
+ return 'flutter';
397
+ if (value.endsWith('.swift'))
398
+ return 'ios';
399
+ if (value.endsWith('.kt') || value.endsWith('.kts'))
400
+ return 'android';
401
+ if (value.endsWith('.java') || value.endsWith('.gradle'))
402
+ return 'java';
403
+ if (value.endsWith('.cs') || value.endsWith('.csproj'))
404
+ return 'dotnet';
405
+ if (value.endsWith('.go'))
406
+ return 'go';
407
+ if (value.endsWith('.php'))
408
+ return 'php';
409
+ if (value.endsWith('.rb'))
410
+ return 'ruby';
411
+ if (value.endsWith('.ts') ||
412
+ value.endsWith('.tsx') ||
413
+ value.endsWith('.js') ||
414
+ value.endsWith('.jsx') ||
415
+ value.endsWith('.mjs') ||
416
+ value.endsWith('.cjs')) {
417
+ return 'node';
418
+ }
419
+ if (value.endsWith('.py'))
420
+ return 'python';
421
+ }
422
+ return undefined;
423
+ }
424
+ async readPackageJson() {
425
+ const pkgPath = path.join(this.workspaceRoot, 'package.json');
426
+ try {
427
+ const raw = await fs.promises.readFile(pkgPath, 'utf8');
428
+ return JSON.parse(raw);
429
+ }
430
+ catch {
431
+ return undefined;
432
+ }
433
+ }
434
+ async detectPackageManager() {
435
+ if (await this.pathExists(path.join(this.workspaceRoot, 'pnpm-lock.yaml')))
436
+ return 'pnpm';
437
+ if (await this.pathExists(path.join(this.workspaceRoot, 'pnpm-workspace.yaml')))
438
+ return 'pnpm';
439
+ if (await this.pathExists(path.join(this.workspaceRoot, 'yarn.lock')))
440
+ return 'yarn';
441
+ if (await this.pathExists(path.join(this.workspaceRoot, 'package-lock.json')))
442
+ return 'npm';
443
+ if (await this.pathExists(path.join(this.workspaceRoot, 'npm-shrinkwrap.json')))
444
+ return 'npm';
445
+ if (await this.pathExists(path.join(this.workspaceRoot, 'package.json')))
446
+ return 'npm';
447
+ return undefined;
448
+ }
449
+ buildScriptCommand(pm, script) {
450
+ if (pm === 'yarn')
451
+ return `yarn ${script}`;
452
+ if (pm === 'pnpm')
453
+ return `pnpm ${script}`;
454
+ return `npm run ${script}`;
455
+ }
456
+ async buildPathCategoryCommands(categories, roots, build) {
457
+ const commands = [];
458
+ for (const category of categories) {
459
+ const dir = await this.findCategoryDir(category, roots);
460
+ if (dir)
461
+ commands.push(build(dir));
462
+ }
463
+ return commands;
464
+ }
465
+ async findCategoryDir(category, roots) {
466
+ for (const root of roots) {
467
+ const candidate = path.join(this.workspaceRoot, root, category);
468
+ if (await this.pathExists(candidate)) {
469
+ return this.toRelativePath(candidate);
470
+ }
471
+ }
472
+ return undefined;
473
+ }
474
+ toRelativePath(targetPath) {
475
+ return path.relative(this.workspaceRoot, targetPath).split(path.sep).join('/');
476
+ }
477
+ async pathExists(targetPath) {
478
+ try {
479
+ await fs.promises.access(targetPath);
480
+ return true;
481
+ }
482
+ catch {
483
+ return false;
484
+ }
485
+ }
486
+ async findFileByExtension(extension) {
487
+ try {
488
+ const entries = await fs.promises.readdir(this.workspaceRoot);
489
+ return entries.some((entry) => entry.toLowerCase().endsWith(extension));
490
+ }
491
+ catch {
492
+ return false;
493
+ }
494
+ }
495
+ }
@@ -6,8 +6,12 @@ export interface TaskSelectionFilters {
6
6
  storyKey?: string;
7
7
  taskKeys?: string[];
8
8
  statusFilter?: string[];
9
+ ignoreStatusFilter?: boolean;
10
+ includeTypes?: string[];
11
+ excludeTypes?: string[];
9
12
  limit?: number;
10
13
  parallel?: number;
14
+ ignoreDependencies?: boolean;
11
15
  }
12
16
  export interface SelectedTask {
13
17
  task: TaskRow & {
@@ -23,7 +27,6 @@ export interface SelectedTask {
23
27
  keys: string[];
24
28
  blocking: string[];
25
29
  };
26
- blockedReason?: string;
27
30
  }
28
31
  export interface TaskSelectionPlan {
29
32
  project?: ProjectRow;
@@ -31,7 +34,6 @@ export interface TaskSelectionPlan {
31
34
  effectiveStatuses: string[];
32
35
  };
33
36
  ordered: SelectedTask[];
34
- blocked: SelectedTask[];
35
37
  warnings: string[];
36
38
  }
37
39
  export declare class TaskSelectionService {
@@ -1 +1 @@
1
- {"version":3,"file":"TaskSelectionService.d.ts","sourceRoot":"","sources":["../../../src/services/execution/TaskSelectionService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAE1E,MAAM,WAAW,oBAAoB;IACnC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,OAAO,GAAG;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;KAC/B,CAAC;IACF,YAAY,EAAE;QACZ,GAAG,EAAE,MAAM,EAAE,CAAC;QACd,IAAI,EAAE,MAAM,EAAE,CAAC;QACf,QAAQ,EAAE,MAAM,EAAE,CAAC;KACpB,CAAC;IACF,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,EAAE,UAAU,CAAC;IACrB,OAAO,EAAE,oBAAoB,GAAG;QAAE,iBAAiB,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAChE,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAyDD,qBAAa,oBAAoB;IACnB,OAAO,CAAC,SAAS;IAAuB,OAAO,CAAC,aAAa;gBAArD,SAAS,EAAE,mBAAmB,EAAU,aAAa,EAAE,mBAAmB;WAEjF,MAAM,CAAC,SAAS,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAK5E,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAId,YAAY;IAK1B,OAAO,CAAC,gBAAgB;YA+BV,SAAS;YA2DT,gBAAgB;IAgC9B,OAAO,CAAC,gBAAgB;IAgElB,WAAW,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,iBAAiB,CAAC;CAiE7E"}
1
+ {"version":3,"file":"TaskSelectionService.d.ts","sourceRoot":"","sources":["../../../src/services/execution/TaskSelectionService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAErE,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAE1E,MAAM,WAAW,oBAAoB;IACnC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,OAAO,GAAG;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;KAC/B,CAAC;IACF,YAAY,EAAE;QACZ,GAAG,EAAE,MAAM,EAAE,CAAC;QACd,IAAI,EAAE,MAAM,EAAE,CAAC;QACf,QAAQ,EAAE,MAAM,EAAE,CAAC;KACpB,CAAC;CACH;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,EAAE,UAAU,CAAC;IACrB,OAAO,EAAE,oBAAoB,GAAG;QAAE,iBAAiB,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAChE,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AA0HD,qBAAa,oBAAoB;IACnB,OAAO,CAAC,SAAS;IAAuB,OAAO,CAAC,aAAa;gBAArD,SAAS,EAAE,mBAAmB,EAAU,aAAa,EAAE,mBAAmB;WAEjF,MAAM,CAAC,SAAS,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAK5E,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAId,YAAY;IAK1B,OAAO,CAAC,gBAAgB;YAiCV,SAAS;YA2DT,gBAAgB;IAgC9B,OAAO,CAAC,gBAAgB;IAgElB,WAAW,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,iBAAiB,CAAC;CA6G7E"}