github-issue-tower-defence-management 1.103.0 → 1.104.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 (47) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/bin/adapter/entry-points/console/ui-dist/assets/{index-CP3-MdUU.js → index-BpccigBS.js} +1 -1
  3. package/bin/adapter/entry-points/console/ui-dist/index.html +1 -1
  4. package/bin/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.js +8 -1
  5. package/bin/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.js.map +1 -1
  6. package/bin/adapter/repositories/issue/GraphqlProjectItemRepository.js +16 -0
  7. package/bin/adapter/repositories/issue/GraphqlProjectItemRepository.js.map +1 -1
  8. package/bin/domain/usecases/SetDependedIssueUrlForOpenTaskPRsUseCase.js +30 -4
  9. package/bin/domain/usecases/SetDependedIssueUrlForOpenTaskPRsUseCase.js.map +1 -1
  10. package/package.json +1 -1
  11. package/src/adapter/entry-points/console/ui/e2e/consoleTestHarness.ts +1 -0
  12. package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsoleErrorToast.stories.tsx +2 -2
  13. package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsoleUndoToast.test.tsx +4 -4
  14. package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsolePage.test.tsx +55 -0
  15. package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsolePage.tsx +1 -1
  16. package/src/adapter/entry-points/console/ui-dist/assets/{index-CP3-MdUU.js → index-BpccigBS.js} +1 -1
  17. package/src/adapter/entry-points/console/ui-dist/index.html +1 -1
  18. package/src/adapter/entry-points/handlers/InTmuxByHumanSessionTokenCountHandler.test.ts +1 -0
  19. package/src/adapter/entry-points/handlers/inTmuxByHumanDataWriter.test.ts +1 -0
  20. package/src/adapter/entry-points/handlers/inTmuxByHumanSessionReconciler.test.ts +1 -0
  21. package/src/adapter/entry-points/handlers/situationFileWriter.test.ts +1 -0
  22. package/src/adapter/repositories/GitHubIssueCommentRepository.test.ts +1 -0
  23. package/src/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.test.ts +9 -0
  24. package/src/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.ts +10 -0
  25. package/src/adapter/repositories/issue/GraphqlProjectItemRepository.ts +24 -0
  26. package/src/adapter/repositories/issue/RestIssueRepository.test.ts +1 -0
  27. package/src/domain/entities/Issue.ts +1 -0
  28. package/src/domain/usecases/CheckIssueReviewReadinessUseCase.test.ts +1 -0
  29. package/src/domain/usecases/GetStoryObjectMapUseCase.test.ts +1 -0
  30. package/src/domain/usecases/InTmuxByHumanSessionTokenCountUseCase.test.ts +1 -0
  31. package/src/domain/usecases/NotifyFinishedIssuePreparationUseCase.test.ts +1 -0
  32. package/src/domain/usecases/RevertNotReadyReviewQueueIssueUseCase.test.ts +1 -0
  33. package/src/domain/usecases/RevertOrphanedPreparationUseCase.test.ts +1 -0
  34. package/src/domain/usecases/SetDependedIssueUrlForOpenTaskPRsUseCase.test.ts +148 -115
  35. package/src/domain/usecases/SetDependedIssueUrlForOpenTaskPRsUseCase.ts +35 -10
  36. package/src/domain/usecases/SetupTowerDefenceProjectUseCase.test.ts +1 -0
  37. package/src/domain/usecases/StartPreparationUseCase.test.ts +1 -0
  38. package/src/domain/usecases/console/GenerateConsoleListsUseCase.test.ts +1 -0
  39. package/src/domain/usecases/intmux/GenerateInTmuxByHumanDataUseCase.test.ts +1 -0
  40. package/src/domain/usecases/intmux/InTmuxByHumanSessionReconcileUseCase.test.ts +1 -0
  41. package/types/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.d.ts.map +1 -1
  42. package/types/adapter/repositories/issue/GraphqlProjectItemRepository.d.ts +1 -0
  43. package/types/adapter/repositories/issue/GraphqlProjectItemRepository.d.ts.map +1 -1
  44. package/types/domain/entities/Issue.d.ts +1 -0
  45. package/types/domain/entities/Issue.d.ts.map +1 -1
  46. package/types/domain/usecases/SetDependedIssueUrlForOpenTaskPRsUseCase.d.ts +3 -2
  47. package/types/domain/usecases/SetDependedIssueUrlForOpenTaskPRsUseCase.d.ts.map +1 -1
@@ -254,6 +254,61 @@ describe('ConsolePage', () => {
254
254
  expect(queryByText('TDPM Console')).toBeNull();
255
255
  expect(queryByText('project: umino')).toBeNull();
256
256
  });
257
+
258
+ it('renders the failure toast in English without any Japanese characters', async () => {
259
+ const fetchMock = jest.fn(
260
+ async (url: string, init?: { method?: string }) => {
261
+ const listMatch = url.match(/\/projects\/[^/]+\/([^/]+)\/list\.json/);
262
+ if (listMatch !== null) {
263
+ return {
264
+ ok: true,
265
+ status: 200,
266
+ json: async () => listPayload(listMatch[1]),
267
+ };
268
+ }
269
+ if (init?.method === 'POST') {
270
+ return {
271
+ ok: false,
272
+ status: 422,
273
+ text: async () =>
274
+ JSON.stringify({ error: 'HTTP 422 Review cannot be requested' }),
275
+ };
276
+ }
277
+ return {
278
+ ok: true,
279
+ status: 200,
280
+ json: async () => ({ body: '# body' }),
281
+ };
282
+ },
283
+ );
284
+ global.fetch = fetchMock as unknown as typeof fetch;
285
+
286
+ jest.useFakeTimers();
287
+ try {
288
+ const { getByText, findByText } = render(<ConsolePage />);
289
+ await waitFor(() => {
290
+ expect(getByText('Add serveConsole subcommand')).toBeInTheDocument();
291
+ });
292
+ fireEvent.click(getByText('Add serveConsole subcommand'));
293
+ fireEvent.click(await findByText('Approve'));
294
+
295
+ await act(async () => {
296
+ jest.advanceTimersByTime(5100);
297
+ await Promise.resolve();
298
+ await Promise.resolve();
299
+ });
300
+
301
+ const toast = getByText(/^Operation failed:/);
302
+ expect(toast.textContent).toBe(
303
+ 'Operation failed: HTTP 422 Review cannot be requested',
304
+ );
305
+ expect(toast.textContent).not.toMatch(
306
+ /[\u{3040}-\u{309F}\u{30A0}-\u{30FF}\u{4E00}-\u{9FFF}]/u,
307
+ );
308
+ } finally {
309
+ jest.useRealTimers();
310
+ }
311
+ });
257
312
  });
258
313
 
259
314
  const twoItemPrPayload = () => ({
@@ -208,7 +208,7 @@ export const ConsolePage = () => {
208
208
  )}
209
209
  {actionQueue.error !== null && (
210
210
  <ConsoleErrorToast
211
- message={`操作に失敗しました: ${actionQueue.error.reason}`}
211
+ message={`Operation failed: ${actionQueue.error.reason}`}
212
212
  onDismiss={actionQueue.dismissError}
213
213
  />
214
214
  )}
@@ -98,4 +98,4 @@ Please report this to https://github.com/markedjs/marked.`,u){const f="<p>An err
98
98
  `)}),d+=1,s=[])};for(const S of u){if(f===null&&/^```mermaid\s*$/.test(S.trim())){h(),f=[];continue}if(f!==null){if(S.trim()==="```"){c.push({kind:"mermaid",key:`mermaid:${d}`,code:f.join(`
99
99
  `)}),d+=1,f=null;continue}f.push(S);continue}s.push(S)}return f!==null&&s.push("```mermaid",...f),h(),c},b0="https://cdn.jsdelivr.net/npm/mermaid@10.9.6/dist/mermaid.min.js";let ci=null,Vh=0;const Kh=o=>(o.initialize({startOnLoad:!1,securityLevel:"strict",theme:"dark",themeVariables:{background:"#0d1117",primaryColor:"#161b22",primaryTextColor:"#e6edf3",primaryBorderColor:"#30363d",lineColor:"#8b949e",fontSize:"14px"}}),o),v0=()=>ci!==null?ci:window.mermaid!==void 0?(ci=Promise.resolve(Kh(window.mermaid)),ci):(ci=new Promise((o,u)=>{const c=document.createElement("script");c.src=b0,c.async=!0,c.onload=()=>{if(window.mermaid===void 0){u(new Error("mermaid failed to load"));return}o(Kh(window.mermaid))},c.onerror=()=>u(new Error("mermaid script failed to load")),document.head.appendChild(c)}),ci),S0=async o=>{const u=await v0();Vh+=1;const c=`console-mermaid-${Vh}`,{svg:s}=await u.render(c,o);return op.sanitize(s,{USE_PROFILES:{svg:!0,svgFilters:!0},ADD_TAGS:["foreignObject"]})},T0=({code:o})=>{const[u,c]=Y.useState({status:"loading"}),s=Y.useRef(null);return Y.useEffect(()=>{let f=!1;return c({status:"loading"}),S0(o).then(d=>{f||c({status:"ready",svg:d})}).catch(d=>{f||c({status:"error",message:d instanceof Error?d.message:String(d)})}),()=>{f=!0}},[o]),Y.useEffect(()=>{const f=s.current;f!==null&&(f.innerHTML=u.status==="ready"?u.svg:"")},[u]),u.status==="loading"?v.jsx("div",{className:"console-mermaid-loading",children:"Rendering diagram..."}):u.status==="error"?v.jsxs("div",{className:"console-mermaid",children:[v.jsxs("div",{className:"console-mermaid-error",children:["Mermaid render error: ",u.message]}),v.jsx("pre",{className:"console-mermaid-source",children:v.jsx("code",{children:o})})]}):v.jsx("div",{ref:s,className:"console-mermaid-rendered"})},E0=({source:o,buildImageProxyUrl:u})=>{const c=Y.useMemo(()=>{const f=_0(o);return u===void 0?f:Py(f,u)},[o,u]),s=Y.useRef(null);return Y.useEffect(()=>{const f=s.current;f!==null&&(f.innerHTML=c)},[c]),v.jsx("div",{ref:s,className:"console-markdown"})},Is=({body:o,buildImageProxyUrl:u})=>{const c=Y.useMemo(()=>y0(o),[o]);return o.trim()===""?v.jsx("p",{className:"console-markdown-empty",children:"No description provided."}):v.jsx("div",{className:"console-markdown-view",children:c.map(s=>s.kind==="mermaid"?v.jsx(T0,{code:s.code},s.key):v.jsx(E0,{source:s.source,buildImageProxyUrl:u},s.key))})},A0=({isPr:o,now:u,onSubmit:c})=>{const[s,f]=Y.useState(!o),[d,h]=Y.useState(""),[S,g]=Y.useState({kind:"idle"}),[_,O]=Y.useState([]),z=async()=>{const C=d.trim();if(!(C.length===0||S.kind==="posting")){g({kind:"posting"});try{const G=await c(C);O(H=>[...H,G]),h(""),g({kind:"idle"})}catch(G){g({kind:"error",message:G instanceof Error?G.message:"failed to post"})}}};return v.jsxs("div",{className:"console-composer",children:[v.jsx("button",{type:"button",className:"console-composer-toggle","aria-expanded":s,onClick:()=>f(C=>!C),children:s?"✕ Cancel":"💬 Add a comment"}),_.length>0&&v.jsx("div",{className:"console-composer-posted",children:_.map(C=>v.jsxs("article",{className:"console-comment",children:[v.jsxs("header",{className:"console-comment-header",title:vr(C.createdAt),children:[v.jsx("span",{className:"console-comment-author",children:C.author===""?"you":C.author}),v.jsx("span",{className:"console-comment-time",children:yu(C.createdAt,u)})]}),v.jsx(Is,{body:C.body})]},`${C.author}:${C.createdAt}:${C.body}`))}),s&&v.jsxs("div",{className:"console-composer-form",children:[v.jsx("textarea",{className:"console-composer-input",rows:3,placeholder:"Leave a comment…",value:d,onChange:C=>h(C.target.value)}),v.jsxs("div",{className:"console-composer-row",children:[v.jsx("button",{type:"button",className:"console-composer-submit",disabled:S.kind==="posting",onClick:()=>{z()},children:"Comment"}),S.kind==="posting"&&v.jsx("span",{className:"console-composer-status",children:"Posting…"}),S.kind==="error"&&v.jsxs("span",{role:"alert",className:"console-composer-status console-composer-error",children:["Failed: ",S.message]})]})]})]})},ra=({title:o,count:u=null,defaultCollapsed:c=!1,headerAction:s,children:f})=>{const[d,h]=Y.useState(c),S=u===null?o:`${o} (${u})`;return v.jsxs("section",{className:"console-panel",children:[v.jsxs("header",{className:"console-panel-header",children:[v.jsxs("button",{type:"button",className:"console-panel-toggle","aria-expanded":!d,onClick:()=>h(g=>!g),children:[v.jsx("span",{className:"console-panel-caret",children:d?"▸":"▾"}),v.jsx("span",{className:"console-panel-title",children:S})]}),s!==void 0&&v.jsx("div",{className:"console-panel-action",children:s})]}),!d&&v.jsx("div",{className:"console-panel-body",children:f})]})},w0=o=>{switch(o){case"added":return{label:"A",color:"#3fb950"};case"modified":return{label:"M",color:"#d29922"};case"removed":return{label:"D",color:"#f85149"};case"renamed":return{label:"R",color:"#a371f7"};case"changed":return{label:"M",color:"#d29922"};default:return{label:"?",color:"#8b949e"}}},x0=/^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/,N0=o=>{const u=[];let c=0,s=0;for(const f of o.split(`
100
100
  `)){if(f.startsWith("@@")){const d=f.match(x0);d!==null&&(c=Number(d[1]),s=Number(d[2])),u.push({kind:"hunk",oldLineNumber:null,newLineNumber:null,content:f});continue}if(f.startsWith("+")){u.push({kind:"add",oldLineNumber:null,newLineNumber:s,content:f}),s+=1;continue}if(f.startsWith("-")){u.push({kind:"del",oldLineNumber:c,newLineNumber:null,content:f}),c+=1;continue}u.push({kind:"ctx",oldLineNumber:c,newLineNumber:s,content:f}),c+=1,s+=1}return u},z0=o=>o.kind==="add"||o.kind==="ctx"?o.newLineNumber===null?null:{line:o.newLineNumber,side:"RIGHT"}:o.kind==="del"?o.oldLineNumber===null?null:{line:o.oldLineNumber,side:"LEFT"}:null,O0=o=>`${o.kind}:${o.oldLineNumber??"x"}:${o.newLineNumber??"x"}:${o.content}`,k0=({target:o,onSubmit:u,onClose:c})=>{const[s,f]=Y.useState(""),[d,h]=Y.useState({kind:"idle"}),S=async()=>{const g=s.trim();if(!(g.length===0||d.kind==="posting")){h({kind:"posting"});try{await u(o.path,o.line,o.side,g),f(""),h({kind:"posted"})}catch(_){h({kind:"error",message:_ instanceof Error?_.message:"failed to post"})}}};return v.jsxs("div",{className:"console-diff-composer",children:[v.jsxs("div",{className:"console-diff-composer-anchor",children:["commenting on line ",o.line," (",o.side,")"]}),d.kind==="posted"?v.jsx("p",{className:"console-diff-composer-posted",children:"Comment posted."}):v.jsxs(v.Fragment,{children:[v.jsx("textarea",{className:"console-diff-composer-input",rows:3,placeholder:"Leave a review comment on this line…",value:s,onChange:g=>f(g.target.value)}),v.jsxs("div",{className:"console-diff-composer-controls",children:[v.jsx("button",{type:"button",className:"console-diff-composer-submit",disabled:d.kind==="posting",onClick:()=>{S()},children:"Comment"}),v.jsx("button",{type:"button",className:"console-diff-composer-cancel",onClick:c,children:"Cancel"}),d.kind==="posting"&&v.jsx("span",{className:"console-diff-composer-status",children:"Posting…"}),d.kind==="error"&&v.jsxs("span",{role:"alert",className:"console-diff-composer-status console-diff-composer-error",children:["Failed: ",d.message]})]})]})]})},R0=({patch:o,path:u,onAddInlineComment:c})=>{const[s,f]=Y.useState(null);if(o===null||o==="")return v.jsx("p",{className:"console-file-diff-empty",children:"(no diff / binary or too large)"});const d=N0(o),h=c!==void 0&&u!==void 0&&u.length>0,S=h?4:3;return v.jsx("table",{className:"console-file-diff",children:v.jsx("tbody",{children:d.map(g=>{const _=O0(g),O=h?z0(g):null,z=s!==null&&O!==null&&s.line===O.line&&s.side===O.side;return v.jsxs(Y.Fragment,{children:[v.jsxs("tr",{className:`console-diff-row console-diff-${g.kind}`,children:[h&&v.jsx("td",{className:"console-diff-comment-cell",children:O!==null&&u!==void 0&&v.jsx("button",{type:"button",className:"console-diff-comment-button","aria-label":`Comment on line ${O.line} (${O.side})`,"aria-expanded":z,onClick:()=>f(z?null:{path:u,line:O.line,side:O.side}),children:"+"})}),v.jsx("td",{className:"console-diff-ln",children:g.oldLineNumber??""}),v.jsx("td",{className:"console-diff-ln",children:g.newLineNumber??""}),v.jsx("td",{className:"console-diff-code",children:g.content})]}),z&&c!==void 0&&s!==null&&v.jsx("tr",{className:"console-diff-composer-row",children:v.jsx("td",{colSpan:S,children:v.jsx(k0,{target:s,onSubmit:c,onClose:()=>f(null)})})})]},_)})})})},C0=({file:o,onAddInlineComment:u})=>{const[c,s]=Y.useState(!1),f=w0(o.status);return v.jsxs("li",{className:"console-file",children:[v.jsxs("button",{type:"button",className:"console-file-row","aria-expanded":c,onClick:()=>s(d=>!d),children:[v.jsx("span",{className:"console-file-caret",children:c?"▾":"▸"}),v.jsx("span",{className:"console-file-badge",style:{color:f.color,borderColor:f.color},children:f.label}),v.jsx("span",{className:"console-file-path",children:o.path}),v.jsxs("span",{className:"console-file-stat console-file-add",children:["+",o.additions]}),v.jsxs("span",{className:"console-file-stat console-file-del",children:["-",o.deletions]})]}),c&&v.jsx(R0,{patch:o.patch,path:o.path,onAddInlineComment:u})]})},vp=({files:o,isLoading:u,error:c,onAddInlineComment:s})=>c!==null?v.jsxs("p",{role:"alert",className:"console-files-error",children:["Failed to load changed files: ",c]}):u?v.jsx("p",{className:"console-files-loading",children:"Loading changed files..."}):o.length===0?v.jsx("p",{className:"console-files-empty",children:"No changed files."}):v.jsx("ul",{className:"console-files",children:o.map(f=>v.jsx(C0,{file:f,onAddInlineComment:s},f.path))}),M0=({comments:o,isLoading:u,error:c,now:s,buildImageProxyUrl:f})=>{const[d,h]=Y.useState(!1);if(c!==null)return v.jsxs("p",{role:"alert",className:"console-comment-error",children:["Failed to load comments: ",c]});if(u)return v.jsx("p",{className:"console-comment-loading",children:"Loading comments..."});if(o.length===0)return v.jsx("p",{className:"console-comment-empty",children:"No comments."});const S=d?o:o.slice(-1);return v.jsxs("div",{className:"console-comment-list",children:[!d&&o.length>1&&v.jsxs("button",{type:"button",className:"console-comment-show-all",onClick:()=>h(!0),children:["Show all ",o.length]}),S.map(g=>v.jsxs("article",{className:"console-comment",children:[v.jsxs("header",{className:"console-comment-header",children:[v.jsx("span",{className:"console-comment-author",children:g.author}),v.jsx("span",{className:"console-comment-time",children:yu(g.createdAt,s)})]}),v.jsx(Is,{body:g.body,buildImageProxyUrl:f})]},`${g.author}:${g.createdAt}:${g.body}`))]})},D0=o=>o.slice(0,7),j0=o=>o.split(`
101
- `)[0],Sp=({commits:o,isLoading:u,error:c,now:s})=>c!==null?v.jsxs("p",{role:"alert",className:"console-commits-error",children:["Failed to load commits: ",c]}):u?v.jsx("p",{className:"console-commits-loading",children:"Loading commits..."}):o.length===0?v.jsx("p",{className:"console-commits-empty",children:"No commits."}):v.jsx("ul",{className:"console-commits",children:o.map(f=>v.jsxs("li",{className:"console-commit",children:[v.jsx("span",{className:"console-commit-message",children:j0(f.message)}),v.jsx("span",{className:"console-commit-sha",children:D0(f.sha)}),v.jsx("span",{className:"console-commit-author",children:f.author}),v.jsx("span",{className:"console-commit-time",children:yu(f.authoredAt,s)})]},f.sha))}),U0=({pullRequest:o,body:u,bodyIsLoading:c,files:s,filesAreLoading:f,filesError:d,commits:h,commitsAreLoading:S,commitsError:g,now:_,buildImageProxyUrl:O})=>{const z=o.summary,C=f||d!==null?null:s.length,G=S||g!==null?null:h.length;return v.jsxs(v.Fragment,{children:[v.jsxs("div",{className:"console-pr-header",children:[v.jsx("a",{href:o.url,className:"console-pr-section-title",target:"_blank",rel:"noopener noreferrer",children:(z==null?void 0:z.title)??o.url}),o.isDraft&&v.jsx("span",{className:"console-pr-section-state",children:"draft"}),v.jsxs("div",{className:"console-pr-statbar",children:[o.branchName!==null&&v.jsx("span",{className:"console-pr-branch",children:o.branchName}),z!==null&&v.jsxs(v.Fragment,{children:[v.jsxs("span",{className:"console-pr-add",children:["+",z.additions]}),v.jsxs("span",{className:"console-pr-del",children:["-",z.deletions]}),v.jsxs("span",{className:"console-pr-files-count",children:[z.changedFiles," files"]})]})]})]}),v.jsx(ra,{title:"Description",defaultCollapsed:!0,children:c?v.jsx("p",{className:"console-pr-body-loading",children:"Loading description..."}):v.jsx(Is,{body:(z==null?void 0:z.body)??u,buildImageProxyUrl:O})}),v.jsx(ra,{title:"Changed files",count:C,children:v.jsx(vp,{files:s,isLoading:f,error:d})}),v.jsx(ra,{title:"Commits",count:G,defaultCollapsed:!0,children:v.jsx(Sp,{commits:h,isLoading:S,error:g,now:_})})]})},L0=({item:o,storyName:u,storyColorEnum:c,overlayStatus:s,state:f,body:d,bodyIsLoading:h,bodyError:S,comments:g,commentsAreLoading:_,commentsError:O,files:z,filesAreLoading:C,filesError:G,commits:H,commitsAreLoading:Q,commitsError:X,relatedPullRequests:ue,now:le,commentComposer:F,operationBar:ce,buildImageProxyUrl:ye,onAddInlineComment:ge})=>{const ee=(f==null?void 0:f.state)??"open",je=(f==null?void 0:f.merged)??!1,$e=!o.isPr&&ee==="closed"?"Closed":null,ht=_u(c),Pe=s?_u(s.color):null,qe=C||G!==null?null:z.length,kt=_||O!==null?null:g.length,xt=Q||X!==null?null:H.length;return v.jsxs("article",{className:"console-detail",children:[u!==null&&v.jsx("div",{className:"console-detail-story",children:v.jsxs("span",{className:"console-storytag",children:[v.jsx("span",{className:"console-story-dot",style:{backgroundColor:ht.dot}}),u]})}),s!==null&&Pe!==null&&v.jsx("span",{className:"console-detail-status-chip",style:{color:Pe.fg,borderColor:Pe.border,backgroundColor:Pe.bg},children:s.name}),v.jsxs("h2",{className:"console-detail-title",children:[v.jsx(Ph,{isPr:o.isPr,state:ee,merged:je,isDraft:!1,stateReason:""}),v.jsx("span",{className:"console-detail-title-text",children:o.title}),v.jsx("span",{className:"console-detail-number",children:o.isPr?`PR #${o.number}`:`#${o.number}`}),$e!==null&&v.jsx("span",{className:"console-detail-closed-label",children:$e})]}),v.jsxs("div",{className:"console-detail-subbar",children:[v.jsx("a",{href:o.url,className:"console-detail-link",target:"_blank",rel:"noopener noreferrer",children:o.isPr?`PR #${o.number}`:`Issue #${o.number}`}),v.jsx("span",{className:"console-detail-repo",children:o.repo}),v.jsx("span",{className:"console-detail-pill",children:o.isPr?"PR":"Issue"})]}),o.labels.length>0&&v.jsx("div",{className:"console-detail-labels",children:o.labels.map(Ae=>v.jsx("span",{className:"console-label-chip",children:Ae},Ae))}),v.jsxs("div",{className:"console-detail-createdat",title:vr(o.createdAt),children:["opened ",yu(o.createdAt,le)]}),v.jsx(ra,{title:"Description",headerAction:v.jsx("a",{href:o.url,className:"console-panel-open-link",target:"_blank",rel:"noopener noreferrer",children:"open"}),children:S!==null?v.jsxs("p",{role:"alert",className:"console-detail-body-error",children:["Failed to load description: ",S]}):h?v.jsx("p",{className:"console-detail-body-loading",children:"Loading description..."}):v.jsx(Is,{body:d,buildImageProxyUrl:ye})}),o.isPr&&v.jsx(ra,{title:"Changed files",count:qe,children:v.jsx(vp,{files:z,isLoading:C,error:G,onAddInlineComment:ge})}),v.jsx(ra,{title:"Comments",count:kt,defaultCollapsed:o.isPr,children:v.jsx(M0,{comments:g,isLoading:_,error:O,now:le,buildImageProxyUrl:ye})}),o.isPr&&v.jsx(ra,{title:"Commits",count:xt,defaultCollapsed:!0,children:v.jsx(Sp,{commits:H,isLoading:Q,error:X,now:le})}),!o.isPr&&ue.map(Ae=>{var R;return v.jsx(U0,{pullRequest:Ae.pullRequest,body:((R=Ae.pullRequest.summary)==null?void 0:R.body)??"",bodyIsLoading:!1,files:Ae.files,filesAreLoading:Ae.filesAreLoading,filesError:Ae.filesError,commits:Ae.commits,commitsAreLoading:Ae.commitsAreLoading,commitsError:Ae.commitsError,now:le,buildImageProxyUrl:ye},Ae.pullRequest.url)}),F,v.jsx("div",{className:"console-actionbar",children:ce})]})},H0=({onClose:o})=>v.jsxs("div",{className:"console-op-group",children:[v.jsx("button",{type:"button",className:"console-op-button",onClick:()=>o("close_not_planned"),children:"Close as not planned"}),v.jsx("button",{type:"button",className:"console-op-button",onClick:()=>o("close"),children:"Close"})]}),q0=({isTodoByHuman:o,onSetNextActionDate:u})=>v.jsxs("div",{className:"console-op-group",children:[v.jsx("button",{type:"button",className:"console-op-button console-op-button-snooze",onClick:()=>u("snooze_1day"),children:"+1 day"}),v.jsx("button",{type:"button",className:"console-op-button console-op-button-snooze",onClick:()=>u("snooze_1week"),children:o?"+1 week and skip":"+1 week"})]}),B0=[{action:"unnecessary",label:"Unnecessary",variant:"unneeded"},{action:"totally_wrong",label:"Totally wrong",variant:"wrong"},{action:"request_changes",label:"Reject",variant:"reject"},{action:"approve",label:"Approve",variant:"approve"}],Y0=({onReview:o})=>v.jsx("div",{className:"console-op-group console-op-group-review",children:B0.map(u=>v.jsx("button",{type:"button",className:`console-op-button console-op-button-${u.variant}`,onClick:()=>o(u.action),children:u.label},u.action))}),G0=(o,u)=>{const c=u.toLowerCase();return o.find(s=>s.name.toLowerCase()===c)??null},Z0=({statusOptions:o,onSetStatus:u,onSetInTmuxByHuman:c})=>{const s=Ty.map(f=>({name:f,option:G0(o,f)})).filter(f=>f.option!==null);return s.length===0?null:v.jsx("div",{className:"console-op-group",children:s.map(({name:f,option:d})=>{const h=_u(d.color),S=f===Ey;return v.jsx("button",{type:"button",className:"console-op-button",style:{color:h.fg,borderColor:h.border,backgroundColor:h.bg},onClick:()=>S?c(d):u(d),children:d.name},d.id)})})},X0=o=>o.name.toLowerCase().includes("no story"),Q0=({storyOptions:o,onSetStory:u})=>{const c=o.filter(s=>!X0(s));return c.length===0?null:v.jsx("div",{className:"console-op-group console-op-group-stories",children:c.map(s=>{const f=_u(s.color);return v.jsx("button",{type:"button",className:"console-op-button",style:{color:f.fg,borderColor:f.border,backgroundColor:f.bg},onClick:()=>u(s),children:s.name},s.id)})})},V0=({tab:o,item:u,hasPullRequest:c,statusOptions:s,storyOptions:f,handlers:d})=>{const h=o==="triage",S=o==="workflow-blocker"||!u.isPr;return v.jsxs("div",{className:"console-operation-bar",children:[c&&v.jsx(Y0,{onReview:d.onReview}),v.jsx(q0,{isTodoByHuman:Ay(o),onSetNextActionDate:d.onSetNextActionDate}),h&&v.jsx(Q0,{storyOptions:f,onSetStory:d.onSetStory}),v.jsx(Z0,{statusOptions:s,onSetStatus:d.onSetStatus,onSetInTmuxByHuman:d.onSetInTmuxByHuman}),S&&v.jsx(H0,{onClose:d.onClose})]})},ri=(o,u,c,s)=>{const f=u!==null?o.peek(u):void 0,[d,h]=Y.useState(f??s),[S,g]=Y.useState(u!==null&&f===void 0),[_,O]=Y.useState(null);return Y.useEffect(()=>{if(u===null||c===null)return;const z=o.peek(u);if(z!==void 0){h(z),g(!1),O(null);return}let C=!1;return g(!0),O(null),o.load(u,c).then(G=>{C||(h(G),g(!1))}).catch(G=>{C||(O(G instanceof Error?G.message:String(G)),g(!1))}),()=>{C=!0}},[o,u,c]),{data:d,isLoading:S,error:_}},K0=[],Jh=[],$h=[],J0=[],$0={state:"open",merged:!1,isPullRequest:!1},I0=(o,u)=>{const c=u!==null?`${u.repo}#${u.number}`:null,s=u!==null?u.url:null,f=(u==null?void 0:u.isPr)??!1,d=ri(o.body,c,s,""),h=ri(o.state,c,s,$0),S=ri(o.comments,c,s,K0),g=ri(o.files,f?c:null,f?s:null,Jh),_=ri(o.commits,f?c:null,f?s:null,$h),O=ri(o.relatedPrs,f?null:c,f?null:s,J0),[z,C]=Y.useState([]);return Y.useEffect(()=>{if(f||O.data.length===0){C([]);return}let G=!1;const H=O.data.map(X=>({pullRequest:X,files:Jh,filesAreLoading:!0,filesError:null,commits:$h,commitsAreLoading:!0,commitsError:null}));C(H);const Q=(X,ue)=>{G||C(le=>le.map(F=>F.pullRequest.url===X?{...F,...ue}:F))};for(const X of O.data){const ue=X.url;o.files.load(ue,X.url).then(le=>Q(X.url,{files:le,filesAreLoading:!1})).catch(le=>Q(X.url,{filesAreLoading:!1,filesError:le instanceof Error?le.message:String(le)})),o.commits.load(ue,X.url).then(le=>Q(X.url,{commits:le,commitsAreLoading:!1})).catch(le=>Q(X.url,{commitsAreLoading:!1,commitsError:le instanceof Error?le.message:String(le)}))}return()=>{G=!0}},[o,f,O.data]),{state:h.data,body:d.data,bodyIsLoading:d.isLoading,bodyError:d.error,comments:S.data,commentsAreLoading:S.isLoading,commentsError:S.error,files:g.data,filesAreLoading:g.isLoading,filesError:g.error,commits:_.data,commitsAreLoading:_.isLoading,commitsError:_.error,relatedPullRequests:z}},F0=({tab:o,item:u,caches:c,operations:s,statusOptions:f,storyOptions:d,storyColors:h,storyName:S,overlayStatus:g,now:_,onQueueAction:O})=>{const z=I0(c,u),{token:C}=Js(),G=Y.useCallback(F=>Wy(F,C),[C]),H=u.isPr||z.relatedPullRequests.length>0,Q=Y.useCallback((F,ce,ye,ge)=>s.addInlineReviewComment(u.url,F,ce,ye,ge),[s,u.url]),X={onReview:F=>{var ye;const ce=u.isPr?u.url:((ye=z.relatedPullRequests[0])==null?void 0:ye.pullRequest.url)??u.url;O({kind:{type:"review",action:F},item:u,commit:()=>s.reviewPullRequest(u,ce,F)})},onSetNextActionDate:F=>{O({kind:{type:"next_action_date",action:F},item:u,commit:()=>s.setNextActionDate(u,F)})},onSetStory:F=>{O({kind:{type:"set_story",optionName:F.name},item:u,commit:()=>s.setStory(u,F)})},onSetStatus:F=>{O({kind:{type:"set_status",optionName:F.name},item:u,commit:()=>s.setStatus(u,F)})},onSetInTmuxByHuman:F=>{O({kind:{type:"set_in_tmux_by_human",optionName:F.name},item:u,commit:()=>s.setInTmuxByHuman(u,F)})},onClose:F=>{O({kind:{type:"close",action:F},item:u,commit:()=>s.closeIssue(u,F)})}},ue=S??(u.story.trim()!==""?u.story:null),le=ue!==null?Ih(h,ue):null;return v.jsx(L0,{item:u,storyName:ue,storyColorEnum:le,overlayStatus:g,state:z.state,body:z.body,bodyIsLoading:z.bodyIsLoading,bodyError:z.bodyError,comments:z.comments,commentsAreLoading:z.commentsAreLoading,commentsError:z.commentsError,files:z.files,filesAreLoading:z.filesAreLoading,filesError:z.filesError,commits:z.commits,commitsAreLoading:z.commitsAreLoading,commitsError:z.commitsError,relatedPullRequests:z.relatedPullRequests,now:_,buildImageProxyUrl:G,onAddInlineComment:u.isPr?Q:void 0,commentComposer:v.jsx(A0,{isPr:u.isPr,now:_,onSubmit:F=>s.addComment(u,F)}),operationBar:v.jsx(V0,{tab:o,item:u,hasPullRequest:H,statusOptions:f,storyOptions:d,handlers:X})})},W0=()=>{const o={};for(const u of pn)o[u.name]=0;return o},P0="console",e1=()=>{const o=Ly(),{snapshots:u,isLoading:c,error:s}=Vy(o),f=jy(o??P0),d=Y.useMemo(()=>{const L=W0();for(const K of pn){const ve=u[K.name];ve!==null&&(L[K.name]=wy(ve.items,f.overlay))}return L},[u,f.overlay]),h=by(o,d),{activeTab:S,selectedItemKey:g,openItem:_,closeItem:O,selectTab:z}=h,C=py(),G=Ry(o,S,f),H=ty(),Q=Date.now(),X=u[S],ue=Y.useMemo(()=>X===null?[]:xy(X.items,f.overlay),[X,f.overlay]),le=Y.useMemo(()=>ue.map(L=>Pn(L)),[ue]),F=Y.useMemo(()=>B_(ue,f.overlay),[ue,f.overlay]),ce=(X==null?void 0:X.storyColors)??{},ye=(X==null?void 0:X.statusOptions)??[],ge=(X==null?void 0:X.storyOptions)??[],ee=(X==null?void 0:X.generatedAt)??null,je=Y.useMemo(()=>g===null||X===null?null:X.items.find(L=>L.projectItemId===g)??null,[g,X]),$e=d[S],ht=Y.useRef({tab:S,count:$e});Y.useEffect(()=>{const L=ht.current;if(ht.current={tab:S,count:$e},L.tab===S&&L.count>0&&$e===0){const K=gy(S,d);K!==null&&(z(K),O())}},[S,$e,d,z,O]);const Pe=(()=>{if(je===null)return null;const L=f.overlay[Pn(je)];return(L==null?void 0:L.status)??null})(),qe=je!==null?mr(je,f.overlay):null,kt=Y.useCallback(L=>{const K=Ky(le,L);K!==null?_(K):O()},[le,_,O]),xt=Y.useCallback(L=>{const K=Pn(L.item);H.enqueue({message:W_(L.kind,L.item,S),color:I_(L.kind),commit:L.commit,advance:()=>{F_(L.kind,S)&&kt(K)}})},[H,S,kt]),Ae=Y.useCallback(L=>{if(g===null||L===null)return;const K=L==="next"?Jy(le,g):$y(le,g);K!==null&&_(K)},[g,le,_]),R=Gy(Ae);return v.jsxs("main",{className:"console-app",children:[H.pending!==null&&v.jsx(V_,{message:H.pending.message,color:H.pending.color,remainingSeconds:H.pending.remainingSeconds,progress:H.pending.progress,onUndo:H.undo}),H.error!==null&&v.jsx(K_,{message:`操作に失敗しました: ${H.error.reason}`,onDismiss:H.dismissError}),v.jsx(H_,{activeTab:S,counts:d,pjcode:o,generatedAt:ee,tabHref:h.tabHref,onSelectTab:h.selectTab}),je===null?v.jsx(Q_,{rows:F,storyColors:ce,activeItemId:null,now:Q,isLoading:c,error:s,onSelectItem:L=>h.openItem(L.projectItemId)}):v.jsx("div",{className:"console-detail-screen",ref:R,children:v.jsx(F0,{tab:S,item:je,caches:C,operations:G,statusOptions:ye,storyOptions:ge,storyColors:ce,storyName:qe,overlayStatus:Pe,now:Q,onQueueAction:xt})})]})},Tp=document.getElementById("root");if(Tp===null)throw new Error("Root container #root not found");L_.createRoot(Tp).render(v.jsx(Y.StrictMode,{children:v.jsx(e1,{})}));
101
+ `)[0],Sp=({commits:o,isLoading:u,error:c,now:s})=>c!==null?v.jsxs("p",{role:"alert",className:"console-commits-error",children:["Failed to load commits: ",c]}):u?v.jsx("p",{className:"console-commits-loading",children:"Loading commits..."}):o.length===0?v.jsx("p",{className:"console-commits-empty",children:"No commits."}):v.jsx("ul",{className:"console-commits",children:o.map(f=>v.jsxs("li",{className:"console-commit",children:[v.jsx("span",{className:"console-commit-message",children:j0(f.message)}),v.jsx("span",{className:"console-commit-sha",children:D0(f.sha)}),v.jsx("span",{className:"console-commit-author",children:f.author}),v.jsx("span",{className:"console-commit-time",children:yu(f.authoredAt,s)})]},f.sha))}),U0=({pullRequest:o,body:u,bodyIsLoading:c,files:s,filesAreLoading:f,filesError:d,commits:h,commitsAreLoading:S,commitsError:g,now:_,buildImageProxyUrl:O})=>{const z=o.summary,C=f||d!==null?null:s.length,G=S||g!==null?null:h.length;return v.jsxs(v.Fragment,{children:[v.jsxs("div",{className:"console-pr-header",children:[v.jsx("a",{href:o.url,className:"console-pr-section-title",target:"_blank",rel:"noopener noreferrer",children:(z==null?void 0:z.title)??o.url}),o.isDraft&&v.jsx("span",{className:"console-pr-section-state",children:"draft"}),v.jsxs("div",{className:"console-pr-statbar",children:[o.branchName!==null&&v.jsx("span",{className:"console-pr-branch",children:o.branchName}),z!==null&&v.jsxs(v.Fragment,{children:[v.jsxs("span",{className:"console-pr-add",children:["+",z.additions]}),v.jsxs("span",{className:"console-pr-del",children:["-",z.deletions]}),v.jsxs("span",{className:"console-pr-files-count",children:[z.changedFiles," files"]})]})]})]}),v.jsx(ra,{title:"Description",defaultCollapsed:!0,children:c?v.jsx("p",{className:"console-pr-body-loading",children:"Loading description..."}):v.jsx(Is,{body:(z==null?void 0:z.body)??u,buildImageProxyUrl:O})}),v.jsx(ra,{title:"Changed files",count:C,children:v.jsx(vp,{files:s,isLoading:f,error:d})}),v.jsx(ra,{title:"Commits",count:G,defaultCollapsed:!0,children:v.jsx(Sp,{commits:h,isLoading:S,error:g,now:_})})]})},L0=({item:o,storyName:u,storyColorEnum:c,overlayStatus:s,state:f,body:d,bodyIsLoading:h,bodyError:S,comments:g,commentsAreLoading:_,commentsError:O,files:z,filesAreLoading:C,filesError:G,commits:H,commitsAreLoading:Q,commitsError:X,relatedPullRequests:ue,now:le,commentComposer:F,operationBar:ce,buildImageProxyUrl:ye,onAddInlineComment:ge})=>{const ee=(f==null?void 0:f.state)??"open",je=(f==null?void 0:f.merged)??!1,$e=!o.isPr&&ee==="closed"?"Closed":null,ht=_u(c),Pe=s?_u(s.color):null,qe=C||G!==null?null:z.length,kt=_||O!==null?null:g.length,xt=Q||X!==null?null:H.length;return v.jsxs("article",{className:"console-detail",children:[u!==null&&v.jsx("div",{className:"console-detail-story",children:v.jsxs("span",{className:"console-storytag",children:[v.jsx("span",{className:"console-story-dot",style:{backgroundColor:ht.dot}}),u]})}),s!==null&&Pe!==null&&v.jsx("span",{className:"console-detail-status-chip",style:{color:Pe.fg,borderColor:Pe.border,backgroundColor:Pe.bg},children:s.name}),v.jsxs("h2",{className:"console-detail-title",children:[v.jsx(Ph,{isPr:o.isPr,state:ee,merged:je,isDraft:!1,stateReason:""}),v.jsx("span",{className:"console-detail-title-text",children:o.title}),v.jsx("span",{className:"console-detail-number",children:o.isPr?`PR #${o.number}`:`#${o.number}`}),$e!==null&&v.jsx("span",{className:"console-detail-closed-label",children:$e})]}),v.jsxs("div",{className:"console-detail-subbar",children:[v.jsx("a",{href:o.url,className:"console-detail-link",target:"_blank",rel:"noopener noreferrer",children:o.isPr?`PR #${o.number}`:`Issue #${o.number}`}),v.jsx("span",{className:"console-detail-repo",children:o.repo}),v.jsx("span",{className:"console-detail-pill",children:o.isPr?"PR":"Issue"})]}),o.labels.length>0&&v.jsx("div",{className:"console-detail-labels",children:o.labels.map(Ae=>v.jsx("span",{className:"console-label-chip",children:Ae},Ae))}),v.jsxs("div",{className:"console-detail-createdat",title:vr(o.createdAt),children:["opened ",yu(o.createdAt,le)]}),v.jsx(ra,{title:"Description",headerAction:v.jsx("a",{href:o.url,className:"console-panel-open-link",target:"_blank",rel:"noopener noreferrer",children:"open"}),children:S!==null?v.jsxs("p",{role:"alert",className:"console-detail-body-error",children:["Failed to load description: ",S]}):h?v.jsx("p",{className:"console-detail-body-loading",children:"Loading description..."}):v.jsx(Is,{body:d,buildImageProxyUrl:ye})}),o.isPr&&v.jsx(ra,{title:"Changed files",count:qe,children:v.jsx(vp,{files:z,isLoading:C,error:G,onAddInlineComment:ge})}),v.jsx(ra,{title:"Comments",count:kt,defaultCollapsed:o.isPr,children:v.jsx(M0,{comments:g,isLoading:_,error:O,now:le,buildImageProxyUrl:ye})}),o.isPr&&v.jsx(ra,{title:"Commits",count:xt,defaultCollapsed:!0,children:v.jsx(Sp,{commits:H,isLoading:Q,error:X,now:le})}),!o.isPr&&ue.map(Ae=>{var R;return v.jsx(U0,{pullRequest:Ae.pullRequest,body:((R=Ae.pullRequest.summary)==null?void 0:R.body)??"",bodyIsLoading:!1,files:Ae.files,filesAreLoading:Ae.filesAreLoading,filesError:Ae.filesError,commits:Ae.commits,commitsAreLoading:Ae.commitsAreLoading,commitsError:Ae.commitsError,now:le,buildImageProxyUrl:ye},Ae.pullRequest.url)}),F,v.jsx("div",{className:"console-actionbar",children:ce})]})},H0=({onClose:o})=>v.jsxs("div",{className:"console-op-group",children:[v.jsx("button",{type:"button",className:"console-op-button",onClick:()=>o("close_not_planned"),children:"Close as not planned"}),v.jsx("button",{type:"button",className:"console-op-button",onClick:()=>o("close"),children:"Close"})]}),q0=({isTodoByHuman:o,onSetNextActionDate:u})=>v.jsxs("div",{className:"console-op-group",children:[v.jsx("button",{type:"button",className:"console-op-button console-op-button-snooze",onClick:()=>u("snooze_1day"),children:"+1 day"}),v.jsx("button",{type:"button",className:"console-op-button console-op-button-snooze",onClick:()=>u("snooze_1week"),children:o?"+1 week and skip":"+1 week"})]}),B0=[{action:"unnecessary",label:"Unnecessary",variant:"unneeded"},{action:"totally_wrong",label:"Totally wrong",variant:"wrong"},{action:"request_changes",label:"Reject",variant:"reject"},{action:"approve",label:"Approve",variant:"approve"}],Y0=({onReview:o})=>v.jsx("div",{className:"console-op-group console-op-group-review",children:B0.map(u=>v.jsx("button",{type:"button",className:`console-op-button console-op-button-${u.variant}`,onClick:()=>o(u.action),children:u.label},u.action))}),G0=(o,u)=>{const c=u.toLowerCase();return o.find(s=>s.name.toLowerCase()===c)??null},Z0=({statusOptions:o,onSetStatus:u,onSetInTmuxByHuman:c})=>{const s=Ty.map(f=>({name:f,option:G0(o,f)})).filter(f=>f.option!==null);return s.length===0?null:v.jsx("div",{className:"console-op-group",children:s.map(({name:f,option:d})=>{const h=_u(d.color),S=f===Ey;return v.jsx("button",{type:"button",className:"console-op-button",style:{color:h.fg,borderColor:h.border,backgroundColor:h.bg},onClick:()=>S?c(d):u(d),children:d.name},d.id)})})},X0=o=>o.name.toLowerCase().includes("no story"),Q0=({storyOptions:o,onSetStory:u})=>{const c=o.filter(s=>!X0(s));return c.length===0?null:v.jsx("div",{className:"console-op-group console-op-group-stories",children:c.map(s=>{const f=_u(s.color);return v.jsx("button",{type:"button",className:"console-op-button",style:{color:f.fg,borderColor:f.border,backgroundColor:f.bg},onClick:()=>u(s),children:s.name},s.id)})})},V0=({tab:o,item:u,hasPullRequest:c,statusOptions:s,storyOptions:f,handlers:d})=>{const h=o==="triage",S=o==="workflow-blocker"||!u.isPr;return v.jsxs("div",{className:"console-operation-bar",children:[c&&v.jsx(Y0,{onReview:d.onReview}),v.jsx(q0,{isTodoByHuman:Ay(o),onSetNextActionDate:d.onSetNextActionDate}),h&&v.jsx(Q0,{storyOptions:f,onSetStory:d.onSetStory}),v.jsx(Z0,{statusOptions:s,onSetStatus:d.onSetStatus,onSetInTmuxByHuman:d.onSetInTmuxByHuman}),S&&v.jsx(H0,{onClose:d.onClose})]})},ri=(o,u,c,s)=>{const f=u!==null?o.peek(u):void 0,[d,h]=Y.useState(f??s),[S,g]=Y.useState(u!==null&&f===void 0),[_,O]=Y.useState(null);return Y.useEffect(()=>{if(u===null||c===null)return;const z=o.peek(u);if(z!==void 0){h(z),g(!1),O(null);return}let C=!1;return g(!0),O(null),o.load(u,c).then(G=>{C||(h(G),g(!1))}).catch(G=>{C||(O(G instanceof Error?G.message:String(G)),g(!1))}),()=>{C=!0}},[o,u,c]),{data:d,isLoading:S,error:_}},K0=[],Jh=[],$h=[],J0=[],$0={state:"open",merged:!1,isPullRequest:!1},I0=(o,u)=>{const c=u!==null?`${u.repo}#${u.number}`:null,s=u!==null?u.url:null,f=(u==null?void 0:u.isPr)??!1,d=ri(o.body,c,s,""),h=ri(o.state,c,s,$0),S=ri(o.comments,c,s,K0),g=ri(o.files,f?c:null,f?s:null,Jh),_=ri(o.commits,f?c:null,f?s:null,$h),O=ri(o.relatedPrs,f?null:c,f?null:s,J0),[z,C]=Y.useState([]);return Y.useEffect(()=>{if(f||O.data.length===0){C([]);return}let G=!1;const H=O.data.map(X=>({pullRequest:X,files:Jh,filesAreLoading:!0,filesError:null,commits:$h,commitsAreLoading:!0,commitsError:null}));C(H);const Q=(X,ue)=>{G||C(le=>le.map(F=>F.pullRequest.url===X?{...F,...ue}:F))};for(const X of O.data){const ue=X.url;o.files.load(ue,X.url).then(le=>Q(X.url,{files:le,filesAreLoading:!1})).catch(le=>Q(X.url,{filesAreLoading:!1,filesError:le instanceof Error?le.message:String(le)})),o.commits.load(ue,X.url).then(le=>Q(X.url,{commits:le,commitsAreLoading:!1})).catch(le=>Q(X.url,{commitsAreLoading:!1,commitsError:le instanceof Error?le.message:String(le)}))}return()=>{G=!0}},[o,f,O.data]),{state:h.data,body:d.data,bodyIsLoading:d.isLoading,bodyError:d.error,comments:S.data,commentsAreLoading:S.isLoading,commentsError:S.error,files:g.data,filesAreLoading:g.isLoading,filesError:g.error,commits:_.data,commitsAreLoading:_.isLoading,commitsError:_.error,relatedPullRequests:z}},F0=({tab:o,item:u,caches:c,operations:s,statusOptions:f,storyOptions:d,storyColors:h,storyName:S,overlayStatus:g,now:_,onQueueAction:O})=>{const z=I0(c,u),{token:C}=Js(),G=Y.useCallback(F=>Wy(F,C),[C]),H=u.isPr||z.relatedPullRequests.length>0,Q=Y.useCallback((F,ce,ye,ge)=>s.addInlineReviewComment(u.url,F,ce,ye,ge),[s,u.url]),X={onReview:F=>{var ye;const ce=u.isPr?u.url:((ye=z.relatedPullRequests[0])==null?void 0:ye.pullRequest.url)??u.url;O({kind:{type:"review",action:F},item:u,commit:()=>s.reviewPullRequest(u,ce,F)})},onSetNextActionDate:F=>{O({kind:{type:"next_action_date",action:F},item:u,commit:()=>s.setNextActionDate(u,F)})},onSetStory:F=>{O({kind:{type:"set_story",optionName:F.name},item:u,commit:()=>s.setStory(u,F)})},onSetStatus:F=>{O({kind:{type:"set_status",optionName:F.name},item:u,commit:()=>s.setStatus(u,F)})},onSetInTmuxByHuman:F=>{O({kind:{type:"set_in_tmux_by_human",optionName:F.name},item:u,commit:()=>s.setInTmuxByHuman(u,F)})},onClose:F=>{O({kind:{type:"close",action:F},item:u,commit:()=>s.closeIssue(u,F)})}},ue=S??(u.story.trim()!==""?u.story:null),le=ue!==null?Ih(h,ue):null;return v.jsx(L0,{item:u,storyName:ue,storyColorEnum:le,overlayStatus:g,state:z.state,body:z.body,bodyIsLoading:z.bodyIsLoading,bodyError:z.bodyError,comments:z.comments,commentsAreLoading:z.commentsAreLoading,commentsError:z.commentsError,files:z.files,filesAreLoading:z.filesAreLoading,filesError:z.filesError,commits:z.commits,commitsAreLoading:z.commitsAreLoading,commitsError:z.commitsError,relatedPullRequests:z.relatedPullRequests,now:_,buildImageProxyUrl:G,onAddInlineComment:u.isPr?Q:void 0,commentComposer:v.jsx(A0,{isPr:u.isPr,now:_,onSubmit:F=>s.addComment(u,F)}),operationBar:v.jsx(V0,{tab:o,item:u,hasPullRequest:H,statusOptions:f,storyOptions:d,handlers:X})})},W0=()=>{const o={};for(const u of pn)o[u.name]=0;return o},P0="console",e1=()=>{const o=Ly(),{snapshots:u,isLoading:c,error:s}=Vy(o),f=jy(o??P0),d=Y.useMemo(()=>{const L=W0();for(const K of pn){const ve=u[K.name];ve!==null&&(L[K.name]=wy(ve.items,f.overlay))}return L},[u,f.overlay]),h=by(o,d),{activeTab:S,selectedItemKey:g,openItem:_,closeItem:O,selectTab:z}=h,C=py(),G=Ry(o,S,f),H=ty(),Q=Date.now(),X=u[S],ue=Y.useMemo(()=>X===null?[]:xy(X.items,f.overlay),[X,f.overlay]),le=Y.useMemo(()=>ue.map(L=>Pn(L)),[ue]),F=Y.useMemo(()=>B_(ue,f.overlay),[ue,f.overlay]),ce=(X==null?void 0:X.storyColors)??{},ye=(X==null?void 0:X.statusOptions)??[],ge=(X==null?void 0:X.storyOptions)??[],ee=(X==null?void 0:X.generatedAt)??null,je=Y.useMemo(()=>g===null||X===null?null:X.items.find(L=>L.projectItemId===g)??null,[g,X]),$e=d[S],ht=Y.useRef({tab:S,count:$e});Y.useEffect(()=>{const L=ht.current;if(ht.current={tab:S,count:$e},L.tab===S&&L.count>0&&$e===0){const K=gy(S,d);K!==null&&(z(K),O())}},[S,$e,d,z,O]);const Pe=(()=>{if(je===null)return null;const L=f.overlay[Pn(je)];return(L==null?void 0:L.status)??null})(),qe=je!==null?mr(je,f.overlay):null,kt=Y.useCallback(L=>{const K=Ky(le,L);K!==null?_(K):O()},[le,_,O]),xt=Y.useCallback(L=>{const K=Pn(L.item);H.enqueue({message:W_(L.kind,L.item,S),color:I_(L.kind),commit:L.commit,advance:()=>{F_(L.kind,S)&&kt(K)}})},[H,S,kt]),Ae=Y.useCallback(L=>{if(g===null||L===null)return;const K=L==="next"?Jy(le,g):$y(le,g);K!==null&&_(K)},[g,le,_]),R=Gy(Ae);return v.jsxs("main",{className:"console-app",children:[H.pending!==null&&v.jsx(V_,{message:H.pending.message,color:H.pending.color,remainingSeconds:H.pending.remainingSeconds,progress:H.pending.progress,onUndo:H.undo}),H.error!==null&&v.jsx(K_,{message:`Operation failed: ${H.error.reason}`,onDismiss:H.dismissError}),v.jsx(H_,{activeTab:S,counts:d,pjcode:o,generatedAt:ee,tabHref:h.tabHref,onSelectTab:h.selectTab}),je===null?v.jsx(Q_,{rows:F,storyColors:ce,activeItemId:null,now:Q,isLoading:c,error:s,onSelectItem:L=>h.openItem(L.projectItemId)}):v.jsx("div",{className:"console-detail-screen",ref:R,children:v.jsx(F0,{tab:S,item:je,caches:C,operations:G,statusOptions:ye,storyOptions:ge,storyColors:ce,storyName:qe,overlayStatus:Pe,now:Q,onQueueAction:xt})})]})},Tp=document.getElementById("root");if(Tp===null)throw new Error("Root container #root not found");L_.createRoot(Tp).render(v.jsx(Y.StrictMode,{children:v.jsx(e1,{})}));
@@ -4,7 +4,7 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>TDPM Console</title>
7
- <script type="module" crossorigin src="/assets/index-CP3-MdUU.js"></script>
7
+ <script type="module" crossorigin src="/assets/index-BpccigBS.js"></script>
8
8
  <link rel="stylesheet" crossorigin href="/assets/index-CO-f_j4f.css">
9
9
  </head>
10
10
  <body>
@@ -45,6 +45,7 @@ const issue = (url: string, status: string): Issue => ({
45
45
  isClosed: false,
46
46
  createdAt: new Date('2026-01-01T00:00:00Z'),
47
47
  author: 'hiromi',
48
+ closingIssueReferenceUrls: [],
48
49
  });
49
50
 
50
51
  describe('InTmuxByHumanSessionTokenCountHandler', () => {
@@ -64,6 +64,7 @@ const makeIssue = (overrides: Partial<Issue>): Issue => ({
64
64
  isClosed: false,
65
65
  createdAt: new Date('2026-06-13T08:18:45.000Z'),
66
66
  author: 'someone',
67
+ closingIssueReferenceUrls: [],
67
68
  ...overrides,
68
69
  });
69
70
 
@@ -29,6 +29,7 @@ const makeIssue = (overrides: Partial<Issue> = {}): Issue => ({
29
29
  isClosed: false,
30
30
  createdAt: new Date(),
31
31
  author: '',
32
+ closingIssueReferenceUrls: [],
32
33
  ...overrides,
33
34
  });
34
35
 
@@ -39,6 +39,7 @@ const createIssue = (overrides: Partial<Issue> = {}): Issue => ({
39
39
  isClosed: false,
40
40
  createdAt: new Date('2025-01-01'),
41
41
  author: 'user',
42
+ closingIssueReferenceUrls: [],
42
43
  ...overrides,
43
44
  });
44
45
 
@@ -25,6 +25,7 @@ const buildIssue = (url: string): Issue => ({
25
25
  isClosed: false,
26
26
  createdAt: new Date('2024-01-01T00:00:00Z'),
27
27
  author: 'testuser',
28
+ closingIssueReferenceUrls: [],
28
29
  });
29
30
 
30
31
  const TEST_URL = 'https://github.com/HiromiShikata/test-repo/issues/123';
@@ -36,6 +36,9 @@ describe('ApiV3CheerioRestIssueRepository', () => {
36
36
  assignees: [],
37
37
  createdAt: '2024-01-01T00:00:00Z',
38
38
  author: 'test-author',
39
+ closingIssueReferenceUrls: [
40
+ 'https://github.com/HiromiShikata/test-repository/issues/7',
41
+ ],
39
42
  customFields: [
40
43
  { name: 'nextActionDate', value: '2000-01-01' },
41
44
  { name: 'nextActionHour', value: '1' },
@@ -69,6 +72,9 @@ describe('ApiV3CheerioRestIssueRepository', () => {
69
72
  isClosed: false,
70
73
  createdAt: new Date('2024-01-01T00:00:00Z'),
71
74
  author: 'test-author',
75
+ closingIssueReferenceUrls: [
76
+ 'https://github.com/HiromiShikata/test-repository/issues/7',
77
+ ],
72
78
  },
73
79
  },
74
80
  {
@@ -86,6 +92,7 @@ describe('ApiV3CheerioRestIssueRepository', () => {
86
92
  assignees: [],
87
93
  createdAt: '2024-01-01T00:00:00Z',
88
94
  author: '',
95
+ closingIssueReferenceUrls: [],
89
96
  customFields: [
90
97
  {
91
98
  name: 'DependedIssueUrls',
@@ -122,6 +129,7 @@ describe('ApiV3CheerioRestIssueRepository', () => {
122
129
  isClosed: false,
123
130
  createdAt: new Date('2024-01-01T00:00:00Z'),
124
131
  author: '',
132
+ closingIssueReferenceUrls: [],
125
133
  },
126
134
  },
127
135
  ];
@@ -253,6 +261,7 @@ describe('ApiV3CheerioRestIssueRepository', () => {
253
261
  isClosed: false,
254
262
  createdAt: new Date('2024-01-01'),
255
263
  author: '',
264
+ closingIssueReferenceUrls: [],
256
265
  };
257
266
  const statusId = 'new-status-id';
258
267
 
@@ -543,6 +543,7 @@ export class ApiV3CheerioRestIssueRepository
543
543
  isClosed: item.state !== 'OPEN',
544
544
  createdAt: new Date(item.createdAt || '2000-01-01'),
545
545
  author: item.author,
546
+ closingIssueReferenceUrls: item.closingIssueReferenceUrls,
546
547
  };
547
548
  };
548
549
  getAllIssuesFromCache = async (
@@ -578,6 +579,14 @@ export class ApiV3CheerioRestIssueRepository
578
579
  !('createdAt' in issue) || typeof issue.createdAt !== 'string'
579
580
  ? new Date()
580
581
  : new Date(issue.createdAt);
582
+ const closingIssueReferenceUrls =
583
+ 'closingIssueReferenceUrls' in issue &&
584
+ Array.isArray(issue.closingIssueReferenceUrls) &&
585
+ issue.closingIssueReferenceUrls.every(
586
+ (url): url is string => typeof url === 'string',
587
+ )
588
+ ? issue.closingIssueReferenceUrls
589
+ : [];
581
590
 
582
591
  return {
583
592
  ...issue,
@@ -585,6 +594,7 @@ export class ApiV3CheerioRestIssueRepository
585
594
  completionDate50PercentConfidence:
586
595
  completionDate50PercentConfidence,
587
596
  createdAt: createdAt,
597
+ closingIssueReferenceUrls: closingIssueReferenceUrls,
588
598
  };
589
599
  });
590
600
 
@@ -14,6 +14,7 @@ export type ProjectItem = {
14
14
  assignees: string[];
15
15
  createdAt: string;
16
16
  author: string;
17
+ closingIssueReferenceUrls: string[];
17
18
  customFields: {
18
19
  name: string;
19
20
  value: string | null;
@@ -214,6 +215,11 @@ query GetProjectItems($projectId: ID!, $after: String, $first: Int!) {
214
215
  repository {
215
216
  nameWithOwner
216
217
  }
218
+ closingIssuesReferences(first: 50) {
219
+ nodes {
220
+ url
221
+ }
222
+ }
217
223
  }
218
224
  }
219
225
  }
@@ -257,6 +263,7 @@ query GetProjectItems($projectId: ID!, $after: String, $first: Int!) {
257
263
  author: { login: string } | null;
258
264
  labels: { nodes: { name: string }[] };
259
265
  assignees: { nodes: { login: string }[] };
266
+ closingIssuesReferences?: { nodes: { url: string }[] };
260
267
  };
261
268
  }[];
262
269
  };
@@ -309,6 +316,7 @@ query GetProjectItems($projectId: ID!, $after: String, $first: Int!) {
309
316
  author: { login: string } | null;
310
317
  labels: { nodes: { name: string }[] };
311
318
  assignees: { nodes: { login: string }[] };
319
+ closingIssuesReferences?: { nodes: { url: string }[] };
312
320
  };
313
321
  }[];
314
322
  };
@@ -364,6 +372,7 @@ query GetProjectItems($projectId: ID!, $after: String, $first: Int!) {
364
372
  author: { login: string } | null;
365
373
  labels: { nodes: { name: string }[] };
366
374
  assignees: { nodes: { login: string }[] };
375
+ closingIssuesReferences?: { nodes: { url: string }[] };
367
376
  };
368
377
  }[];
369
378
  };
@@ -435,6 +444,7 @@ query GetProjectItems($projectId: ID!, $after: String, $first: Int!) {
435
444
  author: { login: string } | null;
436
445
  labels: { nodes: { name: string }[] };
437
446
  assignees: { nodes: { login: string }[] };
447
+ closingIssuesReferences?: { nodes: { url: string }[] };
438
448
  };
439
449
  }[] = pageNodes;
440
450
  projectItems.forEach((item) => {
@@ -453,6 +463,10 @@ query GetProjectItems($projectId: ID!, $after: String, $first: Int!) {
453
463
  assignees: item.content.assignees?.nodes?.map((a) => a.login) || [],
454
464
  createdAt: item.content.createdAt || new Date().toISOString(),
455
465
  author: item.content.author?.login || '',
466
+ closingIssueReferenceUrls:
467
+ item.content.closingIssuesReferences?.nodes
468
+ ?.map((node) => node.url)
469
+ .filter((url) => url.length > 0) || [],
456
470
  customFields: item.fieldValues.nodes
457
471
  .filter((field) => !!field.field)
458
472
  .map((field) => {
@@ -768,6 +782,11 @@ query GetProjectFields($owner: String!, $repository: String!, $issueNumber: Int!
768
782
  repository {
769
783
  nameWithOwner
770
784
  }
785
+ closingIssuesReferences(first: 50) {
786
+ nodes {
787
+ url
788
+ }
789
+ }
771
790
  projectItems(first: 10) {
772
791
  nodes {
773
792
  id
@@ -843,6 +862,7 @@ query GetProjectFields($owner: String!, $repository: String!, $issueNumber: Int!
843
862
  labels: { nodes: { name: string }[] };
844
863
  assignees: { nodes: { login: string }[] };
845
864
  repository: { nameWithOwner: string };
865
+ closingIssuesReferences?: { nodes: { url: string }[] };
846
866
  projectItems: {
847
867
  nodes: {
848
868
  id: string;
@@ -914,6 +934,10 @@ query GetProjectFields($owner: String!, $repository: String!, $issueNumber: Int!
914
934
  assignees: content.assignees?.nodes?.map((a) => a.login) || [],
915
935
  createdAt: content.createdAt || new Date().toISOString(),
916
936
  author: content.author?.login || '',
937
+ closingIssueReferenceUrls:
938
+ content.closingIssuesReferences?.nodes
939
+ ?.map((node) => node.url)
940
+ .filter((url) => url.length > 0) || [],
917
941
  customFields: item.fieldValues.nodes
918
942
  .filter((field) => !!field.field)
919
943
  .map((field) => {
@@ -50,6 +50,7 @@ const buildIssue = (overrides: Partial<Issue> = {}): Issue => ({
50
50
  isClosed: false,
51
51
  createdAt: new Date(),
52
52
  author: '',
53
+ closingIssueReferenceUrls: [],
53
54
  ...overrides,
54
55
  });
55
56
 
@@ -24,4 +24,5 @@ export type Issue = {
24
24
  isClosed: boolean;
25
25
  createdAt: Date;
26
26
  author: string;
27
+ closingIssueReferenceUrls: string[];
27
28
  };
@@ -27,6 +27,7 @@ const createMockIssue = (overrides: Partial<Issue> = {}): Issue => ({
27
27
  isClosed: false,
28
28
  createdAt: new Date('2000-01-01T00:00:00Z'),
29
29
  author: 'test-user',
30
+ closingIssueReferenceUrls: [],
30
31
  ...overrides,
31
32
  });
32
33
 
@@ -67,6 +67,7 @@ describe('GetStoryObjectMapUseCase', () => {
67
67
  isClosed: false,
68
68
  createdAt: new Date(),
69
69
  author: '',
70
+ closingIssueReferenceUrls: [],
70
71
  ...overrides,
71
72
  });
72
73
 
@@ -47,6 +47,7 @@ const issue = (url: string, status: string): Issue => ({
47
47
  isClosed: false,
48
48
  createdAt: new Date('2026-01-01T00:00:00Z'),
49
49
  author: 'hiromi',
50
+ closingIssueReferenceUrls: [],
50
51
  });
51
52
 
52
53
  describe('InTmuxByHumanSessionTokenCountUseCase', () => {
@@ -72,6 +72,7 @@ const createMockIssue = (overrides: Partial<Issue> = {}): Issue => ({
72
72
  isClosed: false,
73
73
  createdAt: new Date(),
74
74
  author: '',
75
+ closingIssueReferenceUrls: [],
75
76
  ...overrides,
76
77
  });
77
78
 
@@ -80,6 +80,7 @@ const createMockIssue = (overrides: Partial<Issue> = {}): Issue => ({
80
80
  isClosed: false,
81
81
  createdAt: new Date(),
82
82
  author: '',
83
+ closingIssueReferenceUrls: [],
83
84
  ...overrides,
84
85
  });
85
86
 
@@ -32,6 +32,7 @@ const createMockIssue = (overrides: Partial<Issue> = {}): Issue => ({
32
32
  isClosed: false,
33
33
  createdAt: new Date(),
34
34
  author: '',
35
+ closingIssueReferenceUrls: [],
35
36
  ...overrides,
36
37
  });
37
38