@anchrd/intel-contract 0.11.0 → 0.12.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.
@@ -497,7 +497,22 @@ export type BoardAssignee = z.infer<typeof BoardAssignee>;
497
497
  * mints a key between theirs, so moving one task writes one task and renumbers nothing — the whole
498
498
  * reason a board is not addressed by position the way a table's rows are (`TableRowPosition`).
499
499
  * A hand-written key could collide, and two tasks sharing a key have no defined order at all.
500
+ *
501
+ * ⚠️ This CHARACTER CLASS is the truth about a stored key, not `fractional-indexing`, and the two
502
+ * are deliberately not the same set (anchrd/intel#359). A board that arrived through a bundle may
503
+ * spell `"0"`, `"a00"`, `"zzz"` or `"A"` — all of them legal here, none of them readable by that
504
+ * library. Narrowing the regex to what it reads would be a rule on the STORED document, so a board
505
+ * carrying one would stop parsing in all four places a board body is read (the board read, the
506
+ * indexer, the link reader, the bundle import) — unreadable, unsearchable and unmovable at once,
507
+ * over a value its owner never wrote. That is the trap #311, #318 and #321 each walked into from a
508
+ * different side.
509
+ *
510
+ * ⚠️ What every consumer may therefore rely on is exactly what stands here: keys are non-empty
511
+ * strings over `[0-9A-Za-z]` and are ORDERED BY STRING COMPARISON. Nothing may assume more — and
512
+ * `packages/api`'s `orderBetween` is the one place that asks `fractional-indexing` for a key and
513
+ * carries on without it when it refuses a bound.
500
514
  */
515
+ export declare const MaxBoardTaskOrderLength = 64;
501
516
  export declare const BoardTaskOrder: z.ZodString;
502
517
  export declare const BoardTaskId: z.ZodString;
503
518
  export declare const BoardTaskLabel: z.ZodString;
@@ -739,6 +754,24 @@ export declare const DeleteBoardTaskInput: z.ZodObject<{
739
754
  idempotencyKey: z.ZodString;
740
755
  }, z.core.$strict>;
741
756
  export type DeleteBoardTaskInput = z.infer<typeof DeleteBoardTaskInput>;
757
+ /**
758
+ * The way out of a board whose `tasks[]` names one id twice (anchrd/intel#341).
759
+ *
760
+ * ⚠️ It names no task, and that is not an oversight. Such a board holds a pair the caller cannot
761
+ * tell apart — every other operation here addresses a task BY id (#285), so the one thing nobody
762
+ * can say is "the second of the two". The board is what is named, and the server does the one thing
763
+ * that removes the ambiguity: the first entry under an id keeps it, every later one gets a freshly
764
+ * minted id and keeps everything else it carries.
765
+ *
766
+ * ⚠️ It exists because the pair is deliberately NOT folded away on read (`upgradeStoredBoard`,
767
+ * `repeatedBoardId`): two tasks under one id are two whole tasks, and a fold on the read is written
768
+ * back by the next save of any kind. So somebody has to ask for the repair, and this is the asking.
769
+ */
770
+ export declare const RepairBoardTaskIdsInput: z.ZodObject<{
771
+ nodeId: z.ZodString;
772
+ idempotencyKey: z.ZodString;
773
+ }, z.core.$strict>;
774
+ export type RepairBoardTaskIdsInput = z.infer<typeof RepairBoardTaskIdsInput>;
742
775
  export declare const BoardTaskResult: z.ZodObject<{
743
776
  node: z.ZodObject<{
744
777
  id: z.ZodString;
@@ -877,6 +910,78 @@ export declare const ConfigureBoardResult: z.ZodObject<{
877
910
  }, z.core.$strict>>;
878
911
  }, z.core.$strict>;
879
912
  export type ConfigureBoardResult = z.infer<typeof ConfigureBoardResult>;
913
+ /**
914
+ * What the repair did, task by task (anchrd/intel#341).
915
+ *
916
+ * ⚠️ `previousId` is the id the entry shared, and it still names a task on this board — the FIRST
917
+ * entry under it, the one that kept it. That is what makes the repair readable: nothing that
918
+ * pointed at that id moved, so a caller can see which of the two the board's `parentId` and
919
+ * `dependsOn` edges have been meaning all along, and move them with `board_task_move` and
920
+ * `board_task_update` if they meant the other one.
921
+ *
922
+ * ⚠️ At least one entry, because a board with nothing to repair is refused rather than answered
923
+ * with an empty list and a new version that changed nothing.
924
+ */
925
+ export declare const RepairBoardTaskIdsResult: z.ZodObject<{
926
+ node: z.ZodObject<{
927
+ id: z.ZodString;
928
+ parentId: z.ZodNullable<z.ZodString>;
929
+ kind: z.ZodEnum<{
930
+ folder: "folder";
931
+ document: "document";
932
+ attachment: "attachment";
933
+ table: "table";
934
+ agent: "agent";
935
+ board: "board";
936
+ }>;
937
+ title: z.ZodString;
938
+ description: z.ZodNullable<z.ZodString>;
939
+ ownerId: z.ZodString;
940
+ currentVersionId: z.ZodNullable<z.ZodString>;
941
+ createdAt: z.ZodISODateTime;
942
+ updatedAt: z.ZodISODateTime;
943
+ archivedAt: z.ZodNullable<z.ZodISODateTime>;
944
+ }, z.core.$strict>;
945
+ version: z.ZodObject<{
946
+ id: z.ZodString;
947
+ nodeId: z.ZodString;
948
+ sequence: z.ZodNumber;
949
+ contentKey: z.ZodString;
950
+ mediaType: z.ZodString;
951
+ contentHash: z.ZodString;
952
+ size: z.ZodNumber;
953
+ segment: z.ZodNullable<z.ZodEnum<{
954
+ append: "append";
955
+ snapshot: "snapshot";
956
+ }>>;
957
+ createdBy: z.ZodString;
958
+ createdAt: z.ZodISODateTime;
959
+ }, z.core.$strict>;
960
+ renumbered: z.ZodArray<z.ZodObject<{
961
+ previousId: z.ZodString;
962
+ task: z.ZodObject<{
963
+ id: z.ZodString;
964
+ title: z.ZodString;
965
+ status: z.ZodString;
966
+ assignee: z.ZodNullable<z.ZodDiscriminatedUnion<[z.ZodObject<{
967
+ type: z.ZodLiteral<"user">;
968
+ id: z.ZodString;
969
+ }, z.core.$strict>, z.ZodObject<{
970
+ type: z.ZodLiteral<"agent">;
971
+ nodeId: z.ZodString;
972
+ }, z.core.$strict>], "type">>;
973
+ labels: z.ZodArray<z.ZodString>;
974
+ startDate: z.ZodNullable<z.ZodISODate>;
975
+ dueDate: z.ZodNullable<z.ZodISODate>;
976
+ parentId: z.ZodNullable<z.ZodString>;
977
+ dependsOn: z.ZodArray<z.ZodString>;
978
+ order: z.ZodString;
979
+ description: z.ZodString;
980
+ references: z.ZodArray<z.ZodString>;
981
+ }, z.core.$strict>;
982
+ }, z.core.$strict>>;
983
+ }, z.core.$strict>;
984
+ export type RepairBoardTaskIdsResult = z.infer<typeof RepairBoardTaskIdsResult>;
880
985
  export declare const AgentMediaType = "application/vnd.anchrd.agent+json";
881
986
  export declare const AgentReferenceRole: z.ZodEnum<{
882
987
  "system-message": "system-message";
@@ -336,8 +336,28 @@ export const BoardAssignee = z.discriminatedUnion("type", [
336
336
  * mints a key between theirs, so moving one task writes one task and renumbers nothing — the whole
337
337
  * reason a board is not addressed by position the way a table's rows are (`TableRowPosition`).
338
338
  * A hand-written key could collide, and two tasks sharing a key have no defined order at all.
339
+ *
340
+ * ⚠️ This CHARACTER CLASS is the truth about a stored key, not `fractional-indexing`, and the two
341
+ * are deliberately not the same set (anchrd/intel#359). A board that arrived through a bundle may
342
+ * spell `"0"`, `"a00"`, `"zzz"` or `"A"` — all of them legal here, none of them readable by that
343
+ * library. Narrowing the regex to what it reads would be a rule on the STORED document, so a board
344
+ * carrying one would stop parsing in all four places a board body is read (the board read, the
345
+ * indexer, the link reader, the bundle import) — unreadable, unsearchable and unmovable at once,
346
+ * over a value its owner never wrote. That is the trap #311, #318 and #321 each walked into from a
347
+ * different side.
348
+ *
349
+ * ⚠️ What every consumer may therefore rely on is exactly what stands here: keys are non-empty
350
+ * strings over `[0-9A-Za-z]` and are ORDERED BY STRING COMPARISON. Nothing may assume more — and
351
+ * `packages/api`'s `orderBetween` is the one place that asks `fractional-indexing` for a key and
352
+ * carries on without it when it refuses a bound.
339
353
  */
340
- export const BoardTaskOrder = z.string().regex(/^[0-9A-Za-z]{1,64}$/);
354
+ // ⚠️ Named because a consumer has to be able to stay inside it. The repair of a repeated task id
355
+ // (anchrd/intel#341) mints a key beside an existing one, and a key one character too long would be
356
+ // written and then refused by the very next read — the whole board lost over a repair.
357
+ export const MaxBoardTaskOrderLength = 64;
358
+ export const BoardTaskOrder = z
359
+ .string()
360
+ .regex(new RegExp(`^[0-9A-Za-z]{1,${MaxBoardTaskOrderLength}}$`));
341
361
  export const BoardTaskId = IntelId;
342
362
  export const BoardTaskLabel = z.string().trim().min(1).max(60);
343
363
  // A day, not an instant. A task is due on a date; giving it a time zone would make the same task
@@ -549,6 +569,23 @@ export const DeleteBoardTaskInput = z.strictObject({
549
569
  taskId: BoardTaskId,
550
570
  idempotencyKey: z.string().min(8).max(200),
551
571
  });
572
+ /**
573
+ * The way out of a board whose `tasks[]` names one id twice (anchrd/intel#341).
574
+ *
575
+ * ⚠️ It names no task, and that is not an oversight. Such a board holds a pair the caller cannot
576
+ * tell apart — every other operation here addresses a task BY id (#285), so the one thing nobody
577
+ * can say is "the second of the two". The board is what is named, and the server does the one thing
578
+ * that removes the ambiguity: the first entry under an id keeps it, every later one gets a freshly
579
+ * minted id and keeps everything else it carries.
580
+ *
581
+ * ⚠️ It exists because the pair is deliberately NOT folded away on read (`upgradeStoredBoard`,
582
+ * `repeatedBoardId`): two tasks under one id are two whole tasks, and a fold on the read is written
583
+ * back by the next save of any kind. So somebody has to ask for the repair, and this is the asking.
584
+ */
585
+ export const RepairBoardTaskIdsInput = z.strictObject({
586
+ nodeId: IntelId,
587
+ idempotencyKey: z.string().min(8).max(200),
588
+ });
552
589
  // The one task that was written, not the whole board: a board can hold thousands of tasks, and
553
590
  // answering a one-card edit with all of them would make every write pay for the read.
554
591
  export const BoardTaskResult = z.strictObject({
@@ -568,6 +605,26 @@ export const ConfigureBoardResult = z.strictObject({
568
605
  version: NodeVersion,
569
606
  statuses: z.array(BoardStatus),
570
607
  });
608
+ /**
609
+ * What the repair did, task by task (anchrd/intel#341).
610
+ *
611
+ * ⚠️ `previousId` is the id the entry shared, and it still names a task on this board — the FIRST
612
+ * entry under it, the one that kept it. That is what makes the repair readable: nothing that
613
+ * pointed at that id moved, so a caller can see which of the two the board's `parentId` and
614
+ * `dependsOn` edges have been meaning all along, and move them with `board_task_move` and
615
+ * `board_task_update` if they meant the other one.
616
+ *
617
+ * ⚠️ At least one entry, because a board with nothing to repair is refused rather than answered
618
+ * with an empty list and a new version that changed nothing.
619
+ */
620
+ export const RepairBoardTaskIdsResult = z.strictObject({
621
+ node: Node,
622
+ version: NodeVersion,
623
+ renumbered: z
624
+ .array(z.strictObject({ previousId: BoardTaskId, task: BoardTask }))
625
+ .min(1)
626
+ .max(5_000),
627
+ });
571
628
  // ── The agent definition (#139, ADR-0005 §4) ─────────────────────────────────────────────────────
572
629
  //
573
630
  // An agent's body is a definition, stored as an immutable version in R2 exactly like a document's.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anchrd/intel-contract",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "type": "module",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {