github-issue-tower-defence-management 1.99.1 → 1.101.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 (35) hide show
  1. package/.github/workflows/close-manual-prs.yml +49 -15
  2. package/.github/workflows/umino-project.yml +1 -3
  3. package/CHANGELOG.md +14 -0
  4. package/bin/adapter/entry-points/console/ui-dist/assets/index-DP5DGKUj.js +101 -0
  5. package/bin/adapter/entry-points/console/ui-dist/assets/{index-N39d52Zc.css → index-ES6SLB1Y.css} +1 -1
  6. package/bin/adapter/entry-points/console/ui-dist/index.html +2 -2
  7. package/bin/domain/usecases/console/GenerateConsoleListsUseCase.js +4 -0
  8. package/bin/domain/usecases/console/GenerateConsoleListsUseCase.js.map +1 -1
  9. package/package.json +1 -1
  10. package/src/adapter/entry-points/console/ui/e2e/consoleTestHarness.ts +12 -0
  11. package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleItemList.test.tsx +12 -3
  12. package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleItemSummary.stories.tsx +4 -0
  13. package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleItemSummary.test.tsx +48 -0
  14. package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleItemSummary.tsx +40 -0
  15. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleItemDetailData.test.ts +4 -0
  16. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleNavigation.test.ts +87 -5
  17. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleNavigation.ts +21 -4
  18. package/src/adapter/entry-points/console/ui/src/features/console/logic/grouping.test.ts +4 -0
  19. package/src/adapter/entry-points/console/ui/src/features/console/logic/overlay.test.ts +4 -0
  20. package/src/adapter/entry-points/console/ui/src/features/console/logic/tabAdvance.test.ts +33 -1
  21. package/src/adapter/entry-points/console/ui/src/features/console/logic/tabAdvance.ts +11 -0
  22. package/src/adapter/entry-points/console/ui/src/features/console/logic/types.ts +4 -0
  23. package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsolePage.test.tsx +58 -15
  24. package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsolePage.tsx +9 -8
  25. package/src/adapter/entry-points/console/ui/src/features/console/testing/fixtures.ts +22 -0
  26. package/src/adapter/entry-points/console/ui/src/index.css +24 -0
  27. package/src/adapter/entry-points/console/ui-dist/assets/index-DP5DGKUj.js +101 -0
  28. package/src/adapter/entry-points/console/ui-dist/assets/{index-N39d52Zc.css → index-ES6SLB1Y.css} +1 -1
  29. package/src/adapter/entry-points/console/ui-dist/index.html +2 -2
  30. package/src/domain/usecases/console/GenerateConsoleListsUseCase.test.ts +43 -0
  31. package/src/domain/usecases/console/GenerateConsoleListsUseCase.ts +9 -0
  32. package/types/domain/usecases/console/GenerateConsoleListsUseCase.d.ts +4 -0
  33. package/types/domain/usecases/console/GenerateConsoleListsUseCase.d.ts.map +1 -1
  34. package/bin/adapter/entry-points/console/ui-dist/assets/index-D79mM9lz.js +0 -101
  35. package/src/adapter/entry-points/console/ui-dist/assets/index-D79mM9lz.js +0 -101
@@ -1,6 +1,20 @@
1
- import { act, fireEvent, render, waitFor } from '@testing-library/react';
1
+ import {
2
+ act,
3
+ fireEvent,
4
+ render,
5
+ waitFor,
6
+ within,
7
+ } from '@testing-library/react';
2
8
  import { ConsolePage } from './ConsolePage';
3
9
 
10
+ const tabBar = (): HTMLElement => {
11
+ const nav = document.querySelector('nav.console-tabbar');
12
+ if (nav === null) {
13
+ throw new Error('console tab bar not found');
14
+ }
15
+ return nav as HTMLElement;
16
+ };
17
+
4
18
  jest.mock('../lib/mermaidLoader', () => ({
5
19
  renderMermaidToSvg: jest.fn(async () => '<svg></svg>'),
6
20
  }));
@@ -24,6 +38,10 @@ const listPayload = (tab: string) => ({
24
38
  itemId: 'PVTI_1',
25
39
  isPr: true,
26
40
  story: 'TDPM Console port',
41
+ status: 'Awaiting Quality Check',
42
+ nextActionDate: null,
43
+ nextActionHour: null,
44
+ dependedIssueUrls: [],
27
45
  labels: [],
28
46
  createdAt: '2026-06-17T00:00:00.000Z',
29
47
  },
@@ -40,6 +58,10 @@ const listPayload = (tab: string) => ({
40
58
  itemId: 'PVTI_2',
41
59
  isPr: false,
42
60
  story: 'TDPM Console port',
61
+ status: 'Unread',
62
+ nextActionDate: null,
63
+ nextActionHour: null,
64
+ dependedIssueUrls: [],
43
65
  labels: [],
44
66
  createdAt: '2026-06-18T00:00:00.000Z',
45
67
  },
@@ -74,8 +96,12 @@ describe('ConsolePage', () => {
74
96
  await waitFor(() => {
75
97
  expect(getByText('Add serveConsole subcommand')).toBeInTheDocument();
76
98
  });
77
- expect(getByText('Awaiting Quality Check')).toBeInTheDocument();
78
- expect(getByText('TDPM Console port')).toBeInTheDocument();
99
+ expect(
100
+ within(tabBar()).getByText('Awaiting Quality Check'),
101
+ ).toBeInTheDocument();
102
+ expect(
103
+ document.querySelector('.console-group-header')?.textContent,
104
+ ).toContain('TDPM Console port');
79
105
  });
80
106
 
81
107
  it('opens the detail view when an item is selected', async () => {
@@ -100,12 +126,13 @@ describe('ConsolePage', () => {
100
126
  it('shows a cancellable toast and only drives the tab to zero after the five second window', async () => {
101
127
  jest.useFakeTimers();
102
128
  try {
103
- const { getByText, findByText, queryByText } = render(<ConsolePage />);
129
+ const { getByText, findByText } = render(<ConsolePage />);
104
130
  await waitFor(() => {
105
131
  expect(getByText('Add serveConsole subcommand')).toBeInTheDocument();
106
132
  });
107
133
  expect(
108
- getByText('Awaiting Quality Check')
134
+ within(tabBar())
135
+ .getByText('Awaiting Quality Check')
109
136
  .closest('a')
110
137
  ?.querySelector('.console-tab-badge')?.textContent,
111
138
  ).toBe('1');
@@ -117,7 +144,8 @@ describe('ConsolePage', () => {
117
144
  expect(getByText('Approved — PR #851')).toBeInTheDocument();
118
145
  expect(getByText('Undo')).toBeInTheDocument();
119
146
  expect(
120
- getByText('Awaiting Quality Check')
147
+ within(tabBar())
148
+ .getByText('Awaiting Quality Check')
121
149
  .closest('a')
122
150
  ?.querySelector('.console-tab-badge')?.textContent,
123
151
  ).toBe('1');
@@ -127,7 +155,9 @@ describe('ConsolePage', () => {
127
155
  });
128
156
 
129
157
  await waitFor(() => {
130
- expect(queryByText('Awaiting Quality Check')).toBeNull();
158
+ expect(
159
+ within(tabBar()).queryByText('Awaiting Quality Check'),
160
+ ).toBeNull();
131
161
  });
132
162
  } finally {
133
163
  jest.useRealTimers();
@@ -177,7 +207,8 @@ describe('ConsolePage', () => {
177
207
  );
178
208
  expect(postCalls.length).toBe(0);
179
209
  expect(
180
- getByText('Awaiting Quality Check')
210
+ within(tabBar())
211
+ .getByText('Awaiting Quality Check')
181
212
  .closest('a')
182
213
  ?.querySelector('.console-tab-badge')?.textContent,
183
214
  ).toBe('1');
@@ -203,15 +234,16 @@ describe('ConsolePage', () => {
203
234
  });
204
235
 
205
236
  it('hides zero-count tabs but keeps non-zero tabs', async () => {
206
- const { getByText, queryByText } = render(<ConsolePage />);
237
+ const { getByText } = render(<ConsolePage />);
207
238
  await waitFor(() => {
208
239
  expect(getByText('Add serveConsole subcommand')).toBeInTheDocument();
209
240
  });
210
- expect(queryByText('Awaiting Quality Check')).not.toBeNull();
211
- expect(queryByText('Unread')).not.toBeNull();
212
- expect(queryByText('Triage')).toBeNull();
213
- expect(queryByText('Failed Preparation')).toBeNull();
214
- expect(queryByText('Todo by human')).toBeNull();
241
+ const tabs = within(tabBar());
242
+ expect(tabs.queryByText('Awaiting Quality Check')).not.toBeNull();
243
+ expect(tabs.queryByText('Unread')).not.toBeNull();
244
+ expect(tabs.queryByText('Triage')).toBeNull();
245
+ expect(tabs.queryByText('Failed Preparation')).toBeNull();
246
+ expect(tabs.queryByText('Todo by human')).toBeNull();
215
247
  });
216
248
 
217
249
  it('does not render the project header bar above the tab bar', async () => {
@@ -241,6 +273,10 @@ const twoItemPrPayload = () => ({
241
273
  itemId: 'PVTI_1',
242
274
  isPr: true,
243
275
  story: 'TDPM Console port',
276
+ status: 'Awaiting Quality Check',
277
+ nextActionDate: null,
278
+ nextActionHour: null,
279
+ dependedIssueUrls: [],
244
280
  labels: [],
245
281
  createdAt: '2026-06-17T00:00:00.000Z',
246
282
  },
@@ -254,6 +290,10 @@ const twoItemPrPayload = () => ({
254
290
  itemId: 'PVTI_2',
255
291
  isPr: true,
256
292
  story: 'TDPM Console port',
293
+ status: 'Awaiting Quality Check',
294
+ nextActionDate: null,
295
+ nextActionHour: null,
296
+ dependedIssueUrls: [],
257
297
  labels: [],
258
298
  createdAt: '2026-06-17T01:00:00.000Z',
259
299
  },
@@ -422,7 +462,10 @@ describe('ConsolePage auto-advance tab', () => {
422
462
  ).toBeInTheDocument();
423
463
  });
424
464
  expect(
425
- getByText('Unread').closest('a')?.getAttribute('aria-current'),
465
+ within(tabBar())
466
+ .getByText('Unread')
467
+ .closest('a')
468
+ ?.getAttribute('aria-current'),
426
469
  ).toBe('page');
427
470
  } finally {
428
471
  jest.useRealTimers();
@@ -52,15 +52,7 @@ const OVERLAY_NAMESPACE_FALLBACK = 'console';
52
52
  export const ConsolePage = () => {
53
53
  const pjcode = useConsolePjcode();
54
54
  const { snapshots, isLoading, error } = useConsoleTabData(pjcode);
55
- const navigation = useConsoleNavigation(pjcode);
56
- const { activeTab, selectedItemKey, openItem, closeItem, selectTab } =
57
- navigation;
58
-
59
55
  const overlayState = useConsoleOverlay(pjcode ?? OVERLAY_NAMESPACE_FALLBACK);
60
- const caches = useConsoleCaches();
61
- const operations = useConsoleOperations(pjcode, activeTab, overlayState);
62
- const actionQueue = useConsoleActionQueue();
63
- const now = Date.now();
64
56
 
65
57
  const counts = useMemo(() => {
66
58
  const result = emptyCounts();
@@ -77,6 +69,15 @@ export const ConsolePage = () => {
77
69
  return result;
78
70
  }, [snapshots, overlayState.overlay]);
79
71
 
72
+ const navigation = useConsoleNavigation(pjcode, counts);
73
+ const { activeTab, selectedItemKey, openItem, closeItem, selectTab } =
74
+ navigation;
75
+
76
+ const caches = useConsoleCaches();
77
+ const operations = useConsoleOperations(pjcode, activeTab, overlayState);
78
+ const actionQueue = useConsoleActionQueue();
79
+ const now = Date.now();
80
+
80
81
  const activeSnapshot = snapshots[activeTab];
81
82
  const pendingItems = useMemo(() => {
82
83
  if (activeSnapshot === null) {
@@ -56,6 +56,12 @@ export const consoleListItemsFixture: ConsoleListItem[] = [
56
56
  itemId: 'PVTI_lADOABCD1234zgABCD01',
57
57
  isPr: true,
58
58
  story: 'TDPM Console port',
59
+ status: 'Awaiting Quality Check',
60
+ nextActionDate: null,
61
+ nextActionHour: null,
62
+ dependedIssueUrls: [
63
+ 'https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/issues/845',
64
+ ],
59
65
  labels: ['claude'],
60
66
  createdAt: '2026-06-17T02:14:33.000Z',
61
67
  },
@@ -71,6 +77,10 @@ export const consoleListItemsFixture: ConsoleListItem[] = [
71
77
  itemId: 'PVTI_lADOABCD1234zgABCD02',
72
78
  isPr: true,
73
79
  story: 'TDPM Console port',
80
+ status: 'Preparation',
81
+ nextActionDate: null,
82
+ nextActionHour: null,
83
+ dependedIssueUrls: [],
74
84
  labels: ['claude'],
75
85
  createdAt: '2026-06-17T05:48:09.000Z',
76
86
  },
@@ -85,6 +95,10 @@ export const consoleListItemsFixture: ConsoleListItem[] = [
85
95
  itemId: 'PVTI_lADOABCD1234zgABCD03',
86
96
  isPr: false,
87
97
  story: 'TDPM Console port',
98
+ status: 'Todo by human',
99
+ nextActionDate: '2026-06-20T07:00:00.000Z',
100
+ nextActionHour: 9,
101
+ dependedIssueUrls: [],
88
102
  labels: [],
89
103
  createdAt: '2026-06-16T22:01:55.000Z',
90
104
  },
@@ -99,6 +113,10 @@ export const consoleListItemsFixture: ConsoleListItem[] = [
99
113
  itemId: 'PVTI_lADOABCD1234zgABCD04',
100
114
  isPr: false,
101
115
  story: 'regular / workflow improvement',
116
+ status: null,
117
+ nextActionDate: null,
118
+ nextActionHour: 14,
119
+ dependedIssueUrls: [],
102
120
  labels: [],
103
121
  createdAt: '2026-06-12T23:01:55.000Z',
104
122
  },
@@ -113,6 +131,10 @@ export const consoleListItemsFixture: ConsoleListItem[] = [
113
131
  itemId: 'PVTI_lADOABCD1234zgABCD05',
114
132
  isPr: false,
115
133
  story: 'Publish product documentation site',
134
+ status: 'Icebox',
135
+ nextActionDate: null,
136
+ nextActionHour: null,
137
+ dependedIssueUrls: [],
116
138
  labels: ['documentation'],
117
139
  createdAt: '2026-06-10T11:42:00.000Z',
118
140
  },
@@ -212,6 +212,30 @@ body {
212
212
  cursor: help;
213
213
  }
214
214
 
215
+ .console-item-fields {
216
+ display: flex;
217
+ flex-wrap: wrap;
218
+ gap: 4px 10px;
219
+ margin-top: 4px;
220
+ font-size: 11.5px;
221
+ color: #adbac7;
222
+ }
223
+
224
+ .console-item-field {
225
+ display: inline-flex;
226
+ align-items: baseline;
227
+ gap: 4px;
228
+ min-width: 0;
229
+ word-break: break-all;
230
+ }
231
+
232
+ .console-item-field-label {
233
+ color: #6e7681;
234
+ font-size: 10px;
235
+ text-transform: uppercase;
236
+ letter-spacing: 0.03em;
237
+ }
238
+
215
239
  .console-list-message {
216
240
  padding: 16px;
217
241
  color: #8b949e;