@a11ign/screenreader-fleet 0.0.0-reserved.0 → 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 (147) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +94 -2
  3. package/dist/capture-client.d.mts +49 -0
  4. package/dist/capture-client.d.mts.map +1 -0
  5. package/dist/capture-client.mjs +352 -0
  6. package/dist/capture-client.mjs.map +1 -0
  7. package/dist/check-worker-code.d.mts +34 -0
  8. package/dist/check-worker-code.d.mts.map +1 -0
  9. package/dist/check-worker-code.mjs +142 -0
  10. package/dist/check-worker-code.mjs.map +1 -0
  11. package/dist/cli-flags.d.mts +71 -0
  12. package/dist/cli-flags.d.mts.map +1 -0
  13. package/dist/cli-flags.mjs +207 -0
  14. package/dist/cli-flags.mjs.map +1 -0
  15. package/dist/code-drift.d.mts +140 -0
  16. package/dist/code-drift.d.mts.map +1 -0
  17. package/dist/code-drift.mjs +284 -0
  18. package/dist/code-drift.mjs.map +1 -0
  19. package/dist/command-line-census.d.mts +33 -0
  20. package/dist/command-line-census.d.mts.map +1 -0
  21. package/dist/command-line-census.mjs +96 -0
  22. package/dist/command-line-census.mjs.map +1 -0
  23. package/dist/compare-workers.d.mts +3 -0
  24. package/dist/compare-workers.d.mts.map +1 -0
  25. package/dist/compare-workers.mjs +332 -0
  26. package/dist/compare-workers.mjs.map +1 -0
  27. package/dist/control-plane-isolation.d.mts +45 -0
  28. package/dist/control-plane-isolation.d.mts.map +1 -0
  29. package/dist/control-plane-isolation.mjs +67 -0
  30. package/dist/control-plane-isolation.mjs.map +1 -0
  31. package/dist/deploy-worker.d.mts +3 -0
  32. package/dist/deploy-worker.d.mts.map +1 -0
  33. package/dist/deploy-worker.mjs +333 -0
  34. package/dist/deploy-worker.mjs.map +1 -0
  35. package/dist/doctor.d.mts +216 -0
  36. package/dist/doctor.d.mts.map +1 -0
  37. package/dist/doctor.mjs +962 -0
  38. package/dist/doctor.mjs.map +1 -0
  39. package/dist/fleet-consistency.d.mts +235 -0
  40. package/dist/fleet-consistency.d.mts.map +1 -0
  41. package/dist/fleet-consistency.mjs +436 -0
  42. package/dist/fleet-consistency.mjs.map +1 -0
  43. package/dist/fleet-env.d.mts +228 -0
  44. package/dist/fleet-env.d.mts.map +1 -0
  45. package/dist/fleet-env.mjs +509 -0
  46. package/dist/fleet-env.mjs.map +1 -0
  47. package/dist/fleet-scripts.d.mts +11 -0
  48. package/dist/fleet-scripts.d.mts.map +1 -0
  49. package/dist/fleet-scripts.mjs +41 -0
  50. package/dist/fleet-scripts.mjs.map +1 -0
  51. package/dist/git-safe-env.d.mts +10 -0
  52. package/dist/git-safe-env.d.mts.map +1 -0
  53. package/dist/git-safe-env.mjs +44 -0
  54. package/dist/git-safe-env.mjs.map +1 -0
  55. package/dist/guest-run.d.mts +26 -0
  56. package/dist/guest-run.d.mts.map +1 -0
  57. package/dist/guest-run.mjs +164 -0
  58. package/dist/guest-run.mjs.map +1 -0
  59. package/dist/host-address.d.mts +33 -0
  60. package/dist/host-address.d.mts.map +1 -0
  61. package/dist/host-address.mjs +105 -0
  62. package/dist/host-address.mjs.map +1 -0
  63. package/dist/host-capacity.d.mts +64 -0
  64. package/dist/host-capacity.d.mts.map +1 -0
  65. package/dist/host-capacity.mjs +152 -0
  66. package/dist/host-capacity.mjs.map +1 -0
  67. package/dist/host-metrics.d.mts +116 -0
  68. package/dist/host-metrics.d.mts.map +1 -0
  69. package/dist/host-metrics.mjs +201 -0
  70. package/dist/host-metrics.mjs.map +1 -0
  71. package/dist/index.d.ts +23 -0
  72. package/dist/index.d.ts.map +1 -0
  73. package/dist/index.js +25 -0
  74. package/dist/index.js.map +1 -0
  75. package/dist/local-vm.d.ts +125 -0
  76. package/dist/local-vm.d.ts.map +1 -0
  77. package/dist/local-vm.js +360 -0
  78. package/dist/local-vm.js.map +1 -0
  79. package/dist/measure-guard.d.mts +34 -0
  80. package/dist/measure-guard.d.mts.map +1 -0
  81. package/dist/measure-guard.mjs +73 -0
  82. package/dist/measure-guard.mjs.map +1 -0
  83. package/dist/normalise-fleet.d.mts +2 -0
  84. package/dist/normalise-fleet.d.mts.map +1 -0
  85. package/dist/normalise-fleet.mjs +76 -0
  86. package/dist/normalise-fleet.mjs.map +1 -0
  87. package/dist/npm-cli-executable.d.mts +42 -0
  88. package/dist/npm-cli-executable.d.mts.map +1 -0
  89. package/dist/npm-cli-executable.mjs +159 -0
  90. package/dist/npm-cli-executable.mjs.map +1 -0
  91. package/dist/probe-outcome.d.mts +89 -0
  92. package/dist/probe-outcome.d.mts.map +1 -0
  93. package/dist/probe-outcome.mjs +104 -0
  94. package/dist/probe-outcome.mjs.map +1 -0
  95. package/dist/protocol-guard.d.mts +34 -0
  96. package/dist/protocol-guard.d.mts.map +1 -0
  97. package/dist/protocol-guard.mjs +121 -0
  98. package/dist/protocol-guard.mjs.map +1 -0
  99. package/dist/source-walk.d.mts +12 -0
  100. package/dist/source-walk.d.mts.map +1 -0
  101. package/dist/source-walk.mjs +56 -0
  102. package/dist/source-walk.mjs.map +1 -0
  103. package/dist/transient-fault.d.mts +6 -0
  104. package/dist/transient-fault.d.mts.map +1 -0
  105. package/dist/transient-fault.mjs +86 -0
  106. package/dist/transient-fault.mjs.map +1 -0
  107. package/dist/utm-deprecated.d.mts +6 -0
  108. package/dist/utm-deprecated.d.mts.map +1 -0
  109. package/dist/utm-deprecated.mjs +23 -0
  110. package/dist/utm-deprecated.mjs.map +1 -0
  111. package/dist/worker-code-check.d.mts +29 -0
  112. package/dist/worker-code-check.d.mts.map +1 -0
  113. package/dist/worker-code-check.mjs +85 -0
  114. package/dist/worker-code-check.mjs.map +1 -0
  115. package/dist/worker-health.d.mts +56 -0
  116. package/dist/worker-health.d.mts.map +1 -0
  117. package/dist/worker-health.mjs +73 -0
  118. package/dist/worker-health.mjs.map +1 -0
  119. package/dist/worker-http.d.mts +103 -0
  120. package/dist/worker-http.d.mts.map +1 -0
  121. package/dist/worker-http.mjs +277 -0
  122. package/dist/worker-http.mjs.map +1 -0
  123. package/dist/worker-stats.d.mts +66 -0
  124. package/dist/worker-stats.d.mts.map +1 -0
  125. package/dist/worker-stats.mjs +143 -0
  126. package/dist/worker-stats.mjs.map +1 -0
  127. package/package.json +96 -4
  128. package/src/local-worker/autounattend.xml +280 -0
  129. package/src/local-worker/build-vm.sh +218 -0
  130. package/src/local-worker/clone-worker.sh +141 -0
  131. package/src/local-worker/create-utm-vm.sh +202 -0
  132. package/src/local-worker/fetch-windows-iso.sh +238 -0
  133. package/src/local-worker/first-boot.cmd +58 -0
  134. package/src/local-worker/worker-ctl.sh +442 -0
  135. package/src/provisioning/README.md +28 -0
  136. package/src/provisioning/apply-foreground-lock-timeout.ps1 +71 -0
  137. package/src/provisioning/bare-metal/README.md +213 -0
  138. package/src/provisioning/bare-metal/a11y-bootstrap.service +58 -0
  139. package/src/provisioning/bare-metal/autounattend.xml +428 -0
  140. package/src/provisioning/bare-metal/serve-bootstrap.sh +86 -0
  141. package/src/provisioning/bootstrap-control-plane.sh +463 -0
  142. package/src/provisioning/bootstrap-windows-worker.ps1 +649 -0
  143. package/src/provisioning/build-lean-worker-image.ps1 +275 -0
  144. package/src/provisioning/diagnose-nvda-worker.ps1 +174 -0
  145. package/src/provisioning/provision-nvda-worker.ps1 +827 -0
  146. package/src/provisioning/set-display-mode.ps1 +411 -0
  147. package/src/provisioning/stamp-provision-revision.ps1 +184 -0
@@ -0,0 +1,228 @@
1
+ /**
2
+ * The fleet named by the environment — ONE parser, because there were three that did not agree.
3
+ *
4
+ * `doctor.mjs` preferred `A11Y_WORKERS`, `check-worker-code.mjs` preferred `A11Y_WORKER`, and the
5
+ * dataset runner read only `A11Y_WORKERS`. With both variables set, `doctor` and `worker:code` reported
6
+ * on **different machines** — so "doctor says the fleet is fine" and "worker:code says a worker is
7
+ * stale" could be statements about two disjoint sets, with nothing to say so.
8
+ *
9
+ * `A11Y_WORKERS` wins, matching the dataset runner: the plural names the pool a run dispatches across,
10
+ * and a diagnostic that describes a different set from the one that will do the work is worse than no
11
+ * diagnostic. Each entry is trimmed and de-slashed, because `A11Y_WORKERS=a, b` otherwise yields a URL
12
+ * with a leading space — a configuration typo wearing a dead-machine costume.
13
+ *
14
+ * Returns `[]` rather than null when neither is set: "no worker was named" is a normal state that means
15
+ * "find the local VMs", and every caller already branches on emptiness.
16
+ *
17
+ * @returns {Array<{ name: string, url: string }>}
18
+ */
19
+ export function configuredWorkers(): Array<{
20
+ name: string;
21
+ url: string;
22
+ }>;
23
+ /**
24
+ * Which group each line of the inventory sits in, index-aligned with `text.split(/\r?\n/)`.
25
+ *
26
+ * Exported so there is ONE group implementation. `fleet-discover.mjs` has its own host reader with its own
27
+ * regexes -- two readers of one file, which this repo's notes call its most expensive recurring shape -- and
28
+ * when this module became group-aware that one did not, so `fleet:discover` probed the lab container on
29
+ * :8765 and reported it "ASLEEP?". A phantom worker in the diagnostic instead of in the dispatch list is
30
+ * still a phantom worker. Rather than teach a second parser about groups, both now ask this.
31
+ *
32
+ * @param {string} text
33
+ * @returns {Array<string | undefined>}
34
+ */
35
+ export function groupPerLine(text: string): Array<string | undefined>;
36
+ /**
37
+ * Worker URLs from the text of an inventory file.
38
+ *
39
+ * `scope` says which question is asked. `"fleet"` (the default) is every enrolled worker -- what `doctor`,
40
+ * `worker:code`, `fleet:status` and the deploy tooling mean, and they must keep seeing a worker that is
41
+ * serving but not capturing. `"capture"` is the fleet minus every host that declares `a11y_capture: false`
42
+ * -- what `A11Y_WORKERS` means. It is a string and not a flag because a boolean argument does not say
43
+ * which of the two you got.
44
+ *
45
+ * Exported and pure so the strictness above is testable: a reader that has never been shown to reject
46
+ * anything is a reader nobody knows the limits of.
47
+ *
48
+ * @param {string} text
49
+ * @param {{ port?: number, group?: string, scope?: "fleet" | "capture" }} [options]
50
+ * @returns {string[]}
51
+ */
52
+ export function workersFromInventory(text: string, { port, group, scope }?: {
53
+ port?: number;
54
+ group?: string;
55
+ scope?: "fleet" | "capture";
56
+ }): string[];
57
+ /**
58
+ * The hosts left OUT of the capture set, so the command that leaves them out can say so.
59
+ *
60
+ * @param {string} text
61
+ * @param {{ port?: number, group?: string }} [options]
62
+ * @returns {{name: string, url: string}[]}
63
+ */
64
+ export function hostsOutOfCaptureSet(text: string, { port, group }?: {
65
+ port?: number;
66
+ group?: string;
67
+ }): {
68
+ name: string;
69
+ url: string;
70
+ }[];
71
+ /**
72
+ * The inventory as `{ url -> name }`, so a report can say which machine a command would act on.
73
+ *
74
+ * Same parser, same group rules — deliberately not a second reader of the same file, which this repo
75
+ * calls its most expensive recurring shape and has already paid for once in `fleet-discover.mjs`.
76
+ *
77
+ * @param {string} text
78
+ * @param {{ port?: number, group?: string }} [options]
79
+ * @returns {Record<string, string>}
80
+ */
81
+ export function workerNamesFromInventory(text: string, { port, group }?: {
82
+ port?: number;
83
+ group?: string;
84
+ }): Record<string, string>;
85
+ /** The port the group vars declare, so it is stated once and not guessed here. */
86
+ /** @param {string} text @returns {number} */
87
+ export function portFromGroupVars(text: string): number;
88
+ /**
89
+ * The workers declared in `inventory.yml` — i.e. the BARE-METAL fleet.
90
+ *
91
+ * Exists so a caller can tell a physical box from a local UTM VM, which decides how it is deployed to and
92
+ * therefore what remedy to print. `worker:code` used to tell every stale worker to run `utmctl` and
93
+ * `npm run worker:deploy`, which CANNOT reach a bare-metal box — it is a `utmctl file push` keyed on a VM
94
+ * UUID and fails immediately off macOS. Following that advice on this fleet wastes the time it takes to
95
+ * discover the tool was describing a different kind of machine.
96
+ *
97
+ * Reads the same file through the same parser as `main()`, rather than a second copy of the knowledge.
98
+ *
99
+ * `inventoryPath`/`groupVarsPath` are INJECTED, defaulting to this monorepo's own control-plane files —
100
+ * see the comment above `INVENTORY` for why the default exists and what it does not fix on its own.
101
+ *
102
+ * @param {{ inventoryPath?: string, groupVarsPath?: string }} [paths]
103
+ */
104
+ export function inventoryWorkerUrls({ inventoryPath, groupVarsPath }?: {
105
+ inventoryPath?: string;
106
+ groupVarsPath?: string;
107
+ }): string[];
108
+ /**
109
+ * The bare-metal fleet as `{name, url}` — the shape a REPORT needs.
110
+ *
111
+ * `fleet-status.mjs` already pairs the two, and its comment records what the address alone cost: "this
112
+ * table named .224 as the box whose Edge had drifted, and .224 is a11y-worker-FIVE — so
113
+ * `fleet:sleep --limit=a11y-worker-4` put a healthy machine to sleep and left the drifted one serving. A
114
+ * report and a command that cannot be matched up is a report you have to translate, and translation is
115
+ * where the mistake goes."
116
+ *
117
+ * Here rather than in each reporter, because that is the same pairing and a second copy would drift.
118
+ *
119
+ * `inventoryPath`/`groupVarsPath` are INJECTED, same reason and same default as `inventoryWorkerUrls`.
120
+ *
121
+ * @param {{ inventoryPath?: string, groupVarsPath?: string }} [paths]
122
+ * @returns {{name: string, url: string}[]} empty when no inventory is declared, like `inventoryWorkerUrls`
123
+ */
124
+ export function namedInventoryWorkers({ inventoryPath, groupVarsPath }?: {
125
+ inventoryPath?: string;
126
+ groupVarsPath?: string;
127
+ }): {
128
+ name: string;
129
+ url: string;
130
+ }[];
131
+ /**
132
+ * WHICH WORKERS TO USE, AND WHERE THAT LIST CAME FROM — the one precedence, in one place.
133
+ *
134
+ * THREE MODULES HELD THREE DIFFERENT ANSWERS, and one of them carried a comment saying they had been
135
+ * unified. Measured 2026-08-29:
136
+ *
137
+ * doctor.mjs named -> inventory
138
+ * check-worker-code.mjs named -> LOCAL UTM POOL -> inventory
139
+ * capture-screenreader-dataset.mjs named -> LOCAL UTM POOL -> single-VM lease (never reads inventory)
140
+ *
141
+ * The corpus capture path's own comment reads "One parser, in fleet-env.mjs. This copy and doctor's and
142
+ * check-worker-code's had drifted apart on precedence, which meant a diagnostic could describe a different
143
+ * fleet from the one about to run." That unification covered the NAMED half only; the fallback order below
144
+ * it stayed three separate answers, so the sentence describes a fix that was half applied.
145
+ *
146
+ * The consequence is the one the comment predicted: on a Mac with any registered UTM guest, `worker:code`
147
+ * reports the local VM while `doctor` reports the five bare-metal boxes, and a capture dispatches to
148
+ * whichever the entry point happened to prefer.
149
+ *
150
+ * ## THE LOCAL UTM POOL IS LAST, and that is a deprecation, not a preference
151
+ *
152
+ * The local guests were a testing arrangement and are deprecated; `inventory.yml` is the fleet, and ADR
153
+ * 0012 already calls it the single source of truth. So the pool is a fallback for a checkout with NO
154
+ * inventory — a supported setup for an outside contributor with one Mac and no hardware — and never a
155
+ * contender with one. Any other order reproduces the divergence above on every Mac that still has a bundle
156
+ * registered.
157
+ *
158
+ * `local` is injected rather than imported: reading the UTM pool means shelling out to `utmctl`, and this
159
+ * module is imported by everything that needs a worker list, including on Linux. A caller that has no
160
+ * local-pool reader simply omits it.
161
+ *
162
+ * @param {{ named?: () => {url: string}[], inventory?: () => string[], local?: () => string[] }} readers
163
+ * @returns {{ urls: string[], source: string }}
164
+ */
165
+ export function resolveWorkerPool({ named, inventory, local, }?: {
166
+ named?: () => {
167
+ url: string;
168
+ }[];
169
+ inventory?: () => string[];
170
+ local?: () => string[];
171
+ }): {
172
+ urls: string[];
173
+ source: string;
174
+ };
175
+ /**
176
+ * What `fleet:env` prints, as data: `stdout` is what a shell reads, `stderr` is what the operator reads.
177
+ *
178
+ * `mode: "list"` is the WHOLE fleet, one URL per line, and leaves nobody out. The default is the capture
179
+ * set as an `export`, and it NAMES every host it left out on stderr -- an omission with no line is a
180
+ * machine nothing reports, which is the failure this module's header is about. stderr, because stdout is
181
+ * `eval`-ed.
182
+ *
183
+ * @param {string} text the inventory
184
+ * @param {{ port?: number, mode?: "env" | "list" }} [options]
185
+ * @returns {{stdout: string, stderr: string}}
186
+ */
187
+ export function fleetEnvOutput(text: string, { port, mode }?: {
188
+ port?: number;
189
+ mode?: "env" | "list";
190
+ }): {
191
+ stdout: string;
192
+ stderr: string;
193
+ };
194
+ export const DEFAULT_WORKER_PORT: 8765;
195
+ /**
196
+ * The inventory group whose hosts are capture workers.
197
+ *
198
+ * This reader was GROUPLESS until 2026-08-21, and that was a live hazard rather than an untidiness: every
199
+ * `ansible_host:` in the file became `http://<addr>:8765`, so adding any non-worker host to `inventory.yml`
200
+ * -- the lab container, the control container, a switch -- would have silently added a phantom worker to
201
+ * `A11Y_WORKERS`, and a run would have dispatched capture cases to it. That is the exact failure this
202
+ * module's own header says it exists to prevent ("dispatched to but never updated", "both of those are
203
+ * silent"), arriving through the door nobody had shut.
204
+ */
205
+ export const WORKER_GROUP: "a11y_workers";
206
+ /**
207
+ * One frame of the indentation stack: a key and the column it started at.
208
+ */
209
+ export type Frame = {
210
+ indent: number;
211
+ key: string;
212
+ };
213
+ /**
214
+ * A host as the inventory declares it — the ADDRESS and the NAME together.
215
+ *
216
+ * They travel as one value because separating them is what sent `fleet:sleep` at the wrong machine: every
217
+ * tool that ACTS on a worker takes the name, every tool that REPORTS on one printed the address, and
218
+ * nothing mapped between them. `collectHost` explains the incident.
219
+ *
220
+ * `capture` is false for a host that declares `a11y_capture: false`: enrolled, served, deployed to, and not
221
+ * handed corpus cases.
222
+ */
223
+ export type Host = {
224
+ name: string | undefined;
225
+ host: string;
226
+ capture: boolean;
227
+ };
228
+ //# sourceMappingURL=fleet-env.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fleet-env.d.mts","sourceRoot":"","sources":["../src/fleet-env.mjs"],"names":[],"mappings":"AA4CA;;;;;;;;;;;;;;;;;GAiBG;AACH,qCAFa,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CAehD;AA+FD;;;;;;;;;;;GAWG;AACH,mCAHW,MAAM,GACJ,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC,CAUrC;AA4FD;;;;;;;;;;;;;;;GAeG;AACH,2CAJW,MAAM,2BACN;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CAAE,GAC5D,MAAM,EAAE,CAWpB;AAED;;;;;;GAMG;AACH,2CAJW,MAAM,oBACN;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAC,EAAE,CAMzC;AAED;;;;;;;;;GASG;AACH,+CAJW,MAAM,oBACN;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAkBlC;AAiCD,kFAAkF;AAClF,6CAA6C;AAC7C,wCADY,MAAM,GAAiB,MAAM,CAIxC;AAED;;;;;;;;;;;;;;;GAeG;AACH,uEAFW;IAAE,aAAa,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,YAW5D;AAED;;;;;;;;;;;;;;;GAeG;AACH,yEAHW;IAAE,aAAa,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,GAChD;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAC,EAAE,CAYzC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,iEAHW;IAAE,KAAK,CAAC,EAAE,MAAM;QAAC,GAAG,EAAE,MAAM,CAAA;KAAC,EAAE,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,MAAM,EAAE,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,MAAM,EAAE,CAAA;CAAE,GACnF;IAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAmB9C;AAED;;;;;;;;;;;GAWG;AACH,qCAJW,MAAM,mBACN;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,KAAK,GAAG,MAAM,CAAA;CAAE,GACtC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAC,CAe5C;AA/dD,kCAAmC,IAAI,CAAC;AAqExC;;;;;;;;;GASG;AACH,2BAA4B,cAAc,CAAC;;;;oBAK9B;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAC;;;;;;;;;;;mBAa7B;IAAC,IAAI,EAAE,MAAM,GAAC,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAC"}