claude-code-session-manager 0.95.0 → 0.97.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/{DataModel-DZK9QZpV.js → DataModel-D93FoaOm.js} +1 -1
- package/dist/assets/History-CXxxqNP1.js +2 -0
- package/dist/assets/{Hooks-CmK6l0uf.js → Hooks-CzeYFQjq.js} +3 -3
- package/dist/assets/{HostBilko-D8TIx-Bx.js → HostBilko-nESrTRIg.js} +1 -1
- package/dist/assets/{Library-DTxpOjx8.js → Library-D2zPkwOC.js} +1 -1
- package/dist/assets/{MarkdownEditor-BPJyrevq.js → MarkdownEditor-DbinP78A.js} +1 -1
- package/dist/assets/{McpServers-B_rvIYDs.js → McpServers-Bu_sVGLr.js} +2 -2
- package/dist/assets/Memory-BgiI6LZ_.js +8 -0
- package/dist/assets/{Permissions-DhMMp27n.js → Permissions-C1MMzZRm.js} +3 -3
- package/dist/assets/Plugins-Dhu6wAZi.js +2 -0
- package/dist/assets/{ProvenanceBadge-ptlItdCK.js → ProvenanceBadge-C3AcWKMG.js} +1 -1
- package/dist/assets/{SaveBar-CSbNSl2W.js → SaveBar-plwYm0iO.js} +1 -1
- package/dist/assets/Scheduler-BVYTeh39.js +16 -0
- package/dist/assets/{ScopeSwitcher-BJof-GWH.js → ScopeSwitcher-DFy0vv_o.js} +1 -1
- package/dist/assets/Settings-DIhGgdfs.js +3 -0
- package/dist/assets/{SkillReferenceGraph-CGl4B89-.js → SkillReferenceGraph-DsI7hRPB.js} +1 -1
- package/dist/assets/Skills-3E748UfB.js +3 -0
- package/dist/assets/{SystemPrompt-DKj-q39J.js → SystemPrompt-BqmfUJOd.js} +1 -1
- package/dist/assets/TagLibrary-CPz6fO8Q.js +1 -0
- package/dist/assets/{TiptapBody-BbcJL9az.js → TiptapBody-D9EoBQ1P.js} +1 -1
- package/dist/assets/{Toggle-DAslvnnv.js → Toggle-BHAmZNDn.js} +1 -1
- package/dist/assets/index-tn5JIVPj.js +3079 -0
- package/dist/assets/{settingsSchema-pzp0TgvN.js → settingsSchema-Crqy_aNz.js} +1 -1
- package/dist/index.html +1 -1
- package/package.json +8 -2
- package/plugins/CLAUDE.md +3 -3
- package/plugins/session-manager-dev/skills/develop/SKILL.md +90 -67
- package/plugins/session-manager-dev/skills/develop/standards.md +5 -11
- package/plugins/session-manager-dev/skills/requesting-code-review/SKILL.md +5 -15
- package/scripts/README.md +1 -0
- package/scripts/hooks/guard-destructive-git.cjs +9 -374
- package/scripts/hooks/guard-inline-implementation.cjs +9 -128
- package/scripts/hooks/guard-prd-writes.cjs +9 -74
- package/scripts/hooks/guard-self-schedule.cjs +9 -61
- package/scripts/hooks/lib/guard-destructive-git-policy.cjs +410 -0
- package/scripts/hooks/lib/guard-inline-implementation-policy.cjs +159 -0
- package/scripts/hooks/lib/guard-prd-writes-policy.cjs +100 -0
- package/scripts/hooks/lib/guard-self-schedule-policy.cjs +89 -0
- package/scripts/scheduler-mcp-server.cjs +8 -1
- package/src/main/__tests__/configWriteBoundaryOwners.test.cjs +59 -0
- package/src/main/__tests__/exchanges.test.cjs +41 -96
- package/src/main/__tests__/exchangesPromptId.test.cjs +16 -25
- package/src/main/__tests__/files-reject-credentials.test.cjs +1 -1
- package/src/main/__tests__/health-credentials.test.cjs +81 -0
- package/src/main/__tests__/ipcSchemas-dependsOn.test.cjs +39 -0
- package/src/main/__tests__/memoryAggregate.test.cjs +40 -1
- package/src/main/__tests__/opsErrorLogTelemetryTap.test.cjs +1 -1
- package/src/main/__tests__/planValidator.test.cjs +125 -0
- package/src/main/__tests__/prdCreate.test.cjs +3 -1
- package/src/main/__tests__/prdSizing.test.cjs +106 -0
- package/src/main/__tests__/queue-starvation-dispatch-driver.test.cjs +46 -0
- package/src/main/__tests__/reconcileFlatPrdSweep.test.cjs +10 -0
- package/src/main/__tests__/scheduler-looks-done.test.cjs +40 -0
- package/src/main/__tests__/scheduler-notify-originating-tab.test.cjs +81 -0
- package/src/main/__tests__/scheduler-shard-quarantine.test.cjs +6 -1
- package/src/main/__tests__/schedulerStateSidecarRestore.test.cjs +110 -0
- package/src/main/__tests__/seedAgentPersonas.test.cjs +19 -1
- package/src/main/__tests__/seedValidatorPersona.test.cjs +116 -0
- package/src/main/__tests__/telemetryClient.test.cjs +2 -2
- package/src/main/__tests__/telemetryContract.test.cjs +2 -2
- package/src/main/__tests__/usageSingleFlight.test.cjs +10 -0
- package/src/main/__tests__/validationSentinels.test.cjs +84 -0
- package/src/main/build-info.json +4 -4
- package/src/main/config.cjs +26 -14
- package/src/main/exchanges.cjs +26 -21
- package/src/main/health.cjs +66 -4
- package/src/main/index.cjs +1 -1
- package/src/main/ipcSchemas.cjs +15 -7
- package/src/main/lib/__tests__/crashTelemetry.test.cjs +1 -1
- package/src/main/lib/__tests__/credentials-futile-refresh.test.cjs +115 -0
- package/src/main/lib/__tests__/epicWorktreeProjectConfig.test.cjs +85 -27
- package/src/main/lib/__tests__/gitWorktree.test.cjs +21 -27
- package/src/main/lib/__tests__/guardShims.test.cjs +10 -3
- package/src/main/lib/__tests__/loadGate.test.cjs +44 -1
- package/src/main/lib/__tests__/opsOwnership.test.cjs +14 -0
- package/src/main/lib/__tests__/telemetryBacklog.test.cjs +4 -4
- package/src/main/lib/__tests__/telemetryConsent.test.cjs +2 -2
- package/src/main/lib/__tests__/telemetryCountersMetadataColumn.test.cjs +1 -1
- package/src/main/lib/agentModelResolve.cjs +1 -0
- package/src/main/lib/credentials.cjs +62 -0
- package/src/main/lib/cwdClassify.cjs +15 -0
- package/src/main/lib/definitionOfDone.cjs +9 -13
- package/src/main/lib/effectiveModelInfo.cjs +2 -9
- package/src/main/lib/epicWorktreeProjectConfig.cjs +75 -31
- package/src/main/lib/loadGate.cjs +29 -5
- package/src/main/lib/opsOwnership.cjs +23 -0
- package/src/main/lib/planValidator.cjs +80 -0
- package/src/main/lib/prdCreate.cjs +8 -4
- package/src/main/lib/prdSizing.cjs +83 -0
- package/src/main/lib/runLogRetention.cjs +2 -8
- package/src/main/lib/telemetryBacklog.cjs +9 -3
- package/src/main/lib/telemetryClient.cjs +12 -3
- package/src/main/lib/telemetrySettings.cjs +8 -2
- package/src/main/lib/validationSentinels.cjs +29 -0
- package/src/main/memoryAggregate.cjs +36 -11
- package/src/main/otelSettings.cjs +8 -2
- package/src/main/scheduler.cjs +215 -31
- package/src/main/seedAgentPersonas.cjs +1 -1
- package/src/main/sessionsStore.cjs +8 -2
- package/src/main/supervisor.cjs +3 -3
- package/src/main/templates/PRD_AUTHORING.md +9 -9
- package/src/main/voiceSettings.cjs +8 -2
- package/src/preload/api.d.ts +3 -3
- package/src/preload/index.cjs +5 -5
- package/src/seed/agents/dev-lead.md +24 -15
- package/src/seed/agents/validator.md +33 -0
- package/dist/assets/History-BDyJUGtR.js +0 -2
- package/dist/assets/Memory-B-9GlHqe.js +0 -8
- package/dist/assets/Plugins-DKfAlmMY.js +0 -2
- package/dist/assets/Scheduler--rn1QBYc.js +0 -16
- package/dist/assets/Settings-Dsx6XZP5.js +0 -3
- package/dist/assets/Skills-D522Zfol.js +0 -3
- package/dist/assets/TagLibrary-BH7CG7-6.js +0 -1
- package/dist/assets/index-Yf8e7VCB.js +0 -3079
|
@@ -1 +1 @@
|
|
|
1
|
-
import{az as b,ak as n,S as N,aO as O,ax as K}from"./index-Yf8e7VCB.js";function T({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(I,{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&&_(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 I({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 _(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 G(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 z(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:B([...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 B(e){return Array.from(new Set(e))}let $=null;function V(){return $||($=z(K)),$}export{T as E,V as s,G as u};
|
|
1
|
+
import{az as b,ak as n,S as N,aR as k,ax as K}from"./index-tn5JIVPj.js";function T({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(R,{...e,node:e.node}):n.jsx(J,{...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(I,{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 R({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:O(g.value)}),n.jsx(C,{scope:g.fromScope})]},d))]}):null}function J({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:O(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&&_(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:O(t.value)}),n.jsx(C,{scope:t.scope,dim:!0})]},i))]})}function I({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: ",O(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 _(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 O(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 G(e,r,s){const a=k(o=>o.files),m=k(o=>o.loadJson),f=k(o=>o.watchFile),x=k(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 z(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:B([...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 B(e){return Array.from(new Set(e))}let $=null;function V(){return $||($=z(K)),$}export{T as E,V as s,G 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-tn5JIVPj.js"></script>
|
|
11
11
|
<link rel="modulepreload" crossorigin href="./assets/monaco-editor-BW5C4Iv1.js">
|
|
12
12
|
<link rel="stylesheet" crossorigin href="./assets/monaco-editor-BTnBOi8r.css">
|
|
13
13
|
<link rel="stylesheet" crossorigin href="./assets/index-CKH5Uxik.css">
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-code-session-manager",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.97.0",
|
|
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",
|
|
@@ -20,6 +20,10 @@
|
|
|
20
20
|
"scripts/hooks/guard-destructive-git.cjs",
|
|
21
21
|
"scripts/hooks/guard-inline-implementation.cjs",
|
|
22
22
|
"scripts/hooks/guard-self-schedule.cjs",
|
|
23
|
+
"scripts/hooks/lib/guard-destructive-git-policy.cjs",
|
|
24
|
+
"scripts/hooks/lib/guard-self-schedule-policy.cjs",
|
|
25
|
+
"scripts/hooks/lib/guard-prd-writes-policy.cjs",
|
|
26
|
+
"scripts/hooks/lib/guard-inline-implementation-policy.cjs",
|
|
23
27
|
"src/main/",
|
|
24
28
|
"src/preload/",
|
|
25
29
|
"src/seed/",
|
|
@@ -39,6 +43,7 @@
|
|
|
39
43
|
"prepack": "node scripts/write-build-info.cjs",
|
|
40
44
|
"prepublishOnly": "node scripts/write-build-info.cjs && vite build",
|
|
41
45
|
"test:unit": "vitest run",
|
|
46
|
+
"test:unit:stability": "bash scripts/test-unit-stability.sh",
|
|
42
47
|
"bench": "node scripts/bench/main-bench.cjs",
|
|
43
48
|
"bench:renderer": "vitest run --config vitest.bench.config.ts",
|
|
44
49
|
"test:e2e": "xvfb-run -a playwright test",
|
|
@@ -58,7 +63,8 @@
|
|
|
58
63
|
"lint:any": "node scripts/check-explicit-any.cjs",
|
|
59
64
|
"lint:main-ts-check": "node scripts/check-main-ts-check.cjs",
|
|
60
65
|
"lint:filenames": "node scripts/check-tracked-filenames.cjs",
|
|
61
|
-
"lint": "
|
|
66
|
+
"lint:renderer-storage": "node scripts/check-renderer-storage.cjs",
|
|
67
|
+
"lint": "npm run lint:selectors && npm run lint:hooks && npm run lint:unregistered-tests && npm run lint:docs && npm run lint:paths && npm run lint:any && npm run lint:main-ts-check && npm run lint:filenames && npm run lint:renderer-storage",
|
|
62
68
|
"sync:settings-schema": "node scripts/sync-settings-schema.cjs"
|
|
63
69
|
},
|
|
64
70
|
"keywords": [
|
package/plugins/CLAUDE.md
CHANGED
|
@@ -49,9 +49,9 @@ for live sibling consumers.
|
|
|
49
49
|
- Do not confuse this with `.claude/` at the repo root — this repo's own unshipped local dev
|
|
50
50
|
config. `.claude/agents/*.md` are per-project OVERLAYS that win over
|
|
51
51
|
`~/.claude/agents/*.md` (Claude Code's own precedence, per `src/main/agentLibrary.cjs`);
|
|
52
|
-
`src/seed/agents/` is the shipped source for
|
|
53
|
-
`src/main/seedAgentPersonas.cjs` copies into `~/.claude/agents/` on first boot (
|
|
54
|
-
`
|
|
52
|
+
`src/seed/agents/` is the shipped source for the four personas
|
|
53
|
+
`src/main/seedAgentPersonas.cjs` copies into `~/.claude/agents/` on first boot (see its
|
|
54
|
+
`PERSONAS` list); `builder` and `bilko-host-publisher` have no seed source
|
|
55
55
|
and exist only as this repo's overlays. Tracked on purpose: `.claude/settings.json` (guard
|
|
56
56
|
hooks) plus the `builder.md`/`project-home-builder.md` overlays (auditable edits) —
|
|
57
57
|
`bilko-host-publisher.md` is untracked despite being in use; nothing else under `.claude/` is.
|
|
@@ -3,7 +3,8 @@ name: develop
|
|
|
3
3
|
description: >-
|
|
4
4
|
Lead a software-development task by analyzing it from multiple angles (positive path, edge
|
|
5
5
|
cases, interaction effects, integration, UI validation) and decomposing it into a series of
|
|
6
|
-
self-contained PRDs
|
|
6
|
+
self-contained PRDs, sized as <10-minute Sonnet-executable work-items — either a handful of
|
|
7
|
+
independent small PRDs, or a 3-5 PRD evolving chain
|
|
7
8
|
with sub-tasked acceptance criteria for larger asks — queued for the session-manager
|
|
8
9
|
scheduler, each pointing the headless executor at the engineering standards file to read at
|
|
9
10
|
runtime — then track those PRDs to completion, verify them against their acceptance criteria,
|
|
@@ -200,6 +201,28 @@ can't load skills.
|
|
|
200
201
|
completeness pass instead of extending the chain further; a chain that long is a sign the
|
|
201
202
|
original decomposition was wrong, not that it needs one more link. A chain does not relax
|
|
202
203
|
the ~15-min/30-min-ceiling sizing below — each link is still individually small.
|
|
204
|
+
|
|
205
|
+
**Every plan ends with one `validate` PRD.** After the work-item PRDs are written, author
|
|
206
|
+
exactly one more through `scheduler_create_prd`: `agentType: "validator"`, `tag: "build"`,
|
|
207
|
+
`estimateMinutes: 10`, `dependsOn` = every other slug in this plan (`dependsOn` is capped at
|
|
208
|
+
100 entries; for a plan bigger than that, list only the plan's sink PRDs — those nothing else
|
|
209
|
+
in the plan depends on — since `hasDownstreamValidator` walks `dependsOn` transitively, so a
|
|
210
|
+
validator anchored on the sinks alone still covers every upstream PRD), slug
|
|
211
|
+
`validate-<short-plan-name>`. Its Goal lists the plan's PRD slugs and titles; its Acceptance
|
|
212
|
+
criteria give, per PRD, where its file lives
|
|
213
|
+
(`<cwd>/session-manager-operations/scheduler/epics/<epic-id>/prds/<NN>-<slug>.md` while queued,
|
|
214
|
+
the sibling `prds-archived/` once terminal — locate by slug in either) and end with the
|
|
215
|
+
review-record path to write and commit:
|
|
216
|
+
`session-manager-operations/reviews/validation/<epic-id>/<validate-slug>.md`.
|
|
217
|
+
Implementation notes: "Work as the validator persona — the procedure is your system prompt."
|
|
218
|
+
While a plan has a pending validator, the scheduler suppresses both the per-PRD validation
|
|
219
|
+
prompt into this session and the in-run `/code-review` steps for its work-items — one review,
|
|
220
|
+
once, at the end. If `scheduler_create_prd` rejects `agentType: "validator"` (persona not
|
|
221
|
+
installed on this machine yet — the usual cause is a running app older than 0.96.0, since the
|
|
222
|
+
validator persona is only seeded to `~/.claude/agents` on app boot), say so and fall back to
|
|
223
|
+
today's per-PRD validation; do not hand-write the file. Note the stale-app cause in your report
|
|
224
|
+
so the human knows to restart onto >=0.96.0.
|
|
225
|
+
|
|
203
226
|
- **Sub-tasked Acceptance Criteria** (either shape, when a single PRD legitimately spans more
|
|
204
227
|
than one concern dimension from step 3 — e.g. it has both core-functionality and
|
|
205
228
|
edge-case/interaction-effect checks): group the `# Acceptance criteria` checklist under
|
|
@@ -355,9 +378,9 @@ can't load skills.
|
|
|
355
378
|
|
|
356
379
|
- [ ] <each line is a verifiable check the executor can run after building>
|
|
357
380
|
- [ ] <include explicit file paths, function names, expected behavior>
|
|
358
|
-
- [ ] a bounded
|
|
359
|
-
`
|
|
360
|
-
|
|
381
|
+
- [ ] exactly one gate line — a bounded command or an `&&` chain of at most two, e.g.
|
|
382
|
+
`timeout 300 npm run typecheck && timeout 300 npx vitest run <file>` (the run-before-done
|
|
383
|
+
rule lives in standards.md; the AC just names the command).
|
|
361
384
|
|
|
362
385
|
# Implementation notes
|
|
363
386
|
|
|
@@ -383,17 +406,31 @@ can't load skills.
|
|
|
383
406
|
"the design we discussed"; if a PRD depends on another PRD's output, say so in
|
|
384
407
|
`# Implementation notes` AND give it a higher `NN` so it queues after.
|
|
385
408
|
|
|
386
|
-
**
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
409
|
+
**Work-item shape — every PRD must be executable by a Sonnet-class executor in under 10
|
|
410
|
+
minutes (2026-09 calibration: wall p50 7.8 min, 60% of runs ≤ 10 min; authored estimates ran
|
|
411
|
+
4× high).**
|
|
412
|
+
- **One change-set per PRD**: ≤ 3 files edited, ≤ 1 new file, exactly ONE gate line (a
|
|
413
|
+
bounded command or an `&&` chain of at most two). If a PRD needs a new shared helper AND
|
|
414
|
+
its first consumer, that is two PRDs (`primitive` → `wire`).
|
|
415
|
+
- **≤ 6 AC lines**: each behavior line names file + symbol + the observable result; exactly
|
|
416
|
+
one tests line naming the test file and the test names; exactly one gate line. No
|
|
417
|
+
open-ended lines ("grep X and update whatever depends on it") — resolve the list yourself
|
|
418
|
+
while authoring and name the files.
|
|
419
|
+
- **Implementation notes are a recipe, not prose**: `Read first:` (≤ 4 files, with line
|
|
420
|
+
ranges), `Steps:` (numbered, each naming the file and the function/signature), `Do not
|
|
421
|
+
touch:` (files a sibling PRD owns). Quote a signature rather than describing it.
|
|
422
|
+
- **`estimateMinutes` ≤ 10 target, 15 ceiling** — project more, split. (The scheduler's kill
|
|
423
|
+
budget floors at 45 min regardless, so a low estimate never starves a run.)
|
|
424
|
+
- **Decomposition types** — name one per PRD in its first Goal sentence, and chain in this
|
|
425
|
+
order when several apply:
|
|
426
|
+
- `primitive` — one new helper/module + its unit test, no call sites.
|
|
427
|
+
- `wire` — adopt an existing primitive at named call sites, no logic change.
|
|
428
|
+
- `behavior` — one function's logic change + the test that pins it.
|
|
429
|
+
- `migration` — mechanical rename/move/config change, no logic; gate is typecheck/lint.
|
|
430
|
+
- `doc` — text only; gate is `lint:docs` or the doc's own test.
|
|
431
|
+
- `validate` — the plan's trailing validation PRD (see Phase 2).
|
|
432
|
+
- `scheduler_create_prd` returns `warnings[]` when a PRD exceeds these limits — fix the PRD
|
|
433
|
+
before confirming it to the user; never queue a warned PRD silently.
|
|
397
434
|
|
|
398
435
|
5. **Emit each PRD.** If you used `scheduler_create_prd`, this step is already done — the tool
|
|
399
436
|
wrote the file to the canonical path with the standards pointer included; skip to step 5.
|
|
@@ -414,64 +451,50 @@ can't load skills.
|
|
|
414
451
|
|
|
415
452
|
6. **Confirm to the user**, per emitted PRD: filename, chosen `NN` + rationale
|
|
416
453
|
(parallel-with-X / serial-after-Y), `cwd`, and an ETA + token-cost ballpark. Note they can
|
|
417
|
-
"Run now" in the SchedulePanel or wait for `when-available` polling.
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
- **
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
- Is a structural refactor (no behavior change intended) → dispatch `refactorer`.
|
|
454
|
-
- Is performance-sensitive or touches a hot path → dispatch `perf-profiler`.
|
|
455
|
-
- Adds or updates a dependency → dispatch `dependency-auditor`.
|
|
456
|
-
- Touches a database schema, migration, or table design → **no specialist exists for this
|
|
457
|
-
in this environment today.** Don't silently let the generic code-reviewer stand in for a
|
|
458
|
-
schema review it isn't specialized for — say so explicitly in your report ("schema change,
|
|
459
|
-
no dedicated reviewer available, manual review recommended") rather than implying coverage
|
|
460
|
-
that isn't there.
|
|
461
|
-
- Anything else, or a **major feature/risky change** not covered above — dispatch the
|
|
462
|
-
generic `requesting-code-review` skill (`code-reviewer` agent) as the default.
|
|
463
|
-
Fix Critical/Important findings from whichever specialist(s) ran before calling it done.
|
|
464
|
-
- **Report back**: what landed, PRD/commit refs, which specialist(s) reviewed it (or the
|
|
465
|
-
explicit "no specialist available" note), verification result, anything left open.
|
|
454
|
+
"Run now" in the SchedulePanel or wait for `when-available` polling. Name the plan's validate
|
|
455
|
+
PRD and state that no per-PRD validation will be requested from this session.
|
|
456
|
+
|
|
457
|
+
## Phase 2 — Validation runs as its own job; this session only decides
|
|
458
|
+
|
|
459
|
+
Every plan queued in Phase 1 ends with a `validate` PRD (agentType `validator`) whose
|
|
460
|
+
`dependsOn` lists every other slug in the plan — or, for a plan over the 100-entry cap, just the
|
|
461
|
+
plan's sink PRDs, since `hasDownstreamValidator` walks `dependsOn` transitively and still credits
|
|
462
|
+
every upstream PRD — so the scheduler runs it exactly once, after the last work-item lands.
|
|
463
|
+
That job — not this session — re-runs each PRD's gate, checks every
|
|
464
|
+
acceptance criterion against the tree, reviews the plan's combined diff (`/code-review`,
|
|
465
|
+
`/security-review`), commits a review record, and ends with `VALIDATION: <slug>
|
|
466
|
+
VERIFIED|REFUTED` per PRD. The scheduler appends one verdict event per PRD to this Epic (the
|
|
467
|
+
traffic light reads them) plus one check-in for the validator itself.
|
|
468
|
+
|
|
469
|
+
7. **Do not poll and do not re-verify per PRD.** Completed work-items arrive here as check-in
|
|
470
|
+
events only; leave them alone. There is no 30-minute loop to start and no `ScheduleWakeup` to
|
|
471
|
+
arm. Act on exactly three signals:
|
|
472
|
+
- **A work-item parks `needs_review` / `failed`** — read the scheduler's auto-filed RCA
|
|
473
|
+
(`<date>-rca-<slug>-<runId>.md` in the project's feedback inbox) and decide: fix the PRD
|
|
474
|
+
(`scheduler_update_prd`) and `scheduler_reset_job`, or `scheduler_archive_prd` it. The
|
|
475
|
+
plan's validator waits behind it. A `rateLimited` exit is the scheduler's benign auto-pause
|
|
476
|
+
— not a signal.
|
|
477
|
+
- **The validator's check-in arrives** — read its review record. Every PRD VERIFIED and no
|
|
478
|
+
Critical/Important finding → the plan is done; report what landed (slugs, commits, record
|
|
479
|
+
path). Any REFUTED PRD or Critical/Important finding → queue a fix wave: one `behavior`/
|
|
480
|
+
`wire` PRD per finding (recipe format, ≤ 10 min each), no `dependsOn`, plus a new trailing
|
|
481
|
+
`validate` PRD for the wave. Do not fix inline.
|
|
482
|
+
- **The validator itself parks** — treat it like any parked job; its RCA says why the
|
|
483
|
+
procedure could not run.
|
|
484
|
+
|
|
485
|
+
8. **Definition of done** = the plan's latest validator reported every PRD VERIFIED with no open
|
|
486
|
+
Critical/Important finding, and its review record is committed. Report: what landed (PRD
|
|
487
|
+
slugs, commits), the record path, findings deferred as Minor, anything left open. A plan with
|
|
488
|
+
a REFUTED PRD is never "done with caveats" — it gets a fix wave or an explicit human decision
|
|
489
|
+
to stop.
|
|
466
490
|
|
|
467
491
|
## References (reuse, don't duplicate)
|
|
468
492
|
|
|
469
493
|
- `~/.claude/session-manager/scheduled-plans/PRD_AUTHORING.md` — the §1–§10 safety rules.
|
|
470
494
|
- `standards.md` beside this file — the engineering + execution-discipline rules. Every PRD points the executor at its absolute path (see "Standards" above) rather than embedding a copy.
|
|
471
495
|
- `test-driven-development`, `systematic-debugging` — interactive dev sessions.
|
|
472
|
-
- `
|
|
473
|
-
|
|
474
|
-
area (see step 8) rather than always defaulting to the generic reviewer.
|
|
496
|
+
- `validator` persona (src/seed/agents/validator.md) — the plan-level review point for scheduled
|
|
497
|
+
work; `requesting-code-review` — interactive sessions reviewing their own inline work only.
|
|
475
498
|
|
|
476
499
|
## Notes
|
|
477
500
|
|
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
# Engineering standards
|
|
2
2
|
|
|
3
|
-
> Single source of truth for the
|
|
4
|
-
>
|
|
5
|
-
>
|
|
6
|
-
>
|
|
7
|
-
>
|
|
8
|
-
> skills and no conversation — inlining this is the only way these rules reach it. Edit
|
|
9
|
-
> here once; every call site updates.
|
|
10
|
-
>
|
|
11
|
-
> The **Execution discipline** section below is the executor-facing core — it is the part
|
|
12
|
-
> that MUST appear in every PRD body. The rest (Performance, Debugging, API reuse, TDD)
|
|
13
|
-
> guides authoring and interactive work.
|
|
3
|
+
> Single source of truth for the engineering rationale behind every scheduled PRD.
|
|
4
|
+
> `scheduler_create_prd` (src/main/lib/prdCreate.cjs) appends a one-line pointer to this file's
|
|
5
|
+
> absolute path to every PRD — never a copy — and the executor's ordered run contract lives in
|
|
6
|
+
> the `dev-lead` persona it is launched as. Read a section here when a contract line needs its
|
|
7
|
+
> reasoning; edit here once and every PRD sees it.
|
|
14
8
|
|
|
15
9
|
## Performance
|
|
16
10
|
|
|
@@ -76,21 +76,11 @@ You: [Fix progress indicators]
|
|
|
76
76
|
|
|
77
77
|
## Integration with /develop
|
|
78
78
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
specialist fits. Don't treat this skill as covering ground those specialists already own.
|
|
85
|
-
|
|
86
|
-
Since this project's actual unit of work is a scheduler PRD (not a live multi-task session), the
|
|
87
|
-
review point is per-PRD, at its own commit range — `BASE_SHA`/`HEAD_SHA` above are that PRD's
|
|
88
|
-
commit(s), not an arbitrary task boundary from a different workflow shape. Review:
|
|
89
|
-
- **After a PRD completes**, as part of `/develop`'s definition-of-done gate (step 8) — every
|
|
90
|
-
major/risky PRD, before calling it done.
|
|
91
|
-
- **When a PRD comes back `needs_review`** — read the scheduler's auto-filed RCA first
|
|
92
|
-
(`rcaFeedbackHook`'s `<date>-rca-<slug>-<runId>.md`), then use this review to confirm the fix
|
|
93
|
-
if one gets queued.
|
|
79
|
+
For scheduled work, review happens once per plan in the trailing `validate` PRD (persona
|
|
80
|
+
`validator`), which runs `/code-review` and `/security-review` over the plan's combined diff and
|
|
81
|
+
reports per-PRD VERIFIED/REFUTED verdicts. This skill is for an interactive session reviewing its
|
|
82
|
+
own inline work. Never dispatch a `code-reviewer` subagent from a headless run — it has no next
|
|
83
|
+
turn to collect the result.
|
|
94
84
|
|
|
95
85
|
## Red Flags
|
|
96
86
|
|
package/scripts/README.md
CHANGED
|
@@ -15,6 +15,7 @@ scripts/lib was moved into src/main/lib (2026-09); nothing under src/ may requir
|
|
|
15
15
|
| check-doc-hierarchy.cjs | `npm run lint:docs` (in `lint`) | no |
|
|
16
16
|
| check-explicit-any.cjs | `npm run lint:any` (in `lint`) — bans explicit `any`/`@ts-ignore` in renderer+preload; per-line `// lint-allow-any: <reason>` | no |
|
|
17
17
|
| check-main-ts-check.cjs | `npm run lint:main-ts-check` (in `lint`) — `tsconfig.main.json` `include` ⇔ `// @ts-check` first line, both directions; explicit list only, `checkJs` false | no |
|
|
18
|
+
| check-renderer-storage.cjs | `npm run lint:renderer-storage` (in `lint`) — ratchet-bans `localStorage.`/`sessionStorage.` in `src/renderer` outside an explicit ALLOWLIST (Epic stateless-ui-review) | no |
|
|
18
19
|
| check-tracked-filenames.cjs | `npm run lint:filenames` (in `lint`) — fails on tracked paths with Windows-illegal chars, trailing dot/space, or reserved device names | no |
|
|
19
20
|
| check-unregistered-tests.cjs | `npm run lint:unregistered-tests` (in `lint`) | no |
|
|
20
21
|
| check-unstable-selectors.cjs | `npm run lint:selectors` (in `lint`) | no |
|