superbee 0.4.3-pre.4 → 0.4.3-pre.6

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.
@@ -3199,7 +3199,8 @@ function isExternalHref(href) {
3199
3199
  const h = href.trim();
3200
3200
  return /^[a-z][a-z0-9+.-]*:\/\//i.test(h) || h.startsWith("mailto:") || h.startsWith("#");
3201
3201
  }
3202
- function extractMarkdownLinks(body) {
3202
+ function extractMarkdownLinks(source, options = {}) {
3203
+ const body = options.skipCode ? maskMarkdownCode(source) : source;
3203
3204
  const out = [];
3204
3205
  let textOpen = -1;
3205
3206
  let afterClose;
@@ -3211,8 +3212,8 @@ function extractMarkdownLinks(body) {
3211
3212
  if (char === ")") {
3212
3213
  if (hrefRest.open === 0 || body[hrefRest.open - 1] !== "!") {
3213
3214
  out.push({
3214
- text: body.slice(hrefRest.open + 1, hrefRest.close),
3215
- href: body.slice(hrefRest.hrefStart, cursor)
3215
+ text: source.slice(hrefRest.open + 1, hrefRest.close),
3216
+ href: source.slice(hrefRest.hrefStart, cursor)
3216
3217
  });
3217
3218
  }
3218
3219
  textOpen = -1;
@@ -3243,6 +3244,150 @@ function extractMarkdownLinks(body) {
3243
3244
  }
3244
3245
  return out;
3245
3246
  }
3247
+ function leadingIndent(line, from, startColumn) {
3248
+ let columns = 0;
3249
+ let index = from;
3250
+ while (index < line.length) {
3251
+ const char = line[index];
3252
+ if (char === " ") columns += 1;
3253
+ else if (char === " ") columns += 4 - (startColumn + columns) % 4;
3254
+ else break;
3255
+ index++;
3256
+ }
3257
+ return { columns, chars: index - from };
3258
+ }
3259
+ var FENCE_OPEN = /^(`{3,}|~{3,})(.*)$/;
3260
+ var LIST_MARKER = /^([-+*]|\d{1,9}[.)])([ \t]+|$)/;
3261
+ var THEMATIC_BREAK = /^(?:(?:\*[ \t]*){3,}|(?:-[ \t]*){3,}|(?:_[ \t]*){3,})$/;
3262
+ var ATX_HEADING = /^#{1,6}(?:[ \t]|$)/;
3263
+ function maskMarkdownCode(body) {
3264
+ const out = body.split("");
3265
+ const blank = (from, to) => {
3266
+ for (let index = from; index < to; index++) if (out[index] !== "\n" && out[index] !== "\r") out[index] = " ";
3267
+ };
3268
+ const lists = [];
3269
+ let fence = null;
3270
+ let inParagraph = false;
3271
+ let segmentStart = -1;
3272
+ const closeSegment = (end) => {
3273
+ if (segmentStart >= 0) maskCodeSpans(body, segmentStart, end, blank);
3274
+ segmentStart = -1;
3275
+ };
3276
+ let lineStart = 0;
3277
+ while (lineStart <= body.length) {
3278
+ const newline = body.indexOf("\n", lineStart);
3279
+ const lineEnd = newline < 0 ? body.length : newline;
3280
+ const line = body.slice(lineStart, lineEnd);
3281
+ let contentAt = 0;
3282
+ let quotes = 0;
3283
+ for (let match = /^ {0,3}> ?/.exec(line); match; match = /^ {0,3}> ?/.exec(line.slice(contentAt))) {
3284
+ if (fence && quotes >= fence.quotes) break;
3285
+ contentAt += match[0].length;
3286
+ quotes++;
3287
+ }
3288
+ const { columns: indent, chars } = leadingIndent(line, contentAt, contentAt);
3289
+ const rest = line.slice(contentAt + chars).replace(/\r$/, "");
3290
+ const isBlank = rest.trim() === "";
3291
+ if (fence && (quotes < fence.quotes || !isBlank && indent < fence.container)) fence = null;
3292
+ if (fence) {
3293
+ const close = indent - fence.container <= 3 ? FENCE_OPEN.exec(rest) : null;
3294
+ if (close && close[1][0] === fence.char && close[1].length >= fence.length && close[2].trim() === "") fence = null;
3295
+ blank(lineStart, lineEnd);
3296
+ } else if (isBlank) {
3297
+ closeSegment(lineStart);
3298
+ inParagraph = false;
3299
+ } else {
3300
+ if (!inParagraph) while (lists.length > 0 && lists[lists.length - 1] > indent) lists.pop();
3301
+ let container = lists.length > 0 ? lists[lists.length - 1] : 0;
3302
+ let relative = indent - container;
3303
+ let text = rest;
3304
+ let textAt = lineStart + contentAt + chars;
3305
+ const marker = relative <= 3 && !THEMATIC_BREAK.test(text) ? LIST_MARKER.exec(text) : null;
3306
+ if (marker) {
3307
+ closeSegment(lineStart);
3308
+ const markerEnd = indent + marker[1].length;
3309
+ const spacing = leadingIndent(marker[2], 0, contentAt + markerEnd).columns;
3310
+ const wide = marker[2] === "" || spacing >= 5;
3311
+ lists.push(markerEnd + (wide ? 1 : spacing));
3312
+ container = lists[lists.length - 1];
3313
+ text = text.slice(marker[1].length + (wide ? 0 : marker[2].length));
3314
+ textAt += marker[1].length + (wide ? 0 : marker[2].length);
3315
+ relative = wide ? Math.max(spacing - 1, 0) : 0;
3316
+ inParagraph = false;
3317
+ }
3318
+ const open = relative <= 3 ? FENCE_OPEN.exec(text) : null;
3319
+ if (open && !(open[1][0] === "`" && open[2].includes("`"))) {
3320
+ closeSegment(lineStart);
3321
+ fence = { char: open[1][0], length: open[1].length, container, quotes };
3322
+ blank(textAt, lineEnd);
3323
+ inParagraph = false;
3324
+ } else if (!inParagraph && relative >= 4) {
3325
+ closeSegment(lineStart);
3326
+ blank(textAt, lineEnd);
3327
+ } else if (ATX_HEADING.test(text) || THEMATIC_BREAK.test(text)) {
3328
+ closeSegment(lineStart);
3329
+ maskCodeSpans(body, textAt, lineEnd, blank);
3330
+ inParagraph = false;
3331
+ } else {
3332
+ if (segmentStart < 0) segmentStart = textAt;
3333
+ inParagraph = text.trim() !== "";
3334
+ }
3335
+ }
3336
+ if (newline < 0) break;
3337
+ lineStart = newline + 1;
3338
+ }
3339
+ closeSegment(body.length);
3340
+ return out.join("");
3341
+ }
3342
+ function maskCodeSpans(body, from, to, blank) {
3343
+ const runs = [];
3344
+ for (let index = from; index < to; ) {
3345
+ if (body[index] !== "`") {
3346
+ index++;
3347
+ continue;
3348
+ }
3349
+ let end = index;
3350
+ while (end < to && body[end] === "`") end++;
3351
+ runs.push({ at: index, length: end - index });
3352
+ index = end;
3353
+ }
3354
+ const byLength = /* @__PURE__ */ new Map();
3355
+ runs.forEach((run, position) => {
3356
+ const list2 = byLength.get(run.length);
3357
+ if (list2) list2.push(position);
3358
+ else byLength.set(run.length, [position]);
3359
+ });
3360
+ const next = /* @__PURE__ */ new Map();
3361
+ const nextRun = (length, after) => {
3362
+ const list2 = byLength.get(length);
3363
+ if (!list2) return -1;
3364
+ let cursor = next.get(length) ?? 0;
3365
+ while (cursor < list2.length && list2[cursor] <= after) cursor++;
3366
+ next.set(length, cursor);
3367
+ return cursor < list2.length ? list2[cursor] : -1;
3368
+ };
3369
+ let escapeScan = from;
3370
+ let escaped = false;
3371
+ for (let position = 0; position < runs.length; position++) {
3372
+ let { at, length } = runs[position];
3373
+ for (; escapeScan < at; escapeScan++) escaped = body[escapeScan] === "\\" ? !escaped : false;
3374
+ if (escaped) {
3375
+ at += 1;
3376
+ length -= 1;
3377
+ escaped = false;
3378
+ if (length === 0) continue;
3379
+ const list2 = byLength.get(length);
3380
+ if (!list2) continue;
3381
+ }
3382
+ const closer = nextRun(length, position);
3383
+ if (closer < 0) continue;
3384
+ const close = runs[closer];
3385
+ blank(at, close.at + close.length);
3386
+ position = closer;
3387
+ escapeScan = close.at + close.length;
3388
+ escaped = false;
3389
+ }
3390
+ }
3246
3391
  function resolveConceptId(fromId, href) {
3247
3392
  const target = (href.split("#")[0] ?? "").split("?")[0]?.trim() ?? "";
3248
3393
  if (target === "" || isExternalHref(target)) return null;
@@ -5015,6 +5160,23 @@ setDefaultBackendFactory((root) => new FilesystemBackend(root));
5015
5160
  // ../core/src/kinds.ts
5016
5161
  var CONVENTIONS_PREFIX = "conventions/";
5017
5162
  var CONVENTION_TYPE = "Convention";
5163
+ var KIND_FIELD_TYPES = [
5164
+ "date",
5165
+ "datetime",
5166
+ "https-url",
5167
+ "https-url-list",
5168
+ "integer",
5169
+ "number",
5170
+ "boolean",
5171
+ "slug",
5172
+ "string-list",
5173
+ "latitude",
5174
+ "longitude"
5175
+ ];
5176
+ var KIND_FIELD_TYPE_SET = new Set(KIND_FIELD_TYPES);
5177
+ function isKindFieldType(value) {
5178
+ return typeof value === "string" && KIND_FIELD_TYPE_SET.has(value);
5179
+ }
5018
5180
  function buildKindRegistry(docs, initialWarnings = [], options = {}) {
5019
5181
  const accepted = /* @__PURE__ */ new Map();
5020
5182
  const warnings = [...initialWarnings];
@@ -5166,7 +5328,8 @@ var VALID_FIELDS_KEYS = /* @__PURE__ */ new Set([
5166
5328
  "values",
5167
5329
  "value_descriptions",
5168
5330
  "terminal",
5169
- "descriptions"
5331
+ "descriptions",
5332
+ "types"
5170
5333
  ]);
5171
5334
  var MISPLACED_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set(["enum", "enums", "values", "constraints"]);
5172
5335
  var CLAIM_COORDINATE_KEYS = [
@@ -5206,7 +5369,7 @@ function parseConventionDoc(doc, options = {}) {
5206
5369
  if (!VALID_FIELDS_KEYS.has(key)) {
5207
5370
  warnings.push({
5208
5371
  code: "KIND_CONVENTION_UNKNOWN_FIELDS_KEY",
5209
- message: `kind convention '${doc.id}' declares an unrecognized key 'fields.${key}' (valid keys: fields.required, fields.optional, fields.values, fields.value_descriptions, fields.terminal, fields.descriptions); ignoring it.`,
5372
+ message: `kind convention '${doc.id}' declares an unrecognized key 'fields.${key}' (valid keys: fields.required, fields.optional, fields.values, fields.value_descriptions, fields.terminal, fields.descriptions, fields.types); ignoring it.`,
5210
5373
  field: `fields.${key}`,
5211
5374
  severity: "warning"
5212
5375
  });
@@ -5263,6 +5426,51 @@ function parseConventionDoc(doc, options = {}) {
5263
5426
  });
5264
5427
  }
5265
5428
  }
5429
+ const typesSource = fieldsRaw.types;
5430
+ const types = {};
5431
+ if (typesSource !== void 0) {
5432
+ if (!isPlainObject(typesSource)) {
5433
+ warnings.push({
5434
+ code: "KIND_CONVENTION_BAD_SHAPE",
5435
+ message: `kind convention '${doc.id}' has a non-map 'fields.types' (${describeShape(typesSource)}; expected a map of field name -> type); ignoring it.`,
5436
+ field: "fields.types",
5437
+ severity: "warning"
5438
+ });
5439
+ } else {
5440
+ for (const [field, declared] of Object.entries(typesSource)) {
5441
+ if (dropReserved(field, `fields.types.${field}`)) continue;
5442
+ if (!isKindFieldType(declared)) {
5443
+ warnings.push({
5444
+ code: "KIND_CONVENTION_UNKNOWN_FIELD_TYPE",
5445
+ message: `kind convention '${doc.id}' declares 'fields.types.${field}' as ${isScalar(declared) ? `'${String(declared)}'` : describeShape(declared)}, which is not a field type (valid types: ${KIND_FIELD_TYPES.join(", ")}); ignoring it.`,
5446
+ field: `fields.types.${field}`,
5447
+ severity: "warning"
5448
+ });
5449
+ continue;
5450
+ }
5451
+ if (!declaredFieldNames.has(field)) {
5452
+ warnings.push({
5453
+ code: "KIND_CONVENTION_UNDECLARED_TYPES_FIELD",
5454
+ message: `kind convention '${doc.id}' declares 'fields.types.${field}' but '${field}' is not in fields.required or fields.optional; ignoring it.`,
5455
+ field: `fields.types.${field}`,
5456
+ severity: "warning"
5457
+ });
5458
+ continue;
5459
+ }
5460
+ setOwn(types, field, declared);
5461
+ }
5462
+ }
5463
+ }
5464
+ for (const field of Object.keys(values)) {
5465
+ if (types[field] !== "https-url-list") continue;
5466
+ warnings.push({
5467
+ code: "KIND_CONVENTION_VALUES_TYPE_MISMATCH",
5468
+ message: `kind convention '${doc.id}' declares 'fields.values.${field}' on a field of type 'https-url-list', which cannot carry an enum; ignoring the values.`,
5469
+ field: `fields.values.${field}`,
5470
+ severity: "warning"
5471
+ });
5472
+ delete values[field];
5473
+ }
5266
5474
  const valueDescriptionsSource = fieldsRaw.value_descriptions;
5267
5475
  const valueDescriptions = {};
5268
5476
  if (valueDescriptionsSource !== void 0) {
@@ -5555,6 +5763,7 @@ function parseConventionDoc(doc, options = {}) {
5555
5763
  governs,
5556
5764
  fields: { required, optional, values, valueDescriptions, terminal, descriptions }
5557
5765
  };
5766
+ if (Object.keys(types).length > 0) kind.fields.types = types;
5558
5767
  if (description !== void 0) kind.description = description;
5559
5768
  if (path4 !== void 0) kind.path = path4;
5560
5769
  if (links !== void 0) kind.links = links;
@@ -31153,7 +31153,8 @@ function isExternalHref(href) {
31153
31153
  const h = href.trim();
31154
31154
  return /^[a-z][a-z0-9+.-]*:\/\//i.test(h) || h.startsWith("mailto:") || h.startsWith("#");
31155
31155
  }
31156
- function extractMarkdownLinks(body) {
31156
+ function extractMarkdownLinks(source, options = {}) {
31157
+ const body = options.skipCode ? maskMarkdownCode(source) : source;
31157
31158
  const out = [];
31158
31159
  let textOpen = -1;
31159
31160
  let afterClose;
@@ -31165,8 +31166,8 @@ function extractMarkdownLinks(body) {
31165
31166
  if (char === ")") {
31166
31167
  if (hrefRest.open === 0 || body[hrefRest.open - 1] !== "!") {
31167
31168
  out.push({
31168
- text: body.slice(hrefRest.open + 1, hrefRest.close),
31169
- href: body.slice(hrefRest.hrefStart, cursor)
31169
+ text: source.slice(hrefRest.open + 1, hrefRest.close),
31170
+ href: source.slice(hrefRest.hrefStart, cursor)
31170
31171
  });
31171
31172
  }
31172
31173
  textOpen = -1;
@@ -31197,6 +31198,150 @@ function extractMarkdownLinks(body) {
31197
31198
  }
31198
31199
  return out;
31199
31200
  }
31201
+ function leadingIndent(line, from, startColumn) {
31202
+ let columns = 0;
31203
+ let index2 = from;
31204
+ while (index2 < line.length) {
31205
+ const char = line[index2];
31206
+ if (char === " ") columns += 1;
31207
+ else if (char === " ") columns += 4 - (startColumn + columns) % 4;
31208
+ else break;
31209
+ index2++;
31210
+ }
31211
+ return { columns, chars: index2 - from };
31212
+ }
31213
+ var FENCE_OPEN = /^(`{3,}|~{3,})(.*)$/;
31214
+ var LIST_MARKER = /^([-+*]|\d{1,9}[.)])([ \t]+|$)/;
31215
+ var THEMATIC_BREAK = /^(?:(?:\*[ \t]*){3,}|(?:-[ \t]*){3,}|(?:_[ \t]*){3,})$/;
31216
+ var ATX_HEADING = /^#{1,6}(?:[ \t]|$)/;
31217
+ function maskMarkdownCode(body) {
31218
+ const out = body.split("");
31219
+ const blank = (from, to) => {
31220
+ for (let index2 = from; index2 < to; index2++) if (out[index2] !== "\n" && out[index2] !== "\r") out[index2] = " ";
31221
+ };
31222
+ const lists = [];
31223
+ let fence = null;
31224
+ let inParagraph = false;
31225
+ let segmentStart = -1;
31226
+ const closeSegment = (end) => {
31227
+ if (segmentStart >= 0) maskCodeSpans(body, segmentStart, end, blank);
31228
+ segmentStart = -1;
31229
+ };
31230
+ let lineStart = 0;
31231
+ while (lineStart <= body.length) {
31232
+ const newline = body.indexOf("\n", lineStart);
31233
+ const lineEnd = newline < 0 ? body.length : newline;
31234
+ const line = body.slice(lineStart, lineEnd);
31235
+ let contentAt = 0;
31236
+ let quotes = 0;
31237
+ for (let match = /^ {0,3}> ?/.exec(line); match; match = /^ {0,3}> ?/.exec(line.slice(contentAt))) {
31238
+ if (fence && quotes >= fence.quotes) break;
31239
+ contentAt += match[0].length;
31240
+ quotes++;
31241
+ }
31242
+ const { columns: indent2, chars } = leadingIndent(line, contentAt, contentAt);
31243
+ const rest = line.slice(contentAt + chars).replace(/\r$/, "");
31244
+ const isBlank = rest.trim() === "";
31245
+ if (fence && (quotes < fence.quotes || !isBlank && indent2 < fence.container)) fence = null;
31246
+ if (fence) {
31247
+ const close = indent2 - fence.container <= 3 ? FENCE_OPEN.exec(rest) : null;
31248
+ if (close && close[1][0] === fence.char && close[1].length >= fence.length && close[2].trim() === "") fence = null;
31249
+ blank(lineStart, lineEnd);
31250
+ } else if (isBlank) {
31251
+ closeSegment(lineStart);
31252
+ inParagraph = false;
31253
+ } else {
31254
+ if (!inParagraph) while (lists.length > 0 && lists[lists.length - 1] > indent2) lists.pop();
31255
+ let container = lists.length > 0 ? lists[lists.length - 1] : 0;
31256
+ let relative = indent2 - container;
31257
+ let text4 = rest;
31258
+ let textAt = lineStart + contentAt + chars;
31259
+ const marker = relative <= 3 && !THEMATIC_BREAK.test(text4) ? LIST_MARKER.exec(text4) : null;
31260
+ if (marker) {
31261
+ closeSegment(lineStart);
31262
+ const markerEnd = indent2 + marker[1].length;
31263
+ const spacing = leadingIndent(marker[2], 0, contentAt + markerEnd).columns;
31264
+ const wide = marker[2] === "" || spacing >= 5;
31265
+ lists.push(markerEnd + (wide ? 1 : spacing));
31266
+ container = lists[lists.length - 1];
31267
+ text4 = text4.slice(marker[1].length + (wide ? 0 : marker[2].length));
31268
+ textAt += marker[1].length + (wide ? 0 : marker[2].length);
31269
+ relative = wide ? Math.max(spacing - 1, 0) : 0;
31270
+ inParagraph = false;
31271
+ }
31272
+ const open = relative <= 3 ? FENCE_OPEN.exec(text4) : null;
31273
+ if (open && !(open[1][0] === "`" && open[2].includes("`"))) {
31274
+ closeSegment(lineStart);
31275
+ fence = { char: open[1][0], length: open[1].length, container, quotes };
31276
+ blank(textAt, lineEnd);
31277
+ inParagraph = false;
31278
+ } else if (!inParagraph && relative >= 4) {
31279
+ closeSegment(lineStart);
31280
+ blank(textAt, lineEnd);
31281
+ } else if (ATX_HEADING.test(text4) || THEMATIC_BREAK.test(text4)) {
31282
+ closeSegment(lineStart);
31283
+ maskCodeSpans(body, textAt, lineEnd, blank);
31284
+ inParagraph = false;
31285
+ } else {
31286
+ if (segmentStart < 0) segmentStart = textAt;
31287
+ inParagraph = text4.trim() !== "";
31288
+ }
31289
+ }
31290
+ if (newline < 0) break;
31291
+ lineStart = newline + 1;
31292
+ }
31293
+ closeSegment(body.length);
31294
+ return out.join("");
31295
+ }
31296
+ function maskCodeSpans(body, from, to, blank) {
31297
+ const runs = [];
31298
+ for (let index2 = from; index2 < to; ) {
31299
+ if (body[index2] !== "`") {
31300
+ index2++;
31301
+ continue;
31302
+ }
31303
+ let end = index2;
31304
+ while (end < to && body[end] === "`") end++;
31305
+ runs.push({ at: index2, length: end - index2 });
31306
+ index2 = end;
31307
+ }
31308
+ const byLength = /* @__PURE__ */ new Map();
31309
+ runs.forEach((run, position2) => {
31310
+ const list3 = byLength.get(run.length);
31311
+ if (list3) list3.push(position2);
31312
+ else byLength.set(run.length, [position2]);
31313
+ });
31314
+ const next = /* @__PURE__ */ new Map();
31315
+ const nextRun = (length, after) => {
31316
+ const list3 = byLength.get(length);
31317
+ if (!list3) return -1;
31318
+ let cursor = next.get(length) ?? 0;
31319
+ while (cursor < list3.length && list3[cursor] <= after) cursor++;
31320
+ next.set(length, cursor);
31321
+ return cursor < list3.length ? list3[cursor] : -1;
31322
+ };
31323
+ let escapeScan = from;
31324
+ let escaped = false;
31325
+ for (let position2 = 0; position2 < runs.length; position2++) {
31326
+ let { at, length } = runs[position2];
31327
+ for (; escapeScan < at; escapeScan++) escaped = body[escapeScan] === "\\" ? !escaped : false;
31328
+ if (escaped) {
31329
+ at += 1;
31330
+ length -= 1;
31331
+ escaped = false;
31332
+ if (length === 0) continue;
31333
+ const list3 = byLength.get(length);
31334
+ if (!list3) continue;
31335
+ }
31336
+ const closer = nextRun(length, position2);
31337
+ if (closer < 0) continue;
31338
+ const close = runs[closer];
31339
+ blank(at, close.at + close.length);
31340
+ position2 = closer;
31341
+ escapeScan = close.at + close.length;
31342
+ escaped = false;
31343
+ }
31344
+ }
31200
31345
  function resolveConceptId(fromId, href) {
31201
31346
  const target = (href.split("#")[0] ?? "").split("?")[0]?.trim() ?? "";
31202
31347
  if (target === "" || isExternalHref(target)) return null;
@@ -33028,6 +33173,23 @@ setDefaultBackendFactory((root) => new FilesystemBackend(root));
33028
33173
  // ../core/src/kinds.ts
33029
33174
  var CONVENTIONS_PREFIX = "conventions/";
33030
33175
  var CONVENTION_TYPE = "Convention";
33176
+ var KIND_FIELD_TYPES = [
33177
+ "date",
33178
+ "datetime",
33179
+ "https-url",
33180
+ "https-url-list",
33181
+ "integer",
33182
+ "number",
33183
+ "boolean",
33184
+ "slug",
33185
+ "string-list",
33186
+ "latitude",
33187
+ "longitude"
33188
+ ];
33189
+ var KIND_FIELD_TYPE_SET = new Set(KIND_FIELD_TYPES);
33190
+ function isKindFieldType(value) {
33191
+ return typeof value === "string" && KIND_FIELD_TYPE_SET.has(value);
33192
+ }
33031
33193
  function buildKindRegistry(docs, initialWarnings = [], options = {}) {
33032
33194
  const accepted = /* @__PURE__ */ new Map();
33033
33195
  const warnings = [...initialWarnings];
@@ -33179,7 +33341,8 @@ var VALID_FIELDS_KEYS = /* @__PURE__ */ new Set([
33179
33341
  "values",
33180
33342
  "value_descriptions",
33181
33343
  "terminal",
33182
- "descriptions"
33344
+ "descriptions",
33345
+ "types"
33183
33346
  ]);
33184
33347
  var MISPLACED_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set(["enum", "enums", "values", "constraints"]);
33185
33348
  var CLAIM_COORDINATE_KEYS = [
@@ -33219,7 +33382,7 @@ function parseConventionDoc(doc, options = {}) {
33219
33382
  if (!VALID_FIELDS_KEYS.has(key)) {
33220
33383
  warnings.push({
33221
33384
  code: "KIND_CONVENTION_UNKNOWN_FIELDS_KEY",
33222
- message: `kind convention '${doc.id}' declares an unrecognized key 'fields.${key}' (valid keys: fields.required, fields.optional, fields.values, fields.value_descriptions, fields.terminal, fields.descriptions); ignoring it.`,
33385
+ message: `kind convention '${doc.id}' declares an unrecognized key 'fields.${key}' (valid keys: fields.required, fields.optional, fields.values, fields.value_descriptions, fields.terminal, fields.descriptions, fields.types); ignoring it.`,
33223
33386
  field: `fields.${key}`,
33224
33387
  severity: "warning"
33225
33388
  });
@@ -33276,6 +33439,51 @@ function parseConventionDoc(doc, options = {}) {
33276
33439
  });
33277
33440
  }
33278
33441
  }
33442
+ const typesSource = fieldsRaw.types;
33443
+ const types = {};
33444
+ if (typesSource !== void 0) {
33445
+ if (!isPlainObject(typesSource)) {
33446
+ warnings.push({
33447
+ code: "KIND_CONVENTION_BAD_SHAPE",
33448
+ message: `kind convention '${doc.id}' has a non-map 'fields.types' (${describeShape(typesSource)}; expected a map of field name -> type); ignoring it.`,
33449
+ field: "fields.types",
33450
+ severity: "warning"
33451
+ });
33452
+ } else {
33453
+ for (const [field, declared] of Object.entries(typesSource)) {
33454
+ if (dropReserved(field, `fields.types.${field}`)) continue;
33455
+ if (!isKindFieldType(declared)) {
33456
+ warnings.push({
33457
+ code: "KIND_CONVENTION_UNKNOWN_FIELD_TYPE",
33458
+ message: `kind convention '${doc.id}' declares 'fields.types.${field}' as ${isScalar(declared) ? `'${String(declared)}'` : describeShape(declared)}, which is not a field type (valid types: ${KIND_FIELD_TYPES.join(", ")}); ignoring it.`,
33459
+ field: `fields.types.${field}`,
33460
+ severity: "warning"
33461
+ });
33462
+ continue;
33463
+ }
33464
+ if (!declaredFieldNames.has(field)) {
33465
+ warnings.push({
33466
+ code: "KIND_CONVENTION_UNDECLARED_TYPES_FIELD",
33467
+ message: `kind convention '${doc.id}' declares 'fields.types.${field}' but '${field}' is not in fields.required or fields.optional; ignoring it.`,
33468
+ field: `fields.types.${field}`,
33469
+ severity: "warning"
33470
+ });
33471
+ continue;
33472
+ }
33473
+ setOwn(types, field, declared);
33474
+ }
33475
+ }
33476
+ }
33477
+ for (const field of Object.keys(values)) {
33478
+ if (types[field] !== "https-url-list") continue;
33479
+ warnings.push({
33480
+ code: "KIND_CONVENTION_VALUES_TYPE_MISMATCH",
33481
+ message: `kind convention '${doc.id}' declares 'fields.values.${field}' on a field of type 'https-url-list', which cannot carry an enum; ignoring the values.`,
33482
+ field: `fields.values.${field}`,
33483
+ severity: "warning"
33484
+ });
33485
+ delete values[field];
33486
+ }
33279
33487
  const valueDescriptionsSource = fieldsRaw.value_descriptions;
33280
33488
  const valueDescriptions = {};
33281
33489
  if (valueDescriptionsSource !== void 0) {
@@ -33568,6 +33776,7 @@ function parseConventionDoc(doc, options = {}) {
33568
33776
  governs,
33569
33777
  fields: { required, optional, values, valueDescriptions, terminal, descriptions }
33570
33778
  };
33779
+ if (Object.keys(types).length > 0) kind2.fields.types = types;
33571
33780
  if (description !== void 0) kind2.description = description;
33572
33781
  if (path6 !== void 0) kind2.path = path6;
33573
33782
  if (links !== void 0) kind2.links = links;