@tutti-os/workspace-issue-manager 0.0.12 → 0.0.13

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.
@@ -16,6 +16,7 @@ import {
16
16
  defaultTaskPriority,
17
17
  formatIssueManagerDate,
18
18
  formatIssueManagerTimestamp,
19
+ logIssueManagerDiagnostic,
19
20
  persistIssueManagerIssueDraftContent,
20
21
  persistIssueManagerTaskDraftContent,
21
22
  resolveIssueManagerErrorMessage,
@@ -23,7 +24,7 @@ import {
23
24
  resolveIssueManagerTopicDeleteErrorMessage,
24
25
  toContextRefInput,
25
26
  toIssueManagerWorkspaceFileLinkInput
26
- } from "./chunk-4A2ECWB6.js";
27
+ } from "./chunk-MLBXKQLG.js";
27
28
  import {
28
29
  appendIssueManagerWorkspaceFileLinksToContent,
29
30
  clampIssueManagerSidebarWidth,
@@ -34,7 +35,7 @@ import {
34
35
  issueManagerSidebarMinWidth,
35
36
  normalizeIssueManagerContent,
36
37
  shouldAutoCollapseIssueManagerSidebar
37
- } from "./chunk-YGTTLXTS.js";
38
+ } from "./chunk-5A25XEF2.js";
38
39
 
39
40
  // src/ui/react/internal/shell/IssueManagerNodeState.ts
40
41
  import { useEffect, useEffectEvent, useState } from "react";
@@ -1434,6 +1435,7 @@ function createIssueManagerControllerActionsBridge(input) {
1434
1435
  const {
1435
1436
  controllerSession,
1436
1437
  copy,
1438
+ diagnostics,
1437
1439
  feature,
1438
1440
  issueDetail,
1439
1441
  issueDraft,
@@ -1460,10 +1462,37 @@ function createIssueManagerControllerActionsBridge(input) {
1460
1462
  ),
1461
1463
  setIsRunningTask: (update) => controllerSession.setIsRunningTask(update),
1462
1464
  setIssueDraftInternal: (update) => controllerSession.setIssueDraftInternal(update),
1463
- setIssueEditorModeState: (update) => controllerSession.setIssueEditorModeState(update),
1465
+ setIssueEditorModeState: (update) => {
1466
+ const nextMode = typeof update === "function" ? update(issueEditorMode) : update;
1467
+ logIssueManagerDiagnostic(
1468
+ diagnostics,
1469
+ "issue_editor_mode.action_requested",
1470
+ {
1471
+ nextIssueEditorMode: nextMode,
1472
+ previousIssueEditorMode: issueEditorMode,
1473
+ selectedIssueId: nodeState.selectedIssueId,
1474
+ selectedTaskId: nodeState.selectedTaskId
1475
+ },
1476
+ { includeStack: true }
1477
+ );
1478
+ controllerSession.setIssueEditorModeState(nextMode);
1479
+ },
1464
1480
  setReferenceTarget: (update) => controllerSession.setReferenceTarget(update),
1465
1481
  setTaskDraftInternal: (update) => controllerSession.setTaskDraftInternal(update),
1466
- setTaskEditorModeState: (update) => controllerSession.setTaskEditorModeState(update),
1482
+ setTaskEditorModeState: (update) => {
1483
+ const nextMode = typeof update === "function" ? update(taskEditorMode) : update;
1484
+ logIssueManagerDiagnostic(
1485
+ diagnostics,
1486
+ "task_editor_mode.action_requested",
1487
+ {
1488
+ nextTaskEditorMode: nextMode,
1489
+ previousSelectedTaskId: nodeState.selectedTaskId,
1490
+ previousTaskEditorMode: taskEditorMode
1491
+ },
1492
+ { includeStack: true }
1493
+ );
1494
+ controllerSession.setTaskEditorModeState(nextMode);
1495
+ },
1467
1496
  taskDetail,
1468
1497
  taskDraft,
1469
1498
  taskEditorMode,
@@ -1481,7 +1510,13 @@ function createIssueManagerControllerNotificationState(current, input) {
1481
1510
 
1482
1511
  // src/ui/react/internal/issue/createIssueManagerIssueBindings.ts
1483
1512
  function createIssueManagerIssueBindings(input) {
1484
- const { controllerSession, feature, issueEditorMode, nodeState } = input;
1513
+ const {
1514
+ controllerSession,
1515
+ diagnostics,
1516
+ feature,
1517
+ issueEditorMode,
1518
+ nodeState
1519
+ } = input;
1485
1520
  return {
1486
1521
  setIssueContent(content) {
1487
1522
  controllerSession.setIssueDraftInternal((current) => {
@@ -1507,6 +1542,17 @@ function createIssueManagerIssueBindings(input) {
1507
1542
  }));
1508
1543
  },
1509
1544
  setIssueEditorMode(mode) {
1545
+ logIssueManagerDiagnostic(
1546
+ diagnostics,
1547
+ "issue_editor_mode.requested",
1548
+ {
1549
+ nextIssueEditorMode: mode,
1550
+ previousIssueEditorMode: issueEditorMode,
1551
+ selectedIssueId: nodeState.selectedIssueId,
1552
+ selectedTaskId: nodeState.selectedTaskId
1553
+ },
1554
+ { includeStack: true }
1555
+ );
1510
1556
  controllerSession.setIssueEditorModeState(mode);
1511
1557
  if (mode === "create") {
1512
1558
  controllerSession.setIssueDraftInternal(
@@ -1540,12 +1586,24 @@ function createIssueManagerIssueBindings(input) {
1540
1586
 
1541
1587
  // src/ui/react/internal/task/createIssueManagerTaskBindings.ts
1542
1588
  function createIssueManagerTaskBindings(input) {
1543
- const { controllerSession, feature, nodeState, taskEditorMode } = input;
1589
+ const { controllerSession, diagnostics, feature, nodeState, taskEditorMode } = input;
1544
1590
  return {
1545
1591
  selectTask(taskId) {
1546
- controllerSession.updateNodeState(
1547
- (current) => applyIssueManagerTaskSelection(current, taskId)
1548
- );
1592
+ controllerSession.updateNodeState((current) => {
1593
+ logIssueManagerDiagnostic(
1594
+ diagnostics,
1595
+ "task_selection.requested",
1596
+ {
1597
+ activeTopicId: current.activeTopicId ?? null,
1598
+ nextSelectedTaskId: taskId,
1599
+ previousSelectedIssueId: current.selectedIssueId,
1600
+ previousSelectedTaskId: current.selectedTaskId,
1601
+ taskEditorMode
1602
+ },
1603
+ { includeStack: true }
1604
+ );
1605
+ return applyIssueManagerTaskSelection(current, taskId);
1606
+ });
1549
1607
  controllerSession.setTaskEditorModeState("read");
1550
1608
  },
1551
1609
  setTaskContent(content) {
@@ -1572,6 +1630,16 @@ function createIssueManagerTaskBindings(input) {
1572
1630
  }));
1573
1631
  },
1574
1632
  setTaskEditorMode(mode) {
1633
+ logIssueManagerDiagnostic(
1634
+ diagnostics,
1635
+ "task_editor_mode.requested",
1636
+ {
1637
+ nextTaskEditorMode: mode,
1638
+ previousSelectedTaskId: nodeState.selectedTaskId,
1639
+ previousTaskEditorMode: taskEditorMode
1640
+ },
1641
+ { includeStack: true }
1642
+ );
1575
1643
  controllerSession.setTaskEditorModeState(mode);
1576
1644
  if (mode === "create") {
1577
1645
  controllerSession.setTaskDraftInternal(
@@ -1607,21 +1675,24 @@ function createIssueManagerTaskBindings(input) {
1607
1675
  function createIssueManagerControllerBindings(input) {
1608
1676
  const {
1609
1677
  controllerSession,
1678
+ diagnostics,
1610
1679
  feature,
1611
1680
  issueEditorMode,
1612
1681
  nodeState,
1613
- onResolveRichTextAtProviders,
1682
+ onResolveRichTextTriggerProviders,
1614
1683
  taskEditorMode,
1615
1684
  workspaceId
1616
1685
  } = input;
1617
1686
  const issueBindings = createIssueManagerIssueBindings({
1618
1687
  controllerSession,
1688
+ diagnostics,
1619
1689
  feature,
1620
1690
  issueEditorMode,
1621
1691
  nodeState
1622
1692
  });
1623
1693
  const taskBindings = createIssueManagerTaskBindings({
1624
1694
  controllerSession,
1695
+ diagnostics,
1625
1696
  feature,
1626
1697
  nodeState,
1627
1698
  taskEditorMode
@@ -1638,16 +1709,26 @@ function createIssueManagerControllerBindings(input) {
1638
1709
  reportIssueSearchUsage(query) {
1639
1710
  controllerSession.reportIssueSearchUsage(query);
1640
1711
  },
1641
- resolveRichTextAtProviders(surface) {
1642
- return onResolveRichTextAtProviders?.({
1712
+ resolveRichTextTriggerProviders(surface) {
1713
+ return onResolveRichTextTriggerProviders?.({
1643
1714
  surface,
1644
1715
  workspaceId
1645
1716
  }) ?? [];
1646
1717
  },
1647
1718
  selectIssue(issueId) {
1648
- controllerSession.updateNodeState(
1649
- (current) => applyIssueManagerIssueSelection(current, issueId)
1650
- );
1719
+ controllerSession.updateNodeState((current) => {
1720
+ logIssueManagerDiagnostic(
1721
+ diagnostics,
1722
+ "issue_selection.requested",
1723
+ {
1724
+ nextSelectedIssueId: issueId,
1725
+ previousSelectedIssueId: current.selectedIssueId,
1726
+ previousSelectedTaskId: current.selectedTaskId
1727
+ },
1728
+ { includeStack: true }
1729
+ );
1730
+ return applyIssueManagerIssueSelection(current, issueId);
1731
+ });
1651
1732
  controllerSession.setIssueEditorModeState("read");
1652
1733
  controllerSession.setTaskEditorModeState("read");
1653
1734
  },
@@ -1684,19 +1765,28 @@ function resolveIssueManagerFloatingNoticeViewState(input) {
1684
1765
 
1685
1766
  // src/ui/react/internal/controller/useIssueManagerControllerRuntime.ts
1686
1767
  function useIssueManagerControllerRuntime(input) {
1687
- const { feature, openSource, onStateChange, service, state, workspaceId } = input;
1768
+ const {
1769
+ diagnostics,
1770
+ feature,
1771
+ openSource,
1772
+ onStateChange,
1773
+ service,
1774
+ state,
1775
+ workspaceId
1776
+ } = input;
1688
1777
  const controllerService = useMemo(
1689
1778
  () => service ?? createIssueManagerControllerService(),
1690
1779
  [service]
1691
1780
  );
1692
1781
  const controllerSession = useMemo(
1693
1782
  () => controllerService.createSession({
1783
+ diagnostics,
1694
1784
  feature,
1695
1785
  openSource,
1696
1786
  state,
1697
1787
  workspaceId
1698
1788
  }),
1699
- [controllerService, feature, openSource, workspaceId]
1789
+ [controllerService, diagnostics, feature, openSource, workspaceId]
1700
1790
  );
1701
1791
  const snapshot = useSnapshot(
1702
1792
  controllerSession.store
@@ -1735,16 +1825,18 @@ function useIssueManagerControllerRuntime(input) {
1735
1825
 
1736
1826
  // src/ui/react/internal/controller/useIssueManagerController.ts
1737
1827
  function useIssueManagerController({
1828
+ diagnostics,
1738
1829
  feature,
1739
1830
  openSource,
1740
1831
  onStateChange,
1741
- resolveRichTextAtProviders,
1832
+ resolveRichTextTriggerProviders,
1742
1833
  service,
1743
1834
  state,
1744
1835
  workspaceId
1745
1836
  }) {
1746
1837
  const copy = feature.i18n;
1747
1838
  const { controllerSession, floatingNotice, snapshot } = useIssueManagerControllerRuntime({
1839
+ diagnostics,
1748
1840
  feature,
1749
1841
  openSource,
1750
1842
  onStateChange,
@@ -1788,6 +1880,7 @@ function useIssueManagerController({
1788
1880
  const actions = createIssueManagerControllerActionsBridge({
1789
1881
  controllerSession,
1790
1882
  copy,
1883
+ diagnostics,
1791
1884
  feature,
1792
1885
  issueDetail,
1793
1886
  issueDraft,
@@ -1801,10 +1894,11 @@ function useIssueManagerController({
1801
1894
  });
1802
1895
  const bindings = createIssueManagerControllerBindings({
1803
1896
  controllerSession,
1897
+ diagnostics,
1804
1898
  feature,
1805
1899
  issueEditorMode,
1806
1900
  nodeState,
1807
- onResolveRichTextAtProviders: resolveRichTextAtProviders,
1901
+ onResolveRichTextTriggerProviders: resolveRichTextTriggerProviders,
1808
1902
  taskEditorMode,
1809
1903
  workspaceId
1810
1904
  });
@@ -1825,6 +1919,7 @@ function useIssueManagerController({
1825
1919
  canSelectExecutionDirectory,
1826
1920
  canUploadWorkspaceFiles,
1827
1921
  copy,
1922
+ diagnostics: diagnostics ?? null,
1828
1923
  async createTopic(topicInput) {
1829
1924
  try {
1830
1925
  const topic = await feature.backend.createTopic({
@@ -1873,6 +1968,12 @@ function useIssueManagerController({
1873
1968
  isRunningTask,
1874
1969
  nodeState,
1875
1970
  notification,
1971
+ async openMention(mention) {
1972
+ await feature.mentionActionHandler?.openMention({
1973
+ mention,
1974
+ workspaceId
1975
+ });
1976
+ },
1876
1977
  providerOptions,
1877
1978
  executionDirectoryProjectService: feature.executionDirectoryPicker?.service ?? null,
1878
1979
  workspaceUserProjectI18n: feature.workspaceUserProjectI18n,
@@ -1916,20 +2017,22 @@ function useIssueManagerController({
1916
2017
 
1917
2018
  // src/ui/react/internal/shell/useIssueManagerNodeView.ts
1918
2019
  function useIssueManagerNodeView({
2020
+ diagnostics,
1919
2021
  feature,
1920
2022
  nodeId,
1921
2023
  openSource,
1922
2024
  onStateChange,
1923
- resolveRichTextAtProviders,
2025
+ resolveRichTextTriggerProviders,
1924
2026
  service,
1925
2027
  state,
1926
2028
  workspaceId
1927
2029
  }) {
1928
2030
  const controller = useIssueManagerController({
2031
+ diagnostics,
1929
2032
  feature,
1930
2033
  openSource,
1931
2034
  onStateChange,
1932
- resolveRichTextAtProviders,
2035
+ resolveRichTextTriggerProviders,
1933
2036
  service,
1934
2037
  state,
1935
2038
  workspaceId
@@ -1966,6 +2069,14 @@ function useIssueManagerNodeView({
1966
2069
  selectedTask,
1967
2070
  shell: {
1968
2071
  onCloseTaskDrawer: () => {
2072
+ logIssueManagerDiagnostic(
2073
+ controller.diagnostics,
2074
+ "task_drawer.close_requested",
2075
+ {
2076
+ selectedIssueId: controller.nodeState.selectedIssueId,
2077
+ selectedTaskId: controller.nodeState.selectedTaskId
2078
+ }
2079
+ );
1969
2080
  controller.selectTask(null);
1970
2081
  },
1971
2082
  onDismissIssueCreate: () => {
@@ -1983,13 +2094,17 @@ import {
1983
2094
  // src/ui/IssueManagerNode.tsx
1984
2095
  import {
1985
2096
  useEffect as useEffect9,
1986
- useRef as useRef5
2097
+ useRef as useRef7
1987
2098
  } from "react";
1988
2099
  import { Button as Button13, PanelIcon, cn as cn11 } from "@tutti-os/ui-system";
1989
2100
  import { WorkspaceFileReferencePicker } from "@tutti-os/workspace-file-reference/ui";
1990
2101
 
1991
2102
  // src/ui/internal/shell/IssueManagerShell.tsx
1992
- import { useEffect as useEffect7, useState as useState8 } from "react";
2103
+ import {
2104
+ useEffect as useEffect7,
2105
+ useRef as useRef6,
2106
+ useState as useState8
2107
+ } from "react";
1993
2108
  import { Button as Button11, FileCreateIcon as FileCreateIcon4, cn as cn9 } from "@tutti-os/ui-system";
1994
2109
 
1995
2110
  // src/ui/internal/shell/IssueManagerPanels.tsx
@@ -2295,6 +2410,7 @@ function IssueManagerOutputSection({
2295
2410
  }
2296
2411
  function IssueManagerSubtaskSection({
2297
2412
  copy,
2413
+ diagnostics,
2298
2414
  onCreate,
2299
2415
  onSelectTask,
2300
2416
  selectedTaskId,
@@ -2316,7 +2432,17 @@ function IssueManagerSubtaskSection({
2316
2432
  selectedTaskId === task.taskId ? "bg-transparency-actived" : "bg-transparent hover:bg-transparency-hover"
2317
2433
  ),
2318
2434
  type: "button",
2319
- onClick: () => onSelectTask(task.taskId),
2435
+ onClick: (event) => {
2436
+ logIssueManagerDiagnostic(diagnostics, "task_row.click", {
2437
+ clientX: event.clientX,
2438
+ clientY: event.clientY,
2439
+ selectedTaskId,
2440
+ surface: "detail_subtasks",
2441
+ taskId: task.taskId,
2442
+ taskTitle: task.title
2443
+ });
2444
+ onSelectTask(task.taskId);
2445
+ },
2320
2446
  children: [
2321
2447
  /* @__PURE__ */ jsxs3("div", { className: "min-w-0 flex-1", children: [
2322
2448
  /* @__PURE__ */ jsxs3("div", { className: "flex min-w-0 items-center gap-2.5", children: [
@@ -2340,10 +2466,20 @@ function IssueManagerSubtaskSection({
2340
2466
 
2341
2467
  // src/ui/internal/issue/IssueManagerIssueAcceptanceState.ts
2342
2468
  function resolveIssueManagerIssueAcceptanceTaskId(input) {
2343
- if (input.selectedIssue?.status !== "pending_acceptance" || input.selectedTaskId || input.latestRun?.status !== "completed") {
2469
+ if (input.selectedIssue?.status !== "pending_acceptance" || input.latestRun?.status !== "completed" || input.selectedTaskId) {
2344
2470
  return null;
2345
2471
  }
2346
- const taskId = input.latestRun.taskId?.trim() ?? "";
2472
+ return resolveIssueManagerIssueRunTaskId({
2473
+ latestRun: input.latestRun,
2474
+ selectedIssue: input.selectedIssue,
2475
+ tasks: input.tasks
2476
+ });
2477
+ }
2478
+ function resolveIssueManagerIssueRunTaskId(input) {
2479
+ if (!input.selectedIssue) {
2480
+ return null;
2481
+ }
2482
+ const taskId = input.latestRun?.taskId?.trim() ?? "";
2347
2483
  if (!taskId) {
2348
2484
  return null;
2349
2485
  }
@@ -2356,7 +2492,7 @@ function resolveIssueManagerIssueAcceptanceTaskId(input) {
2356
2492
  return taskId;
2357
2493
  }
2358
2494
  function resolveIssueManagerVisibleSubtasks(input) {
2359
- const hiddenTaskId = input.hiddenAcceptanceTaskId?.trim() ?? "";
2495
+ const hiddenTaskId = input.hiddenIssueRunTaskId?.trim() ?? "";
2360
2496
  if (!hiddenTaskId) {
2361
2497
  return [...input.tasks];
2362
2498
  }
@@ -2375,6 +2511,7 @@ function IssueManagerDescriptionSection({
2375
2511
  emptyLabel,
2376
2512
  label,
2377
2513
  minHeightClass = "min-h-[14rem]",
2514
+ onMentionAction,
2378
2515
  onOpen,
2379
2516
  variant = "card"
2380
2517
  }) {
@@ -2419,6 +2556,7 @@ function IssueManagerDescriptionSection({
2419
2556
  IssueManagerDescriptionContent,
2420
2557
  {
2421
2558
  content: displayContent,
2559
+ onMentionAction,
2422
2560
  onOpen
2423
2561
  }
2424
2562
  ) }) : /* @__PURE__ */ jsx4("p", { className: "text-[13px] font-normal leading-5 text-[var(--text-secondary)]", children: emptyLabel })
@@ -2446,6 +2584,7 @@ function IssueManagerDescriptionSection({
2446
2584
  IssueManagerDescriptionContent,
2447
2585
  {
2448
2586
  content: displayContent,
2587
+ onMentionAction,
2449
2588
  onOpen
2450
2589
  }
2451
2590
  ) : /* @__PURE__ */ jsx4("p", { className: "font-normal text-[var(--text-secondary)]", children: emptyLabel })
@@ -2467,6 +2606,7 @@ function IssueManagerDescriptionSection({
2467
2606
  }
2468
2607
  function IssueManagerDescriptionContent({
2469
2608
  content,
2609
+ onMentionAction,
2470
2610
  onOpen
2471
2611
  }) {
2472
2612
  return /* @__PURE__ */ jsx4(
@@ -2475,6 +2615,7 @@ function IssueManagerDescriptionContent({
2475
2615
  className: "min-w-0 max-w-full [overflow-wrap:anywhere]",
2476
2616
  paragraphClassName: "break-words [overflow-wrap:anywhere]",
2477
2617
  value: content,
2618
+ onMentionAction,
2478
2619
  onOpenWorkspaceReference: onOpen ? (reference) => onOpen({
2479
2620
  displayName: reference.label,
2480
2621
  kind: reference.kind,
@@ -2486,7 +2627,7 @@ function IssueManagerDescriptionContent({
2486
2627
 
2487
2628
  // src/ui/internal/content/IssueManagerRichTextTextarea.tsx
2488
2629
  import { useEffect as useEffect5, useMemo as useMemo3, useRef as useRef2, useState as useState4 } from "react";
2489
- import { RichTextAtEditor } from "@tutti-os/ui-rich-text/editor";
2630
+ import { RichTextTriggerEditor } from "@tutti-os/ui-rich-text/editor";
2490
2631
  import { Button as Button3, LinkIcon, cn as cn3 } from "@tutti-os/ui-system";
2491
2632
  import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
2492
2633
  var issueManagerRichTextTextareaBaseClassName = "min-h-20 w-full rounded-[8px] border border-transparent bg-[var(--transparency-block)] p-3 text-[13px] font-normal leading-[1.3] text-[var(--text-primary)] transition-[background-color,border-color,color] outline-none shadow-none placeholder:text-[var(--text-placeholder)] hover:bg-[var(--transparency-hover)] focus:bg-[var(--transparency-hover)] focus-visible:border-transparent focus-visible:bg-[var(--transparency-hover)] focus-visible:ring-0 disabled:cursor-not-allowed disabled:bg-[var(--transparency-block)] disabled:text-[var(--text-disabled)] disabled:opacity-100 aria-invalid:border-[var(--state-danger)] aria-invalid:bg-[var(--transparency-block)] aria-invalid:hover:bg-[var(--transparency-hover)] aria-invalid:focus:bg-[var(--transparency-hover)] aria-invalid:focus-visible:bg-[var(--transparency-hover)] aria-invalid:ring-0 aria-invalid:shadow-none";
@@ -2500,7 +2641,7 @@ function IssueManagerRichTextTextarea({
2500
2641
  value
2501
2642
  }) {
2502
2643
  const providers = useMemo3(
2503
- () => controller.resolveRichTextAtProviders(surface),
2644
+ () => controller.resolveRichTextTriggerProviders(surface),
2504
2645
  [controller, surface]
2505
2646
  );
2506
2647
  const showReferenceAction = controller.canReferenceWorkspaceFiles;
@@ -2516,12 +2657,12 @@ function IssueManagerRichTextTextarea({
2516
2657
  previousValueRef.current = value;
2517
2658
  }, [controller.referenceTarget, surface, value]);
2518
2659
  return /* @__PURE__ */ jsx5(
2519
- RichTextAtEditor,
2660
+ RichTextTriggerEditor,
2520
2661
  {
2521
2662
  focusSignal,
2522
2663
  maxResults: 8,
2523
2664
  minQueryLength: 1,
2524
- providers,
2665
+ triggerProviders: providers,
2525
2666
  textOverrides: {
2526
2667
  loadingLabel: controller.copy.t("richTextAt.loading"),
2527
2668
  noMatchesLabel: controller.copy.t("richTextAt.noMatches"),
@@ -2689,7 +2830,8 @@ function IssueManagerIssuePane({
2689
2830
  const tasks = controller.issueDetail.value?.tasks ?? [];
2690
2831
  const selectedTaskId = controller.nodeState.selectedTaskId;
2691
2832
  const selectedTask = selectedTaskId ? (controller.taskDetail.value?.task?.taskId === selectedTaskId ? controller.taskDetail.value.task : tasks.find((task) => task.taskId === selectedTaskId)) ?? null : null;
2692
- const latestRun = selectedTask ? controller.taskDetail.value?.latestRun ?? controller.taskDetail.value?.recentRuns[0] ?? null : controller.issueDetail.value?.latestRun ?? controller.issueDetail.value?.recentRuns[0] ?? null;
2833
+ const issueLatestRun = controller.issueDetail.value?.latestRun ?? controller.issueDetail.value?.recentRuns[0] ?? null;
2834
+ const latestRun = selectedTask ? controller.taskDetail.value?.latestRun ?? controller.taskDetail.value?.recentRuns[0] ?? null : issueLatestRun;
2693
2835
  const latestOutputs = selectedTask ? controller.taskDetail.value?.latestOutputs ?? [] : controller.issueDetail.value?.latestOutputs ?? [];
2694
2836
  const issueAcceptanceTaskId = resolveIssueManagerIssueAcceptanceTaskId({
2695
2837
  latestRun,
@@ -2697,8 +2839,13 @@ function IssueManagerIssuePane({
2697
2839
  selectedTaskId,
2698
2840
  tasks
2699
2841
  });
2842
+ const issueRunTaskId = resolveIssueManagerIssueRunTaskId({
2843
+ latestRun: issueLatestRun,
2844
+ selectedIssue,
2845
+ tasks
2846
+ });
2700
2847
  const visibleTasks = resolveIssueManagerVisibleSubtasks({
2701
- hiddenAcceptanceTaskId: issueAcceptanceTaskId,
2848
+ hiddenIssueRunTaskId: issueRunTaskId,
2702
2849
  tasks
2703
2850
  });
2704
2851
  const [deleteDialogOpen, setDeleteDialogOpen] = useState5(false);
@@ -2893,6 +3040,7 @@ function IssueManagerIssuePane({
2893
3040
  content: issueContent,
2894
3041
  emptyLabel: copy.t("messages.issueContentEmpty"),
2895
3042
  label: copy.t("labels.description"),
3043
+ onMentionAction: controller.openMention,
2896
3044
  onOpen: controller.openReference,
2897
3045
  variant: "plain"
2898
3046
  }
@@ -2919,6 +3067,7 @@ function IssueManagerIssuePane({
2919
3067
  IssueManagerSubtaskSection,
2920
3068
  {
2921
3069
  copy,
3070
+ diagnostics: controller.diagnostics,
2922
3071
  onCreate: controller.createTaskDraft,
2923
3072
  onSelectTask: controller.selectTask,
2924
3073
  selectedTaskId: selectedTask?.taskId ?? null,
@@ -3872,6 +4021,7 @@ function IssueManagerTaskComposerPane({
3872
4021
  }
3873
4022
 
3874
4023
  // src/ui/internal/shell/IssueManagerTaskDrawer.tsx
4024
+ import { useRef as useRef4 } from "react";
3875
4025
  import { ScrollArea as ScrollArea4, cn as cn8 } from "@tutti-os/ui-system";
3876
4026
 
3877
4027
  // src/ui/internal/shell/IssueManagerTaskDrawerSections.tsx
@@ -4097,6 +4247,7 @@ function IssueManagerTaskDrawerReadBody({
4097
4247
  content: taskContent,
4098
4248
  emptyLabel: copy.t("messages.taskContentEmpty"),
4099
4249
  label: copy.t("labels.description"),
4250
+ onMentionAction: controller.openMention,
4100
4251
  onOpen: controller.openReference,
4101
4252
  variant: "plain"
4102
4253
  }
@@ -4208,13 +4359,63 @@ function IssueManagerTaskDrawer({
4208
4359
  renderLatestRunStatus,
4209
4360
  selectedIssue,
4210
4361
  selectedTask,
4211
- onClose
4362
+ onClose,
4363
+ shouldIgnoreBackdropClick
4212
4364
  }) {
4213
4365
  const view = resolveIssueManagerTaskDrawerViewState({
4214
4366
  controller,
4215
4367
  selectedTask
4216
4368
  });
4217
4369
  const taskContent = selectedTask?.content ?? "";
4370
+ const hasRequestedBackdropCloseRef = useRef4(false);
4371
+ const requestBackdropClose = (event, phase) => {
4372
+ const target = event.target;
4373
+ logIssueManagerDiagnostic(
4374
+ controller.diagnostics,
4375
+ "task_drawer.backdrop_close_event",
4376
+ {
4377
+ clientX: event.clientX,
4378
+ clientY: event.clientY,
4379
+ currentTargetTag: event.currentTarget.tagName,
4380
+ hasRequestedBackdropClose: hasRequestedBackdropCloseRef.current,
4381
+ isClosing,
4382
+ isDirectBackdropClick: event.target === event.currentTarget,
4383
+ phase,
4384
+ selectedIssueId: selectedIssue?.issueId ?? null,
4385
+ selectedTaskId: selectedTask?.taskId ?? null,
4386
+ selectedTaskTitle: selectedTask?.title ?? null,
4387
+ targetClassName: target instanceof HTMLElement ? target.className : null,
4388
+ targetTag: target instanceof HTMLElement ? target.tagName : null
4389
+ }
4390
+ );
4391
+ if (event.target !== event.currentTarget) {
4392
+ return;
4393
+ }
4394
+ event.preventDefault();
4395
+ event.stopPropagation();
4396
+ if (hasRequestedBackdropCloseRef.current) {
4397
+ return;
4398
+ }
4399
+ if (shouldIgnoreBackdropClick?.(event)) {
4400
+ return;
4401
+ }
4402
+ hasRequestedBackdropCloseRef.current = true;
4403
+ onClose("backdrop");
4404
+ };
4405
+ const handleBackdropPointerDown = (event) => {
4406
+ if (event.pointerType === "mouse" && event.button !== 0) {
4407
+ return;
4408
+ }
4409
+ requestBackdropClose(event, "pointer_down");
4410
+ };
4411
+ const handleBackdropClick = (event) => {
4412
+ if (hasRequestedBackdropCloseRef.current) {
4413
+ event.preventDefault();
4414
+ event.stopPropagation();
4415
+ return;
4416
+ }
4417
+ requestBackdropClose(event, "click");
4418
+ };
4218
4419
  return /* @__PURE__ */ jsx16(
4219
4420
  "div",
4220
4421
  {
@@ -4222,7 +4423,8 @@ function IssueManagerTaskDrawer({
4222
4423
  "absolute inset-0 z-20 flex justify-end overscroll-contain bg-[var(--backdrop)] backdrop-blur-[1px] motion-reduce:animate-none",
4223
4424
  isClosing ? "motion-safe:animate-out motion-safe:fade-out-0 motion-safe:duration-[180ms] motion-safe:ease-[cubic-bezier(0.4,0,0.2,1)]" : "motion-safe:animate-in motion-safe:fade-in-0 motion-safe:duration-[180ms] motion-safe:ease-[cubic-bezier(0.4,0,0.2,1)]"
4224
4425
  ),
4225
- onClick: onClose,
4426
+ onClick: handleBackdropClick,
4427
+ onPointerDown: handleBackdropPointerDown,
4226
4428
  onTouchMove: (event) => {
4227
4429
  event.preventDefault();
4228
4430
  },
@@ -4244,7 +4446,7 @@ function IssueManagerTaskDrawer({
4244
4446
  IssueManagerTaskDrawerHeader,
4245
4447
  {
4246
4448
  controller,
4247
- onClose,
4449
+ onClose: () => onClose("header_back"),
4248
4450
  selectedTask,
4249
4451
  view
4250
4452
  }
@@ -4294,7 +4496,7 @@ function IssueManagerTaskDrawer({
4294
4496
  import {
4295
4497
  useEffect as useEffect6,
4296
4498
  useEffectEvent as useEffectEvent2,
4297
- useRef as useRef4,
4499
+ useRef as useRef5,
4298
4500
  useState as useState7
4299
4501
  } from "react";
4300
4502
  function useIssueManagerShellView({
@@ -4302,8 +4504,8 @@ function useIssueManagerShellView({
4302
4504
  selectedIssue,
4303
4505
  selectedTask
4304
4506
  }) {
4305
- const layoutRef = useRef4(null);
4306
- const resizeRef = useRef4(null);
4507
+ const layoutRef = useRef5(null);
4508
+ const resizeRef = useRef5(null);
4307
4509
  const [sidebarWidth, setSidebarWidth] = useState7(
4308
4510
  issueManagerSidebarDefaultWidth
4309
4511
  );
@@ -4312,6 +4514,7 @@ function useIssueManagerShellView({
4312
4514
  controller.dismissNotification();
4313
4515
  });
4314
4516
  const floatingNotice = controller.floatingNotice;
4517
+ const lastContentDiagnosticRef = useRef5(null);
4315
4518
  useEffect6(() => {
4316
4519
  const publishLayout = () => {
4317
4520
  const width = layoutRef.current?.getBoundingClientRect().width ?? 0;
@@ -4352,6 +4555,48 @@ function useIssueManagerShellView({
4352
4555
  selectedTaskPresent: selectedTask !== null,
4353
4556
  taskEditorMode: controller.taskEditorMode
4354
4557
  });
4558
+ useEffect6(() => {
4559
+ const nextDiagnostic = {
4560
+ isIssueEditing: content.isIssueEditing,
4561
+ isTaskCreating: content.isTaskCreating,
4562
+ isTaskDrawerOpen: content.isTaskDrawerOpen,
4563
+ issueEditorMode: controller.issueEditorMode,
4564
+ selectedIssueId: controller.nodeState.selectedIssueId,
4565
+ selectedTaskId: controller.nodeState.selectedTaskId,
4566
+ selectedTaskPresent: selectedTask !== null,
4567
+ taskEditorMode: controller.taskEditorMode
4568
+ };
4569
+ const previousDiagnostic = lastContentDiagnosticRef.current;
4570
+ if (previousDiagnostic && previousDiagnostic.isIssueEditing === nextDiagnostic.isIssueEditing && previousDiagnostic.isTaskCreating === nextDiagnostic.isTaskCreating && previousDiagnostic.isTaskDrawerOpen === nextDiagnostic.isTaskDrawerOpen && previousDiagnostic.issueEditorMode === nextDiagnostic.issueEditorMode && previousDiagnostic.selectedIssueId === nextDiagnostic.selectedIssueId && previousDiagnostic.selectedTaskId === nextDiagnostic.selectedTaskId && previousDiagnostic.selectedTaskPresent === nextDiagnostic.selectedTaskPresent && previousDiagnostic.taskEditorMode === nextDiagnostic.taskEditorMode) {
4571
+ return;
4572
+ }
4573
+ lastContentDiagnosticRef.current = nextDiagnostic;
4574
+ logIssueManagerDiagnostic(controller.diagnostics, "shell_content.derived", {
4575
+ isIssueEditing: content.isIssueEditing,
4576
+ isTaskCreating: content.isTaskCreating,
4577
+ isTaskDrawerOpen: content.isTaskDrawerOpen,
4578
+ issueEditorMode: controller.issueEditorMode,
4579
+ previousIsTaskDrawerOpen: previousDiagnostic?.isTaskDrawerOpen ?? null,
4580
+ previousSelectedTaskId: previousDiagnostic?.selectedTaskId ?? null,
4581
+ previousTaskEditorMode: previousDiagnostic?.taskEditorMode ?? null,
4582
+ selectedIssueId: controller.nodeState.selectedIssueId,
4583
+ selectedTaskId: controller.nodeState.selectedTaskId,
4584
+ selectedTaskPresent: selectedTask !== null,
4585
+ showBottomBar: content.showBottomBar,
4586
+ taskEditorMode: controller.taskEditorMode
4587
+ });
4588
+ }, [
4589
+ content.isIssueEditing,
4590
+ content.isTaskCreating,
4591
+ content.isTaskDrawerOpen,
4592
+ content.showBottomBar,
4593
+ controller.diagnostics,
4594
+ controller.issueEditorMode,
4595
+ controller.nodeState.selectedIssueId,
4596
+ controller.nodeState.selectedTaskId,
4597
+ controller.taskEditorMode,
4598
+ selectedTask
4599
+ ]);
4355
4600
  const sidebarViewState = resolveIssueManagerSidebarViewState({
4356
4601
  copy: controller.copy,
4357
4602
  issues: controller.issues
@@ -4444,9 +4689,34 @@ function useIssueManagerShellView({
4444
4689
  };
4445
4690
  }
4446
4691
 
4692
+ // src/ui/internal/shell/IssueManagerTaskDrawerEcho.ts
4693
+ var issueManagerTaskDrawerBackdropEchoMs = 900;
4694
+ var issueManagerTaskDrawerBackdropEchoDistancePx = 72;
4695
+ function shouldIgnoreIssueManagerTaskDrawerBackdropEcho(input) {
4696
+ if (!input.openPointer) {
4697
+ return {
4698
+ distancePx: null,
4699
+ elapsedMs: null,
4700
+ ignore: false
4701
+ };
4702
+ }
4703
+ const elapsedMs = input.nowMs - input.openPointer.timeMs;
4704
+ const distancePx = Math.hypot(
4705
+ input.clickClientX - input.openPointer.clientX,
4706
+ input.clickClientY - input.openPointer.clientY
4707
+ );
4708
+ return {
4709
+ distancePx,
4710
+ elapsedMs,
4711
+ ignore: elapsedMs <= (input.maxElapsedMs ?? issueManagerTaskDrawerBackdropEchoMs) && distancePx <= (input.maxDistancePx ?? issueManagerTaskDrawerBackdropEchoDistancePx)
4712
+ };
4713
+ }
4714
+
4447
4715
  // src/ui/internal/shell/IssueManagerShell.tsx
4448
4716
  import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
4449
4717
  var issueManagerTaskDrawerExitDurationMs = 180;
4718
+ var issueManagerTaskDrawerCloseBlockerMs = 500;
4719
+ var issueManagerTaskDrawerCloseBlockerUntilMs = 0;
4450
4720
  function IssueManagerShell({
4451
4721
  controller,
4452
4722
  emptyIllustration,
@@ -4462,30 +4732,193 @@ function IssueManagerShell({
4462
4732
  selectedTask
4463
4733
  });
4464
4734
  const [renderedTaskDrawerTask, setRenderedTaskDrawerTask] = useState8(selectedTask);
4465
- const [isTaskDrawerClosing, setIsTaskDrawerClosing] = useState8(false);
4735
+ const [taskDrawerCloseBlockerUntilMs, setTaskDrawerCloseBlockerUntilMs] = useState8(issueManagerTaskDrawerCloseBlockerUntilMs);
4736
+ const lastContentPointerDownRef = useRef6(
4737
+ null
4738
+ );
4739
+ const taskDrawerOpenPointerRef = useRef6(
4740
+ null
4741
+ );
4742
+ const pendingTaskDrawerCloseRef = useRef6(false);
4743
+ const taskDrawerCloseBlockerTimeoutRef = useRef6(null);
4744
+ const previousTaskDrawerOpenRef = useRef6({
4745
+ isOpen: shellView.content.isTaskDrawerOpen,
4746
+ taskId: selectedTask?.taskId ?? null
4747
+ });
4748
+ const clearTaskDrawerCloseBlocker = () => {
4749
+ if (taskDrawerCloseBlockerTimeoutRef.current !== null) {
4750
+ window.clearTimeout(taskDrawerCloseBlockerTimeoutRef.current);
4751
+ taskDrawerCloseBlockerTimeoutRef.current = null;
4752
+ }
4753
+ issueManagerTaskDrawerCloseBlockerUntilMs = 0;
4754
+ setTaskDrawerCloseBlockerUntilMs(0);
4755
+ };
4756
+ const startTaskDrawerCloseBlocker = () => {
4757
+ issueManagerTaskDrawerCloseBlockerUntilMs = performance.now() + issueManagerTaskDrawerCloseBlockerMs;
4758
+ setTaskDrawerCloseBlockerUntilMs(issueManagerTaskDrawerCloseBlockerUntilMs);
4759
+ };
4760
+ useEffect7(() => {
4761
+ if (taskDrawerCloseBlockerTimeoutRef.current !== null) {
4762
+ window.clearTimeout(taskDrawerCloseBlockerTimeoutRef.current);
4763
+ taskDrawerCloseBlockerTimeoutRef.current = null;
4764
+ }
4765
+ if (taskDrawerCloseBlockerUntilMs <= performance.now()) {
4766
+ return void 0;
4767
+ }
4768
+ taskDrawerCloseBlockerTimeoutRef.current = window.setTimeout(() => {
4769
+ if (issueManagerTaskDrawerCloseBlockerUntilMs <= performance.now()) {
4770
+ issueManagerTaskDrawerCloseBlockerUntilMs = 0;
4771
+ }
4772
+ taskDrawerCloseBlockerTimeoutRef.current = null;
4773
+ setTaskDrawerCloseBlockerUntilMs(
4774
+ issueManagerTaskDrawerCloseBlockerUntilMs
4775
+ );
4776
+ }, taskDrawerCloseBlockerUntilMs - performance.now());
4777
+ return () => {
4778
+ if (taskDrawerCloseBlockerTimeoutRef.current !== null) {
4779
+ window.clearTimeout(taskDrawerCloseBlockerTimeoutRef.current);
4780
+ taskDrawerCloseBlockerTimeoutRef.current = null;
4781
+ }
4782
+ };
4783
+ }, [taskDrawerCloseBlockerUntilMs]);
4784
+ const handleCloseTaskDrawer = (source) => {
4785
+ logIssueManagerDiagnostic(
4786
+ controller.diagnostics,
4787
+ "task_drawer.close_source_requested",
4788
+ {
4789
+ isTaskDrawerOpen: shellView.content.isTaskDrawerOpen,
4790
+ renderedTaskId: renderedTaskDrawerTask?.taskId ?? null,
4791
+ selectedIssueId: selectedIssue?.issueId ?? null,
4792
+ selectedTaskId: selectedTask?.taskId ?? null,
4793
+ source
4794
+ }
4795
+ );
4796
+ pendingTaskDrawerCloseRef.current = true;
4797
+ setRenderedTaskDrawerTask(null);
4798
+ if (source === "backdrop") {
4799
+ startTaskDrawerCloseBlocker();
4800
+ } else {
4801
+ clearTaskDrawerCloseBlocker();
4802
+ }
4803
+ onCloseTaskDrawer();
4804
+ };
4805
+ const handleContentPointerDownCapture = (event) => {
4806
+ if (shellView.content.isTaskDrawerOpen || event.button !== 0) {
4807
+ return;
4808
+ }
4809
+ lastContentPointerDownRef.current = {
4810
+ clientX: event.clientX,
4811
+ clientY: event.clientY,
4812
+ timeMs: performance.now()
4813
+ };
4814
+ };
4815
+ const shouldIgnoreTaskDrawerBackdropClick = (event) => {
4816
+ const openPointer = taskDrawerOpenPointerRef.current;
4817
+ if (!openPointer) {
4818
+ return false;
4819
+ }
4820
+ const echo = shouldIgnoreIssueManagerTaskDrawerBackdropEcho({
4821
+ clickClientX: event.clientX,
4822
+ clickClientY: event.clientY,
4823
+ nowMs: performance.now(),
4824
+ openPointer
4825
+ });
4826
+ if (echo.ignore) {
4827
+ logIssueManagerDiagnostic(
4828
+ controller.diagnostics,
4829
+ "task_drawer.backdrop_click_ignored_as_open_echo",
4830
+ {
4831
+ clickClientX: event.clientX,
4832
+ clickClientY: event.clientY,
4833
+ distancePx: echo.distancePx,
4834
+ elapsedMs: echo.elapsedMs,
4835
+ openClientX: openPointer.clientX,
4836
+ openClientY: openPointer.clientY,
4837
+ selectedIssueId: selectedIssue?.issueId ?? null,
4838
+ selectedTaskId: selectedTask?.taskId ?? null
4839
+ }
4840
+ );
4841
+ }
4842
+ return echo.ignore;
4843
+ };
4466
4844
  useEffect7(() => {
4845
+ const selectedTaskId = selectedTask?.taskId ?? null;
4846
+ const previousOpen = previousTaskDrawerOpenRef.current;
4467
4847
  if (shellView.content.isTaskDrawerOpen) {
4468
- setRenderedTaskDrawerTask(selectedTask);
4469
- setIsTaskDrawerClosing(false);
4848
+ if (pendingTaskDrawerCloseRef.current) {
4849
+ return void 0;
4850
+ }
4851
+ if (!previousOpen.isOpen || previousOpen.taskId !== selectedTaskId) {
4852
+ taskDrawerOpenPointerRef.current = lastContentPointerDownRef.current;
4853
+ logIssueManagerDiagnostic(
4854
+ controller.diagnostics,
4855
+ "task_drawer.open_state",
4856
+ {
4857
+ isOpen: true,
4858
+ openClientX: taskDrawerOpenPointerRef.current?.clientX ?? null,
4859
+ openClientY: taskDrawerOpenPointerRef.current?.clientY ?? null,
4860
+ selectedIssueId: selectedIssue?.issueId ?? null,
4861
+ selectedTaskId,
4862
+ selectedTaskTitle: selectedTask?.title ?? null
4863
+ }
4864
+ );
4865
+ }
4866
+ previousTaskDrawerOpenRef.current = {
4867
+ isOpen: true,
4868
+ taskId: selectedTaskId
4869
+ };
4870
+ if (renderedTaskDrawerTask?.taskId !== selectedTaskId) {
4871
+ setRenderedTaskDrawerTask(selectedTask);
4872
+ }
4470
4873
  return void 0;
4471
4874
  }
4875
+ previousTaskDrawerOpenRef.current = {
4876
+ isOpen: false,
4877
+ taskId: null
4878
+ };
4879
+ taskDrawerOpenPointerRef.current = null;
4880
+ pendingTaskDrawerCloseRef.current = false;
4472
4881
  if (!renderedTaskDrawerTask) {
4473
4882
  return void 0;
4474
4883
  }
4475
- setIsTaskDrawerClosing(true);
4884
+ logIssueManagerDiagnostic(
4885
+ controller.diagnostics,
4886
+ "task_drawer.exit_started",
4887
+ {
4888
+ renderedTaskId: renderedTaskDrawerTask.taskId,
4889
+ renderedTaskTitle: renderedTaskDrawerTask.title,
4890
+ selectedIssueId: selectedIssue?.issueId ?? null,
4891
+ selectedTaskId: selectedTask?.taskId ?? null
4892
+ }
4893
+ );
4476
4894
  const timeout = window.setTimeout(() => {
4895
+ logIssueManagerDiagnostic(
4896
+ controller.diagnostics,
4897
+ "task_drawer.exit_finished",
4898
+ {
4899
+ renderedTaskId: renderedTaskDrawerTask.taskId,
4900
+ renderedTaskTitle: renderedTaskDrawerTask.title
4901
+ }
4902
+ );
4477
4903
  setRenderedTaskDrawerTask(null);
4478
- setIsTaskDrawerClosing(false);
4479
4904
  }, issueManagerTaskDrawerExitDurationMs);
4480
4905
  return () => {
4481
4906
  window.clearTimeout(timeout);
4482
4907
  };
4483
4908
  }, [
4909
+ controller.diagnostics,
4484
4910
  renderedTaskDrawerTask,
4911
+ renderedTaskDrawerTask?.taskId,
4912
+ selectedIssue?.issueId,
4485
4913
  selectedTask,
4914
+ selectedTask?.taskId,
4915
+ selectedTask?.title,
4486
4916
  shellView.content.isTaskDrawerOpen
4487
4917
  ]);
4488
- const taskDrawerTask = shellView.content.isTaskDrawerOpen ? selectedTask : renderedTaskDrawerTask;
4918
+ const isTaskDrawerOpenForRender = shellView.content.isTaskDrawerOpen && !pendingTaskDrawerCloseRef.current;
4919
+ const taskDrawerTask = isTaskDrawerOpenForRender ? selectedTask : renderedTaskDrawerTask;
4920
+ const isTaskDrawerClosing = !isTaskDrawerOpenForRender && renderedTaskDrawerTask !== null;
4921
+ const isTaskDrawerCloseBlockerVisible = !taskDrawerTask && taskDrawerCloseBlockerUntilMs > performance.now();
4489
4922
  return /* @__PURE__ */ jsxs15(
4490
4923
  "div",
4491
4924
  {
@@ -4529,60 +4962,91 @@ function IssueManagerShell({
4529
4962
  children: /* @__PURE__ */ jsx17("span", { className: "absolute top-0 bottom-0 left-1/2 w-px -translate-x-1/2 bg-transparent transition-[background-color,width] duration-150 group-hover:w-0.5 group-hover:bg-[color-mix(in_srgb,var(--border-focus)_40%,transparent)] group-focus-visible:w-0.5 group-focus-visible:bg-[color-mix(in_srgb,var(--border-focus)_40%,transparent)]" })
4530
4963
  }
4531
4964
  ),
4532
- /* @__PURE__ */ jsxs15("div", { className: "relative h-full min-h-0 overflow-hidden bg-transparent @container/issue-manager-content", children: [
4533
- /* @__PURE__ */ jsxs15("div", { className: "flex h-full min-h-0 flex-col", children: [
4534
- /* @__PURE__ */ jsx17("div", { className: "min-h-0 flex-1 overflow-hidden", children: shellView.content.isIssueEditing ? /* @__PURE__ */ jsx17(
4535
- IssueManagerIssuePane,
4536
- {
4537
- controller,
4538
- renderLatestRunStatus,
4539
- selectedIssue,
4540
- onDismissCreate: onDismissIssueCreate
4541
- }
4542
- ) : shellView.content.isTaskCreating ? /* @__PURE__ */ jsx17(
4543
- IssueManagerTaskComposerPane,
4544
- {
4545
- controller,
4546
- selectedIssue,
4547
- onCancel: () => controller.setTaskEditorMode("read")
4548
- }
4549
- ) : selectedIssue ? /* @__PURE__ */ jsx17(
4550
- IssueManagerIssuePane,
4551
- {
4552
- controller,
4553
- renderLatestRunStatus,
4554
- selectedIssue,
4555
- onDismissCreate: onDismissIssueCreate
4556
- }
4557
- ) : /* @__PURE__ */ jsx17(
4558
- IssueManagerShellEmptyState,
4559
- {
4560
- controller,
4561
- emptyIllustration
4562
- }
4563
- ) }),
4564
- /* @__PURE__ */ jsx17(
4565
- IssueManagerBottomBar,
4566
- {
4567
- controller,
4568
- isNarrowLayout: shellView.isNarrowLayout,
4569
- selectedIssue,
4570
- visible: shellView.content.showBottomBar
4571
- }
4572
- )
4573
- ] }),
4574
- taskDrawerTask ? /* @__PURE__ */ jsx17(
4575
- IssueManagerTaskDrawer,
4576
- {
4577
- controller,
4578
- isClosing: isTaskDrawerClosing,
4579
- renderLatestRunStatus,
4580
- selectedIssue,
4581
- selectedTask: taskDrawerTask,
4582
- onClose: onCloseTaskDrawer
4583
- }
4584
- ) : null
4585
- ] })
4965
+ /* @__PURE__ */ jsxs15(
4966
+ "div",
4967
+ {
4968
+ className: "relative h-full min-h-0 overflow-hidden bg-transparent @container/issue-manager-content",
4969
+ onPointerDownCapture: handleContentPointerDownCapture,
4970
+ children: [
4971
+ /* @__PURE__ */ jsxs15("div", { className: "flex h-full min-h-0 flex-col", children: [
4972
+ /* @__PURE__ */ jsx17("div", { className: "min-h-0 flex-1 overflow-hidden", children: shellView.content.isIssueEditing ? /* @__PURE__ */ jsx17(
4973
+ IssueManagerIssuePane,
4974
+ {
4975
+ controller,
4976
+ renderLatestRunStatus,
4977
+ selectedIssue,
4978
+ onDismissCreate: onDismissIssueCreate
4979
+ }
4980
+ ) : shellView.content.isTaskCreating ? /* @__PURE__ */ jsx17(
4981
+ IssueManagerTaskComposerPane,
4982
+ {
4983
+ controller,
4984
+ selectedIssue,
4985
+ onCancel: () => controller.setTaskEditorMode("read")
4986
+ }
4987
+ ) : selectedIssue ? /* @__PURE__ */ jsx17(
4988
+ IssueManagerIssuePane,
4989
+ {
4990
+ controller,
4991
+ renderLatestRunStatus,
4992
+ selectedIssue,
4993
+ onDismissCreate: onDismissIssueCreate
4994
+ }
4995
+ ) : /* @__PURE__ */ jsx17(
4996
+ IssueManagerShellEmptyState,
4997
+ {
4998
+ controller,
4999
+ emptyIllustration
5000
+ }
5001
+ ) }),
5002
+ /* @__PURE__ */ jsx17(
5003
+ IssueManagerBottomBar,
5004
+ {
5005
+ controller,
5006
+ isNarrowLayout: shellView.isNarrowLayout,
5007
+ selectedIssue,
5008
+ visible: shellView.content.showBottomBar
5009
+ }
5010
+ )
5011
+ ] }),
5012
+ taskDrawerTask ? /* @__PURE__ */ jsx17(
5013
+ IssueManagerTaskDrawer,
5014
+ {
5015
+ controller,
5016
+ isClosing: isTaskDrawerClosing,
5017
+ renderLatestRunStatus,
5018
+ selectedIssue,
5019
+ selectedTask: taskDrawerTask,
5020
+ onClose: handleCloseTaskDrawer,
5021
+ shouldIgnoreBackdropClick: shouldIgnoreTaskDrawerBackdropClick
5022
+ }
5023
+ ) : null,
5024
+ isTaskDrawerCloseBlockerVisible ? /* @__PURE__ */ jsx17(
5025
+ "div",
5026
+ {
5027
+ "aria-hidden": "true",
5028
+ className: "absolute inset-0 z-20 bg-transparent",
5029
+ onClick: (event) => {
5030
+ event.preventDefault();
5031
+ event.stopPropagation();
5032
+ },
5033
+ onDoubleClick: (event) => {
5034
+ event.preventDefault();
5035
+ event.stopPropagation();
5036
+ },
5037
+ onPointerDown: (event) => {
5038
+ event.preventDefault();
5039
+ event.stopPropagation();
5040
+ },
5041
+ onPointerUp: (event) => {
5042
+ event.preventDefault();
5043
+ event.stopPropagation();
5044
+ }
5045
+ }
5046
+ ) : null
5047
+ ]
5048
+ }
5049
+ )
4586
5050
  ]
4587
5051
  }
4588
5052
  );
@@ -4944,6 +5408,7 @@ function IssueManagerTopicDialog({
4944
5408
  // src/ui/IssueManagerNode.tsx
4945
5409
  import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
4946
5410
  function IssueManagerNode({
5411
+ diagnostics,
4947
5412
  emptyIllustration,
4948
5413
  feature,
4949
5414
  nodeId,
@@ -4951,30 +5416,53 @@ function IssueManagerNode({
4951
5416
  openRequest,
4952
5417
  onStateChange,
4953
5418
  renderLatestRunStatus,
4954
- resolveRichTextAtProviders,
5419
+ resolveRichTextTriggerProviders,
4955
5420
  service,
4956
5421
  state,
4957
5422
  workspaceId
4958
5423
  }) {
4959
5424
  const { controller, referencePicker, selectedIssue, selectedTask, shell } = useIssueManagerNodeView({
5425
+ diagnostics,
4960
5426
  feature,
4961
5427
  nodeId,
4962
5428
  openSource,
4963
5429
  onStateChange,
4964
- resolveRichTextAtProviders,
5430
+ resolveRichTextTriggerProviders,
4965
5431
  service,
4966
5432
  state,
4967
5433
  workspaceId
4968
5434
  });
4969
- const lastHandledOpenRequestIdRef = useRef5(null);
5435
+ const lastHandledOpenRequestIdRef = useRef7(null);
4970
5436
  useEffect9(() => {
4971
5437
  if (!openRequest?.requestId) {
4972
5438
  return;
4973
5439
  }
4974
5440
  if (lastHandledOpenRequestIdRef.current === openRequest.requestId) {
5441
+ logIssueManagerDiagnostic(
5442
+ controller.diagnostics,
5443
+ "open_request.skipped_duplicate",
5444
+ {
5445
+ issueId: openRequest.issueId,
5446
+ requestId: openRequest.requestId,
5447
+ taskId: openRequest.taskId?.trim() || null,
5448
+ topicId: openRequest.topicId?.trim() || null
5449
+ }
5450
+ );
4975
5451
  return;
4976
5452
  }
4977
5453
  lastHandledOpenRequestIdRef.current = openRequest.requestId;
5454
+ logIssueManagerDiagnostic(
5455
+ controller.diagnostics,
5456
+ "open_request.consumed",
5457
+ {
5458
+ issueId: openRequest.issueId,
5459
+ mode: openRequest.mode ?? null,
5460
+ requestId: openRequest.requestId,
5461
+ taskId: openRequest.taskId?.trim() || null,
5462
+ topicId: openRequest.topicId?.trim() || null
5463
+ },
5464
+ { includeStack: true }
5465
+ );
4978
5466
  if (openRequest.topicId?.trim()) {
4979
5467
  controller.selectTopic(openRequest.topicId);
4980
5468
  }
@@ -5165,4 +5653,4 @@ export {
5165
5653
  IssueManagerNode,
5166
5654
  IssueManagerNodeHeader
5167
5655
  };
5168
- //# sourceMappingURL=chunk-XC4FNAHC.js.map
5656
+ //# sourceMappingURL=chunk-JOEMRSA4.js.map