adsa-cli 0.1.2 → 0.1.4
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 +94 -11
- package/bin/adsa.mjs +117 -16
- package/lib/badge.mjs +28 -12
- package/lib/config.mjs +123 -47
- package/lib/reference.mjs +32 -0
- package/lib/report.mjs +17 -12
- package/lib/scan.mjs +416 -61
- package/lib/score.mjs +19 -7
- package/lib/target.mjs +82 -0
- package/package.json +1 -1
- package/rubric/reference.json +293 -0
- package/skills/ds-audit/SKILL.md +37 -2
package/lib/config.mjs
CHANGED
|
@@ -3,12 +3,15 @@
|
|
|
3
3
|
* repo is never asked for: the config exists for the handful of things detection
|
|
4
4
|
* gets wrong in a repo laid out unusually.
|
|
5
5
|
*/
|
|
6
|
-
import { join } from "node:path";
|
|
6
|
+
import { basename, dirname, join } from "node:path";
|
|
7
7
|
import { readdirSync } from "node:fs";
|
|
8
|
-
import { exists, isDir, read, readJson } from "./fsx.mjs";
|
|
8
|
+
import { exists, isDir, read, readJson, rel, walk } from "./fsx.mjs";
|
|
9
9
|
|
|
10
10
|
export const CONFIG_NAME = "adsa.config.json";
|
|
11
11
|
|
|
12
|
+
/** Never a workspace package, whatever a glob says. */
|
|
13
|
+
const IGNORED_DIRS = new Set(["node_modules", "dist", "build", "out", ".git", "coverage", "storybook-static"]);
|
|
14
|
+
|
|
12
15
|
export const DEFAULTS = {
|
|
13
16
|
/** Directories that hold component guides, in priority order. */
|
|
14
17
|
guides: null,
|
|
@@ -24,80 +27,153 @@ export const DEFAULTS = {
|
|
|
24
27
|
skip: [],
|
|
25
28
|
};
|
|
26
29
|
|
|
27
|
-
|
|
30
|
+
/** A guide living next to the component it documents: `Button/Button.spec.md`. */
|
|
31
|
+
export const COLOCATED_GUIDE = /\.(spec|docs?|guide)\.mdx?$/i;
|
|
32
|
+
|
|
33
|
+
/** Catch-alls: real guides often live here, but so does everything else. */
|
|
34
|
+
const BROAD_GUIDE_DIRS = new Set(["docs", "documentation"]);
|
|
35
|
+
const GUIDE_DIRS = ["guidelines", "docs/components", "docs/guides", "documentation/components", "www/content", "apps/docs/content", "docs", "documentation"];
|
|
28
36
|
const SOURCE_DIRS = ["src/components", "Sources", "src/main/kotlin", "src", "packages/ui/src", "lib/components", "components"];
|
|
29
37
|
|
|
30
38
|
export function loadConfig(root) {
|
|
31
39
|
const file = readJson(join(root, CONFIG_NAME)) || {};
|
|
32
40
|
const config = { ...DEFAULTS, ...file };
|
|
33
|
-
config.
|
|
34
|
-
config.
|
|
41
|
+
config.guidesExplicit = Boolean(file.guides);
|
|
42
|
+
config.guides = config.guides ? listed(root, config.guides) : defaultGuideDirs(root);
|
|
43
|
+
config.source = config.source ? listed(root, config.source) : defaultSourceDirs(root);
|
|
35
44
|
config.configFile = exists(join(root, CONFIG_NAME)) ? CONFIG_NAME : null;
|
|
36
45
|
return config;
|
|
37
46
|
}
|
|
38
47
|
|
|
39
|
-
function
|
|
40
|
-
const list =
|
|
41
|
-
|
|
42
|
-
// Only the first match from the candidate list, so `docs` does not shadow `guidelines`.
|
|
43
|
-
return value ? found : found.slice(0, 1);
|
|
48
|
+
function listed(root, value) {
|
|
49
|
+
const list = Array.isArray(value) ? value : [value];
|
|
50
|
+
return list.filter((d) => isDir(join(root, d)));
|
|
44
51
|
}
|
|
45
52
|
|
|
46
53
|
/**
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
54
|
+
* Every specific guide directory that exists — a repo can keep `guidelines/` and
|
|
55
|
+
* `docs/components/` and mean both. `docs/` and `documentation/` are catch-alls, so
|
|
56
|
+
* they are only believed when nothing more specific was found.
|
|
57
|
+
*/
|
|
58
|
+
export function defaultGuideDirs(root) {
|
|
59
|
+
const found = GUIDE_DIRS.filter((d) => isDir(join(root, d)));
|
|
60
|
+
const specific = found.filter((d) => !BROAD_GUIDE_DIRS.has(d));
|
|
61
|
+
return specific.length ? specific : found.slice(0, 1);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function defaultSourceDirs(root) {
|
|
65
|
+
// A registry is a distribution format, not a folder somebody happened to name that:
|
|
66
|
+
// `registry.json` is the manifest that says so, and the components it ships are the
|
|
67
|
+
// system. The app's own `components/` is the site's chrome and would win otherwise.
|
|
68
|
+
if (exists(join(root, "registry.json")) && isDir(join(root, "registry"))) return ["registry"];
|
|
69
|
+
|
|
70
|
+
return SOURCE_DIRS.filter((d) => isDir(join(root, d))).slice(0, 1);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* The monorepo root that declares `pkgDir` as one of its own workspaces, or null.
|
|
50
75
|
*
|
|
51
|
-
*
|
|
76
|
+
* This is the only ancestor whose AGENTS.md, CI and agent surface belong to the
|
|
77
|
+
* package being audited. An ancestor that merely happens to contain the directory —
|
|
78
|
+
* a design system vendored inside an unrelated repository, a fixture inside this
|
|
79
|
+
* one — declares nothing, and lending it its parent's files would invent a score.
|
|
52
80
|
*/
|
|
53
|
-
export function
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const candidates = [];
|
|
61
|
-
for (const pattern of patterns) {
|
|
62
|
-
for (const dir of expand(root, pattern)) {
|
|
63
|
-
const p = readJson(join(dir, "package.json"));
|
|
64
|
-
if (!p || p.private === true) continue;
|
|
65
|
-
const guides = countGuides(dir);
|
|
66
|
-
const exports_ = Object.keys(p.exports || {}).filter((k) => k.startsWith("./")).length;
|
|
67
|
-
const score = guides * 3 + exports_;
|
|
68
|
-
if (score > 0) candidates.push({ dir, name: p.name || dir, score, guides, exports: exports_ });
|
|
69
|
-
}
|
|
81
|
+
export function resolveRepoRoot(pkgDir) {
|
|
82
|
+
let dir = dirname(pkgDir);
|
|
83
|
+
for (let i = 0; i < 8; i++) {
|
|
84
|
+
const parent = dirname(dir);
|
|
85
|
+
if (declaresWorkspace(dir, pkgDir)) return dir;
|
|
86
|
+
if (parent === dir) return null;
|
|
87
|
+
dir = parent;
|
|
70
88
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Every workspace directory `root` declares, absolute. Empty when it declares none. */
|
|
93
|
+
export function workspaceDirs(root) {
|
|
94
|
+
const { include, exclude } = workspacePatterns(root, readJson(join(root, "package.json")));
|
|
95
|
+
const excluded = new Set(exclude.flatMap((pattern) => expand(root, pattern)));
|
|
96
|
+
return [...new Set(include.flatMap((pattern) => expand(root, pattern)))].filter((dir) => !excluded.has(dir));
|
|
74
97
|
}
|
|
75
98
|
|
|
99
|
+
function declaresWorkspace(root, pkgDir) {
|
|
100
|
+
return workspaceDirs(root).includes(pkgDir);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* The workspace globs a repository declares, negations kept: `!**\/fixtures/**` is
|
|
105
|
+
* how a repo says a directory full of package.json files is not a package.
|
|
106
|
+
*
|
|
107
|
+
* The pnpm file is read as its own `packages:` block rather than as every list item
|
|
108
|
+
* in the document — `onlyBuiltDependencies` is a list of dependency names, and
|
|
109
|
+
* reading it as workspace globs invents packages the repo does not have.
|
|
110
|
+
*/
|
|
76
111
|
function workspacePatterns(root, pkg) {
|
|
77
112
|
const fromPkg = Array.isArray(pkg?.workspaces) ? pkg.workspaces : pkg?.workspaces?.packages || [];
|
|
78
113
|
const yaml = read(join(root, "pnpm-workspace.yaml")) || "";
|
|
79
|
-
|
|
80
|
-
|
|
114
|
+
// Everything indented under `packages:`, comments and blank lines included — a
|
|
115
|
+
// comment between two entries used to end the list, and half the globs vanished.
|
|
116
|
+
const block = (yaml.match(/^packages:[ \t]*\n((?:(?:[ \t]+[^\n]*)?\n)*)/m) || [, ""])[1];
|
|
117
|
+
const fromYaml = [...block.matchAll(/^\s*-\s*["']?([^"'\n]+)["']?/gm)].map((m) => m[1].trim());
|
|
118
|
+
const all = [...new Set([...fromPkg, ...fromYaml])].filter(Boolean);
|
|
119
|
+
return { include: all.filter((g) => !g.startsWith("!")), exclude: all.filter((g) => g.startsWith("!")).map((g) => g.slice(1)) };
|
|
81
120
|
}
|
|
82
121
|
|
|
83
122
|
/** Only the `dir/*` and `dir` shapes real workspace globs use. */
|
|
123
|
+
/**
|
|
124
|
+
* A workspace glob as the package managers read it, segment by segment: `packages/*`,
|
|
125
|
+
* `packages/**`, `packages/*\/*` for a nested layout, `packages/@scope/*` for a scope
|
|
126
|
+
* folder. Reading only the first segment before the star — what this used to do —
|
|
127
|
+
* returns the scope folders themselves, which have no package.json, so a repo like
|
|
128
|
+
* Mantine or Radix looked like a repo with no packages at all.
|
|
129
|
+
*/
|
|
84
130
|
function expand(root, pattern) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
131
|
+
let dirs = [root];
|
|
132
|
+
for (const segment of pattern.split("/").filter((s) => s && s !== ".")) {
|
|
133
|
+
const next = [];
|
|
134
|
+
for (const dir of dirs) {
|
|
135
|
+
if (segment === "**") next.push(dir, ...descend(dir, 2));
|
|
136
|
+
else if (segment.includes("*")) next.push(...children(dir).filter((d) => segmentMatch(segment, basename(d))));
|
|
137
|
+
else if (isDir(join(dir, segment))) next.push(join(dir, segment));
|
|
138
|
+
}
|
|
139
|
+
dirs = [...new Set(next)];
|
|
140
|
+
if (dirs.length > 4000) break;
|
|
141
|
+
}
|
|
142
|
+
return dirs;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function children(dir) {
|
|
89
146
|
try {
|
|
90
|
-
return readdirSync(
|
|
91
|
-
.filter((e) => e.isDirectory() && !e.name.startsWith("."))
|
|
92
|
-
.map((e) => join(
|
|
147
|
+
return readdirSync(dir, { withFileTypes: true })
|
|
148
|
+
.filter((e) => e.isDirectory() && !e.name.startsWith(".") && !IGNORED_DIRS.has(e.name))
|
|
149
|
+
.map((e) => join(dir, e.name));
|
|
93
150
|
} catch {
|
|
94
151
|
return [];
|
|
95
152
|
}
|
|
96
153
|
}
|
|
97
154
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
155
|
+
/** Every directory under `dir`, `depth` levels down. `**` in a glob means this. */
|
|
156
|
+
function descend(dir, depth, level = 0, out = []) {
|
|
157
|
+
if (level >= depth) return out;
|
|
158
|
+
for (const child of children(dir)) {
|
|
159
|
+
out.push(child);
|
|
160
|
+
descend(child, depth, level + 1, out);
|
|
101
161
|
}
|
|
102
|
-
return
|
|
162
|
+
return out;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function segmentMatch(segment, name) {
|
|
166
|
+
return new RegExp("^" + segment.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*") + "$").test(name);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* How many guides this package actually has. The presence of a `docs/` folder says
|
|
171
|
+
* nothing — a package with one README-shaped page and a package with ninety component
|
|
172
|
+
* guides both used to score 1, and the wrong one won.
|
|
173
|
+
*/
|
|
174
|
+
export function countGuides(dir) {
|
|
175
|
+
let n = 0;
|
|
176
|
+
for (const d of defaultGuideDirs(dir)) n += walk(join(dir, d), [".md", ".mdx"], 6).length;
|
|
177
|
+
for (const s of defaultSourceDirs(dir)) n += walk(join(dir, s), [".md", ".mdx"], 6).filter((f) => COLOCATED_GUIDE.test(f)).length;
|
|
178
|
+
return n;
|
|
103
179
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The measured field. A score out of 45 means nothing on its own — the question a
|
|
3
|
+
* reader always asks first is "is that good?" — so every place a score is shown can
|
|
4
|
+
* answer it with the same public design systems, audited at a named commit.
|
|
5
|
+
*
|
|
6
|
+
* This is not a ranking of design systems. It measures one thing: what a coding agent
|
|
7
|
+
* can find in the repository. A system whose documentation lives on a website scores
|
|
8
|
+
* low here and may still be a fine design system for people.
|
|
9
|
+
*/
|
|
10
|
+
import { readFileSync } from "node:fs";
|
|
11
|
+
import { fileURLToPath } from "node:url";
|
|
12
|
+
import { dirname, join } from "node:path";
|
|
13
|
+
|
|
14
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
15
|
+
export const REFERENCE = JSON.parse(readFileSync(join(here, "..", "rubric", "reference.json"), "utf8"));
|
|
16
|
+
|
|
17
|
+
/** Where a score sits in the field: how many of the reference systems it beats. */
|
|
18
|
+
export function standing(total) {
|
|
19
|
+
const systems = REFERENCE.systems;
|
|
20
|
+
const below = systems.filter((s) => s.total < total).length;
|
|
21
|
+
const best = systems[0];
|
|
22
|
+
return {
|
|
23
|
+
count: systems.length,
|
|
24
|
+
below,
|
|
25
|
+
best,
|
|
26
|
+
median: systems[Math.floor(systems.length / 2)].total,
|
|
27
|
+
sentence:
|
|
28
|
+
total >= best.total
|
|
29
|
+
? `${total}/45 is at or above ${best.name} (${best.total}), the highest of the ${systems.length} public design systems measured with this rubric.`
|
|
30
|
+
: `${total}/45 sits above ${below} of the ${systems.length} public design systems measured with this rubric; ${best.name} leads at ${best.total}.`,
|
|
31
|
+
};
|
|
32
|
+
}
|
package/lib/report.mjs
CHANGED
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
* against frozen real audits, and ported back here as a copy.
|
|
11
11
|
*/
|
|
12
12
|
import { RUBRIC } from "./score.mjs";
|
|
13
|
-
import { badgeColor, badgeMarkdown } from "./badge.mjs";
|
|
13
|
+
import { band as scoreBand, badgeColor, badgeMarkdown } from "./badge.mjs";
|
|
14
|
+
import { standing } from "./reference.mjs";
|
|
14
15
|
|
|
15
16
|
/** What the accessibility dimension is called on each platform. */
|
|
16
17
|
const A11Y_STAT_LABEL = {
|
|
@@ -30,16 +31,14 @@ const PLATFORM_LABEL = {
|
|
|
30
31
|
const MARK = `<svg class="mark" viewBox="0 0 214 135" fill="currentColor" aria-hidden="true"><path d="M211.6 71C211.3 71.1 210.8 71.1 210.5 71.1C210.1 71.1 209.9 71.2 209.8 71.6C208.4 78.1 206.1 82.6 201.9 86.9C196.9 92.3 190.7 95.4 183.8 96.1C181.2 96.4 180.3 96.6 179.1 97.3C176.7 98.6 175.3 100.8 175 103.8C174.5 108.8 173.8 111.7 172.2 114.9C169.5 120.4 165 124.9 159.5 127.7C156.5 129.2 154 130 150 130.9L148.5 131.2L148.6 132.3L148.6 133.5L150 133.4C150.7 133.3 152.1 133.1 153 132.9C163.5 130.5 172 123.3 175.7 113.7C176.9 110.7 177.4 108.3 177.7 104.8C177.9 102.3 178.2 101.6 179.4 100.4C180.5 99.4 181.2 99.1 183.3 98.9C194.4 98 204.5 91.1 209.6 80.8C210.9 78.2 212.2 73.7 212.2 71.7L212.2 70.9L211.6 71Z"/> <path fill-rule="evenodd" clip-rule="evenodd" d="M182.5 58.5C185.2 59.4 187.4 61.6 188.3 64.4C188.9 65.9 188.9 68.8 188.3 70.4C187.8 71.8 186.9 73.2 185.8 74.2C184.1 75.9 182.5 76.5 179.1 76.9C174.8 77.3 171.3 78.4 167.6 80.5C161.8 83.8 157.4 89 155.4 95.1C154.6 97.4 154.3 99.2 154.1 101.9C154 103.1 153.9 104.7 153.7 105.4C152.9 108.8 149.8 112 146.4 112.8C145.3 113 142.7 113 141.5 112.8C138.8 112.2 136.1 110.2 134.8 107.8C134 106.1 133.6 104.7 133.5 102.3C133.1 96.5 130.9 91.1 126.9 86.4C123.8 82.8 119.1 79.8 114.1 78.2C103.7 74.8 92 77.5 85 84.9C81.1 88.9 78.8 94.6 78.8 99.8C78.8 102.8 77.8 105.3 75.9 107.1C74.1 108.9 72.3 109.7 69.6 109.9C66.3 110.1 63.7 109.1 61.7 107.1C60 105.4 59.3 103.8 58.8 100.5C58.1 96.6 56.9 93.6 54.5 90C53.1 87.8 49.4 84.2 47.1 82.7C41.9 79.2 36.7 77.5 30.3 77.1C28.5 77 26.6 76.9 26.2 76.8C23.2 76 20.6 73.4 19.9 70.7C19.5 69.2 19.5 66.8 20 65.3C20.5 63.6 21.7 61.9 23.2 60.8C25.1 59.5 26.3 59.1 30.3 58.9C34.1 58.7 36.2 58.3 39.5 57.1C49.4 53.4 56.6 45.2 58 35.9C58.7 31.9 59.5 30 61.5 28.2C63.4 26.5 65.4 25.8 68.2 25.8C71.2 25.8 73.3 26.6 75.3 28.5C77.2 30.4 78 32.2 78.2 35.7C78.3 37.1 78.5 38.9 78.7 39.7C79.2 41.5 80.3 44.2 81.3 45.9C84.8 51.6 91.2 55.8 99 57.5C100.7 57.8 101.6 57.9 104.5 57.9C108.5 57.9 110.4 57.6 114.1 56.4C122.6 53.6 129.6 47 132.4 39C133.2 36.7 133.5 34.9 133.7 31.8C133.9 30 134 28.7 134.3 27.9C135.7 23.7 139.8 21.1 144.3 21.5C147.1 21.7 149 22.7 150.8 24.6C152.8 26.7 153.4 28.8 153.4 32.8C153.5 35.5 153.8 37.8 154.5 39.8C156.9 46.6 161.5 51.7 168.1 54.9C171.8 56.8 175.1 57.7 179.3 58C180.6 58.1 182 58.3 182.5 58.5ZM184.8 69.4L185.9 70L187 70.5L186.7 71.2C186.1 72.7 184.6 74.1 182.8 75C182 75.4 181.1 75.5 179 75.7C173.6 76.3 169.4 77.9 164.7 81C162.4 82.6 159.2 85.9 157.6 88.1C154.6 92.7 153.4 96.3 152.9 102.9C152.8 104.3 152.6 105.5 152.3 106.2C151.5 108.3 149.3 110.6 147.7 111C147.1 111.2 147.1 111.2 146.6 110.1C146.3 109.6 146.2 109.1 146.3 109C146.4 109 146.9 108.6 147.6 108.1C148.4 107.5 148.8 107.1 149.3 106.1C149.9 104.8 149.9 104.7 150.4 99.8C151.1 93.1 154.2 87 159.5 81.9C164.6 77 171.2 73.9 178.4 73.1C179.8 72.9 181.1 72.7 181.5 72.5C182.6 72.1 183.7 71.2 184.3 70.3L184.8 69.4ZM181.9 59.5C183.9 60.1 185.6 61.5 186.6 63.4C186.9 64 186.8 64.1 185.7 64.7L184.8 65.2L184.1 64.3C182.7 62.5 181.6 62 178.7 61.8C170.5 61.1 163.1 57.7 157.7 52.1C155.5 49.8 153.9 47.7 152.6 45.2C150.4 40.8 149.9 38.7 149.7 33.7C149.4 28.8 149 27.6 146.7 26.1C146.1 25.7 145.7 25.3 145.7 25.2C145.7 25.1 145.9 24.7 146.3 24.2L146.8 23.3L147.5 23.6C148.7 24.1 149.7 24.9 150.4 25.9C152 28 152.3 29 152.4 33.4C152.5 36.8 152.9 38.8 154 41.6C157.9 51.2 168.1 58.4 178.8 59C179.8 59.1 181.2 59.3 181.9 59.5ZM182.5 64.2C182.8 64.5 183.3 65.2 183.5 65.7C184.3 67.2 184 68.8 182.8 70.2C181.8 71.3 180.7 71.8 178.3 72C175.6 72.3 173.9 72.6 171.2 73.6C160 77.3 151.9 86.2 149.7 97.2C149.5 98.2 149.2 100.2 149.1 101.6C148.9 104.5 148.6 105.6 147.5 106.7C145.1 109.2 140.7 108.5 139.2 105.3C138.8 104.6 138.6 103.9 138.5 102C138.1 97.9 137.4 94.9 135.9 91.5C132.1 82.9 125.1 76.6 115.8 73.6C111.6 72.2 110.2 72 105 71.9C100 71.9 98.4 72.2 94.5 73.4C85.9 76.2 79.3 82 75.9 89.8C74.7 92.7 74.1 95.2 73.8 99C73.6 102.1 73.3 102.9 72.1 104C70.1 105.7 66.9 105.5 65.2 103.7C64.3 102.7 64 102 63.7 99.8C62.7 93.4 59.2 86.8 54.2 82.1C47.8 76.1 39.8 72.7 30.7 72.2C28 72.1 27.3 72 26.7 71.7C25.1 70.9 24.2 69.1 24.4 67.5C24.6 66.4 25.5 65.1 26.6 64.5C27.4 64 27.6 64 30.7 63.9C35.5 63.7 39.3 62.8 43.7 60.7C52.1 56.9 58.6 50.1 61.6 42.1C62.3 40 62.7 38.4 63.1 35.8C63.4 33.6 63.8 32.7 64.8 31.8C65.9 30.9 66.7 30.6 68.2 30.6C69.4 30.6 69.8 30.7 70.6 31.2C72.4 32.2 73 33.4 73.3 36.6C73.5 39.4 73.9 41.3 74.8 43.7C76.2 47.6 78.3 50.8 81.3 53.7C91.1 63.3 107.2 65.6 120.2 59.2C126.9 55.9 132.2 50.7 135.5 44.2C137.4 40.5 138.4 37 138.7 32.5C138.8 29.7 139.1 28.7 140.2 27.7C141.1 26.8 142.2 26.3 143.4 26.3C144.9 26.3 145.7 26.6 146.8 27.6C148.2 28.9 148.4 29.4 148.5 33.6C148.7 37.8 149.2 40.2 150.6 43.4C154.8 53.6 165 61.1 176.5 62.6C177.7 62.8 179 62.9 179.5 62.9C180.4 62.9 181.8 63.5 182.5 64.2ZM139.6 107.8C140.2 108.3 140.9 108.8 141.1 108.9C141.5 109 141.5 109 141 110C140.7 110.6 140.4 111.1 140.3 111.1C139.7 111.1 138 110 137.1 109.1C135.4 107.2 134.9 105.9 134.6 102.1C133.7 92.8 129.3 85.5 121.6 80.5C118.6 78.6 114.3 76.8 110.5 76.1C107.9 75.5 101.7 75.6 99.1 76.2C93.1 77.5 88.6 79.8 84.8 83.6C82.6 85.8 81.2 87.7 80 90.3C78.5 93.5 77.9 95.8 77.6 100C77.5 102.4 77.4 102.7 76.8 104C76.1 105.4 74.8 106.9 73.6 107.6C72.8 108 71.7 108.3 71.8 108.1C71.9 108 71.7 107.5 71.5 107L71.1 106.1L72.1 105.3C73.4 104.5 74.3 103.3 74.6 102C74.7 101.5 74.8 100.2 74.9 99.1C75.4 90.5 79.8 83 87.3 77.9C88.8 76.9 92.2 75.3 94.3 74.6C101.3 72.3 108.4 72.3 115.5 74.6C123.8 77.3 130.7 83.2 134.3 90.7C136.2 94.5 136.9 97.3 137.4 102.2C137.7 105.4 138.1 106.3 139.6 107.8ZM140 23.3L140.7 24.3L141.3 25.3L140.7 25.8C138.7 27.3 137.7 29 137.7 30.9C137.7 32.7 137.3 35.7 136.8 37.8C134.8 45.8 129.2 52.9 121.6 57.2C118.1 59.2 114.4 60.6 110 61.3C107.8 61.7 101.9 61.8 99.7 61.4C92.7 60.3 86.3 57.2 81.9 52.8C77.5 48.3 74.9 42.8 74.4 36.8C74.3 35.5 74.1 34.1 74 33.6C73.7 32.5 72.6 31.2 71.4 30.3C70.4 29.7 70.3 29.6 70.5 29.4C70.7 29.2 70.8 29 70.8 28.9C70.8 28.8 71 28.5 71.3 28.1L71.7 27.6L72.8 28.1C74.1 28.8 75.6 30.4 76.3 31.9C76.8 32.9 76.9 33.6 77.1 35.1C77.5 40 78.1 42.2 79.6 45C81.5 48.5 83.5 50.8 86.5 53.1C92.3 57.4 99.7 59.6 106.9 58.9C111.8 58.5 115.7 57.3 120.1 54.9C125.1 52.2 129.6 47.5 132.1 42.4C133.8 38.8 134.6 35.8 134.8 32.1C134.9 29.6 135.1 28.5 135.8 27.2C136.4 25.9 137.9 24.4 139.1 23.8L140 23.3ZM62.7 100.2C63 102.8 63.8 104.3 65.5 105.4C66 105.8 66.4 106.1 66.4 106.1C66.4 106.2 65.5 107.8 65.4 108C65.2 108.3 63.2 107.1 62.4 106.1C60.9 104.6 60.3 103.2 59.8 100.3C59.3 97.3 58.6 95.1 57.1 92.3C55.7 89.5 54.1 87.4 51.5 84.9C48.2 81.7 44.1 79.2 39.5 77.7C36.4 76.7 33.9 76.2 30.3 76C27 75.8 26.1 75.7 24.8 75C23.9 74.5 22.3 73 21.9 72.2C21.5 71.4 21.5 71.3 22.9 70.5L23.6 70.1L24.1 70.9C25.4 72.6 26.5 73.1 29.7 73.3C34.8 73.5 38.5 74.3 42.5 75.9C48.7 78.4 53.9 82.5 57.6 87.7C60.2 91.4 62.1 96.2 62.7 100.2ZM64.1 27.9C64.7 27.7 64.7 27.8 65.2 28.7C65.6 29.2 65.8 29.7 65.8 29.7C65.8 29.7 65.2 30.1 64.6 30.6C63.1 31.7 62.3 33.1 62.1 35.5C61.4 41.3 58.5 47.4 54.1 52C50.2 56.1 45.5 59.1 40.1 61C36.7 62.2 34.6 62.6 30.9 62.7C26.6 62.9 25.5 63.4 24.1 65.3C23.8 65.8 23.5 66.2 23.4 66.2C23.3 66.2 22.9 65.8 22.4 65.4C21.8 64.8 21.7 64.6 21.8 64.2C22 63.4 23.7 61.7 24.9 61.1C26.3 60.3 27.3 60.1 30.5 60C34.9 59.9 38.5 59 42.7 57C49 54 53.8 49.3 56.8 43.4C57.7 41.6 58.7 38.5 59 36.9C59.1 36.2 59.3 35.1 59.4 34.4C59.5 33.7 59.8 32.7 60 32.2C60.7 30.3 62.6 28.3 64.1 27.9Z"/> <path d="M141.7 131.3C141.5 131.2 140.4 131 139.1 130.7C129.3 128.5 121.4 122.8 117.3 114.7C115.5 111.4 114.6 108.4 114.1 104.6C113.8 102.2 113.5 101.3 112.8 100.1C110.1 95.9 104 95.2 100.5 98.8C99.2 100.2 98.7 101.4 98.3 103.9C97.8 108 96.6 112 94.9 115.1C90.4 123.2 82.6 128.8 72.7 130.9L71.2 131.2L71.3 131.9C71.5 133.4 71.5 133.5 72.4 133.4C72.8 133.4 74.1 133.2 75.2 133C80.6 131.8 85.4 129.3 90 125.5C95.9 120.5 100.1 112.7 101 105.1C101.2 102.8 101.6 101.8 102.3 100.9C104.1 98.8 107.1 98.6 109.3 100.3C110.5 101.3 111.1 102.5 111.4 104.9C112 109.9 113.7 114.7 116.7 119.2C118.6 122.1 122.4 125.8 125.4 127.8C129.1 130.3 133.8 132.3 137.7 133.1C140.1 133.6 141.4 133.6 141.6 133.1C141.9 132.1 141.9 131.4 141.7 131.3Z"/> <path fill-rule="evenodd" clip-rule="evenodd" d="M213.6 65.3C213.1 60.4 211.3 55.6 208.5 51.2C206.6 48.3 204.7 46.1 202.1 43.8C196.2 38.7 188.9 35.3 181.8 34.5C179.7 34.2 178.6 33.7 177.9 32.7C177.3 31.9 177.3 31.8 177 28.3C176.4 21.5 174.3 16.1 170.3 11.2C167 7.2 162.1 3.7 156.8 1.9C151.1 -0.2 143.5 -0.6 136.5 0.8C128.2 2.5 120.7 7.4 115.7 14.4C112.5 18.9 110.3 24.9 109.7 30.3C109.6 32 109.4 32.6 108.6 33.5C107 35.4 103.8 35.4 102.1 33.5C101.4 32.7 101.2 32.1 100.9 30C100 22.5 96.6 15.8 91.1 10.6C82.7 2.5 71.1 -0.8 59.4 1.5C55.5 2.3 50.9 4.2 47.6 6.3C39.4 11.7 34 20.7 33.3 30.1C33.2 32.4 33 33 32.2 34C31.2 35 30.6 35.2 28.4 35.6C21.2 36.6 14.9 39.7 9.7 45C6.8 47.9 5.1 50.1 3.4 53.4C2 56.2 1.1 58.8 0.4 61.6C0 63.4 -0 64.1 0 67.9C0 71.5 0.1 72.4 0.4 74C3 85.7 11.8 95.2 23.7 99.4C25.9 100.1 29.2 100.9 31.4 101.2C33.2 101.4 34.4 102 35.1 103.1C35.5 103.8 35.6 104.2 35.8 106C36 108.9 36.2 110.6 36.9 113.1C39.3 122.7 46.4 130.2 56.2 133.5C59.5 134.6 62.2 135 66.3 135C74.5 135 81.2 133.1 87.5 128.8C95.8 123.2 101.1 114.4 102.2 104.3C102.5 101.5 104.1 100.1 106.5 100.3C108.7 100.5 109.9 102 110.2 104.7C111.6 116.4 118.3 125.8 129 131.2C134.2 133.8 138.7 134.8 144.8 134.8C150.9 134.8 155.4 133.8 160.6 131.3C171.3 126.2 177.9 116.5 178.8 104.7C178.9 102.8 179.3 101.9 180.3 101.1C181.1 100.4 181.7 100.2 183.6 100C185.7 99.8 188.7 99.2 190.7 98.6C193.2 97.7 197.1 95.8 199.4 94.2C201.7 92.6 205 89.6 206.7 87.4C210.2 83.1 212.6 77.7 213.3 72.6C213.6 70.7 213.7 67.2 213.6 65.3ZM210.5 71.1C210.8 71.1 211.3 71.1 211.6 71L212.2 70.9L212.2 71.7C212.2 73.7 210.9 78.2 209.6 80.8C204.5 91.1 194.4 98 183.3 98.9C181.2 99.1 180.5 99.4 179.4 100.4C178.2 101.6 177.9 102.3 177.7 104.8C177.4 108.3 176.9 110.7 175.7 113.7C172 123.3 163.5 130.5 153 132.9C152.1 133.1 150.7 133.3 150 133.4L148.6 133.5L148.6 132.3L148.5 131.2L150 130.9C154 130 156.5 129.2 159.5 127.7C165 124.9 169.5 120.4 172.2 114.9C173.8 111.7 174.5 108.8 175 103.8C175.3 100.8 176.7 98.6 179.1 97.3C180.3 96.6 181.2 96.4 183.8 96.1C190.7 95.4 196.9 92.3 201.9 86.9C206.1 82.6 208.4 78.1 209.8 71.6C209.9 71.2 210.1 71.1 210.5 71.1ZM196.9 41.3C204.3 46.1 209.5 53 211.6 60.7C211.8 61.7 212 62.8 212 63.2C212 63.9 212 63.9 211.4 63.9C211 63.9 210.5 64 210.2 64.1C209.8 64.2 209.8 64.2 209.6 63.4C208.3 58.2 206.1 53.9 202.7 49.9C197.7 44.1 190.4 39.9 183.1 38.7C181.9 38.5 180.4 38.2 179.8 38.1C177.4 37.7 175.1 35.9 174 33.6C173.3 32.3 173.3 32.1 173.1 29.5C172.7 22 170.4 16.7 165.5 11.8C161.4 7.7 156.6 5.2 150.8 4.2C149.6 3.9 148.4 3.7 148.2 3.7C147.8 3.6 147.8 3.5 148 3C148.1 2.6 148.1 2.1 148.1 1.8L148.1 1.3L149.9 1.4C154.5 1.7 159.9 3.9 164.5 7.2C166.2 8.4 169.3 11.6 170.6 13.4C172.8 16.5 174.5 20.3 175.2 23.9C175.7 26 175.8 26.9 176 29.8C176.1 31.7 176.2 32.1 176.7 32.9C177.7 34.6 178.7 35.2 181.9 35.6C187.5 36.4 192.2 38.2 196.9 41.3ZM206.9 58.8C207.6 60.4 208.5 63.6 208.7 65.1C208.7 65.4 208.7 67 208.7 68.7C208.7 71.2 208.6 72.1 208.2 73.7C206.2 81.5 200.5 88.5 193.1 92.2C189.8 93.9 186.7 94.8 182.9 95.1C181.9 95.2 180.6 95.5 180 95.7C177.7 96.4 175.4 98.6 174.5 101C174.2 101.7 174 102.8 173.9 104.3C173.6 108.5 172.5 112.1 170.8 115.4C166.8 122.8 159.1 128.1 150.1 129.7C148.2 130 147.4 130.1 144.2 130C140 129.9 138.9 129.7 135.4 128.5C130.3 126.8 125.5 123.7 122.2 120C118.8 116.2 116.2 110.8 115.5 106C115.3 104.9 115.1 103.4 115 102.7C114.4 99.4 111.7 96.5 108.4 95.6C104.2 94.5 100.1 96.4 98.2 100.3C97.7 101.4 97.5 102.1 97.2 103.9C96.7 108 95.6 111.5 93.8 114.8C89.7 122.4 81.3 128.2 72.5 129.7C66.5 130.8 61.8 130.4 56.9 128.5C47.4 124.8 41.6 117 40.8 106.9C40.6 103.5 40.2 102.1 39.3 100.7C37.8 98.4 35.5 96.8 32.9 96.5C29.9 96 28.1 95.6 26.2 95C15.5 91.6 7.2 82.7 5.1 72.3C4.6 69.7 4.6 65.5 5.2 62.9C7.1 54.3 12.8 47 20.7 43C23 41.9 26 40.8 28 40.6C28.9 40.4 30.1 40.3 30.7 40.2C33.4 39.8 36.2 37.6 37.4 35C37.9 33.9 38.1 33.4 38.2 31.4C38.4 28.7 38.9 25.8 39.6 23.8C43.3 13.7 52.9 6.7 64.5 5.6C73.1 4.9 83 8.8 89 15.4C90.7 17.2 92.3 19.6 93.4 21.9C95 25.3 95.6 27.3 96.2 31.7C96.3 32.4 96.6 33.6 96.8 34.1C97.6 36.4 100 38.6 102.4 39.4C104.2 40.1 106.8 40 108.4 39.4C112.2 38 114.3 35.1 114.7 30.7C114.9 27.5 115.8 24.4 117.4 21.1C121.9 11.9 130.8 6 142 4.9C150.8 4 159 6.8 164.7 12.6C167.6 15.5 169.5 18.4 170.7 22.1C171.4 24.1 172 27.6 172 29.3C172 32.4 172.8 34.5 174.7 36.5C176.2 38.1 178 39 180 39.3C180.8 39.4 182.3 39.6 183.3 39.8C193.5 41.7 203.1 49.4 206.9 58.8ZM139.1 130.7C140.4 131 141.5 131.2 141.7 131.3C141.9 131.4 141.9 132.1 141.6 133.1C141.4 133.6 140.1 133.6 137.7 133.1C133.8 132.3 129.1 130.3 125.4 127.8C122.4 125.8 118.6 122.1 116.7 119.2C113.7 114.7 112 109.9 111.4 104.9C111.1 102.5 110.5 101.3 109.3 100.3C107.1 98.6 104.1 98.8 102.3 100.9C101.6 101.8 101.2 102.8 101 105.1C100.1 112.7 95.9 120.5 90 125.5C85.4 129.3 80.6 131.8 75.2 133C74.1 133.2 72.8 133.4 72.4 133.4C71.5 133.5 71.5 133.4 71.3 131.9L71.2 131.2L72.7 130.9C82.6 128.8 90.4 123.2 94.9 115.1C96.6 112 97.8 108 98.3 103.9C98.7 101.4 99.2 100.2 100.5 98.8C104 95.2 110.1 95.9 112.8 100.1C113.5 101.3 113.8 102.2 114.1 104.6C114.6 108.4 115.5 111.4 117.3 114.7C121.4 122.8 129.3 128.5 139.1 130.7ZM139.9 1.5C140.7 1.5 140.7 1.5 140.8 2.2C140.9 3.4 140.9 3.8 140.9 3.8C140.6 3.8 136 4.8 135 5.1C127 7.4 120.2 13.1 116.5 20.6C114.8 23.9 114.1 26.6 113.6 30.3C113.4 32.4 113 33.9 112.5 34.7C110.6 37.9 106.9 39.5 103.5 38.6C101.1 38 99 36.3 98.1 34.3C97.6 33.3 97.4 32.7 96.9 29.2C95.9 22.9 92.6 16.9 87.6 12.5C83.4 8.8 77.9 6.1 71.7 4.8L70.3 4.5L70.5 3.9C71.1 2.1 70.9 2.2 72.2 2.4C75.2 2.7 80.3 4.4 83.4 6.2C92.7 11.5 98.6 20 99.9 30.4C100.2 32.7 100.6 33.5 101.6 34.5C103.2 36.1 105.5 36.5 107.5 35.6C109.4 34.8 110.8 32.7 110.8 30.7C110.8 29.7 111.3 26.8 111.8 25C113.3 19.6 116 15 120.1 11C122.9 8.2 125.2 6.5 128.5 4.8C132.3 2.9 137.2 1.5 139.9 1.5ZM62.3 131.2C63.5 131.4 64.4 131.6 64.5 131.6C64.5 131.6 64.4 131.9 64.3 132.4C64.2 132.8 64.2 133.3 64.2 133.5C64.3 133.9 64.2 133.9 62.8 133.8C59.4 133.5 56.3 132.6 52.7 130.8C49.7 129.4 47.4 127.7 45.1 125.4C40.1 120.4 37.4 114.3 36.9 106.4C36.7 103.5 36.4 102.6 35.2 101.6C34.2 100.7 33.3 100.3 31 100C21.3 98.6 12.7 93.6 7.1 86C4.2 82.1 1.8 76.6 1.5 72.9L1.4 71.7L2.5 71.6C3.6 71.4 3.9 71.6 3.9 72.3C3.9 73 5.3 77.2 6.3 79.2C8.8 84.5 12.3 88.5 17.4 91.9C21.3 94.6 25.5 96.3 29.8 97C31 97.3 32.5 97.5 33 97.6C35.4 98 37.6 99.7 38.7 101.9C39.2 102.8 39.4 103.4 39.5 105C40 110.4 40.9 114 42.3 116.9C46 124.3 53.4 129.6 62.3 131.2ZM61.7 2.3C63.6 2.2 63.5 2.1 63.6 3.7C63.7 4 63.7 4.3 63.6 4.4C63.5 4.4 62.5 4.7 61.3 4.9C53.1 6.5 46 11 41.8 17.3C38.8 21.7 37.7 25.3 37.1 31.7C36.9 33.8 36.4 35 35.1 36.5C33.5 38.3 32 38.9 28.2 39.4C25.3 39.8 20.7 41.5 17.6 43.5C13.4 46.1 8.9 51 6.6 55.5C5.7 57.3 4.7 60.1 4.1 62.4C3.9 63.5 3.6 64.4 3.5 64.5C3.5 64.5 2.9 64.6 2.3 64.7C1.2 64.8 1.2 64.8 1.2 64.2C1.2 63.4 1.9 60 2.4 58.6C3 56.7 5 52.6 6.1 50.9C9.5 46 13.6 42.3 18.8 39.7C22.2 38 25.3 37.1 29 36.6C32.8 36.1 34.2 34.4 34.5 30.1C34.9 21.4 40.1 12.7 47.8 7.5C51.9 4.7 57.6 2.6 61.7 2.3Z"/> <path d="M64.5 131.6C64.4 131.6 63.5 131.4 62.3 131.2C53.4 129.6 46 124.3 42.3 116.9C40.9 114 40 110.4 39.5 105C39.4 103.4 39.2 102.8 38.7 101.9C37.6 99.7 35.4 98 33 97.6C32.5 97.5 31 97.3 29.8 97C25.5 96.3 21.3 94.6 17.4 91.9C12.3 88.5 8.8 84.5 6.3 79.2C5.3 77.2 3.9 73 3.9 72.3C3.9 71.6 3.6 71.4 2.5 71.6L1.4 71.7L1.5 72.9C1.8 76.6 4.2 82.1 7.1 86C12.7 93.6 21.3 98.6 31 100C33.3 100.3 34.2 100.7 35.2 101.6C36.4 102.6 36.7 103.5 36.9 106.4C37.4 114.3 40.1 120.4 45.1 125.4C47.4 127.7 49.7 129.4 52.7 130.8C56.3 132.6 59.4 133.5 62.8 133.8C64.2 133.9 64.3 133.9 64.2 133.5C64.2 133.3 64.2 132.8 64.3 132.4C64.4 131.9 64.5 131.6 64.5 131.6Z"/> <path d="M63.6 3.7C63.5 2.1 63.6 2.2 61.7 2.3C57.6 2.6 51.9 4.7 47.8 7.5C40.1 12.7 34.9 21.4 34.5 30.1C34.2 34.4 32.8 36.1 29 36.6C25.3 37.1 22.2 38 18.8 39.7C13.6 42.3 9.5 46 6.1 50.9C5 52.6 3 56.7 2.4 58.6C1.9 60 1.2 63.4 1.2 64.2C1.2 64.8 1.2 64.8 2.3 64.7C2.9 64.6 3.5 64.5 3.5 64.5C3.6 64.4 3.9 63.5 4.1 62.4C4.7 60.1 5.7 57.3 6.6 55.5C8.9 51 13.4 46.1 17.6 43.5C20.7 41.5 25.3 39.8 28.2 39.4C32 38.9 33.5 38.3 35.1 36.5C36.4 35 36.9 33.8 37.1 31.7C37.7 25.3 38.8 21.7 41.8 17.3C46 11 53.1 6.5 61.3 4.9C62.5 4.7 63.5 4.4 63.6 4.4C63.7 4.3 63.7 4 63.6 3.7Z"/> <path d="M140.8 2.2C140.7 1.5 140.7 1.5 139.9 1.5C137.2 1.5 132.3 2.9 128.5 4.8C125.2 6.5 122.9 8.2 120.1 11C116 15 113.3 19.6 111.8 25C111.3 26.8 110.8 29.7 110.8 30.7C110.8 32.7 109.4 34.8 107.5 35.6C105.5 36.5 103.2 36.1 101.6 34.5C100.6 33.5 100.2 32.7 99.9 30.4C98.6 20 92.7 11.5 83.4 6.2C80.3 4.4 75.2 2.7 72.2 2.4C70.9 2.2 71.1 2.1 70.5 3.9L70.3 4.5L71.7 4.8C77.9 6.1 83.4 8.8 87.6 12.5C92.6 16.9 95.9 22.9 96.9 29.2C97.4 32.7 97.6 33.3 98.1 34.3C99 36.3 101.1 38 103.5 38.6C106.9 39.5 110.6 37.9 112.5 34.7C113 33.9 113.4 32.4 113.6 30.3C114.1 26.6 114.8 23.9 116.5 20.6C120.2 13.1 127 7.4 135 5.1C136 4.8 140.6 3.8 140.9 3.8C140.9 3.8 140.9 3.4 140.8 2.2Z"/> <path d="M140.7 24.3L140 23.3L139.1 23.8C137.9 24.4 136.4 25.9 135.8 27.2C135.1 28.5 134.9 29.6 134.8 32.1C134.6 35.8 133.8 38.8 132.1 42.4C129.6 47.5 125.1 52.2 120.1 54.9C115.7 57.3 111.8 58.5 106.9 58.9C99.7 59.6 92.3 57.4 86.5 53.1C83.5 50.8 81.5 48.5 79.6 45C78.1 42.2 77.5 40 77.1 35.1C76.9 33.6 76.8 32.9 76.3 31.9C75.6 30.4 74.1 28.8 72.8 28.1L71.7 27.6L71.3 28.1C71 28.5 70.8 28.8 70.8 28.9C70.8 29 70.7 29.2 70.5 29.4C70.3 29.6 70.4 29.7 71.4 30.3C72.6 31.2 73.7 32.5 74 33.6C74.1 34.1 74.3 35.5 74.4 36.8C74.9 42.8 77.5 48.3 81.9 52.8C86.3 57.2 92.7 60.3 99.7 61.4C101.9 61.8 107.8 61.7 110 61.3C114.4 60.6 118.1 59.2 121.6 57.2C129.2 52.9 134.8 45.8 136.8 37.8C137.3 35.7 137.7 32.7 137.7 30.9C137.7 29 138.7 27.3 140.7 25.8L141.3 25.3L140.7 24.3Z"/> <path d="M65.2 28.7C64.7 27.8 64.7 27.7 64.1 27.9C62.6 28.3 60.7 30.3 60 32.2C59.8 32.7 59.5 33.7 59.4 34.4C59.3 35.1 59.1 36.2 59 36.9C58.7 38.5 57.7 41.6 56.8 43.4C53.8 49.3 49 54 42.7 57C38.5 59 34.9 59.9 30.5 60C27.3 60.1 26.3 60.3 24.9 61.1C23.7 61.7 22 63.4 21.8 64.2C21.7 64.6 21.8 64.8 22.4 65.4C22.9 65.8 23.3 66.2 23.4 66.2C23.5 66.2 23.8 65.8 24.1 65.3C25.5 63.4 26.6 62.9 30.9 62.7C34.6 62.6 36.7 62.2 40.1 61C45.5 59.1 50.2 56.1 54.1 52C58.5 47.4 61.4 41.3 62.1 35.5C62.3 33.1 63.1 31.7 64.6 30.6C65.2 30.1 65.8 29.7 65.8 29.7C65.8 29.7 65.6 29.2 65.2 28.7Z"/> <path d="M65.5 105.4C63.8 104.3 63 102.8 62.7 100.2C62.1 96.2 60.2 91.4 57.6 87.7C53.9 82.5 48.7 78.4 42.5 75.9C38.5 74.3 34.8 73.5 29.7 73.3C26.5 73.1 25.4 72.6 24.1 70.9L23.6 70.1L22.9 70.5C21.5 71.3 21.5 71.4 21.9 72.2C22.3 73 23.9 74.5 24.8 75C26.1 75.7 27 75.8 30.3 76C33.9 76.2 36.4 76.7 39.5 77.7C44.1 79.2 48.2 81.7 51.5 84.9C54.1 87.4 55.7 89.5 57.1 92.3C58.6 95.1 59.3 97.3 59.8 100.3C60.3 103.2 60.9 104.6 62.4 106.1C63.2 107.1 65.2 108.3 65.4 108C65.5 107.8 66.4 106.2 66.4 106.1C66.4 106.1 66 105.8 65.5 105.4Z"/> <path d="M141.1 108.9C140.9 108.8 140.2 108.3 139.6 107.8C138.1 106.3 137.7 105.4 137.4 102.2C136.9 97.3 136.2 94.5 134.3 90.7C130.7 83.2 123.8 77.3 115.5 74.6C108.4 72.3 101.3 72.3 94.3 74.6C92.2 75.3 88.8 76.9 87.3 77.9C79.8 83 75.4 90.5 74.9 99.1C74.8 100.2 74.7 101.5 74.6 102C74.3 103.3 73.4 104.5 72.1 105.3L71.1 106.1L71.5 107C71.7 107.5 71.9 108 71.8 108.1C71.7 108.3 72.8 108 73.6 107.6C74.8 106.9 76.1 105.4 76.8 104C77.4 102.7 77.5 102.4 77.6 100C77.9 95.8 78.5 93.5 80 90.3C81.2 87.7 82.6 85.8 84.8 83.6C88.6 79.8 93.1 77.5 99.1 76.2C101.7 75.6 107.9 75.5 110.5 76.1C114.3 76.8 118.6 78.6 121.6 80.5C129.3 85.5 133.7 92.8 134.6 102.1C134.9 105.9 135.4 107.2 137.1 109.1C138 110 139.7 111.1 140.3 111.1C140.4 111.1 140.7 110.6 141 110C141.5 109 141.5 109 141.1 108.9Z"/> <path d="M185.9 70L184.8 69.4L184.3 70.3C183.7 71.2 182.6 72.1 181.5 72.5C181.1 72.7 179.8 72.9 178.4 73.1C171.2 73.9 164.6 77 159.5 81.9C154.2 87 151.1 93.1 150.4 99.8C149.9 104.7 149.9 104.8 149.3 106.1C148.8 107.1 148.4 107.5 147.6 108.1C146.9 108.6 146.4 109 146.3 109C146.2 109.1 146.3 109.6 146.6 110.1C147.1 111.2 147.1 111.2 147.7 111C149.3 110.6 151.5 108.3 152.3 106.2C152.6 105.5 152.8 104.3 152.9 102.9C153.4 96.3 154.6 92.7 157.6 88.1C159.2 85.9 162.4 82.6 164.7 81C169.4 77.9 173.6 76.3 179 75.7C181.1 75.5 182 75.4 182.8 75C184.6 74.1 186.1 72.7 186.7 71.2L187 70.5L185.9 70Z"/> <path d="M186.6 63.4C185.6 61.5 183.9 60.1 181.9 59.5C181.2 59.3 179.8 59.1 178.8 59C168.1 58.4 157.9 51.2 154 41.6C152.9 38.8 152.5 36.8 152.4 33.4C152.3 29 152 28 150.4 25.9C149.7 24.9 148.7 24.1 147.5 23.6L146.8 23.3L146.3 24.2C145.9 24.7 145.7 25.1 145.7 25.2C145.7 25.3 146.1 25.7 146.7 26.1C149 27.6 149.4 28.8 149.7 33.7C149.9 38.7 150.4 40.8 152.6 45.2C153.9 47.7 155.5 49.8 157.7 52.1C163.1 57.7 170.5 61.1 178.7 61.8C181.6 62 182.7 62.5 184.1 64.3L184.8 65.2L185.7 64.7C186.8 64.1 186.9 64 186.6 63.4Z"/> <path d="M211.6 60.7C209.5 53 204.3 46.1 196.9 41.3C192.2 38.2 187.5 36.4 181.9 35.6C178.7 35.2 177.7 34.6 176.7 32.9C176.2 32.1 176.1 31.7 176 29.8C175.8 26.9 175.7 26 175.2 23.9C174.5 20.3 172.8 16.5 170.6 13.4C169.3 11.6 166.2 8.4 164.5 7.2C159.9 3.9 154.5 1.7 149.9 1.4L148.1 1.3L148.1 1.8C148.1 2.1 148.1 2.6 148 3C147.8 3.5 147.8 3.6 148.2 3.7C148.4 3.7 149.6 3.9 150.8 4.2C156.6 5.2 161.4 7.7 165.5 11.8C170.4 16.7 172.7 22 173.1 29.5C173.3 32.1 173.3 32.3 174 33.6C175.1 35.9 177.4 37.7 179.8 38.1C180.4 38.2 181.9 38.5 183.1 38.7C190.4 39.9 197.7 44.1 202.7 49.9C206.1 53.9 208.3 58.2 209.6 63.4C209.8 64.2 209.8 64.2 210.2 64.1C210.5 64 211 63.9 211.4 63.9C212 63.9 212 63.9 212 63.2C212 62.8 211.8 61.7 211.6 60.7Z"/> <path fill-rule="evenodd" clip-rule="evenodd" d="M208.7 65.1C208.5 63.6 207.6 60.4 206.9 58.8C203.1 49.4 193.5 41.7 183.3 39.8C182.3 39.6 180.8 39.4 180 39.3C178 39 176.2 38.1 174.7 36.5C172.8 34.5 172 32.4 172 29.3C172 27.6 171.4 24.1 170.7 22.1C169.5 18.4 167.6 15.5 164.7 12.6C159 6.8 150.8 4 142 4.9C130.8 6 121.9 11.9 117.4 21.1C115.8 24.4 114.9 27.5 114.7 30.7C114.3 35.1 112.2 38 108.4 39.4C106.8 40 104.2 40.1 102.4 39.4C100 38.6 97.6 36.4 96.8 34.1C96.6 33.6 96.3 32.4 96.2 31.7C95.6 27.3 95 25.3 93.4 21.9C92.3 19.6 90.7 17.2 89 15.4C83 8.8 73.1 4.9 64.5 5.6C52.9 6.7 43.3 13.7 39.6 23.8C38.9 25.8 38.4 28.7 38.2 31.4C38.1 33.4 37.9 33.9 37.4 35C36.2 37.6 33.4 39.8 30.7 40.2C30.1 40.3 28.9 40.4 28 40.6C26 40.8 23 41.9 20.7 43C12.8 47 7.1 54.3 5.2 62.9C4.6 65.5 4.6 69.7 5.1 72.3C7.2 82.7 15.5 91.6 26.2 95C28.1 95.6 29.9 96 32.9 96.5C35.5 96.8 37.8 98.4 39.3 100.7C40.2 102.1 40.6 103.5 40.8 106.9C41.6 117 47.4 124.8 56.9 128.5C61.8 130.4 66.5 130.8 72.5 129.7C81.3 128.2 89.7 122.4 93.8 114.8C95.6 111.5 96.7 108 97.2 103.9C97.5 102.1 97.7 101.4 98.2 100.3C100.1 96.4 104.2 94.5 108.4 95.6C111.7 96.5 114.4 99.4 115 102.7C115.1 103.4 115.3 104.9 115.5 106C116.2 110.8 118.8 116.2 122.2 120C125.5 123.7 130.3 126.8 135.4 128.5C138.9 129.7 140 129.9 144.2 130C147.4 130.1 148.2 130 150.1 129.7C159.1 128.1 166.8 122.8 170.8 115.4C172.5 112.1 173.6 108.5 173.9 104.3C174 102.8 174.2 101.7 174.5 101C175.4 98.6 177.7 96.4 180 95.7C180.6 95.5 181.9 95.2 182.9 95.1C186.7 94.8 189.8 93.9 193.1 92.2C200.5 88.5 206.2 81.5 208.2 73.7C208.6 72.1 208.7 71.2 208.7 68.7C208.7 67 208.7 65.4 208.7 65.1ZM182.5 58.5C185.2 59.4 187.4 61.6 188.3 64.4C188.9 65.9 188.9 68.8 188.3 70.4C187.8 71.8 186.9 73.2 185.8 74.2C184.1 75.9 182.5 76.5 179.1 76.9C174.8 77.3 171.3 78.4 167.6 80.5C161.8 83.8 157.4 89 155.4 95.1C154.6 97.4 154.3 99.2 154.1 101.9C154 103.1 153.9 104.7 153.7 105.4C152.9 108.8 149.8 112 146.4 112.8C145.3 113 142.7 113 141.5 112.8C138.8 112.2 136.1 110.2 134.8 107.8C134 106.1 133.6 104.7 133.5 102.3C133.1 96.5 130.9 91.1 126.9 86.4C123.8 82.8 119.1 79.8 114.1 78.2C103.7 74.8 92 77.5 85 84.9C81.1 88.9 78.8 94.6 78.8 99.8C78.8 102.8 77.8 105.3 75.9 107.1C74.1 108.9 72.3 109.7 69.6 109.9C66.3 110.1 63.7 109.1 61.7 107.1C60 105.4 59.3 103.8 58.8 100.5C58.1 96.6 56.9 93.6 54.5 90C53.1 87.8 49.4 84.2 47.1 82.7C41.9 79.2 36.7 77.5 30.3 77.1C28.5 77 26.6 76.9 26.2 76.8C23.2 76 20.6 73.4 19.9 70.7C19.5 69.2 19.5 66.8 20 65.3C20.5 63.6 21.7 61.9 23.2 60.8C25.1 59.5 26.3 59.1 30.3 58.9C34.1 58.7 36.2 58.3 39.5 57.1C49.4 53.4 56.6 45.2 58 35.9C58.7 31.9 59.5 30 61.5 28.2C63.4 26.5 65.4 25.8 68.2 25.8C71.2 25.8 73.3 26.6 75.3 28.5C77.2 30.4 78 32.2 78.2 35.7C78.3 37.1 78.5 38.9 78.7 39.7C79.2 41.5 80.3 44.2 81.3 45.9C84.8 51.6 91.2 55.8 99 57.5C100.7 57.8 101.6 57.9 104.5 57.9C108.5 57.9 110.4 57.6 114.1 56.4C122.6 53.6 129.6 47 132.4 39C133.2 36.7 133.5 34.9 133.7 31.8C133.9 30 134 28.7 134.3 27.9C135.7 23.7 139.8 21.1 144.3 21.5C147.1 21.7 149 22.7 150.8 24.6C152.8 26.7 153.4 28.8 153.4 32.8C153.5 35.5 153.8 37.8 154.5 39.8C156.9 46.6 161.5 51.7 168.1 54.9C171.8 56.8 175.1 57.7 179.3 58C180.6 58.1 182 58.3 182.5 58.5Z"/></svg>`;
|
|
31
32
|
const SIGNATURE = "From one designer to all designers, with love <3";
|
|
32
33
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
return r >= 0.85 ? "strong" : r >= 0.6 ? "fair" : r >= 0.35 ? "weak" : "poor";
|
|
36
|
-
};
|
|
34
|
+
/** The four bands live in lib/badge.mjs; these are their class names in this file. */
|
|
35
|
+
const BAND_CLASS = { ready: "strong", good: "fair", gaps: "weak", unready: "poor" };
|
|
37
36
|
|
|
38
37
|
const VERDICT = {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
ready: ["Agent-ready", "Agents can work in this system. Keep the gates that make that true."],
|
|
39
|
+
good: ["Good foundation", "The bones are right. The gaps left are the ones that let an agent invent things."],
|
|
40
|
+
gaps: ["Gaps to address", "An agent will produce plausible, wrong UI here more often than not."],
|
|
41
|
+
unready: ["Not ready", "There is nothing here for an agent to follow, so it will follow its own habits."],
|
|
43
42
|
};
|
|
44
43
|
|
|
45
44
|
/* Mirrors FIXES in lib/fix.mjs. The kind is the honest half of this table: an
|
|
@@ -64,8 +63,10 @@ const KIND_WORD = { apply: "adsa writes it", brief: "brief for your agent" };
|
|
|
64
63
|
export function html(facts, scored, history = []) {
|
|
65
64
|
const rubricVersion = RUBRIC.version;
|
|
66
65
|
const date = new Date().toISOString().slice(0, 10);
|
|
67
|
-
const
|
|
68
|
-
const
|
|
66
|
+
const verdict = scoreBand(scored.total, scored.max);
|
|
67
|
+
const band = BAND_CLASS[verdict.id];
|
|
68
|
+
const [verdictTitle, verdictLine] = VERDICT[verdict.id];
|
|
69
|
+
const field = standing(scored.total);
|
|
69
70
|
const dims = scored.dimensions;
|
|
70
71
|
const live = dims.filter((d) => !d.skipped);
|
|
71
72
|
const weakest = [...live].sort((a, b) => a.score - b.score).slice(0, 3);
|
|
@@ -187,6 +188,7 @@ main{padding:26px clamp(18px,3vw,38px) 60px;display:flex;flex-direction:column;g
|
|
|
187
188
|
.verdict .ring{flex:none}
|
|
188
189
|
.verdict-copy b{display:block;font-size:17px;letter-spacing:-0.02em}
|
|
189
190
|
.verdict-copy p{font-size:13.5px;color:var(--ink-2);margin-top:3px}
|
|
191
|
+
.verdict-copy .field{font-size:12.5px;color:var(--ink-3);margin-top:6px;max-width:56ch}
|
|
190
192
|
.verdict-copy em{font-style:normal;display:block;font-family:var(--mono);font-size:11.5px;color:var(--ink-3);margin-top:8px}
|
|
191
193
|
|
|
192
194
|
.ring{width:112px;height:112px;border-radius:50%;display:grid;place-items:center;print-color-adjust:exact;-webkit-print-color-adjust:exact}
|
|
@@ -384,6 +386,7 @@ ol.todo .dim-of{font-size:12.5px;color:var(--ink-3)}
|
|
|
384
386
|
<div class="verdict-copy">
|
|
385
387
|
<b>${verdictTitle}</b>
|
|
386
388
|
<p>${verdictLine}</p>
|
|
389
|
+
<p class="field">${esc(field.sentence)}</p>
|
|
387
390
|
<em>${delta === null ? `first run · ${live.length} dimensions` : `${delta >= 0 ? "+" : ""}${delta} since the last run${gained.length ? ` · ${gained.map((d) => esc(d.title.toLowerCase())).join(", ")}` : ""}`}</em>
|
|
388
391
|
</div>
|
|
389
392
|
</div>
|
|
@@ -687,7 +690,7 @@ function esc(value) {
|
|
|
687
690
|
|
|
688
691
|
/** The markdown twin: the same facts, for a pull request or a terminal. */
|
|
689
692
|
export function markdown(facts, scored) {
|
|
690
|
-
const band =
|
|
693
|
+
const band = scoreBand(scored.total, scored.max).id;
|
|
691
694
|
const lines = [
|
|
692
695
|
`# ${facts.name} — agent readiness`,
|
|
693
696
|
"",
|
|
@@ -695,6 +698,8 @@ export function markdown(facts, scored) {
|
|
|
695
698
|
"",
|
|
696
699
|
VERDICT[band][1],
|
|
697
700
|
"",
|
|
701
|
+
standing(scored.total).sentence,
|
|
702
|
+
"",
|
|
698
703
|
`| Dimension | Score | Evidence |`,
|
|
699
704
|
`| :-- | :-- | :-- |`,
|
|
700
705
|
];
|