Files
the-nexus/nexus/mnemosyne/__pycache__/archive.cpython-311.pyc

293 lines
39 KiB
Plaintext
Raw Normal View History

<EFBFBD>
d<><64>i<EFBFBD>c<00><01>l<00>dZddlmZddlZddlmZddlmZddlm Z ddl
m Z dZ Gd <09>d
<EFBFBD><00>Z dS) u<>MnemosyneArchive — core archive class.
The living holographic archive. Stores entries, maintains links,
and provides query interfaces for retrieving connected knowledge.
<EFBFBD>)<01> annotationsN)<01>Path)<01>Optional)<01> ArchiveEntry)<01>HolographicLinker<65>1c<01><00>eZdZdZdHdId<05>Zd<06>Zd<07>ZdJdKd<10>ZdLd<14>ZdMdNd<1A>Z dOdPd<1E>Z
dQdRd!<21>Z dSd#<23>Z dTd$<24>Z dUdVd)<29>ZdWd+<2B>ZedXd,<2C><04><00>Z dHdYd.<2E>ZdZd/<2F>Zd[d1<64>ZdQd\d4<64>ZdMd]d5<64>Zd^d6<64>Zd_d9<64>Zd_d:<3A>Zd_d;<3B>Z d`dadA<64>ZdbdC<64>ZdcdE<64>ZdHdddG<64>ZdS)e<>MnemosyneArchiveu<65>The holographic archive — stores and links entries.
Phase 1 uses JSON file storage. Phase 2 will integrate with
MemPalace (ChromaDB) for vector-semantic search.
N<> archive_path<74>Optional[Path]c<01><><00>|ptj<00><00>dz dz dz |_|jj<00>dd<04><05><00>t <00><00>|_i|_|<00><00><00>dS)Nz.hermes<65> mnemosynez archive.jsonT)<02>parents<74>exist_ok) r<00>home<6D>path<74>parent<6E>mkdirr<00>linker<65>_entries<65>_load)<02>selfr s <20>./tmp/mnemosyne-work/nexus/mnemosyne/archive.py<70>__init__zMnemosyneArchive.__init__sf<00><00> <20>Z<>D<EFBFBD>I<EFBFBD>K<EFBFBD>K<EFBFBD>)<29>$;<3B>k<EFBFBD>$I<>N<EFBFBD>$Z<><04> <09> <0C> <09><18><1E><1E>t<EFBFBD>d<EFBFBD><1E>;<3B>;<3B>;<3B>'<27>)<29>)<29><04> <0B>13<31><04> <0A> <0C>
<EFBFBD>
<EFBFBD> <0C> <0C> <0C> <0C> <0C>c<01>p<00>|j<00><00><00>r<> t|j<00><00>5}tj|<01><00>}ddd<00><00>n #1swxYwY|<02>dg<00><00>D]%}t j|<03><00>}||j|j <<00>&dS#tj
tf$rYdSwxYwdS)N<>entries) r<00>exists<74>open<65>json<6F>load<61>getr<00> from_dictr<00>id<69>JSONDecodeError<6F>KeyError)r<00>f<>data<74>
entry_data<EFBFBD>entrys rrzMnemosyneArchive._load!s<00><00> <0F>9<EFBFBD> <1B> <1B> <1D> <1D> <15> <15><19>$<24>)<29>_<EFBFBD>_<EFBFBD>(<28><01><1F>9<EFBFBD>Q<EFBFBD><<3C><<3C>D<EFBFBD>(<28>(<28>(<28>(<28>(<28>(<28>(<28>(<28>(<28>(<28>(<28><><EFBFBD><EFBFBD>(<28>(<28>(<28>(<28>"&<26>(<28>(<28>9<EFBFBD>b<EFBFBD>"9<>"9<>4<>4<>J<EFBFBD>(<28>2<>:<3A>><3E>><3E>E<EFBFBD>.3<EFBFBD>D<EFBFBD>M<EFBFBD>%<25>(<28>+<2B>+<2B>4<>4<><34><19>(<28>(<28>3<> <15> <15> <15><14><04><04> <15><><EFBFBD><EFBFBD> <15> s4<00>B<00>A<03> B<00>A<07>B<00>A<07>?B<00>B3<03>2B3c<01><00>d<01>|j<00><00><00>D<00><00>t|j<00><00>d<02>}t|jd<03><00>5}t j||d<04><05><00>ddd<00><00>dS#1swxYwYdS)Nc<01>6<00>g|]}|<01><00><00><00><02>S<00><00><01>to_dict<63><02>.0<EFBFBD>es r<00>
<listcomp>z*MnemosyneArchive._save.<locals>.<listcomp>.s <00><00>D<>D<>D<><01><01> <09> <09> <0B> <0B>D<>D<>Dr)r<00>count<6E>w<>)<01>indent)r<00>values<65>lenrrr <00>dump)rr(r's r<00>_savezMnemosyneArchive._save,s<><00><00>D<>D<>T<EFBFBD>]<5D>-A<>-A<>-C<>-C<>D<>D<>D<><18><14><1D>'<27>'<27>
<EFBFBD>
<EFBFBD><04><12>$<24>)<29>S<EFBFBD> !<21> !<21> )<29>Q<EFBFBD> <10>I<EFBFBD>d<EFBFBD>A<EFBFBD>a<EFBFBD> (<28> (<28> (<28> (<28> )<29> )<29> )<29> )<29> )<29> )<29> )<29> )<29> )<29> )<29> )<29> )<29><><EFBFBD><EFBFBD> )<29> )<29> )<29> )<29> )<29> )s<00>A3<03>3A7<07>:A7TFr*r<00> auto_link<6E>bool<6F> skip_dups<70>returnc<01><00>|r|<00>|j<00><00>}|r|S||j|j<|r?|j<00>|t |j<00><00><00><00><00><00><00>|<00><00><00>|S)a<>Add an entry to the archive. Auto-links to related entries.
Args:
entry: The entry to add.
auto_link: Whether to automatically compute holographic links.
skip_dups: If True, return existing entry instead of adding a duplicate
(same title+content hash).
Returns:
The added (or existing, if skip_dups=True and duplicate found) entry.
) <09> find_by_hash<73> content_hashrr$r<00> apply_links<6B>listr8r;)rr*r<r><00>existings r<00>addzMnemosyneArchive.add4s<><00><00> <15> <20><1B>(<28>(<28><15>);<3B><<3C><<3C>H<EFBFBD><17> <20><1F><0F>"'<27><04> <0A>e<EFBFBD>h<EFBFBD><1F> <14> I<01> <10>K<EFBFBD> #<23> #<23>E<EFBFBD>4<EFBFBD><04> <0A>0D<30>0D<30>0F<30>0F<30>+G<>+G<> H<> H<> H<> <0C>
<EFBFBD>
<EFBFBD> <0C> <0C> <0C><14> r<00>entry_id<69>str<74>Optional[ArchiveEntry]c<01>6<00>|j<00>|<01><00>S<00>N)rr")rrGs rr"zMnemosyneArchive.getJs<00><00><13>}<7D> <20> <20><18>*<2A>*<2A>*r<00>
<00>query<72>limit<69>int<6E>list[ArchiveEntry]c<01><><00><07>t|<01><00><00><00><00><00><00><00>}g}|j<00><00><00>D]x}|j<00>d|j<00>dd<01>|j<00><00><00><00><05><00><00><00>t<00>fd<02>|D<00><00><00><00>}|dkr|<04>
||f<02><00><00>y|<04> d<04>d<05><06><00>d<07>|d|<02>D<00><00>S) z0Simple keyword search across titles and content.<2E> c3<01>$<00>K<00>|]
}|<01>v<00>dV<00><00> dS)<02>Nr-)r1<00>t<>texts <20>r<00> <genexpr>z*MnemosyneArchive.search.<locals>.<genexpr>Ss'<00><><00><00><00><<3C><<3C>Q<EFBFBD>!<21>t<EFBFBD>)<29>)<29>q<EFBFBD>)<29>)<29>)<29>)<29><<3C><rrc<01><00>|dS<00>Nrr-<00><01>xs r<00><lambda>z)MnemosyneArchive.search.<locals>.<lambda>Vs
<00><00>!<21>A<EFBFBD>$<24>rT<><02>key<65>reversec<01><00>g|]\}}|<02><02>Sr-r-<00>r1<00>_r2s rr3z+MnemosyneArchive.search.<locals>.<listcomp>Ws<00><00>-<2D>-<2D>-<2D>d<EFBFBD>a<EFBFBD><11><01>-<2D>-<2D>-rN) <0C>set<65>lower<65>splitrr8<00>title<6C>content<6E>join<69>topics<63>sum<75>append<6E>sort)rrMrN<00> query_tokens<6E>scoredr*<00>hitsrVs @r<00>searchzMnemosyneArchive.searchMs<><00><><00><1A>5<EFBFBD>;<3B>;<3B>=<3D>=<3D>.<2E>.<2E>0<>0<>1<>1<> <0C><13><06><19>]<5D>)<29>)<29>+<2B>+<2B> -<2D> -<2D>E<EFBFBD><1B>k<EFBFBD>L<>L<>E<EFBFBD>M<EFBFBD>L<>L<>C<EFBFBD>H<EFBFBD>H<EFBFBD>U<EFBFBD>\<5C>4J<34>4J<34>L<>L<>R<>R<>T<>T<>D<EFBFBD><16><<3C><<3C><<3C><<3C>,<2C><<3C><<3C><<3C><<3C><<3C>D<EFBFBD><13>a<EFBFBD>x<EFBFBD>x<EFBFBD><16> <0A> <0A>t<EFBFBD>U<EFBFBD>m<EFBFBD>,<2C>,<2C>,<2C><><0E> <0B> <0B><0E><0E><04> <0B>5<>5<>5<>-<2D>-<2D>f<EFBFBD>V<EFBFBD>e<EFBFBD>V<EFBFBD>n<EFBFBD>-<2D>-<2D>-<2D>-r<><E79A99><EFBFBD><EFBFBD><EFBFBD>?<3F> threshold<6C>floatc
<01><00>tj|<01><00>}|sgSd<01>|jD<00><00>}|j<00><00><00>D] }|jD]}||vr||xxdz cc<<00><17>!t |<05><00><00>d<02><03><00>pd}g} |j<00><00><00>D]<5D>}tj|j<00>d|j<00>dd<04>|j <00><00><00><00><05><00>}
|
s<01>C||
z} ||
z} t| <0B><00>t| <0C><00>z } | |kr-||j |z dz}| <09> | |z|f<02><00><00><>| r,| <09> d<06>d<07><08><00>d <09>| d
|<02>D<00><00>S|<00>||<02> <0B><00>S) abSemantic search using holographic linker similarity.
Scores each entry by Jaccard similarity between query tokens and entry
tokens, then boosts entries with more inbound links (more "holographic").
Falls back to keyword search if no entries meet the similarity threshold.
Args:
query: Natural language query string.
limit: Maximum number of results to return.
threshold: Minimum Jaccard similarity to be considered a semantic match.
Returns:
List of ArchiveEntry sorted by combined relevance score, descending.
c<01><00>i|]}|d<00><02>S<00>rr-<00>r1<00>eids r<00>
<dictcomp>z4MnemosyneArchive.semantic_search.<locals>.<dictcomp>m<00><00><00>"C<>"C<>"C<>c<EFBFBD>3<EFBFBD><01>"C<>"C<>"CrrT)<01>defaultrRg<><67><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?c<01><00>|dSrYr-rZs rr\z2MnemosyneArchive.semantic_search.<locals>.<lambda><3E>s
<00><00>a<EFBFBD><01>d<EFBFBD>rTr]c<01><00>g|]\}}|<02><02>Sr-r-ras rr3z4MnemosyneArchive.semantic_search.<locals>.<listcomp><3E>s<00><00>1<>1<>1<>$<24>!<21>Q<EFBFBD>A<EFBFBD>1<>1<>1rN)rN)r<00> _tokenizerr8<00>links<6B>maxrfrgrhrir9r$rkrlrp)rrMrNrrrm<00>inboundr*<00> linked_id<69> max_inboundrn<00> entry_tokens<6E> intersection<6F>union<6F>jaccard<72>
link_boosts r<00>semantic_searchz MnemosyneArchive.semantic_searchYs<><00><00>)<29>2<>5<EFBFBD>9<>9<> <0C><1B> <16><15>I<EFBFBD>#D<01>"C<>T<EFBFBD>]<5D>"C<>"C<>"C<><07><19>]<5D>)<29>)<29>+<2B>+<2B> ,<2C> ,<2C>E<EFBFBD>"<22>[<5B> ,<2C> ,<2C> <09><1C><07>'<27>'<27><1B>I<EFBFBD>&<26>&<26>&<26>!<21>+<2B>&<26>&<26>&<26><> ,<2C><1A>'<27>.<2E>.<2E>*<2A>*<2A>A<EFBFBD>6<>6<>6<>;<3B>!<21> <0B><13><06><19>]<5D>)<29>)<29>+<2B>+<2B> =<3D> =<3D>E<EFBFBD>,<2C>6<>%<25>+<2B>7p<37>7p<37><05> <0A>7p<37>7p<37>X[<5B>X`<60>X`<60>af<61>am<61>Xn<58>Xn<58>7p<37>7p<37>q<>q<>L<EFBFBD><1F> <19><18>'<27>,<2C>6<>L<EFBFBD> <20><<3C>/<2F>E<EFBFBD><19>,<2C>'<27>'<27>#<23>e<EFBFBD>*<2A>*<2A>4<>G<EFBFBD><16>)<29>#<23>#<23>$<24>U<EFBFBD>X<EFBFBD>.<2E><1B><<3C>s<EFBFBD>B<>
<EFBFBD><16> <0A> <0A>w<EFBFBD><1A>3<>U<EFBFBD>;<3B><<3C><<3C><<3C><> <11> 2<> <12>K<EFBFBD>K<EFBFBD>N<EFBFBD>N<EFBFBD>D<EFBFBD>K<EFBFBD> 9<> 9<> 9<>1<>1<>&<26><16>%<25><16>.<2E>1<>1<>1<> 1<><14>{<7B>{<7B>5<EFBFBD><05>{<7B>.<2E>.<2E>.rrT<00>depthc<01><><00>t<00><00>}|h}g}t|<02><00>D]<5D>}t<00><00>}|D]<5D>}||vr<01>|<03>|<08><00>|j<00>|<08><00>} | rT| jD]L}
|
|vrF|j<00>|
<EFBFBD><00>} | r*|<05>| <0B><00>|<07>|
<EFBFBD><00><00>M<EFBFBD><4D>|}<04><>|S)z;Get entries linked to a given entry, up to specified depth.)rc<00>rangerFrr"rrk) rrGr<><00>visited<65>frontier<65>resultrb<00> next_frontierrxr*r<><00>linkeds r<00>
get_linkedzMnemosyneArchive.get_linked<65>s<><00><00><15>%<25>%<25><07><1C>:<3A><08><13><06><16>u<EFBFBD><1C><1C> %<25> %<25>A<EFBFBD><1F>E<EFBFBD>E<EFBFBD>M<EFBFBD><1F> =<3D> =<3D><03><16>'<27>><3E>><3E><1C><17> <0B> <0B>C<EFBFBD> <20> <20> <20><1C> <0A>)<29>)<29>#<23>.<2E>.<2E><05><18>=<3D>%*<2A>[<5B>=<3D>=<3D> <09>$<24>G<EFBFBD>3<>3<>%)<29>]<5D>%6<>%6<>y<EFBFBD>%A<>%A<>F<EFBFBD>%<25>=<3D> &<26> <0A> <0A>f<EFBFBD> 5<> 5<> 5<> -<2D> 1<> 1<>)<29> <<3C> <<3C> <<3C><><EFBFBD>$<24>H<EFBFBD>H<EFBFBD><15> r<00>topicc<01>v<00><02>|<01><00><00><00><02>fd<01>|j<00><00><00>D<00><00>S)z$Get all entries tagged with a topic.c<01>:<00><01>g|]}<01>d<00>|jD<00><00>v<00>|<01><02>S)c<01>6<00>g|]}|<01><00><00><00><02>Sr-<00>rd<00>r1rUs rr3z8MnemosyneArchive.by_topic.<locals>.<listcomp>.<listcomp><3E>s!<00><00>Da<44>Da<44>Da<44>ST<53>Q<EFBFBD>W<EFBFBD>W<EFBFBD>Y<EFBFBD>Y<EFBFBD>Da<44>Da<44>Dar<00>ri<00>r1r2<00> topic_lowers <20>rr3z-MnemosyneArchive.by_topic.<locals>.<listcomp><3E>s6<00><><00>b<>b<>b<>a<EFBFBD>[<5B>Da<44>Da<44>XY<58>X`<60>Da<44>Da<44>Da<44>5a<35>5a<35><01>5a<35>5a<35>5ar)rdrr8)rr<>r<>s @r<00>by_topiczMnemosyneArchive.by_topic<69>s8<00><><00><1B>k<EFBFBD>k<EFBFBD>m<EFBFBD>m<EFBFBD> <0B>b<>b<>b<>b<>4<EFBFBD>=<3D>/<2F>/<2F>1<>1<>b<>b<>b<>brc<01><><00>||jvrdS|j<00><00><00>D]%}||jvr|j<00>|<01><00><00>&|j|=|<00><00><00>dS)z<>Remove an entry and clean up all bidirectional links.
Returns True if the entry existed and was removed, False otherwise.
FT)rr8r<00>remover;)rrG<00>others rr<>zMnemosyneArchive.remove<76>ss<00><00>
<14>4<EFBFBD>=<3D> (<28> (<28><18>5<EFBFBD><19>]<5D>)<29>)<29>+<2B>+<2B> -<2D> -<2D>E<EFBFBD><17>5<EFBFBD>;<3B>&<26>&<26><15> <0B>"<22>"<22>8<EFBFBD>,<2C>,<2C>,<2C><> <10>M<EFBFBD>(<28> #<23> <0C>
<EFBFBD>
<EFBFBD> <0C> <0C> <0C><13>tr<00> Optional[str]ri<00>Optional[list[str]]<5D>dictc<01>\<00><04><05>t|j<00><00><00><00><00>}|rd<01>|D<00><00><00><04>fd<02>|D<00><00>}|rAt|<01><00><00><00><00><00><00><00><00><05>fd<03>|D<00><00>}t ||d<04>t|<03><00>d<05>|D<00><00>d<06>S)a)Export a filtered subset of the archive.
Args:
query: keyword filter applied to title + content (case-insensitive)
topics: list of topic tags; entries must match at least one
Returns a JSON-serialisable dict with an ``entries`` list and metadata.
c<01>6<00>h|]}|<01><00><00><00><02>Sr-r<>r<>s r<00> <setcomp>z*MnemosyneArchive.export.<locals>.<setcomp><3E>s <00><00>6<>6<>6<>!<21>A<EFBFBD>G<EFBFBD>G<EFBFBD>I<EFBFBD>I<EFBFBD>6<>6<>6rc<01>T<00><01>g|]$}t<00>fd<00>|jD<00><00><00><00><00>"|<01><02>%S)c3<01>D<00>K<00>|]}|<01><00><00><00>vV<00><00>dSrKr<>)r1rU<00> lower_topicss <20>rrWz5MnemosyneArchive.export.<locals>.<listcomp>.<genexpr><3E>s0<00><><00><00><00>C<>C<>Q<EFBFBD>q<EFBFBD>w<EFBFBD>w<EFBFBD>y<EFBFBD>y<EFBFBD>L<EFBFBD>0<>C<>C<>C<>C<>C<>Cr)<02>anyri)r1r2r<>s <20>rr3z+MnemosyneArchive.export.<locals>.<listcomp><3E>sN<00><><00><0E><0E><0E><17><16>C<>C<>C<>C<>!<21>(<28>C<>C<>C<>C<>C<><0E><11><0E><0E>rc<01>L<00><01><01>g|]<1F>t<00>fd<00><08>D<00><00><00><00><00><1D><01><02> S)c 3<01><><00>K<00>|]D}|<01>j<00>d<00>j<00>dd<00><00>j<00><00><00><00><05><00><00>vV<00><00>EdS)rRN)rfrgrhrird)r1<00>tokenr2s <20>rrWz5MnemosyneArchive.export.<locals>.<listcomp>.<genexpr><3E>sp<00><><00><00><00><12><12><1D><1A><01><07>J<>J<>!<21>)<29>J<>J<>c<EFBFBD>h<EFBFBD>h<EFBFBD>q<EFBFBD>x<EFBFBD>6H<36>6H<36>J<>J<>P<>P<>R<>R<>R<><12><12><12><12><12>r)r<>)r1r2rms @<40>rr3z+MnemosyneArchive.export.<locals>.<listcomp><3E>s`<00><><EFBFBD><00><0E><0E><0E><17><16><12><12><12><12>!-<2D><12><12><12><12><12><0E><11><0E><0E>r)rMric<01>6<00>g|]}|<01><00><00><00><02>Sr-r.r0s rr3z+MnemosyneArchive.export.<locals>.<listcomp><3E>s <00><00>8<>8<>8<><01><01> <09> <09> <0B> <0B>8<>8<>8r)<04>version<6F>filtersr4r)rDrr8rcrdre<00>_EXPORT_VERSIONr9)rrMri<00>
candidatesr<EFBFBD>rms @@r<00>exportzMnemosyneArchive.export<72>s<><00><><EFBFBD><00><1A>$<24>-<2D>.<2E>.<2E>0<>0<>1<>1<>
<EFBFBD> <11> <0E>6<>6<>v<EFBFBD>6<>6<>6<>L<EFBFBD><0E><0E><0E><0E>%<25><0E><0E><0E>J<EFBFBD>
<11> <0E><1E>u<EFBFBD>{<7B>{<7B>}<7D>}<7D>2<>2<>4<>4<>5<>5<>L<EFBFBD><0E><0E><0E><0E>%<25><0E><0E><0E>J<EFBFBD>'<27>!&<26>&<26>9<>9<><18><1A>_<EFBFBD>_<EFBFBD>8<>8<>Z<EFBFBD>8<>8<>8<> 
<EFBFBD>
<EFBFBD>
r<00>dict[str, int]c<01><><00>i}|j<00><00><00>D](}|jD]}|<01>|d<01><00>dz||<<00><1F>)t t |<01><00><00>d<03>d<04><05><00><00><00>S)uGReturn a dict mapping topic name → entry count, sorted by count desc.rrTc<01><00>|dS<00>NrTr-rZs rr\z/MnemosyneArchive.topic_counts.<locals>.<lambda><3E>s
<00><00><11>1<EFBFBD><14>rTr])rr8rir"r<><00>sorted<65>items)r<00>countsr*r<>s r<00> topic_countszMnemosyneArchive.topic_counts<74>s<00><00>!#<23><06><19>]<5D>)<29>)<29>+<2B>+<2B> 9<> 9<>E<EFBFBD><1E><1C> 9<> 9<><05> &<26>
<EFBFBD>
<EFBFBD>5<EFBFBD>!<21> 4<> 4<>q<EFBFBD> 8<><06>u<EFBFBD> <0A> <0A> 9<><13>F<EFBFBD>6<EFBFBD><<3C><<3C>><3E>><3E>~<7E>~<7E>t<EFBFBD>L<>L<>L<>M<>M<>Mrc<01>*<00>t|j<00><00>SrK)r9r)rs rr4zMnemosyneArchive.count<6E>s<00><00><12>4<EFBFBD>=<3D>!<21>!<21>!r<00> topic_filterc
<01>v<00> <0C>t|j<00><00><00><00><00>}|r"|<01><00><00><00> <0C> fd<01>|D<00><00>}d<02>|D<00><00>}d<03>|D<00><00>}t <00><00>}g}|D]<5D>}|jD]<5D>}||vr<01>t |j|<08><00>t|j|<08><00>f} | |vr<01>6|<05> | <09><00>|j<00>
|<08><00>}
|
rN|j <00> ||
<EFBFBD><00>} |<06> | d| dt| d<06><00>d<07><03><00><00><><EFBFBD><EFBFBD>||d<08>S) awExport the full connection graph for 3D constellation visualization.
Returns a dict with:
- nodes: list of {id, title, topics, source, created_at}
- edges: list of {source, target, weight} from holographic links
Args:
topic_filter: If set, only include entries matching this topic
and edges between them.
c<01>:<00><01>g|]}<01>d<00>|jD<00><00>v<00>|<01><02>S)c<01>6<00>g|]}|<01><00><00><00><02>Sr-r<>r<>s rr3z:MnemosyneArchive.graph_data.<locals>.<listcomp>.<listcomp><3E>s <00><00>"?<3F>"?<3F>"?<3F><11>1<EFBFBD>7<EFBFBD>7<EFBFBD>9<EFBFBD>9<EFBFBD>"?<3F>"?<3F>"?rr<>r<>s <20>rr3z/MnemosyneArchive.graph_data.<locals>.<listcomp><3E>s?<00><><00><0E><0E><0E><17><1E>"?<3F>"?<3F>a<EFBFBD>h<EFBFBD>"?<3F>"?<3F>"?<3F>?<3F>?<3F><12>?<3F>?<3F>?rc<01><00>h|] }|j<00><02>
Sr-<00>r$r0s rr<>z.MnemosyneArchive.graph_data.<locals>.<setcomp><3E>s<00><00>+<2B>+<2B>+<2B>a<EFBFBD>Q<EFBFBD>T<EFBFBD>+<2B>+<2B>+rc<01>P<00>g|]#}|j|j|j|j|jd<00><05><02>$S)<01>r$rfri<00>source<63>
created_atr<EFBFBD>r0s rr3z/MnemosyneArchive.graph_data.<locals>.<listcomp><3E>sJ<00><00> 
<EFBFBD> 
<EFBFBD> 
<EFBFBD><12> <18>d<EFBFBD><1A><17><1B>(<28><1B>(<28><1F>l<EFBFBD>  <0E> <0E> 
<EFBFBD> 
<EFBFBD> 
rrrT<00>)r<><00>target<65>weight)<02>nodes<65>edges)rDrr8rdrcr<00>minr$r<>rFr"r<00>compute_similarityrk<00>round) rr<>r<00> entry_idsr<73><00>
seen_edgesr<EFBFBD>r2r<><00>pairr<72>r<>r<>s @r<00>
graph_datazMnemosyneArchive.graph_data<74>s<><00><><00><17>t<EFBFBD>}<7D>+<2B>+<2B>-<2D>-<2D>.<2E>.<2E><07> <17> <0E>&<26>,<2C>,<2C>.<2E>.<2E>K<EFBFBD><0E><0E><0E><0E>"<22><0E><0E><0E>G<EFBFBD>
,<2C>+<2B>7<EFBFBD>+<2B>+<2B>+<2B> <09> 
<EFBFBD> 
<EFBFBD><1D> 
<EFBFBD> 
<EFBFBD> 
<EFBFBD><05>,/<2F>5<EFBFBD>5<EFBFBD>
<EFBFBD><12><05><18> <17> <17>A<EFBFBD><1E>W<EFBFBD> <17> <17> <09><1C>I<EFBFBD>-<2D>-<2D><1C><1B>A<EFBFBD>D<EFBFBD>)<29>,<2C>,<2C>c<EFBFBD>!<21>$<24> <09>.B<>.B<>C<><04><17>:<3A>%<25>%<25><1C><1A><0E><0E>t<EFBFBD>$<24>$<24>$<24><1D><1D>*<2A>*<2A>9<EFBFBD>5<>5<><06><19><17>!<21>[<5B>;<3B>;<3B>A<EFBFBD>v<EFBFBD>F<>F<>F<EFBFBD><19>L<EFBFBD>L<EFBFBD>"&<26>q<EFBFBD>'<27>"&<26>q<EFBFBD>'<27>"'<27><06><01>"2<>"2<>"<16>"<16><17><17><17><> <17>"<1F><15>/<2F>/<2F>/rc <01><00>t|j<00><00><00><00><00>}td<01>|D<00><00><00><00>}t <00><00>}|D]}|<03>|j<00><00><00>td<02>|D<00><00><00><00>}t|<01><00>}|rt||z d<03><00>nd}td<05>|D<00><00><00><00>}|r|dnd} |r|dnd}
||t|<03><00>t|<03><00>||| |
d<08>S) Nc3<01>>K<00>|]}t|j<00><00>V<00><00>dSrK<00>r9rr0s rrWz)MnemosyneArchive.stats.<locals>.<genexpr>"s*<00><00><00><00>8<>8<>1<EFBFBD>#<23>a<EFBFBD>g<EFBFBD>,<2C>,<2C>8<>8<>8<>8<>8<>8rc3<01>JK<00>|]}t|j<00><00>dk<00>dV<00><00>dS)rrTNr<4E>r0s rrWz)MnemosyneArchive.stats.<locals>.<genexpr>(s4<00><00><00><00>><3E>><3E>A<EFBFBD>C<EFBFBD><01><07>L<EFBFBD>L<EFBFBD>A<EFBFBD>,=<3D>,=<3D>a<EFBFBD>,=<3D>,=<3D>,=<3D>,=<3D>><3E>>rr<><00>c3<01>$K<00>|] }|jV<00><00> dSrK)r<>r0s rrWz)MnemosyneArchive.stats.<locals>.<genexpr>/s$<00><00><00><00>:<3A>:<3A>Q<EFBFBD>A<EFBFBD>L<EFBFBD>:<3A>:<3A>:<3A>:<3A>:<3A>:rr<00><><EFBFBD><EFBFBD><EFBFBD>)r<00> total_links<6B> unique_topicsri<00>orphans<6E> link_density<74> oldest_entry<72> newest_entry)
rDrr8rjrc<00>updaterir9r<>r<>) rrr<>rir2r<><00>nr<6E><00>
timestampsr<EFBFBD>r<>s r<00>statszMnemosyneArchive.stats s'<00><00><16>t<EFBFBD>}<7D>+<2B>+<2B>-<2D>-<2D>.<2E>.<2E><07><19>8<>8<><07>8<>8<>8<>8<>8<> <0B><1E>5<EFBFBD>5<EFBFBD><06><18> $<24> $<24>A<EFBFBD> <12>M<EFBFBD>M<EFBFBD>!<21>(<28> #<23> #<23> #<23> #<23><16>><3E>><3E><17>><3E>><3E>><3E>><3E>><3E><07> <10><07>L<EFBFBD>L<EFBFBD><01>45<34>><3E>u<EFBFBD>[<5B>1<EFBFBD>_<EFBFBD>a<EFBFBD>0<>0<>0<>3<EFBFBD> <0C><1C>:<3A>:<3A>'<27>:<3A>:<3A>:<3A>:<3A>:<3A>
<EFBFBD>(2<><<3C>z<EFBFBD>!<21>}<7D>}<7D><04> <0C>)3<>=<3D>z<EFBFBD>"<22>~<7E>~<7E><14> <0C><19>&<26> <20><16>[<5B>[<5B><1C>V<EFBFBD>n<EFBFBD>n<EFBFBD><1E>(<28>(<28>(<28> 
<EFBFBD> 
<EFBFBD>
r<00>dict[str, set[str]]c<01><00>d<01>|jD<00><00>}|j<00><00><00>D]T\}}|jD]G}||jvr<||kr6||<00>|<04><00>||<00>|<02><00><00>H<EFBFBD>U|S)zFBuild adjacency dict from entry links. Only includes valid references.c<01>,<00>i|]}|t<00><00><00><02>Sr-)rcrws rryz5MnemosyneArchive._build_adjacency.<locals>.<dictcomp>@s<00><00>#H<>#H<>#H<>3<EFBFBD>C<EFBFBD><13><15><15>#H<>#H<>#Hr)rr<>rrF)r<00>adjrxr*r<>s r<00>_build_adjacencyz!MnemosyneArchive._build_adjacency>s<><00><00>#H<>#H<>$<24>-<2D>#H<>#H<>#H<><03><1E>-<2D>-<2D>-<2D>/<2F>/<2F> ,<2C> ,<2C>J<EFBFBD>C<EFBFBD><15>"<22>[<5B> ,<2C> ,<2C> <09><1C><04> <0A>-<2D>-<2D>)<29>s<EFBFBD>2B<32>2B<32><17><03>H<EFBFBD>L<EFBFBD>L<EFBFBD><19>+<2B>+<2B>+<2B><17> <09>N<EFBFBD>&<26>&<26>s<EFBFBD>+<2B>+<2B>+<2B><> ,<2C><13>
r<00>min_size<7A>
list[dict]c
<01><><00>|<00><00><00>}t<00><00>}g}d}|jD<00>]<5D>}||vr<01>g}|g}|r<>|<08>d<01><00>} | |vr<01>|<03>| <09><00>|<07>| <09><00>|<02>| t<00><00><00><00>D]}
|
|vr|<08>|
<EFBFBD><00><00>|<08><>t|<07><00>|kr<01><>i} d} |D]g} |j| }|jD]}| <0B>|d<01><00>dz| |<<00>| t|<02>| t<00><00><00><00><00><00>z } <0C>h| dz} t|<07><00>}||dz
zdz}|dkrt| |z d<04><00>nd}t| <0B> <00><00>d<06>d<07><08><00>d d
<EFBFBD>}|<04>|||d <0B>|D<00><00>| |d <0C><06><00>|dz }<05><01><>|<04> d <0A>d<07><08><00>|S)a<>Find connected component clusters in the holographic graph.
Uses BFS to discover groups of entries that are reachable from each
other through their links. Returns clusters sorted by size descending.
Args:
min_size: Minimum cluster size to include (filters out isolated entries).
Returns:
List of dicts with keys: cluster_id, size, entries, topics, density
rrTr6r<>r<>c<01><00>|dSr<>r-rZs rr\z1MnemosyneArchive.graph_clusters.<locals>.<lambda>}s
<00><00>a<EFBFBD><01>d<EFBFBD>rTr]N<>c<01><00>g|]\}}|<01><02>Sr-r-)r1rUrbs rr3z3MnemosyneArchive.graph_clusters.<locals>.<listcomp><3E>s<00><00>8<>8<>8<>T<EFBFBD>Q<EFBFBD><01>q<EFBFBD>8<>8<>8r)<06>
cluster_id<EFBFBD>sizer<00>
top_topics<EFBFBD>internal_edges<65>densityc<01><00>|dS)Nr<4E>r-)<01>cs rr\z1MnemosyneArchive.graph_clusters.<locals>.<lambda><3E>s
<00><00>A<EFBFBD>f<EFBFBD>I<EFBFBD>r) r<>rcr<00>poprFrkr"r9rir<>r<>r<>rl)rr<>r<>r<><00>clustersr<73>rx<00> component<6E>queue<75>current<6E>neighbor<6F>cluster_topicsr<73><00>cidr*rUr<><00> max_edgesr<73>r<>s r<00>graph_clusterszMnemosyneArchive.graph_clustersHse<00><00><13>#<23>#<23>%<25>%<25><03><1F>E<EFBFBD>E<EFBFBD><07>!<21><08><16>
<EFBFBD><17>=<3D>. <1C>. <1C>C<EFBFBD><12>g<EFBFBD>~<7E>~<7E><18>#%<25>I<EFBFBD><18>E<EFBFBD>E<EFBFBD><17> /<2F><1F>)<29>)<29>A<EFBFBD>,<2C>,<2C><07><1A>g<EFBFBD>%<25>%<25><1C><17> <0B> <0B>G<EFBFBD>$<24>$<24>$<24><19> <20> <20><17>)<29>)<29>)<29> #<23><07><07><07><13><15><15> 7<> 7<>/<2F>/<2F>H<EFBFBD><1F>w<EFBFBD>.<2E>.<2E><1D> <0C> <0C>X<EFBFBD>.<2E>.<2E>.<2E><><18> /<2F><13>9<EFBFBD>~<7E>~<7E><08>(<28>(<28><18>.0<EFBFBD>N<EFBFBD><1E>N<EFBFBD> <20> ;<3B> ;<3B><03><1C> <0A>c<EFBFBD>*<2A><05><1E><1C>E<01>E<01>A<EFBFBD>(6<>(:<3A>(:<3A>1<EFBFBD>a<EFBFBD>(@<40>(@<40>1<EFBFBD>(D<>N<EFBFBD>1<EFBFBD>%<25>%<25><1E>#<23>c<EFBFBD>g<EFBFBD>g<EFBFBD>c<EFBFBD>3<EFBFBD>5<EFBFBD>5<EFBFBD>&9<>&9<>":<3A>":<3A>:<3A><0E><0E> <1A>q<EFBFBD> <20>N<EFBFBD><14>I<EFBFBD><0E><0E>A<EFBFBD><19>Q<EFBFBD><11>U<EFBFBD> <0B>q<EFBFBD>(<28>I<EFBFBD>>G<>!<21>m<EFBFBD>m<EFBFBD>e<EFBFBD>N<EFBFBD>Y<EFBFBD>6<><01>:<3A>:<3A>:<3A>QT<51>G<EFBFBD> <20><0E> 4<> 4<> 6<> 6<>N<EFBFBD>N<EFBFBD>TX<54>Y<>Y<>Y<>Z\<5C>[\<5C>Z\<5C>]<5D>J<EFBFBD> <14>O<EFBFBD>O<EFBFBD>(<28><19>$<24>8<>8<>Z<EFBFBD>8<>8<>8<>"0<>"<22> <0E><0E> <0F> <0F> <0F> <17>!<21>O<EFBFBD>J<EFBFBD>J<EFBFBD><10> <0A> <0A>-<2D>-<2D>t<EFBFBD> <0A><<3C><<3C><<3C><17>rc <01>><00>|<00><00><00>}d<01>|jD<00><00>}|j<00><00><00>D] }|jD]}||vr||xxdz cc<<00><17>!g}|j<00><00><00>D]<5D>\}}t |<02>|t<00><00><00><00><00><00>}|dkr<01>;|<06>|||<03>|d<03><00>t |j<00><00>|j d<04><05><00><00><>|<06>
d<05>d<06><07><00>|d|<01>S) udFind the most connected entries (highest degree centrality).
These are the "hubs" of the holographic graph — entries that bridge
many topics and attract many links.
Args:
limit: Maximum number of hubs to return.
Returns:
List of dicts with keys: entry, degree, inbound, outbound, topics
c<01><00>i|]}|d<00><02>Srvr-rws rryz0MnemosyneArchive.hub_entries.<locals>.<dictcomp><3E>rzrrTr)r*<00>degreer<65><00>outboundric<01><00>|dS)Nrr-)<01>hs rr\z.MnemosyneArchive.hub_entries.<locals>.<lambda><3E>s
<00><00><01>(<28> <0B>rTr]N) r<>rr8rr<>r9r"rcrkrirl) rrNr<>r<>r*<00>lid<69>hubsrxrs r<00> hub_entrieszMnemosyneArchive.hub_entries<65>sH<00><00><13>#<23>#<23>%<25>%<25><03>"C<>"C<>T<EFBFBD>]<5D>"C<>"C<>"C<><07><19>]<5D>)<29>)<29>+<2B>+<2B> &<26> &<26>E<EFBFBD><1C>{<7B> &<26> &<26><03><16>'<27>><3E>><3E><1B>C<EFBFBD>L<EFBFBD>L<EFBFBD>L<EFBFBD>A<EFBFBD>%<25>L<EFBFBD>L<EFBFBD>L<EFBFBD><4C> &<26><12><04><1E>-<2D>-<2D>-<2D>/<2F>/<2F>
<0F>
<0F>J<EFBFBD>C<EFBFBD><15><18><13><17><17><13>c<EFBFBD>e<EFBFBD>e<EFBFBD>,<2C>,<2C>-<2D>-<2D>F<EFBFBD><15><11>{<7B>{<7B><18> <10>K<EFBFBD>K<EFBFBD><1E> <20>"<22>;<3B>;<3B>s<EFBFBD>A<EFBFBD>.<2E>.<2E><1F><05> <0B>,<2C>,<2C><1F>,<2C> <0E><0E> <0F> <0F> <0F> <0F> <0A> <09> <09>+<2B>+<2B>T<EFBFBD> <09>:<3A>:<3A>:<3A><13>F<EFBFBD>U<EFBFBD>F<EFBFBD>|<7C>rc <01><><00><0F><10><11><12><13><14><15><16><17>|<00><00><00><00>|<00>d<01><02><00>}|sgSg}|D<00>]<5D>}t|d<00><00><00>t<00><14><00>dkr<01>,<2C><0F>fd<04><08>D<00><00><00>i<00>i<00>i<00>t<00><00><00>dg<01>d<11><10><11><12><13><15><16>fd<08> <0C><11>D]}|<04>vrd <09>|<<00>|<04><00><00><17>D<00>]}|j|}d
<EFBFBD><00><16><00><00>D<00><00>}||=|D]}||<00>|<05><00><00>t<00><00>} d}
<EFBFBD>D]<5D>} | |ks| | vr<01> |
d z }
| g} | ro| <0C>d<05><00>} | | vr<01>| <09>| <0A><00>|<07> | t<00><00><00><00>D]}|| vr| <0C>
|<0E><00><00>| <0C>o<EFBFBD><6F>|
d kr%|<02>
||d |
|j d <0A><04><00><00><01><17><01><>|<02> d<0E>d<0F><10><00>|S)u<>Find articulation points — entries whose removal would split a cluster.
These are "bridge" entries in the holographic graph. Removing them
disconnects members that were previously reachable through the bridge.
Uses Tarjan's algorithm for finding articulation points.
Returns:
List of dicts with keys: entry, cluster_size, bridges_between
<20>)r<>rc<01>(<00><02>i|]}|<01>|<00>z<00><02>Sr-r-)r1rxr<><00>memberss <20><>rryz3MnemosyneArchive.bridge_entries.<locals>.<dictcomp><3E>s$<00><><00>B<>B<>B<>3<EFBFBD>s<EFBFBD>C<EFBFBD><03>H<EFBFBD>w<EFBFBD>.<2E>B<>B<>Brr<00>urHc<01><00><07>d}<01> dx<01>|<<00>|<<00> dxxdz cc<<00>|D]<5D>}|<02>vr<>|dz }|<00>|<<00>|<02><00>t<00>|<00>|<00><00><00>|<<00><07>|<00><00><00>|dkr<15><03>|<00><00><00><07>|<00><00><00>'<27>|<00>|kr<15><03>|<00><00><00><>|<02><07>|<00><00>krt<00>|<00>|<00><00><00>|<<00><>dS)NrrT)r<>r"rF)
r <00>children<65>v<>ap<61>dfs<66> discovery<72>lowr<00>sub_adj<64>timers
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>rrz,MnemosyneArchive.bridge_entries.<locals>.dfs<66>s!<00><><00><1C><08>(-<2D>a<EFBFBD><08>0<> <09>!<21> <0C>s<EFBFBD>1<EFBFBD>v<EFBFBD><15>a<EFBFBD><08><08><08>A<EFBFBD> <0A><08><08><08> <20><11><1A> ;<3B> ;<3B>A<EFBFBD><18> <09>)<29>)<29> <20>A<EFBFBD> <0A><08>$%<25><06>q<EFBFBD> <09><1B><03>A<EFBFBD><06><06><06>!$<24>S<EFBFBD><11>V<EFBFBD>S<EFBFBD><11>V<EFBFBD>!4<>!4<><03>A<EFBFBD><06>"<22>:<3A>:<3A>a<EFBFBD>=<3D>=<3D>0<>X<EFBFBD><01>\<5C>\<5C><1E>F<EFBFBD>F<EFBFBD>1<EFBFBD>I<EFBFBD>I<EFBFBD>I<EFBFBD>!<21>:<3A>:<3A>a<EFBFBD>=<3D>=<3D>4<><13>Q<EFBFBD><16>9<EFBFBD>Q<EFBFBD><<3C>9O<39>9O<39><1E>F<EFBFBD>F<EFBFBD>1<EFBFBD>I<EFBFBD>I<EFBFBD>I<EFBFBD><49><1A>f<EFBFBD>j<EFBFBD>j<EFBFBD><11>m<EFBFBD>m<EFBFBD>+<2B>+<2B>!$<24>S<EFBFBD><11>V<EFBFBD>Y<EFBFBD>q<EFBFBD>\<5C>!:<3A>!:<3A><03>A<EFBFBD><06><> ;<3B> ;rNc<01>><00>i|]\}}||<02><00><00><00><02>Sr-)<01>copy)r1<00>krs rryz3MnemosyneArchive.bridge_entries.<locals>.<dictcomp><3E>s&<00><00>D<>D<>D<>D<EFBFBD>A<EFBFBD>q<EFBFBD>A<EFBFBD>q<EFBFBD>v<EFBFBD>v<EFBFBD>x<EFBFBD>x<EFBFBD>D<>D<>DrrTr<>)r*<00> cluster_size<7A>components_after_removalric<01><00>|dS)Nrr-)<01>bs rr\z1MnemosyneArchive.bridge_entries.<locals>.<lambda> s <00><00>1<EFBFBD>%?<3F>#@<40>rTr])r rH) r<>r<>rcr9rr<><00>discardr<64>rFr"rkrirl)rr<><00>bridges<65>clusterrx<00>ap_id<69>ap_entry<72>temp_adjr<00> temp_visited<65>component_count<6E>midr<64><00>cur<75>nbr<62>rrrrr rrrs @@@@@@@@@r<00>bridge_entrieszMnemosyneArchive.bridge_entries<65>s<><00><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><00><13>#<23>#<23>%<25>%<25><03><18>&<26>&<26><01>&<26>2<>2<><08><17> <16><15>I<EFBFBD>!<21><07><1F>G <17>G <17>G<EFBFBD><19>'<27>)<29>,<2C>-<2D>-<2D>G<EFBFBD><12>7<EFBFBD>|<7C>|<7C>a<EFBFBD><1F><1F><18>C<01>B<>B<>B<>B<>'<27>B<>B<>B<>G<EFBFBD>)+<2B>I<EFBFBD>"$<24>C<EFBFBD>/1<>F<EFBFBD><1E>5<EFBFBD>5<EFBFBD>B<EFBFBD><16>C<EFBFBD>E<EFBFBD> ;<3B> ;<3B> ;<3B> ;<3B> ;<3B> ;<3B> ;<3B> ;<3B> ;<3B> ;<3B> ;<3B> ;<3B>&<1F> <1D> <1D><03><16>i<EFBFBD>'<27>'<27>"&<26>F<EFBFBD>3<EFBFBD>K<EFBFBD><17>C<EFBFBD><03>H<EFBFBD>H<EFBFBD>H<EFBFBD><48><1C> <17> <17><05><1F>=<3D><15>/<2F><08>D<>D<>G<EFBFBD>M<EFBFBD>M<EFBFBD>O<EFBFBD>O<EFBFBD>D<>D<>D<><08><1C>U<EFBFBD>O<EFBFBD>!<21>/<2F>/<2F>A<EFBFBD><1C>Q<EFBFBD>K<EFBFBD>'<27>'<27><05>.<2E>.<2E>.<2E>.<2E>*-<2D><15><15> <0C>"#<23><0F>"<22> 1<> 1<>C<EFBFBD><1A>e<EFBFBD>|<7C>|<7C>s<EFBFBD>l<EFBFBD>':<3A>':<3A> <20>#<23>q<EFBFBD>(<28>O<EFBFBD> <20>E<EFBFBD>E<EFBFBD><1F>1<>#<23>i<EFBFBD>i<EFBFBD><01>l<EFBFBD>l<EFBFBD><03><1E>,<2C>.<2E>.<2E>$<24>$<24>(<28>(<28><13>-<2D>-<2D>-<2D>"*<2A>,<2C>,<2C>s<EFBFBD>C<EFBFBD>E<EFBFBD>E<EFBFBD>":<3A>":<3A>1<>1<>B<EFBFBD>!<21><1C>5<>5<> %<25> <0C> <0C>R<EFBFBD> 0<> 0<> 0<><30> <20>1<><31>#<23>Q<EFBFBD>&<26>&<26><1B>N<EFBFBD>N<EFBFBD>!)<29>(/<2F><06><0F>4C<34>"*<2A>/<2F> $<16>$<16><17><17><17><>5 <17>B <10> <0C> <0C>@<40>@<40>$<24> <0C>O<>O<>O<><16>r<00>tags<67> list[str]c<01>^<00>|j<00>|<01><00>}|<03>t|<01><00><00>d<02>|jD<00><00>}|D]Y}|<05><00><00>|vrA|j<00>|<05><00>|<04>|<05><00><00><00><00><00>Z|<00><00><00>|S)aZAdd new tags to an existing entry (deduplicates, case-preserving).
Args:
entry_id: ID of the entry to update.
tags: Tags to add. Already-present tags (case-insensitive) are skipped.
Returns:
The updated ArchiveEntry.
Raises:
KeyError: If entry_id does not exist.
Nc<01>6<00>h|]}|<01><00><00><00><02>Sr-r<>r<>s rr<>z,MnemosyneArchive.add_tags.<locals>.<setcomp>s <00><00>:<3A>:<3A>:<3A><01>!<21>'<27>'<27>)<29>)<29>:<3A>:<3A>:r)rr"r&rirdrkrFr;)rrGr)r*<00>existing_lower<65>tags r<00>add_tagszMnemosyneArchive.add_tagss<><00><00><15> <0A>!<21>!<21>(<28>+<2B>+<2B><05> <10>=<3D><1A>8<EFBFBD>$<24>$<24> $<24>:<3A>:<3A>U<EFBFBD>\<5C>:<3A>:<3A>:<3A><0E><17> 0<> 0<>C<EFBFBD><12>y<EFBFBD>y<EFBFBD>{<7B>{<7B>.<2E>0<>0<><15> <0C>#<23>#<23>C<EFBFBD>(<28>(<28>(<28><1E>"<22>"<22>3<EFBFBD>9<EFBFBD>9<EFBFBD>;<3B>;<3B>/<2F>/<2F>/<2F><> <0C>
<EFBFBD>
<EFBFBD> <0C> <0C> <0C><14> rc<01><><00><04>|j<00>|<01><00>}|<03>t|<01><00><00>d<02>|D<00><00><00><04>fd<03>|jD<00><00>|_|<00><00><00>|S)aRRemove specific tags from an existing entry (case-insensitive match).
Args:
entry_id: ID of the entry to update.
tags: Tags to remove. Tags not present are silently ignored.
Returns:
The updated ArchiveEntry.
Raises:
KeyError: If entry_id does not exist.
Nc<01>6<00>h|]}|<01><00><00><00><02>Sr-r<>r<>s rr<>z/MnemosyneArchive.remove_tags.<locals>.<setcomp>7s <00><00>0<>0<>0<>a<EFBFBD><01><07><07> <09> <09>0<>0<>0rc<01>@<00><01>g|]}|<01><00><00><00>v<01>|<01><02>Sr-r<>)r1rU<00> remove_lowers <20>rr3z0MnemosyneArchive.remove_tags.<locals>.<listcomp>8s+<00><><00>Q<>Q<>Q<>a<EFBFBD>1<EFBFBD>7<EFBFBD>7<EFBFBD>9<EFBFBD>9<EFBFBD>L<EFBFBD>3P<33>3P<33><01>3P<33>3P<33>3Pr)rr"r&rir;)rrGr)r*r3s @r<00> remove_tagszMnemosyneArchive.remove_tags'so<00><><00><15> <0A>!<21>!<21>(<28>+<2B>+<2B><05> <10>=<3D><1A>8<EFBFBD>$<24>$<24> $<24>0<>0<>4<EFBFBD>0<>0<>0<> <0C>Q<>Q<>Q<>Q<>5<EFBFBD><<3C>Q<>Q<>Q<><05> <0C> <0C>
<EFBFBD>
<EFBFBD> <0C> <0C> <0C><14> rc<01>`<00>|j<00>|<01><00>}|<03>t|<01><00><00>t<00><00>}g}|D]T}|<06><00><00>|vr<|<04>|<06><00><00><00><00>|<05>|<06><00><00>U||_|<00><00><00>|S)aOReplace all tags on an existing entry (deduplicates new list).
Args:
entry_id: ID of the entry to update.
tags: New tag list. Duplicates (case-insensitive) are collapsed.
Returns:
The updated ArchiveEntry.
Raises:
KeyError: If entry_id does not exist.
) rr"r&rcrdrFrkrir;)rrGr)r*<00>seen<65>dedupedr.s r<00>retagzMnemosyneArchive.retag<s<><00><00><15> <0A>!<21>!<21>(<28>+<2B>+<2B><05> <10>=<3D><1A>8<EFBFBD>$<24>$<24> $<24><1C><15><15><04><1F><07><17> $<24> $<24>C<EFBFBD><12>y<EFBFBD>y<EFBFBD>{<7B>{<7B>$<24>&<26>&<26><14><08><08><13><19><19><1B><1B>%<25>%<25>%<25><17><0E><0E>s<EFBFBD>#<23>#<23>#<23><><1E><05> <0C> <0C>
<EFBFBD>
<EFBFBD> <0C> <0C> <0C><14> rrfrg<00>metadata<74>Optional[dict]<5D>re_linkc<01><00>|j<00>|<01><00>}|<06>t|<01><00><00>|j}|<02>||_|<03>||_|<04>||_|<06><00><00>|r<>|j|kr<>|j<00><00><00>D]%}||j vr|j <00>
|<01><00><00>&g|_ |j <00> |t|j<00><00><00><00><00><00><00>|<00><00><00>|S)auUpdate fields on an existing entry.
Only provided fields are changed. Bumps updated_at and optionally
recomputes holographic links (since content changed).
Args:
entry_id: ID of the entry to update.
title: New title (None = keep existing).
content: New content (None = keep existing).
metadata: New metadata dict (None = keep existing, {} to clear).
re_link: Whether to recompute holographic links after update.
Returns:
The updated ArchiveEntry.
Raises:
KeyError: If entry_id does not exist.
)rr"r&rBrfrgr9<00>touchr8rr<>rrCrDr;) rrGrfrgr9r;r*<00>old_hashr<68>s r<00> update_entryzMnemosyneArchive.update_entryVs<00><00>4<15> <0A>!<21>!<21>(<28>+<2B>+<2B><05> <10>=<3D><1A>8<EFBFBD>$<24>$<24> $<24><18>%<25><08> <10> <1C><1F>E<EFBFBD>K<EFBFBD> <12> <1E>#<23>E<EFBFBD>M<EFBFBD> <13> <1F>%<25>E<EFBFBD>N<EFBFBD> <0A> <0B> <0B> <0A> <0A> <0A> <13> I<01>u<EFBFBD>)<29>X<EFBFBD>5<>5<><1D><1D>-<2D>-<2D>/<2F>/<2F> 1<> 1<><05><1B>u<EFBFBD>{<7B>*<2A>*<2A><19>K<EFBFBD>&<26>&<26>x<EFBFBD>0<>0<>0<><30><1C>E<EFBFBD>K<EFBFBD> <10>K<EFBFBD> #<23> #<23>E<EFBFBD>4<EFBFBD><04> <0A>0D<30>0D<30>0F<30>0F<30>+G<>+G<> H<> H<> H<> <0C>
<EFBFBD>
<EFBFBD> <0C> <0C> <0C><14> rrBc<01>\<00>|j<00><00><00>D]}|j|kr|cS<00>dS)z<>Find an entry by its content hash (title + content SHA-256).
Returns the first match, or None if no entry has this hash.
N)rr8rB)rrBr*s rrAzMnemosyneArchive.find_by_hash<73>sB<00><00>
<1A>]<5D>)<29>)<29>+<2B>+<2B> <1D> <1D>E<EFBFBD><14>!<21>\<5C>1<>1<><1C> <0C> <0C> <0C>2<><13>tr<00>list[list[ArchiveEntry]]c<01><00>i}|j<00><00><00>D]2}|j}|<01>|g<00><00><00>|<02><00><00>3d<01>|<01><00><00>D<00><00>}|<04>d<02>d<03><04><00>|S)z<>Find groups of entries with identical content hashes.
Returns a list of groups, where each group is a list of 2+ entries
sharing the same title+content. Sorted by group size descending.
c<01>8<00>g|]}t|<01><00>dk<00>|<01><02>S<00>rT<00>r9)r1<00>groups rr3z4MnemosyneArchive.find_duplicates.<locals>.<listcomp><3E>s#<00><00>J<>J<>J<>%<25>3<EFBFBD>u<EFBFBD>:<3A>:<3A><01>><3E>><3E><05>><3E>><3E>>rc<01> <00>t|<00><00>SrKrE)<01>gs rr\z2MnemosyneArchive.find_duplicates.<locals>.<lambda><3E>s <00><00><03>A<EFBFBD><06><06>rTr])rr8rB<00>
setdefaultrkrl)r<00> hash_groupsr*r<00>dupss r<00>find_duplicatesz MnemosyneArchive.find_duplicates<65>s<><00><00> 68<36> <0B><19>]<5D>)<29>)<29>+<2B>+<2B> 8<> 8<>E<EFBFBD><15>"<22>A<EFBFBD> <17> "<22> "<22>1<EFBFBD>b<EFBFBD> )<29> )<29> 0<> 0<><15> 7<> 7<> 7<> 7<>J<>J<>;<3B>#5<>#5<>#7<>#7<>J<>J<>J<><04> <0C> <09> <09>&<26>&<26><04> <09>5<>5<>5<><13> r<00>Optional[float]c<01>|<00><07>|<01>|jj}||j_|j<00><00><00>D] <09>g<00>_<00>
t |j<00><00><00><00><00>}d}|D]0<><07>fd<03>|D<00><00>}|j<00><00>|<05><00>}||z }<04>1|<01> ||j_|<00><00><00>|S)aURecompute all links from scratch.
Clears existing links and re-applies the holographic linker to every
entry pair. Useful after bulk ingestion or threshold changes.
Args:
threshold: Override the linker's default similarity threshold.
Returns:
Total number of links created.
Nrc<01>4<00><01>g|]}|j<00>jk<00>|<01><02>Sr-r<>)r1r2r*s <20>rr3z2MnemosyneArchive.rebuild_links.<locals>.<listcomp><3E>s'<00><><00>A<>A<>A<><01><01><04><05><08>0@<40>0@<40>!<21>0@<40>0@<40>0@r)rrrrr8rrDrCr;)rrr<00> old_thresholdrr<>r<><00> new_linksr*s @r<00> rebuild_linkszMnemosyneArchive.rebuild_links<6B>s<><00><><00> <15> <20> <20>K<EFBFBD>1<>M<EFBFBD>$-<2D>D<EFBFBD>K<EFBFBD> !<21><1A>]<5D>)<29>)<29>+<2B>+<2B> <1D> <1D>E<EFBFBD><1C>E<EFBFBD>K<EFBFBD>K<EFBFBD><16>t<EFBFBD>}<7D>+<2B>+<2B>-<2D>-<2D>.<2E>.<2E><07><17> <0B><1D> %<25> %<25>E<EFBFBD>A<>A<>A<>A<>W<EFBFBD>A<>A<>A<>J<EFBFBD><1C> <0B>/<2F>/<2F><05>z<EFBFBD>B<>B<>I<EFBFBD> <17>9<EFBFBD> $<24>K<EFBFBD>K<EFBFBD> <14> <20>$1<>D<EFBFBD>K<EFBFBD> !<21> <0C>
<EFBFBD>
<EFBFBD> <0C> <0C> <0C><1A>rrK)r r )TF)r*rr<r=r>r=r?r)rGrHr?rI)rL)rMrHrNrOr?rP)rLrq)rMrHrNrOrrrsr?rPrD)rGrHr<>rOr?rP)r<>rHr?rP)rGrHr?r=)NN)rMr<>rir<>r?r<>)r?r<>)r?rO)r<>r<>r?r<>)r?r<>)r?r<>)r<>rOr?r<>)rNrOr?r<>)r?r<>)rGrHr)r*r?r)NNNT) rGrHrfr<>rgr<>r9r:r;r=r?r)rBrHr?rI)r?rA)rrrMr?rO)<1F>__name__<5F>
__module__<EFBFBD> __qualname__<5F>__doc__rrr;rFr"rpr<>r<>r<>r<>r<>r<><00>propertyr4r<>r<>r<>r<>rr(r/r4r8r?rArLrRr-rrr
r
s<><00><00><00><00><00><00><08><08> <15><15><15><15><15> <15> <15> <15>)<29>)<29>)<29><15><15><15><15><15>,+<2B>+<2B>+<2B>+<2B>
.<2E>
.<2E>
.<2E>
.<2E>
.<2E>-/<2F>-/<2F>-/<2F>-/<2F>-/<2F>^<16><16><16><16><16>,c<01>c<01>c<01>c<01>
<14> <14> <14> <14>" $<24>&*<2A>%
<EFBFBD>%
<EFBFBD>%
<EFBFBD>%
<EFBFBD>%
<EFBFBD>NN<01>N<01>N<01>N<01><0E>"<22>"<22>"<22><0E>X<EFBFBD>"<22>
'+<2B>90<>90<>90<>90<>90<>v
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD><<13><13><13><13>B<18>B<18>B<18>B<18>B<18>H"<1C>"<1C>"<1C>"<1C>"<1C>H]<17>]<17>]<17>]<17>~<15><15><15><15>0<15><15><15><15>*<15><15><15><15>: $<24>!%<25>#'<27><1C> 3<15>3<15>3<15>3<15>3<15>j<14><14><14><14> <14> <14> <14> <14>!<1B>!<1B>!<1B>!<1B>!<1B>!<1B>!rr
)rV<00>
__future__rr <00>pathlibr<00>typingr<00>nexus.mnemosyne.entryr<00>nexus.mnemosyne.linkerrr<>r
r-rr<00><module>r]s<><00><01><04><04> #<23>"<22>"<22>"<22>"<22>"<22> <0B> <0B> <0B> <0B><18><18><18><18><18><18><1B><1B><1B><1B><1B><1B>.<2E>.<2E>.<2E>.<2E>.<2E>.<2E>4<>4<>4<>4<>4<>4<><15><0F>q
<1B>q
<1B>q
<1B>q
<1B>q
<1B>q
<1B>q
<1B>q
<1B>q
<1B>q
r