PageSourceSearch

https://alterfo.github.io/assets/chunks/DecisionJournal.0BaYaSYS.js

js alterfo.github.io collected 2026-10-03 08:36:43 UTC 30,633 bytes, 1 lines download raw bytes

1import{v as V,b as le,c as Qe}from"../app.DKJFytgf.js";import{e as se,p as oe,u as ae,d as ue,a as ie,r as We}from"./crypto.DPRYzh5h.js";import{s as Ze,H as et}from"./onboarding.C5K28TbO.js";import{_ as tt}from"./plugin-vue_export-helper.DlAUqK2U.js";import{U as De,T as b,_ as nt,a4 as lt,o as v,c as p,b as e,t as c,ah as C,e as h,P as B,F as T,r as L,i as j,g as st,w as ot,f as U,K as at}from"./runtime-core.esm-bundler.BcSW7cUG.js";const ut="decision-journal",it=1,K="vault",Ce="envelope",pe="decisions:ping";let X=null;function Se(){return X?Promise.resolve(X):new Promise((a,o)=>{const u=indexedDB.open(ut,it);u.onupgradeneeded=i=>{const s=i.target.result;s.objectStoreNames.contains(K)||s.createObjectStore(K)},u.onsuccess=i=>{X=i.target.result,a(X)},u.onerror=i=>o(i.target.error)})}async function ce(){if(typeof indexedDB>"u")return null;try{const a=await Se();return await new Promise((o,u)=>{const s=a.transaction(K,"readonly").objectStore(K).get(Ce);s.onsuccess=d=>o(d.target.result??null),s.onerror=d=>u(d.target.error)})}catch(a){return console.warn("[decisions] loadEnvelope failed:",a),null}}let re=null;async function Ee(a){const o=await Se();return new Promise((u,i)=>{const d=o.transaction(K,"readwrite").objectStore(K).put(a,Ce);d.onsuccess=()=>u(),d.onerror=f=>i(f.target.error)})}function ct(a){typeof indexedDB>"u"||(clearTimeout(re),re=setTimeout(async()=>{try{await Ee(a);try{localStorage.setItem(pe,String(Date.now()))}catch{}}catch(o){console.warn("[decisions] saveEnvelope failed:",o)}},300))}function Oe(){clearTimeout(re)}async function dt(a,{notify:o=!1}={}){if(!(typeof indexedDB>"u")&&(await Ee(a),o))try{localStorage.setItem(pe,String(Date.now()))}catch{}}function rt(a){if(typeof window>"u")return()=>{};const o=u=>{u.key===pe&&a()};return window.addEventListener("storage",o),()=>window.removeEventListener("storage",o)}function vt(a,o="decisions"){const u=new Date().toISOString().slice(0,10),i=`${o}-${u}.decisions`,s=new Blob([a],{type:"application/octet-stream"}),d=URL.createObjectURL(s),f=document.createElement("a");f.href=d,f.download=i,document.body.appendChild(f),f.click(),document.body.removeChild(f),setTimeout(()=>URL.revokeObjectURL(d),100)}function pt(a){return a.text()}function Q(){return{version:1,decisions:{},createdAt:new Date().toISOString()}}function ft(){return crypto.randomUUID().slice(0,8)}const mt=new Set(["correct","wrong"]);function jt(a){const o=Math.round(Number(a));return Number.isFinite(o)?Math.max(0,Math.min(100,o)):50}function wt(a,o,u=new Date().toISOString()){const i=o.id||ft(),s=a.decisions[i],d={id:i,title:o.title??(s==null?void 0:s.title)??"",context:o.context??(s==null?void 0:s.context)??"",options:Array.isArray(o.options)?[...o.options]:s!=null&&s.options?[...s.options]:[],chosen:o.chosen??(s==null?void 0:s.chosen)??"",expectedOutcome:o.expectedOutcome??(s==null?void 0:s.expectedOutcome)??"",confidence:jt(o.confidence??(s==null?void 0:s.confidence)??50),reviewDate:o.reviewDate!==void 0?o.reviewDate:(s==null?void 0:s.reviewDate)??null,outcome:o.outcome!==void 0?o.outcome:(s==null?void 0:s.outcome)??null,actualOutcome:o.actualOutcome??(s==null?void 0:s.actualOutcome)??"",reviewedAt:o.reviewedAt!==void 0?o.reviewedAt:(s==null?void 0:s.reviewedAt)??null,deleted:o.deleted??(s==null?void 0:s.deleted)??!1,createdAt:s?s.createdAt:o.createdAt??u,updatedAt:u};return a.decisions[i]=d,d}function yt(a,o,u,i="",s=new Date().toISOString()){const d=a.decisions[o];return d?(d.outcome=mt.has(u)?u:null,d.actualOutcome=i??"",d.reviewedAt=s,d.updatedAt=s,d):null}function bt(a,o,u=new Date().toISOString()){const i=a.decisions[o];if(i)return i.deleted=!0,i.updatedAt=u,i}function ht(a,o){return Object.values(a.decisions).filter(u=>!u.deleted&&u.outcome==null&&u.reviewDate&&u.reviewDate<=o).sort((u,i)=>u.reviewDate<i.reviewDate?-1:u.reviewDate>i.reviewDate?1:0)}function _t(a){return Object.values(a.decisions).filter(o=>!o.deleted&&o.outcome==null).sort((o,u)=>{const i=o.reviewDate||"ï¿¿",s=u.reviewDate||"ï¿¿";return i<s?-1:i>s?1:0})}function kt(a){return Object.values(a.decisions).filter(o=>!o.deleted&&o.outcome!=null).sort((o,u)=>(u.reviewedAt||"").localeCompare(o.reviewedAt||""))}function xe(a,o){const u=a.decisions||{},i=o.decisions||{}
1,s={version:Math.max(a.version||1,o.version||1),decisions:{},createdAt:(a.createdAt||"￿")<(o.createdAt||"￿")?a.createdAt:o.createdAt},d=new Set([...Object.keys(u),...Object.keys(i)]);for(const f of d){const g=u[f],w=i[f];g?w?s.decisions[f]=(g.updatedAt||"")>=(w.updatedAt||"")?{...g}:{...w}:s.decisions[f]={...g}:s.decisions[f]={...w}}return s}const Ve=a=>a&&!a.deleted,Ae=a=>Ve(a)&&(a.outcome==="correct"||a.outcome==="wrong");function ve(a){return Number.isFinite(a.confidence)?a.confidence:50}function gt(a){return Number.isFinite(a)?Math.max(0,Math.min(1,a)):.5}function Dt(a){const o=(a||[]).filter(Ae);return o.length===0?null:o.reduce((i,s)=>{const d=gt(ve(s)/100),f=s.outcome==="correct"?1:0,g=d-f;return i+g*g},0)/o.length}function Ot(a,o=[50,60,70,80,90,101]){const u=(a||[]).filter(Ae),i=[0,...o],s=[];for(let d=0;d<i.length-1;d++){const f=i[d],g=i[d+1],w=u.filter(I=>{const A=ve(I);return A>=f&&A<g}),x=w.length,m=x?w.reduce((I,A)=>I+ve(A),0)/x:null,q=w.filter(I=>I.outcome==="correct").length,H=x?q/x:null;s.push({label:`${f}–${Math.min(g,100)}%`,n:x,avgConfidence:m,hitRate:H})}return s}function xt(a,o){const u=(a||[]).filter(Ve),i=u.filter(f=>f.outcome==null),s=u.filter(f=>f.outcome!=null),d=o?i.filter(f=>f.reviewDate&&f.reviewDate<=o):[];return{total:u.length,open:i.length,due:d.length,reviewed:s.length}}const Ct={class:"dj-root"},St={key:0,class:"dj-center"},Et={key:1,class:"dj-center"},Vt={class:"dj-lock-card"},At={class:"dj-lock-title"},It={class:"dj-lock-desc"},Ut=["placeholder","autocomplete"],Nt={class:"dj-lock-actions"},Bt=["disabled"],$t={key:1,class:"dj-error"},Rt={key:2,class:"dj-unlocked"},Mt={class:"dj-sidebar"},Tt={class:"dj-sidebar-actions"},Pt={class:"dj-queues"},Ft={key:0,class:"dj-section"},Lt={class:"dj-section-title dj-section-due"},Kt=["onClick"],qt={class:"dj-card-title"},Jt={class:"dj-card-meta"},Ht={class:"dj-card-conf"},Yt={class:"dj-card-date"},Gt={class:"dj-section"},zt={class:"dj-section-title"},Xt=["onClick"],Qt={class:"dj-card-title"},Wt={class:"dj-card-meta"},Zt={class:"dj-card-conf"},en={key:0,class:"dj-card-date"},tn={key:0,class:"dj-empty-hint"},nn={key:1,class:"dj-section"},ln=["onClick"],sn={class:"dj-card-title"},on={class:"dj-card-meta"},an={class:"dj-card-conf"},un={class:"dj-sidebar-footer"},cn={class:"dj-footer-actions"},dn={key:0,class:"dj-import-dialog"},rn={class:"dj-import-actions"},vn=["disabled"],pn={key:0,class:"dj-import-error"},fn={key:1,class:"dj-import-error"},mn={class:"dj-main"},jn={key:0,class:"dj-main-empty"},wn={key:1,class:"dj-panel"},yn={class:"dj-panel-title"},bn={class:"dj-field"},hn={class:"dj-field"},_n={class:"dj-field"},kn=["onUpdate:modelValue","placeholder"],gn=["onClick"],Dn={class:"dj-field"},On=["value"],xn={class:"dj-field"},Cn={class:"dj-field"},Sn={class:"dj-field-label"},En={class:"dj-conf-row"},Vn={class:"dj-field"},An={key:0,class:"dj-form-error"},In={class:"dj-form-actions"},Un={key:2,class:"dj-panel"},Nn={class:"dj-review-box"},Bn={class:"dj-review-row"},$n={class:"dj-review-v"},Rn={key:0,class:"dj-review-row"},Mn={class:"dj-review-v"},Tn={key:1,class:"dj-review-row"},Pn={class:"dj-review-v"},Fn={class:"dj-review-row"},Ln={class:"dj-review-v"},Kn={class:"dj-outcome-buttons"},qn={class:"dj-field"},Jn={key:0,class:"dj-form-error"},Hn={key:3,class:"dj-panel"},Yn={class:"dj-panel-title"},Gn={class:"dj-review-box"},zn={key:0,class:"dj-review-row"},Xn={class:"dj-review-v"},Qn={key:1,class:"dj-review-row"},Wn={class:"dj-review-v"},Zn={key:2,class:"dj-review-row"},el={class:"dj-review-v"},tl={class:"dj-review-row"},nl={class:"dj-review-v"},ll={class:"dj-review-row"},sl={key:3,class:"dj-review-row"},ol={class:"dj-review-v"},al={class:"dj-form-actions"},ul={key:4,class:"dj-panel"},il={class:"dj-counts"},cl={class:"dj-count"},dl={class:"dj-count-n"},rl={class:"dj-count"},vl={class:"dj-count-n"},pl={class:"dj-count"},fl={class:"dj-count-n"},ml={class:"dj-count"},jl={class:"dj-count-n"},wl={class:"dj-brier"},yl={class:"dj-brier-n"},bl={class:"dj-cal-table"},hl={class:"dj-cal-avg"},_l={class:"dj-cal-rate"},kl={key:1,class:"dj-empty-hint dj-stats-empty"},de=6e5,gl={__name:"DecisionJournal",setup(a){const o=b(!1),u=b(null);let i=null;const s=b("loading");De(s,l=>{l==="unlocked"&&Ze("decisions:seen-help")&&(o.value=!0)});const d=b(!1),f=b(""),g=b(""),w=b(""),x=b(!1),m=b(Q());function q(l=new Date){const t=l.getFullYear(),n=String(l.getMonth()+1).padStart(2,"0"),k=String(l.getDate()).padStart(2,"0");return`${t}-${n}-${k}`}function H(l){const t=new Date;return t.setDate(t.getDate()+l),q(t)}const I=U(()=>Object.values(m.value.decisions||{})),A=U(()=>ht(m.value,q())),Ie=U(()=>new Set(A.value.map(l=>l.id))),W=U(()=>_t(m.value).filter(l=>!Ie.value.has(l.id))),Z=U(()=>kt(m.value)),$=U(()=>({brier:Dt(I.value),buckets:Ot(I.value).filter(l=>l.n>0),counts:xt(I.value,q())})),y=b("empty"),D=b(null),Y=b(!1);async function fe(){if(w.value="",!f.value){w.value="Введите пароль для защиты журнала.";return}if(f.value.length<6){w.value="Пароль не короче 6 символов.";return}if(f.value!==g.value){w.value="Пароли не совпадают.";return}x.value=!0;try{const l=We(16);i=l,u.value=await ue(f.value,l),m.value=Q();const{iv:t,ciphertext:n}=await se(u.value,m.value);await dt(oe({salt:l,iterations:de,iv:t,ciphertext:n})),d.value=!0,s.value="unlocked",y.value="empty",ee()}catch(l){w.value="Не удалось создать журнал: "+((l==null?void 0:l.message)||l),u.value=null}finally{x.value=!1}}async function me(){if(w.value="",!f.value){w.value="Введите пароль.";return}x.value=!0;try{const l=await ce();if(!l){d.value=!1;return}const{salt:t,iterations:n,iv:k,ciphertext:F}=ae(l),z=await ue(f.value,t,n),ne=await ie(z,{iv:k,ciphertext:F});u.value=z,i=t,m.value=ne&&ne.decisions?ne:Q(),s.value="unlocked",y.value="empty",ee()}catch{w.value="Неверный пароль или повреждённые данные.",u.value=null}finally{x.value=!1}}function Ue(){u.value=null,i=null,Oe(),m.value=Q(),r.value=null,_.value=null,D.value=null,y.value="empty",ke(),s.value="locked",ee()}function ee(){f.value="",g.value="",w.value=""}function je(){x.value||(d.value?me():fe())}const r=b(null),N=b("");function we(){r.value={id:null,title:"",context:"",options:["",""],chosen:"",expectedOutcome:"",confidence:70,reviewDate:H(30)},N.value="",D.value=null,y.value="form"}function ye(l){const t=m.value.decisions[l];
1t&&(r.value={id:t.id,title:t.title||"",context:t.context||"",options:t.options&&t.options.length?[...t.options]:["",""],chosen:t.chosen||"",expectedOutcome:t.expectedOutcome||"",confidence:t.confidence??70,reviewDate:t.reviewDate||H(30)},N.value="",D.value=l,y.value="form")}const Ne=U(()=>{var l;return(((l=r.value)==null?void 0:l.options)||[]).map(t=>t.trim()).filter(Boolean)});function Be(){r.value.options.push("")}function $e(l){r.value.options.splice(l,1),r.value.options.length===0&&r.value.options.push("")}function Re(){if(N.value="",!r.value.title.trim()){N.value="Введите заголовок решения.";return}const l=Number(r.value.confidence);if(!Number.isFinite(l)){N.value="Укажите уверенность (0–100%).";return}const t=r.value.options.map(n=>n.trim()).filter(Boolean);wt(m.value,{id:r.value.id||void 0,title:r.value.title.trim(),context:r.value.context,options:t,chosen:t.includes(r.value.chosen)?r.value.chosen:"",expectedOutcome:r.value.expectedOutcome,confidence:l,reviewDate:r.value.reviewDate||null}),r.value=null,y.value="empty",D.value=null}function be(){r.value=null,N.value="",y.value="empty",D.value=null}function Me(){var t;const l=(t=r.value)==null?void 0:t.id;if(!l){be();return}confirm("Удалить это решение?")&&(bt(m.value,l),r.value=null,y.value="empty",D.value=null)}const _=b(null),P=b("");function Te(l){const t=m.value.decisions[l];t&&(_.value={id:l,outcome:null,actualOutcome:t.actualOutcome||""},P.value="",D.value=l,y.value="review")}const R=U(()=>_.value?m.value.decisions[_.value.id]:null);function Pe(){if(P.value="",!!_.value){if(!_.value.outcome){P.value="Отметьте, сбылось ли ожидание.";return}yt(m.value,_.value.id,_.value.outcome,_.value.actualOutcome),_.value=null,D.value=null,y.value="stats"}}function Fe(){_.value=null,P.value="",y.value="empty",D.value=null}const O=U(()=>D.value?m.value.decisions[D.value]:null);function Le(l){D.value=l,y.value="detail"}function Ke(l){return l==null?"—":l.toFixed(3)}function qe(l){return l==null?"—":Math.round(l)+"%"}function Je(l){return l==null?"—":Math.round(l*100)+"%"}function he(l){return l==="correct"?"✓ Сбылось":l==="wrong"?"✗ Не сбылось":"—"}async function He(){if(!(!u.value||!i))try{const{iv:l,ciphertext:t}=await se(u.value,m.value);vt(oe({salt:i,iterations:de,iv:l,ciphertext:t}),"decisions")}catch(l){console.warn("[decisions] export failed:",l)}}const S=b("idle"),M=b(""),E=b("");let J=null;const G=b(null);function Ye(){E.value="",G.value&&(G.value.value="",G.value.click())}async function Ge(l){const t=l.target.files[0];if(t)try{J=await pt(t),M.value="",E.value="",S.value="awaiting-passphrase"}catch{E.value="Не удалось прочитать файл.",S.value="idle"}}async function _e(){if(!(!J||!u.value||S.value==="merging")){if(!M.value.trim()){E.value="Введите пароль импортируемого файла.";return}S.value="merging",E.value="";try{const{salt:l,iterations:t,iv:n,ciphertext:k}=ae(J),F=await ue(M.value,l,t),z=await ie(F,{iv:n,ciphertext:k});m.value=xe(m.value,z),M.value="",J=null,S.value="idle",y.value="stats"}catch{E.value="Не удалось расшифровать — проверьте пароль.",S.value="awaiting-passphrase"}}}function ke(){J=null,M.value="",E.value="",S.value="idle"}let te=!1;const ze=De(m,async l=>{if(!(!u.value||te))try{const{iv:t,ciphertext:n}=await se(u.value,l);ct(oe({salt:i,iterations:de,iv:t,ciphertext:n}))}catch(t){console.warn("[decisions] autosave failed:",t)}},{deep:!0});let ge=()=>{};
1async function Xe(){if(u.value)try{const l=await ce();if(!l)return;const{iv:t,ciphertext:n}=ae(l),k=await ie(u.value,{iv:t,ciphertext:n});te=!0,m.value=xe(m.value,k),await at()}catch(l){console.warn("[decisions] cross-tab sync failed:",l)}finally{te=!1}}return nt(async()=>{ge=rt(Xe);const l=await ce();d.value=l!=null,s.value="locked"}),lt(()=>{ge(),Oe(),ze(),u.value=null}),(l,t)=>(v(),p("div",Ct,[s.value==="loading"?(v(),p("div",St,[...t[19]||(t[19]=[e("span",{class:"dj-muted"},"Загрузка…",-1)])])):s.value==="locked"?(v(),p("div",Et,[e("div",Vt,[t[20]||(t[20]=e("div",{class:"dj-lock-icon"},"⚖️",-1)),e("p",At,c(d.value?"Открыть журнал решений":"Создать журнал решений"),1),e("p",It,c(d.value?"Введите пароль для расшифровки ваших решений и калибровки.":"Придумайте пароль. Данные хранятся зашифрованными только на вашем устройстве."),1),C(e("input",{"onUpdate:modelValue":t[0]||(t[0]=n=>f.value=n),type:"password",class:"dj-input",placeholder:d.value?"Пароль":"Новый пароль",autocomplete:d.value?"current-password":"new-password",onKeydown:le(je,["enter"])},null,40,Ut),[[V,f.value]]),d.value?h("",!0):C((v(),p("input",{key:0,"onUpdate:modelValue":t[1]||(t[1]=n=>g.value=n),type:"password",class:"dj-input",placeholder:"Повторите пароль",autocomplete:"new-password",onKeydown:le(je,["enter"])},null,544)),[[V,g.value]]),e("div",Nt,[e("button",{class:"dj-btn dj-btn-primary",disabled:x.value,onClick:t[2]||(t[2]=n=>d.value?me():fe())},c(d.value?"Открыть":"Создать"),9,Bt)]),w.value?(v(),p("p",$t,c(w.value),1)):h("",!0)])])):(v(),p("div",Rt,[e("aside",Mt,[t[22]||(t[22]=e("div",{class:"dj-sidebar-head"},[e("strong",{class:"dj-sidebar-title"},"Журнал решений")],-1)),e("div",Tt,[e("button",{class:"dj-new-decision",onClick:we},"+ Новое решение"),e("button",{class:B(["dj-stats-btn",{active:y.value==="stats"}]),onClick:t[3]||(t[3]=n=>y.value="stats")},"📊 Статистика",2)]),e("div",Pt,[A.value.length?(v(),p("section",Ft,[e("h3",Lt,"⏰ На ревью ("+c(A.value.length)+")",1),(v(!0),p(T,null,L(A.value,n=>(v(),p("div",{key:n.id,class:B(["dj-card dj-card-due",{active:D.value===n.id}]),onClick:k=>Te(n.id)},[e("span",qt,c(n.title||"Без названия"),1),e("span",Jt,[e("span",Ht,c(n.confidence)+"%",1),e("span",Yt,c(n.reviewDate),1)])],10,Kt))),128))])):h("",!0),e("section",Gt,[e("h3",zt,"Открытые ("+c(W.value.length)+")",1),(v(!0),p(T,null,L(W.value,n=>(v(),p("div",{key:n.id,class:B(["dj-card",{active:D.value===n.id}]),onClick:k=>ye(n.id)},[e("span",Qt,c(n.title||"Без названия"),1),e("span",Wt,[e("span",Zt,c(n.confidence)+"%",1),n.reviewDate?(v(),p("span",en,c(n.reviewDate),1)):h("",!0)])],10,Xt))),128)),!W.value.length&&!A.value.length?(v(),p("p",tn,"Пока нет решений. Добавьте первое.")):h("",!0)]),Z.value.length?(v(),p("section",nn,[e("h3",{class:"dj-section-title dj-section-toggle",onClick:t[4]||(t[4]=n=>Y.value=!Y.value)},[e("span",null,c(Y.value?"▾":"▸")+" Оценённые ("+c(Z.value.length)+")",1)]),Y.value?(v(!0),p(T,{key:0},L(Z.value,n=>(v(),p("div",{key:n.id,class:B(["dj-card dj-card-reviewed",{active:D.value===n.id}]),onClick:k=>Le(n.id)},[e("span",sn,c(n.title||"Без названия"),1),e("span",on,[e("span",{class:B(["dj-outcome",n.outcome==="correct"?"ok":"bad"])},c(he(n.outcome)),3),e("span",an,c(n.confidence)+"%",1)])],10,ln))),128)):h("",!0)])):h("",!0)]),e("div",un,[e("div",cn,[e("button",{class:"dj-btn-sm",onClick:He},"Экспорт"),e("button",{class:"dj-btn-sm",onClick:Ye},"Импорт"),e("button",{class:"dj-btn-sm dj-help-btn",title:"Справка","aria-label":"Справка",onClick:t[5]||(t[5]=n=>o.value=!0)},"?")]),e("input",{ref_key:"fileInputEl",ref:G,type:"file",accept:".decisions",style:{display:"none"},onChange:Ge},null,544),S.value!=="idle"?(v(),p("div",dn,[t[21]||(t[21]=e("div",{class:"dj-import-label"},"Пароль импортируемого файла:",-1)),C(e("input",{"onUpdate:modelValue":t[6]||(t[6]=n=>M.value=n),type:"password",class:"dj-import-input",placeholder:"Пароль",autocomplete:"off",onKeydown:le(_e,["enter"])},null,544),[[V,M.value]]),e("div",rn,[e("button",{class:"dj-btn-sm dj-import-merge",disabled:S.value==="merging",onClick:_e},c(S.value==="merging"?"Расшифровка…":"Объединить"),9,vn),e("button",{class:"dj-btn-sm",onClick:ke},"Отмена")]),E.value?(v(),p("p",pn,c(E.value),1)):h("",!0)])):h("",!0),E.value&&S.value==="idle"?(v(),p("p",fn,c(E.value),1)):h("",!0),e("button",{class:"dj-btn-sm dj-lock-btn",onClick:Ue},"🔒 Заблокировать")])]),e("main",mn,[y.value==="empty"?(v(),p("div",jn,[e("div",{class:"dj-empty-card"},[t[23]||(t[23]=e("div",{class:"dj-empty-icon"},"⚖️",-1)),t[24]||(t[24]=e("p",{class:"dj-empty-title"},"Журнал решений",-1)),t[25]||(t[25]=e("p",{class:"dj-empty-text"}," Записывайте решения с уверенностью в процентах и датой ревью. Когда дата придёт — отметьте исход, и журнал посчитает вашу калибровку. ",-1)),e("button",{class:"dj-btn dj-btn-primary",onClick:we},"+ Новое решение")])])):y.value==="form"?(v(),p("div",wn,[e("h2",yn,c(r.value.id?"Редактировать решение":"Новое решение"),
11),e("label",bn,[t[26]||(t[26]=e("span",{class:"dj-field-label"},"Заголовок *",-1)),C(e("input",{"onUpdate:modelValue":t[7]||(t[7]=n=>r.value.title=n),class:"dj-text",placeholder:"Какое решение я принимаю?"},null,512),[[V,r.value.title]])]),e("label",hn,[t[27]||(t[27]=e("span",{class:"dj-field-label"},"Контекст",-1)),C(e("textarea",{"onUpdate:modelValue":t[8]||(t[8]=n=>r.value.context=n),class:"dj-textarea",placeholder:"Что известно? Почему сейчас?"},null,512),[[V,r.value.context]])]),e("div",_n,[t[28]||(t[28]=e("span",{class:"dj-field-label"},"Варианты",-1)),(v(!0),p(T,null,L(r.value.options,(n,k)=>(v(),p("div",{key:k,class:"dj-option-row"},[C(e("input",{"onUpdate:modelValue":F=>r.value.options[k]=F,class:"dj-text",placeholder:`Вариант ${k+1}`},null,8,kn),[[V,r.value.options[k]]]),e("button",{class:"dj-option-del",title:"Убрать вариант","aria-label":"Убрать вариант",onClick:F=>$e(k)},"✕",8,gn)]))),128)),e("button",{class:"dj-add-option",onClick:Be},"+ Вариант")]),e("label",Dn,[t[30]||(t[30]=e("span",{class:"dj-field-label"},"Выбранный вариант",-1)),C(e("select",{"onUpdate:modelValue":t[9]||(t[9]=n=>r.value.chosen=n),class:"dj-select"},[t[29]||(t[29]=e("option",{value:""},"(не выбран)",-1)),(v(!0),p(T,null,L(Ne.value,n=>(v(),p("option",{key:n,value:n},c(n),9,On))),128))],512),[[Qe,r.value.chosen]])]),e("label",xn,[t[31]||(t[31]=e("span",{class:"dj-field-label"},"Ожидаемый исход",-1)),C(e("textarea",{"onUpdate:modelValue":t[10]||(t[10]=n=>r.value.expectedOutcome=n),class:"dj-textarea",placeholder:"Что я ожидаю, что произойдёт?"},null,512),[[V,r.value.expectedOutcome]])]),e("div",Cn,[e("span",Sn,"Уверенность: "+c(r.value.confidence)+"%",1),e("div",En,[C(e("input",{"onUpdate:modelValue":t[11]||(t[11]=n=>r.value.confidence=n),type:"range",min:"0",max:"100",step:"1",class:"dj-range"},null,512),[[V,r.value.confidence]]),C(e("input",{"onUpdate:modelValue":t[12]||(t[12]=n=>r.value.confidence=n),type:"number",min:"0",max:"100",class:"dj-conf-num"},null,512),[[V,r.value.confidence]])])]),e("label",Vn,[t[32]||(t[32]=e("span",{class:"dj-field-label"},"Дата ревью",-1)),C(e("input",{"onUpdate:modelValue":t[13]||(t[13]=n=>r.value.reviewDate=n),type:"date",class:"dj-date"},null,512),[[V,r.value.reviewDate]])]),N.value?(v(),p("p",An,c(N.value),1)):h("",!0),e("div",In,[e("button",{class:"dj-btn dj-btn-primary",onClick:Re},"Сохранить"),e("button",{class:"dj-btn dj-btn-ghost",onClick:be},"Отмена"),r.value.id?(v(),p("button",{key:0,class:"dj-btn dj-btn-danger",onClick:Me},"Удалить")):h("",!0)])])):y.value==="review"&&R.value?(v(),p("div",Un,[t[38]||(t[38]=e("h2",{class:"dj-panel-title"},"Ревью решения",-1)),e("div",Nn,[e("div",Bn,[t[33]||(t[33]=e("span",{class:"dj-review-k"},"Решение",-1)),e("span",$n,c(R.value.title),1)]),R.value.chosen?(v(),p("div",Rn,[t[34]||(t[34]=e("span",{class:"dj-review-k"},"Выбор",-1)),e("span",Mn,c(R.value.chosen),1)])):h("",!0),R.value.expectedOutcome?(v(),p("div",Tn,[t[35]||(t[35]=e("span",{class:"dj-review-k"},"Ожидание",-1)),e("span",Pn,c(R.value.expectedOutcome),1)])):h("",!0),e("div",Fn,[t[36]||(t[36]=e("span",{class:"dj-review-k"},"Уверенность",-1)),e("span",Ln,c(R.value.confidence)+"%",1)])]),t[39]||(t[39]=e("p",{class:"dj-review-q"},"Сбылось ли ожидание?",-1)),e("div",Kn,[e("button",{class:B(["dj-outcome-btn ok",{selected:_.value.outcome==="correct"}]),onClick:t[14]||(t[14]=n=>_.value.outcome="correct")},"✓ Да, сбылось",2),e("button",{class:B(["dj-outcome-btn bad",{selected:_.value.outcome==="wrong"}]),onClick:t[15]||(t[15]=n=>_.value.outcome="wrong")},"✗ Нет, не сбылось",2)]),e("label",qn,[t[37]||(t[37]=e("span",{class:"dj-field-label"},"Что произошло на самом деле",-1)),C(e("textarea",{"onUpdate:modelValue":t[16]||(t[16]=n=>_.value.actualOutcome=n),class:"dj-textarea",placeholder:"Фактический исход (по желанию)"},null,512),[[V,_.value.actualOutcome]])]),P.value?(v(),p("p",Jn,c(P.value),1)):h("",!0),e("div",{class:"dj-form-actions"},[e("button",{class:"dj-btn dj-btn-primary",onClick:Pe},"Записать исход"),e("button",{class:"dj-btn dj-btn-ghost",onClick:Fe},"Отмена")])])):y.value==="detail"&&O.value?(v(),p("div",Hn,[e("h2",Yn,c(O.value.title),
11),e("div",Gn,[O.value.context?(v(),p("div",zn,[t[40]||(t[40]=e("span",{class:"dj-review-k"},"Контекст",-1)),e("span",Xn,c(O.value.context),1)])):h("",!0),O.value.chosen?(v(),p("div",Qn,[t[41]||(t[41]=e("span",{class:"dj-review-k"},"Выбор",-1)),e("span",Wn,c(O.value.chosen),1)])):h("",!0),O.value.expectedOutcome?(v(),p("div",Zn,[t[42]||(t[42]=e("span",{class:"dj-review-k"},"Ожидание",-1)),e("span",el,c(O.value.expectedOutcome),1)])):h("",!0),e("div",tl,[t[43]||(t[43]=e("span",{class:"dj-review-k"},"Уверенность",-1)),e("span",nl,c(O.value.confidence)+"%",1)]),e("div",ll,[t[44]||(t[44]=e("span",{class:"dj-review-k"},"Исход",-1)),e("span",{class:B(["dj-review-v dj-outcome",O.value.outcome==="correct"?"ok":"bad"])},c(he(O.value.outcome)),3)]),O.value.actualOutcome?(v(),p("div",sl,[t[45]||(t[45]=e("span",{class:"dj-review-k"},"Факт",-1)),e("span",ol,c(O.value.actualOutcome),1)])):h("",!0)]),e("div",al,[e("button",{class:"dj-btn dj-btn-ghost",onClick:t[17]||(t[17]=n=>ye(O.value.id))},"Редактировать")])])):y.value==="stats"?(v(),p("div",ul,[t[53]||(t[53]=e("h2",{class:"dj-panel-title"},"Калибровка",-1)),e("div",il,[e("div",cl,[e("span",dl,c($.value.counts.total),1),t[46]||(t[46]=e("span",{class:"dj-count-l"},"всего",-1))]),e("div",rl,[e("span",vl,c($.value.counts.open),1),t[47]||(t[47]=e("span",{class:"dj-count-l"},"открыто",-1))]),e("div",pl,[e("span",fl,c($.value.counts.due),1),t[48]||(t[48]=e("span",{class:"dj-count-l"},"на ревью",-1))]),e("div",ml,[e("span",jl,c($.value.counts.reviewed),1),t[49]||(t[49]=e("span",{class:"dj-count-l"},"оценено",-1))])]),$.value.counts.reviewed?(v(),p(T,{key:0},[e("div",wl,[e("span",yl,c(Ke($.value.brier)),1),t[50]||(t[50]=e("span",{class:"dj-brier-l"},[j("Brier score "),e("em",null,"(0 — идеал, 0.25 — монетка, 1 — макс. ошибка)")],-1))]),e("table",bl,[t[51]||(t[51]=e("thead",null,[e("tr",null,[e("th",null,"Заявлено"),e("th",null,"Сбылось"),e("th",null,"Решений")])],-1)),e("tbody",null,[(v(!0),p(T,null,L($.value.buckets,n=>(v(),p("tr",{key:n.label},[e("td",null,[j(c(n.label)+" ",1),e("span",hl,"(ср. "+c(qe(n.avgConfidence))+")",1)]),e("td",_l,c(Je(n.hitRate)),1),e("td",null,c(n.n),1)]))),128))])]),t[52]||(t[52]=e("p",{class:"dj-cal-hint"},"Хорошая калибровка: «сбылось» близко к «заявлено». Завышенная уверенность — «сбылось» ниже заявленного.",-1))],64)):(v(),p("p",kl," Пока нет оценённых решений. Отметьте исход хотя бы одного решения, дата ревью которого наступила, — и здесь появится калибровка. "))])):h("",!0)])])),st(et,{modelValue:o.value,"onUpdate:modelValue":t[18]||(t[18]=n=>o.value=n)},{default:ot(()=>[...t[54]||(t[54]=[e("h2",null,"Журнал решений с калибровкой",-1),e("p",null,[j("Решения забываются, а память подгоняет прошлую уверенность под результат. Этот журнал фиксирует выбор "),e("strong",null,"до"),j(" того, как стал известен исход — и со временем показывает, насколько ваша уверенность совпадает с реальностью.")],-1),e("h3",null,"Как записывать решение",-1),e("ul",null,[e("li",null,[e("strong",null,"Контекст"),j(" и "),e("strong",null,"варианты"),j(" — что известно и из чего выбираете")]),e("li",null,[e("strong",null,"Выбранный вариант"),j(" и "),e("strong",null,"ожидаемый исход"),j(" — что, по-вашему, произойдёт")]),e("li",null,[e("strong",null,"Уверенность 0–100%"),j(" — насколько вы убеждены в исходе")]),e("li",null,[e("strong",null,"Дата ревью"),j(" — когда станет ясно, сбылось ли (по умолчанию +30 дней)")])],-1),e("h3",null,"Ревью",-1),e("p",null,[j("Когда дата ревью наступает, решение попадает в очередь "),e("strong",null,"«⏰ На ревью»"),j(". Откройте его и честно отметьте, сбылось ли ожидание — «да» или «нет», по желанию опишите фактический исход. Честность здесь важнее, чем «оказаться правым».")],-1),e("h3",null,"Калибровка",-1),e("ul",null,[e("li",null,[e("strong",null,"Brier score"),j(": "),e("code",null,"0"),j(" — идеал, "),e("code",null,"0.25"),j(" — уровень монетки (50% наугад), "),e("code",null,"1"),j(" — максимально уверенная ошибка")]),e("li",null,[e("strong",null,"Корзин
1ы уверенности"),j(": «заявлено 80% → сбылось X%». У хорошо откалиброванного автора «сбылось» близко к «заявлено»; если «сбылось» стабильно ниже — уверенность завышена")])],-1),e("h3",null,"Приватность",-1),e("ul",null,[e("li",null,[j("Всё "),e("strong",null,"шифруется прямо в браузере"),j(" (PBKDF2 → AES-GCM 256, как в дневнике); на диске лежит лишь envelope "),e("code",null,"{ соль, итерации, IV, шифротекст }")]),e("li",null,"Ключ выводится из пароля и живёт только в памяти сессии — при перезагрузке нужно ввести пароль снова"),e("li",null,[e("strong",null,"Экспорт"),j(" скачивает зашифрованный файл "),e("code",null,".decisions"),j("; "),e("strong",null,"импорт"),j(" спрашивает его пароль и сливает данные по принципу «побеждает последнее обновление»")])],-1)])]),_:1},8,["modelValue"])]))}},El=tt(gl,[["__scopeId","data-v-005eeffd"]]);export{El as default};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.