@a-company/paradigm 5.21.0 → 5.21.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/mcp.js CHANGED
@@ -739,7 +739,7 @@ This structured output helps track progress and pass context between agents.`);l
739
739
  `)[0].trim(),color:d.color,appliesTo:d["applies-to"]}))),(o==="all"||o==="suggested")&&(c.suggested=(a.suggested||[]).map(l=>({tag:l.tag,reason:l.reason,proposedBy:l["proposed-by"],proposedAt:l["proposed-at"]}))),c.summary={coreCount:Object.keys(a.core||{}).length,projectCount:Object.keys(a.project||{}).length,suggestedCount:(a.suggested||[]).length},{handled:true,text:JSON.stringify(c,null,2)}}if(t==="search"){if(!i)return {handled:true,text:JSON.stringify({error:"Query required for search action"})};let c=i.toLowerCase(),l=[];for(let[d,p]of Object.entries(a.core||{}))(d.toLowerCase().includes(c)||p.description?.toLowerCase().includes(c)||p.aliases?.some(u=>u.toLowerCase().includes(c)))&&l.push({tag:d,category:"core",description:p.description?.split(`
740
740
  `)[0].trim()||""});for(let[d,p]of Object.entries(a.project||{}))(d.toLowerCase().includes(c)||p.description?.toLowerCase().includes(c)||p.aliases?.some(u=>u.toLowerCase().includes(c)))&&l.push({tag:d,category:"project",description:p.description?.split(`
741
741
  `)[0].trim()||""});return {handled:true,text:JSON.stringify({query:i,count:l.length,matches:l},null,2)}}if(t==="get"){if(!r)return {handled:true,text:JSON.stringify({error:"Tag name required for get action"})};if(a.core?.[r]){let l=a.core[r];return {handled:true,text:JSON.stringify({tag:r,category:"core",description:l.description,color:l.color,appliesTo:l["applies-to"],aliases:l.aliases,requiresAspect:l["requires-aspect"]},null,2)}}if(a.project?.[r]){let l=a.project[r];return {handled:true,text:JSON.stringify({tag:r,category:"project",description:l.description,color:l.color,appliesTo:l["applies-to"],aliases:l.aliases,requiresAspect:l["requires-aspect"]},null,2)}}let c=a.suggested?.find(l=>l.tag===r);return c?{handled:true,text:JSON.stringify({tag:r,category:"suggested",reason:c.reason,proposedBy:c["proposed-by"],proposedAt:c["proposed-at"],appliesTo:c["applies-to"],exampleSymbols:c["example-symbols"],status:"pending approval"},null,2)}:{handled:true,text:JSON.stringify({error:`Tag "${r}" not found`,suggestion:'Use paradigm_tags with action "list" to see available tags'})}}return {handled:true,text:JSON.stringify({error:`Unknown action: ${t}`})}}case "paradigm_tags_suggest":{let{tag:t,description:i,reason:r,appliesTo:o,exampleSymbols:a}=e,c=ga(s.rootDir);if(!c)return {handled:true,text:JSON.stringify({error:"Tag bank not found",suggestion:"Create .paradigm/tags.yaml first"})};if(c.core?.[t]||c.project?.[t])return {handled:true,text:JSON.stringify({error:`Tag "${t}" already exists`,existing:c.core?.[t]?"core":"project"})};if(c.suggested?.some(d=>d.tag===t))return {handled:true,text:JSON.stringify({error:`Tag "${t}" is already in the suggested queue`,status:"pending approval"})};let l={tag:t,"proposed-by":"claude","proposed-at":new Date().toISOString(),reason:r,"applies-to":o||["#"],"example-symbols":a};return c.suggested||(c.suggested=[]),c.suggested.push(l),zd(s.rootDir,c),{handled:true,text:JSON.stringify({success:true,tag:t,status:"pending approval",message:"Tag suggestion added. Human review required before use.",nextSteps:["Human can approve via Sentinel UI or CLI",'Once approved, tag moves to "project" section',"Then AI can use the tag for classification"]},null,2)}}case "paradigm_aspect_check":{let{aspect:t}=e,i=t.startsWith("~")?t:`~${t}`,r=h$1(s.index,i);if(!r)return {handled:true,text:JSON.stringify({error:`Aspect "${i}" not found`,suggestion:"Use paradigm_search to find available aspects"})};if(r.type!=="aspect")return {handled:true,text:JSON.stringify({error:`Symbol "${i}" is not an aspect (type: ${r.type})`,note:"Only ~ symbols are aspects"})};let o=r.anchors||[],a=[];for(let m of o){let y=F.isAbsolute(m.path)?m.path:F.join(s.rootDir,m.path),f=O.existsSync(y),b;if(f)try{let w=O.readFileSync(y,"utf-8").split(`
742
- `);typeof m.lines=="number"?b=1:Array.isArray(m.lines)&&m.lines.length===2?b=m.lines[1]-m.lines[0]+1:Array.isArray(m.lines)&&(b=m.lines.length);}catch{}a.push({path:m.path,lines:m.raw.split(":")[1]||"full file",exists:f,lineCount:b});}let c=o.length>0&&a.every(m=>m.exists),l=r.appliesTo||[],d=n(s.index),p=[],u=[];for(let m of d)for(let y of l)if(new RegExp("^"+y.replace(/\*/g,".*").replace(/\?/g,".")+"$").test(m.symbol)){p.push(m.symbol),(m.data?.aspects?.includes?.(i)||m.data?.aspects?.includes?.(t))&&u.push(m.symbol);break}let g=p.filter(m=>!u.includes(m));return {handled:true,text:JSON.stringify({aspect:i,valid:c,description:r.description,enforcement:r.enforcement,anchors:a,coverage:{appliesTo:l,matchingSymbols:p.length,symbolsWithAspect:u.length,missing:g.slice(0,10),missingCount:g.length},warnings:[...o.length===0?["CRITICAL: Aspect has no anchors - aspects MUST have code anchors"]:[],...a.filter(m=>!m.exists).map(m=>`Anchor file not found: ${m.path}`),...g.length>0?[`${g.length} symbols match applies-to but don't have this aspect`]:[]],recommendation:c?g.length>0?"Aspect is valid but has coverage gaps - consider applying to matching symbols":"Aspect is valid and fully applied":"INVALID: Add code anchors to this aspect"},null,2)}}default:return {handled:false,text:""}}}var Bd=["#","$","^","!","~"];function W(n){return n.length>1&&Bd.includes(n[0])?n.slice(1):n}function q(n,e){let s=W(n);return `${e}${s}`}function ce(n,e){let s=F.isAbsolute(n)?n:F.resolve(e,n);return s.endsWith(".purpose")?s:F.join(s,".purpose")}function le(n){if(!O.existsSync(n))return {};let e=a$8(n);if(!e.data)throw new Error(`Failed to parse ${n}: ${e.errors.join(", ")}`);return e.data}function de(n,e){let s=F.dirname(n);O.existsSync(s)||O.mkdirSync(s,{recursive:true});let t=b$a(e);O.writeFileSync(n,t,"utf8");}function Ye(n){if(!n)return {};if(!Array.isArray(n))return n;let e={};for(let s of n){let{id:t,...i}=s;e[t]=i;}return e}function Tn(n){if(!n)return {};if(!Array.isArray(n))return n;let e={};for(let s of n)e[s.name]={description:s.description,steps:s.steps};return e}function at(n,e){if(!e||e.length===0)return n;if(!n||n.length===0)return e;let s=new Set(n);for(let t of e)s.add(t);return Array.from(s)}var Vd={"#":"#","^":"^","!":"!",$:"$","~":"~"};async function ya(n,e,s,t){let i=Vd[t];if(!i)throw new Error(`Invalid symbol type: ${t}. Expected one of: # ^ ! $ ~`);let r=W(e),o=W(s),a=q(r,i),c=q(o,i),l=await c$5(n),d=[];for(let p of l){let u=le(p),g=false,y={"#":"components","^":"gates","!":"signals",$:"flows","~":"aspects"}[i];if(y&&y!=="flows"){let f=u[y];f&&!Array.isArray(f)&&r in f&&(f[o]=f[r],delete f[r],g=true);}if(i==="#")for(let f of ["features","components"]){let b=u[f];b&&!Array.isArray(b)&&r in b&&(b[o]=b[r],delete b[r],g=true);}i==="$"&&u.flows&&!Array.isArray(u.flows)&&r in u.flows&&(u.flows[o]=u.flows[r],delete u.flows[r],g=true);for(let f of ["features","components"]){let b=Ye(u[f]);for(let[h,w]of Object.entries(b))g=Yd(w,a,c)||g;g&&Object.keys(b).length>0&&(u[f]=b);}if(u.flows){let f=Tn(u.flows);for(let[b,h]of Object.entries(f)){if(h.gates){let w=h.gates.indexOf(a);w!==-1&&(h.gates[w]=c,g=true);}if(h.signals){let w=h.signals.indexOf(a);w!==-1&&(h.signals[w]=c,g=true);}if(h.components){let w=h.components.indexOf(a);w!==-1&&(h.components[w]=c,g=true);}if(h.steps)for(let w of h.steps)typeof w=="object"&&"component"in w&&(w.component===a||w.component===r)&&(w.component=i==="#"?o:c,g=true);}g&&(u.flows=f);}if(u.gates){for(let[f,b]of Object.entries(u.gates))if(b.signals){let h=b.signals.indexOf(a);h!==-1&&(b.signals[h]=c,g=true);}}if(u.aspects){for(let[f,b]of Object.entries(u.aspects))if(b["applies-to"]){let h=b["applies-to"].indexOf(a);h!==-1&&(b["applies-to"][h]=c,g=true);}}g&&(de(p,u),d.push(p));}return d}function Yd(n,e,s){let t=false,i=["signals","gates","flows","components","states"];for(let r of i){let o=n[r];if(o){let a=o.indexOf(e);a!==-1&&(o[a]=s,t=true);}}if(n.aspects&&Array.isArray(n.aspects)){let r=n.aspects.indexOf(e);r!==-1&&(n.aspects[r]=s,t=true);}return t}function Dn(n){let e=F.join(n,"portal.yaml");if(!O.existsSync(e))return {data:{version:"1.0.0",gates:{}},filePath:e};let s=O.readFileSync(e,"utf8");return {data:Z.load(s)||{version:"1.0.0",gates:{}},filePath:e}}function ba(n,e){let s=Z.dump(e,{indent:2,lineWidth:-1,noRefs:true,sortKeys:false});O.writeFileSync(n,s,"utf8");}function wa(n,e){let{data:s,filePath:t}=Dn(n);s.gates||(s.gates={});let i=W(e.id),r=s.gates[i]||{};return r.description=e.description,e.type!==void 0&&(r.type=e.type),e.location!==void 0&&(r.location=e.location),e.requires!==void 0&&(r.requires=e.requires),e.check!==void 0&&(r.check=e.check),e.grants!==void 0&&(r.grants=e.grants),e.emits!==void 0&&(r.emits=e.emits),e.prizes!==void 0&&(r.prizes=e.prizes),r.prizes||(r.prizes=[]),s.gates[i]=r,ba(t,s),t}function va(n,e){let{data:s,filePath:t}=Dn(n);s.routes||(s.routes={});let i=`${e.method} ${e.route}`,r=e.gates.map(o=>`^${W(o)}`);return s.routes[i]=r,ba(t,s),t}var Kd={name:"paradigm_purpose_init",description:"Create or update file-level metadata on a .purpose file. Does NOT overwrite existing components/signals/etc \u2014 only touches top-level metadata (name, description, context, version). ~100 tokens.",inputSchema:{type:"object",properties:{purposeFile:{type:"string",description:"Path to .purpose file or parent directory (relative to project root)"},name:{type:"string",description:"Name/title for this purpose file"},description:{type:"string",description:"Description of what this directory/module does"},context:{type:"array",items:{type:"string"},description:"Context notes for AI agents"},version:{type:"string",description:'Version string (default: "1.0.0")'}},required:["purposeFile","name"]},annotations:{readOnlyHint:false,destructiveHint:false}},Qd={name:"paradigm_purpose_add_component",description:"Add or update a component (#) or feature in a .purpose file. Strips # prefix from id automatically. ~100 tokens.",inputSchema:{type:"object",properties:{purposeFile:{type:"string",description:"Path to .purpose file or parent directory"},id:{type:"string",description:'Component ID (e.g. "payment-service" or "#payment-service")'},description:{type:"string",description:"What this component does"},section:{type:"string",enum:["components","features"],description:'Which section to add to (default: "components")'},file:{type:"string",description:"Source file path for this component"},status:{type:"string",description:'Component status (e.g. "active", "deprecated")'},endpoints:{type:"array",items:{type:"string"},description:'API endpoints (e.g. ["POST /api/payments"])'},tests:{type:"array",items:{type:"string"},description:"Test file paths"},flows:{type:"array",items:{type:"string"},description:'Flow references (e.g. ["$checkout-flow"])'},gates:{type:"array",items:{type:"string"},description:'Gate references (e.g. ["^authenticated"])'},signals:{type:"array",items:{type:"string"},description:'Signal references (e.g. ["!payment-completed"])'},aspects:{type:"array",items:{type:"string"},description:'Aspect references (e.g. ["~audit-required"])'},components:{type:"array",items:{type:"string"},description:'Component references (e.g. ["#stripe-service"])'},type:{type:"string",description:'Component type (e.g., "view", "service", "model", "tool"). Open string per project vocabulary.'},parent:{type:"string",description:'Parent component (e.g., "#payment-page"). Establishes hierarchy.'}},required:["purposeFile","id","description"]},annotations:{readOnlyHint:false,destructiveHint:false}},Xd={name:"paradigm_purpose_add_aspect",description:'Add or update an aspect (~) with ENFORCED anchors. Anchors are required and must point to code locations. Strips ~ prefix automatically. This prevents the common "~aspect:name" format error. ~100 tokens.',inputSchema:{type:"object",properties:{purposeFile:{type:"string",description:"Path to .purpose file or parent directory"},id:{type:"string",description:'Aspect ID (e.g. "audit-required" or "~audit-required")'},description:{type:"string",description:"What this aspect enforces"},anchors:{type:"array",items:{type:"string"},description:'REQUIRED. Code anchor locations (e.g. ["src/middleware/audit.ts:15-35"])'},tags:{type:"array",items:{type:"string"},description:'Classification tags (e.g. ["compliance", "security"])'},appliesTo:{type:"array",items:{type:"string"},description:'Glob patterns for symbols this applies to (e.g. ["#*Service"])'},enforcement:{type:"string",description:'How this aspect is enforced (e.g. "middleware", "decorator")'}},required:["purposeFile","id","description","anchors"]},annotations:{readOnlyHint:false,destructiveHint:false}},Zd={name:"paradigm_purpose_add_signal",description:"Add a signal (!) definition. Handles YAML ! quoting automatically. Strips ! prefix from id. ~100 tokens.",inputSchema:{type:"object",properties:{purposeFile:{type:"string",description:"Path to .purpose file or parent directory"},id:{type:"string",description:'Signal ID (e.g. "payment-completed" or "!payment-completed")'},description:{type:"string",description:"What this signal represents"},category:{type:"string",description:'Signal category (e.g. "business", "system", "security")'},severity:{type:"string",enum:["info","warn","error"],description:"Severity level"},emitters:{type:"array",items:{type:"string"},description:'Components that emit this signal (e.g. ["#payment-service"])'},related:{type:"array",items:{type:"string"},description:"Related signals or symbols"},data:{type:"object",description:"Schema/shape of data emitted with this signal"}},required:["purposeFile","id","description"]},annotations:{readOnlyHint:false,destructiveHint:false}},ep={name:"paradigm_purpose_add_flow",description:"Add a flow ($) definition. Strips $ prefix from id. ~100 tokens.",inputSchema:{type:"object",properties:{purposeFile:{type:"string",description:"Path to .purpose file or parent directory"},id:{type:"string",description:'Flow ID (e.g. "checkout-flow" or "$checkout-flow")'},description:{type:"string",description:"What this flow does"},gates:{type:"array",items:{type:"string"},description:"Gate references in this flow"},signals:{type:"array",items:{type:"string"},description:"Signals emitted during this flow"},components:{type:"array",items:{type:"string"},description:"Components involved in this flow"},steps:{type:"array",items:{type:"object",properties:{component:{type:"string"},action:{type:"string"},description:{type:"string"}},required:["component","action"]},description:"Ordered steps in the flow"}},required:["purposeFile","id","description"]},annotations:{readOnlyHint:false,destructiveHint:false}},tp={name:"paradigm_purpose_add_gate",description:"Add a gate (^) to a .purpose file's gates section. This is for purpose-level gates, NOT portal.yaml. Strips ^ prefix. ~100 tokens.",inputSchema:{type:"object",properties:{purposeFile:{type:"string",description:"Path to .purpose file or parent directory"},id:{type:"string",description:'Gate ID (e.g. "authenticated" or "^authenticated")'},description:{type:"string",description:"What this gate checks"},requires:{type:"array",items:{type:"string"},description:"Requirements for this gate"},keys:{type:"array",items:{type:"string"},description:"Key expressions for gate evaluation"},signals:{type:"array",items:{type:"string"},description:"Signals emitted by this gate (e.g. on pass/fail)"}},required:["purposeFile","id","description"]},annotations:{readOnlyHint:false,destructiveHint:false}},np={name:"paradigm_purpose_add_state",description:"Add a state definition to a .purpose file. ~100 tokens.",inputSchema:{type:"object",properties:{purposeFile:{type:"string",description:"Path to .purpose file or parent directory"},id:{type:"string",description:'State ID (e.g. "user-store")'},description:{type:"string",description:"What this state represents"},type:{type:"string",description:'Type of state (e.g. "object", "array", "string")'},default:{description:"Default value for the state"},properties:{type:"object",description:"State properties as {name: {type, description}}"}},required:["purposeFile","id","description"]},annotations:{readOnlyHint:false,destructiveHint:false}},sp={name:"paradigm_purpose_link",description:"Add references to an existing component without rewriting all fields. Merges into existing arrays (no clobber). Example: add ~rate-limited to #payment-service's aspects. ~100 tokens.",inputSchema:{type:"object",properties:{purposeFile:{type:"string",description:"Path to .purpose file or parent directory"},componentId:{type:"string",description:"Component or feature ID to add references to"},section:{type:"string",enum:["components","features"],description:"Which section the component is in (default: auto-detect)"},signals:{type:"array",items:{type:"string"},description:"Signal references to add"},aspects:{type:"array",items:{type:"string"},description:"Aspect references to add"},gates:{type:"array",items:{type:"string"},description:"Gate references to add"},flows:{type:"array",items:{type:"string"},description:"Flow references to add"},components:{type:"array",items:{type:"string"},description:"Component references to add"}},required:["purposeFile","componentId"]},annotations:{readOnlyHint:false,destructiveHint:false}},ip={name:"paradigm_purpose_remove",description:"Remove any element by section + id from a .purpose file. ~100 tokens.",inputSchema:{type:"object",properties:{purposeFile:{type:"string",description:"Path to .purpose file or parent directory"},section:{type:"string",enum:["components","features","gates","signals","aspects","flows","states"],description:"Which section to remove from"},id:{type:"string",description:"ID of the element to remove"}},required:["purposeFile","section","id"]},annotations:{readOnlyHint:false,destructiveHint:true}},rp={name:"paradigm_purpose_rename",description:"Rename a symbol across ALL .purpose files in the project. Updates both definitions and references. ~200 tokens.",inputSchema:{type:"object",properties:{oldId:{type:"string",description:'Current symbol ID (e.g. "payment-service")'},newId:{type:"string",description:'New symbol ID (e.g. "billing-service")'},symbolType:{type:"string",enum:["#","^","!","$","~"],description:"Symbol type prefix"}},required:["oldId","newId","symbolType"]},annotations:{readOnlyHint:false,destructiveHint:false}},op={name:"paradigm_portal_add_gate",description:"Add or update a gate (^) in portal.yaml. Creates portal.yaml if it doesn't exist. Strips ^ prefix. ~100 tokens.",inputSchema:{type:"object",properties:{id:{type:"string",description:'Gate ID (e.g. "authenticated" or "^authenticated")'},description:{type:"string",description:"What this gate checks"},type:{type:"string",description:'Gate type (e.g. "auth", "role", "ownership")'},location:{type:"string",description:'Where the gate is enforced (e.g. "middleware", "route-handler")'},requires:{type:"array",items:{type:"string"},description:"Prerequisite gates"},check:{type:"string",description:'Expression to evaluate (e.g. "req.user != null")'},grants:{type:"array",items:{type:"string"},description:"What passing this gate grants access to"},emits:{type:"array",items:{type:"string"},description:"Signals emitted when gate is checked"},prizes:{type:"array",items:{type:"object",properties:{id:{type:"string"},oneTime:{type:"boolean"}},required:["id"]},description:"Side effects triggered on pass"}},required:["id","description"]},annotations:{readOnlyHint:false,destructiveHint:false}},ap={name:"paradigm_portal_add_route",description:"Add a route with gates to portal.yaml. Creates routes section if needed. ~100 tokens.",inputSchema:{type:"object",properties:{route:{type:"string",description:'Route path (e.g. "/api/users/:id")'},method:{type:"string",enum:["GET","POST","PUT","PATCH","DELETE"],description:"HTTP method"},gates:{type:"array",items:{type:"string"},description:'Gate IDs to apply (e.g. ["^authenticated", "^user-owner"])'}},required:["route","method","gates"]},annotations:{readOnlyHint:false,destructiveHint:false}},cp={name:"paradigm_purpose_validate",description:"Validate .purpose files and portal.yaml. Returns issues found. If no purposeFile specified, validates all files. ~200 tokens.",inputSchema:{type:"object",properties:{purposeFile:{type:"string",description:"Specific .purpose file to validate (validates all if omitted)"},includePortal:{type:"boolean",description:"Also validate portal.yaml (default: true)"}}},annotations:{readOnlyHint:true,destructiveHint:false}};function Sa(){return [Kd,Qd,Xd,Zd,ep,tp,np,sp,ip,rp,op,ap,cp]}async function xa(n,e,s,t){switch(n){case "paradigm_purpose_init":return lp(e,s,t);case "paradigm_purpose_add_component":return dp(e,s,t);case "paradigm_purpose_add_aspect":return pp(e,s,t);case "paradigm_purpose_add_signal":return up(e,s,t);case "paradigm_purpose_add_flow":return gp(e,s,t);case "paradigm_purpose_add_gate":return mp(e,s,t);case "paradigm_purpose_add_state":return fp(e,s,t);case "paradigm_purpose_link":return yp(e,s,t);case "paradigm_purpose_remove":return hp(e,s,t);case "paradigm_purpose_rename":return bp(e,s,t);case "paradigm_portal_add_gate":return wp(e,s,t);case "paradigm_portal_add_route":return vp(e,s,t);case "paradigm_purpose_validate":return Sp(e,s);default:return {handled:false,text:""}}}function X(n){return {handled:true,text:JSON.stringify(n,null,2)}}function Me(n){return {handled:true,text:JSON.stringify({error:n},null,2)}}async function lp(n,e,s){let{purposeFile:t,name:i,description:r,context:o,version:a}=n,c=ce(t,e.rootDir),l=le(c);return a!==void 0?l.version=a:l.version||(l.version="1.0.0"),r!==void 0?l.description=r:l.description||(l.description=i),o!==void 0&&(l.context=o),de(c,l),await s(),X({action:"purpose_init",file:c,metadata:{name:i,description:l.description,version:l.version}})}async function dp(n,e,s){let{purposeFile:t,id:i,description:r,section:o="components",file:a,status:c,endpoints:l,tests:d,flows:p,gates:u,signals:g,aspects:m,components:y,type:f,parent:b}=n,h=ce(t,e.rootDir),w=le(h),_=W(i),S=o,v=Ye(w[S]),x=v[_]||{description:""};return x.description=r,a!==void 0&&(x.file=a),c!==void 0&&(x.status=c),l!==void 0&&(x.endpoints=l),d!==void 0&&(x.tests=d),p!==void 0&&(x.flows=p.map(k=>q(k,"$"))),u!==void 0&&(x.gates=u.map(k=>q(k,"^"))),g!==void 0&&(x.signals=g.map(k=>q(k,"!"))),m!==void 0&&(x.aspects=m.map(k=>q(k,"~"))),y!==void 0&&(x.components=y.map(k=>q(k,"#"))),f!==void 0&&(x.type=f),b!==void 0&&(x.parent=q(b,"#")),v[_]=x,w[S]=v,de(h,w),await s(),X({action:"add_component",file:h,section:S,id:_,symbol:`#${_}`})}async function pp(n,e,s){let{purposeFile:t,id:i,description:r,anchors:o,tags:a,appliesTo:c,enforcement:l}=n;if(!o||o.length===0)return Me('Aspects (~) REQUIRE at least one code anchor. Provide anchors like ["src/middleware/audit.ts:15-35"].');let d=/^[^\s:]+:\d+(-\d+)?(,\d+)*$/;for(let y of o)if(!d.test(y))return Me(`Invalid anchor format: "${y}". Expected format: "file.ts:15", "file.ts:15-20", or "file.ts:15,25,30".`);let p=ce(t,e.rootDir),u=F.dirname(p);for(let y of o){let f=y.replace(/:.*$/,""),b=F.resolve(u,f);if(!O.existsSync(b)){let h=F.resolve(e.rootDir,f);if(O.existsSync(h)){let w=F.relative(u,h),_=o.indexOf(y);o[_]=y.replace(f,w);}else return Me(`Anchor file not found: "${f}". Anchors must be relative to the .purpose file directory (${u}).`)}}let g=le(p);g.aspects||(g.aspects={});let m=W(i);return g.aspects[m]={description:r,anchors:o,...a&&{tags:a},...c&&{"applies-to":c},...l&&{enforcement:l}},de(p,g),await s(),X({action:"add_aspect",file:p,id:m,symbol:`~${m}`,anchors:o})}async function up(n,e,s){let{purposeFile:t,id:i,description:r,category:o,severity:a,emitters:c,related:l,data:d}=n,p=ce(t,e.rootDir),u=le(p);u.signals||(u.signals={});let g=W(i);return u.signals[g]={description:r,...o&&{category:o},...a&&{severity:a},...c&&{emitters:c.map(m=>q(m,"#"))},...l&&{related:l},...d&&{data:d}},de(p,u),await s(),X({action:"add_signal",file:p,id:g,symbol:`!${g}`})}async function gp(n,e,s){let{purposeFile:t,id:i,description:r,gates:o,signals:a,components:c,steps:l}=n,d=ce(t,e.rootDir),p=le(d),u=Tn(p.flows),g=W(i),m={description:r,...o&&{gates:o.map(y=>q(y,"^"))},...a&&{signals:a.map(y=>q(y,"!"))},...c&&{components:c.map(y=>q(y,"#"))},...l&&{steps:l}};return u[g]=m,p.flows=u,de(d,p),await s(),X({action:"add_flow",file:d,id:g,symbol:`$${g}`})}async function mp(n,e,s){let{purposeFile:t,id:i,description:r,requires:o,keys:a,signals:c}=n,l=ce(t,e.rootDir),d=le(l);d.gates||(d.gates={});let p=W(i);return d.gates[p]={description:r,...o&&{requires:o},...a&&{keys:a},...c&&{signals:c.map(u=>q(u,"!"))}},de(l,d),await s(),X({action:"add_gate",file:l,id:p,symbol:`^${p}`})}async function fp(n,e,s){let{purposeFile:t,id:i,description:r,type:o,default:a,properties:c}=n,l=ce(t,e.rootDir),d=le(l);d.states||(d.states={});let p=W(i),u={description:r};return o!==void 0&&(u.type=o),a!==void 0&&(u.default=a),c!==void 0&&(u.properties=c),d.states[p]=u,de(l,d),await s(),X({action:"add_state",file:l,id:p})}async function yp(n,e,s){let{purposeFile:t,componentId:i,section:r,signals:o,aspects:a,gates:c,flows:l,components:d}=n,p=ce(t,e.rootDir),u=le(p),g=W(i),m=r;if(!m){let h=Ye(u.components),w=Ye(u.features);if(g in h)m="components";else if(g in w)m="features";else return Me(`Component "${g}" not found in components or features. Specify section explicitly.`)}let y=Ye(u[m]);if(!(g in y))return Me(`Component "${g}" not found in ${m} section.`);let f=y[g];o&&(f.signals=at(f.signals,o.map(h=>q(h,"!")))),c&&(f.gates=at(f.gates,c.map(h=>q(h,"^")))),l&&(f.flows=at(f.flows,l.map(h=>q(h,"$")))),d&&(f.components=at(f.components,d.map(h=>q(h,"#")))),a&&(f.aspects=at(f.aspects,a.map(h=>q(h,"~")))),y[g]=f,u[m]=y,de(p,u),await s();let b=[];return o&&b.push(`signals: ${o.join(", ")}`),a&&b.push(`aspects: ${a.join(", ")}`),c&&b.push(`gates: ${c.join(", ")}`),l&&b.push(`flows: ${l.join(", ")}`),d&&b.push(`components: ${d.join(", ")}`),X({action:"link",file:p,componentId:g,section:m,added:b})}async function hp(n,e,s){let{purposeFile:t,section:i,id:r}=n,o=ce(t,e.rootDir),a=le(o),c=W(r);if(i==="flows"){let l=Tn(a.flows);if(!(c in l))return Me(`Flow "${c}" not found in flows section.`);delete l[c],a.flows=l;}else if(i==="components"||i==="features"){let l=Ye(a[i]);if(!(c in l))return Me(`"${c}" not found in ${i} section.`);delete l[c],a[i]=l;}else {let l=a[i];if(!l||!(c in l))return Me(`"${c}" not found in ${i} section.`);delete l[c];}return de(o,a),await s(),X({action:"remove",file:o,section:i,id:c})}async function bp(n,e,s){let{oldId:t,newId:i,symbolType:r}=n,o=await ya(e.rootDir,t,i,r);return await s(),X({action:"rename",oldSymbol:`${r}${W(t)}`,newSymbol:`${r}${W(i)}`,filesModified:o.length,files:o})}async function wp(n,e,s){let{id:t,description:i,type:r,location:o,requires:a,check:c,grants:l,emits:d,prizes:p}=n,u=wa(e.rootDir,{id:t,description:i,type:r,location:o,requires:a,check:c,grants:l,emits:d,prizes:p});await s();let g=W(t);return X({action:"portal_add_gate",file:u,id:g,symbol:`^${g}`})}async function vp(n,e,s){let{route:t,method:i,gates:r}=n,o=va(e.rootDir,{route:t,method:i,gates:r});return await s(),X({action:"portal_add_route",file:o,route:`${i} ${t}`,gates:r})}var _p=/\[NEEDS CLARIFICATION:\s*[^\]]+\]/gi;function _a(n,e){let s=[];function t(r,o){if(typeof r=="string"){let a=r.match(_p);if(a)for(let c of a)s.push({type:"warning",message:`Clarification needed: ${c}`,path:o});}}t(n.description,"description");let i=[{key:"components",items:n.components},{key:"features",items:n.features},{key:"gates",items:n.gates},{key:"signals",items:n.signals},{key:"aspects",items:n.aspects}];for(let r of i)if(r.items&&typeof r.items=="object")for(let[o,a]of Object.entries(r.items))a&&typeof a.description=="string"&&t(a.description,`${r.key}.${o}.description`);if(n.flows&&typeof n.flows=="object"){let r=Array.isArray(n.flows)?[]:Object.entries(n.flows);for(let[o,a]of r)a&&typeof a.description=="string"&&t(a.description,`flows.${o}.description`);}return s}async function Sp(n,e){let{purposeFile:s,includePortal:t=true}=n,i=[];if(s){let a=ce(s,e.rootDir),c=a$8(a);if(!c.data)i.push({file:a,valid:false,issues:c.errors.map(l=>({type:"error",message:l}))});else {let l=d$9(c.data,a);if(c.data.aspects)for(let[p,u]of Object.entries(c.data.aspects))(!u.anchors||u.anchors.length===0)&&(l.issues.push({type:"error",message:`Aspect "${p}" is missing required anchors`,path:`aspects.${p}`}),l.valid=false);let d=_a(c.data);l.issues.push(...d),i.push({file:a,valid:l.valid,issues:l.issues});}}else {let a=await c$5(e.rootDir);for(let c of a){let l=a$8(c);if(!l.data){i.push({file:c,valid:false,issues:l.errors.map(u=>({type:"error",message:u}))});continue}let d=d$9(l.data,c);if(l.data.aspects)for(let[u,g]of Object.entries(l.data.aspects))(!g.anchors||g.anchors.length===0)&&(d.issues.push({type:"error",message:`Aspect "${u}" is missing required anchors`,path:`aspects.${u}`}),d.valid=false);let p=_a(l.data);d.issues.push(...p),i.push({file:c,valid:d.valid,issues:d.issues});}}if(t){let{data:a,filePath:c}=Dn(e.rootDir),l=[];if(a.gates)for(let[d,p]of Object.entries(a.gates))p.description||l.push({type:"warning",message:`Gate "${d}" has no description`,path:`gates.${d}`}),p.prizes||l.push({type:"warning",message:`Gate "${d}" is missing prizes array (v2 requirement)`,path:`gates.${d}`});l.length>0&&i.push({file:c,valid:l.every(d=>d.type!=="error"),issues:l});}let r=i.reduce((a,c)=>a+c.issues.length,0),o=i.every(a=>a.valid);return X({action:"validate",valid:o,totalFiles:i.length,totalIssues:r,results:i})}var Fa=[{id:"explore-before-implement",name:"Explore Before Implementing",description:"Call ripple/navigate/search before modifying existing symbols to understand impact",category:"discovery",trigger:"preflight",severity:"advisory",check:{type:"tool-called",params:{tools:["paradigm_ripple","paradigm_navigate","paradigm_search","paradigm_related"]}},enabled:true},{id:"ripple-before-modify",name:"Ripple Before Modifying",description:"Run ripple analysis before modifying symbols with dependents",category:"discovery",trigger:"preflight",severity:"advisory",check:{type:"tool-called",params:{tools:["paradigm_ripple"]}},enabled:true},{id:"check-fragility",name:"Check Fragility",description:"Check history fragility for symbols before modifying frequently-broken code",category:"discovery",trigger:"preflight",severity:"advisory",check:{type:"tool-called",params:{tools:["paradigm_history_fragility"]}},enabled:true},{id:"wisdom-before-implement",name:"Check Team Wisdom",description:"Check team wisdom (preferences, antipatterns, decisions) before implementing",category:"collaboration",trigger:"preflight",severity:"advisory",check:{type:"tool-called",params:{tools:["paradigm_wisdom_context","paradigm_wisdom_expert"]}},enabled:true},{id:"verify-before-done",name:"Verify Before Done",description:"Run postflight compliance checks before finishing a session",category:"verification",trigger:"on-stop",severity:"warn",check:{type:"tool-called",params:{tools:["paradigm_pm_postflight"]}},enabled:true},{id:"postflight-compliance",name:"Postflight Compliance",description:"Ensure postflight checks pass without errors before finishing",category:"verification",trigger:"on-stop",severity:"advisory",check:{type:"tool-called",params:{tools:["paradigm_pm_postflight","paradigm_reindex"]}},enabled:true},{id:"test-new-components",name:"Test New Components",description:"New components should have associated tests or test plan documented",category:"testing",trigger:"postflight",severity:"advisory",check:{type:"tests-exist",params:{patterns:["**/*.test.*","**/*.spec.*","**/tests/**"]}},enabled:true},{id:"purpose-coverage",name:"Purpose File Coverage",description:"All modified source directories should have .purpose file coverage",category:"documentation",trigger:"postflight",severity:"warn",check:{type:"file-exists",params:{patterns:["**/.purpose"]}},enabled:true},{id:"record-lore-for-significant",name:"Record Lore for Significant Changes",description:"Sessions modifying 3+ files should record a lore entry",category:"documentation",trigger:"on-stop",severity:"warn",check:{type:"lore-recorded",params:{}},enabled:true},{id:"confidence-on-decisions",name:"Confidence on Decisions",description:"When recording lore, include a confidence score (0.0-1.0) to enable calibration tracking over time",category:"documentation",trigger:"on-stop",severity:"advisory",check:{type:"tool-called",params:{tools:["paradigm_lore_record"]}},enabled:true},{id:"gates-for-routes",name:"Gates for Routes",description:"API routes should have corresponding gate declarations in portal.yaml",category:"security",trigger:"postflight",severity:"warn",check:{type:"gates-declared",params:{requireRoutes:true}},enabled:true},{id:"university-content-valid",name:"University Content Valid",description:"Validate university content integrity when files in symbol-covered areas change",category:"quality",trigger:"on-stop",severity:"advisory",check:{type:"tool-called",params:{tools:["paradigm_university_validate"]}},enabled:true},{id:"university-onboarded",name:"University Onboarding",description:"Call paradigm_university_onboard at session start for project-specific learning content",category:"discovery",trigger:"preflight",severity:"advisory",check:{type:"tool-called",params:{tools:["paradigm_university_onboard"]}},enabled:false},{id:"orchestration-required",name:"Orchestrate Complex Tasks",description:"Tasks affecting 3+ files or touching security symbols should use paradigm_orchestrate_inline to determine which agents are needed. Ensures security review, test coverage, and documentation.",category:"collaboration",trigger:"preflight",severity:"warn",check:{type:"tool-called",params:{tools:["paradigm_orchestrate_inline"]}},enabled:true},{id:"agent-coverage-validated",name:"Validate Agent Involvement",description:"After completing work, verify that agents with relevant expertise were consulted. Check nominations that were surfaced but not acted on.",category:"collaboration",trigger:"postflight",severity:"advisory",check:{type:"tool-called",params:{tools:["paradigm_ambient_nominations","paradigm_agent_list"]}},enabled:true},{id:"hot-mode-incident",name:"Incident Response Acknowledgment",description:"During incident response, orchestration enforcement is waived. But a post-incident lore entry is required and a postflight review should be scheduled.",category:"collaboration",trigger:"on-stop",severity:"advisory",check:{type:"lore-recorded"},enabled:true}],Rp=30*1e3,$s=new Map;function ie(n){let e=F.resolve(n),s=$s.get(e);if(s&&Date.now()-s.loadedAt<Rp)return s.habits;let t=jp(e);return $s.set(e,{habits:t,loadedAt:Date.now()}),t}function jp(n){let e=new Map;for(let a of Fa)e.set(a.id,{...a});let s=process.env.HOME||process.env.USERPROFILE||"~",t=ja(F.join(s,".paradigm","habits.yaml"));t&&Ta(e,t);let i=Aa(F.join(s,".paradigm","habits"));for(let a of i)e.set(a.id,a);let r=ja(F.join(n,".paradigm","habits.yaml"));r&&Ta(e,r);let o=Aa(F.join(n,".paradigm","habits"));for(let a of o)e.set(a.id,a);return Array.from(e.values())}function ja(n){if(!O.existsSync(n))return null;try{let e=O.readFileSync(n,"utf8");return Z.load(e)}catch{return null}}function Ta(n,e){if(e.habits)for(let s of e.habits)n.set(s.id,{...s});if(e.overrides)for(let[s,t]of Object.entries(e.overrides)){let i=n.get(s);i&&(t.severity!==void 0&&(i.severity=t.severity),t.enabled!==void 0&&(i.enabled=t.enabled));}}function Tp(n,e){return n.filter(s=>s.enabled&&s.trigger===e)}function Fs(n){$s.delete(F.resolve(n));}function Aa(n){if(!O.existsSync(n))return [];try{let e=O.readdirSync(n).filter(t=>t.endsWith(".habit")).sort(),s=[];for(let t of e)try{let i=O.readFileSync(F.join(n,t),"utf8"),r=Z.load(i);r?.id&&r?.name&&s.push(r);}catch{}return s}catch{return []}}var Da=["discovery","verification","testing","documentation","collaboration","security"],Oa=["preflight","postflight","on-commit","on-stop"],Ia=["advisory","warn","block"],$a=["tool-called","file-exists","file-modified","lore-recorded","symbols-registered","gates-declared","tests-exist","git-clean","commit-message-format","flow-coverage","context-checked","aspect-anchored"],Ap=/^[a-z0-9]+(-[a-z0-9]+)*$/;function Ns(n){let e=[];if(n.id||e.push("Missing required field: id"),n.name||e.push("Missing required field: name"),n.description||e.push("Missing required field: description"),n.category||e.push("Missing required field: category"),n.trigger||e.push("Missing required field: trigger"),n.severity||e.push("Missing required field: severity"),n.check||e.push("Missing required field: check"),(n.enabled===void 0||n.enabled===null)&&e.push("Missing required field: enabled"),n.id&&!Ap.test(n.id)&&e.push(`Invalid id format: "${n.id}" \u2014 must be kebab-case (lowercase, hyphens only)`),n.category&&!Da.includes(n.category)&&e.push(`Invalid category: "${n.category}" \u2014 must be one of: ${Da.join(", ")}`),n.trigger&&!Oa.includes(n.trigger)&&e.push(`Invalid trigger: "${n.trigger}" \u2014 must be one of: ${Oa.join(", ")}`),n.severity&&!Ia.includes(n.severity)&&e.push(`Invalid severity: "${n.severity}" \u2014 must be one of: ${Ia.join(", ")}`),n.check){$a.includes(n.check.type)||e.push(`Invalid check.type: "${n.check.type}" \u2014 must be one of: ${$a.join(", ")}`);let s=n.check.params||{};switch(n.check.type){case "tool-called":(!s.tools||!Array.isArray(s.tools)||s.tools.length===0)&&e.push('check.type "tool-called" requires check.params.tools[] (non-empty array)');break;case "file-exists":case "file-modified":(!s.patterns||!Array.isArray(s.patterns)||s.patterns.length===0)&&e.push(`check.type "${n.check.type}" requires check.params.patterns[] (non-empty array)`);break;case "commit-message-format":(!s.messagePatterns||!Array.isArray(s.messagePatterns)||s.messagePatterns.length===0)&&e.push('check.type "commit-message-format" requires check.params.messagePatterns[] (non-empty array)');break}}return {valid:e.length===0,errors:e}}var Dp=new Set(Fa.map(n=>n.id));function Hn(n){return Dp.has(n)}function Es(n,e,s="project"){let t=s==="global"?F.join(process.env.HOME||process.env.USERPROFILE||"~",".paradigm","habits"):F.join(n,".paradigm","habits");O.existsSync(t)||O.mkdirSync(t,{recursive:true});let i=F.join(t,`${e.id}.habit`),r=Z.dump(e,{lineWidth:120,noRefs:true});return O.writeFileSync(i,r,"utf8"),Fs(n),i}function Na(n,e){if(Hn(e))return {removed:false,reason:`"${e}" is a seed habit and cannot be removed. Use overrides in habits.yaml to disable it.`};let s=F.join(n,".paradigm","habits",`${e}.habit`);if(O.existsSync(s))return O.unlinkSync(s),Fs(n),{removed:true};let t=process.env.HOME||process.env.USERPROFILE||"~",i=F.join(t,".paradigm","habits",`${e}.habit`);return O.existsSync(i)?(O.unlinkSync(i),Fs(n),{removed:true}):{removed:false,reason:`No .habit file found for "${e}". It may be defined in habits.yaml \u2014 edit that file directly.`}}var Hs=0;function Nt(n,e,s,t,i){let r=Tp(n,e);t&&(r=r.filter(u=>!u.platforms||u.platforms.includes(t)));let o=0;if(i)try{let{isGraduated:u}=(En(),d$a(Ra)),g=r.length;r=r.filter(m=>!u(i,m.id)),o=g-r.length;}catch{}Hs=o;let a=r.map(u=>Op(u,s)),c=a.filter(u=>u.result==="followed").length,l=a.filter(u=>u.result==="skipped").length,d=a.filter(u=>u.result==="partial").length,p=a.filter(u=>u.result==="skipped"&&u.habit.severity==="block").length;return {trigger:e,evaluations:a,summary:{total:a.length,followed:c,skipped:l,partial:d,blockingViolations:p},blocksCompletion:p>0}}function Et(n){return {toolsCalled:n.toolsCalled||[],filesModified:n.filesModified||[],symbolsTouched:n.symbolsTouched||[],loreRecorded:n.loreRecorded||false,hasPortalRoutes:n.hasPortalRoutes||false,taskAddsRoutes:n.taskAddsRoutes||false,taskDescription:n.taskDescription,gitClean:n.gitClean}}function Op(n,e){switch(n.check.type){case "tool-called":return Ip(n,e);case "file-exists":return $p(n,e);case "file-modified":return Mp(n,e);case "lore-recorded":return Fp(n,e);case "symbols-registered":return Np(n,e);case "gates-declared":return Ep(n,e);case "tests-exist":return Hp(n,e);case "git-clean":return qp(n,e);default:return {habit:n,result:"partial",reason:`Unknown check: ${n.check.type}`}}}function Ip(n,e){let s=n.check.params.tools||[];if(s.length===0)return {habit:n,result:"followed",reason:"No tools required"};let t=s.filter(i=>e.toolsCalled.includes(i));return t.length>0?{habit:n,result:"followed",reason:`Called: ${t.join(", ")}`,evidence:t}:e.filesModified.length===0&&e.symbolsTouched.length===0?{habit:n,result:"followed",reason:"No modifications, habit not applicable"}:{habit:n,result:"skipped",reason:`None of [${s.join(", ")}] were called before modifying code`}}function $p(n,e){if(e.filesModified.length===0)return {habit:n,result:"followed",reason:"No files modified"};if(e.filesModified.some(i=>i.endsWith(".purpose")||i.includes(".paradigm/")))return {habit:n,result:"followed",reason:"Purpose files updated"};let t=e.filesModified.filter(i=>!i.endsWith(".md")&&!i.endsWith(".json")&&!i.endsWith(".yaml")&&!i.endsWith(".yml")&&!i.endsWith(".lock")&&!i.endsWith(".purpose")&&!i.includes(".paradigm/"));return t.length===0?{habit:n,result:"followed",reason:"Only non-source files modified"}:{habit:n,result:"skipped",reason:`${t.length} source file(s) without .purpose updates`,evidence:t.slice(0,5)}}function Fp(n,e){let s=e.filesModified.filter(t=>!t.endsWith(".md")&&!t.endsWith(".json")&&!t.endsWith(".yaml")&&!t.endsWith(".yml")&&!t.endsWith(".lock")&&!t.endsWith(".purpose")&&!t.includes(".paradigm/"));return s.length<3?{habit:n,result:"followed",reason:"Session not significant (< 3 source files)"}:e.loreRecorded||e.toolsCalled.includes("paradigm_lore_record")?{habit:n,result:"followed",reason:"Lore recorded"}:{habit:n,result:"skipped",reason:`${s.length} source files modified, no lore entry`,evidence:s.slice(0,5)}}function Np(n,e){if(e.symbolsTouched.length===0)return {habit:n,result:"followed",reason:"No symbols touched"};let t=["paradigm_purpose_add_component","paradigm_purpose_add_signal","paradigm_purpose_add_flow","paradigm_purpose_add_gate","paradigm_purpose_add_aspect","paradigm_purpose_init"].filter(i=>e.toolsCalled.includes(i));return t.length>0?{habit:n,result:"followed",reason:`Purpose tools called: ${t.join(", ")}`,evidence:t}:{habit:n,result:"partial",reason:`${e.symbolsTouched.length} symbol(s) touched, no purpose registration`}}function Ep(n,e){if(!e.taskAddsRoutes)return {habit:n,result:"followed",reason:"No routes added"};if(e.hasPortalRoutes)return {habit:n,result:"followed",reason:"Portal.yaml has routes"};let t=["paradigm_gates_for_route","paradigm_portal_add_route","paradigm_portal_add_gate"].filter(i=>e.toolsCalled.includes(i));return t.length>0?{habit:n,result:"followed",reason:`Gate tools called: ${t.join(", ")}`,evidence:t}:{habit:n,result:"skipped",reason:"Routes added without gate declarations"}}function Hp(n,e){if(e.filesModified.length===0)return {habit:n,result:"followed",reason:"No files modified"};let s=e.filesModified.filter(i=>i.includes(".test.")||i.includes(".spec.")||i.includes("/tests/")||i.includes("/test/")||i.includes("__tests__"));if(s.length>0)return {habit:n,result:"followed",reason:`Test files: ${s.length}`,evidence:s.slice(0,5)};let t=e.filesModified.filter(i=>!i.endsWith(".md")&&!i.endsWith(".json")&&!i.endsWith(".yaml")&&!i.endsWith(".lock")&&!i.endsWith(".purpose")&&!i.includes(".paradigm/")&&!i.includes("node_modules/"));return t.length===0?{habit:n,result:"followed",reason:"No source files to test"}:{habit:n,result:"partial",reason:`${t.length} source file(s), no test files updated`,evidence:t.slice(0,5)}}function Mp(n,e){if(e.filesModified.length===0)return {habit:n,result:"followed",reason:"No files modified"};let s=n.check.params.patterns||[];if(s.length===0)return {habit:n,result:"followed",reason:"No patterns specified"};let t=e.filesModified.filter(i=>s.some(r=>i.includes(r)||F.basename(i)===r));return t.length>0?{habit:n,result:"followed",reason:`Matching files: ${t.join(", ")}`,evidence:t}:{habit:n,result:"skipped",reason:`None of [${s.join(", ")}] found in modified files`}}function qp(n,e){return e.filesModified.length===0?{habit:n,result:"followed",reason:"No files modified"}:e.gitClean===void 0?{habit:n,result:"partial",reason:"Git status not available"}:e.gitClean?{habit:n,result:"followed",reason:"Working tree is clean \u2014 changes committed"}:{habit:n,result:"skipped",reason:"Uncommitted changes in working tree"}}var Ht=null,Ms=false;async function qs(n){if(Ht)Ms||(await Ht.ensureReady(),Ms=true);else {let e=F.join(n,".paradigm","sentinel","sentinel.db");Ht=new f$4(e),await Ht.ensureReady(),Ms=true;}return Ht}async function Lp(n,e){return (await qs(n)).recordPracticeEvent(e)}async function Ha(n,e){return (await qs(n)).getPracticeEvents(e)}async function pe(n,e){return (await qs(n)).getComplianceRate(e)}async function Mt(n,e){let s=["discovery","verification","testing","documentation","collaboration","security"],t=[];for(let i of s){let r=await pe(n,{...e,habitCategory:i});r.total>0&&t.push({category:i,...r});}return t}async function Ma(n,e,s){let t=[];for(let i of e){let r=await Lp(n,{habitId:i.habitId,habitCategory:i.habitCategory,result:i.result,engineer:s.engineer,sessionId:s.sessionId,loreEntryId:s.loreEntryId,taskDescription:s.taskDescription,symbolsTouched:s.symbolsTouched,filesModified:s.filesModified,notes:i.notes});t.push(r);}return t}var Jp=/[@#$%^!?&~][a-zA-Z][a-zA-Z0-9_-]*/g,Gp=["endpoint","route","api","handler","get","post","put","patch","delete","rest","crud","controller"],Up=[/\.(get|post|put|patch|delete)\s*\(\s*['"`]([^'"`]+)['"`]/gi,/export\s+(async\s+)?function\s+(GET|POST|PUT|PATCH|DELETE)/gi];function qa(){return [{name:"paradigm_pm_preflight",description:`REQUIRED before implementing features. Call with mode="plan" to get the right agents and cost estimate. Skipping this for complex tasks leads to missed security reviews and wasted tokens.
742
+ `);typeof m.lines=="number"?b=1:Array.isArray(m.lines)&&m.lines.length===2?b=m.lines[1]-m.lines[0]+1:Array.isArray(m.lines)&&(b=m.lines.length);}catch{}a.push({path:m.path,lines:m.raw.split(":")[1]||"full file",exists:f,lineCount:b});}let c=o.length>0&&a.every(m=>m.exists),l=r.appliesTo||[],d=n(s.index),p=[],u=[];for(let m of d)for(let y of l)if(new RegExp("^"+y.replace(/\*/g,".*").replace(/\?/g,".")+"$").test(m.symbol)){p.push(m.symbol),(m.data?.aspects?.includes?.(i)||m.data?.aspects?.includes?.(t))&&u.push(m.symbol);break}let g=p.filter(m=>!u.includes(m));return {handled:true,text:JSON.stringify({aspect:i,valid:c,description:r.description,enforcement:r.enforcement,anchors:a,coverage:{appliesTo:l,matchingSymbols:p.length,symbolsWithAspect:u.length,missing:g.slice(0,10),missingCount:g.length},warnings:[...o.length===0?["CRITICAL: Aspect has no anchors - aspects MUST have code anchors"]:[],...a.filter(m=>!m.exists).map(m=>`Anchor file not found: ${m.path}`),...g.length>0?[`${g.length} symbols match applies-to but don't have this aspect`]:[]],recommendation:c?g.length>0?"Aspect is valid but has coverage gaps - consider applying to matching symbols":"Aspect is valid and fully applied":"INVALID: Add code anchors to this aspect"},null,2)}}default:return {handled:false,text:""}}}var Bd=["#","$","^","!","~"];function W(n){return n.length>1&&Bd.includes(n[0])?n.slice(1):n}function q(n,e){let s=W(n);return `${e}${s}`}function ce(n,e){let s=F.isAbsolute(n)?n:F.resolve(e,n);return s.endsWith(".purpose")?s:F.join(s,".purpose")}function le(n){if(!O.existsSync(n))return {};let e=a$8(n);if(!e.data)throw new Error(`Failed to parse ${n}: ${e.errors.join(", ")}`);return e.data}function de(n,e){let s=F.dirname(n);O.existsSync(s)||O.mkdirSync(s,{recursive:true});let t=b$a(e);O.writeFileSync(n,t,"utf8");}function Ye(n){if(!n)return {};if(!Array.isArray(n))return n;let e={};for(let s of n){let{id:t,...i}=s;e[t]=i;}return e}function Tn(n){if(!n)return {};if(!Array.isArray(n))return n;let e={};for(let s of n)e[s.name]={description:s.description,steps:s.steps};return e}function at(n,e){if(!e||e.length===0)return n;if(!n||n.length===0)return e;let s=new Set(n);for(let t of e)s.add(t);return Array.from(s)}var Vd={"#":"#","^":"^","!":"!",$:"$","~":"~"};async function ya(n,e,s,t){let i=Vd[t];if(!i)throw new Error(`Invalid symbol type: ${t}. Expected one of: # ^ ! $ ~`);let r=W(e),o=W(s),a=q(r,i),c=q(o,i),l=await c$5(n),d=[];for(let p of l){let u=le(p),g=false,y={"#":"components","^":"gates","!":"signals",$:"flows","~":"aspects"}[i];if(y&&y!=="flows"){let f=u[y];f&&!Array.isArray(f)&&r in f&&(f[o]=f[r],delete f[r],g=true);}if(i==="#")for(let f of ["features","components"]){let b=u[f];b&&!Array.isArray(b)&&r in b&&(b[o]=b[r],delete b[r],g=true);}i==="$"&&u.flows&&!Array.isArray(u.flows)&&r in u.flows&&(u.flows[o]=u.flows[r],delete u.flows[r],g=true);for(let f of ["features","components"]){let b=Ye(u[f]);for(let[h,w]of Object.entries(b))g=Yd(w,a,c)||g;g&&Object.keys(b).length>0&&(u[f]=b);}if(u.flows){let f=Tn(u.flows);for(let[b,h]of Object.entries(f)){if(h.gates){let w=h.gates.indexOf(a);w!==-1&&(h.gates[w]=c,g=true);}if(h.signals){let w=h.signals.indexOf(a);w!==-1&&(h.signals[w]=c,g=true);}if(h.components){let w=h.components.indexOf(a);w!==-1&&(h.components[w]=c,g=true);}if(h.steps)for(let w of h.steps)typeof w=="object"&&"component"in w&&(w.component===a||w.component===r)&&(w.component=i==="#"?o:c,g=true);}g&&(u.flows=f);}if(u.gates){for(let[f,b]of Object.entries(u.gates))if(b.signals){let h=b.signals.indexOf(a);h!==-1&&(b.signals[h]=c,g=true);}}if(u.aspects){for(let[f,b]of Object.entries(u.aspects))if(b["applies-to"]){let h=b["applies-to"].indexOf(a);h!==-1&&(b["applies-to"][h]=c,g=true);}}g&&(de(p,u),d.push(p));}return d}function Yd(n,e,s){let t=false,i=["signals","gates","flows","components","states"];for(let r of i){let o=n[r];if(o){let a=o.indexOf(e);a!==-1&&(o[a]=s,t=true);}}if(n.aspects&&Array.isArray(n.aspects)){let r=n.aspects.indexOf(e);r!==-1&&(n.aspects[r]=s,t=true);}return t}function Dn(n){let e=F.join(n,"portal.yaml");if(!O.existsSync(e))return {data:{version:"1.0.0",gates:{}},filePath:e};let s=O.readFileSync(e,"utf8");return {data:Z.load(s)||{version:"1.0.0",gates:{}},filePath:e}}function ba(n,e){let s=Z.dump(e,{indent:2,lineWidth:-1,noRefs:true,sortKeys:false});O.writeFileSync(n,s,"utf8");}function wa(n,e){let{data:s,filePath:t}=Dn(n);s.gates||(s.gates={});let i=W(e.id),r=s.gates[i]||{};return r.description=e.description,e.type!==void 0&&(r.type=e.type),e.location!==void 0&&(r.location=e.location),e.requires!==void 0&&(r.requires=e.requires),e.check!==void 0&&(r.check=e.check),e.grants!==void 0&&(r.grants=e.grants),e.emits!==void 0&&(r.emits=e.emits),e.prizes!==void 0&&(r.prizes=e.prizes),r.prizes||(r.prizes=[]),s.gates[i]=r,ba(t,s),t}function va(n,e){let{data:s,filePath:t}=Dn(n);s.routes||(s.routes={});let i=`${e.method} ${e.route}`,r=e.gates.map(o=>`^${W(o)}`);return s.routes[i]=r,ba(t,s),t}var Kd={name:"paradigm_purpose_init",description:"Create or update file-level metadata on a .purpose file. Does NOT overwrite existing components/signals/etc \u2014 only touches top-level metadata (name, description, context, version). ~100 tokens.",inputSchema:{type:"object",properties:{purposeFile:{type:"string",description:"Path to .purpose file or parent directory (relative to project root)"},name:{type:"string",description:"Name/title for this purpose file"},description:{type:"string",description:"Description of what this directory/module does"},context:{type:"array",items:{type:"string"},description:"Context notes for AI agents"},version:{type:"string",description:'Version string (default: "1.0.0")'}},required:["purposeFile","name"]},annotations:{readOnlyHint:false,destructiveHint:false}},Qd={name:"paradigm_purpose_add_component",description:"Add or update a component (#) or feature in a .purpose file. Strips # prefix from id automatically. ~100 tokens.",inputSchema:{type:"object",properties:{purposeFile:{type:"string",description:"Path to .purpose file or parent directory"},id:{type:"string",description:'Component ID (e.g. "payment-service" or "#payment-service")'},description:{type:"string",description:"What this component does"},section:{type:"string",enum:["components","features"],description:'Which section to add to (default: "components")'},file:{type:"string",description:"Source file path for this component"},status:{type:"string",description:'Component status (e.g. "active", "deprecated")'},endpoints:{type:"array",items:{type:"string"},description:'API endpoints (e.g. ["POST /api/payments"])'},tests:{type:"array",items:{type:"string"},description:"Test file paths"},flows:{type:"array",items:{type:"string"},description:'Flow references (e.g. ["$checkout-flow"])'},gates:{type:"array",items:{type:"string"},description:'Gate references (e.g. ["^authenticated"])'},signals:{type:"array",items:{type:"string"},description:'Signal references (e.g. ["!payment-completed"])'},aspects:{type:"array",items:{type:"string"},description:'Aspect references (e.g. ["~audit-required"])'},components:{type:"array",items:{type:"string"},description:'Component references (e.g. ["#stripe-service"])'},type:{type:"string",description:'Component type (e.g., "view", "service", "model", "tool"). Open string per project vocabulary.'},parent:{type:"string",description:'Parent component (e.g., "#payment-page"). Establishes hierarchy.'}},required:["purposeFile","id","description"]},annotations:{readOnlyHint:false,destructiveHint:false}},Xd={name:"paradigm_purpose_add_aspect",description:'Add or update an aspect (~) with ENFORCED anchors. Anchors are required and must point to code locations. Strips ~ prefix automatically. This prevents the common "~aspect:name" format error. ~100 tokens.',inputSchema:{type:"object",properties:{purposeFile:{type:"string",description:"Path to .purpose file or parent directory"},id:{type:"string",description:'Aspect ID (e.g. "audit-required" or "~audit-required")'},description:{type:"string",description:"What this aspect enforces"},anchors:{type:"array",items:{type:"string"},description:'REQUIRED. Code anchor locations (e.g. ["src/middleware/audit.ts:15-35"])'},tags:{type:"array",items:{type:"string"},description:'Classification tags (e.g. ["compliance", "security"])'},appliesTo:{type:"array",items:{type:"string"},description:'Glob patterns for symbols this applies to (e.g. ["#*Service"])'},enforcement:{type:"string",description:'How this aspect is enforced (e.g. "middleware", "decorator")'}},required:["purposeFile","id","description","anchors"]},annotations:{readOnlyHint:false,destructiveHint:false}},Zd={name:"paradigm_purpose_add_signal",description:"Add a signal (!) definition. Handles YAML ! quoting automatically. Strips ! prefix from id. ~100 tokens.",inputSchema:{type:"object",properties:{purposeFile:{type:"string",description:"Path to .purpose file or parent directory"},id:{type:"string",description:'Signal ID (e.g. "payment-completed" or "!payment-completed")'},description:{type:"string",description:"What this signal represents"},category:{type:"string",description:'Signal category (e.g. "business", "system", "security")'},severity:{type:"string",enum:["info","warn","error"],description:"Severity level"},emitters:{type:"array",items:{type:"string"},description:'Components that emit this signal (e.g. ["#payment-service"])'},related:{type:"array",items:{type:"string"},description:"Related signals or symbols"},data:{type:"object",description:"Schema/shape of data emitted with this signal"}},required:["purposeFile","id","description"]},annotations:{readOnlyHint:false,destructiveHint:false}},ep={name:"paradigm_purpose_add_flow",description:"Add a flow ($) definition. Strips $ prefix from id. ~100 tokens.",inputSchema:{type:"object",properties:{purposeFile:{type:"string",description:"Path to .purpose file or parent directory"},id:{type:"string",description:'Flow ID (e.g. "checkout-flow" or "$checkout-flow")'},description:{type:"string",description:"What this flow does"},gates:{type:"array",items:{type:"string"},description:"Gate references in this flow"},signals:{type:"array",items:{type:"string"},description:"Signals emitted during this flow"},components:{type:"array",items:{type:"string"},description:"Components involved in this flow"},steps:{type:"array",items:{type:"object",properties:{component:{type:"string"},action:{type:"string"},description:{type:"string"}},required:["component","action"]},description:"Ordered steps in the flow"}},required:["purposeFile","id","description"]},annotations:{readOnlyHint:false,destructiveHint:false}},tp={name:"paradigm_purpose_add_gate",description:"Add a gate (^) to a .purpose file's gates section. This is for purpose-level gates, NOT portal.yaml. Strips ^ prefix. ~100 tokens.",inputSchema:{type:"object",properties:{purposeFile:{type:"string",description:"Path to .purpose file or parent directory"},id:{type:"string",description:'Gate ID (e.g. "authenticated" or "^authenticated")'},description:{type:"string",description:"What this gate checks"},requires:{type:"array",items:{type:"string"},description:"Requirements for this gate"},keys:{type:"array",items:{type:"string"},description:"Key expressions for gate evaluation"},signals:{type:"array",items:{type:"string"},description:"Signals emitted by this gate (e.g. on pass/fail)"}},required:["purposeFile","id","description"]},annotations:{readOnlyHint:false,destructiveHint:false}},np={name:"paradigm_purpose_add_state",description:"Add a state definition to a .purpose file. ~100 tokens.",inputSchema:{type:"object",properties:{purposeFile:{type:"string",description:"Path to .purpose file or parent directory"},id:{type:"string",description:'State ID (e.g. "user-store")'},description:{type:"string",description:"What this state represents"},type:{type:"string",description:'Type of state (e.g. "object", "array", "string")'},default:{description:"Default value for the state"},properties:{type:"object",description:"State properties as {name: {type, description}}"}},required:["purposeFile","id","description"]},annotations:{readOnlyHint:false,destructiveHint:false}},sp={name:"paradigm_purpose_link",description:"Add references to an existing component without rewriting all fields. Merges into existing arrays (no clobber). Example: add ~rate-limited to #payment-service's aspects. ~100 tokens.",inputSchema:{type:"object",properties:{purposeFile:{type:"string",description:"Path to .purpose file or parent directory"},componentId:{type:"string",description:"Component or feature ID to add references to"},section:{type:"string",enum:["components","features"],description:"Which section the component is in (default: auto-detect)"},signals:{type:"array",items:{type:"string"},description:"Signal references to add"},aspects:{type:"array",items:{type:"string"},description:"Aspect references to add"},gates:{type:"array",items:{type:"string"},description:"Gate references to add"},flows:{type:"array",items:{type:"string"},description:"Flow references to add"},components:{type:"array",items:{type:"string"},description:"Component references to add"}},required:["purposeFile","componentId"]},annotations:{readOnlyHint:false,destructiveHint:false}},ip={name:"paradigm_purpose_remove",description:"Remove any element by section + id from a .purpose file. ~100 tokens.",inputSchema:{type:"object",properties:{purposeFile:{type:"string",description:"Path to .purpose file or parent directory"},section:{type:"string",enum:["components","features","gates","signals","aspects","flows","states"],description:"Which section to remove from"},id:{type:"string",description:"ID of the element to remove"}},required:["purposeFile","section","id"]},annotations:{readOnlyHint:false,destructiveHint:true}},rp={name:"paradigm_purpose_rename",description:"Rename a symbol across ALL .purpose files in the project. Updates both definitions and references. ~200 tokens.",inputSchema:{type:"object",properties:{oldId:{type:"string",description:'Current symbol ID (e.g. "payment-service")'},newId:{type:"string",description:'New symbol ID (e.g. "billing-service")'},symbolType:{type:"string",enum:["#","^","!","$","~"],description:"Symbol type prefix"}},required:["oldId","newId","symbolType"]},annotations:{readOnlyHint:false,destructiveHint:false}},op={name:"paradigm_portal_add_gate",description:"Add or update a gate (^) in portal.yaml. Creates portal.yaml if it doesn't exist. Strips ^ prefix. ~100 tokens.",inputSchema:{type:"object",properties:{id:{type:"string",description:'Gate ID (e.g. "authenticated" or "^authenticated")'},description:{type:"string",description:"What this gate checks"},type:{type:"string",description:'Gate type (e.g. "auth", "role", "ownership")'},location:{type:"string",description:'Where the gate is enforced (e.g. "middleware", "route-handler")'},requires:{type:"array",items:{type:"string"},description:"Prerequisite gates"},check:{type:"string",description:'Expression to evaluate (e.g. "req.user != null")'},grants:{type:"array",items:{type:"string"},description:"What passing this gate grants access to"},emits:{type:"array",items:{type:"string"},description:"Signals emitted when gate is checked"},prizes:{type:"array",items:{type:"object",properties:{id:{type:"string"},oneTime:{type:"boolean"}},required:["id"]},description:"Side effects triggered on pass"}},required:["id","description"]},annotations:{readOnlyHint:false,destructiveHint:false}},ap={name:"paradigm_portal_add_route",description:"Add a route with gates to portal.yaml. Creates routes section if needed. ~100 tokens.",inputSchema:{type:"object",properties:{route:{type:"string",description:'Route path (e.g. "/api/users/:id")'},method:{type:"string",enum:["GET","POST","PUT","PATCH","DELETE"],description:"HTTP method"},gates:{type:"array",items:{type:"string"},description:'Gate IDs to apply (e.g. ["^authenticated", "^user-owner"])'}},required:["route","method","gates"]},annotations:{readOnlyHint:false,destructiveHint:false}},cp={name:"paradigm_purpose_validate",description:"Validate .purpose files and portal.yaml. Returns issues found. If no purposeFile specified, validates all files. ~200 tokens.",inputSchema:{type:"object",properties:{purposeFile:{type:"string",description:"Specific .purpose file to validate (validates all if omitted)"},includePortal:{type:"boolean",description:"Also validate portal.yaml (default: true)"}}},annotations:{readOnlyHint:true,destructiveHint:false}};function Sa(){return [Kd,Qd,Xd,Zd,ep,tp,np,sp,ip,rp,op,ap,cp]}async function xa(n,e,s,t){switch(n){case "paradigm_purpose_init":return lp(e,s,t);case "paradigm_purpose_add_component":return dp(e,s,t);case "paradigm_purpose_add_aspect":return pp(e,s,t);case "paradigm_purpose_add_signal":return up(e,s,t);case "paradigm_purpose_add_flow":return gp(e,s,t);case "paradigm_purpose_add_gate":return mp(e,s,t);case "paradigm_purpose_add_state":return fp(e,s,t);case "paradigm_purpose_link":return yp(e,s,t);case "paradigm_purpose_remove":return hp(e,s,t);case "paradigm_purpose_rename":return bp(e,s,t);case "paradigm_portal_add_gate":return wp(e,s,t);case "paradigm_portal_add_route":return vp(e,s,t);case "paradigm_purpose_validate":return Sp(e,s);default:return {handled:false,text:""}}}function X(n){return {handled:true,text:JSON.stringify(n,null,2)}}function Me(n){return {handled:true,text:JSON.stringify({error:n},null,2)}}async function lp(n,e,s){let{purposeFile:t,name:i,description:r,context:o,version:a}=n,c=ce(t,e.rootDir),l=le(c);return a!==void 0?l.version=a:l.version||(l.version="1.0.0"),r!==void 0?l.description=r:l.description||(l.description=i),o!==void 0&&(l.context=o),de(c,l),await s(),X({action:"purpose_init",file:c,metadata:{name:i,description:l.description,version:l.version}})}async function dp(n,e,s){let{purposeFile:t,id:i,description:r,section:o="components",file:a,status:c,endpoints:l,tests:d,flows:p,gates:u,signals:g,aspects:m,components:y,type:f,parent:b}=n,h=ce(t,e.rootDir),w=le(h),_=W(i),S=o,v=Ye(w[S]),x=v[_]||{description:""};return x.description=r,a!==void 0&&(x.file=a),c!==void 0&&(x.status=c),l!==void 0&&(x.endpoints=l),d!==void 0&&(x.tests=d),p!==void 0&&(x.flows=p.map(k=>q(k,"$"))),u!==void 0&&(x.gates=u.map(k=>q(k,"^"))),g!==void 0&&(x.signals=g.map(k=>q(k,"!"))),m!==void 0&&(x.aspects=m.map(k=>q(k,"~"))),y!==void 0&&(x.components=y.map(k=>q(k,"#"))),f!==void 0&&(x.type=f),b!==void 0&&(x.parent=q(b,"#")),v[_]=x,w[S]=v,de(h,w),await s(),X({action:"add_component",file:h,section:S,id:_,symbol:`#${_}`})}async function pp(n,e,s){let{purposeFile:t,id:i,description:r,anchors:o,tags:a,appliesTo:c,enforcement:l}=n;if(!o||o.length===0)return Me('Aspects (~) REQUIRE at least one code anchor. Provide anchors like ["src/middleware/audit.ts:15-35"].');let d=/^[^\s:]+:\d+(-\d+)?(,\d+)*$/;for(let y of o)if(!d.test(y))return Me(`Invalid anchor format: "${y}". Expected format: "file.ts:15", "file.ts:15-20", or "file.ts:15,25,30".`);let p=ce(t,e.rootDir),u=F.dirname(p);for(let y of o){let f=y.replace(/:.*$/,""),b=F.resolve(u,f);if(!O.existsSync(b)){let h=F.resolve(e.rootDir,f);if(O.existsSync(h)){let w=F.relative(u,h),_=o.indexOf(y);o[_]=y.replace(f,w);}else return Me(`Anchor file not found: "${f}". Anchors must be relative to the .purpose file directory (${u}).`)}}let g=le(p);g.aspects||(g.aspects={});let m=W(i);return g.aspects[m]={description:r,anchors:o,...a&&{tags:a},...c&&{"applies-to":c},...l&&{enforcement:l}},de(p,g),await s(),X({action:"add_aspect",file:p,id:m,symbol:`~${m}`,anchors:o})}async function up(n,e,s){let{purposeFile:t,id:i,description:r,category:o,severity:a,emitters:c,related:l,data:d}=n,p=ce(t,e.rootDir),u=le(p);u.signals||(u.signals={});let g=W(i);return u.signals[g]={description:r,...o&&{category:o},...a&&{severity:a},...c&&{emitters:c.map(m=>q(m,"#"))},...l&&{related:l},...d&&{data:d}},de(p,u),await s(),X({action:"add_signal",file:p,id:g,symbol:`!${g}`})}async function gp(n,e,s){let{purposeFile:t,id:i,description:r,gates:o,signals:a,components:c,steps:l}=n,d=ce(t,e.rootDir),p=le(d),u=Tn(p.flows),g=W(i),m={description:r,...o&&{gates:o.map(y=>q(y,"^"))},...a&&{signals:a.map(y=>q(y,"!"))},...c&&{components:c.map(y=>q(y,"#"))},...l&&{steps:l}};return u[g]=m,p.flows=u,de(d,p),await s(),X({action:"add_flow",file:d,id:g,symbol:`$${g}`})}async function mp(n,e,s){let{purposeFile:t,id:i,description:r,requires:o,keys:a,signals:c}=n,l=ce(t,e.rootDir),d=le(l);d.gates||(d.gates={});let p=W(i);return d.gates[p]={description:r,...o&&{requires:o},...a&&{keys:a},...c&&{signals:c.map(u=>q(u,"!"))}},de(l,d),await s(),X({action:"add_gate",file:l,id:p,symbol:`^${p}`})}async function fp(n,e,s){let{purposeFile:t,id:i,description:r,type:o,default:a,properties:c}=n,l=ce(t,e.rootDir),d=le(l);d.states||(d.states={});let p=W(i),u={description:r};return o!==void 0&&(u.type=o),a!==void 0&&(u.default=a),c!==void 0&&(u.properties=c),d.states[p]=u,de(l,d),await s(),X({action:"add_state",file:l,id:p})}async function yp(n,e,s){let{purposeFile:t,componentId:i,section:r,signals:o,aspects:a,gates:c,flows:l,components:d}=n,p=ce(t,e.rootDir),u=le(p),g=W(i),m=r;if(!m){let h=Ye(u.components),w=Ye(u.features);if(g in h)m="components";else if(g in w)m="features";else return Me(`Component "${g}" not found in components or features. Specify section explicitly.`)}let y=Ye(u[m]);if(!(g in y))return Me(`Component "${g}" not found in ${m} section.`);let f=y[g];o&&(f.signals=at(f.signals,o.map(h=>q(h,"!")))),c&&(f.gates=at(f.gates,c.map(h=>q(h,"^")))),l&&(f.flows=at(f.flows,l.map(h=>q(h,"$")))),d&&(f.components=at(f.components,d.map(h=>q(h,"#")))),a&&(f.aspects=at(f.aspects,a.map(h=>q(h,"~")))),y[g]=f,u[m]=y,de(p,u),await s();let b=[];return o&&b.push(`signals: ${o.join(", ")}`),a&&b.push(`aspects: ${a.join(", ")}`),c&&b.push(`gates: ${c.join(", ")}`),l&&b.push(`flows: ${l.join(", ")}`),d&&b.push(`components: ${d.join(", ")}`),X({action:"link",file:p,componentId:g,section:m,added:b})}async function hp(n,e,s){let{purposeFile:t,section:i,id:r}=n,o=ce(t,e.rootDir),a=le(o),c=W(r);if(i==="flows"){let l=Tn(a.flows);if(!(c in l))return Me(`Flow "${c}" not found in flows section.`);delete l[c],a.flows=l;}else if(i==="components"||i==="features"){let l=Ye(a[i]);if(!(c in l))return Me(`"${c}" not found in ${i} section.`);delete l[c],a[i]=l;}else {let l=a[i];if(!l||!(c in l))return Me(`"${c}" not found in ${i} section.`);delete l[c];}return de(o,a),await s(),X({action:"remove",file:o,section:i,id:c})}async function bp(n,e,s){let{oldId:t,newId:i,symbolType:r}=n,o=await ya(e.rootDir,t,i,r);return await s(),X({action:"rename",oldSymbol:`${r}${W(t)}`,newSymbol:`${r}${W(i)}`,filesModified:o.length,files:o})}async function wp(n,e,s){let{id:t,description:i,type:r,location:o,requires:a,check:c,grants:l,emits:d,prizes:p}=n,u=wa(e.rootDir,{id:t,description:i,type:r,location:o,requires:a,check:c,grants:l,emits:d,prizes:p});await s();let g=W(t);return X({action:"portal_add_gate",file:u,id:g,symbol:`^${g}`})}async function vp(n,e,s){let{route:t,method:i,gates:r}=n,o=va(e.rootDir,{route:t,method:i,gates:r});return await s(),X({action:"portal_add_route",file:o,route:`${i} ${t}`,gates:r})}var _p=/\[NEEDS CLARIFICATION:\s*[^\]]+\]/gi;function _a(n,e){let s=[];function t(r,o){if(typeof r=="string"){let a=r.match(_p);if(a)for(let c of a)s.push({type:"warning",message:`Clarification needed: ${c}`,path:o});}}t(n.description,"description");let i=[{key:"components",items:n.components},{key:"features",items:n.features},{key:"gates",items:n.gates},{key:"signals",items:n.signals},{key:"aspects",items:n.aspects}];for(let r of i)if(r.items&&typeof r.items=="object")for(let[o,a]of Object.entries(r.items))a&&typeof a.description=="string"&&t(a.description,`${r.key}.${o}.description`);if(n.flows&&typeof n.flows=="object"){let r=Array.isArray(n.flows)?[]:Object.entries(n.flows);for(let[o,a]of r)a&&typeof a.description=="string"&&t(a.description,`flows.${o}.description`);}return s}async function Sp(n,e){let{purposeFile:s,includePortal:t=true}=n,i=[];if(s){let a=ce(s,e.rootDir),c=a$8(a);if(!c.data)i.push({file:a,valid:false,issues:c.errors.map(l=>({type:"error",message:l}))});else {let l=d$9(c.data,a);if(c.data.aspects)for(let[p,u]of Object.entries(c.data.aspects))(!u.anchors||u.anchors.length===0)&&(l.issues.push({type:"error",message:`Aspect "${p}" is missing required anchors`,path:`aspects.${p}`}),l.valid=false);let d=_a(c.data);l.issues.push(...d),i.push({file:a,valid:l.valid,issues:l.issues});}}else {let a=await c$5(e.rootDir);for(let c of a){let l=a$8(c);if(!l.data){i.push({file:c,valid:false,issues:l.errors.map(u=>({type:"error",message:u}))});continue}let d=d$9(l.data,c);if(l.data.aspects)for(let[u,g]of Object.entries(l.data.aspects))(!g.anchors||g.anchors.length===0)&&(d.issues.push({type:"error",message:`Aspect "${u}" is missing required anchors`,path:`aspects.${u}`}),d.valid=false);let p=_a(l.data);d.issues.push(...p),i.push({file:c,valid:d.valid,issues:d.issues});}}if(t){let{data:a,filePath:c}=Dn(e.rootDir),l=[];if(a.gates)for(let[d,p]of Object.entries(a.gates))p.description||l.push({type:"warning",message:`Gate "${d}" has no description`,path:`gates.${d}`}),p.prizes||l.push({type:"warning",message:`Gate "${d}" is missing prizes array (v2 requirement)`,path:`gates.${d}`});l.length>0&&i.push({file:c,valid:l.every(d=>d.type!=="error"),issues:l});}let r=i.reduce((a,c)=>a+c.issues.length,0),o=i.every(a=>a.valid);return X({action:"validate",valid:o,totalFiles:i.length,totalIssues:r,results:i})}var Fa=[{id:"explore-before-implement",name:"Explore Before Implementing",description:"Call ripple/navigate/search before modifying existing symbols to understand impact",category:"discovery",trigger:"preflight",severity:"advisory",check:{type:"tool-called",params:{tools:["paradigm_ripple","paradigm_navigate","paradigm_search","paradigm_related"]}},enabled:true},{id:"ripple-before-modify",name:"Ripple Before Modifying",description:"Run ripple analysis before modifying symbols with dependents",category:"discovery",trigger:"preflight",severity:"advisory",check:{type:"tool-called",params:{tools:["paradigm_ripple"]}},enabled:true},{id:"check-fragility",name:"Check Fragility",description:"Check history fragility for symbols before modifying frequently-broken code",category:"discovery",trigger:"preflight",severity:"advisory",check:{type:"tool-called",params:{tools:["paradigm_history_fragility"]}},enabled:true},{id:"wisdom-before-implement",name:"Check Team Wisdom",description:"Check team wisdom (preferences, antipatterns, decisions) before implementing",category:"collaboration",trigger:"preflight",severity:"advisory",check:{type:"tool-called",params:{tools:["paradigm_wisdom_context","paradigm_wisdom_expert"]}},enabled:true},{id:"verify-before-done",name:"Verify Before Done",description:"Run postflight compliance checks before finishing a session",category:"verification",trigger:"on-stop",severity:"warn",check:{type:"tool-called",params:{tools:["paradigm_pm_postflight"]}},enabled:true},{id:"postflight-compliance",name:"Postflight Compliance",description:"Ensure postflight checks pass without errors before finishing",category:"verification",trigger:"on-stop",severity:"advisory",check:{type:"tool-called",params:{tools:["paradigm_pm_postflight","paradigm_reindex"]}},enabled:true},{id:"test-new-components",name:"Test New Components",description:"New components should have associated tests or test plan documented",category:"testing",trigger:"postflight",severity:"advisory",check:{type:"tests-exist",params:{patterns:["**/*.test.*","**/*.spec.*","**/tests/**"]}},enabled:true},{id:"purpose-coverage",name:"Purpose File Coverage",description:"All modified source directories should have .purpose file coverage",category:"documentation",trigger:"postflight",severity:"warn",check:{type:"file-exists",params:{patterns:["**/.purpose"]}},enabled:true},{id:"record-lore-for-significant",name:"Record Lore for Significant Changes",description:"Sessions modifying 3+ files should record a lore entry",category:"documentation",trigger:"on-stop",severity:"warn",check:{type:"lore-recorded",params:{}},enabled:true},{id:"confidence-on-decisions",name:"Confidence on Decisions",description:"When recording lore, include a confidence score (0.0-1.0) to enable calibration tracking over time",category:"documentation",trigger:"on-stop",severity:"advisory",check:{type:"tool-called",params:{tools:["paradigm_lore_record"]}},enabled:true},{id:"gates-for-routes",name:"Gates for Routes",description:"API routes should have corresponding gate declarations in portal.yaml",category:"security",trigger:"postflight",severity:"warn",check:{type:"gates-declared",params:{requireRoutes:true}},enabled:true},{id:"university-content-valid",name:"University Content Valid",description:"Validate university content integrity when files in symbol-covered areas change",category:"quality",trigger:"on-stop",severity:"advisory",check:{type:"tool-called",params:{tools:["paradigm_university_validate"]}},enabled:true},{id:"university-onboarded",name:"University Onboarding",description:"Call paradigm_university_onboard at session start for project-specific learning content",category:"discovery",trigger:"preflight",severity:"advisory",check:{type:"tool-called",params:{tools:["paradigm_university_onboard"]}},enabled:false},{id:"orchestration-required",name:"Orchestrate Complex Tasks",description:"Tasks affecting 3+ files or touching security symbols should use paradigm_orchestrate_inline to determine which agents are needed. Ensures security review, test coverage, and documentation.",category:"collaboration",trigger:"preflight",severity:"warn",check:{type:"tool-called",params:{tools:["paradigm_orchestrate_inline"]}},enabled:true},{id:"agent-coverage-validated",name:"Validate Agent Involvement",description:"After completing work, verify that agents with relevant expertise were consulted. Check nominations that were surfaced but not acted on.",category:"collaboration",trigger:"postflight",severity:"advisory",check:{type:"tool-called",params:{tools:["paradigm_ambient_nominations","paradigm_agent_list"]}},enabled:true},{id:"hot-mode-incident",name:"Incident Response Acknowledgment",description:"During incident response, orchestration enforcement is waived. But a post-incident lore entry is required and a postflight review should be scheduled.",category:"collaboration",trigger:"on-stop",severity:"advisory",check:{type:"lore-recorded"},enabled:true}],Rp=30*1e3,$s=new Map;function ie(n){let e=F.resolve(n),s=$s.get(e);if(s&&Date.now()-s.loadedAt<Rp)return s.habits;let t=jp(e);return $s.set(e,{habits:t,loadedAt:Date.now()}),t}function jp(n){let e=new Map;for(let a of Fa)e.set(a.id,{...a});let s=process.env.HOME||process.env.USERPROFILE||"~",t=ja(F.join(s,".paradigm","habits.yaml"));t&&Ta(e,t);let i=Aa(F.join(s,".paradigm","habits"));for(let a of i)e.set(a.id,a);let r=ja(F.join(n,".paradigm","habits.yaml"));r&&Ta(e,r);let o=Aa(F.join(n,".paradigm","habits"));for(let a of o)e.set(a.id,a);return Array.from(e.values())}function ja(n){if(!O.existsSync(n))return null;try{let e=O.readFileSync(n,"utf8");return Z.load(e)}catch{return null}}function Ta(n,e){if(e.habits)for(let s of e.habits)n.set(s.id,{...s});if(e.overrides)for(let[s,t]of Object.entries(e.overrides)){let i=n.get(s);i&&(t.severity!==void 0&&(i.severity=t.severity),t.enabled!==void 0&&(i.enabled=t.enabled));}}function Tp(n,e){return n.filter(s=>s.enabled&&s.trigger===e)}function Fs(n){$s.delete(F.resolve(n));}function Aa(n){if(!O.existsSync(n))return [];try{let e=O.readdirSync(n).filter(t=>t.endsWith(".habit")).sort(),s=[];for(let t of e)try{let i=O.readFileSync(F.join(n,t),"utf8"),r=Z.load(i);r?.id&&r?.name&&s.push(r);}catch{}return s}catch{return []}}var Da=["discovery","verification","testing","documentation","collaboration","security"],Oa=["preflight","postflight","on-commit","on-stop"],Ia=["advisory","warn","block"],$a=["tool-called","file-exists","file-modified","lore-recorded","symbols-registered","gates-declared","tests-exist","git-clean","commit-message-format","flow-coverage","context-checked","aspect-anchored"],Ap=/^[a-z0-9]+(-[a-z0-9]+)*$/;function Ns(n){let e=[];if(n.id||e.push("Missing required field: id"),n.name||e.push("Missing required field: name"),n.description||e.push("Missing required field: description"),n.category||e.push("Missing required field: category"),n.trigger||e.push("Missing required field: trigger"),n.severity||e.push("Missing required field: severity"),n.check||e.push("Missing required field: check"),(n.enabled===void 0||n.enabled===null)&&e.push("Missing required field: enabled"),n.id&&!Ap.test(n.id)&&e.push(`Invalid id format: "${n.id}" \u2014 must be kebab-case (lowercase, hyphens only)`),n.category&&!Da.includes(n.category)&&e.push(`Invalid category: "${n.category}" \u2014 must be one of: ${Da.join(", ")}`),n.trigger&&!Oa.includes(n.trigger)&&e.push(`Invalid trigger: "${n.trigger}" \u2014 must be one of: ${Oa.join(", ")}`),n.severity&&!Ia.includes(n.severity)&&e.push(`Invalid severity: "${n.severity}" \u2014 must be one of: ${Ia.join(", ")}`),n.check){$a.includes(n.check.type)||e.push(`Invalid check.type: "${n.check.type}" \u2014 must be one of: ${$a.join(", ")}`);let s=n.check.params||{};switch(n.check.type){case "tool-called":(!s.tools||!Array.isArray(s.tools)||s.tools.length===0)&&e.push('check.type "tool-called" requires check.params.tools[] (non-empty array)');break;case "file-exists":case "file-modified":(!s.patterns||!Array.isArray(s.patterns)||s.patterns.length===0)&&e.push(`check.type "${n.check.type}" requires check.params.patterns[] (non-empty array)`);break;case "commit-message-format":(!s.messagePatterns||!Array.isArray(s.messagePatterns)||s.messagePatterns.length===0)&&e.push('check.type "commit-message-format" requires check.params.messagePatterns[] (non-empty array)');break}}return {valid:e.length===0,errors:e}}var Dp=new Set(Fa.map(n=>n.id));function Hn(n){return Dp.has(n)}function Es(n,e,s="project"){let t=s==="global"?F.join(process.env.HOME||process.env.USERPROFILE||"~",".paradigm","habits"):F.join(n,".paradigm","habits");O.existsSync(t)||O.mkdirSync(t,{recursive:true});let i=F.join(t,`${e.id}.habit`),r=Z.dump(e,{lineWidth:120,noRefs:true});return O.writeFileSync(i,r,"utf8"),Fs(n),i}function Na(n,e){if(Hn(e))return {removed:false,reason:`"${e}" is a seed habit and cannot be removed. Use overrides in habits.yaml to disable it.`};let s=F.join(n,".paradigm","habits",`${e}.habit`);if(O.existsSync(s))return O.unlinkSync(s),Fs(n),{removed:true};let t=process.env.HOME||process.env.USERPROFILE||"~",i=F.join(t,".paradigm","habits",`${e}.habit`);return O.existsSync(i)?(O.unlinkSync(i),Fs(n),{removed:true}):{removed:false,reason:`No .habit file found for "${e}". It may be defined in habits.yaml \u2014 edit that file directly.`}}var Hs=0;function Nt(n,e,s,t,i){let r=Tp(n,e);t&&(r=r.filter(u=>!u.platforms||u.platforms.includes(t)));let o=0;if(i)try{let{isGraduated:u}=(En(),d$a(Ra)),g=r.length;r=r.filter(m=>!u(i,m.id)),o=g-r.length;}catch{}Hs=o;let a=r.map(u=>Op(u,s)),c=a.filter(u=>u.result==="followed").length,l=a.filter(u=>u.result==="skipped").length,d=a.filter(u=>u.result==="partial").length,p=a.filter(u=>u.result==="skipped"&&u.habit.severity==="block").length;return {trigger:e,evaluations:a,summary:{total:a.length,followed:c,skipped:l,partial:d,blockingViolations:p},blocksCompletion:p>0}}function Et(n){return {toolsCalled:n.toolsCalled||[],filesModified:n.filesModified||[],symbolsTouched:n.symbolsTouched||[],loreRecorded:n.loreRecorded||false,hasPortalRoutes:n.hasPortalRoutes||false,taskAddsRoutes:n.taskAddsRoutes||false,taskDescription:n.taskDescription,gitClean:n.gitClean}}function Op(n,e){switch(n.check.type){case "tool-called":return Ip(n,e);case "file-exists":return $p(n,e);case "file-modified":return Mp(n,e);case "lore-recorded":return Fp(n,e);case "symbols-registered":return Np(n,e);case "gates-declared":return Ep(n,e);case "tests-exist":return Hp(n,e);case "git-clean":return qp(n,e);default:return {habit:n,result:"partial",reason:`Unknown check: ${n.check.type}`}}}function Ip(n,e){let s=n.check.params.tools||[];if(s.length===0)return {habit:n,result:"followed",reason:"No tools required"};let t=s.filter(i=>e.toolsCalled.includes(i));return t.length>0?{habit:n,result:"followed",reason:`Called: ${t.join(", ")}`,evidence:t}:e.filesModified.length===0&&e.symbolsTouched.length===0?{habit:n,result:"followed",reason:"No modifications, habit not applicable"}:{habit:n,result:"skipped",reason:`None of [${s.join(", ")}] were called before modifying code`}}function $p(n,e){if(e.filesModified.length===0)return {habit:n,result:"followed",reason:"No files modified"};if(e.filesModified.some(i=>i.endsWith(".purpose")||i.includes(".paradigm/")))return {habit:n,result:"followed",reason:"Purpose files updated"};let t=e.filesModified.filter(i=>!i.endsWith(".md")&&!i.endsWith(".json")&&!i.endsWith(".yaml")&&!i.endsWith(".yml")&&!i.endsWith(".lock")&&!i.endsWith(".purpose")&&!i.includes(".paradigm/"));return t.length===0?{habit:n,result:"followed",reason:"Only non-source files modified"}:{habit:n,result:"skipped",reason:`${t.length} source file(s) without .purpose updates`,evidence:t.slice(0,5)}}function Fp(n,e){let s=e.filesModified.filter(t=>!t.endsWith(".md")&&!t.endsWith(".json")&&!t.endsWith(".yaml")&&!t.endsWith(".yml")&&!t.endsWith(".lock")&&!t.endsWith(".purpose")&&!t.includes(".paradigm/"));return s.length<3?{habit:n,result:"followed",reason:"Session not significant (< 3 source files)"}:e.loreRecorded||e.toolsCalled.includes("paradigm_lore_record")?{habit:n,result:"followed",reason:"Lore recorded"}:{habit:n,result:"skipped",reason:`${s.length} source files modified, no lore entry`,evidence:s.slice(0,5)}}function Np(n,e){if(e.symbolsTouched.length===0)return {habit:n,result:"followed",reason:"No symbols touched"};let t=["paradigm_purpose_add_component","paradigm_purpose_add_signal","paradigm_purpose_add_flow","paradigm_purpose_add_gate","paradigm_purpose_add_aspect","paradigm_purpose_init"].filter(i=>e.toolsCalled.includes(i));return t.length>0?{habit:n,result:"followed",reason:`Purpose tools called: ${t.join(", ")}`,evidence:t}:{habit:n,result:"partial",reason:`${e.symbolsTouched.length} symbol(s) touched, no purpose registration`}}function Ep(n,e){if(!e.taskAddsRoutes)return {habit:n,result:"followed",reason:"No routes added"};if(e.hasPortalRoutes)return {habit:n,result:"followed",reason:"Portal.yaml has routes"};let t=["paradigm_gates_for_route","paradigm_portal_add_route","paradigm_portal_add_gate"].filter(i=>e.toolsCalled.includes(i));return t.length>0?{habit:n,result:"followed",reason:`Gate tools called: ${t.join(", ")}`,evidence:t}:{habit:n,result:"skipped",reason:"Routes added without gate declarations"}}function Hp(n,e){if(e.filesModified.length===0)return {habit:n,result:"followed",reason:"No files modified"};let s=e.filesModified.filter(i=>i.includes(".test.")||i.includes(".spec.")||i.includes("/tests/")||i.includes("/test/")||i.includes("__tests__"));if(s.length>0)return {habit:n,result:"followed",reason:`Test files: ${s.length}`,evidence:s.slice(0,5)};let t=e.filesModified.filter(i=>!i.endsWith(".md")&&!i.endsWith(".json")&&!i.endsWith(".yaml")&&!i.endsWith(".lock")&&!i.endsWith(".purpose")&&!i.includes(".paradigm/")&&!i.includes("node_modules/"));return t.length===0?{habit:n,result:"followed",reason:"No source files to test"}:{habit:n,result:"partial",reason:`${t.length} source file(s), no test files updated`,evidence:t.slice(0,5)}}function Mp(n,e){if(e.filesModified.length===0)return {habit:n,result:"followed",reason:"No files modified"};let s=n.check.params.patterns||[];if(s.length===0)return {habit:n,result:"followed",reason:"No patterns specified"};if(n.trigger==="on-stop"&&n.severity==="block"){let i=e.filesModified.filter(r=>s.some(o=>r.includes(o)||F.basename(r)===o));return i.length>0?{habit:n,result:"followed",reason:`Matching files: ${i.join(", ")}`,evidence:i}:{habit:n,result:"partial",reason:`None of [${s.join(", ")}] in git diff yet (may not be committed). Use on-commit trigger for reliable check.`}}let t=e.filesModified.filter(i=>s.some(r=>i.includes(r)||F.basename(i)===r));return t.length>0?{habit:n,result:"followed",reason:`Matching files: ${t.join(", ")}`,evidence:t}:{habit:n,result:"skipped",reason:`None of [${s.join(", ")}] found in modified files`}}function qp(n,e){return e.filesModified.length===0?{habit:n,result:"followed",reason:"No files modified"}:n.trigger==="on-stop"?{habit:n,result:"followed",reason:"git-clean skipped on-stop (uncommitted changes expected before commit)"}:e.gitClean===void 0?{habit:n,result:"partial",reason:"Git status not available"}:e.gitClean?{habit:n,result:"followed",reason:"Working tree is clean \u2014 changes committed"}:{habit:n,result:"skipped",reason:"Uncommitted changes in working tree"}}var Ht=null,Ms=false;async function qs(n){if(Ht)Ms||(await Ht.ensureReady(),Ms=true);else {let e=F.join(n,".paradigm","sentinel","sentinel.db");Ht=new f$4(e),await Ht.ensureReady(),Ms=true;}return Ht}async function Lp(n,e){return (await qs(n)).recordPracticeEvent(e)}async function Ha(n,e){return (await qs(n)).getPracticeEvents(e)}async function pe(n,e){return (await qs(n)).getComplianceRate(e)}async function Mt(n,e){let s=["discovery","verification","testing","documentation","collaboration","security"],t=[];for(let i of s){let r=await pe(n,{...e,habitCategory:i});r.total>0&&t.push({category:i,...r});}return t}async function Ma(n,e,s){let t=[];for(let i of e){let r=await Lp(n,{habitId:i.habitId,habitCategory:i.habitCategory,result:i.result,engineer:s.engineer,sessionId:s.sessionId,loreEntryId:s.loreEntryId,taskDescription:s.taskDescription,symbolsTouched:s.symbolsTouched,filesModified:s.filesModified,notes:i.notes});t.push(r);}return t}var Jp=/[@#$%^!?&~][a-zA-Z][a-zA-Z0-9_-]*/g,Gp=["endpoint","route","api","handler","get","post","put","patch","delete","rest","crud","controller"],Up=[/\.(get|post|put|patch|delete)\s*\(\s*['"`]([^'"`]+)['"`]/gi,/export\s+(async\s+)?function\s+(GET|POST|PUT|PATCH|DELETE)/gi];function qa(){return [{name:"paradigm_pm_preflight",description:`REQUIRED before implementing features. Call with mode="plan" to get the right agents and cost estimate. Skipping this for complex tasks leads to missed security reviews and wasted tokens.
743
743
 
744
744
  Runs pre-flight compliance checks: extracts affected symbols, runs ripple analysis, checks portal.yaml status, and suggests required agents. Returns affected symbols, ripple summary, gate recommendations, and suggested agents. ~300 tokens.`,inputSchema:{type:"object",properties:{task:{type:"string",description:"The task description to analyze for compliance requirements"}},required:["task"]},annotations:{readOnlyHint:true,destructiveHint:false}},{name:"paradigm_pm_postflight",description:"Run after completing a task to check compliance. Verifies that new components, routes, and events are properly registered in .purpose files and portal.yaml. Flags unregistered symbols and uncaptured wisdom. Returns compliance checklist with pass/fail status for purpose files, portal.yaml, and wisdom capture. ~200 tokens.",inputSchema:{type:"object",properties:{filesModified:{type:"array",items:{type:"string"},description:"List of files modified during the task"},symbolsTouched:{type:"array",items:{type:"string"},description:'List of symbols (e.g., ["#auth-handler", "^authenticated"]) touched during the task'}},required:["filesModified","symbolsTouched"]},annotations:{readOnlyHint:true,destructiveHint:false}}]}async function La(n,e,s){switch(n){case "paradigm_pm_preflight":{let{task:t}=e,i=await zp(t,s),r=JSON.stringify(i,null,2);return o(r.length,n),{text:r,handled:true}}case "paradigm_pm_postflight":{let{filesModified:t,symbolsTouched:i}=e,r=Vp(t,i,s),o$1=JSON.stringify(r,null,2);return o(o$1.length,n),{text:o$1,handled:true}}default:return {text:"",handled:false}}}async function zp(n,e){let s=n.toLowerCase(),t=n.match(Jp)||[],i=[...new Set(t)],r=i.map(u=>{let g=j$2(e.index,u),m=g.length>0?g[0]:null;return {symbol:u,exists:!!m,type:m?.type,description:m?.description}}),o=r.filter(u=>u.exists).map(u=>{let g=k(e.index,u.symbol),m=new Set;for(let b of g){let h=k(e.index,b.symbol);for(let w of h)w.symbol!==u.symbol&&!g.find(_=>_.symbol===w.symbol)&&m.add(w.symbol);}let y=g.length+m.size,f="low";return y>10?f="high":y>3&&(f="medium"),{symbol:u.symbol,directDependents:g.length,indirectDependents:m.size,impact:f}}),a={exists:e.gateConfig!==null,gateCount:0,gates:[],routeCount:0};if(e.gateConfig){let u=Object.keys(e.gateConfig.gates||{});a.gateCount=u.length,a.gates=u.map(g=>g.startsWith("^")?g:`^${g}`),a.routeCount=Object.keys(e.gateConfig.routes||{}).length;}let c=Gp.some(u=>s.includes(u)),l=[];r.some(u=>u.exists)&&l.push("ripple-analysis"),c&&l.push("portal-compliance"),i.some(u=>u.startsWith("^"))&&l.push("gate-validation"),i.some(u=>u.startsWith("!"))&&l.push("signal-registration"),l.push("purpose-coverage");let d=null,p=null;try{let u=ie(e.rootDir),m=j$1().getStats(),y=[...new Set(m.toolCalls.map(w=>w.toolName))],f=Et({toolsCalled:y,filesModified:[],symbolsTouched:i,loreRecorded:!1,hasPortalRoutes:a.exists&&a.routeCount>0,taskAddsRoutes:c,taskDescription:n}),b=Nt(u,"preflight",f,void 0,e.rootDir);d={total:b.summary.total,followed:b.summary.followed,skipped:b.summary.skipped,partial:b.summary.partial,results:b.evaluations.map(w=>({id:w.habit.id,name:w.habit.name,severity:w.habit.severity,result:w.result,reason:w.reason}))};let h=new Date(Date.now()-720*60*60*1e3).toISOString();p=await pe(e.rootDir,{dateFrom:h});}catch{}return {task:n.slice(0,100)+(n.length>100?"...":""),affectedSymbols:r,rippleAnalysis:o,portalStatus:a,taskAddsRoutes:c,requiredChecks:l,recommendations:Bp(r,o,a,c),habits:{evaluation:d,recentCompliance:p?{rate:p.rate,totalEvents:p.total}:null}}}function Bp(n,e,s,t){let i=[],r=n.filter(c=>!c.exists);r.length>0&&i.push(`New symbols detected: ${r.map(c=>c.symbol).join(", ")}. Register in .purpose files after implementation.`);let o=e.filter(c=>c.impact==="high");o.length>0&&i.push(`HIGH IMPACT: ${o.map(c=>c.symbol).join(", ")} \u2014 review all dependents before modifying.`),t&&!s.exists?i.push("Task adds routes but no portal.yaml exists. Create one with appropriate ^gates."):t&&i.push("Task adds routes. Update portal.yaml with gate entries after implementation.");let a=n.filter(c=>c.symbol.startsWith("^")&&!c.exists);return a.length>0&&i.push(`New gates referenced: ${a.map(c=>c.symbol).join(", ")}. Add to portal.yaml.`),i}function Vp(n,e,s){let t=[],i$1=s.gateConfig?.routes?Object.keys(s.gateConfig.routes):[];for(let p of n){let u=F.isAbsolute(p)?p:F.join(s.rootDir,p);if(!O.existsSync(u))continue;let g;try{g=O.readFileSync(u,"utf-8");}catch{continue}for(let m of Up){m.lastIndex=0;let y;for(;(y=m.exec(g))!==null;){let f=y[2]||y[0];f&&f.startsWith("/")&&(!i$1.some(h=>h.replace(/\s+(GET|POST|PUT|PATCH|DELETE)\s*$/,"").trim()===f)&&s.gateConfig?t.push({type:"missing-portal-gate",severity:"warning",message:`Route "${f}" in ${F.relative(s.rootDir,u)} not in portal.yaml`,file:F.relative(s.rootDir,u),suggestion:"Add route to portal.yaml with ^gates. Use paradigm_gates_for_route for suggestions."}):!s.gateConfig&&f.startsWith("/api/")&&t.push({type:"missing-portal-gate",severity:"warning",message:`API route "${f}" found but no portal.yaml exists`,file:F.relative(s.rootDir,u),suggestion:"Create portal.yaml to declare gates for API routes."}));}}}for(let p of e)j$2(s.index,p).length===0&&t.push({type:"unregistered-symbol",severity:"error",message:`Symbol "${p}" is not registered in any .purpose file`,suggestion:"Add to nearest .purpose file using paradigm_purpose_add_component or paradigm_purpose_add_signal."});let r=s.gateConfig?Object.keys(s.gateConfig.gates||{}).map(p=>p.startsWith("^")?p.slice(1):p):[];for(let p of e)if(p.startsWith("^")){let u=p.slice(1);r.includes(u)||t.push({type:"missing-portal-gate",severity:"error",message:`Gate "${p}" referenced but not declared in portal.yaml`,suggestion:`Add ${p} to portal.yaml with description and check expression.`});}let o=i(s.index,"aspect");for(let p of o){let u=p.appliesTo||[];if(u.length!==0){for(let g of u){let m=g.includes("*");for(let y of e){let f=false;if(m?f=new RegExp("^"+g.replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/\\\*/g,".*")+"$").test(y):f=y===g,f){let b=p.anchors||[];if(b.length===0)t.push({type:"stale-aspect",severity:"warning",message:`Aspect "${p.symbol}" applies to "${y}" but has no code anchors`,suggestion:`Add anchors to ${p.symbol} in .purpose file. Run paradigm_aspect_check for details.`});else for(let h of b){let w=F.isAbsolute(h.path)?h.path:F.join(s.rootDir,h.path);O.existsSync(w)||t.push({type:"stale-aspect",severity:"warning",message:`Aspect "${p.symbol}" anchor "${h.raw}" points to missing file`,suggestion:`Update anchors for ${p.symbol} in .purpose file.`});}}}}for(let g of e){if(!g.startsWith("#"))continue;(p.data||{}).aspects||[];for(let f of u){if(!f.includes("*"))continue;if(new RegExp("^"+f.replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/\\\*/g,".*")+"$").test(g))break}}}}n.length>=5&&e.length>=3&&t.push({type:"uncaptured-wisdom",severity:"warning",message:`Large change (${n.length} files, ${e.length} symbols) \u2014 consider recording decisions`,suggestion:"Use paradigm_wisdom_record to capture architectural decisions or antipatterns."});for(let p of e){let u=j$2(s.index,p);if(u.length===0)continue;let g=u[0];g.parentSymbol&&j$2(s.index,g.parentSymbol).length===0&&t.push({type:"broken-reference",severity:"warning",message:`Symbol "${p}" references parent "${g.parentSymbol}" which does not exist`,suggestion:"Create the parent symbol or update the parent reference in the .purpose file."});}let a=t.filter(p=>p.severity==="error").length,c=t.filter(p=>p.severity==="warning").length,l="pass";a>0?l="violations":c>0&&(l="warnings");let d=null;try{let p=ie(s.rootDir),g=j$1().getStats(),m=[...new Set(g.toolCalls.map(_=>_.toolName))],y=m.includes("paradigm_lore_record"),f;try{f=execSync("git status --porcelain",{cwd:s.rootDir,encoding:"utf8",timeout:5e3}).trim()==="";}catch{}let b=Et({toolsCalled:m,filesModified:n,symbolsTouched:e,loreRecorded:y,hasPortalRoutes:s.gateConfig!==null&&s.gateConfig.routes!=null,taskAddsRoutes:!1,gitClean:f}),h=Nt(p,"postflight",b,void 0,s.rootDir);d={trigger:"postflight",total:h.summary.total,followed:h.summary.followed,skipped:h.summary.skipped,partial:h.summary.partial,blockingViolations:h.summary.blockingViolations,results:h.evaluations.map(_=>({id:_.habit.id,name:_.habit.name,severity:_.habit.severity,result:_.result,reason:_.reason}))};let w=F.join(s.rootDir,".paradigm",".habits-blocking");if(h.blocksCompletion){let _=h.evaluations.filter(S=>S.result==="skipped"&&S.habit.severity==="block").map(S=>`${S.habit.name}: ${S.reason}`);O.writeFileSync(w,_.join(`
745
745
  `),"utf8");}else O.existsSync(w)&&O.unlinkSync(w);}catch{}return {status:l,violations:t,summary:{totalChecks:7,passed:7-(a>0?1:0)-(c>0?1:0),warnings:c,errors:a},blocksCompletion:a>0,habitsEvaluation:d}}j();function Wa(){let n=process.env.PARADIGM_AUTHOR;if(n)return Ls(n);try{let e=execSync("git config user.name",{encoding:"utf-8",timeout:3e3}).trim();if(e)return Ls(e)}catch{}try{let e=oa.userInfo().username;if(e)return Ls(e)}catch{}return "unknown"}function Ls(n){return n.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"").slice(0,20)||"unknown"}function Ua(){return [{name:"paradigm_lore_search",description:"Search lore entries by symbol, author, date range, type, or tags. Returns project history records. Returns matching entries with titles, dates, and symbol references. ~200 tokens.",inputSchema:{type:"object",properties:{symbol:{type:"string",description:'Filter by symbol (e.g., "#sentinel-sdk", "^authenticated")'},author:{type:"string",description:'Filter by author (human user name, e.g., "ascend")'},hasAgent:{type:"boolean",description:"Filter by AI assistance: true = AI-assisted entries, false = human-only"},authorType:{type:"string",enum:["human","agent"],description:"(Deprecated, use hasAgent) Filter by old author type"},type:{type:"string",enum:["agent-session","human-note","decision","review","incident","milestone","retro","insight"],description:"Filter by entry type"},tag:{type:"string",description:'Filter by tag prefix (e.g., "arc:lore-evolution" for arc entries)'},hasBody:{type:"boolean",description:"Filter for entries with/without long-form body content"},dateFrom:{type:"string",description:'Filter from date (ISO 8601, e.g., "2026-02-20")'},dateTo:{type:"string",description:"Filter to date (ISO 8601)"},tags:{type:"array",items:{type:"string"},description:"Filter by tags (OR logic)"},hasReview:{type:"boolean",description:"Filter for entries with/without reviews"},hasConfidence:{type:"boolean",description:"Filter for entries with/without confidence scores"},hasAssessment:{type:"boolean",description:"Filter for entries with/without assessment verdicts"},limit:{type:"number",description:"Maximum results (default: 20)"},offset:{type:"number",description:"Offset for pagination"}}},annotations:{readOnlyHint:true,destructiveHint:false}},{name:"paradigm_lore_record",description:"Record a new lore entry (agent session, decision, milestone, etc.). Call after completing significant work. Returns the created entry ID and file path. ~100 tokens.",inputSchema:{type:"object",properties:{type:{type:"string",enum:["agent-session","human-note","decision","review","incident","milestone","retro","insight"],description:"Entry type"},title:{type:"string",description:'Short title (e.g., "Built Sentinel Phase 1")'},summary:{type:"string",description:"2-3 sentence narrative summary"},symbols_touched:{type:"array",items:{type:"string"},description:'Symbols affected (e.g., ["#sentinel-sdk", "^authenticated"])'},symbols_created:{type:"array",items:{type:"string"},description:"New symbols introduced"},files_created:{type:"array",items:{type:"string"},description:"Files created"},files_modified:{type:"array",items:{type:"string"},description:"Files modified"},lines_added:{type:"number",description:"Lines of code added"},lines_removed:{type:"number",description:"Lines of code removed"},commit:{type:"string",description:"Git commit hash"},duration_minutes:{type:"number",description:"Duration in minutes"},decisions:{type:"array",items:{type:"object",properties:{id:{type:"string"},decision:{type:"string"},rationale:{type:"string"}},required:["id","decision","rationale"]},description:"Decisions made during this work"},errors_encountered:{type:"array",items:{type:"object",properties:{description:{type:"string"},resolution:{type:"string"},time_to_fix:{type:"string"}},required:["description","resolution"]}},learnings:{type:"array",items:{type:"string"},description:"Key learnings from this work"},verification:{type:"object",properties:{status:{type:"string",enum:["pass","fail","partial","untested"]},details:{type:"object",description:'Per-check results (e.g., { "build": "pass", "tests": "fail" })'}}},tags:{type:"array",items:{type:"string"},description:"Tags for categorization"},meta:{type:"object",description:'Project-defined metadata (open-ended key-value pairs, e.g., { meeting_type: "design-review", sprint: 12 })'},body:{type:"string",description:"Long-form content (detailed retrospective notes, decision rationale, etc.)"},linked_lore:{type:"array",items:{type:"string"},description:"Cross-references to other lore entry IDs"},linked_tasks:{type:"array",items:{type:"string"},description:"References to paradigm task IDs"},linked_commits:{type:"array",items:{type:"string"},description:"Git commit SHAs related to this entry"},confidence:{type:"number",description:"Agent confidence in correctness of this work (0.0 to 1.0)"},stream:{type:"string",enum:["work-log","journal","decision","auto"],description:'Knowledge stream classification. "auto" classifies based on content. Default: stores in lore (backward compatible).'}},required:["title","summary","symbols_touched"]},annotations:{readOnlyHint:false,destructiveHint:false}},{name:"paradigm_lore_timeline",description:"Get lore timeline overview: recent entries, active authors, hot symbols. Call for project history orientation. ~200 tokens.",inputSchema:{type:"object",properties:{limit:{type:"number",description:"Number of recent entries to include (default: 10)"}}},annotations:{readOnlyHint:true,destructiveHint:false}},{name:"paradigm_lore_get",description:"Fetch a single lore entry by ID. Returns the full entry with all fields. ~150 tokens.",inputSchema:{type:"object",properties:{id:{type:"string",description:'Lore entry ID (e.g., "L-2026-02-23-001" or "L-2026-03-02-ascend-143025-001")'}},required:["id"]},annotations:{readOnlyHint:true,destructiveHint:false}},{name:"paradigm_lore_update",description:"Update an existing lore entry. Merges provided fields into the existing entry. Returns updated entry confirmation. ~100 tokens.",inputSchema:{type:"object",properties:{id:{type:"string",description:"Lore entry ID to update"},title:{type:"string",description:"New title"},summary:{type:"string",description:"New summary"},type:{type:"string",enum:["agent-session","human-note","decision","review","incident","milestone","retro","insight"],description:"New entry type"},symbols_touched:{type:"array",items:{type:"string"},description:"Updated symbols list"},symbols_created:{type:"array",items:{type:"string"},description:"Updated created symbols"},files_created:{type:"array",items:{type:"string"}},files_modified:{type:"array",items:{type:"string"}},lines_added:{type:"number"},lines_removed:{type:"number"},commit:{type:"string"},duration_minutes:{type:"number"},learnings:{type:"array",items:{type:"string"},description:"Updated learnings"},verification:{type:"object",properties:{status:{type:"string",enum:["pass","fail","partial","untested"]},details:{type:"object"}}},tags:{type:"array",items:{type:"string"}},confidence:{type:"number",description:"Agent confidence in correctness (0.0 to 1.0)"}},required:["id"]},annotations:{readOnlyHint:false,destructiveHint:false}},{name:"paradigm_lore_assess",description:"Record a human assessment verdict on a lore entry (correct/partial/incorrect). Computes calibration delta if confidence was recorded. ~100 tokens.",inputSchema:{type:"object",properties:{id:{type:"string",description:"Lore entry ID to assess"},verdict:{type:"string",enum:["correct","partial","incorrect"],description:"Assessment verdict on the decisions/changes made"},notes:{type:"string",description:"Optional assessment notes"}},required:["id","verdict"]},annotations:{readOnlyHint:false,destructiveHint:false}},{name:"paradigm_lore_calibration",description:"Query calibration statistics across assessed lore entries. Returns accuracy rate, average confidence, calibration score, and verdict breakdown. Supports groupBy for domain-specific reliability maps. ~200 tokens.",inputSchema:{type:"object",properties:{symbol:{type:"string",description:'Filter by symbol (e.g., "#auth-middleware")'},tag:{type:"string",description:"Filter by tag prefix"},author:{type:"string",description:"Filter by author"},dateFrom:{type:"string",description:"Filter from date (ISO 8601)"},dateTo:{type:"string",description:"Filter to date (ISO 8601)"},groupBy:{type:"string",enum:["symbol","tag","type"],description:"Group calibration stats by dimension"}}},annotations:{readOnlyHint:true,destructiveHint:false}},{name:"paradigm_lore_delete",description:"Delete a lore entry. Requires explicit confirmation to prevent accidental deletion. ~100 tokens.",inputSchema:{type:"object",properties:{id:{type:"string",description:"Lore entry ID to delete"},confirm:{type:"boolean",description:"Must be true to proceed with deletion"}},required:["id","confirm"]},annotations:{readOnlyHint:false,destructiveHint:true}}]}async function za(n,e,s){switch(n){case "paradigm_lore_search":{let t={author:e.author,hasAgent:e.hasAgent,authorType:e.authorType,symbol:e.symbol,dateFrom:e.dateFrom,dateTo:e.dateTo,type:e.type,tag:e.tag,hasBody:e.hasBody,tags:e.tags,hasReview:e.hasReview,hasConfidence:e.hasConfidence,hasAssessment:e.hasAssessment,limit:e.limit||20,offset:e.offset},i=await a$1(s.rootDir,t);return {handled:true,text:JSON.stringify({count:i.length,filter:Object.fromEntries(Object.entries(t).filter(([,r])=>r!==void 0)),entries:i.map(Ja)},null,2)}}case "paradigm_lore_record":{let{type:t,title:i,summary:r,symbols_touched:o,symbols_created:a,files_created:c,files_modified:l,lines_added:d,lines_removed:p,commit:u,duration_minutes:g,decisions:m,errors_encountered:y,learnings:f,verification:b,tags:h,meta:w,body:_,linked_lore:S,linked_tasks:v,linked_commits:x,confidence:k}=e,C;try{let I=new Date(Date.now()-2592e6).toISOString(),D=await pe(s.rootDir,{dateFrom:I});if(D.total>0){let H=(await Mt(s.rootDir,{dateFrom:I})).filter(M=>M.rate<60).map(M=>M.category);C={rate:D.rate,followed:D.followed,skipped:D.skipped,partial:D.partial,weakAreas:H.length>0?H:void 0};}}catch{}let T={id:"",type:t||"agent-session",timestamp:new Date().toISOString(),duration_minutes:g,author:Wa(),agent:{provider:"anthropic",model:"claude-opus-4-6"},title:i,summary:r,symbols_touched:o,symbols_created:a,files_created:c,files_modified:l,lines_added:d,lines_removed:p,commit:u,decisions:m,errors_encountered:y,learnings:f,verification:b,tags:h,meta:w||void 0,habit_compliance:C,body:_,linked_lore:S,linked_tasks:v,linked_commits:x,confidence:k!=null&&k>=0&&k<=1?k:void 0},R=await d$1(s.rootDir,T);j$1().setLastLoreEntryId(R);try{let I=process.env.PARADIGM_AGENT_ID;if(I&&o&&o.length>0){let{updateExpertiseFromLore:D}=await import('./agent-loader-EPXURMO7.js');D(s.rootDir,I,{symbols_touched:o,confidence:k!=null&&k>=0&&k<=1?k:void 0});}}catch{}let P=null;try{c&&c.length>=2&&(P=Z$1(s.rootDir,c,l||[]));}catch{}let A;if(e.stream){let I=e.stream,D=I==="auto"?Kp(e):I;try{if(D==="work-log"){let{recordWorkLog:N}=await import('./work-log-loader-DL5GZ2BQ.js');N(s.rootDir,{agent:T.agent?.model||"unknown",summary:T.summary,outcome:T.verification?.status==="pass"?"pass":T.verification?.status==="fail"?"fail":"partial",files_modified:T.files_modified,symbols_touched:T.symbols_touched,commit:T.commit,linked_lore:T.id||R}),A="work-log";}else if(D==="journal"&&T.learnings?.length){let{recordJournalEntry:N}=await import('./journal-loader-GLH7XFTK.js');for(let H of T.learnings)N(T.agent?.model||"unknown",{trigger:"self_reflection",insight:H,project:s.projectName||"unknown",transferable:!1,linked_work_log:T.id||R});A="journal";}else if(D==="decision"&&T.decisions?.length){let{recordDecision:N}=await import('./decision-loader-2XPZE4EZ.js');for(let H of T.decisions)N(s.rootDir,{title:H.decision.slice(0,100),decision:H.decision,rationale:H.rationale,participants:[{id:`agent/${T.agent?.model||"unknown"}`,role:"agent",stance:"proposed"}],symbols_affected:T.symbols_touched,status:"active",linked_lore:T.id||R});A="decision";}}catch{}}return {handled:true,text:JSON.stringify({success:true,id:R,type:t,title:i,message:"Lore entry recorded successfully",...A?{stream:A}:{},...P?{protocol_suggestion:P}:{}})}}case "paradigm_lore_timeline":{let t=e.limit||10,i=await c$1(s.rootDir),r=await a$1(s.rootDir,{limit:t}),o={};for(let l of r)for(let d of l.symbols_touched)o[d]=(o[d]||0)+1;let a=Object.entries(o).sort(([,l],[,d])=>d-l).slice(0,10).map(([l,d])=>({symbol:l,count:d})),c={};for(let l of r){let d=l.author;c[d]||(c[d]={count:0,lastActive:l.timestamp,hasAgent:l.agent!=null}),c[d].count++,l.agent&&(c[d].hasAgent=true),l.timestamp>c[d].lastActive&&(c[d].lastActive=l.timestamp);}return {handled:true,text:JSON.stringify({timeline:i||{version:"1.0",project:"unknown",entries:0,last_updated:"",authors:[]},recentEntries:r.map(Ja),hotSymbols:a,authors:Object.entries(c).map(([l,d])=>({id:l,hasAgent:d.hasAgent,entries:d.count,lastActive:d.lastActive}))},null,2)}}case "paradigm_lore_get":{let t=e.id,i=await b$3(s.rootDir,t);return i?{handled:true,text:JSON.stringify(i,null,2)}:{handled:true,text:JSON.stringify({error:`Lore entry not found: ${t}`})}}case "paradigm_lore_update":{let t=e.id,{id:i,...r}=e,o={};for(let[c,l]of Object.entries(r))l!==void 0&&(o[c]=l);let a=await g$4(s.rootDir,t,o);return {handled:true,text:JSON.stringify({success:a,id:t,message:a?"Lore entry updated":`Lore entry not found: ${t}`})}}case "paradigm_lore_assess":{let t=e.id,i=e.verdict,r=e.notes,o=await b$3(s.rootDir,t);if(!o)return {handled:true,text:JSON.stringify({error:`Lore entry not found: ${t}`})};let a={verdict:i,assessed_by:Wa(),assessed_at:new Date().toISOString(),notes:r},c=await h$3(s.rootDir,t,a);try{let u=process.env.PARADIGM_AGENT_ID;if(u&&c&&o.symbols_touched?.length){let{updateExpertiseFromAssessment:g}=await import('./agent-loader-EPXURMO7.js');g(s.rootDir,u,{symbols_touched:o.symbols_touched,verdict:i});}}catch{}let l=i==="correct"?1:i==="partial"?.5:0,d=o.confidence!=null?l-o.confidence:null,p=d!=null?d>.1?"Under-confident (actual outcome better than predicted)":d<-0.1?"Over-confident (actual outcome worse than predicted)":"Well-calibrated":"No confidence recorded \u2014 delta not computed";return {handled:true,text:JSON.stringify({success:c,id:t,verdict:i,confidence:o.confidence??null,delta:d,deltaDescription:p,message:c?`Assessment recorded: ${i}${d!=null?` (delta: ${d>0?"+":""}${d.toFixed(2)})`:""}`:`Failed to assess: ${t}`})}}case "paradigm_lore_calibration":{let t={symbol:e.symbol,tag:e.tag,author:e.author,dateFrom:e.dateFrom,dateTo:e.dateTo,hasAssessment:true},i=await a$1(s.rootDir,t),r=i.filter(_=>_.confidence!=null),o=i.length,a=r.length,c={correct:0,partial:0,incorrect:0},l=0,d=0,p=0;for(let _ of i){let S=_.assessment.verdict;c[S]++;let v=S==="correct"?1:S==="partial"?.5:0;l+=v,_.confidence!=null&&(d+=_.confidence,p+=Math.abs(v-_.confidence));}let u=o>0?l/o:0,g=a>0?d/a:null,m=a>0?l/o-d/a:null,y=a>0?1-p/a:null,f=e.groupBy,b;if(f&&o>0){let _=new Map;for(let S of i){let v=[];f==="symbol"?v=S.symbols_touched||[]:f==="tag"?v=S.tags||[]:f==="type"&&(v=[S.type||"agent-session"]);for(let x of v)_.has(x)||_.set(x,[]),_.get(x).push(S);}b=Array.from(_.entries()).map(([S,v])=>{let x=v.filter(P=>P.confidence!=null),k={correct:0,partial:0,incorrect:0},C=0,T=0,R=0;for(let P of v){let A=P.assessment.verdict;k[A]++;let I=A==="correct"?1:A==="partial"?.5:0;C+=I,P.confidence!=null&&(T+=P.confidence,R+=Math.abs(I-P.confidence));}return {key:S,total:v.length,accuracyRate:C/v.length,avgConfidence:x.length>0?T/x.length:null,calibrationScore:x.length>0?1-R/x.length:null,verdictBreakdown:k}}).sort((S,v)=>v.total-S.total);}let h=[],w=o<5?`Low sample size (N=${o}). Stats may not be representative.`:o<15?`Moderate sample (N=${o}). Trends are directional, not conclusive.`:null;return w&&h.push(w),y!=null&&(y>=.9?h.push("Excellent calibration \u2014 confidence predictions closely match outcomes."):y>=.7?h.push("Good calibration \u2014 some room for improvement in confidence estimates."):y>=.5?h.push("Fair calibration \u2014 significant gap between predicted confidence and outcomes."):h.push("Poor calibration \u2014 confidence predictions diverge substantially from outcomes.")),m!=null&&(m>.15?h.push("Tendency toward under-confidence \u2014 outcomes are better than predicted."):m<-0.15&&h.push("Tendency toward over-confidence \u2014 outcomes are worse than predicted.")),c.incorrect>o*.3&&o>=5&&h.push(`High error rate: ${c.incorrect}/${o} entries assessed as incorrect.`),{handled:true,text:JSON.stringify({totalAssessed:o,totalWithConfidence:a,accuracyRate:Math.round(u*1e3)/1e3,avgConfidence:g!=null?Math.round(g*1e3)/1e3:null,avgDelta:m!=null?Math.round(m*1e3)/1e3:null,calibrationScore:y!=null?Math.round(y*1e3)/1e3:null,verdictBreakdown:c,...b?{groups:b}:{},insights:h},null,2)}}case "paradigm_lore_delete":{let t=e.id;if(!e.confirm)return {handled:true,text:JSON.stringify({success:false,message:"Deletion requires confirm: true"})};let r=await i$1(s.rootDir,t);return {handled:true,text:JSON.stringify({success:r,id:t,message:r?"Lore entry deleted":`Lore entry not found: ${t}`})}}default:return {handled:false,text:""}}}function Kp(n){return n.task_ref||n.files_modified||n.commit?"work-log":n.learnings||n.confidence!==void 0?"journal":n.decisions?.some(s=>s.rationale)?"decision":"work-log"}function Ja(n){return {id:n.id,type:n.type,title:n.title,summary:n.summary,author:n.author,agent:n.agent,timestamp:n.timestamp,duration_minutes:n.duration_minutes,symbols_touched:n.symbols_touched,verification:n.verification?.status,review:n.review?{completeness:n.review.completeness,quality:n.review.quality}:null,confidence:n.confidence??null,assessment:n.assessment?n.assessment.verdict:null,assessment_delta:n.assessment_delta??null,tags:n.tags}}function Va(){return [{name:"paradigm_habits_list",description:"List all habit definitions: seed (built-in), global (~/.paradigm/habits.yaml), and project (.paradigm/habits.yaml). Shows what habits exist, their triggers, severity, and enabled state. Use to discover available habits before evaluating them. Returns habit definitions with id, check type, trigger, severity, category, and enabled state. ~300 tokens.",inputSchema:{type:"object",properties:{trigger:{type:"string",enum:["preflight","postflight","on-commit","on-stop"],description:"Filter by trigger point"},category:{type:"string",enum:["discovery","verification","testing","documentation","collaboration","security"],description:"Filter by category"},enabled:{type:"boolean",description:"Filter by enabled state (default: show all)"}}},annotations:{readOnlyHint:true,destructiveHint:false}},{name:"paradigm_habits_check",description:"Evaluate habit compliance for the current session and record practice events. Call at preflight (before implementing), postflight (after implementing), or on-stop (session end). Returns which habits were followed, skipped, or partially met. Returns per-habit follow/skip/partial results and blocking status. ~200 tokens.",inputSchema:{type:"object",properties:{trigger:{type:"string",enum:["preflight","postflight","on-stop","on-commit"],description:"When to evaluate: preflight (before task), postflight (after task), on-stop (session end)"},filesModified:{type:"array",items:{type:"string"},description:"Files modified during the session/task"},symbolsTouched:{type:"array",items:{type:"string"},description:"Symbols touched during the session/task"},taskDescription:{type:"string",description:"Description of the task being performed"},record:{type:"boolean",description:"Whether to record practice events (default: true)"}},required:["trigger"]},annotations:{readOnlyHint:false,destructiveHint:false}},{name:"paradigm_habits_status",description:"View practice profile: compliance rates by category, trends, and incident correlations. Shows how well habits are being followed over time. Returns overall rate, per-category rates, trend direction, and incident correlations. ~200 tokens.",inputSchema:{type:"object",properties:{engineer:{type:"string",description:"Filter by engineer name (default: all)"},period:{type:"string",enum:["7d","30d","90d","all"],description:"Time period for analysis (default: 30d)"}}},annotations:{readOnlyHint:true,destructiveHint:false}},{name:"paradigm_practice_context",description:"Get proactive practice warnings before modifying symbols. Shows recent compliance gaps and team-aware suggestions. Call this alongside paradigm_wisdom_context for full context. Returns relevant habits, compliance gaps, and behavioral suggestions. ~200 tokens.",inputSchema:{type:"object",properties:{symbols:{type:"array",items:{type:"string"},description:"Symbols about to be modified"},task:{type:"string",description:"Description of the upcoming task"}},required:["symbols"]},annotations:{readOnlyHint:true,destructiveHint:false}},{name:"paradigm_habits_add",description:'Create a new custom habit as an individual .habit file. Validates all fields and checks for ID collisions with seed habits. Use scope "global" for ~/.paradigm/habits/ or "project" (default) for .paradigm/habits/. ~150 tokens.',inputSchema:{type:"object",properties:{id:{type:"string",description:'Unique habit ID in kebab-case (e.g. "check-changelog")'},name:{type:"string",description:"Human-readable habit name"},description:{type:"string",description:"What this habit checks and why"},category:{type:"string",enum:["discovery","verification","testing","documentation","collaboration","security"],description:"Habit category"},trigger:{type:"string",enum:["preflight","postflight","on-commit","on-stop"],description:"When the habit is evaluated"},severity:{type:"string",enum:["advisory","warn","block"],description:"How strictly to enforce (block prevents session completion)"},check:{type:"object",description:"Check definition with type and params",properties:{type:{type:"string",enum:["tool-called","file-exists","file-modified","lore-recorded","symbols-registered","gates-declared","tests-exist","git-clean","commit-message-format","flow-coverage","context-checked","aspect-anchored"]},params:{type:"object",description:"Check-specific parameters (tools[], patterns[], etc.)"}},required:["type","params"]},enabled:{type:"boolean",description:"Whether the habit is active (default: true)"},platforms:{type:"array",items:{type:"string"},description:'Platforms this habit applies to (e.g. ["claude", "cursor"]). Omit for all.'},scope:{type:"string",enum:["project","global"],description:'Where to save: "project" (default) or "global" (~/.paradigm/habits/)'}},required:["id","name","description","category","trigger","severity","check"]},annotations:{readOnlyHint:false,destructiveHint:false}},{name:"paradigm_habits_edit",description:"Update fields on an existing custom .habit file. Cannot edit seed habits \u2014 use overrides in habits.yaml instead. Merges provided fields with existing definition and re-validates. ~150 tokens.",inputSchema:{type:"object",properties:{id:{type:"string",description:"ID of the habit to edit"},name:{type:"string",description:"Updated name"},description:{type:"string",description:"Updated description"},category:{type:"string",enum:["discovery","verification","testing","documentation","collaboration","security"]},trigger:{type:"string",enum:["preflight","postflight","on-commit","on-stop"]},severity:{type:"string",enum:["advisory","warn","block"]},check:{type:"object",properties:{type:{type:"string"},params:{type:"object"}},required:["type","params"]},enabled:{type:"boolean"},platforms:{type:"array",items:{type:"string"}}},required:["id"]},annotations:{readOnlyHint:false,destructiveHint:false}},{name:"paradigm_habits_remove",description:"Delete a custom .habit file. Cannot remove seed habits \u2014 use overrides to disable them instead. Searches both project and global habit directories. ~100 tokens.",inputSchema:{type:"object",properties:{id:{type:"string",description:"ID of the habit to remove"}},required:["id"]},annotations:{readOnlyHint:false,destructiveHint:true}}]}async function Ya(n,e,s){switch(n){case "paradigm_habits_list":{let t=Xp(e,s);return o(t.length,n),{text:t,handled:true}}case "paradigm_habits_check":{let t=await Zp(e,s);return o(t.length,n),{text:t,handled:true}}case "paradigm_habits_status":{let t=await iu(e,s);return o(t.length,n),{text:t,handled:true}}case "paradigm_practice_context":{let t=await ru(e,s);return o(t.length,n),{text:t,handled:true}}case "paradigm_habits_add":{let t=tu(e,s);return o(t.length,n),{text:t,handled:true}}case "paradigm_habits_edit":{let t=nu(e,s);return o(t.length,n),{text:t,handled:true}}case "paradigm_habits_remove":{let t=su(e,s);return o(t.length,n),{text:t,handled:true}}default:return {text:"",handled:false}}}function Xp(n,e){let s=n.trigger,t=n.category,i=n.enabled,r=ie(e.rootDir);s&&(r=r.filter(a=>a.trigger===s)),t&&(r=r.filter(a=>a.category===t)),i!==void 0&&(r=r.filter(a=>a.enabled===i));let o={};for(let a of r)o[a.trigger]||(o[a.trigger]=[]),o[a.trigger].push(a);return JSON.stringify({total:r.length,filters:Object.fromEntries(Object.entries({trigger:s,category:t,enabled:i}).filter(([,a])=>a!==void 0)),byTrigger:Object.fromEntries(Object.entries(o).map(([a,c])=>[a,c.map(l=>({id:l.id,name:l.name,description:l.description,category:l.category,severity:l.severity,enabled:l.enabled,check:{type:l.check.type,params:l.check.params},platforms:l.platforms||null}))]))},null,2)}async function Zp(n,e){let s=n.trigger,t=n.filesModified||[],i=n.symbolsTouched||[],r=n.taskDescription,o=n.record!==false,a=ie(e.rootDir),c=j$1(),l=c.getStats(),d=[...new Set(l.toolCalls.map(S=>S.toolName))],p=d.includes("paradigm_lore_record"),u=(r||"").toLowerCase(),g=["endpoint","route","api","handler","get","post","put","patch","delete"].some(S=>u.includes(S)),m;try{m=execSync("git status --porcelain",{cwd:e.rootDir,encoding:"utf8",timeout:5e3}).trim()==="";}catch{}let y=Et({toolsCalled:d,filesModified:t,symbolsTouched:i,loreRecorded:p,hasPortalRoutes:e.gateConfig!==null&&e.gateConfig.routes!=null,taskAddsRoutes:g,taskDescription:r,gitClean:m}),b=Nt(a,s,y,"claude",e.rootDir),h=[];if(o&&b.evaluations.length>0)try{let S=c.getLastLoreEntryId()??void 0;h=await Ma(e.rootDir,b.evaluations.map(v=>({habitId:v.habit.id,habitCategory:v.habit.category,result:v.result,notes:v.reason})),{engineer:"agent",sessionId:l.sessionId,loreEntryId:S,taskDescription:r,symbolsTouched:i,filesModified:t});}catch{}let w=F.join(e.rootDir,".paradigm",".habits-blocking");try{if(s==="on-stop"&&b.blocksCompletion){let S=b.evaluations.filter(v=>v.result==="skipped"&&v.habit.severity==="block").map(v=>`${v.habit.name}: ${v.reason}`);O.writeFileSync(w,S.join(`
@@ -48,7 +48,7 @@ component_types:
48
48
  `),{status:"applied",message:"Added component_types glossary to config.yaml",filesModified:[".paradigm/config.yaml"]}):{status:"error",message:"Cannot read config.yaml"}}},ue={id:"add-discipline-config",introducedIn:"3.4.0",description:"Add discipline field to config.yaml",category:"config",auto:true,async check(e){let t=A(e);return t?D(t,"discipline")?{needed:false,reason:"discipline already set"}:{needed:true,reason:"Missing discipline field"}:{needed:false,reason:"No config.yaml found"}},async apply(e,t){if(t.dryRun)return {status:"skipped",message:"Would add discipline to config.yaml"};let n=I(e);if(!n)return {status:"error",message:"Cannot read config.yaml"};let i=n.replace(/^(project:\s*.+)$/m,`$1
49
49
  discipline: auto`);return i===n?x(e,n.trimEnd()+`
50
50
  discipline: auto
51
- `):x(e,i),{status:"applied",message:"Added discipline: auto to config.yaml",filesModified:[".paradigm/config.yaml"]}}},fe={id:"sync-templates",introducedIn:"evergreen",description:"Update specs/ and docs/ from installed CLI templates",category:"template",auto:true,async check(e){let t=$();if(!t)return {needed:false,reason:"Templates directory not found"};let n=[],i=["specs","docs","prompts"];for(let r of i){let a=p.join(t,r),d=p.join(e,".paradigm",r);if(o.existsSync(a))try{let g=o.readdirSync(a).filter(m=>o.statSync(p.join(a,m)).isFile());for(let m of g)o.existsSync(p.join(d,m))||n.push(`${r}/${m}`);}catch{}}return n.length===0?{needed:false,reason:"All templates are up to date"}:{needed:true,reason:`${n.length} new template file(s) available`,details:n.map(r=>`New: ${r}`)}},async apply(e,t){let n=$();if(!n)return {status:"error",message:"Templates directory not found"};let i=p.basename(e),r=[],a=["specs","docs","prompts"];for(let d of a){let g=p.join(n,d),m=p.join(e,".paradigm",d);if(o.existsSync(g)){t.dryRun||o.mkdirSync(m,{recursive:true});try{let S=o.readdirSync(g,{withFileTypes:!0});for(let k of S){if(k.isDirectory())continue;let M=p.join(m,k.name);if(!o.existsSync(M)){if(t.dryRun){r.push(`${d}/${k.name}`);continue}let c=o.readFileSync(p.join(g,k.name),"utf8");c=c.replace(/\{\{PROJECT_NAME\}\}/g,i),o.writeFileSync(M,c,"utf8"),r.push(`${d}/${k.name}`);}}}catch{}}}return t.dryRun?{status:"skipped",message:`Would copy ${r.length} template file(s)`}:r.length===0?{status:"skipped",message:"No new templates to sync"}:{status:"applied",message:`Synced ${r.length} template file(s)`,filesCreated:r.map(d=>`.paradigm/${d}`)}}},me={id:"refresh-hooks",introducedIn:"evergreen",description:"Reinstall hook scripts from plugin",category:"hook",auto:true,async check(e){let t=[p.join(e,".claude","hooks"),p.join(e,".cursor","hooks")];for(let i of t)if(o.existsSync(i))try{if(o.readdirSync(i).some(a=>a.includes("paradigm")))return {needed:!1,reason:"Hooks are installed"}}catch{}let n=p.join(e,".claude","settings.local.json");if(o.existsSync(n))try{if(JSON.parse(o.readFileSync(n,"utf8")).hooks)return {needed:!1,reason:"Plugin-managed hooks are configured"}}catch{}return {needed:true,reason:"No paradigm hooks found"}},async apply(e,t){if(t.dryRun)return {status:"skipped",message:"Would reinstall hooks"};try{let{hooksInstallCommand:n}=await import('./hooks-XH52VGOU.js');return await n({force:!0}),{status:"applied",message:"Hooks reinstalled"}}catch(n){return {status:"error",message:`Hook install failed: ${n.message}`}}}},b=[Q,X,Z,ee,te,ne,se,ue,de,le,re,oe,ie,ae,ce,pe,ge,fe,me];var he=createRequire(import.meta.url),{version:W}=he("../package.json");function C(e){let t=p.join(e,".paradigm","migrate.yaml");if(!o.existsSync(t))return null;try{let n=o.readFileSync(t,"utf8");return F.load(n)}catch{return null}}async function V(e){let t=p.join(e,".paradigm"),n=C(e),i=n?.applied.map(l=>l.id)??[],r="unknown",a=p.join(t,"config.yaml");if(o.existsSync(a))try{let l=F.load(o.readFileSync(a,"utf8"));r=String(l.version??"unknown");}catch{}let g=["specs","docs","prompts","lore","tasks","protocols","personas"].filter(l=>!o.existsSync(p.join(t,l))),m=["discipline","tag-bank","purpose-required","component_types"],S=[];if(o.existsSync(a))try{let l=F.load(o.readFileSync(a,"utf8"));S=m.filter(h=>{let j=h.replace(/-/g,"_");return !(h in l)&&!(j in l)&&!(h.replace(/_/g,"-")in l)});}catch{}let k=[],M=$();if(M){let l=["specs","docs"];for(let h of l){let j=p.join(M,h),L=p.join(t,h);if(o.existsSync(j)&&o.existsSync(L)){let J=o.readdirSync(j).filter(R=>!o.statSync(p.join(j,R)).isDirectory());for(let R of J){let Y=p.join(L,R);o.existsSync(Y)||k.push(`${h}/${R}`);}}}}let c=!o.existsSync(p.join(e,".claude","hooks")),u=[];for(let l of b){let h=l.introducedIn==="evergreen";if(i.includes(l.id)&&!h)continue;(await l.check(e)).needed&&u.push(l);}return {configVersion:r,cliVersion:W,pendingMigrations:u,appliedIds:i,health:{missingDirectories:g,missingConfigFields:S,staleTemplates:k,hooksOutdated:c}}}async function U(e){let t=[],n=new Date().toISOString();for(let i of b){if(i.introducedIn==="evergreen")continue;(await i.check(e)).needed||t.push({id:i.id,appliedAt:n,cliVersion:W});}return t}function $(){let e=new URL(import.meta.url).pathname,t=p.dirname(e),n=[p.join(t,"..","..","..","templates","paradigm"),p.join(t,"..","..","templates","paradigm"),p.join(t,"..","templates","paradigm")];for(let i of n)if(o.existsSync(i))return i;return null}var ke=createRequire(import.meta.url),{version:N}=ke("../package.json");async function B(e){let t=C(e);if(t)return t;let n=await U(e);return {version:"1.0",cliVersion:N,lastMigrated:new Date().toISOString(),applied:n}}function _(e,t){let n=p.join(e,".paradigm","migrate.yaml");o.mkdirSync(p.dirname(n),{recursive:true}),t.cliVersion=N,t.lastMigrated=new Date().toISOString(),o.writeFileSync(n,F.dump(t,{indent:2,lineWidth:120,noRefs:true,sortKeys:false,quotingType:'"'}),"utf8");}async function E(e,t,n,i){let r={applied:0,skipped:0,errors:0,manual:0,results:[]},a=new Date().toISOString();for(let d of t){if(!d.auto){r.manual++,r.results.push({id:d.id,result:{status:"skipped",message:"Manual review recommended"}});continue}try{let g=await d.apply(e,n);r.results.push({id:d.id,result:g}),g.status==="applied"?(r.applied++,i.applied.push({id:d.id,appliedAt:a,cliVersion:N})):g.status==="skipped"?r.skipped++:r.errors++;}catch(g){r.errors++,r.results.push({id:d.id,result:{status:"error",message:g.message}});}}return r}async function _e(e={}){let t=process.cwd(),n=p.join(t,".paradigm");if((!o.existsSync(n)||!o.statSync(n).isDirectory())&&!(o.existsSync(n)&&o.statSync(n).isFile())){e.quiet||console.log(s.yellow("\n No .paradigm/ directory found. Run `paradigm init` or `paradigm shift` first.\n"));return}let i=we();e.quiet||i.start("Detecting project state...");let r=await V(t);e.quiet||i.stop();let a=await B(t),d=r.pendingMigrations;if(e.only&&e.only.length>0&&(d=d.filter(c=>e.only.includes(c.id))),e.category&&(d=d.filter(c=>c.category===e.category)),e.force){let c=e.only?b.filter(u=>e.only.includes(u.id)):e.category?b.filter(u=>u.category===e.category):b;d=[];for(let u of c)((await u.check(t)).needed||e.force)&&d.push(u);}let g=d.filter(c=>c.auto),m=d.filter(c=>!c.auto);if(e.list){Me(a,r,e);return}if(e.quiet){if(g.length===0)return;let c=await E(t,g,e,a);return _(t,a),c}let S=C(t);if(console.log(s.blue(`
51
+ `):x(e,i),{status:"applied",message:"Added discipline: auto to config.yaml",filesModified:[".paradigm/config.yaml"]}}},fe={id:"sync-templates",introducedIn:"evergreen",description:"Update specs/ and docs/ from installed CLI templates",category:"template",auto:true,async check(e){let t=$();if(!t)return {needed:false,reason:"Templates directory not found"};let n=[],i=["specs","docs","prompts"];for(let r of i){let a=p.join(t,r),d=p.join(e,".paradigm",r);if(o.existsSync(a))try{let g=o.readdirSync(a).filter(m=>o.statSync(p.join(a,m)).isFile());for(let m of g)o.existsSync(p.join(d,m))||n.push(`${r}/${m}`);}catch{}}return n.length===0?{needed:false,reason:"All templates are up to date"}:{needed:true,reason:`${n.length} new template file(s) available`,details:n.map(r=>`New: ${r}`)}},async apply(e,t){let n=$();if(!n)return {status:"error",message:"Templates directory not found"};let i=p.basename(e),r=[],a=["specs","docs","prompts"];for(let d of a){let g=p.join(n,d),m=p.join(e,".paradigm",d);if(o.existsSync(g)){t.dryRun||o.mkdirSync(m,{recursive:true});try{let S=o.readdirSync(g,{withFileTypes:!0});for(let k of S){if(k.isDirectory())continue;let M=p.join(m,k.name);if(!o.existsSync(M)){if(t.dryRun){r.push(`${d}/${k.name}`);continue}let c=o.readFileSync(p.join(g,k.name),"utf8");c=c.replace(/\{\{PROJECT_NAME\}\}/g,i),o.writeFileSync(M,c,"utf8"),r.push(`${d}/${k.name}`);}}}catch{}}}return t.dryRun?{status:"skipped",message:`Would copy ${r.length} template file(s)`}:r.length===0?{status:"skipped",message:"No new templates to sync"}:{status:"applied",message:`Synced ${r.length} template file(s)`,filesCreated:r.map(d=>`.paradigm/${d}`)}}},me={id:"refresh-hooks",introducedIn:"evergreen",description:"Reinstall hook scripts from plugin",category:"hook",auto:true,async check(e){let t=[p.join(e,".claude","hooks"),p.join(e,".cursor","hooks")];for(let i of t)if(o.existsSync(i))try{if(o.readdirSync(i).some(a=>a.includes("paradigm")))return {needed:!1,reason:"Hooks are installed"}}catch{}let n=p.join(e,".claude","settings.local.json");if(o.existsSync(n))try{if(JSON.parse(o.readFileSync(n,"utf8")).hooks)return {needed:!1,reason:"Plugin-managed hooks are configured"}}catch{}return {needed:true,reason:"No paradigm hooks found"}},async apply(e,t){if(t.dryRun)return {status:"skipped",message:"Would reinstall hooks"};try{let{hooksInstallCommand:n}=await import('./hooks-JQKA3TUG.js');return await n({force:!0}),{status:"applied",message:"Hooks reinstalled"}}catch(n){return {status:"error",message:`Hook install failed: ${n.message}`}}}},b=[Q,X,Z,ee,te,ne,se,ue,de,le,re,oe,ie,ae,ce,pe,ge,fe,me];var he=createRequire(import.meta.url),{version:W}=he("../package.json");function C(e){let t=p.join(e,".paradigm","migrate.yaml");if(!o.existsSync(t))return null;try{let n=o.readFileSync(t,"utf8");return F.load(n)}catch{return null}}async function V(e){let t=p.join(e,".paradigm"),n=C(e),i=n?.applied.map(l=>l.id)??[],r="unknown",a=p.join(t,"config.yaml");if(o.existsSync(a))try{let l=F.load(o.readFileSync(a,"utf8"));r=String(l.version??"unknown");}catch{}let g=["specs","docs","prompts","lore","tasks","protocols","personas"].filter(l=>!o.existsSync(p.join(t,l))),m=["discipline","tag-bank","purpose-required","component_types"],S=[];if(o.existsSync(a))try{let l=F.load(o.readFileSync(a,"utf8"));S=m.filter(h=>{let j=h.replace(/-/g,"_");return !(h in l)&&!(j in l)&&!(h.replace(/_/g,"-")in l)});}catch{}let k=[],M=$();if(M){let l=["specs","docs"];for(let h of l){let j=p.join(M,h),L=p.join(t,h);if(o.existsSync(j)&&o.existsSync(L)){let J=o.readdirSync(j).filter(R=>!o.statSync(p.join(j,R)).isDirectory());for(let R of J){let Y=p.join(L,R);o.existsSync(Y)||k.push(`${h}/${R}`);}}}}let c=!o.existsSync(p.join(e,".claude","hooks")),u=[];for(let l of b){let h=l.introducedIn==="evergreen";if(i.includes(l.id)&&!h)continue;(await l.check(e)).needed&&u.push(l);}return {configVersion:r,cliVersion:W,pendingMigrations:u,appliedIds:i,health:{missingDirectories:g,missingConfigFields:S,staleTemplates:k,hooksOutdated:c}}}async function U(e){let t=[],n=new Date().toISOString();for(let i of b){if(i.introducedIn==="evergreen")continue;(await i.check(e)).needed||t.push({id:i.id,appliedAt:n,cliVersion:W});}return t}function $(){let e=new URL(import.meta.url).pathname,t=p.dirname(e),n=[p.join(t,"..","..","..","templates","paradigm"),p.join(t,"..","..","templates","paradigm"),p.join(t,"..","templates","paradigm")];for(let i of n)if(o.existsSync(i))return i;return null}var ke=createRequire(import.meta.url),{version:N}=ke("../package.json");async function B(e){let t=C(e);if(t)return t;let n=await U(e);return {version:"1.0",cliVersion:N,lastMigrated:new Date().toISOString(),applied:n}}function _(e,t){let n=p.join(e,".paradigm","migrate.yaml");o.mkdirSync(p.dirname(n),{recursive:true}),t.cliVersion=N,t.lastMigrated=new Date().toISOString(),o.writeFileSync(n,F.dump(t,{indent:2,lineWidth:120,noRefs:true,sortKeys:false,quotingType:'"'}),"utf8");}async function E(e,t,n,i){let r={applied:0,skipped:0,errors:0,manual:0,results:[]},a=new Date().toISOString();for(let d of t){if(!d.auto){r.manual++,r.results.push({id:d.id,result:{status:"skipped",message:"Manual review recommended"}});continue}try{let g=await d.apply(e,n);r.results.push({id:d.id,result:g}),g.status==="applied"?(r.applied++,i.applied.push({id:d.id,appliedAt:a,cliVersion:N})):g.status==="skipped"?r.skipped++:r.errors++;}catch(g){r.errors++,r.results.push({id:d.id,result:{status:"error",message:g.message}});}}return r}async function _e(e={}){let t=process.cwd(),n=p.join(t,".paradigm");if((!o.existsSync(n)||!o.statSync(n).isDirectory())&&!(o.existsSync(n)&&o.statSync(n).isFile())){e.quiet||console.log(s.yellow("\n No .paradigm/ directory found. Run `paradigm init` or `paradigm shift` first.\n"));return}let i=we();e.quiet||i.start("Detecting project state...");let r=await V(t);e.quiet||i.stop();let a=await B(t),d=r.pendingMigrations;if(e.only&&e.only.length>0&&(d=d.filter(c=>e.only.includes(c.id))),e.category&&(d=d.filter(c=>c.category===e.category)),e.force){let c=e.only?b.filter(u=>e.only.includes(u.id)):e.category?b.filter(u=>u.category===e.category):b;d=[];for(let u of c)((await u.check(t)).needed||e.force)&&d.push(u);}let g=d.filter(c=>c.auto),m=d.filter(c=>!c.auto);if(e.list){Me(a,r,e);return}if(e.quiet){if(g.length===0)return;let c=await E(t,g,e,a);return _(t,a),c}let S=C(t);if(console.log(s.blue(`
52
52
  \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510`)),console.log(s.blue("\u2502")+s.white.bold(" paradigm migrate ")+s.blue("\u2502")),console.log(s.blue("\u2502")+s.gray(" Bring your project up to date ")+s.blue("\u2502")),console.log(s.blue(`\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518
53
53
  `)),console.log(s.white(` Project: ${s.cyan(p.basename(t))}`)),console.log(s.white(` Config version: ${s.cyan(r.configVersion)}`)),console.log(s.white(` CLI version: ${s.cyan(r.cliVersion)}`)),console.log(s.white(` Last migrated: ${s.cyan(S?.lastMigrated??"never")}`)),console.log(""),d.length===0){console.log(s.green(` All migrations are up to date.
54
54
  `)),S||(_(t,a),e.verbose&&console.log(s.gray(` Created .paradigm/migrate.yaml with bootstrap state.
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import {a,b}from'./chunk-L6K5HNDL.js';import'./chunk-TYWB5IQJ.js';import'./chunk-WESTEMIM.js';import'./chunk-FYDRENK7.js';import'./chunk-IZSBGW6E.js';import {e as e$1}from'./chunk-AO7ZSRME.js';import'./chunk-NW6OKHE6.js';import {d,c}from'./chunk-EKZDFEJW.js';import'./chunk-T6IDXUUA.js';import'./chunk-JIXHEBGK.js';import'./chunk-QT2LKB3P.js';import'./chunk-5TAVYPOV.js';import*as S from'path';import e from'chalk';import O from'ora';async function I(o,n,t){let i=n?S.resolve(n):process.cwd();if(!o){t.json?console.log(JSON.stringify({error:"Task is required"})):(console.log(e.red(`
2
+ import {a,b}from'./chunk-DG236EXP.js';import'./chunk-TYWB5IQJ.js';import'./chunk-WESTEMIM.js';import'./chunk-FYDRENK7.js';import'./chunk-IZSBGW6E.js';import {e as e$1}from'./chunk-AO7ZSRME.js';import'./chunk-SHD27BQX.js';import {d,c}from'./chunk-EKZDFEJW.js';import'./chunk-T6IDXUUA.js';import'./chunk-JIXHEBGK.js';import'./chunk-QT2LKB3P.js';import'./chunk-5TAVYPOV.js';import*as S from'path';import e from'chalk';import O from'ora';async function I(o,n,t){let i=n?S.resolve(n):process.cwd();if(!o){t.json?console.log(JSON.stringify({error:"Task is required"})):(console.log(e.red(`
3
3
  Task is required.`)),console.log(e.gray(`Example: paradigm team orchestrate "Build @payment-system with Stripe"
4
4
  `)));return}if(!e$1(i)){t.json?console.log(JSON.stringify({error:"Team not configured"})):console.log(e.yellow("\nTeam not configured. Run `paradigm team init` first.\n"));return}let f="faceted";t.solo&&(f="solo"),t.faceted&&(f="faceted");let g;if(t.budget){let s=t.budget.split(",");g={};for(let l of s){let[a,r]=l.split("=");a==="tokens"&&(g.maxTokens=parseInt(r)),a==="cost"&&(g.maxCostUsd=parseFloat(r)),a==="warn"&&(g.warnAtPercent=parseInt(r));}}let c=O({text:"Initializing orchestrator...",isSilent:t.quiet||t.json}).start(),y=new a(i);try{await y.initialize();}catch(s){c.fail("Failed to initialize orchestrator"),t.json?console.log(JSON.stringify({error:s instanceof Error?s.message:String(s)})):console.log(e.red(`
5
5
  Error: ${s instanceof Error?s.message:s}
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import {d,e}from'./chunk-NW6OKHE6.js';import'./chunk-5TAVYPOV.js';import n from'chalk';async function c(l){let s=process.cwd(),e$1=await d(s);if(l.json)console.log(JSON.stringify({status:e$1.status,declaredButUnusedCount:e$1.declaredButUnused.length,usedButUndeclaredCount:e$1.usedButUndeclared.length,properlyDeclaredCount:e$1.properlyDeclared.length,declaredButUnused:e$1.declaredButUnused,usedButUndeclared:e$1.usedButUndeclared,properlyDeclared:e$1.properlyDeclared}));else {let o=e(e$1);e$1.status==="compliant"?console.log(n.green(`
2
+ import {d,e}from'./chunk-SHD27BQX.js';import'./chunk-5TAVYPOV.js';import n from'chalk';async function c(l){let s=process.cwd(),e$1=await d(s);if(l.json)console.log(JSON.stringify({status:e$1.status,declaredButUnusedCount:e$1.declaredButUnused.length,usedButUndeclaredCount:e$1.usedButUndeclared.length,properlyDeclaredCount:e$1.properlyDeclared.length,declaredButUnused:e$1.declaredButUnused,usedButUndeclared:e$1.usedButUndeclared,properlyDeclared:e$1.properlyDeclared}));else {let o=e(e$1);e$1.status==="compliant"?console.log(n.green(`
3
3
  ${o}
4
4
  `)):e$1.status==="warnings"?console.log(n.yellow(`
5
5
  ${o}
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- export{d as checkPortalCompliance,b as extractDeclaredGates,c as findGateReferences,e as formatComplianceReport,f as getComplianceSummary,a as loadPortalConfig}from'./chunk-NW6OKHE6.js';import'./chunk-5TAVYPOV.js';
2
+ export{d as checkPortalCompliance,b as extractDeclaredGates,c as findGateReferences,e as formatComplianceReport,f as getComplianceSummary,a as loadPortalConfig}from'./chunk-SHD27BQX.js';import'./chunk-5TAVYPOV.js';
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import {b}from'./chunk-NXRVR37G.js';import'./chunk-L6K5HNDL.js';import'./chunk-TYWB5IQJ.js';import'./chunk-WESTEMIM.js';import'./chunk-FYDRENK7.js';import'./chunk-IZSBGW6E.js';import {d as d$2}from'./chunk-AO7ZSRME.js';import'./chunk-Y4XFVDZC.js';import {a as a$5}from'./chunk-Z2UZUCY6.js';import {d as d$1}from'./chunk-W5IWDW4Y.js';import {a as a$3,b as b$1}from'./chunk-AGVAHVUA.js';import'./chunk-NW6OKHE6.js';import {a as a$6}from'./chunk-RVRARWSY.js';import'./chunk-EKZDFEJW.js';import {a as a$1}from'./chunk-33LKBMVK.js';import {b as b$2}from'./chunk-JBDMCRPP.js';import'./chunk-4TXOVRWD.js';import'./chunk-T6IDXUUA.js';import'./chunk-JIXHEBGK.js';import'./chunk-QT2LKB3P.js';import'./chunk-VCKKJDLP.js';import'./chunk-WR6D3SC6.js';import {a as a$2}from'./chunk-UIKLE3WD.js';import {a as a$4}from'./chunk-QNZEG7IT.js';import'./chunk-HMQ5BHP2.js';import'./chunk-JQKKVAAN.js';import {a}from'./chunk-LKAT7IAK.js';import'./chunk-5TAVYPOV.js';import*as r from'fs';import*as n from'path';import e from'chalk';import U from'ora';import*as d from'js-yaml';async function te(l={}){let s=process.cwd(),h=n.basename(s),u=n.join(s,".paradigm"),k=r.existsSync(u)&&r.statSync(u).isDirectory();console.log(e.blue(`
2
+ import {b}from'./chunk-VPMJWJ5R.js';import'./chunk-DG236EXP.js';import'./chunk-TYWB5IQJ.js';import'./chunk-WESTEMIM.js';import'./chunk-FYDRENK7.js';import'./chunk-IZSBGW6E.js';import {d as d$2}from'./chunk-AO7ZSRME.js';import'./chunk-Y4XFVDZC.js';import {a as a$5}from'./chunk-SWFC4HD7.js';import {d as d$1}from'./chunk-W5IWDW4Y.js';import {a as a$3,b as b$1}from'./chunk-AGVAHVUA.js';import'./chunk-SHD27BQX.js';import {a as a$6}from'./chunk-UONPO7SC.js';import'./chunk-EKZDFEJW.js';import {a as a$1}from'./chunk-33LKBMVK.js';import {b as b$2}from'./chunk-JBDMCRPP.js';import'./chunk-4TXOVRWD.js';import'./chunk-T6IDXUUA.js';import'./chunk-JIXHEBGK.js';import'./chunk-QT2LKB3P.js';import'./chunk-VCKKJDLP.js';import'./chunk-WR6D3SC6.js';import {a as a$2}from'./chunk-UIKLE3WD.js';import {a as a$4}from'./chunk-QNZEG7IT.js';import'./chunk-HMQ5BHP2.js';import'./chunk-JQKKVAAN.js';import {a}from'./chunk-LKAT7IAK.js';import'./chunk-5TAVYPOV.js';import*as r from'fs';import*as n from'path';import e from'chalk';import U from'ora';import*as d from'js-yaml';async function te(l={}){let s=process.cwd(),h=n.basename(s),u=n.join(s,".paradigm"),k=r.existsSync(u)&&r.statSync(u).isDirectory();console.log(e.blue(`
3
3
  \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510`)),console.log(e.blue("\u2502")+e.white.bold(" paradigm shift ")+e.blue("\u2502")),console.log(e.blue("\u2502")+e.gray(" Full project setup in one command ")+e.blue("\u2502")),console.log(e.blue(`\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518
4
4
  `)),console.log(e.white(` \u{1F4C1} Project: ${e.cyan(h)}`)),console.log(e.white(` \u{1F4CD} Status: ${k?e.green("Paradigm detected"):e.yellow("New project")}`)),console.log("");let j=a.command("shift").start("Running paradigm shift",{project:h}),i=U();if(!k||l.force){i.start("Step 1/6: Initializing Paradigm...");try{await a$1({force:l.force,quick:!0,name:h,stack:l.stack}),i.succeed(e.green("Paradigm initialized"));}catch(t){i.fail(e.red(`Init failed: ${t.message}`)),j.error("Shift failed at init",{error:t.message});return}}else {i.succeed(e.gray("Step 1/6: Already initialized (use --force to reinit)"));let t=n.join(u,"config.yaml");if(r.existsSync(t))try{let o=r.readFileSync(t,"utf8"),a=d.load(o);if(!a.discipline||a.discipline==="auto"){let c=a$2(s);if(c!=="backend"){let f=o.replace(/^discipline:\s*auto\b.*$/m,`discipline: ${c}`);f!==o&&(r.writeFileSync(t,f,"utf8"),console.log(e.green(` \u2713 Detected discipline: ${e.cyan(c)} (updated config.yaml)`)));}else if(!a.discipline){let f=o.replace(/^(project:\s*.+)$/m,`$1
5
- discipline: ${c}`);f!==o&&(r.writeFileSync(t,f,"utf8"),console.log(e.green(` \u2713 Added discipline: ${e.cyan(c)} to config.yaml`)));}}}catch(o){a.operation("shift").debug("Discipline detection failed",{error:o.message});}}if(k){i.start("Step 1b/6: Checking for migrations...");try{let{migrateCommand:t}=await import('./migrate-X5OMAFAQ.js');await t({apply:!0,quiet:!0,noSync:!0}),i.succeed(e.green("Migrations applied"));}catch(t){i.warn(e.yellow(`Migration warning: ${t.message}`));}}{let t=n.join(u,"config.yaml");if(l.workspace&&r.existsSync(t)){let o=l.workspacePath?n.resolve(s,l.workspacePath):n.join(n.dirname(s),".paradigm-workspace");if(r.existsSync(o))try{let a=d.load(r.readFileSync(o,"utf8")),c=n.basename(s),f=n.dirname(o),g="./"+n.relative(f,s);if(a.members.some(y=>n.resolve(f,y.path)===s))console.log(e.green(` \u2713 Already a member of workspace: ${e.cyan(a.name)}`));else {let y=d$1(c,s);a.members.push({name:c,path:g,...y&&{role:y}}),r.writeFileSync(o,d.dump(a,{indent:2,lineWidth:120,noRefs:!0,sortKeys:!1,quotingType:'"'}),"utf8"),console.log(e.green(` \u2713 Joined workspace: ${e.cyan(a.name)} (added as member)`));}}catch(a){console.log(e.yellow(` \u26A0 Failed to join workspace: ${a.message}`));}else try{let a=n.basename(s),c=n.dirname(o),f="./"+n.relative(c,s),g=d$1(a,s),p={version:"1.0",name:l.workspace,members:[{name:a,path:f,...g&&{role:g}}]};r.mkdirSync(n.dirname(o),{recursive:!0}),r.writeFileSync(o,d.dump(p,{indent:2,lineWidth:120,noRefs:!0,sortKeys:!1,quotingType:'"'}),"utf8"),console.log(e.green(` \u2713 Created workspace: ${e.cyan(l.workspace)} at ${e.gray(n.relative(s,o))}`));}catch(a){console.log(e.yellow(` \u26A0 Failed to create workspace: ${a.message}`));}try{let a=r.readFileSync(t,"utf8"),c=d.load(a),f=n.relative(s,o);if(c.workspace!==f){if(c.workspace){let g=a.replace(/^workspace:\s*.*$/m,`workspace: "${f}"`);r.writeFileSync(t,g,"utf8");}else {let g=a.trimEnd()+`
5
+ discipline: ${c}`);f!==o&&(r.writeFileSync(t,f,"utf8"),console.log(e.green(` \u2713 Added discipline: ${e.cyan(c)} to config.yaml`)));}}}catch(o){a.operation("shift").debug("Discipline detection failed",{error:o.message});}}if(k){i.start("Step 1b/6: Checking for migrations...");try{let{migrateCommand:t}=await import('./migrate-ZLITTMVW.js');await t({apply:!0,quiet:!0,noSync:!0}),i.succeed(e.green("Migrations applied"));}catch(t){i.warn(e.yellow(`Migration warning: ${t.message}`));}}{let t=n.join(u,"config.yaml");if(l.workspace&&r.existsSync(t)){let o=l.workspacePath?n.resolve(s,l.workspacePath):n.join(n.dirname(s),".paradigm-workspace");if(r.existsSync(o))try{let a=d.load(r.readFileSync(o,"utf8")),c=n.basename(s),f=n.dirname(o),g="./"+n.relative(f,s);if(a.members.some(y=>n.resolve(f,y.path)===s))console.log(e.green(` \u2713 Already a member of workspace: ${e.cyan(a.name)}`));else {let y=d$1(c,s);a.members.push({name:c,path:g,...y&&{role:y}}),r.writeFileSync(o,d.dump(a,{indent:2,lineWidth:120,noRefs:!0,sortKeys:!1,quotingType:'"'}),"utf8"),console.log(e.green(` \u2713 Joined workspace: ${e.cyan(a.name)} (added as member)`));}}catch(a){console.log(e.yellow(` \u26A0 Failed to join workspace: ${a.message}`));}else try{let a=n.basename(s),c=n.dirname(o),f="./"+n.relative(c,s),g=d$1(a,s),p={version:"1.0",name:l.workspace,members:[{name:a,path:f,...g&&{role:g}}]};r.mkdirSync(n.dirname(o),{recursive:!0}),r.writeFileSync(o,d.dump(p,{indent:2,lineWidth:120,noRefs:!0,sortKeys:!1,quotingType:'"'}),"utf8"),console.log(e.green(` \u2713 Created workspace: ${e.cyan(l.workspace)} at ${e.gray(n.relative(s,o))}`));}catch(a){console.log(e.yellow(` \u26A0 Failed to create workspace: ${a.message}`));}try{let a=r.readFileSync(t,"utf8"),c=d.load(a),f=n.relative(s,o);if(c.workspace!==f){if(c.workspace){let g=a.replace(/^workspace:\s*.*$/m,`workspace: "${f}"`);r.writeFileSync(t,g,"utf8");}else {let g=a.trimEnd()+`
6
6
  workspace: "${f}"
7
7
  `;r.writeFileSync(t,g,"utf8");}console.log(e.green(" \u2713 Linked workspace in config.yaml"));}}catch(a$1){a.operation("shift").debug("Workspace config link failed",{error:a$1.message});}}else if(r.existsSync(t))try{let o=r.readFileSync(t,"utf8");if(!d.load(o).workspace){let c=n.dirname(s);for(let f=0;f<3;f++){let g=n.join(c,".paradigm-workspace");if(r.existsSync(g)){let y=n.relative(s,g),N=o.trimEnd()+`
8
8
  workspace: "${y}"
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- export{e as teamAcceptCommand,f as teamCheckCommand,d as teamHandoffCommand,g as teamHistoryCommand,b as teamInitCommand,a as teamModelsCommand,h as teamResetCommand,c as teamStatusCommand}from'./chunk-NXRVR37G.js';import'./chunk-L6K5HNDL.js';import'./chunk-TYWB5IQJ.js';import'./chunk-WESTEMIM.js';import'./chunk-FYDRENK7.js';import'./chunk-IZSBGW6E.js';import'./chunk-AO7ZSRME.js';import'./chunk-Y4XFVDZC.js';import'./chunk-NW6OKHE6.js';import'./chunk-EKZDFEJW.js';import'./chunk-T6IDXUUA.js';import'./chunk-JIXHEBGK.js';import'./chunk-QT2LKB3P.js';import'./chunk-5TAVYPOV.js';
2
+ export{e as teamAcceptCommand,f as teamCheckCommand,d as teamHandoffCommand,g as teamHistoryCommand,b as teamInitCommand,a as teamModelsCommand,h as teamResetCommand,c as teamStatusCommand}from'./chunk-VPMJWJ5R.js';import'./chunk-DG236EXP.js';import'./chunk-TYWB5IQJ.js';import'./chunk-WESTEMIM.js';import'./chunk-FYDRENK7.js';import'./chunk-IZSBGW6E.js';import'./chunk-AO7ZSRME.js';import'./chunk-Y4XFVDZC.js';import'./chunk-SHD27BQX.js';import'./chunk-EKZDFEJW.js';import'./chunk-T6IDXUUA.js';import'./chunk-JIXHEBGK.js';import'./chunk-QT2LKB3P.js';import'./chunk-5TAVYPOV.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@a-company/paradigm",
3
- "version": "5.21.0",
3
+ "version": "5.21.2",
4
4
  "description": "Unified CLI for Paradigm developer tools",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env node
2
- import*as y from'fs';import*as h from'path';import*as R from'js-yaml';import {execFileSync}from'child_process';var A=["node_modules",".git","dist","build","coverage",".paradigm","vendor","__pycache__",".next","target"];function S(e){let t=h.join(e,"portal.yaml");if(!y.existsSync(t))return null;try{let n=y.readFileSync(t,"utf-8");return R.load(n)}catch{return null}}function B(e){let t=new Set;if(e.gates)for(let n of Object.keys(e.gates)){let s=n.startsWith("^")?n.slice(1):n;t.add(s);}if(e.routes)for(let n of Object.values(e.routes)){let s=Array.isArray(n)?n:n.gates||[];for(let r of s){let a=r.startsWith("^")?r.slice(1):r;t.add(a);}}return Array.from(t)}function P(e){let t=new Set;if(e.routes)for(let n of Object.values(e.routes)){let s=Array.isArray(n)?n:n.gates||[];for(let r of s){let a=r.startsWith("^")?r.slice(1):r;t.add(a);}}return t}function x(e,t){let n={encoding:"utf-8",maxBuffer:10485760,stdio:["ignore","pipe","pipe"]};try{let i=["-n","--no-ignore-vcs",...A.flatMap(l=>["--glob",`!${l}/**`]),"--engine","auto",t,e];return execFileSync("rg",i,n)}catch{}let r=["-rn",...A.map(a=>`--exclude-dir=${a}`),"-E",t,"--",e];try{return execFileSync("grep",r,n)}catch(a){return a?.code===1||a?.status===1,""}}function $(e){let t=[],s=x(e,"\\^[a-zA-Z][a-zA-Z0-9_-]+");for(let a of s.split(`
3
- `).filter(Boolean)){let i=a.match(/^(.+?):(\d+):(.*)$/);if(i){let[,l,d,u]=i,g=u.match(/\^([a-zA-Z][a-zA-Z0-9_-]+)/);g&&t.push({gate:g[1],file:h.relative(e,l),line:parseInt(d,10),context:u.trim().slice(0,100),matchType:"symbol"});}}let r=[{pattern:`checkGate\\s*\\(['"]([^'"]+)['"]`,type:"function"},{pattern:`requireGate\\s*\\(['"]([^'"]+)['"]`,type:"function"},{pattern:`gate:\\s*['"]([^'"]+)['"]`,type:"config"},{pattern:`@Gate\\s*\\(['"]?([^'"\\)]+)['"]?\\)`,type:"function"}];for(let{pattern:a,type:i}of r){let l=x(e,a);for(let d of l.split(`
4
- `).filter(Boolean)){let u=d.match(/^(.+?):(\d+):(.*)$/);if(u){let[,g,f,m]=u,c=m.match(new RegExp(a));if(c&&c[1]){let p=c[1].startsWith("^")?c[1].slice(1):c[1];t.push({gate:p,file:h.relative(e,g),line:parseInt(f,10),context:m.trim().slice(0,100),matchType:i});}}}}return t}function b(e){return [...new Set(e.map(t=>t.gate))]}async function w(e){let t=S(e);if(!t){let o=$(e),U=b(o);return U.length===0?{status:"compliant",declaredButUnused:[],routeAttachedUnused:[],orphanUnused:[],usedButUndeclared:[],properlyDeclared:[],suggestions:["No portal.yaml found, and no gate references detected in code."],references:[]}:{status:"violations",declaredButUnused:[],routeAttachedUnused:[],orphanUnused:[],usedButUndeclared:U,properlyDeclared:[],suggestions:["Gate references found in code but no portal.yaml exists.","Create a portal.yaml file to declare these gates:",...U.map(C=>` - ^${C}`),"","Run: paradigm portal init"],references:o}}let n=B(t),s=P(t),r=$(e),a=b(r),i=new Set(n),l=new Set(a),d=n.filter(o=>!l.has(o)),u=d.filter(o=>s.has(o)),g=d.filter(o=>!s.has(o)),f=a.filter(o=>!i.has(o)),m=n.filter(o=>l.has(o)),c=[];if(u.length>0){c.push("Gates documented on routes but no checkGate/requireGate in code:");for(let o of u)c.push(` - ^${o} (documented on routes; if enforced by middleware, this may be intentional)`);c.push("");}if(g.length>0){c.push("Orphan gates (declared but never on a route or in code):");for(let o of g)c.push(` - ^${o} (add to a route or remove from portal.yaml)`);c.push("");}if(f.length>0){c.push("Gates used in code but not declared in portal.yaml:");for(let o of f)c.push(` - ^${o} (add to portal.yaml with proper definition)`);c.push("");}let p="compliant";return f.length>0?p="violations":d.length>0&&(p="warnings"),{status:p,declaredButUnused:d,routeAttachedUnused:u,orphanUnused:g,usedButUndeclared:f,properlyDeclared:m,suggestions:c,references:r}}function k(e){let t=[],n=e.status==="compliant"?"\u2713":e.status==="warnings"?"\u26A0":"\u2717";if(t.push(`Portal Compliance: ${n} ${e.status.toUpperCase()}`),t.push(""),t.push(`Properly Declared: ${e.properlyDeclared.length}`),e.routeAttachedUnused.length>0&&t.push(`Route-Attached, No Code: ${e.routeAttachedUnused.length}`),e.orphanUnused.length>0&&t.push(`Orphan Gates: ${e.orphanUnused.length}`),e.usedButUndeclared.length>0&&t.push(`Used but Undeclared: ${e.usedButUndeclared.length}`),t.push(""),e.properlyDeclared.length>0){t.push("Gates in Use:");for(let s of e.properlyDeclared)t.push(` \u2713 ^${s}`);t.push("");}if(e.routeAttachedUnused.length>0){t.push("Route-Attached (no checkGate/requireGate in code):");for(let s of e.routeAttachedUnused)t.push(` \u26A0 ^${s}`);t.push("");}if(e.orphanUnused.length>0){t.push("Orphan Gates (declared but never on route or in code):");for(let s of e.orphanUnused)t.push(` \u26A0 ^${s}`);t.push("");}if(e.usedButUndeclared.length>0){t.push("Undeclared Gates (used but not in portal.yaml):");for(let s of e.usedButUndeclared){t.push(` \u2717 ^${s}`);let r=e.references.filter(a=>a.gate===s).slice(0,3);for(let a of r)t.push(` at ${a.file}:${a.line}`);}t.push("");}if(e.suggestions.length>0&&e.status!=="compliant"){t.push("Suggestions:");for(let s of e.suggestions)s&&t.push(` ${s}`);}return t.join(`
5
- `)}function N(e){if(e.status==="compliant")return {status:"ok",message:`${e.properlyDeclared.length} gates properly declared`};if(e.status==="warnings"){let t=[];return e.routeAttachedUnused.length>0&&t.push(`${e.routeAttachedUnused.length} route-attached`),e.orphanUnused.length>0&&t.push(`${e.orphanUnused.length} orphan`),{status:"warn",message:t.length>0?t.join(", ")+" gate(s)":`${e.declaredButUnused.length} unused gates`}}return {status:"error",message:`${e.usedButUndeclared.length} gates used but not declared`}}export{S as a,B as b,$ as c,w as d,k as e,N as f};
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- export{a as doctorCommand}from'./chunk-RVRARWSY.js';import'./chunk-HMQ5BHP2.js';import'./chunk-JQKKVAAN.js';import'./chunk-LKAT7IAK.js';import'./chunk-5TAVYPOV.js';