@sascha384/tic 5.16.0 → 5.17.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.
Files changed (106) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/dist/backends/ado/index.js +1 -1
  3. package/dist/backends/ado/index.js.map +1 -1
  4. package/dist/backends/ado/mappers.d.ts +2 -2
  5. package/dist/backends/ado/mappers.js +7 -2
  6. package/dist/backends/ado/mappers.js.map +1 -1
  7. package/dist/backends/files/index.d.ts +6 -0
  8. package/dist/backends/files/index.js +36 -0
  9. package/dist/backends/files/index.js.map +1 -1
  10. package/dist/backends/files/sync.d.ts +2 -2
  11. package/dist/backends/files/sync.js +9 -7
  12. package/dist/backends/files/sync.js.map +1 -1
  13. package/dist/backends/github/index.js +3 -3
  14. package/dist/backends/github/index.js.map +1 -1
  15. package/dist/backends/github/mappers.js +2 -1
  16. package/dist/backends/github/mappers.js.map +1 -1
  17. package/dist/backends/github/pr-mappers.d.ts +1 -1
  18. package/dist/backends/github/pr-mappers.js +1 -1
  19. package/dist/backends/github/pr-mappers.js.map +1 -1
  20. package/dist/backends/gitlab/index.js +13 -6
  21. package/dist/backends/gitlab/index.js.map +1 -1
  22. package/dist/backends/gitlab/mappers.js +2 -1
  23. package/dist/backends/gitlab/mappers.js.map +1 -1
  24. package/dist/backends/jira/index.js +2 -2
  25. package/dist/backends/jira/index.js.map +1 -1
  26. package/dist/backends/jira/mappers.d.ts +1 -1
  27. package/dist/backends/jira/mappers.js +5 -4
  28. package/dist/backends/jira/mappers.js.map +1 -1
  29. package/dist/backends/local/items.js +9 -2
  30. package/dist/backends/local/items.js.map +1 -1
  31. package/dist/backends/types.d.ts +2 -3
  32. package/dist/backends/types.js +8 -2
  33. package/dist/backends/types.js.map +1 -1
  34. package/dist/cli/commands/config.js +0 -1
  35. package/dist/cli/commands/config.js.map +1 -1
  36. package/dist/cli/commands/item.js +45 -17
  37. package/dist/cli/commands/item.js.map +1 -1
  38. package/dist/cli/commands/mcp.js +24 -9
  39. package/dist/cli/commands/mcp.js.map +1 -1
  40. package/dist/cli/commands/pr.js +12 -6
  41. package/dist/cli/commands/pr.js.map +1 -1
  42. package/dist/cli/index.js +13 -6
  43. package/dist/cli/index.js.map +1 -1
  44. package/dist/components/BranchList.js +4 -2
  45. package/dist/components/BranchList.js.map +1 -1
  46. package/dist/components/CommandBar.js +8 -7
  47. package/dist/components/CommandBar.js.map +1 -1
  48. package/dist/components/DetailPanel.js +2 -2
  49. package/dist/components/DetailPanel.js.map +1 -1
  50. package/dist/components/Settings.js +1 -1
  51. package/dist/components/Settings.js.map +1 -1
  52. package/dist/components/StatusScreen.js +2 -2
  53. package/dist/components/StatusScreen.js.map +1 -1
  54. package/dist/components/WorkItemForm.js +107 -73
  55. package/dist/components/WorkItemForm.js.map +1 -1
  56. package/dist/components/WorkItemList.d.ts +5 -3
  57. package/dist/components/WorkItemList.js +175 -124
  58. package/dist/components/WorkItemList.js.map +1 -1
  59. package/dist/components/buildTree.js +15 -13
  60. package/dist/components/buildTree.js.map +1 -1
  61. package/dist/components/fuzzyMatch.js +1 -1
  62. package/dist/components/fuzzyMatch.js.map +1 -1
  63. package/dist/components/getMarkedDistribution.d.ts +2 -2
  64. package/dist/components/getMarkedDistribution.js +1 -1
  65. package/dist/components/getMarkedDistribution.js.map +1 -1
  66. package/dist/git.d.ts +2 -1
  67. package/dist/hooks/useFormValidation.js +31 -21
  68. package/dist/hooks/useFormValidation.js.map +1 -1
  69. package/dist/implement.js +3 -3
  70. package/dist/implement.js.map +1 -1
  71. package/dist/index.js +3 -1
  72. package/dist/index.js.map +1 -1
  73. package/dist/storage/config.d.ts +0 -1
  74. package/dist/storage/config.js +0 -6
  75. package/dist/storage/config.js.map +1 -1
  76. package/dist/storage/index.d.ts +25 -6
  77. package/dist/storage/index.js +304 -183
  78. package/dist/storage/index.js.map +1 -1
  79. package/dist/storage/mappers.d.ts +1 -1
  80. package/dist/storage/mappers.js +5 -3
  81. package/dist/storage/mappers.js.map +1 -1
  82. package/dist/storage/schema.d.ts +83 -380
  83. package/dist/storage/schema.js +27 -55
  84. package/dist/storage/schema.js.map +1 -1
  85. package/dist/storage/syncQueue.d.ts +2 -3
  86. package/dist/storage/syncQueue.js +10 -17
  87. package/dist/storage/syncQueue.js.map +1 -1
  88. package/dist/storage/undo.js +7 -6
  89. package/dist/storage/undo.js.map +1 -1
  90. package/dist/stores/backendDataStore.js +3 -1
  91. package/dist/stores/backendDataStore.js.map +1 -1
  92. package/dist/stores/formStackStore.d.ts +1 -1
  93. package/dist/stores/listViewStore.d.ts +6 -6
  94. package/dist/stores/navigationStore.d.ts +7 -7
  95. package/dist/stores/undoStore.d.ts +2 -2
  96. package/dist/sync/SyncManager.d.ts +6 -1
  97. package/dist/sync/SyncManager.js +80 -76
  98. package/dist/sync/SyncManager.js.map +1 -1
  99. package/dist/sync/types.d.ts +6 -7
  100. package/dist/test-helpers.d.ts +1 -1
  101. package/dist/test-helpers.js +11 -8
  102. package/dist/test-helpers.js.map +1 -1
  103. package/dist/types.d.ts +6 -5
  104. package/drizzle/0006_dual_id.sql +173 -0
  105. package/drizzle/meta/_journal.json +7 -0
  106. package/package.json +1 -1
@@ -54,11 +54,21 @@ export function WorkItemForm() {
54
54
  popWorkItem: s.popWorkItem,
55
55
  })));
56
56
  const queue = useBackendDataStore((s) => s.queue);
57
- const queueWrite = async (action, itemId, extra) => {
57
+ /** Look up the rowId for a display ID. Returns -1 if not found. */
58
+ const rowIdOf = (displayId) => {
59
+ const item = allItems.find((i) => i.id === displayId);
60
+ return item?.rowId ?? -1;
61
+ };
62
+ /** Look up the display ID for a rowId. Returns null if not found. */
63
+ const displayIdOf = (rowId) => {
64
+ const item = allItems.find((i) => i.rowId === rowId);
65
+ return item?.id ?? null;
66
+ };
67
+ const queueWrite = async (action, itemRowId, extra) => {
58
68
  if (queue) {
59
69
  await queue.append({
60
70
  action,
61
- itemId,
71
+ itemRowId,
62
72
  timestamp: new Date().toISOString(),
63
73
  ...(extra?.commentData ? { commentData: extra.commentData } : {}),
64
74
  ...(extra?.templateSlug ? { templateSlug: extra.templateSlug } : {}),
@@ -97,16 +107,24 @@ export function WorkItemForm() {
97
107
  }
98
108
  let cancelled = false;
99
109
  setItemLoading(true);
110
+ const displayId = displayIdOf(selectedWorkItemId);
111
+ if (!displayId) {
112
+ setItemLoading(false);
113
+ return;
114
+ }
100
115
  void (async () => {
101
116
  try {
102
- const item = await backend.getWorkItem(selectedWorkItemId);
117
+ const item = await backend.getWorkItem(displayId);
103
118
  const [ch, dep] = capabilities.relationships
104
119
  ? await Promise.all([
105
- backend.getChildren(selectedWorkItemId),
106
- backend.getDependents(selectedWorkItemId),
120
+ backend.getChildren(displayId),
121
+ backend.getDependents(displayId),
107
122
  ])
108
123
  : [[], []];
109
- const pi = item.parent ? await backend.getWorkItem(item.parent) : null;
124
+ const parentDisplayId = item.parent !== null ? displayIdOf(item.parent) : null;
125
+ const pi = parentDisplayId
126
+ ? await backend.getWorkItem(parentDisplayId)
127
+ : null;
110
128
  if (cancelled)
111
129
  return;
112
130
  setExistingItem(item);
@@ -180,10 +198,10 @@ export function WorkItemForm() {
180
198
  all.push('rel-parent');
181
199
  }
182
200
  for (const child of children) {
183
- all.push(`rel-child-${child.id}`);
201
+ all.push(`rel-child-${child.rowId}`);
184
202
  }
185
203
  for (const dep of dependents) {
186
- all.push(`rel-dependent-${dep.id}`);
204
+ all.push(`rel-dependent-${dep.rowId}`);
187
205
  }
188
206
  }
189
207
  return all;
@@ -205,7 +223,9 @@ export function WorkItemForm() {
205
223
  return required;
206
224
  }, [selectedWorkItemId, capabilities.customTypes]);
207
225
  const requiredFieldsList = useMemo(() => capabilities.requiredFields ?? [...requiredFields], [capabilities.requiredFields, requiredFields]);
208
- const { errors: validationErrors, validate, clearError, } = useFormValidation(allItems, selectedWorkItemId, requiredFieldsList);
226
+ // Convert selectedWorkItemId (rowId) to display ID for validation
227
+ const selectedDisplayId = selectedWorkItemId !== null ? displayIdOf(selectedWorkItemId) : null;
228
+ const { errors: validationErrors, validate, clearError, } = useFormValidation(allItems, selectedDisplayId, requiredFieldsList);
209
229
  const [comments, setComments] = useState([]);
210
230
  // Derive field values from current draft
211
231
  const title = currentDraft?.fields.title ?? '';
@@ -252,10 +272,9 @@ export function WorkItemForm() {
252
272
  const { createChildParentId, setCreateChildParentId } = navigationStore.getState();
253
273
  let parentId = '';
254
274
  if (selectedWorkItemId === null && createChildParentId) {
255
- const parent = allItems.find((i) => i.id === createChildParentId);
256
- parentId = parent
257
- ? `#${createChildParentId} - ${parent.title}`
258
- : `#${createChildParentId}`;
275
+ const parent = allItems.find((i) => i.rowId === createChildParentId);
276
+ const displayId = parent?.id ?? String(createChildParentId);
277
+ parentId = parent ? `#${displayId} - ${parent.title}` : `#${displayId}`;
259
278
  setCreateChildParentId(null);
260
279
  }
261
280
  const initialFields = {
@@ -273,7 +292,9 @@ export function WorkItemForm() {
273
292
  };
274
293
  const draft = {
275
294
  itemId: selectedWorkItemId,
276
- itemTitle: selectedWorkItemId ? `#${selectedWorkItemId}` : '(new)',
295
+ itemTitle: selectedWorkItemId
296
+ ? `#${selectedDisplayId ?? selectedWorkItemId}`
297
+ : '(new)',
277
298
  fields: initialFields,
278
299
  initialSnapshot: { ...initialFields },
279
300
  focusedField: 0,
@@ -291,16 +312,20 @@ export function WorkItemForm() {
291
312
  // Build field values
292
313
  const parentIdValue = existingItem.parent !== null && existingItem.parent !== undefined
293
314
  ? (() => {
294
- const pi = allItems.find((i) => i.id === existingItem.parent);
315
+ const pi = allItems.find((i) => i.rowId === existingItem.parent);
316
+ const parentDisplayId = pi?.id ?? String(existingItem.parent);
295
317
  return pi
296
- ? `#${existingItem.parent} - ${pi.title}`
318
+ ? `#${parentDisplayId} - ${pi.title}`
297
319
  : String(existingItem.parent);
298
320
  })()
299
321
  : '';
300
322
  const dependsOnValue = existingItem.dependsOn
301
- ?.map((depId) => {
302
- const depItem = allItems.find((i) => i.id === depId);
303
- return depItem ? `#${depId} - ${depItem.title}` : depId;
323
+ ?.map((depRowId) => {
324
+ const depItem = allItems.find((i) => i.rowId === depRowId);
325
+ const depDisplayId = depItem?.id ?? String(depRowId);
326
+ return depItem
327
+ ? `#${depDisplayId} - ${depItem.title}`
328
+ : String(depRowId);
304
329
  })
305
330
  .join(', ') ?? '';
306
331
  const newFields = {
@@ -403,7 +428,7 @@ export function WorkItemForm() {
403
428
  }, [formMode, editingTemplateSlug, backend]);
404
429
  const parentSuggestions = useMemo(() => {
405
430
  return allItems
406
- .filter((item) => item.id !== selectedWorkItemId)
431
+ .filter((item) => item.rowId !== selectedWorkItemId && item.id !== null)
407
432
  .map((item) => `#${item.id} - ${item.title}`);
408
433
  }, [allItems, selectedWorkItemId]);
409
434
  const [editing, setEditing] = useState(false);
@@ -431,23 +456,26 @@ export function WorkItemForm() {
431
456
  .split(',')
432
457
  .map((l) => l.trim())
433
458
  .filter((l) => l.length > 0);
459
+ // Parse display IDs from form fields and resolve to rowIds
434
460
  const parsedParent = (() => {
435
461
  const trimmed = parentId.trim();
436
462
  if (!trimmed)
437
463
  return null;
438
464
  const match = trimmed.match(/^#(\S+)\s*-\s/);
439
- return match ? match[1] : trimmed;
465
+ const displayId = match ? match[1] : trimmed;
466
+ return rowIdOf(displayId);
440
467
  })();
441
468
  const parsedDependsOn = dependsOn
442
469
  .split(',')
443
470
  .map((s) => {
444
471
  const trimmed = s.trim();
445
472
  if (!trimmed)
446
- return '';
473
+ return -1;
447
474
  const match = trimmed.match(/^#(\S+)\s*-\s/);
448
- return match ? match[1] : trimmed;
475
+ const displayId = match ? match[1] : trimmed;
476
+ return rowIdOf(displayId);
449
477
  })
450
- .filter((s) => s.length > 0);
478
+ .filter((rowId) => rowId !== -1);
451
479
  if (formMode === 'template') {
452
480
  const template = {
453
481
  slug: editingTemplateSlug ?? slugifyTemplateName(title),
@@ -467,19 +495,23 @@ export function WorkItemForm() {
467
495
  template.iteration = iteration;
468
496
  if (description)
469
497
  template.description = description;
470
- if (parsedParent)
471
- template.parent = parsedParent;
472
- if (parsedDependsOn.length > 0)
473
- template.dependsOn = parsedDependsOn;
498
+ if (parsedParent !== null) {
499
+ template.parent = displayIdOf(parsedParent);
500
+ }
501
+ if (parsedDependsOn.length > 0) {
502
+ template.dependsOn = parsedDependsOn
503
+ .map((rid) => displayIdOf(rid))
504
+ .filter((id) => id !== null);
505
+ }
474
506
  if (editingTemplateSlug) {
475
507
  await backend.updateTemplate(editingTemplateSlug, template);
476
- await queueWrite('template-update', template.slug, {
508
+ await queueWrite('template-update', 0, {
477
509
  templateSlug: template.slug,
478
510
  });
479
511
  }
480
512
  else {
481
513
  await backend.createTemplate(template);
482
- await queueWrite('template-create', template.slug, {
514
+ await queueWrite('template-create', 0, {
483
515
  templateSlug: template.slug,
484
516
  });
485
517
  }
@@ -488,9 +520,9 @@ export function WorkItemForm() {
488
520
  setEditingTemplateSlug(null);
489
521
  return;
490
522
  }
491
- if (selectedWorkItemId !== null) {
492
- const snapshot = await backend.getWorkItem(selectedWorkItemId);
493
- await backend.cachedUpdateWorkItem(selectedWorkItemId, {
523
+ if (selectedWorkItemId !== null && selectedDisplayId) {
524
+ const snapshot = await backend.getWorkItem(selectedDisplayId);
525
+ await backend.cachedUpdateWorkItem(selectedDisplayId, {
494
526
  title,
495
527
  type,
496
528
  status,
@@ -505,13 +537,13 @@ export function WorkItemForm() {
505
537
  await queueWrite('update', selectedWorkItemId);
506
538
  undoStore.getState().pushUndo({
507
539
  type: 'update',
508
- label: `edited #${selectedWorkItemId}`,
540
+ label: `edited #${selectedDisplayId}`,
509
541
  itemSnapshots: [snapshot],
510
- syncItemIds: [selectedWorkItemId],
542
+ syncItemRowIds: [selectedWorkItemId],
511
543
  syncAction: 'update',
512
544
  });
513
545
  if (capabilities.comments && newComment.trim().length > 0) {
514
- const added = await backend.addComment(selectedWorkItemId, {
546
+ const added = await backend.addComment(selectedDisplayId, {
515
547
  author: 'me',
516
548
  body: newComment.trim(),
517
549
  });
@@ -521,10 +553,10 @@ export function WorkItemForm() {
521
553
  setComments((prev) => [...prev, added]);
522
554
  setNewComment('');
523
555
  }
524
- await backendDataStore.getState().reloadItem(selectedWorkItemId);
556
+ await backendDataStore.getState().reloadItem(selectedDisplayId);
525
557
  uiStore
526
558
  .getState()
527
- .setToast(`Item #${selectedWorkItemId} updated — press u to undo`);
559
+ .setToast(`Item #${selectedDisplayId} updated — press u to undo`);
528
560
  }
529
561
  else {
530
562
  const created = await backend.cachedCreateWorkItem({
@@ -539,28 +571,30 @@ export function WorkItemForm() {
539
571
  parent: parsedParent,
540
572
  dependsOn: parsedDependsOn,
541
573
  });
542
- await queueWrite('create', created.id);
574
+ await queueWrite('create', created.rowId);
543
575
  undoStore.getState().pushUndo({
544
576
  type: 'create',
545
- label: `created #${created.id}`,
577
+ label: `created #${created.id ?? created.rowId}`,
546
578
  itemSnapshots: [],
547
- syncItemIds: [created.id],
579
+ syncItemRowIds: [created.rowId],
548
580
  syncAction: 'create',
549
- createdIds: [created.id],
581
+ createdRowIds: [created.rowId],
550
582
  });
551
- if (capabilities.comments && newComment.trim().length > 0) {
583
+ if (capabilities.comments && newComment.trim().length > 0 && created.id) {
552
584
  await backend.addComment(created.id, {
553
585
  author: 'me',
554
586
  body: newComment.trim(),
555
587
  });
556
- await queueWrite('comment', created.id, {
588
+ await queueWrite('comment', created.rowId, {
557
589
  commentData: { author: 'me', body: newComment.trim() },
558
590
  });
559
591
  }
560
- await backendDataStore.getState().reloadItem(created.id);
592
+ if (created.id) {
593
+ await backendDataStore.getState().reloadItem(created.id);
594
+ }
561
595
  uiStore
562
596
  .getState()
563
- .setToast(`Item #${created.id} created — press u to undo`);
597
+ .setToast(`Item #${created.id ?? created.rowId} created — press u to undo`);
564
598
  setActiveTemplate(null);
565
599
  }
566
600
  // Update the initialSnapshot after saving so isDirty becomes false
@@ -592,7 +626,7 @@ export function WorkItemForm() {
592
626
  await save();
593
627
  if (pendingRelNav) {
594
628
  // Push a new draft for the target item
595
- const targetItem = allItems.find((i) => i.id === pendingRelNav);
629
+ const targetItem = allItems.find((i) => i.rowId === pendingRelNav);
596
630
  const defaultFields = {
597
631
  title: '',
598
632
  type: activeType ?? types[0] ?? '',
@@ -608,7 +642,7 @@ export function WorkItemForm() {
608
642
  };
609
643
  const newDraft = {
610
644
  itemId: pendingRelNav,
611
- itemTitle: targetItem?.title ?? `#${pendingRelNav}`,
645
+ itemTitle: targetItem?.title ?? `#${targetItem?.id ?? pendingRelNav}`,
612
646
  fields: defaultFields,
613
647
  initialSnapshot: { ...defaultFields },
614
648
  focusedField: 0,
@@ -642,7 +676,7 @@ export function WorkItemForm() {
642
676
  if (pendingRelNav) {
643
677
  // Push a new draft for the target item (discarding current)
644
678
  formStackStore.getState().pop();
645
- const targetItem = allItems.find((i) => i.id === pendingRelNav);
679
+ const targetItem = allItems.find((i) => i.rowId === pendingRelNav);
646
680
  const defaultFields = {
647
681
  title: '',
648
682
  type: activeType ?? types[0] ?? '',
@@ -658,7 +692,7 @@ export function WorkItemForm() {
658
692
  };
659
693
  const newDraft = {
660
694
  itemId: pendingRelNav,
661
- itemTitle: targetItem?.title ?? `#${pendingRelNav}`,
695
+ itemTitle: targetItem?.title ?? `#${targetItem?.id ?? pendingRelNav}`,
662
696
  fields: defaultFields,
663
697
  initialSnapshot: { ...defaultFields },
664
698
  focusedField: 0,
@@ -790,24 +824,24 @@ export function WorkItemForm() {
790
824
  }
791
825
  if (matchesCommand('form-edit', _input, key)) {
792
826
  if (isRelationshipField) {
793
- let targetId = null;
827
+ let targetRowId = null;
794
828
  if (currentField === 'rel-parent' && existingItem?.parent) {
795
- targetId = existingItem.parent;
829
+ targetRowId = existingItem.parent;
796
830
  }
797
831
  else if (currentField.startsWith('rel-child-')) {
798
- targetId = currentField.slice('rel-child-'.length);
832
+ targetRowId = Number(currentField.slice('rel-child-'.length));
799
833
  }
800
834
  else if (currentField.startsWith('rel-dependent-')) {
801
- targetId = currentField.slice('rel-dependent-'.length);
835
+ targetRowId = Number(currentField.slice('rel-dependent-'.length));
802
836
  }
803
- if (targetId) {
837
+ if (targetRowId) {
804
838
  if (isDirty) {
805
- setPendingRelNav(targetId);
839
+ setPendingRelNav(targetRowId);
806
840
  setShowDirtyPrompt(true);
807
841
  }
808
842
  else {
809
843
  // Create new draft for target item before navigating
810
- const targetItem = allItems.find((i) => i.id === targetId);
844
+ const targetItem = allItems.find((i) => i.rowId === targetRowId);
811
845
  const defaultFields = {
812
846
  title: '',
813
847
  type: activeType ?? types[0] ?? '',
@@ -822,14 +856,14 @@ export function WorkItemForm() {
822
856
  newComment: '',
823
857
  };
824
858
  const newDraft = {
825
- itemId: targetId,
826
- itemTitle: targetItem?.title ?? `#${targetId}`,
859
+ itemId: targetRowId,
860
+ itemTitle: targetItem?.title ?? `#${targetItem?.id ?? targetRowId}`,
827
861
  fields: defaultFields,
828
862
  initialSnapshot: { ...defaultFields },
829
863
  focusedField: 0,
830
864
  };
831
865
  pushDraft(newDraft);
832
- pushWorkItem(targetId);
866
+ pushWorkItem(targetRowId);
833
867
  }
834
868
  }
835
869
  }
@@ -1089,24 +1123,24 @@ export function WorkItemForm() {
1089
1123
  function renderRelationshipField(field, index) {
1090
1124
  const focused = index === focusedField;
1091
1125
  const cursor = focused ? '>' : ' ';
1092
- const id = field.startsWith('rel-child-')
1093
- ? field.slice('rel-child-'.length)
1126
+ const rowId = field.startsWith('rel-child-')
1127
+ ? Number(field.slice('rel-child-'.length))
1094
1128
  : field.startsWith('rel-dependent-')
1095
- ? field.slice('rel-dependent-'.length)
1129
+ ? Number(field.slice('rel-dependent-'.length))
1096
1130
  : null;
1097
- let item = null;
1131
+ let relItem = null;
1098
1132
  if (field === 'rel-parent' && parentItem) {
1099
- item = { id: parentItem.id, title: parentItem.title };
1133
+ relItem = parentItem;
1100
1134
  }
1101
- else if (id) {
1102
- const child = children.find((c) => c.id === id);
1103
- const dep = dependents.find((d) => d.id === id);
1104
- const relItem = child ?? dep;
1105
- item = relItem ? { id: relItem.id, title: relItem.title } : null;
1135
+ else if (rowId !== null) {
1136
+ relItem =
1137
+ children.find((c) => c.rowId === rowId) ??
1138
+ dependents.find((d) => d.rowId === rowId) ??
1139
+ null;
1106
1140
  }
1107
- if (!item)
1141
+ if (!relItem)
1108
1142
  return null;
1109
- return (_jsxs(Box, { children: [_jsxs(Text, { color: focused ? accent : undefined, children: [cursor, " "] }), _jsxs(Text, { bold: focused, color: focused ? accent : undefined, children: ["#", item.id, " (", item.title, ")"] })] }, field));
1143
+ return (_jsxs(Box, { children: [_jsxs(Text, { color: focused ? accent : undefined, children: [cursor, " "] }), _jsxs(Text, { bold: focused, color: focused ? accent : undefined, children: ["#", relItem.id ?? relItem.rowId, " (", relItem.title, ")"] })] }, field));
1110
1144
  }
1111
1145
  const formStackLength = useFormStackStore((s) => s.stack.length);
1112
1146
  const chromeLines = useMemo(() => {
@@ -1151,7 +1185,7 @@ export function WorkItemForm() {
1151
1185
  const typeLabel = formMode === 'template' ? '' : type.charAt(0).toUpperCase() + type.slice(1);
1152
1186
  const isFieldVisible = (index) => index >= viewport.start && index < viewport.end;
1153
1187
  return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { bold: true, color: accent, children: [mode, typeLabel ? ` ${typeLabel}` : '', formMode !== 'template' && selectedWorkItemId !== null
1154
- ? ` #${selectedWorkItemId}`
1188
+ ? ` #${selectedDisplayId ?? selectedWorkItemId}`
1155
1189
  : ''] }) }), _jsx(Breadcrumbs, {}), fields.map((field, index) => {
1156
1190
  if (field === 'rel-parent' ||
1157
1191
  field.startsWith('rel-child-') ||