@domandigital/craft 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -23,10 +23,12 @@ __export(index_exports, {
23
23
  AI_PHRASES: () => AI_PHRASES,
24
24
  AI_VIOLET: () => AI_VIOLET,
25
25
  AI_WORDS: () => AI_WORDS,
26
+ BASELINE_VERSION: () => BASELINE_VERSION,
26
27
  BUZZWORDS: () => BUZZWORDS,
27
28
  CATALOGUE: () => CATALOGUE,
28
29
  CATALOGUE_VERSION: () => CATALOGUE_VERSION,
29
30
  CHOICE_KEYS: () => CHOICE_KEYS,
31
+ DEFAULT_IGNORE: () => DEFAULT_IGNORE,
30
32
  DENSITIES: () => DENSITIES,
31
33
  DENSITY_NAMES: () => DENSITY_NAMES,
32
34
  DIRECTION_VERSION: () => DIRECTION_VERSION,
@@ -41,6 +43,7 @@ __export(index_exports, {
41
43
  HOUSE: () => HOUSE,
42
44
  HOUSE_BUDGET: () => HOUSE_BUDGET,
43
45
  HOUSE_TYPE: () => HOUSE_TYPE,
46
+ JSON_SCHEMA_VERSION: () => JSON_SCHEMA_VERSION,
44
47
  LIGHTNESS_CURVE: () => LIGHTNESS_CURVE,
45
48
  MIN_DECIDED: () => MIN_DECIDED,
46
49
  MIN_RUNS: () => MIN_RUNS,
@@ -71,7 +74,9 @@ __export(index_exports, {
71
74
  accentFork: () => accentFork,
72
75
  addSite: () => addSite,
73
76
  apcaContrast: () => apcaContrast,
77
+ applyBaseline: () => applyBaseline,
74
78
  applyHouseGate: () => applyHouseGate,
79
+ applySeverity: () => applySeverity,
75
80
  auditSnapshot: () => auditSnapshot,
76
81
  catalogueTable: () => catalogueTable,
77
82
  characterReport: () => characterReport,
@@ -82,6 +87,7 @@ __export(index_exports, {
82
87
  compareFacts: () => compareFacts,
83
88
  compareToEstate: () => compareToEstate,
84
89
  craftTokens: () => craftTokens,
90
+ createBaseline: () => createBaseline,
85
91
  deltaEOk: () => deltaEOk,
86
92
  deltaEOkHex: () => deltaEOkHex,
87
93
  densityCss: () => densityCss,
@@ -93,6 +99,7 @@ __export(index_exports, {
93
99
  extractHtml: () => extractHtml,
94
100
  findClaims: () => findClaims,
95
101
  findColours: () => findColours,
102
+ findingKey: () => findingKey,
96
103
  fingerprint: () => fingerprint,
97
104
  fingerprintDistance: () => fingerprintDistance,
98
105
  fluidClamp: () => fluidClamp,
@@ -103,12 +110,14 @@ __export(index_exports, {
103
110
  formatComparison: () => formatComparison,
104
111
  formatHex: () => formatHex,
105
112
  formatReport: () => formatReport,
113
+ globToRegExp: () => globToRegExp,
106
114
  groundName: () => groundName,
107
115
  harvest: () => harvest,
108
116
  hexToOklch: () => hexToOklch,
109
117
  houseRule: () => houseRule,
110
118
  hueName: () => hueName,
111
119
  hueSwatch: () => hueSwatch,
120
+ ignoreMatcher: () => ignoreMatcher,
112
121
  inP3Gamut: () => inP3Gamut,
113
122
  inSrgbGamut: () => inSrgbGamut,
114
123
  initDirection: () => initDirection,
@@ -123,7 +132,9 @@ __export(index_exports, {
123
132
  oklchToHex: () => oklchToHex,
124
133
  oklchToRgb: () => oklchToRgb,
125
134
  paletteFromPixels: () => paletteFromPixels,
135
+ parseBaseline: () => parseBaseline,
126
136
  parseColour: () => parseColour,
137
+ parseCraftConfig: () => parseCraftConfig,
127
138
  parseHex: () => parseHex,
128
139
  propose: () => propose,
129
140
  protectedFacts: () => protectedFacts,
@@ -134,6 +145,7 @@ __export(index_exports, {
134
145
  scanSource: () => scanSource,
135
146
  sectionRhythm: () => sectionRhythm,
136
147
  semantic: () => semantic,
148
+ severityExceptions: () => severityExceptions,
137
149
  shapeName: () => shapeName,
138
150
  sharedParts: () => sharedParts,
139
151
  shouldAnimate: () => shouldAnimate,
@@ -142,6 +154,8 @@ __export(index_exports, {
142
154
  tailwindV4Theme: () => tailwindV4Theme,
143
155
  tellById: () => tellById,
144
156
  toGamut: () => toGamut,
157
+ toJson: () => toJson,
158
+ toSarif: () => toSarif,
145
159
  typeFeatureTokens: () => typeFeatureTokens,
146
160
  typicality: () => typicality,
147
161
  validateDirection: () => validateDirection,
@@ -4752,6 +4766,194 @@ function formatClaims(report2, label = "craft copy claims") {
4752
4766
  return lines.join("\n");
4753
4767
  }
4754
4768
 
4769
+ // src/character/baseline.ts
4770
+ var BASELINE_VERSION = 1;
4771
+ function fnv1a(text) {
4772
+ let hash = 2166136261;
4773
+ for (let i = 0; i < text.length; i += 1) {
4774
+ hash ^= text.charCodeAt(i);
4775
+ hash = Math.imul(hash, 16777619);
4776
+ }
4777
+ return (hash >>> 0).toString(16).padStart(8, "0");
4778
+ }
4779
+ var excerptHash = (f4) => fnv1a(f4.excerpt.replace(/\s+/g, " ").trim());
4780
+ var keyOf = (tell, path, excerpt) => `${tell}\0${path}\0${excerpt}`;
4781
+ function findingKey(f4) {
4782
+ return keyOf(f4.tell, f4.path, excerptHash(f4));
4783
+ }
4784
+ function createBaseline(report2) {
4785
+ const counts = /* @__PURE__ */ new Map();
4786
+ for (const f4 of report2.findings) {
4787
+ const excerpt = excerptHash(f4);
4788
+ const key = keyOf(f4.tell, f4.path, excerpt);
4789
+ const entry = counts.get(key);
4790
+ if (entry) entry.count += 1;
4791
+ else counts.set(key, { tell: f4.tell, path: f4.path, excerpt, count: 1 });
4792
+ }
4793
+ const entries = [...counts.values()].sort((a, b) => a.path.localeCompare(b.path) || a.tell.localeCompare(b.tell) || a.excerpt.localeCompare(b.excerpt));
4794
+ return { version: BASELINE_VERSION, catalogueVersion: report2.catalogueVersion, entries };
4795
+ }
4796
+ function parseBaseline(data, source = "baseline") {
4797
+ const b = data;
4798
+ if (!b || typeof b !== "object" || b.version !== BASELINE_VERSION || !Array.isArray(b.entries)) {
4799
+ throw new Error(`${source}: not a craft baseline (version ${BASELINE_VERSION})`);
4800
+ }
4801
+ for (const e of b.entries) {
4802
+ if (typeof e?.tell !== "string" || typeof e.path !== "string" || typeof e.excerpt !== "string" || !Number.isInteger(e.count) || e.count < 1) {
4803
+ throw new Error(`${source}: malformed entry ${JSON.stringify(e)}`);
4804
+ }
4805
+ }
4806
+ return b;
4807
+ }
4808
+ function recount(report2, findings) {
4809
+ const byGeneration = { 1: 0, 2: 0, 3: 0 };
4810
+ const byTell = {};
4811
+ for (const f4 of findings) {
4812
+ byGeneration[f4.generation] += 1;
4813
+ byTell[f4.tell] = (byTell[f4.tell] ?? 0) + 1;
4814
+ }
4815
+ return {
4816
+ ...report2,
4817
+ findings,
4818
+ summary: { ...report2.summary, findings: findings.length, byGeneration, byTell, blocking: findings.filter((f4) => f4.severity === "block").length }
4819
+ };
4820
+ }
4821
+ function applyBaseline(report2, baseline) {
4822
+ const remaining = /* @__PURE__ */ new Map();
4823
+ for (const e of baseline.entries) {
4824
+ const key = keyOf(e.tell, e.path, e.excerpt);
4825
+ remaining.set(key, (remaining.get(key) ?? 0) + e.count);
4826
+ }
4827
+ const kept = [];
4828
+ let baselined = 0;
4829
+ for (const f4 of report2.findings) {
4830
+ const key = findingKey(f4);
4831
+ const left = remaining.get(key) ?? 0;
4832
+ if (left > 0) {
4833
+ remaining.set(key, left - 1);
4834
+ baselined += 1;
4835
+ } else kept.push(f4);
4836
+ }
4837
+ return { ...recount(report2, kept), baselined };
4838
+ }
4839
+
4840
+ // src/character/config.ts
4841
+ var DEFAULT_IGNORE = [".claude", ".agents", ".cursor"];
4842
+ var KEYS = /* @__PURE__ */ new Set(["$schema", "ignore", "copyPaths", "severity"]);
4843
+ var LEVELS = /* @__PURE__ */ new Set(["warn", "block", "off"]);
4844
+ var MIN_BECAUSE = 12;
4845
+ var isRecord = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
4846
+ var isStringArray = (v) => Array.isArray(v) && v.every((s) => typeof s === "string");
4847
+ function parseCraftConfig(data, knownTells, source = "craft.config.json") {
4848
+ if (!isRecord(data)) throw new Error(`${source}: expected an object`);
4849
+ for (const key of Object.keys(data)) if (!KEYS.has(key)) throw new Error(`${source}: unknown key "${key}"`);
4850
+ const ignore = data.ignore ?? [];
4851
+ if (!isStringArray(ignore)) throw new Error(`${source}: "ignore" must be an array of glob strings`);
4852
+ if (data.copyPaths !== void 0 && !isStringArray(data.copyPaths)) throw new Error(`${source}: "copyPaths" must be an array of paths`);
4853
+ const severity = {};
4854
+ const raw = data.severity ?? {};
4855
+ if (!isRecord(raw)) throw new Error(`${source}: "severity" must map a tell id to { level, because }`);
4856
+ for (const [tell, value] of Object.entries(raw)) {
4857
+ if (!knownTells.has(tell)) throw new Error(`${source}: severity names no tell called "${tell}"`);
4858
+ if (!isRecord(value) || !LEVELS.has(value.level)) {
4859
+ throw new Error(`${source}: severity.${tell} needs a level of "warn", "block" or "off"`);
4860
+ }
4861
+ if (typeof value.because !== "string" || value.because.trim().length < MIN_BECAUSE) {
4862
+ throw new Error(`${source}: severity.${tell} needs a because of at least a sentence`);
4863
+ }
4864
+ severity[tell] = { level: value.level, because: value.because };
4865
+ }
4866
+ return { ignore, severity, ...data.copyPaths ? { copyPaths: data.copyPaths } : {} };
4867
+ }
4868
+ function globToRegExp(glob) {
4869
+ const pattern = glob.replace(/^\.\//, "").replace(/\/$/, "").replace(/\/\*\*$/, "");
4870
+ let body = "";
4871
+ for (let i = 0; i < pattern.length; i += 1) {
4872
+ const c = pattern[i];
4873
+ if (c === "*" && pattern[i + 1] === "*") {
4874
+ const slash = pattern[i + 2] === "/";
4875
+ body += slash ? "(?:.*/)?" : ".*";
4876
+ i += slash ? 2 : 1;
4877
+ } else if (c === "*") body += "[^/]*";
4878
+ else if (c === "?") body += "[^/]";
4879
+ else body += c.replace(/[.+^${}()|[\]\\]/g, "\\$&");
4880
+ }
4881
+ const anywhere = !pattern.includes("/");
4882
+ return new RegExp(`^${anywhere ? "(?:.*/)?" : ""}${body}(?:/.*)?$`);
4883
+ }
4884
+ function ignoreMatcher(patterns) {
4885
+ const res = patterns.map(globToRegExp);
4886
+ return (path) => {
4887
+ const p = path.replace(/\\/g, "/").replace(/^\.\//, "");
4888
+ return res.some((re) => re.test(p));
4889
+ };
4890
+ }
4891
+ function severityExceptions(config) {
4892
+ return Object.entries(config.severity).filter(([, o]) => o.level === "off").map(([tell, o]) => ({ tell, because: `craft.config.json: ${o.because}` }));
4893
+ }
4894
+ function applySeverity(report2, config) {
4895
+ const findings = report2.findings.map((f4) => {
4896
+ const o = config.severity[f4.tell];
4897
+ return o && o.level !== "off" ? { ...f4, severity: o.level } : f4;
4898
+ });
4899
+ return { ...report2, findings, summary: { ...report2.summary, blocking: findings.filter((f4) => f4.severity === "block").length } };
4900
+ }
4901
+
4902
+ // src/character/sarif.ts
4903
+ var isUrl = (path) => /^[a-z][a-z0-9+.-]*:\/\//i.test(path);
4904
+ function toSarif(report2, options) {
4905
+ const byId = new Map(options.tells.map((t) => [t.id, t]));
4906
+ const ids = [...new Set(report2.findings.map((f4) => f4.tell))].sort();
4907
+ const index = new Map(ids.map((id, i) => [id, i]));
4908
+ const rules = ids.map((id) => {
4909
+ const t = byId.get(id);
4910
+ return {
4911
+ id,
4912
+ name: t?.name ?? id,
4913
+ shortDescription: { text: t?.name ?? id },
4914
+ ...t ? { fullDescription: { text: t.why }, help: { text: t.fix } } : {}
4915
+ };
4916
+ });
4917
+ const results = report2.findings.map((f4) => ({
4918
+ ruleId: f4.tell,
4919
+ ruleIndex: index.get(f4.tell),
4920
+ level: f4.severity === "block" ? "error" : "warning",
4921
+ message: { text: `${f4.message}. ${f4.fix}` },
4922
+ locations: [
4923
+ {
4924
+ physicalLocation: {
4925
+ artifactLocation: { uri: isUrl(f4.path) ? f4.path : f4.path.replace(/\\/g, "/") },
4926
+ ...f4.line > 0 ? { region: { startLine: f4.line, snippet: { text: f4.excerpt } } } : {}
4927
+ }
4928
+ }
4929
+ ],
4930
+ partialFingerprints: { "craftFinding/v1": fnv1a(findingKey(f4)) }
4931
+ }));
4932
+ return {
4933
+ $schema: "https://json.schemastore.org/sarif-2.1.0.json",
4934
+ version: "2.1.0",
4935
+ runs: [
4936
+ {
4937
+ tool: {
4938
+ driver: {
4939
+ name: "craft",
4940
+ version: report2.catalogueVersion,
4941
+ informationUri: options.informationUri ?? "https://www.npmjs.com/package/@domandigital/craft",
4942
+ rules
4943
+ }
4944
+ },
4945
+ results
4946
+ }
4947
+ ]
4948
+ };
4949
+ }
4950
+
4951
+ // src/character/json.ts
4952
+ var JSON_SCHEMA_VERSION = 1;
4953
+ function toJson(data) {
4954
+ return JSON.stringify({ schemaVersion: JSON_SCHEMA_VERSION, ...data }, null, 2);
4955
+ }
4956
+
4755
4957
  // src/fingerprint/index.ts
4756
4958
  var FINGERPRINT_VERSION = 1;
4757
4959
  var CHROMATIC = 0.03;
@@ -5647,10 +5849,12 @@ function retrofitPlan(report2, direction) {
5647
5849
  AI_PHRASES,
5648
5850
  AI_VIOLET,
5649
5851
  AI_WORDS,
5852
+ BASELINE_VERSION,
5650
5853
  BUZZWORDS,
5651
5854
  CATALOGUE,
5652
5855
  CATALOGUE_VERSION,
5653
5856
  CHOICE_KEYS,
5857
+ DEFAULT_IGNORE,
5654
5858
  DENSITIES,
5655
5859
  DENSITY_NAMES,
5656
5860
  DIRECTION_VERSION,
@@ -5665,6 +5869,7 @@ function retrofitPlan(report2, direction) {
5665
5869
  HOUSE,
5666
5870
  HOUSE_BUDGET,
5667
5871
  HOUSE_TYPE,
5872
+ JSON_SCHEMA_VERSION,
5668
5873
  LIGHTNESS_CURVE,
5669
5874
  MIN_DECIDED,
5670
5875
  MIN_RUNS,
@@ -5695,7 +5900,9 @@ function retrofitPlan(report2, direction) {
5695
5900
  accentFork,
5696
5901
  addSite,
5697
5902
  apcaContrast,
5903
+ applyBaseline,
5698
5904
  applyHouseGate,
5905
+ applySeverity,
5699
5906
  auditSnapshot,
5700
5907
  catalogueTable,
5701
5908
  characterReport,
@@ -5706,6 +5913,7 @@ function retrofitPlan(report2, direction) {
5706
5913
  compareFacts,
5707
5914
  compareToEstate,
5708
5915
  craftTokens,
5916
+ createBaseline,
5709
5917
  deltaEOk,
5710
5918
  deltaEOkHex,
5711
5919
  densityCss,
@@ -5717,6 +5925,7 @@ function retrofitPlan(report2, direction) {
5717
5925
  extractHtml,
5718
5926
  findClaims,
5719
5927
  findColours,
5928
+ findingKey,
5720
5929
  fingerprint,
5721
5930
  fingerprintDistance,
5722
5931
  fluidClamp,
@@ -5727,12 +5936,14 @@ function retrofitPlan(report2, direction) {
5727
5936
  formatComparison,
5728
5937
  formatHex,
5729
5938
  formatReport,
5939
+ globToRegExp,
5730
5940
  groundName,
5731
5941
  harvest,
5732
5942
  hexToOklch,
5733
5943
  houseRule,
5734
5944
  hueName,
5735
5945
  hueSwatch,
5946
+ ignoreMatcher,
5736
5947
  inP3Gamut,
5737
5948
  inSrgbGamut,
5738
5949
  initDirection,
@@ -5747,7 +5958,9 @@ function retrofitPlan(report2, direction) {
5747
5958
  oklchToHex,
5748
5959
  oklchToRgb,
5749
5960
  paletteFromPixels,
5961
+ parseBaseline,
5750
5962
  parseColour,
5963
+ parseCraftConfig,
5751
5964
  parseHex,
5752
5965
  propose,
5753
5966
  protectedFacts,
@@ -5758,6 +5971,7 @@ function retrofitPlan(report2, direction) {
5758
5971
  scanSource,
5759
5972
  sectionRhythm,
5760
5973
  semantic,
5974
+ severityExceptions,
5761
5975
  shapeName,
5762
5976
  sharedParts,
5763
5977
  shouldAnimate,
@@ -5766,6 +5980,8 @@ function retrofitPlan(report2, direction) {
5766
5980
  tailwindV4Theme,
5767
5981
  tellById,
5768
5982
  toGamut,
5983
+ toJson,
5984
+ toSarif,
5769
5985
  typeFeatureTokens,
5770
5986
  typicality,
5771
5987
  validateDirection,
package/dist/index.d.cts CHANGED
@@ -1188,6 +1188,190 @@ declare function namedSources(sentence: string): string[];
1188
1188
  declare function findClaims(files: SourceFile[]): ClaimsReport;
1189
1189
  declare function formatClaims(report: ClaimsReport, label?: string): string;
1190
1190
 
1191
+ /**
1192
+ * Baselines: adopt craft on a repo that already has findings, and fail only
1193
+ * on new ones.
1194
+ *
1195
+ * A finding is keyed on its tell, its path and a hash of its excerpt with the
1196
+ * whitespace collapsed, never on its line: an edit above a known finding
1197
+ * moves it, and a moved finding is not a new one. Keys are counted, so a file
1198
+ * with two identical findings and a baseline of one reports the second.
1199
+ *
1200
+ * Pure. The command line reads and writes the file.
1201
+ */
1202
+
1203
+ declare const BASELINE_VERSION = 1;
1204
+ interface BaselineEntry {
1205
+ tell: string;
1206
+ path: string;
1207
+ /** FNV-1a of the excerpt, whitespace collapsed. */
1208
+ excerpt: string;
1209
+ count: number;
1210
+ }
1211
+ interface Baseline {
1212
+ version: typeof BASELINE_VERSION;
1213
+ catalogueVersion: string;
1214
+ entries: BaselineEntry[];
1215
+ }
1216
+ /** The key a finding is matched on. Also the SARIF partial fingerprint. */
1217
+ declare function findingKey(f: Finding): string;
1218
+ /** Every finding in a report, as a baseline. */
1219
+ declare function createBaseline(report: CheckReport): Baseline;
1220
+ /** Validate a parsed baseline file. */
1221
+ declare function parseBaseline(data: unknown, source?: string): Baseline;
1222
+ /**
1223
+ * The report without the findings the baseline already knows about.
1224
+ * `baselined` is how many were removed, so the output can say so: a
1225
+ * baseline that hides findings silently is a hole.
1226
+ */
1227
+ declare function applyBaseline(report: CheckReport, baseline: Baseline): CheckReport & {
1228
+ baselined: number;
1229
+ };
1230
+
1231
+ /**
1232
+ * `craft.config.json`: what a repo tells craft about itself.
1233
+ *
1234
+ * Pure: the command line reads the file and hands the parsed JSON here. The
1235
+ * design choices live in `art-direction.json`; this file is about the tool:
1236
+ * which paths are not the site, where the copy is, and a repo's own decisions
1237
+ * about a tell's severity.
1238
+ *
1239
+ * {
1240
+ * "ignore": ["docs/archive/**", "*.stories.tsx"],
1241
+ * "copyPaths": ["content", "src/app"],
1242
+ * "severity": {
1243
+ * "ai-violet": { "level": "off", "because": "The client's shopfront has been this violet since 1998." },
1244
+ * "em-dash": { "level": "block", "because": "House style for this client bans them outright." }
1245
+ * }
1246
+ * }
1247
+ *
1248
+ * A severity change needs a `because`, like an exception in
1249
+ * `art-direction.json`, and for the same reason: a tell switched off with no
1250
+ * reason is a guard nobody can audit. `off` becomes an exception, so the
1251
+ * report still lists what it silenced.
1252
+ */
1253
+
1254
+ type SeverityLevel = "warn" | "block" | "off";
1255
+ interface SeverityOverride {
1256
+ level: SeverityLevel;
1257
+ because: string;
1258
+ }
1259
+ interface CraftConfig {
1260
+ /** Glob patterns for paths that are not the site. Added to `DEFAULT_IGNORE`. */
1261
+ ignore: string[];
1262
+ /** Where `craft copy` looks when no path is given. */
1263
+ copyPaths?: string[];
1264
+ severity: Record<string, SeverityOverride>;
1265
+ }
1266
+ /**
1267
+ * Agent and tool folders: instructions for the people and models building
1268
+ * the site, not copy a visitor reads. Always ignored by a directory walk.
1269
+ */
1270
+ declare const DEFAULT_IGNORE: string[];
1271
+ /**
1272
+ * Validate a parsed `craft.config.json`. Throws with the file name and the
1273
+ * key at fault: a config that half-applies is worse than one that stops the
1274
+ * run.
1275
+ */
1276
+ declare function parseCraftConfig(data: unknown, knownTells: ReadonlySet<string>, source?: string): CraftConfig;
1277
+ /**
1278
+ * A glob as a regular expression over a `/`-separated relative path.
1279
+ * `*` is one segment's worth, `**` any depth, `?` one character. A pattern
1280
+ * with no `/` matches a file or folder of that name anywhere; otherwise it is
1281
+ * anchored at the repo root. Anything under a matched folder matches too.
1282
+ */
1283
+ declare function globToRegExp(glob: string): RegExp;
1284
+ /** A matcher for a set of globs. Paths are normalised to `/` before matching. */
1285
+ declare function ignoreMatcher(patterns: string[]): (path: string) => boolean;
1286
+ /** `off` entries, as exceptions: applied, and listed as silenced in the report. */
1287
+ declare function severityExceptions(config: CraftConfig): TellException[];
1288
+ /** `warn` and `block` entries, applied to a finished report. */
1289
+ declare function applySeverity(report: CheckReport, config: CraftConfig): CheckReport;
1290
+
1291
+ /**
1292
+ * A report as SARIF 2.1.0, for GitHub code scanning and any other tool that
1293
+ * reads it. Pure.
1294
+ *
1295
+ * One rule per tell the report names, carrying the tell's `why` and `fix`.
1296
+ * `block` findings are errors, `warn` findings warnings. A finding on a
1297
+ * rendered page has the URL as its location and no line: GitHub code
1298
+ * scanning only shows results in files of the repo, so those appear in the
1299
+ * SARIF file but not in the Security tab.
1300
+ */
1301
+
1302
+ interface SarifTell {
1303
+ id: string;
1304
+ name: string;
1305
+ why: string;
1306
+ fix: string;
1307
+ }
1308
+ interface SarifOptions {
1309
+ /** The catalogue, for each rule's description. */
1310
+ tells: readonly SarifTell[];
1311
+ /** Where a reader learns more. */
1312
+ informationUri?: string;
1313
+ }
1314
+ declare function toSarif(report: CheckReport, options: SarifOptions): {
1315
+ $schema: string;
1316
+ version: "2.1.0";
1317
+ runs: {
1318
+ tool: {
1319
+ driver: {
1320
+ name: string;
1321
+ version: string;
1322
+ informationUri: string;
1323
+ rules: {
1324
+ fullDescription?: {
1325
+ text: string;
1326
+ } | undefined;
1327
+ help?: {
1328
+ text: string;
1329
+ } | undefined;
1330
+ id: string;
1331
+ name: string;
1332
+ shortDescription: {
1333
+ text: string;
1334
+ };
1335
+ }[];
1336
+ };
1337
+ };
1338
+ results: {
1339
+ ruleId: string;
1340
+ ruleIndex: number;
1341
+ level: "error" | "warning";
1342
+ message: {
1343
+ text: string;
1344
+ };
1345
+ locations: {
1346
+ physicalLocation: {
1347
+ region?: {
1348
+ startLine: number;
1349
+ snippet: {
1350
+ text: string;
1351
+ };
1352
+ } | undefined;
1353
+ artifactLocation: {
1354
+ uri: string;
1355
+ };
1356
+ };
1357
+ }[];
1358
+ partialFingerprints: {
1359
+ "craftFinding/v1": string;
1360
+ };
1361
+ }[];
1362
+ }[];
1363
+ };
1364
+
1365
+ /**
1366
+ * The `--json` contract. Every JSON document a craft command prints carries
1367
+ * `schemaVersion`, so a script reading it can refuse a shape it does not
1368
+ * know instead of misreading it. Bump it when a field is removed or changes
1369
+ * meaning; adding a field is not a bump.
1370
+ */
1371
+ declare const JSON_SCHEMA_VERSION = 1;
1372
+ /** A command's JSON output, versioned. */
1373
+ declare function toJson(data: object): string;
1374
+
1191
1375
  /**
1192
1376
  * The rendered detection path for tells that can be seen on a live page.
1193
1377
  *
@@ -1820,4 +2004,4 @@ declare function characterReport(input: CharacterInputs, copyTells?: Set<string>
1820
2004
 
1821
2005
  declare function retrofitPlan(report: CharacterReport, direction?: ArtDirection | null): string;
1822
2006
 
1823
- export { AI_PHRASES, AI_VIOLET, AI_WORDS, type AccentFork, type AccentForkOptions, type Action, type Area, type ArtDirection, BUZZWORDS, CATALOGUE, CATALOGUE_VERSION, CHOICE_KEYS, type CandidateKind, type CharacterInputs, type CharacterReport, type CheckOptions, type CheckReport, type CheckRestraintInput, type ChoiceKey, type Claim, type ClaimsReport, type ContrastCheck, type ContrastReport, type CopyTell, type CraftTokensInput, type CraftTokensResult, DENSITIES, DENSITY_NAMES, DIRECTION_VERSION, DISTANCE_WEIGHTS, DURATION_MS, DURATION_S, type DensityCssOptions, type DensityName, type DirectionChoice, type DirectionProblem, type DirectionReport, type DirectionSource, type DurationName, EASE, EASE_TUPLE, ESTATE_VERSION, EXIT_RATIO, type EaseName, type EmitCssOptions, type EstateMatch, type EstatePair, type EstateRegister, type EstateSite, FINGERPRINT_VERSION, type Fact, type FactComparison, type FactKind, type Finding, type Fingerprint, type FingerprintDistance, type FluidSpaceOptions, type FluidTypeOptions, type FluidTypeResult, type FontClass, type Gamut, type Generation, HOUSE, HOUSE_BUDGET, HOUSE_TYPE, type HarvestCandidate, type HarvestOptions, type Hit, type HouseRule, type HouseTier, LIGHTNESS_CURVE, MIN_DECIDED, MIN_RUNS, type MotionDecision, type MotionKind, NEGATIVE_REASSURANCE, NULL_VERSION, type NullModel, type NullRun, type Oklch, type OklchToHexOptions, PILL_LIMIT, PLAINER_WORDS, PROPOSED, type PaletteColour, type Proposal, type ProposeInput, RAMP_STEPS, REFLEX_FONTS_1, REFLEX_FONTS_2, RENDERED_PATHS, REVEAL_LIMIT, REVIEW_PHRASES, type Ramp, type RampFromAnchorsOptions, type RampOptions, type RampStep, type RestraintBudget, type RestraintReport, type RestraintSeverity, type RestraintViolation, type Rgb, SCALE, SHADCN_LIMIT, SHADCN_PRIMITIVES, SIBLING_AT, SNAPSHOT_VERSION, SOURCE_KINDS, SPACE_STEPS, SPRING, STOCK_PHRASES, type SectionKind, type SectionRhythmOptions, type SemanticInput, type SemanticResult, type Severity, type ShouldAnimateInput, type SignalResult, type Snapshot, type SnapshotColour, type SnapshotControl, type SnapshotEffects, type SnapshotFont, type SnapshotGradient, type SnapshotHeading, type SnapshotMotion, type SnapshotPatch, type SnapshotSection, type SourceFile, type SourceKind, type SourceTell, type SpaceStep, type Surface, TELL_HEAVY, TYPE_STEPS, TYPICAL_AT, type TailwindPreset, type Tell, type TellException, type TypeStep, type Typicality, VAGUE_WORDS, type ValidateContext, type Verdict, accentFork, addSite, apcaContrast, applyHouseGate, auditSnapshot, catalogueTable, characterReport, checkCopy, checkPair, checkRestraint, choicesOf, compareFacts, compareToEstate, craftTokens, deltaEOk, deltaEOkHex, densityCss, densityTokens, emitCss, emptyEstate, estatePairs, exitDuration, extractHtml, findClaims, findColours, fingerprint, fingerprintDistance, fluidClamp, fluidSpace, fluidType, fontClass, formatClaims, formatComparison, formatHex, formatReport, groundName, harvest, hexToOklch, houseRule, hueName, hueSwatch, inP3Gamut, inSrgbGamut, initDirection, isAiViolet, isCream, makeSnapshot, motionTokens, namedSources, nearest, normaliseFamily, nullPrompt, oklchToHex, oklchToRgb, paletteFromPixels, parseColour, parseHex, propose, protectedFacts, ramp, rampFromAnchors, retrofitPlan, runTell, scanSource, sectionRhythm, semantic, shapeName, sharedParts, shouldAnimate, siblingLine, tailwindV3Preset, tailwindV4Theme, tellById, toGamut, typeFeatureTokens, typicality, validateDirection, visibleText, wcagContrast, wordListsJson };
2007
+ export { AI_PHRASES, AI_VIOLET, AI_WORDS, type AccentFork, type AccentForkOptions, type Action, type Area, type ArtDirection, BASELINE_VERSION, BUZZWORDS, type Baseline, type BaselineEntry, CATALOGUE, CATALOGUE_VERSION, CHOICE_KEYS, type CandidateKind, type CharacterInputs, type CharacterReport, type CheckOptions, type CheckReport, type CheckRestraintInput, type ChoiceKey, type Claim, type ClaimsReport, type ContrastCheck, type ContrastReport, type CopyTell, type CraftConfig, type CraftTokensInput, type CraftTokensResult, DEFAULT_IGNORE, DENSITIES, DENSITY_NAMES, DIRECTION_VERSION, DISTANCE_WEIGHTS, DURATION_MS, DURATION_S, type DensityCssOptions, type DensityName, type DirectionChoice, type DirectionProblem, type DirectionReport, type DirectionSource, type DurationName, EASE, EASE_TUPLE, ESTATE_VERSION, EXIT_RATIO, type EaseName, type EmitCssOptions, type EstateMatch, type EstatePair, type EstateRegister, type EstateSite, FINGERPRINT_VERSION, type Fact, type FactComparison, type FactKind, type Finding, type Fingerprint, type FingerprintDistance, type FluidSpaceOptions, type FluidTypeOptions, type FluidTypeResult, type FontClass, type Gamut, type Generation, HOUSE, HOUSE_BUDGET, HOUSE_TYPE, type HarvestCandidate, type HarvestOptions, type Hit, type HouseRule, type HouseTier, JSON_SCHEMA_VERSION, LIGHTNESS_CURVE, MIN_DECIDED, MIN_RUNS, type MotionDecision, type MotionKind, NEGATIVE_REASSURANCE, NULL_VERSION, type NullModel, type NullRun, type Oklch, type OklchToHexOptions, PILL_LIMIT, PLAINER_WORDS, PROPOSED, type PaletteColour, type Proposal, type ProposeInput, RAMP_STEPS, REFLEX_FONTS_1, REFLEX_FONTS_2, RENDERED_PATHS, REVEAL_LIMIT, REVIEW_PHRASES, type Ramp, type RampFromAnchorsOptions, type RampOptions, type RampStep, type RestraintBudget, type RestraintReport, type RestraintSeverity, type RestraintViolation, type Rgb, SCALE, SHADCN_LIMIT, SHADCN_PRIMITIVES, SIBLING_AT, SNAPSHOT_VERSION, SOURCE_KINDS, SPACE_STEPS, SPRING, STOCK_PHRASES, type SarifOptions, type SarifTell, type SectionKind, type SectionRhythmOptions, type SemanticInput, type SemanticResult, type Severity, type SeverityLevel, type SeverityOverride, type ShouldAnimateInput, type SignalResult, type Snapshot, type SnapshotColour, type SnapshotControl, type SnapshotEffects, type SnapshotFont, type SnapshotGradient, type SnapshotHeading, type SnapshotMotion, type SnapshotPatch, type SnapshotSection, type SourceFile, type SourceKind, type SourceTell, type SpaceStep, type Surface, TELL_HEAVY, TYPE_STEPS, TYPICAL_AT, type TailwindPreset, type Tell, type TellException, type TypeStep, type Typicality, VAGUE_WORDS, type ValidateContext, type Verdict, accentFork, addSite, apcaContrast, applyBaseline, applyHouseGate, applySeverity, auditSnapshot, catalogueTable, characterReport, checkCopy, checkPair, checkRestraint, choicesOf, compareFacts, compareToEstate, craftTokens, createBaseline, deltaEOk, deltaEOkHex, densityCss, densityTokens, emitCss, emptyEstate, estatePairs, exitDuration, extractHtml, findClaims, findColours, findingKey, fingerprint, fingerprintDistance, fluidClamp, fluidSpace, fluidType, fontClass, formatClaims, formatComparison, formatHex, formatReport, globToRegExp, groundName, harvest, hexToOklch, houseRule, hueName, hueSwatch, ignoreMatcher, inP3Gamut, inSrgbGamut, initDirection, isAiViolet, isCream, makeSnapshot, motionTokens, namedSources, nearest, normaliseFamily, nullPrompt, oklchToHex, oklchToRgb, paletteFromPixels, parseBaseline, parseColour, parseCraftConfig, parseHex, propose, protectedFacts, ramp, rampFromAnchors, retrofitPlan, runTell, scanSource, sectionRhythm, semantic, severityExceptions, shapeName, sharedParts, shouldAnimate, siblingLine, tailwindV3Preset, tailwindV4Theme, tellById, toGamut, toJson, toSarif, typeFeatureTokens, typicality, validateDirection, visibleText, wcagContrast, wordListsJson };