git-history-ui 2.0.3 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/CHANGELOG.md +98 -0
  2. package/README.md +75 -13
  3. package/build/frontend/chunk-36NFLS3P.js +1 -0
  4. package/build/frontend/chunk-3BORCJKI.js +2 -0
  5. package/build/frontend/chunk-3FFYILBL.js +1 -0
  6. package/build/frontend/chunk-B7ZU76GM.js +1 -0
  7. package/build/frontend/chunk-HQV5AEMT.js +3 -0
  8. package/build/frontend/chunk-ITIFFECZ.js +1 -0
  9. package/build/frontend/chunk-N7UHDKJ7.js +1 -0
  10. package/build/frontend/chunk-NUMLL3OZ.js +1 -0
  11. package/build/frontend/chunk-QUDEGJKI.js +1 -0
  12. package/build/frontend/chunk-R33W2FKN.js +7 -0
  13. package/build/frontend/chunk-TQE5NWMZ.js +5 -0
  14. package/build/frontend/chunk-TQVUSJBM.js +1 -0
  15. package/build/frontend/chunk-YSTG766K.js +1 -0
  16. package/build/frontend/index.html +2 -2
  17. package/build/frontend/main-6LGPRO6C.js +1 -0
  18. package/build/frontend/styles-BOEVKAI2.css +1 -0
  19. package/dist/backend/aggregations.d.ts +57 -0
  20. package/dist/backend/aggregations.js +130 -0
  21. package/dist/backend/aggregations.js.map +1 -0
  22. package/dist/backend/annotations.d.ts +30 -0
  23. package/dist/backend/annotations.js +90 -0
  24. package/dist/backend/annotations.js.map +1 -0
  25. package/dist/backend/gitService.d.ts +14 -0
  26. package/dist/backend/gitService.js +81 -0
  27. package/dist/backend/gitService.js.map +1 -1
  28. package/dist/backend/grouping/prGrouping.d.ts +39 -0
  29. package/dist/backend/grouping/prGrouping.js +210 -0
  30. package/dist/backend/grouping/prGrouping.js.map +1 -0
  31. package/dist/backend/impact.d.ts +16 -0
  32. package/dist/backend/impact.js +66 -0
  33. package/dist/backend/impact.js.map +1 -0
  34. package/dist/backend/insights.d.ts +9 -0
  35. package/dist/backend/insights.js +44 -0
  36. package/dist/backend/insights.js.map +1 -0
  37. package/dist/backend/llm/anthropicProvider.d.ts +13 -0
  38. package/dist/backend/llm/anthropicProvider.js +90 -0
  39. package/dist/backend/llm/anthropicProvider.js.map +1 -0
  40. package/dist/backend/llm/heuristicProvider.d.ts +15 -0
  41. package/dist/backend/llm/heuristicProvider.js +127 -0
  42. package/dist/backend/llm/heuristicProvider.js.map +1 -0
  43. package/dist/backend/llm/index.d.ts +17 -0
  44. package/dist/backend/llm/index.js +66 -0
  45. package/dist/backend/llm/index.js.map +1 -0
  46. package/dist/backend/llm/openaiProvider.d.ts +13 -0
  47. package/dist/backend/llm/openaiProvider.js +100 -0
  48. package/dist/backend/llm/openaiProvider.js.map +1 -0
  49. package/dist/backend/llm/types.d.ts +32 -0
  50. package/dist/backend/llm/types.js +3 -0
  51. package/dist/backend/llm/types.js.map +1 -0
  52. package/dist/backend/search/datePhrase.d.ts +20 -0
  53. package/dist/backend/search/datePhrase.js +113 -0
  54. package/dist/backend/search/datePhrase.js.map +1 -0
  55. package/dist/backend/search/nlSearch.d.ts +39 -0
  56. package/dist/backend/search/nlSearch.js +90 -0
  57. package/dist/backend/search/nlSearch.js.map +1 -0
  58. package/dist/backend/server.d.ts +3 -0
  59. package/dist/backend/server.js +137 -2
  60. package/dist/backend/server.js.map +1 -1
  61. package/dist/backend/snapshot.d.ts +16 -0
  62. package/dist/backend/snapshot.js +42 -0
  63. package/dist/backend/snapshot.js.map +1 -0
  64. package/docs/launch.md +66 -0
  65. package/package.json +12 -3
  66. package/build/frontend/main-VDZAFLAV.js +0 -11
  67. package/build/frontend/styles-CO6MLMTR.css +0 -1
@@ -0,0 +1 @@
1
+ import{$ as N,$a as se,A as ee,Jb as m,Ka as D,La as a,Qa as L,Ra as u,Rb as f,Sa as h,Sb as P,V as g,Va as x,Wb as W,X as H,Xa as ie,Z as p,Za as re,Zb as ae,_b as $,a as l,b as d,j as K,la as te,nb as b,oa as O,p as J,sa as ne,ta as C,u as Q,va as V,xb as oe}from"./chunk-TQE5NWMZ.js";var me=(()=>{class n{_renderer;_elementRef;onChange=t=>{};onTouched=()=>{};constructor(t,i){this._renderer=t,this._elementRef=i}setProperty(t,i){this._renderer.setProperty(this._elementRef.nativeElement,t,i)}registerOnTouched(t){this.onTouched=t}registerOnChange(t){this.onChange=t}setDisabledState(t){this.setProperty("disabled",t)}static \u0275fac=function(i){return new(i||n)(a(D),a(V))};static \u0275dir=u({type:n})}return n})(),T=(()=>{class n extends me{static \u0275fac=(()=>{let t;return function(r){return(t||(t=C(n)))(r||n)}})();static \u0275dir=u({type:n,features:[h]})}return n})(),I=new p("");var Se={provide:I,useExisting:g(()=>_e),multi:!0};function Ne(){let n=$()?$().getUserAgent():"";return/android (\d+)/.test(n.toLowerCase())}var Oe=new p(""),_e=(()=>{class n extends me{_compositionMode;_composing=!1;constructor(t,i,r){super(t,i),this._compositionMode=r,this._compositionMode==null&&(this._compositionMode=!Ne())}writeValue(t){let i=t??"";this.setProperty("value",i)}_handleInput(t){(!this._compositionMode||this._compositionMode&&!this._composing)&&this.onChange(t)}_compositionStart(){this._composing=!0}_compositionEnd(t){this._composing=!1,this._compositionMode&&this.onChange(t)}static \u0275fac=function(i){return new(i||n)(a(D),a(V),a(Oe,8))};static \u0275dir=u({type:n,selectors:[["input","formControlName","",3,"type","checkbox"],["textarea","formControlName",""],["input","formControl","",3,"type","checkbox"],["textarea","formControl",""],["input","ngModel","",3,"type","checkbox"],["textarea","ngModel",""],["","ngDefaultControl",""]],hostBindings:function(i,r){i&1&&b("input",function(o){return r._handleInput(o.target.value)})("blur",function(){return r.onTouched()})("compositionstart",function(){return r._compositionStart()})("compositionend",function(o){return r._compositionEnd(o.target.value)})},standalone:!1,features:[m([Se]),h]})}return n})();var xe=new p(""),Pe=new p("");function ve(n){return n!=null}function ye(n){return re(n)?J(n):n}function Ce(n){let e={};return n.forEach(t=>{e=t!=null?l(l({},e),t):e}),Object.keys(e).length===0?null:e}function Ve(n,e){return e.map(t=>t(n))}function Re(n){return!n.validate}function De(n){return n.map(e=>Re(e)?e:t=>e.validate(t))}function ke(n){if(!n)return null;let e=n.filter(ve);return e.length==0?null:function(t){return Ce(Ve(t,e))}}function be(n){return n!=null?ke(De(n)):null}function je(n){if(!n)return null;let e=n.filter(ve);return e.length==0?null:function(t){let i=Ve(t,e).map(ye);return ee(i).pipe(Q(Ce))}}function Ae(n){return n!=null?je(De(n)):null}function le(n,e){return n===null?[e]:Array.isArray(n)?[...n,e]:[n,e]}function Ge(n){return n._rawValidators}function Te(n){return n._rawAsyncValidators}function q(n){return n?Array.isArray(n)?n:[n]:[]}function k(n,e){return Array.isArray(n)?n.includes(e):n===e}function ue(n,e){let t=q(e);return q(n).forEach(r=>{k(t,r)||t.push(r)}),t}function de(n,e){return q(e).filter(t=>!k(n,t))}var j=class{get value(){return this.control?this.control.value:null}get valid(){return this.control?this.control.valid:null}get invalid(){return this.control?this.control.invalid:null}get pending(){return this.control?this.control.pending:null}get disabled(){return this.control?this.control.disabled:null}get enabled(){return this.control?this.control.enabled:null}get errors(){return this.control?this.control.errors:null}get pristine(){return this.control?this.control.pristine:null}get dirty(){return this.control?this.control.dirty:null}get touched(){return this.control?this.control.touched:null}get status(){return this.control?this.control.status:null}get untouched(){return this.control?this.control.untouched:null}get statusChanges(){return this.control?this.control.statusChanges:null}get valueChanges(){return this.control?this.control.valueChanges:null}get path(){return null}_composedValidatorFn;_composedAsyncValidatorFn;_rawValidators=[];_rawAsyncValidators=[];_setValidators(e){this._rawValidators=e||[],this._composedValidatorFn=be(this._rawValidators)}_setAsyncValidators(e){this._rawAsyncValidators=e||[],this._composedAsyncValidatorFn=Ae(this._rawAsyncValidators)}get validator(){return this._composedValidatorFn||null}get asyncValidator(){return this._composedAsyncValidatorFn||null}_onDestroyCallbacks=[];_registerOnDestroy(e){this._onDestroyCallbacks.push(e)}_invokeOnDestroyCallbacks(){this._onDestroyCallbacks.forEach(e=>e()),this._onDestroyCallbacks=[]}reset(e=void 0){this.control&&this.control.reset(e)}hasError(e,t){return this.control?this.control.hasError(e,t):!1}getError(e,t){return this.control?this.control.getError(e,t):null}},z=class extends j{name;get formDirective(){return null}get path(){return null}},F=class extends j{_parent=null;name=null;valueAccessor=null},Z=class{_cd;constructor(e){this._cd=e}get isTouched(){return this._cd?.control?._touched?.(),!!this._cd?.control?.touched}get isUntouched(){return!!this._cd?.control?.untouched}get isPristine(){return this._cd?.control?._pristine?.(),!!this._cd?.control?.pristine}get isDirty(){return!!this._cd?.control?.dirty}get isValid(){return this._cd?.control?._status?.(),!!this._cd?.control?.valid}get isInvalid(){return!!this._cd?.control?.invalid}get isPending(){return!!this._cd?.control?.pending}get isSubmitted(){return this._cd?._submitted?.(),!!this._cd?.submitted}},Be={"[class.ng-untouched]":"isUntouched","[class.ng-touched]":"isTouched","[class.ng-pristine]":"isPristine","[class.ng-dirty]":"isDirty","[class.ng-valid]":"isValid","[class.ng-invalid]":"isInvalid","[class.ng-pending]":"isPending"},Ot=d(l({},Be),{"[class.ng-submitted]":"isSubmitted"}),xt=(()=>{class n extends Z{constructor(t){super(t)}static \u0275fac=function(i){return new(i||n)(a(F,2))};static \u0275dir=u({type:n,selectors:[["","formControlName",""],["","ngModel",""],["","formControl",""]],hostVars:14,hostBindings:function(i,r){i&2&&oe("ng-untouched",r.isUntouched)("ng-touched",r.isTouched)("ng-pristine",r.isPristine)("ng-dirty",r.isDirty)("ng-valid",r.isValid)("ng-invalid",r.isInvalid)("ng-pending",r.isPending)},standalone:!1,features:[h]})}return n})();var A="VALID",R="INVALID",_="PENDING",M="DISABLED",y=class{},G=class extends y{value;source;constructor(e,t){super(),this.value=e,this.source=t}},E=class extends y{pristine;source;constructor(e,t){super(),this.pristine=e,this.source=t}},w=class extends y{touched;source;constructor(e,t){super(),this.touched=e,this.source=t}},v=class extends y{status;source;constructor(e,t){super(),this.status=e,this.source=t}};function Ue(n){return(B(n)?n.validators:n)||null}function He(n){return Array.isArray(n)?be(n):n||null}function Le(n,e){return(B(e)?e.asyncValidators:n)||null}function We(n){return Array.isArray(n)?Ae(n):n||null}function B(n){return n!=null&&!Array.isArray(n)&&typeof n=="object"}var X=class{_pendingDirty=!1;_hasOwnPendingAsyncValidator=null;_pendingTouched=!1;_onCollectionChange=()=>{};_updateOn;_parent=null;_asyncValidationSubscription;_composedValidatorFn;_composedAsyncValidatorFn;_rawValidators;_rawAsyncValidators;value;constructor(e,t){this._assignValidators(e),this._assignAsyncValidators(t)}get validator(){return this._composedValidatorFn}set validator(e){this._rawValidators=this._composedValidatorFn=e}get asyncValidator(){return this._composedAsyncValidatorFn}set asyncValidator(e){this._rawAsyncValidators=this._composedAsyncValidatorFn=e}get parent(){return this._parent}get status(){return f(this.statusReactive)}set status(e){f(()=>this.statusReactive.set(e))}_status=P(()=>this.statusReactive());statusReactive=O(void 0);get valid(){return this.status===A}get invalid(){return this.status===R}get pending(){return this.status==_}get disabled(){return this.status===M}get enabled(){return this.status!==M}errors;get pristine(){return f(this.pristineReactive)}set pristine(e){f(()=>this.pristineReactive.set(e))}_pristine=P(()=>this.pristineReactive());pristineReactive=O(!0);get dirty(){return!this.pristine}get touched(){return f(this.touchedReactive)}set touched(e){f(()=>this.touchedReactive.set(e))}_touched=P(()=>this.touchedReactive());touchedReactive=O(!1);get untouched(){return!this.touched}_events=new K;events=this._events.asObservable();valueChanges;statusChanges;get updateOn(){return this._updateOn?this._updateOn:this.parent?this.parent.updateOn:"change"}setValidators(e){this._assignValidators(e)}setAsyncValidators(e){this._assignAsyncValidators(e)}addValidators(e){this.setValidators(ue(e,this._rawValidators))}addAsyncValidators(e){this.setAsyncValidators(ue(e,this._rawAsyncValidators))}removeValidators(e){this.setValidators(de(e,this._rawValidators))}removeAsyncValidators(e){this.setAsyncValidators(de(e,this._rawAsyncValidators))}hasValidator(e){return k(this._rawValidators,e)}hasAsyncValidator(e){return k(this._rawAsyncValidators,e)}clearValidators(){this.validator=null}clearAsyncValidators(){this.asyncValidator=null}markAsTouched(e={}){let t=this.touched===!1;this.touched=!0;let i=e.sourceControl??this;this._parent&&!e.onlySelf&&this._parent.markAsTouched(d(l({},e),{sourceControl:i})),t&&e.emitEvent!==!1&&this._events.next(new w(!0,i))}markAllAsDirty(e={}){this.markAsDirty({onlySelf:!0,emitEvent:e.emitEvent,sourceControl:this}),this._forEachChild(t=>t.markAllAsDirty(e))}markAllAsTouched(e={}){this.markAsTouched({onlySelf:!0,emitEvent:e.emitEvent,sourceControl:this}),this._forEachChild(t=>t.markAllAsTouched(e))}markAsUntouched(e={}){let t=this.touched===!0;this.touched=!1,this._pendingTouched=!1;let i=e.sourceControl??this;this._forEachChild(r=>{r.markAsUntouched({onlySelf:!0,emitEvent:e.emitEvent,sourceControl:i})}),this._parent&&!e.onlySelf&&this._parent._updateTouched(e,i),t&&e.emitEvent!==!1&&this._events.next(new w(!1,i))}markAsDirty(e={}){let t=this.pristine===!0;this.pristine=!1;let i=e.sourceControl??this;this._parent&&!e.onlySelf&&this._parent.markAsDirty(d(l({},e),{sourceControl:i})),t&&e.emitEvent!==!1&&this._events.next(new E(!1,i))}markAsPristine(e={}){let t=this.pristine===!1;this.pristine=!0,this._pendingDirty=!1;let i=e.sourceControl??this;this._forEachChild(r=>{r.markAsPristine({onlySelf:!0,emitEvent:e.emitEvent})}),this._parent&&!e.onlySelf&&this._parent._updatePristine(e,i),t&&e.emitEvent!==!1&&this._events.next(new E(!0,i))}markAsPending(e={}){this.status=_;let t=e.sourceControl??this;e.emitEvent!==!1&&(this._events.next(new v(this.status,t)),this.statusChanges.emit(this.status)),this._parent&&!e.onlySelf&&this._parent.markAsPending(d(l({},e),{sourceControl:t}))}disable(e={}){let t=this._parentMarkedDirty(e.onlySelf);this.status=M,this.errors=null,this._forEachChild(r=>{r.disable(d(l({},e),{onlySelf:!0}))}),this._updateValue();let i=e.sourceControl??this;e.emitEvent!==!1&&(this._events.next(new G(this.value,i)),this._events.next(new v(this.status,i)),this.valueChanges.emit(this.value),this.statusChanges.emit(this.status)),this._updateAncestors(d(l({},e),{skipPristineCheck:t}),this),this._onDisabledChange.forEach(r=>r(!0))}enable(e={}){let t=this._parentMarkedDirty(e.onlySelf);this.status=A,this._forEachChild(i=>{i.enable(d(l({},e),{onlySelf:!0}))}),this.updateValueAndValidity({onlySelf:!0,emitEvent:e.emitEvent}),this._updateAncestors(d(l({},e),{skipPristineCheck:t}),this),this._onDisabledChange.forEach(i=>i(!1))}_updateAncestors(e,t){this._parent&&!e.onlySelf&&(this._parent.updateValueAndValidity(e),e.skipPristineCheck||this._parent._updatePristine({},t),this._parent._updateTouched({},t))}setParent(e){this._parent=e}getRawValue(){return this.value}updateValueAndValidity(e={}){if(this._setInitialStatus(),this._updateValue(),this.enabled){let i=this._cancelExistingSubscription();this.errors=this._runValidator(),this.status=this._calculateStatus(),(this.status===A||this.status===_)&&this._runAsyncValidator(i,e.emitEvent)}let t=e.sourceControl??this;e.emitEvent!==!1&&(this._events.next(new G(this.value,t)),this._events.next(new v(this.status,t)),this.valueChanges.emit(this.value),this.statusChanges.emit(this.status)),this._parent&&!e.onlySelf&&this._parent.updateValueAndValidity(d(l({},e),{sourceControl:t}))}_updateTreeValidity(e={emitEvent:!0}){this._forEachChild(t=>t._updateTreeValidity(e)),this.updateValueAndValidity({onlySelf:!0,emitEvent:e.emitEvent})}_setInitialStatus(){this.status=this._allControlsDisabled()?M:A}_runValidator(){return this.validator?this.validator(this):null}_runAsyncValidator(e,t){if(this.asyncValidator){this.status=_,this._hasOwnPendingAsyncValidator={emitEvent:t!==!1,shouldHaveEmitted:e!==!1};let i=ye(this.asyncValidator(this));this._asyncValidationSubscription=i.subscribe(r=>{this._hasOwnPendingAsyncValidator=null,this.setErrors(r,{emitEvent:t,shouldHaveEmitted:e})})}}_cancelExistingSubscription(){if(this._asyncValidationSubscription){this._asyncValidationSubscription.unsubscribe();let e=(this._hasOwnPendingAsyncValidator?.emitEvent||this._hasOwnPendingAsyncValidator?.shouldHaveEmitted)??!1;return this._hasOwnPendingAsyncValidator=null,e}return!1}setErrors(e,t={}){this.errors=e,this._updateControlsErrors(t.emitEvent!==!1,this,t.shouldHaveEmitted)}get(e){let t=e;return t==null||(Array.isArray(t)||(t=t.split(".")),t.length===0)?null:t.reduce((i,r)=>i&&i._find(r),this)}getError(e,t){let i=t?this.get(t):this;return i&&i.errors?i.errors[e]:null}hasError(e,t){return!!this.getError(e,t)}get root(){let e=this;for(;e._parent;)e=e._parent;return e}_updateControlsErrors(e,t,i){this.status=this._calculateStatus(),e&&this.statusChanges.emit(this.status),(e||i)&&this._events.next(new v(this.status,t)),this._parent&&this._parent._updateControlsErrors(e,t,i)}_initObservables(){this.valueChanges=new x,this.statusChanges=new x}_calculateStatus(){return this._allControlsDisabled()?M:this.errors?R:this._hasOwnPendingAsyncValidator||this._anyControlsHaveStatus(_)?_:this._anyControlsHaveStatus(R)?R:A}_anyControlsHaveStatus(e){return this._anyControls(t=>t.status===e)}_anyControlsDirty(){return this._anyControls(e=>e.dirty)}_anyControlsTouched(){return this._anyControls(e=>e.touched)}_updatePristine(e,t){let i=!this._anyControlsDirty(),r=this.pristine!==i;this.pristine=i,this._parent&&!e.onlySelf&&this._parent._updatePristine(e,t),r&&this._events.next(new E(this.pristine,t))}_updateTouched(e={},t){this.touched=this._anyControlsTouched(),this._events.next(new w(this.touched,t)),this._parent&&!e.onlySelf&&this._parent._updateTouched(e,t)}_onDisabledChange=[];_registerOnCollectionChange(e){this._onCollectionChange=e}_setUpdateStrategy(e){B(e)&&e.updateOn!=null&&(this._updateOn=e.updateOn)}_parentMarkedDirty(e){let t=this._parent&&this._parent.dirty;return!e&&!!t&&!this._parent._anyControlsDirty()}_find(e){return null}_assignValidators(e){this._rawValidators=Array.isArray(e)?e.slice():e,this._composedValidatorFn=He(this._rawValidators)}_assignAsyncValidators(e){this._rawAsyncValidators=Array.isArray(e)?e.slice():e,this._composedAsyncValidatorFn=We(this._rawAsyncValidators)}};var Me=new p("",{providedIn:"root",factory:()=>Y}),Y="always";function $e(n,e){return[...e.path,n]}function qe(n,e,t=Y){Ze(n,e),e.valueAccessor.writeValue(n.value),(n.disabled||t==="always")&&e.valueAccessor.setDisabledState?.(n.disabled),Xe(n,e),Ke(n,e),Ye(n,e),ze(n,e)}function ce(n,e){n.forEach(t=>{t.registerOnValidatorChange&&t.registerOnValidatorChange(e)})}function ze(n,e){if(e.valueAccessor.setDisabledState){let t=i=>{e.valueAccessor.setDisabledState(i)};n.registerOnDisabledChange(t),e._registerOnDestroy(()=>{n._unregisterOnDisabledChange(t)})}}function Ze(n,e){let t=Ge(n);e.validator!==null?n.setValidators(le(t,e.validator)):typeof t=="function"&&n.setValidators([t]);let i=Te(n);e.asyncValidator!==null?n.setAsyncValidators(le(i,e.asyncValidator)):typeof i=="function"&&n.setAsyncValidators([i]);let r=()=>n.updateValueAndValidity();ce(e._rawValidators,r),ce(e._rawAsyncValidators,r)}function Xe(n,e){e.valueAccessor.registerOnChange(t=>{n._pendingValue=t,n._pendingChange=!0,n._pendingDirty=!0,n.updateOn==="change"&&Ee(n,e)})}function Ye(n,e){e.valueAccessor.registerOnTouched(()=>{n._pendingTouched=!0,n.updateOn==="blur"&&n._pendingChange&&Ee(n,e),n.updateOn!=="submit"&&n.markAsTouched()})}function Ee(n,e){n._pendingDirty&&n.markAsDirty(),n.setValue(n._pendingValue,{emitModelToViewChange:!1}),e.viewToModelUpdate(n._pendingValue),n._pendingChange=!1}function Ke(n,e){let t=(i,r)=>{e.valueAccessor.writeValue(i),r&&e.viewToModelUpdate(i)};n.registerOnChange(t),e._registerOnDestroy(()=>{n._unregisterOnChange(t)})}function Je(n,e){if(!n.hasOwnProperty("model"))return!1;let t=n.model;return t.isFirstChange()?!0:!Object.is(e,t.currentValue)}function Qe(n){return Object.getPrototypeOf(n.constructor)===T}function et(n,e){if(!e)return null;Array.isArray(e);let t,i,r;return e.forEach(s=>{s.constructor===_e?t=s:Qe(s)?i=s:r=s}),r||i||t||null}function he(n,e){let t=n.indexOf(e);t>-1&&n.splice(t,1)}function fe(n){return typeof n=="object"&&n!==null&&Object.keys(n).length===2&&"value"in n&&"disabled"in n}var tt=class extends X{defaultValue=null;_onChange=[];_pendingValue;_pendingChange=!1;constructor(e=null,t,i){super(Ue(t),Le(i,t)),this._applyFormState(e),this._setUpdateStrategy(t),this._initObservables(),this.updateValueAndValidity({onlySelf:!0,emitEvent:!!this.asyncValidator}),B(t)&&(t.nonNullable||t.initialValueIsDefault)&&(fe(e)?this.defaultValue=e.value:this.defaultValue=e)}setValue(e,t={}){this.value=this._pendingValue=e,this._onChange.length&&t.emitModelToViewChange!==!1&&this._onChange.forEach(i=>i(this.value,t.emitViewToModelChange!==!1)),this.updateValueAndValidity(t)}patchValue(e,t={}){this.setValue(e,t)}reset(e=this.defaultValue,t={}){this._applyFormState(e),this.markAsPristine(t),this.markAsUntouched(t),this.setValue(this.value,t),this._pendingChange=!1}_updateValue(){}_anyControls(e){return!1}_allControlsDisabled(){return this.disabled}registerOnChange(e){this._onChange.push(e)}_unregisterOnChange(e){he(this._onChange,e)}registerOnDisabledChange(e){this._onDisabledChange.push(e)}_unregisterOnDisabledChange(e){he(this._onDisabledChange,e)}_forEachChild(e){}_syncPendingControls(){return this.updateOn==="submit"&&(this._pendingDirty&&this.markAsDirty(),this._pendingTouched&&this.markAsTouched(),this._pendingChange)?(this.setValue(this._pendingValue,{onlySelf:!0,emitModelToViewChange:!1}),!0):!1}_applyFormState(e){fe(e)?(this.value=this._pendingValue=e.value,e.disabled?this.disable({onlySelf:!0,emitEvent:!1}):this.enable({onlySelf:!0,emitEvent:!1})):this.value=this._pendingValue=e}};var nt={provide:F,useExisting:g(()=>it)},ge=Promise.resolve(),it=(()=>{class n extends F{_changeDetectorRef;callSetDisabledState;control=new tt;static ngAcceptInputType_isDisabled;_registered=!1;viewModel;name="";isDisabled;model;options;update=new x;constructor(t,i,r,s,o,c){super(),this._changeDetectorRef=o,this.callSetDisabledState=c,this._parent=t,this._setValidators(i),this._setAsyncValidators(r),this.valueAccessor=et(this,s)}ngOnChanges(t){if(this._checkForErrors(),!this._registered||"name"in t){if(this._registered&&(this._checkName(),this.formDirective)){let i=t.name.previousValue;this.formDirective.removeControl({name:i,path:this._getPath(i)})}this._setUpControl()}"isDisabled"in t&&this._updateDisabled(t),Je(t,this.viewModel)&&(this._updateValue(this.model),this.viewModel=this.model)}ngOnDestroy(){this.formDirective&&this.formDirective.removeControl(this)}get path(){return this._getPath(this.name)}get formDirective(){return this._parent?this._parent.formDirective:null}viewToModelUpdate(t){this.viewModel=t,this.update.emit(t)}_setUpControl(){this._setUpdateStrategy(),this._isStandalone()?this._setUpStandalone():this.formDirective.addControl(this),this._registered=!0}_setUpdateStrategy(){this.options&&this.options.updateOn!=null&&(this.control._updateOn=this.options.updateOn)}_isStandalone(){return!this._parent||!!(this.options&&this.options.standalone)}_setUpStandalone(){qe(this.control,this,this.callSetDisabledState),this.control.updateValueAndValidity({emitEvent:!1})}_checkForErrors(){this._checkName()}_checkName(){this.options&&this.options.name&&(this.name=this.options.name),!this._isStandalone()&&this.name}_updateValue(t){ge.then(()=>{this.control.setValue(t,{emitViewToModelChange:!1}),this._changeDetectorRef?.markForCheck()})}_updateDisabled(t){let i=t.isDisabled.currentValue,r=i!==0&&ae(i);ge.then(()=>{r&&!this.control.disabled?this.control.disable():!r&&this.control.disabled&&this.control.enable(),this._changeDetectorRef?.markForCheck()})}_getPath(t){return this._parent?$e(t,this._parent):[t]}static \u0275fac=function(i){return new(i||n)(a(z,9),a(xe,10),a(Pe,10),a(I,10),a(W,8),a(Me,8))};static \u0275dir=u({type:n,selectors:[["","ngModel","",3,"formControlName","",3,"formControl",""]],inputs:{name:"name",isDisabled:[0,"disabled","isDisabled"],model:[0,"ngModel","model"],options:[0,"ngModelOptions","options"]},outputs:{update:"ngModelChange"},exportAs:["ngModel"],standalone:!1,features:[m([nt]),h,ne]})}return n})();var rt={provide:I,useExisting:g(()=>st),multi:!0},st=(()=>{class n extends T{writeValue(t){this.setProperty("value",parseFloat(t))}registerOnChange(t){this.onChange=i=>{t(i==""?null:parseFloat(i))}}static \u0275fac=(()=>{let t;return function(r){return(t||(t=C(n)))(r||n)}})();static \u0275dir=u({type:n,selectors:[["input","type","range","formControlName",""],["input","type","range","formControl",""],["input","type","range","ngModel",""]],hostBindings:function(i,r){i&1&&b("change",function(o){return r.onChange(o.target.value)})("input",function(o){return r.onChange(o.target.value)})("blur",function(){return r.onTouched()})},standalone:!1,features:[m([rt]),h]})}return n})();var ot={provide:I,useExisting:g(()=>Fe),multi:!0};function we(n,e){return n==null?`${e}`:(e&&typeof e=="object"&&(e="Object"),`${n}: ${e}`.slice(0,50))}function at(n){return n.split(":")[0]}var Fe=(()=>{class n extends T{value;_optionMap=new Map;_idCounter=0;set compareWith(t){this._compareWith=t}_compareWith=Object.is;appRefInjector=N(se).injector;destroyRef=N(te);cdr=N(W);_queuedWrite=!1;_writeValueAfterRender(){this._queuedWrite||this.appRefInjector.destroyed||(this._queuedWrite=!0,ie({write:()=>{this.destroyRef.destroyed||(this._queuedWrite=!1,this.writeValue(this.value))}},{injector:this.appRefInjector}))}writeValue(t){this.cdr.markForCheck(),this.value=t;let i=this._getOptionId(t),r=we(i,t);this.setProperty("value",r)}registerOnChange(t){this.onChange=i=>{this.value=this._getOptionValue(i),t(this.value)}}_registerOption(){return(this._idCounter++).toString()}_getOptionId(t){for(let i of this._optionMap.keys())if(this._compareWith(this._optionMap.get(i),t))return i;return null}_getOptionValue(t){let i=at(t);return this._optionMap.has(i)?this._optionMap.get(i):t}static \u0275fac=(()=>{let t;return function(r){return(t||(t=C(n)))(r||n)}})();static \u0275dir=u({type:n,selectors:[["select","formControlName","",3,"multiple",""],["select","formControl","",3,"multiple",""],["select","ngModel","",3,"multiple",""]],hostBindings:function(i,r){i&1&&b("change",function(o){return r.onChange(o.target.value)})("blur",function(){return r.onTouched()})},inputs:{compareWith:"compareWith"},standalone:!1,features:[m([ot]),h]})}return n})(),Rt=(()=>{class n{_element;_renderer;_select;id;constructor(t,i,r){this._element=t,this._renderer=i,this._select=r,this._select&&(this.id=this._select._registerOption())}set ngValue(t){this._select!=null&&(this._select._optionMap.set(this.id,t),this._setElementValue(we(this.id,t)),this._select._writeValueAfterRender())}set value(t){this._setElementValue(t),this._select&&this._select._writeValueAfterRender()}_setElementValue(t){this._renderer.setProperty(this._element.nativeElement,"value",t)}ngOnDestroy(){this._select&&(this._select._optionMap.delete(this.id),this._select._writeValueAfterRender())}static \u0275fac=function(i){return new(i||n)(a(V),a(D),a(Fe,9))};static \u0275dir=u({type:n,selectors:[["option"]],inputs:{ngValue:"ngValue",value:"value"},standalone:!1})}return n})(),lt={provide:I,useExisting:g(()=>Ie),multi:!0};function pe(n,e){return n==null?`${e}`:(typeof e=="string"&&(e=`'${e}'`),e&&typeof e=="object"&&(e="Object"),`${n}: ${e}`.slice(0,50))}function ut(n){return n.split(":")[0]}var Ie=(()=>{class n extends T{value;_optionMap=new Map;_idCounter=0;set compareWith(t){this._compareWith=t}_compareWith=Object.is;writeValue(t){this.value=t;let i;if(Array.isArray(t)){let r=t.map(s=>this._getOptionId(s));i=(s,o)=>{s._setSelected(r.indexOf(o.toString())>-1)}}else i=(r,s)=>{r._setSelected(!1)};this._optionMap.forEach(i)}registerOnChange(t){this.onChange=i=>{let r=[],s=i.selectedOptions;if(s!==void 0){let o=s;for(let c=0;c<o.length;c++){let S=o[c],U=this._getOptionValue(S.value);r.push(U)}}else{let o=i.options;for(let c=0;c<o.length;c++){let S=o[c];if(S.selected){let U=this._getOptionValue(S.value);r.push(U)}}}this.value=r,t(r)}}_registerOption(t){let i=(this._idCounter++).toString();return this._optionMap.set(i,t),i}_getOptionId(t){for(let i of this._optionMap.keys())if(this._compareWith(this._optionMap.get(i)._value,t))return i;return null}_getOptionValue(t){let i=ut(t);return this._optionMap.has(i)?this._optionMap.get(i)._value:t}static \u0275fac=(()=>{let t;return function(r){return(t||(t=C(n)))(r||n)}})();static \u0275dir=u({type:n,selectors:[["select","multiple","","formControlName",""],["select","multiple","","formControl",""],["select","multiple","","ngModel",""]],hostBindings:function(i,r){i&1&&b("change",function(o){return r.onChange(o.target)})("blur",function(){return r.onTouched()})},inputs:{compareWith:"compareWith"},standalone:!1,features:[m([lt]),h]})}return n})(),kt=(()=>{class n{_element;_renderer;_select;id;_value;constructor(t,i,r){this._element=t,this._renderer=i,this._select=r,this._select&&(this.id=this._select._registerOption(this))}set ngValue(t){this._select!=null&&(this._value=t,this._setElementValue(pe(this.id,t)),this._select.writeValue(this._select.value))}set value(t){this._select?(this._value=t,this._setElementValue(pe(this.id,t)),this._select.writeValue(this._select.value)):this._setElementValue(t)}_setElementValue(t){this._renderer.setProperty(this._element.nativeElement,"value",t)}_setSelected(t){this._renderer.setProperty(this._element.nativeElement,"selected",t)}ngOnDestroy(){this._select&&(this._select._optionMap.delete(this.id),this._select.writeValue(this._select.value))}static \u0275fac=function(i){return new(i||n)(a(V),a(D),a(Ie,9))};static \u0275dir=u({type:n,selectors:[["option"]],inputs:{ngValue:"ngValue",value:"value"},standalone:!1})}return n})();var dt=(()=>{class n{static \u0275fac=function(i){return new(i||n)};static \u0275mod=L({type:n});static \u0275inj=H({})}return n})();var jt=(()=>{class n{static withConfig(t){return{ngModule:n,providers:[{provide:Me,useValue:t.callSetDisabledState??Y}]}}static \u0275fac=function(i){return new(i||n)};static \u0275mod=L({type:n});static \u0275inj=H({imports:[dt]})}return n})();export{_e as a,xt as b,it as c,st as d,Fe as e,Rt as f,kt as g,jt as h};
@@ -9,8 +9,8 @@
9
9
  <meta name="theme-color" content="#0b1020" media="(prefers-color-scheme: dark)">
10
10
  <meta name="theme-color" content="#f7f8fa" media="(prefers-color-scheme: light)">
11
11
  <link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%234f46e5' d='M12 .5a11.5 11.5 0 1 0 11.5 11.5A11.5 11.5 0 0 0 12 .5Zm5.7 14.83a1 1 0 0 1-1.41 1.41L13 13.41V19a1 1 0 0 1-2 0v-5.59l-3.29 3.33A1 1 0 1 1 6.3 15.34l5-5.05a1 1 0 0 1 1.42 0Z'/%3E%3C/svg%3E">
12
- <style>*,:before,:after{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246 / .5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}:root{color-scheme:light;--bg-app:#f7f8fa;--bg-surface:#ffffff;--bg-surface-2:#f3f4f6;--bg-elevated:#ffffff;--bg-hover:#eef2ff;--bg-selected:#e0e7ff;--bg-overlay:rgba(15, 23, 42, .45);--fg-primary:#0f172a;--fg-secondary:#475569;--fg-muted:#64748b;--fg-subtle:#94a3b8;--fg-inverted:#ffffff;--border-soft:#e2e8f0;--border-strong:#cbd5e1;--border-focus:#6366f1;--accent:#4f46e5;--accent-hover:#4338ca;--accent-soft:#eef2ff;--accent-fg:#ffffff;--success:#16a34a;--warning:#d97706;--danger:#dc2626;--diff-add-bg:#dcfce7;--diff-add-fg:#14532d;--diff-add-gutter:#86efac;--diff-del-bg:#fee2e2;--diff-del-fg:#7f1d1d;--diff-del-gutter:#fca5a5;--diff-hunk-bg:#f1f5f9;--diff-hunk-fg:#475569;--graph-guide:rgba(148, 163, 184, .28);--graph-row-alt:rgba(15, 23, 42, .025);--graph-row-hover:rgba(79, 70, 229, .08);--graph-row-selected:rgba(79, 70, 229, .14);--graph-node-ring:#ffffff;--graph-shadow:rgba(15, 23, 42, .12);--shadow-sm:0 1px 2px rgba(15, 23, 42, .06);--shadow-md:0 4px 12px rgba(15, 23, 42, .08);--shadow-lg:0 12px 32px rgba(15, 23, 42, .12);--radius-sm:6px;--radius-md:10px;--radius-lg:14px;--font-sans:ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, "Cascadia Mono", "Liberation Mono", "Courier New", monospace}*,*:before,*:after{box-sizing:border-box}html,body{height:100%}body{margin:0;font-family:var(--font-sans);font-size:14px;line-height:1.5;color:var(--fg-primary);background:var(--bg-app);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-rendering:optimizeLegibility}</style><link rel="stylesheet" href="styles-CO6MLMTR.css" media="print" onload="this.media='all'"><noscript><link rel="stylesheet" href="styles-CO6MLMTR.css"></noscript></head>
12
+ <style>*,:before,:after{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246 / .5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}:root{color-scheme:light;--bg-app:#f7f8fa;--bg-surface:#ffffff;--bg-surface-2:#f3f4f6;--bg-elevated:#ffffff;--bg-hover:#eef2ff;--bg-selected:#e0e7ff;--bg-overlay:rgba(15, 23, 42, .45);--fg-primary:#0f172a;--fg-secondary:#475569;--fg-muted:#64748b;--fg-subtle:#94a3b8;--fg-inverted:#ffffff;--border-soft:#e2e8f0;--border-strong:#cbd5e1;--border-focus:#6366f1;--accent:#4f46e5;--accent-hover:#4338ca;--accent-soft:#eef2ff;--accent-fg:#ffffff;--success:#16a34a;--warning:#d97706;--danger:#dc2626;--diff-add-bg:#dcfce7;--diff-add-fg:#14532d;--diff-add-gutter:#86efac;--diff-del-bg:#fee2e2;--diff-del-fg:#7f1d1d;--diff-del-gutter:#fca5a5;--diff-hunk-bg:#f1f5f9;--diff-hunk-fg:#475569;--graph-guide:rgba(148, 163, 184, .28);--graph-row-alt:rgba(15, 23, 42, .025);--graph-row-hover:rgba(79, 70, 229, .08);--graph-row-selected:rgba(79, 70, 229, .14);--graph-node-ring:#ffffff;--graph-shadow:rgba(15, 23, 42, .12);--shadow-sm:0 1px 2px rgba(15, 23, 42, .06);--shadow-md:0 4px 12px rgba(15, 23, 42, .08);--shadow-lg:0 12px 32px rgba(15, 23, 42, .12);--radius-sm:6px;--radius-md:10px;--radius-lg:14px;--font-sans:ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, "Cascadia Mono", "Liberation Mono", "Courier New", monospace}*,*:before,*:after{box-sizing:border-box}html,body{height:100%}body{margin:0;font-family:var(--font-sans);font-size:14px;line-height:1.5;color:var(--fg-primary);background:var(--bg-app);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-rendering:optimizeLegibility}</style><link rel="stylesheet" href="styles-BOEVKAI2.css" media="print" onload="this.media='all'"><noscript><link rel="stylesheet" href="styles-BOEVKAI2.css"></noscript></head>
13
13
  <body>
14
14
  <app-root></app-root>
15
- <script src="polyfills-5CFQRCPP.js" type="module"></script><script src="main-VDZAFLAV.js" type="module"></script></body>
15
+ <link rel="modulepreload" href="chunk-36NFLS3P.js"><link rel="modulepreload" href="chunk-YSTG766K.js"><link rel="modulepreload" href="chunk-NUMLL3OZ.js"><link rel="modulepreload" href="chunk-N7UHDKJ7.js"><link rel="modulepreload" href="chunk-3FFYILBL.js"><link rel="modulepreload" href="chunk-TQE5NWMZ.js"><script src="polyfills-5CFQRCPP.js" type="module"></script><script src="main-6LGPRO6C.js" type="module"></script></body>
16
16
  </html>
@@ -0,0 +1 @@
1
+ import{a as be,b as ve,c as xe}from"./chunk-36NFLS3P.js";import{a as z,b as R,c as B,e as he,f as fe,g as _e,h as K}from"./chunk-YSTG766K.js";import{a as Ce}from"./chunk-NUMLL3OZ.js";import{a as S}from"./chunk-N7UHDKJ7.js";import{a as ae,c as de,e as me,f as ge,g as ue}from"./chunk-3FFYILBL.js";import{$ as _,Ab as f,Bb as N,D as Y,Ea as ie,F as ee,Fa as F,Ga as a,Kb as oe,Pa as C,Qb as re,R as te,Sb as y,Ta as u,Tb as M,W as ne,ab as E,db as c,dc as P,ea as m,eb as r,ec as k,fa as g,fb as o,ga as O,gb as b,ha as $,hc as w,kb as I,lb as V,mb as x,mc as se,nb as d,nc as le,oa as T,ob as h,oc as ce,pc as pe,q as X,sb as D,tb as L,ub as H,xb as A,zb as l}from"./chunk-TQE5NWMZ.js";var ye=[{path:"",loadComponent:()=>import("./chunk-3BORCJKI.js").then(n=>n.HomeShellComponent),pathMatch:"full"},{path:"timeline",loadComponent:()=>import("./chunk-B7ZU76GM.js").then(n=>n.TimelineComponent)},{path:"file/:path",loadComponent:()=>import("./chunk-TQVUSJBM.js").then(n=>n.FileHistoryComponent)},{path:"insights",loadComponent:()=>import("./chunk-HQV5AEMT.js").then(n=>n.InsightsComponent)},{path:"**",redirectTo:""}];var Me={providers:[re({eventCoalescing:!0}),ue(ye),ce(pe())]};var we=["input"];function Se(n,e){if(n&1){let t=x();r(0,"div",3),d("click",function(){m(t);let s=h();return g(s.close())}),o()}}function Te(n,e){if(n&1){let t=x();r(0,"li",11),d("mouseenter",function(){let s=m(t).index,p=h(2);return g(p.index.set(s))})("click",function(){let s=m(t).$implicit,p=h(2);return g(p.pick(s))}),r(1,"span",12),l(2),o(),r(3,"span",13),l(4),o(),r(5,"span",14),l(6),o()()}if(n&2){let t=e.$implicit,i=e.index,s=h(2);A("active",i===s.index()),E("aria-selected",i===s.index()),a(2),f(t.shortHash),a(2),f(t.subject),a(2),f(t.author)}}function Oe(n,e){n&1&&(r(0,"li",15),l(1,"No matches."),o())}function Ee(n,e){if(n&1){let t=x();r(0,"div",4)(1,"input",5,0),d("ngModelChange",function(s){m(t);let p=h();return g(p.onQuery(s))})("keydown",function(s){m(t);let p=h();return g(p.onKey(s))}),o(),r(3,"ul",6),u(4,Te,7,6,"li",7)(5,Oe,2,0,"li",8),o(),r(6,"div",9)(7,"span")(8,"kbd",10),l(9,"\u2191"),o(),r(10,"kbd",10),l(11,"\u2193"),o(),l(12," navigate"),o(),r(13,"span")(14,"kbd",10),l(15,"Enter"),o(),l(16," select"),o(),r(17,"span")(18,"kbd",10),l(19,"Esc"),o(),l(20," close"),o()()()}if(n&2){let t=h();a(),c("ngModel",t.query()),a(3),c("ngForOf",t.results())("ngForTrackBy",t.trackByHash),a(),c("ngIf",!t.results().length)}}var j=class n{state=_(S);input;query=T("");index=T(0);results=y(()=>{let e=this.query().trim().toLowerCase(),t=this.state.commits();return e?t.filter(i=>i.hash.toLowerCase().startsWith(e)||i.shortHash.toLowerCase().startsWith(e)||i.subject.toLowerCase().includes(e)||i.author.toLowerCase().includes(e)).slice(0,50):t.slice(0,50)});constructor(){M(()=>{this.state.paletteOpen()&&(this.query.set(""),this.index.set(0),queueMicrotask(()=>this.input?.nativeElement.focus()))}),M(()=>{let e=this.results().length;this.index()>=e&&this.index.set(Math.max(0,e-1))})}trackByHash(e,t){return t.hash}onQuery(e){this.query.set(e),this.index.set(0)}onKey(e){if(e.key==="ArrowDown")e.preventDefault(),this.index.update(t=>Math.min(this.results().length-1,t+1));else if(e.key==="ArrowUp")e.preventDefault(),this.index.update(t=>Math.max(0,t-1));else if(e.key==="Enter"){e.preventDefault();let t=this.results()[this.index()];t&&this.pick(t)}else e.key==="Escape"&&(e.preventDefault(),this.close())}pick(e){this.state.selectHash(e.hash),this.close()}close(){this.state.paletteOpen.set(!1)}onGlobal(e){(e.metaKey||e.ctrlKey)&&(e.key==="k"||e.key==="K")&&(e.preventDefault(),this.state.paletteOpen.set(!this.state.paletteOpen()))}static \u0275fac=function(t){return new(t||n)};static \u0275cmp=C({type:n,selectors:[["app-command-palette"]],viewQuery:function(t,i){if(t&1&&D(we,5),t&2){let s;L(s=H())&&(i.input=s.first)}},hostBindings:function(t,i){t&1&&d("keydown",function(p){return i.onGlobal(p)},F)},decls:2,vars:2,consts:[["input",""],["class","backdrop",3,"click",4,"ngIf"],["class","palette","role","dialog","aria-modal","true",4,"ngIf"],[1,"backdrop",3,"click"],["role","dialog","aria-modal","true",1,"palette"],["type","text","placeholder","Jump to a commit by hash, subject, or author\u2026",1,"search",3,"ngModelChange","keydown","ngModel"],["role","listbox",1,"results"],["class","result",3,"active","mouseenter","click",4,"ngFor","ngForOf","ngForTrackBy"],["class","result empty",4,"ngIf"],[1,"footer"],[1,"kbd"],[1,"result",3,"mouseenter","click"],[1,"hash"],[1,"subj"],[1,"auth"],[1,"result","empty"]],template:function(t,i){t&1&&u(0,Se,1,0,"div",1)(1,Ee,21,4,"div",2),t&2&&(c("ngIf",i.state.paletteOpen()),a(),c("ngIf",i.state.paletteOpen()))},dependencies:[w,P,k,K,z,R,B],styles:[".backdrop[_ngcontent-%COMP%]{position:fixed;inset:0;background:var(--bg-overlay);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);z-index:90}.palette[_ngcontent-%COMP%]{position:fixed;top:12vh;left:50%;transform:translate(-50%);width:min(640px,calc(100vw - 32px));background:var(--bg-elevated);border:1px solid var(--border-soft);border-radius:var(--radius-lg);box-shadow:var(--shadow-lg);z-index:100;overflow:hidden}.search[_ngcontent-%COMP%]{width:100%;border:0;outline:0;padding:.85rem 1rem;background:transparent;color:var(--fg-primary);font-size:14px;border-bottom:1px solid var(--border-soft)}.results[_ngcontent-%COMP%]{list-style:none;margin:0;padding:.25rem 0;max-height:50vh;overflow:auto}.result[_ngcontent-%COMP%]{display:grid;grid-template-columns:70px 1fr auto;align-items:center;gap:.6rem;padding:.45rem 1rem;cursor:pointer;font-size:13px}.result.active[_ngcontent-%COMP%]{background:var(--bg-hover)}.result.empty[_ngcontent-%COMP%]{grid-template-columns:1fr;color:var(--fg-muted);cursor:default}.hash[_ngcontent-%COMP%]{font-family:var(--font-mono);color:var(--fg-muted)}.subj[_ngcontent-%COMP%]{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--fg-primary)}.auth[_ngcontent-%COMP%]{color:var(--fg-muted);font-size:11px}.footer[_ngcontent-%COMP%]{display:flex;gap:1rem;padding:.4rem .75rem;background:var(--bg-surface-2);border-top:1px solid var(--border-soft);font-size:11px;color:var(--fg-muted)}"],changeDetection:0})};function Pe(n,e){if(n&1&&(r(0,"kbd",11),l(1),o()),n&2){let t=e.$implicit;a(),f(t)}}function Ie(n,e){if(n&1&&(r(0,"li")(1,"span",8),l(2),o(),r(3,"span",9),u(4,Pe,2,1,"kbd",10),o()()),n&2){let t=e.$implicit;a(2),f(t.description),a(2),c("ngForOf",t.keys)}}function Ve(n,e){if(n&1&&(r(0,"section")(1,"h3"),l(2),o(),r(3,"ul"),u(4,Ie,5,2,"li",7),o()()),n&2){let t=e.$implicit;a(2),f(t.title),a(2),c("ngForOf",t.bindings)}}function Ne(n,e){if(n&1){let t=x();I(0),r(1,"div",1),d("click",function(){m(t);let s=h();return g(s.close())}),o(),r(2,"div",2)(3,"div",3)(4,"h2",4),l(5,"Keyboard shortcuts"),o(),r(6,"button",5),d("click",function(){m(t);let s=h();return g(s.close())}),l(7,"\u2715"),o()(),r(8,"div",6),u(9,Ve,5,2,"section",7),o()(),V()}if(n&2){let t=h();a(9),c("ngForOf",t.groups)}}var Fe=[{title:"Navigation",bindings:[{keys:["j"],description:"Next commit"},{keys:["k"],description:"Previous commit"},{keys:["g"],description:"Jump to newest commit"},{keys:["G"],description:"Jump to oldest commit"}]},{title:"Search & overlays",bindings:[{keys:["/"],description:"Focus search"},{keys:["\u2318","K"],description:"Open command palette"},{keys:["?"],description:"Show this help"},{keys:["Esc"],description:"Close overlays"}]}],Z=class n{state=_(S);groups=Fe;close(){this.state.shortcutsOpen.set(!1)}onKey(e){e.key==="?"&&!this.isTyping(e.target)&&(e.preventDefault(),this.state.shortcutsOpen.set(!0)),e.key==="Escape"&&(this.state.shortcutsOpen.set(!1),this.state.paletteOpen.set(!1))}isTyping(e){return e instanceof HTMLElement?["INPUT","TEXTAREA","SELECT"].includes(e.tagName)||e.isContentEditable:!1}static \u0275fac=function(t){return new(t||n)};static \u0275cmp=C({type:n,selectors:[["app-shortcuts-modal"]],hostBindings:function(t,i){t&1&&d("keydown",function(p){return i.onKey(p)},F)},decls:1,vars:1,consts:[[4,"ngIf"],[1,"backdrop",3,"click"],["role","dialog","aria-modal","true","aria-labelledby","shortcuts-title",1,"modal"],[1,"head"],["id","shortcuts-title"],["aria-label","Close",1,"btn","btn-ghost","btn-icon",3,"click"],[1,"body"],[4,"ngFor","ngForOf"],[1,"desc"],[1,"keys"],["class","kbd",4,"ngFor","ngForOf"],[1,"kbd"]],template:function(t,i){t&1&&u(0,Ne,10,1,"ng-container",0),t&2&&c("ngIf",i.state.shortcutsOpen())},dependencies:[w,P,k],styles:[".backdrop[_ngcontent-%COMP%]{position:fixed;inset:0;background:var(--bg-overlay);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);z-index:90}.modal[_ngcontent-%COMP%]{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);width:min(560px,calc(100vw - 32px));max-height:80vh;overflow:auto;background:var(--bg-elevated);border:1px solid var(--border-soft);border-radius:var(--radius-lg);box-shadow:var(--shadow-lg);z-index:100}.head[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between;padding:.75rem 1rem;border-bottom:1px solid var(--border-soft)}.head[_ngcontent-%COMP%] h2[_ngcontent-%COMP%]{margin:0;font-size:16px}.body[_ngcontent-%COMP%]{padding:.75rem 1rem 1rem}h3[_ngcontent-%COMP%]{margin:1rem 0 .4rem;font-size:12px;color:var(--fg-muted);text-transform:uppercase;letter-spacing:.04em}h3[_ngcontent-%COMP%]:first-child{margin-top:0}ul[_ngcontent-%COMP%]{list-style:none;margin:0;padding:0;display:flex;flex-direction:column}li[_ngcontent-%COMP%]{display:flex;justify-content:space-between;align-items:center;padding:.45rem .25rem;border-bottom:1px dashed var(--border-soft)}li[_ngcontent-%COMP%]:last-child{border-bottom:0}.desc[_ngcontent-%COMP%]{color:var(--fg-secondary);font-size:13px}.keys[_ngcontent-%COMP%]{display:flex;gap:4px}"],changeDetection:0})};var De=["searchInput"],Le=()=>({exact:!0});function He(n,e){if(n&1&&(r(0,"span",33),l(1),o()),n&2){let t=e.ngIf;a(),f(t)}}function Ae(n,e){n&1&&(I(0),O(),r(1,"svg",34),b(2,"path",35),o(),V())}function ze(n,e){n&1&&(I(0),r(1,"span",36),l(2,"AI"),o(),V())}function Re(n,e){n&1&&(r(0,"kbd",37),l(1,"/"),o())}function Be(n,e){if(n&1&&(r(0,"option",38),l(1),o()),n&2){let t=e.$implicit;c("value",t),a(),f(t)}}function Ke(n,e){n&1&&(O(),r(0,"svg",26),b(1,"path",39),o())}function je(n,e){n&1&&(O(),r(0,"svg",26),b(1,"path",40),o())}function qe(n,e){if(n&1&&(r(0,"span",46),l(1),o()),n&2){let t=h().ngIf;a(),N("author: ",t.author)}}function Ze(n,e){if(n&1&&(r(0,"span",46),l(1),o()),n&2){let t=h().ngIf;a(),N("since: ",t.since)}}function Ge(n,e){if(n&1&&(r(0,"span",46),l(1),o()),n&2){let t=h().ngIf;a(),N("until: ",t.until)}}function Qe(n,e){if(n&1&&(r(0,"span",46),l(1),o()),n&2){let t=e.$implicit;a(),f(t)}}function Ue(n,e){n&1&&(r(0,"span",47),l(1,"no structured filters detected"),o())}function $e(n,e){if(n&1&&(r(0,"div",41)(1,"span",42),l(2,"Interpreted as"),o(),u(3,qe,2,1,"span",43)(4,Ze,2,1,"span",43)(5,Ge,2,1,"span",43)(6,Qe,2,1,"span",44)(7,Ue,2,0,"span",45),o()),n&2){let t=e.ngIf;a(3),c("ngIf",t.author),a(),c("ngIf",t.since),a(),c("ngIf",t.until),a(),c("ngForOf",t.keywords),a(),c("ngIf",t.keywords.length===0&&!t.author&&!t.since)}}var G=class n{state=_(S);theme=_(xe);searchEl;searchValue=T("");totalLabel=y(()=>{let e=this.state.total();return e?`${e.toLocaleString()} commits`:""});themeLabel=y(()=>`Switch to ${this.theme.resolved()==="light"?"dark":"light"} mode`);searchPlaceholder=y(()=>this.state.searchMode()==="nl"?'Ask anything: "login bug last month", "payments by alice"\u2026':"Search commits\u2026 ( / )");searchModeTooltip=y(()=>this.state.searchMode()==="nl"?"Natural-language search active. Click to switch to literal search.":"Literal git-grep search. Click to switch to natural-language search.");viewModeTooltip=y(()=>this.state.viewMode()==="grouped"?"Showing PR / feature groups. Click for flat list.":"Showing flat commit list. Click for PR / feature groups.");debounce=null;constructor(){M(()=>{let e=this.state.filters();this.searchValue.set(e.search??"")})}onKeydown(e){e.key==="/"&&!this.isTyping(e.target)&&(e.preventDefault(),queueMicrotask(()=>this.searchEl?.nativeElement.focus()))}onSearchInput(e){this.searchValue.set(e),this.debounce&&clearTimeout(this.debounce),this.debounce=setTimeout(()=>{this.state.patchFilters({search:e||void 0})},250)}onAuthor(e){this.state.patchFilters({author:e||void 0})}onSince(e){this.state.patchFilters({since:e||void 0})}onUntil(e){this.state.patchFilters({until:e||void 0})}onFile(e){this.state.patchFilters({file:e||void 0})}toggleSearchMode(){let e=this.state.searchMode()==="classic"?"nl":"classic";this.state.searchMode.set(e),e==="classic"&&this.state.nlInterpretation.set(null),this.state.patchFilters({})}toggleViewMode(){this.state.viewMode.set(this.state.viewMode()==="flat"?"grouped":"flat")}isTyping(e){return e instanceof HTMLElement?["INPUT","TEXTAREA","SELECT"].includes(e.tagName)||e.isContentEditable:!1}static \u0275fac=function(t){return new(t||n)};static \u0275cmp=C({type:n,selectors:[["app-toolbar"]],viewQuery:function(t,i){if(t&1&&D(De,5),t&2){let s;L(s=H())&&(i.searchEl=s.first)}},hostBindings:function(t,i){t&1&&d("keydown",function(p){return i.onKeydown(p)},ie)},decls:43,vars:25,consts:[["searchInput",""],[1,"toolbar"],[1,"brand"],["aria-hidden","true",1,"brand-mark"],[1,"brand-text"],[1,"brand-title"],["class","brand-sub",4,"ngIf"],[1,"nav"],["routerLink","/","routerLinkActive","active",3,"routerLinkActiveOptions"],["routerLink","/timeline","routerLinkActive","active"],["routerLink","/insights","routerLinkActive","active"],[1,"filters"],[1,"search"],["type","button",1,"search-mode",3,"click","title"],[4,"ngIf"],["type","text","aria-label","Search commits",1,"search-input",3,"ngModelChange","placeholder","ngModel"],["class","kbd",4,"ngIf"],["aria-label","Filter by author",1,"select",3,"ngModelChange","ngModel"],["value",""],[3,"value",4,"ngFor","ngForOf"],["type","date","aria-label","Since date",1,"input","date",3,"ngModelChange","ngModel"],["type","date","aria-label","Until date",1,"input","date",3,"ngModelChange","ngModel"],["type","text","placeholder","path/to/file","aria-label","Filter by file path",1,"input",3,"ngModelChange","ngModel"],[1,"actions"],[1,"btn","btn-ghost","view-toggle",3,"click","title"],["title","Command palette (\u2318K)",1,"btn","btn-ghost","btn-icon",3,"click"],["viewBox","0 0 24 24","width","16","height","16","aria-hidden","true"],["fill","currentColor","d","M3 6a3 3 0 0 1 3-3h12a3 3 0 0 1 3 3v12a3 3 0 0 1-3 3H6a3 3 0 0 1-3-3Zm3-1a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1Zm2 4h2v2H8Zm4 0h6v2h-6Zm-4 4h6v2H8Zm8 0h2v2h-2Z"],["title","Keyboard shortcuts (?)",1,"btn","btn-ghost","btn-icon",3,"click"],["fill","currentColor","d","M11 18h2v-2h-2Zm1-16a8 8 0 0 0-8 8h2a6 6 0 1 1 9.6 4.8c-1.06.8-1.6 1.42-1.6 3.2v.5h-2v-.5c0-2.6.94-3.5 2.13-4.39A4 4 0 1 0 8 10H6a6 6 0 0 1 6-8Z"],[1,"btn","btn-ghost","btn-icon",3,"click","title"],["viewBox","0 0 24 24","width","16","height","16","aria-hidden","true",4,"ngIf"],["class","nl-chips",4,"ngIf"],[1,"brand-sub"],["viewBox","0 0 20 20","width","14","height","14","aria-hidden","true"],["fill","currentColor","d","M9 2a7 7 0 1 1-4.32 12.5l-3.1 3.09a1 1 0 0 1-1.42-1.42l3.1-3.09A7 7 0 0 1 9 2Zm0 2a5 5 0 1 0 0 10A5 5 0 0 0 9 4Z"],[1,"ai-pill"],[1,"kbd"],[3,"value"],["fill","currentColor","d","M12 4V2m0 20v-2m8-8h2M2 12h2m13.66-6.34 1.42-1.42M4.92 19.08l1.42-1.42m0-11.32L4.92 4.92m14.16 14.16-1.42-1.42M12 7a5 5 0 1 1 0 10 5 5 0 0 1 0-10Z"],["fill","currentColor","d","M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79Z"],[1,"nl-chips"],[1,"chip-label"],["class","chip",4,"ngIf"],["class","chip",4,"ngFor","ngForOf"],["class","chip muted",4,"ngIf"],[1,"chip"],[1,"chip","muted"]],template:function(t,i){if(t&1){let s=x();r(0,"header",1)(1,"div",2)(2,"span",3),l(3,"\u2387"),o(),r(4,"div",4)(5,"span",5),l(6,"Git History"),o(),u(7,He,2,1,"span",6),o()(),r(8,"nav",7)(9,"a",8),l(10,"History"),o(),r(11,"a",9),l(12,"Timeline"),o(),r(13,"a",10),l(14,"Insights"),o()(),r(15,"div",11)(16,"label",12)(17,"button",13),d("click",function(){return m(s),g(i.toggleSearchMode())}),u(18,Ae,3,0,"ng-container",14)(19,ze,3,0,"ng-container",14),o(),r(20,"input",15,0),d("ngModelChange",function(v){return m(s),g(i.onSearchInput(v))}),o(),u(22,Re,2,0,"kbd",16),o(),r(23,"select",17),d("ngModelChange",function(v){return m(s),g(i.onAuthor(v))}),r(24,"option",18),l(25,"All authors"),o(),u(26,Be,2,2,"option",19),o(),r(27,"input",20),d("ngModelChange",function(v){return m(s),g(i.onSince(v))}),o(),r(28,"input",21),d("ngModelChange",function(v){return m(s),g(i.onUntil(v))}),o(),r(29,"input",22),d("ngModelChange",function(v){return m(s),g(i.onFile(v))}),o()(),r(30,"div",23)(31,"button",24),d("click",function(){return m(s),g(i.toggleViewMode())}),l(32),o(),r(33,"button",25),d("click",function(){return m(s),g(i.state.paletteOpen.set(!0))}),O(),r(34,"svg",26),b(35,"path",27),o()(),$(),r(36,"button",28),d("click",function(){return m(s),g(i.state.shortcutsOpen.set(!0))}),O(),r(37,"svg",26),b(38,"path",29),o()(),$(),r(39,"button",30),d("click",function(){return m(s),g(i.theme.cycle())}),u(40,Ke,2,0,"svg",31)(41,je,2,0,"svg",31),o()()(),u(42,$e,8,5,"div",32)}t&2&&(a(7),c("ngIf",i.totalLabel()),a(2),c("routerLinkActiveOptions",oe(24,Le)),a(7),A("search-nl",i.state.searchMode()==="nl"),a(),c("title",i.searchModeTooltip()),E("aria-label",i.searchModeTooltip()),a(),c("ngIf",i.state.searchMode()==="classic"),a(),c("ngIf",i.state.searchMode()==="nl"),a(),c("placeholder",i.searchPlaceholder())("ngModel",i.searchValue()),a(2),c("ngIf",!i.searchValue()),a(),c("ngModel",i.state.filters().author??""),a(3),c("ngForOf",i.state.authors()),a(),c("ngModel",i.state.filters().since??""),a(),c("ngModel",i.state.filters().until??""),a(),c("ngModel",i.state.filters().file??""),a(2),c("title",i.viewModeTooltip()),E("aria-label",i.viewModeTooltip()),a(),N(" ",i.state.viewMode()==="grouped"?"Grouped":"Flat"," "),a(7),c("title",i.themeLabel()),E("aria-label",i.themeLabel()),a(),c("ngIf",i.theme.resolved()==="light"),a(),c("ngIf",i.theme.resolved()==="dark"),a(),c("ngIf",i.state.searchMode()==="nl"&&i.state.nlInterpretation()))},dependencies:[w,P,k,K,fe,_e,z,he,R,B,me,ge],styles:["[_nghost-%COMP%]{display:block;position:sticky;top:0;z-index:50;background:color-mix(in oklab,var(--bg-surface) 92%,transparent);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border-bottom:1px solid var(--border-soft)}.toolbar[_ngcontent-%COMP%]{display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:1rem;padding:.6rem 1rem}.brand[_ngcontent-%COMP%]{display:flex;align-items:center;gap:.6rem;padding-right:.5rem}.brand-mark[_ngcontent-%COMP%]{width:32px;height:32px;border-radius:8px;display:grid;place-items:center;background:linear-gradient(135deg,var(--accent),#06b6d4);color:var(--accent-fg);font-weight:700;font-size:18px}.brand-text[_ngcontent-%COMP%]{display:flex;flex-direction:column;line-height:1.1}.brand-title[_ngcontent-%COMP%]{font-weight:600}.brand-sub[_ngcontent-%COMP%]{font-size:11px;color:var(--fg-muted)}.filters[_ngcontent-%COMP%]{display:flex;gap:.5rem;align-items:center;flex-wrap:wrap;min-width:0}.search[_ngcontent-%COMP%]{position:relative;display:flex;align-items:center;gap:.4rem;flex:1 1 240px;min-width:200px;max-width:420px;padding:0 .6rem;background:var(--bg-surface);border:1px solid var(--border-soft);border-radius:var(--radius-sm);color:var(--fg-muted)}.search[_ngcontent-%COMP%]:focus-within{border-color:var(--border-focus);box-shadow:0 0 0 3px #6366f12e}.search-input[_ngcontent-%COMP%]{flex:1;border:0;outline:0;background:transparent;color:var(--fg-primary);font-size:13px;padding:.45rem 0}.search-input[_ngcontent-%COMP%]::placeholder{color:var(--fg-subtle)}.search[_ngcontent-%COMP%] .kbd[_ngcontent-%COMP%]{margin-left:.4rem}.date[_ngcontent-%COMP%]{width:9rem}.actions[_ngcontent-%COMP%]{display:flex;gap:.3rem;align-items:center}.nav[_ngcontent-%COMP%]{display:flex;gap:.25rem;padding:.5rem 1rem 0}.nav[_ngcontent-%COMP%] a[_ngcontent-%COMP%]{font-size:12px;color:var(--fg-muted);text-decoration:none;padding:.3rem .7rem;border-radius:var(--radius-sm);transition:background .15s ease,color .15s ease}.nav[_ngcontent-%COMP%] a[_ngcontent-%COMP%]:hover{background:var(--bg-elevated);color:var(--fg-primary)}.nav[_ngcontent-%COMP%] a.active[_ngcontent-%COMP%]{background:var(--bg-elevated);color:var(--accent);font-weight:600}.search-mode[_ngcontent-%COMP%]{background:transparent;border:0;padding:0;cursor:pointer;color:var(--fg-muted);display:flex;align-items:center}.search-mode[_ngcontent-%COMP%]:hover{color:var(--fg-primary)}.search.search-nl[_ngcontent-%COMP%]{border-color:var(--accent);box-shadow:0 0 0 2px color-mix(in oklab,var(--accent) 20%,transparent)}.ai-pill[_ngcontent-%COMP%]{font-size:10px;font-weight:700;letter-spacing:.04em;background:var(--accent);color:var(--accent-fg);padding:1px 5px;border-radius:4px}.view-toggle[_ngcontent-%COMP%]{font-size:11px;letter-spacing:.04em;text-transform:uppercase;padding:.35rem .6rem}.nl-chips[_ngcontent-%COMP%]{display:flex;flex-wrap:wrap;align-items:center;gap:.4rem;padding:.4rem 1rem;border-bottom:1px solid var(--border-soft);background:var(--bg-surface);font-size:11px}.chip-label[_ngcontent-%COMP%]{color:var(--fg-muted);margin-right:.2rem}.chip[_ngcontent-%COMP%]{background:var(--bg-elevated);border:1px solid var(--border-soft);padding:2px 8px;border-radius:999px;color:var(--fg-secondary)}.chip.muted[_ngcontent-%COMP%]{font-style:italic;color:var(--fg-subtle)}"],changeDetection:0})};var Q=class n{http=_(le);base="/api";naturalLanguage(e,t=1,i=100){let s=new se().set("q",e).set("page",String(t)).set("pageSize",String(i));return this.http.get(`${this.base}/search`,{params:s})}static \u0275fac=function(t){return new(t||n)};static \u0275prov=ne({token:n,factory:n.\u0275fac,providedIn:"root"})};function Je(n,e){if(n&1&&(r(0,"div",2)(1,"span"),l(2),o()()),n&2){let t=e.ngIf;a(2),f(t)}}function We(n,e){n&1&&(r(0,"div",3),b(1,"span",4),l(2," Loading commits\u2026 "),o())}var U=class n{state=_(S);git=_(Ce);search=_(Q);commitsResp=ve(be(this.state.filters).pipe(ee(200),te(e=>(this.state.loading.set(!0),this.state.error.set(null),(this.state.searchMode()==="nl"&&(e.search||"").trim().length>0?this.search.naturalLanguage(e.search||"",e.page,e.pageSize):this.git.getCommits(e)).pipe(Y(p=>(this.state.error.set(this.errorMessage(p)),this.state.loading.set(!1),X(null))))))),{initialValue:null});authorsLoaded=T(!1);constructor(){M(()=>{let e=this.commitsResp();if(!e)return;this.state.commits.set(e.commits),this.state.total.set(e.total),this.state.page.set(e.page),this.state.pageSize.set(e.pageSize),this.state.loading.set(!1);let t=e.parsedQuery;this.state.nlInterpretation.set(t??null),!this.state.selectedHash()&&e.commits.length&&this.state.selectHash(e.commits[0].hash)}),M(()=>{this.commitsResp()&&!this.authorsLoaded()&&(this.authorsLoaded.set(!0),this.git.getAuthors().subscribe({next:e=>this.state.authors.set(e),error:()=>this.state.authors.set([])}),this.git.getBranches().subscribe({next:e=>this.state.branches.set(e),error:()=>this.state.branches.set([])}),this.git.getTags().subscribe({next:e=>this.state.tags.set(e),error:()=>this.state.tags.set([])}))})}errorMessage(e){if(e&&typeof e=="object"&&"error"in e){let t=e.error;if(t?.error)return t.error}return e instanceof Error?e.message:"Failed to load commits."}static \u0275fac=function(t){return new(t||n)};static \u0275cmp=C({type:n,selectors:[["app-root"]],decls:6,vars:2,consts:[["class","status-bar",4,"ngIf"],["class","loading","aria-live","polite",4,"ngIf"],[1,"status-bar"],["aria-live","polite",1,"loading"],[1,"spinner"]],template:function(t,i){t&1&&(b(0,"app-toolbar"),u(1,Je,3,1,"div",0),b(2,"router-outlet"),u(3,We,3,0,"div",1),b(4,"app-command-palette")(5,"app-shortcuts-modal")),t&2&&(a(),c("ngIf",i.state.error()),a(2),c("ngIf",i.state.loading()))},dependencies:[w,k,de,G,j,Z],styles:["[_nghost-%COMP%]{display:flex;flex-direction:column;height:100vh;width:100vw;overflow:hidden;background:var(--bg-app);color:var(--fg-primary)}.status-bar[_ngcontent-%COMP%]{padding:.5rem 1rem;background:#dc26261a;color:var(--danger);border-bottom:1px solid var(--border-soft);font-size:13px}.loading[_ngcontent-%COMP%]{position:fixed;bottom:1rem;right:1rem;display:flex;align-items:center;gap:.5rem;padding:.5rem .85rem;background:var(--bg-elevated);border:1px solid var(--border-soft);border-radius:var(--radius-md);box-shadow:var(--shadow-md);font-size:12px;color:var(--fg-secondary);z-index:80}.spinner[_ngcontent-%COMP%]{width:14px;height:14px;border:2px solid var(--border-strong);border-top-color:var(--accent);border-radius:50%;animation:_ngcontent-%COMP%_spin .7s linear infinite}@keyframes _ngcontent-%COMP%_spin{to{transform:rotate(360deg)}}"],changeDetection:0})};ae(U,Me).catch(n=>console.error(n));
@@ -0,0 +1 @@
1
+ *,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.visible{visibility:visible}.invisible{visibility:hidden}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.block{display:block}.flex{display:flex}.table{display:table}.grid{display:grid}.hidden{display:none}.flex-shrink{flex-shrink:1}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.resize{resize:both}.flex-wrap{flex-wrap:wrap}.border{border-width:1px}.uppercase{text-transform:uppercase}.italic{font-style:italic}.underline{text-decoration-line:underline}.shadow{--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / .1), 0 1px 2px -1px rgb(0 0 0 / .1);--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.outline{outline-style:solid}.blur{--tw-blur: blur(8px);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-filter{-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}:root{color-scheme:light;--bg-app: #f7f8fa;--bg-surface: #ffffff;--bg-surface-2: #f3f4f6;--bg-elevated: #ffffff;--bg-hover: #eef2ff;--bg-selected: #e0e7ff;--bg-overlay: rgba(15, 23, 42, .45);--fg-primary: #0f172a;--fg-secondary: #475569;--fg-muted: #64748b;--fg-subtle: #94a3b8;--fg-inverted: #ffffff;--border-soft: #e2e8f0;--border-strong: #cbd5e1;--border-focus: #6366f1;--accent: #4f46e5;--accent-hover: #4338ca;--accent-soft: #eef2ff;--accent-fg: #ffffff;--success: #16a34a;--warning: #d97706;--danger: #dc2626;--diff-add-bg: #dcfce7;--diff-add-fg: #14532d;--diff-add-gutter: #86efac;--diff-del-bg: #fee2e2;--diff-del-fg: #7f1d1d;--diff-del-gutter: #fca5a5;--diff-hunk-bg: #f1f5f9;--diff-hunk-fg: #475569;--graph-guide: rgba(148, 163, 184, .28);--graph-row-alt: rgba(15, 23, 42, .025);--graph-row-hover: rgba(79, 70, 229, .08);--graph-row-selected: rgba(79, 70, 229, .14);--graph-node-ring: #ffffff;--graph-shadow: rgba(15, 23, 42, .12);--shadow-sm: 0 1px 2px rgba(15, 23, 42, .06);--shadow-md: 0 4px 12px rgba(15, 23, 42, .08);--shadow-lg: 0 12px 32px rgba(15, 23, 42, .12);--radius-sm: 6px;--radius-md: 10px;--radius-lg: 14px;--font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, "Cascadia Mono", "Liberation Mono", "Courier New", monospace}:root.dark{color-scheme:dark;--bg-app: #0b1020;--bg-surface: #111827;--bg-surface-2: #0f172a;--bg-elevated: #1f2937;--bg-hover: #1e293b;--bg-selected: #312e81;--bg-overlay: rgba(2, 6, 23, .6);--fg-primary: #f8fafc;--fg-secondary: #cbd5e1;--fg-muted: #94a3b8;--fg-subtle: #64748b;--fg-inverted: #0b1020;--border-soft: #1f2937;--border-strong: #334155;--border-focus: #818cf8;--accent: #818cf8;--accent-hover: #a5b4fc;--accent-soft: #1e1b4b;--accent-fg: #0b1020;--success: #4ade80;--warning: #fbbf24;--danger: #f87171;--diff-add-bg: rgba(34, 197, 94, .16);--diff-add-fg: #bbf7d0;--diff-add-gutter: #166534;--diff-del-bg: rgba(239, 68, 68, .18);--diff-del-fg: #fecaca;--diff-del-gutter: #7f1d1d;--diff-hunk-bg: #1f2937;--diff-hunk-fg: #cbd5e1;--graph-guide: rgba(148, 163, 184, .22);--graph-row-alt: rgba(248, 250, 252, .025);--graph-row-hover: rgba(129, 140, 248, .12);--graph-row-selected: rgba(129, 140, 248, .2);--graph-node-ring: #111827;--graph-shadow: rgba(0, 0, 0, .45);--shadow-sm: 0 1px 2px rgba(0, 0, 0, .45);--shadow-md: 0 6px 16px rgba(0, 0, 0, .45);--shadow-lg: 0 18px 40px rgba(0, 0, 0, .55)}*,*:before,*:after{box-sizing:border-box}html,body{height:100%}body{margin:0;font-family:var(--font-sans);font-size:14px;line-height:1.5;color:var(--fg-primary);background:var(--bg-app);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-rendering:optimizeLegibility}::selection{background:var(--accent);color:var(--accent-fg)}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-thumb{background:var(--border-strong);border-radius:999px;border:2px solid transparent;background-clip:padding-box}::-webkit-scrollbar-track{background:transparent}:focus-visible{outline:2px solid var(--border-focus);outline-offset:2px}button{font-family:inherit}.btn{display:inline-flex;align-items:center;justify-content:center;gap:.4rem;padding:.45rem .85rem;font-size:13px;font-weight:500;border-radius:var(--radius-sm);background:var(--bg-surface-2);color:var(--fg-primary);border:1px solid var(--border-soft);cursor:pointer;transition:background .12s,border-color .12s,color .12s,transform 60ms}.btn:hover{background:var(--bg-hover);border-color:var(--border-strong)}.btn:active{transform:translateY(1px)}.btn-primary{background:var(--accent);color:var(--accent-fg);border-color:transparent}.btn-primary:hover{background:var(--accent-hover)}.btn-ghost{background:transparent;border-color:transparent}.btn-ghost:hover{background:var(--bg-hover)}.btn-icon{width:32px;padding:0;height:32px}.input,.select{background:var(--bg-surface);color:var(--fg-primary);border:1px solid var(--border-soft);border-radius:var(--radius-sm);padding:.4rem .6rem;font-size:13px;outline:none;min-height:32px}.input::placeholder{color:var(--fg-subtle)}.input:focus,.select:focus{border-color:var(--border-focus);box-shadow:0 0 0 3px #6366f12e}.kbd{display:inline-flex;align-items:center;justify-content:center;min-width:22px;padding:1px 6px;font-family:var(--font-mono);font-size:11px;font-weight:600;color:var(--fg-secondary);background:var(--bg-surface);border:1px solid var(--border-strong);border-bottom-width:2px;border-radius:4px}.divider{height:1px;background:var(--border-soft)}.hljs{background:transparent;color:var(--fg-primary)}.hljs-keyword,.hljs-selector-tag,.hljs-meta-keyword,.hljs-doctag,.hljs-section,.hljs-name{color:#c084fc}.dark .hljs-keyword,.dark .hljs-selector-tag,.dark .hljs-meta-keyword,.dark .hljs-doctag,.dark .hljs-section,.dark .hljs-name{color:#d8b4fe}.hljs-string,.hljs-attr,.hljs-symbol,.hljs-bullet,.hljs-addition{color:#15803d}.dark .hljs-string,.dark .hljs-attr,.dark .hljs-symbol,.dark .hljs-bullet,.dark .hljs-addition{color:#86efac}.hljs-number,.hljs-literal,.hljs-link{color:#b45309}.dark .hljs-number,.dark .hljs-literal,.dark .hljs-link{color:#fcd34d}.hljs-comment,.hljs-quote{color:var(--fg-subtle);font-style:italic}.hljs-title,.hljs-class .hljs-title,.hljs-type{color:#1d4ed8}.dark .hljs-title,.dark .hljs-class .hljs-title,.dark .hljs-type{color:#93c5fd}.hljs-deletion{color:#b91c1c}.dark .hljs-deletion{color:#fca5a5}.cdk-overlay-dark-backdrop{background:var(--bg-overlay);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}
@@ -0,0 +1,57 @@
1
+ import type { Commit, DiffFile } from './gitService';
2
+ export interface ContributorStat {
3
+ author: string;
4
+ email: string;
5
+ commits: number;
6
+ firstCommit: string;
7
+ lastCommit: string;
8
+ }
9
+ export interface FileChurn {
10
+ file: string;
11
+ commits: number;
12
+ additions: number;
13
+ deletions: number;
14
+ lastTouched: string;
15
+ authors: number;
16
+ }
17
+ export interface RiskyFile {
18
+ file: string;
19
+ riskScore: number;
20
+ reason: string;
21
+ commits: number;
22
+ authors: number;
23
+ churn: number;
24
+ }
25
+ export interface InsightsBundle {
26
+ windowStart: string | null;
27
+ windowEnd: string | null;
28
+ totalCommits: number;
29
+ totalAuthors: number;
30
+ topContributors: ContributorStat[];
31
+ hotspots: FileChurn[];
32
+ churnByDay: Array<{
33
+ date: string;
34
+ commits: number;
35
+ additions: number;
36
+ deletions: number;
37
+ }>;
38
+ riskyFiles: RiskyFile[];
39
+ }
40
+ export declare function computeContributorStats(commits: Commit[]): ContributorStat[];
41
+ /**
42
+ * Compute file churn from a sequence of {commit, files}. Caller is expected to
43
+ * fetch diff for each commit (potentially expensively); this is a pure aggregator.
44
+ */
45
+ export declare function computeFileChurn(pairs: Array<{
46
+ commit: Commit;
47
+ files: DiffFile[];
48
+ }>): FileChurn[];
49
+ export declare function computeChurnByDay(pairs: Array<{
50
+ commit: Commit;
51
+ files: DiffFile[];
52
+ }>): InsightsBundle['churnByDay'];
53
+ /**
54
+ * Risk score: heuristic combining churn density, contributor diversity,
55
+ * and recency. Inspired by Microsoft Research's "fault density" findings.
56
+ */
57
+ export declare function computeRiskyFiles(churn: FileChurn[], limit?: number): RiskyFile[];
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.computeContributorStats = computeContributorStats;
4
+ exports.computeFileChurn = computeFileChurn;
5
+ exports.computeChurnByDay = computeChurnByDay;
6
+ exports.computeRiskyFiles = computeRiskyFiles;
7
+ function computeContributorStats(commits) {
8
+ const map = new Map();
9
+ for (const c of commits) {
10
+ const key = c.authorEmail || c.author;
11
+ const cur = map.get(key);
12
+ if (cur) {
13
+ cur.commits++;
14
+ if (c.date > cur.lastCommit)
15
+ cur.lastCommit = c.date;
16
+ if (c.date < cur.firstCommit)
17
+ cur.firstCommit = c.date;
18
+ }
19
+ else {
20
+ map.set(key, {
21
+ author: c.author,
22
+ email: c.authorEmail,
23
+ commits: 1,
24
+ firstCommit: c.date,
25
+ lastCommit: c.date
26
+ });
27
+ }
28
+ }
29
+ return Array.from(map.values()).sort((a, b) => b.commits - a.commits);
30
+ }
31
+ /**
32
+ * Compute file churn from a sequence of {commit, files}. Caller is expected to
33
+ * fetch diff for each commit (potentially expensively); this is a pure aggregator.
34
+ */
35
+ function computeFileChurn(pairs) {
36
+ const map = new Map();
37
+ for (const { commit, files } of pairs) {
38
+ for (const f of files) {
39
+ const key = f.file;
40
+ let cur = map.get(key);
41
+ if (!cur) {
42
+ cur = {
43
+ file: key,
44
+ commits: 0,
45
+ additions: 0,
46
+ deletions: 0,
47
+ lastTouched: commit.date,
48
+ authors: 0,
49
+ authorSet: new Set()
50
+ };
51
+ map.set(key, cur);
52
+ }
53
+ cur.commits++;
54
+ cur.additions += f.additions || 0;
55
+ cur.deletions += f.deletions || 0;
56
+ cur.authorSet.add(commit.authorEmail || commit.author);
57
+ if (commit.date > cur.lastTouched)
58
+ cur.lastTouched = commit.date;
59
+ }
60
+ }
61
+ return Array.from(map.values())
62
+ .map(({ authorSet, ...rest }) => ({ ...rest, authors: authorSet.size }))
63
+ .sort((a, b) => b.commits - a.commits);
64
+ }
65
+ function computeChurnByDay(pairs) {
66
+ const map = new Map();
67
+ for (const { commit, files } of pairs) {
68
+ const day = (commit.date || '').slice(0, 10);
69
+ if (!day)
70
+ continue;
71
+ let cur = map.get(day);
72
+ if (!cur) {
73
+ cur = { commits: 0, additions: 0, deletions: 0 };
74
+ map.set(day, cur);
75
+ }
76
+ cur.commits++;
77
+ for (const f of files) {
78
+ cur.additions += f.additions || 0;
79
+ cur.deletions += f.deletions || 0;
80
+ }
81
+ }
82
+ return Array.from(map.entries())
83
+ .map(([date, v]) => ({ date, ...v }))
84
+ .sort((a, b) => a.date.localeCompare(b.date));
85
+ }
86
+ /**
87
+ * Risk score: heuristic combining churn density, contributor diversity,
88
+ * and recency. Inspired by Microsoft Research's "fault density" findings.
89
+ */
90
+ function computeRiskyFiles(churn, limit = 20) {
91
+ if (churn.length === 0)
92
+ return [];
93
+ const maxCommits = Math.max(...churn.map((c) => c.commits));
94
+ const maxChurn = Math.max(...churn.map((c) => c.additions + c.deletions));
95
+ const now = Date.now();
96
+ return churn
97
+ .map((c) => {
98
+ const churnRaw = c.additions + c.deletions;
99
+ const norm = 0.4 * (c.commits / Math.max(1, maxCommits)) +
100
+ 0.4 * (churnRaw / Math.max(1, maxChurn)) +
101
+ 0.2 * Math.min(1, c.authors / 5);
102
+ const ageDays = (now - new Date(c.lastTouched || 0).getTime()) / (1000 * 60 * 60 * 24);
103
+ const recencyBoost = ageDays < 30 ? 0.15 : ageDays < 90 ? 0.08 : 0;
104
+ const score = Math.min(1, norm + recencyBoost);
105
+ const reasons = [];
106
+ if (c.commits >= 0.5 * maxCommits)
107
+ reasons.push('high commit frequency');
108
+ if (churnRaw >= 0.5 * maxChurn)
109
+ reasons.push('large churn');
110
+ if (c.authors >= 5)
111
+ reasons.push('many contributors');
112
+ if (ageDays < 30)
113
+ reasons.push('recently modified');
114
+ return {
115
+ file: c.file,
116
+ riskScore: round(score, 3),
117
+ reason: reasons.join(', ') || 'general activity',
118
+ commits: c.commits,
119
+ authors: c.authors,
120
+ churn: churnRaw
121
+ };
122
+ })
123
+ .sort((a, b) => b.riskScore - a.riskScore)
124
+ .slice(0, limit);
125
+ }
126
+ function round(n, p) {
127
+ const f = 10 ** p;
128
+ return Math.round(n * f) / f;
129
+ }
130
+ //# sourceMappingURL=aggregations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aggregations.js","sourceRoot":"","sources":["../../src/backend/aggregations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ export interface AnnotationComment {
2
+ id: string;
3
+ author: string;
4
+ body: string;
5
+ createdAt: string;
6
+ }
7
+ export interface CommitAnnotations {
8
+ hash: string;
9
+ comments: AnnotationComment[];
10
+ }
11
+ /**
12
+ * Local-first annotations store. Per-repo JSON file under
13
+ * ~/.git-history-ui/<repo-hash>/annotations.json.
14
+ *
15
+ * Local-only: nothing is synced unless the user opts into a share server later.
16
+ */
17
+ export declare class AnnotationsStore {
18
+ private file;
19
+ private mu;
20
+ constructor(repoCwd: string);
21
+ list(hash: string): Promise<AnnotationComment[]>;
22
+ add(hash: string, input: {
23
+ author: string;
24
+ body: string;
25
+ }): Promise<AnnotationComment>;
26
+ remove(hash: string, id: string): Promise<boolean>;
27
+ private load;
28
+ private save;
29
+ private withLock;
30
+ }
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.AnnotationsStore = void 0;
7
+ const crypto_1 = __importDefault(require("crypto"));
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const os_1 = __importDefault(require("os"));
10
+ const path_1 = __importDefault(require("path"));
11
+ const ROOT_DIR = path_1.default.join(os_1.default.homedir(), '.git-history-ui');
12
+ /**
13
+ * Local-first annotations store. Per-repo JSON file under
14
+ * ~/.git-history-ui/<repo-hash>/annotations.json.
15
+ *
16
+ * Local-only: nothing is synced unless the user opts into a share server later.
17
+ */
18
+ class AnnotationsStore {
19
+ file;
20
+ mu = Promise.resolve();
21
+ constructor(repoCwd) {
22
+ const id = crypto_1.default.createHash('sha256').update(path_1.default.resolve(repoCwd)).digest('hex').slice(0, 16);
23
+ this.file = path_1.default.join(ROOT_DIR, id, 'annotations.json');
24
+ }
25
+ async list(hash) {
26
+ const data = await this.load();
27
+ return data.byHash[hash] ?? [];
28
+ }
29
+ async add(hash, input) {
30
+ let result;
31
+ await this.withLock(async () => {
32
+ const data = await this.load();
33
+ const comment = {
34
+ id: crypto_1.default.randomUUID(),
35
+ author: input.author || 'anonymous',
36
+ body: input.body,
37
+ createdAt: new Date().toISOString()
38
+ };
39
+ const list = data.byHash[hash] ?? [];
40
+ list.push(comment);
41
+ data.byHash[hash] = list;
42
+ await this.save(data);
43
+ result = comment;
44
+ });
45
+ return result;
46
+ }
47
+ async remove(hash, id) {
48
+ let removed = false;
49
+ await this.withLock(async () => {
50
+ const data = await this.load();
51
+ const list = data.byHash[hash] ?? [];
52
+ const idx = list.findIndex((c) => c.id === id);
53
+ if (idx === -1)
54
+ return;
55
+ list.splice(idx, 1);
56
+ data.byHash[hash] = list;
57
+ await this.save(data);
58
+ removed = true;
59
+ });
60
+ return removed;
61
+ }
62
+ async load() {
63
+ try {
64
+ const raw = await fs_1.default.promises.readFile(this.file, 'utf8');
65
+ const parsed = JSON.parse(raw);
66
+ if (parsed?.version === 1 && parsed.byHash)
67
+ return parsed;
68
+ }
69
+ catch {
70
+ /* missing or corrupt -> default */
71
+ }
72
+ return { version: 1, byHash: {} };
73
+ }
74
+ async save(data) {
75
+ await fs_1.default.promises.mkdir(path_1.default.dirname(this.file), { recursive: true });
76
+ const tmp = `${this.file}.tmp-${process.pid}`;
77
+ await fs_1.default.promises.writeFile(tmp, JSON.stringify(data, null, 2), 'utf8');
78
+ await fs_1.default.promises.rename(tmp, this.file);
79
+ }
80
+ withLock(fn) {
81
+ const prev = this.mu;
82
+ let release;
83
+ this.mu = new Promise((resolve) => {
84
+ release = resolve;
85
+ });
86
+ return prev.then(fn).finally(() => release());
87
+ }
88
+ }
89
+ exports.AnnotationsStore = AnnotationsStore;
90
+ //# sourceMappingURL=annotations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"annotations.js","sourceRoot":"","sources":["../../src/backend/annotations.ts"],"names":[],"mappings":"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"}
@@ -63,6 +63,20 @@ export declare class GitService {
63
63
  getCommit(hash: string): Promise<Commit>;
64
64
  getAuthors(): Promise<string[]>;
65
65
  getDiff(hash: string): Promise<DiffFile[]>;
66
+ getRangeDiff(from: string, to: string): Promise<DiffFile[]>;
67
+ /** Resolve any ref (branch/tag/HEAD) to its commit at or before `atIso`. */
68
+ revAt(ref: string, atIso: string): Promise<string | null>;
69
+ /** Origin URL of the first remote (typically `origin`). */
70
+ getRemoteUrl(name?: string): Promise<string>;
71
+ getFileStats(filePath: string): Promise<{
72
+ file: string;
73
+ firstSeen: string;
74
+ lastTouched: string;
75
+ totalCommits: number;
76
+ contributors: string[];
77
+ }>;
78
+ /** Read the contents of a file at a specific commit. */
79
+ getFileAtCommit(hash: string, filePath: string): Promise<string>;
66
80
  getBlame(filePath: string): Promise<BlameLine[]>;
67
81
  getTags(): Promise<string[]>;
68
82
  getBranches(): Promise<string[]>;