pagespeed-quest 0.10.0 → 0.11.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 (49) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.ja.md +42 -0
  3. package/README.md +43 -0
  4. package/build/cli.d.ts +8 -0
  5. package/build/cli.js +264 -0
  6. package/build/command.js +3 -229
  7. package/build/llm.d.ts +20 -0
  8. package/build/llm.js +42 -0
  9. package/llmdocs/00-guide.md +124 -0
  10. package/llmdocs/10-inventory.md +133 -0
  11. package/llmdocs/20-experiments.md +194 -0
  12. package/llmdocs/30-measuring.md +117 -0
  13. package/llmdocs/90-commands.md +181 -0
  14. package/package.json +12 -6
  15. package/scripts/build-llm-docs.js +70 -0
  16. package/scripts/validate-plugin-skills.js +117 -0
  17. package/build/docs/assets/css/main.css +0 -1
  18. package/build/docs/assets/images/icons.png +0 -0
  19. package/build/docs/assets/images/icons@2x.png +0 -0
  20. package/build/docs/assets/images/widgets.png +0 -0
  21. package/build/docs/assets/images/widgets@2x.png +0 -0
  22. package/build/docs/assets/js/main.js +0 -51
  23. package/build/docs/classes/inventoryrepository.html +0 -305
  24. package/build/docs/classes/playbackproxy.html +0 -524
  25. package/build/docs/classes/proxy.html +0 -474
  26. package/build/docs/classes/recordingproxy.html +0 -532
  27. package/build/docs/classes/testproxy.html +0 -497
  28. package/build/docs/classes/throttle.html +0 -425
  29. package/build/docs/classes/throttlinglog.html +0 -174
  30. package/build/docs/classes/throttlingtransform.html +0 -6297
  31. package/build/docs/globals.html +0 -1131
  32. package/build/docs/index.html +0 -348
  33. package/build/docs/interfaces/beautifyresult.html +0 -174
  34. package/build/docs/interfaces/contentencodingpair.html +0 -174
  35. package/build/docs/interfaces/inventory.html +0 -174
  36. package/build/docs/interfaces/lighthouseoptions.html +0 -230
  37. package/build/docs/interfaces/playbacktransaction.html +0 -272
  38. package/build/docs/interfaces/proxyoptions.html +0 -423
  39. package/build/docs/interfaces/recordingsession.html +0 -174
  40. package/build/docs/interfaces/recordingtransaction.html +0 -286
  41. package/build/docs/interfaces/resource.html +0 -314
  42. package/build/docs/interfaces/transaction.html +0 -258
  43. package/build/docs/interfaces/withproxyoptions.html +0 -418
  44. package/build/logger.d.ts +0 -2
  45. package/build/logger.js +0 -15
  46. package/build/proxy.d.ts +0 -35
  47. package/build/proxy.js +0 -96
  48. package/build/throttling.d.ts +0 -33
  49. package/build/throttling.js +0 -89
package/CHANGELOG.md CHANGED
@@ -2,4 +2,15 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### 0.11.0 (2026-08-16)
6
+
7
+ * Add `psq llm` — the embedded reference for AI agents (`--format markdown|json`), sourced from `llmdocs/` and shipped with the package
8
+ * Add `psq --version`
9
+ * Ship an Agent Skills bundle (`plugins/pagespeed-quest/`): `psq-install`, `psq-usage`, `psq-inventory`, `psq-video`, installable through the ideamans Claude Code marketplace or `gh skill`
10
+ * Add `context7.json` so agents with the context7 MCP server can look the project up
11
+ * Generate `llmdocs/90-commands.md` from the actual command tree (`yarn ai:regen`), and fail the test suite when it is stale or when the skill bundle drifts
12
+ * Extract the command tree into `src/cli.ts` (`createProgram()`); `src/command.ts` is now only the bin entry point
13
+ * Publish to npm on a `v*` tag push instead of on every push to `main`, verifying the tag against `package.json` and the plugin manifest
14
+ * Require Node.js 22.19 or newer (Lighthouse 13's floor); CI runs 22.x and 24.x
15
+
5
16
  ### 0.2.1 (2024-09-11)
package/README.ja.md CHANGED
@@ -136,6 +136,48 @@ yarn psq proxy -p 8080 --record https://example.com/
136
136
  /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --ignore-certificate-errors --proxy-server=http://localhost:8080
137
137
  ```
138
138
 
139
+ ## AIエージェントから使う
140
+
141
+ PageSpeed Quest は、AIエージェント向けのリファレンスを自分で持っています。
142
+ 鉄則・インベントリのスキーマ・再生時のタイミングの計算式・「どの編集がどの施策を
143
+ 模擬するか」の一覧が、1コマンドで全部出ます。
144
+
145
+ ```sh
146
+ yarn psq llm # Markdown(既定)
147
+ yarn psq llm --format json # 章ごとのJSON配列
148
+ ```
149
+
150
+ インストールされたパッケージに同梱されているので、**実行中のバージョンと必ず
151
+ 一致します**(ドキュメントサイトと違って古くなりません)。
152
+
153
+ ### Claude Code / gh skill
154
+
155
+ `plugins/pagespeed-quest/` に Agent Skills を同梱しています。
156
+
157
+ | スキル | 内容 |
158
+ | --- | --- |
159
+ | `psq-install` | `psq` が動く状態のプロジェクトを用意する |
160
+ | `psq-usage` | 記録 → ベースライン → 編集 → 計測のループ |
161
+ | `psq-inventory` | ファイル構造と、施策ごとの編集レシピ |
162
+ | `psq-video` | 読み込み過程のビフォーアフター動画 |
163
+
164
+ Claude Code の場合:
165
+
166
+ ```sh
167
+ /plugin marketplace add ideamans/claude-public-plugins
168
+ /plugin install pagespeed-quest
169
+ ```
170
+
171
+ Copilot / Cursor / Gemini CLI / Codex などは同じ SKILL.md を `gh skill` で
172
+ 入れられます。
173
+
174
+ ```sh
175
+ gh skill install ideamans/pagespeed-quest/plugins/pagespeed-quest/skills/psq-usage --agent copilot
176
+ ```
177
+
178
+ [context7](https://context7.com/) にも登録しているので、context7 MCP を繋いだ
179
+ エージェントは何も入れずに参照できます。
180
+
139
181
  ## 開発環境の共有やトレーニングにも
140
182
 
141
183
  PageSpeed Questは、Webアプリケーションのリリースを必要としないスピーディーな仮説検証以外にも有用です。
package/README.md CHANGED
@@ -136,6 +136,49 @@ However, since this HTTP proxy uses a dummy SSL certificate, please disable the
136
136
  /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --ignore-certificate-errors --proxy-server=http://localhost:8080
137
137
  ```
138
138
 
139
+ ## Driving it with an AI agent
140
+
141
+ PageSpeed Quest ships its own reference for AI agents. One command prints
142
+ everything an agent needs — the ground rules, the inventory schema, the timing
143
+ model, and a catalogue of which edit models which optimization:
144
+
145
+ ```sh
146
+ yarn psq llm # Markdown (default)
147
+ yarn psq llm --format json # one object per chapter
148
+ ```
149
+
150
+ The reference is embedded in the installed package, so it always matches the
151
+ version you are running.
152
+
153
+ ### Claude Code / gh skill
154
+
155
+ The repository also ships an Agent Skills bundle under
156
+ `plugins/pagespeed-quest/`:
157
+
158
+ | Skill | What it covers |
159
+ | --- | --- |
160
+ | `psq-install` | setting up a quest project so `psq` runs |
161
+ | `psq-usage` | the record → baseline → edit → measure loop |
162
+ | `psq-inventory` | the file layout and the catalogue of experiments |
163
+ | `psq-video` | before/after videos of the load |
164
+
165
+ For Claude Code, add the ideamans marketplace and install the plugin:
166
+
167
+ ```sh
168
+ /plugin marketplace add ideamans/claude-public-plugins
169
+ /plugin install pagespeed-quest
170
+ ```
171
+
172
+ For other agents (Copilot, Cursor, Gemini CLI, Codex), the same skills install
173
+ through `gh skill`:
174
+
175
+ ```sh
176
+ gh skill install ideamans/pagespeed-quest/plugins/pagespeed-quest/skills/psq-usage --agent copilot
177
+ ```
178
+
179
+ The project is also registered with [context7](https://context7.com/), so agents
180
+ with the context7 MCP server can look it up without installing anything.
181
+
139
182
  ## For Sharing Development Environments and Training
140
183
 
141
184
  PageSpeed Quest is useful not only for speedy hypothesis verification without the need for a Web application release but also for other purposes.
package/build/cli.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ import { Command } from 'commander';
2
+ /**
3
+ * Build the `psq` command tree.
4
+ *
5
+ * Exported so that scripts/build-llm-docs.js can walk it to generate the
6
+ * command catalog (llmdocs/90-commands.md) instead of hand-maintaining it.
7
+ */
8
+ export declare function createProgram(): Command;
package/build/cli.js ADDED
@@ -0,0 +1,264 @@
1
+ import Path from 'path';
2
+ import { Command } from 'commander';
3
+ import Watch from 'node-watch';
4
+ import { Dependency } from './dependency.js';
5
+ import { execLighthouse } from './lighthouse.js';
6
+ import { packageVersion, renderLlmDocs } from './llm.js';
7
+ import { execLoadshow } from './loadshow.js';
8
+ import { execWebshotCapture, execWebshotCompare } from './webshot.js';
9
+ import { InventoryRepository, withPlaybackProxy, withRecordingProxy } from './index.js';
10
+ /**
11
+ * The dependency container is created lazily.
12
+ *
13
+ * Building it eagerly would spawn the pino-pretty transport worker as a side
14
+ * effect of importing this module, which breaks tools that only want to walk
15
+ * the command tree (see scripts/build-llm-docs.js).
16
+ */
17
+ let dependencyInstance;
18
+ function dependency() {
19
+ if (!dependencyInstance)
20
+ dependencyInstance = new Dependency();
21
+ return dependencyInstance;
22
+ }
23
+ function collect(value, previous) {
24
+ return previous.concat([value]);
25
+ }
26
+ function registerLighthouseCommands(main) {
27
+ const lighthouse = main.command('lighthouse');
28
+ lighthouse.description('Run Lighthouse (performance category) via a proxy');
29
+ lighthouse.option('-a, --artifacts <dir>', 'Artifacts directory', './artifacts');
30
+ lighthouse.option('-l, --laud', 'Show browser and open the report after completion', false);
31
+ lighthouse.option('-t, --timeout <ms>', 'Timeout milliseconds', '30000');
32
+ const recording = lighthouse.command('recording');
33
+ recording.description('Record contents by lighthouse');
34
+ recording.option('-d, --device <mobile|desktop>', 'Device type', 'mobile');
35
+ recording.option('-x, --exclude <pattern>', 'Regex patterns to exclude URLs from recording (repeatable)', collect, []);
36
+ recording.argument('<url>', 'Url to measure performance');
37
+ recording.action(async (url) => {
38
+ const inventoryRepository = new InventoryRepository(main.opts().inventory || './inventory');
39
+ const deviceType = recording.opts().device || 'mobile';
40
+ const artifactsDir = lighthouse.opts().artifacts || './artifacts';
41
+ const laud = !!lighthouse.opts().laud;
42
+ const timeout = Number(lighthouse.opts().timeout || '30000');
43
+ const excludePatterns = recording.opts().exclude || [];
44
+ await withRecordingProxy({
45
+ entryUrl: url,
46
+ deviceType,
47
+ inventoryRepository,
48
+ excludePatterns: excludePatterns.length > 0 ? excludePatterns : undefined,
49
+ }, dependency(), async (proxy) => {
50
+ await execLighthouse({
51
+ url,
52
+ proxyPort: proxy.port,
53
+ deviceType,
54
+ view: laud,
55
+ artifactsDir,
56
+ headless: !laud,
57
+ timeout,
58
+ }, dependency());
59
+ dependency().logger?.info('Lighthouse completed. Saving inventory...');
60
+ });
61
+ });
62
+ const playback = lighthouse.command('playback');
63
+ playback.description('Playback contents for lighthouse');
64
+ playback.action(async () => {
65
+ const inventoryDir = main.opts().inventory || './inventory';
66
+ const inventoryRepository = new InventoryRepository(inventoryDir);
67
+ const artifactsDir = lighthouse.opts().artifacts || './artifacts';
68
+ const laud = !!lighthouse.opts().laud;
69
+ const timeout = Number(lighthouse.opts().timeout || '30000');
70
+ // Load inventory for traffic statistics
71
+ const inventory = await inventoryRepository.loadInventory();
72
+ await withPlaybackProxy({
73
+ inventoryRepository,
74
+ }, dependency(), async (proxy) => {
75
+ await execLighthouse({
76
+ url: proxy.entryUrl,
77
+ proxyPort: proxy.port,
78
+ deviceType: proxy.deviceType,
79
+ view: laud,
80
+ artifactsDir,
81
+ headless: !laud,
82
+ timeout,
83
+ inventoryDir,
84
+ resources: inventory.resources,
85
+ }, dependency());
86
+ dependency().logger?.info('Lighthouse completed');
87
+ });
88
+ });
89
+ }
90
+ function registerLoadshowCommands(main) {
91
+ const loadshow = main.command('loadshow');
92
+ loadshow.description('Run loadshow via a proxy');
93
+ loadshow.option('-a, --artifacts <dir>', 'Artifacts directory', './artifacts');
94
+ loadshow.option('-c, --credit <string>', 'Credit string');
95
+ loadshow.option('-t, --timeout <ms>', 'Timeout milliseconds', '30000');
96
+ const recording = loadshow.command('recording');
97
+ recording.description('Record contents by loadshow');
98
+ recording.option('-d, --device <mobile|desktop>', 'Device type', 'mobile');
99
+ recording.option('-x, --exclude <pattern>', 'Regex patterns to exclude URLs from recording (repeatable)', collect, []);
100
+ recording.argument('<url>', 'Url to measure performance');
101
+ recording.action(async (url) => {
102
+ const inventoryRepository = new InventoryRepository(main.opts().inventory || './inventory');
103
+ const deviceType = recording.opts().device || 'mobile';
104
+ const artifactsDir = loadshow.opts().artifacts || './artifacts';
105
+ const credit = loadshow.opts().credit || '';
106
+ const timeout = Number(loadshow.opts().timeout || '30000');
107
+ const excludePatterns = recording.opts().exclude || [];
108
+ await withRecordingProxy({
109
+ entryUrl: url,
110
+ deviceType,
111
+ inventoryRepository,
112
+ excludePatterns: excludePatterns.length > 0 ? excludePatterns : undefined,
113
+ }, dependency(), async (proxy) => {
114
+ await execLoadshow({ url, proxyPort: proxy.port, deviceType, artifactsDir, credit, timeout }, dependency());
115
+ dependency().logger?.info('Loadshow completed. Saving inventory...');
116
+ });
117
+ });
118
+ const playback = loadshow.command('playback');
119
+ playback.description('Playback contents for loadshow');
120
+ playback.action(async () => {
121
+ const inventoryRepository = new InventoryRepository(main.opts().inventory || './inventory');
122
+ const artifactsDir = loadshow.opts().artifacts || './artifacts';
123
+ const credit = loadshow.opts().credit || '';
124
+ const timeout = Number(loadshow.opts().timeout || '30000');
125
+ await withPlaybackProxy({
126
+ inventoryRepository,
127
+ }, dependency(), async (proxy) => {
128
+ await execLoadshow({
129
+ url: proxy.entryUrl,
130
+ proxyPort: proxy.port,
131
+ deviceType: proxy.deviceType,
132
+ artifactsDir,
133
+ credit,
134
+ timeout,
135
+ }, dependency());
136
+ dependency().logger?.info('Loadshow completed');
137
+ });
138
+ });
139
+ }
140
+ function registerProxyCommands(main) {
141
+ const proxy = main.command('proxy');
142
+ proxy.description('Run the playback (or recording) proxy standalone');
143
+ proxy.option('-p, --port <number>', 'Proxy port', '8080');
144
+ proxy.option('-r, --record <url>', 'Recording URL to start the proxy as recording mode', '');
145
+ proxy.option('-x, --exclude <pattern>', 'Regex patterns to exclude URLs from recording (repeatable)', collect, []);
146
+ proxy.action(async () => {
147
+ const inventoryRepository = new InventoryRepository(main.opts().inventory || './inventory');
148
+ const port = Number(proxy.opts().port || '8080');
149
+ if (proxy.opts().record) {
150
+ const url = proxy.opts().record;
151
+ if (!url) {
152
+ throw new Error('Recording URL must be specified with --record option.');
153
+ }
154
+ const excludePatterns = proxy.opts().exclude || [];
155
+ // Recordingモード
156
+ await withRecordingProxy({
157
+ inventoryRepository,
158
+ port,
159
+ entryUrl: url,
160
+ excludePatterns: excludePatterns.length > 0 ? excludePatterns : undefined,
161
+ }, dependency(), async () => {
162
+ dependency().logger?.info(`Recording proxy started on port ${port}. Press Ctrl+C to stop.`);
163
+ // Wait for Ctrl+C signal
164
+ return new Promise((resolve) => {
165
+ process.on('SIGINT', () => {
166
+ dependency().logger?.info('Saving the inventory...');
167
+ resolve();
168
+ });
169
+ });
170
+ });
171
+ }
172
+ else {
173
+ // Playbackモード
174
+ // eslint-disable-next-line no-constant-condition
175
+ while (true) {
176
+ await withPlaybackProxy({ inventoryRepository, port }, dependency(), async () => {
177
+ const watcher = Watch(inventoryRepository.dirPath, { recursive: true });
178
+ return new Promise((ok) => {
179
+ watcher.on('change', () => {
180
+ watcher.close();
181
+ dependency().logger?.info('Inventory changed. Restarting proxy...');
182
+ ok();
183
+ });
184
+ });
185
+ });
186
+ }
187
+ }
188
+ });
189
+ }
190
+ function registerCaptureCommands(main) {
191
+ const visualTest = main.command('capture');
192
+ visualTest.description('Capture a screenshot via playback proxy and optionally compare with a baseline');
193
+ visualTest.option('-a, --artifacts <dir>', 'Artifacts directory', './artifacts');
194
+ visualTest.option('-t, --timeout <ms>', 'Timeout milliseconds', '30000');
195
+ visualTest.option('--compare <file>', 'Baseline PNG file to compare against');
196
+ visualTest.option('--baseline-label <label>', 'Label for the baseline image', '前回');
197
+ visualTest.option('--current-label <label>', 'Label for the current image', '今回');
198
+ visualTest.action(async () => {
199
+ const inventoryRepository = new InventoryRepository(main.opts().inventory || './inventory');
200
+ const artifactsDir = visualTest.opts().artifacts || './artifacts';
201
+ const timeout = Number(visualTest.opts().timeout || '30000');
202
+ const compareFile = visualTest.opts().compare;
203
+ const baselineLabel = visualTest.opts().baselineLabel || '前回';
204
+ const currentLabel = visualTest.opts().currentLabel || '今回';
205
+ await withPlaybackProxy({
206
+ inventoryRepository,
207
+ fullThrottle: true,
208
+ }, dependency(), async (proxy) => {
209
+ const outputPath = Path.join(artifactsDir, 'capture.png');
210
+ await dependency().mkdirp(artifactsDir);
211
+ await execWebshotCapture({
212
+ url: proxy.entryUrl,
213
+ proxyPort: proxy.port,
214
+ preset: proxy.deviceType === 'desktop' ? 'desktop' : 'mobile',
215
+ output: outputPath,
216
+ timeout,
217
+ }, dependency());
218
+ dependency().logger?.info(`Screenshot saved to ${outputPath}`);
219
+ if (compareFile) {
220
+ const diffOutput = Path.join(artifactsDir, 'capture-diff.png');
221
+ const digestTxt = Path.join(artifactsDir, 'capture-diff.txt');
222
+ await execWebshotCompare({
223
+ baseline: compareFile,
224
+ current: outputPath,
225
+ output: diffOutput,
226
+ digestTxt,
227
+ baselineLabel,
228
+ currentLabel,
229
+ }, dependency());
230
+ dependency().logger?.info(`Diff image saved to ${diffOutput}`);
231
+ dependency().logger?.info(`Diff digest saved to ${digestTxt}`);
232
+ }
233
+ });
234
+ });
235
+ }
236
+ function registerLlmCommands(main) {
237
+ const llm = main.command('llm');
238
+ llm.description('Print the embedded reference for AI agents');
239
+ llm.option('-f, --format <markdown|json>', 'Output format', 'markdown');
240
+ llm.action(async () => {
241
+ const format = llm.opts().format === 'json' ? 'json' : 'markdown';
242
+ process.stdout.write(await renderLlmDocs(format));
243
+ });
244
+ }
245
+ /**
246
+ * Build the `psq` command tree.
247
+ *
248
+ * Exported so that scripts/build-llm-docs.js can walk it to generate the
249
+ * command catalog (llmdocs/90-commands.md) instead of hand-maintaining it.
250
+ */
251
+ export function createProgram() {
252
+ const main = new Command();
253
+ main.name('psq');
254
+ main.version(packageVersion(), '-v, --version', 'Output the version number');
255
+ main.description('Record a web page through a proxy, edit the recording, and replay it to measure the difference');
256
+ main.option('-i, --inventory <dir>', 'Inventory directory', './inventory');
257
+ registerLighthouseCommands(main);
258
+ registerLoadshowCommands(main);
259
+ registerProxyCommands(main);
260
+ registerCaptureCommands(main);
261
+ registerLlmCommands(main);
262
+ return main;
263
+ }
264
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2NsaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLElBQUksTUFBTSxNQUFNLENBQUE7QUFFdkIsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFdBQVcsQ0FBQTtBQUNuQyxPQUFPLEtBQUssTUFBTSxZQUFZLENBQUE7QUFFOUIsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGlCQUFpQixDQUFBO0FBQzVDLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQTtBQUNoRCxPQUFPLEVBQUUsY0FBYyxFQUFFLGFBQWEsRUFBRSxNQUFNLFVBQVUsQ0FBQTtBQUN4RCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sZUFBZSxDQUFBO0FBRTVDLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGNBQWMsQ0FBQTtBQUVyRSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsaUJBQWlCLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxZQUFZLENBQUE7QUFFdkY7Ozs7OztHQU1HO0FBQ0gsSUFBSSxrQkFBMEMsQ0FBQTtBQUU5QyxTQUFTLFVBQVU7SUFDakIsSUFBSSxDQUFDLGtCQUFrQjtRQUFFLGtCQUFrQixHQUFHLElBQUksVUFBVSxFQUFFLENBQUE7SUFDOUQsT0FBTyxrQkFBa0IsQ0FBQTtBQUMzQixDQUFDO0FBRUQsU0FBUyxPQUFPLENBQUMsS0FBYSxFQUFFLFFBQWtCO0lBQ2hELE9BQU8sUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUE7QUFDakMsQ0FBQztBQUVELFNBQVMsMEJBQTBCLENBQUMsSUFBYTtJQUMvQyxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFBO0lBQzdDLFVBQVUsQ0FBQyxXQUFXLENBQUMsbURBQW1ELENBQUMsQ0FBQTtJQUMzRSxVQUFVLENBQUMsTUFBTSxDQUFD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