#!/usr/bin/env node
import {a,b,c,e,d}from'./chunk-BRHQJLTG.js';import'./chunk-XHJ27CER.js';import*as g from'fs';import*as u from'path';import {execSync}from'child_process';import o from'chalk';import*as C from'js-yaml';var $=".paradigm/habits.yaml",G=new Set(["explore-before-implement","ripple-before-modify","check-fragility","wisdom-before-implement","verify-before-done","postflight-compliance","test-new-components","purpose-coverage","record-lore-for-significant","gates-for-routes"]),x=["discovery","verification","testing","documentation","collaboration","security"],E=["preflight","postflight","on-stop","on-commit"],I=["advisory","warn","block"],P=["tool-called","file-exists","file-modified","lore-recorded","symbols-registered","gates-declared","tests-exist","git-clean"];function T(e,t){let r=u.join(e,$),i=F(r,t);if(i)return {source:"project",...i};let n=process.env.HOME||process.env.USERPROFILE||"~",l=u.join(n,".paradigm","habits.yaml"),c=F(l,t);return c?{source:"global",...c}:G.has(t)?{source:"seed",filePath:"",index:-1}:null}function F(e,t){if(!g.existsSync(e))return null;try{let r=g.readFileSync(e,"utf8"),i=C.load(r);if(!i?.habits)return null;let n=i.habits.findIndex(l=>l.id===t);return n===-1?null:{filePath:e,index:n}}catch{return null}}function D(e){let t=g.readFileSync(e,"utf8"),r=C.load(t);return r.habits||(r.habits=[]),r.overrides||(r.overrides={}),r}function w(e,t){g.writeFileSync(e,C.dump(t,{lineWidth:80,noRefs:true}),"utf8");}function L(e){let t=u.join(e,$);if(!g.existsSync(t)){let r=u.dirname(t);g.existsSync(r)||g.mkdirSync(r,{recursive:true}),w(t,{version:"1.0",habits:[],overrides:{}});}return t}async function J(e){let t=process.cwd(),r;try{r=a(t);}catch(s){console.log(o.red("Failed to load habits:"),s.message);return}if(e.trigger&&(r=r.filter(s=>s.trigger===e.trigger)),e.category&&(r=r.filter(s=>s.category===e.category)),e.json){console.log(JSON.stringify(r,null,2));return}let i=r.filter(s=>s.enabled),n=r.filter(s=>!s.enabled);console.log(o.magenta(`
  Habits (${i.length} active, ${n.length} disabled)
`));let l=["preflight","postflight","on-stop","on-commit"];for(let s of l){let y=r.filter(d=>d.trigger===s);if(y.length!==0){console.log(o.cyan(`  ${s}:`));for(let d of y){let a=d.enabled?o.green("ON"):o.gray("OFF"),m=d.severity==="block"?o.red(d.severity):d.severity==="warn"?o.yellow(d.severity):o.gray(d.severity);console.log(`    ${a} ${o.white(d.id)} [${m}] - ${d.name}`),console.log(o.gray(`       ${d.description}`));}console.log();}}let c=u.join(t,$);g.existsSync(c)?console.log(o.gray(`  Config: ${$}`)):console.log(o.gray("  Config: using seed habits only (run 'paradigm habits init' to customize)")),console.log();}async function W(e){let t=process.cwd(),r;try{r=a(t);}catch(c){console.log(o.red("Failed to load habits:"),c.message);return}let i=b(r),n=null;try{let{SentinelStorage:c}=await import('./dist-OKM6BXTH.js'),s=u.join(t,".paradigm","sentinel");if(g.existsSync(s)){let y=new c(s),d=e.period||"30d",a=parseInt(d.replace("d",""),10)||30,m=d==="all"?void 0:new Date(Date.now()-a*24*60*60*1e3).toISOString(),v=y.getComplianceRate({dateFrom:m}),f=y.getPracticeEvents({dateFrom:m,limit:500}),b=new Map;for(let h of f){let p=h.habitCategory,S=b.get(p)||{followed:0,skipped:0,partial:0};S[h.result]++,b.set(p,S);}let j=Array.from(b.entries()).map(([h,p])=>{let S=p.followed+p.skipped+p.partial,O=S>0?Math.round((p.followed+p.partial*.5)/S*100):100;return {category:h,rate:O,total:S}}).sort((h,p)=>h.rate-p.rate);n={total:v.total,followed:v.followed,skipped:v.skipped,partial:v.partial,rate:v.rate,byCategory:j};}}catch{}if(e.json){console.log(JSON.stringify({habits:{total:r.length,enabled:i.length},practice:n},null,2));return}console.log(o.magenta(`
  Habits Practice Profile
`)),console.log(o.white(`  Total habits: ${r.length} (${i.length} active)`));let l=new Map;for(let c of i)l.set(c.trigger,(l.get(c.trigger)||0)+1);for(let[c,s]of l)console.log(o.gray(`    ${c}: ${s} habit(s)`));if(console.log(),n&&n.total>0){let c=n.rate>=80?o.green:n.rate>=60?o.yellow:o.red;if(console.log(o.white(`  Compliance Rate: ${c(`${n.rate}%`)}`)),console.log(o.gray(`    Followed: ${n.followed} | Skipped: ${n.skipped} | Partial: ${n.partial}`)),console.log(o.gray(`    Total events: ${n.total}
`)),n.byCategory.length>0){console.log(o.white("  By Category:"));for(let s of n.byCategory){let y=s.rate>=80?o.green:s.rate>=60?o.yellow:o.red,d="\u2588".repeat(Math.round(s.rate/5))+"\u2591".repeat(20-Math.round(s.rate/5));console.log(`    ${s.category.padEnd(15)} ${y(d)} ${y(`${s.rate}%`)} (${s.total})`);}}}else console.log(o.gray("  No practice events recorded yet.")),console.log(o.gray(`  Call paradigm_habits_check via MCP to start recording.
`));console.log();}async function Y(e){let t=process.cwd(),r=u.join(t,$);if(g.existsSync(r)&&!e.force){console.log(o.yellow(`${$} already exists. Use --force to overwrite.`));return}let i=u.dirname(r);g.existsSync(i)||g.mkdirSync(i,{recursive:true});let l=`# Paradigm Habits Configuration
# See: paradigm habits list (for all seed habits)
#
# Seed habits are built-in and active by default.
# Use 'overrides' to tune severity or disable specific habits.
# Add custom habits in the 'habits' section.

${C.dump({version:"1.0",habits:[],overrides:{"verify-before-done":{severity:"warn"}}},{lineWidth:80,noRefs:true})}
# Example custom habit:
# habits:
#   - id: my-custom-check
#     name: "Custom Check"
#     description: "Describe what this habit enforces"
#     category: verification
#     trigger: postflight
#     severity: advisory
#     check:
#       type: tool-called
#       params:
#         tools: [paradigm_pm_postflight]
#     enabled: true
#
# Override seed habits:
# overrides:
#   verify-before-done:
#     severity: block      # Upgrade to blocking
#   check-fragility:
#     enabled: false        # Disable this habit
`;g.writeFileSync(r,l,"utf8"),c(t),console.log(o.green(`Created ${$}`)),console.log(o.gray("  10 seed habits are active by default.")),console.log(o.gray("  Use overrides section to tune severity or disable habits.")),console.log(o.gray("  Run `paradigm habits list` to see all habits.\n"));}async function q(e){let t=process.cwd(),r=u.join(t,$);if(!g.existsSync(r)){console.log(o.yellow(`No ${$} found. Run 'paradigm habits init' first.`));return}if(!x.includes(e.category)){console.log(o.red(`Invalid category: ${e.category}. Valid: ${x.join(", ")}`));return}if(!E.includes(e.trigger)){console.log(o.red(`Invalid trigger: ${e.trigger}. Valid: ${E.join(", ")}`));return}if(e.severity&&!I.includes(e.severity)){console.log(o.red(`Invalid severity: ${e.severity}. Valid: ${I.join(", ")}`));return}let i=e.checkType||"tool-called";if(!P.includes(i)){console.log(o.red(`Invalid check-type: ${i}. Valid: ${P.join(", ")}`));return}let n;try{let a=g.readFileSync(r,"utf8");n=C.load(a),n.habits||(n.habits=[]);}catch(a){console.log(o.red("Failed to parse habits.yaml:"),a.message);return}if(new Set([...n.habits.map(a=>a.id),...a(t).map(a=>a.id)]).has(e.id)){console.log(o.yellow(`Habit "${e.id}" already exists.`));return}let c$1=e.tools?e.tools.split(",").map(a=>a.trim()):[],s=e.patterns?e.patterns.split(",").map(a=>a.trim()):[],y={};i==="tool-called"&&c$1.length>0&&(y.tools=c$1),(i==="file-exists"||i==="file-modified"||i==="tests-exist")&&s.length>0&&(y.patterns=s);let d={id:e.id,name:e.name,description:e.description,category:e.category,trigger:e.trigger,severity:e.severity||"advisory",check:{type:i,params:y},enabled:true};n.habits.push(d),w(r,n),c(t),console.log(o.green(`Added habit: ${e.id}`)),console.log(o.gray(`  Name: ${e.name}`)),console.log(o.gray(`  Category: ${e.category} | Trigger: ${e.trigger} | Severity: ${e.severity||"advisory"}`)),console.log(o.gray(`  Check: ${i}`)),c$1.length>0&&console.log(o.gray(`  Tools: ${c$1.join(", ")}`)),s.length>0&&console.log(o.gray(`  Patterns: ${s.join(", ")}`)),console.log();}async function z(e,t){let r=process.cwd();if(t.category&&!x.includes(t.category)){console.log(o.red(`Invalid category: ${t.category}. Valid: ${x.join(", ")}`));return}if(t.trigger&&!E.includes(t.trigger)){console.log(o.red(`Invalid trigger: ${t.trigger}. Valid: ${E.join(", ")}`));return}if(t.severity&&!I.includes(t.severity)){console.log(o.red(`Invalid severity: ${t.severity}. Valid: ${I.join(", ")}`));return}if(t.checkType&&!P.includes(t.checkType)){console.log(o.red(`Invalid check-type: ${t.checkType}. Valid: ${P.join(", ")}`));return}let i=T(r,e);if(!i){console.log(o.red(`Habit not found: ${e}`));return}if(i.source==="seed"){if(["name","description","category","trigger","checkType","patterns","tools"].some(m=>t[m]!==void 0)){console.log(o.yellow(`"${e}" is a seed habit. Only --severity and --enabled can be changed.`)),console.log(o.gray("  Other fields require creating a custom habit with the same functionality."));return}if(!t.severity&&t.enabled===void 0){console.log(o.yellow("No changes specified. Use --severity or --enabled for seed habits."));return}let d=L(r),a=D(d);a.overrides||(a.overrides={}),a.overrides[e]||(a.overrides[e]={}),t.severity&&(a.overrides[e].severity=t.severity),t.enabled!==void 0&&(a.overrides[e].enabled=t.enabled==="true"),w(d,a),c(r),console.log(o.green(`Updated seed habit override: ${e}`)),t.severity&&console.log(o.gray(`  Severity: ${t.severity}`)),t.enabled!==void 0&&console.log(o.gray(`  Enabled: ${t.enabled}`)),console.log();return}let n=D(i.filePath),l=n.habits[i.index];t.name&&(l.name=t.name),t.description&&(l.description=t.description),t.category&&(l.category=t.category),t.trigger&&(l.trigger=t.trigger),t.severity&&(l.severity=t.severity),t.enabled!==void 0&&(l.enabled=t.enabled==="true"),t.checkType&&(l.check.type=t.checkType),t.tools&&(l.check.params.tools=t.tools.split(",").map(s=>s.trim())),t.patterns&&(l.check.params.patterns=t.patterns.split(",").map(s=>s.trim())),n.habits[i.index]=l,w(i.filePath,n),c(r);let c$1=i.source==="global"?"(global)":"(project)";console.log(o.green(`Updated habit: ${e} ${o.gray(c$1)}`)),console.log();}async function Q(e,t){let r=process.cwd(),i=T(r,e);if(!i){console.log(o.red(`Habit not found: ${e}`));return}if(i.source==="seed"){console.log(o.yellow(`"${e}" is a seed habit and cannot be removed.`)),console.log(o.gray(`  Use: paradigm habits edit ${e} --enabled false`));return}let n=D(i.filePath),l=n.habits[i.index];if(!t.yes){console.log(o.yellow(`
Will remove habit: ${l.name} (${e})`)),console.log(o.gray(`  Source: ${i.source} (${i.filePath})`)),console.log(o.gray(`  Use --yes to confirm.
`));return}n.habits.splice(i.index,1),w(i.filePath,n),c(r),console.log(o.green(`Removed habit: ${e}`)),console.log();}async function X(e,t){let r=process.cwd(),i=t==="enable",n=T(r,e);if(!n){console.log(o.red(`Habit not found: ${e}`));return}if(n.source==="seed"){let c$1=L(r),s=D(c$1);s.overrides||(s.overrides={}),s.overrides[e]||(s.overrides[e]={}),s.overrides[e].enabled=i,w(c$1,s),c(r),console.log(o.green(`${i?"Enabled":"Disabled"} seed habit: ${e}`)),console.log();return}let l=D(n.filePath);l.habits[n.index].enabled=i,w(n.filePath,l),c(r),console.log(o.green(`${i?"Enabled":"Disabled"} habit: ${e}`)),console.log();}async function Z(e$1){let t=process.cwd(),r=e$1.trigger,i;try{i=a(t);}catch(f){console.log(o.red("Failed to load habits:"),f.message),process.exitCode=1;return}let n=e$1.files?e$1.files.split(",").map(f=>f.trim()).filter(Boolean):N(t),l=e$1.symbols?e$1.symbols.split(",").map(f=>f.trim()).filter(Boolean):[],c;try{c=execSync("git status --porcelain",{cwd:t,encoding:"utf8",timeout:5e3}).trim()==="";}catch{}let s=u.join(t,"portal.yaml"),y=false;if(g.existsSync(s))try{let f=g.readFileSync(s,"utf8"),b=C.load(f);y=b?.routes!=null&&Object.keys(b.routes).length>0;}catch{}let d$1=e({toolsCalled:[],filesModified:n,symbolsTouched:l,loreRecorded:false,hasPortalRoutes:y,taskAddsRoutes:false,gitClean:c}),a$1=d(i,r,d$1),m=0;if(e$1.record&&a$1.evaluations.length>0)try{let f=u.join(t,".paradigm","sentinel");if(g.existsSync(f)){let{SentinelStorage:b}=await import('./dist-OKM6BXTH.js'),j=new b(f);for(let h of a$1.evaluations)j.recordPracticeEvent({habitId:h.habit.id,habitCategory:h.habit.category,result:h.result,engineer:"agent",sessionId:`cli-${Date.now().toString(36)}`,symbolsTouched:l,filesModified:n,notes:h.reason}),m++;}}catch{}let v=u.join(t,".paradigm",".habits-blocking");try{if(r==="on-stop"&&a$1.blocksCompletion){let f=a$1.evaluations.filter(b=>b.result==="skipped"&&b.habit.severity==="block").map(b=>`${b.habit.name}: ${b.reason}`);g.writeFileSync(v,f.join(`
`),"utf8");}else r==="on-stop"&&g.existsSync(v)&&g.unlinkSync(v);}catch{}e$1.json?console.log(JSON.stringify({trigger:r,evaluation:{total:a$1.summary.total,followed:a$1.summary.followed,skipped:a$1.summary.skipped,partial:a$1.summary.partial,blockingViolations:a$1.summary.blockingViolations,blocksCompletion:a$1.blocksCompletion},habits:a$1.evaluations.map(f=>({id:f.habit.id,name:f.habit.name,category:f.habit.category,severity:f.habit.severity,result:f.result,reason:f.reason,evidence:f.evidence})),recorded:m},null,2)):U(a$1,m),a$1.blocksCompletion&&(process.exitCode=1);}function N(e){try{return execSync("git diff --name-only HEAD",{cwd:e,encoding:"utf8",timeout:5e3}).trim().split(`
`).filter(Boolean)}catch{return []}}function U(e,t){let{summary:r}=e;console.log(o.magenta(`
  Habits Check (${e.trigger})
`));for(let i of e.evaluations){let n=i.result==="followed"?o.green("PASS"):i.result==="skipped"?i.habit.severity==="block"?o.red("BLOCK"):o.yellow("SKIP"):o.gray("PART"),l=i.habit.severity==="block"?o.red(i.habit.severity):i.habit.severity==="warn"?o.yellow(i.habit.severity):o.gray(i.habit.severity);console.log(`  ${n} ${o.white(i.habit.id)} [${l}]`),console.log(o.gray(`       ${i.reason}`));}console.log(),console.log(o.white(`  Summary: ${r.followed} followed, ${r.skipped} skipped, ${r.partial} partial`)),r.blockingViolations>0&&console.log(o.red(`  ${r.blockingViolations} blocking violation(s) \u2014 exit code 1`)),t>0&&console.log(o.gray(`  Recorded ${t} practice event(s) to Sentinel`)),console.log();}export{q as habitsAddCommand,Z as habitsCheckCommand,z as habitsEditCommand,Y as habitsInitCommand,J as habitsListCommand,Q as habitsRemoveCommand,W as habitsStatusCommand,X as habitsToggleCommand};