@haoyiyin/workflow 0.2.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 (223) hide show
  1. package/README.md +168 -0
  2. package/SETUP.md +71 -0
  3. package/SKILL.md +68 -0
  4. package/USAGE.md +152 -0
  5. package/dist/bin/yi-workflow.d.ts +3 -0
  6. package/dist/bin/yi-workflow.d.ts.map +1 -0
  7. package/dist/bin/yi-workflow.js +39 -0
  8. package/dist/bin/yi-workflow.js.map +1 -0
  9. package/dist/src/agents/contracts.d.ts +120 -0
  10. package/dist/src/agents/contracts.d.ts.map +1 -0
  11. package/dist/src/agents/contracts.js +431 -0
  12. package/dist/src/agents/contracts.js.map +1 -0
  13. package/dist/src/agents/dispatcher-enhanced.d.ts +68 -0
  14. package/dist/src/agents/dispatcher-enhanced.d.ts.map +1 -0
  15. package/dist/src/agents/dispatcher-enhanced.js +290 -0
  16. package/dist/src/agents/dispatcher-enhanced.js.map +1 -0
  17. package/dist/src/agents/dispatcher.d.ts +107 -0
  18. package/dist/src/agents/dispatcher.d.ts.map +1 -0
  19. package/dist/src/agents/dispatcher.js +454 -0
  20. package/dist/src/agents/dispatcher.js.map +1 -0
  21. package/dist/src/agents/index.d.ts +11 -0
  22. package/dist/src/agents/index.d.ts.map +1 -0
  23. package/dist/src/agents/index.js +10 -0
  24. package/dist/src/agents/index.js.map +1 -0
  25. package/dist/src/agents/resilience.d.ts +86 -0
  26. package/dist/src/agents/resilience.d.ts.map +1 -0
  27. package/dist/src/agents/resilience.js +183 -0
  28. package/dist/src/agents/resilience.js.map +1 -0
  29. package/dist/src/agents/token-budget.d.ts +47 -0
  30. package/dist/src/agents/token-budget.d.ts.map +1 -0
  31. package/dist/src/agents/token-budget.js +63 -0
  32. package/dist/src/agents/token-budget.js.map +1 -0
  33. package/dist/src/agents/types.d.ts +59 -0
  34. package/dist/src/agents/types.d.ts.map +1 -0
  35. package/dist/src/agents/types.js +5 -0
  36. package/dist/src/agents/types.js.map +1 -0
  37. package/dist/src/guard/main-agent.d.ts +72 -0
  38. package/dist/src/guard/main-agent.d.ts.map +1 -0
  39. package/dist/src/guard/main-agent.js +184 -0
  40. package/dist/src/guard/main-agent.js.map +1 -0
  41. package/dist/src/hooks/builtin/index.d.ts +9 -0
  42. package/dist/src/hooks/builtin/index.d.ts.map +1 -0
  43. package/dist/src/hooks/builtin/index.js +9 -0
  44. package/dist/src/hooks/builtin/index.js.map +1 -0
  45. package/dist/src/hooks/builtin/on-error.d.ts +7 -0
  46. package/dist/src/hooks/builtin/on-error.d.ts.map +1 -0
  47. package/dist/src/hooks/builtin/on-error.js +15 -0
  48. package/dist/src/hooks/builtin/on-error.js.map +1 -0
  49. package/dist/src/hooks/builtin/post-execute.d.ts +7 -0
  50. package/dist/src/hooks/builtin/post-execute.d.ts.map +1 -0
  51. package/dist/src/hooks/builtin/post-execute.js +30 -0
  52. package/dist/src/hooks/builtin/post-execute.js.map +1 -0
  53. package/dist/src/hooks/builtin/post-plan.d.ts +7 -0
  54. package/dist/src/hooks/builtin/post-plan.d.ts.map +1 -0
  55. package/dist/src/hooks/builtin/post-plan.js +15 -0
  56. package/dist/src/hooks/builtin/post-plan.js.map +1 -0
  57. package/dist/src/hooks/builtin/pre-execute.d.ts +7 -0
  58. package/dist/src/hooks/builtin/pre-execute.d.ts.map +1 -0
  59. package/dist/src/hooks/builtin/pre-execute.js +22 -0
  60. package/dist/src/hooks/builtin/pre-execute.js.map +1 -0
  61. package/dist/src/hooks/builtin/pre-plan.d.ts +7 -0
  62. package/dist/src/hooks/builtin/pre-plan.d.ts.map +1 -0
  63. package/dist/src/hooks/builtin/pre-plan.js +19 -0
  64. package/dist/src/hooks/builtin/pre-plan.js.map +1 -0
  65. package/dist/src/hooks/index.d.ts +8 -0
  66. package/dist/src/hooks/index.d.ts.map +1 -0
  67. package/dist/src/hooks/index.js +4 -0
  68. package/dist/src/hooks/index.js.map +1 -0
  69. package/dist/src/hooks/loader.d.ts +16 -0
  70. package/dist/src/hooks/loader.d.ts.map +1 -0
  71. package/dist/src/hooks/loader.js +77 -0
  72. package/dist/src/hooks/loader.js.map +1 -0
  73. package/dist/src/hooks/manager.d.ts +20 -0
  74. package/dist/src/hooks/manager.d.ts.map +1 -0
  75. package/dist/src/hooks/manager.js +76 -0
  76. package/dist/src/hooks/manager.js.map +1 -0
  77. package/dist/src/hooks/types-enhanced.d.ts +30 -0
  78. package/dist/src/hooks/types-enhanced.d.ts.map +1 -0
  79. package/dist/src/hooks/types-enhanced.js +22 -0
  80. package/dist/src/hooks/types-enhanced.js.map +1 -0
  81. package/dist/src/hooks/types.d.ts +27 -0
  82. package/dist/src/hooks/types.d.ts.map +1 -0
  83. package/dist/src/hooks/types.js +2 -0
  84. package/dist/src/hooks/types.js.map +1 -0
  85. package/dist/src/index.d.ts +43 -0
  86. package/dist/src/index.d.ts.map +1 -0
  87. package/dist/src/index.js +41 -0
  88. package/dist/src/index.js.map +1 -0
  89. package/dist/src/persistence/index.d.ts +7 -0
  90. package/dist/src/persistence/index.d.ts.map +1 -0
  91. package/dist/src/persistence/index.js +6 -0
  92. package/dist/src/persistence/index.js.map +1 -0
  93. package/dist/src/persistence/plan-md.d.ts +11 -0
  94. package/dist/src/persistence/plan-md.d.ts.map +1 -0
  95. package/dist/src/persistence/plan-md.js +125 -0
  96. package/dist/src/persistence/plan-md.js.map +1 -0
  97. package/dist/src/persistence/state-md.d.ts +17 -0
  98. package/dist/src/persistence/state-md.d.ts.map +1 -0
  99. package/dist/src/persistence/state-md.js +143 -0
  100. package/dist/src/persistence/state-md.js.map +1 -0
  101. package/dist/src/persistence/types.d.ts +85 -0
  102. package/dist/src/persistence/types.d.ts.map +1 -0
  103. package/dist/src/persistence/types.js +5 -0
  104. package/dist/src/persistence/types.js.map +1 -0
  105. package/dist/src/router/classifier.d.ts +108 -0
  106. package/dist/src/router/classifier.d.ts.map +1 -0
  107. package/dist/src/router/classifier.js +476 -0
  108. package/dist/src/router/classifier.js.map +1 -0
  109. package/dist/src/router/guard.d.ts +128 -0
  110. package/dist/src/router/guard.d.ts.map +1 -0
  111. package/dist/src/router/guard.js +370 -0
  112. package/dist/src/router/guard.js.map +1 -0
  113. package/dist/src/router/index.d.ts +10 -0
  114. package/dist/src/router/index.d.ts.map +1 -0
  115. package/dist/src/router/index.js +8 -0
  116. package/dist/src/router/index.js.map +1 -0
  117. package/dist/src/router/router.d.ts +58 -0
  118. package/dist/src/router/router.d.ts.map +1 -0
  119. package/dist/src/router/router.js +78 -0
  120. package/dist/src/router/router.js.map +1 -0
  121. package/dist/src/router/types.d.ts +100 -0
  122. package/dist/src/router/types.d.ts.map +1 -0
  123. package/dist/src/router/types.js +24 -0
  124. package/dist/src/router/types.js.map +1 -0
  125. package/dist/src/skills/agents-md/index.d.ts +9 -0
  126. package/dist/src/skills/agents-md/index.d.ts.map +1 -0
  127. package/dist/src/skills/agents-md/index.js +28 -0
  128. package/dist/src/skills/agents-md/index.js.map +1 -0
  129. package/dist/src/skills/execute-plan/index.d.ts +141 -0
  130. package/dist/src/skills/execute-plan/index.d.ts.map +1 -0
  131. package/dist/src/skills/execute-plan/index.js +784 -0
  132. package/dist/src/skills/execute-plan/index.js.map +1 -0
  133. package/dist/src/skills/index.d.ts +14 -0
  134. package/dist/src/skills/index.d.ts.map +1 -0
  135. package/dist/src/skills/index.js +10 -0
  136. package/dist/src/skills/index.js.map +1 -0
  137. package/dist/src/skills/quick-task/index.d.ts +75 -0
  138. package/dist/src/skills/quick-task/index.d.ts.map +1 -0
  139. package/dist/src/skills/quick-task/index.js +284 -0
  140. package/dist/src/skills/quick-task/index.js.map +1 -0
  141. package/dist/src/skills/registry.d.ts +15 -0
  142. package/dist/src/skills/registry.d.ts.map +1 -0
  143. package/dist/src/skills/registry.js +44 -0
  144. package/dist/src/skills/registry.js.map +1 -0
  145. package/dist/src/skills/review-diff/index.d.ts +96 -0
  146. package/dist/src/skills/review-diff/index.d.ts.map +1 -0
  147. package/dist/src/skills/review-diff/index.js +316 -0
  148. package/dist/src/skills/review-diff/index.js.map +1 -0
  149. package/dist/src/skills/skill.d.ts +24 -0
  150. package/dist/src/skills/skill.d.ts.map +1 -0
  151. package/dist/src/skills/skill.js +39 -0
  152. package/dist/src/skills/skill.js.map +1 -0
  153. package/dist/src/skills/systematic-debugging/index.d.ts +90 -0
  154. package/dist/src/skills/systematic-debugging/index.d.ts.map +1 -0
  155. package/dist/src/skills/systematic-debugging/index.js +305 -0
  156. package/dist/src/skills/systematic-debugging/index.js.map +1 -0
  157. package/dist/src/skills/tdd/index.d.ts +103 -0
  158. package/dist/src/skills/tdd/index.d.ts.map +1 -0
  159. package/dist/src/skills/tdd/index.js +338 -0
  160. package/dist/src/skills/tdd/index.js.map +1 -0
  161. package/dist/src/skills/to-plan/index-enhanced.d.ts +100 -0
  162. package/dist/src/skills/to-plan/index-enhanced.d.ts.map +1 -0
  163. package/dist/src/skills/to-plan/index-enhanced.js +452 -0
  164. package/dist/src/skills/to-plan/index-enhanced.js.map +1 -0
  165. package/dist/src/skills/to-plan/index.d.ts +131 -0
  166. package/dist/src/skills/to-plan/index.d.ts.map +1 -0
  167. package/dist/src/skills/to-plan/index.js +460 -0
  168. package/dist/src/skills/to-plan/index.js.map +1 -0
  169. package/dist/src/skills/types.d.ts +44 -0
  170. package/dist/src/skills/types.d.ts.map +1 -0
  171. package/dist/src/skills/types.js +2 -0
  172. package/dist/src/skills/types.js.map +1 -0
  173. package/dist/src/state/cleanup.d.ts +22 -0
  174. package/dist/src/state/cleanup.d.ts.map +1 -0
  175. package/dist/src/state/cleanup.js +87 -0
  176. package/dist/src/state/cleanup.js.map +1 -0
  177. package/dist/src/state/index.d.ts +9 -0
  178. package/dist/src/state/index.d.ts.map +1 -0
  179. package/dist/src/state/index.js +5 -0
  180. package/dist/src/state/index.js.map +1 -0
  181. package/dist/src/state/manager.d.ts +15 -0
  182. package/dist/src/state/manager.d.ts.map +1 -0
  183. package/dist/src/state/manager.js +73 -0
  184. package/dist/src/state/manager.js.map +1 -0
  185. package/dist/src/state/persistence.d.ts +13 -0
  186. package/dist/src/state/persistence.d.ts.map +1 -0
  187. package/dist/src/state/persistence.js +68 -0
  188. package/dist/src/state/persistence.js.map +1 -0
  189. package/dist/src/state/types.d.ts +26 -0
  190. package/dist/src/state/types.d.ts.map +1 -0
  191. package/dist/src/state/types.js +2 -0
  192. package/dist/src/state/types.js.map +1 -0
  193. package/dist/src/state/validator.d.ts +12 -0
  194. package/dist/src/state/validator.d.ts.map +1 -0
  195. package/dist/src/state/validator.js +56 -0
  196. package/dist/src/state/validator.js.map +1 -0
  197. package/dist/src/types.d.ts +83 -0
  198. package/dist/src/types.d.ts.map +1 -0
  199. package/dist/src/types.js +5 -0
  200. package/dist/src/types.js.map +1 -0
  201. package/dist/src/utils/compress.d.ts +37 -0
  202. package/dist/src/utils/compress.d.ts.map +1 -0
  203. package/dist/src/utils/compress.js +298 -0
  204. package/dist/src/utils/compress.js.map +1 -0
  205. package/dist/src/utils/git.d.ts +9 -0
  206. package/dist/src/utils/git.d.ts.map +1 -0
  207. package/dist/src/utils/git.js +81 -0
  208. package/dist/src/utils/git.js.map +1 -0
  209. package/dist/src/utils/index.d.ts +7 -0
  210. package/dist/src/utils/index.d.ts.map +1 -0
  211. package/dist/src/utils/index.js +7 -0
  212. package/dist/src/utils/index.js.map +1 -0
  213. package/dist/src/utils/logger.d.ts +6 -0
  214. package/dist/src/utils/logger.d.ts.map +1 -0
  215. package/dist/src/utils/logger.js +19 -0
  216. package/dist/src/utils/logger.js.map +1 -0
  217. package/dist/src/utils/paths.d.ts +12 -0
  218. package/dist/src/utils/paths.d.ts.map +1 -0
  219. package/dist/src/utils/paths.js +44 -0
  220. package/dist/src/utils/paths.js.map +1 -0
  221. package/package.json +76 -0
  222. package/scripts/postinstall.js +69 -0
  223. package/yi-workflow.js +17 -0
@@ -0,0 +1,370 @@
1
+ /**
2
+ * Main Agent Guard - enforces that the main agent NEVER does substantive work.
3
+ *
4
+ * The guard is the enforcement mechanism for the "thin dispatcher" pattern.
5
+ * When embargo is active, the main agent is blocked from everything except
6
+ * meta-operations (reading plan files, state files, and dispatching subagents).
7
+ *
8
+ * Usage:
9
+ * ```typescript
10
+ * const guard = MainAgentGuard.create({
11
+ * defaultModel: 'haiku',
12
+ * planningThreshold: 0.6,
13
+ * maxMainAgentTokens: 10000,
14
+ * autoRoute: true,
15
+ * })
16
+ *
17
+ * const check = guard.checkOperation('read-source', { path: 'src/main.ts' })
18
+ * if (!check.allowed) {
19
+ * throw new Error(check.reason)
20
+ * }
21
+ * ```
22
+ */
23
+ import { MAIN_AGENT_PROHIBITED } from './types.js';
24
+ // ---------------------------------------------------------------------------
25
+ // Helpers
26
+ // ---------------------------------------------------------------------------
27
+ const META_OPERATIONS = new Set([
28
+ 'dispatch-subagent',
29
+ 'relay-results',
30
+ 'read-meta-file',
31
+ 'read-plan',
32
+ 'read-state',
33
+ 'list-plans',
34
+ 'check-state',
35
+ 'read-config',
36
+ ]);
37
+ const ALWAYS_ALLOWED_PATHS = [
38
+ '.pi/plans/**',
39
+ '.pi/yi-workflow/state/**',
40
+ 'SKILL.md',
41
+ 'AGENTS.md',
42
+ 'CLAUDE.md',
43
+ 'package.json',
44
+ '.claude/**',
45
+ ];
46
+ const ALWAYS_FORBIDDEN_PATHS = [
47
+ 'src/**',
48
+ 'lib/**',
49
+ 'app/**',
50
+ 'dist/**',
51
+ 'node_modules/**',
52
+ '**/*.test.ts',
53
+ '**/*.spec.ts',
54
+ '**/*.test.tsx',
55
+ '**/*.spec.tsx',
56
+ ];
57
+ /**
58
+ * Parses a simple glob pattern into a regex for matching.
59
+ * Supports ** for recursive matching and * for single-segment.
60
+ */
61
+ function globToRegex(pattern) {
62
+ const escaped = pattern
63
+ .replace(/[.+^${}()|[\]\\]/g, '\\$&')
64
+ .replace(/\*\*/g, '___DOUBLESTAR___')
65
+ .replace(/\*/g, '[^/]*')
66
+ .replace(/___DOUBLESTAR___/g, '.*');
67
+ return new RegExp(`^${escaped}$`);
68
+ }
69
+ /** Check whether a path matches any of the given glob patterns. */
70
+ function matchesAnyGlob(filePath, patterns) {
71
+ const normalized = filePath.replace(/^\.\//, '');
72
+ for (const pattern of patterns) {
73
+ const regex = globToRegex(pattern);
74
+ if (regex.test(normalized)) {
75
+ return true;
76
+ }
77
+ }
78
+ return false;
79
+ }
80
+ // ---------------------------------------------------------------------------
81
+ // MainAgentGuard
82
+ // ---------------------------------------------------------------------------
83
+ /**
84
+ * Enforces the "main agent as thin dispatcher" constraint.
85
+ *
86
+ * When embargoActive is true, the main agent is FORBIDDEN from doing
87
+ * ANY substantive work. It can only read meta-files and dispatch subagents.
88
+ */
89
+ export class MainAgentGuard {
90
+ config;
91
+ violations;
92
+ pendingSubagents;
93
+ embargoActive;
94
+ tokensUsed;
95
+ constructor(config) {
96
+ this.config = Object.freeze({ ...config });
97
+ this.violations = [];
98
+ this.pendingSubagents = new Set();
99
+ this.embargoActive = false;
100
+ this.tokensUsed = 0;
101
+ }
102
+ // -----------------------------------------------------------------------
103
+ // Factory methods
104
+ // -----------------------------------------------------------------------
105
+ /** Create a guard with embargo active (strictest mode). */
106
+ static createEmbargoAll(config) {
107
+ const guard = new MainAgentGuard(config);
108
+ guard.activateEmbargo();
109
+ return guard;
110
+ }
111
+ /** Create a guard with embargo lifted (use with extreme caution). */
112
+ static createDisabled(config) {
113
+ return new MainAgentGuard(config);
114
+ }
115
+ /** Convenience: create with default config. */
116
+ static create(config) {
117
+ return new MainAgentGuard(config);
118
+ }
119
+ // -----------------------------------------------------------------------
120
+ // Operation checks
121
+ // -----------------------------------------------------------------------
122
+ /**
123
+ * Check whether an operation is permitted for the main agent.
124
+ *
125
+ * @param operation - The operation being attempted
126
+ * @returns GuardCheckResult with allowed flag and reason
127
+ */
128
+ checkOperation(operation) {
129
+ // If embargo is inactive, everything is permitted
130
+ if (!this.embargoActive) {
131
+ return {
132
+ allowed: true,
133
+ reason: 'Embargo is inactive - main agent may operate',
134
+ rule: 'embargo-off',
135
+ };
136
+ }
137
+ // Meta-operations are always allowed (they ARE the main agent's job)
138
+ if (META_OPERATIONS.has(operation)) {
139
+ return {
140
+ allowed: true,
141
+ reason: 'Meta-operation permitted for orchestration',
142
+ rule: 'meta-operation',
143
+ };
144
+ }
145
+ // Check against prohibited operations
146
+ const prohibitionMap = {
147
+ 'read-source': MAIN_AGENT_PROHIBITED.readSourceFiles,
148
+ 'search-codebase': MAIN_AGENT_PROHIBITED.searchCodebase,
149
+ 'write-files': MAIN_AGENT_PROHIBITED.writeFiles,
150
+ 'edit-files': MAIN_AGENT_PROHIBITED.writeFiles,
151
+ 'run-build': MAIN_AGENT_PROHIBITED.runBuildCommands,
152
+ 'run-tests': MAIN_AGENT_PROHIBITED.runTests,
153
+ 'git-commit': MAIN_AGENT_PROHIBITED.writeFiles,
154
+ 'git-push': MAIN_AGENT_PROHIBITED.writeFiles,
155
+ 'read-diffs': MAIN_AGENT_PROHIBITED.readSourceFiles,
156
+ 'long-running-task': MAIN_AGENT_PROHIBITED.longRunningTasks,
157
+ };
158
+ if (prohibitionMap[operation]) {
159
+ return {
160
+ allowed: false,
161
+ reason: `Operation "${operation}" is prohibited for the main agent`,
162
+ rule: 'prohibited-operation',
163
+ };
164
+ }
165
+ // Unknown operations under embargo: deny by default
166
+ return {
167
+ allowed: false,
168
+ reason: `Operation "${operation}" is not recognized and embargo is active`,
169
+ rule: 'unknown-operation-deny',
170
+ };
171
+ }
172
+ /**
173
+ * Check whether a file path is permitted to be read by the main agent.
174
+ */
175
+ checkReadPath(filePath) {
176
+ if (!this.embargoActive) {
177
+ return { allowed: true, reason: 'Embargo is inactive', rule: 'embargo-off' };
178
+ }
179
+ const normalized = filePath.replace(/^\.\//, '');
180
+ // Explicitly forbidden paths take precedence
181
+ if (matchesAnyGlob(normalized, ALWAYS_FORBIDDEN_PATHS)) {
182
+ return {
183
+ allowed: false,
184
+ reason: `Path "${filePath}" is forbidden under embargo`,
185
+ rule: 'forbidden-path',
186
+ };
187
+ }
188
+ // Check if path is in the allowed list
189
+ if (matchesAnyGlob(normalized, ALWAYS_ALLOWED_PATHS)) {
190
+ return { allowed: true, reason: 'Path is in the allowed list', rule: 'allowed-path' };
191
+ }
192
+ // Default: deny
193
+ return {
194
+ allowed: false,
195
+ reason: `Path "${filePath}" is not in the allowed list and embargo is active`,
196
+ rule: 'default-deny-path',
197
+ };
198
+ }
199
+ /**
200
+ * Comprehensive check combining operation and optional file path/context.
201
+ */
202
+ check(context) {
203
+ // Check the operation
204
+ const opCheck = this.checkOperation(context.operation);
205
+ if (!opCheck.allowed) {
206
+ return opCheck;
207
+ }
208
+ // If a path is provided, check read access
209
+ if (context.path) {
210
+ const pathCheck = this.checkReadPath(context.path);
211
+ if (!pathCheck.allowed) {
212
+ return pathCheck;
213
+ }
214
+ }
215
+ // Check token budget
216
+ if (this.tokensUsed > this.config.maxMainAgentTokens) {
217
+ return {
218
+ allowed: false,
219
+ reason: `Token budget exceeded: ${this.tokensUsed}/${this.config.maxMainAgentTokens}`,
220
+ rule: 'token-budget-exceeded',
221
+ };
222
+ }
223
+ return { allowed: true, reason: 'All checks passed' };
224
+ }
225
+ /**
226
+ * Assert an operation is allowed. Throws if violated.
227
+ */
228
+ assertAllowed(context) {
229
+ const result = this.check(context);
230
+ if (!result.allowed) {
231
+ const error = new Error(`GUARD VIOLATION: ${result.reason}\n` +
232
+ `Operation: ${context.operation}\n` +
233
+ `${context.path ? `Path: ${context.path}\n` : ''}` +
234
+ `Rule: ${result.rule}`);
235
+ this.violations.push({
236
+ operation: context.operation,
237
+ path: context.path,
238
+ timestamp: new Date(),
239
+ reason: result.reason,
240
+ });
241
+ throw error;
242
+ }
243
+ }
244
+ /**
245
+ * Record a violation without throwing (for audit trail).
246
+ */
247
+ recordViolation(context) {
248
+ const result = this.check(context);
249
+ this.violations.push({
250
+ operation: context.operation,
251
+ path: context.path,
252
+ timestamp: new Date(),
253
+ reason: result.reason,
254
+ });
255
+ }
256
+ // -----------------------------------------------------------------------
257
+ // Embargo control
258
+ // -----------------------------------------------------------------------
259
+ /** Activate embargo mode - main agent must delegate everything. */
260
+ activateEmbargo() {
261
+ this.embargoActive = true;
262
+ }
263
+ /** Deactivate embargo mode - main agent regains limited capabilities. */
264
+ deactivateEmbargo() {
265
+ this.embargoActive = false;
266
+ }
267
+ /** Check if embargo is currently active. */
268
+ isEmbargoActive() {
269
+ return this.embargoActive;
270
+ }
271
+ // -----------------------------------------------------------------------
272
+ // Subagent tracking
273
+ // -----------------------------------------------------------------------
274
+ /** Register a dispatched subagent. */
275
+ registerSubagent(id) {
276
+ this.pendingSubagents.add(id);
277
+ }
278
+ /** Mark a subagent as completed. */
279
+ completeSubagent(id) {
280
+ this.pendingSubagents.delete(id);
281
+ }
282
+ /** Check if there are any subagents still pending. */
283
+ hasPendingSubagents() {
284
+ return this.pendingSubagents.size > 0;
285
+ }
286
+ // -----------------------------------------------------------------------
287
+ // Token tracking
288
+ // -----------------------------------------------------------------------
289
+ /** Track token usage by the main agent. */
290
+ trackTokens(count) {
291
+ this.tokensUsed += count;
292
+ }
293
+ /** Get current token usage. */
294
+ getTokensUsed() {
295
+ return this.tokensUsed;
296
+ }
297
+ /** Percentage of token budget consumed (0-1). */
298
+ tokenBudgetUtilization() {
299
+ return this.tokensUsed / this.config.maxMainAgentTokens;
300
+ }
301
+ // -----------------------------------------------------------------------
302
+ // Status and reporting
303
+ // -----------------------------------------------------------------------
304
+ /** Current guard status snapshot. */
305
+ getStatus() {
306
+ return {
307
+ embargoActive: this.embargoActive,
308
+ pendingSubagents: [...this.pendingSubagents],
309
+ violations: [...this.violations],
310
+ prohibitedOperations: Object.entries(MAIN_AGENT_PROHIBITED)
311
+ .filter(([, prohibited]) => prohibited)
312
+ .map(([key]) => key),
313
+ allowedPaths: [...ALWAYS_ALLOWED_PATHS],
314
+ forbiddenPaths: [...ALWAYS_FORBIDDEN_PATHS],
315
+ };
316
+ }
317
+ /**
318
+ * Generate the system prompt fragment that enforces guard rules.
319
+ * Injected into the main agent's system prompt.
320
+ */
321
+ generateSystemPromptFragment() {
322
+ if (!this.embargoActive) {
323
+ return `
324
+ ## Main Agent Guard: INACTIVE
325
+
326
+ The guard is currently disabled. You may operate normally,
327
+ but prefer delegation to subagents for substantive work where possible.
328
+ `;
329
+ }
330
+ const prohibited = Object.entries(MAIN_AGENT_PROHIBITED)
331
+ .filter(([, v]) => v)
332
+ .map(([k]) => `- ❌ ${k}`)
333
+ .join('\n');
334
+ const allowed = [...ALWAYS_ALLOWED_PATHS].map((p) => `- ${p}`).join('\n');
335
+ const pendingCount = this.pendingSubagents.size;
336
+ const tokenPct = Math.round(this.tokenBudgetUtilization() * 100);
337
+ return `
338
+ ## CRITICAL: Main Agent Guard — EMBARGO ACTIVE
339
+
340
+ You are a **thin dispatcher**, NOT an executor. Your only job:
341
+ 1. Classify the user's request
342
+ 2. Dispatch subagents to do the actual work
343
+ 3. Relay subagent results back to the user
344
+
345
+ ### Prohibited (NEVER do these):
346
+ ${prohibited}
347
+
348
+ ### Allowed to read ONLY:
349
+ ${allowed}
350
+
351
+ ### Status:
352
+ - Token budget: ${tokenPct}% used (${this.tokensUsed}/${this.config.maxMainAgentTokens})
353
+ - Pending subagents: ${pendingCount}
354
+ - Violations recorded: ${this.violations.length}
355
+
356
+ ### Routing rules:
357
+ - Trivial typo/whitespace → handle directly (1-2 char fix)
358
+ - Small scoped change → dispatch quick-task agent
359
+ - New feature / complex change → dispatch to-plan → then execute-plan
360
+ - Bug/debugging → dispatch systematic-debugging agent
361
+ - Code review → dispatch review-diff agent
362
+ - Research/exploration → dispatch explorer agent
363
+ - TDD work → dispatch tdd agent
364
+ - Everything else → dispatch general subagent
365
+
366
+ ### NEVER execute any task yourself. ALWAYS use the Agent tool.
367
+ `;
368
+ }
369
+ }
370
+ //# sourceMappingURL=guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guard.js","sourceRoot":"","sources":["../../../src/router/guard.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Router module index
3
+ *
4
+ * The router ensures ALL user requests go through subagents.
5
+ * Main Agent is a "thin dispatcher" — it NEVER executes tasks itself.
6
+ */
7
+ export type { IntentClassification, IntentType, RouterConfig, RoutingDecision, SubagentContract, PermissionSet, RouterInput, RouterOutput, MAIN_AGENT_PROHIBITED, ROUTE_KEYWORDS, } from './types.js';
8
+ export { createRouter } from './router.js';
9
+ export type { Router } from './router.js';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/router/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,YAAY,EACV,oBAAoB,EACpB,UAAU,EACV,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,WAAW,EACX,YAAY,EACZ,qBAAqB,EACrB,cAAc,GACf,MAAM,YAAY,CAAA;AAEnB,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,YAAY,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Router module index
3
+ *
4
+ * The router ensures ALL user requests go through subagents.
5
+ * Main Agent is a "thin dispatcher" — it NEVER executes tasks itself.
6
+ */
7
+ export { createRouter } from './router.js';
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/router/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAeH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Router - wires up classification and guard into a single dispatch pipeline.
3
+ *
4
+ * The createRouter factory produces an object that:
5
+ * 1. Classifies user requests
6
+ * 2. Validates against main-agent guard rules
7
+ * 3. Produces a routing decision (what subagent to dispatch)
8
+ *
9
+ * Usage:
10
+ * ```typescript
11
+ * import { createRouter } from './router/router.js'
12
+ * import type { RouterConfig } from './router/types.js'
13
+ *
14
+ * const config: RouterConfig = {
15
+ * defaultModel: 'haiku',
16
+ * planningThreshold: 0.6,
17
+ * maxMainAgentTokens: 10000,
18
+ * autoRoute: true,
19
+ * }
20
+ *
21
+ * const router = createRouter(config)
22
+ * const output = router.route({
23
+ * request: "Fix the typo in src/utils.ts",
24
+ * planFileExists: false,
25
+ * isExecutingPlan: false,
26
+ * hasUncommittedChanges: true,
27
+ * mentionedFiles: ['src/utils.ts'],
28
+ * })
29
+ * // output.classification.type === 'quick-task'
30
+ * ```
31
+ */
32
+ import type { RouterConfig, RouterInput, RouterOutput } from './types.js';
33
+ import { RequestClassifier } from './classifier.js';
34
+ import { MainAgentGuard } from './guard.js';
35
+ /**
36
+ * High-level router interface.
37
+ */
38
+ export interface Router {
39
+ /** Classify a request and produce a routing decision */
40
+ route: (input: RouterInput) => RouterOutput;
41
+ /** Get the underlying classifier */
42
+ classifier: RequestClassifier;
43
+ /** Get the underlying guard */
44
+ guard: MainAgentGuard;
45
+ /** Generate the system prompt fragment for the main agent */
46
+ generateSystemPrompt: () => string;
47
+ /** Check if an operation is allowed under current guard state */
48
+ isOperationAllowed: (operation: string) => boolean;
49
+ }
50
+ /**
51
+ * Create a router with the given configuration.
52
+ *
53
+ * Wires together:
54
+ * - RequestClassifier: analyzes user input, determines intent
55
+ * - MainAgentGuard: enforces thin-dispatcher constraints
56
+ */
57
+ export declare function createRouter(config: RouterConfig): Router;
58
+ //# sourceMappingURL=router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../../src/router/router.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AACzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAEnD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAE3C;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB,wDAAwD;IACxD,KAAK,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,YAAY,CAAA;IAE3C,oCAAoC;IACpC,UAAU,EAAE,iBAAiB,CAAA;IAE7B,+BAA+B;IAC/B,KAAK,EAAE,cAAc,CAAA;IAErB,6DAA6D;IAC7D,oBAAoB,EAAE,MAAM,MAAM,CAAA;IAElC,iEAAiE;IACjE,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAA;CACnD;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CA2CzD"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Router - wires up classification and guard into a single dispatch pipeline.
3
+ *
4
+ * The createRouter factory produces an object that:
5
+ * 1. Classifies user requests
6
+ * 2. Validates against main-agent guard rules
7
+ * 3. Produces a routing decision (what subagent to dispatch)
8
+ *
9
+ * Usage:
10
+ * ```typescript
11
+ * import { createRouter } from './router/router.js'
12
+ * import type { RouterConfig } from './router/types.js'
13
+ *
14
+ * const config: RouterConfig = {
15
+ * defaultModel: 'haiku',
16
+ * planningThreshold: 0.6,
17
+ * maxMainAgentTokens: 10000,
18
+ * autoRoute: true,
19
+ * }
20
+ *
21
+ * const router = createRouter(config)
22
+ * const output = router.route({
23
+ * request: "Fix the typo in src/utils.ts",
24
+ * planFileExists: false,
25
+ * isExecutingPlan: false,
26
+ * hasUncommittedChanges: true,
27
+ * mentionedFiles: ['src/utils.ts'],
28
+ * })
29
+ * // output.classification.type === 'quick-task'
30
+ * ```
31
+ */
32
+ import { RequestClassifier } from './classifier.js';
33
+ import { MainAgentGuard } from './guard.js';
34
+ /**
35
+ * Create a router with the given configuration.
36
+ *
37
+ * Wires together:
38
+ * - RequestClassifier: analyzes user input, determines intent
39
+ * - MainAgentGuard: enforces thin-dispatcher constraints
40
+ */
41
+ export function createRouter(config) {
42
+ const classifier = new RequestClassifier(config);
43
+ const guard = new MainAgentGuard(config);
44
+ function route(input) {
45
+ const context = {
46
+ planFileExists: input.planFileExists,
47
+ isExecutingPlan: input.isExecutingPlan,
48
+ hasUncommittedChanges: input.hasUncommittedChanges,
49
+ currentBranch: input.currentBranch,
50
+ mentionedFiles: input.mentionedFiles,
51
+ };
52
+ const result = classifier.classify(input.request, context);
53
+ // Activate embargo after routing (unless trivial edit)
54
+ if (result.classification.type !== 'quick-task') {
55
+ guard.activateEmbargo();
56
+ }
57
+ return {
58
+ classification: result.classification,
59
+ routing: result.routing,
60
+ confidence: result.confidence,
61
+ matchedRule: result.matchedRule,
62
+ };
63
+ }
64
+ function generateSystemPrompt() {
65
+ return guard.generateSystemPromptFragment();
66
+ }
67
+ function isOperationAllowed(operation) {
68
+ return guard.checkOperation(operation).allowed;
69
+ }
70
+ return {
71
+ route,
72
+ classifier,
73
+ guard,
74
+ generateSystemPrompt,
75
+ isOperationAllowed,
76
+ };
77
+ }
78
+ //# sourceMappingURL=router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.js","sourceRoot":"","sources":["../../../src/router/router.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAEnD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAsB3C;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,MAAoB;IAC/C,MAAM,UAAU,GAAG,IAAI,iBAAiB,CAAC,MAAM,CAAC,CAAA;IAChD,MAAM,KAAK,GAAG,IAAI,cAAc,CAAC,MAAM,CAAC,CAAA;IAExC,SAAS,KAAK,CAAC,KAAkB;QAC/B,MAAM,OAAO,GAA0B;YACrC,cAAc,EAAE,KAAK,CAAC,cAAc;YACpC,eAAe,EAAE,KAAK,CAAC,eAAe;YACtC,qBAAqB,EAAE,KAAK,CAAC,qBAAqB;YAClD,aAAa,EAAE,KAAK,CAAC,aAAa;YAClC,cAAc,EAAE,KAAK,CAAC,cAAc;SACrC,CAAA;QAED,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;QAE1D,uDAAuD;QACvD,IAAI,MAAM,CAAC,cAAc,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YAChD,KAAK,CAAC,eAAe,EAAE,CAAA;QACzB,CAAC;QAED,OAAO;YACL,cAAc,EAAE,MAAM,CAAC,cAAc;YACrC,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,WAAW,EAAE,MAAM,CAAC,WAAW;SAChC,CAAA;IACH,CAAC;IAED,SAAS,oBAAoB;QAC3B,OAAO,KAAK,CAAC,4BAA4B,EAAE,CAAA;IAC7C,CAAC;IAED,SAAS,kBAAkB,CAAC,SAAiB;QAC3C,OAAO,KAAK,CAAC,cAAc,CAAC,SAAuD,CAAC,CAAC,OAAO,CAAA;IAC9F,CAAC;IAED,OAAO;QACL,KAAK;QACL,UAAU;QACV,KAAK;QACL,oBAAoB;QACpB,kBAAkB;KACnB,CAAA;AACH,CAAC"}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Router system types - Controls all user input routing
3
+ */
4
+ import type { SubagentConfig, SubagentResult } from '../agents/types.js';
5
+ /** Classification of user intent */
6
+ export type IntentType = 'plan' | 'quick-task' | 'execute' | 'review' | 'debug' | 'tdd' | 'general';
7
+ export interface IntentClassification {
8
+ type: IntentType;
9
+ confidence: number;
10
+ reasoning: string;
11
+ suggestedAgent: string;
12
+ }
13
+ export interface RouterConfig {
14
+ /** Default model for subagents */
15
+ defaultModel: string;
16
+ /** Threshold for routing to quick-task vs to-plan */
17
+ planningThreshold: number;
18
+ /** Max tokens before forcing subagent dispatch */
19
+ maxMainAgentTokens: number;
20
+ /** Whether to auto-route based on keywords */
21
+ autoRoute: boolean;
22
+ }
23
+ export interface RoutingDecision {
24
+ /** The subagent to dispatch */
25
+ subagent: SubagentConfig;
26
+ /** Contract/prompt for the subagent */
27
+ contract: SubagentContract;
28
+ /** Whether to wait for result or stream */
29
+ async: boolean;
30
+ }
31
+ export interface SubagentContract {
32
+ /** What this subagent is allowed to do */
33
+ permissions: PermissionSet;
34
+ /** Exact prompt to send */
35
+ prompt: string;
36
+ /** Required output format */
37
+ outputSchema?: Record<string, unknown>;
38
+ /** Files this subagent owns */
39
+ owns: string[];
40
+ /** Files this subagent may read */
41
+ reads: string[];
42
+ }
43
+ export interface PermissionSet {
44
+ readFiles: boolean;
45
+ searchCode: boolean;
46
+ runCommands: boolean;
47
+ writeFiles: boolean;
48
+ gitOperations: boolean;
49
+ }
50
+ export interface RouterResult {
51
+ decision: RoutingDecision;
52
+ /** Estimated token usage */
53
+ estimatedTokens: number;
54
+ /** Fallback if subagent fails */
55
+ fallbackStrategy: 'retry' | 'escalate' | 'abort';
56
+ }
57
+ export interface ExecutionResult {
58
+ success: boolean;
59
+ result?: SubagentResult;
60
+ error?: string;
61
+ /** Tokens used by entire routing chain */
62
+ totalTokens: number;
63
+ /** Time taken */
64
+ duration: number;
65
+ }
66
+ /** Input to the router: raw request + classification context. */
67
+ export interface RouterInput {
68
+ /** Raw user request text */
69
+ request: string;
70
+ /** Whether a plan file already exists */
71
+ planFileExists: boolean;
72
+ /** Whether mid-execution of a plan */
73
+ isExecutingPlan: boolean;
74
+ /** Whether there are uncommitted changes */
75
+ hasUncommittedChanges: boolean;
76
+ /** Current git branch */
77
+ currentBranch?: string;
78
+ /** Files mentioned by the user */
79
+ mentionedFiles: string[];
80
+ }
81
+ /** Output from the router: classification + full routing decision. */
82
+ export interface RouterOutput {
83
+ classification: IntentClassification;
84
+ routing: RoutingDecision;
85
+ confidence: number;
86
+ matchedRule: string;
87
+ }
88
+ /** Main Agent is NEVER allowed to do these */
89
+ export declare const MAIN_AGENT_PROHIBITED: {
90
+ readSourceFiles: boolean;
91
+ searchCodebase: boolean;
92
+ writeFiles: boolean;
93
+ runBuildCommands: boolean;
94
+ runTests: boolean;
95
+ editLargeFiles: boolean;
96
+ longRunningTasks: boolean;
97
+ };
98
+ /** Keywords that trigger specific routes */
99
+ export declare const ROUTE_KEYWORDS: Record<IntentType, string[]>;
100
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/router/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAExE,oCAAoC;AACpC,MAAM,MAAM,UAAU,GAClB,MAAM,GACN,YAAY,GACZ,SAAS,GACT,QAAQ,GACR,OAAO,GACP,KAAK,GACL,SAAS,CAAA;AAEb,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,UAAU,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,cAAc,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,kCAAkC;IAClC,YAAY,EAAE,MAAM,CAAA;IACpB,qDAAqD;IACrD,iBAAiB,EAAE,MAAM,CAAA;IACzB,kDAAkD;IAClD,kBAAkB,EAAE,MAAM,CAAA;IAC1B,8CAA8C;IAC9C,SAAS,EAAE,OAAO,CAAA;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,+BAA+B;IAC/B,QAAQ,EAAE,cAAc,CAAA;IACxB,uCAAuC;IACvC,QAAQ,EAAE,gBAAgB,CAAA;IAC1B,2CAA2C;IAC3C,KAAK,EAAE,OAAO,CAAA;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,0CAA0C;IAC1C,WAAW,EAAE,aAAa,CAAA;IAC1B,2BAA2B;IAC3B,MAAM,EAAE,MAAM,CAAA;IACd,6BAA6B;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACtC,+BAA+B;IAC/B,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,mCAAmC;IACnC,KAAK,EAAE,MAAM,EAAE,CAAA;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,OAAO,CAAA;IAClB,UAAU,EAAE,OAAO,CAAA;IACnB,WAAW,EAAE,OAAO,CAAA;IACpB,UAAU,EAAE,OAAO,CAAA;IACnB,aAAa,EAAE,OAAO,CAAA;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,eAAe,CAAA;IACzB,4BAA4B;IAC5B,eAAe,EAAE,MAAM,CAAA;IACvB,iCAAiC;IACjC,gBAAgB,EAAE,OAAO,GAAG,UAAU,GAAG,OAAO,CAAA;CACjD;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,CAAC,EAAE,cAAc,CAAA;IACvB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,0CAA0C;IAC1C,WAAW,EAAE,MAAM,CAAA;IACnB,iBAAiB;IACjB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,iEAAiE;AACjE,MAAM,WAAW,WAAW;IAC1B,4BAA4B;IAC5B,OAAO,EAAE,MAAM,CAAA;IACf,yCAAyC;IACzC,cAAc,EAAE,OAAO,CAAA;IACvB,sCAAsC;IACtC,eAAe,EAAE,OAAO,CAAA;IACxB,4CAA4C;IAC5C,qBAAqB,EAAE,OAAO,CAAA;IAC9B,yBAAyB;IACzB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,kCAAkC;IAClC,cAAc,EAAE,MAAM,EAAE,CAAA;CACzB;AAED,sEAAsE;AACtE,MAAM,WAAW,YAAY;IAC3B,cAAc,EAAE,oBAAoB,CAAA;IACpC,OAAO,EAAE,eAAe,CAAA;IACxB,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,8CAA8C;AAC9C,eAAO,MAAM,qBAAqB;;;;;;;;CAQjC,CAAA;AAED,4CAA4C;AAC5C,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,CAQvD,CAAA"}