roast-my-design-system 9.1.1 → 9.1.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.
package/README.md
CHANGED
|
@@ -63,9 +63,9 @@ This tool draws the map.
|
|
|
63
63
|
|
|
64
64
|
## What you get
|
|
65
65
|
|
|
66
|
-
### Where
|
|
66
|
+
### Where will your agent have to guess?
|
|
67
67
|
|
|
68
|
-
The places where the repo has no answer yet.
|
|
68
|
+
The first thing the report says: the places where the repo has no answer yet, or "No gaps found".
|
|
69
69
|
|
|
70
70
|
- the gap, in one line
|
|
71
71
|
- the files that prove it
|
|
@@ -142,11 +142,11 @@ Eleven reports, hosted exactly as the tool writes them. Every number determinist
|
|
|
142
142
|
|
|
143
143
|
The full report for vercel/ai-chatbot. The verdict answers what the agent will learn here, the gap section comes first, then "What the repo teaches the agent", Claude's read of the scan:
|
|
144
144
|
|
|
145
|
-

|
|
146
146
|
|
|
147
147
|
The same report in light mode (one file, built-in toggle):
|
|
148
148
|
|
|
149
|
-

|
|
150
150
|
|
|
151
151
|
## Why the numbers hold
|
|
152
152
|
|
|
@@ -348,7 +348,7 @@ You get the roast in chat plus `design-system-roast.html` at your repo root, a s
|
|
|
348
348
|
- a **light/dark theme toggle** in one file
|
|
349
349
|
- the usage-weighted palette bar, the grey ramp, the off-scale spacing receipts, the duplicate-component receipts with clickable file paths, and the worst-offenders ledger
|
|
350
350
|
- a **Fix what makes agents guess** list: up to 3 moves derived from your repo's own numbers, each with a file-path receipt
|
|
351
|
-
-
|
|
351
|
+
- **Where will your agent have to guess?** opens the report: the gaps where the repo has no answer yet, with the files that prove each one and the move that closes it, or "No gaps found"
|
|
352
352
|
- **Give the agent the answers**: `design-system-rules.md` wrapped inside the report as a present. Unwrap, then copy or download the agent rules generated from your scan
|
|
353
353
|
|
|
354
354
|
After the roast, the skill offers to write `design-system-rules.md` to disk and merge it into your CLAUDE.md, `.cursor/rules` or AGENTS.md.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "roast-my-design-system",
|
|
3
|
-
"version": "9.1.
|
|
3
|
+
"version": "9.1.2",
|
|
4
4
|
"mcpName": "io.github.gregkozakiewicz/roast-my-design-system",
|
|
5
5
|
"description": "Your AI can write the UI. This makes sure it writes your UI. A deterministic scanner scores your design system 0-100 against 112 public repos, reads React and web components (Stencil, Lit), hands you a copy-paste fix prompt for each top finding, writes rules for Claude, Cursor, Copilot and Windsurf with --apply, and runs as a local MCP server with --mcp.",
|
|
6
6
|
"keywords": [
|
|
@@ -354,13 +354,20 @@ let verdict = noSystemLikely
|
|
|
354
354
|
// The lead line answers the report's first question, where will the agent
|
|
355
355
|
// have to guess, before the measured verdict does. A repo with an answer gets
|
|
356
356
|
// copied; a repo with no answer gets guessed at. A gap named here is one
|
|
357
|
-
// lib/gaps admitted after a fleet probe; nothing else is called a gap.
|
|
357
|
+
// lib/gaps admitted after a fleet probe; nothing else is called a gap. The
|
|
358
|
+
// card never talks about the scan's reach: a reader came for a diagnosis,
|
|
359
|
+
// not for the limits of the instrument (Greg, 28 Sep 2026).
|
|
358
360
|
const gapLead = (noSystemLikely || fresh) ? '' : (() => {
|
|
359
361
|
const gaps = h.gaps ?? [];
|
|
360
|
-
|
|
361
|
-
const named = gaps.map((g) => g.title.charAt(0).toLowerCase() + g.title.slice(1));
|
|
362
|
-
return `${gaps.length === 1 ? 'In one place' : `In ${gaps.length} places`} your repo gives the agent no clear answer: ${esc(named.join('; '))}. Asked to build there, it has to decide for itself.`;
|
|
362
|
+
return gaps.length ? `${gaps.length} gap${gaps.length === 1 ? '' : 's'} found.` : 'No gaps found.';
|
|
363
363
|
})();
|
|
364
|
+
// Under the headline: the condition, and nothing about the scan's reach.
|
|
365
|
+
// What the fixes do to the score is said once, in the fixes section.
|
|
366
|
+
function gapSub() {
|
|
367
|
+
return (h.gaps ?? []).length
|
|
368
|
+
? 'The agent has no clear answer for these parts of the system.'
|
|
369
|
+
: 'Your repo gives the agent a clear answer for every check in this scan.';
|
|
370
|
+
}
|
|
364
371
|
if (bench && findings.length && !fresh) {
|
|
365
372
|
const core = [['colors', tokenLed ? colorStrays : colors.length], ['greys', tokenLed ? greyStrays : greys.length],
|
|
366
373
|
['spacing', spacingTotal], ['typefaces', typefaces.length], ['exactDuplicates', hardDupes.length], ['inlineStyles', inline.count]];
|
|
@@ -1214,9 +1221,9 @@ function whereToStartSection() {
|
|
|
1214
1221
|
for (const item of top3) if (item.metric && item.after !== undefined && item.delta > 0) applied.set(item.metric, item.after);
|
|
1215
1222
|
const after = projectedScore(applied);
|
|
1216
1223
|
startProjection = { count: top3.length, after };
|
|
1217
|
-
const words = ['One
|
|
1224
|
+
const words = ['One fix', 'Two fixes', 'Three fixes'][top3.length - 1];
|
|
1218
1225
|
const head = healthScore !== null && after > healthScore
|
|
1219
|
-
? `${words}
|
|
1226
|
+
? `${words} could raise the design system health score from <b class="proj">${healthScore} to ${after}</b>.`
|
|
1220
1227
|
: `${words} to increase your score.`;
|
|
1221
1228
|
const chip = (item) => item.delta > 0
|
|
1222
1229
|
? `<span class="delta" title="once all of them are done">+${item.delta}</span>`
|
|
@@ -1258,24 +1265,17 @@ function whereToStartSection() {
|
|
|
1258
1265
|
// A gap is a place where the next piece of UI has nothing to reuse (lib/gaps).
|
|
1259
1266
|
// The September 2026 runs showed agents inventing exactly there; the section
|
|
1260
1267
|
// names the gap, the files that prove it and the one move that closes it.
|
|
1261
|
-
function
|
|
1268
|
+
function gapsList() {
|
|
1262
1269
|
if (noSystemLikely || fresh) return '';
|
|
1263
1270
|
const gaps = h.gaps ?? [];
|
|
1264
|
-
if (!gaps.length)
|
|
1265
|
-
|
|
1266
|
-
${sectionHead('Where agents will invent', 'No gap found: the gaps where a design system has no answer yet are all closed here. This scan checks for one kind of gap so far, a chart palette, and this repo either has one or has no charts. The list grows as more gap kinds are measured on real agent runs; a clean result here says the known gaps are closed, and no more than that.')}
|
|
1267
|
-
</section>`;
|
|
1268
|
-
}
|
|
1269
|
-
const head = `The gaps where your design system has no answer yet. ${gaps.length === 1 ? 'One place' : `${gaps.length} places`} where this repo gives an agent nothing to copy; asked to build there, an agent invents, because that is what the repo taught it. Nothing here is a violation: there is no rule yet to break. Define the answer once and every agent after that inherits it.`;
|
|
1270
|
-
return `<section class="glass pad" style="margin-top:16px">
|
|
1271
|
-
${sectionHead('Where agents will invent', head)}
|
|
1272
|
-
<div class="ledger">${gaps.map((g, i) => `
|
|
1271
|
+
if (!gaps.length) return '';
|
|
1272
|
+
return `<div class="ledger gaps-list">${gaps.map((g, i) => `
|
|
1273
1273
|
<div class="ledger-row gap-row">
|
|
1274
1274
|
<span class="ledger-idx">${String(i + 1).padStart(2, '0')}</span>
|
|
1275
1275
|
<div class="start-body"><div class="start-head"><div class="start-title">${esc(g.title)}</div></div><div class="sub">${esc(g.detail)}</div>
|
|
1276
1276
|
<div class="sub" style="margin-top:6px"><b>Close it:</b> ${esc(g.fix)}</div>
|
|
1277
1277
|
${g.files?.length ? `<div class="chips-row" style="margin-top:8px">${g.files.map((f) => `<span class="chip mono">${esc(f)}</span>`).join('')}</div>` : ''}</div>
|
|
1278
|
-
</div>`).join('')}</div
|
|
1278
|
+
</div>`).join('')}</div>`;
|
|
1279
1279
|
}
|
|
1280
1280
|
|
|
1281
1281
|
// ---------- package by package ----------
|
|
@@ -1561,16 +1561,16 @@ function ogTags() {
|
|
|
1561
1561
|
// index of what rendered, and what is not the team's and not counted.
|
|
1562
1562
|
function sidePanel() {
|
|
1563
1563
|
const date = esc((h.harvestedAt ?? '').slice(0, 10));
|
|
1564
|
-
const def = 'How
|
|
1564
|
+
const def = 'How well this repo follows the design system rules Roast checks.';
|
|
1565
1565
|
const lift = startProjection && healthScore !== null && startProjection.after > healthScore
|
|
1566
|
-
? ` <b>${['One fix
|
|
1566
|
+
? ` <b>${['One fix', 'Two fixes', 'Three fixes'][startProjection.count - 1] ?? 'The fixes'} could raise it to ${startProjection.after}.</b>` : '';
|
|
1567
1567
|
const rp = P.shadcn?.registryPaint ?? null;
|
|
1568
1568
|
const bd = breakdown.ownScore !== null && breakdown.installedPoints > 0 && rp
|
|
1569
1569
|
? `<div class="bd">Of which <b>${breakdown.installedPoints} point${breakdown.installedPoints === 1 ? '' : 's'}</b> come from installed code you did not write: ${esc(rp.dirs.map((d) => basename(d)).join(', '))} (${n(rp.files)} file${rp.files === 1 ? '' : 's'}, ${n(rp.tinUses)} palette colour${rp.tinUses === 1 ? '' : 's'}). Your own code alone would score <b>${breakdown.ownScore}</b>. Kept in the score because your agent reads those files like everything else; left out of the fixes because they are not yours to edit.</div>` : '';
|
|
1570
1570
|
const scoreBlock = healthScore !== null
|
|
1571
|
-
? `<div class="score">${eyebrow('
|
|
1571
|
+
? `<div class="score">${eyebrow('Design system health')}<div class="val">${healthScore}<span class="slash">/</span><span class="of">100</span></div><div class="def">${def}${lift}</div>${bd}</div>`
|
|
1572
1572
|
: noSystemLikely
|
|
1573
|
-
? `<div class="score muted">${eyebrow('
|
|
1573
|
+
? `<div class="score muted">${eyebrow('Design system health')}<div class="val">—</div><div class="note">nothing here was measured · see the note</div><div class="def">${def}</div></div>` : '';
|
|
1574
1574
|
const chips = `<div class="chips">${stack.map((c) => `<span class="chip">${esc(c)}</span>`).join('')}${(P.shadcn?.sheet?.tweakcnPresent ?? 0) >= 10 ? '<span class="chip">tweakcn theme</span>' : ''}${P.shadcn?.lint ? '<span class="chip">shadcn/lint</span>' : ''}${dsUnrecognised ? '<span class="chip chip-dim">design system: unrecognised</span>' : ''}${legacyChip ? `<span class="chip chip-dim">${esc(legacyChip)}</span>` : ''}${agentFiles.map((c) => `<span class="chip chip-agent">${esc(c.file)}</span>`).join('')}</div>`;
|
|
1575
1575
|
const facts = [
|
|
1576
1576
|
shadcnReceipt(),
|
|
@@ -1788,6 +1788,7 @@ ${ogTags()}
|
|
|
1788
1788
|
.verdict-card .b2 { left:-40px; bottom:-80px; width:224px; height:224px; background:var(--blob2); filter:blur(48px); }
|
|
1789
1789
|
.verdict { position:relative; font:600 clamp(18px,2.6vw,24px)/1.45 var(--disp); letter-spacing:-.01em; margin-top:10px; }
|
|
1790
1790
|
.verdict-sub { position:relative; margin-top:12px; font-size:14.5px; line-height:1.6; color:var(--dim); }
|
|
1791
|
+
.verdict-card .gaps-list { position:relative; margin-top:18px; }
|
|
1791
1792
|
.gap-empty { padding:0 26px 22px; color:var(--dim); font-size:14px; line-height:1.6; }
|
|
1792
1793
|
.gap-why { margin-top:6px; color:var(--dim); font-size:13.5px; }
|
|
1793
1794
|
|
|
@@ -2112,11 +2113,9 @@ ${sidePanel()}
|
|
|
2112
2113
|
<div class="glass verdict-card">
|
|
2113
2114
|
<div class="blob b1"></div><div class="blob b2"></div>
|
|
2114
2115
|
${eyebrow(noSystemLikely || fresh ? 'Summary' : 'Where will your agent have to guess?')}
|
|
2115
|
-
${gapLead ? `<div class="verdict">${gapLead}</div><div class="verdict-sub">${
|
|
2116
|
+
${gapLead ? `<div class="verdict">${gapLead}</div><div class="verdict-sub">${gapSub()}</div>${gapsList()}` : `<div class="verdict">${esc(verdict)}</div>`}
|
|
2116
2117
|
</div>
|
|
2117
2118
|
|
|
2118
|
-
${gapsSection()}
|
|
2119
|
-
|
|
2120
2119
|
${notesSection()}
|
|
2121
2120
|
|
|
2122
2121
|
${extraSectionsHtml()}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Single version constant for the engine — imported by diagnose (report
|
|
2
2
|
// footer) and rules (generated-by line). This is the bump spot that used to
|
|
3
3
|
// live as a const inside diagnose/index.mjs.
|
|
4
|
-
export const VERSION = '9.1.
|
|
4
|
+
export const VERSION = '9.1.2';
|
|
5
5
|
// The shape of harvest.json and summary.json. Bumped only when a field is
|
|
6
6
|
// renamed, removed or changes meaning; a new field is not a new schema. A
|
|
7
7
|
// tool comparing two scans compares like with like by this number, not by VERSION.
|