pagespeed-quest 0.11.0 → 0.12.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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,19 @@
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.12.0 (2026-10-11)
6
+
7
+ * **Lighthouse now reports the replay as observed** (`--throttling-method=provided`, plus `--throttling.requestLatencyMs=0`). Until now Lighthouse ran with its default `simulate` method, which re-derives every metric from its own network model and ignores the timing the proxy reproduces — reported FCP could even be shorter than the document's TTFB, and repeated runs of one recording disagreed by hundreds of milliseconds. **Scores and metrics change, and are not comparable with earlier versions.** A playback run now takes roughly 20–30 seconds, because Lighthouse waits for the page to go quiet
8
+ * Restructure the Agent Skills bundle around a whole investigation of a URL. `psq-usage` now runs record → measure → investigate → one change per trial → adopt or reject → report, with `baseline/` (never edited), `accepted/` (adopted changes) and a `quest-log.md`; new `psq-record` (recording, checking it, freezing the baseline) and `psq-measure` (several runs per state with medians and spread, reading `lighthouse.report.json` for the LCP element, waterfall, script cost and third parties, screenshot diffs)
9
+ * The skills and `llmdocs/20-experiments.md` no longer prescribe optimizations; they cover how an edit reaches the replay and what cannot be modelled, and leave the choice of changes to the agent
10
+ * Document that the report written by `psq lighthouse recording` measured the live site and must not be used as the baseline
11
+ * Fix the documented inventory layout: method directories are lower-case (`contents/get/…`), queries are URL-encoded before the extension, and `contentFilePath` is relative to the inventory directory
12
+ * Document that `method`, `url` and `ttfbMs` are required when adding a resource to `index.json`
13
+ * **Bundle rust-http-playback-proxy 0.11.1.** Recordings now carry `formatVersion: 2`: a resource you did not edit replays byte for byte as the site sent it, in the recorded time, and an edited one takes time proportional to its size on the wire at the recorded per-resource speed. Shrinking a file finally makes it arrive sooner. HTML is stored as recorded instead of reformatted, and the bytes that went over the wire are kept in `inventory/originals/` — do not edit them or the `original` field. Recordings made with earlier versions still replay as before (recorded duration whatever the size); re-record them to get size-proportional timing
14
+ * The *Traffic* table in `summary.md` is now what the browser received in the run (Lighthouse's `network-requests`), not an estimate from fixed compression ratios; *Resource* is the decoded size from the same source
15
+ * Windows (x64) gets a playback proxy built for this release; until now the npm package carried a v0.3.0 binary. **Intel Macs are no longer supported**: postinstall stops with `Unsupported platform` instead of downloading arm64 binaries that cannot run there
16
+ * Fix the documentation of inline `contentUtf8` / `contentBase64`: they are used only when there is no `contentFilePath`, not in preference to the file
17
+
5
18
  ### 0.11.0 (2026-08-16)
6
19
 
7
20
  * Add `psq llm` — the embedded reference for AI agents (`--format markdown|json`), sourced from `llmdocs/` and shipped with the package
package/README.ja.md CHANGED
@@ -139,8 +139,8 @@ yarn psq proxy -p 8080 --record https://example.com/
139
139
  ## AIエージェントから使う
140
140
 
141
141
  PageSpeed Quest は、AIエージェント向けのリファレンスを自分で持っています。
142
- 鉄則・インベントリのスキーマ・再生時のタイミングの計算式・「どの編集がどの施策を
143
- 模擬するか」の一覧が、1コマンドで全部出ます。
142
+ 鉄則・調査の進め方・インベントリのスキーマ・再生時のタイミングの計算式・
143
+ 編集が再生にどう効くか・計測結果の読み方が、1コマンドで全部出ます。
144
144
 
145
145
  ```sh
146
146
  yarn psq llm # Markdown(既定)
@@ -156,11 +156,16 @@ yarn psq llm --format json # 章ごとのJSON配列
156
156
 
157
157
  | スキル | 内容 |
158
158
  | --- | --- |
159
+ | `psq-usage` | URL の調査を通しで行う。記録 → 計測 → ボトルネック調査 → 1つずつ試す → 効いたものを採用 → 改善幅を報告 |
159
160
  | `psq-install` | `psq` が動く状態のプロジェクトを用意する |
160
- | `psq-usage` | 記録 → ベースライン → 編集 → 計測のループ |
161
- | `psq-inventory` | ファイル構造と、施策ごとの編集レシピ |
161
+ | `psq-record` | ページを記録し、記録を点検し、ベースラインとして凍結する |
162
+ | `psq-measure` | Lighthouse の複数回計測と中央値、レポートからボトルネックを読む、スクリーンショット比較 |
163
+ | `psq-inventory` | 記録への編集が再生にどう効くか |
162
164
  | `psq-video` | 読み込み過程のビフォーアフター動画 |
163
165
 
166
+ スキルが教えるのはツールの使い方で、Web 高速化の施策ではありません。
167
+ 何を改善するかはエージェントの判断に任せています。
168
+
164
169
  Claude Code の場合:
165
170
 
166
171
  ```sh
package/README.md CHANGED
@@ -139,8 +139,9 @@ However, since this HTTP proxy uses a dummy SSL certificate, please disable the
139
139
  ## Driving it with an AI agent
140
140
 
141
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:
142
+ everything an agent needs — the ground rules, the investigation loop, the
143
+ inventory schema, the timing model, how an edit reaches the replay, and how to
144
+ read the measurements:
144
145
 
145
146
  ```sh
146
147
  yarn psq llm # Markdown (default)
@@ -157,11 +158,16 @@ The repository also ships an Agent Skills bundle under
157
158
 
158
159
  | Skill | What it covers |
159
160
  | --- | --- |
161
+ | `psq-usage` | the whole investigation of a URL: record, measure, find bottlenecks, try changes one at a time, adopt what helps, report the gain |
160
162
  | `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-record` | recording a page, checking the recording, freezing the baseline |
164
+ | `psq-measure` | repeated Lighthouse runs and medians, reading the report for bottlenecks, screenshot diffs |
165
+ | `psq-inventory` | how an edit to the recording reaches the replay |
163
166
  | `psq-video` | before/after videos of the load |
164
167
 
168
+ The skills teach the tool, not web performance: choosing what to optimize is
169
+ left to the agent.
170
+
165
171
  For Claude Code, add the ideamans marketplace and install the plugin:
166
172
 
167
173
  ```sh
package/build/cli.js CHANGED
@@ -80,7 +80,6 @@ function registerLighthouseCommands(main) {
80
80
  artifactsDir,
81
81
  headless: !laud,
82
82
  timeout,
83
- inventoryDir,
84
83
  resources: inventory.resources,
85
84
  }, dependency());
86
85
  dependency().logger?.info('Lighthouse completed');
@@ -261,4 +260,4 @@ export function createProgram() {
261
260
  registerLlmCommands(main);
262
261
  return main;
263
262
  }
264
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2NsaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLElBQUksTUFBTSxNQUFNLENBQUE7QUFFdkIsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFdBQVcsQ0FBQTtBQUNuQyxPQUFPLEtBQUssTUFBTSxZQUFZLENBQUE7QUFFOUIsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGlCQUFpQixDQUFBO0FBQzVDLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQTtBQUNoRCxPQUFPLEVBQUUsY0FBYyxFQUFFLGFBQWEsRUFBRSxNQUFNLFVBQVUsQ0FBQTtBQUN4RCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sZUFBZSxDQUFBO0FBRTVDLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGNBQWMsQ0FBQTtBQUVyRSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsaUJBQWlCLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxZQUFZLENBQUE7QUFFdkY7Ozs7OztHQU1HO0FBQ0gsSUFBSSxrQkFBMEMsQ0FBQTtBQUU5QyxTQUFTLFVBQVU7SUFDakIsSUFBSSxDQUFDLGtCQUFrQjtRQUFFLGtCQUFrQixHQUFHLElBQUksVUFBVSxFQUFFLENBQUE7SUFDOUQsT0FBTyxrQkFBa0IsQ0FBQTtBQUMzQixDQUFDO0FBRUQsU0FBUyxPQUFPLENBQUMsS0FBYSxFQUFFLFFBQWtCO0lBQ2hELE9BQU8sUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUE7QUFDakMsQ0FBQztBQUVELFNBQVMsMEJBQTBCLENBQUMsSUFBYTtJQUMvQyxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFBO0lBQzdDLFVBQVUsQ0FBQyxXQUFXLENBQUMsbURBQW1ELENBQUMsQ0FBQTtJQUMzRSxVQUFVLENBQUMsTUFBTSxDQUFD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
263
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2NsaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLElBQUksTUFBTSxNQUFNLENBQUE7QUFFdkIsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFdBQVcsQ0FBQTtBQUNuQyxPQUFPLEtBQUssTUFBTSxZQUFZLENBQUE7QUFFOUIsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGlCQUFpQixDQUFBO0FBQzVDLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQTtBQUNoRCxPQUFPLEVBQUUsY0FBYyxFQUFFLGFBQWEsRUFBRSxNQUFNLFVBQVUsQ0FBQTtBQUN4RCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sZUFBZSxDQUFBO0FBRTVDLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGNBQWMsQ0FBQTtBQUVyRSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsaUJBQWlCLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxZQUFZLENBQUE7QUFFdkY7Ozs7OztHQU1HO0FBQ0gsSUFBSSxrQkFBMEMsQ0FBQTtBQUU5QyxTQUFTLFVBQVU7SUFDakIsSUFBSSxDQUFDLGtCQUFrQjtRQUFFLGtCQUFrQixHQUFHLElBQUksVUFBVSxFQUFFLENBQUE7SUFDOUQsT0FBTyxrQkFBa0IsQ0FBQTtBQUMzQixDQUFDO0FBRUQsU0FBUyxPQUFPLENBQUMsS0FBYSxFQUFFLFFBQWtCO0lBQ2hELE9BQU8sUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUE7QUFDakMsQ0FBQztBQUVELFNBQVMsMEJBQTBCLENBQUMsSUFBYTtJQUMvQyxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFBO0lBQzdDLFVBQVUsQ0FBQyxXQUFXLENBQUMsbURBQW1ELENBQUMsQ0FBQTtJQUMzRSxVQUFVLENBQUMsTUFBTSxDQUFD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
@@ -9,6 +9,9 @@ export interface LighthouseAudit {
9
9
  score: number | null;
10
10
  numericValue?: number;
11
11
  displayValue?: string;
12
+ details?: {
13
+ items?: unknown[];
14
+ };
12
15
  }
13
16
  /**
14
17
  * Lighthouse JSON report structure (partial)
@@ -26,7 +29,6 @@ export interface LighthouseReport {
26
29
  export interface GenerateLighthouseSummaryInput {
27
30
  jsonPath: string;
28
31
  outputPath: string;
29
- inventoryDir?: string;
30
32
  resources?: Resource[];
31
33
  }
32
34
  /**
@@ -12,9 +12,21 @@ const PERFORMANCE_METRICS = [
12
12
  { id: 'speed-index', abbr: 'SI', unit: 'ms', weight: 0.1 },
13
13
  ];
14
14
  /**
15
- * Maps MIME type to resource type category
15
+ * Maps a Lighthouse request to a resource type category
16
16
  */
17
- function getResourceType(mime) {
17
+ function getResourceType(resourceType, mime) {
18
+ switch (resourceType) {
19
+ case 'Document':
20
+ return 'document';
21
+ case 'Stylesheet':
22
+ return 'stylesheet';
23
+ case 'Script':
24
+ return 'script';
25
+ case 'Image':
26
+ return 'image';
27
+ case 'Font':
28
+ return 'font';
29
+ }
18
30
  if (!mime)
19
31
  return 'other';
20
32
  if (mime.includes('html'))
@@ -41,57 +53,30 @@ function formatBytes(bytes) {
41
53
  return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
42
54
  }
43
55
  /**
44
- * Calculates traffic statistics by resource type
56
+ * Calculates traffic statistics by resource type from what the browser
57
+ * actually received in this run (Lighthouse's `network-requests` audit)
45
58
  */
46
- async function calculateResourceStats(resources, inventoryDir) {
59
+ function calculateResourceStats(report) {
47
60
  const statsMap = new Map();
48
61
  // Initialize all resource types
49
62
  const types = ['document', 'stylesheet', 'script', 'image', 'font', 'other'];
50
63
  for (const type of types) {
51
64
  statsMap.set(type, { type, count: 0, trafficSize: 0, resourceSize: 0 });
52
65
  }
53
- for (const resource of resources) {
54
- if (!resource.contentFilePath)
66
+ const items = (report.audits?.['network-requests']?.details?.items ?? []);
67
+ for (const item of items) {
68
+ // data: and blob: URLs never crossed the network
69
+ if (!item.url || !/^https?:/.test(item.url))
55
70
  continue;
56
- const type = getResourceType(resource.contentTypeMime);
57
- const stat = statsMap.get(type);
71
+ const stat = statsMap.get(getResourceType(item.resourceType, item.mimeType));
58
72
  if (!stat)
59
73
  continue;
60
- try {
61
- const filePath = Path.join(inventoryDir, resource.contentFilePath);
62
- const fileStat = await fs.stat(filePath);
63
- const resourceSize = fileStat.size;
64
- // Traffic size: if content-encoding exists, estimate compressed size
65
- // Otherwise use resource size
66
- // Note: The file is stored decompressed, so we estimate traffic size
67
- // based on typical compression ratios for each type
68
- let trafficSize = resourceSize;
69
- if (resource.contentEncoding) {
70
- // For compressed resources, estimate traffic size based on typical ratios
71
- // These are rough estimates - actual values would require re-compression
72
- const compressionRatios = {
73
- document: 0.2,
74
- stylesheet: 0.15,
75
- script: 0.25,
76
- image: 0.95, // Images are usually already compressed
77
- font: 0.7,
78
- other: 0.5,
79
- };
80
- trafficSize = Math.round(resourceSize * compressionRatios[type]);
81
- }
82
- stat.count++;
83
- stat.trafficSize += trafficSize;
84
- stat.resourceSize += resourceSize;
85
- }
86
- catch {
87
- // File not found or other error - skip
88
- }
74
+ stat.count++;
75
+ stat.trafficSize += item.transferSize ?? 0;
76
+ stat.resourceSize += item.resourceSize ?? 0;
89
77
  }
90
78
  // Filter out types with no resources and sort by fixed order
91
- const typeOrder = ['document', 'stylesheet', 'script', 'image', 'font', 'other'];
92
- const stats = Array.from(statsMap.values())
93
- .filter((s) => s.count > 0)
94
- .sort((a, b) => typeOrder.indexOf(a.type) - typeOrder.indexOf(b.type));
79
+ const stats = types.map((type) => statsMap.get(type)).filter((s) => s.count > 0);
95
80
  const totals = stats.reduce((acc, s) => ({
96
81
  trafficSize: acc.trafficSize + s.trafficSize,
97
82
  resourceSize: acc.resourceSize + s.resourceSize,
@@ -158,10 +143,10 @@ export async function generateLighthouseSummary(opts, dependency) {
158
143
  lines.push(`- **Overall** ${formatScore(overallScore)}`);
159
144
  lines.push('');
160
145
  // Section 3: Resource Traffic (if inventory data is provided)
161
- if (opts.resources && opts.inventoryDir) {
162
- const { stats, totals } = await calculateResourceStats(opts.resources, opts.inventoryDir);
146
+ if (opts.resources) {
147
+ const { stats, totals } = calculateResourceStats(report);
163
148
  if (stats.length > 0) {
164
- // Traffic section (compressed/transferred size)
149
+ // Traffic section (bytes received, after compression and headers)
165
150
  lines.push('## Traffic: Type / Count / Size / Bytes');
166
151
  lines.push('');
167
152
  for (const stat of stats) {
@@ -169,7 +154,7 @@ export async function generateLighthouseSummary(opts, dependency) {
169
154
  }
170
155
  lines.push(`- **total** / ${stats.reduce((sum, s) => sum + s.count, 0)} / ${formatBytes(totals.trafficSize)} / ${totals.trafficSize}`);
171
156
  lines.push('');
172
- // Resource section (decompressed/original size)
157
+ // Resource section (decoded body size)
173
158
  lines.push('## Resource: Type / Count / Size / Bytes');
174
159
  lines.push('');
175
160
  for (const stat of stats) {
@@ -186,4 +171,4 @@ export async function generateLighthouseSummary(opts, dependency) {
186
171
  await fs.writeFile(opts.outputPath, lines.join('\n'), 'utf-8');
187
172
  dependency.logger?.info(`Lighthouse summary saved to ${opts.outputPath}`);
188
173
  }
189
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlnaHRob3VzZS1zdW1tYXJ5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2xpZ2h0aG91c2Utc3VtbWFyeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxhQUFhLENBQUE7QUFDNUIsT0FBTyxJQUFJLE1BQU0sTUFBTSxDQUFBO0FBOEJ2Qjs7O0dBR0c7QUFDSCxNQUFNLG1CQUFtQixHQUFHO0lBQzFCLEVBQUUsRUFBRSxFQUFFLDBCQUEwQixFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO0lBQ3pFLEVBQUUsRUFBRSxFQUFFLHlCQUF5QixFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO0lBQ3RFLEVBQUUsRUFBRSxFQUFFLHFCQUFxQixFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFO0lBQ25FLEVBQUUsRUFBRSxFQUFFLHdCQUF3QixFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFO0lBQ3RFLEVBQUUsRUFBRSxFQUFFLGFBQWEsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRTtDQUMzRCxDQUFBO0FBd0JEOztHQUVHO0FBQ0gsU0FBUyxlQUFlLENBQUMsSUFBd0I7SUFDL0MsSUFBSSxDQUFDLElBQUk7UUFBRSxPQUFPLE9BQU8sQ0FBQTtJQUN6QixJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDO1FBQUUsT0FBTyxVQUFVLENBQUE7SUFDNUMsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQztRQUFFLE9BQU8sWUFBWSxDQUFBO0lB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
174
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlnaHRob3VzZS1zdW1tYXJ5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2xpZ2h0aG91c2Utc3VtbWFyeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxhQUFhLENBQUE7QUFDNUIsT0FBTyxJQUFJLE1BQU0sTUFBTSxDQUFBO0FBK0J2Qjs7O0dBR0c7QUFDSCxNQUFNLG1CQUFtQixHQUFHO0lBQzFCLEVBQUUsRUFBRSxFQUFFLDBCQUEwQixFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO0lBQ3pFLEVBQUUsRUFBRSxFQUFFLHlCQUF5QixFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO0lBQ3RFLEVBQUUsRUFBRSxFQUFFLHFCQUFxQixFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFO0lBQ25FLEVBQUUsRUFBRSxFQUFFLHdCQUF3QixFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFO0lBQ3RFLEVBQUUsRUFBRSxFQUFFLGFBQWEsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRTtDQUMzRCxDQUFBO0FBb0NEOztHQUVHO0FBQ0gsU0FBUyxlQUFlLENBQUMsWUFBZ0MsRUFBRSxJQUF3QjtJQUNqRixRQUFRLFlBQVksRUFBRSxDQUFDO1FBQ3JCLEtBQUssVUFBVTtZQUNiLE9BQU8sVUFBVSxDQUFBO1FBQ25CLEtBQUssWUFBWTtZQUNmLE9BQU8sWUFBWSxDQUFBO1FBQ3JCLEtBQUssUUFBUTtZQUNYLE9BQU8sUUFBUSxDQUFBO1FBQ2pCLEtBQUssT0FBTztZQUNW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
@@ -9,7 +9,6 @@ export interface ExecLighthouseInput {
9
9
  headless: boolean;
10
10
  timeout: number;
11
11
  captureScoreAndMetrics?: boolean;
12
- inventoryDir?: string;
13
12
  resources?: Resource[];
14
13
  }
15
14
  export declare function execLighthouse(opts: ExecLighthouseInput, dependency: Pick<DependencyInterface, 'mkdirp' | 'executeLighthouse' | 'logger'>): Promise<void>;
@@ -15,7 +15,12 @@ export async function execLighthouse(opts, dependency) {
15
15
  `--form-factor=${deviceType}`,
16
16
  // Set screen emulation to match form factor
17
17
  `--screenEmulation.mobile=${deviceType === 'mobile' ? 'true' : 'false'}`,
18
+ // Report the load as observed. The proxy already reproduces each resource's
19
+ // timing; Lighthouse's default 'simulate' method would discard that and
20
+ // re-derive the metrics from its own network model, which ignores the proxy.
21
+ '--throttling-method=provided',
18
22
  // Disable throttling as Rust proxy handles timing accurately
23
+ '--throttling.requestLatencyMs=0',
19
24
  '--throttling.rttMs=0',
20
25
  '--throttling.throughputKbps=0',
21
26
  '--throttling.downloadThroughputKbps=0',
@@ -52,7 +57,6 @@ export async function execLighthouse(opts, dependency) {
52
57
  await generateLighthouseSummary({
53
58
  jsonPath,
54
59
  outputPath: summaryPath,
55
- inventoryDir: opts.inventoryDir,
56
60
  resources: opts.resources,
57
61
  }, dependency);
58
62
  }
@@ -61,4 +65,4 @@ export async function execLighthouse(opts, dependency) {
61
65
  }
62
66
  }
63
67
  }
64
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlnaHRob3VzZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9saWdodGhvdXNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sSUFBSSxNQUFNLE1BQU0sQ0FBQTtBQUd2QixPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQTtBQUNoRSxPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQTtBQWdCbkUsTUFBTSxDQUFDLEtBQUssVUFBVSxjQUFjLENBQ2xDLElBQXlCLEVBQ3pCLFVBQWdGO0lBRWhGLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxZQUFZLElBQUksYUFBYSxDQUFBO0lBQ3ZELE1BQU0sVUFBVSxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQTtJQUVyQyxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsVUFBVSxJQUFJLFFBQVEsQ0FBQTtJQUM5QyxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSxZQUFZLENBQUMsQ0FBQTtJQUN4RCxNQUFNLElBQUksR0FBYTtRQUNyQixJQUFJLENBQUMsR0FBRztRQUNSLGVBQWU7UUFDZixvQkFBb0I7UUFDcEIsaUJBQWlCLFVBQVUsRUFBRTtRQUM3QiwrQkFBK0I7UUFDL0IsaUJBQWlCLFVBQVUsRUFBRTtRQUM3Qiw0Q0FBNEM7UUFDNUMsNEJBQTRCLFVBQVUsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsT0FBTyxFQUFFO1FBQ3hFLDZEQUE2RDtRQUM3RCxzQkFBc0I7UUFDdEIsK0JBQStCO1FBQy9CLHVDQUF1QztRQUN2QyxxQ0FBcUM7UUFDckMsc0NBQXNDO0tBQ3ZDLENBQUE7SUFFRCxJQUFJLENBQUMsSUFBSSxDQUFDLHVCQUF1QixJQUFJLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQTtJQUVoRCxNQUFNLFdBQVcsR0FBYSxDQUFDLDZCQUE2QixFQUFFLG1DQUFtQyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQTtJQUNsSCxJQUFJLElBQUksQ0FBQyxRQUFRO1FBQUUsV0FBVyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQTtJQUNqRCxJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixXQUFXLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQTtJQUVwRCxJQUFJLElBQUksQ0FBQyxJQUFJO1FBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQTtJQUVsQyxNQUFNLFVBQVUsQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsQ0FBQTtJQUV4QyxvREFBb0Q7SUFDcEQsSUFBSSxJQUFJLENBQUMsc0JBQXNCLEtBQUssS0FBSyxFQUFFLENBQUM7UUFDMUMsTUFBTSxRQUFRLEdBQUcsR0FBRyxVQUFVLGNBQWMsQ0FBQTtRQUM1QyxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSx1QkFBdUIsQ0FBQyxDQUFBO1FBRW5FLElBQUksQ0FBQztZQUNILE1BQU0sdUJBQXVCLENBQzNCO2dCQUNFLFFBQVE7Z0JBQ1IsVUFBVSxFQUFFLFVBQVU7YUFDdkIsRUFDRCxVQUFVLENBQ1gsQ0FBQTtRQUNILENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsVUFBVSxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsbURBQW1ELEtBQUssRUFBRSxDQUFDLENBQUE7UUFDckYsQ0FBQztJQUNILENBQUM7SUFFRCw0QkFBNEI7SUFDNUIsSUFBSSxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDdEIsTUFBTSxRQUFRLEdBQUcsR0FBRyxVQUFVLGNBQWMsQ0FBQTtRQUM1QyxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSxZQUFZLENBQUMsQ0FBQTtRQUV6RCxJQUFJLENBQUM7WUFDSCxNQUFNLHlCQUF5QixDQUM3QjtnQkFDRSxRQUFRO2dCQUNSLFVBQVUsRUFBRSxXQUFXO2dCQUN2QixZQUFZLEVBQUUsSUFBSSxDQUFDLFlBQVk7Z0JBQy9CLFNBQVMsRUFBRSxJQUFJLENBQUMsU0FBUzthQUMxQixFQUNELFVBQVUsQ0FDWCxDQUFBO1FBQ0gsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixVQUFVLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQywwQ0FBMEMsS0FBSyxFQUFFLENBQUMsQ0FBQTtRQUM1RSxDQUFDO0lBQ0gsQ0FBQztBQUNILENBQUMifQ==
68
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlnaHRob3VzZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9saWdodGhvdXNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sSUFBSSxNQUFNLE1BQU0sQ0FBQTtBQUd2QixPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQTtBQUNoRSxPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQTtBQWVuRSxNQUFNLENBQUMsS0FBSyxVQUFVLGNBQWMsQ0FDbEMsSUFBeUIsRUFDekIsVUFBZ0Y7SUFFaEYsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLFlBQVksSUFBSSxhQUFhLENBQUE7SUFDdkQsTUFBTSxVQUFVLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFBO0lBRXJDLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxVQUFVLElBQUksUUFBUSxDQUFBO0lBQzlDLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLFlBQVksQ0FBQyxDQUFBO0lBQ3hELE1BQU0sSUFBSSxHQUFhO1FBQ3JCLElBQUksQ0FBQyxHQUFHO1FBQ1IsZUFBZTtRQUNmLG9CQUFvQjtRQUNwQixpQkFBaUIsVUFBVSxFQUFFO1FBQzdCLCtCQUErQjtRQUMvQixpQkFBaUIsVUFBVSxFQUFFO1FBQzdCLDRDQUE0QztRQUM1Qyw0QkFBNEIsVUFBVSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxPQUFPLEVBQUU7UUFDeEUsNEVBQTRFO1FBQzVFLHdFQUF3RTtRQUN4RSw2RUFBNkU7UUFDN0UsOEJBQThCO1FBQzlCLDZEQUE2RDtRQUM3RCxpQ0FBaUM7UUFDakMsc0JBQXNCO1FBQ3RCLCtCQUErQjtRQUMvQix1Q0FBdUM7UUFDdkMscUNBQXFDO1FBQ3JDLHNDQUFzQztLQUN2QyxDQUFBO0lBRUQsSUFBSSxDQUFDLElBQUksQ0FBQyx1QkFBdUIsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUE7SUFFaEQsTUFBTSxXQUFXLEdBQWEsQ0FBQyw2QkFBNkIsRUFBRSxtQ0FBbUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUE7SUFDbEgsSUFBSSxJQUFJLENBQUMsUUFBUTtRQUFFLFdBQVcsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUE7SUFDakQsSUFBSSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsV0FBVyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUE7SUFFcEQsSUFBSSxJQUFJLENBQUMsSUFBSTtRQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUE7SUFFbEMsTUFBTSxVQUFVLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLENBQUE7SUFFeEMsb0RBQW9EO0lBQ3BELElBQUksSUFBSSxDQUFDLHNCQUFzQixLQUFLLEtBQUssRUFBRSxDQUFDO1FBQzFDLE1BQU0sUUFBUSxHQUFHLEdBQUcsVUFBVSxjQUFjLENBQUE7UUFDNUMsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsdUJBQXVCLENBQUMsQ0FBQTtRQUVuRSxJQUFJLENBQUM7WUFDSCxNQUFNLHVCQUF1QixDQUMzQjtnQkFDRSxRQUFRO2dCQUNSLFVBQVUsRUFBRSxVQUFVO2FBQ3ZCLEVBQ0QsVUFBVSxDQUNYLENBQUE7UUFDSCxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLFVBQVUsQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLG1EQUFtRCxLQUFLLEVBQUUsQ0FBQyxDQUFBO1FBQ3JGLENBQUM7SUFDSCxDQUFDO0lBRUQsNEJBQTRCO0lBQzVCLElBQUksSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBQ3RCLE1BQU0sUUFBUSxHQUFHLEdBQUcsVUFBVSxjQUFjLENBQUE7UUFDNUMsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsWUFBWSxDQUFDLENBQUE7UUFFekQsSUFBSSxDQUFDO1lBQ0gsTUFBTSx5QkFBeUIsQ0FDN0I7Z0JBQ0UsUUFBUTtnQkFDUixVQUFVLEVBQUUsV0FBVztnQkFDdkIsU0FBUyxFQUFFLElBQUksQ0FBQyxTQUFTO2FBQzFCLEVBQ0QsVUFBVSxDQUNYLENBQUE7UUFDSCxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLFVBQVUsQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLDBDQUEwQyxLQUFLLEVBQUUsQ0FBQyxDQUFBO1FBQzVFLENBQUM7SUFDSCxDQUFDO0FBQ0gsQ0FBQyJ9
@@ -51,9 +51,12 @@ version installed in the project you are working in.
51
51
  the inventory at recording time and reused. If you need to change either,
52
52
  record again.
53
53
 
54
- 5. **Lighthouse throttling is deliberately disabled** (`--throttling.*=0`,
55
- `cpuSlowdownMultiplier=1`). Timing is reproduced by the proxy, per resource.
56
- Re-enabling Lighthouse throttling would apply the penalty twice.
54
+ 5. **Lighthouse reports the load as observed** (`--throttling-method=provided`,
55
+ `--throttling.*=0`, `cpuSlowdownMultiplier=1`). Timing is reproduced by the
56
+ proxy, per resource, so Lighthouse must neither throttle again nor simulate.
57
+ Its default `simulate` method re-derives the metrics from a network model
58
+ that ignores the proxy — psq before 0.12 did that, and its numbers could even
59
+ fall below the document's TTFB. Do not compare scores across that boundary.
57
60
 
58
61
  6. **Unmatched requests get a 404.** The playback proxy only serves what is in
59
62
  the inventory. That is deliberate — falling through to the network would make
@@ -61,40 +64,55 @@ version installed in the project you are working in.
61
64
  failed request, not a request that never happens. To model "this resource is
62
65
  gone", also remove the reference to it from the HTML.
63
66
 
64
- 7. **Treat small deltas as noise.** Even against a fixed recording, Lighthouse
65
- varies by a few points and tens of milliseconds run to run. Repeat a
66
- measurement before believing a change under ~5% .
67
+ 7. **Never conclude from one run.** Runs of the same recording are close but
68
+ not identical, and an occasional run is an outlier. Measure each state at
69
+ least three times, compare medians, and treat a difference smaller than the
70
+ spread within each state as no difference.
71
+
72
+ 8. **The recording run is not the baseline.** `psq lighthouse recording` also
73
+ writes a Lighthouse report, but it measured the live site through the
74
+ recording proxy. Send it somewhere out of the way
75
+ (`psq lighthouse -a ./artifacts/recording recording <url>`) and measure the
76
+ baseline by playback.
67
77
 
68
78
  ## The loop
69
79
 
70
80
  ```sh
71
81
  # 1. Freeze the page (writes ./inventory)
72
- npx psq lighthouse recording https://example.com/
82
+ npx psq lighthouse -a ./artifacts/recording recording https://example.com/
73
83
 
74
- # 2. Keep the untouched copy
84
+ # 2. Keep the untouched copy, and a copy that accumulates adopted changes
75
85
  cp -r inventory baseline
86
+ cp -r inventory accepted
87
+
88
+ # 3. Measure the baseline, three runs → artifacts/baseline-N/summary.md, lighthouse.report.json
89
+ for n in 1 2 3; do npx psq -i ./baseline lighthouse -a ./artifacts/baseline-$n playback; done
76
90
 
77
- # 3. Measure the baseline → artifacts/summary.md, artifacts/lighthouse.report.html
78
- npx psq -i ./baseline lighthouse -a ./artifacts-baseline playback
91
+ # 4. Each trial: start from accepted, make ONE edit to ./inventory (chapter "Experiments")
92
+ rm -rf inventory && cp -r accepted inventory
79
93
 
80
- # 4. Edit ./inventory — see chapter "Experiments"
94
+ # 5. Measure the trial, three runs, and check it still renders (chapter "Measuring")
95
+ for n in 1 2 3; do npx psq lighthouse -a ./artifacts/t01-$n playback; done
81
96
 
82
- # 5. Measure the edited version
83
- npx psq lighthouse playback
97
+ # 6. Better beyond the spread and visually unchanged → adopt it
98
+ rm -rf accepted && cp -r inventory accepted
84
99
 
85
- # 6. Compare artifacts-baseline/summary.md with artifacts/summary.md
100
+ # 7. At the end, measure accepted against baseline from scratch
101
+ for n in 1 2 3; do npx psq -i ./accepted lighthouse -a ./artifacts/final-$n playback; done
86
102
  ```
87
103
 
88
104
  `summary.md` is a short Markdown digest (metrics, per-metric scores with their
89
- Lighthouse weights, traffic by resource type). It is written for exactly this
90
- comparison — diff the two files rather than opening two HTML reports.
105
+ Lighthouse weights, traffic by resource type). Medians across runs and the
106
+ evidence for *why* a page is slow come from `lighthouse.report.json` — see
107
+ "Measuring".
91
108
 
92
109
  ## What lives where
93
110
 
94
111
  | Path | What it is |
95
112
  | --- | --- |
96
113
  | `inventory/index.json` | the resource list and every resource's metadata. This is the file the proxy reads |
97
- | `inventory/contents/<METHOD>/<protocol>/<host>/<path>` | one file per recorded response body |
114
+ | `baseline/`, `accepted/` | conventional copies: the page as recorded, and the page with the adopted changes |
115
+ | `inventory/contents/<method>/<protocol>/<host>/<path>` | one file per recorded response body; `contentFilePath` gives the exact path |
98
116
  | `artifacts/lighthouse.report.html`, `.report.json` | the full Lighthouse report |
99
117
  | `artifacts/summary.md` | the digest to diff |
100
118
  | `artifacts/lighthouse.digest.png` | score and metrics as an image |
@@ -109,16 +127,20 @@ comparison — diff the two files rather than opening two HTML reports.
109
127
  | `unknown option '-i'` / the option is ignored | root and group options were placed after the subcommand | `psq -i ./baseline lighthouse -a ./art playback` |
110
128
  | the "after" is faster but the page is visibly broken | a referenced resource was deleted from `index.json` but not from the HTML | run `psq capture --compare` and look at the diff before trusting any number |
111
129
  | edits to a `.js` / `.css` file seem to have no effect on transfer size | the resource has `"minify": true`, so playback re-minifies before serving | expected — the wire size reflects the minified bytes, which is what the original site shipped |
130
+ | a smaller file loads no faster | the recording has no `formatVersion: 2` (made before psq 0.12) and replays the recorded duration | re-record |
112
131
  | the page looks fine but LCP got worse for no reason | an edit changed the byte size of a resource, and transfer time scales with size at the recorded `mbps` | that *is* the simulation working; check `summary.md` traffic figures |
113
132
  | recording captured analytics and ad beacons | third parties were not excluded | re-record with `-x 'google-analytics|doubleclick|facebook'` (repeatable) |
114
133
  | `loadshow` / `static-webshot` not found | the postinstall step that downloads them did not run | re-run `npm rebuild pagespeed-quest`, or set `LOADSHOW_PATH` / `WEBSHOT_PATH` |
115
134
  | Lighthouse cannot be found | it resolves to `./node_modules/.bin/lighthouse` | run inside the quest project, or set `LIGHTHOUSE_PATH` |
116
- | numbers drift between identical runs | normal measurement noise | repeat; do not act on deltas under ~5% |
135
+ | numbers drift between identical runs | normal measurement noise | three runs or more per state; compare medians against the spread |
136
+ | the baseline came from the recording run | that report measured the live site | measure the baseline with `psq -i ./baseline lighthouse … playback` |
137
+ | trial deltas cannot be attributed | a trial was built on the previous trial, or bundled several edits | start every trial from a fresh copy of `accepted/`, one edit each |
117
138
 
118
139
  ## What this tool will not do
119
140
 
120
141
  - It does not crawl. One entry URL plus whatever that page load requests.
121
142
  - It does not modify the live site, and nothing you edit locally reaches it.
122
- - It does not rewrite your resources for you. Editing the inventory is the
123
- work; this reference tells you which edit models which optimization.
143
+ - It does not rewrite your resources for you, and this reference does not
144
+ prescribe optimizations. Deciding what to change is the work; this reference
145
+ covers how an edit reaches the replay and how to measure it.
124
146
  - It does not replay user interaction. What is recorded is one page load.
@@ -6,8 +6,9 @@ receive during playback comes from here, and nothing else does.
6
6
  ```
7
7
  inventory/
8
8
  ├── index.json ← the resource list. THIS is what the proxy reads
9
+ ├── originals/ ← the recorded wire bytes of reformatted bodies. Never edit
9
10
  └── contents/
10
- └── GET/
11
+ └── get/
11
12
  └── https/
12
13
  └── example.com/
13
14
  ├── index.html
@@ -22,25 +23,32 @@ inventory/
22
23
  traffic figures while the proxy serves from `index.json` — the two silently
23
24
  disagree. Delete `inventory.json`, or keep it byte-identical.
24
25
  - **`contents/` holds one file per response body.** Text bodies are stored
25
- decoded, converted to UTF-8 and pretty-printed, so they are diffable and
26
- editable by hand.
26
+ decoded and converted to UTF-8; minified CSS and JavaScript are also
27
+ pretty-printed (and marked `minify: true`), HTML is kept as recorded.
28
+ - **`originals/` keeps the bytes that went over the wire** for every body that
29
+ was stored differently (decompressed, re-encoded or pretty-printed). Playback
30
+ serves them for unedited resources. Do not edit or delete it.
27
31
 
28
32
  ## How a URL becomes a path
29
33
 
30
- `contents/<METHOD>/<protocol>/<host>/<pathname>`
34
+ `contents/<method, lower-case>/<protocol>/<host>/<pathname>`
31
35
 
32
36
  | URL | File |
33
37
  | --- | --- |
34
- | `https://example.com/` | `contents/GET/https/example.com/index.html` |
35
- | `https://example.com/assets/app.css` | `contents/GET/https/example.com/assets/app.css` |
36
- | `https://example.com/api?id=1` | `contents/GET/https/example.com/api~id=1` |
37
- | `https://cdn.example.com:8443/a.js` | `contents/GET/https/cdn.example.com~8443/a.js` |
38
+ | `https://example.com/` | `contents/get/https/example.com/index.html` |
39
+ | `https://example.com/assets/app.css` | `contents/get/https/example.com/assets/app.css` |
40
+ | `https://example.com/app.js?v=1` | `contents/get/https/example.com/app~v%3D1.js` |
38
41
 
39
- Rules: a trailing `/` (or a path with no extension) gets `index.html`; the query
40
- string is appended after `~`; a colon in the host becomes `~`; an over-long
41
- basename is truncated and suffixed with a short SHA-1. Do not rename these files
42
- by hand — the mapping comes from `contentFilePath` in `index.json`, and the file
43
- name is only a convenience.
42
+ Rules: a trailing `/` gets `index.html`; the query string is URL-encoded and
43
+ inserted after `~`, before the extension; a query longer than 32 characters is
44
+ cut there and suffixed with `.~<sha1 of the rest>`. Do not guess and do not
45
+ rename these files by hand — `contentFilePath` in `index.json` (relative to the
46
+ inventory directory, so it starts with `contents/`) is the mapping, and the file
47
+ name is only a convenience:
48
+
49
+ ```sh
50
+ jq -r '.resources[] | [.url, .contentFilePath] | @tsv' inventory/index.json
51
+ ```
44
52
 
45
53
  ## `index.json`
46
54
 
@@ -48,6 +56,7 @@ name is only a convenience.
48
56
  {
49
57
  "entryUrl": "https://example.com/",
50
58
  "deviceType": "mobile",
59
+ "formatVersion": 2,
51
60
  "resources": [ ... ]
52
61
  }
53
62
  ```
@@ -55,35 +64,49 @@ name is only a convenience.
55
64
  `entryUrl` and `deviceType` are what `playback` uses instead of asking you for a
56
65
  URL. Changing `deviceType` here changes the Lighthouse form factor and the
57
66
  loadshow preset on the next playback — it does **not** re-record.
67
+ `formatVersion` is `2` for recordings made with psq 0.12 or later; without it
68
+ the older timing model applies (see below).
58
69
 
59
70
  ### A resource
60
71
 
61
72
  | Field | Effect at playback time |
62
73
  | --- | --- |
63
- | `method`, `url` | how the request is matched. A request that matches nothing gets a 404 |
64
- | `ttfbMs` | **the proxy sleeps this long after receiving the request, before the first byte.** Per request, not an offset from page start |
65
- | `durationMs` | recorded transfer duration. Informational; playback derives its own from size and `mbps` |
66
- | `mbps` | transfer speed for the body. Missing → 1.0 Mbps |
74
+ | `method`, `url` | how the request is matched. A request that matches nothing gets a 404. Required |
75
+ | `ttfbMs` | **the proxy sleeps this long after receiving the request, before the first byte.** Per request, not an offset from page start. Required |
76
+ | `durationMs` | recorded transfer duration. Used as-is only by recordings without `formatVersion: 2` |
77
+ | `mbps` | transfer speed for the body, measured at recording. Used for an edited body. Missing → the median of the same host |
67
78
  | `statusCode` | the status served |
68
79
  | `rawHeaders` | headers served, minus `content-length` and `content-encoding`, which are recomputed |
69
80
  | `contentEncoding` | `gzip` / `br` / `deflate` / `zstd` / `compress` / `identity`. The body is **re-compressed with this before it goes on the wire**, so it decides the transferred size |
70
81
  | `contentTypeMime`, `contentCharset` | the `Content-Type` served. `contentCharset` re-encodes the body from UTF-8 on the way out |
71
82
  | `contentFilePath` | the file under `contents/` to serve |
72
- | `contentUtf8` / `contentBase64` | inline body, used instead of the file when present |
83
+ | `contentUtf8` / `contentBase64` | inline body, used only when there is no `contentFilePath`. Recordings do not write it |
73
84
  | `minify` | `true` → the body is **re-minified before serving**. Set during recording when the original was minified |
74
85
  | `httpVersion` | protocol version reported for the response |
86
+ | `original` | written by the recorder: the path of the recorded wire bytes under `originals/`, a SHA-256 of the file in `contents/`, and the `contentEncoding` / `contentCharset` / `minify` at recording time. **Do not edit** |
75
87
 
76
88
  ### The timing model, precisely
77
89
 
78
90
  ```
79
- response time ≈ ttfbMs + (bytes on the wire × 8) / (mbps × 1,000,000)
91
+ unedited body: recorded wire bytes, ttfbMs + the recorded transfer time
92
+ edited body: ttfbMs + (bytes on the wire × 8) / (mbps × 1,000,000)
80
93
  ```
81
94
 
95
+ - A body is **unedited** while its file still matches the hash in `original`
96
+ and `contentEncoding`, `contentCharset` and `minify` are as recorded. It is
97
+ then served byte for byte as the site sent it — same compression, same size,
98
+ same time. Changing any of those makes it edited.
82
99
  - `ttfbMs` is a fixed per-request delay. It models server think time plus
83
100
  connection latency. Lower it to model a faster origin or a nearer CDN edge.
84
- - The second term is recomputed **from the bytes you leave in the file**, after
85
- minification and after `contentEncoding` compression. So shrinking a file
86
- makes it arrive sooner, automatically, with no other edit.
101
+ - For an edited body the transfer time is recomputed **from the bytes you leave
102
+ in the file**, after minification and after `contentEncoding` compression. So
103
+ shrinking a file makes it arrive sooner, with no other edit. `mbps` was
104
+ measured per resource at recording, so the same bytes take the time they took
105
+ on that connection.
106
+ - **Recordings without `formatVersion: 2`** (psq before 0.12) replay every body
107
+ in its recorded `durationMs` whatever its size, and re-minify text bodies with
108
+ an older minifier. Shrinking a file does not make it faster there. Re-record
109
+ to get the model above.
87
110
  - `--full-throttle` (used internally by `psq capture`) skips both. Never compare
88
111
  a full-throttle run with a normal one.
89
112
 
@@ -104,9 +127,10 @@ discarded.
104
127
 
105
128
  ## Editing safely
106
129
 
107
- 1. Copy `inventory/` to `baseline/` before the first edit.
130
+ 1. Copy `inventory/` to `baseline/` (and to `accepted/`) before the first edit.
108
131
  2. Change **one thing at a time**, then measure. Two edits in one run means you
109
- cannot attribute the delta.
132
+ cannot attribute the delta. Start each trial from a fresh copy of
133
+ `accepted/` (see "The loop" in the guide).
110
134
  3. After a structural edit (removing a script, changing a URL), run
111
135
  `psq capture --compare` and look at the picture. A faster broken page is easy
112
136
  to produce and easy to mistake for a win.
@@ -1,175 +1,72 @@
1
- # Experiments — which edit models which optimization
1
+ # Experiments — how an edit reaches the replay
2
2
 
3
- Each recipe is: the hypothesis, the exact edit, what should move, and what to
4
- watch out for. Make one edit, measure, record the delta, revert or keep. The
5
- metric names are the Lighthouse ones reported in `artifacts/summary.md`
6
- (LCP ×0.25, CLS ×0.25, TBT ×0.30, FCP ×0.10, SI ×0.10).
3
+ This chapter is about the mechanics of changing a recording so that a replay
4
+ reflects a change you want to test. **It does not prescribe optimizations** —
5
+ deciding what to try is the agent's or the engineer's judgement. What matters
6
+ here is that the edit models what you intend, and nothing else.
7
7
 
8
8
  Paths below are relative to the inventory directory.
9
9
 
10
- ## Images
11
-
12
- ### Compress or re-encode an image
13
-
14
- **Hypothesis** "the hero image is far heavier than it needs to be."
15
-
16
- Replace the file in place, keeping the same path:
17
-
18
- ```sh
19
- cwebp -q 75 contents/GET/https/example.com/img/hero.jpg \
20
- -o contents/GET/https/example.com/img/hero.jpg
21
- ```
22
-
23
- Then, in `index.json`, set the served type to match the new bytes:
24
-
25
- ```json
26
- { "contentTypeMime": "image/webp", "rawHeaders": { "content-type": "image/webp" } }
27
- ```
28
-
29
- **Moves** LCP, SI, and total transfer. Transfer time falls in proportion to the
30
- byte count at the recorded `mbps`.
31
-
32
- **Watch out** The URL still ends in `.jpg`; that is fine, browsers go by
33
- `Content-Type`. Do not touch `content-length`. If the format is not supported by
34
- the recorded device profile the image simply fails to decode — check
35
- `psq capture`.
36
-
37
- ### Serve a correctly sized image
38
-
39
- Same edit, but resize rather than re-encode. This is usually the larger win on
40
- mobile recordings, because the recorded page often ships a desktop-sized asset.
41
- Compare `summary.md`'s image traffic line before and after.
42
-
43
- ### Lazy-load below-the-fold images
44
-
45
- Edit the document: add `loading="lazy"` to `<img>` elements below the fold.
46
-
47
- **Moves** FCP and SI, sometimes LCP indirectly (bandwidth freed for the hero).
48
- Nothing needs to change in `index.json` — the lazily-loaded requests simply do
49
- not happen during the measured window.
50
-
51
- ### Preload the LCP image
52
-
53
- ```html
54
- <link rel="preload" as="image" href="/img/hero.webp" fetchpriority="high">
55
- ```
56
-
57
- in `<head>`. **Moves** LCP. **Watch out** the recorded `ttfbMs` of that resource
58
- still applies as a fixed delay, so the win is bounded by it.
59
-
60
- ## Scripts
61
-
62
- ### Defer or async a render-blocking script
63
-
64
- Edit the document, add `defer` (order preserved) or `async` (order not).
65
-
66
- **Moves** FCP, LCP, SI. TBT often moves too, because the work lands after the
67
- first paint.
68
-
69
- ### Remove a third-party tag
70
-
71
- Delete the `<script>` from the document. Optionally also delete the resource
72
- from `index.json` — but only after the reference is gone, or the browser will
73
- record a failed request (see the 404 rule).
74
-
75
- **Moves** TBT most visibly, plus whatever the tag was blocking. This is the
76
- single most informative experiment on most commercial pages: it puts a number on
77
- "what is the tag manager costing us".
78
-
79
- **Watch out** Some tags inject further requests. Removing the parent removes
80
- those too, which is realistic — but it makes the delta larger than the tag's own
81
- weight, so say so when reporting.
82
-
83
- ### Shrink the bundle
84
-
85
- Replace the file under `contents/` with a smaller build (drop a polyfill, remove
86
- a library, run a real minifier). Because the browser actually executes what you
87
- serve, **TBT and main-thread time respond for real** — this is not a simulated
88
- number.
89
-
90
- ## CSS and fonts
91
-
92
- ### Inline critical CSS, defer the rest
93
-
94
- In the document, add a `<style>` block with the above-the-fold rules and switch
95
- the stylesheet link to a deferred load:
96
-
97
- ```html
98
- <link rel="preload" href="/assets/app.css" as="style" onload="this.rel='stylesheet'">
99
- ```
100
-
101
- **Moves** FCP, LCP, SI. **Watch out** CLS often gets *worse* if the inlined
102
- subset is incomplete — check `psq capture --compare` as well as the score.
103
-
104
- ### Remove unused CSS
105
-
106
- Edit the stylesheet under `contents/`. Remember `minify: true` re-minifies, so
107
- the win shows up as fewer bytes, not as tidier formatting.
108
-
109
- ### `font-display: swap` and font preloading
110
-
111
- Edit the `@font-face` block in the stylesheet, and/or add
112
- `<link rel="preload" as="font" crossorigin>` to the document.
113
-
114
- **Moves** FCP and LCP when text was the largest element; CLS if the swap causes
115
- reflow. Subsetting the font file itself is the transfer-size half of the same
116
- experiment.
117
-
118
- ## Network and server
119
-
120
- These are the levers that do not exist in a normal development environment, and
121
- they are the reason for the `index.json` fields.
122
-
123
- ### "What if the server responded faster?"
124
-
125
- Lower `ttfbMs` on the document resource (often 200–800 ms on a real recording):
126
-
127
- ```json
128
- { "url": "https://example.com/", "ttfbMs": 80 }
129
- ```
130
-
131
- **Moves** everything downstream, roughly one-for-one. Run this early — it tells
132
- you how much of the budget is back-end and therefore *not* fixable in the
133
- front-end.
134
-
135
- ### "What if we put it on a CDN / on a faster link?"
136
-
137
- Raise `mbps` on the resources served from the slow host. To model a slower
138
- network instead, lower it. Apply it to a whole host, not a single file, or the
139
- result will not resemble anything real.
140
-
141
- ### "What if we finally enabled compression?"
142
-
143
- Set `contentEncoding` to `br` (or `gzip`) on the text resources that had
144
- `identity`. The proxy re-compresses and the transfer time follows.
145
-
146
- The reverse — setting `identity` on everything — quantifies what compression is
147
- already buying you, which is a useful number when someone proposes turning it
148
- off for CPU reasons.
149
-
150
- ### "What if there were fewer requests?"
151
-
152
- Concatenate two files into one under `contents/`, update the document to
153
- reference the survivor, and delete the other entry from `index.json`. The win
154
- here is mostly the removed `ttfbMs`, so it is only worth it where that value is
155
- large.
156
-
157
- ## Layout stability
158
-
159
- ### Reserve space for images and embeds
160
-
161
- Add `width` / `height` (or an `aspect-ratio` rule) in the document or the
162
- stylesheet. **Moves** CLS, which carries the same weight as LCP — a cheap edit
163
- with a disproportionate score effect.
10
+ ## Content edits
11
+
12
+ Edit the file a resource's `contentFilePath` points to. The browser receives and
13
+ executes exactly those bytes, so effects on parsing, script execution, layout
14
+ and paint are **measured, not estimated**, and the transfer time follows the new
15
+ size (see the timing model in "The inventory" — this needs a recording with
16
+ `formatVersion: 2`, i.e. made with psq 0.12 or later).
17
+
18
+ psq-specific rules:
19
+
20
+ - **Changing an image's format** — replace the bytes at the same path, then set
21
+ the served type to match:
22
+
23
+ ```json
24
+ { "contentTypeMime": "image/webp", "rawHeaders": { "content-type": "image/webp" } }
25
+ ```
26
+
27
+ The URL may keep its old extension; browsers go by `Content-Type`. Never edit
28
+ `content-length`.
29
+ - **`minify: true`** — the file is re-minified before serving. Whitespace has no
30
+ effect on the wire; a syntax error may surface as a minifier failure.
31
+ - **Leave `original` and `originals/` alone.** They are how playback recognises
32
+ the resources you did not touch and serves them exactly as recorded.
33
+ - **`ttfbMs` does not move with the content.** A preloaded, reprioritised or
34
+ shrunk resource still waits its recorded `ttfbMs` before its first byte.
35
+
36
+ ## Adding and removing resources
37
+
38
+ - **Removing**: delete the reference from the HTML (or CSS, or script) in the
39
+ same edit. An entry deleted while still referenced becomes a 404 — a failed
40
+ request, which makes the result look worse than the truth. Removing a parent
41
+ tag also removes whatever it would have injected; say so when reporting.
42
+ - **Adding** (a split file, a self-hosted font, a new preload): add an entry to
43
+ `resources`. `method`, `url` and `ttfbMs` are required — an entry missing them
44
+ makes `index.json` unreadable. Set `statusCode`, `contentTypeMime` and
45
+ `contentFilePath`, and copy `ttfbMs` / `mbps` from a comparable resource on
46
+ the same host so the timing is not invented. Any URL the browser requests
47
+ that has no entry gets a 404.
48
+
49
+ ## Metadata edits — what a front-end change cannot do
50
+
51
+ These levers do not exist in a normal development environment, and they are the
52
+ reason for the `index.json` fields.
53
+
54
+ | To model | Edit | Note |
55
+ | --- | --- | --- |
56
+ | a faster or slower origin | lower / raise `ttfbMs`, the document first | separates the back-end share of the load from the front-end share |
57
+ | a faster or slower link, a CDN | `mbps` on every resource of that host | per host, not per file, or the result resembles nothing real |
58
+ | compression on or off | `contentEncoding` (`br`, `gzip`, `identity`) on text resources | the proxy re-compresses; the reverse quantifies what compression already buys |
59
+ | a different form factor | top-level `deviceType` | changes the Lighthouse form factor and the loadshow preset; does not re-record |
164
60
 
165
61
  ## What this cannot model
166
62
 
167
63
  State these plainly when reporting results.
168
64
 
169
- - **Caching across page views.** Every playback is a cold load.
65
+ - **Caching across page views.** Every playback is a cold load, so
66
+ `cache-insight` and `bf-cache` findings cannot be acted on in a replay.
170
67
  - **HTTP/2 prioritisation and connection contention.** Each host is served by
171
- its own local server; the real contention on a shared connection is not
172
- reproduced.
68
+ the local proxy; the real contention on a shared connection is not
69
+ reproduced, and `modern-http-insight` describes the proxy, not the origin.
173
70
  - **Server-side changes that alter the HTML.** You can hand-edit the HTML to
174
71
  what the server *would* emit, but the edit is your hypothesis, not a
175
72
  measurement of it.
@@ -179,16 +76,18 @@ State these plainly when reporting results.
179
76
  moment of recording, which is a feature for comparison and a limitation for
180
77
  representativeness.
181
78
 
182
- ## Reporting a result
79
+ ## Reporting a trial
183
80
 
184
- A useful report answers three questions: what was changed, what moved, and
185
- whether the page still looks right.
81
+ A useful line answers four questions: what was changed, what evidence led to it,
82
+ what moved (medians of several runs, reference → trial), and whether the page
83
+ still looks right.
186
84
 
187
85
  ```
188
- Hypothesis : defer the tag manager
189
- Edit : removed <script src="gtm.js"> from contents/GET/https/example.com/index.html
190
- Before : LCP 3.41s TBT 890ms Overall 42 (artifacts-baseline/summary.md)
191
- After : LCP 2.78s TBT 210ms Overall 61 (artifacts/summary.md)
192
- Visual : no diff (artifacts/capture-diff.txt)
193
- Caveat : removing the parent tag also removed 4 requests it injected
86
+ Trial : t01 defer tag manager
87
+ Evidence : render-blocking-insight lists gtm.js
88
+ Edit : contents/get/https/example.com/index.html — added defer to <script src="gtm.js">
89
+ Reference : Score 61 LCP 3.41s TBT 890ms (median of 3, artifacts/baseline-*)
90
+ Trial : Score 68 LCP 2.95s TBT 640ms (median of 3, artifacts/t01-defer-gtm-*)
91
+ Visual : no diff (artifacts/t01-capture/capture-diff.txt)
92
+ Decision : adopted
194
93
  ```
@@ -12,40 +12,78 @@ see the same page. Choose by the question being asked.
12
12
  Keep the two sides in separate artifact directories. `-a` is an option of the
13
13
  `lighthouse` / `loadshow` group, so it goes before the sub-subcommand.
14
14
 
15
- ## Lighthouse before / after
15
+ ## Lighthouse, several runs per state
16
16
 
17
17
  ```sh
18
- psq -i ./baseline lighthouse -a ./artifacts-baseline playback
19
- psq -i ./inventory lighthouse -a ./artifacts-after playback
20
- diff artifacts-baseline/summary.md artifacts-after/summary.md
18
+ for n in 1 2 3; do psq -i ./baseline lighthouse -a ./artifacts/baseline-$n playback; done
19
+ for n in 1 2 3; do psq -i ./inventory lighthouse -a ./artifacts/t01-$n playback; done
21
20
  ```
22
21
 
22
+ One directory per run — the same `-a` twice overwrites. Name them
23
+ `<label>-<n>`, the label naming the state.
24
+
23
25
  Each run writes:
24
26
 
25
27
  | File | Contents |
26
28
  | --- | --- |
27
29
  | `summary.md` | metrics, per-metric scores with weights, overall score, traffic and resource size by type |
28
30
  | `lighthouse.report.html` | the full report (open it when a number needs explaining) |
29
- | `lighthouse.report.json` | the same, machine-readable |
31
+ | `lighthouse.report.json` | the same, machine-readable — the source for medians and for the diagnosis |
30
32
  | `lighthouse.digest.png` | score gauge and metrics as one image — the thing to paste into a report |
31
33
  | `lighthouse-0.trace.json`, `*.devtoolslog.json` | saved assets (`--save-assets`) |
32
34
 
33
- `summary.md` is the file to diff. It is deliberately short and stable, so the
34
- diff shows the delta and nothing else.
35
+ A playback run takes roughly 20–30 seconds: Lighthouse measures the load as
36
+ observed (`--throttling-method=provided`) and waits for the page to go quiet.
35
37
 
36
38
  Options on the `lighthouse` group: `-a/--artifacts` (default `./artifacts`),
37
39
  `-t/--timeout` (ms, default 30000), `-l/--laud` — show the browser window and
38
40
  open the report at the end. `--laud` is for watching a run, not for measuring;
39
41
  a visible browser is not the same environment as the headless one.
40
42
 
41
- **Repeat before concluding.** Lighthouse noise on a fixed recording is a few
42
- points. Three runs per side is usually enough to see whether a delta is real.
43
+ ### Medians and spread
44
+
45
+ **Never conclude from one run.** Runs of the same recording are close but not
46
+ identical, and an occasional run is an outlier. Take the median of at least three runs
47
+ per state, and call a difference real only when it is larger than the spread
48
+ (max − min) within each state:
49
+
50
+ ```sh
51
+ jq -s -r '
52
+ def median: sort | if length % 2 == 1 then .[length/2|floor] else (.[length/2-1] + .[length/2]) / 2 end;
53
+ map({Score: (.categories.performance.score*100),
54
+ LCP: .audits["largest-contentful-paint"].numericValue,
55
+ FCP: .audits["first-contentful-paint"].numericValue,
56
+ SI: .audits["speed-index"].numericValue,
57
+ TBT: .audits["total-blocking-time"].numericValue,
58
+ CLS: .audits["cumulative-layout-shift"].numericValue}) as $r
59
+ | ["Score","LCP","FCP","SI","TBT","CLS"][] as $m | [$r[][$m]] as $v
60
+ | "\($m)\t\($v|median)\t\($v|min)\t\($v|max)"' artifacts/baseline-*/lighthouse.report.json
61
+ ```
62
+
63
+ ### Where the time goes
64
+
65
+ `lighthouse.report.json` holds the evidence. With
66
+ `J=artifacts/baseline-1/lighthouse.report.json`:
67
+
68
+ | Question | jq |
69
+ | --- | --- |
70
+ | which audits flag a problem | `.audits[] \| select(.score != null and .score < 1) \| [.id, .displayValue, .metricSavings]` |
71
+ | the LCP element | `.audits["lcp-breakdown-insight"].details.items[] \| select(.type=="node") \| .snippet` |
72
+ | how LCP time splits | `.audits["lcp-breakdown-insight"].details.items[] \| select(.type=="table") \| .items` |
73
+ | the request waterfall | `.audits["network-requests"].details.items` (`networkRequestTime`, `networkEndTime`, `transferSize`, `url`) |
74
+ | script cost per URL | `.audits["bootup-time"].details.items` |
75
+ | third parties | `.audits["third-parties-insight"].details.items` |
76
+
77
+ Lighthouse 13 keeps most of its diagnosis in `*-insight` audits. To act on a
78
+ URL, look up its `contentFilePath` in `index.json`. `cache-insight`, `bf-cache`,
79
+ `modern-http-insight` and interaction metrics describe things a replay cannot
80
+ model (see "Experiments").
43
81
 
44
82
  ## Video of the load, before and after
45
83
 
46
84
  ```sh
47
- psq -i ./baseline loadshow -a ./artifacts-baseline playback
48
- psq -i ./inventory loadshow -a ./artifacts-after playback
85
+ psq -i ./baseline loadshow -a ./artifacts/video-baseline playback
86
+ psq -i ./accepted loadshow -a ./artifacts/video-after playback
49
87
  ```
50
88
 
51
89
  Each writes `<artifacts>/loadshow.mp4` — a filmstrip of the load, laid out in
@@ -57,15 +95,15 @@ Use `-c/--credit` to stamp a label into the video, which is what makes a pair of
57
95
  videos legible side by side:
58
96
 
59
97
  ```sh
60
- psq -i ./baseline loadshow -a ./artifacts-baseline -c "Before" playback
61
- psq -i ./inventory loadshow -a ./artifacts-after -c "After — deferred GTM" playback
98
+ psq -i ./baseline loadshow -a ./artifacts/video-baseline -c "Before" playback
99
+ psq -i ./accepted loadshow -a ./artifacts/video-after -c "After — deferred GTM" playback
62
100
  ```
63
101
 
64
102
  To place them side by side, stack the two MP4s with ffmpeg; `psq` does not
65
103
  compose videos:
66
104
 
67
105
  ```sh
68
- ffmpeg -i artifacts-baseline/loadshow.mp4 -i artifacts-after/loadshow.mp4 \
106
+ ffmpeg -i artifacts/video-baseline/loadshow.mp4 -i artifacts/video-after/loadshow.mp4 \
69
107
  -filter_complex hstack -c:v libx264 before-after.mp4
70
108
  ```
71
109
 
@@ -82,8 +120,8 @@ so that the recording and the playback are driven the same way.
82
120
  ## Screenshot and visual diff
83
121
 
84
122
  ```sh
85
- psq -i ./baseline capture -a ./artifacts-baseline # baseline.png
86
- psq capture --compare ./artifacts-baseline/capture.png \
123
+ psq -i ./baseline capture -a ./artifacts/baseline-capture
124
+ psq capture -a ./artifacts/t01-capture --compare ./artifacts/baseline-capture/capture.png \
87
125
  --baseline-label "Before" --current-label "After"
88
126
  ```
89
127
 
@@ -112,6 +150,9 @@ banner will make every metric better and the page wrong.
112
150
  - script / 14 / 512.3 KB / 524595
113
151
  ```
114
152
 
115
- *Traffic* is what crossed the wire (after compression); *Resource* is the
116
- decompressed size. A change that moves resource size but not traffic size means
117
- you edited something that compresses away — expect little timing effect.
153
+ *Traffic* is what the browser received in this run, as Lighthouse measured it
154
+ (after compression, headers included); *Resource* is the decoded body size.
155
+ Both come from the report's `network-requests` audit, so they count every
156
+ request the page made, including 404s. A change that moves resource size but
157
+ not traffic size means you edited something that compresses away — expect
158
+ little timing effect.
@@ -12,7 +12,8 @@ Record a web page through a proxy, edit the recording, and replay it to measure
12
12
  ```
13
13
  Usage: psq [options] [command]
14
14
 
15
- Record a web page through a proxy, edit the recording, and replay it to measure the difference
15
+ Record a web page through a proxy, edit the recording, and replay it to measure
16
+ the difference
16
17
 
17
18
  Options:
18
19
  -v, --version Output the version number
@@ -23,7 +24,8 @@ Commands:
23
24
  lighthouse [options] Run Lighthouse (performance category) via a proxy
24
25
  loadshow [options] Run loadshow via a proxy
25
26
  proxy [options] Run the playback (or recording) proxy standalone
26
- capture [options] Capture a screenshot via playback proxy and optionally compare with a baseline
27
+ capture [options] Capture a screenshot via playback proxy and optionally
28
+ compare with a baseline
27
29
  llm [options] Print the embedded reference for AI agents
28
30
  help [command] display help for command
29
31
  ```
@@ -39,7 +41,8 @@ Run Lighthouse (performance category) via a proxy
39
41
 
40
42
  Options:
41
43
  -a, --artifacts <dir> Artifacts directory (default: "./artifacts")
42
- -l, --laud Show browser and open the report after completion (default: false)
44
+ -l, --laud Show browser and open the report after completion
45
+ (default: false)
43
46
  -t, --timeout <ms> Timeout milliseconds (default: "30000")
44
47
  -h, --help display help for command
45
48
 
@@ -63,7 +66,8 @@ Arguments:
63
66
 
64
67
  Options:
65
68
  -d, --device <mobile|desktop> Device type (default: "mobile")
66
- -x, --exclude <pattern> Regex patterns to exclude URLs from recording (repeatable) (default: [])
69
+ -x, --exclude <pattern> Regex patterns to exclude URLs from recording
70
+ (repeatable) (default: [])
67
71
  -h, --help display help for command
68
72
  ```
69
73
 
@@ -115,7 +119,8 @@ Arguments:
115
119
 
116
120
  Options:
117
121
  -d, --device <mobile|desktop> Device type (default: "mobile")
118
- -x, --exclude <pattern> Regex patterns to exclude URLs from recording (repeatable) (default: [])
122
+ -x, --exclude <pattern> Regex patterns to exclude URLs from recording
123
+ (repeatable) (default: [])
119
124
  -h, --help display help for command
120
125
  ```
121
126
 
@@ -143,8 +148,10 @@ Run the playback (or recording) proxy standalone
143
148
 
144
149
  Options:
145
150
  -p, --port <number> Proxy port (default: "8080")
146
- -r, --record <url> Recording URL to start the proxy as recording mode (default: "")
147
- -x, --exclude <pattern> Regex patterns to exclude URLs from recording (repeatable) (default: [])
151
+ -r, --record <url> Recording URL to start the proxy as recording mode
152
+ (default: "")
153
+ -x, --exclude <pattern> Regex patterns to exclude URLs from recording
154
+ (repeatable) (default: [])
148
155
  -h, --help display help for command
149
156
  ```
150
157
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pagespeed-quest",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "type": "module",
5
5
  "description": "A framework for efficient web front-end speed improvement",
6
6
  "main": "build/index.js",
@@ -69,7 +69,7 @@
69
69
  "pino-pretty": "^11.2.2",
70
70
  "prettier": "^2.1.1",
71
71
  "puppeteer": "^24.31.0",
72
- "rust-http-playback-proxy": "0.9.0",
72
+ "rust-http-playback-proxy": "0.11.1",
73
73
  "tmp-promise": "^3.0.3"
74
74
  },
75
75
  "devDependencies": {
@@ -18,7 +18,16 @@ const outputPath = join(projectRoot, 'llmdocs', '90-commands.md')
18
18
 
19
19
  const { createProgram } = await import(join(projectRoot, 'build', 'cli.js'))
20
20
 
21
+ /**
22
+ * Commander wraps help text to the terminal width, which would make the
23
+ * generated catalog depend on whoever ran the generator. Pin it so the output
24
+ * is reproducible and `--check` means something.
25
+ */
26
+ const HELP_WIDTH = 80
27
+
21
28
  function walk(command, path, depth, lines) {
29
+ command.configureHelp({ helpWidth: HELP_WIDTH })
30
+
22
31
  const heading = '#'.repeat(Math.min(depth + 1, 6))
23
32
  const title = [...path, command.name()].join(' ')
24
33
 
@@ -22,9 +22,6 @@ function getPlatformInfo() {
22
22
 
23
23
  if (platform === 'darwin' && arch === 'arm64') {
24
24
  return { os: 'darwin', arch: 'arm64', ext: 'tar.gz' }
25
- } else if (platform === 'darwin' && arch === 'x64') {
26
- // macOS x64 is not available, fall back to arm64 (Rosetta 2)
27
- return { os: 'darwin', arch: 'arm64', ext: 'tar.gz' }
28
25
  } else if (platform === 'linux' && arch === 'x64') {
29
26
  return { os: 'linux', arch: 'amd64', ext: 'tar.gz' }
30
27
  } else if (platform === 'linux' && arch === 'arm64') {
@@ -32,6 +29,8 @@ function getPlatformInfo() {
32
29
  } else if (platform === 'win32' && arch === 'x64') {
33
30
  return { os: 'windows', arch: 'amd64', ext: 'zip' }
34
31
  } else {
32
+ // Intel Macs are not supported: none of loadshow, static-webshot or the
33
+ // playback proxy ship a darwin-x64 build
35
34
  throw new Error(`Unsupported platform: ${platform} ${arch}`)
36
35
  }
37
36
  }