claude-code-session-manager 0.35.0 → 0.35.2
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.
- package/dist/assets/{TiptapBody-BqDK21Pr.js → TiptapBody-CIEmzy3k.js} +1 -1
- package/dist/assets/{index-zepGuf8m.js → index-2Om-ouz6.js} +519 -521
- package/dist/assets/index-DeIJ8SM5.css +32 -0
- package/dist/index.html +2 -2
- package/package.json +1 -1
- package/plugins/session-manager-dev/.claude-plugin/plugin.json +1 -1
- package/plugins/session-manager-dev/skills/develop/SKILL.md +95 -10
- package/plugins/session-manager-dev/skills/explain-to-me/SKILL.md +1 -1
- package/src/main/__tests__/chat-cancel-terminal.test.cjs +89 -0
- package/src/main/chatRunner.cjs +42 -17
- package/src/main/lib/claudeBin.cjs +3 -0
- package/dist/assets/index-CPTin6qz.css +0 -32
- package/plugins/session-manager-dev/skills/prd/SKILL.md +0 -134
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2014 The xterm.js authors. All rights reserved.
|
|
3
|
+
* Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
|
|
4
|
+
* https://github.com/chjj/term.js
|
|
5
|
+
* @license MIT
|
|
6
|
+
*
|
|
7
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
9
|
+
* in the Software without restriction, including without limitation the rights
|
|
10
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
12
|
+
* furnished to do so, subject to the following conditions:
|
|
13
|
+
*
|
|
14
|
+
* The above copyright notice and this permission notice shall be included in
|
|
15
|
+
* all copies or substantial portions of the Software.
|
|
16
|
+
*
|
|
17
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
22
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
23
|
+
* THE SOFTWARE.
|
|
24
|
+
*
|
|
25
|
+
* Originally forked from (with the author's permission):
|
|
26
|
+
* Fabrice Bellard's javascript vt100 for jslinux:
|
|
27
|
+
* http://bellard.org/jslinux/
|
|
28
|
+
* Copyright (c) 2011 Fabrice Bellard
|
|
29
|
+
* The original design remains. The terminal itself
|
|
30
|
+
* has been extended to include xterm CSI codes, among
|
|
31
|
+
* other features.
|
|
32
|
+
*/.xterm{cursor:text;position:relative;-moz-user-select:none;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{position:absolute;top:0;z-index:5}.xterm .xterm-helper-textarea{padding:0;border:0;margin:0;position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-5;white-space:nowrap;overflow:hidden;resize:none}.xterm .composition-view{background:#000;color:#fff;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;right:0;left:0;top:0;bottom:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm .xterm-scroll-area{visibility:hidden}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{position:absolute;left:0;top:0;bottom:0;right:0;z-index:10;color:transparent;pointer-events:none}.xterm .xterm-accessibility-tree:not(.debug) *::-moz-selection{color:transparent}.xterm .xterm-accessibility-tree:not(.debug) *::selection{color:transparent}.xterm .xterm-accessibility-tree{-webkit-user-select:text;-moz-user-select:text;user-select:text;white-space:pre}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{-webkit-text-decoration:double underline;text-decoration:double underline}.xterm-underline-3{-webkit-text-decoration:wavy underline;text-decoration:wavy underline}.xterm-underline-4{-webkit-text-decoration:dotted underline;text-decoration:dotted underline}.xterm-underline-5{-webkit-text-decoration:dashed underline;text-decoration:dashed underline}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:overline underline}.xterm-overline.xterm-underline-2{-webkit-text-decoration:overline double underline;text-decoration:overline double underline}.xterm-overline.xterm-underline-3{-webkit-text-decoration:overline wavy underline;text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{-webkit-text-decoration:overline dotted underline;text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{-webkit-text-decoration:overline dashed underline;text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;position:absolute;top:0;right:0;pointer-events:none}.xterm-decoration-top{z-index:2;position:relative}*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:Geist,system-ui,sans-serif;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}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;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:IBM Plex Mono,JetBrains Mono,ui-monospace,SFMono-Regular,Menlo,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.\!container{width:100%!important}.container{width:100%}@media(min-width:640px){.\!container{max-width:640px!important}.container{max-width:640px}}@media(min-width:768px){.\!container{max-width:768px!important}.container{max-width:768px}}@media(min-width:1024px){.\!container{max-width:1024px!important}.container{max-width:1024px}}@media(min-width:1280px){.\!container{max-width:1280px!important}.container{max-width:1280px}}@media(min-width:1536px){.\!container{max-width:1536px!important}.container{max-width:1536px}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.visible{visibility:visible}.invisible{visibility:hidden}.collapse{visibility:collapse}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{top:0;right:0;bottom:0;left:0}.inset-x-0{left:0;right:0}.-left-\[10px\]{left:-10px}.-left-\[4px\]{left:-4px}.bottom-0{bottom:0}.bottom-10{bottom:2.5rem}.bottom-2{bottom:.5rem}.bottom-3{bottom:.75rem}.bottom-4{bottom:1rem}.bottom-full{bottom:100%}.left-0{left:0}.left-1\/2{left:50%}.left-2\.5{left:.625rem}.right-0{right:0}.right-1\.5{right:.375rem}.right-11{right:2.75rem}.right-2{right:.5rem}.right-3{right:.75rem}.right-4{right:1rem}.top-0{top:0}.top-0\.5{top:.125rem}.top-1\.5{top:.375rem}.top-1\/2{top:50%}.top-10{top:2.5rem}.top-12{top:3rem}.top-2{top:.5rem}.top-3{top:.75rem}.top-9{top:2.25rem}.top-full{top:100%}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.z-\[200\]{z-index:200}.z-\[300\]{z-index:300}.z-\[400\]{z-index:400}.z-\[55\]{z-index:55}.z-\[60\]{z-index:60}.col-span-2{grid-column:span 2 / span 2}.-m-1{margin:-.25rem}.m-0{margin:0}.mx-0\.5{margin-left:.125rem;margin-right:.125rem}.mx-1{margin-left:.25rem;margin-right:.25rem}.mx-2{margin-left:.5rem;margin-right:.5rem}.mx-3{margin-left:.75rem;margin-right:.75rem}.mx-4{margin-left:1rem;margin-right:1rem}.mx-\[18px\]{margin-left:18px;margin-right:18px}.mx-auto{margin-left:auto;margin-right:auto}.my-1{margin-top:.25rem;margin-bottom:.25rem}.my-2{margin-top:.5rem;margin-bottom:.5rem}.my-3{margin-top:.75rem;margin-bottom:.75rem}.my-8{margin-top:2rem;margin-bottom:2rem}.-mb-px{margin-bottom:-1px}.mb-0{margin-bottom:0}.mb-0\.5{margin-bottom:.125rem}.mb-1{margin-bottom:.25rem}.mb-1\.5{margin-bottom:.375rem}.mb-2{margin-bottom:.5rem}.mb-2\.5{margin-bottom:.625rem}.mb-3{margin-bottom:.75rem}.mb-3\.5{margin-bottom:.875rem}.mb-4{margin-bottom:1rem}.mb-5{margin-bottom:1.25rem}.mb-6{margin-bottom:1.5rem}.mb-7{margin-bottom:1.75rem}.mb-\[18px\]{margin-bottom:18px}.mb-\[22px\]{margin-bottom:22px}.mb-\[5px\]{margin-bottom:5px}.mb-px{margin-bottom:1px}.ml-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.ml-3{margin-left:.75rem}.ml-5{margin-left:1.25rem}.ml-6{margin-left:1.5rem}.ml-8{margin-left:2rem}.ml-auto{margin-left:auto}.mr-1{margin-right:.25rem}.mr-2{margin-right:.5rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-1\.5{margin-top:.375rem}.mt-2{margin-top:.5rem}.mt-2\.5{margin-top:.625rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.mt-\[18px\]{margin-top:18px}.line-clamp-2{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}.\!block{display:block!important}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.contents{display:contents}.hidden{display:none}.h-0\.5{height:.125rem}.h-1{height:.25rem}.h-1\.5{height:.375rem}.h-10{height:2.5rem}.h-11{height:2.75rem}.h-12{height:3rem}.h-14{height:3.5rem}.h-2{height:.5rem}.h-2\.5{height:.625rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-32{height:8rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-80{height:20rem}.h-9{height:2.25rem}.h-\[18px\]{height:18px}.h-\[22px\]{height:22px}.h-\[30px\]{height:30px}.h-\[34px\]{height:34px}.h-\[38px\]{height:38px}.h-\[52px\]{height:52px}.h-\[80vh\]{height:80vh}.h-\[90vh\]{height:90vh}.h-\[9px\]{height:9px}.h-full{height:100%}.max-h-24{max-height:6rem}.max-h-40{max-height:10rem}.max-h-48{max-height:12rem}.max-h-60{max-height:15rem}.max-h-64{max-height:16rem}.max-h-72{max-height:18rem}.max-h-\[60vh\]{max-height:60vh}.max-h-\[70vh\]{max-height:70vh}.max-h-\[85vh\]{max-height:85vh}.max-h-\[90vh\]{max-height:90vh}.max-h-full{max-height:100%}.min-h-0{min-height:0px}.min-h-32{min-height:8rem}.min-h-\[140px\]{min-height:140px}.min-h-\[16rem\]{min-height:16rem}.min-h-\[200px\]{min-height:200px}.min-h-\[26px\]{min-height:26px}.min-h-\[60px\]{min-height:60px}.w-1{width:.25rem}.w-1\.5{width:.375rem}.w-10{width:2.5rem}.w-11{width:2.75rem}.w-12{width:3rem}.w-14{width:3.5rem}.w-16{width:4rem}.w-2{width:.5rem}.w-2\/5{width:40%}.w-20{width:5rem}.w-24{width:6rem}.w-28{width:7rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-32{width:8rem}.w-4{width:1rem}.w-44{width:11rem}.w-48{width:12rem}.w-5{width:1.25rem}.w-56{width:14rem}.w-6{width:1.5rem}.w-60{width:15rem}.w-64{width:16rem}.w-7{width:1.75rem}.w-72{width:18rem}.w-8{width:2rem}.w-80{width:20rem}.w-9{width:2.25rem}.w-96{width:24rem}.w-\[10px\]{width:10px}.w-\[110px\]{width:110px}.w-\[22px\]{width:22px}.w-\[240px\]{width:240px}.w-\[280px\]{width:280px}.w-\[30px\]{width:30px}.w-\[34px\]{width:34px}.w-\[38px\]{width:38px}.w-\[3px\]{width:3px}.w-\[420px\]{width:420px}.w-\[52px\]{width:52px}.w-\[600px\]{width:600px}.w-\[640px\]{width:640px}.w-\[840px\]{width:840px}.w-\[900px\]{width:900px}.w-\[9px\]{width:9px}.w-full{width:100%}.w-px{width:1px}.min-w-0{min-width:0px}.min-w-\[104px\]{min-width:104px}.min-w-\[200px\]{min-width:200px}.min-w-\[240px\]{min-width:240px}.min-w-\[280px\]{min-width:280px}.min-w-\[6rem\]{min-width:6rem}.min-w-\[7\.5rem\]{min-width:7.5rem}.min-w-\[80px\]{min-width:80px}.max-w-2xl{max-width:42rem}.max-w-3xl{max-width:48rem}.max-w-4xl{max-width:56rem}.max-w-5xl{max-width:64rem}.max-w-\[1100px\]{max-width:1100px}.max-w-\[12rem\]{max-width:12rem}.max-w-\[16ch\]{max-width:16ch}.max-w-\[16rem\]{max-width:16rem}.max-w-\[180px\]{max-width:180px}.max-w-\[18rem\]{max-width:18rem}.max-w-\[200px\]{max-width:200px}.max-w-\[220px\]{max-width:220px}.max-w-\[22rem\]{max-width:22rem}.max-w-\[24rem\]{max-width:24rem}.max-w-\[320px\]{max-width:320px}.max-w-\[420px\]{max-width:420px}.max-w-\[440px\]{max-width:440px}.max-w-\[500px\]{max-width:500px}.max-w-\[560px\]{max-width:560px}.max-w-\[600px\]{max-width:600px}.max-w-\[620px\]{max-width:620px}.max-w-\[70\%\]{max-width:70%}.max-w-\[760px\]{max-width:760px}.max-w-\[80\%\]{max-width:80%}.max-w-\[820px\]{max-width:820px}.max-w-\[8rem\]{max-width:8rem}.max-w-\[90\%\]{max-width:90%}.max-w-\[90vw\]{max-width:90vw}.max-w-\[95vw\]{max-width:95vw}.max-w-\[calc\(100vw-1rem\)\]{max-width:calc(100vw - 1rem)}.max-w-\[min\(96vw\,1400px\)\]{max-width:min(96vw,1400px)}.max-w-full{max-width:100%}.max-w-md{max-width:28rem}.max-w-none{max-width:none}.max-w-sm{max-width:24rem}.max-w-xl{max-width:36rem}.max-w-xs{max-width:20rem}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.border-collapse{border-collapse:collapse}.-translate-x-1\/2{--tw-translate-x: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-0\.5{--tw-translate-x: .125rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-1\/2{--tw-translate-x: 50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-3\.5{--tw-translate-x: .875rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-90{--tw-rotate: 90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.cursor-col-resize{cursor:col-resize}.cursor-default{cursor:default}.cursor-grab{cursor:grab}.cursor-grabbing{cursor:grabbing}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.cursor-wait{cursor:wait}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.select-all{-webkit-user-select:all;-moz-user-select:all;user-select:all}.resize-none{resize:none}.resize-y{resize:vertical}.resize{resize:both}.list-inside{list-style-position:inside}.list-disc{list-style-type:disc}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}.grid-cols-\[116px_1fr_auto_auto\]{grid-template-columns:116px 1fr auto auto}.grid-cols-\[5rem_1fr_auto\]{grid-template-columns:5rem 1fr auto}.grid-cols-\[auto_1fr\]{grid-template-columns:auto 1fr}.grid-cols-\[auto_1fr_auto\]{grid-template-columns:auto 1fr auto}.grid-cols-\[repeat\(auto-fit\,minmax\(160px\,1fr\)\)\]{grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.place-items-center{place-items:center}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.items-baseline{align-items:baseline}.items-stretch{align-items:stretch}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-0{gap:0px}.gap-0\.5{gap:.125rem}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-2\.5{gap:.625rem}.gap-3{gap:.75rem}.gap-3\.5{gap:.875rem}.gap-4{gap:1rem}.gap-5{gap:1.25rem}.gap-6{gap:1.5rem}.gap-\[18px\]{gap:18px}.gap-px{gap:1px}.gap-x-3{-moz-column-gap:.75rem;column-gap:.75rem}.gap-x-4{-moz-column-gap:1rem;column-gap:1rem}.gap-y-0\.5{row-gap:.125rem}.gap-y-1{row-gap:.25rem}.gap-y-2{row-gap:.5rem}.space-y-0\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.125rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.125rem * var(--tw-space-y-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.375rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-2\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.625rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.625rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.25rem * var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem * var(--tw-space-y-reverse))}.space-y-\[22px\]>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(22px * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(22px * var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}.divide-line>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:rgb(224 211 184 / var(--tw-divide-opacity, 1))}.divide-line\/60>:not([hidden])~:not([hidden]){border-color:#e0d3b899}.self-start{align-self:flex-start}.self-center{align-self:center}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-normal{white-space:normal}.whitespace-nowrap{white-space:nowrap}.whitespace-pre{white-space:pre}.whitespace-pre-wrap{white-space:pre-wrap}.text-pretty{text-wrap:pretty}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:1rem}.rounded-\[10px\]{border-radius:10px}.rounded-\[11px\]{border-radius:11px}.rounded-\[12px\]{border-radius:12px}.rounded-\[13px\]{border-radius:13px}.rounded-\[14px\]{border-radius:14px}.rounded-\[7px\]{border-radius:7px}.rounded-\[9px\]{border-radius:9px}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-sm{border-radius:.125rem}.rounded-xl{border-radius:.75rem}.rounded-b-sm{border-bottom-right-radius:.125rem;border-bottom-left-radius:.125rem}.rounded-l{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.rounded-r{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.rounded-t{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.rounded-t-\[10px\]{border-top-left-radius:10px;border-top-right-radius:10px}.rounded-t-sm{border-top-left-radius:.125rem;border-top-right-radius:.125rem}.rounded-bl-lg{border-bottom-left-radius:.5rem}.rounded-br-sm{border-bottom-right-radius:.125rem}.rounded-tl-lg{border-top-left-radius:.5rem}.rounded-tr-lg{border-top-right-radius:.5rem}.border{border-width:1px}.border-0{border-width:0px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-b-0{border-bottom-width:0px}.border-l{border-left-width:1px}.border-l-0{border-left-width:0px}.border-l-2{border-left-width:2px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-t-2{border-top-width:2px}.border-dashed{border-style:dashed}.\!border-sage\/40{border-color:#6f7d5266!important}.border-\[\#8e641a\]\/40{border-color:#8e641a66}.border-\[\#b8443c\]\/40{border-color:#b8443c66}.border-\[\#e8cdb9\]{--tw-border-opacity: 1;border-color:rgb(232 205 185 / var(--tw-border-opacity, 1))}.border-\[\#eccdbe\]{--tw-border-opacity: 1;border-color:rgb(236 205 190 / var(--tw-border-opacity, 1))}.border-accent{--tw-border-opacity: 1;border-color:rgb(184 92 52 / var(--tw-border-opacity, 1))}.border-accent-muted{--tw-border-opacity: 1;border-color:rgb(232 169 136 / var(--tw-border-opacity, 1))}.border-accent\/20{border-color:#b85c3433}.border-accent\/30{border-color:#b85c344d}.border-accent\/40{border-color:#b85c3466}.border-accent\/50{border-color:#b85c3480}.border-accent\/60{border-color:#b85c3499}.border-amber-400\/25{border-color:#fbbf2440}.border-amber-400\/30{border-color:#fbbf244d}.border-amber-500\/15{border-color:#f59e0b26}.border-amber-500\/25{border-color:#f59e0b40}.border-amber-500\/40{border-color:#f59e0b66}.border-amber-700{--tw-border-opacity: 1;border-color:rgb(180 83 9 / var(--tw-border-opacity, 1))}.border-amber-700\/50{border-color:#b4530980}.border-amber-700\/60{border-color:#b4530999}.border-amber-800\/60{border-color:#92400e99}.border-blue-500{--tw-border-opacity: 1;border-color:rgb(59 130 246 / var(--tw-border-opacity, 1))}.border-blue-500\/20{border-color:#3b82f633}.border-blue-900\/40{border-color:#1e3a8a66}.border-butter{--tw-border-opacity: 1;border-color:rgb(228 184 90 / var(--tw-border-opacity, 1))}.border-butter\/60{border-color:#e4b85a99}.border-cyan-500\/20{border-color:#06b6d433}.border-fg-faint\/20{border-color:#8a7a6033}.border-green-500\/20{border-color:#22c55e33}.border-green-800\/60{border-color:#16653499}.border-hive-plum{--tw-border-opacity: 1;border-color:rgb(138 90 110 / var(--tw-border-opacity, 1))}.border-hive-slate{--tw-border-opacity: 1;border-color:rgb(95 111 134 / var(--tw-border-opacity, 1))}.border-hive-teal{--tw-border-opacity: 1;border-color:rgb(79 125 114 / var(--tw-border-opacity, 1))}.border-honey\/30{border-color:#d3a23c4d}.border-line{--tw-border-opacity: 1;border-color:rgb(224 211 184 / var(--tw-border-opacity, 1))}.border-line\/30{border-color:#e0d3b84d}.border-line\/50{border-color:#e0d3b880}.border-line\/60{border-color:#e0d3b899}.border-orange-500\/20{border-color:#f9731633}.border-orange-800\/60{border-color:#9a341299}.border-pink-500\/20{border-color:#ec489933}.border-purple-500\/20{border-color:#a855f733}.border-purple-900\/40{border-color:#581c8766}.border-red-400\/30{border-color:#f871714d}.border-red-500\/20{border-color:#ef444433}.border-red-500\/40{border-color:#ef444466}.border-red-500\/50{border-color:#ef444480}.border-red-500\/70{border-color:#ef4444b3}.border-red-700{--tw-border-opacity: 1;border-color:rgb(185 28 28 / var(--tw-border-opacity, 1))}.border-red-700\/50{border-color:#b91c1c80}.border-red-700\/60{border-color:#b91c1c99}.border-red-800{--tw-border-opacity: 1;border-color:rgb(153 27 27 / var(--tw-border-opacity, 1))}.border-red-800\/40{border-color:#991b1b66}.border-red-800\/60{border-color:#991b1b99}.border-red-900\/40{border-color:#7f1d1d66}.border-red-900\/50{border-color:#7f1d1d80}.border-red-900\/60{border-color:#7f1d1d99}.border-rule{--tw-border-opacity: 1;border-color:rgb(217 201 168 / var(--tw-border-opacity, 1))}.border-sage{--tw-border-opacity: 1;border-color:rgb(111 125 82 / var(--tw-border-opacity, 1))}.border-sage\/30{border-color:#6f7d524d}.border-sage\/40{border-color:#6f7d5266}.border-sage\/50{border-color:#6f7d5280}.border-sage\/60{border-color:#6f7d5299}.border-transparent{border-color:transparent}.border-white\/10{border-color:#ffffff1a}.border-white\/5{border-color:#ffffff0d}.border-yellow-400\/30{border-color:#facc154d}.border-yellow-500\/20{border-color:#eab30833}.border-yellow-600\/50{border-color:#ca8a0480}.border-yellow-600\/60{border-color:#ca8a0499}.border-yellow-800{--tw-border-opacity: 1;border-color:rgb(133 77 14 / var(--tw-border-opacity, 1))}.border-yellow-800\/40{border-color:#854d0e66}.border-yellow-900\/40{border-color:#713f1266}.bg-\[\#8e641a\]\/10{background-color:#8e641a1a}.bg-\[\#b8443c\]\/10{background-color:#b8443c1a}.bg-\[\#e4ebd6\]{--tw-bg-opacity: 1;background-color:rgb(228 235 214 / var(--tw-bg-opacity, 1))}.bg-\[\#e5ecd8\]{--tw-bg-opacity: 1;background-color:rgb(229 236 216 / var(--tw-bg-opacity, 1))}.bg-\[\#f0d9c8\]{--tw-bg-opacity: 1;background-color:rgb(240 217 200 / var(--tw-bg-opacity, 1))}.bg-\[\#f5e9df\]{--tw-bg-opacity: 1;background-color:rgb(245 233 223 / var(--tw-bg-opacity, 1))}.bg-\[\#f8e8e0\]{--tw-bg-opacity: 1;background-color:rgb(248 232 224 / var(--tw-bg-opacity, 1))}.bg-accent{--tw-bg-opacity: 1;background-color:rgb(184 92 52 / var(--tw-bg-opacity, 1))}.bg-accent\/10{background-color:#b85c341a}.bg-accent\/15{background-color:#b85c3426}.bg-accent\/20{background-color:#b85c3433}.bg-accent\/\[0\.06\]{background-color:#b85c340f}.bg-amber-100\/40{background-color:#fef3c766}.bg-amber-400{--tw-bg-opacity: 1;background-color:rgb(251 191 36 / var(--tw-bg-opacity, 1))}.bg-amber-400\/10{background-color:#fbbf241a}.bg-amber-400\/15{background-color:#fbbf2426}.bg-amber-400\/20{background-color:#fbbf2433}.bg-amber-500\/10{background-color:#f59e0b1a}.bg-amber-500\/20{background-color:#f59e0b33}.bg-amber-500\/5{background-color:#f59e0b0d}.bg-amber-950\/10{background-color:#451a031a}.bg-amber-950\/50{background-color:#451a0380}.bg-amber-950\/60{background-color:#451a0399}.bg-bg{--tw-bg-opacity: 1;background-color:rgb(246 239 225 / var(--tw-bg-opacity, 1))}.bg-bg-elev{--tw-bg-opacity: 1;background-color:rgb(239 230 211 / var(--tw-bg-opacity, 1))}.bg-bg-elev\/40{background-color:#efe6d366}.bg-bg-elev\/50{background-color:#efe6d380}.bg-bg-elev\/60{background-color:#efe6d399}.bg-bg-elev\/80{background-color:#efe6d3cc}.bg-bg-elev\/85{background-color:#efe6d3d9}.bg-bg-hi{--tw-bg-opacity: 1;background-color:rgb(251 246 236 / var(--tw-bg-opacity, 1))}.bg-bg-hi\/40{background-color:#fbf6ec66}.bg-bg\/40{background-color:#f6efe166}.bg-black\/50{background-color:#00000080}.bg-black\/60{background-color:#0009}.bg-black\/65{background-color:#000000a6}.bg-blue-400{--tw-bg-opacity: 1;background-color:rgb(96 165 250 / var(--tw-bg-opacity, 1))}.bg-blue-500\/10{background-color:#3b82f61a}.bg-blue-600{--tw-bg-opacity: 1;background-color:rgb(37 99 235 / var(--tw-bg-opacity, 1))}.bg-blue-950\/30{background-color:#1725544d}.bg-butter{--tw-bg-opacity: 1;background-color:rgb(228 184 90 / var(--tw-bg-opacity, 1))}.bg-butter\/20{background-color:#e4b85a33}.bg-butter\/25{background-color:#e4b85a40}.bg-butter\/30{background-color:#e4b85a4d}.bg-current{background-color:currentColor}.bg-cyan-500\/10{background-color:#06b6d41a}.bg-cyan-500\/70{background-color:#06b6d4b3}.bg-emerald-400{--tw-bg-opacity: 1;background-color:rgb(52 211 153 / var(--tw-bg-opacity, 1))}.bg-fg{--tw-bg-opacity: 1;background-color:rgb(42 34 26 / var(--tw-bg-opacity, 1))}.bg-fg-faint{--tw-bg-opacity: 1;background-color:rgb(138 122 96 / var(--tw-bg-opacity, 1))}.bg-fg-faint\/10{background-color:#8a7a601a}.bg-fg-faint\/40{background-color:#8a7a6066}.bg-fg\/5{background-color:#2a221a0d}.bg-green-500{--tw-bg-opacity: 1;background-color:rgb(34 197 94 / var(--tw-bg-opacity, 1))}.bg-green-500\/10{background-color:#22c55e1a}.bg-green-900\/30{background-color:#14532d4d}.bg-green-950\/50{background-color:#052e1680}.bg-hive-plum{--tw-bg-opacity: 1;background-color:rgb(138 90 110 / var(--tw-bg-opacity, 1))}.bg-hive-slate{--tw-bg-opacity: 1;background-color:rgb(95 111 134 / var(--tw-bg-opacity, 1))}.bg-hive-teal{--tw-bg-opacity: 1;background-color:rgb(79 125 114 / var(--tw-bg-opacity, 1))}.bg-honey{--tw-bg-opacity: 1;background-color:rgb(211 162 60 / var(--tw-bg-opacity, 1))}.bg-honey\/10{background-color:#d3a23c1a}.bg-honey\/15{background-color:#d3a23c26}.bg-line{--tw-bg-opacity: 1;background-color:rgb(224 211 184 / var(--tw-bg-opacity, 1))}.bg-orange-500\/10{background-color:#f973161a}.bg-orange-950\/50{background-color:#43140780}.bg-pink-500\/10{background-color:#ec48991a}.bg-purple-500\/10{background-color:#a855f71a}.bg-purple-500\/70{background-color:#a855f7b3}.bg-purple-950\/30{background-color:#3b07644d}.bg-red-400{--tw-bg-opacity: 1;background-color:rgb(248 113 113 / var(--tw-bg-opacity, 1))}.bg-red-500{--tw-bg-opacity: 1;background-color:rgb(239 68 68 / var(--tw-bg-opacity, 1))}.bg-red-500\/10{background-color:#ef44441a}.bg-red-500\/5{background-color:#ef44440d}.bg-red-600{--tw-bg-opacity: 1;background-color:rgb(220 38 38 / var(--tw-bg-opacity, 1))}.bg-red-900\/20{background-color:#7f1d1d33}.bg-red-900\/30{background-color:#7f1d1d4d}.bg-red-950{--tw-bg-opacity: 1;background-color:rgb(69 10 10 / var(--tw-bg-opacity, 1))}.bg-red-950\/10{background-color:#450a0a1a}.bg-red-950\/20{background-color:#450a0a33}.bg-red-950\/30{background-color:#450a0a4d}.bg-red-950\/40{background-color:#450a0a66}.bg-red-950\/50{background-color:#450a0a80}.bg-red-950\/60{background-color:#450a0a99}.bg-red-950\/95{background-color:#450a0af2}.bg-rule{--tw-bg-opacity: 1;background-color:rgb(217 201 168 / var(--tw-bg-opacity, 1))}.bg-sage{--tw-bg-opacity: 1;background-color:rgb(111 125 82 / var(--tw-bg-opacity, 1))}.bg-sage\/10{background-color:#6f7d521a}.bg-sage\/15{background-color:#6f7d5226}.bg-sage\/20{background-color:#6f7d5233}.bg-sage\/25{background-color:#6f7d5240}.bg-transparent{background-color:transparent}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.bg-yellow-400{--tw-bg-opacity: 1;background-color:rgb(250 204 21 / var(--tw-bg-opacity, 1))}.bg-yellow-400\/15{background-color:#facc1526}.bg-yellow-500\/10{background-color:#eab3081a}.bg-yellow-500\/5{background-color:#eab3080d}.bg-yellow-950\/20{background-color:#42200633}.bg-yellow-950\/30{background-color:#4220064d}.bg-zinc-500{--tw-bg-opacity: 1;background-color:rgb(113 113 122 / var(--tw-bg-opacity, 1))}.object-contain{-o-object-fit:contain;object-fit:contain}.p-0{padding:0}.p-0\.5{padding:.125rem}.p-1{padding:.25rem}.p-1\.5{padding:.375rem}.p-2{padding:.5rem}.p-2\.5{padding:.625rem}.p-3{padding:.75rem}.p-3\.5{padding:.875rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.px-0{padding-left:0;padding-right:0}.px-0\.5{padding-left:.125rem;padding-right:.125rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-10{padding-left:2.5rem;padding-right:2.5rem}.px-14{padding-left:3.5rem;padding-right:3.5rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-3\.5{padding-left:.875rem;padding-right:.875rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.px-8{padding-left:2rem;padding-right:2rem}.px-9{padding-left:2.25rem;padding-right:2.25rem}.px-\[18px\]{padding-left:18px;padding-right:18px}.px-\[22px\]{padding-left:22px;padding-right:22px}.px-\[9px\]{padding-left:9px;padding-right:9px}.py-0{padding-top:0;padding-bottom:0}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-10{padding-top:2.5rem;padding-bottom:2.5rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-16{padding-top:4rem;padding-bottom:4rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-3\.5{padding-top:.875rem;padding-bottom:.875rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.py-9{padding-top:2.25rem;padding-bottom:2.25rem}.py-\[14px\]{padding-top:14px;padding-bottom:14px}.py-\[15px\]{padding-top:15px;padding-bottom:15px}.py-\[18px\]{padding-top:18px;padding-bottom:18px}.py-\[22px\]{padding-top:22px;padding-bottom:22px}.py-\[3px\]{padding-top:3px;padding-bottom:3px}.py-\[7px\]{padding-top:7px;padding-bottom:7px}.py-\[9px\]{padding-top:9px;padding-bottom:9px}.py-px{padding-top:1px;padding-bottom:1px}.pb-0{padding-bottom:0}.pb-1{padding-bottom:.25rem}.pb-1\.5{padding-bottom:.375rem}.pb-2{padding-bottom:.5rem}.pb-3{padding-bottom:.75rem}.pb-4{padding-bottom:1rem}.pb-5{padding-bottom:1.25rem}.pb-6{padding-bottom:1.5rem}.pb-7{padding-bottom:1.75rem}.pb-\[10px\]{padding-bottom:10px}.pb-\[15px\]{padding-bottom:15px}.pl-1{padding-left:.25rem}.pl-12{padding-left:3rem}.pl-2{padding-left:.5rem}.pl-3{padding-left:.75rem}.pl-4{padding-left:1rem}.pl-5{padding-left:1.25rem}.pl-9{padding-left:2.25rem}.pl-\[3\.75rem\]{padding-left:3.75rem}.pr-2{padding-right:.5rem}.pr-3{padding-right:.75rem}.pt-0{padding-top:0}.pt-0\.5{padding-top:.125rem}.pt-1{padding-top:.25rem}.pt-1\.5{padding-top:.375rem}.pt-2{padding-top:.5rem}.pt-3{padding-top:.75rem}.pt-3\.5{padding-top:.875rem}.pt-4{padding-top:1rem}.pt-6{padding-top:1.5rem}.pt-7{padding-top:1.75rem}.pt-\[12vh\]{padding-top:12vh}.pt-\[14px\]{padding-top:14px}.pt-\[15px\]{padding-top:15px}.pt-\[15vh\]{padding-top:15vh}.pt-\[8vh\]{padding-top:8vh}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.font-mono{font-family:IBM Plex Mono,JetBrains Mono,ui-monospace,SFMono-Regular,Menlo,monospace}.font-sans{font-family:Geist,system-ui,sans-serif}.font-serif{font-family:Newsreader,Georgia,serif}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-\[10\.5px\]{font-size:10.5px}.text-\[10px\]{font-size:10px}.text-\[11\.5px\]{font-size:11.5px}.text-\[11px\]{font-size:11px}.text-\[12\.5px\]{font-size:12.5px}.text-\[12px\]{font-size:12px}.text-\[13\.5px\]{font-size:13.5px}.text-\[13px\]{font-size:13px}.text-\[14\.5px\]{font-size:14.5px}.text-\[14px\]{font-size:14px}.text-\[15px\]{font-size:15px}.text-\[17px\]{font-size:17px}.text-\[18px\]{font-size:18px}.text-\[19px\]{font-size:19px}.text-\[22px\]{font-size:22px}.text-\[30px\]{font-size:30px}.text-\[34px\]{font-size:34px}.text-\[38px\]{font-size:38px}.text-\[40px\]{font-size:40px}.text-\[9px\]{font-size:9px}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.capitalize{text-transform:capitalize}.normal-case{text-transform:none}.italic{font-style:italic}.not-italic{font-style:normal}.tabular-nums{--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction)}.leading-5{line-height:1.25rem}.leading-\[1\.1\]{line-height:1.1}.leading-\[1\.45\]{line-height:1.45}.leading-\[1\.4\]{line-height:1.4}.leading-\[1\.55\]{line-height:1.55}.leading-\[1\.5\]{line-height:1.5}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.leading-snug{line-height:1.375}.leading-tight{line-height:1.25}.tracking-\[-0\.01em\]{letter-spacing:-.01em}.tracking-\[0\.01em\]{letter-spacing:.01em}.tracking-\[0\.06em\]{letter-spacing:.06em}.tracking-\[0\.07em\]{letter-spacing:.07em}.tracking-\[0\.08em\]{letter-spacing:.08em}.tracking-\[0\.3em\]{letter-spacing:.3em}.tracking-\[0\.6px\]{letter-spacing:.6px}.tracking-\[0\.7px\]{letter-spacing:.7px}.tracking-\[0\.8px\]{letter-spacing:.8px}.tracking-\[6px\]{letter-spacing:6px}.tracking-normal{letter-spacing:0em}.tracking-tight{letter-spacing:-.025em}.tracking-wide{letter-spacing:.025em}.tracking-wider{letter-spacing:.05em}.tracking-widest{letter-spacing:.1em}.\!text-sage{--tw-text-opacity: 1 !important;color:rgb(111 125 82 / var(--tw-text-opacity, 1))!important}.text-\[\#7a5416\]{--tw-text-opacity: 1;color:rgb(122 84 22 / var(--tw-text-opacity, 1))}.text-\[\#8a2f28\]{--tw-text-opacity: 1;color:rgb(138 47 40 / var(--tw-text-opacity, 1))}.text-\[\#9a3f1f\]{--tw-text-opacity: 1;color:rgb(154 63 31 / var(--tw-text-opacity, 1))}.text-accent{--tw-text-opacity: 1;color:rgb(184 92 52 / var(--tw-text-opacity, 1))}.text-accent\/80{color:#b85c34cc}.text-accent\/90{color:#b85c34e6}.text-amber-200{--tw-text-opacity: 1;color:rgb(253 230 138 / var(--tw-text-opacity, 1))}.text-amber-300{--tw-text-opacity: 1;color:rgb(252 211 77 / var(--tw-text-opacity, 1))}.text-amber-400{--tw-text-opacity: 1;color:rgb(251 191 36 / var(--tw-text-opacity, 1))}.text-amber-400\/70{color:#fbbf24b3}.text-amber-700{--tw-text-opacity: 1;color:rgb(180 83 9 / var(--tw-text-opacity, 1))}.text-bg{--tw-text-opacity: 1;color:rgb(246 239 225 / var(--tw-text-opacity, 1))}.text-blue-300\/90{color:#93c5fde6}.text-blue-400{--tw-text-opacity: 1;color:rgb(96 165 250 / var(--tw-text-opacity, 1))}.text-blue-400\/80{color:#60a5facc}.text-butter{--tw-text-opacity: 1;color:rgb(228 184 90 / var(--tw-text-opacity, 1))}.text-cyan-400{--tw-text-opacity: 1;color:rgb(34 211 238 / var(--tw-text-opacity, 1))}.text-fg{--tw-text-opacity: 1;color:rgb(42 34 26 / var(--tw-text-opacity, 1))}.text-fg-dim{--tw-text-opacity: 1;color:rgb(91 74 54 / var(--tw-text-opacity, 1))}.text-fg-faint{--tw-text-opacity: 1;color:rgb(138 122 96 / var(--tw-text-opacity, 1))}.text-fg-faint\/30{color:#8a7a604d}.text-fg-faint\/40{color:#8a7a6066}.text-fg-faint\/50{color:#8a7a6080}.text-fg-faint\/60{color:#8a7a6099}.text-fg-faint\/70{color:#8a7a60b3}.text-fg\/40{color:#2a221a66}.text-fg\/50{color:#2a221a80}.text-fg\/70{color:#2a221ab3}.text-fg\/85{color:#2a221ad9}.text-green-200{--tw-text-opacity: 1;color:rgb(187 247 208 / var(--tw-text-opacity, 1))}.text-green-300{--tw-text-opacity: 1;color:rgb(134 239 172 / var(--tw-text-opacity, 1))}.text-green-400{--tw-text-opacity: 1;color:rgb(74 222 128 / var(--tw-text-opacity, 1))}.text-green-400\/70{color:#4ade80b3}.text-green-500{--tw-text-opacity: 1;color:rgb(34 197 94 / var(--tw-text-opacity, 1))}.text-green-500\/70{color:#22c55eb3}.text-hive-plum{--tw-text-opacity: 1;color:rgb(138 90 110 / var(--tw-text-opacity, 1))}.text-hive-slate{--tw-text-opacity: 1;color:rgb(95 111 134 / var(--tw-text-opacity, 1))}.text-hive-teal{--tw-text-opacity: 1;color:rgb(79 125 114 / var(--tw-text-opacity, 1))}.text-honey-dark{--tw-text-opacity: 1;color:rgb(154 108 18 / var(--tw-text-opacity, 1))}.text-orange-200{--tw-text-opacity: 1;color:rgb(254 215 170 / var(--tw-text-opacity, 1))}.text-orange-400{--tw-text-opacity: 1;color:rgb(251 146 60 / var(--tw-text-opacity, 1))}.text-pink-400{--tw-text-opacity: 1;color:rgb(244 114 182 / var(--tw-text-opacity, 1))}.text-purple-400{--tw-text-opacity: 1;color:rgb(192 132 252 / var(--tw-text-opacity, 1))}.text-purple-400\/80{color:#c084fccc}.text-red-200{--tw-text-opacity: 1;color:rgb(254 202 202 / var(--tw-text-opacity, 1))}.text-red-300{--tw-text-opacity: 1;color:rgb(252 165 165 / var(--tw-text-opacity, 1))}.text-red-300\/70{color:#fca5a5b3}.text-red-400{--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity, 1))}.text-red-400\/60{color:#f8717199}.text-red-400\/70{color:#f87171b3}.text-red-400\/80{color:#f87171cc}.text-red-500{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.text-sage{--tw-text-opacity: 1;color:rgb(111 125 82 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.text-yellow-200{--tw-text-opacity: 1;color:rgb(254 240 138 / var(--tw-text-opacity, 1))}.text-yellow-300{--tw-text-opacity: 1;color:rgb(253 224 71 / var(--tw-text-opacity, 1))}.text-yellow-400{--tw-text-opacity: 1;color:rgb(250 204 21 / var(--tw-text-opacity, 1))}.text-yellow-400\/80{color:#facc15cc}.text-yellow-500\/70{color:#eab308b3}.text-yellow-500\/80{color:#eab308cc}.text-yellow-500\/90{color:#eab308e6}.underline{text-decoration-line:underline}.line-through{text-decoration-line:line-through}.no-underline{text-decoration-line:none}.underline-offset-2{text-underline-offset:2px}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.placeholder-fg-faint::-moz-placeholder{--tw-placeholder-opacity: 1;color:rgb(138 122 96 / var(--tw-placeholder-opacity, 1))}.placeholder-fg-faint::placeholder{--tw-placeholder-opacity: 1;color:rgb(138 122 96 / var(--tw-placeholder-opacity, 1))}.accent-accent{accent-color:#b85c34}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-40{opacity:.4}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.opacity-80{opacity:.8}.shadow{--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / .1), 0 1px 2px -1px rgb(0 0 0 / .1);--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-2xl{--tw-shadow: 0 25px 50px -12px rgb(0 0 0 / .25);--tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[0_0_0_1px_rgba\(184\,92\,52\,0\.25\)\]{--tw-shadow: 0 0 0 1px rgba(184,92,52,.25);--tw-shadow-colored: 0 0 0 1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[0_2px_0_\#e0d3b8\]{--tw-shadow: 0 2px 0 #e0d3b8;--tw-shadow-colored: 0 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[0_2px_0_rgba\(0\,0\,0\,0\.18\)\]{--tw-shadow: 0 2px 0 rgba(0,0,0,.18);--tw-shadow-colored: 0 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.outline{outline-style:solid}.ring{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-1{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-2{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-inset{--tw-ring-inset: inset}.ring-accent{--tw-ring-opacity: 1;--tw-ring-color: rgb(184 92 52 / var(--tw-ring-opacity, 1))}.ring-accent\/20{--tw-ring-color: rgb(184 92 52 / .2)}.ring-butter{--tw-ring-opacity: 1;--tw-ring-color: rgb(228 184 90 / var(--tw-ring-opacity, 1))}.ring-hive-plum{--tw-ring-opacity: 1;--tw-ring-color: rgb(138 90 110 / var(--tw-ring-opacity, 1))}.ring-hive-slate{--tw-ring-opacity: 1;--tw-ring-color: rgb(95 111 134 / var(--tw-ring-opacity, 1))}.ring-hive-teal{--tw-ring-opacity: 1;--tw-ring-color: rgb(79 125 114 / var(--tw-ring-opacity, 1))}.ring-line{--tw-ring-opacity: 1;--tw-ring-color: rgb(224 211 184 / var(--tw-ring-opacity, 1))}.ring-red-400{--tw-ring-opacity: 1;--tw-ring-color: rgb(248 113 113 / var(--tw-ring-opacity, 1))}.ring-red-500{--tw-ring-opacity: 1;--tw-ring-color: rgb(239 68 68 / var(--tw-ring-opacity, 1))}.ring-sage{--tw-ring-opacity: 1;--tw-ring-color: rgb(111 125 82 / var(--tw-ring-opacity, 1))}.blur{--tw-blur: blur(8px);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.\!filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)!important}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur{--tw-backdrop-blur: blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.backdrop-blur-sm{--tw-backdrop-blur: blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-\[width\]{transition-property:width;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-shadow{transition-property:box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-1000{transition-duration:1s}.duration-150{transition-duration:.15s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.duration-75{transition-duration:75ms}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.\[writing-mode\:vertical-rl\]{writing-mode:vertical-rl}.burn-proj-stripe{background-image:repeating-linear-gradient(45deg,#6f7d52 0px,#6f7d52 4px,transparent 4px,transparent 8px)}.tiptap-content h1{font-size:1.5rem;font-weight:600;margin:.75rem 0 .5rem;line-height:1.3;color:#2a221a;font-family:Newsreader,Georgia,serif}.tiptap-content h2{font-size:1.25rem;font-weight:600;margin:.75rem 0 .4rem;line-height:1.3;color:#2a221a;font-family:Newsreader,Georgia,serif}.tiptap-content h3{font-size:1.1rem;font-weight:600;margin:.6rem 0 .3rem;line-height:1.3;color:#2a221a;font-family:Newsreader,Georgia,serif}.tiptap-content p{margin:.4rem 0;color:#2a221a;line-height:1.6}.tiptap-content ul{list-style:disc;padding-left:1.5rem;margin:.4rem 0;color:#2a221a}.tiptap-content ol{list-style:decimal;padding-left:1.5rem;margin:.4rem 0;color:#2a221a}.tiptap-content li{margin:.15rem 0}.tiptap-content blockquote{border-left:3px solid #d9c9a8;padding-left:.75rem;color:#5b4a36;margin:.4rem 0;font-style:italic}.tiptap-content code{background:#fbf6ec;color:#b85c34;padding:.1em .35em;border-radius:3px;font-size:.88em;font-family:IBM Plex Mono,ui-monospace,monospace;border:1px solid #e0d3b8}.tiptap-content pre{background:#fbf6ec;color:#2a221a;padding:.75rem 1rem;border-radius:6px;overflow-x:auto;margin:.5rem 0;font-size:.85em;font-family:IBM Plex Mono,ui-monospace,monospace;border:1px solid #e0d3b8}.tiptap-content pre code{background:none;padding:0;color:inherit;font-size:inherit;border:0}.tiptap-content a{color:#b85c34;text-decoration:underline}.tiptap-content hr{border:none;border-top:1px solid #d9c9a8;margin:.75rem 0}.tiptap-content strong{font-weight:600}.tiptap-content em{font-style:italic}.tiptap-content:focus{outline:none}.markdown-body{color:#2a221a}.markdown-body h1{font-size:1.9rem;font-weight:600;margin:1.4rem 0 .7rem;line-height:1.25;font-family:Newsreader,Georgia,serif}.markdown-body h2{font-size:1.5rem;font-weight:600;margin:1.2rem 0 .6rem;line-height:1.3;font-family:Newsreader,Georgia,serif;border-bottom:1px solid #e6dcc4;padding-bottom:.2rem}.markdown-body h3{font-size:1.2rem;font-weight:600;margin:1rem 0 .4rem;line-height:1.3;font-family:Newsreader,Georgia,serif}.markdown-body h4,.markdown-body h5,.markdown-body h6{font-weight:600;margin:.8rem 0 .3rem;font-family:Newsreader,Georgia,serif}.markdown-body p{margin:.6rem 0;line-height:1.7}.markdown-body ul{list-style:disc;padding-left:1.6rem;margin:.5rem 0}.markdown-body ol{list-style:decimal;padding-left:1.6rem;margin:.5rem 0}.markdown-body li{margin:.2rem 0;line-height:1.6}.markdown-body li>input[type=checkbox]{margin-right:.4rem}.markdown-body blockquote{border-left:3px solid #d9c9a8;padding-left:.85rem;color:#5b4a36;margin:.6rem 0;font-style:italic}.markdown-body code{background:#fbf6ec;color:#b85c34;padding:.1em .35em;border-radius:3px;font-size:.88em;font-family:IBM Plex Mono,ui-monospace,monospace;border:1px solid #e0d3b8}.markdown-body pre{background:#fbf6ec;color:#2a221a;padding:.8rem 1rem;border-radius:6px;overflow-x:auto;margin:.7rem 0;font-size:.85em;font-family:IBM Plex Mono,ui-monospace,monospace;border:1px solid #e0d3b8}.markdown-body pre code{background:none;padding:0;color:inherit;font-size:inherit;border:0}.markdown-body a{color:#b85c34;text-decoration:underline}.markdown-body hr{border:none;border-top:1px solid #d9c9a8;margin:1rem 0}.markdown-body strong{font-weight:600}.markdown-body em{font-style:italic}.markdown-body img{max-width:100%;border-radius:4px}.markdown-body table{border-collapse:collapse;margin:.7rem 0;font-size:.9em}.markdown-body th,.markdown-body td{border:1px solid #e0d3b8;padding:.35rem .6rem;text-align:left}.markdown-body th{background:#f1e7d2;font-weight:600}.markdown-body h1[id],.markdown-body h2[id],.markdown-body h3[id]{scroll-margin-top:1rem}.prose-chat--plan{border:1px solid #8e641a40;border-radius:14px;background:#8e641a0d}.prose-chat--plan ul,.prose-chat--plan ol{list-style:none;padding-left:1.4rem;margin:.4rem 0}.prose-chat--plan li{position:relative;margin:.3rem 0}.prose-chat--plan li:before{content:"✓";position:absolute;left:-1.4rem;color:#4d7a4d;font-weight:600}html,body,#root{height:100%;margin:0;overflow:hidden}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-track{background:#efe6d3}::-webkit-scrollbar-thumb{background:#d9c9a8;border-radius:5px}::-webkit-scrollbar-thumb:hover{background:#c8b88f}.placeholder\:text-fg-dim::-moz-placeholder{--tw-text-opacity: 1;color:rgb(91 74 54 / var(--tw-text-opacity, 1))}.placeholder\:text-fg-dim::placeholder{--tw-text-opacity: 1;color:rgb(91 74 54 / var(--tw-text-opacity, 1))}.placeholder\:text-fg-faint::-moz-placeholder{--tw-text-opacity: 1;color:rgb(138 122 96 / var(--tw-text-opacity, 1))}.placeholder\:text-fg-faint::placeholder{--tw-text-opacity: 1;color:rgb(138 122 96 / var(--tw-text-opacity, 1))}.placeholder\:text-fg-faint\/40::-moz-placeholder{color:#8a7a6066}.placeholder\:text-fg-faint\/40::placeholder{color:#8a7a6066}.last\:mb-0:last-child{margin-bottom:0}.last\:border-0:last-child{border-width:0px}.even\:bg-bg-elev\/40:nth-child(2n){background-color:#efe6d366}.hover\:border-accent:hover{--tw-border-opacity: 1;border-color:rgb(184 92 52 / var(--tw-border-opacity, 1))}.hover\:border-accent\/30:hover{border-color:#b85c344d}.hover\:border-accent\/40:hover{border-color:#b85c3466}.hover\:border-accent\/60:hover{border-color:#b85c3499}.hover\:border-amber-400\/60:hover{border-color:#fbbf2499}.hover\:border-fg-faint:hover{--tw-border-opacity: 1;border-color:rgb(138 122 96 / var(--tw-border-opacity, 1))}.hover\:border-red-400\/50:hover{border-color:#f8717180}.hover\:border-red-400\/60:hover{border-color:#f8717199}.hover\:bg-\[\#b8443c\]\/10:hover{background-color:#b8443c1a}.hover\:bg-accent:hover{--tw-bg-opacity: 1;background-color:rgb(184 92 52 / var(--tw-bg-opacity, 1))}.hover\:bg-accent\/25:hover{background-color:#b85c3440}.hover\:bg-accent\/40:hover{background-color:#b85c3466}.hover\:bg-accent\/80:hover{background-color:#b85c34cc}.hover\:bg-accent\/90:hover{background-color:#b85c34e6}.hover\:bg-amber-900\/20:hover{background-color:#78350f33}.hover\:bg-bg:hover{--tw-bg-opacity: 1;background-color:rgb(246 239 225 / var(--tw-bg-opacity, 1))}.hover\:bg-bg-elev:hover{--tw-bg-opacity: 1;background-color:rgb(239 230 211 / var(--tw-bg-opacity, 1))}.hover\:bg-bg-elev\/20:hover{background-color:#efe6d333}.hover\:bg-bg-elev\/50:hover{background-color:#efe6d380}.hover\:bg-bg-hi:hover{--tw-bg-opacity: 1;background-color:rgb(251 246 236 / var(--tw-bg-opacity, 1))}.hover\:bg-bg-hi\/40:hover{background-color:#fbf6ec66}.hover\:bg-bg-hi\/50:hover{background-color:#fbf6ec80}.hover\:bg-bg-hi\/60:hover{background-color:#fbf6ec99}.hover\:bg-bg-hi\/70:hover{background-color:#fbf6ecb3}.hover\:bg-bg-hi\/80:hover{background-color:#fbf6eccc}.hover\:bg-bg\/40:hover{background-color:#f6efe166}.hover\:bg-blue-500:hover{--tw-bg-opacity: 1;background-color:rgb(59 130 246 / var(--tw-bg-opacity, 1))}.hover\:bg-blue-900\/40:hover{background-color:#1e3a8a66}.hover\:bg-red-500:hover{--tw-bg-opacity: 1;background-color:rgb(239 68 68 / var(--tw-bg-opacity, 1))}.hover\:bg-red-900\/20:hover{background-color:#7f1d1d33}.hover\:bg-red-950\/30:hover{background-color:#450a0a4d}.hover\:bg-transparent:hover{background-color:transparent}.hover\:bg-white\/10:hover{background-color:#ffffff1a}.hover\:bg-white\/5:hover{background-color:#ffffff0d}.hover\:bg-yellow-600:hover{--tw-bg-opacity: 1;background-color:rgb(202 138 4 / var(--tw-bg-opacity, 1))}.hover\:text-accent:hover{--tw-text-opacity: 1;color:rgb(184 92 52 / var(--tw-text-opacity, 1))}.hover\:text-amber-300:hover{--tw-text-opacity: 1;color:rgb(252 211 77 / var(--tw-text-opacity, 1))}.hover\:text-amber-400:hover{--tw-text-opacity: 1;color:rgb(251 191 36 / var(--tw-text-opacity, 1))}.hover\:text-bg:hover{--tw-text-opacity: 1;color:rgb(246 239 225 / var(--tw-text-opacity, 1))}.hover\:text-fg:hover{--tw-text-opacity: 1;color:rgb(42 34 26 / var(--tw-text-opacity, 1))}.hover\:text-fg-dim:hover{--tw-text-opacity: 1;color:rgb(91 74 54 / var(--tw-text-opacity, 1))}.hover\:text-red-300:hover{--tw-text-opacity: 1;color:rgb(252 165 165 / var(--tw-text-opacity, 1))}.hover\:text-red-400:hover{--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity, 1))}.hover\:text-red-500:hover{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.hover\:text-yellow-300:hover{--tw-text-opacity: 1;color:rgb(253 224 71 / var(--tw-text-opacity, 1))}.hover\:underline:hover{text-decoration-line:underline}.hover\:no-underline:hover{text-decoration-line:none}.hover\:opacity-100:hover{opacity:1}.hover\:opacity-80:hover{opacity:.8}.hover\:opacity-90:hover{opacity:.9}.hover\:shadow-sm:hover{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.hover\:brightness-125:hover{--tw-brightness: brightness(1.25);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.focus\:border-accent:focus{--tw-border-opacity: 1;border-color:rgb(184 92 52 / var(--tw-border-opacity, 1))}.focus\:border-accent\/40:focus{border-color:#b85c3466}.focus\:border-accent\/50:focus{border-color:#b85c3480}.focus\:border-accent\/60:focus{border-color:#b85c3499}.focus\:border-fg-faint:focus{--tw-border-opacity: 1;border-color:rgb(138 122 96 / var(--tw-border-opacity, 1))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-1:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-inset:focus{--tw-ring-inset: inset}.focus\:ring-accent:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(184 92 52 / var(--tw-ring-opacity, 1))}.active\:bg-accent\/60:active{background-color:#b85c3499}.disabled\:cursor-default:disabled{cursor:default}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-30:disabled{opacity:.3}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}.disabled\:hover\:bg-transparent:hover:disabled{background-color:transparent}.group:hover .group-hover\:block{display:block}.group:hover .group-hover\:hidden{display:none}.group:hover .group-hover\:opacity-100{opacity:1}.group:hover .group-hover\:opacity-70{opacity:.7}@media(min-width:768px){.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(min-width:1280px){.xl\:sticky{position:sticky}.xl\:top-6{top:1.5rem}.xl\:grid-cols-\[minmax\(0\,1fr\)_340px\]{grid-template-columns:minmax(0,1fr) 340px}.xl\:grid-cols-\[minmax\(0\,1fr\)_380px\]{grid-template-columns:minmax(0,1fr) 380px}.xl\:p-9{padding:2.25rem}}.\[\&\>span\]\:w-full>span{width:100%}.\[\&_p\]\:max-w-lg p{max-width:32rem}.\[\&_pre\]\:max-w-none pre{max-width:none}
|
package/dist/index.html
CHANGED
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
8
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
9
|
<link href="https://fonts.googleapis.com/css2?family=Newsreader:ital,opsz,wght@0,6..72,400;0,6..72,500;0,6..72,600;0,6..72,700;1,6..72,400&family=Geist:wght@300;400;500;600;700&family=IBM+Plex+Mono:wght@400;500;600&display=swap" rel="stylesheet">
|
|
10
|
-
<script type="module" crossorigin src="./assets/index-
|
|
10
|
+
<script type="module" crossorigin src="./assets/index-2Om-ouz6.js"></script>
|
|
11
11
|
<link rel="modulepreload" crossorigin href="./assets/monaco-editor-BW5C4Iv1.js">
|
|
12
12
|
<link rel="stylesheet" crossorigin href="./assets/monaco-editor-BTnBOi8r.css">
|
|
13
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
13
|
+
<link rel="stylesheet" crossorigin href="./assets/index-DeIJ8SM5.css">
|
|
14
14
|
</head>
|
|
15
15
|
<body class="bg-bg text-fg font-sans antialiased">
|
|
16
16
|
<div id="root"></div>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-code-session-manager",
|
|
3
|
-
"version": "0.35.
|
|
3
|
+
"version": "0.35.2",
|
|
4
4
|
"description": "Local cockpit for the Claude Code CLI — multi-tab terminal, full config surface, scheduler, voice dictation, and live observability.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/main/index.cjs",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "session-manager-dev",
|
|
3
|
-
"description": "The default end-to-end development skillset for the Claude Code Session Manager: decompose work into scheduler PRDs (/develop
|
|
3
|
+
"description": "The default end-to-end development skillset for the Claude Code Session Manager: decompose work into scheduler PRDs (/develop), triage cross-project feedback (/process-feedback, /my-feedback), roll up operational status and optimize the North-Star KPI (/project-status, /optimize-kpi, /local-project-health), gate with review (/requesting-code-review, /security-review), and document how the project works (/explain-to-me). Together with the session-manager scheduler these form a closed develop → queue → track → review → status → improve loop.",
|
|
4
4
|
"version": "0.1.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Stanislav Georgiev",
|
|
@@ -21,8 +21,7 @@ arrives via `/process-feedback`, which evaluates it and then calls this skill. E
|
|
|
21
21
|
here on is identical regardless of who asked.
|
|
22
22
|
|
|
23
23
|
**Never** hand-implement the work inline in chat, and never restate rules that live elsewhere:
|
|
24
|
-
|
|
25
|
-
Reference them; don't fork them.
|
|
24
|
+
the engineering rules belong to `standards.md`. Reference it; don't fork it.
|
|
26
25
|
|
|
27
26
|
## Standards (single source of truth)
|
|
28
27
|
|
|
@@ -48,12 +47,10 @@ can't load skills.
|
|
|
48
47
|
reuse (per the API-reuse standard — search before writing new code), the test command, and
|
|
49
48
|
any constraints. Capture exact file paths and signatures; they go straight into the PRDs.
|
|
50
49
|
|
|
51
|
-
3. **Decompose into a series of SMALL, bounded PRDs.**
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
highest in-use number deterministically — never eyeball or narrow-grep the `ls`** (a
|
|
56
|
-
narrowed pattern like `'^10[0-9]'` silently misses `110+` and collides):
|
|
50
|
+
3. **Decompose into a series of SMALL, bounded PRDs.** Split a large ask into multiple PRDs and
|
|
51
|
+
sequence them. To pick each PRD's `NN` (parallel group), **compute the highest in-use number
|
|
52
|
+
deterministically — never eyeball or narrow-grep the `ls`** (a narrowed pattern like
|
|
53
|
+
`'^10[0-9]'` silently misses `110+` and collides):
|
|
57
54
|
```bash
|
|
58
55
|
ls ~/.claude/session-manager/scheduled-plans/prds/ | grep -oE '^[0-9]+' | sort -n | uniq | tail -5
|
|
59
56
|
```
|
|
@@ -62,7 +59,93 @@ can't load skills.
|
|
|
62
59
|
is unrelated to every existing group. Record each cross-PRD dependency in the dependent
|
|
63
60
|
PRD's notes.
|
|
64
61
|
|
|
65
|
-
|
|
62
|
+
### PRD structure and location
|
|
63
|
+
|
|
64
|
+
Each individual PRD must follow this structure — this is `/develop`'s single authority on
|
|
65
|
+
one PRD's structure, location, and scope sizing (the engineering rules stay separate, in
|
|
66
|
+
`standards.md`).
|
|
67
|
+
|
|
68
|
+
You are writing a PRD that will be executed by the user's session-manager scheduler — a
|
|
69
|
+
system that runs `claude -p <prd-body> --dangerously-skip-permissions` jobs around 5-hour
|
|
70
|
+
token-window resets, with auto-pause on rate-limit and auto-resume.
|
|
71
|
+
|
|
72
|
+
**Canonical location — non-negotiable.** PRDs MUST be written to:
|
|
73
|
+
```
|
|
74
|
+
~/.claude/session-manager/scheduled-plans/prds/<NN>-<kebab-slug>.md
|
|
75
|
+
```
|
|
76
|
+
**Anywhere else doesn't get scheduled.** If you write to `data/prds/`, `docs/prds/`, or the
|
|
77
|
+
project root, the scheduler will not see it and the user loses their token-budget-managed
|
|
78
|
+
execution. There is exactly one queue for all projects — that's intentional, because the
|
|
79
|
+
5-hour token budget is global across all of the user's Claude work. The `~` expands to
|
|
80
|
+
`os.homedir()` so the same convention works for any user on any machine.
|
|
81
|
+
|
|
82
|
+
**Filename rules.** `NN` is the 2-digit zero-padded parallel group (picked per the `ls`
|
|
83
|
+
command above — same `NN` as an independent sibling, or next free `NN` = max+1 when this PRD
|
|
84
|
+
hard-depends on prior work). `<kebab-slug>` is a short, descriptive kebab-case identifier
|
|
85
|
+
(e.g. `voice-commands-send-cancel`, `ticker-velocity-mcp`), kept under 60 chars. Verify your
|
|
86
|
+
chosen filename doesn't already exist before writing.
|
|
87
|
+
|
|
88
|
+
**Required frontmatter:**
|
|
89
|
+
```yaml
|
|
90
|
+
---
|
|
91
|
+
title: <one-line human-readable title>
|
|
92
|
+
cwd: <path to target project — where claude -p will run>
|
|
93
|
+
estimateMinutes: <integer wall-clock estimate>
|
|
94
|
+
---
|
|
95
|
+
```
|
|
96
|
+
`cwd` is critical — without it the job runs in the scheduler's default cwd (session-manager).
|
|
97
|
+
Always set it to the path of the project the work targets, written as `~/Projects/<repo>`
|
|
98
|
+
(the parser expands `~` to `os.homedir()` at ingest, so the same PRD works on any machine).
|
|
99
|
+
Avoid hardcoding an absolute home path (`/home/<you>/Projects/<repo>`); it breaks on any
|
|
100
|
+
machine with a different home directory.
|
|
101
|
+
|
|
102
|
+
**Required body sections, in this order:**
|
|
103
|
+
```markdown
|
|
104
|
+
# Goal
|
|
105
|
+
|
|
106
|
+
<2-4 sentences. What the executor will build and why it matters. NO "as a user I want to"
|
|
107
|
+
framing. Concrete: name the function, the file, the user-visible change.>
|
|
108
|
+
|
|
109
|
+
# Acceptance criteria
|
|
110
|
+
|
|
111
|
+
- [ ] <each line is a verifiable check the executor can run after building>
|
|
112
|
+
- [ ] <include explicit file paths, function names, expected behavior>
|
|
113
|
+
- [ ] a bounded test command passes, e.g. `timeout 300 npm run typecheck` / `pytest -x` /
|
|
114
|
+
`cargo check` (the run-before-done / never-end-on-red rule lives in standards.md →
|
|
115
|
+
Execution discipline; the AC just has to name the command).
|
|
116
|
+
|
|
117
|
+
# Implementation notes
|
|
118
|
+
|
|
119
|
+
<file paths the executor will need to read first; the architectural pattern to follow; any
|
|
120
|
+
non-obvious constraints. Be specific. Quote function signatures if it saves the executor a
|
|
121
|
+
Read call.>
|
|
122
|
+
|
|
123
|
+
# Out of scope
|
|
124
|
+
|
|
125
|
+
<short bulleted list of what NOT to build, to prevent scope creep>
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
**Self-containment is load-bearing.** The executor (`claude -p`) starts with NO conversation
|
|
129
|
+
context — only the PRD body and the project files. So: include exact file paths (e.g.
|
|
130
|
+
`src/main/index.cjs:142`); quote function signatures or relevant code blocks if the executor
|
|
131
|
+
would have to grep for them; name the libraries/patterns to use (e.g. "use the existing
|
|
132
|
+
`validatePath` helper in `config.cjs`"); don't reference "the conversation we just had" or
|
|
133
|
+
"the design we discussed"; if a PRD depends on another PRD's output, say so in
|
|
134
|
+
`# Implementation notes` AND give it a higher `NN` so it queues after.
|
|
135
|
+
|
|
136
|
+
**Scope sizing — keep it SMALL (data-driven, 2026-06).** Across 400+ real runs the median
|
|
137
|
+
PRD finishes in **~7 minutes**, p90 **~21 min**, p99 **~66 min** — yet authored
|
|
138
|
+
`estimateMinutes` ran 5–8× too high. Oversized scoping anchors PRDs too big and pushes them
|
|
139
|
+
into the rare >60-min tail where ~100% of true hangs live (deploy poll-loops, unbounded e2e
|
|
140
|
+
suites). Target ~15 minutes of wall-clock work per PRD — **hard ceiling ~30 min; if you
|
|
141
|
+
project more, SPLIT** into sequential `NN` PRDs and document the dependency in each. Set
|
|
142
|
+
`estimateMinutes` realistically: **p50≈8, p90≈21** — don't write 60/90, it's almost always
|
|
143
|
+
wrong and hides real outliers. Each execution costs ~$0.50–$2; smaller PRDs = smaller blast
|
|
144
|
+
radius when a run is rate-limited, timed out, or killed. **`rateLimited` exit-1 is NOT a
|
|
145
|
+
failure** — it's the scheduler's designed auto-pause; the job auto-resumes at the next
|
|
146
|
+
window reset. Don't add retry logic for it.
|
|
147
|
+
|
|
148
|
+
4. **Emit each PRD** to the canonical path and structure above, then **append `## Engineering
|
|
66
149
|
standards` and paste the full contents of `standards.md` verbatim.** This is the
|
|
67
150
|
load-bearing step — it's the only way the standards (incl. Execution discipline) reach the
|
|
68
151
|
headless run. Honor the `PRD_AUTHORING.md` §10 pre-queue checklist.
|
|
@@ -99,7 +182,6 @@ single definition of "tracked to done" for both entry paths.
|
|
|
99
182
|
|
|
100
183
|
## References (reuse, don't duplicate)
|
|
101
184
|
|
|
102
|
-
- `~/.claude/skills/prd/SKILL.md` — canonical single-PRD structure, location, filename rules, scope sizing.
|
|
103
185
|
- `~/.claude/session-manager/scheduled-plans/PRD_AUTHORING.md` — the §1–§10 safety rules.
|
|
104
186
|
- `~/.claude/skills/develop/standards.md` — the engineering + execution-discipline rules inlined into every PRD.
|
|
105
187
|
- `test-driven-development`, `systematic-debugging` — interactive dev sessions.
|
|
@@ -110,3 +192,6 @@ single definition of "tracked to done" for both entry paths.
|
|
|
110
192
|
- Write PRD files directly, then confirm — don't draft them inline in chat for review first.
|
|
111
193
|
- Don't combine unrelated features into one PRD. One focused, completable unit each.
|
|
112
194
|
- Don't add a `parallelGroup` frontmatter key — the filename `NN-` prefix drives grouping.
|
|
195
|
+
- Don't write a PRD to `data/prds/`, `docs/prds/`, the project's own folder, or anywhere outside
|
|
196
|
+
the canonical path. The user has explicitly flagged this as a recurring problem.
|
|
197
|
+
- Don't leave `cwd` unset hoping for the default. Be explicit.
|
|
@@ -62,7 +62,7 @@ If you can't state it in the present tense without a date or a PRD, cut it.
|
|
|
62
62
|
- **The Skill Map** — `HUMAN_LEARN/SKILL_MAP.html`, a **separate, dedicated** page
|
|
63
63
|
(NOT a section of index.html) that visualizes the *local-development skill chain*:
|
|
64
64
|
the two intakes (interactive human prompt; agent feedback via `/process-feedback`)
|
|
65
|
-
converging on `/develop`, which
|
|
65
|
+
converging on `/develop`, which owns PRD authoring + reads `standards.md`, queues onto the
|
|
66
66
|
scheduler, and gates with review/verify — plus `/my-feedback` outbound. It is the
|
|
67
67
|
"how I build on this project" companion to index.html's "how this project works."
|
|
68
68
|
index.html links to it from the nav; it links back.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* chat-cancel-terminal.test.cjs — regression for the "stuck thinking" hang.
|
|
3
|
+
*
|
|
4
|
+
* Bug (2026-07-05): cancelling an active chat run SIGTERM'd the child, but the
|
|
5
|
+
* exit handler's `if (!gotResult && !killed)` guard skipped every broadcast
|
|
6
|
+
* because `killed === true`. No terminal IPC event ever reached the renderer,
|
|
7
|
+
* so the chat store stayed `running:true` forever — disabled textarea, endless
|
|
8
|
+
* "running…" spinner, unresponsive chat UI.
|
|
9
|
+
*
|
|
10
|
+
* Fix: every run emits EXACTLY ONE terminal event (complete/needs-input/error),
|
|
11
|
+
* and the exit path emits a fallback `chat:run:error` when a run settled
|
|
12
|
+
* without one (cancel, crash, silent exit). This test drives the REAL spawn
|
|
13
|
+
* path (via SM_CLAUDE_BIN pointing at a stub process) and asserts a terminal
|
|
14
|
+
* event is broadcast on cancel.
|
|
15
|
+
*
|
|
16
|
+
* Run: timeout 120 node --test src/main/__tests__/chat-cancel-terminal.test.cjs
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
'use strict';
|
|
20
|
+
|
|
21
|
+
delete process.env.SM_CHAT_CONCURRENCY;
|
|
22
|
+
|
|
23
|
+
const { test } = require('node:test');
|
|
24
|
+
const assert = require('node:assert/strict');
|
|
25
|
+
const fs = require('node:fs');
|
|
26
|
+
const os = require('node:os');
|
|
27
|
+
const path = require('node:path');
|
|
28
|
+
|
|
29
|
+
// A stub "claude" that ignores stdin/args and stays alive until killed —
|
|
30
|
+
// mimics a long-running headless run so cancel() has something to SIGTERM.
|
|
31
|
+
// Shebang + chmod makes it directly spawnable as a single executable (spawn
|
|
32
|
+
// does not split a path on spaces, so SM_CLAUDE_BIN must be one binary).
|
|
33
|
+
const stubPath = path.join(os.tmpdir(), `sm-claude-stub-${process.pid}.cjs`);
|
|
34
|
+
fs.writeFileSync(
|
|
35
|
+
stubPath,
|
|
36
|
+
`#!${process.execPath}\nsetInterval(() => {}, 1000);\n`,
|
|
37
|
+
{ mode: 0o755 },
|
|
38
|
+
);
|
|
39
|
+
process.env.SM_CLAUDE_BIN = stubPath;
|
|
40
|
+
|
|
41
|
+
const cr = require('../chatRunner.cjs');
|
|
42
|
+
|
|
43
|
+
const tick = () => new Promise((r) => setImmediate(r));
|
|
44
|
+
|
|
45
|
+
test('cancelling an ACTIVE run broadcasts a terminal event (unsticks the UI)', async () => {
|
|
46
|
+
const events = [];
|
|
47
|
+
// Fake BrowserWindow that captures every broadcast.
|
|
48
|
+
cr.attachWindow({
|
|
49
|
+
isDestroyed: () => false,
|
|
50
|
+
webContents: {
|
|
51
|
+
isDestroyed: () => false,
|
|
52
|
+
send: (channel, payload) => events.push({ channel, payload }),
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
cr.run({ tabId: 'T', sessionId: 'S', prompt: 'hello', cwd: process.cwd(), resume: false });
|
|
57
|
+
|
|
58
|
+
// Let the spawn happen and started event fire.
|
|
59
|
+
for (let i = 0; i < 6; i++) await tick();
|
|
60
|
+
assert.ok(
|
|
61
|
+
events.some((e) => e.channel === 'chat:run:started'),
|
|
62
|
+
'started event should fire once the run launches',
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
cr.cancel('T');
|
|
66
|
+
|
|
67
|
+
// Wait for SIGTERM → child exit → fallback terminal broadcast.
|
|
68
|
+
for (let i = 0; i < 40 && !events.some((e) => isTerminal(e.channel)); i++) {
|
|
69
|
+
await new Promise((r) => setTimeout(r, 25));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const terminal = events.filter((e) => isTerminal(e.channel));
|
|
73
|
+
assert.equal(terminal.length, 1, 'exactly one terminal event is emitted');
|
|
74
|
+
assert.equal(terminal[0].channel, 'chat:run:error', 'cancel surfaces as an error turn');
|
|
75
|
+
assert.match(terminal[0].payload.message, /cancel/i, 'message names the cancellation');
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
function isTerminal(channel) {
|
|
79
|
+
return (
|
|
80
|
+
channel === 'chat:run:complete' ||
|
|
81
|
+
channel === 'chat:run:needs-input' ||
|
|
82
|
+
channel === 'chat:run:error'
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
test.after(() => {
|
|
87
|
+
try { fs.unlinkSync(stubPath); } catch { /* already gone */ }
|
|
88
|
+
delete process.env.SM_CLAUDE_BIN;
|
|
89
|
+
});
|
package/src/main/chatRunner.cjs
CHANGED
|
@@ -174,6 +174,20 @@ function executeRun({ tabId, sessionId, prompt, cwd, resume }) {
|
|
|
174
174
|
resolve();
|
|
175
175
|
};
|
|
176
176
|
|
|
177
|
+
// Guarantees the renderer receives EXACTLY ONE terminal event
|
|
178
|
+
// (complete / needs-input / error) per run. Without this, a cancelled or
|
|
179
|
+
// killed run exits with `killed=true` and the old exit-guard broadcast
|
|
180
|
+
// nothing — leaving the chat store stuck at running:true forever (disabled
|
|
181
|
+
// textarea, "running…" spinner, unresponsive UI). Every terminal broadcast
|
|
182
|
+
// funnels through here so the exit path can emit a fallback only when the
|
|
183
|
+
// run settled without one.
|
|
184
|
+
let terminalSent = false;
|
|
185
|
+
const emitTerminal = (channel, payload) => {
|
|
186
|
+
if (terminalSent) return;
|
|
187
|
+
terminalSent = true;
|
|
188
|
+
broadcast(channel, payload);
|
|
189
|
+
};
|
|
190
|
+
|
|
177
191
|
const claudeBin = resolveClaudeBin();
|
|
178
192
|
const childEnv = cleanChildEnv({ PATH: pathWithUserBins() });
|
|
179
193
|
|
|
@@ -209,7 +223,7 @@ function executeRun({ tabId, sessionId, prompt, cwd, resume }) {
|
|
|
209
223
|
detached: true, // own process group so killTree can SIGTERM descendants
|
|
210
224
|
});
|
|
211
225
|
} catch (err) {
|
|
212
|
-
|
|
226
|
+
emitTerminal('chat:run:error', {
|
|
213
227
|
tabId,
|
|
214
228
|
sessionId,
|
|
215
229
|
message: `spawn failed: ${err?.message ?? String(err)}`,
|
|
@@ -237,7 +251,7 @@ function executeRun({ tabId, sessionId, prompt, cwd, resume }) {
|
|
|
237
251
|
|
|
238
252
|
// Hard wall-clock ceiling — SIGTERM + SIGKILL on expiry
|
|
239
253
|
const killTimer = setTimeout(() => {
|
|
240
|
-
|
|
254
|
+
emitTerminal('chat:run:error', {
|
|
241
255
|
tabId,
|
|
242
256
|
sessionId,
|
|
243
257
|
message: 'run exceeded 30-minute wall-clock ceiling',
|
|
@@ -253,7 +267,6 @@ function executeRun({ tabId, sessionId, prompt, cwd, resume }) {
|
|
|
253
267
|
let lineBuffer = '';
|
|
254
268
|
let finalAssistantText = '';
|
|
255
269
|
let stderrBuffer = '';
|
|
256
|
-
let gotResult = false;
|
|
257
270
|
|
|
258
271
|
const processLine = (line) => {
|
|
259
272
|
if (!line) return;
|
|
@@ -273,7 +286,6 @@ function executeRun({ tabId, sessionId, prompt, cwd, resume }) {
|
|
|
273
286
|
}
|
|
274
287
|
}
|
|
275
288
|
} else if (event.type === 'result') {
|
|
276
|
-
gotResult = true;
|
|
277
289
|
// Use the authoritative `result` field when available; fall back to
|
|
278
290
|
// accumulated assistant text (same content, different source).
|
|
279
291
|
const text = typeof event.result === 'string' ? event.result : finalAssistantText;
|
|
@@ -281,21 +293,21 @@ function executeRun({ tabId, sessionId, prompt, cwd, resume }) {
|
|
|
281
293
|
if (event.subtype === 'success') {
|
|
282
294
|
const signal = parseStopSignal(text);
|
|
283
295
|
if (signal) {
|
|
284
|
-
|
|
296
|
+
emitTerminal('chat:run:needs-input', {
|
|
285
297
|
tabId,
|
|
286
298
|
sessionId,
|
|
287
299
|
questions: signal.questions,
|
|
288
300
|
raw: text,
|
|
289
301
|
});
|
|
290
302
|
} else {
|
|
291
|
-
|
|
303
|
+
emitTerminal('chat:run:complete', { tabId, sessionId, finalMessage: text });
|
|
292
304
|
// Record durable exchange off the hot path — UI must not wait on Haiku
|
|
293
305
|
recordExchange({ sessionId, cwd, prompt, result: text }).catch((err) => {
|
|
294
306
|
console.error('[chatRunner] recordExchange failed:', err?.message ?? err);
|
|
295
307
|
});
|
|
296
308
|
}
|
|
297
309
|
} else {
|
|
298
|
-
|
|
310
|
+
emitTerminal('chat:run:error', {
|
|
299
311
|
tabId,
|
|
300
312
|
sessionId,
|
|
301
313
|
message: `run ended with result subtype: ${event.subtype ?? 'unknown'}`,
|
|
@@ -319,7 +331,7 @@ function executeRun({ tabId, sessionId, prompt, cwd, resume }) {
|
|
|
319
331
|
|
|
320
332
|
child.on('error', (err) => {
|
|
321
333
|
clearTimeout(killTimer);
|
|
322
|
-
|
|
334
|
+
emitTerminal('chat:run:error', {
|
|
323
335
|
tabId,
|
|
324
336
|
sessionId,
|
|
325
337
|
message: err?.message ?? String(err),
|
|
@@ -332,15 +344,28 @@ function executeRun({ tabId, sessionId, prompt, cwd, resume }) {
|
|
|
332
344
|
// Flush any partial line that didn't end with \n
|
|
333
345
|
if (lineBuffer.trim()) processLine(lineBuffer.trim());
|
|
334
346
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
347
|
+
// Emit a fallback terminal event for any run that ended without one — a
|
|
348
|
+
// cancel/SIGTERM (killed=true), a crash before a result, or a silent
|
|
349
|
+
// exit. `emitTerminal` no-ops if the run already sent complete/needs-
|
|
350
|
+
// input/error, so the normal success path never double-fires. This is
|
|
351
|
+
// what unsticks the renderer's running flag after Cancel.
|
|
352
|
+
if (!terminalSent) {
|
|
353
|
+
if (killed) {
|
|
354
|
+
emitTerminal('chat:run:error', {
|
|
355
|
+
tabId,
|
|
356
|
+
sessionId,
|
|
357
|
+
message: 'run cancelled',
|
|
358
|
+
});
|
|
359
|
+
} else {
|
|
360
|
+
const errDetail = stderrBuffer.trim()
|
|
361
|
+
? `: ${stderrBuffer.trim().slice(0, 300)}`
|
|
362
|
+
: '';
|
|
363
|
+
emitTerminal('chat:run:error', {
|
|
364
|
+
tabId,
|
|
365
|
+
sessionId,
|
|
366
|
+
message: `process exited without a result event (code=${code} signal=${signal})${errDetail}`,
|
|
367
|
+
});
|
|
368
|
+
}
|
|
344
369
|
}
|
|
345
370
|
settle();
|
|
346
371
|
});
|
|
@@ -18,6 +18,9 @@ const os = require('node:os');
|
|
|
18
18
|
let cached = null;
|
|
19
19
|
|
|
20
20
|
function resolveClaudeBin() {
|
|
21
|
+
// Explicit override wins and is never cached — lets operators pin a binary
|
|
22
|
+
// and lets tests point the runner at a controllable stub process.
|
|
23
|
+
if (process.env.SM_CLAUDE_BIN) return process.env.SM_CLAUDE_BIN;
|
|
21
24
|
if (cached) return cached;
|
|
22
25
|
// Merged candidate list — was forked in scheduler vs pluginInstall before.
|
|
23
26
|
const home = os.homedir();
|