claude-code-session-manager 0.118.0 → 0.119.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-CEI6vsmu.js → AgentLibrary-BpW0pGgk.js} +1 -1
- package/dist/assets/{Button-BuyzGzO8.js → Button-DZX5guWb.js} +1 -1
- package/dist/assets/{DataModel-CbXI_rEf.js → DataModel-WG4pG_4z.js} +1 -1
- package/dist/assets/{History-axy4nJyY.js → History-D58whvn_.js} +1 -1
- package/dist/assets/{Hooks-D5ghOppL.js → Hooks-DCI9ezg4.js} +1 -1
- package/dist/assets/{Library-wBI4Fwh3.js → Library-YqMi-vsA.js} +1 -1
- package/dist/assets/{ListDetail-CY5hhwn9.js → ListDetail-ap4W5z_Z.js} +1 -1
- package/dist/assets/{McpServers-CwEVZqfu.js → McpServers-CT0pBTF8.js} +1 -1
- package/dist/assets/{Memory-Beh2r4Xk.js → Memory-BODDUBy4.js} +1 -1
- package/dist/assets/{Panel-yOYf80ax.js → Panel-CeOfUS9B.js} +1 -1
- package/dist/assets/{Permissions-DA-SMXO3.js → Permissions-DyOqpLQx.js} +1 -1
- package/dist/assets/{Plugins-qfKt6BxH.js → Plugins-DBXzKjL2.js} +2 -2
- package/dist/assets/{ProvenanceBadge-DFyBe7Po.js → ProvenanceBadge-C47IX1Q6.js} +1 -1
- package/dist/assets/{RemoteMachines-AG0K7kqS.js → RemoteMachines-CtkAJvkZ.js} +1 -1
- package/dist/assets/{SaveBar-35Nw2YsZ.js → SaveBar-YMtzcCzP.js} +1 -1
- package/dist/assets/{Scheduler-BPBAU0TO.js → Scheduler-BNiYg0YD.js} +1 -1
- package/dist/assets/{ScopeSwitcher-BCXNrrrs.js → ScopeSwitcher-Dgi8CiDi.js} +1 -1
- package/dist/assets/{Settings-C4yhzfZI.js → Settings-B4LuoRnd.js} +1 -1
- package/dist/assets/{SkillReferenceGraph-Ca5z2avC.js → SkillReferenceGraph-CaFsccNI.js} +1 -1
- package/dist/assets/{Skills-5WWusmKG.js → Skills-BeCMBQ3l.js} +1 -1
- package/dist/assets/{SystemPrompt-ofVCdHAW.js → SystemPrompt-C3WmcPEF.js} +1 -1
- package/dist/assets/{TagLibrary-rSrpD-Bz.js → TagLibrary-DP4GH7Dr.js} +1 -1
- package/dist/assets/{TiptapBody-DAYcdcVt.js → TiptapBody-CXCMvRr_.js} +1 -1
- package/dist/assets/{Toggle-BzHdpXZI.js → Toggle-TY-Wa8hv.js} +1 -1
- package/dist/assets/{ViewTabs-D82jJ4VS.js → ViewTabs-CaacRnp6.js} +1 -1
- package/dist/assets/{historyTotals-DMGFqK5h.js → historyTotals-C28IlVVQ.js} +1 -1
- package/dist/assets/{index-DZ5TJKNI.js → index-DdEMkmbi.js} +3 -3
- package/dist/assets/{settingsSchema-BfnNE6ne.js → settingsSchema-7Yg6dNNB.js} +1 -1
- package/dist/assets/{skillFrontmatter-ED1DjPE1.js → skillFrontmatter-Dcuys1km.js} +1 -1
- package/dist/assets/{useAgentsDirWatch-CbpQIu3P.js → useAgentsDirWatch-B0H4M-TT.js} +1 -1
- package/dist/assets/{useRemotePeers-Dy_o0WlY.js → useRemotePeers-Zp9jchCS.js} +1 -1
- package/dist/index.html +1 -1
- package/package.json +1 -1
- package/plugins/session-manager-dev/skills/develop/SKILL.md +2 -0
- package/src/main/build-info.json +4 -4
- package/src/main/lib/prd/prdCreate.cjs +23 -0
- package/src/main/lib/prd/prdWorktreeReach.cjs +77 -0
- package/src/main/lib/scheduler/rcaReport.cjs +14 -2
- package/src/main/templates/PRD_AUTHORING.md +5 -1
- package/src/main/webRemote.cjs +3 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
import{aF as b,ap as n,S as N,a_ as O}from"./index-DZ5TJKNI.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-DdEMkmbi.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-DdEMkmbi.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-DdEMkmbi.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-DdEMkmbi.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-DdEMkmbi.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-DAMBm3UN.css">
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-code-session-manager",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.119.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",
|
|
@@ -178,6 +178,8 @@ the API rejects that.
|
|
|
178
178
|
criterion. The executor ends with `SCHEDULER_VERDICT: NEEDS_HUMAN <question>` for those, and
|
|
179
179
|
the PRD notes say so. Why: no executor can pass such a gate, so the job parks as
|
|
180
180
|
`sentinel_fail`.
|
|
181
|
+
Live-run steps that need gitignored state follow PRD_AUTHORING.md §7 (absolute main-checkout
|
|
182
|
+
paths, artifact-only).
|
|
181
183
|
|
|
182
184
|
### files rules
|
|
183
185
|
|
package/src/main/build-info.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.
|
|
3
|
-
"gitSha": "
|
|
4
|
-
"gitShortSha": "
|
|
2
|
+
"version": "0.119.1",
|
|
3
|
+
"gitSha": "cf5b9a824d41bda817c4b926f1c642502af59477",
|
|
4
|
+
"gitShortSha": "cf5b9a82",
|
|
5
5
|
"gitBranch": "HEAD",
|
|
6
|
-
"builtAt": "2026-10-
|
|
6
|
+
"builtAt": "2026-10-17T15:33:05.947Z",
|
|
7
7
|
"dirty": false
|
|
8
8
|
}
|
|
@@ -32,6 +32,8 @@ const { resolveDepSlug, findNearMatches } = require('./depSlugResolve.cjs');
|
|
|
32
32
|
const { isFixPlanSlug } = require('../scheduler/fixPlanSlug.cjs');
|
|
33
33
|
const { isIncomplete, resolveChainTerminals, isValidPlanId, mintPlanId, resolveInheritedPlanId } = require('./prdDisposition.cjs');
|
|
34
34
|
const { sizingWarnings } = require('./prdSizing.cjs');
|
|
35
|
+
const { execGit } = require('../git/gitExec.cjs');
|
|
36
|
+
const { extractRepoPathCandidates, worktreeReachWarnings } = require('./prdWorktreeReach.cjs');
|
|
35
37
|
const { validateGate, validateFiles, renderFilesSection, renderGateSection } = require('./prdGateFiles.cjs');
|
|
36
38
|
const { resolveGate, parseChain, isNoneGate } = require('../scheduler/definitionOfDone.cjs');
|
|
37
39
|
|
|
@@ -186,6 +188,26 @@ function resolveSourcePromptIdFromClaudeSession(cwd, claudeSessionId) {
|
|
|
186
188
|
return null;
|
|
187
189
|
}
|
|
188
190
|
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Advisory: which relative paths the PRD names are gitignored in `cwd` (so absent from the job
|
|
194
|
+
* worktree). execGit has no stdin, so candidates go as argv after `--` (still one call). Exit 1 =
|
|
195
|
+
* nothing ignored; any other failure (not a repo, timeout) is swallowed — never blocks the write.
|
|
196
|
+
*/
|
|
197
|
+
async function worktreeReachAdvisory(input, cwd) {
|
|
198
|
+
try {
|
|
199
|
+
const text = [input.goal, ...(Array.isArray(input.acceptanceCriteria) ? input.acceptanceCriteria : []),
|
|
200
|
+
input.implementationNotes].filter((s) => typeof s === 'string').join('\n');
|
|
201
|
+
const candidates = extractRepoPathCandidates(text);
|
|
202
|
+
if (candidates.length === 0) return [];
|
|
203
|
+
const out = await execGit(cwd, ['check-ignore', '--', ...candidates], { timeout: 10000 });
|
|
204
|
+
const ignored = out.split('\n').map((l) => l.trim()).filter(Boolean);
|
|
205
|
+
return worktreeReachWarnings(input, ignored);
|
|
206
|
+
} catch {
|
|
207
|
+
return [];
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
189
211
|
/**
|
|
190
212
|
* Core create-PRD orchestration: cwd validation, slug derivation, NN
|
|
191
213
|
* allocation, existing-file collision check, body build, write. Shared by
|
|
@@ -419,6 +441,7 @@ async function createPrd(input, remote) {
|
|
|
419
441
|
} else {
|
|
420
442
|
extraWarnings.push('No files list: the executor is not told which files it may change.');
|
|
421
443
|
}
|
|
444
|
+
extraWarnings.push(...await worktreeReachAdvisory(input, cwd));
|
|
422
445
|
|
|
423
446
|
const nn = await remote.allocateParallelGroup(input.cwd);
|
|
424
447
|
const filenameSlug = `${nn}-${slug}`;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* prdWorktreeReach.cjs — pure PRD worktree-reach advisory rule.
|
|
3
|
+
*
|
|
4
|
+
* Incident: burrow PRD 1516-fb-bilko-first-pumpkin named a gitignored runtime path by RELATIVE
|
|
5
|
+
* path (downloads/fb-tracker.db) and an install-cron.sh that baked a worktree path. Scheduled
|
|
6
|
+
* PRDs run in an isolated git job worktree holding only tracked files plus symlinked dependency
|
|
7
|
+
* dirs (DEFAULT_DEP_DIRS), so that path pointed at a file that did not exist there and the job
|
|
8
|
+
* parked needs_human.
|
|
9
|
+
*
|
|
10
|
+
* Two exports: `extractRepoPathCandidates(text)` pulls repo-relative path-looking tokens out of
|
|
11
|
+
* PRD prose; `worktreeReachWarnings(input, ignoredPaths)` turns the ones the caller found
|
|
12
|
+
* gitignored (via `git check-ignore` — not done here) into one advisory warning. No I/O.
|
|
13
|
+
* Warnings never block a write.
|
|
14
|
+
*/
|
|
15
|
+
'use strict';
|
|
16
|
+
|
|
17
|
+
const { DEFAULT_DEP_DIRS } = require('../git/worktreeDeps.cjs');
|
|
18
|
+
|
|
19
|
+
const MAX_CANDIDATES = 200;
|
|
20
|
+
const MAX_NAMED_PATHS = 5;
|
|
21
|
+
|
|
22
|
+
const LEADING_JUNK_RE = /^[`'"([<]+/;
|
|
23
|
+
const TRAILING_JUNK_RE = /[`'")\]>.,:;]+$/;
|
|
24
|
+
|
|
25
|
+
function isCandidate(token) {
|
|
26
|
+
if (!token.includes('/')) return false;
|
|
27
|
+
if (/^[/~$-]/.test(token)) return false;
|
|
28
|
+
if (token.includes('://')) return false;
|
|
29
|
+
if (token.split('/').includes('..')) return false;
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Pure. Deduped repo-relative tokens containing a '/', capped at 200. */
|
|
34
|
+
function extractRepoPathCandidates(text) {
|
|
35
|
+
const seen = new Set();
|
|
36
|
+
for (const raw of String(text == null ? '' : text).split(/\s+/)) {
|
|
37
|
+
if (!raw) continue;
|
|
38
|
+
const token = raw.replace(LEADING_JUNK_RE, '').replace(TRAILING_JUNK_RE, '');
|
|
39
|
+
if (!token || !isCandidate(token)) continue;
|
|
40
|
+
seen.add(token);
|
|
41
|
+
if (seen.size >= MAX_CANDIDATES) break;
|
|
42
|
+
}
|
|
43
|
+
return [...seen];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function normalize(p) {
|
|
47
|
+
return String(p).replace(/^(\.\/)+/, '');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Pure. `input` mirrors createPrd()'s shape; missing fields are treated as empty.
|
|
52
|
+
* `ignoredPaths` is the caller's list of gitignored repo-relative paths. Returns `[]` when none
|
|
53
|
+
* remain after exempting symlinked dependency dirs, else exactly one warning string.
|
|
54
|
+
*/
|
|
55
|
+
function worktreeReachWarnings(input, ignoredPaths) {
|
|
56
|
+
const { goal, acceptanceCriteria, implementationNotes } = input || {};
|
|
57
|
+
const ac = Array.isArray(acceptanceCriteria) ? acceptanceCriteria.filter((l) => typeof l === 'string') : [];
|
|
58
|
+
const ignored = (Array.isArray(ignoredPaths) ? ignoredPaths : [])
|
|
59
|
+
.filter((p) => typeof p === 'string' && p)
|
|
60
|
+
.map(normalize)
|
|
61
|
+
.filter((p) => !DEFAULT_DEP_DIRS.includes(p.split('/')[0]));
|
|
62
|
+
if (ignored.length === 0) return [];
|
|
63
|
+
|
|
64
|
+
const text = [goal, ...ac, implementationNotes].filter((s) => typeof s === 'string').join('\n');
|
|
65
|
+
const mentioned = new Set(extractRepoPathCandidates(text).map(normalize));
|
|
66
|
+
const offending = [...new Set(ignored)].filter((p) => mentioned.has(p) || mentioned.has(p.replace(/\/+$/, '')));
|
|
67
|
+
const named = (offending.length ? offending : [...new Set(ignored)]).slice(0, MAX_NAMED_PATHS);
|
|
68
|
+
|
|
69
|
+
return [
|
|
70
|
+
`This PRD references gitignored path(s) by relative path: ${named.join(', ')}. `
|
|
71
|
+
+ 'The job runs in an isolated worktree where gitignored files do not exist, so those paths will '
|
|
72
|
+
+ 'be missing (or a baked-in worktree path will dangle). Address the main checkout by absolute path '
|
|
73
|
+
+ 'in an artifact-only PRD (or split the PRD) — see PRD_AUTHORING.md section 7.',
|
|
74
|
+
];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
module.exports = { extractRepoPathCandidates, worktreeReachWarnings };
|
|
@@ -73,6 +73,7 @@ const FAILURE_CLASSES = {
|
|
|
73
73
|
TRANSCRIPT_ERRORS: 'transcript-errors',
|
|
74
74
|
ABANDONED_BACKGROUND_TASK: 'abandoned-background-task',
|
|
75
75
|
BLOCKED_BY_FOREIGN_WIP: 'blocked-by-foreign-wip',
|
|
76
|
+
NEEDS_HUMAN: 'needs-human',
|
|
76
77
|
UNKNOWN: 'unknown',
|
|
77
78
|
};
|
|
78
79
|
|
|
@@ -82,8 +83,11 @@ const FAILURE_CLASSES = {
|
|
|
82
83
|
// nothing to investigate, and re-queuing is already owned by
|
|
83
84
|
// reconcile()'s requeueForeignWipBlockedJobs, not this action), 'resume-and-commit'
|
|
84
85
|
// (PRD 1111's --resume dispatch owns this), 'verify-and-close' (the work
|
|
85
|
-
// likely landed, just missing its sentinel), '
|
|
86
|
-
//
|
|
86
|
+
// likely landed, just missing its sentinel), 'ask-human' (the executor
|
|
87
|
+
// correctly stopped on a step only a person can do — answer the job's
|
|
88
|
+
// humanQuestion, then update + reset the PRD; never a fix-plan, and the review
|
|
89
|
+
// ladder never auto-fixes it), 'investigate' (the only class that still buys a
|
|
90
|
+
// fix-plan investigation).
|
|
87
91
|
const RECOVERY_ACTIONS = {
|
|
88
92
|
[FAILURE_CLASSES.ALREADY_SHIPPED]: 'archive',
|
|
89
93
|
[FAILURE_CLASSES.SELF_QUEUE]: 'investigate',
|
|
@@ -104,6 +108,7 @@ const RECOVERY_ACTIONS = {
|
|
|
104
108
|
// guidance into that cold-read investigation.
|
|
105
109
|
[FAILURE_CLASSES.ABANDONED_BACKGROUND_TASK]: 'investigate',
|
|
106
110
|
[FAILURE_CLASSES.BLOCKED_BY_FOREIGN_WIP]: 'archive',
|
|
111
|
+
[FAILURE_CLASSES.NEEDS_HUMAN]: 'ask-human',
|
|
107
112
|
[FAILURE_CLASSES.UNKNOWN]: 'investigate',
|
|
108
113
|
};
|
|
109
114
|
|
|
@@ -131,6 +136,8 @@ const PREVENTION_HINTS = {
|
|
|
131
136
|
'A headless run cannot receive a background-task completion notification — never let a long Bash command auto-background past its foreground timeout and then wait for it. Run long commands with an explicit bound (`timeout <N> <cmd>`) so they finish in the foreground, or poll their output file directly instead of waiting on Monitor/notification.',
|
|
132
137
|
[FAILURE_CLASSES.BLOCKED_BY_FOREIGN_WIP]:
|
|
133
138
|
'This job correctly reported `SCHEDULER_VERDICT: BLOCKED_BY_FOREIGN_WIP` against a sibling job\'s in-flight, uncommitted files three times in a row — auto-requeue is exhausted (reconcile() only clears this once the blocked paths go clean). This is not a defect in this PRD\'s own work: check on the sibling job/human that owns the still-dirty path(s) named on the job row, and either wait for them to commit or manually reset this job to `pending` once the tree is clear. Do not author a fix-plan PRD against it.',
|
|
139
|
+
[FAILURE_CLASSES.NEEDS_HUMAN]:
|
|
140
|
+
'The run stopped on a step that needs a person or live runtime state — the executor was right to stop, so this is not a defect to fix-plan. Answer the job\'s humanQuestion, then update and reset the PRD. If the reason is that the job worktree lacks gitignored runtime state (databases, browser profile, downloads/, crontab paths), re-author the step as an artifact-only PRD that addresses the main checkout by absolute path, per PRD_AUTHORING.md section 7.',
|
|
134
141
|
[FAILURE_CLASSES.UNKNOWN]:
|
|
135
142
|
'Re-run the acceptance criteria gate locally against the failure log to pin down the specific break before re-queuing.',
|
|
136
143
|
};
|
|
@@ -192,6 +199,11 @@ function classifyFailure({ verdict, logTail: rawLogTail }) {
|
|
|
192
199
|
const logTail = stripHarnessInitEvents(rawLogTail);
|
|
193
200
|
const lines = logTail.split('\n');
|
|
194
201
|
|
|
202
|
+
// Checked before every other rule, log-tail heuristics included: the
|
|
203
|
+
// executor deliberately stopped on a human-only step, so words like
|
|
204
|
+
// "sleep"/"until" in its tail say nothing about the cause.
|
|
205
|
+
if (verdict === 'needs_human') return FAILURE_CLASSES.NEEDS_HUMAN;
|
|
206
|
+
|
|
195
207
|
// Checked before every other rule: an unambiguous, materially-checked
|
|
196
208
|
// verdict (the scheduler itself validated the executor's claimed paths
|
|
197
209
|
// against the job's disclosed foreign-WIP manifest before ever landing
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- PRD_AUTHORING.md
|
|
1
|
+
<!-- PRD_AUTHORING.md v6 -->
|
|
2
2
|
# PRD Authoring Guide — Scheduler Safety Rules
|
|
3
3
|
|
|
4
4
|
Rule: every PRD you queue follows the rules below.
|
|
@@ -125,6 +125,9 @@ A short Epic-context digest is prepended automatically for orientation only —
|
|
|
125
125
|
|
|
126
126
|
The executor can't ask you anything: no `ScheduleWakeup`, Cron, Monitor, `AskUserQuestion`, plan mode, or worktree tools; background tasks are off (a `timeout` command is always on PATH — the app installs a shim on macOS). It must never stop to ask a question — it makes the safest reasonable call and reports it, so write the PRD so that call is obvious.
|
|
127
127
|
|
|
128
|
+
Worktree reach: every PRD runs in an isolated git worktree holding tracked files plus symlinked `node_modules`/`.venv`/`venv` only. A step that needs gitignored runtime state (databases, `downloads/`, browser profiles, logs) or a live side effect must address the main checkout by absolute path (e.g. `$HOME/Projects/<repo>/...`), be artifact-only (a deliverable artifact + `artifactPaths`, no tracked edits), and `dependsOn` the PRD that lands its tracked edits. Host crontab installs stay human-only (see §15).
|
|
129
|
+
Why: burrow PRD 1516 halted because its relative `.venv` python against `downloads/fb-tracker.db`, `scripts/install-cron.sh` and `pipeline-cron.sh --now` resolved inside the worktree (no runtime state; install-cron would bake a temporary worktree path into crontab), while sibling 1494 succeeded the same day using an absolute main-checkout path and artifact-only output. `scheduler_create_prd` warns on relative gitignored paths.
|
|
130
|
+
|
|
128
131
|
---
|
|
129
132
|
|
|
130
133
|
## §8 Scope sizing — target ≤10 min, ceiling 15
|
|
@@ -228,6 +231,7 @@ Before queueing a new PRD, verify each of these:
|
|
|
228
231
|
- [ ] **§5 Frontmatter:** `title`, `cwd` (exists on this machine), `estimateMinutes` present; `dependsOn` used for ordering, not `parallelGroup`.
|
|
229
232
|
- [ ] **§6 Gate and files:** `gate` follows every rule in §6 (or is `["none"]` alone); `files` is 1–50 repo-relative paths, no overlap with a concurrent PRD.
|
|
230
233
|
- [ ] **§7 Self-contained:** no reference to "the conversation" or outside context; paths/identifiers inline; clean UTF-8, no NUL bytes (`grep -qP '\x00' file && echo BAD`).
|
|
234
|
+
- [ ] **§7 Worktree reach:** no relative path to a gitignored file; live-run steps use absolute main-checkout paths in an artifact-only PRD. Why: the job worktree has no gitignored runtime state, so relative paths fail or bake a temporary path into host config (burrow 1516).
|
|
231
235
|
- [ ] **§8 Scope:** targets ≤10 min, ceiling 15; e2e/publish sharded to one spec per PRD.
|
|
232
236
|
- [ ] **§9 Failure surfacing:** errors exit 1 with a diagnostic line; no silent `|| true`.
|
|
233
237
|
- [ ] **§10 Negative assertions:** every "should find nothing" check is inverted to exit 0 on the clean case.
|
package/src/main/webRemote.cjs
CHANGED
|
@@ -481,6 +481,9 @@ async function connect() {
|
|
|
481
481
|
// too. This keeps the session up even if the relay ever stops answering the
|
|
482
482
|
// app-level pings (the exact failure that silently dropped sessions every ~100s
|
|
483
483
|
// before the relay learned to pong). node 'ws' auto-replies to the ping itself.
|
|
484
|
+
// Relay protocol pings are not guaranteed to reach the desktop through the
|
|
485
|
+
// bilko.run front proxy (observed 2026-10-17: none in 120s on a live link), so
|
|
486
|
+
// they must never be used as a liveness requirement.
|
|
484
487
|
ws.on('ping', () => { _missedPongs = 0; });
|
|
485
488
|
}
|
|
486
489
|
|