@warmhub/sdk-ts 0.77.0 → 0.78.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -30,8 +30,13 @@ var SYNTHESIZED_CONTENT_NAMES = ["LlmsTxt"];
30
30
  var isContentShape = (s) => s === "Content";
31
31
  var isStoredContentName = (n) => STORED_CONTENT_NAMES.includes(n);
32
32
  var isSynthesizedContentName = (n) => SYNTHESIZED_CONTENT_NAMES.includes(n);
33
+ var BUILTIN_VIEW_SHAPE_NAMES = ["View"];
34
+ var isViewShape = (name) => BUILTIN_VIEW_SHAPE_NAMES.includes(name);
35
+ function isRenameableSquattedShape(name) {
36
+ return isReservedCollectionShape(name) || isViewShape(name);
37
+ }
33
38
  function isBuiltinShape(name) {
34
- return BUILTIN_SHAPE_NAMES.includes(name) || BUILTIN_CONTENT_SHAPE_NAMES.includes(name);
39
+ return BUILTIN_SHAPE_NAMES.includes(name) || BUILTIN_CONTENT_SHAPE_NAMES.includes(name) || BUILTIN_VIEW_SHAPE_NAMES.includes(name);
35
40
  }
36
41
 
37
42
  // ../rules/src/client-header.ts
@@ -302,466 +307,139 @@ function joinFieldPathWithEscaper(escapeSegment, segments) {
302
307
  ).join(".").replace(/\.\[/g, "[");
303
308
  }
304
309
 
305
- // ../rules/src/tokens.ts
306
- var COMMIT_TOKEN_SYNTAX_REMOVED_MESSAGE = "$N/#N commit-token syntax is no longer supported. Use explicit names and explicit wrefs. For assertions about newly created things, create the thing with a deterministic name and set about to that wref in the same commit.";
307
- var ANY_TOKEN_RE = /[$#]\d+/;
308
- function hasAnyTokens(s) {
309
- return ANY_TOKEN_RE.test(s);
310
- }
311
-
312
- // ../rules/src/preflight-commit.ts
313
- function preflightCommitDiagnostics(operations, options) {
314
- const errors = [];
315
- rejectCommitTokenSyntax(operations, errors);
316
- illegalOpSequences(operations, errors, options?.checkAddAdd ?? true);
317
- return errors;
318
- }
319
- function getOpName(op) {
320
- return op.name;
310
+ // ../rules/src/shape-types.ts
311
+ var BASE_PRIMITIVE_TYPES = [
312
+ "number",
313
+ "string",
314
+ "boolean",
315
+ "wref",
316
+ "array"
317
+ ];
318
+ var BASE_PRIMITIVE_TYPE_SET = new Set(BASE_PRIMITIVE_TYPES);
319
+ var VALID_PRIMITIVE_TYPES = /* @__PURE__ */ new Set([
320
+ "number",
321
+ "string",
322
+ "boolean",
323
+ "wref",
324
+ "array",
325
+ "number?",
326
+ "string?",
327
+ "boolean?",
328
+ "wref?",
329
+ "array?"
330
+ ]);
331
+ function isPlainObject(value) {
332
+ return typeof value === "object" && value !== null && !Array.isArray(value);
321
333
  }
322
- function tokenStringFields(op) {
323
- const fields = [getOpName(op), op.newName];
324
- if (typeof op.about === "string") {
325
- fields.push(op.about);
326
- }
327
- if (op.members) {
328
- fields.push(...op.members);
334
+ var STRING_CONSTRAINT_KEYS = /* @__PURE__ */ new Set([
335
+ "minLength",
336
+ "maxLength",
337
+ "pattern",
338
+ "enum"
339
+ ]);
340
+ var NUMBER_CONSTRAINT_KEYS = /* @__PURE__ */ new Set(["minimum", "maximum", "integer"]);
341
+ var WREF_CONSTRAINT_KEYS = /* @__PURE__ */ new Set(["shape"]);
342
+ var ARRAY_CONSTRAINT_KEYS = /* @__PURE__ */ new Set(["items", "minItems", "maxItems"]);
343
+ var COMMON_TYPESPEC_KEYS = /* @__PURE__ */ new Set(["type", "description"]);
344
+ var VALID_TYPESPEC_KEYS = /* @__PURE__ */ new Set([
345
+ ...COMMON_TYPESPEC_KEYS,
346
+ ...STRING_CONSTRAINT_KEYS,
347
+ ...NUMBER_CONSTRAINT_KEYS,
348
+ ...WREF_CONSTRAINT_KEYS,
349
+ ...ARRAY_CONSTRAINT_KEYS
350
+ ]);
351
+ var CONSTRAINT_KEYS_BY_TYPE = {
352
+ string: STRING_CONSTRAINT_KEYS,
353
+ number: NUMBER_CONSTRAINT_KEYS,
354
+ wref: WREF_CONSTRAINT_KEYS,
355
+ array: ARRAY_CONSTRAINT_KEYS,
356
+ boolean: /* @__PURE__ */ new Set()
357
+ // no constraints
358
+ };
359
+ function isTypeSpecObject(value) {
360
+ if (!isPlainObject(value) || !("type" in value)) return false;
361
+ if (typeof value.type !== "string" || !VALID_PRIMITIVE_TYPES.has(value.type))
362
+ return false;
363
+ const baseType = value.type.endsWith("?") ? value.type.slice(0, -1) : value.type;
364
+ const allowedConstraints = CONSTRAINT_KEYS_BY_TYPE[baseType] ?? /* @__PURE__ */ new Set();
365
+ if (!Object.keys(value).every(
366
+ (k) => COMMON_TYPESPEC_KEYS.has(k) || allowedConstraints.has(k)
367
+ ))
368
+ return false;
369
+ if ("minLength" in value && typeof value.minLength !== "number") return false;
370
+ if ("maxLength" in value && typeof value.maxLength !== "number") return false;
371
+ if ("pattern" in value && typeof value.pattern !== "string") return false;
372
+ if ("pattern" in value && typeof value.pattern === "string" && VALID_PRIMITIVE_TYPES.has(value.pattern)) {
373
+ const baseType2 = typeof value.type === "string" && value.type.endsWith("?") ? value.type.slice(0, -1) : value.type;
374
+ if (baseType2 !== "string") return false;
329
375
  }
330
- return fields;
331
- }
332
- function rejectCommitTokenSyntax(operations, errors) {
333
- for (let i = 0; i < operations.length; i++) {
334
- const op = operations[i];
335
- if (!op) continue;
336
- for (const field of tokenStringFields(op)) {
337
- if (field && hasAnyTokens(field)) {
338
- errors.push({
339
- code: "COMMIT_TOKEN_SYNTAX_REMOVED",
340
- operationIndex: i,
341
- message: COMMIT_TOKEN_SYNTAX_REMOVED_MESSAGE
342
- });
343
- break;
344
- }
345
- }
376
+ if ("enum" in value && !Array.isArray(value.enum)) return false;
377
+ if ("minimum" in value && typeof value.minimum !== "number") return false;
378
+ if ("maximum" in value && typeof value.maximum !== "number") return false;
379
+ if ("integer" in value && typeof value.integer !== "boolean") return false;
380
+ if ("shape" in value && typeof value.shape !== "string") return false;
381
+ if ("shape" in value && typeof value.shape === "string" && VALID_PRIMITIVE_TYPES.has(value.shape)) {
382
+ const baseType2 = typeof value.type === "string" && value.type.endsWith("?") ? value.type.slice(0, -1) : value.type;
383
+ if (baseType2 !== "wref") return false;
346
384
  }
385
+ if ("items" in value && typeof value.items === "number") return false;
386
+ if ("items" in value && typeof value.items === "boolean") return false;
387
+ if ("minItems" in value && typeof value.minItems !== "number") return false;
388
+ if ("maxItems" in value && typeof value.maxItems !== "number") return false;
389
+ return true;
347
390
  }
348
- function illegalOpSequences(operations, errors, checkAddAdd) {
349
- const opHistory = /* @__PURE__ */ new Map();
350
- for (let i = 0; i < operations.length; i++) {
351
- const op = operations[i];
352
- if (!op) continue;
353
- const name = getOpName(op);
354
- if (!name) continue;
355
- if (hasAnyTokens(name)) continue;
356
- const kind = inferOperationKind({ ...op, name });
357
- const qualName = kind === "shape" ? `shape:${name}` : `thing:${name}`;
358
- const history = opHistory.get(qualName) ?? [];
359
- history.push({ operation: op.operation, index: i });
360
- opHistory.set(qualName, history);
391
+ function primitiveTypeSpecFromFieldSpec(fieldType) {
392
+ if (typeof fieldType === "string" && VALID_PRIMITIVE_TYPES.has(fieldType)) {
393
+ return fieldType;
361
394
  }
362
- for (const [qualName, history] of opHistory) {
363
- if (history.length < 2) continue;
364
- for (let i = 1; i < history.length; i++) {
365
- const prev = history[i - 1];
366
- const curr = history[i];
367
- if (!prev || !curr) continue;
368
- const pair = `${prev.operation}+${curr.operation}`;
369
- if (checkAddAdd && pair === "add+add") {
370
- errors.push({
371
- code: "ILLEGAL_OP_SEQUENCE",
372
- operationIndex: curr.index,
373
- message: `Cannot add "${qualName}" twice in the same commit`
374
- });
375
- }
376
- if (pair === "revise+add") {
377
- errors.push({
378
- code: "ILLEGAL_OP_SEQUENCE",
379
- operationIndex: curr.index,
380
- message: `Cannot revise then add "${qualName}" in the same commit`
381
- });
382
- }
383
- }
395
+ if (isTypeSpecObject(fieldType)) {
396
+ return fieldType.type;
384
397
  }
398
+ return null;
399
+ }
400
+ function basePrimitiveTypeFromSpec(fieldType) {
401
+ const typeSpec = primitiveTypeSpecFromFieldSpec(fieldType);
402
+ if (!typeSpec) return null;
403
+ const base = typeSpec.endsWith("?") ? typeSpec.slice(0, -1) : typeSpec;
404
+ return BASE_PRIMITIVE_TYPE_SET.has(base) ? base : null;
385
405
  }
386
406
 
387
- // ../rules/src/preflight-operation.ts
388
- var collectionTypes = ["arc", "bond", "set", "list", "pair"];
389
- var canonicalCollectionTypes = ["arc", "bond", "set", "list"];
390
- var collectionOps = ["add", "revise"];
391
- var COLLECTION_CREATE_REQUIRES_NAME_MESSAGE = "Collection create requires a name. Collections are ordinary named things (ADR 0004).";
392
- var COLLECTION_ABOUT_REMOVED_MESSAGE = 'about accepts a wref. Create the collection as its own named operation, then point the assertion at it. Prefer deterministic relationship names, for example: [{"operation":"add","kind":"collection","type":"arc","name":"a-to-b","members":["A","B"]},{"operation":"add","kind":"assertion","about":"Arc/a-to-b","name":"Assertion/example","data":{}}]. For CLI usage, use wh commit submit --file with the two operations.';
393
- function preflightOpDiagnostics(op, operationIndex) {
394
- const errors = [];
395
- errors.push(...builtinShapeGuard(op, operationIndex));
396
- errors.push(...contentNameGuard(op, operationIndex));
397
- errors.push(...plusSignGuard(op, operationIndex));
398
- errors.push(...validateCollectionAbouts(op, operationIndex));
399
- errors.push(...validateCollectionOps(op, operationIndex));
400
- return errors;
401
- }
402
- function builtinShapeGuard(op, operationIndex) {
403
- const errors = [];
404
- const name = op.name;
405
- const isShapeRename = op.operation === "rename" && (op.kind === "shape" || op.name !== void 0 && !splitLocalPath(op.name));
406
- const reservedSourcePassThrough = isShapeRename && name !== void 0 && isReservedCollectionShape(name) && op.newName !== void 0 && !isReservedCollectionShape(op.newName) && !isBuiltinShape(op.newName);
407
- if (name && isRetiredCollectionShape(name) && !reservedSourcePassThrough) {
408
- errors.push({
409
- code: "RESERVED_NAME",
410
- operationIndex,
411
- message: `Shape "${name}" is a retired collection shape and cannot be written manually`
412
- });
413
- }
414
- if (op.operation === "rename" && (op.kind === "shape" || op.name !== void 0 && !splitLocalPath(op.name)) && op.newName && isRetiredCollectionShape(op.newName)) {
415
- errors.push({
416
- code: "RESERVED_NAME",
417
- operationIndex,
418
- message: `Shape "${op.newName}" is a retired collection shape and cannot be written manually`
419
- });
420
- } else {
421
- const builtinShapeName = name && isBuiltinShape(name) && !reservedSourcePassThrough ? name : isShapeRename && op.newName && isBuiltinShape(op.newName) ? op.newName : void 0;
422
- if (builtinShapeName && (isShapeRename || op.operation !== "retract" && op.kind === "shape")) {
423
- const action = op.operation === "add" ? "created" : op.operation === "rename" ? "renamed" : "revised";
424
- errors.push({
425
- code: "RESERVED_NAME",
426
- operationIndex,
427
- message: `Shape "${builtinShapeName}" is a built-in shape and cannot be ${action} manually`
428
- });
429
- }
430
- }
431
- if (name) {
432
- const local = splitLocalPath(name);
433
- if (local && isRetiredCollectionShape(local.shapePrefix)) {
434
- errors.push({
435
- code: "VALIDATION_ERROR",
436
- operationIndex,
437
- message: `Cannot ${op.operation} under retired collection shape "${local.shapePrefix}". Triple is read-only and retired for new collection writes.`
438
- });
439
- } else if (op.kind === "thing" && local && isBuiltinCollectionShape(local.shapePrefix)) {
440
- const message = op.operation === "add" ? `Cannot add kind="thing" under built-in shape "${local.shapePrefix}". Use kind="collection" instead.` : `Cannot revise kind="thing" under built-in shape "${local.shapePrefix}". Use kind="collection" to revise a collection.`;
441
- errors.push({
442
- code: "VALIDATION_ERROR",
443
- operationIndex,
444
- message
445
- });
446
- }
447
- }
448
- return errors;
449
- }
450
- function contentNameGuard(op, operationIndex) {
451
- if (op.kind !== "thing" || !op.name) return [];
452
- const local = splitLocalPath(op.name);
453
- if (!local || !isContentShape(local.shapePrefix)) return [];
454
- const bareName = local.bareName;
455
- if (isSynthesizedContentName(bareName)) {
456
- return [
457
- {
458
- code: "READ_ONLY_BUILTIN_CONTENT",
459
- operationIndex,
460
- message: `${local.shapePrefix}/${bareName} is synthesized; writes are not allowed`
461
- }
462
- ];
463
- }
464
- if (!isStoredContentName(bareName)) {
465
- return [
466
- {
467
- code: "UNKNOWN_CONTENT_NAME",
468
- operationIndex,
469
- message: `${local.shapePrefix}/${bareName} is not a recognized well-known content name`
470
- }
471
- ];
472
- }
473
- return [];
474
- }
475
- function plusSignGuard(op, operationIndex) {
476
- const errors = [];
477
- const name = op.name;
478
- if (op.newName?.includes("+")) {
479
- errors.push({
480
- code: "VALIDATION_ERROR",
481
- operationIndex,
482
- message: `Name "${op.newName}" contains reserved character "+". The "+" character is reserved for the historical collection auto-name namespace and is not allowed in user-supplied names.`
483
- });
484
- return errors;
485
- }
486
- if (name?.includes("+")) {
487
- if (op.kind === "collection" && op.operation === "add") {
488
- errors.push({
489
- code: "VALIDATION_ERROR",
490
- operationIndex,
491
- message: `Name "${name}" contains reserved character "+". The "+" character is reserved for the historical collection auto-name namespace and is not allowed in user-supplied names.`
492
- });
493
- return errors;
494
- }
495
- if (op.kind === "collection") return errors;
496
- const local = splitLocalPath(name);
497
- if (local && isReservedCollectionShape(local.shapePrefix)) return errors;
498
- errors.push({
499
- code: "VALIDATION_ERROR",
500
- operationIndex,
501
- message: `Name "${name}" contains reserved character "+". The "+" character is reserved for the historical collection auto-name namespace and is not allowed in user-supplied names.`
502
- });
503
- }
504
- return errors;
505
- }
506
- function validateCollectionAbouts(op, operationIndex) {
507
- const errors = [];
508
- if (!op.about || typeof op.about === "string") return errors;
509
- errors.push({
510
- code: "VALIDATION_ERROR",
511
- operationIndex,
512
- message: COLLECTION_ABOUT_REMOVED_MESSAGE
513
- });
514
- return errors;
515
- }
516
- function validateCollectionOps(op, operationIndex) {
517
- const errors = [];
518
- if (op.kind !== "collection") return errors;
519
- if (!collectionOps.includes(op.operation)) {
520
- return errors;
521
- }
522
- if (op.operation === "add" && !op.name) {
523
- errors.push({
524
- code: "VALIDATION_ERROR",
525
- operationIndex,
526
- message: COLLECTION_CREATE_REQUIRES_NAME_MESSAGE
527
- });
528
- }
529
- if (!op.type || !collectionTypes.includes(op.type)) {
530
- errors.push({
531
- code: "VALIDATION_ERROR",
532
- operationIndex,
533
- message: `Collection "type" is invalid. Use one of: ${canonicalCollectionTypes.join(", ")}. Got: "${op.type ?? ""}"`
534
- });
535
- }
536
- if (!op.members || !Array.isArray(op.members)) {
537
- errors.push({
538
- code: "VALIDATION_ERROR",
539
- operationIndex,
540
- message: 'Collection requires a "members" array'
541
- });
542
- } else {
543
- for (let i = 0; i < op.members.length; i++) {
544
- if (typeof op.members[i] !== "string") {
545
- errors.push({
546
- code: "VALIDATION_ERROR",
547
- operationIndex,
548
- message: `Collection member at index ${i} must be a string`
549
- });
550
- }
551
- }
552
- }
553
- if (op.type && op.members) {
554
- const arityError = collectionArityError(
555
- op.type,
556
- op.members
557
- );
558
- if (arityError) {
559
- errors.push({
560
- code: "VALIDATION_ERROR",
561
- operationIndex,
562
- message: arityError
563
- });
564
- }
565
- }
566
- return errors;
567
- }
568
- function collectionArityError(tag, members) {
569
- switch (tag) {
570
- case "arc":
571
- return members.length !== 2 ? `Arc requires exactly 2 members, got ${members.length}` : null;
572
- case "bond":
573
- return members.length !== 2 ? `Bond requires exactly 2 members, got ${members.length}` : null;
574
- case "pair":
575
- return members.length !== 2 ? `Pair requires exactly 2 members, got ${members.length}` : null;
576
- case "set":
577
- case "list":
578
- return members.length < 1 ? `${tag === "set" ? "Set" : "List"} requires at least 1 member, got 0` : null;
579
- }
580
- }
581
-
582
- // ../rules/src/preflight.ts
583
- function preflightOpDiagnostics2(op, operationIndex) {
584
- return preflightOpDiagnostics(op, operationIndex);
585
- }
586
- function preflightCommitDiagnostics2(operations, options) {
587
- return preflightCommitDiagnostics(operations, options);
588
- }
589
-
590
- // ../rules/src/reserved-orgs.ts
591
- var RESERVED_RAW_CONTENT_TOP_LEVEL_NAMES = [
592
- "_app",
593
- "_static",
594
- "api",
595
- "health",
596
- "healthz",
597
- "mcp",
598
- "readyz",
599
- "robots.txt",
600
- "sse",
601
- "trpc",
602
- "version"
603
- ];
604
- var RESERVED_ORG_NAMES = [
605
- ...RESERVED_RAW_CONTENT_TOP_LEVEL_NAMES,
606
- "admin",
607
- "billing",
608
- "blog",
609
- "docs",
610
- "help",
611
- "login",
612
- "public",
613
- "settings",
614
- "signup",
615
- "status",
616
- "support",
617
- "system",
618
- "warmhub",
619
- "www"
620
- ];
621
- new Set(RESERVED_ORG_NAMES);
622
-
623
- // ../rules/src/shape-field-key.ts
624
- function foldFieldName(name) {
625
- const stripped = name.endsWith("?") ? name.slice(0, -1) : name;
626
- return stripped.toLowerCase();
627
- }
628
- function foldFieldPath(path) {
629
- return path.split(".").map((segment) => foldFieldName(segment)).join(".");
630
- }
631
-
632
- // ../rules/src/shape-types.ts
633
- var BASE_PRIMITIVE_TYPES = [
634
- "number",
635
- "string",
636
- "boolean",
637
- "wref",
638
- "array"
639
- ];
640
- var BASE_PRIMITIVE_TYPE_SET = new Set(BASE_PRIMITIVE_TYPES);
641
- var VALID_PRIMITIVE_TYPES = /* @__PURE__ */ new Set([
642
- "number",
643
- "string",
644
- "boolean",
645
- "wref",
646
- "array",
647
- "number?",
648
- "string?",
649
- "boolean?",
650
- "wref?",
651
- "array?"
652
- ]);
653
- function isPlainObject(value) {
654
- return typeof value === "object" && value !== null && !Array.isArray(value);
655
- }
656
- var STRING_CONSTRAINT_KEYS = /* @__PURE__ */ new Set([
657
- "minLength",
658
- "maxLength",
659
- "pattern",
660
- "enum"
661
- ]);
662
- var NUMBER_CONSTRAINT_KEYS = /* @__PURE__ */ new Set(["minimum", "maximum", "integer"]);
663
- var WREF_CONSTRAINT_KEYS = /* @__PURE__ */ new Set(["shape"]);
664
- var ARRAY_CONSTRAINT_KEYS = /* @__PURE__ */ new Set(["items", "minItems", "maxItems"]);
665
- var COMMON_TYPESPEC_KEYS = /* @__PURE__ */ new Set(["type", "description"]);
666
- var VALID_TYPESPEC_KEYS = /* @__PURE__ */ new Set([
667
- ...COMMON_TYPESPEC_KEYS,
668
- ...STRING_CONSTRAINT_KEYS,
669
- ...NUMBER_CONSTRAINT_KEYS,
670
- ...WREF_CONSTRAINT_KEYS,
671
- ...ARRAY_CONSTRAINT_KEYS
672
- ]);
673
- var CONSTRAINT_KEYS_BY_TYPE = {
674
- string: STRING_CONSTRAINT_KEYS,
675
- number: NUMBER_CONSTRAINT_KEYS,
676
- wref: WREF_CONSTRAINT_KEYS,
677
- array: ARRAY_CONSTRAINT_KEYS,
678
- boolean: /* @__PURE__ */ new Set()
679
- // no constraints
680
- };
681
- function isTypeSpecObject(value) {
682
- if (!isPlainObject(value) || !("type" in value)) return false;
683
- if (typeof value.type !== "string" || !VALID_PRIMITIVE_TYPES.has(value.type))
684
- return false;
685
- const baseType = value.type.endsWith("?") ? value.type.slice(0, -1) : value.type;
686
- const allowedConstraints = CONSTRAINT_KEYS_BY_TYPE[baseType] ?? /* @__PURE__ */ new Set();
687
- if (!Object.keys(value).every(
688
- (k) => COMMON_TYPESPEC_KEYS.has(k) || allowedConstraints.has(k)
689
- ))
690
- return false;
691
- if ("minLength" in value && typeof value.minLength !== "number") return false;
692
- if ("maxLength" in value && typeof value.maxLength !== "number") return false;
693
- if ("pattern" in value && typeof value.pattern !== "string") return false;
694
- if ("pattern" in value && typeof value.pattern === "string" && VALID_PRIMITIVE_TYPES.has(value.pattern)) {
695
- const baseType2 = typeof value.type === "string" && value.type.endsWith("?") ? value.type.slice(0, -1) : value.type;
696
- if (baseType2 !== "string") return false;
697
- }
698
- if ("enum" in value && !Array.isArray(value.enum)) return false;
699
- if ("minimum" in value && typeof value.minimum !== "number") return false;
700
- if ("maximum" in value && typeof value.maximum !== "number") return false;
701
- if ("integer" in value && typeof value.integer !== "boolean") return false;
702
- if ("shape" in value && typeof value.shape !== "string") return false;
703
- if ("shape" in value && typeof value.shape === "string" && VALID_PRIMITIVE_TYPES.has(value.shape)) {
704
- const baseType2 = typeof value.type === "string" && value.type.endsWith("?") ? value.type.slice(0, -1) : value.type;
705
- if (baseType2 !== "wref") return false;
706
- }
707
- if ("items" in value && typeof value.items === "number") return false;
708
- if ("items" in value && typeof value.items === "boolean") return false;
709
- if ("minItems" in value && typeof value.minItems !== "number") return false;
710
- if ("maxItems" in value && typeof value.maxItems !== "number") return false;
711
- return true;
712
- }
713
- function primitiveTypeSpecFromFieldSpec(fieldType) {
714
- if (typeof fieldType === "string" && VALID_PRIMITIVE_TYPES.has(fieldType)) {
715
- return fieldType;
716
- }
717
- if (isTypeSpecObject(fieldType)) {
718
- return fieldType.type;
719
- }
720
- return null;
721
- }
722
- function basePrimitiveTypeFromSpec(fieldType) {
723
- const typeSpec = primitiveTypeSpecFromFieldSpec(fieldType);
724
- if (!typeSpec) return null;
725
- const base = typeSpec.endsWith("?") ? typeSpec.slice(0, -1) : typeSpec;
726
- return BASE_PRIMITIVE_TYPE_SET.has(base) ? base : null;
727
- }
728
-
729
- // ../../node_modules/.bun/re2js@2.8.3/node_modules/re2js/build/index.js
730
- var RE2Flags = class RE2Flags2 {
731
- static FOLD_CASE = 1;
732
- static LITERAL = 2;
733
- static CLASS_NL = 4;
734
- static DOT_NL = 8;
735
- static ONE_LINE = 16;
736
- static NON_GREEDY = 32;
737
- static PERL_X = 64;
738
- static UNICODE_GROUPS = 128;
739
- static WAS_DOLLAR = 256;
740
- static LOOKBEHIND = 512;
741
- static MATCH_NL = RE2Flags2.CLASS_NL | RE2Flags2.DOT_NL;
742
- static PERL = RE2Flags2.CLASS_NL | RE2Flags2.ONE_LINE | RE2Flags2.PERL_X | RE2Flags2.UNICODE_GROUPS;
743
- static POSIX = 0;
744
- static UNANCHORED = 0;
745
- static ANCHOR_START = 1;
746
- static ANCHOR_BOTH = 2;
747
- };
748
- var PublicFlags = {
749
- CASE_INSENSITIVE: 1,
750
- DOTALL: 2,
751
- MULTILINE: 4,
752
- DISABLE_UNICODE_GROUPS: 8,
753
- LONGEST_MATCH: 16,
754
- LOOKBEHINDS: 512
755
- };
756
- var ASCII_SIZE = 128;
757
- var ASCII_TO_UPPER = new Int32Array(ASCII_SIZE);
758
- var ASCII_TO_LOWER = new Int32Array(ASCII_SIZE);
759
- var MAX_BMP = 65535;
760
- for (let i = 0; i < ASCII_SIZE; i++) {
761
- if (i >= 97 && i <= 122) ASCII_TO_UPPER[i] = i - 32;
762
- else ASCII_TO_UPPER[i] = i;
763
- if (i >= 65 && i <= 90) ASCII_TO_LOWER[i] = i + 32;
764
- else ASCII_TO_LOWER[i] = i;
407
+ // ../../node_modules/.bun/re2js@2.8.3/node_modules/re2js/build/index.js
408
+ var RE2Flags = class RE2Flags2 {
409
+ static FOLD_CASE = 1;
410
+ static LITERAL = 2;
411
+ static CLASS_NL = 4;
412
+ static DOT_NL = 8;
413
+ static ONE_LINE = 16;
414
+ static NON_GREEDY = 32;
415
+ static PERL_X = 64;
416
+ static UNICODE_GROUPS = 128;
417
+ static WAS_DOLLAR = 256;
418
+ static LOOKBEHIND = 512;
419
+ static MATCH_NL = RE2Flags2.CLASS_NL | RE2Flags2.DOT_NL;
420
+ static PERL = RE2Flags2.CLASS_NL | RE2Flags2.ONE_LINE | RE2Flags2.PERL_X | RE2Flags2.UNICODE_GROUPS;
421
+ static POSIX = 0;
422
+ static UNANCHORED = 0;
423
+ static ANCHOR_START = 1;
424
+ static ANCHOR_BOTH = 2;
425
+ };
426
+ var PublicFlags = {
427
+ CASE_INSENSITIVE: 1,
428
+ DOTALL: 2,
429
+ MULTILINE: 4,
430
+ DISABLE_UNICODE_GROUPS: 8,
431
+ LONGEST_MATCH: 16,
432
+ LOOKBEHINDS: 512
433
+ };
434
+ var ASCII_SIZE = 128;
435
+ var ASCII_TO_UPPER = new Int32Array(ASCII_SIZE);
436
+ var ASCII_TO_LOWER = new Int32Array(ASCII_SIZE);
437
+ var MAX_BMP = 65535;
438
+ for (let i = 0; i < ASCII_SIZE; i++) {
439
+ if (i >= 97 && i <= 122) ASCII_TO_UPPER[i] = i - 32;
440
+ else ASCII_TO_UPPER[i] = i;
441
+ if (i >= 65 && i <= 90) ASCII_TO_LOWER[i] = i + 32;
442
+ else ASCII_TO_LOWER[i] = i;
765
443
  }
766
444
  var Codepoint = class {
767
445
  static CODES = /* @__PURE__ */ new Map([
@@ -6890,186 +6568,520 @@ var RE2JS = class RE2JS2 {
6890
6568
  last = m.end();
6891
6569
  continue;
6892
6570
  }
6893
- if (limit > 0 && result.length === limit - 1) break;
6894
- if (last === m.start()) {
6895
- if (limit === 0) {
6896
- emptiesSkipped += 1;
6897
- last = m.end();
6898
- continue;
6899
- }
6900
- } else while (emptiesSkipped > 0) {
6901
- result.push("");
6902
- emptiesSkipped -= 1;
6571
+ if (limit > 0 && result.length === limit - 1) break;
6572
+ if (last === m.start()) {
6573
+ if (limit === 0) {
6574
+ emptiesSkipped += 1;
6575
+ last = m.end();
6576
+ continue;
6577
+ }
6578
+ } else while (emptiesSkipped > 0) {
6579
+ result.push("");
6580
+ emptiesSkipped -= 1;
6581
+ }
6582
+ result.push(m.substring(last, m.start()));
6583
+ last = m.end();
6584
+ }
6585
+ if (limit === 0 && last !== m.inputLength()) {
6586
+ while (emptiesSkipped > 0) {
6587
+ result.push("");
6588
+ emptiesSkipped -= 1;
6589
+ }
6590
+ result.push(m.substring(last, m.inputLength()));
6591
+ }
6592
+ if (limit !== 0 || result.length === 0) result.push(m.substring(last, m.inputLength()));
6593
+ return result;
6594
+ }
6595
+ /**
6596
+ * Returns an iterator of all results matching a string against the regular expression,
6597
+ * including capturing groups.
6598
+ *
6599
+ * @param {string|number[]|Uint8Array} input the input string or byte array
6600
+ * @returns {IterableIterator<Array>}
6601
+ */
6602
+ *matchAll(input) {
6603
+ const m = this.matcher(input);
6604
+ while (m.find()) {
6605
+ const result = [m.group(0)];
6606
+ for (let i = 1; i <= m.groupCount(); i++) {
6607
+ const groupVal = m.group(i);
6608
+ result.push(groupVal === null ? void 0 : groupVal);
6609
+ }
6610
+ result.index = m.start(0);
6611
+ result.input = input;
6612
+ const namedGroups = this.namedGroups();
6613
+ if (Object.keys(namedGroups).length > 0) {
6614
+ const parsedGroups = m.getNamedGroups();
6615
+ for (const key in parsedGroups) if (parsedGroups[key] === null) parsedGroups[key] = void 0;
6616
+ result.groups = parsedGroups;
6617
+ } else result.groups = void 0;
6618
+ yield result;
6619
+ }
6620
+ }
6621
+ /**
6622
+ *
6623
+ * @returns {string}
6624
+ */
6625
+ toString() {
6626
+ return this.patternInput;
6627
+ }
6628
+ /**
6629
+ * Returns the program size of this pattern.
6630
+ *
6631
+ * <p>
6632
+ * Similar to the C++ implementation, the program size is a very approximate measure of a regexp's
6633
+ * "cost". Larger numbers are more expensive than smaller numbers.
6634
+ * </p>
6635
+ *
6636
+ * @returns {number} the program size of this pattern
6637
+ */
6638
+ programSize() {
6639
+ return this.re2Input.numberOfInstructions();
6640
+ }
6641
+ /**
6642
+ * Returns the number of capturing groups in this matcher's pattern. Group zero denotes the entire
6643
+ * pattern and is excluded from this count.
6644
+ *
6645
+ * @returns {number} the number of capturing groups in this pattern
6646
+ */
6647
+ groupCount() {
6648
+ return this.re2Input.numberOfCapturingGroups();
6649
+ }
6650
+ /**
6651
+ * Return a map of the capturing groups in this matcher's pattern, where key is the name and value
6652
+ * is the index of the group in the pattern.
6653
+ * @returns {Record<string, number>}
6654
+ */
6655
+ namedGroups() {
6656
+ return this.re2Input.namedGroups;
6657
+ }
6658
+ /**
6659
+ *
6660
+ * @param {*} other
6661
+ * @returns {boolean}
6662
+ */
6663
+ equals(other) {
6664
+ if (this === other) return true;
6665
+ if (other === null || this.constructor !== other.constructor) return false;
6666
+ return this.flagsInput === other.flagsInput && this.patternInput === other.patternInput;
6667
+ }
6668
+ };
6669
+
6670
+ // ../rules/src/shape-validation-types.ts
6671
+ var MAX_CONTENT_FIELD_BYTES = 64 * 1024;
6672
+ var MAX_INDEXABLE_SCALAR_FIELDS_PER_SHAPE = 256;
6673
+ var MAX_INDEXABLE_FIELD_PATH_BYTES = 256;
6674
+ var UNSUPPORTED_REGEX_SYNTAX_REASON = "uses unsupported regex syntax";
6675
+ var CONTENT_FIELD_LIMIT_ERROR = `WarmHub content fields are limited to ${MAX_CONTENT_FIELD_BYTES} bytes. WarmHub is not a document store; store large documents in S3, Box, Drive, or another document system and reference them from WarmHub instead.`;
6676
+ var textEncoder = new TextEncoder();
6677
+ function utf8ByteLength(value) {
6678
+ return textEncoder.encode(value).byteLength;
6679
+ }
6680
+ function contentFieldLimitError(path, value) {
6681
+ if (value.length * 3 <= MAX_CONTENT_FIELD_BYTES) return null;
6682
+ const byteLength = utf8ByteLength(value);
6683
+ if (byteLength <= MAX_CONTENT_FIELD_BYTES) return null;
6684
+ return `Field "${path}" is ${byteLength} bytes; ${CONTENT_FIELD_LIMIT_ERROR}`;
6685
+ }
6686
+ function assertContentFieldWithinLimit(path, value, errors) {
6687
+ const message = contentFieldLimitError(path, value);
6688
+ if (message) errors.push(message);
6689
+ }
6690
+ function nativeRegexSyntaxError(pattern) {
6691
+ try {
6692
+ new RegExp(pattern);
6693
+ return false;
6694
+ } catch {
6695
+ return true;
6696
+ }
6697
+ }
6698
+ function normalizePatternForPortableEngine(pattern) {
6699
+ let normalized = "";
6700
+ let inCharacterClass = false;
6701
+ for (let i = 0; i < pattern.length; i++) {
6702
+ const char = pattern[i];
6703
+ if (char === "\\") {
6704
+ const next = pattern[i + 1];
6705
+ if (inCharacterClass && next === "b") {
6706
+ normalized += "\\x08";
6707
+ i++;
6708
+ continue;
6709
+ }
6710
+ normalized += char;
6711
+ if (next !== void 0) {
6712
+ normalized += next;
6713
+ i++;
6903
6714
  }
6904
- result.push(m.substring(last, m.start()));
6905
- last = m.end();
6715
+ continue;
6906
6716
  }
6907
- if (limit === 0 && last !== m.inputLength()) {
6908
- while (emptiesSkipped > 0) {
6909
- result.push("");
6910
- emptiesSkipped -= 1;
6717
+ if (char === "[") {
6718
+ inCharacterClass = true;
6719
+ } else if (char === "]") {
6720
+ inCharacterClass = false;
6721
+ }
6722
+ normalized += char;
6723
+ }
6724
+ return normalized;
6725
+ }
6726
+ function compilePortablePattern(pattern) {
6727
+ try {
6728
+ return RE2JS.compile(normalizePatternForPortableEngine(pattern));
6729
+ } catch {
6730
+ return void 0;
6731
+ }
6732
+ }
6733
+ function unsupportedPortablePatternReason(pattern) {
6734
+ return compilePortablePattern(pattern) ? void 0 : UNSUPPORTED_REGEX_SYNTAX_REASON;
6735
+ }
6736
+ function normalizeOptionalTypeSpec(spec) {
6737
+ if (typeof spec === "string" && spec.endsWith("?")) {
6738
+ return { spec: spec.slice(0, -1), optionalByType: true };
6739
+ }
6740
+ if (isTypeSpecObject(spec) && typeof spec.type === "string" && spec.type.endsWith("?")) {
6741
+ return {
6742
+ spec: { ...spec, type: spec.type.slice(0, -1) },
6743
+ optionalByType: true
6744
+ };
6745
+ }
6746
+ return { spec, optionalByType: false };
6747
+ }
6748
+ function isFieldOptional(fieldKey, typeSpec) {
6749
+ const optionalByKey = fieldKey?.endsWith("?");
6750
+ return optionalByKey || normalizeOptionalTypeSpec(typeSpec).optionalByType;
6751
+ }
6752
+
6753
+ // ../rules/src/name-charset.ts
6754
+ var RESERVED_NAME_SEGMENT_CHARS = ["?", "#", "@", ":", "$"];
6755
+ function escapeForCharClass(char) {
6756
+ return char.replace(/[\\\]^-]/g, "\\$&");
6757
+ }
6758
+ RESERVED_NAME_SEGMENT_CHARS.map(escapeForCharClass).join("");
6759
+
6760
+ // ../rules/src/tokens.ts
6761
+ var COMMIT_TOKEN_SYNTAX_REMOVED_MESSAGE = "$N/#N commit-token syntax is no longer supported. Use explicit names and explicit wrefs. For assertions about newly created things, create the thing with a deterministic name and set about to that wref in the same commit.";
6762
+ var ANY_TOKEN_RE = /[$#]\d+/;
6763
+ function hasAnyTokens(s) {
6764
+ return ANY_TOKEN_RE.test(s);
6765
+ }
6766
+
6767
+ // ../rules/src/preflight-commit.ts
6768
+ function preflightCommitDiagnostics(operations, options) {
6769
+ const errors = [];
6770
+ rejectCommitTokenSyntax(operations, errors);
6771
+ illegalOpSequences(operations, errors, options?.checkAddAdd ?? true);
6772
+ return errors;
6773
+ }
6774
+ function getOpName(op) {
6775
+ return op.name;
6776
+ }
6777
+ function tokenStringFields(op) {
6778
+ const fields = [getOpName(op), op.newName];
6779
+ if (typeof op.about === "string") {
6780
+ fields.push(op.about);
6781
+ }
6782
+ if (op.members) {
6783
+ fields.push(...op.members);
6784
+ }
6785
+ return fields;
6786
+ }
6787
+ function rejectCommitTokenSyntax(operations, errors) {
6788
+ for (let i = 0; i < operations.length; i++) {
6789
+ const op = operations[i];
6790
+ if (!op) continue;
6791
+ for (const field of tokenStringFields(op)) {
6792
+ if (field && hasAnyTokens(field)) {
6793
+ errors.push({
6794
+ code: "COMMIT_TOKEN_SYNTAX_REMOVED",
6795
+ operationIndex: i,
6796
+ message: COMMIT_TOKEN_SYNTAX_REMOVED_MESSAGE
6797
+ });
6798
+ break;
6911
6799
  }
6912
- result.push(m.substring(last, m.inputLength()));
6913
6800
  }
6914
- if (limit !== 0 || result.length === 0) result.push(m.substring(last, m.inputLength()));
6915
- return result;
6916
6801
  }
6917
- /**
6918
- * Returns an iterator of all results matching a string against the regular expression,
6919
- * including capturing groups.
6920
- *
6921
- * @param {string|number[]|Uint8Array} input the input string or byte array
6922
- * @returns {IterableIterator<Array>}
6923
- */
6924
- *matchAll(input) {
6925
- const m = this.matcher(input);
6926
- while (m.find()) {
6927
- const result = [m.group(0)];
6928
- for (let i = 1; i <= m.groupCount(); i++) {
6929
- const groupVal = m.group(i);
6930
- result.push(groupVal === null ? void 0 : groupVal);
6802
+ }
6803
+ function illegalOpSequences(operations, errors, checkAddAdd) {
6804
+ const opHistory = /* @__PURE__ */ new Map();
6805
+ for (let i = 0; i < operations.length; i++) {
6806
+ const op = operations[i];
6807
+ if (!op) continue;
6808
+ const name = getOpName(op);
6809
+ if (!name) continue;
6810
+ if (hasAnyTokens(name)) continue;
6811
+ const kind = inferOperationKind({ ...op, name });
6812
+ const qualName = kind === "shape" ? `shape:${name}` : `thing:${name}`;
6813
+ const history = opHistory.get(qualName) ?? [];
6814
+ history.push({ operation: op.operation, index: i });
6815
+ opHistory.set(qualName, history);
6816
+ }
6817
+ for (const [qualName, history] of opHistory) {
6818
+ if (history.length < 2) continue;
6819
+ for (let i = 1; i < history.length; i++) {
6820
+ const prev = history[i - 1];
6821
+ const curr = history[i];
6822
+ if (!prev || !curr) continue;
6823
+ const pair = `${prev.operation}+${curr.operation}`;
6824
+ if (checkAddAdd && pair === "add+add") {
6825
+ errors.push({
6826
+ code: "ILLEGAL_OP_SEQUENCE",
6827
+ operationIndex: curr.index,
6828
+ message: `Cannot add "${qualName}" twice in the same commit`
6829
+ });
6830
+ }
6831
+ if (pair === "revise+add") {
6832
+ errors.push({
6833
+ code: "ILLEGAL_OP_SEQUENCE",
6834
+ operationIndex: curr.index,
6835
+ message: `Cannot revise then add "${qualName}" in the same commit`
6836
+ });
6931
6837
  }
6932
- result.index = m.start(0);
6933
- result.input = input;
6934
- const namedGroups = this.namedGroups();
6935
- if (Object.keys(namedGroups).length > 0) {
6936
- const parsedGroups = m.getNamedGroups();
6937
- for (const key in parsedGroups) if (parsedGroups[key] === null) parsedGroups[key] = void 0;
6938
- result.groups = parsedGroups;
6939
- } else result.groups = void 0;
6940
- yield result;
6941
6838
  }
6942
6839
  }
6943
- /**
6944
- *
6945
- * @returns {string}
6946
- */
6947
- toString() {
6948
- return this.patternInput;
6840
+ }
6841
+
6842
+ // ../rules/src/preflight-operation.ts
6843
+ var collectionTypes = ["arc", "bond", "set", "list", "pair"];
6844
+ var canonicalCollectionTypes = ["arc", "bond", "set", "list"];
6845
+ var collectionOps = ["add", "revise"];
6846
+ var COLLECTION_CREATE_REQUIRES_NAME_MESSAGE = "Collection create requires a name. Collections are ordinary named things (ADR 0004).";
6847
+ var COLLECTION_ABOUT_REMOVED_MESSAGE = 'about accepts a wref. Create the collection as its own named operation, then point the assertion at it. Prefer deterministic relationship names, for example: [{"operation":"add","kind":"collection","type":"arc","name":"a-to-b","members":["A","B"]},{"operation":"add","kind":"assertion","about":"Arc/a-to-b","name":"Assertion/example","data":{}}]. For CLI usage, use wh commit submit --file with the two operations.';
6848
+ function preflightOpDiagnostics(op, operationIndex) {
6849
+ const errors = [];
6850
+ errors.push(...builtinShapeGuard(op, operationIndex));
6851
+ errors.push(...contentNameGuard(op, operationIndex));
6852
+ errors.push(...plusSignGuard(op, operationIndex));
6853
+ errors.push(...validateCollectionAbouts(op, operationIndex));
6854
+ errors.push(...validateCollectionOps(op, operationIndex));
6855
+ return errors;
6856
+ }
6857
+ function builtinShapeGuard(op, operationIndex) {
6858
+ const errors = [];
6859
+ const name = op.name;
6860
+ const isShapeRename = op.operation === "rename" && (op.kind === "shape" || op.name !== void 0 && !splitLocalPath(op.name));
6861
+ const reservedSourcePassThrough = isShapeRename && name !== void 0 && isRenameableSquattedShape(name) && op.newName !== void 0 && !isReservedCollectionShape(op.newName) && !isBuiltinShape(op.newName);
6862
+ if (name && isRetiredCollectionShape(name) && !reservedSourcePassThrough) {
6863
+ errors.push({
6864
+ code: "RESERVED_NAME",
6865
+ operationIndex,
6866
+ message: `Shape "${name}" is a retired collection shape and cannot be written manually`
6867
+ });
6949
6868
  }
6950
- /**
6951
- * Returns the program size of this pattern.
6952
- *
6953
- * <p>
6954
- * Similar to the C++ implementation, the program size is a very approximate measure of a regexp's
6955
- * "cost". Larger numbers are more expensive than smaller numbers.
6956
- * </p>
6957
- *
6958
- * @returns {number} the program size of this pattern
6959
- */
6960
- programSize() {
6961
- return this.re2Input.numberOfInstructions();
6869
+ if (op.operation === "rename" && (op.kind === "shape" || op.name !== void 0 && !splitLocalPath(op.name)) && op.newName && isRetiredCollectionShape(op.newName)) {
6870
+ errors.push({
6871
+ code: "RESERVED_NAME",
6872
+ operationIndex,
6873
+ message: `Shape "${op.newName}" is a retired collection shape and cannot be written manually`
6874
+ });
6875
+ } else {
6876
+ const builtinShapeName = name && isBuiltinShape(name) && !reservedSourcePassThrough ? name : isShapeRename && op.newName && isBuiltinShape(op.newName) ? op.newName : void 0;
6877
+ if (builtinShapeName && (isShapeRename || op.operation !== "retract" && op.kind === "shape")) {
6878
+ const action = op.operation === "add" ? "created" : op.operation === "rename" ? "renamed" : "revised";
6879
+ errors.push({
6880
+ code: "RESERVED_NAME",
6881
+ operationIndex,
6882
+ message: `Shape "${builtinShapeName}" is a built-in shape and cannot be ${action} manually`
6883
+ });
6884
+ }
6885
+ }
6886
+ if (name) {
6887
+ const local = splitLocalPath(name);
6888
+ if (local && isRetiredCollectionShape(local.shapePrefix)) {
6889
+ errors.push({
6890
+ code: "VALIDATION_ERROR",
6891
+ operationIndex,
6892
+ message: `Cannot ${op.operation} under retired collection shape "${local.shapePrefix}". Triple is read-only and retired for new collection writes.`
6893
+ });
6894
+ } else if (op.kind === "thing" && local && isBuiltinCollectionShape(local.shapePrefix)) {
6895
+ const message = op.operation === "add" ? `Cannot add kind="thing" under built-in shape "${local.shapePrefix}". Use kind="collection" instead.` : `Cannot revise kind="thing" under built-in shape "${local.shapePrefix}". Use kind="collection" to revise a collection.`;
6896
+ errors.push({
6897
+ code: "VALIDATION_ERROR",
6898
+ operationIndex,
6899
+ message
6900
+ });
6901
+ }
6902
+ }
6903
+ return errors;
6904
+ }
6905
+ function contentNameGuard(op, operationIndex) {
6906
+ if (op.kind !== "thing" || !op.name) return [];
6907
+ const local = splitLocalPath(op.name);
6908
+ if (!local || !isContentShape(local.shapePrefix)) return [];
6909
+ const bareName = local.bareName;
6910
+ if (isSynthesizedContentName(bareName)) {
6911
+ return [
6912
+ {
6913
+ code: "READ_ONLY_BUILTIN_CONTENT",
6914
+ operationIndex,
6915
+ message: `${local.shapePrefix}/${bareName} is synthesized; writes are not allowed`
6916
+ }
6917
+ ];
6962
6918
  }
6963
- /**
6964
- * Returns the number of capturing groups in this matcher's pattern. Group zero denotes the entire
6965
- * pattern and is excluded from this count.
6966
- *
6967
- * @returns {number} the number of capturing groups in this pattern
6968
- */
6969
- groupCount() {
6970
- return this.re2Input.numberOfCapturingGroups();
6919
+ if (!isStoredContentName(bareName)) {
6920
+ return [
6921
+ {
6922
+ code: "UNKNOWN_CONTENT_NAME",
6923
+ operationIndex,
6924
+ message: `${local.shapePrefix}/${bareName} is not a recognized well-known content name`
6925
+ }
6926
+ ];
6971
6927
  }
6972
- /**
6973
- * Return a map of the capturing groups in this matcher's pattern, where key is the name and value
6974
- * is the index of the group in the pattern.
6975
- * @returns {Record<string, number>}
6976
- */
6977
- namedGroups() {
6978
- return this.re2Input.namedGroups;
6928
+ return [];
6929
+ }
6930
+ function plusSignGuard(op, operationIndex) {
6931
+ const errors = [];
6932
+ const name = op.name;
6933
+ if (op.newName?.includes("+")) {
6934
+ errors.push({
6935
+ code: "VALIDATION_ERROR",
6936
+ operationIndex,
6937
+ message: `Name "${op.newName}" contains reserved character "+". The "+" character is reserved for the historical collection auto-name namespace and is not allowed in user-supplied names.`
6938
+ });
6939
+ return errors;
6979
6940
  }
6980
- /**
6981
- *
6982
- * @param {*} other
6983
- * @returns {boolean}
6984
- */
6985
- equals(other) {
6986
- if (this === other) return true;
6987
- if (other === null || this.constructor !== other.constructor) return false;
6988
- return this.flagsInput === other.flagsInput && this.patternInput === other.patternInput;
6941
+ if (name?.includes("+")) {
6942
+ if (op.kind === "collection" && op.operation === "add") {
6943
+ errors.push({
6944
+ code: "VALIDATION_ERROR",
6945
+ operationIndex,
6946
+ message: `Name "${name}" contains reserved character "+". The "+" character is reserved for the historical collection auto-name namespace and is not allowed in user-supplied names.`
6947
+ });
6948
+ return errors;
6949
+ }
6950
+ if (op.kind === "collection") return errors;
6951
+ const local = splitLocalPath(name);
6952
+ if (local && isReservedCollectionShape(local.shapePrefix)) return errors;
6953
+ errors.push({
6954
+ code: "VALIDATION_ERROR",
6955
+ operationIndex,
6956
+ message: `Name "${name}" contains reserved character "+". The "+" character is reserved for the historical collection auto-name namespace and is not allowed in user-supplied names.`
6957
+ });
6989
6958
  }
6990
- };
6991
-
6992
- // ../rules/src/shape-validation-types.ts
6993
- var MAX_CONTENT_FIELD_BYTES = 64 * 1024;
6994
- var MAX_INDEXABLE_SCALAR_FIELDS_PER_SHAPE = 256;
6995
- var MAX_INDEXABLE_FIELD_PATH_BYTES = 256;
6996
- var UNSUPPORTED_REGEX_SYNTAX_REASON = "uses unsupported regex syntax";
6997
- var CONTENT_FIELD_LIMIT_ERROR = `WarmHub content fields are limited to ${MAX_CONTENT_FIELD_BYTES} bytes. WarmHub is not a document store; store large documents in S3, Box, Drive, or another document system and reference them from WarmHub instead.`;
6998
- var textEncoder = new TextEncoder();
6999
- function utf8ByteLength(value) {
7000
- return textEncoder.encode(value).byteLength;
7001
- }
7002
- function contentFieldLimitError(path, value) {
7003
- if (value.length * 3 <= MAX_CONTENT_FIELD_BYTES) return null;
7004
- const byteLength = utf8ByteLength(value);
7005
- if (byteLength <= MAX_CONTENT_FIELD_BYTES) return null;
7006
- return `Field "${path}" is ${byteLength} bytes; ${CONTENT_FIELD_LIMIT_ERROR}`;
6959
+ return errors;
7007
6960
  }
7008
- function assertContentFieldWithinLimit(path, value, errors) {
7009
- const message = contentFieldLimitError(path, value);
7010
- if (message) errors.push(message);
6961
+ function validateCollectionAbouts(op, operationIndex) {
6962
+ const errors = [];
6963
+ if (!op.about || typeof op.about === "string") return errors;
6964
+ errors.push({
6965
+ code: "VALIDATION_ERROR",
6966
+ operationIndex,
6967
+ message: COLLECTION_ABOUT_REMOVED_MESSAGE
6968
+ });
6969
+ return errors;
7011
6970
  }
7012
- function nativeRegexSyntaxError(pattern) {
7013
- try {
7014
- new RegExp(pattern);
7015
- return false;
7016
- } catch {
7017
- return true;
6971
+ function validateCollectionOps(op, operationIndex) {
6972
+ const errors = [];
6973
+ if (op.kind !== "collection") return errors;
6974
+ if (!collectionOps.includes(op.operation)) {
6975
+ return errors;
7018
6976
  }
7019
- }
7020
- function normalizePatternForPortableEngine(pattern) {
7021
- let normalized = "";
7022
- let inCharacterClass = false;
7023
- for (let i = 0; i < pattern.length; i++) {
7024
- const char = pattern[i];
7025
- if (char === "\\") {
7026
- const next = pattern[i + 1];
7027
- if (inCharacterClass && next === "b") {
7028
- normalized += "\\x08";
7029
- i++;
7030
- continue;
7031
- }
7032
- normalized += char;
7033
- if (next !== void 0) {
7034
- normalized += next;
7035
- i++;
6977
+ if (op.operation === "add" && !op.name) {
6978
+ errors.push({
6979
+ code: "VALIDATION_ERROR",
6980
+ operationIndex,
6981
+ message: COLLECTION_CREATE_REQUIRES_NAME_MESSAGE
6982
+ });
6983
+ }
6984
+ if (!op.type || !collectionTypes.includes(op.type)) {
6985
+ errors.push({
6986
+ code: "VALIDATION_ERROR",
6987
+ operationIndex,
6988
+ message: `Collection "type" is invalid. Use one of: ${canonicalCollectionTypes.join(", ")}. Got: "${op.type ?? ""}"`
6989
+ });
6990
+ }
6991
+ if (!op.members || !Array.isArray(op.members)) {
6992
+ errors.push({
6993
+ code: "VALIDATION_ERROR",
6994
+ operationIndex,
6995
+ message: 'Collection requires a "members" array'
6996
+ });
6997
+ } else {
6998
+ for (let i = 0; i < op.members.length; i++) {
6999
+ if (typeof op.members[i] !== "string") {
7000
+ errors.push({
7001
+ code: "VALIDATION_ERROR",
7002
+ operationIndex,
7003
+ message: `Collection member at index ${i} must be a string`
7004
+ });
7036
7005
  }
7037
- continue;
7038
7006
  }
7039
- if (char === "[") {
7040
- inCharacterClass = true;
7041
- } else if (char === "]") {
7042
- inCharacterClass = false;
7007
+ }
7008
+ if (op.type && op.members) {
7009
+ const arityError = collectionArityError(
7010
+ op.type,
7011
+ op.members
7012
+ );
7013
+ if (arityError) {
7014
+ errors.push({
7015
+ code: "VALIDATION_ERROR",
7016
+ operationIndex,
7017
+ message: arityError
7018
+ });
7043
7019
  }
7044
- normalized += char;
7045
7020
  }
7046
- return normalized;
7021
+ return errors;
7047
7022
  }
7048
- function compilePortablePattern(pattern) {
7049
- try {
7050
- return RE2JS.compile(normalizePatternForPortableEngine(pattern));
7051
- } catch {
7052
- return void 0;
7023
+ function collectionArityError(tag, members) {
7024
+ switch (tag) {
7025
+ case "arc":
7026
+ return members.length !== 2 ? `Arc requires exactly 2 members, got ${members.length}` : null;
7027
+ case "bond":
7028
+ return members.length !== 2 ? `Bond requires exactly 2 members, got ${members.length}` : null;
7029
+ case "pair":
7030
+ return members.length !== 2 ? `Pair requires exactly 2 members, got ${members.length}` : null;
7031
+ case "set":
7032
+ case "list":
7033
+ return members.length < 1 ? `${tag === "set" ? "Set" : "List"} requires at least 1 member, got 0` : null;
7053
7034
  }
7054
7035
  }
7055
- function unsupportedPortablePatternReason(pattern) {
7056
- return compilePortablePattern(pattern) ? void 0 : UNSUPPORTED_REGEX_SYNTAX_REASON;
7036
+
7037
+ // ../rules/src/preflight.ts
7038
+ function preflightOpDiagnostics2(op, operationIndex) {
7039
+ return preflightOpDiagnostics(op, operationIndex);
7057
7040
  }
7058
- function normalizeOptionalTypeSpec(spec) {
7059
- if (typeof spec === "string" && spec.endsWith("?")) {
7060
- return { spec: spec.slice(0, -1), optionalByType: true };
7061
- }
7062
- if (isTypeSpecObject(spec) && typeof spec.type === "string" && spec.type.endsWith("?")) {
7063
- return {
7064
- spec: { ...spec, type: spec.type.slice(0, -1) },
7065
- optionalByType: true
7066
- };
7067
- }
7068
- return { spec, optionalByType: false };
7041
+ function preflightCommitDiagnostics2(operations, options) {
7042
+ return preflightCommitDiagnostics(operations, options);
7069
7043
  }
7070
- function isFieldOptional(fieldKey, typeSpec) {
7071
- const optionalByKey = fieldKey?.endsWith("?");
7072
- return optionalByKey || normalizeOptionalTypeSpec(typeSpec).optionalByType;
7044
+
7045
+ // ../rules/src/reserved-orgs.ts
7046
+ var RESERVED_RAW_CONTENT_TOP_LEVEL_NAMES = [
7047
+ "_app",
7048
+ "_static",
7049
+ "api",
7050
+ "health",
7051
+ "healthz",
7052
+ "mcp",
7053
+ "readyz",
7054
+ "robots.txt",
7055
+ "sse",
7056
+ "trpc",
7057
+ "version"
7058
+ ];
7059
+ var RESERVED_ORG_NAMES = [
7060
+ ...RESERVED_RAW_CONTENT_TOP_LEVEL_NAMES,
7061
+ "admin",
7062
+ "billing",
7063
+ "blog",
7064
+ "docs",
7065
+ "help",
7066
+ "login",
7067
+ "public",
7068
+ "settings",
7069
+ "signup",
7070
+ "status",
7071
+ "support",
7072
+ "system",
7073
+ "warmhub",
7074
+ "www"
7075
+ ];
7076
+ new Set(RESERVED_ORG_NAMES);
7077
+
7078
+ // ../rules/src/shape-field-key.ts
7079
+ function foldFieldName(name) {
7080
+ const stripped = name.endsWith("?") ? name.slice(0, -1) : name;
7081
+ return stripped.toLowerCase();
7082
+ }
7083
+ function foldFieldPath(path) {
7084
+ return path.split(".").map((segment) => foldFieldName(segment)).join(".");
7073
7085
  }
7074
7086
 
7075
7087
  // ../rules/src/shape-validation-runtime.ts
@@ -7141,7 +7153,9 @@ function validatePersistedStringFieldLimits(value, typeDef, errors, path) {
7141
7153
  }
7142
7154
  if (Array.isArray(value)) {
7143
7155
  const elementType = arrayElementType(normalized);
7144
- if (elementType === void 0 && !isDeclaredArrayType(normalized)) return;
7156
+ if (normalized !== void 0 && elementType === void 0 && !isDeclaredArrayType(normalized)) {
7157
+ return;
7158
+ }
7145
7159
  for (let i = 0; i < value.length; i++) {
7146
7160
  validatePersistedStringFieldLimits(
7147
7161
  value[i],
@@ -7156,11 +7170,13 @@ function validatePersistedStringFieldLimits(value, typeDef, errors, path) {
7156
7170
  const fields = nestedObjectFields(normalized);
7157
7171
  if (normalized !== void 0 && fields === void 0) return;
7158
7172
  for (const [key, nestedValue] of Object.entries(value)) {
7173
+ const keyPath = path ? joinFieldPath(path, key) : escapeFieldNameForDisplay(key);
7174
+ assertContentFieldWithinLimit(keyPath, key, errors);
7159
7175
  validatePersistedStringFieldLimits(
7160
7176
  nestedValue,
7161
7177
  fields?.get(key),
7162
7178
  errors,
7163
- path ? joinFieldPath(path, key) : escapeFieldNameForDisplay(key)
7179
+ keyPath
7164
7180
  );
7165
7181
  }
7166
7182
  }
@@ -8536,7 +8552,7 @@ var SDK_DEVELOPMENT_VERSION = "0.0.0-development";
8536
8552
  function sdkVersionIsDevelopment(version) {
8537
8553
  return version === SDK_DEVELOPMENT_VERSION;
8538
8554
  }
8539
- var SDK_VERSION = "0.77.0" ;
8555
+ var SDK_VERSION = "0.78.0" ;
8540
8556
 
8541
8557
  // src/component-cli.ts
8542
8558
  var SUPPORTED_METHODS = /* @__PURE__ */ new Set([
@@ -11366,6 +11382,20 @@ var WarmHubClient = class _WarmHubClient {
11366
11382
  throw toWarmHubError(error);
11367
11383
  }
11368
11384
  },
11385
+ /**
11386
+ * Return the newest visible action run for each subscription in a repo.
11387
+ *
11388
+ * This grouped read is intended for subscription summaries that need
11389
+ * complete per-subscription recency without walking repo-wide history or
11390
+ * issuing one request per subscription.
11391
+ */
11392
+ latestRuns: async (orgName, repoName) => {
11393
+ try {
11394
+ return await this.trpc.action.latestRuns.query({ orgName, repoName });
11395
+ } catch (error) {
11396
+ throw toWarmHubError(error);
11397
+ }
11398
+ },
11369
11399
  /**
11370
11400
  * Aggregate run counts (total + per-status) for a repo or one subscription.
11371
11401
  *
@@ -12889,5 +12919,5 @@ re2js/build/index.js:
12889
12919
  */
12890
12920
 
12891
12921
  export { AllStreamOperationsFailedError, CLI_INSTALL_REPO_HEADER, CLI_SIGNATURE_HEADER, CLI_TIMESTAMP_HEADER, CONTENT_FIELD_LIMIT_ERROR, CliCallVerificationError, DEFAULT_API_URL, DEFAULT_STREAM_CHUNK_SIZE, MAX_CONTENT_FIELD_BYTES, MAX_STREAM_APPEND_OPERATION_COUNT2 as MAX_STREAM_APPEND_OPERATION_COUNT, OperationBuilder, PartialStreamSubmissionError, SDK_VERSION, WarmHubClient, WarmHubError, connectionErrorMessage, contentFieldLimitError, countStreamAppendResultStatuses, isConnectionError, isRetryable, isWarmHubError, normalizeWref, resolveFunctionLogMode, sanitizeErrorMessage, sdkVersionIsBelowMinimum, streamAppendResultStatus, submitOperationsViaStream, toWarmHubError, validateAgainstShape, verifyCliCall };
12892
- //# sourceMappingURL=chunk-ZX3MGOFM.js.map
12893
- //# sourceMappingURL=chunk-ZX3MGOFM.js.map
12922
+ //# sourceMappingURL=chunk-27SITT67.js.map
12923
+ //# sourceMappingURL=chunk-27SITT67.js.map