claude-code-session-manager 0.122.0 → 0.122.1
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/{AgentLibrary-BmJ8hIPw.js → AgentLibrary-C2qUX9WU.js} +1 -1
- package/dist/assets/{Button-BS4kmz4p.js → Button-ssBzvFha.js} +1 -1
- package/dist/assets/{DataModel-DZHBZrfL.js → DataModel-CENoTvc2.js} +1 -1
- package/dist/assets/{History-pg00b2Gd.js → History-BRdRp1J_.js} +1 -1
- package/dist/assets/{Hooks-BTEs0UZY.js → Hooks--hiGPBQy.js} +1 -1
- package/dist/assets/{Library-DuaJ-VSn.js → Library-0XYvkhh2.js} +1 -1
- package/dist/assets/{ListDetail-Cud72s-O.js → ListDetail-CkKXAM59.js} +1 -1
- package/dist/assets/{McpServers-Dy-wnG_X.js → McpServers-CCjHSwFm.js} +1 -1
- package/dist/assets/{Memory-Bs1T1Jo7.js → Memory-C7RXoVO4.js} +1 -1
- package/dist/assets/{Panel-8UhLXEOW.js → Panel-C92O_aAH.js} +1 -1
- package/dist/assets/{Permissions-BfwzvmBS.js → Permissions-DuTJ1FUb.js} +1 -1
- package/dist/assets/{Plugins-McjyvvKh.js → Plugins-DSXsP4hM.js} +2 -2
- package/dist/assets/{ProvenanceBadge-D0Ov_6WJ.js → ProvenanceBadge-CWdDkU1m.js} +1 -1
- package/dist/assets/{RemoteMachines-gOlFTvWq.js → RemoteMachines-BFmbIGpW.js} +1 -1
- package/dist/assets/{SaveBar-Cd6hJR6K.js → SaveBar-ob2dJJjH.js} +1 -1
- package/dist/assets/{Scheduler-BZXKqYJP.js → Scheduler-Du4HgPKY.js} +1 -1
- package/dist/assets/{ScopeSwitcher-C24ysV1K.js → ScopeSwitcher-Dv_6M_Ci.js} +1 -1
- package/dist/assets/{Settings-DWnN2qxn.js → Settings-DMoI0cqB.js} +1 -1
- package/dist/assets/{SkillReferenceGraph-BsWuiTbw.js → SkillReferenceGraph-Dx1Qs8Y0.js} +1 -1
- package/dist/assets/{Skills-6pHn6glu.js → Skills-DYWQTQB1.js} +1 -1
- package/dist/assets/{SystemPrompt-DT0LBH-K.js → SystemPrompt-Df0IfOuI.js} +1 -1
- package/dist/assets/{TagLibrary-DbJ0zbYL.js → TagLibrary-BuMsGx-2.js} +1 -1
- package/dist/assets/{TiptapBody-C4kIvIMH.js → TiptapBody-Cihe5er3.js} +1 -1
- package/dist/assets/{Toggle-pP19zlyk.js → Toggle-CpYVC8bF.js} +1 -1
- package/dist/assets/{ViewTabs-CpzN8e5I.js → ViewTabs-C3FN6P_C.js} +1 -1
- package/dist/assets/{historyTotals-Caq78bb5.js → historyTotals-C4Rs37Cd.js} +1 -1
- package/dist/assets/{index-Bjtguv6I.js → index-S-F5jp_h.js} +3 -3
- package/dist/assets/{settingsSchema-CC2ySu3d.js → settingsSchema-BZcdzHTQ.js} +1 -1
- package/dist/assets/{skillFrontmatter-hDhNo8jE.js → skillFrontmatter-EfNERt4b.js} +1 -1
- package/dist/assets/{useAgentsDirWatch-BuOtY25U.js → useAgentsDirWatch-BfbrFvB3.js} +1 -1
- package/dist/assets/{useRemotePeers-CNQmRBpt.js → useRemotePeers-CKVakQPc.js} +1 -1
- package/dist/index.html +1 -1
- package/package.json +1 -1
- package/plugins/session-manager-dev/skills/develop/SKILL.md +1 -0
- package/scripts/scheduler-mcp-server.cjs +18 -4
- package/src/main/build-info.json +4 -4
- package/src/main/lib/mcpToolCatalog.cjs +5 -7
- package/src/main/lib/prd/prdCreate.cjs +45 -0
- package/src/main/scheduler.cjs +13 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
import{aF as b,ap as n,S as N,a_ as O}from"./index-Bjtguv6I.js";import{r as K}from"./claude-settings-schema-COigsajx.js";function G({node:e,targetScope:r,onOverride:s,schema:a,rootLabel:m}){const[f,x]=b.useState(""),[u,o]=b.useState(!0),g=[],d=e.kind==="object"&&Object.keys(e.children).length===0,y=((a==null?void 0:a.rootKeys())??[]).length>0;return n.jsxs("div",{className:"h-full flex flex-col",children:[n.jsxs("div",{className:"shrink-0 border-b border-line bg-bg-elev px-3 py-1.5 flex items-center gap-2 text-xs",children:[n.jsxs("span",{className:"text-fg-faint",children:["merged · overrides → ",n.jsx("span",{className:"text-fg-dim",children:N[r].label})]}),y&&n.jsxs("label",{className:"flex items-center gap-1 text-fg-faint cursor-pointer",children:[n.jsx("input",{type:"checkbox",checked:u,onChange:t=>o(t.target.checked),className:"accent-accent"}),"show unset keys"]}),n.jsx("div",{className:"flex-1"}),n.jsx("input",{value:f,onChange:t=>x(t.target.value),placeholder:"filter keys or descriptions…",className:"bg-bg border border-line rounded px-2 py-0.5 text-xs text-fg w-56"})]}),n.jsx("div",{className:"flex-1 overflow-auto px-3 py-2 font-mono text-xs",children:d&&!u?n.jsx("div",{className:"text-fg-faint italic px-2 py-4",children:"no settings resolved — all scope files empty or missing"}):n.jsx(E,{node:e,path:g,label:m??"(root)",targetScope:r,onOverride:s,filter:f,depth:0,schema:a,showGhosts:u,defaultOpen:!0})})]})}function E(e){return e.node.kind==="object"?n.jsx(P,{...e,node:e.node}):e.node.kind==="array"?n.jsx(J,{...e,node:e.node}):n.jsx(R,{...e,node:e.node})}function A(e,r){return r.trim()?e.toLowerCase().includes(r.toLowerCase()):!0}function w(e,r,s){return!!(!s.trim()||e.some(a=>A(a,s))||r!=null&&r.description&&A(r.description,s))}function P({node:e,path:r,label:s,targetScope:a,onOverride:m,filter:f,depth:x,schema:u,showGhosts:o,defaultOpen:g}){const[d,h]=b.useState(g??x<2),y=(u==null?void 0:u.at(r))??null,t=new Set(Object.keys(e.children)),i=o?(y==null?void 0:y.knownChildren)??[]:[],c=Array.from(new Set([...t,...i])).sort(),l=b.useMemo(()=>f.trim()?c.filter(p=>{const v=(u==null?void 0:u.at([...r,p]))??null;return w([...r,p],v,f)?!0:t.has(p)?L(e.children[p],[...r,p],f,u):!1}):c,[c.join(","),f,e,r.join("."),u]);if(f.trim()&&l.length===0&&!w(r,y,f))return null;if(r.length===0)return n.jsx("div",{children:l.map(p=>j(p))});return n.jsxs("div",{children:[n.jsxs("div",{className:"flex items-center gap-1 py-0.5 hover:bg-bg-elev/50 rounded cursor-pointer",style:{paddingLeft:x*14},onClick:()=>h(!d),children:[n.jsx("span",{className:"text-fg-faint w-3 shrink-0",children:d?"▾":"▸"}),n.jsx("span",{className:"text-fg",children:s}),n.jsxs("span",{className:"text-fg-faint",children:[" {",t.size,i.length>t.size?`/${new Set([...t,...i]).size}`:"","}"]}),(y==null?void 0:y.description)&&n.jsxs("span",{className:"text-fg-faint truncate max-w-md",title:y.description,children:["— ",y.description]})]}),d&&l.map(p=>j(p))]});function j(p){if(t.has(p))return n.jsx(E,{node:e.children[p],path:[...r,p],label:p,targetScope:a,onOverride:m,filter:f,depth:x+1,schema:u,showGhosts:o},p);const v=(u==null?void 0:u.at([...r,p]))??null;return v?n.jsx(_,{path:[...r,p],label:p,info:v,targetScope:a,onSet:m,depth:x+1,filter:f},p):null}}function L(e,r,s,a){const m=(a==null?void 0:a.at(r))??null;if(w(r,m,s))return!0;if(e.kind!=="object")return!1;for(const f of Object.keys(e.children))if(L(e.children[f],[...r,f],s,a))return!0;return!1}function J({node:e,path:r,label:s,filter:a,depth:m,schema:f}){const[x,u]=b.useState(!0),o=(f==null?void 0:f.at(r))??null;return w(r,o,a)?n.jsxs("div",{children:[n.jsxs("div",{className:"flex items-center gap-1 py-0.5 hover:bg-bg-elev/50 rounded cursor-pointer",style:{paddingLeft:m*14},onClick:()=>u(!x),children:[n.jsx("span",{className:"text-fg-faint w-3 shrink-0",children:x?"▾":"▸"}),n.jsx("span",{className:"text-fg",children:s}),n.jsxs("span",{className:"text-fg-faint",children:[" [",e.items.length,"]"]}),n.jsx(S,{tone:"warn",children:"accumulated"}),(o==null?void 0:o.description)&&n.jsxs("span",{className:"text-fg-faint truncate max-w-md",title:o.description,children:["— ",o.description]})]}),x&&e.items.map((g,d)=>n.jsxs("div",{className:"flex items-start gap-2 py-0.5",style:{paddingLeft:(m+1)*14},children:[n.jsx("span",{className:"text-fg-faint w-3 shrink-0"}),n.jsxs("span",{className:"text-fg-faint",children:[d,":"]}),n.jsx("span",{className:"text-fg-dim truncate max-w-xl",children:k(g.value)}),n.jsx(C,{scope:g.fromScope})]},d))]}):null}function R({node:e,path:r,label:s,targetScope:a,onOverride:m,filter:f,depth:x,schema:u}){const[o,g]=b.useState(!1),d=(u==null?void 0:u.at(r))??null;if(!w(r,d,f))return null;const h=e.winner!==a,y=e.shadowed.length>0;return n.jsxs("div",{children:[n.jsxs("div",{className:"group flex items-center gap-2 py-0.5 hover:bg-bg-elev/50 rounded",style:{paddingLeft:x*14},children:[n.jsx("span",{className:`w-3 shrink-0 ${y?"text-fg-faint cursor-pointer":""}`,onClick:()=>y&&g(!o),children:y?o?"▾":"▸":""}),n.jsxs("span",{className:"text-fg",children:[s,":"]}),n.jsx("span",{className:"text-fg-dim truncate max-w-md",children:k(e.value)}),n.jsx(C,{scope:e.winner}),(d==null?void 0:d.deprecated)&&n.jsx(S,{tone:"warn",children:"deprecated"}),(d==null?void 0:d.default)!==void 0&&I(e.value,d.default)&&n.jsx(S,{tone:"dim",children:"= default"}),e.typeMismatch&&n.jsx("span",{className:"text-yellow-500/80",title:"shadowed scopes have a different value type",children:"⚠"}),(d==null?void 0:d.description)&&n.jsxs("span",{className:"text-fg-faint truncate max-w-md",title:d.description,children:["— ",d.description]}),n.jsx("div",{className:"flex-1"}),(d==null?void 0:d.enum)&&n.jsx(F,{values:d.enum}),n.jsx("button",{disabled:!h,onClick:()=>m(r,e.value),className:`opacity-0 group-hover:opacity-100 px-1.5 py-0 text-[10px] border rounded transition-opacity ${h?"border-accent/50 text-accent hover:bg-accent hover:text-bg":"border-line text-fg-faint cursor-not-allowed"}`,title:h?`copy into ${N[a].label} draft`:`already winning in ${N[a].label}`,children:"override"})]}),o&&e.shadowed.map((t,i)=>n.jsxs("div",{className:"flex items-center gap-2 py-0.5 text-fg-faint line-through",style:{paddingLeft:(x+1)*14+12},children:[n.jsx("span",{children:"shadowed:"}),n.jsx("span",{className:"truncate max-w-xl",children:k(t.value)}),n.jsx(C,{scope:t.scope,dim:!0})]},i))]})}function _({path:e,label:r,info:s,targetScope:a,onSet:m,depth:f,filter:x}){if(!w(e,s,x))return null;const u=s.default!==void 0?s.default:M(s.type),o=Array.isArray(s.type)?s.type.join("|"):s.type??"?";return n.jsxs("div",{className:"group flex items-center gap-2 py-0.5 hover:bg-bg-elev/50 rounded opacity-60",style:{paddingLeft:f*14},children:[n.jsx("span",{className:"w-3 shrink-0"}),n.jsx("span",{className:"text-fg-dim",children:r}),n.jsx(S,{tone:"dim",children:o}),s.required&&n.jsx(S,{tone:"warn",children:"required"}),s.default!==void 0&&n.jsxs("span",{className:"text-fg-faint",children:["default: ",k(s.default)]}),s.description&&n.jsxs("span",{className:"text-fg-faint truncate max-w-md",title:s.description,children:["— ",s.description]}),n.jsx("div",{className:"flex-1"}),s.enum&&n.jsx(F,{values:s.enum}),n.jsx("button",{onClick:()=>m(e,u),className:"opacity-0 group-hover:opacity-100 px-1.5 py-0 text-[10px] border border-accent/50 rounded text-accent hover:bg-accent hover:text-bg transition-opacity",title:`write to ${N[a].label} draft`,children:"set"})]})}function I(e,r){return e===r?!0:typeof e!=typeof r?!1:e&&r&&typeof e=="object"?JSON.stringify(e)===JSON.stringify(r):!1}function M(e){switch(Array.isArray(e)?e[0]:e){case"boolean":return!1;case"integer":case"number":return 0;case"string":return"";case"array":return[];case"object":return{};case"null":return null;default:return null}}function k(e){if(typeof e=="string")return JSON.stringify(e);if(e===null)return"null";if(typeof e=="object"){const r=JSON.stringify(e);return r.length>100?r.slice(0,100)+"…":r}return String(e)}function C({scope:e,dim:r}){const s=e==="user"?"bg-bg-hi text-fg-dim border-line":e==="project"?"bg-blue-950/30 text-blue-400/80 border-blue-900/40":"bg-purple-950/30 text-purple-400/80 border-purple-900/40";return n.jsx("span",{className:`text-[10px] px-1 py-0 rounded border uppercase tracking-wide shrink-0 ${s} ${r?"opacity-60":""}`,children:N[e].label})}function S({children:e,tone:r="default"}){const s={default:"bg-bg-hi text-fg-dim border-line",warn:"bg-yellow-950/30 text-yellow-500/80 border-yellow-900/40",dim:"bg-bg-elev text-fg-faint border-line"}[r];return n.jsx("span",{className:`text-[10px] px-1 py-0 rounded border uppercase tracking-wide shrink-0 ${s}`,children:e})}function F({values:e}){const r=e.map(s=>String(s)).join(" | ");return n.jsxs("span",{className:"text-[10px] text-fg-faint truncate max-w-xs",title:`allowed: ${r}`,children:["∈ ",r.length>30?r.slice(0,30)+"…":r]})}function V(e,r,s){const a=O(o=>o.files),m=O(o=>o.loadJson),f=O(o=>o.watchFile),x=O(o=>o.unwatchFile),u=b.useMemo(()=>{const o={};for(const g of e.scopes){const d=e.resolve(g,r??"",s);d&&(o[g]=d)}return o},[e,r,s]);return b.useEffect(()=>{const o=Object.values(u).filter(Boolean);return o.forEach(g=>{a[g]||m(g),f(g)}),()=>{o.forEach(g=>x(g))}},[JSON.stringify(u)]),u}function B(e){const r=e??{},s={...r.$defs??{},...r.definitions??{}},a=t=>{if(!t)return{};if(!t.$ref)return x(t);const i=/^#\/(\$defs|definitions)\/(.+)$/.exec(t.$ref);if(!i)return x(t);const c=s[i[2]];return c?a({...c,...u(t)}):x(t)},m=new Set(["__proto__","constructor","prototype"]),f=t=>{if(!t)return{};const i={};for(const[c,l]of Object.entries(t))m.has(c)||(i[c]=l);return i},x=t=>{if(!t.allOf||t.allOf.length===0)return t;const i={...t};delete i.allOf;for(const c of t.allOf){const l=a(c);Object.assign(i,{properties:{...f(i.properties),...f(l.properties)},required:q([...i.required??[],...l.required??[]])}),!i.description&&l.description&&(i.description=l.description),i.default===void 0&&l.default!==void 0&&(i.default=l.default),!i.type&&l.type&&(i.type=l.type)}return i},u=t=>{const{$ref:i,...c}=t;return c},o=(t,i)=>{let c=a(t);for(const l of i){if(!c)return null;if(/^\d+$/.test(l)){const v=Array.isArray(c.items)?c.items[Number(l)]:c.items;c=v?a(v):null;continue}const j=c.properties;if(j&&!m.has(l)&&l in j){c=a(j[l]);continue}const p=c.additionalProperties;if(p&&typeof p=="object"){c=a(p);continue}return null}return c},g=(t,i,c)=>{if(!t)return null;const l={};if(t.description&&(l.description=t.description),t.type&&(l.type=t.type),t.default!==void 0&&(l.default=t.default),t.enum&&(l.enum=t.enum),t.const!==void 0&&(l.const=t.const),t.deprecated&&(l.deprecated=!0),t.examples&&(l.examples=t.examples),t.properties&&(l.knownChildren=Object.keys(t.properties)),c&&(i!=null&&i.includes(c))&&(l.required=!0),t.items&&!Array.isArray(t.items)){const j=a(t.items),p=g(j,void 0,null);p&&(l.itemsInfo=p)}return(t.additionalProperties===!0||typeof t.additionalProperties=="object")&&(l.open=!0),l},d=t=>i=>{if(i.length===0)return g(a(t),void 0,null);const c=o(t,i.slice(0,-1));if(!c)return null;const l=i[i.length-1],j=o(c,[l]);return g(j,c.required,l)},h=t=>{const i=a(t);return Object.keys(i.properties??{})},y=t=>({at:d(t),rootKeys:()=>h(t),rootedAt:i=>{const c=o(t,i);return y(c??{})}});return y(r)}function q(e){return Array.from(new Set(e))}let $=null;function D(){return $||($=B(K)),$}export{G as E,D as s,V as u};
|
|
1
|
+
import{aF as b,ap as n,S as N,a_ as O}from"./index-S-F5jp_h.js";import{r as K}from"./claude-settings-schema-COigsajx.js";function G({node:e,targetScope:r,onOverride:s,schema:a,rootLabel:m}){const[f,x]=b.useState(""),[u,o]=b.useState(!0),g=[],d=e.kind==="object"&&Object.keys(e.children).length===0,y=((a==null?void 0:a.rootKeys())??[]).length>0;return n.jsxs("div",{className:"h-full flex flex-col",children:[n.jsxs("div",{className:"shrink-0 border-b border-line bg-bg-elev px-3 py-1.5 flex items-center gap-2 text-xs",children:[n.jsxs("span",{className:"text-fg-faint",children:["merged · overrides → ",n.jsx("span",{className:"text-fg-dim",children:N[r].label})]}),y&&n.jsxs("label",{className:"flex items-center gap-1 text-fg-faint cursor-pointer",children:[n.jsx("input",{type:"checkbox",checked:u,onChange:t=>o(t.target.checked),className:"accent-accent"}),"show unset keys"]}),n.jsx("div",{className:"flex-1"}),n.jsx("input",{value:f,onChange:t=>x(t.target.value),placeholder:"filter keys or descriptions…",className:"bg-bg border border-line rounded px-2 py-0.5 text-xs text-fg w-56"})]}),n.jsx("div",{className:"flex-1 overflow-auto px-3 py-2 font-mono text-xs",children:d&&!u?n.jsx("div",{className:"text-fg-faint italic px-2 py-4",children:"no settings resolved — all scope files empty or missing"}):n.jsx(E,{node:e,path:g,label:m??"(root)",targetScope:r,onOverride:s,filter:f,depth:0,schema:a,showGhosts:u,defaultOpen:!0})})]})}function E(e){return e.node.kind==="object"?n.jsx(P,{...e,node:e.node}):e.node.kind==="array"?n.jsx(J,{...e,node:e.node}):n.jsx(R,{...e,node:e.node})}function A(e,r){return r.trim()?e.toLowerCase().includes(r.toLowerCase()):!0}function w(e,r,s){return!!(!s.trim()||e.some(a=>A(a,s))||r!=null&&r.description&&A(r.description,s))}function P({node:e,path:r,label:s,targetScope:a,onOverride:m,filter:f,depth:x,schema:u,showGhosts:o,defaultOpen:g}){const[d,h]=b.useState(g??x<2),y=(u==null?void 0:u.at(r))??null,t=new Set(Object.keys(e.children)),i=o?(y==null?void 0:y.knownChildren)??[]:[],c=Array.from(new Set([...t,...i])).sort(),l=b.useMemo(()=>f.trim()?c.filter(p=>{const v=(u==null?void 0:u.at([...r,p]))??null;return w([...r,p],v,f)?!0:t.has(p)?L(e.children[p],[...r,p],f,u):!1}):c,[c.join(","),f,e,r.join("."),u]);if(f.trim()&&l.length===0&&!w(r,y,f))return null;if(r.length===0)return n.jsx("div",{children:l.map(p=>j(p))});return n.jsxs("div",{children:[n.jsxs("div",{className:"flex items-center gap-1 py-0.5 hover:bg-bg-elev/50 rounded cursor-pointer",style:{paddingLeft:x*14},onClick:()=>h(!d),children:[n.jsx("span",{className:"text-fg-faint w-3 shrink-0",children:d?"▾":"▸"}),n.jsx("span",{className:"text-fg",children:s}),n.jsxs("span",{className:"text-fg-faint",children:[" {",t.size,i.length>t.size?`/${new Set([...t,...i]).size}`:"","}"]}),(y==null?void 0:y.description)&&n.jsxs("span",{className:"text-fg-faint truncate max-w-md",title:y.description,children:["— ",y.description]})]}),d&&l.map(p=>j(p))]});function j(p){if(t.has(p))return n.jsx(E,{node:e.children[p],path:[...r,p],label:p,targetScope:a,onOverride:m,filter:f,depth:x+1,schema:u,showGhosts:o},p);const v=(u==null?void 0:u.at([...r,p]))??null;return v?n.jsx(_,{path:[...r,p],label:p,info:v,targetScope:a,onSet:m,depth:x+1,filter:f},p):null}}function L(e,r,s,a){const m=(a==null?void 0:a.at(r))??null;if(w(r,m,s))return!0;if(e.kind!=="object")return!1;for(const f of Object.keys(e.children))if(L(e.children[f],[...r,f],s,a))return!0;return!1}function J({node:e,path:r,label:s,filter:a,depth:m,schema:f}){const[x,u]=b.useState(!0),o=(f==null?void 0:f.at(r))??null;return w(r,o,a)?n.jsxs("div",{children:[n.jsxs("div",{className:"flex items-center gap-1 py-0.5 hover:bg-bg-elev/50 rounded cursor-pointer",style:{paddingLeft:m*14},onClick:()=>u(!x),children:[n.jsx("span",{className:"text-fg-faint w-3 shrink-0",children:x?"▾":"▸"}),n.jsx("span",{className:"text-fg",children:s}),n.jsxs("span",{className:"text-fg-faint",children:[" [",e.items.length,"]"]}),n.jsx(S,{tone:"warn",children:"accumulated"}),(o==null?void 0:o.description)&&n.jsxs("span",{className:"text-fg-faint truncate max-w-md",title:o.description,children:["— ",o.description]})]}),x&&e.items.map((g,d)=>n.jsxs("div",{className:"flex items-start gap-2 py-0.5",style:{paddingLeft:(m+1)*14},children:[n.jsx("span",{className:"text-fg-faint w-3 shrink-0"}),n.jsxs("span",{className:"text-fg-faint",children:[d,":"]}),n.jsx("span",{className:"text-fg-dim truncate max-w-xl",children:k(g.value)}),n.jsx(C,{scope:g.fromScope})]},d))]}):null}function R({node:e,path:r,label:s,targetScope:a,onOverride:m,filter:f,depth:x,schema:u}){const[o,g]=b.useState(!1),d=(u==null?void 0:u.at(r))??null;if(!w(r,d,f))return null;const h=e.winner!==a,y=e.shadowed.length>0;return n.jsxs("div",{children:[n.jsxs("div",{className:"group flex items-center gap-2 py-0.5 hover:bg-bg-elev/50 rounded",style:{paddingLeft:x*14},children:[n.jsx("span",{className:`w-3 shrink-0 ${y?"text-fg-faint cursor-pointer":""}`,onClick:()=>y&&g(!o),children:y?o?"▾":"▸":""}),n.jsxs("span",{className:"text-fg",children:[s,":"]}),n.jsx("span",{className:"text-fg-dim truncate max-w-md",children:k(e.value)}),n.jsx(C,{scope:e.winner}),(d==null?void 0:d.deprecated)&&n.jsx(S,{tone:"warn",children:"deprecated"}),(d==null?void 0:d.default)!==void 0&&I(e.value,d.default)&&n.jsx(S,{tone:"dim",children:"= default"}),e.typeMismatch&&n.jsx("span",{className:"text-yellow-500/80",title:"shadowed scopes have a different value type",children:"⚠"}),(d==null?void 0:d.description)&&n.jsxs("span",{className:"text-fg-faint truncate max-w-md",title:d.description,children:["— ",d.description]}),n.jsx("div",{className:"flex-1"}),(d==null?void 0:d.enum)&&n.jsx(F,{values:d.enum}),n.jsx("button",{disabled:!h,onClick:()=>m(r,e.value),className:`opacity-0 group-hover:opacity-100 px-1.5 py-0 text-[10px] border rounded transition-opacity ${h?"border-accent/50 text-accent hover:bg-accent hover:text-bg":"border-line text-fg-faint cursor-not-allowed"}`,title:h?`copy into ${N[a].label} draft`:`already winning in ${N[a].label}`,children:"override"})]}),o&&e.shadowed.map((t,i)=>n.jsxs("div",{className:"flex items-center gap-2 py-0.5 text-fg-faint line-through",style:{paddingLeft:(x+1)*14+12},children:[n.jsx("span",{children:"shadowed:"}),n.jsx("span",{className:"truncate max-w-xl",children:k(t.value)}),n.jsx(C,{scope:t.scope,dim:!0})]},i))]})}function _({path:e,label:r,info:s,targetScope:a,onSet:m,depth:f,filter:x}){if(!w(e,s,x))return null;const u=s.default!==void 0?s.default:M(s.type),o=Array.isArray(s.type)?s.type.join("|"):s.type??"?";return n.jsxs("div",{className:"group flex items-center gap-2 py-0.5 hover:bg-bg-elev/50 rounded opacity-60",style:{paddingLeft:f*14},children:[n.jsx("span",{className:"w-3 shrink-0"}),n.jsx("span",{className:"text-fg-dim",children:r}),n.jsx(S,{tone:"dim",children:o}),s.required&&n.jsx(S,{tone:"warn",children:"required"}),s.default!==void 0&&n.jsxs("span",{className:"text-fg-faint",children:["default: ",k(s.default)]}),s.description&&n.jsxs("span",{className:"text-fg-faint truncate max-w-md",title:s.description,children:["— ",s.description]}),n.jsx("div",{className:"flex-1"}),s.enum&&n.jsx(F,{values:s.enum}),n.jsx("button",{onClick:()=>m(e,u),className:"opacity-0 group-hover:opacity-100 px-1.5 py-0 text-[10px] border border-accent/50 rounded text-accent hover:bg-accent hover:text-bg transition-opacity",title:`write to ${N[a].label} draft`,children:"set"})]})}function I(e,r){return e===r?!0:typeof e!=typeof r?!1:e&&r&&typeof e=="object"?JSON.stringify(e)===JSON.stringify(r):!1}function M(e){switch(Array.isArray(e)?e[0]:e){case"boolean":return!1;case"integer":case"number":return 0;case"string":return"";case"array":return[];case"object":return{};case"null":return null;default:return null}}function k(e){if(typeof e=="string")return JSON.stringify(e);if(e===null)return"null";if(typeof e=="object"){const r=JSON.stringify(e);return r.length>100?r.slice(0,100)+"…":r}return String(e)}function C({scope:e,dim:r}){const s=e==="user"?"bg-bg-hi text-fg-dim border-line":e==="project"?"bg-blue-950/30 text-blue-400/80 border-blue-900/40":"bg-purple-950/30 text-purple-400/80 border-purple-900/40";return n.jsx("span",{className:`text-[10px] px-1 py-0 rounded border uppercase tracking-wide shrink-0 ${s} ${r?"opacity-60":""}`,children:N[e].label})}function S({children:e,tone:r="default"}){const s={default:"bg-bg-hi text-fg-dim border-line",warn:"bg-yellow-950/30 text-yellow-500/80 border-yellow-900/40",dim:"bg-bg-elev text-fg-faint border-line"}[r];return n.jsx("span",{className:`text-[10px] px-1 py-0 rounded border uppercase tracking-wide shrink-0 ${s}`,children:e})}function F({values:e}){const r=e.map(s=>String(s)).join(" | ");return n.jsxs("span",{className:"text-[10px] text-fg-faint truncate max-w-xs",title:`allowed: ${r}`,children:["∈ ",r.length>30?r.slice(0,30)+"…":r]})}function V(e,r,s){const a=O(o=>o.files),m=O(o=>o.loadJson),f=O(o=>o.watchFile),x=O(o=>o.unwatchFile),u=b.useMemo(()=>{const o={};for(const g of e.scopes){const d=e.resolve(g,r??"",s);d&&(o[g]=d)}return o},[e,r,s]);return b.useEffect(()=>{const o=Object.values(u).filter(Boolean);return o.forEach(g=>{a[g]||m(g),f(g)}),()=>{o.forEach(g=>x(g))}},[JSON.stringify(u)]),u}function B(e){const r=e??{},s={...r.$defs??{},...r.definitions??{}},a=t=>{if(!t)return{};if(!t.$ref)return x(t);const i=/^#\/(\$defs|definitions)\/(.+)$/.exec(t.$ref);if(!i)return x(t);const c=s[i[2]];return c?a({...c,...u(t)}):x(t)},m=new Set(["__proto__","constructor","prototype"]),f=t=>{if(!t)return{};const i={};for(const[c,l]of Object.entries(t))m.has(c)||(i[c]=l);return i},x=t=>{if(!t.allOf||t.allOf.length===0)return t;const i={...t};delete i.allOf;for(const c of t.allOf){const l=a(c);Object.assign(i,{properties:{...f(i.properties),...f(l.properties)},required:q([...i.required??[],...l.required??[]])}),!i.description&&l.description&&(i.description=l.description),i.default===void 0&&l.default!==void 0&&(i.default=l.default),!i.type&&l.type&&(i.type=l.type)}return i},u=t=>{const{$ref:i,...c}=t;return c},o=(t,i)=>{let c=a(t);for(const l of i){if(!c)return null;if(/^\d+$/.test(l)){const v=Array.isArray(c.items)?c.items[Number(l)]:c.items;c=v?a(v):null;continue}const j=c.properties;if(j&&!m.has(l)&&l in j){c=a(j[l]);continue}const p=c.additionalProperties;if(p&&typeof p=="object"){c=a(p);continue}return null}return c},g=(t,i,c)=>{if(!t)return null;const l={};if(t.description&&(l.description=t.description),t.type&&(l.type=t.type),t.default!==void 0&&(l.default=t.default),t.enum&&(l.enum=t.enum),t.const!==void 0&&(l.const=t.const),t.deprecated&&(l.deprecated=!0),t.examples&&(l.examples=t.examples),t.properties&&(l.knownChildren=Object.keys(t.properties)),c&&(i!=null&&i.includes(c))&&(l.required=!0),t.items&&!Array.isArray(t.items)){const j=a(t.items),p=g(j,void 0,null);p&&(l.itemsInfo=p)}return(t.additionalProperties===!0||typeof t.additionalProperties=="object")&&(l.open=!0),l},d=t=>i=>{if(i.length===0)return g(a(t),void 0,null);const c=o(t,i.slice(0,-1));if(!c)return null;const l=i[i.length-1],j=o(c,[l]);return g(j,c.required,l)},h=t=>{const i=a(t);return Object.keys(i.properties??{})},y=t=>({at:d(t),rootKeys:()=>h(t),rootedAt:i=>{const c=o(t,i);return y(c??{})}});return y(r)}function q(e){return Array.from(new Set(e))}let $=null;function D(){return $||($=B(K)),$}export{G as E,D as s,V as u};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{ap as k,F as E}from"./index-
|
|
1
|
+
import{ap as k,F as E}from"./index-S-F5jp_h.js";function M({value:t,onChange:n,path:e,readOnly:i}){return k.jsx(E,{path:`file://${e}`,defaultLanguage:"markdown",value:t,onChange:s=>n(s??""),theme:"vs-dark",options:{minimap:{enabled:!1},fontSize:13,fontFamily:"JetBrains Mono, ui-monospace, Menlo, monospace",lineNumbers:"on",renderLineHighlight:"line",scrollBeyondLastLine:!1,tabSize:2,wordWrap:"on",readOnly:i,automaticLayout:!0}})}const f=/^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/,u="disable-model-invocation",g=/^\s*disable-model-invocation\s*:/;function j(t){const n=t.match(f);if(!n)return!1;for(const e of n[1].split(/\r?\n/)){if(!g.test(e))continue;const i=e.slice(e.indexOf(":")+1).trim().toLowerCase();return i==="true"||i==="yes"}return!1}function S(t){const n=t.trim();return n.length>=2&&(n[0]==='"'&&n[n.length-1]==='"'||n[0]==="'"&&n[n.length-1]==="'")?n.slice(1,-1):n}function h(t){return t.length-t.trimStart().length}function v(t){const n=t.match(f);if(!n)return{name:null,description:null,body:t};const e=n[1].split(/\r?\n/),i=n[2]??"";let s=null,r=null;for(let o=0;o<e.length;o++){const m=e[o],d=m.match(/^(\s*)(name|description)\s*:(.*)$/);if(!d)continue;const[,,y,$]=d,l=$.trim(),b=h(m);let c;if(l===""||l===">-"||l===">"||l==="|-"||l==="|"){const p=[];let a=o+1;for(;a<e.length&&e[a].trim()!==""&&h(e[a])>b;)p.push(e[a].trim()),a++;c=p.join(" ")}else c=S(l);y==="name"?s=c:r=c}return{name:s,description:r,body:i}}function w(t,n){const e=t.match(f);if(!e){if(!n)return t;const o=t.startsWith(`
|
|
2
2
|
`)?"":`
|
|
3
3
|
`;return`---
|
|
4
4
|
${u}: true
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{W as e,b4 as a,a$ as n}from"./index-
|
|
1
|
+
import{W as e,b4 as a,a$ as n}from"./index-S-F5jp_h.js";const c=new Set(e.map(t=>t.tag));function l(t){return t.filter(o=>c.has(o))}function s(t,o={}){return{name:t.name,originalName:t.name,description:t.description??"",tools:t.tools,model:t.model??"inherit",effort:t.effort??void 0,color:t.color??"",tags:l(t.tags),projects:t.projects,action:t.action??void 0,actionLabel:t.actionLabel??void 0,title:t.title??void 0,body:t.body,...o}}function d(t,o){const i=a();n([i?`${i}/.claude/agents`:null,t?`${t}/.claude/agents`:null],o)}export{s as a,l as t,d as u};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{ap as t,A as f,bf as g,aF as d}from"./index-
|
|
1
|
+
import{ap as t,A as f,bf as g,aF as d}from"./index-S-F5jp_h.js";function j({children:s,right:e}){return t.jsxs("div",{className:"flex items-baseline justify-between mb-2.5",children:[t.jsx("span",{className:"text-[11.5px] font-bold uppercase tracking-[0.8px] text-fg-faint",children:s}),e]})}function y({kind:s="soft",icon:e,children:c,onClick:i,disabled:o,testId:n}){return t.jsxs("button",{type:"button","data-testid":n,onClick:i,disabled:o,className:`shrink-0 inline-flex items-center gap-2 rounded-lg px-3.5 py-2 text-[13px] font-semibold transition-colors disabled:opacity-50 ${s==="soft"?"bg-bg-hi border border-line text-fg hover:bg-bg":"text-fg-dim hover:text-fg"}`,children:[e&&t.jsx(f,{name:e,size:15}),c]})}function N({icon:s,title:e,subtitle:c,badge:i,action:o,testId:n}){return t.jsxs("div",{"data-testid":n,className:"flex items-center gap-3.5 bg-bg-hi border border-line rounded-xl px-[18px] py-3.5",children:[t.jsx("span",{className:"w-[34px] h-[34px] rounded-lg bg-bg border border-line grid place-items-center text-fg-dim shrink-0",children:t.jsx(f,{name:s,size:17})}),t.jsxs("div",{className:"flex-1 min-w-0",children:[t.jsxs("div",{className:"flex items-center gap-2.5 mb-0.5",children:[t.jsx("span",{className:"text-sm font-semibold text-fg truncate",children:e}),i]}),t.jsx("div",{className:"font-mono text-[11.5px] text-fg-faint truncate",children:c})]}),o]})}function v({onClick:s,disabled:e,testId:c,children:i="Revoke"}){return t.jsx("button",{"data-testid":c,onClick:s,disabled:e,className:"shrink-0 rounded-lg border border-line bg-bg text-accent px-3.5 py-1.5 text-[12.5px] font-semibold hover:bg-bg-hi disabled:opacity-50 transition-colors",children:i})}function k({code:s,onConfirm:e,testId:c,codeTestId:i,confirmTestId:o,peer:n="browser"}){return t.jsxs("div",{"data-testid":c,className:"flex items-start gap-3.5 px-5 py-4 rounded-2xl border border-accent/40 bg-accent/[0.06]",children:[t.jsx("span",{className:"w-[38px] h-[38px] rounded-[11px] shrink-0 grid place-items-center bg-bg-hi text-accent",children:t.jsx(f,{name:"shield",size:20})}),t.jsxs("div",{className:"flex-1 min-w-0 text-sm text-fg",children:[t.jsx("strong",{className:"font-semibold",children:"Verify E2E session."})," Compare this code with the ",n," — they must match.",t.jsx("div",{"data-testid":i,className:"my-2 text-3xl font-mono tracking-[0.3em] text-center text-accent select-all",children:s}),t.jsx("p",{className:"text-[12.5px] text-fg-faint mb-3",children:"If the codes match, confirm below. Mutating commands are blocked until confirmed."}),t.jsx("button",{"data-testid":o,onClick:e,className:"rounded-lg bg-accent text-white px-4 py-2 text-[13px] font-semibold hover:opacity-90 transition-opacity",children:"Codes match — confirm"})]})]})}function C({children:s,testId:e}){return t.jsx("div",{"data-testid":e,className:"bg-bg-hi border border-line rounded-xl p-5 text-center text-[13.5px] text-fg-faint italic font-serif",children:s})}const m=s=>(s==null?void 0:s.message)||String(s);function S(s){const e=g(r=>r.show),[c,i]=d.useState([]),o=d.useRef(s);o.current=s;const n=d.useCallback(async()=>{try{i(await window.api.remoteClient.list())}catch(r){e("error",m(r))}},[e]);d.useEffect(()=>{n();const r=window.api.remoteClient.onStatus(a=>{var x;(x=o.current)==null||x.call(o,a),i(l=>l.map(b=>b.peerId===a.peerId?{...b,status:a.status,reason:a.reason,sas:a.sas}:b))});return()=>{r()}},[n]);const p=d.useCallback(async r=>{try{const a=await window.api.remoteClient.connect(r);i(x=>x.map(l=>l.peerId===r?{...l,status:a.status,reason:a.reason,sas:a.sas}:l))}catch(a){e("error",m(a))}},[e]),u=d.useCallback(async r=>{try{const a=await window.api.remoteClient.confirmSas(r);a.ok||e("error",a.reason??"SAS confirmation failed"),await n()}catch(a){e("error",m(a))}},[e,n]),h=d.useCallback(async r=>{try{await window.api.remoteClient.remove(r),await n()}catch(a){e("error",m(a))}},[e,n]);return{peers:c,refresh:n,connect:p,confirmSas:u,revoke:h}}export{C as E,y as P,N as R,k as S,v as a,j as b,S as u};
|
package/dist/index.html
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
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-S-F5jp_h.js"></script>
|
|
11
11
|
<link rel="modulepreload" crossorigin href="./assets/monaco-editor-BsIlgG7c.js">
|
|
12
12
|
<link rel="stylesheet" crossorigin href="./assets/monaco-editor-Cu5D__1H.css">
|
|
13
13
|
<link rel="stylesheet" crossorigin href="./assets/index-Dd7UQabV.css">
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-code-session-manager",
|
|
3
|
-
"version": "0.122.
|
|
3
|
+
"version": "0.122.1",
|
|
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",
|
|
@@ -69,6 +69,7 @@ failure modes have different fixes:
|
|
|
69
69
|
error is not this case: fix the input and retry. **STOP. Do not write any PRD file.** Tell the
|
|
70
70
|
human to start the app, then retry the same call. Why: a PRD file the API did not write is
|
|
71
71
|
quarantined and never runs.
|
|
72
|
+
- **(c) Create errors with "did not answer" or "Connection closed".** It may still have been written; retry the same call with the same slug (it returns the existing PRD with `alreadyExisted: true`) and never re-issue it under a new slug.
|
|
72
73
|
- **(b) Tool ABSENT from your tool list.** The `session-manager-scheduler` MCP server is not
|
|
73
74
|
registered: a **misconfiguration**, not an offline app.
|
|
74
75
|
**STOP. Do not write any PRD file.** Tell the human. The app registers the server at user
|
|
@@ -80,6 +80,16 @@ function errorResult(text) {
|
|
|
80
80
|
const NOT_RUNNING_ERROR =
|
|
81
81
|
`session-manager app is not running (admin API unreachable) — start it first${HELP_POINTER}`;
|
|
82
82
|
|
|
83
|
+
// The app accepted (or may have accepted) the request but did not answer: the
|
|
84
|
+
// write may already be applied, so the advice is "check, then same slug" —
|
|
85
|
+
// never a new slug.
|
|
86
|
+
function busyError(code) {
|
|
87
|
+
return `session-manager admin API did not answer (${code}) — the app is running but busy; the request may still be applied. `
|
|
88
|
+
+ 'Before retrying a create, call scheduler_list_prds for this Epic with no status filter '
|
|
89
|
+
+ '(a just-written PRD has status null), or retry the same call with the same slug; '
|
|
90
|
+
+ `never re-issue it under a new slug.${HELP_POINTER}`;
|
|
91
|
+
}
|
|
92
|
+
|
|
83
93
|
// Same resolution fetchReadiness() below uses: a project-home-builder session
|
|
84
94
|
// running inside an Epic worktree still targets the real project cwd, not
|
|
85
95
|
// the worktree's own pwd.
|
|
@@ -114,11 +124,15 @@ async function adminRequest(method, urlPath, body) {
|
|
|
114
124
|
},
|
|
115
125
|
body: body ? JSON.stringify(body) : undefined,
|
|
116
126
|
});
|
|
127
|
+
} catch (err) {
|
|
128
|
+
if (err?.cause?.code === 'ECONNREFUSED') throw new Error(NOT_RUNNING_ERROR);
|
|
129
|
+
throw new Error(busyError(err?.cause?.code || err?.name || 'unknown'));
|
|
130
|
+
}
|
|
131
|
+
try {
|
|
132
|
+
return await res.json();
|
|
117
133
|
} catch {
|
|
118
|
-
throw new Error(
|
|
134
|
+
throw new Error(`admin API answered HTTP ${res.status} with a non-JSON body`);
|
|
119
135
|
}
|
|
120
|
-
const json = await res.json();
|
|
121
|
-
return json;
|
|
122
136
|
}
|
|
123
137
|
|
|
124
138
|
// session_manager_help's live half. The catalog/recipes below are static and
|
|
@@ -870,4 +884,4 @@ if (require.main === module) {
|
|
|
870
884
|
});
|
|
871
885
|
}
|
|
872
886
|
|
|
873
|
-
module.exports = { TOOLS, handleCallTool, HELP_POINTER, NOT_RUNNING_ERROR };
|
|
887
|
+
module.exports = { TOOLS, handleCallTool, HELP_POINTER, NOT_RUNNING_ERROR, busyError };
|
package/src/main/build-info.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.122.
|
|
3
|
-
"gitSha": "
|
|
4
|
-
"gitShortSha": "
|
|
2
|
+
"version": "0.122.1",
|
|
3
|
+
"gitSha": "7f6a60c94e69454a3b52ccae59549e1ee33df648",
|
|
4
|
+
"gitShortSha": "7f6a60c9",
|
|
5
5
|
"gitBranch": "HEAD",
|
|
6
|
-
"builtAt": "2026-10-
|
|
6
|
+
"builtAt": "2026-10-24T16:08:59.401Z",
|
|
7
7
|
"dirty": false
|
|
8
8
|
}
|
|
@@ -111,12 +111,10 @@ const MCP_TOOL_CATALOG = [
|
|
|
111
111
|
+ 'them with `dependsOn` instead.',
|
|
112
112
|
whenToUse: 'Use whenever new work should be queued into an already-approved Epic — this is the /develop path.',
|
|
113
113
|
whenNotToUse: 'TWO DISTINCT FAILURE MODES if this tool is not usable — do not conflate them: '
|
|
114
|
-
+ '(a) this tool call is PRESENT in your tool list but ERRORS
|
|
115
|
-
+ 'API unreachable
|
|
116
|
-
+ '
|
|
117
|
-
+ '
|
|
118
|
-
+ 'verification) since the server-side validation, atomic NN allocation, and '
|
|
119
|
-
+ 'Epic-existence check this tool performs did not run for that file. '
|
|
114
|
+
+ '(a) this tool call is PRESENT in your tool list but ERRORS — NEVER hand-write a PRD file. '
|
|
115
|
+
+ 'On "not running" (admin API unreachable): stop, ask the human to start the app, then retry the same call. '
|
|
116
|
+
+ 'On "did not answer": the app is busy and the PRD may already exist — check with scheduler_list_prds '
|
|
117
|
+
+ '(no status filter) or retry the same slug. '
|
|
120
118
|
+ '(b) this tool is ABSENT from your tool list entirely — you were never offered it, so '
|
|
121
119
|
+ 'there is no error to catch. That means the session-manager-scheduler MCP server is not '
|
|
122
120
|
+ 'registered for this project: a MISCONFIGURATION, not an offline app. In that case DO '
|
|
@@ -400,7 +398,7 @@ const MCP_RECIPES = [
|
|
|
400
398
|
title: 'Queue work into an already-approved Epic (/develop)',
|
|
401
399
|
steps: [
|
|
402
400
|
'Confirm an Epic already exists for this work (proposed or active) — scheduler_create_prd never mints one.',
|
|
403
|
-
'Call scheduler_create_prd with sourcePromptId set to that Epic id, plus title/cwd/
|
|
401
|
+
'Call scheduler_create_prd with sourcePromptId set to that Epic id, plus title/cwd/goal/acceptanceCriteria/implementationNotes/gate/files.',
|
|
404
402
|
'The response has enqueued:false — the queue row is derived by the scheduler\'s next reconcile pass (~1 minute), not by this call.',
|
|
405
403
|
'Optionally call scheduler_list_prds with cwd/status to confirm the PRD picked up a job row.',
|
|
406
404
|
],
|
|
@@ -32,6 +32,7 @@ const { resolveDepSlug, findNearMatches } = require('./depSlugResolve.cjs');
|
|
|
32
32
|
const { resolveEpicPrdWriteDir } = require('./prdLocations.cjs');
|
|
33
33
|
const { isFixPlanSlug } = require('../scheduler/fixPlanSlug.cjs');
|
|
34
34
|
const { isIncomplete, resolveChainTerminals, isValidPlanId, mintPlanId, resolveInheritedPlanId } = require('./prdDisposition.cjs');
|
|
35
|
+
const { splitFrontmatter } = require('./prdFrontmatter.cjs');
|
|
35
36
|
const { sizingWarnings } = require('./prdSizing.cjs');
|
|
36
37
|
const { execGit } = require('../git/gitExec.cjs');
|
|
37
38
|
const { extractRepoPathCandidates, worktreeReachWarnings } = require('./prdWorktreeReach.cjs');
|
|
@@ -224,7 +225,18 @@ async function worktreeReachAdvisory(input, cwd) {
|
|
|
224
225
|
* on failure — `status` is the HTTP status code the caller should map errors to
|
|
225
226
|
* (400/409/500), left to the caller since only the HTTP route needs it.
|
|
226
227
|
*/
|
|
228
|
+
const inFlightCreates = new Set();
|
|
229
|
+
|
|
227
230
|
async function createPrd(input, remote) {
|
|
231
|
+
const ctl = { key: null };
|
|
232
|
+
try {
|
|
233
|
+
return await createPrdInner(input, remote, ctl);
|
|
234
|
+
} finally {
|
|
235
|
+
if (ctl.key) inFlightCreates.delete(ctl.key);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
async function createPrdInner(input, remote, ctl) {
|
|
228
240
|
// cwd is untrusted AND, since this PRD, optional — a caller inside an
|
|
229
241
|
// Epic's git worktree naturally passes its worktree pwd (or omits cwd
|
|
230
242
|
// entirely and relies on originClaudeSessionId/sourcePromptId). Resolve the
|
|
@@ -450,6 +462,16 @@ async function createPrd(input, remote) {
|
|
|
450
462
|
// Finished rows leave queue.json, so an author can re-issue a landed PRD under a fresh NN.
|
|
451
463
|
// Refused before NN allocation so it burns no number. Fix plans are exempt.
|
|
452
464
|
if (input.sourcePromptId && !isFixPlanSlug(`0-${slug}`)) {
|
|
465
|
+
const inFlightKey = `${input.sourcePromptId}\u0000${slug}`;
|
|
466
|
+
if (inFlightCreates.has(inFlightKey)) {
|
|
467
|
+
return {
|
|
468
|
+
ok: false,
|
|
469
|
+
status: 409,
|
|
470
|
+
error: `A create for slug "${slug}" in this Epic is still in progress — wait for it to finish, then retry the same call`,
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
inFlightCreates.add(inFlightKey);
|
|
474
|
+
ctl.key = inFlightKey;
|
|
453
475
|
let epicDirs = [];
|
|
454
476
|
try {
|
|
455
477
|
const prdsDir = resolveEpicPrdWriteDir(cwd, input.sourcePromptId);
|
|
@@ -460,6 +482,28 @@ async function createPrd(input, remote) {
|
|
|
460
482
|
try { names = await fsp.readdir(dir); } catch { /* missing dir counts as empty */ }
|
|
461
483
|
const dup = names.find((n) => n.endsWith('.md') && n.slice(0, -3).replace(/^\d+-/, '') === slug);
|
|
462
484
|
if (dup) {
|
|
485
|
+
let existingTitle = null;
|
|
486
|
+
try {
|
|
487
|
+
existingTitle = splitFrontmatter(await fsp.readFile(path.join(dir, dup), 'utf8')).fm.title ?? null;
|
|
488
|
+
} catch { /* unreadable — treat as different */ }
|
|
489
|
+
if (existingTitle !== null && String(existingTitle).trim() === String(input.title ?? '').trim()) {
|
|
490
|
+
const existingSlug = dup.slice(0, -3);
|
|
491
|
+
let enqueuedExisting = false;
|
|
492
|
+
try {
|
|
493
|
+
if (typeof remote.getJob === 'function') enqueuedExisting = Boolean(await remote.getJob(existingSlug));
|
|
494
|
+
} catch { /* non-fatal */ }
|
|
495
|
+
return {
|
|
496
|
+
ok: true,
|
|
497
|
+
alreadyExisted: true,
|
|
498
|
+
nn: Number((/^(\d+)-/.exec(dup) || [])[1]),
|
|
499
|
+
filename: dup,
|
|
500
|
+
prdPath: path.join(dir, dup),
|
|
501
|
+
epicId: input.sourcePromptId,
|
|
502
|
+
enqueued: enqueuedExisting,
|
|
503
|
+
note: 'PRD was not written again: this Epic already has that file with the same title, which usually means an earlier call\'s response was lost, so treat it as created.',
|
|
504
|
+
warnings: [],
|
|
505
|
+
};
|
|
506
|
+
}
|
|
463
507
|
return {
|
|
464
508
|
ok: false,
|
|
465
509
|
status: 409,
|
|
@@ -720,6 +764,7 @@ function registerAdminRoute(adminHttp, remote) {
|
|
|
720
764
|
// Mirror createPrd()'s own honest shape verbatim — never re-add a
|
|
721
765
|
// 'status' field here. See createPrd's return above for why.
|
|
722
766
|
sendJson(res, 200, {
|
|
767
|
+
...(result.alreadyExisted ? { alreadyExisted: true } : {}),
|
|
723
768
|
nn: result.nn,
|
|
724
769
|
filename: result.filename,
|
|
725
770
|
prdPath: result.prdPath ?? null,
|
package/src/main/scheduler.cjs
CHANGED
|
@@ -10358,7 +10358,7 @@ function toCompactPrdEntry(entry) {
|
|
|
10358
10358
|
* `schedule:list-prds` IPC handler and the admin HTTP `GET
|
|
10359
10359
|
* /admin/scheduler/prds` route (PRD 1024) — neither re-implements this scan.
|
|
10360
10360
|
*/
|
|
10361
|
-
async function listPrdsInternal() {
|
|
10361
|
+
async function listPrdsInternal({ cwd } = {}) {
|
|
10362
10362
|
ensureDirs();
|
|
10363
10363
|
const out = [];
|
|
10364
10364
|
const seenSlugs = new Set();
|
|
@@ -10410,12 +10410,21 @@ async function listPrdsInternal() {
|
|
|
10410
10410
|
// Live PRDs first, so an archived duplicate (shouldn't exist, but a
|
|
10411
10411
|
// stale rename copy is possible) never shadows the still-runnable live
|
|
10412
10412
|
// entry.
|
|
10413
|
-
|
|
10413
|
+
// A non-empty cwd scopes the scan to that one project's dirs (cost = that
|
|
10414
|
+
// project's files, not every project's); no cwd = the machine-wide scan.
|
|
10415
|
+
const scoped = typeof cwd === 'string' && cwd.length > 0;
|
|
10416
|
+
const liveDirs = scoped
|
|
10417
|
+
? [...new Set([schedulerPaths.prdsRoot(), prdPaths.prdDirForCwd(cwd), ...listEpicPrdDirs(cwd)])]
|
|
10418
|
+
: prdPaths.candidatePrdsDirs();
|
|
10419
|
+
const archivedDirs = scoped
|
|
10420
|
+
? [...new Set(listArchivedPrdDirs(cwd))]
|
|
10421
|
+
: prdPaths.candidateArchivedPrdsDirs();
|
|
10422
|
+
for (const dir of liveDirs) {
|
|
10414
10423
|
await readDirInto(dir, { archived: false });
|
|
10415
10424
|
}
|
|
10416
10425
|
|
|
10417
10426
|
const archivedStart = out.length;
|
|
10418
|
-
for (const dir of
|
|
10427
|
+
for (const dir of archivedDirs) {
|
|
10419
10428
|
await readDirInto(dir, { archived: true });
|
|
10420
10429
|
}
|
|
10421
10430
|
|
|
@@ -10658,7 +10667,7 @@ const remote = {
|
|
|
10658
10667
|
// paging by offset can't skip or duplicate an entry between requests as
|
|
10659
10668
|
// long as the underlying PRD set doesn't change mid-page.
|
|
10660
10669
|
async listPrds(filter = {}) {
|
|
10661
|
-
const all = await listPrdsInternal();
|
|
10670
|
+
const all = await listPrdsInternal({ cwd: filter.cwd });
|
|
10662
10671
|
const filtered = all.filter((entry) => {
|
|
10663
10672
|
if (filter.cwd && entry.cwd !== filter.cwd) return false;
|
|
10664
10673
|
if (filter.epicId && entry.epicId !== filter.epicId) return false;
|