this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Update salary model, unify report styling, and improve copy

- Salary: 150k base x 1.33x specialization multiplier = 200k/yr,
with reference rate table (NLnet, STF, Mozilla, Servo grant)
- Standardize on 3yr cost horizon across both reports
- Unify hero cards: same order, same styling, same set of 5 cards
- Add summary callout above hero cards in both reports
- Add ceiling year (~2037) to plateau language
- Link Baseline Widely Available to web-platform-dx
- Spell out percentage points in prose
- Replace vague most likely already supported with explicit breakdown
- Reframe usage-prioritized language as phased approach toward full parity
- Add research question, acknowledgments, and AI disclosure
- Remove draft banner, add inline DRAFT label next to date

+175 -136
+41 -20
dashboard.html
··· 12 12 body { font-family: "Pragati Narrow", sans-serif; background: rgb(247, 226, 231); color: #1d1d1d; padding: 24px; font-size: 1.1rem; line-height: 1.3; } 13 13 h1 { font-size: 28px; margin-bottom: 8px; color: rgb(71, 11, 0); } 14 14 h2 { font-size: 20px; margin-bottom: 12px; color: rgb(71, 11, 0); font-weight: 700; } 15 - .byline { font-size: 13px; color: #1d1d1d; } 15 + .byline { font-size: 12px; color: #1d1d1d; margin-bottom: 16px; } 16 16 .byline a { color: rgb(71, 11, 0); } 17 17 .subtitle { color: #666; margin-bottom: 32px; font-size: 14px; } 18 18 .grid { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; margin-bottom: 24px; } 19 19 .card { background: #fff; border-radius: 12px; padding: 20px; border: 1px solid rgba(71, 11, 0, 0.15); } 20 20 .card.full { grid-column: 1 / -1; } 21 21 .card h3 { font-size: 15px; color: rgb(71, 11, 0); margin-bottom: 16px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; } 22 - .metric { display: flex; gap: 32px; margin-bottom: 20px; flex-wrap: wrap; } 23 - .metric-item { text-align: center; } 22 + .metric { display: flex; gap: 16px; margin-bottom: 20px; flex-wrap: wrap; } 23 + .metric-item { text-align: center; flex: 1; min-width: 140px; background: rgba(71, 11, 0, 0.04); border: 1px solid rgba(71, 11, 0, 0.15); border-radius: 8px; padding: 16px 12px; } 24 24 .metric-value { font-size: 36px; font-weight: 700; color: rgb(71, 11, 0); } 25 25 .metric-label { font-size: 12px; color: #666; margin-top: 4px; } 26 26 .chart-container { position: relative; height: 300px; } ··· 47 47 <body> 48 48 49 49 <h1>Servo Baseline Readiness</h1> 50 - <div class="byline">Dietrich Ayala &mdash; <a href="https://webtransitions.org">webtransitions.org</a></div> 51 - <p class="subtitle">This dashboard evaluates the Servo web engine&rsquo;s readiness to support Baseline &ldquo;Widely Available&rdquo; (BWA) web features &mdash; the set of web platform features supported across all major browsers for at least 30 months. Data as of March 2026.</p> 50 + <div class="byline">Dietrich Ayala &mdash; dietrich@webtransitions.org &mdash; <a href="https://webtransitions.org">webtransitions.org</a></div> 51 + <div style="background:rgba(71,11,0,0.04);border:1px solid rgba(71,11,0,0.15);border-radius:8px;padding:14px 18px;margin-bottom:16px;font-size:14px;line-height:1.5;color:#1d1d1d;"> 52 + Servo is falling behind the web. It completes <strong>~22 features/year</strong> at production quality, while the Baseline &ldquo;<a href="https://web-platform-dx.github.io/web-features/" target="_blank">Widely Available</a>&rdquo; set grows at <strong>~52 features/year</strong>. At this pace, Servo plateaus around <strong>80% by ~2037 and never catches up</strong>. Full velocity parity requires <strong>~44 FTE</strong> (<strong>&euro;8.8M/yr</strong>, <strong>&euro;26.3M over 3yr</strong>). BWA features vary widely in real-world usage &mdash; a phased approach that prioritizes high-usage features first could reduce the initial headcount and cost by up to 40% while building toward full parity. The highest-leverage actions are <strong>unstalling 141 blocked features</strong> and fixing <strong>51 regressions</strong> (features that lost &gt;5 percentage points). This report asks: <strong>what would it cost in engineering investment alone to bring Servo to velocity parity within 3 years</strong>, excluding non-engineering and operational costs? 53 + </div> 52 54 53 55 <div class="metric"> 54 56 <div class="metric-item"> 55 - <div class="metric-value" style="color:#c44">22 <span style="font-size:20px;color:#999">vs 52</span></div> 56 - <div class="metric-label">Web Feature Velocity Gap<br>Servo completions/yr vs BWA growth/yr</div> 57 + <div class="metric-value">19.8% <span style="font-size:20px;color:#999">(87/439)</span></div> 58 + <div class="metric-label">Current BWA Readiness<br>(measurable features &ge;95%)</div> 57 59 </div> 58 60 <div class="metric-item"> 59 - <div class="metric-value" style="color:rgb(71,11,0)">44 FTE</div> 60 - <div class="metric-label">Velocity Parity<br>&euro;6.6M/yr &mdash; &euro;33.0M over 5yr</div> 61 + <div class="metric-value">593 <span style="font-size:20px;color:#999">&rarr; ~879</span></div> 62 + <div class="metric-label">BWA Growth<br>today &rarr; by 2031 (~52/yr)</div> 61 63 </div> 62 64 <div class="metric-item"> 63 - <div class="metric-value" style="color:#b87800">19.8% <span style="font-size:20px;color:#999">(87/439)</span></div> 64 - <div class="metric-label">Current Readiness<br>(measurable features &ge;95%)</div> 65 + <div class="metric-value">22 <span style="font-size:20px;color:#999">vs 52</span></div> 66 + <div class="metric-label">Web Feature Velocity Gap<br>Servo completions/yr vs BWA growth/yr</div> 65 67 </div> 66 68 <div class="metric-item"> 67 - <div class="metric-value" style="color:#999">~80%</div> 68 - <div class="metric-label">Ceiling at 13 FTE<br>Web outgrows Servo</div> 69 + <div class="metric-value">44 FTE</div> 70 + <div class="metric-label">Velocity Parity<br>&euro;8.8M/yr &mdash; &euro;26.3M over 3yr</div> 69 71 </div> 70 72 <div class="metric-item"> 71 - <div class="metric-value" style="color:rgb(71,11,0)">593 <span style="font-size:20px;color:#999">&rarr; ~879</span></div> 72 - <div class="metric-label">BWA Features<br>today &rarr; by 2031 (~52/yr)</div> 73 + <div class="metric-value">38&ndash;41 FTE</div> 74 + <div class="metric-label">Usage-Prioritized Parity<br>&euro;7.6&ndash;8.2M/yr (skip low-usage)</div> 73 75 </div> 74 76 </div> 75 77 ··· 134 136 </div> 135 137 <div style="flex:1;min-width:260px;"> 136 138 <label style="display:block;color:#666;font-size:13px;margin-bottom:6px;">Avg Annual Salary (EUR)</label> 137 - <input type="range" id="calcSalary" min="50000" max="400000" step="10000" value="150000" style="width:100%;accent-color:rgb(71,11,0);"> 138 - <div style="display:flex;justify-content:space-between;font-size:12px;color:#999;"><span>&euro;50k</span><span id="calcSalaryVal" style="color:rgb(71,11,0);font-size:16px;font-weight:600;">&euro;150k</span><span>&euro;400k</span></div> 139 + <input type="range" id="calcSalary" min="50000" max="400000" step="10000" value="199500" style="width:100%;accent-color:rgb(71,11,0);"> 140 + <div style="display:flex;justify-content:space-between;font-size:12px;color:#999;"><span>&euro;50k</span><span id="calcSalaryVal" style="color:rgb(71,11,0);font-size:16px;font-weight:600;">&euro;200k</span><span>&euro;400k</span></div> 139 141 </div> 140 142 <div style="flex:1;min-width:260px;"> 141 143 <label style="display:block;color:#666;font-size:13px;margin-bottom:6px;">Scaling Exponent (<a href="https://en.wikipedia.org/wiki/Brooks%27s_law" target="_blank">Brooks's Law</a>)</label> ··· 179 181 180 182 <h2>Key Insights</h2> 181 183 <details class="insight"> 182 - <summary><strong>Regressions are the #1 problem</strong> <span>— 51 features went backward, some by 50-75pp. Fixing regressions is cheaper than new implementation.</span></summary> 184 + <summary><strong>Regressions are the #1 problem</strong> <span>— 51 features went backward, some by 50–75 percentage points. Fixing regressions is cheaper than new implementation.</span></summary> 183 185 <div class="insight-body"> 184 186 <div class="cols"> 185 187 <div> ··· 390 392 391 393 <h3 style="margin-top:20px;">Scoring Model</h3> 392 394 <p style="margin-bottom:12px;">Each feature's score is the average per-test pass rate across all matched WPT tests. For tests with subtests, the score is <code style="color:rgb(71,11,0);">passed_subtests / total_subtests</code>. For simple pass/fail tests, the score is 0 or 1. A feature is considered <strong style="color:#2a7d2a;">fully supported</strong> at &ge;95% score.</p> 393 - <p style="margin-bottom:12px;">Features with no WPT manifest mapping (154 of 593) are categorized as &ldquo;No Data.&rdquo; These break down into 78 JS built-ins (supported via SpiderMonkey, tested by test262 not WPT), 23 semantic HTML elements (trivial &mdash; no special behavior to test), 20 WebGL extensions (GPU-driver-dependent), and 33 other features (basic DOM, CSS, HTTP, WebAssembly). Most are likely already supported.</p> 395 + <p style="margin-bottom:12px;">Features with no WPT manifest mapping (154 of 593) are categorized as &ldquo;No Data.&rdquo; These break down into 78 JS built-ins (supported via SpiderMonkey, tested by test262 not WPT), 23 semantic HTML elements (trivial &mdash; no special behavior to test), 20 WebGL extensions (GPU-driver-dependent), and 33 other features (basic DOM, CSS, HTTP, WebAssembly). The 78 JS built-ins and 23 semantic HTML elements are supported via SpiderMonkey and the HTML parser respectively; the 20 WebGL extensions depend on GPU driver support; the remaining 33 have unknown status.</p> 394 396 395 397 <h3 style="margin-top:20px;">FTE-Equivalent Contributors</h3> 396 398 <p style="margin-bottom:12px;">The contributor count uses <strong style="color:rgb(71,11,0);">full-time equivalents (FTE)</strong>, not raw headcount. Computed from per-author commit counts over Jul 2025 &ndash; Jan 2026 (7 months), excluding bots (dependabot, WPT Sync). Each author's FTE fraction = <code style="color:rgb(71,11,0);">min(their_commits / 154, 1.0)</code>, where 154 = 22 commits/month &times; 7 months (~1 commit per working day). The sum across all 115 human authors yields <strong style="color:rgb(71,11,0);">~13 FTE</strong>. Of these, 9 core contributors operate at &ge;50% FTE, with a long tail of occasional contributors. This FTE figure is what drives the projection and cost models — it represents the effective engineering capacity, which is what matters for funding decisions.</p> 397 399 398 400 <h3 style="margin-top:20px;">Velocity & Projections</h3> 399 - <p style="margin-bottom:12px;">Per-feature velocity is computed as the improvement per quarter from 2023-Q3 to present. We use <code style="color:rgb(71,11,0);">max(overall_velocity, recent_velocity)</code> where recent velocity covers the last 4 quarters, to account for accelerating progress. Features with velocity &le;0.001 pp/quarter are classified as <strong style="color:#b87800;">stalled</strong>.</p> 401 + <p style="margin-bottom:12px;">Per-feature velocity is computed as the improvement per quarter from 2023-Q3 to present. We use <code style="color:rgb(71,11,0);">max(overall_velocity, recent_velocity)</code> where recent velocity covers the last 4 quarters, to account for accelerating progress. Features with velocity &le;0.001 percentage points/quarter are classified as <strong style="color:#b87800;">stalled</strong>.</p> 400 402 <p style="margin-bottom:12px;">Projections extrapolate each feature individually: <code style="color:rgb(71,11,0);">quarters_to_95% = (0.95 - current_score) / (velocity &times; scale_factor)</code>. The scale factor models additional FTEs using a sublinear power law: <code style="color:rgb(71,11,0);">scale = (new_fte / current_fte)<sup>exponent</sup></code>. The default exponent of 0.7 reflects <a href="https://en.wikipedia.org/wiki/Brooks%27s_law" target="_blank" style="color:rgb(71,11,0);">Brooks's Law</a> — communication overhead means doubling contributors doesn't double output.</p> 401 403 402 404 <h3 style="margin-top:20px;">Cost Model</h3> 403 405 <p style="margin-bottom:12px;">Cost is calculated as: <code style="color:rgb(71,11,0);">additional_FTE &times; salary &times; years_to_milestone</code>, where the milestone date is determined by the Nth-percentile feature reaching 95%. This represents the <em>marginal</em> cost of accelerating beyond the current trajectory — not the total program cost. The model assumes FTEs can be allocated to stalled features and that the scaling exponent applies uniformly.</p> 404 406 407 + <h3 style="margin-top:20px;">Salary Assumptions</h3> 408 + <p style="margin-bottom:12px;">The default salary of <strong style="color:rgb(71,11,0);">&euro;200k/yr</strong> is composed of a <strong>&euro;150k base</strong> (European senior software engineer median total cost to employer) &times; a <strong>1.33&times; specialization multiplier</strong> for two factors:</p> 409 + <ul style="margin-left:20px;margin-bottom:12px;"> 410 + <li><strong>Highly specialized domain</strong> — browser engine internals (Rust, rendering pipelines, layout algorithms) draws from a very small global talent pool</li> 411 + <li><strong>Multi-disciplinary practice</strong> — each contributor combines software development, <a href="https://www.w3.org/" target="_blank" style="color:rgb(71,11,0);">W3C</a>/<a href="https://whatwg.org/" target="_blank" style="color:rgb(71,11,0);">WHATWG</a> standards body participation, and open-source community contribution management</li> 412 + </ul> 413 + <p style="margin-bottom:8px;font-size:12px;">Reference rates used to calibrate this figure:</p> 414 + <table style="width:auto;font-size:11px;margin-bottom:12px;"> 415 + <tr><th style="text-align:left;">Source</th><th style="text-align:right;">Annual Equivalent</th><th>Notes</th></tr> 416 + <tr><td><a href="https://nlnet.nl/funding.html" target="_blank" style="color:rgb(71,11,0);">NLnet</a> grants (&euro;60/hr)</td><td style="text-align:right;">&euro;108k</td><td style="color:#999;">Below-market philanthropy rate</td></tr> 417 + <tr><td><a href="https://www.sovereign.tech/programs/fellowship" target="_blank" style="color:rgb(71,11,0);">Sovereign Tech Fund</a> (employment + social)</td><td style="text-align:right;">&euro;79&ndash;101k</td><td style="color:#999;">German public-sector TVöD scale</td></tr> 418 + <tr><td>European senior SWE median (total cost)</td><td style="text-align:right;">&euro;100&ndash;140k</td><td style="color:#999;">Varies by country; incl. employer costs</td></tr> 419 + <tr><td>Mozilla Germany senior SWE (<a href="https://www.levels.fyi/companies/mozilla/salaries/software-engineer/locations/germany" target="_blank" style="color:rgb(71,11,0);">Levels.fyi</a>)</td><td style="text-align:right;">&euro;145&ndash;164k</td><td style="color:#999;">Top-tier browser-engine employer</td></tr> 420 + <tr style="background:rgba(71,11,0,0.05);font-weight:600;"><td>Model default (&euro;150k &times; 1.33)</td><td style="text-align:right;">&euro;200k</td><td style="color:#999;">Specialized + multi-disciplinary premium</td></tr> 421 + <tr><td><a href="https://github.com/servo/project/issues/181" target="_blank" style="color:rgb(71,11,0);">Servo grant</a> ($150/hr &times; 1800)</td><td style="text-align:right;">&euro;248k</td><td style="color:#999;">US contractor rate with overhead</td></tr> 422 + </table> 423 + 405 424 <h3 style="margin-top:20px;">Limitations</h3> 406 425 <ul style="margin-left:20px;"> 407 426 <li>26% of Widely Available features lack WPT test mapping, creating a coverage gap</li> ··· 412 431 <li>Stalled features may require architectural work rather than incremental test fixes</li> 413 432 </ul> 414 433 </div> 434 + 435 + <p style="font-size:12px;line-height:1.5;color:#686868;margin:20px 0;">Thanks to the people who&rsquo;ve reviewed the methodology and approach so far. NOTE: AI was used in the making of this draft report. For suggestions for improvement or spotting of inaccuracies, contact <a href="mailto:dietrich@webtransitions.org" style="color:rgb(71,11,0);">dietrich@webtransitions.org</a>.</p> 415 436 416 437 <script> 417 438 Chart.defaults.color = '#666';
+30 -36
data/build-one-pager.mjs
··· 11 11 snapshots, widelyAvailable, totalBWA, 12 12 featureVelocities, stalledFeatures, regressions, 13 13 measurableCount, fullCount, readinessPct, noDataCount, noDataByReason, 14 - servoCompletionsPerYear, bwaGrowthPerYear, ceilingPct, 14 + servoCompletionsPerYear, bwaGrowthPerYear, ceilingPct, ceilingYear, 15 15 parityFTE, parityCostPerYear, parityCost3yr, 16 16 parityFTE_49, parityFTE_47, 17 17 projectedBWA, 18 - SALARY, SCALING_EXP, currentContributors, 18 + BASE_SALARY, SPECIALIZATION_MULTIPLIER, SALARY, SCALING_EXP, currentContributors, 19 19 } = m; 20 20 21 21 // ============================================================ ··· 133 133 font-size: 1.1rem; line-height: 1.3; 134 134 } 135 135 136 - .header { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 14px; border-bottom: 2px solid rgb(71, 11, 0); padding-bottom: 10px; } 136 + .header { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 14px; padding-bottom: 10px; } 137 137 h1 { font-size: 26px; font-weight: 700; color: rgb(71, 11, 0); } 138 138 .byline { font-size: 12px; color: #1d1d1d; margin-top: 2px; } 139 139 .byline a { color: rgb(71, 11, 0); } ··· 141 141 142 142 .hero { display: flex; gap: 10px; margin-bottom: 14px; } 143 143 .hero-card { 144 - flex: 1; background: #fff; border-radius: 8px; padding: 12px 10px; 145 - border: 1px solid rgba(71, 11, 0, 0.15); text-align: center; 144 + flex: 1; border-radius: 8px; padding: 12px 10px; text-align: center; 145 + background: rgba(71, 11, 0, 0.04); border: 1px solid rgba(71, 11, 0, 0.15); 146 146 } 147 - .hero-card.primary { border-color: rgb(71, 11, 0); background: rgba(71, 11, 0, 0.05); } 148 - .hero-card.warn { border-color: #a33; background: rgba(204, 68, 68, 0.05); } 149 147 .hero-label { font-size: 9px; color: #666; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 3px; } 150 148 .hero-value { font-size: 26px; font-weight: 700; color: rgb(71, 11, 0); } 151 - .hero-value.alert { color: #a33; } 152 - .hero-value.accent { color: rgb(71, 11, 0); } 153 149 .hero-sub { font-size: 10px; color: #666; margin-top: 2px; line-height: 1.4; } 154 150 155 151 .section { margin-bottom: 12px; } ··· 188 184 </head> 189 185 <body> 190 186 191 - <div style="background:#a33;color:#fff;text-align:center;padding:4px;font-size:11px;font-weight:700;letter-spacing:0.1em;text-transform:uppercase;margin-bottom:6px;">DRAFT &mdash; Do not circulate without permission</div> 192 - 193 187 <div class="header"> 194 188 <div> 195 189 <h1>Servo Baseline Readiness</h1> 196 190 <div class="byline">Dietrich Ayala &mdash; dietrich@webtransitions.org &mdash; <a href="https://webtransitions.org">webtransitions.org</a></div> 197 191 </div> 198 - <span class="date">March 2026</span> 192 + <div><span style="color:#a33;font-weight:700;font-size:12px;letter-spacing:0.06em;margin-right:8px;">DRAFT</span><span class="date">March 2026</span></div> 199 193 </div> 200 194 201 - <p style="font-size:11.5px;line-height:1.5;color:#1d1d1d;margin-bottom:10px;">This report evaluates the Servo web engine&rsquo;s readiness to support Baseline &ldquo;Widely Available&rdquo; (BWA) web features &mdash; the set of web platform features that have been supported across all major browsers for at least 30 months.</p> 195 + <div class="callout"> 196 + <p>Servo is falling behind the web. It completes <strong>~${servoCompletionsPerYear} features/year</strong> at production quality, while the Baseline &ldquo;<a href="https://web-platform-dx.github.io/web-features/">Widely Available</a>&rdquo; set grows at <strong>~${bwaGrowthPerYear} features/year</strong>. At this pace, Servo plateaus around <strong>${ceilingPct}% by ~${ceilingYear} and never catches up</strong>. Full velocity parity requires <strong>~${parityFTE} FTE</strong> (<strong>&euro;${parityCostPerYear}M/yr</strong>, <strong>&euro;${parityCost3yr}M over 3yr</strong>). BWA features vary widely in real-world usage &mdash; a phased approach that prioritizes high-usage features first could reduce the initial headcount and cost by up to 40% while building toward full parity. The highest-leverage actions are <strong>unstalling ${stalledFeatures.length} blocked features</strong> and fixing <strong>${regressions.length} regressions</strong> (features that lost &gt;5 percentage points). This report asks: <strong>what would it cost in engineering investment alone to bring Servo to velocity parity within 3 years</strong>, excluding non-engineering and operational costs?</p> 197 + </div> 202 198 203 199 <div class="hero"> 204 - <div class="hero-card warn"> 200 + <div class="hero-card"> 201 + <div class="hero-label">Current BWA readiness</div> 202 + <div class="hero-value">${readinessPct}%</div> 203 + <div class="hero-sub">${fullCount} of ${measurableCount} measurable at &ge;95%</div> 204 + </div> 205 + <div class="hero-card"> 206 + <div class="hero-label">BWA growth</div> 207 + <div class="hero-value">${widelyAvailable.length} <span style="font-size:16px;color:#686868;">&rarr; ~${projectedBWA.find(p => p.year === 2031)?.total ?? 879}</span></div> 208 + <div class="hero-sub">today &rarr; by 2031 (~${bwaGrowthPerYear}/yr)</div> 209 + </div> 210 + <div class="hero-card"> 205 211 <div class="hero-label">Web feature velocity gap</div> 206 - <div class="hero-value alert">${servoCompletionsPerYear} vs ${bwaGrowthPerYear}</div> 212 + <div class="hero-value">${servoCompletionsPerYear} vs ${bwaGrowthPerYear}</div> 207 213 <div class="hero-sub">Servo completes ${servoCompletionsPerYear} features/yr<br>Web adds ${bwaGrowthPerYear} new features/yr</div> 208 214 </div> 209 - <div class="hero-card primary"> 215 + <div class="hero-card"> 210 216 <div class="hero-label">Velocity parity</div> 211 - <div class="hero-value accent">${parityFTE} FTE</div> 217 + <div class="hero-value">${parityFTE} FTE</div> 212 218 <div class="hero-sub">&euro;${parityCostPerYear}M/yr &mdash; &euro;${parityCost3yr}M over 3yr<br><span style="color:#686868;">(${currentContributors} existing + ${parityFTE - currentContributors} new)</span></div> 213 219 </div> 214 220 <div class="hero-card"> 215 - <div class="hero-label">Current BWA readiness</div> 216 - <div class="hero-value warn-text">${readinessPct}%</div> 217 - <div class="hero-sub">${fullCount} of ${measurableCount} measurable at &ge;95%</div> 218 - </div> 219 - <div class="hero-card"> 220 - <div class="hero-label">Current pace &rarr; ceiling</div> 221 - <div class="hero-value" style="color:#686868;">~${ceilingPct}%</div> 222 - <div class="hero-sub">Web outgrows Servo at ${currentContributors} FTE</div> 223 - </div> 224 - <div class="hero-card" style="border-color:#1f6e1f;background:rgba(42,125,42,0.05);"> 225 221 <div class="hero-label">Usage-prioritized parity</div> 226 - <div class="hero-value pass">${parityFTE_47}&ndash;${parityFTE_49} FTE</div> 222 + <div class="hero-value">${parityFTE_47}&ndash;${parityFTE_49} FTE</div> 227 223 <div class="hero-sub">&euro;${costPerYear_47}&ndash;${costPerYear_49}M/yr<br><span style="color:#686868;">skip low-usage (&lt;1&ndash;5%) features</span></div> 228 224 </div> 229 - </div> 230 - 231 - <div class="callout"> 232 - <p>Servo is falling behind the web. It completes <strong>~${servoCompletionsPerYear} features/year</strong> at production quality, while the Baseline &ldquo;Widely Available&rdquo; set grows at <strong>~${bwaGrowthPerYear} features/year</strong>. At this pace, Servo plateaus around <strong>${ceilingPct}% and never catches up</strong>. Full velocity parity requires <strong>~${parityFTE} FTE</strong> (<strong>&euro;${parityCostPerYear}M/yr</strong>, <strong>&euro;${parityCost3yr}M over 3yr</strong>). But not all BWA features matter equally &mdash; deprioritizing low-usage features could significantly reduce the parity target. The highest-impact investments remain <strong>unstalling ${stalledFeatures.length} blocked features</strong> and fixing <strong>${regressions.length} regressions</strong> (features that lost &gt;5 percentage points).</p> 233 225 </div> 234 226 235 227 <table style="width:100%;border-collapse:collapse;font-size:11px;margin-bottom:12px;background:#fff;border-radius:6px;overflow:hidden;border:1px solid rgba(71,11,0,0.15);"> ··· 257 249 return ` <tr${rowStyle}><td>${s.label}</td><td>~${compl}</td><td class="${vAll.cls}">${vAll.sym}${vAll.extra}</td><td class="${v49.cls}">${v49.sym}</td><td class="${v47.cls}">${v47.sym}</td><td>&euro;${costPerYear(s.fte)}M</td><td>&euro;${cost3yr(s.fte)}M</td></tr>`; 258 250 }).join('\n')} 259 251 </table> 260 - <p style="font-size:9.5px;color:#686868;margin-top:3px;">All BWA = ${totalBWA} features (~${bwaGrowthPerYear}/yr). &lt;1% = drop ${drop1_count} features below 1% usage (~49/yr). &lt;5% = drop ${drop5_count} features (~47/yr). Completions/yr = ${servoCompletionsPerYear} &times; (FTE/${currentContributors})<sup>${SCALING_EXP}</sup>. Cost = FTE &times; &euro;${(SALARY/1000).toFixed(0)}k. <a href="https://en.wikipedia.org/wiki/Brooks%27s_law">Brooks's Law</a> scaling exponent ${SCALING_EXP}.</p> 252 + <p style="font-size:9.5px;color:#686868;margin-top:3px;">All BWA = ${totalBWA} features (~${bwaGrowthPerYear}/yr). &lt;1% = drop ${drop1_count} features below 1% usage (~49/yr). &lt;5% = drop ${drop5_count} features (~47/yr). Completions/yr = ${servoCompletionsPerYear} &times; (FTE/${currentContributors})<sup>${SCALING_EXP}</sup>. Cost = FTE &times; &euro;${(SALARY/1000).toFixed(0)}k (&euro;${(BASE_SALARY/1000).toFixed(0)}k base &times; ${SPECIALIZATION_MULTIPLIER}&times; specialization). <a href="https://en.wikipedia.org/wiki/Brooks%27s_law">Brooks's Law</a> scaling exponent ${SCALING_EXP}.</p> 261 253 </div> 262 254 263 255 <div class="section"> ··· 272 264 <span><span style="color:#8a5a00;">&#9632;</span> ${partialCount} partial (${partialPct}%)</span> 273 265 <span><span style="color:#a33;">&#9632;</span> ${unsupportedCount} unsupported (${unsupportedPct}%)</span> 274 266 </div> 275 - <p style="font-size:10.5px;color:#1d1d1d;line-height:1.4;">Of ${totalBWA} BWA features, ${measurableCount} have WPT test coverage. ${noDataCount} lack WPT mapping: ${(noDataByReason['js-builtin'] || []).length} JS built-ins (SpiderMonkey/test262), ${(noDataByReason['semantic-html'] || []).length} semantic HTML elements, ${noDataCount - (noDataByReason['js-builtin'] || []).length - (noDataByReason['semantic-html'] || []).length} other (WebGL extensions, DOM, CSS, etc.). Most are likely already supported. WPT pass rate doubled from 30% to 62% over 2.5 years.</p> 267 + <p style="font-size:10.5px;color:#1d1d1d;line-height:1.4;">Of ${totalBWA} BWA features, ${measurableCount} have WPT test coverage. ${noDataCount} lack WPT mapping: ${(noDataByReason['js-builtin'] || []).length} JS built-ins (SpiderMonkey/test262), ${(noDataByReason['semantic-html'] || []).length} semantic HTML elements, ${noDataCount - (noDataByReason['js-builtin'] || []).length - (noDataByReason['semantic-html'] || []).length} other (WebGL extensions, DOM, CSS, etc.). The ${(noDataByReason['js-builtin'] || []).length} JS built-ins and ${(noDataByReason['semantic-html'] || []).length} semantic HTML elements (~${Math.round(((noDataByReason['js-builtin'] || []).length + (noDataByReason['semantic-html'] || []).length) / noDataCount * 100)}% of unmeasured) are supported via SpiderMonkey and the HTML parser respectively; the remaining ${noDataCount - (noDataByReason['js-builtin'] || []).length - (noDataByReason['semantic-html'] || []).length} have unknown status. WPT pass rate doubled from 30% to 62% over 2.5 years.</p> 276 268 <h2 style="margin-top:8px;">BWA Growth Pipeline</h2> 277 269 <table> 278 270 <tr><th>Year</th><th>New BWA</th><th>Cumulative</th><th>Source</th></tr> ··· 320 312 <h2>Key Strategic Factors</h2> 321 313 <div class="insight-row"> 322 314 <div class="insight-num">1</div> 323 - <div class="insight-text"><strong class="fail">Velocity gap</strong> — Servo completes ${servoCompletionsPerYear} features/yr vs ${bwaGrowthPerYear} new BWA/yr. At ${currentContributors} FTE it plateaus at ~${ceilingPct}% and never catches up. This is the core funding case.</div> 315 + <div class="insight-text"><strong class="fail">Velocity gap</strong> — Servo completes ${servoCompletionsPerYear} features/yr vs ${bwaGrowthPerYear} new BWA/yr. At ${currentContributors} FTE it plateaus at ~${ceilingPct}% by ~${ceilingYear} and never catches up. This is the core funding case.</div> 324 316 </div> 325 317 <div class="insight-row"> 326 318 <div class="insight-num">2</div> ··· 344 336 345 337 <div class="section"> 346 338 <h2>Methodology</h2> 347 - <p style="font-size:10px;line-height:1.45;color:#666;">Readiness measured against Baseline &ldquo;Widely Available&rdquo; (BWA) web features &mdash; supported 30+ months across all major browsers. Feature scores from Web Platform Tests (WPT) via WPT Feature Manifest mapping. ${measurableCount} of ${totalBWA} BWA features are measurable; ${noDataCount} lack WPT mapping (${(noDataByReason['js-builtin'] || []).length} JS built-ins tested by test262 not WPT, ${(noDataByReason['semantic-html'] || []).length} semantic HTML elements, ${noDataCount - (noDataByReason['js-builtin'] || []).length - (noDataByReason['semantic-html'] || []).length} other &mdash; most likely already supported). FTE-equivalent from per-author commit frequency (1 FTE &asymp; 22 commits/month, capped at 1.0 per person; 115 authors sum to ~${currentContributors} FTE). BWA growth rate of ~${bwaGrowthPerYear}/year is the 2023&ndash;2025 average, normalized to exclude the 2022 interop spike. Known pipeline: ${projectedBWA.filter(p => p.year <= 2028).reduce((s, p) => s + p.added, 0)} features graduating by 2028. Velocity parity = Servo&rsquo;s annual feature completion rate &ge; BWA annual growth rate. Completions/yr = ${servoCompletionsPerYear} &times; (FTE/${currentContributors})<sup>${SCALING_EXP}</sup> (sublinear <a href="https://en.wikipedia.org/wiki/Brooks%27s_law">Brooks&rsquo;s Law</a> scaling). Stalled = zero or negative velocity over the full observation period (2023-Q3 to 2026-Q1). Regressions = features that lost &gt;5 percentage points. Cost at &euro;${(SALARY/1000).toFixed(0)}k/yr average engineering salary only &mdash; excludes other opex, infrastructure, management overhead, benefits loading, and inflation. Usage-prioritized scenarios: at &lt;1% threshold, ${drop1_count} features deprioritized (target ${target_drop1}, growth ~49/yr); at &lt;5%, ${drop5_count} features deprioritized (target ${target_drop5}, growth ~47/yr). Data: wpt.fyi, web-features, Servo git history. Full interactive dashboard: dashboard.html.</p> 339 + <p style="font-size:10px;line-height:1.45;color:#666;">Readiness measured against Baseline &ldquo;Widely Available&rdquo; (BWA) web features &mdash; supported 30+ months across all major browsers. Feature scores from Web Platform Tests (WPT) via WPT Feature Manifest mapping. ${measurableCount} of ${totalBWA} BWA features are measurable; ${noDataCount} lack WPT mapping (${(noDataByReason['js-builtin'] || []).length} JS built-ins tested by test262 not WPT, ${(noDataByReason['semantic-html'] || []).length} semantic HTML elements, ${noDataCount - (noDataByReason['js-builtin'] || []).length - (noDataByReason['semantic-html'] || []).length} other with unknown status). FTE-equivalent from per-author commit frequency (1 FTE &asymp; 22 commits/month, capped at 1.0 per person; 115 authors sum to ~${currentContributors} FTE). BWA growth rate of ~${bwaGrowthPerYear}/year is the 2023&ndash;2025 average, normalized to exclude the 2022 interop spike. Known pipeline: ${projectedBWA.filter(p => p.year <= 2028).reduce((s, p) => s + p.added, 0)} features graduating by 2028. Velocity parity = Servo&rsquo;s annual feature completion rate &ge; BWA annual growth rate. Completions/yr = ${servoCompletionsPerYear} &times; (FTE/${currentContributors})<sup>${SCALING_EXP}</sup> (sublinear <a href="https://en.wikipedia.org/wiki/Brooks%27s_law">Brooks&rsquo;s Law</a> scaling). Stalled = zero or negative velocity over the full observation period (2023-Q3 to 2026-Q1). Regressions = features that lost &gt;5 percentage points. Cost at &euro;${(SALARY/1000).toFixed(0)}k/yr per FTE: &euro;${(BASE_SALARY/1000).toFixed(0)}k European senior SWE median total cost &times; ${SPECIALIZATION_MULTIPLIER}&times; premium for browser-engine specialization (small talent pool, Rust/rendering/layout) and multi-disciplinary practice (software development + W3C/WHATWG standards participation + open-source community management). Calibrated against <a href="https://nlnet.nl/funding.html">NLnet</a> (&euro;108k), <a href="https://www.sovereign.tech/programs/fellowship">Sovereign Tech Fund</a> (&euro;79&ndash;101k), <a href="https://www.levels.fyi/companies/mozilla/salaries/software-engineer/locations/germany">Mozilla Germany</a> (&euro;145&ndash;164k), and <a href="https://github.com/servo/project/issues/181">Servo grant rates</a> (&euro;248k US contractor). Excludes other opex, infrastructure, management overhead, and inflation. Usage-prioritized scenarios: at &lt;1% threshold, ${drop1_count} features deprioritized (target ${target_drop1}, growth ~49/yr); at &lt;5%, ${drop5_count} features deprioritized (target ${target_drop5}, growth ~47/yr). Data: wpt.fyi, web-features, Servo git history. Full interactive dashboard: dashboard.html.</p> 348 340 </div> 341 + 342 + <p style="font-size:9px;line-height:1.45;color:#686868;margin-top:8px;">Thanks to the people who&rsquo;ve reviewed the methodology and approach so far. NOTE: AI was used in the making of this draft report. For suggestions for improvement or spotting of inaccuracies, contact <a href="mailto:dietrich@webtransitions.org">dietrich@webtransitions.org</a>.</p> 349 343 350 344 <div class="footer"> 351 345 Servo Baseline Readiness Evaluation &mdash; Data as of March 2026 &mdash; <a href="https://webtransitions.org">webtransitions.org</a>
+44 -23
data/generate-dashboard.mjs
··· 17 17 nearComplete, nearCompleteStalled, nearCompleteActive, 18 18 quarterlyRates, noDataFeatures, noDataByArea, noDataByReason, 19 19 measurableCount, fullCount, readinessPct, noDataCount, 20 - servoCompletionsPerYear, bwaGrowthPerYear, ceilingPct, 21 - parityFTE, parityCostPerYear, parityCost3yr, parityCost5yr, 20 + servoCompletionsPerYear, bwaGrowthPerYear, ceilingPct, ceilingYear, 21 + parityFTE, parityCostPerYear, parityCost3yr, parityFTE_49, parityFTE_47, 22 22 medianActiveVelocity, p25ActiveVelocity, p75ActiveVelocity, 23 23 recentAvgGrowth, projectedBWA, pipelineScoreData, globalAvgScore, 24 24 movingTargetFeatures, 25 - FULL_THRESHOLD, TOTAL_Q, SALARY, SCALING_EXP, currentContributors, 25 + FULL_THRESHOLD, TOTAL_Q, BASE_SALARY, SPECIALIZATION_MULTIPLIER, SALARY, SCALING_EXP, currentContributors, 26 26 } = m; 27 27 28 28 const first = snapshots[0]; ··· 200 200 body { font-family: "Pragati Narrow", sans-serif; background: rgb(247, 226, 231); color: #1d1d1d; padding: 24px; font-size: 1.1rem; line-height: 1.3; } 201 201 h1 { font-size: 28px; margin-bottom: 8px; color: rgb(71, 11, 0); } 202 202 h2 { font-size: 20px; margin-bottom: 12px; color: rgb(71, 11, 0); font-weight: 700; } 203 - .byline { font-size: 13px; color: #1d1d1d; } 203 + .byline { font-size: 12px; color: #1d1d1d; margin-bottom: 16px; } 204 204 .byline a { color: rgb(71, 11, 0); } 205 205 .subtitle { color: #666; margin-bottom: 32px; font-size: 14px; } 206 206 .grid { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; margin-bottom: 24px; } 207 207 .card { background: #fff; border-radius: 12px; padding: 20px; border: 1px solid rgba(71, 11, 0, 0.15); } 208 208 .card.full { grid-column: 1 / -1; } 209 209 .card h3 { font-size: 15px; color: rgb(71, 11, 0); margin-bottom: 16px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; } 210 - .metric { display: flex; gap: 32px; margin-bottom: 20px; flex-wrap: wrap; } 211 - .metric-item { text-align: center; } 210 + .metric { display: flex; gap: 16px; margin-bottom: 20px; flex-wrap: wrap; } 211 + .metric-item { text-align: center; flex: 1; min-width: 140px; background: rgba(71, 11, 0, 0.04); border: 1px solid rgba(71, 11, 0, 0.15); border-radius: 8px; padding: 16px 12px; } 212 212 .metric-value { font-size: 36px; font-weight: 700; color: rgb(71, 11, 0); } 213 213 .metric-label { font-size: 12px; color: #666; margin-top: 4px; } 214 214 .chart-container { position: relative; height: 300px; } ··· 235 235 <body> 236 236 237 237 <h1>Servo Baseline Readiness</h1> 238 - <div class="byline">Dietrich Ayala &mdash; <a href="https://webtransitions.org">webtransitions.org</a></div> 239 - <p class="subtitle">This dashboard evaluates the Servo web engine&rsquo;s readiness to support Baseline &ldquo;Widely Available&rdquo; (BWA) web features &mdash; the set of web platform features supported across all major browsers for at least 30 months. Data as of March 2026.</p> 238 + <div class="byline">Dietrich Ayala &mdash; dietrich@webtransitions.org &mdash; <a href="https://webtransitions.org">webtransitions.org</a></div> 239 + <div style="background:rgba(71,11,0,0.04);border:1px solid rgba(71,11,0,0.15);border-radius:8px;padding:14px 18px;margin-bottom:16px;font-size:14px;line-height:1.5;color:#1d1d1d;"> 240 + Servo is falling behind the web. It completes <strong>~${servoCompletionsPerYear} features/year</strong> at production quality, while the Baseline &ldquo;<a href="https://web-platform-dx.github.io/web-features/" target="_blank">Widely Available</a>&rdquo; set grows at <strong>~${bwaGrowthPerYear} features/year</strong>. At this pace, Servo plateaus around <strong>${ceilingPct}% by ~${ceilingYear} and never catches up</strong>. Full velocity parity requires <strong>~${parityFTE} FTE</strong> (<strong>&euro;${parityCostPerYear}M/yr</strong>, <strong>&euro;${parityCost3yr}M over 3yr</strong>). BWA features vary widely in real-world usage &mdash; a phased approach that prioritizes high-usage features first could reduce the initial headcount and cost by up to 40% while building toward full parity. The highest-leverage actions are <strong>unstalling ${stalledFeatures.length} blocked features</strong> and fixing <strong>${regressions.length} regressions</strong> (features that lost &gt;5 percentage points). This report asks: <strong>what would it cost in engineering investment alone to bring Servo to velocity parity within 3 years</strong>, excluding non-engineering and operational costs? 241 + </div> 240 242 241 243 <div class="metric"> 242 244 <div class="metric-item"> 243 - <div class="metric-value" style="color:#c44">${servoCompletionsPerYear} <span style="font-size:20px;color:#999">vs ${bwaGrowthPerYear}</span></div> 244 - <div class="metric-label">Web Feature Velocity Gap<br>Servo completions/yr vs BWA growth/yr</div> 245 + <div class="metric-value">${readinessPct}% <span style="font-size:20px;color:#999">(${fullCount}/${measurableCount})</span></div> 246 + <div class="metric-label">Current BWA Readiness<br>(measurable features &ge;95%)</div> 245 247 </div> 246 248 <div class="metric-item"> 247 - <div class="metric-value" style="color:rgb(71,11,0)">${parityFTE} FTE</div> 248 - <div class="metric-label">Velocity Parity<br>&euro;${parityCostPerYear}M/yr &mdash; &euro;${parityCost5yr}M over 5yr</div> 249 + <div class="metric-value">${widelyAvailable.length} <span style="font-size:20px;color:#999">&rarr; ~${projectedBWA.find(p => p.year === 2031)?.total ?? 879}</span></div> 250 + <div class="metric-label">BWA Growth<br>today &rarr; by 2031 (~${bwaGrowthPerYear}/yr)</div> 249 251 </div> 250 252 <div class="metric-item"> 251 - <div class="metric-value" style="color:#b87800">${readinessPct}% <span style="font-size:20px;color:#999">(${fullCount}/${measurableCount})</span></div> 252 - <div class="metric-label">Current Readiness<br>(measurable features &ge;95%)</div> 253 + <div class="metric-value">${servoCompletionsPerYear} <span style="font-size:20px;color:#999">vs ${bwaGrowthPerYear}</span></div> 254 + <div class="metric-label">Web Feature Velocity Gap<br>Servo completions/yr vs BWA growth/yr</div> 253 255 </div> 254 256 <div class="metric-item"> 255 - <div class="metric-value" style="color:#999">~${ceilingPct}%</div> 256 - <div class="metric-label">Ceiling at ${currentContributors} FTE<br>Web outgrows Servo</div> 257 + <div class="metric-value">${parityFTE} FTE</div> 258 + <div class="metric-label">Velocity Parity<br>&euro;${parityCostPerYear}M/yr &mdash; &euro;${parityCost3yr}M over 3yr</div> 257 259 </div> 258 260 <div class="metric-item"> 259 - <div class="metric-value" style="color:rgb(71,11,0)">${widelyAvailable.length} <span style="font-size:20px;color:#999">&rarr; ~${projectedBWA.find(p => p.year === 2031)?.total ?? 879}</span></div> 260 - <div class="metric-label">BWA Features<br>today &rarr; by 2031 (~${bwaGrowthPerYear}/yr)</div> 261 + <div class="metric-value">${parityFTE_47}&ndash;${parityFTE_49} FTE</div> 262 + <div class="metric-label">Usage-Prioritized Parity<br>&euro;${(parityFTE_47 * SALARY / 1e6).toFixed(1)}&ndash;${(parityFTE_49 * SALARY / 1e6).toFixed(1)}M/yr (skip low-usage)</div> 261 263 </div> 262 264 </div> 263 265 ··· 322 324 </div> 323 325 <div style="flex:1;min-width:260px;"> 324 326 <label style="display:block;color:#666;font-size:13px;margin-bottom:6px;">Avg Annual Salary (EUR)</label> 325 - <input type="range" id="calcSalary" min="50000" max="400000" step="10000" value="150000" style="width:100%;accent-color:rgb(71,11,0);"> 326 - <div style="display:flex;justify-content:space-between;font-size:12px;color:#999;"><span>&euro;50k</span><span id="calcSalaryVal" style="color:rgb(71,11,0);font-size:16px;font-weight:600;">&euro;150k</span><span>&euro;400k</span></div> 327 + <input type="range" id="calcSalary" min="50000" max="400000" step="10000" value="${SALARY}" style="width:100%;accent-color:rgb(71,11,0);"> 328 + <div style="display:flex;justify-content:space-between;font-size:12px;color:#999;"><span>&euro;50k</span><span id="calcSalaryVal" style="color:rgb(71,11,0);font-size:16px;font-weight:600;">&euro;${(SALARY/1000).toFixed(0)}k</span><span>&euro;400k</span></div> 327 329 </div> 328 330 <div style="flex:1;min-width:260px;"> 329 331 <label style="display:block;color:#666;font-size:13px;margin-bottom:6px;">Scaling Exponent (<a href="https://en.wikipedia.org/wiki/Brooks%27s_law" target="_blank">Brooks's Law</a>)</label> ··· 367 369 368 370 <h2>Key Insights</h2> 369 371 <details class="insight"> 370 - <summary><strong>Regressions are the #1 problem</strong> <span>— ${regressions.length} features went backward, some by 50-75pp. Fixing regressions is cheaper than new implementation.</span></summary> 372 + <summary><strong>Regressions are the #1 problem</strong> <span>— ${regressions.length} features went backward, some by 50–75 percentage points. Fixing regressions is cheaper than new implementation.</span></summary> 371 373 <div class="insight-body"> 372 374 <div class="cols"> 373 375 <div> ··· 528 530 529 531 <h3 style="margin-top:20px;">Scoring Model</h3> 530 532 <p style="margin-bottom:12px;">Each feature's score is the average per-test pass rate across all matched WPT tests. For tests with subtests, the score is <code style="color:rgb(71,11,0);">passed_subtests / total_subtests</code>. For simple pass/fail tests, the score is 0 or 1. A feature is considered <strong style="color:#2a7d2a;">fully supported</strong> at &ge;95% score.</p> 531 - <p style="margin-bottom:12px;">Features with no WPT manifest mapping (${noDataFeatures.length} of ${totalBWA}) are categorized as &ldquo;No Data.&rdquo; These break down into ${(noDataByReason['js-builtin'] || []).length} JS built-ins (supported via SpiderMonkey, tested by test262 not WPT), ${(noDataByReason['semantic-html'] || []).length} semantic HTML elements (trivial &mdash; no special behavior to test), ${(noDataByReason['webgl-extension'] || []).length} WebGL extensions (GPU-driver-dependent), and ${noDataFeatures.length - (noDataByReason['js-builtin'] || []).length - (noDataByReason['semantic-html'] || []).length - (noDataByReason['webgl-extension'] || []).length} other features (basic DOM, CSS, HTTP, WebAssembly). Most are likely already supported.</p> 533 + <p style="margin-bottom:12px;">Features with no WPT manifest mapping (${noDataFeatures.length} of ${totalBWA}) are categorized as &ldquo;No Data.&rdquo; These break down into ${(noDataByReason['js-builtin'] || []).length} JS built-ins (supported via SpiderMonkey, tested by test262 not WPT), ${(noDataByReason['semantic-html'] || []).length} semantic HTML elements (trivial &mdash; no special behavior to test), ${(noDataByReason['webgl-extension'] || []).length} WebGL extensions (GPU-driver-dependent), and ${noDataFeatures.length - (noDataByReason['js-builtin'] || []).length - (noDataByReason['semantic-html'] || []).length - (noDataByReason['webgl-extension'] || []).length} other features (basic DOM, CSS, HTTP, WebAssembly). The ${(noDataByReason['js-builtin'] || []).length} JS built-ins and ${(noDataByReason['semantic-html'] || []).length} semantic HTML elements are supported via SpiderMonkey and the HTML parser respectively; the ${(noDataByReason['webgl-extension'] || []).length} WebGL extensions depend on GPU driver support; the remaining ${noDataFeatures.length - (noDataByReason['js-builtin'] || []).length - (noDataByReason['semantic-html'] || []).length - (noDataByReason['webgl-extension'] || []).length} have unknown status.</p> 532 534 533 535 <h3 style="margin-top:20px;">FTE-Equivalent Contributors</h3> 534 536 <p style="margin-bottom:12px;">The contributor count uses <strong style="color:rgb(71,11,0);">full-time equivalents (FTE)</strong>, not raw headcount. Computed from per-author commit counts over Jul 2025 &ndash; Jan 2026 (7 months), excluding bots (dependabot, WPT Sync). Each author's FTE fraction = <code style="color:rgb(71,11,0);">min(their_commits / 154, 1.0)</code>, where 154 = 22 commits/month &times; 7 months (~1 commit per working day). The sum across all 115 human authors yields <strong style="color:rgb(71,11,0);">~13 FTE</strong>. Of these, 9 core contributors operate at &ge;50% FTE, with a long tail of occasional contributors. This FTE figure is what drives the projection and cost models — it represents the effective engineering capacity, which is what matters for funding decisions.</p> 535 537 536 538 <h3 style="margin-top:20px;">Velocity & Projections</h3> 537 - <p style="margin-bottom:12px;">Per-feature velocity is computed as the improvement per quarter from 2023-Q3 to present. We use <code style="color:rgb(71,11,0);">max(overall_velocity, recent_velocity)</code> where recent velocity covers the last 4 quarters, to account for accelerating progress. Features with velocity &le;0.001 pp/quarter are classified as <strong style="color:#b87800;">stalled</strong>.</p> 539 + <p style="margin-bottom:12px;">Per-feature velocity is computed as the improvement per quarter from 2023-Q3 to present. We use <code style="color:rgb(71,11,0);">max(overall_velocity, recent_velocity)</code> where recent velocity covers the last 4 quarters, to account for accelerating progress. Features with velocity &le;0.001 percentage points/quarter are classified as <strong style="color:#b87800;">stalled</strong>.</p> 538 540 <p style="margin-bottom:12px;">Projections extrapolate each feature individually: <code style="color:rgb(71,11,0);">quarters_to_95% = (0.95 - current_score) / (velocity &times; scale_factor)</code>. The scale factor models additional FTEs using a sublinear power law: <code style="color:rgb(71,11,0);">scale = (new_fte / current_fte)<sup>exponent</sup></code>. The default exponent of 0.7 reflects <a href="https://en.wikipedia.org/wiki/Brooks%27s_law" target="_blank" style="color:rgb(71,11,0);">Brooks's Law</a> — communication overhead means doubling contributors doesn't double output.</p> 539 541 540 542 <h3 style="margin-top:20px;">Cost Model</h3> 541 543 <p style="margin-bottom:12px;">Cost is calculated as: <code style="color:rgb(71,11,0);">additional_FTE &times; salary &times; years_to_milestone</code>, where the milestone date is determined by the Nth-percentile feature reaching 95%. This represents the <em>marginal</em> cost of accelerating beyond the current trajectory — not the total program cost. The model assumes FTEs can be allocated to stalled features and that the scaling exponent applies uniformly.</p> 542 544 545 + <h3 style="margin-top:20px;">Salary Assumptions</h3> 546 + <p style="margin-bottom:12px;">The default salary of <strong style="color:rgb(71,11,0);">&euro;${(SALARY/1000).toFixed(0)}k/yr</strong> is composed of a <strong>&euro;${(BASE_SALARY/1000).toFixed(0)}k base</strong> (European senior software engineer median total cost to employer) &times; a <strong>${SPECIALIZATION_MULTIPLIER}&times; specialization multiplier</strong> for two factors:</p> 547 + <ul style="margin-left:20px;margin-bottom:12px;"> 548 + <li><strong>Highly specialized domain</strong> — browser engine internals (Rust, rendering pipelines, layout algorithms) draws from a very small global talent pool</li> 549 + <li><strong>Multi-disciplinary practice</strong> — each contributor combines software development, <a href="https://www.w3.org/" target="_blank" style="color:rgb(71,11,0);">W3C</a>/<a href="https://whatwg.org/" target="_blank" style="color:rgb(71,11,0);">WHATWG</a> standards body participation, and open-source community contribution management</li> 550 + </ul> 551 + <p style="margin-bottom:8px;font-size:12px;">Reference rates used to calibrate this figure:</p> 552 + <table style="width:auto;font-size:11px;margin-bottom:12px;"> 553 + <tr><th style="text-align:left;">Source</th><th style="text-align:right;">Annual Equivalent</th><th>Notes</th></tr> 554 + <tr><td><a href="https://nlnet.nl/funding.html" target="_blank" style="color:rgb(71,11,0);">NLnet</a> grants (&euro;60/hr)</td><td style="text-align:right;">&euro;108k</td><td style="color:#999;">Below-market philanthropy rate</td></tr> 555 + <tr><td><a href="https://www.sovereign.tech/programs/fellowship" target="_blank" style="color:rgb(71,11,0);">Sovereign Tech Fund</a> (employment + social)</td><td style="text-align:right;">&euro;79&ndash;101k</td><td style="color:#999;">German public-sector TVöD scale</td></tr> 556 + <tr><td>European senior SWE median (total cost)</td><td style="text-align:right;">&euro;100&ndash;140k</td><td style="color:#999;">Varies by country; incl. employer costs</td></tr> 557 + <tr><td>Mozilla Germany senior SWE (<a href="https://www.levels.fyi/companies/mozilla/salaries/software-engineer/locations/germany" target="_blank" style="color:rgb(71,11,0);">Levels.fyi</a>)</td><td style="text-align:right;">&euro;145&ndash;164k</td><td style="color:#999;">Top-tier browser-engine employer</td></tr> 558 + <tr style="background:rgba(71,11,0,0.05);font-weight:600;"><td>Model default (&euro;${(BASE_SALARY/1000).toFixed(0)}k &times; ${SPECIALIZATION_MULTIPLIER})</td><td style="text-align:right;">&euro;${(SALARY/1000).toFixed(0)}k</td><td style="color:#999;">Specialized + multi-disciplinary premium</td></tr> 559 + <tr><td><a href="https://github.com/servo/project/issues/181" target="_blank" style="color:rgb(71,11,0);">Servo grant</a> ($150/hr &times; 1800)</td><td style="text-align:right;">&euro;248k</td><td style="color:#999;">US contractor rate with overhead</td></tr> 560 + </table> 561 + 543 562 <h3 style="margin-top:20px;">Limitations</h3> 544 563 <ul style="margin-left:20px;"> 545 564 <li>26% of Widely Available features lack WPT test mapping, creating a coverage gap</li> ··· 550 569 <li>Stalled features may require architectural work rather than incremental test fixes</li> 551 570 </ul> 552 571 </div> 572 + 573 + <p style="font-size:12px;line-height:1.5;color:#686868;margin:20px 0;">Thanks to the people who&rsquo;ve reviewed the methodology and approach so far. NOTE: AI was used in the making of this draft report. For suggestions for improvement or spotting of inaccuracies, contact <a href="mailto:dietrich@webtransitions.org" style="color:rgb(71,11,0);">dietrich@webtransitions.org</a>.</p> 553 574 554 575 <script> 555 576 Chart.defaults.color = '#666';
+1 -1
data/projections.mjs
··· 314 314 { contributors: currentContributors * 5, label: "5x contributors" }, 315 315 ]; 316 316 317 - const DEFAULT_SALARY = 150000; 317 + const DEFAULT_SALARY = 200000; 318 318 319 319 console.log(`Assumptions:`); 320 320 console.log(` Current contributors: ~${currentContributors}`);
+11 -2
data/servo-metrics.mjs
··· 9 9 // ============================================================ 10 10 export const FULL_THRESHOLD = 0.95; 11 11 export const TOTAL_Q = 10; 12 - export const SALARY = 150000; 12 + export const BASE_SALARY = 150000; // European senior SWE median total cost to employer 13 + export const SPECIALIZATION_MULTIPLIER = 1.33; // Browser-engine specialization + multi-disciplinary premium 14 + export const SALARY = Math.round(BASE_SALARY * SPECIALIZATION_MULTIPLIER); // ~€200k 13 15 export const SCALING_EXP = 0.7; 14 16 export const currentContributors = 13; 15 17 ··· 205 207 // Ceiling 206 208 const activeCount = featureVelocities.filter(f => f.score >= FULL_THRESHOLD || f.velocity > 0.001).length; 207 209 const ceilingPct = Math.round((activeCount + noDataCount) / widelyAvailable.length * 100); 210 + // Estimate year Servo reaches the ceiling on today's BWA features (ignoring new growth). 211 + // At servoCompletionsPerYear, how many years to complete all active + no-data features? 212 + const reachableCount = activeCount + noDataCount; 213 + const remainingToReach = reachableCount - (fullCount + noDataCount); 214 + const ceilingYear = 2026 + Math.ceil(Math.max(remainingToReach, 0) / Math.max(servoCompletionsPerYear, 1)); 208 215 209 216 // FTE and cost 210 217 const parityFTE = Math.round(currentContributors * Math.pow(bwaGrowthPerYear / Math.max(servoCompletionsPerYear, 1), 1 / SCALING_EXP)); ··· 376 383 noDataCount, 377 384 servoCompletionsPerYear, 378 385 bwaGrowthPerYear, 379 - ceilingPct, 386 + ceilingPct, ceilingYear, 380 387 parityFTE, 381 388 parityCostPerYear, 382 389 parityCost3yr, ··· 399 406 // Constants (re-exported for convenience) 400 407 FULL_THRESHOLD, 401 408 TOTAL_Q, 409 + BASE_SALARY, 410 + SPECIALIZATION_MULTIPLIER, 402 411 SALARY, 403 412 SCALING_EXP, 404 413 currentContributors,
+7 -7
index.html
··· 136 136 </div> 137 137 <div style="flex:1;min-width:260px;"> 138 138 <label style="display:block;color:#666;font-size:13px;margin-bottom:6px;">Avg Annual Salary (EUR)</label> 139 - <input type="range" id="calcSalary" min="50000" max="400000" step="10000" value="150000" style="width:100%;accent-color:rgb(71,11,0);"> 140 - <div style="display:flex;justify-content:space-between;font-size:12px;color:#686868;"><span>&euro;50k</span><span id="calcSalaryVal" style="color:rgb(71,11,0);font-size:16px;font-weight:600;">&euro;150k</span><span>&euro;400k</span></div> 139 + <input type="range" id="calcSalary" min="50000" max="400000" step="10000" value="200000" style="width:100%;accent-color:rgb(71,11,0);"> 140 + <div style="display:flex;justify-content:space-between;font-size:12px;color:#686868;"><span>&euro;50k</span><span id="calcSalaryVal" style="color:rgb(71,11,0);font-size:16px;font-weight:600;">&euro;200k</span><span>&euro;400k</span></div> 141 141 </div> 142 142 <div style="flex:1;min-width:260px;"> 143 143 <label style="display:block;color:#666;font-size:13px;margin-bottom:6px;">Scaling Exponent (<a href="https://en.wikipedia.org/wiki/Brooks%27s_law" target="_blank">Brooks's Law</a>)</label> ··· 197 197 </div> 198 198 <div style="flex:1;min-width:260px;"> 199 199 <label style="display:block;color:#666;font-size:13px;margin-bottom:6px;">Avg Annual Salary (EUR)</label> 200 - <input type="range" id="sprintSalary" min="50000" max="400000" step="10000" value="150000" style="width:100%;accent-color:rgb(71,11,0);"> 201 - <div style="display:flex;justify-content:space-between;font-size:12px;color:#686868;"><span>&euro;50k</span><span id="sprintSalaryVal" style="color:rgb(71,11,0);font-size:16px;font-weight:600;">&euro;150k</span><span>&euro;400k</span></div> 200 + <input type="range" id="sprintSalary" min="50000" max="400000" step="10000" value="200000" style="width:100%;accent-color:rgb(71,11,0);"> 201 + <div style="display:flex;justify-content:space-between;font-size:12px;color:#686868;"><span>&euro;50k</span><span id="sprintSalaryVal" style="color:rgb(71,11,0);font-size:16px;font-weight:600;">&euro;200k</span><span>&euro;400k</span></div> 202 202 </div> 203 203 </div> 204 204 ··· 239 239 240 240 <h2>Key Insights</h2> 241 241 <details class="insight"> 242 - <summary><strong>79 regressions are the #1 problem</strong> <span>— features went backward, some by 50-75pp. Fixing regressions is cheaper than new implementation.</span></summary> 242 + <summary><strong>79 regressions are the #1 problem</strong> <span>— features went backward, some by 50–75 percentage points. Fixing regressions is cheaper than new implementation.</span></summary> 243 243 <div class="insight-body"> 244 244 <div class="cols"> 245 245 <div> ··· 478 478 479 479 <h3 style="margin-top:20px;">Scoring Model</h3> 480 480 <p style="margin-bottom:12px;">Each feature's score is the average per-test pass rate across all matched WPT tests. For tests with subtests, the score is <code style="color:rgb(71,11,0);">passed_subtests / total_subtests</code>. For simple pass/fail tests, the score is 0 or 1. A feature is considered <strong style="color:#1f6e1f;">fully supported</strong> at &ge;95% score.</p> 481 - <p style="margin-bottom:12px;">Features with no WPT manifest mapping (154 of 593) are categorized as &ldquo;No Data.&rdquo; These break down into 78 JS built-ins (supported via SpiderMonkey, tested by test262 not WPT), 23 semantic HTML elements (trivial &mdash; no special behavior to test), 20 WebGL extensions (GPU-driver-dependent), and 33 other features (basic DOM, CSS, HTTP, WebAssembly). Most are likely already supported.</p> 481 + <p style="margin-bottom:12px;">Features with no WPT manifest mapping (154 of 593) are categorized as &ldquo;No Data.&rdquo; These break down into 78 JS built-ins (supported via SpiderMonkey, tested by test262 not WPT), 23 semantic HTML elements (trivial &mdash; no special behavior to test), 20 WebGL extensions (GPU-driver-dependent), and 33 other features (basic DOM, CSS, HTTP, WebAssembly). The 78 JS built-ins and 23 semantic HTML elements are supported via SpiderMonkey and the HTML parser respectively; the 20 WebGL extensions depend on GPU driver support; the remaining 33 have unknown status.</p> 482 482 483 483 <h3 style="margin-top:20px;">FTE-Equivalent Contributors</h3> 484 484 <p style="margin-bottom:12px;">The contributor count uses <strong style="color:rgb(71,11,0);">full-time equivalents (FTE)</strong>, not raw headcount. Computed from per-author commit counts over Jul 2025 &ndash; Jan 2026 (7 months), excluding bots (dependabot, WPT Sync). Each author's FTE fraction = <code style="color:rgb(71,11,0);">min(their_commits / 154, 1.0)</code>, where 154 = 22 commits/month &times; 7 months (~1 commit per working day). The sum across all 115 human authors yields <strong style="color:rgb(71,11,0);">~13 FTE</strong>. Of these, 9 core contributors operate at &ge;50% FTE, with a long tail of occasional contributors. This FTE figure is what drives the projection and cost models — it represents the effective engineering capacity, which is what matters for funding decisions.</p> 485 485 486 486 <h3 style="margin-top:20px;">Velocity & Projections</h3> 487 - <p style="margin-bottom:12px;">Per-feature velocity is computed as the improvement per quarter from 2023-Q3 to present. We use <code style="color:rgb(71,11,0);">max(overall_velocity, recent_velocity)</code> where recent velocity covers the last 4 quarters, to account for accelerating progress. Features with velocity &le;0.001 pp/quarter are classified as <strong style="color:#8a5a00;">stalled</strong>.</p> 487 + <p style="margin-bottom:12px;">Per-feature velocity is computed as the improvement per quarter from 2023-Q3 to present. We use <code style="color:rgb(71,11,0);">max(overall_velocity, recent_velocity)</code> where recent velocity covers the last 4 quarters, to account for accelerating progress. Features with velocity &le;0.001 percentage points/quarter are classified as <strong style="color:#8a5a00;">stalled</strong>.</p> 488 488 <p style="margin-bottom:12px;">Projections extrapolate each feature individually: <code style="color:rgb(71,11,0);">quarters_to_95% = (0.95 - current_score) / (velocity &times; scale_factor)</code>. The scale factor models additional FTEs using a sublinear power law: <code style="color:rgb(71,11,0);">scale = (new_fte / current_fte)<sup>exponent</sup></code>. The default exponent of 0.7 reflects <a href="https://en.wikipedia.org/wiki/Brooks%27s_law" target="_blank" style="color:rgb(71,11,0);">Brooks's Law</a> — communication overhead means doubling contributors doesn't double output.</p> 489 489 490 490 <h3 style="margin-top:20px;">Cost Model</h3>
+2 -2
one-pager-document.html
··· 130 130 <tr class="highlight"><td>35</td><td>~60</td><td class="pass">&#x2713; parity</td><td class="pass">&#x2713;</td><td class="pass">&#x2713;</td><td>&euro;5.3M</td><td>&euro;15.9M</td></tr> 131 131 <tr><td>45</td><td>~62</td><td class="pass">&#x2713;</td><td class="pass">&#x2713;</td><td class="pass">&#x2713;</td><td>&euro;6.8M</td><td>&euro;20.4M</td></tr> 132 132 </table> 133 - <p style="font-size:9px;color:#686868;">All BWA = 593 features (~52/yr). &lt;1% = drop 35 features below 1% Chrome page loads (~49/yr). &lt;5% = drop 56 features (~47/yr). Cost = FTE &times; &euro;150k. <a href="https://en.wikipedia.org/wiki/Brooks%27s_law">Brooks&rsquo;s Law</a> (0.7).</p> 133 + <p style="font-size:9px;color:#686868;">All BWA = 593 features (~52/yr). &lt;1% = drop 35 features below 1% Chrome page loads (~49/yr). &lt;5% = drop 56 features (~47/yr). Cost = FTE &times; &euro;200k (&euro;150k base &times; 1.33&times; specialization). <a href="https://en.wikipedia.org/wiki/Brooks%27s_law">Brooks&rsquo;s Law</a> (0.7).</p> 134 134 </div> 135 135 </div> 136 136 137 137 <h2>Methodology</h2> 138 - <p class="methodology">Readiness measured against Baseline &ldquo;Widely Available&rdquo; (BWA) web features&mdash;supported 30+ months across all major browsers. Feature scores from Web Platform Tests (WPT) via WPT Feature Manifest mapping. FTE-equivalent from per-author commit frequency (1 FTE &asymp; 22 commits/month, capped at 1.0; 115 authors sum to ~13 FTE). BWA growth rate ~52/yr (2023&ndash;2025 avg, excluding 2022 interop spike). Velocity parity = annual completion rate &ge; BWA growth rate. Projections use sublinear contributor scaling (exponent 0.7). Cost at &euro;150k/yr avg engineering salary only&mdash;excludes other opex, infrastructure, overhead, and inflation. Usage data: 111 of 593 BWA features have Chrome page-load data (webstatus.dev); 482 are fundamental features not tracked by Use Counters. Data: wpt.fyi, web-features, webstatus.dev, Servo git history.</p> 138 + <p class="methodology">Readiness measured against Baseline &ldquo;Widely Available&rdquo; (BWA) web features&mdash;supported 30+ months across all major browsers. Feature scores from Web Platform Tests (WPT) via WPT Feature Manifest mapping. FTE-equivalent from per-author commit frequency (1 FTE &asymp; 22 commits/month, capped at 1.0; 115 authors sum to ~13 FTE). BWA growth rate ~52/yr (2023&ndash;2025 avg, excluding 2022 interop spike). Velocity parity = annual completion rate &ge; BWA growth rate. Projections use sublinear contributor scaling (exponent 0.7). Cost at &euro;200k/yr per FTE: &euro;150k European senior SWE median total cost &times; 1.33&times; premium for browser-engine specialization and multi-disciplinary practice (software development + W3C/WHATWG standards participation + open-source community management). Calibrated against NLnet (&euro;108k), Sovereign Tech Fund (&euro;79&ndash;101k), Mozilla Germany (&euro;145&ndash;164k), and Servo grant rates (&euro;248k US contractor). Excludes other opex, infrastructure, overhead, and inflation. Usage data: 111 of 593 BWA features have Chrome page-load data (webstatus.dev); 482 are fundamental features not tracked by Use Counters. Data: wpt.fyi, web-features, webstatus.dev, Servo git history.</p> 139 139 140 140 <div class="footer"> 141 141 Servo Baseline Readiness Evaluation &mdash; Data as of February 13, 2026 &mdash; Full report: <a href="https://webtransitions.org/servo-readiness">webtransitions.org/servo-readiness</a>
+39 -45
one-pager.html
··· 17 17 font-size: 1.1rem; line-height: 1.3; 18 18 } 19 19 20 - .header { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 14px; border-bottom: 2px solid rgb(71, 11, 0); padding-bottom: 10px; } 20 + .header { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 14px; padding-bottom: 10px; } 21 21 h1 { font-size: 26px; font-weight: 700; color: rgb(71, 11, 0); } 22 22 .byline { font-size: 12px; color: #1d1d1d; margin-top: 2px; } 23 23 .byline a { color: rgb(71, 11, 0); } ··· 25 25 26 26 .hero { display: flex; gap: 10px; margin-bottom: 14px; } 27 27 .hero-card { 28 - flex: 1; background: #fff; border-radius: 8px; padding: 12px 10px; 29 - border: 1px solid rgba(71, 11, 0, 0.15); text-align: center; 28 + flex: 1; border-radius: 8px; padding: 12px 10px; text-align: center; 29 + background: rgba(71, 11, 0, 0.04); border: 1px solid rgba(71, 11, 0, 0.15); 30 30 } 31 - .hero-card.primary { border-color: rgb(71, 11, 0); background: rgba(71, 11, 0, 0.05); } 32 - .hero-card.warn { border-color: #a33; background: rgba(204, 68, 68, 0.05); } 33 31 .hero-label { font-size: 9px; color: #666; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 3px; } 34 32 .hero-value { font-size: 26px; font-weight: 700; color: rgb(71, 11, 0); } 35 - .hero-value.alert { color: #a33; } 36 - .hero-value.accent { color: rgb(71, 11, 0); } 37 33 .hero-sub { font-size: 10px; color: #666; margin-top: 2px; line-height: 1.4; } 38 34 39 35 .section { margin-bottom: 12px; } ··· 72 68 </head> 73 69 <body> 74 70 75 - <div style="background:#a33;color:#fff;text-align:center;padding:4px;font-size:11px;font-weight:700;letter-spacing:0.1em;text-transform:uppercase;margin-bottom:6px;">DRAFT &mdash; Do not circulate without permission</div> 76 - 77 71 <div class="header"> 78 72 <div> 79 73 <h1>Servo Baseline Readiness</h1> 80 74 <div class="byline">Dietrich Ayala &mdash; dietrich@webtransitions.org &mdash; <a href="https://webtransitions.org">webtransitions.org</a></div> 81 75 </div> 82 - <span class="date">March 2026</span> 76 + <div><span style="color:#a33;font-weight:700;font-size:12px;letter-spacing:0.06em;margin-right:8px;">DRAFT</span><span class="date">March 2026</span></div> 83 77 </div> 84 78 85 - <p style="font-size:11.5px;line-height:1.5;color:#1d1d1d;margin-bottom:10px;">This report evaluates the Servo web engine&rsquo;s readiness to support Baseline &ldquo;Widely Available&rdquo; (BWA) web features &mdash; the set of web platform features that have been supported across all major browsers for at least 30 months.</p> 79 + <div class="callout"> 80 + <p>Servo is falling behind the web. It completes <strong>~22 features/year</strong> at production quality, while the Baseline &ldquo;<a href="https://web-platform-dx.github.io/web-features/">Widely Available</a>&rdquo; set grows at <strong>~52 features/year</strong>. At this pace, Servo plateaus around <strong>80% by ~2037 and never catches up</strong>. Full velocity parity requires <strong>~44 FTE</strong> (<strong>&euro;8.8M/yr</strong>, <strong>&euro;26.3M over 3yr</strong>). BWA features vary widely in real-world usage &mdash; a phased approach that prioritizes high-usage features first could reduce the initial headcount and cost by up to 40% while building toward full parity. The highest-leverage actions are <strong>unstalling 141 blocked features</strong> and fixing <strong>51 regressions</strong> (features that lost &gt;5 percentage points). This report asks: <strong>what would it cost in engineering investment alone to bring Servo to velocity parity within 3 years</strong>, excluding non-engineering and operational costs?</p> 81 + </div> 86 82 87 83 <div class="hero"> 88 - <div class="hero-card warn"> 89 - <div class="hero-label">Web feature velocity gap</div> 90 - <div class="hero-value alert">22 vs 52</div> 91 - <div class="hero-sub">Servo completes 22 features/yr<br>Web adds 52 new features/yr</div> 92 - </div> 93 - <div class="hero-card primary"> 94 - <div class="hero-label">Velocity parity</div> 95 - <div class="hero-value accent">44 FTE</div> 96 - <div class="hero-sub">&euro;6.6M/yr &mdash; &euro;19.8M over 3yr<br><span style="color:#686868;">(13 existing + 31 new)</span></div> 97 - </div> 98 84 <div class="hero-card"> 99 85 <div class="hero-label">Current BWA readiness</div> 100 - <div class="hero-value warn-text">19.8%</div> 86 + <div class="hero-value">19.8%</div> 101 87 <div class="hero-sub">87 of 439 measurable at &ge;95%</div> 102 88 </div> 103 89 <div class="hero-card"> 104 - <div class="hero-label">Current pace &rarr; ceiling</div> 105 - <div class="hero-value" style="color:#686868;">~80%</div> 106 - <div class="hero-sub">Web outgrows Servo at 13 FTE</div> 90 + <div class="hero-label">BWA growth</div> 91 + <div class="hero-value">593 <span style="font-size:16px;color:#686868;">&rarr; ~879</span></div> 92 + <div class="hero-sub">today &rarr; by 2031 (~52/yr)</div> 107 93 </div> 108 - <div class="hero-card" style="border-color:#1f6e1f;background:rgba(42,125,42,0.05);"> 94 + <div class="hero-card"> 95 + <div class="hero-label">Web feature velocity gap</div> 96 + <div class="hero-value">22 vs 52</div> 97 + <div class="hero-sub">Servo completes 22 features/yr<br>Web adds 52 new features/yr</div> 98 + </div> 99 + <div class="hero-card"> 100 + <div class="hero-label">Velocity parity</div> 101 + <div class="hero-value">44 FTE</div> 102 + <div class="hero-sub">&euro;8.8M/yr &mdash; &euro;26.3M over 3yr<br><span style="color:#686868;">(13 existing + 31 new)</span></div> 103 + </div> 104 + <div class="hero-card"> 109 105 <div class="hero-label">Usage-prioritized parity</div> 110 - <div class="hero-value pass">38&ndash;41 FTE</div> 111 - <div class="hero-sub">&euro;5.7&ndash;6.2M/yr<br><span style="color:#686868;">skip low-usage (&lt;1&ndash;5%) features</span></div> 106 + <div class="hero-value">38&ndash;41 FTE</div> 107 + <div class="hero-sub">&euro;7.6&ndash;8.2M/yr<br><span style="color:#686868;">skip low-usage (&lt;1&ndash;5%) features</span></div> 112 108 </div> 113 109 </div> 114 110 115 - <div class="callout"> 116 - <p>Servo is falling behind the web. It completes <strong>~22 features/year</strong> at production quality, while the Baseline &ldquo;Widely Available&rdquo; set grows at <strong>~52 features/year</strong>. At this pace, Servo plateaus around <strong>80% and never catches up</strong>. Full velocity parity requires <strong>~44 FTE</strong> (<strong>&euro;6.6M/yr</strong>, <strong>&euro;19.8M over 3yr</strong>). But not all BWA features matter equally &mdash; deprioritizing low-usage features could significantly reduce the parity target. The highest-impact investments remain <strong>unstalling 141 blocked features</strong> and fixing <strong>51 regressions</strong> (features that lost &gt;5 percentage points).</p> 117 - </div> 118 - 119 111 <table style="width:100%;border-collapse:collapse;font-size:11px;margin-bottom:12px;background:#fff;border-radius:6px;overflow:hidden;border:1px solid rgba(71,11,0,0.15);"> 120 112 <tr style="background:rgba(71,11,0,0.05);"><th style="padding:5px 8px;text-align:left;border-bottom:1px solid rgba(71,11,0,0.2);color:rgb(71,11,0);">Impact of Usage Prioritization</th><th style="padding:5px 8px;text-align:right;border-bottom:1px solid rgba(71,11,0,0.2);color:#666;">Full BWA</th><th style="padding:5px 8px;text-align:right;border-bottom:1px solid rgba(71,11,0,0.2);color:#666;">Drop &lt;1%</th><th style="padding:5px 8px;text-align:right;border-bottom:1px solid rgba(71,11,0,0.2);color:#666;">Drop &lt;5%</th></tr> 121 113 <tr><td style="padding:4px 8px;border-bottom:1px solid rgba(71,11,0,0.08);">Target features</td><td style="padding:4px 8px;text-align:right;border-bottom:1px solid rgba(71,11,0,0.08);">593</td><td style="padding:4px 8px;text-align:right;border-bottom:1px solid rgba(71,11,0,0.08);">558 (<span class="pass">&minus;35</span>)</td><td style="padding:4px 8px;text-align:right;border-bottom:1px solid rgba(71,11,0,0.08);">537 (<span class="pass">&minus;56</span>)</td></tr> 122 114 <tr><td style="padding:4px 8px;border-bottom:1px solid rgba(71,11,0,0.08);">BWA growth rate</td><td style="padding:4px 8px;text-align:right;border-bottom:1px solid rgba(71,11,0,0.08);">~52/yr</td><td style="padding:4px 8px;text-align:right;border-bottom:1px solid rgba(71,11,0,0.08);">~49/yr</td><td style="padding:4px 8px;text-align:right;border-bottom:1px solid rgba(71,11,0,0.08);">~47/yr</td></tr> 123 115 <tr><td style="padding:4px 8px;border-bottom:1px solid rgba(71,11,0,0.08);">Parity FTE</td><td style="padding:4px 8px;text-align:right;border-bottom:1px solid rgba(71,11,0,0.08);font-weight:700;">~44</td><td style="padding:4px 8px;text-align:right;border-bottom:1px solid rgba(71,11,0,0.08);font-weight:700;color:#1f6e1f;">~41</td><td style="padding:4px 8px;text-align:right;border-bottom:1px solid rgba(71,11,0,0.08);font-weight:700;color:#1f6e1f;">~38</td></tr> 124 - <tr><td style="padding:4px 8px;border-bottom:1px solid rgba(71,11,0,0.08);">Cost/yr</td><td style="padding:4px 8px;text-align:right;border-bottom:1px solid rgba(71,11,0,0.08);">&euro;6.6M</td><td style="padding:4px 8px;text-align:right;border-bottom:1px solid rgba(71,11,0,0.08);">&euro;6.2M</td><td style="padding:4px 8px;text-align:right;border-bottom:1px solid rgba(71,11,0,0.08);">&euro;5.7M</td></tr> 125 - <tr><td style="padding:4px 8px;border-bottom:1px solid rgba(71,11,0,0.08);">3yr total</td><td style="padding:4px 8px;text-align:right;border-bottom:1px solid rgba(71,11,0,0.08);">&euro;19.8M</td><td style="padding:4px 8px;text-align:right;border-bottom:1px solid rgba(71,11,0,0.08);">&euro;18.4M</td><td style="padding:4px 8px;text-align:right;border-bottom:1px solid rgba(71,11,0,0.08);">&euro;17.1M</td></tr> 126 - <tr style="background:rgba(42,125,42,0.06);"><td style="padding:4px 8px;font-weight:700;color:#1f6e1f;">3yr savings</td><td style="padding:4px 8px;text-align:right;color:#686868;">&mdash;</td><td style="padding:4px 8px;text-align:right;font-weight:700;color:#1f6e1f;">&euro;1.4M</td><td style="padding:4px 8px;text-align:right;font-weight:700;color:#1f6e1f;">&euro;2.7M</td></tr> 116 + <tr><td style="padding:4px 8px;border-bottom:1px solid rgba(71,11,0,0.08);">Cost/yr</td><td style="padding:4px 8px;text-align:right;border-bottom:1px solid rgba(71,11,0,0.08);">&euro;8.8M</td><td style="padding:4px 8px;text-align:right;border-bottom:1px solid rgba(71,11,0,0.08);">&euro;8.2M</td><td style="padding:4px 8px;text-align:right;border-bottom:1px solid rgba(71,11,0,0.08);">&euro;7.6M</td></tr> 117 + <tr><td style="padding:4px 8px;border-bottom:1px solid rgba(71,11,0,0.08);">3yr total</td><td style="padding:4px 8px;text-align:right;border-bottom:1px solid rgba(71,11,0,0.08);">&euro;26.3M</td><td style="padding:4px 8px;text-align:right;border-bottom:1px solid rgba(71,11,0,0.08);">&euro;24.5M</td><td style="padding:4px 8px;text-align:right;border-bottom:1px solid rgba(71,11,0,0.08);">&euro;22.7M</td></tr> 118 + <tr style="background:rgba(42,125,42,0.06);"><td style="padding:4px 8px;font-weight:700;color:#1f6e1f;">3yr savings</td><td style="padding:4px 8px;text-align:right;color:#686868;">&mdash;</td><td style="padding:4px 8px;text-align:right;font-weight:700;color:#1f6e1f;">&euro;1.8M</td><td style="padding:4px 8px;text-align:right;font-weight:700;color:#1f6e1f;">&euro;3.6M</td></tr> 127 119 </table> 128 120 129 121 <div class="two-col"> ··· 132 124 <h2>Investment Scenarios (Moving Target)</h2> 133 125 <table> 134 126 <tr><th>FTE</th><th>Compl/yr</th><th>vs All BWA<br>(52/yr)</th><th>vs &lt;1%<br>(49/yr)</th><th>vs &lt;5%<br>(47/yr)</th><th>&euro;/yr</th><th>3yr</th></tr> 135 - <tr><td>13 (now)</td><td>~22</td><td class="fail">&#x2717;</td><td class="fail">&#x2717;</td><td class="fail">&#x2717;</td><td>&euro;1.9M</td><td>&euro;5.8M</td></tr> 136 - <tr><td>25</td><td>~35</td><td class="fail">&#x2717;</td><td class="fail">&#x2717;</td><td class="fail">&#x2717;</td><td>&euro;3.8M</td><td>&euro;11.3M</td></tr> 137 - <tr style="background:rgba(42,125,42,0.08);"><td><strong>38</strong></td><td>~47</td><td class="fail">&#x2717;</td><td class="warn-text">&#x2248;</td><td class="pass">&#x2713;</td><td>&euro;5.7M</td><td>&euro;17.1M</td></tr> 138 - <tr style="background:rgba(42,125,42,0.08);"><td><strong>41</strong></td><td>~49</td><td class="fail">&#x2717;</td><td class="pass">&#x2713;</td><td class="pass">&#x2713;</td><td>&euro;6.2M</td><td>&euro;18.4M</td></tr> 139 - <tr class="highlight"><td>44</td><td>~52</td><td class="pass">&#x2713; parity</td><td class="pass">&#x2713;</td><td class="pass">&#x2713;</td><td>&euro;6.6M</td><td>&euro;19.8M</td></tr> 140 - <tr><td>55</td><td>~60</td><td class="pass">&#x2713;</td><td class="pass">&#x2713;</td><td class="pass">&#x2713;</td><td>&euro;8.3M</td><td>&euro;24.8M</td></tr> 127 + <tr><td>13 (now)</td><td>~22</td><td class="fail">&#x2717;</td><td class="fail">&#x2717;</td><td class="fail">&#x2717;</td><td>&euro;2.6M</td><td>&euro;7.8M</td></tr> 128 + <tr><td>25</td><td>~35</td><td class="fail">&#x2717;</td><td class="fail">&#x2717;</td><td class="fail">&#x2717;</td><td>&euro;5.0M</td><td>&euro;15.0M</td></tr> 129 + <tr style="background:rgba(42,125,42,0.08);"><td><strong>38</strong></td><td>~47</td><td class="fail">&#x2717;</td><td class="warn-text">&#x2248;</td><td class="pass">&#x2713;</td><td>&euro;7.6M</td><td>&euro;22.7M</td></tr> 130 + <tr style="background:rgba(42,125,42,0.08);"><td><strong>41</strong></td><td>~49</td><td class="fail">&#x2717;</td><td class="pass">&#x2713;</td><td class="pass">&#x2713;</td><td>&euro;8.2M</td><td>&euro;24.5M</td></tr> 131 + <tr class="highlight"><td>44</td><td>~52</td><td class="pass">&#x2713; parity</td><td class="pass">&#x2713;</td><td class="pass">&#x2713;</td><td>&euro;8.8M</td><td>&euro;26.3M</td></tr> 132 + <tr><td>55</td><td>~60</td><td class="pass">&#x2713;</td><td class="pass">&#x2713;</td><td class="pass">&#x2713;</td><td>&euro;11.0M</td><td>&euro;32.9M</td></tr> 141 133 </table> 142 - <p style="font-size:9.5px;color:#686868;margin-top:3px;">All BWA = 593 features (~52/yr). &lt;1% = drop 35 features below 1% usage (~49/yr). &lt;5% = drop 56 features (~47/yr). Completions/yr = 22 &times; (FTE/13)<sup>0.7</sup>. Cost = FTE &times; &euro;150k. <a href="https://en.wikipedia.org/wiki/Brooks%27s_law">Brooks's Law</a> scaling exponent 0.7.</p> 134 + <p style="font-size:9.5px;color:#686868;margin-top:3px;">All BWA = 593 features (~52/yr). &lt;1% = drop 35 features below 1% usage (~49/yr). &lt;5% = drop 56 features (~47/yr). Completions/yr = 22 &times; (FTE/13)<sup>0.7</sup>. Cost = FTE &times; &euro;200k (&euro;150k base &times; 1.33&times; specialization). <a href="https://en.wikipedia.org/wiki/Brooks%27s_law">Brooks's Law</a> scaling exponent 0.7.</p> 143 135 </div> 144 136 145 137 <div class="section"> ··· 154 146 <span><span style="color:#8a5a00;">&#9632;</span> 333 partial (75.9%)</span> 155 147 <span><span style="color:#a33;">&#9632;</span> 19 unsupported (4.3%)</span> 156 148 </div> 157 - <p style="font-size:10.5px;color:#1d1d1d;line-height:1.4;">Of 593 BWA features, 439 have WPT test coverage. 154 lack WPT mapping: 78 JS built-ins (SpiderMonkey/test262), 23 semantic HTML elements, 53 other (WebGL extensions, DOM, CSS, etc.). Most are likely already supported. WPT pass rate doubled from 30% to 62% over 2.5 years.</p> 149 + <p style="font-size:10.5px;color:#1d1d1d;line-height:1.4;">Of 593 BWA features, 439 have WPT test coverage. 154 lack WPT mapping: 78 JS built-ins (SpiderMonkey/test262), 23 semantic HTML elements, 53 other (WebGL extensions, DOM, CSS, etc.). The 78 JS built-ins and 23 semantic HTML elements (~66% of unmeasured) are supported via SpiderMonkey and the HTML parser respectively; the remaining 53 have unknown status. WPT pass rate doubled from 30% to 62% over 2.5 years.</p> 158 150 <h2 style="margin-top:8px;">BWA Growth Pipeline</h2> 159 151 <table> 160 152 <tr><th>Year</th><th>New BWA</th><th>Cumulative</th><th>Source</th></tr> ··· 185 177 <h2>Key Strategic Factors</h2> 186 178 <div class="insight-row"> 187 179 <div class="insight-num">1</div> 188 - <div class="insight-text"><strong class="fail">Velocity gap</strong> — Servo completes 22 features/yr vs 52 new BWA/yr. At 13 FTE it plateaus at ~80% and never catches up. This is the core funding case.</div> 180 + <div class="insight-text"><strong class="fail">Velocity gap</strong> — Servo completes 22 features/yr vs 52 new BWA/yr. At 13 FTE it plateaus at ~80% by ~2037 and never catches up. This is the core funding case.</div> 189 181 </div> 190 182 <div class="insight-row"> 191 183 <div class="insight-num">2</div> ··· 209 201 210 202 <div class="section"> 211 203 <h2>Methodology</h2> 212 - <p style="font-size:10px;line-height:1.45;color:#666;">Readiness measured against Baseline &ldquo;Widely Available&rdquo; (BWA) web features &mdash; supported 30+ months across all major browsers. Feature scores from Web Platform Tests (WPT) via WPT Feature Manifest mapping. 439 of 593 BWA features are measurable; 154 lack WPT mapping (78 JS built-ins tested by test262 not WPT, 23 semantic HTML elements, 53 other &mdash; most likely already supported). FTE-equivalent from per-author commit frequency (1 FTE &asymp; 22 commits/month, capped at 1.0 per person; 115 authors sum to ~13 FTE). BWA growth rate of ~52/year is the 2023&ndash;2025 average, normalized to exclude the 2022 interop spike. Known pipeline: 130 features graduating by 2028. Velocity parity = Servo&rsquo;s annual feature completion rate &ge; BWA annual growth rate. Completions/yr = 22 &times; (FTE/13)<sup>0.7</sup> (sublinear <a href="https://en.wikipedia.org/wiki/Brooks%27s_law">Brooks&rsquo;s Law</a> scaling). Stalled = zero or negative velocity over the full observation period (2023-Q3 to 2026-Q1). Regressions = features that lost &gt;5 percentage points. Cost at &euro;150k/yr average engineering salary only &mdash; excludes other opex, infrastructure, management overhead, benefits loading, and inflation. Usage-prioritized scenarios: at &lt;1% threshold, 35 features deprioritized (target 558, growth ~49/yr); at &lt;5%, 56 features deprioritized (target 537, growth ~47/yr). Data: wpt.fyi, web-features, Servo git history. Full interactive dashboard: dashboard.html.</p> 204 + <p style="font-size:10px;line-height:1.45;color:#666;">Readiness measured against Baseline &ldquo;Widely Available&rdquo; (BWA) web features &mdash; supported 30+ months across all major browsers. Feature scores from Web Platform Tests (WPT) via WPT Feature Manifest mapping. 439 of 593 BWA features are measurable; 154 lack WPT mapping (78 JS built-ins tested by test262 not WPT, 23 semantic HTML elements, 53 other with unknown status). FTE-equivalent from per-author commit frequency (1 FTE &asymp; 22 commits/month, capped at 1.0 per person; 115 authors sum to ~13 FTE). BWA growth rate of ~52/year is the 2023&ndash;2025 average, normalized to exclude the 2022 interop spike. Known pipeline: 130 features graduating by 2028. Velocity parity = Servo&rsquo;s annual feature completion rate &ge; BWA annual growth rate. Completions/yr = 22 &times; (FTE/13)<sup>0.7</sup> (sublinear <a href="https://en.wikipedia.org/wiki/Brooks%27s_law">Brooks&rsquo;s Law</a> scaling). Stalled = zero or negative velocity over the full observation period (2023-Q3 to 2026-Q1). Regressions = features that lost &gt;5 percentage points. Cost at &euro;200k/yr per FTE: &euro;150k European senior SWE median total cost &times; 1.33&times; premium for browser-engine specialization (small talent pool, Rust/rendering/layout) and multi-disciplinary practice (software development + W3C/WHATWG standards participation + open-source community management). Calibrated against <a href="https://nlnet.nl/funding.html">NLnet</a> (&euro;108k), <a href="https://www.sovereign.tech/programs/fellowship">Sovereign Tech Fund</a> (&euro;79&ndash;101k), <a href="https://www.levels.fyi/companies/mozilla/salaries/software-engineer/locations/germany">Mozilla Germany</a> (&euro;145&ndash;164k), and <a href="https://github.com/servo/project/issues/181">Servo grant rates</a> (&euro;248k US contractor). Excludes other opex, infrastructure, management overhead, and inflation. Usage-prioritized scenarios: at &lt;1% threshold, 35 features deprioritized (target 558, growth ~49/yr); at &lt;5%, 56 features deprioritized (target 537, growth ~47/yr). Data: wpt.fyi, web-features, Servo git history. Full interactive dashboard: dashboard.html.</p> 213 205 </div> 206 + 207 + <p style="font-size:9px;line-height:1.45;color:#686868;margin-top:8px;">Thanks to the people who&rsquo;ve reviewed the methodology and approach so far. NOTE: AI was used in the making of this draft report. For suggestions for improvement or spotting of inaccuracies, contact <a href="mailto:dietrich@webtransitions.org">dietrich@webtransitions.org</a>.</p> 214 208 215 209 <div class="footer"> 216 210 Servo Baseline Readiness Evaluation &mdash; Data as of March 2026 &mdash; <a href="https://webtransitions.org">webtransitions.org</a>