github-issue-tower-defence-management 1.143.1 → 1.143.3

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 (46) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +2 -2
  3. package/bin/adapter/entry-points/console/ui-dist/assets/index-1G1iHxrl.css +2 -0
  4. package/bin/adapter/entry-points/console/ui-dist/assets/index-vdcFItOm.js +81 -0
  5. package/bin/adapter/entry-points/console/ui-dist/index.html +2 -2
  6. package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js +2 -9
  7. package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js.map +1 -1
  8. package/bin/adapter/entry-points/handlers/notifySilentTmuxSessions.js +2 -5
  9. package/bin/adapter/entry-points/handlers/notifySilentTmuxSessions.js.map +1 -1
  10. package/bin/adapter/repositories/TmuxSilentSessionNotificationRepository.js +2 -1
  11. package/bin/adapter/repositories/TmuxSilentSessionNotificationRepository.js.map +1 -1
  12. package/bin/domain/usecases/DefaultSilentSessionMessageComposer.js +1 -1
  13. package/bin/domain/usecases/DefaultSilentSessionMessageComposer.js.map +1 -1
  14. package/bin/domain/usecases/NotifySilentLiveSessionsUseCase.js +1 -35
  15. package/bin/domain/usecases/NotifySilentLiveSessionsUseCase.js.map +1 -1
  16. package/package.json +1 -1
  17. package/src/adapter/entry-points/console/ui/src/features/console/components/shared/ConsoleClipboardCopyButton.test.tsx +34 -0
  18. package/src/adapter/entry-points/console/ui/src/features/console/components/shared/ConsoleClipboardCopyButton.tsx +29 -6
  19. package/src/adapter/entry-points/console/ui/src/features/console/logic/clipboard.test.ts +90 -0
  20. package/src/adapter/entry-points/console/ui/src/features/console/logic/clipboard.ts +37 -0
  21. package/src/adapter/entry-points/console/ui-dist/assets/index-1G1iHxrl.css +2 -0
  22. package/src/adapter/entry-points/console/ui-dist/assets/index-vdcFItOm.js +81 -0
  23. package/src/adapter/entry-points/console/ui-dist/index.html +2 -2
  24. package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts +0 -5
  25. package/src/adapter/entry-points/handlers/notifySilentTmuxSessions.test.ts +3 -8
  26. package/src/adapter/entry-points/handlers/notifySilentTmuxSessions.ts +0 -8
  27. package/src/adapter/repositories/TmuxSilentSessionNotificationRepository.test.ts +35 -4
  28. package/src/adapter/repositories/TmuxSilentSessionNotificationRepository.ts +2 -1
  29. package/src/adapter/repositories/TranscriptOwnerCallStatusProvider.test.ts +0 -6
  30. package/src/domain/usecases/DefaultSilentSessionMessageComposer.test.ts +21 -1
  31. package/src/domain/usecases/DefaultSilentSessionMessageComposer.ts +1 -1
  32. package/src/domain/usecases/NotifySilentLiveSessionsUseCase.test.ts +21 -98
  33. package/src/domain/usecases/NotifySilentLiveSessionsUseCase.ts +0 -44
  34. package/types/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.d.ts.map +1 -1
  35. package/types/adapter/entry-points/handlers/notifySilentTmuxSessions.d.ts +0 -1
  36. package/types/adapter/entry-points/handlers/notifySilentTmuxSessions.d.ts.map +1 -1
  37. package/types/adapter/repositories/TmuxSilentSessionNotificationRepository.d.ts.map +1 -1
  38. package/types/domain/usecases/NotifySilentLiveSessionsUseCase.d.ts +1 -3
  39. package/types/domain/usecases/NotifySilentLiveSessionsUseCase.d.ts.map +1 -1
  40. package/bin/adapter/entry-points/console/ui-dist/assets/index-BWy8G--c.js +0 -81
  41. package/bin/adapter/entry-points/console/ui-dist/assets/index-Bp-p-XOs.css +0 -2
  42. package/src/adapter/entry-points/console/ui-dist/assets/index-BWy8G--c.js +0 -81
  43. package/src/adapter/entry-points/console/ui-dist/assets/index-Bp-p-XOs.css +0 -2
  44. package/src/adapter/repositories/FileSystemSilentSessionNotifiedStateRepository.test.ts +0 -127
  45. package/src/adapter/repositories/FileSystemSilentSessionNotifiedStateRepository.ts +0 -108
  46. package/src/domain/usecases/adapter-interfaces/SilentSessionNotifiedStateRepository.ts +0 -10
@@ -1,2 +0,0 @@
1
- /*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
2
- @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-font-weight:initial;--tw-outline-style:solid;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000}}}@layer theme{:root,:host{--font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--font-weight-medium:500;--font-weight-semibold:600;--radius-md:.375rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-input:#e5e5e5;--color-ring:#0a0a0a;--color-background:#fff;--color-foreground:#0a0a0a;--color-primary:#171717;--color-primary-foreground:#fafafa;--color-secondary:#f5f5f5;--color-secondary-foreground:#171717;--color-accent:#f5f5f5;--color-accent-foreground:#171717}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.visible{visibility:visible}.relative{position:relative}.static{position:static}.container{width:100%}@media (width>=40rem){.container{max-width:40rem}}@media (width>=48rem){.container{max-width:48rem}}@media (width>=64rem){.container{max-width:64rem}}@media (width>=80rem){.container{max-width:80rem}}@media (width>=96rem){.container{max-width:96rem}}.block{display:block}.hidden{display:none}.inline{display:inline}.inline-flex{display:inline-flex}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-10{height:calc(var(--spacing) * 10)}.items-center{align-items:center}.justify-center{justify-content:center}.gap-2{gap:calc(var(--spacing) * 2)}.rounded-md{border-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-input{border-color:var(--color-input)}.border-transparent{border-color:#0000}.bg-background{background-color:var(--color-background)}.bg-primary{background-color:var(--color-primary)}.bg-secondary{background-color:var(--color-secondary)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-8{padding-inline:calc(var(--spacing) * 8)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-2{padding-block:calc(var(--spacing) * 2)}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.whitespace-nowrap{white-space:nowrap}.text-foreground{color:var(--color-foreground)}.text-primary-foreground{color:var(--color-primary-foreground)}.text-secondary-foreground{color:var(--color-secondary-foreground)}.lowercase{text-transform:lowercase}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}@media (hover:hover){.hover\:bg-accent:hover{background-color:var(--color-accent)}.hover\:bg-primary\/90:hover{background-color:#171717e6}@supports (color:color-mix(in lab, red, red)){.hover\:bg-primary\/90:hover{background-color:color-mix(in oklab, var(--color-primary) 90%, transparent)}}.hover\:bg-secondary\/80:hover{background-color:#f5f5f5cc}@supports (color:color-mix(in lab, red, red)){.hover\:bg-secondary\/80:hover{background-color:color-mix(in oklab, var(--color-secondary) 80%, transparent)}}.hover\:text-accent-foreground:hover{color:var(--color-accent-foreground)}}.focus-visible\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus-visible\:ring-ring:focus-visible{--tw-ring-color:var(--color-ring)}.focus-visible\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:opacity-50:disabled{opacity:.5}}html{font-size:clamp(15px,2.1vw,26px)}body{color:#e6edf3;background-color:#0d1117;margin:0;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif}.console-app{flex-direction:column;width:100%;min-height:100dvh;display:flex}.console-tabbar{-webkit-overflow-scrolling:touch;background:#161b22;border-bottom:2px solid #30363d;flex-wrap:nowrap;align-items:stretch;gap:0;min-height:42px;padding:0 8px;display:flex;overflow-x:auto}.console-tab{color:#8b949e;white-space:nowrap;cursor:pointer;background:0 0;border:none;border-bottom:2px solid #0000;align-items:center;gap:6px;margin-bottom:-2px;padding:10px 14px;font-size:.8125rem;font-weight:500;line-height:1.2;text-decoration:none;display:inline-flex}.console-tab:hover{color:#e6edf3}.console-tab[data-active=true]{color:#e6edf3;border-bottom-color:#2f81f7;font-weight:700}.console-tab-badge{text-align:center;color:#e6edf3;background:#484f58;border-radius:20px;min-width:20px;padding:1px 7px;font-size:.6875rem;font-weight:700;line-height:1.5}.console-tab-badge[data-zero=true]{color:#8b949e;background:#30363d}.console-tab-pjname{color:#8b949e;align-self:center;margin-left:auto;padding:0 8px;font-size:.7188rem}.console-tab-geninfo{color:#8b949e;align-self:center;padding:0 4px;font-size:.6875rem}.console-list{margin:0;padding:12px 18px 18px;list-style:none}.console-list-group{list-style:none}.console-item-row .console-item-icon{flex:none;margin-top:3px}.console-group-header{background:#0b0f14;border-bottom:1px solid #21262d;justify-content:space-between;align-items:center;padding:6px 12px;display:flex}.console-storytag{align-items:center;gap:8px;font-size:.8125rem;font-weight:700;display:inline-flex}.console-story-dot{border-radius:999px;width:10px;height:10px;display:inline-block}.console-group-count{color:#8b949e;font-size:.75rem}.console-item-row{color:#e6edf3;text-align:left;cursor:pointer;background:#161b22;border:1px solid #30363d;border-radius:8px;align-items:flex-start;gap:14px;width:100%;margin-bottom:10px;padding:12px 16px;display:flex}.console-item-row:hover{background:#1a2029;border-color:#484f58}.console-item-row[data-active=true]{background:#1a2029;border-color:#4493f8}.console-item-meta{flex:1;min-width:0}.console-item-title{font-size:.9063rem;font-weight:600;display:block}.console-item-sub{color:#8b949e;margin-top:3px;font-size:.7813rem;display:block}.console-item-pill{color:#8b949e;border:1px solid #30363d;border-radius:20px;margin-right:6px;padding:1px 8px;font-size:.6875rem;display:inline-block}.console-item-createdat{color:#8b949e;cursor:help}.console-item-fields{color:#adbac7;flex-wrap:wrap;gap:4px 10px;margin-top:4px;font-size:.7188rem;display:flex}.console-item-field{word-break:break-all;align-items:baseline;gap:4px;min-width:0;display:inline-flex}.console-item-field-label{color:#6e7681;text-transform:uppercase;letter-spacing:.03em;font-size:.625rem}.console-list-message{color:#8b949e;padding:16px;font-size:.875rem}.console-list-empty{text-align:center;color:#8b949e;padding:40px;font-size:.875rem}.console-list-error,.console-comment-error,.console-files-error,.console-commits-error,.console-detail-body-error{color:#f85149}.console-detail{flex-direction:column;flex:1 0 auto;gap:12px;padding:16px 16px 0;display:flex}.console-detail-title{align-items:center;gap:8px;margin:0;font-size:1.25rem;display:flex}.console-detail-title-text{flex:1}.console-detail-number{color:#8b949e;font-weight:400}.console-detail-closed-label{color:#a371f7;font-size:.8125rem}.console-detail-subbar{align-items:center;gap:12px;font-size:.8125rem;display:flex}.console-detail-link{color:#4493f8}.console-detail-repo{color:#8b949e;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.console-copy-url-button{color:#c9d1d9;border:1px solid #30363d;border-radius:6px;height:24px;padding:0 8px;font-size:.75rem}.console-copy-url-button:hover{color:#e6edf3;background-color:#21262d}.console-detail-pill,.console-label-chip,.console-detail-status-chip{border:1px solid #30363d;border-radius:999px;padding:2px 8px;font-size:.75rem;display:inline-block}.console-detail-pr-status-row{flex-wrap:wrap;align-items:center;gap:6px;margin-top:-4px;display:flex}.console-detail-pr-status{flex-wrap:wrap;align-items:center;gap:6px;display:inline-flex}.console-detail-ci-missing{opacity:.85;font-weight:400}.console-detail-mergeable-chip{font-weight:600}.console-detail-mergeable-chip-unknown{opacity:.7;font-weight:400}.console-detail-labels{flex-wrap:wrap;gap:6px;display:flex}.console-detail-createdat{color:#8b949e;font-size:.75rem}.console-panel{border:1px solid #30363d;border-radius:8px;overflow:hidden}.console-panel-header{background:#161b22;justify-content:space-between;align-items:center;display:flex}.console-panel-toggle{color:#e6edf3;text-align:left;cursor:pointer;background:0 0;border:none;flex:1;align-items:center;gap:8px;padding:6px 12px;font-size:.875rem;font-weight:600;display:flex}.console-panel-toggle:hover{background:#1a2029}.console-panel-action{padding:6px 12px}.console-panel-body{padding:12px}.console-markdown{word-break:break-word;font-size:.875rem;line-height:1.5}.console-markdown ul{margin:.5em 0;padding-left:1.5em;list-style:outside}.console-markdown ol{margin:.5em 0;padding-left:1.5em;list-style:decimal}.console-markdown li{margin:.25em 0}.console-markdown table{border-collapse:collapse;margin:.5em 0}.console-markdown th,.console-markdown td{border:1px solid #30363d;padding:4px 8px}.console-markdown th{background:#161b22}.console-markdown h1,.console-markdown h2,.console-markdown h3,.console-markdown h4,.console-markdown h5,.console-markdown h6{margin:1em 0 .5em;font-weight:700;line-height:1.25}.console-markdown h1{font-size:1.6em}.console-markdown h2{font-size:1.4em}.console-markdown h3{font-size:1.2em}.console-markdown h4{font-size:1.05em}.console-markdown h5{font-size:.95em}.console-markdown h6{color:#8b949e;font-size:.9em}.console-markdown pre{background:#161b22;border:1px solid #30363d;border-radius:6px;margin:.5em 0;padding:12px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.8125rem;line-height:1.45;overflow-x:auto}.console-markdown code{background:#6e768166;border-radius:4px;padding:.15em .4em;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.9em}.console-markdown pre code{font-size:inherit;background:0 0;border-radius:0;padding:0}.console-markdown-code-block{flex-direction:column;margin:.5em 0;display:flex}.console-markdown-code-block pre{margin:0}.console-markdown-code-copy-host{justify-content:flex-end;margin-bottom:4px;display:flex}.console-copy-code-button{color:#c9d1d9;background-color:#161b22;border:1px solid #30363d;border-radius:6px;height:24px;padding:0 8px;font-size:.75rem}.console-copy-code-button:hover{color:#e6edf3;background-color:#21262d}.console-markdown blockquote{color:#8b949e;border-left:3px solid #30363d;margin:.5em 0;padding:0 1em}.console-markdown a{color:#4493f8;text-decoration:none}.console-markdown a:hover{text-decoration:underline}.console-markdown-reference-host{display:inline}.console-markdown-reference{vertical-align:baseline;align-items:center;gap:.25em;display:inline-flex}.console-markdown-reference .console-item-icon{flex-shrink:0}.console-markdown-reference-title{text-decoration:none}.console-markdown-reference:hover .console-markdown-reference-title{text-decoration:underline}.console-markdown hr{border:none;border-top:1px solid #30363d;margin:1em 0}.console-mermaid-error{color:#f85149;font-size:.8125rem}.console-comment{background:#161b22;border:1px solid #30363d;border-radius:8px;margin-bottom:10px;padding:12px 16px}.console-comment-header{color:#8b949e;gap:8px;font-size:.75rem;display:flex}.console-comment-show-all{color:#e6edf3;cursor:pointer;background:#21262d;border:1px solid #30363d;border-radius:6px;margin-bottom:10px;padding:6px 12px;font-size:.75rem;font-weight:600}.console-comment-show-all:hover{background-color:#262c34;border-color:#484f58}.console-comment-author{color:#e6edf3;font-weight:600}.console-files,.console-commits{margin:0;padding:0;list-style:none}.console-commit{align-items:center;gap:8px;padding:4px 0;font-size:.8125rem;display:flex}.console-file{flex-direction:column;font-size:.8125rem;display:flex}.console-file-tree,.console-file-tree-children{margin:0;padding:0;list-style:none}.console-file-tree-dir{flex-direction:column;display:flex}.console-file-tree-dir-name{color:#8b949e;align-items:center;gap:6px;padding:4px 0;font-weight:600;display:flex}.console-file-tree-dir-icon{flex:none}.console-file-badge{text-align:center;border:1px solid;border-radius:4px;width:18px;font-size:.6875rem}.console-file-path,.console-commit-message{flex:1;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.console-file-add,.console-pr-add{color:#3fb950}.console-file-del,.console-pr-del{color:#f85149}.console-commit-sha{color:#8b949e;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.console-actionbar{z-index:100;padding:10px 16px;padding-bottom:calc(10px + env(safe-area-inset-bottom));background:#161b22;border-top:2px solid #30363d;margin-top:auto;position:sticky;bottom:0}.console-operation-bar{flex-direction:column;gap:8px;width:100%;display:flex}.console-op-group{flex-wrap:wrap;justify-content:flex-end;align-items:center;gap:8px;display:flex}.console-op-group-review{gap:10px}.console-op-group-stories{max-height:33vh;overflow-y:auto}.console-op-button{color:#e6edf3;white-space:nowrap;cursor:pointer;background:#21262d;border:1px solid #30363d;border-radius:6px;padding:9px 16px;font-size:.8125rem;font-weight:600}.console-op-button:hover{border-color:#484f58}.console-op-button-approve{color:#fff;background:#238636;border-color:#2ea043}.console-op-button-reject{color:#ffd166;background:#7d5000;border-color:#a06800}.console-op-button-wrong{color:#f85149;background:#3a1518;border-color:#f85149}.console-op-button-unneeded{color:#aab0b8;background:#2a2d31;border-color:#6e7681}.console-op-button-snooze{color:#79c0ff;background:#1c2b4a;border-color:#4493f8}.console-pr-section{border:1px solid #30363d;border-radius:8px;flex-direction:column;gap:10px;padding:12px;display:flex}.console-pr-statbar{color:#8b949e;gap:12px;font-size:.75rem;display:flex}.console-detail-screen{flex-direction:column;flex:1 0 auto;display:flex}.console-panel-open-link{color:#4493f8;font-size:.8125rem;font-weight:400}.console-composer{margin-top:4px}.console-composer-toggle{color:#8b949e;cursor:pointer;background:0 0;border:none;padding:2px 0;font-size:.7813rem}.console-composer-toggle:hover{color:#e6edf3}.console-composer-posted{flex-direction:column;gap:8px;margin-top:8px;display:flex}.console-composer-form{margin-top:8px}.console-composer-input{box-sizing:border-box;color:#e6edf3;width:100%;font:inherit;resize:vertical;background:#21262d;border:1px solid #30363d;border-radius:6px;padding:8px;font-size:.875rem}.console-composer-row{justify-content:flex-end;align-items:center;gap:8px;margin-top:6px;display:flex}.console-composer-submit{color:#fff;cursor:pointer;background:#238636;border:1px solid #2ea043;border-radius:6px;padding:7px 16px;font-size:.8125rem;font-weight:600}.console-composer-submit:disabled{opacity:.6;cursor:default}.console-composer-status{color:#8b949e;font-size:.75rem}.console-composer-error{color:#f85149}.console-undo-toast{z-index:9998;white-space:nowrap;border-radius:10px;align-items:center;gap:12px;max-width:92vw;padding:12px 18px;font-size:.8438rem;display:flex;position:fixed;top:12px;left:50%;transform:translate(-50%);box-shadow:0 4px 20px #0009}.console-undo-toast-green{color:#3fb950;background:#0d3320;border:1px solid #2ea043}.console-undo-toast-amber{color:#ffd166;background:#3a2800;border:1px solid #a06800}.console-undo-toast-red{color:#f85149;background:#3a1518;border:1px solid #da3633}.console-undo-toast-gray{color:#aab0b8;background:#2a2d31;border:1px solid #6e7681}.console-undo-toast-blue{color:#79c0ff;background:#0d1f40;border:1px solid #4493f8}.console-undo-toast-error{color:#f85149;background:#3a1518;border:1px solid #f85149}.console-undo-toast-message{text-overflow:ellipsis;flex:1;min-width:0;overflow:hidden}.console-undo-toast-undo{cursor:pointer;color:inherit;background:#ffffff1f;border:none;border-radius:6px;flex:none;padding:4px 12px;font-size:.8125rem;font-weight:700}.console-undo-toast-undo:hover{background:#ffffff38}.console-undo-toast-countdown{opacity:.7;flex:none;font-size:.6875rem}.console-undo-toast-bar{opacity:.5;background:currentColor;border-radius:0 0 10px 10px;height:3px;transition:width .1s linear;position:absolute;bottom:0;left:0}.console-file-row{width:100%;color:inherit;font:inherit;text-align:left;cursor:pointer;background:0 0;border:none;align-items:center;gap:8px;padding:4px 0;font-size:.8125rem;display:flex}.console-file-row:hover{background:#1a2029}.console-file-caret{color:#8b949e;flex:none;width:1em}.console-file-diff{border-collapse:collapse;width:100%;margin:4px 0 8px;font:.8125rem/1.6 ui-monospace,SFMono-Regular,Menlo,monospace}.console-file-diff td{white-space:pre-wrap;word-break:break-word;vertical-align:top;padding:0 10px}.console-diff-ln{text-align:right;color:#6e7681;-webkit-user-select:none;user-select:none;white-space:nowrap;border-right:1px solid #30363d;width:1%;padding:0 8px}.console-file-diff td.console-diff-ln{white-space:nowrap;word-break:normal;overflow-wrap:normal}.console-diff-add td{background:#2ea04326}.console-diff-add .console-diff-code{color:#aff5b4}.console-diff-del td{background:#f8514926}.console-diff-del .console-diff-code{color:#ffdcd7}.console-diff-hunk td{color:#79c0ff;background:#161b22}.console-diff-ctx .console-diff-code{color:#c9d1d9}.console-file-diff-empty{color:#8b949e;padding:8px 14px;font-size:.75rem}.console-diff-comment-cell{text-align:center;-webkit-user-select:none;user-select:none;width:1%;padding:0 2px}.console-diff-comment-button{color:#6e7681;cursor:pointer;opacity:.6;background:0 0;border:1px solid #30363d;border-radius:4px;width:18px;height:18px;padding:0;font-size:.875rem;line-height:16px}.console-diff-row:hover .console-diff-comment-button,.console-diff-comment-button:focus-visible,.console-diff-comment-button[aria-expanded=true]{opacity:1;color:#fff;background:#1f6feb;border-color:#2f81f7}.console-diff-composer-row td{background:#0d1117;padding:6px 10px}.console-diff-composer{background:#161b22;border:1px solid #30363d;border-radius:6px;flex-direction:column;gap:6px;padding:8px;display:flex}.console-diff-composer-anchor{color:#8b949e;font-size:.6875rem}.console-diff-composer-input{resize:vertical;color:#c9d1d9;width:100%;font:inherit;background:#0d1117;border:1px solid #30363d;border-radius:6px;padding:6px 8px}.console-diff-composer-controls{align-items:center;gap:8px;display:flex}.console-diff-composer-submit{color:#fff;cursor:pointer;background:#238636;border:1px solid #238636;border-radius:6px;padding:4px 12px}.console-diff-composer-submit:disabled{opacity:.6;cursor:default}.console-diff-composer-cancel{color:#c9d1d9;cursor:pointer;background:0 0;border:1px solid #30363d;border-radius:6px;padding:4px 12px}.console-diff-composer-status{color:#8b949e;font-size:.75rem}.console-diff-composer-error{color:#ff7b72}.console-diff-composer-posted{color:#3fb950;margin:0;font-size:.75rem}.console-pr-header{flex-wrap:wrap;align-items:center;gap:10px;padding-top:4px;display:flex}.console-pr-section-title{color:#e6edf3;font-size:.9375rem;font-weight:600}.console-pr-section-state{color:#8b949e;border:1px solid #6e7681;border-radius:999px;padding:1px 8px;font-size:.6875rem}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}
@@ -1,127 +0,0 @@
1
- import * as fs from 'fs';
2
- import * as os from 'os';
3
- import * as path from 'path';
4
- import { FileSystemSilentSessionNotifiedStateRepository } from './FileSystemSilentSessionNotifiedStateRepository';
5
-
6
- describe('FileSystemSilentSessionNotifiedStateRepository', () => {
7
- let rootDirectory: string;
8
- let stateFilePath: string;
9
-
10
- beforeEach(() => {
11
- rootDirectory = fs.mkdtempSync(
12
- path.join(os.tmpdir(), 'silent-session-notified-state-'),
13
- );
14
- stateFilePath = path.join(rootDirectory, 'silent-session-notified.json');
15
- });
16
-
17
- afterEach(() => {
18
- fs.rmSync(rootDirectory, { force: true, recursive: true });
19
- });
20
-
21
- const sessionAlpha = 'https://github.com/HiromiShikata/repo/issues/100';
22
- const sessionBravo = 'https://github.com/HiromiShikata/repo/issues/200';
23
-
24
- it('round-trips a saved notified set so the next cycle reads it back', async () => {
25
- const repository = new FileSystemSilentSessionNotifiedStateRepository(
26
- stateFilePath,
27
- );
28
- const now = new Date('2026-06-26T00:00:00Z');
29
-
30
- await repository.saveNotifiedSessionNames({
31
- sessionNames: [sessionAlpha, sessionBravo],
32
- now,
33
- });
34
- const loaded = await repository.loadRecentNotifiedSessionNames({
35
- now: new Date('2026-06-26T00:01:00Z'),
36
- recencyWindowSeconds: 15 * 60,
37
- });
38
-
39
- expect(loaded).toEqual(new Set([sessionAlpha, sessionBravo]));
40
- });
41
-
42
- it('returns an empty set when no state file exists yet', async () => {
43
- const repository = new FileSystemSilentSessionNotifiedStateRepository(
44
- stateFilePath,
45
- );
46
-
47
- const loaded = await repository.loadRecentNotifiedSessionNames({
48
- now: new Date('2026-06-26T00:00:00Z'),
49
- recencyWindowSeconds: 15 * 60,
50
- });
51
-
52
- expect(loaded).toEqual(new Set<string>());
53
- });
54
-
55
- it('excludes an entry older than the recency window when loading', async () => {
56
- const repository = new FileSystemSilentSessionNotifiedStateRepository(
57
- stateFilePath,
58
- );
59
-
60
- await repository.saveNotifiedSessionNames({
61
- sessionNames: [sessionAlpha],
62
- now: new Date('2026-06-26T00:00:00Z'),
63
- });
64
- const loaded = await repository.loadRecentNotifiedSessionNames({
65
- now: new Date('2026-06-26T00:20:00Z'),
66
- recencyWindowSeconds: 15 * 60,
67
- });
68
-
69
- expect(loaded).toEqual(new Set<string>());
70
- });
71
-
72
- it('overwrites the latch on save so a pruned session no longer lingers', async () => {
73
- const repository = new FileSystemSilentSessionNotifiedStateRepository(
74
- stateFilePath,
75
- );
76
-
77
- await repository.saveNotifiedSessionNames({
78
- sessionNames: [sessionAlpha, sessionBravo],
79
- now: new Date('2026-06-26T00:00:00Z'),
80
- });
81
- await repository.saveNotifiedSessionNames({
82
- sessionNames: [sessionAlpha],
83
- now: new Date('2026-06-26T00:01:30Z'),
84
- });
85
- const loaded = await repository.loadRecentNotifiedSessionNames({
86
- now: new Date('2026-06-26T00:02:00Z'),
87
- recencyWindowSeconds: 15 * 60,
88
- });
89
-
90
- expect(loaded).toEqual(new Set([sessionAlpha]));
91
- });
92
-
93
- it('refreshes the recorded timestamp on each save so a continuously latched session stays within the window', async () => {
94
- const repository = new FileSystemSilentSessionNotifiedStateRepository(
95
- stateFilePath,
96
- );
97
-
98
- await repository.saveNotifiedSessionNames({
99
- sessionNames: [sessionAlpha],
100
- now: new Date('2026-06-26T00:00:00Z'),
101
- });
102
- await repository.saveNotifiedSessionNames({
103
- sessionNames: [sessionAlpha],
104
- now: new Date('2026-06-26T00:14:00Z'),
105
- });
106
- const loaded = await repository.loadRecentNotifiedSessionNames({
107
- now: new Date('2026-06-26T00:20:00Z'),
108
- recencyWindowSeconds: 15 * 60,
109
- });
110
-
111
- expect(loaded).toEqual(new Set([sessionAlpha]));
112
- });
113
-
114
- it('returns an empty set when the state file is not valid JSON', async () => {
115
- fs.writeFileSync(stateFilePath, 'not json');
116
- const repository = new FileSystemSilentSessionNotifiedStateRepository(
117
- stateFilePath,
118
- );
119
-
120
- const loaded = await repository.loadRecentNotifiedSessionNames({
121
- now: new Date('2026-06-26T00:00:00Z'),
122
- recencyWindowSeconds: 15 * 60,
123
- });
124
-
125
- expect(loaded).toEqual(new Set<string>());
126
- });
127
- });
@@ -1,108 +0,0 @@
1
- import * as fs from 'fs';
2
- import * as os from 'os';
3
- import * as path from 'path';
4
- import { SilentSessionNotifiedStateRepository } from '../../domain/usecases/adapter-interfaces/SilentSessionNotifiedStateRepository';
5
-
6
- type StoredNotifiedEntry = {
7
- sessionName: string;
8
- recordedEpochSeconds: number;
9
- };
10
-
11
- const isRecord = (value: unknown): value is Record<string, unknown> =>
12
- typeof value === 'object' && value !== null && !Array.isArray(value);
13
-
14
- const defaultStateFilePath = (): string => {
15
- const base = process.env.XDG_CACHE_HOME ?? path.join(os.homedir(), '.cache');
16
- return path.join(base, 'tdpm', 'silent-session-notified.json');
17
- };
18
-
19
- // Persists the fire-once latch: the set of session names that have already
20
- // received the current silent-episode reminder. The use case re-writes the
21
- // full latch each cycle with the current timestamp, keeping a session latched
22
- // for as long as it stays a reminder candidate (a continuous silent episode
23
- // produces exactly one reminder), and prunes a session the moment it stops
24
- // being a candidate so a later re-qualification fires again. The save
25
- // intentionally OVERWRITES rather than merges: the use case supplies the
26
- // complete latch to persist, so a pruned session must not linger.
27
- export class FileSystemSilentSessionNotifiedStateRepository implements SilentSessionNotifiedStateRepository {
28
- constructor(
29
- private readonly stateFilePath: string = defaultStateFilePath(),
30
- ) {}
31
-
32
- loadRecentNotifiedSessionNames = async (params: {
33
- now: Date;
34
- recencyWindowSeconds: number;
35
- }): Promise<Set<string>> => {
36
- const nowEpochSeconds = Math.floor(params.now.getTime() / 1000);
37
- const oldestAllowedEpochSeconds =
38
- nowEpochSeconds - params.recencyWindowSeconds;
39
- const recentSessionNames = new Set<string>();
40
- for (const entry of this.readNotifiedEntries()) {
41
- if (entry.recordedEpochSeconds >= oldestAllowedEpochSeconds) {
42
- recentSessionNames.add(entry.sessionName);
43
- }
44
- }
45
- return recentSessionNames;
46
- };
47
-
48
- saveNotifiedSessionNames = async (params: {
49
- sessionNames: string[];
50
- now: Date;
51
- }): Promise<void> => {
52
- const recordedEpochSeconds = Math.floor(params.now.getTime() / 1000);
53
- const notifiedBySessionName = new Map<string, StoredNotifiedEntry>();
54
- for (const sessionName of params.sessionNames) {
55
- notifiedBySessionName.set(sessionName, {
56
- sessionName,
57
- recordedEpochSeconds,
58
- });
59
- }
60
- this.writeState(Array.from(notifiedBySessionName.values()));
61
- };
62
-
63
- private readNotifiedEntries = (): StoredNotifiedEntry[] => {
64
- let raw: string;
65
- try {
66
- raw = fs.readFileSync(this.stateFilePath, 'utf8');
67
- } catch {
68
- return [];
69
- }
70
- let parsed: unknown;
71
- try {
72
- parsed = JSON.parse(raw);
73
- } catch {
74
- return [];
75
- }
76
- if (!isRecord(parsed)) {
77
- return [];
78
- }
79
- const storedEntries = parsed.notified;
80
- if (!Array.isArray(storedEntries)) {
81
- return [];
82
- }
83
- const entries: StoredNotifiedEntry[] = [];
84
- for (const storedEntry of storedEntries) {
85
- if (!isRecord(storedEntry)) {
86
- continue;
87
- }
88
- const sessionName = storedEntry.sessionName;
89
- const recordedEpochSeconds = storedEntry.recordedEpochSeconds;
90
- if (
91
- typeof sessionName === 'string' &&
92
- typeof recordedEpochSeconds === 'number' &&
93
- Number.isFinite(recordedEpochSeconds)
94
- ) {
95
- entries.push({ sessionName, recordedEpochSeconds });
96
- }
97
- }
98
- return entries;
99
- };
100
-
101
- private writeState = (notified: StoredNotifiedEntry[]): void => {
102
- const directory = path.dirname(this.stateFilePath);
103
- fs.mkdirSync(directory, { recursive: true });
104
- const temporaryPath = `${this.stateFilePath}.${process.pid}.tmp`;
105
- fs.writeFileSync(temporaryPath, JSON.stringify({ notified }));
106
- fs.renameSync(temporaryPath, this.stateFilePath);
107
- };
108
- }
@@ -1,10 +0,0 @@
1
- export interface SilentSessionNotifiedStateRepository {
2
- loadRecentNotifiedSessionNames: (params: {
3
- now: Date;
4
- recencyWindowSeconds: number;
5
- }) => Promise<Set<string>>;
6
- saveNotifiedSessionNames: (params: {
7
- sessionNames: string[];
8
- now: Date;
9
- }) => Promise<void>;
10
- }