opengstack 0.14.0 → 0.14.2

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 (69) hide show
  1. package/AGENTS.md +4 -4
  2. package/CLAUDE.md +127 -110
  3. package/README.md +10 -5
  4. package/SKILL.md +500 -70
  5. package/bin/opengstack.js +69 -69
  6. package/commands/autoplan.md +7 -9
  7. package/commands/benchmark.md +84 -91
  8. package/commands/browse.md +60 -64
  9. package/commands/canary.md +7 -9
  10. package/commands/careful.md +2 -2
  11. package/commands/codex.md +7 -9
  12. package/commands/connect-chrome.md +7 -9
  13. package/commands/cso.md +7 -9
  14. package/commands/design-consultation.md +7 -9
  15. package/commands/design-review.md +7 -9
  16. package/commands/design-shotgun.md +7 -9
  17. package/commands/document-release.md +7 -9
  18. package/commands/freeze.md +3 -3
  19. package/commands/guard.md +4 -4
  20. package/commands/investigate.md +7 -9
  21. package/commands/land-and-deploy.md +7 -9
  22. package/commands/office-hours.md +7 -9
  23. package/commands/{gstack-upgrade.md → opengstack-upgrade.md} +64 -65
  24. package/commands/plan-ceo-review.md +7 -9
  25. package/commands/plan-design-review.md +7 -9
  26. package/commands/plan-eng-review.md +7 -9
  27. package/commands/qa-only.md +7 -9
  28. package/commands/qa.md +7 -9
  29. package/commands/retro.md +7 -9
  30. package/commands/review.md +7 -9
  31. package/commands/setup-browser-cookies.md +22 -26
  32. package/commands/setup-deploy.md +7 -9
  33. package/commands/ship.md +7 -9
  34. package/commands/unfreeze.md +7 -7
  35. package/docs/designs/CHROME_VS_CHROMIUM_EXPLORATION.md +9 -9
  36. package/docs/designs/CONDUCTOR_CHROME_SIDEBAR_INTEGRATION.md +2 -2
  37. package/docs/designs/CONDUCTOR_SESSION_API.md +16 -16
  38. package/docs/designs/DESIGN_SHOTGUN.md +74 -74
  39. package/docs/designs/DESIGN_TOOLS_V1.md +111 -111
  40. package/docs/skills.md +483 -202
  41. package/package.json +42 -43
  42. package/scripts/analytics.ts +188 -0
  43. package/scripts/dev-skill.ts +83 -0
  44. package/scripts/discover-skills.ts +39 -0
  45. package/scripts/eval-compare.ts +97 -0
  46. package/scripts/eval-list.ts +117 -0
  47. package/scripts/eval-select.ts +86 -0
  48. package/scripts/eval-summary.ts +188 -0
  49. package/scripts/eval-watch.ts +172 -0
  50. package/scripts/gen-skill-docs.ts +473 -0
  51. package/scripts/resolvers/browse.ts +129 -0
  52. package/scripts/resolvers/codex-helpers.ts +133 -0
  53. package/scripts/resolvers/composition.ts +48 -0
  54. package/scripts/resolvers/confidence.ts +37 -0
  55. package/scripts/resolvers/constants.ts +50 -0
  56. package/scripts/resolvers/design.ts +950 -0
  57. package/scripts/resolvers/index.ts +59 -0
  58. package/scripts/resolvers/learnings.ts +96 -0
  59. package/scripts/resolvers/preamble.ts +505 -0
  60. package/scripts/resolvers/review.ts +884 -0
  61. package/scripts/resolvers/testing.ts +573 -0
  62. package/scripts/resolvers/types.ts +45 -0
  63. package/scripts/resolvers/utility.ts +421 -0
  64. package/scripts/skill-check.ts +190 -0
  65. package/scripts/cleanup.py +0 -100
  66. package/scripts/filter-skills.sh +0 -114
  67. package/scripts/filter_skills.py +0 -164
  68. package/scripts/install-commands.js +0 -45
  69. package/scripts/install-skills.js +0 -60
package/bin/opengstack.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * OpenGStack CLI - Install and manage AI workflow skills
4
+ * opengstack CLI - Install and manage AI workflow skills
5
5
  * Usage: opengstack [options]
6
6
  * Example: opengstack --install
7
7
  */
@@ -13,93 +13,93 @@ const PKG_DIR = path.dirname(__dirname);
13
13
  const SKILLS_SOURCE = path.join(PKG_DIR, 'skills');
14
14
 
15
15
  function getSkillDescription(skillName) {
16
- const skillPath = path.join(SKILLS_SOURCE, skillName, 'SKILL.md');
17
- if (!fs.existsSync(skillPath)) return '';
18
-
19
- const content = fs.readFileSync(skillPath, 'utf8');
20
- const match = content.match(/description:\s*\|?\s*([^\n]+)/);
21
- return match ? match[1].trim() : '';
16
+ const skillPath = path.join(SKILLS_SOURCE, skillName, 'SKILL.md');
17
+ if (!fs.existsSync(skillPath)) return '';
18
+
19
+ const content = fs.readFileSync(skillPath, 'utf8');
20
+ const match = content.match(/description:\s*\|?\s*([^\n]+)/);
21
+ return match ? match[1].trim() : '';
22
22
  }
23
23
 
24
24
  function showHelp() {
25
- console.log(`
26
- OpenGStack - AI Engineering Workflow Skills
25
+ console.log(`
26
+ opengstack - AI Engineering Workflow Skills
27
27
 
28
28
  Usage: opengstack [options]
29
29
 
30
30
  Options:
31
- -h, --help Show this help message
32
- -l, --list List all available skills
33
- -i, --install Install skills to ~/.config/opencode/skills/,
34
- ~/.claude/skills/, and ~/.agents/skills/
31
+ -h, --help Show this help message
32
+ -l, --list List all available skills
33
+ -i, --install Install skills to ~/.config/opencode/skills/,
34
+ ~/.claude/skills/, and ~/.agents/skills/
35
35
 
36
36
  In opencode/Claude, use /slash commands:
37
- /ship, /qa, /review, etc.
37
+ /ship, /qa, /review, etc.
38
38
  `);
39
39
  }
40
40
 
41
41
  function listSkills() {
42
- console.log('\nAvailable skills:\n');
43
-
44
- if (!fs.existsSync(SKILLS_SOURCE)) {
45
- console.error('❌ No skills/ folder found');
46
- process.exit(1);
47
- }
48
-
49
- fs.readdirSync(SKILLS_SOURCE).forEach(skillName => {
50
- const skillPath = path.join(SKILLS_SOURCE, skillName, 'SKILL.md');
51
- if (!fs.existsSync(skillPath)) return;
52
-
53
- const content = fs.readFileSync(skillPath, 'utf8');
54
- const match = content.match(/description:\s*\|?\s*([^\n]+)/);
55
- let description = '';
56
- if (match) {
57
- description = match[1].trim().substring(0, 60);
58
- if (description.length === 60) description += '...';
59
- }
60
- console.log(` ${skillName.padEnd(20)} ${description}`);
61
- });
62
- console.log('');
42
+ console.log('\nAvailable skills:\n');
43
+
44
+ if (!fs.existsSync(SKILLS_SOURCE)) {
45
+ console.error('❌ No skills/ folder found');
46
+ process.exit(1);
47
+ }
48
+
49
+ fs.readdirSync(SKILLS_SOURCE).forEach(skillName => {
50
+ const skillPath = path.join(SKILLS_SOURCE, skillName, 'SKILL.md');
51
+ if (!fs.existsSync(skillPath)) return;
52
+
53
+ const content = fs.readFileSync(skillPath, 'utf8');
54
+ const match = content.match(/description:\s*\|?\s*([^\n]+)/);
55
+ let description = '';
56
+ if (match) {
57
+ description = match[1].trim().substring(0, 60);
58
+ if (description.length === 60) description += '...';
59
+ }
60
+ console.log(` ${skillName.padEnd(20)} ${description}`);
61
+ });
62
+ console.log('');
63
63
  }
64
64
 
65
65
  function installSkills() {
66
- console.log('Installing skills...');
67
- require('../scripts/install-skills.js');
66
+ console.log('Installing skills...');
67
+ require('../scripts/install-skills.js');
68
68
  }
69
69
 
70
70
  function main() {
71
- const args = process.argv.slice(2);
72
- const command = args[0];
73
-
74
- if (!command || command === '-h' || command === '--help') {
75
- showHelp();
76
- process.exit(0);
77
- }
78
-
79
- if (command === '-l' || command === '--list') {
80
- listSkills();
81
- process.exit(0);
82
- }
83
-
84
- if (command === '-i' || command === '--install') {
85
- installSkills();
86
- process.exit(0);
87
- }
88
-
89
- // Check if skill exists in package
90
- const skillPath = path.join(SKILLS_SOURCE, command, 'SKILL.md');
91
- if (!fs.existsSync(skillPath)) {
92
- console.error(`Unknown command: ${command}`);
93
- console.error('Run "opengstack --help" for available commands');
94
- process.exit(1);
95
- }
96
-
97
- // Print instructions for using the skill
98
- console.log(`\n🎯 Skill: ${command}`);
99
- console.log(`📍 Location: ${skillPath}`);
100
- console.log(`\nTo use this skill in opencode/Claude, type:`);
101
- console.log(` /${command}\n`);
102
- console.log('The skill instructions will be loaded automatically.\n');
71
+ const args = process.argv.slice(2);
72
+ const command = args[0];
73
+
74
+ if (!command || command === '-h' || command === '--help') {
75
+ showHelp();
76
+ process.exit(0);
77
+ }
78
+
79
+ if (command === '-l' || command === '--list') {
80
+ listSkills();
81
+ process.exit(0);
82
+ }
83
+
84
+ if (command === '-i' || command === '--install') {
85
+ installSkills();
86
+ process.exit(0);
87
+ }
88
+
89
+ // Check if skill exists in package
90
+ const skillPath = path.join(SKILLS_SOURCE, command, 'SKILL.md');
91
+ if (!fs.existsSync(skillPath)) {
92
+ console.error(`Unknown command: ${command}`);
93
+ console.error('Run "opengstack --help" for available commands');
94
+ process.exit(1);
95
+ }
96
+
97
+ // Print instructions for using the skill
98
+ console.log(`\n🎯 Skill: ${command}`);
99
+ console.log(`📍 Location: ${skillPath}`);
100
+ console.log(`\nTo use this skill in opencode/Claude, type:`);
101
+ console.log(` /${command}\n`);
102
+ console.log('The skill instructions will be loaded automatically.\n');
103
103
  }
104
104
 
105
105
  main();
@@ -3,30 +3,28 @@
3
3
 
4
4
  ## Preamble (run first)
5
5
 
6
-
7
- If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
6
+ If `PROACTIVE` is `"false"`, do not proactively suggest opengstack skills AND do not
8
7
  auto-invoke skills based on conversation context. Only run skills the user explicitly
9
8
  types (e.g., /qa, /ship). If you would have auto-invoked a skill, instead briefly say:
10
9
  "I think /skillname might help here — want me to run it?" and wait for confirmation.
11
10
  The user opted out of proactive behavior.
12
11
 
13
12
  If `SKILL_PREFIX` is `"true"`, the user has namespaced skill names. When suggesting
14
- or invoking other gstack skills, use the `/gstack-` prefix (e.g., `/gstack-qa` instead
15
- of `/qa`, `/gstack-ship` instead of `/ship`). Disk paths are unaffected — always use
13
+ or invoking other opengstack skills, use the `/opengstack-` prefix (e.g., `/opengstack-qa` instead
14
+ of `/qa`, `/opengstack-ship` instead of `/ship`). Disk paths are unaffected — always use
16
15
  `~/.claude/skills/opengstack/[skill-name]/SKILL.md` for reading skill files.
17
16
 
18
17
  If `LAKE_INTRO` is `no`: Before continuing, introduce the Completeness Principle.
19
18
  Then offer to open the essay in their default browser:
20
19
 
21
20
  ```bash
22
- touch ~/.gstack/.completeness-intro-seen
21
+ touch ~/.opengstack/.completeness-intro-seen
23
22
 
24
23
  Only run `open` if the user says yes. Always run `touch` to mark as seen. This only happens once.
25
24
 
26
- If `PROACTIVE_PROMPTED` is `no` AND `TEL_PROMPTED` is `yes`: After telemetry is handled,
27
25
  ask the user about proactive behavior. Use AskUserQuestion:
28
26
 
29
- > gstack can proactively figure out when you might need a skill while you work —
27
+ > opengstack can proactively figure out when you might need a skill while you work —
30
28
  > like suggesting /qa when you say "does this work?" or /investigate when you hit
31
29
  > a bug. We recommend keeping this on — it speeds up every part of your workflow.
32
30
 
@@ -39,13 +37,13 @@ If B: run `echo set proactive false`
39
37
 
40
38
  Always run:
41
39
  ```bash
42
- touch ~/.gstack/.proactive-prompted
40
+ touch ~/.opengstack/.proactive-prompted
43
41
 
44
42
  This only happens once. If `PROACTIVE_PROMPTED` is `yes`, skip this entirely.
45
43
 
46
44
  ## Voice
47
45
 
48
- You are OpenGStack, an open source AI builder framework
46
+ You are opengstack, an open source AI builder framework
49
47
 
50
48
  Lead with the point. Say what it does, why it matters, and what changes for the builder. Sound like someone who shipped code today and cares whether the thing actually works for users.
51
49
 
@@ -3,30 +3,28 @@
3
3
 
4
4
  ## Preamble (run first)
5
5
 
6
-
7
- If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
6
+ If `PROACTIVE` is `"false"`, do not proactively suggest opengstack skills AND do not
8
7
  auto-invoke skills based on conversation context. Only run skills the user explicitly
9
8
  types (e.g., /qa, /ship). If you would have auto-invoked a skill, instead briefly say:
10
9
  "I think /skillname might help here — want me to run it?" and wait for confirmation.
11
10
  The user opted out of proactive behavior.
12
11
 
13
12
  If `SKILL_PREFIX` is `"true"`, the user has namespaced skill names. When suggesting
14
- or invoking other gstack skills, use the `/gstack-` prefix (e.g., `/gstack-qa` instead
15
- of `/qa`, `/gstack-ship` instead of `/ship`). Disk paths are unaffected — always use
13
+ or invoking other opengstack skills, use the `/opengstack-` prefix (e.g., `/opengstack-qa` instead
14
+ of `/qa`, `/opengstack-ship` instead of `/ship`). Disk paths are unaffected — always use
16
15
  `~/.claude/skills/opengstack/[skill-name]/SKILL.md` for reading skill files.
17
16
 
18
17
  If `LAKE_INTRO` is `no`: Before continuing, introduce the Completeness Principle.
19
18
  Then offer to open the essay in their default browser:
20
19
 
21
20
  ```bash
22
- touch ~/.gstack/.completeness-intro-seen
21
+ touch ~/.opengstack/.completeness-intro-seen
23
22
 
24
23
  Only run `open` if the user says yes. Always run `touch` to mark as seen. This only happens once.
25
24
 
26
- If `PROACTIVE_PROMPTED` is `no` AND `TEL_PROMPTED` is `yes`: After telemetry is handled,
27
25
  ask the user about proactive behavior. Use AskUserQuestion:
28
26
 
29
- > gstack can proactively figure out when you might need a skill while you work —
27
+ > opengstack can proactively figure out when you might need a skill while you work —
30
28
  > like suggesting /qa when you say "does this work?" or /investigate when you hit
31
29
  > a bug. We recommend keeping this on — it speeds up every part of your workflow.
32
30
 
@@ -39,7 +37,7 @@ If B: run `echo set proactive false`
39
37
 
40
38
  Always run:
41
39
  ```bash
42
- touch ~/.gstack/.proactive-prompted
40
+ touch ~/.opengstack/.proactive-prompted
43
41
 
44
42
  This only happens once. If `PROACTIVE_PROMPTED` is `yes`, skip this entirely.
45
43
 
@@ -77,30 +75,29 @@ RECOMMENDATION:
77
75
 
78
76
  Replace `SKILL_NAME` with the actual skill name from frontmatter, `OUTCOME` with
79
77
  success/error/abort, and `USED_BROWSE` with true/false based on whether `$B` was used.
80
- If you cannot determine the outcome, use "unknown". The local JSONL always logs. The
81
- remote binary only runs if telemetry is not off and the binary exists.
78
+ If you cannot determine the outcome, use "unknown".
82
79
 
83
80
  ## Plan Status Footer
84
81
 
85
82
  When you are in plan mode and about to call ExitPlanMode:
86
83
 
87
- 1. Check if the plan file already has a `## GSTACK REVIEW REPORT` section.
84
+ 1. Check if the plan file already has a `## opengstack REVIEW REPORT` section.
88
85
  2. If it DOES — skip (a review skill already wrote a richer report).
89
86
  3. If it does NOT — run this command:
90
87
 
91
88
  \`\`\`bash
92
- ~/.claude/skills/opengstack/bin/gstack-review-read
89
+ ~/.claude/skills/opengstack/bin/opengstack-review-read
93
90
  \`\`\`
94
91
 
95
- Then write a `## GSTACK REVIEW REPORT` section to the end of the plan file:
92
+ Then write a `## opengstack REVIEW REPORT` section to the end of the plan file:
96
93
 
97
94
  - If the output contains review entries (JSONL lines before `---CONFIG---`): format the
98
- standard report table with runs/status/findings per skill, same format as the review
99
- skills use.
95
+ standard report table with runs/status/findings per skill, same format as the review
96
+ skills use.
100
97
  - If the output is `NO_REVIEWS` or empty: write this placeholder table:
101
98
 
102
99
  \`\`\`markdown
103
- ## GSTACK REVIEW REPORT
100
+ ## opengstack REVIEW REPORT
104
101
 
105
102
  | Review | Trigger | Why | Runs | Status | Findings |
106
103
  |--------|---------|-----|------|--------|----------|
@@ -121,23 +118,23 @@ plan's living status.
121
118
  ```bash
122
119
  _ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
123
120
  B=""
124
- [ -n "$_ROOT" ] && [ -x "$_ROOT/.claude/skills/gstack/browse/dist/browse" ] && B="$_ROOT/.claude/skills/gstack/browse/dist/browse"
121
+ [ -n "$_ROOT" ] && [ -x "$_ROOT/.claude/skills/opengstack/browse/dist/browse" ] && B="$_ROOT/.claude/skills/opengstack/browse/dist/browse"
125
122
  [ -z "$B" ] && B=~/.claude/skills/opengstack/browse/dist/browse
126
123
  if [ -x "$B" ]; then
127
- echo "READY: $B"
124
+ echo "READY: $B"
128
125
  else
129
- echo "NEEDS_SETUP"
126
+ echo "NEEDS_SETUP"
130
127
  fi
131
128
 
132
129
  If `NEEDS_SETUP`:
133
- 1. Tell the user: "gstack browse needs a one-time build (~10 seconds). OK to proceed?" Then STOP and wait.
130
+ 1. Tell the user: "opengstack browse needs a one-time build (~10 seconds). OK to proceed?" Then STOP and wait.
134
131
  2. Run: `cd <SKILL_DIR> && ./setup`
135
132
  3. If `bun` is not installed:
136
- ```bash
137
- if ! command -v bun >/dev/null 2>&1; then
138
- curl -fsSL https://bun.sh/install | BUN_VERSION=1.3.10 bash
139
- fi
140
- ```
133
+ ```bash
134
+ if ! command -v bun >/dev/null 2>&1; then
135
+ curl -fsSL https://bun.sh/install | BUN_VERSION=1.3.10 bash
136
+ fi
137
+ ```
141
138
 
142
139
  # /benchmark — Performance Regression Detection
143
140
 
@@ -161,9 +158,9 @@ When the user types `/benchmark`, run this skill.
161
158
  ### Phase 1: Setup
162
159
 
163
160
  ```bash
164
- eval "$(~/.claude/skills/opengstack/bin/gstack-slug 2>/dev/null || echo "SLUG=unknown")"
165
- mkdir -p .gstack/benchmark-reports
166
- mkdir -p .gstack/benchmark-reports/baselines
161
+ eval "$(~/.claude/skills/opengstack/bin/opengstack-slug 2>/dev/null || echo "SLUG=unknown")"
162
+ mkdir -p .OpenGStack/benchmark-reports
163
+ mkdir -p .OpenGStack/benchmark-reports/baselines
167
164
 
168
165
  ### Phase 2: Page Discovery
169
166
 
@@ -213,59 +210,58 @@ Save metrics to baseline file:
213
210
 
214
211
  ```json
215
212
  {
216
- "url": "<url>",
217
- "timestamp": "<ISO>",
218
- "branch": "<branch>",
219
- "pages": {
220
- "/": {
221
- "ttfb_ms": 120,
222
- "fcp_ms": 450,
223
- "lcp_ms": 800,
224
- "dom_interactive_ms": 600,
225
- "dom_complete_ms": 1200,
226
- "full_load_ms": 1400,
227
- "total_requests": 42,
228
- "total_transfer_bytes": 1250000,
229
- "js_bundle_bytes": 450000,
230
- "css_bundle_bytes": 85000,
231
- "largest_resources": [
232
- {"name": "main.js", "size": 320000, "duration": 180},
233
- {"name": "vendor.js", "size": 130000, "duration": 90}
234
- ]
235
- }
236
- }
213
+ "url": "<url>",
214
+ "timestamp": "<ISO>",
215
+ "branch": "<branch>",
216
+ "pages": {
217
+ "/": {
218
+ "ttfb_ms": 120,
219
+ "fcp_ms": 450,
220
+ "lcp_ms": 800,
221
+ "dom_interactive_ms": 600,
222
+ "dom_complete_ms": 1200,
223
+ "full_load_ms": 1400,
224
+ "total_requests": 42,
225
+ "total_transfer_bytes": 1250000,
226
+ "js_bundle_bytes": 450000,
227
+ "css_bundle_bytes": 85000,
228
+ "largest_resources": [
229
+ {"name": "main.js", "size": 320000, "duration": 180},
230
+ {"name": "vendor.js", "size": 130000, "duration": 90}
231
+ ]
232
+ }
233
+ }
237
234
  }
238
235
 
239
- Write to `.gstack/benchmark-reports/baselines/baseline.json`.
236
+ Write to `.OpenGStack/benchmark-reports/baselines/baseline.json`.
240
237
 
241
238
  ### Phase 5: Comparison
242
239
 
243
240
  If baseline exists, compare current metrics against it:
244
241
 
245
-
246
242
  PERFORMANCE REPORT —
247
243
  ══════════════════════════
248
244
  Branch: [current-branch] vs baseline ([baseline-branch])
249
245
 
250
246
  Page: /
251
247
  ─────────────────────────────────────────────────────
252
- Metric Baseline Current Delta Status
253
- ──────── ──────── ─────── ───── ──────
254
- TTFB 120ms 135ms +15ms OK
255
- FCP 450ms 480ms +30ms OK
256
- LCP 800ms 1600ms +800ms REGRESSION
257
- DOM Interactive 600ms 650ms +50ms OK
258
- DOM Complete 1200ms 1350ms +150ms WARNING
259
- Full Load 1400ms 2100ms +700ms REGRESSION
260
- Total Requests 42 58 +16 WARNING
261
- Transfer Size 1.2MB 1.8MB +0.6MB REGRESSION
262
- JS Bundle 450KB 720KB +270KB REGRESSION
263
- CSS Bundle 85KB 88KB +3KB OK
248
+ Metric Baseline Current Delta Status
249
+ ──────── ──────── ─────── ───── ──────
250
+ TTFB 120ms 135ms +15ms OK
251
+ FCP 450ms 480ms +30ms OK
252
+ LCP 800ms 1600ms +800ms REGRESSION
253
+ DOM Interactive 600ms 650ms +50ms OK
254
+ DOM Complete 1200ms 1350ms +150ms WARNING
255
+ Full Load 1400ms 2100ms +700ms REGRESSION
256
+ Total Requests 42 58 +16 WARNING
257
+ Transfer Size 1.2MB 1.8MB +0.6MB REGRESSION
258
+ JS Bundle 450KB 720KB +270KB REGRESSION
259
+ CSS Bundle 85KB 88KB +3KB OK
264
260
 
265
261
  REGRESSIONS DETECTED: 3
266
- [1] LCP doubled (800ms → 1600ms) — likely a large new image or blocking resource
267
- [2] Total transfer +50% (1.2MB → 1.8MB) — check new JS bundles
268
- [3] JS bundle +60% (450KB → 720KB) — new dependency or missing tree-shaking
262
+ [1] LCP doubled (800ms → 1600ms) — likely a large new image or blocking resource
263
+ [2] Total transfer +50% (1.2MB → 1.8MB) — check new JS bundles
264
+ [3] JS bundle +60% (450KB → 720KB) — new dependency or missing tree-shaking
269
265
 
270
266
  **Regression thresholds:**
271
267
  - Timing metrics: >50% increase OR >500ms absolute increase = REGRESSION
@@ -276,15 +272,14 @@ REGRESSIONS DETECTED: 3
276
272
 
277
273
  ### Phase 6: Slowest Resources
278
274
 
279
-
280
275
  TOP 10 SLOWEST RESOURCES
281
276
  ═════════════════════════
282
- # Resource Type Size Duration
283
- 1 vendor.chunk.js script 320KB 480ms
284
- 2 main.js script 250KB 320ms
285
- 3 hero-image.webp img 180KB 280ms
286
- 4 analytics.js script 45KB 250ms ← third-party
287
- 5 fonts/inter-var.woff2 font 95KB 180ms
277
+ # Resource Type Size Duration
278
+ 1 vendor.chunk.js script 320KB 480ms
279
+ 2 main.js script 250KB 320ms
280
+ 3 hero-image.webp img 180KB 280ms
281
+ 4 analytics.js script 45KB 250ms ← third-party
282
+ 5 fonts/inter-var.woff2 font 95KB 180ms
288
283
  ...
289
284
 
290
285
  RECOMMENDATIONS:
@@ -296,17 +291,16 @@ RECOMMENDATIONS:
296
291
 
297
292
  Check against industry budgets:
298
293
 
299
-
300
294
  PERFORMANCE BUDGET CHECK
301
295
  ════════════════════════
302
- Metric Budget Actual Status
303
- ──────── ────── ────── ──────
304
- FCP < 1.8s 0.48s PASS
305
- LCP < 2.5s 1.6s PASS
306
- Total JS < 500KB 720KB FAIL
307
- Total CSS < 100KB 88KB PASS
308
- Total Transfer < 2MB 1.8MB WARNING (90%)
309
- HTTP Requests < 50 58 FAIL
296
+ Metric Budget Actual Status
297
+ ──────── ────── ────── ──────
298
+ FCP < 1.8s 0.48s PASS
299
+ LCP < 2.5s 1.6s PASS
300
+ Total JS < 500KB 720KB FAIL
301
+ Total CSS < 100KB 88KB PASS
302
+ Total Transfer < 2MB 1.8MB WARNING (90%)
303
+ HTTP Requests < 50 58 FAIL
310
304
 
311
305
  Grade: B (4/6 passing)
312
306
 
@@ -314,22 +308,21 @@ Grade: B (4/6 passing)
314
308
 
315
309
  Load historical baseline files and show trends:
316
310
 
317
-
318
311
  PERFORMANCE TRENDS (last 5 benchmarks)
319
312
  ══════════════════════════════════════
320
- Date FCP LCP Bundle Requests Grade
321
- 2026-03-10 420ms 750ms 380KB 38 A
322
- 2026-03-12 440ms 780ms 410KB 40 A
323
- 2026-03-14 450ms 800ms 450KB 42 A
324
- 2026-03-16 460ms 850ms 520KB 48 B
325
- 2026-03-18 480ms 1600ms 720KB 58 B
313
+ Date FCP LCP Bundle Requests Grade
314
+ 2026-03-10 420ms 750ms 380KB 38 A
315
+ 2026-03-12 440ms 780ms 410KB 40 A
316
+ 2026-03-14 450ms 800ms 450KB 42 A
317
+ 2026-03-16 460ms 850ms 520KB 48 B
318
+ 2026-03-18 480ms 1600ms 720KB 58 B
326
319
 
327
320
  TREND: Performance degrading. LCP doubled in 8 days.
328
- JS bundle growing 50KB/week. Investigate.
321
+ JS bundle growing 50KB/week. Investigate.
329
322
 
330
323
  ### Phase 9: Save Report
331
324
 
332
- Write to `.gstack/benchmark-reports/{date}-benchmark.md` and `.gstack/benchmark-reports/{date}-benchmark.json`.
325
+ Write to `.OpenGStack/benchmark-reports/{date}-benchmark.md` and `.OpenGStack/benchmark-reports/{date}-benchmark.json`.
333
326
 
334
327
  ## Important Rules
335
328