@tendrilapp/cli 0.1.20 → 0.1.23

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/tendril.js CHANGED
@@ -14,11 +14,11 @@ var __export = (target, all) => {
14
14
  __defProp(target, name, { get: all[name], enumerable: true });
15
15
  };
16
16
 
17
- // packages/core/src/ir.ts
17
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/core/src/ir.ts
18
18
  import { z } from "zod";
19
19
  var IrLayoutSchema, IrMotionSchema, IrPositionSchema, IrNodeSchema, ComponentIrSchema;
20
20
  var init_ir = __esm({
21
- "packages/core/src/ir.ts"() {
21
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/core/src/ir.ts"() {
22
22
  "use strict";
23
23
  IrLayoutSchema = z.object({
24
24
  mode: z.enum(["flex-row", "flex-column", "grid", "none"]),
@@ -110,14 +110,14 @@ var init_ir = __esm({
110
110
  }
111
111
  });
112
112
 
113
- // packages/figma/src/source.ts
113
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/figma/src/source.ts
114
114
  var init_source = __esm({
115
- "packages/figma/src/source.ts"() {
115
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/figma/src/source.ts"() {
116
116
  "use strict";
117
117
  }
118
118
  });
119
119
 
120
- // packages/figma/src/svg-safety.ts
120
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/figma/src/svg-safety.ts
121
121
  function checkSvgSafety(source) {
122
122
  const issues = [];
123
123
  if (!/<\s*svg\b/i.test(source)) issues.push("not an <svg> document");
@@ -132,7 +132,7 @@ function assetExportName(key) {
132
132
  }
133
133
  var UNSAFE_PATTERNS;
134
134
  var init_svg_safety = __esm({
135
- "packages/figma/src/svg-safety.ts"() {
135
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/figma/src/svg-safety.ts"() {
136
136
  "use strict";
137
137
  UNSAFE_PATTERNS = [
138
138
  [/<\s*script\b/i, "script element"],
@@ -146,11 +146,11 @@ var init_svg_safety = __esm({
146
146
  }
147
147
  });
148
148
 
149
- // packages/figma/src/provided.ts
149
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/figma/src/provided.ts
150
150
  import { z as z2 } from "zod";
151
151
  var ProvidedVariableSchema, RangeSchema, PinnedPlacementSchema, VariantValueFactsSchema, ProvidedMetadataSchema, ProvidedContextSchema, ProvidedContextSource;
152
152
  var init_provided = __esm({
153
- "packages/figma/src/provided.ts"() {
153
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/figma/src/provided.ts"() {
154
154
  "use strict";
155
155
  init_svg_safety();
156
156
  ProvidedVariableSchema = z2.object({
@@ -269,7 +269,7 @@ var init_provided = __esm({
269
269
  }
270
270
  });
271
271
 
272
- // packages/figma/src/mcp/client.ts
272
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/figma/src/mcp/client.ts
273
273
  function parseMessages(body, contentType) {
274
274
  if (body.trim() === "") return [];
275
275
  if (!contentType.includes("text/event-stream")) {
@@ -285,7 +285,7 @@ function parseMessages(body, contentType) {
285
285
  }
286
286
  var PROTOCOL_VERSION, McpUnavailableError, McpProtocolError, McpHttpClient;
287
287
  var init_client = __esm({
288
- "packages/figma/src/mcp/client.ts"() {
288
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/figma/src/mcp/client.ts"() {
289
289
  "use strict";
290
290
  PROTOCOL_VERSION = "2025-06-18";
291
291
  McpUnavailableError = class extends Error {
@@ -389,7 +389,7 @@ var init_client = __esm({
389
389
  }
390
390
  });
391
391
 
392
- // packages/figma/src/mcp/normalize.ts
392
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/figma/src/mcp/normalize.ts
393
393
  function decodeXmlEntities(v) {
394
394
  return v.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&#39;/g, "'").replace(/&amp;/g, "&");
395
395
  }
@@ -472,7 +472,7 @@ function mergeVariantAxes(childNames) {
472
472
  }
473
473
  var TAG_TO_TYPE, TAG_RE, ATTR_RE;
474
474
  var init_normalize = __esm({
475
- "packages/figma/src/mcp/normalize.ts"() {
475
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/figma/src/mcp/normalize.ts"() {
476
476
  "use strict";
477
477
  init_svg_safety();
478
478
  TAG_TO_TYPE = {
@@ -488,10 +488,10 @@ var init_normalize = __esm({
488
488
  }
489
489
  });
490
490
 
491
- // packages/figma/src/mock/fixtures/button.ts
491
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/figma/src/mock/fixtures/button.ts
492
492
  var buttonVariables, buttonMetadata, buttonNodeTree;
493
493
  var init_button = __esm({
494
- "packages/figma/src/mock/fixtures/button.ts"() {
494
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/figma/src/mock/fixtures/button.ts"() {
495
495
  "use strict";
496
496
  buttonVariables = [
497
497
  {
@@ -600,10 +600,10 @@ var init_button = __esm({
600
600
  }
601
601
  });
602
602
 
603
- // packages/figma/src/mock/mock-source.ts
603
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/figma/src/mock/mock-source.ts
604
604
  var MockFigmaSource;
605
605
  var init_mock_source = __esm({
606
- "packages/figma/src/mock/mock-source.ts"() {
606
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/figma/src/mock/mock-source.ts"() {
607
607
  "use strict";
608
608
  init_button();
609
609
  MockFigmaSource = class {
@@ -640,7 +640,7 @@ var init_mock_source = __esm({
640
640
  }
641
641
  });
642
642
 
643
- // packages/figma/src/css-ident.ts
643
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/figma/src/css-ident.ts
644
644
  function canonicalCssIdentPart(part) {
645
645
  return part.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
646
646
  }
@@ -649,27 +649,27 @@ function variableNameToCssVar(name) {
649
649
  return `--${parts.join("-")}`;
650
650
  }
651
651
  var init_css_ident = __esm({
652
- "packages/figma/src/css-ident.ts"() {
652
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/figma/src/css-ident.ts"() {
653
653
  "use strict";
654
654
  }
655
655
  });
656
656
 
657
- // packages/figma/src/mcp/var-decoder.ts
657
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/figma/src/mcp/var-decoder.ts
658
658
  var init_var_decoder = __esm({
659
- "packages/figma/src/mcp/var-decoder.ts"() {
659
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/figma/src/mcp/var-decoder.ts"() {
660
660
  "use strict";
661
661
  init_css_ident();
662
662
  }
663
663
  });
664
664
 
665
- // packages/figma/src/mcp/font-normalize.ts
665
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/figma/src/mcp/font-normalize.ts
666
666
  var init_font_normalize = __esm({
667
- "packages/figma/src/mcp/font-normalize.ts"() {
667
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/figma/src/mcp/font-normalize.ts"() {
668
668
  "use strict";
669
669
  }
670
670
  });
671
671
 
672
- // packages/figma/src/provided-recording.ts
672
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/figma/src/provided-recording.ts
673
673
  import { z as z3 } from "zod";
674
674
  function checkPngPayload(base64) {
675
675
  let raw;
@@ -684,7 +684,7 @@ function checkPngPayload(base64) {
684
684
  }
685
685
  var MAX_EMISSION_BYTES, MAX_IMAGE_BYTES, MAX_ASSET_BYTES, PNG_MAGIC, TextEnvelopeSchema, ImageEnvelopeSchema, ProvidedRepSchema, ManifestWireSchema, ProvidedRecordingSetSchema;
686
686
  var init_provided_recording = __esm({
687
- "packages/figma/src/provided-recording.ts"() {
687
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/figma/src/provided-recording.ts"() {
688
688
  "use strict";
689
689
  init_svg_safety();
690
690
  MAX_EMISSION_BYTES = 2 * 1024 * 1024;
@@ -752,7 +752,7 @@ var init_provided_recording = __esm({
752
752
  }
753
753
  });
754
754
 
755
- // packages/figma/src/recording/axis-defaults.ts
755
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/figma/src/recording/axis-defaults.ts
756
756
  function resolveAxisDefaultWithRule(domain, recorded, override) {
757
757
  if (override !== void 0) return { value: override, rule: "override" };
758
758
  const literal = domain.find((v) => kebab(v) === "default" || kebab(v) === "enabled");
@@ -787,7 +787,7 @@ function resolveAxisDefault(domain, recorded, override) {
787
787
  }
788
788
  var INTERACTION_STATES, BOOLEAN_STATES, ENGAGED_STATES, INTERACTION_EVIDENCE_VALUES, kebab, OFF_VALUES, ON_VALUES;
789
789
  var init_axis_defaults = __esm({
790
- "packages/figma/src/recording/axis-defaults.ts"() {
790
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/figma/src/recording/axis-defaults.ts"() {
791
791
  "use strict";
792
792
  INTERACTION_STATES = /* @__PURE__ */ new Set(["hover", "focus", "focus-visible", "active", "pressed"]);
793
793
  BOOLEAN_STATES = /* @__PURE__ */ new Set(["disabled", "loading"]);
@@ -810,7 +810,7 @@ var init_axis_defaults = __esm({
810
810
  }
811
811
  });
812
812
 
813
- // packages/figma/src/recording/plan.ts
813
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/figma/src/recording/plan.ts
814
814
  function singleAxes(name) {
815
815
  const parsed = parseVariantAxes(name);
816
816
  if (parsed === void 0) return void 0;
@@ -920,7 +920,7 @@ function planQueue(symbols, opts = {}) {
920
920
  }
921
921
  var kebab2;
922
922
  var init_plan = __esm({
923
- "packages/figma/src/recording/plan.ts"() {
923
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/figma/src/recording/plan.ts"() {
924
924
  "use strict";
925
925
  init_normalize();
926
926
  init_axis_defaults();
@@ -928,7 +928,7 @@ var init_plan = __esm({
928
928
  }
929
929
  });
930
930
 
931
- // packages/figma/src/recording/session.ts
931
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/figma/src/recording/session.ts
932
932
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
933
933
  import path from "node:path";
934
934
  import { z as z4 } from "zod";
@@ -939,14 +939,25 @@ function manifestMains(manifest) {
939
939
  function requiredToolsFor(manifest, slug) {
940
940
  return manifestMains(manifest).includes(slug) ? [...REQUIRED_TOOLS, INTERIOR_TOOL] : REQUIRED_TOOLS;
941
941
  }
942
- function loadManifest(setDir) {
942
+ function readManifestFile(setDir) {
943
943
  const p = manifestPath(setDir);
944
944
  if (!existsSync(p)) throw new Error(`no recording-set.json in ${setDir} \u2014 run \`tendril record plan\` first`);
945
- return SessionManifestSchema.parse(JSON.parse(readFileSync(p, "utf8")));
945
+ const raw = JSON.parse(readFileSync(p, "utf8"));
946
+ return { manifest: SessionManifestSchema.parse(raw), raw };
947
+ }
948
+ function loadManifest(setDir) {
949
+ return readManifestFile(setDir).manifest;
950
+ }
951
+ function writeManifest(setDir, raw) {
952
+ const manifest = SessionManifestSchema.parse(raw);
953
+ mkdirSync(setDir, { recursive: true });
954
+ writeFileSync(manifestPath(setDir), `${JSON.stringify(raw, null, 1)}
955
+ `);
956
+ return manifest;
946
957
  }
947
958
  function planSet(setDir, component, symbols, opts = {}) {
948
959
  if (existsSync(manifestPath(setDir))) {
949
- const existing = loadManifest(setDir);
960
+ const { manifest: existing, raw } = readManifestFile(setDir);
950
961
  const wantsNewDefaults = opts.defaults !== void 0 && JSON.stringify(opts.defaults) !== JSON.stringify(existing.defaults ?? {});
951
962
  const anythingRecorded = existing.reps.some((r) => RECORD_TOOLS.some((t) => existsSync(path.join(setDir, r.slug, `${t}.json`))));
952
963
  if (!wantsNewDefaults || anythingRecorded) {
@@ -963,12 +974,11 @@ function planSet(setDir, component, symbols, opts = {}) {
963
974
  usedSlugs.add(slug);
964
975
  return { slug, nodeId: r.nodeId, ...r.sourceFrame !== void 0 ? { sourceFrame: r.sourceFrame } : {} };
965
976
  });
966
- existing.reps.push(...appended);
967
- existing.planMode = "full";
968
- delete existing.notRecorded;
969
- writeFileSync(manifestPath(setDir), `${JSON.stringify(existing, null, 1)}
970
- `);
971
- return { manifest: existing, plan: { reps: [], notRecorded: [] }, resumed: true, toppedUp: appended.map((a) => ({ slug: a.slug, nodeId: a.nodeId })) };
977
+ raw["reps"].push(...appended);
978
+ raw["planMode"] = "full";
979
+ delete raw["notRecorded"];
980
+ const manifest2 = writeManifest(setDir, raw);
981
+ return { manifest: manifest2, plan: { reps: [], notRecorded: [] }, resumed: true, toppedUp: appended.map((a) => ({ slug: a.slug, nodeId: a.nodeId })) };
972
982
  }
973
983
  }
974
984
  return { manifest: existing, plan: { reps: [], notRecorded: [] }, resumed: true };
@@ -989,9 +999,7 @@ function planSet(setDir, component, symbols, opts = {}) {
989
999
  planMode: opts.sample === true ? "sample" : "full",
990
1000
  ...plan.notRecorded.length > 0 ? { notRecorded: plan.notRecorded.map((n) => `${n.name} (${n.nodeId}): ${n.reason}`).join("; ") } : {}
991
1001
  };
992
- mkdirSync(setDir, { recursive: true });
993
- writeFileSync(manifestPath(setDir), `${JSON.stringify(manifest, null, 1)}
994
- `);
1002
+ writeManifest(setDir, manifest);
995
1003
  return { manifest, plan, resumed: false };
996
1004
  }
997
1005
  function sessionStatus(setDir) {
@@ -1070,7 +1078,7 @@ function ingestAsset(setDir, slug, name, content) {
1070
1078
  }
1071
1079
  var RECORD_TOOLS, INTERIOR_TOOL, REQUIRED_TOOLS, SessionManifestSchema, manifestPath, PROTOCOL_ORDER, byProtocolOrder;
1072
1080
  var init_session = __esm({
1073
- "packages/figma/src/recording/session.ts"() {
1081
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/figma/src/recording/session.ts"() {
1074
1082
  "use strict";
1075
1083
  init_svg_safety();
1076
1084
  init_provided_recording();
@@ -1115,7 +1123,7 @@ var init_session = __esm({
1115
1123
  }
1116
1124
  });
1117
1125
 
1118
- // packages/figma/src/recording/roles.ts
1126
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/figma/src/recording/roles.ts
1119
1127
  import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
1120
1128
  import path2 from "node:path";
1121
1129
  function emissionIdSets(emission) {
@@ -1184,16 +1192,16 @@ function deriveRoles(setDir, manifest) {
1184
1192
  }
1185
1193
  var NODE_ID_RE;
1186
1194
  var init_roles = __esm({
1187
- "packages/figma/src/recording/roles.ts"() {
1195
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/figma/src/recording/roles.ts"() {
1188
1196
  "use strict";
1189
1197
  init_session();
1190
1198
  NODE_ID_RE = /data-node-id="([^"]+)"/g;
1191
1199
  }
1192
1200
  });
1193
1201
 
1194
- // packages/figma/src/index.ts
1202
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/figma/src/index.ts
1195
1203
  var init_src = __esm({
1196
- "packages/figma/src/index.ts"() {
1204
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/figma/src/index.ts"() {
1197
1205
  "use strict";
1198
1206
  init_source();
1199
1207
  init_provided();
@@ -1212,7 +1220,7 @@ var init_src = __esm({
1212
1220
  }
1213
1221
  });
1214
1222
 
1215
- // packages/tokens/src/dtcg.ts
1223
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/tokens/src/dtcg.ts
1216
1224
  function variableNameToPath(name) {
1217
1225
  return name.split("/").map(canonicalCssIdentPart).filter((part) => part.length > 0);
1218
1226
  }
@@ -1318,7 +1326,7 @@ function mapVariablesToDtcg(variables, defaultMode = "light") {
1318
1326
  }
1319
1327
  var DIMENSION_COLLECTIONS, DtcgMappingError;
1320
1328
  var init_dtcg = __esm({
1321
- "packages/tokens/src/dtcg.ts"() {
1329
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/tokens/src/dtcg.ts"() {
1322
1330
  "use strict";
1323
1331
  init_src();
1324
1332
  DIMENSION_COLLECTIONS = /* @__PURE__ */ new Set(["spacing", "radius", "size", "border-width"]);
@@ -1333,7 +1341,7 @@ var init_dtcg = __esm({
1333
1341
  }
1334
1342
  });
1335
1343
 
1336
- // packages/tokens/src/emit.ts
1344
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/tokens/src/emit.ts
1337
1345
  function decomposeFontValue(raw, valueByCssVar) {
1338
1346
  const field = (name) => new RegExp(`${name}:\\s*("[^"]*"|[^,)]+)`).exec(raw)?.[1]?.trim();
1339
1347
  const resolve = (v) => {
@@ -1400,7 +1408,7 @@ export default {
1400
1408
  }
1401
1409
  var STYLE_WEIGHTS;
1402
1410
  var init_emit = __esm({
1403
- "packages/tokens/src/emit.ts"() {
1411
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/tokens/src/emit.ts"() {
1404
1412
  "use strict";
1405
1413
  init_src();
1406
1414
  STYLE_WEIGHTS = {
@@ -1419,7 +1427,7 @@ var init_emit = __esm({
1419
1427
  }
1420
1428
  });
1421
1429
 
1422
- // packages/tokens/src/synthesize.ts
1430
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/tokens/src/synthesize.ts
1423
1431
  function synthesizeSpacingVariables(tree, variantFacts, existing) {
1424
1432
  if (existing.some((v) => v.collection === "spacing")) return [];
1425
1433
  const values = /* @__PURE__ */ new Set();
@@ -1458,7 +1466,7 @@ function synthesizeSpacingVariables(tree, variantFacts, existing) {
1458
1466
  }
1459
1467
  var SPACING_FIELDS;
1460
1468
  var init_synthesize = __esm({
1461
- "packages/tokens/src/synthesize.ts"() {
1469
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/tokens/src/synthesize.ts"() {
1462
1470
  "use strict";
1463
1471
  SPACING_FIELDS = [
1464
1472
  "paddingTop",
@@ -1470,9 +1478,9 @@ var init_synthesize = __esm({
1470
1478
  }
1471
1479
  });
1472
1480
 
1473
- // packages/tokens/src/index.ts
1481
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/tokens/src/index.ts
1474
1482
  var init_src2 = __esm({
1475
- "packages/tokens/src/index.ts"() {
1483
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/tokens/src/index.ts"() {
1476
1484
  "use strict";
1477
1485
  init_dtcg();
1478
1486
  init_emit();
@@ -1481,7 +1489,7 @@ var init_src2 = __esm({
1481
1489
  }
1482
1490
  });
1483
1491
 
1484
- // packages/core/src/ir-builder.ts
1492
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/core/src/ir-builder.ts
1485
1493
  function isObject(value) {
1486
1494
  return typeof value === "object" && value !== null && !Array.isArray(value);
1487
1495
  }
@@ -1666,7 +1674,7 @@ function canonicalizeFactIdents(variantFacts) {
1666
1674
  }
1667
1675
  var RAW_PAYLOAD_FLAG_BYTES, MIN_HEALTHY_RATIO, RATIO_CHECK_MIN_BYTES, PADDING_FIELDS;
1668
1676
  var init_ir_builder = __esm({
1669
- "packages/core/src/ir-builder.ts"() {
1677
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/core/src/ir-builder.ts"() {
1670
1678
  "use strict";
1671
1679
  init_src2();
1672
1680
  init_src2();
@@ -1677,10 +1685,10 @@ var init_ir_builder = __esm({
1677
1685
  }
1678
1686
  });
1679
1687
 
1680
- // packages/core/src/exit-codes.ts
1688
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/core/src/exit-codes.ts
1681
1689
  var ExitCode;
1682
1690
  var init_exit_codes = __esm({
1683
- "packages/core/src/exit-codes.ts"() {
1691
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/core/src/exit-codes.ts"() {
1684
1692
  "use strict";
1685
1693
  ExitCode = {
1686
1694
  Success: 0,
@@ -1701,7 +1709,7 @@ var init_exit_codes = __esm({
1701
1709
  }
1702
1710
  });
1703
1711
 
1704
- // packages/core/src/readiness.ts
1712
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/core/src/readiness.ts
1705
1713
  function collectDefaultNamedLayers(tree, found) {
1706
1714
  const name = tree["name"];
1707
1715
  const visible = tree["visible"];
@@ -1751,15 +1759,15 @@ function scoreReadiness(metadata, tree) {
1751
1759
  }
1752
1760
  var DEFAULT_LAYER_NAME;
1753
1761
  var init_readiness = __esm({
1754
- "packages/core/src/readiness.ts"() {
1762
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/core/src/readiness.ts"() {
1755
1763
  "use strict";
1756
1764
  DEFAULT_LAYER_NAME = /^(Group|Frame|Rectangle|Ellipse|Vector|Component)\s*\d*$/;
1757
1765
  }
1758
1766
  });
1759
1767
 
1760
- // packages/core/src/index.ts
1768
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/core/src/index.ts
1761
1769
  var init_src3 = __esm({
1762
- "packages/core/src/index.ts"() {
1770
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/core/src/index.ts"() {
1763
1771
  "use strict";
1764
1772
  init_ir();
1765
1773
  init_ir_builder();
@@ -1768,7 +1776,7 @@ var init_src3 = __esm({
1768
1776
  }
1769
1777
  });
1770
1778
 
1771
- // packages/verify/src/browser.ts
1779
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/browser.ts
1772
1780
  import { execFileSync } from "node:child_process";
1773
1781
  import { existsSync as existsSync3, readdirSync } from "node:fs";
1774
1782
  import path3 from "node:path";
@@ -1826,7 +1834,7 @@ function chromeVersion() {
1826
1834
  }
1827
1835
  var MAC_CANDIDATES, WIN_CANDIDATES, PATH_NAMES, _version;
1828
1836
  var init_browser = __esm({
1829
- "packages/verify/src/browser.ts"() {
1837
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/browser.ts"() {
1830
1838
  "use strict";
1831
1839
  MAC_CANDIDATES = [
1832
1840
  "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
@@ -1841,7 +1849,7 @@ var init_browser = __esm({
1841
1849
  }
1842
1850
  });
1843
1851
 
1844
- // packages/verify/src/runtime.ts
1852
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/runtime.ts
1845
1853
  import { existsSync as existsSync4, mkdtempSync, symlinkSync } from "node:fs";
1846
1854
  import { createRequire } from "node:module";
1847
1855
  import os from "node:os";
@@ -1891,12 +1899,12 @@ function reactPinPlugin() {
1891
1899
  };
1892
1900
  }
1893
1901
  var init_runtime = __esm({
1894
- "packages/verify/src/runtime.ts"() {
1902
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/runtime.ts"() {
1895
1903
  "use strict";
1896
1904
  }
1897
1905
  });
1898
1906
 
1899
- // packages/verify/src/gates.ts
1907
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/gates.ts
1900
1908
  function scanForbiddenPatterns(source) {
1901
1909
  const violations = [];
1902
1910
  const lines = source.split("\n");
@@ -1915,7 +1923,7 @@ function scanForbiddenPatterns(source) {
1915
1923
  }
1916
1924
  var FORBIDDEN_PATTERNS;
1917
1925
  var init_gates = __esm({
1918
- "packages/verify/src/gates.ts"() {
1926
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/gates.ts"() {
1919
1927
  "use strict";
1920
1928
  FORBIDDEN_PATTERNS = [
1921
1929
  { name: "eslint-disable", regex: /eslint-disable/ },
@@ -1927,7 +1935,7 @@ var init_gates = __esm({
1927
1935
  }
1928
1936
  });
1929
1937
 
1930
- // packages/verify/src/tsc-check.ts
1938
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/tsc-check.ts
1931
1939
  import ts from "typescript";
1932
1940
  import path5 from "node:path";
1933
1941
  function runTscStrict(files) {
@@ -1947,7 +1955,7 @@ function runTscStrict(files) {
1947
1955
  }
1948
1956
  var STRICT_OPTIONS;
1949
1957
  var init_tsc_check = __esm({
1950
- "packages/verify/src/tsc-check.ts"() {
1958
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/tsc-check.ts"() {
1951
1959
  "use strict";
1952
1960
  STRICT_OPTIONS = {
1953
1961
  strict: true,
@@ -1967,7 +1975,7 @@ var init_tsc_check = __esm({
1967
1975
  }
1968
1976
  });
1969
1977
 
1970
- // packages/verify/src/token-lint.ts
1978
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/token-lint.ts
1971
1979
  import strictValue from "stylelint-declaration-strict-value";
1972
1980
  import stylelint from "stylelint";
1973
1981
  async function runTokenLint(css, fileLabel = "generated.css", definedVars2, recordedMapEmpty = false) {
@@ -2028,7 +2036,7 @@ async function runTokenLint(css, fileLabel = "generated.css", definedVars2, reco
2028
2036
  }
2029
2037
  var TOKEN_ENFORCED_PROPERTIES, ALLOWED_KEYWORDS, STYLELINT_CONFIG, LEGAL_CUSTOM_PROP;
2030
2038
  var init_token_lint = __esm({
2031
- "packages/verify/src/token-lint.ts"() {
2039
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/token-lint.ts"() {
2032
2040
  "use strict";
2033
2041
  TOKEN_ENFORCED_PROPERTIES = [
2034
2042
  "/color$/",
@@ -2088,7 +2096,7 @@ var init_token_lint = __esm({
2088
2096
  }
2089
2097
  });
2090
2098
 
2091
- // packages/verify/src/loop.ts
2099
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/loop.ts
2092
2100
  import { rmSync, writeFileSync as writeFileSync2 } from "node:fs";
2093
2101
  import path6 from "node:path";
2094
2102
  async function runChecks(componentName, files, extraFiles, definedVars2) {
@@ -2162,7 +2170,7 @@ function definedVarsFrom(tokensCss) {
2162
2170
  }
2163
2171
  var SKIPPED_CHECKS;
2164
2172
  var init_loop = __esm({
2165
- "packages/verify/src/loop.ts"() {
2173
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/loop.ts"() {
2166
2174
  "use strict";
2167
2175
  init_runtime();
2168
2176
  init_gates();
@@ -2172,7 +2180,7 @@ var init_loop = __esm({
2172
2180
  }
2173
2181
  });
2174
2182
 
2175
- // packages/verify/src/report.ts
2183
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/report.ts
2176
2184
  import { z as z5 } from "zod";
2177
2185
  function isTokenEnforcedProperty(property) {
2178
2186
  return enforcedMatchers.some((m) => m.test(property));
@@ -2212,7 +2220,7 @@ function buildReport(input) {
2212
2220
  }
2213
2221
  var ReportSchema, enforcedMatchers;
2214
2222
  var init_report = __esm({
2215
- "packages/verify/src/report.ts"() {
2223
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/report.ts"() {
2216
2224
  "use strict";
2217
2225
  init_token_lint();
2218
2226
  ReportSchema = z5.object({
@@ -2274,7 +2282,32 @@ var init_report = __esm({
2274
2282
  }
2275
2283
  });
2276
2284
 
2277
- // packages/verify/src/image-diff.ts
2285
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/mount-limits.ts
2286
+ function lcdTextEnabled() {
2287
+ return process.env["TENDRIL_ENABLE_LCD_TEXT"] === "1";
2288
+ }
2289
+ function mountArgs() {
2290
+ return [MEMORY_CAP_ARG, ...lcdTextEnabled() ? [] : ["--disable-lcd-text"]];
2291
+ }
2292
+ function raceMountDeadline(work, deadlineMs, onDeadline) {
2293
+ return Promise.race([
2294
+ work,
2295
+ new Promise((resolve) => {
2296
+ const timer = setTimeout(() => resolve(onDeadline()), deadlineMs);
2297
+ timer.unref();
2298
+ })
2299
+ ]);
2300
+ }
2301
+ var MEMORY_CAP_ARG, ENGINE_MOUNT_DEADLINE_MS;
2302
+ var init_mount_limits = __esm({
2303
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/mount-limits.ts"() {
2304
+ "use strict";
2305
+ MEMORY_CAP_ARG = "--js-flags=--max-old-space-size=512";
2306
+ ENGINE_MOUNT_DEADLINE_MS = 3e4;
2307
+ }
2308
+ });
2309
+
2310
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/image-diff.ts
2278
2311
  import { PNG } from "pngjs";
2279
2312
  import pixelmatch from "pixelmatch";
2280
2313
  function channelDistance(a, b) {
@@ -2716,7 +2749,7 @@ function cropPng(png, x, y, width, height) {
2716
2749
  }
2717
2750
  var INK_DELTA, ABSENT_RADIUS, ABSENT_MIN_PX;
2718
2751
  var init_image_diff = __esm({
2719
- "packages/verify/src/image-diff.ts"() {
2752
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/image-diff.ts"() {
2720
2753
  "use strict";
2721
2754
  INK_DELTA = 30;
2722
2755
  ABSENT_RADIUS = 3;
@@ -2724,7 +2757,7 @@ var init_image_diff = __esm({
2724
2757
  }
2725
2758
  });
2726
2759
 
2727
- // packages/verify/src/visual-facts.ts
2760
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/visual-facts.ts
2728
2761
  import path7 from "node:path";
2729
2762
  import { fileURLToPath as fileURLToPath2 } from "node:url";
2730
2763
  import { build } from "esbuild";
@@ -3030,7 +3063,7 @@ ${input.tokensCss}
3030
3063
  ${input.files.css}
3031
3064
  #root { display: inline-block; }
3032
3065
  </style></head><body><div id="root"></div><script>${js}</script></body></html>`;
3033
- const browser = await chromium.launch({ executablePath, headless: true });
3066
+ const browser = await chromium.launch({ executablePath, headless: true, args: mountArgs() });
3034
3067
  try {
3035
3068
  const page = await browser.newPage({ viewport: { width: 800, height: 600 } });
3036
3069
  await page.setContent(html, { waitUntil: "load" });
@@ -3265,9 +3298,10 @@ ${input.files.css}
3265
3298
  }
3266
3299
  var RESOLVE_DIR, TOLERANCE_PX, WIDTH_SLACK, IMAGE_SIMILARITY_FLOOR, INK_RECALL_FLOOR;
3267
3300
  var init_visual_facts = __esm({
3268
- "packages/verify/src/visual-facts.ts"() {
3301
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/visual-facts.ts"() {
3269
3302
  "use strict";
3270
3303
  init_browser();
3304
+ init_mount_limits();
3271
3305
  init_image_diff();
3272
3306
  RESOLVE_DIR = path7.resolve(path7.dirname(fileURLToPath2(import.meta.url)), "..");
3273
3307
  TOLERANCE_PX = 2;
@@ -3277,19 +3311,19 @@ var init_visual_facts = __esm({
3277
3311
  }
3278
3312
  });
3279
3313
 
3280
- // packages/verify/src/paths.ts
3314
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/paths.ts
3281
3315
  import path8 from "node:path";
3282
3316
  import { fileURLToPath as fileURLToPath3 } from "node:url";
3283
3317
  var VERIFY_PKG_DIR, REPO_ROOT;
3284
3318
  var init_paths = __esm({
3285
- "packages/verify/src/paths.ts"() {
3319
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/paths.ts"() {
3286
3320
  "use strict";
3287
3321
  VERIFY_PKG_DIR = path8.resolve(path8.dirname(fileURLToPath3(import.meta.url)), "..");
3288
3322
  REPO_ROOT = path8.resolve(VERIFY_PKG_DIR, "..", "..");
3289
3323
  }
3290
3324
  });
3291
3325
 
3292
- // packages/verify/src/font-resolve.ts
3326
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/font-resolve.ts
3293
3327
  import { createHash } from "node:crypto";
3294
3328
  import { existsSync as existsSync5, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "node:fs";
3295
3329
  import os2 from "node:os";
@@ -3299,6 +3333,21 @@ function fontCacheDir() {
3299
3333
  if (env !== void 0 && env !== "") return path9.resolve(env);
3300
3334
  return path9.join(os2.homedir(), ".tendril", "fonts");
3301
3335
  }
3336
+ function normalizeFontLicense(value) {
3337
+ return typeof value === "string" && FONT_LICENSES.includes(value) ? value : "unknown";
3338
+ }
3339
+ async function googleFontMetadata(queryName) {
3340
+ try {
3341
+ const res = await fetch(`https://fonts.google.com/metadata/fonts/${encodeURIComponent(queryName)}`, { headers: { "User-Agent": UA } });
3342
+ if (!res.ok) return { license: "unknown", family: null };
3343
+ const parsed = JSON.parse((await res.text()).replace(/^\)\]\}'\s*/, ""));
3344
+ const family = typeof parsed.family === "string" && parsed.family !== "" ? parsed.family : null;
3345
+ if (parsed.isOpenSource !== true || typeof parsed.license !== "string") return { license: "unknown", family };
3346
+ return { license: GOOGLE_LICENSE_IDS.get(parsed.license.toLowerCase()) ?? "unknown", family };
3347
+ } catch {
3348
+ return { license: "unknown", family: null };
3349
+ }
3350
+ }
3302
3351
  function googleQueryCandidates(family) {
3303
3352
  const stripped = family.replace(/\s+(Variable|VF)$/i, "");
3304
3353
  return stripped === family ? [family] : [family, stripped];
@@ -3309,12 +3358,14 @@ async function resolveFonts(family, weights, cacheDir = DEFAULT_FONT_CACHE) {
3309
3358
  const failures = [];
3310
3359
  let css = null;
3311
3360
  let lastStatus = 0;
3361
+ let servedName = family;
3312
3362
  try {
3313
3363
  for (const queryName of googleQueryCandidates(family)) {
3314
3364
  const cssUrl = `https://fonts.googleapis.com/css2?family=${encodeURIComponent(queryName).replace(/%20/g, "+")}:wght@${weights.join(";")}&display=swap`;
3315
3365
  const res = await fetch(cssUrl, { headers: { "User-Agent": UA } });
3316
3366
  if (res.ok) {
3317
3367
  css = await res.text();
3368
+ servedName = queryName;
3318
3369
  break;
3319
3370
  }
3320
3371
  lastStatus = res.status;
@@ -3328,6 +3379,7 @@ async function resolveFonts(family, weights, cacheDir = DEFAULT_FONT_CACHE) {
3328
3379
  } catch (err) {
3329
3380
  return { resolved, failures: weights.map((weight) => ({ family, weight, reason: `offline or fetch failed: ${err instanceof Error ? err.message : String(err)}` })) };
3330
3381
  }
3382
+ const meta = await googleFontMetadata(servedName);
3331
3383
  for (const weight of weights) {
3332
3384
  const blocks = [...css.matchAll(/@font-face\s*{[^}]*}/g)].map((m) => m[0]);
3333
3385
  const block = blocks.find((b) => b.includes(`font-weight: ${weight}`) && /unicode-range:[^;]*U\+0000/.test(b));
@@ -3346,7 +3398,7 @@ async function resolveFonts(family, weights, cacheDir = DEFAULT_FONT_CACHE) {
3346
3398
  const sha256 = createHash("sha256").update(bytes).digest("hex");
3347
3399
  const file = path9.join(cacheDir, `${family.toLowerCase().replace(/\s+/g, "-")}-${weight}.woff2`);
3348
3400
  writeFileSync3(file, bytes);
3349
- resolved.push({ family, weight, source: url, sha256, file });
3401
+ resolved.push({ family, weight, source: url, sha256, file, license: meta.license, ...meta.family !== null ? { servedFamily: meta.family } : {} });
3350
3402
  } catch (err) {
3351
3403
  failures.push({ family, weight, reason: `download failed: ${err instanceof Error ? err.message : String(err)}` });
3352
3404
  }
@@ -3372,7 +3424,7 @@ function addLocalFont(family, weight, filePath, cacheDir = DEFAULT_FONT_CACHE) {
3372
3424
  const sha256 = createHash("sha256").update(bytes).digest("hex");
3373
3425
  const file = path9.join(cacheDir, `${family.toLowerCase().replace(/\s+/g, "-")}-${weight}${ext}`);
3374
3426
  writeFileSync3(file, bytes);
3375
- const face = { family, weight, source: `local:${path9.basename(src)}`, sha256, file };
3427
+ const face = { family, weight, source: `local:${path9.basename(src)}`, sha256, file, license: "unknown" };
3376
3428
  const mPath = path9.join(cacheDir, "manifest.json");
3377
3429
  const prior = existsSync5(mPath) ? JSON.parse(readFileSync3(mPath, "utf8")) : [];
3378
3430
  const merged = [...prior.filter((p) => !(p.family === family && p.weight === weight)), { ...face, file: path9.basename(file) }];
@@ -3412,7 +3464,28 @@ function requiredFontsManifest(families, cacheDir = DEFAULT_FONT_CACHE) {
3412
3464
  const mPath = path9.join(cacheDir, "manifest.json");
3413
3465
  const manifest = existsSync5(mPath) ? JSON.parse(readFileSync3(mPath, "utf8")) : [];
3414
3466
  const wanted = new Set(families.map((f) => f.toLowerCase()));
3415
- return manifest.filter((f) => wanted.has(f.family.toLowerCase()));
3467
+ return manifest.filter((f) => wanted.has(f.family.toLowerCase())).map((f) => ({
3468
+ family: f.family,
3469
+ weight: f.weight,
3470
+ source: f.source,
3471
+ sha256: f.sha256,
3472
+ file: f.file,
3473
+ license: normalizeFontLicense(f.license),
3474
+ ...typeof f.servedFamily === "string" && f.servedFamily !== "" ? { servedFamily: f.servedFamily } : {}
3475
+ }));
3476
+ }
3477
+ function facesMissingLicense(cacheDir = DEFAULT_FONT_CACHE) {
3478
+ const mPath = path9.join(cacheDir, "manifest.json");
3479
+ if (!existsSync5(mPath)) return [];
3480
+ let entries;
3481
+ try {
3482
+ entries = JSON.parse(readFileSync3(mPath, "utf8"));
3483
+ } catch {
3484
+ return [];
3485
+ }
3486
+ return entries.filter(
3487
+ (e) => typeof e.family === "string" && typeof e.weight === "number" && typeof e.source === "string" && e.source.startsWith(GOOGLE_FONT_FILE_PREFIX) && !(typeof e.license === "string" && FONT_LICENSES.includes(e.license))
3488
+ ).map((e) => ({ family: e.family, weight: e.weight, sha256: e.sha256 }));
3416
3489
  }
3417
3490
  function verifiedFontFamilies(cacheDir = DEFAULT_FONT_CACHE) {
3418
3491
  const mPath = path9.join(cacheDir, "manifest.json");
@@ -3435,16 +3508,24 @@ function verifiedFontFamilies(cacheDir = DEFAULT_FONT_CACHE) {
3435
3508
  }
3436
3509
  return [...byFamily.entries()].map(([family, w]) => ({ family, weights: [...w].sort((a, b) => a - b) }));
3437
3510
  }
3438
- var DEFAULT_FONT_CACHE, UA;
3511
+ var DEFAULT_FONT_CACHE, UA, FONT_LICENSES, GOOGLE_LICENSE_IDS, GOOGLE_FONT_FILE_PREFIX;
3439
3512
  var init_font_resolve = __esm({
3440
- "packages/verify/src/font-resolve.ts"() {
3513
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/font-resolve.ts"() {
3441
3514
  "use strict";
3442
3515
  DEFAULT_FONT_CACHE = fontCacheDir();
3443
3516
  UA = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36";
3517
+ FONT_LICENSES = ["OFL-1.1", "Apache-2.0", "UFL-1.0", "proprietary", "unknown"];
3518
+ GOOGLE_LICENSE_IDS = /* @__PURE__ */ new Map([
3519
+ ["ofl", "OFL-1.1"],
3520
+ ["apache2", "Apache-2.0"],
3521
+ ["apache", "Apache-2.0"],
3522
+ ["ufl", "UFL-1.0"]
3523
+ ]);
3524
+ GOOGLE_FONT_FILE_PREFIX = "https://fonts.gstatic.com/";
3444
3525
  }
3445
3526
  });
3446
3527
 
3447
- // packages/verify/src/font-faces.ts
3528
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/font-faces.ts
3448
3529
  import { createHash as createHash2 } from "node:crypto";
3449
3530
  import { existsSync as existsSync6, readFileSync as readFileSync4 } from "node:fs";
3450
3531
  import path10 from "node:path";
@@ -3479,32 +3560,13 @@ function fontFaceCss(manifestPath2 = path10.join(fontCacheDir(), "manifest.json"
3479
3560
  }).join("\n");
3480
3561
  }
3481
3562
  var init_font_faces = __esm({
3482
- "packages/verify/src/font-faces.ts"() {
3563
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/font-faces.ts"() {
3483
3564
  "use strict";
3484
3565
  init_font_resolve();
3485
3566
  }
3486
3567
  });
3487
3568
 
3488
- // packages/verify/src/mount-limits.ts
3489
- function raceMountDeadline(work, deadlineMs, onDeadline) {
3490
- return Promise.race([
3491
- work,
3492
- new Promise((resolve) => {
3493
- const timer = setTimeout(() => resolve(onDeadline()), deadlineMs);
3494
- timer.unref();
3495
- })
3496
- ]);
3497
- }
3498
- var MEMORY_CAP_ARG, ENGINE_MOUNT_DEADLINE_MS;
3499
- var init_mount_limits = __esm({
3500
- "packages/verify/src/mount-limits.ts"() {
3501
- "use strict";
3502
- MEMORY_CAP_ARG = "--js-flags=--max-old-space-size=512";
3503
- ENGINE_MOUNT_DEADLINE_MS = 3e4;
3504
- }
3505
- });
3506
-
3507
- // packages/verify/src/admission.ts
3569
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/admission.ts
3508
3570
  import { readFileSync as readFileSync5, readdirSync as readdirSync2, existsSync as existsSync7, writeFileSync as writeFileSync4 } from "node:fs";
3509
3571
  import path11 from "node:path";
3510
3572
  import { build as build2 } from "esbuild";
@@ -3521,7 +3583,7 @@ function fontWeightsByFamily() {
3521
3583
  }
3522
3584
  var FONT_WEIGHTS;
3523
3585
  var init_admission = __esm({
3524
- "packages/verify/src/admission.ts"() {
3586
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/admission.ts"() {
3525
3587
  "use strict";
3526
3588
  init_paths();
3527
3589
  init_src();
@@ -3534,11 +3596,11 @@ var init_admission = __esm({
3534
3596
  }
3535
3597
  });
3536
3598
 
3537
- // packages/verify/src/tasks.ts
3599
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/tasks.ts
3538
3600
  import path12 from "node:path";
3539
3601
  var CALENDAR_CONFIGS, CALENDAR_API, CALENDAR_BEHAVIORS, BUTTON_CONFIGS, BUTTON_API, COMBO_FIX, COMBO_CONFIGS, COMBO_API, MODAL_CONFIGS, MODAL_API, BUTTON_BEHAVIORS, COMBO_BEHAVIORS, MODAL_BEHAVIORS, TASKS;
3540
3602
  var init_tasks = __esm({
3541
- "packages/verify/src/tasks.ts"() {
3603
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/tasks.ts"() {
3542
3604
  "use strict";
3543
3605
  init_paths();
3544
3606
  CALENDAR_CONFIGS = [
@@ -3730,7 +3792,7 @@ BEHAVIORAL CONTRACT (machine-verified, gating): the primary action and close con
3730
3792
  }
3731
3793
  });
3732
3794
 
3733
- // packages/verify/src/behavior.ts
3795
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/behavior.ts
3734
3796
  var behavior_exports = {};
3735
3797
  __export(behavior_exports, {
3736
3798
  checkBehaviors: () => checkBehaviors,
@@ -4080,7 +4142,7 @@ async function checkBehaviors(task, bundleDir, opts = {}) {
4080
4142
  const js = await compileMount(task, bundleDir);
4081
4143
  if (typeof js !== "string") return task.behaviors.map((b) => ({ id: b.id, pass: false, detail: js.error }));
4082
4144
  const css = ["tokens.css", "styles.css"].map((f) => path13.join(bundleDir, f)).filter((f) => existsSync8(f)).map((f) => readFileSync6(f, "utf8")).join("\n");
4083
- const server = await chromium3.launchServer({ executablePath: resolveChrome(), headless: true, args: [MEMORY_CAP_ARG] });
4145
+ const server = await chromium3.launchServer({ executablePath: resolveChrome(), headless: true, args: mountArgs() });
4084
4146
  const browser = await chromium3.connect(server.wsEndpoint());
4085
4147
  const results = [];
4086
4148
  let deadlined = false;
@@ -4186,7 +4248,7 @@ body{margin:0;padding:20px}
4186
4248
  }
4187
4249
  var _fontFaces, ANIMATED_PROBE, COMMIT_GAP_CLOSED, POSE_GAP_FLOOR, PRELUDE_ROOT_PROPS;
4188
4250
  var init_behavior = __esm({
4189
- "packages/verify/src/behavior.ts"() {
4251
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/behavior.ts"() {
4190
4252
  "use strict";
4191
4253
  init_runtime();
4192
4254
  init_browser();
@@ -4221,7 +4283,7 @@ var init_behavior = __esm({
4221
4283
  }
4222
4284
  });
4223
4285
 
4224
- // packages/verify/src/bundle-quality.ts
4286
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/bundle-quality.ts
4225
4287
  import { readFileSync as readFileSync7, rmSync as rmSync2, writeFileSync as writeFileSync5, existsSync as existsSync9 } from "node:fs";
4226
4288
  import path14 from "node:path";
4227
4289
  function definedVars(tokensCss) {
@@ -4279,7 +4341,7 @@ async function checkBundleQuality(bundleDir, entry, set) {
4279
4341
  return { findings, tokensAbsent: tokensCss === void 0 && !/var\(\s*--/.test(css) };
4280
4342
  }
4281
4343
  var init_bundle_quality = __esm({
4282
- "packages/verify/src/bundle-quality.ts"() {
4344
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/bundle-quality.ts"() {
4283
4345
  "use strict";
4284
4346
  init_src();
4285
4347
  init_runtime();
@@ -4288,7 +4350,7 @@ var init_bundle_quality = __esm({
4288
4350
  }
4289
4351
  });
4290
4352
 
4291
- // packages/verify/src/effect-geometry.ts
4353
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/effect-geometry.ts
4292
4354
  function fold(into, dx, dy, radius, spread) {
4293
4355
  const reach = radius + spread;
4294
4356
  into.top = Math.max(into.top, reach - dy);
@@ -4320,13 +4382,13 @@ function extentsExplainPad(near, far, pad, tolerance = 2) {
4320
4382
  }
4321
4383
  var NO_EXTENTS;
4322
4384
  var init_effect_geometry = __esm({
4323
- "packages/verify/src/effect-geometry.ts"() {
4385
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/effect-geometry.ts"() {
4324
4386
  "use strict";
4325
4387
  NO_EXTENTS = { top: 0, right: 0, bottom: 0, left: 0 };
4326
4388
  }
4327
4389
  });
4328
4390
 
4329
- // packages/verify/src/bundle-score.ts
4391
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/bundle-score.ts
4330
4392
  import { existsSync as existsSync10, mkdirSync as mkdirSync3, readFileSync as readFileSync8, writeFileSync as writeFileSync6 } from "node:fs";
4331
4393
  import path15 from "node:path";
4332
4394
  import { build as build4 } from "esbuild";
@@ -4512,7 +4574,7 @@ if (root && C) createRoot(root).render(createElement(C, cfg.props));
4512
4574
  }
4513
4575
  return detectBackdrop(ref);
4514
4576
  };
4515
- const server = await chromium4.launchServer({ executablePath: resolveChrome(), headless: true, args: [MEMORY_CAP_ARG] });
4577
+ const server = await chromium4.launchServer({ executablePath: resolveChrome(), headless: true, args: mountArgs() });
4516
4578
  const browser = await chromium4.connect(server.wsEndpoint());
4517
4579
  const scores = [];
4518
4580
  try {
@@ -4626,7 +4688,7 @@ body{margin:0;background:rgb(${backdrop.join(",")})}
4626
4688
  }
4627
4689
  var BAR, MARGIN, _fontFaces2, CONFIGS, SEAT_WINDOW, EFFECT_BLEED_MAX;
4628
4690
  var init_bundle_score = __esm({
4629
- "packages/verify/src/bundle-score.ts"() {
4691
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/bundle-score.ts"() {
4630
4692
  "use strict";
4631
4693
  init_runtime();
4632
4694
  init_browser();
@@ -4644,11 +4706,11 @@ var init_bundle_score = __esm({
4644
4706
  }
4645
4707
  });
4646
4708
 
4647
- // packages/verify/src/containment.ts
4709
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/containment.ts
4648
4710
  import { build as build5 } from "esbuild";
4649
4711
  import { chromium as chromium5 } from "playwright-core";
4650
4712
  var init_containment = __esm({
4651
- "packages/verify/src/containment.ts"() {
4713
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/containment.ts"() {
4652
4714
  "use strict";
4653
4715
  init_runtime();
4654
4716
  init_browser();
@@ -4658,10 +4720,10 @@ var init_containment = __esm({
4658
4720
  }
4659
4721
  });
4660
4722
 
4661
- // packages/verify/src/prelude.ts
4723
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/prelude.ts
4662
4724
  var PRELUDE_CONTRACT;
4663
4725
  var init_prelude = __esm({
4664
- "packages/verify/src/prelude.ts"() {
4726
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/prelude.ts"() {
4665
4727
  "use strict";
4666
4728
  PRELUDE_CONTRACT = `BUNDLE PRELUDE (machine-verified on computed styles \u2014 the harness page provides NONE of this; your CSS must):
4667
4729
  - Containment reset on the component subtree: margin 0, box-sizing border-box, line-height/letter-spacing/font-family inherited from the root (host globals must not leak in).
@@ -4673,7 +4735,7 @@ var init_prelude = __esm({
4673
4735
  }
4674
4736
  });
4675
4737
 
4676
- // packages/verify/src/parity.ts
4738
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/parity.ts
4677
4739
  import { existsSync as existsSync11, readFileSync as readFileSync9 } from "node:fs";
4678
4740
  import path16 from "node:path";
4679
4741
  import { chromium as chromium6 } from "playwright-core";
@@ -4705,7 +4767,7 @@ async function checkHoverParity(task, bundleDir, opts = {}) {
4705
4767
  const js = await compileMount(task, bundleDir);
4706
4768
  if (typeof js !== "string") return configs.map((c) => ({ id: `parity:${c.rep}`, pass: false, detail: js.error }));
4707
4769
  const css = ["tokens.css", "styles.css"].map((f) => path16.join(bundleDir, f)).filter((f) => existsSync11(f)).map((f) => readFileSync9(f, "utf8")).join("\n");
4708
- const server = await chromium6.launchServer({ executablePath: resolveChrome(), headless: true, args: [MEMORY_CAP_ARG] });
4770
+ const server = await chromium6.launchServer({ executablePath: resolveChrome(), headless: true, args: mountArgs() });
4709
4771
  const browser = await chromium6.connect(server.wsEndpoint());
4710
4772
  const results = [];
4711
4773
  try {
@@ -4773,7 +4835,7 @@ body{margin:0;padding:20px}
4773
4835
  }
4774
4836
  var _fontFaces3;
4775
4837
  var init_parity = __esm({
4776
- "packages/verify/src/parity.ts"() {
4838
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/parity.ts"() {
4777
4839
  "use strict";
4778
4840
  init_browser();
4779
4841
  init_behavior();
@@ -4782,7 +4844,7 @@ var init_parity = __esm({
4782
4844
  }
4783
4845
  });
4784
4846
 
4785
- // packages/verify/src/composition.ts
4847
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/composition.ts
4786
4848
  import { createRequire as createRequire2 } from "node:module";
4787
4849
  import { existsSync as existsSync12, readFileSync as readFileSync10 } from "node:fs";
4788
4850
  import path17 from "node:path";
@@ -4879,7 +4941,7 @@ async function checkCropComposition(task, bundleDir, regions, opts = {}) {
4879
4941
  return regions.map((r) => ({ id: cropId(r), pass: false, similarity: 0, inkRecall: 0, detail: js.error }));
4880
4942
  }
4881
4943
  const css = ["tokens.css", "styles.css"].map((f) => path17.join(bundleDir, f)).filter((f) => existsSync12(f)).map((f) => readFileSync10(f, "utf8")).join("\n");
4882
- const server = await chromium7.launchServer({ executablePath: resolveChrome(), headless: true, args: [MEMORY_CAP_ARG] });
4944
+ const server = await chromium7.launchServer({ executablePath: resolveChrome(), headless: true, args: mountArgs() });
4883
4945
  const browser = await chromium7.connect(server.wsEndpoint());
4884
4946
  const PAD = 4;
4885
4947
  try {
@@ -4984,7 +5046,7 @@ async function checkStructuralComposition(task, bundleDir, roles, opts = {}) {
4984
5046
  const js = await compileInstrumentedMount(task, bundleDir);
4985
5047
  if (typeof js !== "string") return [...results, ...mains.map((m) => ({ id: `composition:${m}`, pass: false, detail: js.error }))];
4986
5048
  const css = ["tokens.css", "styles.css"].map((f) => path17.join(bundleDir, f)).filter((f) => existsSync12(f)).map((f) => readFileSync10(f, "utf8")).join("\n");
4987
- const server = await chromium7.launchServer({ executablePath: resolveChrome(), headless: true, args: [MEMORY_CAP_ARG] });
5049
+ const server = await chromium7.launchServer({ executablePath: resolveChrome(), headless: true, args: mountArgs() });
4988
5050
  const browser = await chromium7.connect(server.wsEndpoint());
4989
5051
  try {
4990
5052
  for (const mainSlug of mains) {
@@ -5048,7 +5110,7 @@ body{margin:0;padding:20px}
5048
5110
  }
5049
5111
  var _fontFaces4, REAL_JSX_SPEC, JSX_SHIM, CROP_BAR, cropId;
5050
5112
  var init_composition = __esm({
5051
- "packages/verify/src/composition.ts"() {
5113
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/composition.ts"() {
5052
5114
  "use strict";
5053
5115
  init_runtime();
5054
5116
  init_browser();
@@ -5072,7 +5134,7 @@ export const jsxs = (t, p, k) => real.jsxs(t, inject(t, p), k);
5072
5134
  }
5073
5135
  });
5074
5136
 
5075
- // packages/verify/src/occlusion.ts
5137
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/occlusion.ts
5076
5138
  import { existsSync as existsSync13 } from "node:fs";
5077
5139
  import path18 from "node:path";
5078
5140
  import { build as build7 } from "esbuild";
@@ -5124,7 +5186,7 @@ async function checkSiblingOcclusion(task, bundleDir, css, opts = {}) {
5124
5186
  const js = await compileTwoUp(task, bundleDir);
5125
5187
  if (typeof js !== "string") return [{ id: "sibling-overlay-hit-testable", pass: false, detail: js.error }];
5126
5188
  const timeoutMs = opts.mountDeadlineMs ?? ENGINE_MOUNT_DEADLINE_MS;
5127
- const server = await chromium8.launchServer({ executablePath: resolveChrome(), headless: true, args: [MEMORY_CAP_ARG] });
5189
+ const server = await chromium8.launchServer({ executablePath: resolveChrome(), headless: true, args: mountArgs() });
5128
5190
  const browser = await chromium8.connect(server.wsEndpoint());
5129
5191
  try {
5130
5192
  const work = (async () => {
@@ -5221,7 +5283,7 @@ body{margin:0;padding:16px;display:flex;flex-direction:column;gap:8px;align-item
5221
5283
  }
5222
5284
  var OVERLAY_SELECTOR;
5223
5285
  var init_occlusion = __esm({
5224
- "packages/verify/src/occlusion.ts"() {
5286
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/occlusion.ts"() {
5225
5287
  "use strict";
5226
5288
  init_runtime();
5227
5289
  init_browser();
@@ -5230,9 +5292,9 @@ var init_occlusion = __esm({
5230
5292
  }
5231
5293
  });
5232
5294
 
5233
- // packages/verify/src/index.ts
5295
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/index.ts
5234
5296
  var init_src4 = __esm({
5235
- "packages/verify/src/index.ts"() {
5297
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/verify/src/index.ts"() {
5236
5298
  "use strict";
5237
5299
  init_browser();
5238
5300
  init_runtime();
@@ -5250,6 +5312,7 @@ var init_src4 = __esm({
5250
5312
  init_containment();
5251
5313
  init_tasks();
5252
5314
  init_prelude();
5315
+ init_mount_limits();
5253
5316
  init_font_faces();
5254
5317
  init_font_resolve();
5255
5318
  init_paths();
@@ -5259,7 +5322,7 @@ var init_src4 = __esm({
5259
5322
  }
5260
5323
  });
5261
5324
 
5262
- // packages/cli/src/environment.ts
5325
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/environment.ts
5263
5326
  import { existsSync as existsSync14, readFileSync as readFileSync11 } from "node:fs";
5264
5327
  import path19 from "node:path";
5265
5328
  import { createHash as createHash3 } from "node:crypto";
@@ -5289,23 +5352,25 @@ function environmentStamp(taskFamilies) {
5289
5352
  chrome = resolveChrome();
5290
5353
  } catch {
5291
5354
  }
5292
- return { chrome, chromeVersion: chrome === "unavailable" ? null : chromeVersion(), fontsManifestSha256: fontsHash };
5355
+ const ver = chrome === "unavailable" ? null : chromeVersion();
5356
+ const lcdSuffix = lcdTextEnabled() ? " (lcd-text-enabled)" : "";
5357
+ return { chrome, chromeVersion: ver === null ? null : ver + lcdSuffix, fontsManifestSha256: fontsHash };
5293
5358
  }
5294
5359
  var init_environment = __esm({
5295
- "packages/cli/src/environment.ts"() {
5360
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/environment.ts"() {
5296
5361
  "use strict";
5297
5362
  init_src4();
5298
5363
  }
5299
5364
  });
5300
5365
 
5301
- // packages/cli/src/describe.ts
5366
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/describe.ts
5302
5367
  function printDescription(description) {
5303
5368
  process.stdout.write(`${JSON.stringify(description, null, 2)}
5304
5369
  `);
5305
5370
  }
5306
5371
  var COMMON_EXIT_CODES;
5307
5372
  var init_describe = __esm({
5308
- "packages/cli/src/describe.ts"() {
5373
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/describe.ts"() {
5309
5374
  "use strict";
5310
5375
  COMMON_EXIT_CODES = {
5311
5376
  0: "success",
@@ -5317,7 +5382,7 @@ var init_describe = __esm({
5317
5382
  }
5318
5383
  });
5319
5384
 
5320
- // packages/cli/src/env.ts
5385
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/env.ts
5321
5386
  import { existsSync as existsSync15, readFileSync as readFileSync12 } from "node:fs";
5322
5387
  import path20 from "node:path";
5323
5388
  function parseEnv(content) {
@@ -5336,12 +5401,12 @@ function resolveCredential(name) {
5336
5401
  return parseEnv(readFileSync12(envPath, "utf8")).get(name);
5337
5402
  }
5338
5403
  var init_env = __esm({
5339
- "packages/cli/src/env.ts"() {
5404
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/env.ts"() {
5340
5405
  "use strict";
5341
5406
  }
5342
5407
  });
5343
5408
 
5344
- // packages/cli/src/output.ts
5409
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/output.ts
5345
5410
  var output_exports = {};
5346
5411
  __export(output_exports, {
5347
5412
  PROGRESS_PREFIX: () => PROGRESS_PREFIX,
@@ -5385,14 +5450,14 @@ function warn(flags, message) {
5385
5450
  }
5386
5451
  var PROGRESS_PREFIX;
5387
5452
  var init_output = __esm({
5388
- "packages/cli/src/output.ts"() {
5453
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/output.ts"() {
5389
5454
  "use strict";
5390
5455
  init_src3();
5391
5456
  PROGRESS_PREFIX = "@tendril-progress ";
5392
5457
  }
5393
5458
  });
5394
5459
 
5395
- // packages/cli/src/entitlement.ts
5460
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/entitlement.ts
5396
5461
  import { chmodSync, existsSync as existsSync16, mkdirSync as mkdirSync4, readFileSync as readFileSync13, writeFileSync as writeFileSync7 } from "node:fs";
5397
5462
  import crypto from "node:crypto";
5398
5463
  import os3 from "node:os";
@@ -5480,7 +5545,7 @@ function requireEntitlement(flags) {
5480
5545
  }
5481
5546
  var ENT_PREFIX, PUBLIC_KEYS, TOLERANCE_MS, CLOCK_ROLLBACK_MS, b64urlDecode, ACTIVATE_REMEDIATION;
5482
5547
  var init_entitlement = __esm({
5483
- "packages/cli/src/entitlement.ts"() {
5548
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/entitlement.ts"() {
5484
5549
  "use strict";
5485
5550
  init_src3();
5486
5551
  init_output();
@@ -5493,7 +5558,7 @@ var init_entitlement = __esm({
5493
5558
  }
5494
5559
  });
5495
5560
 
5496
- // packages/cli/src/commands/doctor.ts
5561
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/commands/doctor.ts
5497
5562
  import { spawnSync } from "node:child_process";
5498
5563
  import { existsSync as existsSync17, readFileSync as readFileSync14, readdirSync as readdirSync3 } from "node:fs";
5499
5564
  import os4 from "node:os";
@@ -5532,7 +5597,7 @@ async function runDoctorChecks(options) {
5532
5597
  );
5533
5598
  try {
5534
5599
  const chrome = resolveChrome();
5535
- checks.push({ name: "browser", ok: true, detail: `${chromeVersion() ?? "version unknown"} at ${chrome}` });
5600
+ checks.push({ name: "browser", ok: true, detail: `${chromeVersion() ?? "version unknown"}${lcdTextEnabled() ? " \u2014 EXPERIMENT override active (lcd-text-enabled): scores not comparable to canonical greyscale runs" : ""} at ${chrome}` });
5536
5601
  } catch (err) {
5537
5602
  checks.push({
5538
5603
  name: "browser",
@@ -5670,7 +5735,7 @@ async function runDoctor(flags) {
5670
5735
  }
5671
5736
  var DEFAULT_MCP_URL, DOCTOR_DESCRIPTION;
5672
5737
  var init_doctor = __esm({
5673
- "packages/cli/src/commands/doctor.ts"() {
5738
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/commands/doctor.ts"() {
5674
5739
  "use strict";
5675
5740
  init_src4();
5676
5741
  init_src();
@@ -5698,7 +5763,7 @@ var init_doctor = __esm({
5698
5763
  }
5699
5764
  });
5700
5765
 
5701
- // packages/llm/src/model-config.ts
5766
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/llm/src/model-config.ts
5702
5767
  import { z as z6 } from "zod";
5703
5768
  function resolveModel(config, requestedId) {
5704
5769
  const entry = config.allowlist.find((m) => m.id === requestedId);
@@ -5719,7 +5784,7 @@ function resolveModel(config, requestedId) {
5719
5784
  }
5720
5785
  var ModelStatusSchema, ModelEntrySchema, ModelConfigSchema, DEFAULT_MODEL_CONFIG;
5721
5786
  var init_model_config = __esm({
5722
- "packages/llm/src/model-config.ts"() {
5787
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/llm/src/model-config.ts"() {
5723
5788
  "use strict";
5724
5789
  ModelStatusSchema = z6.enum(["verified", "degraded"]);
5725
5790
  ModelEntrySchema = z6.object({
@@ -5808,10 +5873,10 @@ var init_model_config = __esm({
5808
5873
  }
5809
5874
  });
5810
5875
 
5811
- // packages/llm/src/openrouter.ts
5876
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/llm/src/openrouter.ts
5812
5877
  var FALLBACK_KINDS, DEFAULT_REQUEST_TIMEOUT_MS, OpenRouterClient;
5813
5878
  var init_openrouter = __esm({
5814
- "packages/llm/src/openrouter.ts"() {
5879
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/llm/src/openrouter.ts"() {
5815
5880
  "use strict";
5816
5881
  FALLBACK_KINDS = /* @__PURE__ */ new Set(["rate-limit", "server", "network", "timeout"]);
5817
5882
  DEFAULT_REQUEST_TIMEOUT_MS = 6e5;
@@ -5938,7 +6003,7 @@ var init_openrouter = __esm({
5938
6003
  }
5939
6004
  });
5940
6005
 
5941
- // packages/llm/src/semantics.ts
6006
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/llm/src/semantics.ts
5942
6007
  import { z as z7 } from "zod";
5943
6008
  function portable(node) {
5944
6009
  if (Array.isArray(node)) return node.map(portable);
@@ -5976,7 +6041,7 @@ function docsJsonSchema() {
5976
6041
  }
5977
6042
  var PropTypeSchema, SemanticsSchema, CodegenOutputSchema, DocsOutputSchema;
5978
6043
  var init_semantics = __esm({
5979
- "packages/llm/src/semantics.ts"() {
6044
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/llm/src/semantics.ts"() {
5980
6045
  "use strict";
5981
6046
  PropTypeSchema = z7.discriminatedUnion("kind", [
5982
6047
  z7.object({ kind: z7.literal("enum"), values: z7.array(z7.string()).min(1) }),
@@ -6065,10 +6130,10 @@ var init_semantics = __esm({
6065
6130
  }
6066
6131
  });
6067
6132
 
6068
- // packages/llm/src/golden/button.ts
6133
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/llm/src/golden/button.ts
6069
6134
  var goldenButtonSemantics, goldenButtonCode, goldenButtonDocs;
6070
6135
  var init_button2 = __esm({
6071
- "packages/llm/src/golden/button.ts"() {
6136
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/llm/src/golden/button.ts"() {
6072
6137
  "use strict";
6073
6138
  goldenButtonSemantics = {
6074
6139
  componentName: "Button",
@@ -6226,7 +6291,7 @@ handling come from the platform.
6226
6291
  }
6227
6292
  });
6228
6293
 
6229
- // packages/llm/src/prompt.ts
6294
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/llm/src/prompt.ts
6230
6295
  function buildStablePrefix(input) {
6231
6296
  const tokens = [...input.tokenLines].sort().join("\n");
6232
6297
  const golden = `GOLDEN EXAMPLE (canonical quality bar)
@@ -6260,7 +6325,7 @@ ${input.irJson}` });
6260
6325
  }
6261
6326
  var SYSTEM_RULES;
6262
6327
  var init_prompt = __esm({
6263
- "packages/llm/src/prompt.ts"() {
6328
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/llm/src/prompt.ts"() {
6264
6329
  "use strict";
6265
6330
  init_button2();
6266
6331
  SYSTEM_RULES = `You generate production React components from a design-system IR.
@@ -6356,10 +6421,10 @@ strictly in the requested JSON shape.`;
6356
6421
  }
6357
6422
  });
6358
6423
 
6359
- // packages/llm/src/generation-model.ts
6424
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/llm/src/generation-model.ts
6360
6425
  var MockGenerationModel, MAX_SCHEMA_ATTEMPTS, OpenRouterGenerationModel;
6361
6426
  var init_generation_model = __esm({
6362
- "packages/llm/src/generation-model.ts"() {
6427
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/llm/src/generation-model.ts"() {
6363
6428
  "use strict";
6364
6429
  init_openrouter();
6365
6430
  init_prompt();
@@ -6516,9 +6581,9 @@ ${JSON.stringify(semantics)}`,
6516
6581
  }
6517
6582
  });
6518
6583
 
6519
- // packages/llm/src/index.ts
6584
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/llm/src/index.ts
6520
6585
  var init_src5 = __esm({
6521
- "packages/llm/src/index.ts"() {
6586
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/llm/src/index.ts"() {
6522
6587
  "use strict";
6523
6588
  init_model_config();
6524
6589
  init_openrouter();
@@ -6529,11 +6594,11 @@ var init_src5 = __esm({
6529
6594
  }
6530
6595
  });
6531
6596
 
6532
- // packages/metadata/src/component-json.ts
6597
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/metadata/src/component-json.ts
6533
6598
  import { z as z8 } from "zod";
6534
6599
  var TokenUseSchema, AntiPatternSchema, ComponentJsonSchema;
6535
6600
  var init_component_json = __esm({
6536
- "packages/metadata/src/component-json.ts"() {
6601
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/metadata/src/component-json.ts"() {
6537
6602
  "use strict";
6538
6603
  TokenUseSchema = z8.object({
6539
6604
  /** DTCG token path, e.g. "color.primary". */
@@ -6585,7 +6650,7 @@ var init_component_json = __esm({
6585
6650
  }
6586
6651
  });
6587
6652
 
6588
- // packages/metadata/src/extract.ts
6653
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/metadata/src/extract.ts
6589
6654
  import { parse } from "react-docgen";
6590
6655
  function extractProps(tsxSource, filename) {
6591
6656
  const docs = parse(tsxSource, { filename });
@@ -6658,17 +6723,74 @@ function buildComponentJson(input) {
6658
6723
  });
6659
6724
  }
6660
6725
  var init_extract = __esm({
6661
- "packages/metadata/src/extract.ts"() {
6726
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/metadata/src/extract.ts"() {
6662
6727
  "use strict";
6663
6728
  init_component_json();
6664
6729
  }
6665
6730
  });
6666
6731
 
6667
- // packages/metadata/src/recording-set.ts
6732
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/metadata/src/recording-set.ts
6668
6733
  import { z as z9 } from "zod";
6669
- var RECORDING_SET_VERSION, EnvelopeSchema, RepEntrySchema, RolesSchema, RecordingSetManifestSchema;
6734
+ function roleLossToken(loss) {
6735
+ return loss.kind === "main" ? `main:${loss.main}` : `part:${loss.part}${EDGE_ARROW}${loss.main}`;
6736
+ }
6737
+ function parseRoleLossToken(token) {
6738
+ if (token.startsWith("main:")) {
6739
+ const main2 = token.slice("main:".length);
6740
+ return main2 === "" ? void 0 : { kind: "main", main: main2 };
6741
+ }
6742
+ if (!token.startsWith("part:")) return void 0;
6743
+ const [part, main, ...rest] = token.slice("part:".length).split(EDGE_ARROW);
6744
+ if (rest.length > 0 || part === void 0 || part === "" || main === void 0 || main === "") return void 0;
6745
+ return { kind: "edge", part, main };
6746
+ }
6747
+ function validateRecordingSet(manifest, fileExists) {
6748
+ const issues = [];
6749
+ const parsed = RecordingSetManifestSchema.safeParse(manifest);
6750
+ if (!parsed.success) {
6751
+ return {
6752
+ issues: [
6753
+ {
6754
+ severity: "error",
6755
+ message: `manifest does not match recording-set layout v${RECORDING_SET_VERSION}: ${parsed.error.issues.slice(0, 3).map((i) => `${i.path.join(".")}: ${i.message}`).join("; ")}`
6756
+ }
6757
+ ]
6758
+ };
6759
+ }
6760
+ const m = parsed.data;
6761
+ const slugs = /* @__PURE__ */ new Set();
6762
+ for (const rep of m.reps) {
6763
+ if (slugs.has(rep.slug)) issues.push({ severity: "error", message: `duplicate rep slug "${rep.slug}"` });
6764
+ slugs.add(rep.slug);
6765
+ for (const f of REQUIRED_REP_FILES) {
6766
+ if (!fileExists(`${rep.slug}/${f}`)) issues.push({ severity: "error", message: `${rep.slug}: missing ${f}` });
6767
+ }
6768
+ if (rep.sourceFrame !== void 0 && m.sourceFrames?.[rep.sourceFrame] === void 0)
6769
+ issues.push({ severity: "warning", message: `${rep.slug}: sourceFrame ${rep.sourceFrame} not described in sourceFrames` });
6770
+ }
6771
+ if (m.roles !== void 0) {
6772
+ for (const slug of m.roles.main)
6773
+ if (!slugs.has(slug)) issues.push({ severity: "error", message: `roles.main references unknown slug "${slug}"` });
6774
+ for (const [slug, part] of Object.entries(m.roles.parts)) {
6775
+ if (!slugs.has(slug)) issues.push({ severity: "error", message: `roles.parts references unknown slug "${slug}"` });
6776
+ for (const of of part.partOf)
6777
+ if (!m.roles.main.includes(of)) issues.push({ severity: "error", message: `roles.parts["${slug}"].partOf references non-main "${of}"` });
6778
+ }
6779
+ for (const token of m.roles.narrowingAccepted ?? []) {
6780
+ const loss = parseRoleLossToken(token);
6781
+ if (loss === void 0) {
6782
+ issues.push({ severity: "error", message: `roles.narrowingAccepted entry "${token}" is not "main:<slug>" or "part:<part-slug>-><main-slug>"` });
6783
+ continue;
6784
+ }
6785
+ for (const slug of loss.kind === "main" ? [loss.main] : [loss.part, loss.main])
6786
+ if (!slugs.has(slug)) issues.push({ severity: "error", message: `roles.narrowingAccepted "${token}" references unknown slug "${slug}"` });
6787
+ }
6788
+ }
6789
+ return { manifest: m, issues };
6790
+ }
6791
+ var RECORDING_SET_VERSION, EnvelopeSchema, RepEntrySchema, RolesSchema, EDGE_ARROW, RecordingSetManifestSchema, REQUIRED_REP_FILES;
6670
6792
  var init_recording_set = __esm({
6671
- "packages/metadata/src/recording-set.ts"() {
6793
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/metadata/src/recording-set.ts"() {
6672
6794
  "use strict";
6673
6795
  RECORDING_SET_VERSION = 1;
6674
6796
  EnvelopeSchema = z9.object({
@@ -6699,10 +6821,21 @@ var init_recording_set = __esm({
6699
6821
  * derivation — disclosed, never silently dropped (Calendar's Icon
6700
6822
  * Buttons; unrecorded base variants). */
6701
6823
  external: z9.array(z9.string()).optional(),
6702
- /** True when a human override changed derived roles (surfaced in
6703
- * provenance downstream). */
6704
- humanOverride: z9.boolean().optional()
6824
+ /** Where this graph came from. A graph with empty `parts` makes the
6825
+ * structural composition check return an affirmative PASS, so a
6826
+ * human-authored override and a derived graph must never be
6827
+ * indistinguishable in a report. The CLI stamps this itself — a
6828
+ * supplied roles file cannot claim "derived" for itself. */
6829
+ rolesSource: z9.enum(["derived", "human-override"]).optional(),
6830
+ /** Losses in the DERIVED relation a human override deliberately
6831
+ * accepts, one token per loss (`roleLossToken`). Named one by one on
6832
+ * purpose: emptying out what composition measures — by dropping a
6833
+ * main, or by dropping/re-pointing a part→main edge — is exactly what
6834
+ * turns composition into a vacuous pass, so it is an acceptance
6835
+ * someone signs rather than an omission nobody notices. */
6836
+ narrowingAccepted: z9.array(z9.string()).optional()
6705
6837
  });
6838
+ EDGE_ARROW = "->";
6706
6839
  RecordingSetManifestSchema = z9.object({
6707
6840
  version: z9.literal(RECORDING_SET_VERSION),
6708
6841
  /** Human-readable component/system name. */
@@ -6714,10 +6847,11 @@ var init_recording_set = __esm({
6714
6847
  notRecorded: z9.string().optional(),
6715
6848
  roles: RolesSchema.optional()
6716
6849
  });
6850
+ REQUIRED_REP_FILES = ["get_design_context.json", "get_metadata.json", "get_screenshot.json"];
6717
6851
  }
6718
6852
  });
6719
6853
 
6720
- // packages/metadata/src/bundle.ts
6854
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/metadata/src/bundle.ts
6721
6855
  import { z as z10 } from "zod";
6722
6856
  function readBundleManifest(raw) {
6723
6857
  if (Buffer.byteLength(raw, "utf8") > MAX_BUNDLE_MANIFEST_BYTES) {
@@ -6786,7 +6920,7 @@ function hashRecordingSet(relPaths, readFile, sha256) {
6786
6920
  }
6787
6921
  var BUNDLE_VERSION, ConfigStatusSchema, PinnedPropSchema, PropAdapterSchema, RequiredFontSchema, ConfigClaimSchema, BehaviorClaimSchema, BundleProvenanceSchema, BundleComponentJsonSchema, MAX_BUNDLE_MANIFEST_BYTES, MAX_BUNDLE_SOURCE_BYTES;
6788
6922
  var init_bundle = __esm({
6789
- "packages/metadata/src/bundle.ts"() {
6923
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/metadata/src/bundle.ts"() {
6790
6924
  "use strict";
6791
6925
  init_recording_set();
6792
6926
  BUNDLE_VERSION = 1;
@@ -6884,9 +7018,9 @@ var init_bundle = __esm({
6884
7018
  }
6885
7019
  });
6886
7020
 
6887
- // packages/metadata/src/index.ts
7021
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/metadata/src/index.ts
6888
7022
  var init_src6 = __esm({
6889
- "packages/metadata/src/index.ts"() {
7023
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/metadata/src/index.ts"() {
6890
7024
  "use strict";
6891
7025
  init_component_json();
6892
7026
  init_extract();
@@ -6895,7 +7029,7 @@ var init_src6 = __esm({
6895
7029
  }
6896
7030
  });
6897
7031
 
6898
- // packages/cli/src/commands/activate.ts
7032
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/commands/activate.ts
6899
7033
  var activate_exports = {};
6900
7034
  __export(activate_exports, {
6901
7035
  ENTITLEMENT_SERVICE_URL: () => ENTITLEMENT_SERVICE_URL,
@@ -6980,7 +7114,7 @@ Waiting for approval\u2026
6980
7114
  }
6981
7115
  var ENTITLEMENT_SERVICE_URL;
6982
7116
  var init_activate = __esm({
6983
- "packages/cli/src/commands/activate.ts"() {
7117
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/commands/activate.ts"() {
6984
7118
  "use strict";
6985
7119
  init_src3();
6986
7120
  init_entitlement();
@@ -6989,12 +7123,13 @@ var init_activate = __esm({
6989
7123
  }
6990
7124
  });
6991
7125
 
6992
- // packages/cli/src/commands/record.ts
7126
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/commands/record.ts
6993
7127
  var record_exports = {};
6994
7128
  __export(record_exports, {
6995
7129
  instanceLeads: () => instanceLeads,
6996
7130
  isFigmaAssetUrl: () => isFigmaAssetUrl,
6997
7131
  isLocalAssetUrl: () => isLocalAssetUrl,
7132
+ narrowedRoles: () => narrowedRoles,
6998
7133
  nextPayload: () => nextPayload,
6999
7134
  runRecordAsset: () => runRecordAsset,
7000
7135
  runRecordFetch: () => runRecordFetch,
@@ -7531,11 +7666,66 @@ ${status.reps.filter((r) => r.missing.length > 0).length} rep(s) pending
7531
7666
  `);
7532
7667
  });
7533
7668
  }
7669
+ function narrowedRoles(derived, override) {
7670
+ const losses = [];
7671
+ const mains = new Set(override.main);
7672
+ for (const main of derived.main) if (!mains.has(main)) losses.push({ kind: "main", main });
7673
+ for (const [part, entry] of Object.entries(derived.parts))
7674
+ for (const main of entry.partOf) if (override.parts[part]?.partOf.includes(main) !== true) losses.push({ kind: "edge", part, main });
7675
+ return losses.sort((a, b) => roleLossToken(a) < roleLossToken(b) ? -1 : 1);
7676
+ }
7677
+ function rolesFromFile(opts, file, derived) {
7678
+ let json;
7679
+ try {
7680
+ json = JSON.parse(readFileSync16(path25.resolve(file), "utf8"));
7681
+ } catch (err) {
7682
+ fail(opts, ExitCode.InputValidation, {
7683
+ error: `cannot read roles file ${file}: ${err instanceof Error ? err.message.split("\n")[0] : String(err)}`,
7684
+ code: "roles-file-unreadable",
7685
+ remediation: 'The roles file is JSON: {"main":["<slug>"],"parts":{"<slug>":{"partOf":["<main-slug>"]}}}.'
7686
+ });
7687
+ }
7688
+ const parsed = RolesSchema.safeParse(json);
7689
+ if (!parsed.success) {
7690
+ fail(opts, ExitCode.InputValidation, {
7691
+ error: `roles file rejected: ${parsed.error.issues.slice(0, 3).map((i) => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`,
7692
+ code: "roles-file-invalid",
7693
+ remediation: 'The roles file is JSON: {"main":["<slug>"],"parts":{"<slug>":{"partOf":["<main-slug>"]}},"external":["\u2026"]}.'
7694
+ });
7695
+ }
7696
+ const accepted = parsed.data.narrowingAccepted ?? [];
7697
+ const unaccepted = narrowedRoles(derived, parsed.data).filter((loss) => !accepted.includes(roleLossToken(loss)));
7698
+ if (unaccepted.length > 0) {
7699
+ fail(opts, ExitCode.InputValidation, {
7700
+ error: `roles file narrows what this set's derivation found: it ${unaccepted.map(describeRoleLoss).join("; ")} \u2014 a main the graph never names is not composition-checked at all, and a main whose graph names no parts passes the check vacuously`,
7701
+ code: "roles-file-narrows",
7702
+ remediation: `Keep the derived mains and part edges in the graph, or accept each loss by name: add "narrowingAccepted": ${JSON.stringify(
7703
+ [.../* @__PURE__ */ new Set([...accepted, ...unaccepted.map(roleLossToken)])].sort()
7704
+ )} to the roles file.`
7705
+ });
7706
+ }
7707
+ return {
7708
+ main: parsed.data.main,
7709
+ parts: parsed.data.parts,
7710
+ ...parsed.data.external !== void 0 ? { external: parsed.data.external } : {},
7711
+ ...accepted.length > 0 ? { narrowingAccepted: accepted } : {},
7712
+ // Stamped by the CLI, never read from the file: a supplied graph
7713
+ // does not get to describe itself as derived.
7714
+ rolesSource: "human-override"
7715
+ };
7716
+ }
7534
7717
  function runRecordFinish(opts) {
7535
- const manifest = loadManifest(opts.setDir);
7718
+ if (!existsSync19(path25.join(opts.setDir, "recording-set.json"))) {
7719
+ fail(opts, ExitCode.InputValidation, {
7720
+ error: `no recording-set.json in ${opts.setDir}`,
7721
+ code: "no-recording-set",
7722
+ remediation: `Run \`tendril record plan --set ${opts.setDir} --component <name> --metadata <envelope.json>\` first \u2014 \`record finish\` closes a set the planner opened.`
7723
+ });
7724
+ }
7725
+ const { manifest, raw } = readManifestFile(opts.setDir);
7536
7726
  const derived = deriveRoles(opts.setDir, manifest);
7537
- const roles = opts.rolesFile !== void 0 ? { ...JSON.parse(readFileSync16(path25.resolve(opts.rolesFile), "utf8")), humanOverride: true } : { main: derived.main, parts: derived.parts, external: derived.external, humanOverride: false };
7538
- emitData(opts, { derived, confirmed: opts.confirmRoles }, () => {
7727
+ const roles = opts.rolesFile !== void 0 ? rolesFromFile(opts, opts.rolesFile, derived) : { main: derived.main, parts: derived.parts, external: derived.external, rolesSource: "derived" };
7728
+ emitData(opts, { derived, confirmed: opts.confirmRoles, rolesSource: roles.rolesSource, narrowingAccepted: roles.narrowingAccepted ?? [] }, () => {
7539
7729
  process.stdout.write(`derived mains: ${derived.main.join(", ") || "(none)"}
7540
7730
  `);
7541
7731
  for (const [slug, part] of Object.entries(derived.parts)) process.stdout.write(` part ${slug} \u2192 ${part.partOf.join(", ")}
@@ -7560,32 +7750,47 @@ function runRecordFinish(opts) {
7560
7750
  remediation: "A human runs `tendril record finish --set <dir> --confirm-roles` in their own terminal. Agents: show the proposal to your operator instead of confirming it."
7561
7751
  });
7562
7752
  }
7563
- const updated = { ...manifest, roles };
7564
- writeFileSync9(path25.join(opts.setDir, "recording-set.json"), `${JSON.stringify(updated, null, 1)}
7753
+ const merged = { ...raw, roles };
7754
+ const { issues } = validateRecordingSet(merged, (rel) => existsSync19(path25.join(opts.setDir, rel)));
7755
+ const errors = issues.filter((i) => i.severity === "error");
7756
+ if (errors.length > 0) {
7757
+ fail(opts, ExitCode.InputValidation, {
7758
+ error: `recording set rejected \u2014 roles NOT written: ${errors.map((e) => e.message).join("; ")}`,
7759
+ code: "recording-set-invalid",
7760
+ remediation: "Fix the set (`tendril record status --set <dir>` lists missing envelopes) or the roles graph, then re-run `record finish`."
7761
+ });
7762
+ }
7763
+ for (const issue of issues) if (issue.severity === "warning") warn(opts, issue.message);
7764
+ writeManifest(opts.setDir, merged);
7765
+ if (!opts.json) {
7766
+ const accepted = roles.narrowingAccepted ?? [];
7767
+ process.stdout.write(`roles written to recording-set.json (source: ${roles.rolesSource})${accepted.length > 0 ? ` \u2014 narrowing accepted by name: ${accepted.join(", ")}` : ""}
7565
7768
  `);
7566
- if (!opts.json) process.stdout.write("roles written to recording-set.json\n");
7769
+ }
7567
7770
  }
7568
- var ENVELOPE_HELP, isAutoFetchAssetUrl;
7771
+ var ENVELOPE_HELP, isAutoFetchAssetUrl, describeRoleLoss;
7569
7772
  var init_record = __esm({
7570
- "packages/cli/src/commands/record.ts"() {
7773
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/commands/record.ts"() {
7571
7774
  "use strict";
7572
7775
  init_src3();
7573
7776
  init_src();
7777
+ init_src6();
7574
7778
  init_output();
7575
7779
  init_entitlement();
7576
7780
  ENVELOPE_HELP = 'Envelope format: text tools save {"content":[{"type":"text","text":"<VERBATIM response text incl. any Currently-selected-nodes block>"}]}; get_screenshot: do NOT download the image yourself \u2014 pass its image_url to `tendril record fetch` (MCP: tendril_record_fetch), which pulls the bytes to disk directly. That keeps the pixel ground truth out of your context and costs one approval instead of a shell command per asset. Assets are asset-<first-8-hex-of-figma-uuid>.<ext>; their URLs appear as const declarations inside the design-context text and also expire.';
7577
7781
  isAutoFetchAssetUrl = (url) => isFigmaAssetUrl(url) || isLocalAssetUrl(url);
7782
+ describeRoleLoss = (loss) => loss.kind === "main" ? `drops main "${loss.main}"` : `stops "${loss.part}" being a part of main "${loss.main}"`;
7578
7783
  }
7579
7784
  });
7580
7785
 
7581
- // packages/generate/src/engine.ts
7786
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/generate/src/engine.ts
7582
7787
  var init_engine = __esm({
7583
- "packages/generate/src/engine.ts"() {
7788
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/generate/src/engine.ts"() {
7584
7789
  "use strict";
7585
7790
  }
7586
7791
  });
7587
7792
 
7588
- // packages/generate/src/parse.ts
7793
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/generate/src/parse.ts
7589
7794
  function parseFiles(text, entry) {
7590
7795
  const out = /* @__PURE__ */ new Map();
7591
7796
  const re = /```[a-z]*[^\n]*\n(?:\/\/|\/\*)[ \t]*FILE:[ \t]*([\w.]+)[ \t]*(?:\*\/)?[ \t]*\n([\s\S]*?)```/g;
@@ -7618,15 +7823,15 @@ ${content}\`\`\``);
7618
7823
  return blocks.join("\n");
7619
7824
  }
7620
7825
  var init_parse = __esm({
7621
- "packages/generate/src/parse.ts"() {
7826
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/generate/src/parse.ts"() {
7622
7827
  "use strict";
7623
7828
  }
7624
7829
  });
7625
7830
 
7626
- // packages/generate/src/engine-curated.ts
7831
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/generate/src/engine-curated.ts
7627
7832
  var CuratedEngine;
7628
7833
  var init_engine_curated = __esm({
7629
- "packages/generate/src/engine-curated.ts"() {
7834
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/generate/src/engine-curated.ts"() {
7630
7835
  "use strict";
7631
7836
  init_parse();
7632
7837
  CuratedEngine = class {
@@ -7764,7 +7969,7 @@ var init_engine_curated = __esm({
7764
7969
  }
7765
7970
  });
7766
7971
 
7767
- // packages/generate/src/loop.ts
7972
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/generate/src/loop.ts
7768
7973
  import { existsSync as existsSync20, mkdirSync as mkdirSync6, readFileSync as readFileSync17, renameSync, writeFileSync as writeFileSync10 } from "node:fs";
7769
7974
  import path26 from "node:path";
7770
7975
  import { z as z11 } from "zod";
@@ -7958,7 +8163,7 @@ async function runEngineLoop(opts) {
7958
8163
  }
7959
8164
  var better, RegionSchema, ConfigScoreSchema, BehaviorResultSchema, LoopStateSchema;
7960
8165
  var init_loop2 = __esm({
7961
- "packages/generate/src/loop.ts"() {
8166
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/generate/src/loop.ts"() {
7962
8167
  "use strict";
7963
8168
  better = (a, b) => a[0] !== b[0] ? a[0] > b[0] : a[1] !== b[1] ? a[1] > b[1] : a[2] > b[2];
7964
8169
  RegionSchema = z11.object({ x0: z11.number(), y0: z11.number(), x1: z11.number(), y1: z11.number(), density: z11.number() });
@@ -8003,7 +8208,7 @@ var init_loop2 = __esm({
8003
8208
  }
8004
8209
  });
8005
8210
 
8006
- // packages/generate/src/brief.ts
8211
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/generate/src/brief.ts
8007
8212
  import { existsSync as existsSync21, readFileSync as readFileSync18 } from "node:fs";
8008
8213
  import path27 from "node:path";
8009
8214
  function singleAxes2(name) {
@@ -8164,7 +8369,7 @@ ${propLines.join("\n")}
8164
8369
 
8165
8370
  ${syntheticCombos.length > 0 ? `UNRECORDED REACHABLE COMBINATIONS: the design's exclusive axis cannot express ${syntheticCombos.join(", ")} \u2014 the API split makes them reachable with NO recorded truth. Compose them from the recorded per-axis truth (paint variables: one axis sets, the other consumes), never invent a bespoke look, and list them in your report.
8166
8371
  ` : ""}${slots.length > 0 ? `CONTENT PROPS: every string prop defaults to its RECORDED text \u2014 render the PROP, never a hardcoded literal. Configs pass per-pose recorded strings wherever the recording varies, and pixels enforce them: a hardcoded string fails those configs. Content presence (a heading that only exists in some poses) follows the AXIS props; the string prop only supplies the text. RICH-TEXT DEFAULTS: when the recorded content is a multi-run rich node (mixed weights, an underlined link span) whose concatenation is the prop's default string, a plain-string default would flatten the recorded formatting \u2014 default the parameter to undefined and render the recorded rich markup when the prop is absent; a caller-supplied string then renders plainly. That mirrors the design tool's own emission logic and keeps every recorded pose pixel-exact.
8167
- ` : ""}Rules: plain CSS in styles.css (tokens.css optional, loaded first) \u2014 no Tailwind, no imports beyond react/react-dom, and NEVER import the stylesheet from the entry module: the harness injects tokens.css and styles.css itself, and an entry that imports CSS does not compile here (measured cost: one full round, every config 0). The component renders the RECORDED content as its defaults \u2014 reproduce it from the emissions. ${forcingCanon}${fontsLine}The host sizes nothing: the component is its natural recorded size. FLUIDITY AFFORDANCE (emit it always): every ROOT width declaration rides width: var(--tendril-root-width, <recorded>px) with that pose's recorded width as the fallback \u2014 per-variant root widths reuse the SAME property name with their own recorded fallbacks. With the property unset this is byte-equivalent truth: identical pixels, identical operability measurement (measured: flipping roots to a bare 100% held 20/20 pixels but made a commit check unmeasurable \u2014 the recorded pin carries real signal). A consumer makes an instance fluid by setting --tendril-root-width (e.g. 100%) on a wrapper, no edit to certified CSS. Widths only: recorded heights and internal geometry stay literal \u2014 fixed heights are often genuine design intent.`;
8372
+ ` : ""}Rules: generated element ids come from React's useId() \u2014 never Math.random() in render/state init (SSR hydration hazard; measured: two same-day bundles disagreed). Plain CSS in styles.css (tokens.css optional, loaded first) \u2014 no Tailwind, no imports beyond react/react-dom, and NEVER import the stylesheet from the entry module: the harness injects tokens.css and styles.css itself, and an entry that imports CSS does not compile here (measured cost: one full round, every config 0). The component renders the RECORDED content as its defaults \u2014 reproduce it from the emissions. ${forcingCanon}${fontsLine}The host sizes nothing: the component is its natural recorded size. FLUIDITY AFFORDANCE (emit it always): every ROOT width declaration rides width: var(--tendril-root-width, <recorded>px) with that pose's recorded width as the fallback \u2014 per-variant root widths reuse the SAME property name with their own recorded fallbacks. With the property unset this is byte-equivalent truth: identical pixels, identical operability measurement (measured: flipping roots to a bare 100% held 20/20 pixels but made a commit check unmeasurable \u2014 the recorded pin carries real signal). A consumer makes an instance fluid by setting --tendril-root-width (e.g. 100%) on a wrapper, no edit to certified CSS. Widths only: recorded heights and internal geometry stay literal \u2014 fixed heights are often genuine design intent.`;
8168
8373
  const mappedTokens = /* @__PURE__ */ new Set([...forcedStates, ...props.filter((p) => p.kind === "boolean").map((p) => p.name)]);
8169
8374
  const unmappedInteractionEvidence = interactionEvidence.filter((e) => {
8170
8375
  const sel = e.endsWith(" (selection axis)");
@@ -8596,7 +8801,7 @@ RESOLVED FOR THIS RECORDING: it is ${opts.colorScheme}-mode truth, so pin color-
8596
8801
  }
8597
8802
  var PoseCompletenessError, kebab3, camel, pascal, RESERVED_PROPS, axisPropName, isStateAxis, DISMISS_NAMES, symbolName, STYLE_WEIGHTS2, styleWeight;
8598
8803
  var init_brief = __esm({
8599
- "packages/generate/src/brief.ts"() {
8804
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/generate/src/brief.ts"() {
8600
8805
  "use strict";
8601
8806
  init_src();
8602
8807
  init_src4();
@@ -8650,7 +8855,7 @@ var init_brief = __esm({
8650
8855
  }
8651
8856
  });
8652
8857
 
8653
- // packages/generate/src/segments.ts
8858
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/generate/src/segments.ts
8654
8859
  import { existsSync as existsSync22, readFileSync as readFileSync19, readdirSync as readdirSync6 } from "node:fs";
8655
8860
  import path28 from "node:path";
8656
8861
  function repText(set, rep, tool) {
@@ -8782,14 +8987,14 @@ Write the COMPLETE files (${task.entry}, styles.css, optional tokens.css) into y
8782
8987
  }
8783
8988
  var cssIdent;
8784
8989
  var init_segments = __esm({
8785
- "packages/generate/src/segments.ts"() {
8990
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/generate/src/segments.ts"() {
8786
8991
  "use strict";
8787
8992
  init_src();
8788
8993
  cssIdent = (name) => name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
8789
8994
  }
8790
8995
  });
8791
8996
 
8792
- // packages/generate/src/consent.ts
8997
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/generate/src/consent.ts
8793
8998
  function formatConsentLines(e) {
8794
8999
  return [
8795
9000
  `engine=${e.engineId} model=${e.modelId} route=${e.providerRoute}`,
@@ -8799,12 +9004,12 @@ function formatConsentLines(e) {
8799
9004
  ];
8800
9005
  }
8801
9006
  var init_consent = __esm({
8802
- "packages/generate/src/consent.ts"() {
9007
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/generate/src/consent.ts"() {
8803
9008
  "use strict";
8804
9009
  }
8805
9010
  });
8806
9011
 
8807
- // packages/generate/src/adapter.ts
9012
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/generate/src/adapter.ts
8808
9013
  function resolveAdapterSettings(entry, overrides = {}) {
8809
9014
  const notes = [];
8810
9015
  let maxTokens = DEFAULT_MAX_TOKENS;
@@ -8836,13 +9041,13 @@ function resolveAdapterSettings(entry, overrides = {}) {
8836
9041
  }
8837
9042
  var DEFAULT_MAX_TOKENS;
8838
9043
  var init_adapter = __esm({
8839
- "packages/generate/src/adapter.ts"() {
9044
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/generate/src/adapter.ts"() {
8840
9045
  "use strict";
8841
9046
  DEFAULT_MAX_TOKENS = 2e4;
8842
9047
  }
8843
9048
  });
8844
9049
 
8845
- // packages/generate/src/bundle-emit.ts
9050
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/generate/src/bundle-emit.ts
8846
9051
  import { createHash as createHash4 } from "node:crypto";
8847
9052
  import { copyFileSync, existsSync as existsSync23, mkdirSync as mkdirSync7, readFileSync as readFileSync20, readdirSync as readdirSync7, rmSync as rmSync3, writeFileSync as writeFileSync11 } from "node:fs";
8848
9053
  import path29 from "node:path";
@@ -8893,6 +9098,11 @@ function cssFontFamilies(css) {
8893
9098
  }
8894
9099
  return [...out];
8895
9100
  }
9101
+ function upstreamAttribution(face) {
9102
+ if (!face.source.startsWith(GOOGLE_FONT_FILE_PREFIX)) return face.source;
9103
+ if (face.servedFamily === void 0) return `the Google Fonts specimen for "${face.family.replace(/[\r\n]+/g, " ")}"`;
9104
+ return `https://fonts.google.com/specimen/${encodeURIComponent(face.servedFamily).replace(/%20/g, "+")}/license`;
9105
+ }
8896
9106
  function fontsCssFor(faces, bundleDir, cacheDir = DEFAULT_FONT_CACHE, substitutedFamilies = []) {
8897
9107
  const header = [
8898
9108
  "/* tendril fonts.css \u2014 the exact faces this bundle was scored with (sha-pinned in",
@@ -8906,27 +9116,73 @@ function fontsCssFor(faces, bundleDir, cacheDir = DEFAULT_FONT_CACHE, substitute
8906
9116
  ] : []
8907
9117
  ];
8908
9118
  const lines = [];
9119
+ const notices = [];
9120
+ const licenseTexts = /* @__PURE__ */ new Map();
8909
9121
  for (const face of faces) {
8910
9122
  const src = path29.join(cacheDir, path29.basename(face.file));
8911
9123
  const target = `./fonts/${path29.basename(face.file)}`;
8912
9124
  const format = FONT_FORMATS[path29.extname(face.file).toLowerCase()] ?? "truetype";
8913
9125
  const family = face.family.replace(/['\\]/g, "").replace(/\*\//g, "");
8914
9126
  const decl = `@font-face { font-family: '${family}'; font-weight: ${face.weight}; font-style: normal; src: url(${target}) format('${format}'); }`;
8915
- if (face.source.startsWith("local:")) {
8916
- lines.push(
8917
- `/* '${family}' ${face.weight} is a user-licensed face (tendril fonts add; sha256 ${face.sha256.slice(0, 16)}\u2026).`,
8918
- ` Licensed bytes are never copied into bundles \u2014 place your copy at ${target} and uncomment: */`,
8919
- `/* ${decl} */`
8920
- );
9127
+ const license = normalizeFontLicense(face.license);
9128
+ const terms = REDISTRIBUTABLE.get(license);
9129
+ if (terms === void 0) {
9130
+ if (face.source.startsWith("local:")) {
9131
+ lines.push(
9132
+ `/* '${family}' ${face.weight} is a user-licensed face (tendril fonts add; sha256 ${face.sha256.slice(0, 16)}\u2026).`,
9133
+ ` Licensed bytes are never copied into bundles \u2014 place your copy at ${target} and uncomment: */`,
9134
+ `/* ${decl} */`
9135
+ );
9136
+ } else if (license === "unknown") {
9137
+ lines.push(
9138
+ `/* '${family}' ${face.weight}: no licence on record (sha256 ${face.sha256.slice(0, 16)}\u2026). That is a gap`,
9139
+ " in the font cache, not a statement about your rights \u2014 Tendril copies font bytes into a",
9140
+ " bundle only under a licence it can name, so this face is declared here instead. Establish",
9141
+ ` the licence with \`tendril fonts resolve "${family}" --weights ${face.weight}\``,
9142
+ " (or `tendril fonts resolve --set <recording-dir>`) and re-emit. If it is a face you licence",
9143
+ ` rather than one free to redistribute, place your copy at ${target} and uncomment: */`,
9144
+ `/* ${decl} */`
9145
+ );
9146
+ } else {
9147
+ lines.push(
9148
+ `/* '${family}' ${face.weight} is recorded as ${license} (sha256 ${face.sha256.slice(0, 16)}\u2026), which does`,
9149
+ " not permit redistribution \u2014 Tendril never copies such bytes. Place your licensed copy",
9150
+ ` at ${target} and uncomment: */`,
9151
+ `/* ${decl} */`
9152
+ );
9153
+ }
8921
9154
  } else if (existsSync23(src) && createHash4("sha256").update(readFileSync20(src)).digest("hex") === face.sha256) {
8922
9155
  mkdirSync7(path29.join(bundleDir, "fonts"), { recursive: true });
8923
9156
  copyFileSync(src, path29.join(bundleDir, "fonts", path29.basename(face.file)));
9157
+ licenseTexts.set(terms.file, terms.text);
9158
+ const upstream = upstreamAttribution(face);
9159
+ notices.push(
9160
+ "",
9161
+ `${face.family.replace(/[\r\n]+/g, " ")} ${face.weight} \u2014 ./${path29.basename(face.file)}`,
9162
+ ` licence: ${terms.title} \u2014 full text in ./${terms.file}`,
9163
+ ` source: ${face.source}`,
9164
+ ` sha256: ${face.sha256}`,
9165
+ " copyright: this face's upstream copyright statement is published with its",
9166
+ ` original release \u2014 ${upstream}`
9167
+ );
8924
9168
  lines.push(decl);
8925
9169
  } else {
8926
9170
  lines.push(`/* '${family}' ${face.weight} (sha256 ${face.sha256.slice(0, 16)}\u2026) could not be shipped: cache bytes missing or hash mismatch \u2014 re-run \`tendril fonts resolve\` and re-emit. */`);
8927
9171
  }
8928
9172
  }
8929
- return lines.length === 0 ? null : `${[...header, ...lines].join("\n")}
9173
+ if (lines.length === 0) return null;
9174
+ if (notices.length > 0) {
9175
+ const fontsDir = path29.join(bundleDir, "fonts");
9176
+ for (const [file, text] of licenseTexts) writeFileSync11(path29.join(fontsDir, file), text);
9177
+ writeFileSync11(path29.join(fontsDir, "NOTICE.txt"), `${[NOTICE_PREAMBLE, ...notices].join("\n")}
9178
+ `);
9179
+ header.push(
9180
+ "/* REDISTRIBUTION: the face files in ./fonts/ are redistributed under the licences",
9181
+ ` recorded in ./fonts/NOTICE.txt; full texts in ${[...licenseTexts.keys()].map((f) => `./fonts/${f}`).join(", ")}.`,
9182
+ " Keep NOTICE.txt and the licence texts with the font files wherever they travel. */"
9183
+ );
9184
+ }
9185
+ return `${[...header, ...lines].join("\n")}
8930
9186
  `;
8931
9187
  }
8932
9188
  function countLatticeSymbols(setDir) {
@@ -9069,9 +9325,9 @@ ${stripped}`);
9069
9325
  const statusLine = `bundle: ${pass}/${statuses.length} recorded configs \u2265 pass bar (${certified} certified), ` + (interaction.length === 0 ? "interaction behaviors NONE VERIFIED" : `interaction behaviors ${interaction.filter((b) => b.pass).length}/${interaction.length}`) + (prelude.length === 0 ? "" : `, page hygiene ${prelude.filter((b) => b.pass).length}/${prelude.length}`) + (unrecorded === null ? "" : `; ${unrecorded} lattice configs UNVERIFIED`) + ` \u2014 claims in component.json, recompute with \`tendril verify\``;
9070
9326
  return { manifest, statusLine, written };
9071
9327
  }
9072
- var FONT_FORMATS, BARS;
9328
+ var FONT_FORMATS, BARS, NOTICE_PREAMBLE, OFL_1_1_TEXT, UFL_1_0_TEXT, APACHE_2_0_TEXT, REDISTRIBUTABLE;
9073
9329
  var init_bundle_emit = __esm({
9074
- "packages/generate/src/bundle-emit.ts"() {
9330
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/generate/src/bundle-emit.ts"() {
9075
9331
  "use strict";
9076
9332
  init_src6();
9077
9333
  init_src();
@@ -9081,12 +9337,414 @@ var init_bundle_emit = __esm({
9081
9337
  pass: { sim: 0.95, ink: 0.95 },
9082
9338
  cert: { sim: 0.97, ink: 0.95 }
9083
9339
  };
9340
+ NOTICE_PREAMBLE = [
9341
+ "Font redistribution notice \u2014 tendril bundle",
9342
+ "===========================================",
9343
+ "",
9344
+ "The font files in this directory were copied into the bundle because the",
9345
+ "licence they are served under permits redistribution. Each entry below names",
9346
+ "that licence, the exact file the bytes came from, and the sha256 the bundle",
9347
+ "was scored against. Full licence texts sit beside this file \u2014 keep them, and",
9348
+ "this notice, with the font files wherever they travel."
9349
+ ].join("\n");
9350
+ OFL_1_1_TEXT = `-----------------------------------------------------------
9351
+ SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
9352
+ -----------------------------------------------------------
9353
+
9354
+ PREAMBLE
9355
+ The goals of the Open Font License (OFL) are to stimulate worldwide
9356
+ development of collaborative font projects, to support the font creation
9357
+ efforts of academic and linguistic communities, and to provide a free and
9358
+ open framework in which fonts may be shared and improved in partnership
9359
+ with others.
9360
+
9361
+ The OFL allows the licensed fonts to be used, studied, modified and
9362
+ redistributed freely as long as they are not sold by themselves. The
9363
+ fonts, including any derivative works, can be bundled, embedded,
9364
+ redistributed and/or sold with any software provided that any reserved
9365
+ names are not used by derivative works. The fonts and derivatives,
9366
+ however, cannot be released under any other type of license. The
9367
+ requirement for fonts to remain under this license does not apply
9368
+ to any document created using the fonts or their derivatives.
9369
+
9370
+ DEFINITIONS
9371
+ "Font Software" refers to the set of files released by the Copyright
9372
+ Holder(s) under this license and clearly marked as such. This may
9373
+ include source files, build scripts and documentation.
9374
+
9375
+ "Reserved Font Name" refers to any names specified as such after the
9376
+ copyright statement(s).
9377
+
9378
+ "Original Version" refers to the collection of Font Software components as
9379
+ distributed by the Copyright Holder(s).
9380
+
9381
+ "Modified Version" refers to any derivative made by adding to, deleting,
9382
+ or substituting -- in part or in whole -- any of the components of the
9383
+ Original Version, by changing formats or by porting the Font Software to a
9384
+ new environment.
9385
+
9386
+ "Author" refers to any designer, engineer, programmer, technical
9387
+ writer or other person who contributed to the Font Software.
9388
+
9389
+ PERMISSION & CONDITIONS
9390
+ Permission is hereby granted, free of charge, to any person obtaining
9391
+ a copy of the Font Software, to use, study, copy, merge, embed, modify,
9392
+ redistribute, and sell modified and unmodified copies of the Font
9393
+ Software, subject to the following conditions:
9394
+
9395
+ 1) Neither the Font Software nor any of its individual components,
9396
+ in Original or Modified Versions, may be sold by itself.
9397
+
9398
+ 2) Original or Modified Versions of the Font Software may be bundled,
9399
+ redistributed and/or sold with any software, provided that each copy
9400
+ contains the above copyright notice and this license. These can be
9401
+ included either as stand-alone text files, human-readable headers or
9402
+ in the appropriate machine-readable metadata fields within text or
9403
+ binary files as long as those fields can be easily viewed by the user.
9404
+
9405
+ 3) No Modified Version of the Font Software may use the Reserved Font
9406
+ Name(s) unless explicit written permission is granted by the corresponding
9407
+ Copyright Holder. This restriction only applies to the primary font name as
9408
+ presented to the users.
9409
+
9410
+ 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
9411
+ Software shall not be used to promote, endorse or advertise any
9412
+ Modified Version, except to acknowledge the contribution(s) of the
9413
+ Copyright Holder(s) and the Author(s) or with their explicit written
9414
+ permission.
9415
+
9416
+ 5) The Font Software, modified or unmodified, in part or in whole,
9417
+ must be distributed entirely under this license, and must not be
9418
+ distributed under any other license. The requirement for fonts to
9419
+ remain under this license does not apply to any document created
9420
+ using the Font Software.
9421
+
9422
+ TERMINATION
9423
+ This license becomes null and void if any of the above conditions are
9424
+ not met.
9425
+
9426
+ DISCLAIMER
9427
+ THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
9428
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
9429
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
9430
+ OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
9431
+ COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
9432
+ INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
9433
+ DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
9434
+ FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
9435
+ OTHER DEALINGS IN THE FONT SOFTWARE.
9436
+ `;
9437
+ UFL_1_0_TEXT = `-------------------------------
9438
+ UBUNTU FONT LICENCE Version 1.0
9439
+ -------------------------------
9440
+
9441
+ PREAMBLE
9442
+ This licence allows the licensed fonts to be used, studied, modified and
9443
+ redistributed freely. The fonts, including any derivative works, can be
9444
+ bundled, embedded, and redistributed provided the terms of this licence
9445
+ are met. The fonts and derivatives, however, cannot be released under
9446
+ any other licence. The requirement for fonts to remain under this
9447
+ licence does not require any document created using the fonts or their
9448
+ derivatives to be published under this licence, as long as the primary
9449
+ purpose of the document is not to be a vehicle for the distribution of
9450
+ the fonts.
9451
+
9452
+ DEFINITIONS
9453
+ "Font Software" refers to the set of files released by the Copyright
9454
+ Holder(s) under this licence and clearly marked as such. This may
9455
+ include source files, build scripts and documentation.
9456
+
9457
+ "Original Version" refers to the collection of Font Software components
9458
+ as received under this licence.
9459
+
9460
+ "Modified Version" refers to any derivative made by adding to, deleting,
9461
+ or substituting -- in part or in whole -- any of the components of the
9462
+ Original Version, by changing formats or by porting the Font Software to
9463
+ a new environment.
9464
+
9465
+ "Copyright Holder(s)" refers to all individuals and companies who have a
9466
+ copyright ownership of the Font Software.
9467
+
9468
+ "Substantially Changed" refers to Modified Versions which can be easily
9469
+ identified as dissimilar to the Font Software by users of the Font
9470
+ Software comparing the Original Version with the Modified Version.
9471
+
9472
+ To "Propagate" a work means to do anything with it that, without
9473
+ permission, would make you directly or secondarily liable for
9474
+ infringement under applicable copyright law, except executing it on a
9475
+ computer or modifying a private copy. Propagation includes copying,
9476
+ distribution (with or without modification and with or without charging
9477
+ a redistribution fee), making available to the public, and in some
9478
+ countries other activities as well.
9479
+
9480
+ PERMISSION & CONDITIONS
9481
+ This licence does not grant any rights under trademark law and all such
9482
+ rights are reserved.
9483
+
9484
+ Permission is hereby granted, free of charge, to any person obtaining a
9485
+ copy of the Font Software, to propagate the Font Software, subject to
9486
+ the below conditions:
9487
+
9488
+ 1) Each copy of the Font Software must contain the above copyright
9489
+ notice and this licence. These can be included either as stand-alone
9490
+ text files, human-readable headers or in the appropriate machine-
9491
+ readable metadata fields within text or binary files as long as those
9492
+ fields can be easily viewed by the user.
9493
+
9494
+ 2) The font name complies with the following:
9495
+ (a) The Original Version must retain its name, unmodified.
9496
+ (b) Modified Versions which are Substantially Changed must be renamed to
9497
+ avoid use of the name of the Original Version or similar names entirely.
9498
+ (c) Modified Versions which are not Substantially Changed must be
9499
+ renamed to both (i) retain the name of the Original Version and (ii) add
9500
+ additional naming elements to distinguish the Modified Version from the
9501
+ Original Version. The name of such Modified Versions must be the name of
9502
+ the Original Version, with "derivative X" where X represents the name of
9503
+ the new work, appended to that name.
9504
+
9505
+ 3) The name(s) of the Copyright Holder(s) and any contributor to the
9506
+ Font Software shall not be used to promote, endorse or advertise any
9507
+ Modified Version, except (i) as required by this licence, (ii) to
9508
+ acknowledge the contribution(s) of the Copyright Holder(s) or (iii) with
9509
+ their explicit written permission.
9510
+
9511
+ 4) The Font Software, modified or unmodified, in part or in whole, must
9512
+ be distributed entirely under this licence, and must not be distributed
9513
+ under any other licence. The requirement for fonts to remain under this
9514
+ licence does not affect any document created using the Font Software,
9515
+ except any version of the Font Software extracted from a document
9516
+ created using the Font Software may only be distributed under this
9517
+ licence.
9518
+
9519
+ TERMINATION
9520
+ This licence becomes null and void if any of the above conditions are
9521
+ not met.
9522
+
9523
+ DISCLAIMER
9524
+ THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
9525
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
9526
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
9527
+ COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
9528
+ COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
9529
+ INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
9530
+ DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
9531
+ FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER
9532
+ DEALINGS IN THE FONT SOFTWARE.
9533
+ `;
9534
+ APACHE_2_0_TEXT = `
9535
+ Apache License
9536
+ Version 2.0, January 2004
9537
+ http://www.apache.org/licenses/
9538
+
9539
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
9540
+
9541
+ 1. Definitions.
9542
+
9543
+ "License" shall mean the terms and conditions for use, reproduction,
9544
+ and distribution as defined by Sections 1 through 9 of this document.
9545
+
9546
+ "Licensor" shall mean the copyright owner or entity authorized by
9547
+ the copyright owner that is granting the License.
9548
+
9549
+ "Legal Entity" shall mean the union of the acting entity and all
9550
+ other entities that control, are controlled by, or are under common
9551
+ control with that entity. For the purposes of this definition,
9552
+ "control" means (i) the power, direct or indirect, to cause the
9553
+ direction or management of such entity, whether by contract or
9554
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
9555
+ outstanding shares, or (iii) beneficial ownership of such entity.
9556
+
9557
+ "You" (or "Your") shall mean an individual or Legal Entity
9558
+ exercising permissions granted by this License.
9559
+
9560
+ "Source" form shall mean the preferred form for making modifications,
9561
+ including but not limited to software source code, documentation
9562
+ source, and configuration files.
9563
+
9564
+ "Object" form shall mean any form resulting from mechanical
9565
+ transformation or translation of a Source form, including but
9566
+ not limited to compiled object code, generated documentation,
9567
+ and conversions to other media types.
9568
+
9569
+ "Work" shall mean the work of authorship, whether in Source or
9570
+ Object form, made available under the License, as indicated by a
9571
+ copyright notice that is included in or attached to the work
9572
+ (an example is provided in the Appendix below).
9573
+
9574
+ "Derivative Works" shall mean any work, whether in Source or Object
9575
+ form, that is based on (or derived from) the Work and for which the
9576
+ editorial revisions, annotations, elaborations, or other modifications
9577
+ represent, as a whole, an original work of authorship. For the purposes
9578
+ of this License, Derivative Works shall not include works that remain
9579
+ separable from, or merely link (or bind by name) to the interfaces of,
9580
+ the Work and Derivative Works thereof.
9581
+
9582
+ "Contribution" shall mean any work of authorship, including
9583
+ the original version of the Work and any modifications or additions
9584
+ to that Work or Derivative Works thereof, that is intentionally
9585
+ submitted to Licensor for inclusion in the Work by the copyright owner
9586
+ or by an individual or Legal Entity authorized to submit on behalf of
9587
+ the copyright owner. For the purposes of this definition, "submitted"
9588
+ means any form of electronic, verbal, or written communication sent
9589
+ to the Licensor or its representatives, including but not limited to
9590
+ communication on electronic mailing lists, source code control systems,
9591
+ and issue tracking systems that are managed by, or on behalf of, the
9592
+ Licensor for the purpose of discussing and improving the Work, but
9593
+ excluding communication that is conspicuously marked or otherwise
9594
+ designated in writing by the copyright owner as "Not a Contribution."
9595
+
9596
+ "Contributor" shall mean Licensor and any individual or Legal Entity
9597
+ on behalf of whom a Contribution has been received by Licensor and
9598
+ subsequently incorporated within the Work.
9599
+
9600
+ 2. Grant of Copyright License. Subject to the terms and conditions of
9601
+ this License, each Contributor hereby grants to You a perpetual,
9602
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
9603
+ copyright license to reproduce, prepare Derivative Works of,
9604
+ publicly display, publicly perform, sublicense, and distribute the
9605
+ Work and such Derivative Works in Source or Object form.
9606
+
9607
+ 3. Grant of Patent License. Subject to the terms and conditions of
9608
+ this License, each Contributor hereby grants to You a perpetual,
9609
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
9610
+ (except as stated in this section) patent license to make, have made,
9611
+ use, offer to sell, sell, import, and otherwise transfer the Work,
9612
+ where such license applies only to those patent claims licensable
9613
+ by such Contributor that are necessarily infringed by their
9614
+ Contribution(s) alone or by combination of their Contribution(s)
9615
+ with the Work to which such Contribution(s) was submitted. If You
9616
+ institute patent litigation against any entity (including a
9617
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
9618
+ or a Contribution incorporated within the Work constitutes direct
9619
+ or contributory patent infringement, then any patent licenses
9620
+ granted to You under this License for that Work shall terminate
9621
+ as of the date such litigation is filed.
9622
+
9623
+ 4. Redistribution. You may reproduce and distribute copies of the
9624
+ Work or Derivative Works thereof in any medium, with or without
9625
+ modifications, and in Source or Object form, provided that You
9626
+ meet the following conditions:
9627
+
9628
+ (a) You must give any other recipients of the Work or
9629
+ Derivative Works a copy of this License; and
9630
+
9631
+ (b) You must cause any modified files to carry prominent notices
9632
+ stating that You changed the files; and
9633
+
9634
+ (c) You must retain, in the Source form of any Derivative Works
9635
+ that You distribute, all copyright, patent, trademark, and
9636
+ attribution notices from the Source form of the Work,
9637
+ excluding those notices that do not pertain to any part of
9638
+ the Derivative Works; and
9639
+
9640
+ (d) If the Work includes a "NOTICE" text file as part of its
9641
+ distribution, then any Derivative Works that You distribute must
9642
+ include a readable copy of the attribution notices contained
9643
+ within such NOTICE file, excluding those notices that do not
9644
+ pertain to any part of the Derivative Works, in at least one
9645
+ of the following places: within a NOTICE text file distributed
9646
+ as part of the Derivative Works; within the Source form or
9647
+ documentation, if provided along with the Derivative Works; or,
9648
+ within a display generated by the Derivative Works, if and
9649
+ wherever such third-party notices normally appear. The contents
9650
+ of the NOTICE file are for informational purposes only and
9651
+ do not modify the License. You may add Your own attribution
9652
+ notices within Derivative Works that You distribute, alongside
9653
+ or as an addendum to the NOTICE text from the Work, provided
9654
+ that such additional attribution notices cannot be construed
9655
+ as modifying the License.
9656
+
9657
+ You may add Your own copyright statement to Your modifications and
9658
+ may provide additional or different license terms and conditions
9659
+ for use, reproduction, or distribution of Your modifications, or
9660
+ for any such Derivative Works as a whole, provided Your use,
9661
+ reproduction, and distribution of the Work otherwise complies with
9662
+ the conditions stated in this License.
9663
+
9664
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
9665
+ any Contribution intentionally submitted for inclusion in the Work
9666
+ by You to the Licensor shall be under the terms and conditions of
9667
+ this License, without any additional terms or conditions.
9668
+ Notwithstanding the above, nothing herein shall supersede or modify
9669
+ the terms of any separate license agreement you may have executed
9670
+ with Licensor regarding such Contributions.
9671
+
9672
+ 6. Trademarks. This License does not grant permission to use the trade
9673
+ names, trademarks, service marks, or product names of the Licensor,
9674
+ except as required for reasonable and customary use in describing the
9675
+ origin of the Work and reproducing the content of the NOTICE file.
9676
+
9677
+ 7. Disclaimer of Warranty. Unless required by applicable law or
9678
+ agreed to in writing, Licensor provides the Work (and each
9679
+ Contributor provides its Contributions) on an "AS IS" BASIS,
9680
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
9681
+ implied, including, without limitation, any warranties or conditions
9682
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
9683
+ PARTICULAR PURPOSE. You are solely responsible for determining the
9684
+ appropriateness of using or redistributing the Work and assume any
9685
+ risks associated with Your exercise of permissions under this License.
9686
+
9687
+ 8. Limitation of Liability. In no event and under no legal theory,
9688
+ whether in tort (including negligence), contract, or otherwise,
9689
+ unless required by applicable law (such as deliberate and grossly
9690
+ negligent acts) or agreed to in writing, shall any Contributor be
9691
+ liable to You for damages, including any direct, indirect, special,
9692
+ incidental, or consequential damages of any character arising as a
9693
+ result of this License or out of the use or inability to use the
9694
+ Work (including but not limited to damages for loss of goodwill,
9695
+ work stoppage, computer failure or malfunction, or any and all
9696
+ other commercial damages or losses), even if such Contributor
9697
+ has been advised of the possibility of such damages.
9698
+
9699
+ 9. Accepting Warranty or Additional Liability. While redistributing
9700
+ the Work or Derivative Works thereof, You may choose to offer,
9701
+ and charge a fee for, acceptance of support, warranty, indemnity,
9702
+ or other liability obligations and/or rights consistent with this
9703
+ License. However, in accepting such obligations, You may act only
9704
+ on Your own behalf and on Your sole responsibility, not on behalf
9705
+ of any other Contributor, and only if You agree to indemnify,
9706
+ defend, and hold each Contributor harmless for any liability
9707
+ incurred by, or claims asserted against, such Contributor by reason
9708
+ of your accepting any such warranty or additional liability.
9709
+
9710
+ END OF TERMS AND CONDITIONS
9711
+
9712
+ APPENDIX: How to apply the Apache License to your work.
9713
+
9714
+ To apply the Apache License to your work, attach the following
9715
+ boilerplate notice, with the fields enclosed by brackets "[]"
9716
+ replaced with your own identifying information. (Don't include
9717
+ the brackets!) The text should be enclosed in the appropriate
9718
+ comment syntax for the file format. We also recommend that a
9719
+ file or class name and description of purpose be included on the
9720
+ same "printed page" as the copyright notice for easier
9721
+ identification within third-party archives.
9722
+
9723
+ Copyright [yyyy] [name of copyright owner]
9724
+
9725
+ Licensed under the Apache License, Version 2.0 (the "License");
9726
+ you may not use this file except in compliance with the License.
9727
+ You may obtain a copy of the License at
9728
+
9729
+ http://www.apache.org/licenses/LICENSE-2.0
9730
+
9731
+ Unless required by applicable law or agreed to in writing, software
9732
+ distributed under the License is distributed on an "AS IS" BASIS,
9733
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9734
+ See the License for the specific language governing permissions and
9735
+ limitations under the License.
9736
+ `;
9737
+ REDISTRIBUTABLE = /* @__PURE__ */ new Map([
9738
+ ["OFL-1.1", { title: "SIL Open Font License 1.1", file: "LICENSE-OFL-1.1.txt", text: OFL_1_1_TEXT }],
9739
+ ["Apache-2.0", { title: "Apache License 2.0", file: "LICENSE-Apache-2.0.txt", text: APACHE_2_0_TEXT }],
9740
+ ["UFL-1.0", { title: "Ubuntu Font Licence 1.0", file: "LICENSE-UFL-1.0.txt", text: UFL_1_0_TEXT }]
9741
+ ]);
9084
9742
  }
9085
9743
  });
9086
9744
 
9087
- // packages/generate/src/index.ts
9745
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/generate/src/index.ts
9088
9746
  var init_src7 = __esm({
9089
- "packages/generate/src/index.ts"() {
9747
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/generate/src/index.ts"() {
9090
9748
  "use strict";
9091
9749
  init_engine();
9092
9750
  init_engine_curated();
@@ -9100,7 +9758,7 @@ var init_src7 = __esm({
9100
9758
  }
9101
9759
  });
9102
9760
 
9103
- // packages/cli/src/commands/fonts.ts
9761
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/commands/fonts.ts
9104
9762
  var fonts_exports = {};
9105
9763
  __export(fonts_exports, {
9106
9764
  DEFAULT_FONT_CACHE: () => DEFAULT_FONT_CACHE,
@@ -9145,30 +9803,54 @@ async function runFontsResolveSet(opts) {
9145
9803
  });
9146
9804
  }
9147
9805
  const inCache = new Set(resolvedFontFamilies(opts.cacheDir).flatMap((f) => f.weights.map((w) => `${f.family.toLowerCase()}:${w}`)));
9806
+ const unstamped = new Map(facesMissingLicense(opts.cacheDir).map((f) => [`${f.family.toLowerCase()}:${f.weight}`, f.sha256]));
9148
9807
  const cached = [];
9149
9808
  const resolved = [];
9150
9809
  const failures = [];
9810
+ const relicensed = [];
9811
+ const unlicensed = [];
9812
+ const byteDrift = [];
9151
9813
  for (const need of needs) {
9152
9814
  const missing = [];
9815
+ const toStamp = [];
9153
9816
  for (const w of need.weights) {
9154
- if (inCache.has(`${need.family.toLowerCase()}:${w}`)) cached.push({ family: need.family, weight: w });
9155
- else missing.push(w);
9817
+ const key = `${need.family.toLowerCase()}:${w}`;
9818
+ if (!inCache.has(key)) missing.push(w);
9819
+ else if (unstamped.has(key)) toStamp.push(w);
9820
+ else cached.push({ family: need.family, weight: w });
9821
+ }
9822
+ if (missing.length > 0) {
9823
+ const result = await resolveFonts(need.family, missing, opts.cacheDir);
9824
+ resolved.push(...result.resolved);
9825
+ failures.push(...result.failures);
9826
+ }
9827
+ if (toStamp.length > 0) {
9828
+ const result = await resolveFonts(need.family, toStamp, opts.cacheDir);
9829
+ for (const face of result.resolved) {
9830
+ if (face.license === "unknown") unlicensed.push({ family: face.family, weight: face.weight, reason: "the foundry's metadata named no licence for this family" });
9831
+ else relicensed.push({ family: face.family, weight: face.weight, license: face.license });
9832
+ if (unstamped.get(`${face.family.toLowerCase()}:${face.weight}`) !== face.sha256) byteDrift.push({ family: face.family, weight: face.weight });
9833
+ }
9834
+ unlicensed.push(...result.failures);
9156
9835
  }
9157
- if (missing.length === 0) continue;
9158
- const result = await resolveFonts(need.family, missing, opts.cacheDir);
9159
- resolved.push(...result.resolved);
9160
- failures.push(...result.failures);
9161
9836
  }
9162
- emitData(opts, { set: setDir, needs, cached, resolved, failures }, () => {
9837
+ emitData(opts, { set: setDir, needs, cached, resolved, relicensed, unlicensed, failures }, () => {
9163
9838
  process.stdout.write(`set declares: ${needs.map((n) => `${n.family} (${n.weights.join(", ")})`).join(" \xB7 ")}
9164
9839
  `);
9165
9840
  for (const f of cached) process.stdout.write(`cached ${f.family} ${f.weight}
9166
9841
  `);
9167
9842
  for (const f of resolved) process.stdout.write(`resolved ${f.family} ${f.weight} (${f.sha256.slice(0, 12)}\u2026)
9843
+ `);
9844
+ for (const f of relicensed) process.stdout.write(`licence ${f.family} ${f.weight}: ${f.license} \u2014 recorded now; bundles may ship these bytes with the licence text
9845
+ `);
9846
+ for (const f of unlicensed) process.stdout.write(`licence ${f.family} ${f.weight}: still not on record (${f.reason}) \u2014 the cached face renders as always; bundles declare it instead of copying it
9168
9847
  `);
9169
9848
  for (const f of failures) process.stdout.write(`FAILED ${f.family} ${f.weight}: ${f.reason}
9170
9849
  `);
9171
9850
  });
9851
+ if (byteDrift.length > 0) {
9852
+ warn(opts, `${byteDrift.map((f) => `${f.family} ${f.weight}`).join(", ")}: the foundry now serves different bytes than the cache held \u2014 the faces were re-fetched to record their licence, so re-pin any font lock deliberately`);
9853
+ }
9172
9854
  if (failures.length > 0) {
9173
9855
  warn(opts, `${failures.length} face(s) unresolved \u2014 verification will refuse to score under substitution`);
9174
9856
  process.exitCode = ExitCode.FontsUnproven;
@@ -9224,7 +9906,7 @@ function runFontsAdd(opts) {
9224
9906
  });
9225
9907
  }
9226
9908
  var init_fonts = __esm({
9227
- "packages/cli/src/commands/fonts.ts"() {
9909
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/commands/fonts.ts"() {
9228
9910
  "use strict";
9229
9911
  init_src3();
9230
9912
  init_src4();
@@ -9233,7 +9915,7 @@ var init_fonts = __esm({
9233
9915
  }
9234
9916
  });
9235
9917
 
9236
- // packages/cli/src/font-guidance.ts
9918
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/font-guidance.ts
9237
9919
  function fontsUnprovenRemediation(setDir) {
9238
9920
  if (setDir !== void 0) {
9239
9921
  try {
@@ -9287,18 +9969,24 @@ function missingWeights(setDir, cacheDir) {
9287
9969
  return gaps;
9288
9970
  }
9289
9971
  var init_font_guidance = __esm({
9290
- "packages/cli/src/font-guidance.ts"() {
9972
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/font-guidance.ts"() {
9291
9973
  "use strict";
9292
9974
  init_src4();
9293
9975
  init_src7();
9294
9976
  }
9295
9977
  });
9296
9978
 
9297
- // packages/cli/src/commands/verify.ts
9979
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/commands/verify.ts
9298
9980
  var verify_exports = {};
9299
9981
  __export(verify_exports, {
9982
+ NO_ROLE_MANIFEST: () => NO_ROLE_MANIFEST,
9983
+ ROLES_NOT_RESOLVED: () => ROLES_NOT_RESOLVED,
9984
+ checkSummarySegments: () => checkSummarySegments,
9985
+ compositionReport: () => compositionReport,
9986
+ failureTally: () => failureTally,
9300
9987
  foldConfigStatus: () => foldConfigStatus,
9301
9988
  interactionCoverage: () => interactionCoverage,
9989
+ resolveComposition: () => resolveComposition,
9302
9990
  runVerify: () => runVerify
9303
9991
  });
9304
9992
  import { existsSync as existsSync25, readFileSync as readFileSync22 } from "node:fs";
@@ -9332,6 +10020,46 @@ function foldConfigStatus(s, failDemotions, substitutedFamilies) {
9332
10020
  absentInkDemoted
9333
10021
  };
9334
10022
  }
10023
+ function resolveComposition(raw) {
10024
+ if (raw === void 0) return NO_ROLE_MANIFEST;
10025
+ const parsed = RolesSchema.safeParse(raw);
10026
+ if (parsed.success) return { roles: parsed.data };
10027
+ const why = parsed.error.issues.slice(0, 3).map((i) => `${i.path.join(".") === "" ? "roles" : i.path.join(".")}: ${i.message}`).join("; ");
10028
+ return {
10029
+ short: "roles block REJECTED",
10030
+ unavailable: `the recording set's roles block was REJECTED by the schema (${why}) \u2014 composition (structural + crop) was NEVER CHECKED`,
10031
+ warn: `recording set roles block REJECTED (${why}) \u2014 the composition checks (structural + crop) did NOT run, while the set still reads as role-confirmed. This is an instrument failure, not a clean bill. Repair the set's roles block and re-verify.`
10032
+ };
10033
+ }
10034
+ function rolesSourceLabel(roles) {
10035
+ return roles.rolesSource === "human-override" ? "HUMAN-OVERRIDE" : roles.rolesSource ?? UNSTAMPED_ROLES;
10036
+ }
10037
+ function checkSummarySegments(input) {
10038
+ const tally = (rows) => `${rows.filter((r) => r.pass).length}/${rows.length}`;
10039
+ const { availability } = input;
10040
+ const composition = availability.unavailable !== void 0 ? `composition NOT CHECKED (${availability.short})` : `composition ${tally(input.structural)} structural, ${input.crops !== void 0 ? `${tally(input.crops)} crops` : "crops unavailable"} (roles: ${rolesSourceLabel(availability.roles)}${(availability.roles.narrowingAccepted ?? []).length > 0 ? `, ${(availability.roles.narrowingAccepted ?? []).length} narrowing(s) accepted: ${(availability.roles.narrowingAccepted ?? []).join(", ")}` : ""})`;
10041
+ const occlusion = input.occlusion.length === 0 ? "occlusion not applicable (no overlay declared)" : `occlusion ${tally(input.occlusion)}`;
10042
+ return ` \xB7 ${composition} \xB7 ${occlusion}`;
10043
+ }
10044
+ function compositionReport(input) {
10045
+ const { availability, regions } = input;
10046
+ if (availability.unavailable !== void 0) return { unavailable: availability.unavailable };
10047
+ const cropsUnavailable = regions !== void 0 && "unavailable" in regions ? regions.unavailable : "interior geometry was never computed for this run";
10048
+ return {
10049
+ rolesSource: availability.roles.rolesSource ?? UNSTAMPED_ROLES,
10050
+ // Each token is a derived main, or a part→main edge, that a human
10051
+ // signed away at confirm time. Every one of them REMOVES something
10052
+ // the structural check would otherwise have had to satisfy, so the
10053
+ // list belongs beside the pass it enabled — not only in the manifest
10054
+ // that recorded it.
10055
+ narrowingAccepted: availability.roles.narrowingAccepted ?? [],
10056
+ structural: input.structural,
10057
+ crops: input.crops ?? { unavailable: cropsUnavailable }
10058
+ };
10059
+ }
10060
+ function failureTally(t) {
10061
+ return `${t.configs.length} config(s), ${t.behaviors.length} behavior(s), ${t.structural.length + t.crops.length} composition check(s), ${t.occlusion.length} occlusion check(s) below the ${t.bar} bar${t.evidenceUnverified ? "; PLUS the interaction-evidence instrument gate failed (operability could not be verified \u2014 see FAIL interaction-evidence above)" : ""} \u2014 bundle written, verdict honest (Q4)`;
10062
+ }
9335
10063
  function taskFromManifest(opts, manifest, setDir) {
9336
10064
  const recordedSlugs = loadManifest(setDir).reps.map((r) => r.slug);
9337
10065
  const adapterSlugs = Object.keys(manifest.propAdapter);
@@ -9395,7 +10123,7 @@ async function runVerify(opts) {
9395
10123
  let unmapped = [];
9396
10124
  let interactionEvidence = [];
9397
10125
  let unmappedInteractionEvidence = [];
9398
- let roles;
10126
+ let availability = ROLES_NOT_RESOLVED;
9399
10127
  if (opts.task !== void 0) {
9400
10128
  const registry = TASKS[opts.task];
9401
10129
  if (registry === void 0) {
@@ -9438,8 +10166,8 @@ async function runVerify(opts) {
9438
10166
  interactionEvidence = built.interactionEvidence;
9439
10167
  unmappedInteractionEvidence = built.unmappedInteractionEvidence;
9440
10168
  for (const s of built.adapterOnly) warn(opts, `prop adapter maps "${s}" which is not in the recording set \u2014 ignored`);
9441
- const rolesParse = RolesSchema.safeParse(loadManifest(setDir).roles);
9442
- if (rolesParse.success) roles = rolesParse.data;
10169
+ availability = resolveComposition(loadManifest(setDir).roles);
10170
+ if (availability.warn !== void 0) warn(opts, availability.warn);
9443
10171
  }
9444
10172
  const hash = recordingSetHash(setDir, task.configs);
9445
10173
  if (hash !== manifest.provenance.recordingSet.hash) {
@@ -9464,6 +10192,7 @@ async function runVerify(opts) {
9464
10192
  remediation: `Regenerate the bundle (bundle v1 carries its prop manifest), or pass --task <${Object.keys(TASKS).join("|")}> for legacy bundles.`
9465
10193
  });
9466
10194
  }
10195
+ const roles = availability.roles;
9467
10196
  if (!fontsResolved()) {
9468
10197
  fail(opts, ExitCode.FontsUnproven, {
9469
10198
  error: "resolved font cache absent \u2014 verification under system font substitution is refused",
@@ -9471,6 +10200,9 @@ async function runVerify(opts) {
9471
10200
  remediation: fontsUnprovenRemediation(task.set)
9472
10201
  });
9473
10202
  }
10203
+ if (lcdTextEnabled()) {
10204
+ warn(opts, "EXPERIMENT override active (TENDRIL_ENABLE_LCD_TEXT=1): text renders with platform LCD antialiasing instead of canonical greyscale \u2014 scores are NOT comparable to default runs; the environment stamp and report are marked");
10205
+ }
9474
10206
  const substitutedFamilies = unprovisionedFamilies(task.set);
9475
10207
  if (substitutedFamilies.length > 0) {
9476
10208
  warn(opts, `substituted fonts: cache lacks ${substitutedFamilies.map((f) => `"${f}"`).join(", ")} \u2014 scores measure a substitute face and no config can be certified under one (the stamp covers only the provisioned subset); resolve the families to certify`);
@@ -9535,7 +10267,10 @@ async function runVerify(opts) {
9535
10267
  ...opts.task !== void 0 ? { task: opts.task } : {},
9536
10268
  ...manifest !== void 0 ? { bundleManifest: { name: manifest.name, bundleVersion: manifest.bundleVersion, recordingSetHash: manifest.provenance.recordingSet.hash } } : {},
9537
10269
  targetBar: opts.bar,
9538
- environment: environmentStamp(taskFontFamilies(task.set)),
10270
+ // Canonical mount semantics are VERSION-scoped (0.1.22 review: the
10271
+ // greyscale flip changed Windows pixels under an identical-looking
10272
+ // stamp) — the ruler version is part of the comparability key.
10273
+ environment: { ...environmentStamp(taskFontFamilies(task.set)), ruler: cliVersion() },
9539
10274
  coverage: {
9540
10275
  scoredConfigs: statuses.length,
9541
10276
  certified,
@@ -9580,18 +10315,23 @@ async function runVerify(opts) {
9580
10315
  configs: statuses,
9581
10316
  behaviors,
9582
10317
  evidence: { dir: evidenceDir, files: "per config: <rep>-render.png, <rep>-ref.png, <rep>-diff.png" },
9583
- ...roles !== void 0 ? {
9584
- composition: {
9585
- structural,
9586
- crops: crops ?? { unavailable: regionsOut !== void 0 && "unavailable" in regionsOut ? regionsOut.unavailable : "no role manifest" }
9587
- }
9588
- } : {},
10318
+ composition: compositionReport({ availability, structural, crops, regions: regionsOut }),
9589
10319
  verdict: ok ? "verified" : "verification-failed",
9590
10320
  // Machine-readable cause (adversarial review): a cert-bar failure
9591
10321
  // with zero pixel/behavior/composition failures was only
9592
10322
  // explainable from stderr prose.
9593
10323
  ...certBlockedByAbsentInk.length > 0 ? { certBlockedByAbsentInk } : {},
9594
- ...weightGaps.length > 0 ? { fontWeightGaps: weightGaps } : {}
10324
+ ...weightGaps.length > 0 ? { fontWeightGaps: weightGaps } : {},
10325
+ ...lcdTextEnabled() ? { environmentOverrides: ["enable-lcd-text"] } : {},
10326
+ // Run 13 finding 1: the eye-check nudge lived only in the human
10327
+ // footer, so MCP-driven agents — the documented path — were never
10328
+ // told the check exists and shipped without ever opening a sheet.
10329
+ // Structured here so every consumer sees it.
10330
+ eyeCheck: {
10331
+ command: `tendril inspect "${opts.bundleDir}"`,
10332
+ sheetPath: path31.join(opts.bundleDir, "verify-evidence", "inspect.html"),
10333
+ note: "magnified recorded-vs-rendered crops of every small node; scores cannot see shape. The command WRITES/refreshes the sheet at sheetPath \u2014 re-run it after every verify; an existing sheet may show stale crops."
10334
+ }
9595
10335
  };
9596
10336
  emitData(opts, report, () => {
9597
10337
  for (const s of statuses) {
@@ -9613,17 +10353,22 @@ async function runVerify(opts) {
9613
10353
  process.stdout.write(`${o.pass ? "PASS" : "FAIL"} ${o.id}${o.detail !== void 0 ? ` [${o.detail}]` : ""}
9614
10354
  `);
9615
10355
  }
9616
- if (crops !== void 0) {
10356
+ if (availability.unavailable !== void 0) {
10357
+ process.stdout.write(`UNAVAILABLE composition \u2014 ${availability.unavailable}
10358
+ `);
10359
+ } else if (crops !== void 0) {
9617
10360
  for (const c of crops) process.stdout.write(`${c.pass ? "PASS" : "FAIL"} ${c.id} sim=${c.similarity} ink=${c.inkRecall}${c.detail !== void 0 ? ` [${c.detail}]` : ""}
9618
10361
  `);
9619
- } else if (roles !== void 0 && regionsOut !== void 0 && "unavailable" in regionsOut) {
10362
+ } else if (regionsOut !== void 0 && "unavailable" in regionsOut) {
9620
10363
  process.stdout.write(`UNAVAILABLE composition crops \u2014 ${regionsOut.unavailable}
9621
10364
  `);
9622
10365
  }
9623
10366
  const ic = interactionCoverage(behaviors);
9624
10367
  process.stdout.write(
9625
10368
  `
9626
- ${certified}/${statuses.length} certified \xB7 ${report.coverage.pass}/${statuses.length} \u2265 pass bar \xB7 behaviors ${behaviors.length - behaviorFailures.length}/${behaviors.length}${roles !== void 0 ? ` \xB7 composition ${structural.length - structuralFailures.length}/${structural.length} structural${crops !== void 0 ? `, ${crops.length - cropFailures.length}/${crops.length} crops` : ", crops unavailable"}` : ""}
10369
+ ${certified}/${statuses.length} certified \xB7 ${report.coverage.pass}/${statuses.length} \u2265 pass bar \xB7 behaviors ${behaviors.length - behaviorFailures.length}/${behaviors.length}${checkSummarySegments(
10370
+ { availability, structural, crops, occlusion }
10371
+ )}
9627
10372
  `
9628
10373
  );
9629
10374
  const QUALITY_SHOWN = 8;
@@ -9691,7 +10436,7 @@ ${certified}/${statuses.length} certified \xB7 ${report.coverage.pass}/${statuse
9691
10436
  }
9692
10437
  process.stdout.write(`evidence: ${evidenceDir} (render/ref/diff per config)
9693
10438
  `);
9694
- process.stdout.write(`eye check: tendril inspect ${opts.bundleDir} \u2014 magnified recorded-vs-rendered crops of every small node; scores cannot see shape
10439
+ process.stdout.write(`eye check: tendril inspect "${opts.bundleDir}" \u2014 magnified recorded-vs-rendered crops of every small node; scores cannot see shape (re-run after every verify)
9695
10440
  `);
9696
10441
  });
9697
10442
  if (opts.bar === "cert" && substitutedFamilies.length > 0) {
@@ -9718,14 +10463,22 @@ ${certified}/${statuses.length} certified \xB7 ${report.coverage.pass}/${statuse
9718
10463
  if (!okExceptDemotion) {
9719
10464
  warn(
9720
10465
  opts,
9721
- `${pixelFailures.length} config(s), ${behaviorFailures.length} behavior(s), ${structuralFailures.length + cropFailures.length + occlusionFailures.length} composition check(s) below the ${opts.bar} bar${evidenceUnverified ? "; PLUS the interaction-evidence instrument gate failed (operability could not be verified \u2014 see FAIL interaction-evidence above)" : ""} \u2014 bundle written, verdict honest (Q4)`
10466
+ failureTally({
10467
+ configs: pixelFailures,
10468
+ behaviors: behaviorFailures,
10469
+ structural: structuralFailures,
10470
+ crops: cropFailures,
10471
+ occlusion: occlusionFailures,
10472
+ bar: opts.bar,
10473
+ evidenceUnverified
10474
+ })
9722
10475
  );
9723
10476
  process.exitCode = ExitCode.VerificationFailed;
9724
10477
  }
9725
10478
  }
9726
- var BARS2;
10479
+ var BARS2, NO_ROLE_MANIFEST, ROLES_NOT_RESOLVED, UNSTAMPED_ROLES;
9727
10480
  var init_verify = __esm({
9728
- "packages/cli/src/commands/verify.ts"() {
10481
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/commands/verify.ts"() {
9729
10482
  "use strict";
9730
10483
  init_src3();
9731
10484
  init_src6();
@@ -9739,10 +10492,19 @@ var init_verify = __esm({
9739
10492
  pass: { sim: 0.95, ink: 0.95 },
9740
10493
  cert: { sim: 0.97, ink: 0.95 }
9741
10494
  };
10495
+ NO_ROLE_MANIFEST = Object.freeze({
10496
+ short: "no role manifest",
10497
+ unavailable: "the recording set declares no role manifest \u2014 composition (structural + crop) was NEVER CHECKED; nothing here says the main renders the SHIPPED part modules rather than a pixel-identical re-implementation"
10498
+ });
10499
+ ROLES_NOT_RESOLVED = Object.freeze({
10500
+ short: "roles never resolved on this path",
10501
+ unavailable: "this run never resolved a role manifest \u2014 the legacy --task adapter and pre-manifest reference sets skip the set's roles block entirely, so composition (structural + crop) was NEVER CHECKED and the set was never asked what it declares; nothing here says the main renders the SHIPPED part modules rather than a pixel-identical re-implementation"
10502
+ });
10503
+ UNSTAMPED_ROLES = "unstamped";
9742
10504
  }
9743
10505
  });
9744
10506
 
9745
- // packages/cli/src/commands/engine.ts
10507
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/commands/engine.ts
9746
10508
  var engine_exports = {};
9747
10509
  __export(engine_exports, {
9748
10510
  runEngineBrief: () => runEngineBrief,
@@ -9883,6 +10645,9 @@ async function runEngineScore(opts) {
9883
10645
  remediation: fontsUnprovenRemediation(task.set)
9884
10646
  });
9885
10647
  }
10648
+ if (lcdTextEnabled()) {
10649
+ warn(opts, "EXPERIMENT override active (TENDRIL_ENABLE_LCD_TEXT=1): text renders with platform LCD antialiasing instead of canonical greyscale \u2014 scores are NOT comparable to default runs; the environment stamp and report are marked");
10650
+ }
9886
10651
  const substitutedFamilies = unprovisionedFamilies(task.set);
9887
10652
  if (substitutedFamilies.length > 0) {
9888
10653
  warn(opts, `substituted fonts: cache lacks ${substitutedFamilies.map((f) => `"${f}"`).join(", ")} \u2014 scores measure a substitute face and no config can be certified under one (the stamp covers only the provisioned subset); resolve the families to certify`);
@@ -9982,6 +10747,8 @@ METRIC DEADBAND (read before iterating on near-misses): the scored similarity/in
9982
10747
  bundleManifest: emitted.written[0],
9983
10748
  note: "styles.css was stamped with the bundle provenance comment on line 1 \u2014 preserve it in any post-score edit",
9984
10749
  allPass,
10750
+ environment: { ...environmentStamp(taskFontFamilies(task.set)), ruler: cliVersion() },
10751
+ ...lcdTextEnabled() ? { environmentOverrides: ["enable-lcd-text"] } : {},
9985
10752
  // Run 11: generators read allPass:true and reported success on
9986
10753
  // bundles verify then FAILED on the interaction-evidence gate —
9987
10754
  // the oracle must say what verify will say, including this.
@@ -10026,7 +10793,7 @@ ${obj[0]}/${total} \xB7 certified ${certifiedReps.length}/${total} \xB7 floor=${
10026
10793
  }
10027
10794
  var BARS3;
10028
10795
  var init_engine2 = __esm({
10029
- "packages/cli/src/commands/engine.ts"() {
10796
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/commands/engine.ts"() {
10030
10797
  "use strict";
10031
10798
  init_src3();
10032
10799
  init_src7();
@@ -10045,7 +10812,7 @@ var init_engine2 = __esm({
10045
10812
  }
10046
10813
  });
10047
10814
 
10048
- // packages/cli/src/commands/codeconnect.ts
10815
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/commands/codeconnect.ts
10049
10816
  var codeconnect_exports = {};
10050
10817
  __export(codeconnect_exports, {
10051
10818
  runCodeConnect: () => runCodeConnect
@@ -10209,7 +10976,7 @@ function runCodeConnect(opts) {
10209
10976
  }
10210
10977
  var kebab4, q;
10211
10978
  var init_codeconnect = __esm({
10212
- "packages/cli/src/commands/codeconnect.ts"() {
10979
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/commands/codeconnect.ts"() {
10213
10980
  "use strict";
10214
10981
  init_src3();
10215
10982
  init_src7();
@@ -10221,7 +10988,7 @@ var init_codeconnect = __esm({
10221
10988
  }
10222
10989
  });
10223
10990
 
10224
- // packages/mcp/src/server.ts
10991
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/mcp/src/server.ts
10225
10992
  import { createHash as createHash5 } from "node:crypto";
10226
10993
  import { existsSync as existsSync28, mkdtempSync as mkdtempSync3, readFileSync as readFileSync25, readdirSync as readdirSync8, writeFileSync as writeFileSync14 } from "node:fs";
10227
10994
  import os6 from "node:os";
@@ -10239,7 +11006,7 @@ function sourceHash() {
10239
11006
  }
10240
11007
  var REPO_ROOT3, CLI_BIN, BUNDLED_CLI, CLI_SPAWN, str, optStr, TOOLS, BOOT_HASH;
10241
11008
  var init_server = __esm({
10242
- "packages/mcp/src/server.ts"() {
11009
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/mcp/src/server.ts"() {
10243
11010
  "use strict";
10244
11011
  REPO_ROOT3 = path34.resolve(path34.dirname(fileURLToPath5(import.meta.url)), "..", "..", "..");
10245
11012
  CLI_BIN = path34.join(REPO_ROOT3, "packages", "cli", "src", "bin.ts");
@@ -10535,7 +11302,7 @@ var init_server = __esm({
10535
11302
  }
10536
11303
  });
10537
11304
 
10538
- // packages/cli/src/commands/permissions.ts
11305
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/commands/permissions.ts
10539
11306
  var permissions_exports = {};
10540
11307
  __export(permissions_exports, {
10541
11308
  PERMISSIONS_DESCRIPTION: () => PERMISSIONS_DESCRIPTION,
@@ -10649,7 +11416,7 @@ ${result.directConfigNote}
10649
11416
  }
10650
11417
  var FIGMA_TOOL_FALLBACK, PERMISSIONS_DESCRIPTION, TENDRIL_PLUGIN_PREFIX, FIGMA_PLUGIN_PREFIX;
10651
11418
  var init_permissions = __esm({
10652
- "packages/cli/src/commands/permissions.ts"() {
11419
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/commands/permissions.ts"() {
10653
11420
  "use strict";
10654
11421
  init_src3();
10655
11422
  init_src();
@@ -10684,7 +11451,7 @@ var init_permissions = __esm({
10684
11451
  }
10685
11452
  });
10686
11453
 
10687
- // packages/cli/src/commands/inspect.ts
11454
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/commands/inspect.ts
10688
11455
  var inspect_exports = {};
10689
11456
  __export(inspect_exports, {
10690
11457
  INSPECT_DESCRIPTION: () => INSPECT_DESCRIPTION,
@@ -10773,7 +11540,7 @@ ${reps.length} config(s), ${crops} detail crop pair(s) \u2014 open the sheet and
10773
11540
  }
10774
11541
  var INSPECT_DESCRIPTION, esc;
10775
11542
  var init_inspect = __esm({
10776
- "packages/cli/src/commands/inspect.ts"() {
11543
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/commands/inspect.ts"() {
10777
11544
  "use strict";
10778
11545
  init_src3();
10779
11546
  init_src6();
@@ -10801,7 +11568,7 @@ var init_inspect = __esm({
10801
11568
  }
10802
11569
  });
10803
11570
 
10804
- // packages/cli/src/commands/generate-route.ts
11571
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/commands/generate-route.ts
10805
11572
  var generate_route_exports = {};
10806
11573
  __export(generate_route_exports, {
10807
11574
  routeGenerate: () => routeGenerate
@@ -10814,12 +11581,12 @@ function routeGenerate(input) {
10814
11581
  return { path: "facts", ...input.url !== void 0 ? { url: input.url } : {} };
10815
11582
  }
10816
11583
  var init_generate_route = __esm({
10817
- "packages/cli/src/commands/generate-route.ts"() {
11584
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/commands/generate-route.ts"() {
10818
11585
  "use strict";
10819
11586
  }
10820
11587
  });
10821
11588
 
10822
- // packages/cli/src/commands/generate-recorded.ts
11589
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/commands/generate-recorded.ts
10823
11590
  var generate_recorded_exports = {};
10824
11591
  __export(generate_recorded_exports, {
10825
11592
  runGenerateRecorded: () => runGenerateRecorded
@@ -11101,7 +11868,7 @@ ${certified}/${statuses.length} certified \xB7 ${statuses.length - pixelFailures
11101
11868
  }
11102
11869
  var BARS4;
11103
11870
  var init_generate_recorded = __esm({
11104
- "packages/cli/src/commands/generate-recorded.ts"() {
11871
+ "../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/commands/generate-recorded.ts"() {
11105
11872
  "use strict";
11106
11873
  init_src3();
11107
11874
  init_src5();
@@ -11120,17 +11887,17 @@ var init_generate_recorded = __esm({
11120
11887
  }
11121
11888
  });
11122
11889
 
11123
- // packages/cli/src/bin.ts
11890
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/bin.ts
11124
11891
  init_src3();
11125
11892
  import { CommanderError } from "commander";
11126
11893
 
11127
- // packages/cli/src/program.ts
11894
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/program.ts
11128
11895
  init_src3();
11129
11896
  init_environment();
11130
11897
  init_doctor();
11131
11898
  import { Command } from "commander";
11132
11899
 
11133
- // packages/cli/src/commands/init.ts
11900
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/commands/init.ts
11134
11901
  init_src3();
11135
11902
  init_describe();
11136
11903
  init_env();
@@ -11240,7 +12007,7 @@ async function runInit(flags) {
11240
12007
  });
11241
12008
  }
11242
12009
 
11243
- // packages/cli/src/commands/generate.ts
12010
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/commands/generate.ts
11244
12011
  init_src3();
11245
12012
  init_src();
11246
12013
  init_src5();
@@ -11252,14 +12019,14 @@ init_entitlement();
11252
12019
  import { confirm as confirm2, isCancel as isCancel2 } from "@clack/prompts";
11253
12020
  import { readFileSync as readFileSync15, readdirSync as readdirSync4, existsSync as existsSync18 } from "node:fs";
11254
12021
 
11255
- // packages/cli/src/pipeline.ts
12022
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/pipeline.ts
11256
12023
  init_src2();
11257
12024
  init_src4();
11258
12025
  init_src6();
11259
12026
  import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync8 } from "node:fs";
11260
12027
  import path24 from "node:path";
11261
12028
 
11262
- // packages/cli/src/assets-module.ts
12029
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/assets-module.ts
11263
12030
  init_src();
11264
12031
  var KEBAB_ATTRS = {
11265
12032
  "fill-rule": "fillRule",
@@ -11370,7 +12137,7 @@ function buildAssetsModule(assets, aliases = {}) {
11370
12137
  return { source, flags };
11371
12138
  }
11372
12139
 
11373
- // packages/cli/src/pipeline.ts
12140
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/pipeline.ts
11374
12141
  var VerifyFailedError = class extends Error {
11375
12142
  constructor(loop) {
11376
12143
  super(
@@ -11631,7 +12398,7 @@ async function runGenerationPipeline(input) {
11631
12398
  return { semantics, loop: finalLoop, report, componentJson, usageMd: docs.usageMd, written };
11632
12399
  }
11633
12400
 
11634
- // packages/cli/src/commands/generate.ts
12401
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/commands/generate.ts
11635
12402
  var TOOL_VERSION = "0.0.0";
11636
12403
  var GENERATE_DESCRIPTION = {
11637
12404
  name: "generate",
@@ -11959,7 +12726,7 @@ bundle written to ${flags.out}/${result.semantics.componentName}/:
11959
12726
  );
11960
12727
  }
11961
12728
 
11962
- // packages/cli/src/program.ts
12729
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/program.ts
11963
12730
  init_src4();
11964
12731
  function globalFlags(cmd) {
11965
12732
  const opts = cmd.optsWithGlobals();
@@ -12216,7 +12983,7 @@ function buildProgram() {
12216
12983
  return program;
12217
12984
  }
12218
12985
 
12219
- // packages/cli/src/bin.ts
12986
+ // ../../../../../../Users/jordyarnoldussen/Desktop/Tendril/packages/cli/src/bin.ts
12220
12987
  try {
12221
12988
  await buildProgram().parseAsync(process.argv);
12222
12989
  } catch (err) {