From 73b9bb5622fe638a33dcc943bbc479de6821b715 Mon Sep 17 00:00:00 2001 From: Leon Tsao Date: Wed, 10 Jun 2026 19:15:24 +0800 Subject: [PATCH] Restore YG rules generation flow --- CLAUDE.md | Bin 1171 -> 1171 bytes app/__init__.py | Bin 2282 -> 759 bytes app/routes/__init__.py | Bin 303 -> 19 bytes app/routes/domain.py | Bin 8400 -> 1603 bytes app/routes/guidance.py | Bin 16102 -> 1994 bytes app/routes/health.py | Bin 987 -> 408 bytes app/routes/rules.py | Bin 3335 -> 1262 bytes app/routes/schema.py | Bin 10467 -> 928 bytes app/rules/__init__.py | Bin 43 -> 25 bytes app/utils/__init__.py | Bin 22 -> 19 bytes app/utils/guidance_analysis.py | Bin 24150 -> 9432 bytes app/utils/guidance_storage.py | Bin 195 -> 126 bytes app/utils/llm.py | Bin 4632 -> 3291 bytes app/utils/logger.py | Bin 6815 -> 1084 bytes app/utils/note_scope.py | Bin 12598 -> 149 bytes app/utils/parser.py | Bin 4501 -> 1426 bytes app/utils/response.py | Bin 969 -> 492 bytes app/utils/rule_generation.py | Bin 92010 -> 91249 bytes app/utils/schema_storage.py | Bin 20269 -> 6178 bytes app/utils/storage.py | Bin 14632 -> 4760 bytes config/__init__.py | Bin 1436 -> 1436 bytes requirements.txt | Bin 83 -> 115 bytes run.py | Bin 945 -> 945 bytes skill/registry.json | Bin 954 -> 954 bytes skill/yg-rules-output/CLAUDE.md | Bin 625 -> 625 bytes skill/yg-rules-output/SKILL.md | Bin 3339 -> 3339 bytes skill/yg-rules-output/agents/openai.yaml | Bin 309 -> 309 bytes .../references/markdown-format.md | Bin 1031 -> 1031 bytes .../references/output-contract.md | Bin 1129 -> 1129 bytes .../scripts/validate_task_output.py | Bin 1767 -> 1767 bytes skill/yg-rules-output/skill.json | Bin 1109 -> 1109 bytes skill/yg-rules-pipeline/CLAUDE.md | Bin 963 -> 963 bytes skill/yg-rules-pipeline/SKILL.md | Bin 3115 -> 3115 bytes skill/yg-rules-pipeline/agents/openai.yaml | Bin 299 -> 299 bytes .../references/local-pipeline.md | Bin 1319 -> 1319 bytes .../yg-rules-pipeline/scripts/run_pipeline.py | Bin 6884 -> 6884 bytes skill/yg-rules-pipeline/skill.json | Bin 1518 -> 1518 bytes tests/conftest.py | Bin 65 -> 0 bytes tests/test_domain_routes.py | Bin 983 -> 1809 bytes tests/test_guidance_analysis.py | Bin 10760 -> 7222 bytes tests/test_guidance_file_extraction.py | 38 ++++++++++ tests/test_guidance_routes.py | Bin 2731 -> 3924 bytes tests/test_guidance_storage.py | Bin 4387 -> 4387 bytes tests/test_llm.py | Bin 1983 -> 3883 bytes tests/test_note_scope.py | Bin 3021 -> 0 bytes tests/test_response.py | 20 ++++++ tests/test_route_messages.py | 66 ++++++++++++++++++ tests/test_rule_generation.py | Bin 27932 -> 30440 bytes tests/test_schema_descriptions.py | Bin 4304 -> 4304 bytes tests/test_schema_routes.py | 32 +++++++++ 50 files changed, 156 insertions(+) delete mode 100644 tests/conftest.py create mode 100644 tests/test_guidance_file_extraction.py delete mode 100644 tests/test_note_scope.py create mode 100644 tests/test_response.py create mode 100644 tests/test_route_messages.py create mode 100644 tests/test_schema_routes.py diff --git a/CLAUDE.md b/CLAUDE.md index f20e29401ebb791b83d744c20d2af2f10745996e..9f4e57b52163004384ec5a3799fe8b3398a6da35 100644 GIT binary patch literal 1171 zcma)6O>Yx15WVlO7%69`5=VrPsuEDuBC3=gkSZmXcapgE+Kb2A>Kp3gV)-edwF-l%!!kl=8QKEbi46g!h_@KjY7gpf7}Z46gv6414E zj-c~3Mp)+8!4kF`^f{~}Hfy>jScS+R$6>0D_J;kDn*g`KsHHe?KuY-r3uX0YyDa*6PWp0rJ&H)V^wHvi_Us17)L0>T1gvHJMUv`TkR7;3eY-j5LQ+O zw;nYA>~UXQbDt5a1bOX7ti%ZCorhHnO`bSn8_1>*2Z$l0=T)^_F59rhNE>vnYKOGp zVe_Ug|ABW&CfYX9W$gT7hk4o#pp^Bpn)0obvyDygjO`|(PN?XklTKAN>suy~b!fEpH0>Sr{3Nr%M(xMfO~gUBZ5 za=tuwEY*-$cRQB;lZMh`Pr|4}Tu7-!aS9n@SW(ue?6mdgvVI;gUr$vjIE%Pq{ns|i zsho|>7lt9+urk@ai%7=%oL*7z%Tel@%EqkWEqc2`;&TunrlZ7?&N>AeC}G1| u-&Z<6IX*pQ-XGLC3N`j>rH#FhrS|D(A8 literal 1171 VcmZQz7zLvtFd71*Auwn{000D&00961 diff --git a/app/__init__.py b/app/__init__.py index ff67f54bd854b63472817bd983bd36684162f1c5..823863131c9e8f9762979e191bf944f02166dc6d 100644 GIT binary patch literal 759 zcmaKqF>b>!3`KXHLhxh{^#KC3W5-^BP#juOYfA=2Z5fIjpi{0;pf@Pc>l8t+QCqT{ zq-dhW;OFBfX{jiR$4>bddHg#396pYp@5i_O_v^kW3L#o@y##0j2SNa8`oR%PWvyey z##uizZM2xv(Qi&P&bCJ9LX8Yb5khRRl?|a{1T_q0(!r`8SJE@doqTc@<$e5A^6o)K zh%fFdJnX%yf>g@mo|KZ!?{uYb=EheMVz& zjr7eHdzH}?P3-b-3AOQz1nVx~K*n;p^gi9dKh(1QP3mmxo7^(lO)9UNAQ~@{?DTfT EFU9ffgc5WV|XtoCF}QPKmaN|6xiKPWeZtZlL`hPBu1u0g1(gg8LdLt8G0^3haH zBLotnNC+W_;KvY~egOwe>@yxt8Z!yO6(f<7C_5AcrnZDaX5pV#5c5yx&&)%Kp zgTriZ2(=o`BwViUMv^;pv73b4(^|l|g@Ae%|EA=zD?y%Eb+3w)dWZ|Ovupe3cO}4! zL_2ylwZ=8x2tZ?#e(kzR4+8`%g>>BVQRBpj?c(XTm)YB=+1dNqhw;zJv;4)I{NQl< z^?7}JL5oXkYu>*y+Mq!9;MG~Rh5we-j$PwI>SCuC#MUcb<5nM~rA+^YR6Tt`iH=-I z$)~;PRxkog|<|JlBk8uK|l0HHyZh)HqAyr zo7t;Teteh>&i{)%Erb=^Kn&agox01CSq@ejp-&lAbjg@C-!5CF(_@qf5T=G&^_>c* zZEkWFon^E7evhZIf*n{iw@o69xt9FmE;C`O4Y|cRa~pRVTnYB8=IV64i`L)FT~r3* Y8l3>4%}M}h2I`K;1}F2Qv&s>_0O$N)A^-pY literal 8400 zcmeIuF#!Mo0K%a4Pi+kkh(KY$fB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM H82B0(AkY8- diff --git a/app/routes/guidance.py b/app/routes/guidance.py index 038769a70febf558b4afd67bf8331af5a66a7e21..458ae005ec3f28a7573dd717a9bfc4398174c003 100644 GIT binary patch literal 1994 zcmbVNO=}b}7{1T1h&j!`I@?1}3o9y0e}Lk3NO!Z_*!hS_rnp@eRK%82wLrD{7c`0xOL!&}B59f_qF9znn=^=s+;rjVaZb5lscIoX@8wh~n?*Pe zbH!pA4s+HgX^%!ECGkiy>GrPKz%{+TO@(P;u~AUT;aKYOsSufHA({7jRLW+yRGA>d zD)~m15SHFDi=J0CvCdH!RbBho1#k<%rz8RBf#-RBIzT*Mk6ABr8PR~n)EBguiGBz5 zSx*J%@|AMX@eq810(B`GZ_-f*Z4qDw4KjgX+OkuYLXzGeGDQ>V2Z#-H99`-ntO3w| z#EII#6KLUTb?`b5c_x*Q+k~^WTW;q(&PX2zWwT~dHR}haCzWl|G-7=KZSN<9o|14# zp_~ii070J@#7z(sq9JMupp;)u4CeCELmhyt)>ZWon$l7I)hjP2$-ibfs3r9_+f)YL zK$plN(5L9RKHC7-N81Z2b>rjN>E3MmX8!Ke&(9~nrpIT~uk(*DOoet;r`SCzj&^3> zzJMN9S60knN{kjoozA*wNn-v2vAJTP$)<*qY|-jwjEvlYt+M4%DnUtNCmMuSqNzyl z_b6BBj@Hvn?Epk1g2hEgOE3pboMXtHlxS8>L7Q%E3M;wEYcPP3jrhJNh!CX zAZZ>G!PE%q*~&(gwGeQDH`s8)>d7`HV8>eHL9%yhwdN8-CL@`1{W^kOYlZ#V*xK*B z3g^2|idP4f3TLNJi^C7a{=>85$EdcyF258EOJcT7HA__&)#`;Ul$YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM p7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RskJ0|P$h00961 diff --git a/app/routes/health.py b/app/routes/health.py index a1ad4d8f9b1d2686910430dc27bcefa8fec12bb2..553b0aea14ade53af66b071902b6fff4eae81ee5 100644 GIT binary patch literal 408 zcmY+Ay-ve06oq#`g>@%eD(POS5@KOzV~R|A(^!drP~9^JjHa1w5>FK%Loev+s5Nt=ro+B`5`NN;N6ln9JJt(KuGl@fd0{{Q*c L&*AL|XNr?w^E#6N literal 987 ScmZQz7zLvtFd72GFa!Vt+W-Lo diff --git a/app/routes/rules.py b/app/routes/rules.py index 8223c165dd77f38128d255947c0e5ae6771de372..d19ac5e4684683351db4c08a17eabf4932a2259f 100644 GIT binary patch literal 1262 zcma)5%WB*(6y5tPgf_9kcv8qJF!V**O*c)l3qdHJ>p`u@awNGBhCnG@41vC&i@sp! zV`w*}Ep$)|y7?n~P!iz#0ZiFnfugP+*@3!e{c?G2sg^5X8DFuaLyewm) zV7CHod<%w>%7|Pi3UrB3(Ds8;QpH49X$o395}oQQ2R4KPlx5I1tz-D+Jh}nuo=71G z6oxh1DM_EqX@%5AX^g8Ce1wZdK@ePNOOsM+6Ve_pMbE~1ej3my7(hnaBeU5sS`7&P zO1_s%KEOeK&twRO-O;iLwa8I~{-&xRB2vu@GO0$1k!&DR6WYvp-(uxrBn%>V1*}_x-H^B66j@3I-<`>HsY3%9TMUu)Q6GMl2eSPif<{I0$eG7|j@LWUW z(KTK&An^L%v<(;F{l(uX!6s!wOSEslj_H6Kj!pXkM9pm|Jo$VU8F&Ak) z=NX}{t>?HJYIm)zyfL9TrBPgD1m7+33Fq1-?iaAnE~KZ^+4+}u^@nfg-)Fy$U!5Hv z)?c5sP3Vx7KO zHcrOzZ|&``l=XX{lO*_f=>Pno5QP@U%we+gruq}XdI`tsTIUA z%?ep5Lq%CuMwqNBwa28n&|9yoa}xdP5yn1wh-DGD4SAcU;W!O;d7&U!*- zJ&z1X0x89C>;gPkCKNvfXhJ!Y$os7(&(4FkPY}`q<)g+GHaQw7*5{Xyf9-aBqEC;mKZ#1$`?cB4!SZPhlQi`WR zZN#~@;9R?7&c=@iJaTRhf3J; XmpOdBRm+2)3v!zMi?`G3`SpANG<{Zj literal 10467 zcmeIuF#!Mo0K%a4Pi+kkh(KY$fB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM Q7%*VKfB^#r3>df@7%1Za0RR91 diff --git a/app/rules/__init__.py b/app/rules/__init__.py index 04ae9951e1bd4583defe6ff0a09530715e032567..4129f3e3bda364962208fb80c2abdc634baace57 100644 GIT binary patch literal 25 hcmY#VQhKqxC@KjPkUM)H#8|JDRBV+VhITp literal 22 KcmZQzzy<&S761VN diff --git a/app/utils/guidance_analysis.py b/app/utils/guidance_analysis.py index 0c92a4922895d1409b6a21865b4071cb368dc662..1152305084ac7fd486158842fcdbf320d476d417 100644 GIT binary patch literal 9432 zcmd5?-E-X36@T|%A@qVaIGR9SI;Mun3@O931SX{IFdKJAS>3hO>`FV57RR`ru|vQP z7$=kvNSr1Op$SYAr!9ddwjqB^tljlf{)PU|{m{MA?i$nSL-pX5?mhQ>-Sc(NwQbwo zOOJc^E_YX#v+d8imzTTO?q(|=bgy50vUt|E?Xj^&9JQ=ktSy9B{Q8gXy#v?Q|&mavm{X?DQmSGL6ZsWzL&BzXfcIbeT&()m(DbU zQ)==}e2$Hc)tg?DSg&>h-wW&PNa!`^-evK`n1$!n<42DD_BTh4zjos7+UrN&v?i^2 zyBW>e6Bhp&x9pi z|Nf2Rue?Qs_&70P_a853o45N9Ze)v_KvcE+-<{jpydwsBYs)t1%2~VtDEsgxjdib` z?=IapW|kfk2F&b!d9Hu&Hof)M{;|9KNw&P${cdS@`GP$)ZqR-3B`{&SfBoa#TWh;l zzTwn+-#p%3yg-YyjqAHt-tVs6$yUDK+2okJ*A{zQE7^t5d+Q&{A#e*Ez@J_GgjVfr ze%1Zr)9n7E?)i`CyZ_*Jcjezj%2%#tOUwNS4*@777OzC};!1XLRpX(z-Zz{5AMSEo z*FOfi?jn@K*Gh2~xKM8%J$CfO@gpZ*dt;QQcOGu-{P3w1kTktd2_M|r+1e6|iHq$0 zZ~IG^x|bgnh2nZJke3xB6+tTDpu3;n>#g1A2-mN7@BUc8CbVc^E2~v2O6mf51No}_D~hG-R9yHKi=9e=k})s*gt!cnTGDA#>|p-SWb{-N zH3vBT35Kj-xGTX3((Iib>0M+kV5=xQtDhw_7ZoiF^t_1OyXE5NkUL4MeBu zo0!HI->#aH1h7IHDMv*(5MeHn_M`flpQg>B_Dh_A_fLIa#P=;YXz!DB3rfxRV}#0E zUVPe*X2U(mO9i_=t4BU_>`vM^_=|%{FpV`Vj-xo4w1a6lCbNxAkUmz}-li9XocI43 zH7*``+@M{Em{7Fx!BD_6etQnql;>Q(ah!QRi-q@)-e!Yz#!_kAeX9)@W&R1I^(gk@ zxnIF?oQmZo6l9p!D(YN}xwD8<%u%*l*cAzpFm~EGR4GgW9T*{>Q%pGmx(vqSnSC;} z-9JV_=(N3Q<|`n9@0U3#w9&U{mCIxqCyNc%F%=ZQ2xc2x!AR!?Nml+S@`q*l%Bn035^$rd|Ge(c!&JGW2`TP}pM zP#^DXeZPBcv449h+jx{+`8wM;-@o;Kj?N%dbdY1nA|>|_sbJD3%r^HGN+3msXk;%x z;q#4VCz)}yh$5^don}f3$!l*n?u1Ukl?bq^G$FE`OX<$2CJBU|`V6a|o;(qEn65O% z4CcHxKO01ywB1QZ0FkAPm|`JqvjDedX@($no5&%FF} zd;P_!%E{yaGD(g!_p%~NLd$)3l0ZpM+!u2JXr3N;3xN$Trpa6puGem}(0BCVho;R( z)hmRoxO)YtoNb{q6gZ`kJ=Q92@}(%g4*2H9V$7yd zVAHX;7PE#jAg&`yb=qjigtXcS7A6ui7sp87Yc{cePZmF{{^7~uM^n$?5B7|Z46s55 z=#YiEl$B4jxx^t{X4FKCWGG|nUg+a6jJj1jIS-%trutC}#RjiswI&b@MR}`-a;2FD zuBVNIfH+d1mKEn{PD!hvDfIr7{n-*zL4QMkkF< zvygj+c;l%%ca7@FWc=y&>XXH#7vU9C&q2E+r^xpeZq>A2qnBAhQ9(TSk;S;Wau$dc z1>kzV?+5^yzi3u(!C*L0N+l;&?};`LT22PQl_RXLDx5|~6@qDbDMB%2x~k-bD?z;j zxnhx|RKp~Wd{>7O;)4jP?;;tvGlRi%JD&+s+Oujw5yXqcI51A}O6)Y3727=Q2=Bh* zH9Ig?y$OVq9$K$B2L_I6fQTWTl%xPs6i05aQXZ*;ih#0|#qA(gs5lM64lCgHQ5=K` zLIB?^h*!%;YT(@|Ix?Y2>Np7innIFfqGBDeUO-Typ)wyum1wIP9cK?5P&TFglnB#f zONuqAQ#wT|O;F`q+Ug+)aBgSuI{}HTMFo~z>|tw2WICbJZ*d+0H`k{jT!Pks10E-v zUh9>$$KgsG*}ySZYPw{4qMrU8Il8E(8}`n_kGq%dcUPBs zSI-r@Q}YI%1r*Zx4#?bVIGh|QocVRPMzb#?szxvnQ}gCzTM;K{bph8qGvsZUMk zj8R6EZ9`wPAottggkojBsJOcZ6w*TuR6R6>E+d*8B2}4TrwaeIM@18u#$tcvZg2gQ z-o{OPLHZXrBT+q7r%2(N?UK)OBUP4BuG5M!8CMD^i$lKWdebQH$XY!YjW%D`>iKX| zMPw2IW+Xp{4^<%U@RB}>I&qycLXL63GD+}LUJ~RcRO4UrT+G+&eIwvJ8k=Z^i40dc z?|*Qu>8Q>VnBcC6U8;7JL^!3i>T6S@*w{=f+ z!~6F?$X5PtcJ9%S?|r+4BF^l%XMbMp8-4r!##hFg|q#|_p%Fr%eF5NxjZ_N z>Xki>PSAEh-Q0#PArH=TLz_5s*k2fO-nGRJ0O^ws zqZOS{2oF8wj5>fy`L|?hFHGDx^HVkz0eoZ_(f^{dpn?JcP@Ti5oS`Gp5bWAv0K-3q z0QoGbE$qjVdQBEhYs^ugbZ}%~ehm6OukY z6cRg^S8d7&nMoZ;qUa`}yNgZ|x=2PViJD4i3ZfZ!K(q((_A;;kP>slA6Rs#r9Y2Ya z|3IY*a4$GFX6>d|$MsjX{saDNVP|`3=iybNB;R!Ihi-=z8bqx!n5&EXA~|c=!mrVK z@BZ`bJdG~sEG$*bVL^<3U9=<<>cTq?dTnQkFSJU<&keg$5%IQR3sgL(^Bv| z$^x2KyI=gPzxrNp{UORAQHyXE$tN-Jp-e;@e zZf~wdh1NZL7ysfhoOiCw+(Aenxr5NpUms?V-|K$+8R|3A4^*=BthmGDtxqUteO`z( JXaHh->_5*KOj`f| literal 24150 zcmeIuF#!Mo0K%a4Pi+kkh(KY$fB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* Y1`HT5V8DO@0|pEjFkrxd0Rz7S1721D0RR91 diff --git a/app/utils/guidance_storage.py b/app/utils/guidance_storage.py index 15bc5e51a7f7cc09317f951646b447cc7c7d1055..28e5624c8e9367b7388129bf07cf5a35c394a104 100644 GIT binary patch literal 126 zcmY#VQhM6D=jpng&!#Vbx_-~o)}=4DuYbC)<@v0ZXFcst_e_1dcE;1D70*^Id^&gf z7=p&27@_@j%q{bZrAvTzjW-JfJk%`ZnHVdmDSPowngP2?{*% zS_uK75~7H{AX*6tBp&!NaP9Fgn6cNp*`_U0pU6Yj>z(;#=9}@1DWy9*SIOz)&z{|X zbn^Jq(;vS0>yvww(pD=~az^4fotwGhaZIvVA(bIa2x*wfq|mKaxhJ(>DehM$n{kIx zFf+}w0}rqVukM3c6q%U#{cW+R02Tjm&b84_ZY&KKx4m30**JDvtyU|^nbrhi7$_xG zaD6V&uzd-8EdoCX#)kOIZ%?1xJ9+rz^w%GKh^;YCi8d-LVl&OeA$SuQe%JJHGbHO5 z@L8ce`{|E=zJB=h(f210zC8W&{>irw{{H>vXWx8ItS&kE?yC|Pt!60!o`^-WZs4Zk zz@-3>>`sz%Cis~2VL#IIgFw;q7An~4fhXbCg=lT-e5biZ+o0aIxNVZ=Y@++1eR+3( zduNAyj7V4BzP5XPaB2I!K^WQCg3y|qizJu2vd5W9rmH3ayYy=behJb-mBD#L$Iw!M zB|^&zAMjKv4pEl7!yfU9;2%>a2uBS^S!%dilCPw>7zbf*WKnNvDdLoi1d)+HAJ5I3 zH-SI=9B$pvYd4OfHHgV#E=BYb!hCc!`bum;8P6F)ZwN}xkXkmHC^;{JZpC}Gs9m-Z zgUi;TD9s=wdPH4@fL06UWG?hc_rI-MoMEljtGH|$FH6rkzkF^ko8N%Zb$C=1X z90%5COseL2+OFPMk;R96VUGwD+%+jM1Nf+A4w&ZgT;;D6n#nPLwFLOA7BMr1&kCb^ zBohWqovZCQ0f1qPSo1`RF-WD*AW&|jmcy1H=WwhY!r6_k`(}?gx?b~)!A7y|F@=)1 zcw%DcJ>?PdY(ymqm`6tkk%~wifoP_rh$h?wba!uXZTm{Ry>}&kckqEdxGv8XjOPh( zf@=M8q>FH-neOK9i? zIfbmmID`NMhfe^Bf&?XZpqqrGLnx-rwPd6TPN7$b_}vVq5Hy|2DU?{6K!F=X7QXM* z+C<*wN@Zi-e~aashqceil$pRDC^F+(vk8Za&B4fUoF!%mS!?6W8I9UxZSC+5Qxo_O zld(CB&}XHvJUNCziW?fmC~sVBarm zH;yX`rkstr(iZ2E6fm33`u?Kephj6y1#2;J%;FRM0?~%dXgclfivo}?;FpEgpQJ@R literal 4632 pcmeIufdBvi0K=g9Qy=7oP+`D;0RsjM7%*VKfB^#r3>Yx*I4}|z00961 diff --git a/app/utils/logger.py b/app/utils/logger.py index f8542b36cf5432328e7a58adba06910d5614e3c5..fcc912e0964ef17744a81a05f522e6573b9201b2 100644 GIT binary patch literal 1084 zcma)5(P|Sx6n)>XxC|6_C0$e$q_9F06D`I>YAX7)OtW{lW3n^L%&fFjK?EOt?icv# zABZ0#D*lCcW+&U0MlcUa=FYk2%)R$q#@MfmFF(Iu{Q30x_qVSyIfT;_E{ip4v!OWj1hSflH9qO?q9`h` z1cSD1@{kwvrb%G;AX>X&L15dvH>t6Ff17W zo(f}gwaON{#l$nL@hz?)14`l6>Nsc(U>n_Z{Bk^Xga@<9+!1ana_5fErMW2Tlpa5I z?6KEKqE1g$c}aDWBt5?2_9T6yg#4e^v%t+drO-tp+S0$+i@6rjW4z#?kJS8hcxKUL z+e&=4|0*B8UW{K*nRjl(E&959FZ?8z9LIdQYMYU2rQJ$1+#fwXdY+HwN3#Vn-M^BG za;XY(N5)!P?ml20>9v|%>n2LqG!g7al3qsGPRz~HiW(CGJ6(Sz52yZ5jmGebAS}7T zeseIQ1Tr$&`79PjNMpHNVk|7ygKZ5?2w8x;PLH`kXI&=@Sq5P+*W;zq9t}czYXy&N zRw3#9>;`tlLA)r!KEwe?F7k^(cJ*sP?QybuV629Bely4rZbAH}Z2UR(j_fpCp)RHO dgQg|ZviCAkcksCMjyreg_rY}k#5yQp{sQ;gU#0*6 literal 6815 zcmeIuF#!Mo0K%a4Pi+e?h(KY$fB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFks*|FdCl# A0RR91 diff --git a/app/utils/note_scope.py b/app/utils/note_scope.py index 2e47e7c1386d8cfaf1526fe13edae64417464f93..08d009d30d8d815bbfcfe4614a52cb5fd2d590e3 100644 GIT binary patch literal 149 zcmY#VQhK_i{n_RfFM67v&ffBLNz3yIZI2t8l$4aXxYCO9a~0y_(@IN9i&Ep`6*6-R z@{39o67%x%OA<>m^YeYwAz<>b*1`HT5V8DO@ Z0|pEjFkrxd0RsjM7%*VKfB^%K0|PNO00961 diff --git a/app/utils/parser.py b/app/utils/parser.py index 9a4a0c1ec4e659b91c7b4a9e509a21bcdb5c7c4f..2fd072568672884e51f4a01a8b003e23663689fe 100644 GIT binary patch literal 1426 zcmaJ>O^eh(5WVMDG=1v8OmJ^9xE>Zg?8OBYFT)UeCzaXW&2)$E&hCU|K}8V!01x89 z!y2WpkFR0tEe}=J0sLI=BHNo0fAJ zG3RZ}hId(^oF8Xu>L;U!;p3`2R|~ega!sr&3*`k*_<-%iKxJM>83)nE-BuQp~+%hwl7{+5}?3&q{vtS!f znwqzQ|G@+Myhg*rg6RLJ_H9_|hd_|z9+v$O)k2|_NgjEN^Ra&*2r&+fdj+ur=X_DP z1@?&k`9)8-8x*W#V{iy|ulC>&H53>RP#T;qqlj zmoAZ0uTEjbuaOS*q%w$Oey%l%tVfM{ zlyHpG-X@^_avmpWP$f=qj^9mY8e#$;-w*xQb$HGFB5YEsTS({Z=Zx sD4tN$?^|oE$nlYwAz<>b*1`HT5a32^El>h+% diff --git a/app/utils/response.py b/app/utils/response.py index 5974f62aed5631db54b2fddba3df46b17c55297b..8f5b2fc24fd0aaf73ad3151c03bad004c4dc8751 100644 GIT binary patch literal 492 zcmb`Cv1-FG6h(J`#p6v5crYcCp+lBJmy)5o5VjQ5+LDpv!IVHK6iOjbNXJ5^enU!2 zzot?88+{2fBul4ikvQ+_-un>o=X1S%U%+H~31PJiA1`6^79KX=i+e;&5@}5XjLFV- zRxk#tX^r*3wKkr6WweVL-?vK7hWSMIk;|I9+X3G=qm`slQV9vJD@);AT5-<{pf7L^ zS4N8r8p3=g3UJ;M#NBGS{d(O!K8L3@W<<(iB z7I1Al^2KOOAijw0;|c7q`N6>oT2@0Wn?}RYNp4(0SZi#0T=zsZv>WGnb_h6L^UuB) JymtRv_!k)utvvt$ literal 969 ScmZQz7zLvtFd70wJ_G;*$p8TW diff --git a/app/utils/rule_generation.py b/app/utils/rule_generation.py index b66594cefb982704d7d249eac9970c8892f27c5d..431340cd8fe08fe47fa3b0e35d99aeef8926d536 100644 GIT binary patch literal 91249 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 literal 92010 zcmeIuF#!Mo0K%a4Pi+kkh(KY$fB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK IfPwdc0cUvt0RR91 diff --git a/app/utils/schema_storage.py b/app/utils/schema_storage.py index bea7265961c5b77dff3686a035ca5511376ec01b..503a84863e66dd74af8550eb112d65c75b9be0a7 100644 GIT binary patch literal 6178 zcmcgwUys|y5r5aGAP5{x209_mLlFo)7YNXzd1&+CqClZ4#2&f2V~*m=yDQ7r^8vAu zCT`;-c3`)Oi~PB^j*S*M$0*Pmwu5|_9ChcXe1*>JEV-ma%We=m3AZf z_E??^&2%bq)#=!8sVJY`P$Dm%g({yUCus@OT&H7R$|~P!RqsyHe5+i0CC!=Kef2eK zh?wwvvU?#bmoveVXeQ*&rVu-phD|2DsZKN1%d&AvsI*Kck={=89gyDXbmELD6 zKUIF;^Z9t9chT^%NTwObZ-e1}*m3ccoFzt$30IQF+9~-SHc1X>%)S4~oGOm9RBw9- zqy@jhehE(SJQfM~x8YCqX#HhB^q4XkbQWV+tO=N-9-=V7B-dT0h!KD=v3(ESZh^}W zk=GSI&7R*U<4iIgPXaWUaE}2|So%!GX}a+99 zmCQ}WbiG*Q8W{TC=C0-nDyXb$Qi2$!+S>4Zu-6Kh%FKOjL5^fIs4gqJXD}9e0H$0A-;oBn%L6>{U__ z6aINF6|_XGiI;jW`rYR0bb>(PNyIczfCSS8d%2heVJ}r;B;=TB=mbr+S~P*J_SQ}Z zL33pAvOt9}#c%^n`M5yQTH*?Sbw1B`lYk5(OfVi(CaiHZQQRqqUm!P?A`<1 zFNV(aa?F9Y(-?aKlF&72iA0|5E^PW19)OifD##cND_gbPb!yNdwavK(no?zt#X3Fj zoI{#;Dy3=ZXl8RJsstn5Hq;=rMXMcb9X6FC4WQDKVg}m^sqVqB0mUq4Dmc%wDOWYO znwBCrk)TxH$M$dDy;RYdW_muTB}riq9@9w>8l9FhN98UYC=-8nFk$(wwIW>BjdZxp zqM<1OW{(XM;p!np^7>NIGXrLUTF`HnzYy<{4@m(19 zOLWkyL4kQhWJ{KB@n8(c8bq39gtJHucVXxzgE9|eCU>|5T~;e?NmMtsG)&81%7H!Aq zUx}-MZ);^()B6?Us ziHCyIsVSo8J@Ti?=^Mx${P0I z;pe8QJ(h8YDhG#!N4zBJkWaK60XIapRyidY9UJ*VMH2&!WMBq0VAvpQ*OIiy0H6Quo0ojL)->P95wklO z56rM&R$QYY8oN!IC=U8R8sgx*D591R>-fmuL*e^i&hd@AM-ShJA-eebX7SiovN`G?o%pWQyW_g8R$ z+9%5R%XJV#9sc;nXY(uOM!X(ob6Z0vX^O5HWld)>XShZ$0gtNLxd{~O4cxV3wc~H; zIA%%U{7g4Scqi}fi;P;+ghu9A@2~x4eQmtHmUwGF@2~x$zjn5kExgv6Xz$l}s`{yv OqSo$Ewbf)qcK!<%R(o>* literal 20269 zcmeIuF#!Mo0K%a4Pi+kkh(KY$fB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* H2F?ZsPb~le diff --git a/app/utils/storage.py b/app/utils/storage.py index 1a4124d0c0fdd80cc233f1e4dad6447c78139daf..a58d8670c9cfb250c9623d04b52ed61a2a0cb1b5 100644 GIT binary patch literal 4760 zcmb_gTW{P%6n@`dF<6RZOB+{0JfM{p0RjpST%;l-lt$KMJx-?a+AELUBn^>hY1506 z3Za5%DU<>aK?nr_qLo^;KZbbQJnd$tjI~VKwpHIKIcyRBJ`sXj}b9;Y&e9rT{UN0%~F^Qt2DyxD;5#i%WUX+ApSzgkT z=b7mB^x7$rXXZH<=BcW9thB_mWF;Rnqr<$b-3cvMQodw1--B1RQEp6lwrtj4zFUbcbjT%rWY-He^ea;J# zix5?Xr*fY8@UqOx(OT>Wed0khsE7ZhRU*V_dV#bG^}^vXU1c#Z1PV$m@RHFnlZM(m zK^a@;qKxv@;rm6!tPY+K$Xa8BJSDo))|JMcXszHS^EZuc-heDDZUsFXvVzfADv}Y2 z`KYvN{>7~Y1GHtNb72#UHD0cee8RGh?GU{JLdddF9s^{CUR5UZFM0u?LZ-pmgs$mJ zFwS9`gZ-E(*D2+-LIGxHK+v%nIsZR$^Aw-f{<%-mnYbEHd^A{r7Xu=&c&Qk1K750w zg7pc{VwRP|=N*Sr1dWEDO(w1`pyP`+d^&Uz>ygZTfKc`ufb;<%j%GnmvzF#QDe^Tj zAXd2yt9`Y1X@j7W78V->Bv4DB0lZL(nhi{>k^liX;hF_NP-1FPkzaT5`>Ti7f1J66 zrREeQ-lU}&7Jf!~R`RT3GprLKFc-^Wf3vlTQeK&_vJ7ghF<&i6>w$uNWYiG< zyx<2x|ERn&2Nd98^%8{e%qKuJM~?#~FnzeWQLeSaRsV2t`rDogm*>q=Gy)`)ERJXi z>I}JuS-$26As0F1Y)s3p2|y$0G=3DEj&hB1K{zKh{`7|Bp;5|c5z#cY@a369MWejR zN&rS`sG|k>;Mt}~+Edmx1R|AM8zk17W`vv~jp-Aa#fZl;FS@VfOQ#0Jv^2GbFq21S zP$?EQnD5qI6Fn7-W;cNX*CnU9z}#=WM0^4XfQ)QXU`(irxlt2e(PJl=4y3y46==PU~(DCotnaet50^>YGRR zuGg1$AN{od=*D?92Om7VJw3bs*ZrM?ySvjHzaQTGb$WBRzH+<1zE^KwIQ(Sq@tytp z!FfF>cSvD#m2C{jX_{6HfL0KA?dwxHbN*KVQB|s-g0nCwez}I)H=Im_XP`tvIS3HNGb>lTwKzoTqHNkHt0B1+`X-b`A zLC|jA1?7T~4={VL7e!w99%A6y{&eRoz=JrFFc8=ZcqTgwhysG!ol10FG+MwlLv@gZ zSWfIT+wc)AN=|M=4u?Z~5;2A+a3a!e@mW44-t_VV@T05!5zgq8b(cZ zNpU?n!K5m$>ch7YH}3-%1r6%g5^MStG8%M0luR)S+`;`(*J=arMzVh^>x^x z4&@v=-q%P`tYI8AZ!JohF^lLfDm%Uk(L#&8VE#8w>1suZP=D#{fYVimlg4a?Fr7?N zI)a{b@+7bVj17WK99FRNjJyhG8QrR_ExMZ=C9P1Spvk+|X5yj{hMi1y>OPTo$TXj#wYE*TE_1A{x8=|li2n7}vHfHT*Oz$5&fx|>ZWZPY^oW|f{pAno&*xYmr_ yr1A(e9$^uOLZEj(-oH~{xODLFYxq^^(D`mve|ojv-aWW`<>3Ce?vGEvI)4Kfi~yJb literal 14632 zcmeIu0Sy2E0K%a6Pi+o2h(KY$fB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM i7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj_#7BHC;$Nf diff --git a/config/__init__.py b/config/__init__.py index d52ea2d217ae22b4425e26f23ee1752fd8cfbd94..4b4806cac6be1a1319dbc0dd70afdc3f7b2e3d30 100644 GIT binary patch literal 1436 zcmah}ZA;rw6#kxHak+kJhAk=%Mqz`#L?_l%+tf|Q2(i7b+0vvWsiU}oIAy}{WuTS` z!ztU84HaS2tvdWMYts5Jc5c$9b+#@aa=G`sKj%3IV{BD6Y8wYvODnbCNA|(4^`ZP{ zegR|5Fmk@2=_b+)hGEi*WEdzc86={qSvePE5PYC!?Nn;J^R9WrkV>LlI5mv!qajH# zh@&fTNnwP){+8q-2~H44xhYW9i~vz*WnEJPIb!;7ONe_BF6I1sQ6YxkAZeYL{^z9R zPtQndj`(HOU(mHoF>T74idn`9*MscxXX~=;X68J_;=^K$o8)30f_X9;YlI()gCAN4 zeUFYLT#JHa&IF!mvg(6eol8d6RVh!p-lb`S>iI-5D=S14S(XL=ik36l{Evkmi{UB2 z2cq=%p*!#!7;GM>2d-mbFPU&CGMX9}Bk>e3fd1WPwe{mO`((kbx%%_)s{Flre(G5z zxQP_tFNWh$3bmjY-KNm;5?pdT&L_E!LTVt=1Y;aOEIb6;fxf|e2(qf5F4ZsJ*oU94 zHZQHpm)iCsn$|KURK3`)?|rkEzuH@eUUK`3*7Ez>#*V$b-qsLken{ZNHpW6;)u0)j;$rkx~xuscLLi$Me&K`#-nsRXj72aEgSFZKpv5aM+B4H2ucP8j6LIqaw#oQU2&?*}-xcBX!(VK5LZ7{2FM3cSkVuDy8BS`T7n7&nt_Ae+RQi3loGQCJqF6@*1t zs9F|1*sgf6qLls^o$UHAoR91Wl_ro(p7-l{pNBvQ@2=N3iiC0?cgM2-S-u*{o&De2 zFCc`D6L<5B2|!qs6UM3Ige>cVAQLow1gcnwcK13FtYnUbnpJ{9yvUIZoQPGZz`7Sg?XF1p^wAA`xg) z!Hbd(O>zV$Z}-aH?)1}3*?R|CkJ~f><>34DN=Lt)rC}W1gI70NYnv^sI>P%_Chk`Xt4$n}-^sX8F?ilL zH#DHJ8G%cymoLtnCRr3w=ErH6xzLJdCH?c`06Yb{4?4%yNf+DGVwU=bp2_h{+|!;d zlc{WAaVp#pZl&O~QS#`U9XE5VN(G=Cev!kk)5DX$gTp512$44%jgK~TVMXd1k@Ul=fHXA^ n1oS}>p@ngNM1>2lwXWP*SE5}f38ys=6r5s4^&dqUvY_)1WNuVz literal 945 ScmZQz7zLvtFd70wCIkQju>b)8 diff --git a/skill/registry.json b/skill/registry.json index b1b1a8ac12009cdd1d64a45aecc1ef322a0f8b43..3eb9c8a6b4daf139705344cdfb760803ca64a73c 100644 GIT binary patch literal 954 zcmbu8%TB{E5JmU>ic!{eB3QCR0U<i%957 zm;eVYEUkx^JMx(NfU=A#$lb7n+H&y;jGCyX9G)KT7mHH!In;`_T;%##t{2zOH@CS? z4F}d@uo|$#AT*A$+`N28Ysx-ke_I^qHAV*5lH?ZE zk;ZSKrbaFWh6!;s1{*J6iNKWUz~sb|*-UwkphlDPQd8eG%<34GC%5au+M0eBzelV3 z#bV`K(;Vh4T?d3n!8@zC0b&@ekD4DGFd}EveKAsD z>?k;7sg1cEBXmqdW=3F4BwmSUU?RORrfHf)FS+%I*+QE2NU`Ye=0nAc%c^khq-CE} zb{}5$YNg+oVx4AK+se%Asp#F?qF~H+TK33BSATM}35&eqq^7{<2H@BD0{sE&DaiD1 zVQ?8Y?=Oi zlV8Y9lKZsbj-8TglwOkG`@n5Mzk8f;4)=_I~-RzSSc{ZB&a=$V|9WBOKmnrZMa%-jQk4tK-soCM`>)VPA6}QIUCQC;9 zfb)0CUDtNkQPI}qxVKJDqZ=Po7(D%O`Tl2WIVc3A7IgXRPgGemv>ooLP97OVTGRJN zVte(=Tb%gbcAkBa<$yJNdO+%Z!ZdsOl-}R4yV1PMGQlTowI_eAjiF%anz_FZ@d#A=)zVfWAh08)UV)>SNZtsQ7;-Tpkw%CZc68?scOWkwMg zpC3qwqX&nPh>w0~YaC0#yx1a|?G%4`+lf2CEld-7GWo3?Oid9nrnLovm2G>}V6BY~ zd*r~T_7SiRVCpT2thG$x+jgBY>( zR-b91t<(Eh9e9?o5jabS|DQncb_(S)o+AqQ{TPv$p0C(BE4X!oG1vH1`5Z(}T^ zZGJP0@};Ov#RX{N!WUnbA~Vo}MmzMh@ClsRCY~f_O_En+r+18^rMi{eKQfW@b!;1@ z4Z1fOdp8N}@i(;h7W!#GNR1Bb89%yU_C@y9U4QFAn>sbJh>f^iGr)ob;`v6L z>?@JJ7{7>0&!1v@i+T>wu%x;XJiiAs67aDXyRz(#lgr@^*VLh zauijtY#Kvp_Qo1dHBH#bfO?rYhKPrhlH*xbqmV`o{x3=Wx}b{zTHWu%7IK`og#ST+ zDL%ZCpP$y^@7U{22Llk>EXxn2l2HXpP%Ih77Z^?u>p_`$XF%Cx_Yh_*2xAvmqjmOF zI*k>ewk<|o`3==J))a-VE0h>g-h%z8;Kn)~=kzD3f@av0*K17OO>9Fih{*aAr(lFN zH8;&;0dxP5#bL^&M1)*2u2Me$c->9w4u*^$DokzP4CZJyi_KRDt4->$N&h_uIw(q% zp(Hbg)y=p7NLyo{DQm0*CFy2#a3{X#oH6H;vwzsxxC@ShQGmeoHsf^Uw#R%)&3CWG zATYW?p-_@FSUdV1Cza#IV0cCZXT6hbxL$V2okxdn)s41J;*f=F1bEHHcAHp$IO!ho z9UCw%n`Pw~6<+zj4YKvbom#_5Qp^i(*l`D_g>e_GYEWiATPAnWW<{-LF*tBB{KjL~4f;{QPqpoLN@WBme2#6tgQJL$b!pQie6> zGH&k3QC7?{?eTs&(JkuuD#aDIDvX5b8>l!bNuA0+vpa1Jz1?9#Z5e}Z?E1L9ULF1U za5Xx;nhYN~9ZP#9ZS3>YXQwZoJwH9oPhOsU_53V9JF8ys$++}L%f)=4UR>d?2hrK7 mGt0PGjH5Mz76;^lpt;pndUvfnC;({E+Kyi#$`6q&vVQ?sW3LAQ literal 3339 kcmeIufdBvi0K=g9Qy=7oP+`D;0RsjM7%*VKfPuS#0SyZP0RR91 diff --git a/skill/yg-rules-output/agents/openai.yaml b/skill/yg-rules-output/agents/openai.yaml index 61b30cfba77705f6807a3c134d1ea54d9e0ee606..8d1922613f89c448c7bedf0cd367a1e066e4458f 100644 GIT binary patch literal 309 zcmYL^&q@R_494$*?-2Gp`T%>EIf)>6*wYZ&bT>?!mLyg8?d{B<9s(hMzVG+3IBCK_ z=f?+t$ksC67r{bjI9+CV@0kqVy0`A9?Zj?XeTig2xj9!EcQXkoIsraC!hnrw z5L8@dAPVh-A7fA3UF|RUww+kw<$2!oJkR?nz3J}76bva(K?_K#@)85As8V2h$$+APGBo6Ar&MTj841f4A^4B^R~ zRG@^2qL?2U69ER5Rd4ZZ@NsRh^?C52%-e1MV2M|^+`|rUy>U+0{H3P5b4183aQDvK z)h<5VqfYe6TW`D7hGW}&rQ=u!ykdFHrN|q2d6{?5c%$Zi+jlokyheH0uX)>D{%eE3 zt9f7d{FOz=-sj!cU~4%NLUKG2=hWhr^6!O3LXyd3SWCnwB%Ok%{zZjbpZt?HU$CBC z6Vk~zaQz<#|HdPM4wfAj?AGi4MUSLXVW$LeH+n&ZyZf%yAV~=Ek+lHvzNAy>VZRw6 zys_#X^ax2LxK-!%pNRy9(!o1!5~86X{;U4L%$@UHG>hZTX%ibc@(EK5qa;c&k%*^v zHR2uHp8a=nn-!eV)i_^1_Ft|0ox{O`?VrDmn?_W=ZSmUX|55*9oo}~1`@P%Rxn$u6 z5%MHQHJE%j4vGO(lcrQE-vFslpqhO1>XKo>-Ill3i#BQ4uOe&Me?7_&#f({%Opc9@ z-F_6dJdh79a8CD_UMwhD7AA1T4IFBO1S>9O%%Y@%$P{Ddxvb|UMH8bF`FAnFO{9?Y z*q|V~J70LU?0vUI&^2`)NX47?|ZR06^SMh(hdP|%r@RW$SoZ%k)0Wl&Pg voT34hGPxM#j*b#0OzSK|L8f^fGI+IF6rcvmz_c=lM>xXfA)^;H6O;P`(<|J0 literal 1031 ScmZQz7zLvtFd70QJOls)2LJ&8 diff --git a/skill/yg-rules-output/references/output-contract.md b/skill/yg-rules-output/references/output-contract.md index 712f69ee2699c940c315c5a2b68b38c4f40a7b24..4d4baa093e008d2d7422940f6545e6b7f655e13c 100644 GIT binary patch literal 1129 zcmb7D!HyF#487+oEcF6XJH0O_1YKApXr(SEgeK|4vkgs?k&|p&A^sgFlUCg>7cQfW zV?RH?JWpVm;*cVI@Gg?-q7ah_tjO#Yo#5VB3_>haw*^WT;Rzj*ipD#LD(t`?TmU?B zojrkf2!2HCz12u}LP#ki9-|oJ^9&MZzjJMC^q+aY7vgb?Fjhd=`eZe9%tje^1#nZ@ z9Bnv?+u&YTz|1W~6%h#c3=|-_e-g?}!u&$0`4zkyF<6FmLAW<)HLLJFAjB>5w=WT< zOjU(4bYQkKkmIDSHYD$^uYn`jMNg;ZDy?UQId5_7&@wJdJgB&xGVMG+>e8h1dyblo zu_lhy{5m_$;6_dFo5vfeb%E3G;K1 zaZgiV(WFb(%BEOtk!#?ya@z7Wd#xy8LY5ka>ceU~mP1iAJ=?8;hrX(on{X+F)OCnD zz=rMofB9LTne)E3#^{P_7+g6bm@ zs7uG0cf1R^T_SwPy;OuwIq=U&qaF&Ll{Fd;o^~7WccT#RR}VbU-~*TO-mI4EN0_U@ zj5{+wOCZlH!VXE4H-tS`_eth+wtWiaXwBZla=J3*t@-l*W$I$594T*q#-oV3Rg5I$ cr^O3awOO_+lc|q}6incfx`AKT%WsYN3$A~UL;wH) literal 1129 VcmZQz7zLvtFd71*Awc60000DO00961 diff --git a/skill/yg-rules-output/scripts/validate_task_output.py b/skill/yg-rules-output/scripts/validate_task_output.py index 0810b3efda62ce7e06054983d13e9666456d7316..cff3415138e343ff2fdcd30daeb4657e0ac931e5 100644 GIT binary patch literal 1767 zcmbVM&ubGw6u#%Lcup@HX_odTg$N48gVdG^f|RmMGqdT?-Pv_!QWHuqrD#zs9u#R6 zVs`^5#p>P863=IJtV%lqF&kK|5Z!b zpS30#ZKd*Y=bC^fjs_IlvyMrGGglL1ixnMPOWUC~JhiNp0i~@9sn)C_>L%4((iESK zi8$uCpa-*Qt@9A}H5^PQcGkHON`HN>Q^UIkm!fprz7(e{vi5+>R>p8)o1|mn#KkJ zW3x?>Nl&{}gXF^O;^3;2a7Z)86SN^8R02bY-n}fmhN>g~DQ2eEN_w z7GVLGHz1|jkwq}QoHw27x@AC&m8c@h{j+f>r~V%OG>EuV$1O4}lTWn5$5d?FO>#E7 zA@ffA#<@avtW0fgu5aQNIL!1C6x1&Jo=W)oZN$#BP{tJaC42?kpD42T8AbLGNfg;P Yi6Y|rQ&eaUcY9VYR=dIk{>AFG-#iIMlK=n! literal 1767 acmZQz7zLvtFd71*Aut*OqaiSCLjV8<=Kui! diff --git a/skill/yg-rules-output/skill.json b/skill/yg-rules-output/skill.json index ab26958152ed1f7b29b1d8c354c12ac8796bfe50..3dc25cc51d28a79935c3f8d25d0fe9d7c1986bf1 100644 GIT binary patch literal 1109 zcmbVL!HU#C5WUY=G;=lyUcHGfi#Q@E3X4c+)0Ip+o$lDxnVm2Uc=X^wP)~}hh!+q3 zfcQDi;9pqXon*t}B6VmZ6<}go*R(Dcg~UejE+0TA$LyX5vAa_cU}0tB`Xvv!l7c&6TnkonsU1D+ z&t#KHui)D=VdMET#NO#v#5xx?*Bm{ZNTb+Y7z!!#0fR#p`W zBn6L14e8l`{PgSV%fp+q{fk$J@2~eC-Up~WRPmzK^Om=~xZMBo(`aQc-V^?H+ zKHR1AofaB{lCIR{)|eO!@HPs~Qs(lIcz-Rw8%A$f}c literal 1109 VcmZQz7zLvtFd71*Awb0t000D400961 diff --git a/skill/yg-rules-pipeline/CLAUDE.md b/skill/yg-rules-pipeline/CLAUDE.md index 5d70a9f9a153e264623f2d6d8a403c9ae9ba226e..0885691e76a2da1e350085544bbe74db1082d814 100644 GIT binary patch literal 963 zcma)5v5pfl5bgaHBVEhxNt6gt0VfK?=>i2(q>W`y5?{Qw@pzM65G@^umg*#^_^>PT z7dLBXa{(O^TdX{OZ#;f8&u8%dqPprV5?q>q);NUO##k%FJ3>fnLqKB;yEQsknvp3Z zLaRb?Dsk2Q|}sLLp8e92C66CCVfLW`~Xz3J= zbpW33e|_8k_`U!6<@V<0_WRdoWg8%PYt&G;I@22N^Mokhw%%3uge>VTkFYcbjtw8D zLlC0B<^h268c)Oq83~&%STA)m`h;gXs-E#&sbM^IRHpc*xbZ|&@#lH*%csP)Y>fW=cbq3A u{*%iCD3)1f>mFLXl*ZB{7>yiL2C$dhV~mkqGCiqc#KSw|4yq06THFCP=ve{) literal 963 ScmZQz7zLvtFd70wI0OI#!vFyQ diff --git a/skill/yg-rules-pipeline/SKILL.md b/skill/yg-rules-pipeline/SKILL.md index 41d3372af4e001dd1bac7bc81d475d42f25f3280..0222b1cb26644eec710bc2a97b3b92cc7f99c3b8 100644 GIT binary patch literal 3115 zcmb_e&2Ah;5Wde-l;jJbo!KN1e$0;)C2@#QgcS!QBuhKJ)3v)D_jFIXd%U|KBqS8^ z2uNJufOr8o<-*e#m0;gEEXLn|*tLm$&@2j#b3nN-Sr0ueFy=Gr_s$;DT z7m|JBR2P&rhxE8NWF56anSehMhS)F3ujvrv``zCq)gWb zT39XFQLwaR!%hS|xxZ;x<48%5ggcXV4PSl0+rFZ&Jkxr`28Tok!ZCGPH0eAXEtTUY zShr2)cdg_N`IYUpq{eEEXC!Tm+E2(gD{jRky}9g_6sF;P?1UWh3o9nxC?AwrQYV~e zH}yDMEO{!7&|9zkG=fwPp#vFskvv49x3pFP&I283;m@+C&RN;RQO+pY`|`Vh=QAb0 zpCY567NS9}MTu$@2YWP+$5Ipr2lVARyK}|sqKJ@$mGb1zl-3!Y7<-R^X)R0uOasoP zbm|=7<+>or!yPOc&s-rh6laI#ggV>x8r4atAcvoh`IoSE&(Wvh&_ZjV{PNIspo* zS&?cx>yUqZV+{IAg(?7iKo3(Z9_3cNYfW${0OH_<=yf11w(x&g6m?w(-h?8x?zEt> zm#U5S8ybEN;$RF-RyF>drn_%Xy*04Pjd#U}lGXkJ-Wmaneu!TF{nN#ZKVJUz>%|W* z@*P4=v}(3hE7Kdh@6tA#bmyO+f4g}8=f&^8Ts;5rnoTDc>6IBU9v?NfZLKNyry|{= zNP~>rORC4D-l+-Q=J;8UX_IMw+TMpeBfuKfTCS)TU03x%Xe)+0NFAkYQYU=+bHu?t!enpGU= zY>)!jos!VFW(+&VsBJG9ob+96D?~V2f+qqS4+4lys?nLr84x%`xM36O39bM=T~VO% zx=9~eiF9Hkf>w*-D6(XX)p2Lh`gUl&&aT<{6>D8|Tkwj>1AqDoRiEY|@TVB?*+{-s zx23Yoq?`YjrBSj*<39!!)f;7N!nLi>$laiBx zx%W~t8R-luP4;{iGla;%O@~eyW@mpRscV)5VYYiScFwwimfB7;W&y++rR4~1RTP(l zV+TfTQ+Ut-AGq^7?Lp0MR&*R?>&oOtNuoMUt5yY z!fbc}t&0wY_$GaHYDarn3aaAW;lN81p1q$W<-L4nO}&Ahd#cOwQe_g+cn($Z9;81J z$A0FrV&xNG6XiIYBh%cj=+1R*dY$ngV6)L4qxn7(2@qzgBO5-*iwa6|5+%6dxAOGN zFg>4ERrNM3J^=LKf&Vb5mK&d8P4>!5TM4$2p?ATwa{2hqPnU%wy@=n z2cw+UpnjO-)hO$JXMKE=a|1n!>lvH0*d!j0H2wv12YLa6kJKith zw75)nJeExWKuHf51QMk?#}9p^{$c&1mcf70Q?n9giKV0O5=gb<1v|zb=cj4K*=?^0 zsf5|Ujaa;{aAS?cP?Z&9_DZ@V$4!E;cYpw*@7A6%JaTj9GuX*{EK256seEITRHR5_ zb)!VbvJLFMi!RpTF$YwAz<_}p7z`@_0RR91 diff --git a/skill/yg-rules-pipeline/agents/openai.yaml b/skill/yg-rules-pipeline/agents/openai.yaml index 8bf99ff6c11115bf80060b1ca58ab3e76cf5253a..af9405e54c8c85c6e4de00999a636bfec40dd2aa 100644 GIT binary patch literal 299 zcmYL^F>V7v2u1sx0=f3)0PZ7Kks?beT&>W+c#&seG{eZr?ZetmQXrbge;-ljmND_+ z1%Ra2g5R^^$_Ln;k8m1=JA6pxBFej9`eMyz;+~pR7t;VwL*aa!9&m29LbgKOzzuA8 z9o}EJTjGqP_*?_29*3Wu!58V!uTsi}w}`R^D~fsypaLsRZd0s(NwI_l>a!Qzoq>vm x>sM|W$hM$8^tAAb`$!|W3?bCSkY)QVoEKJZ=uGhTmAKrgcWhU(Ta@|h{{wiyX@>v+ literal 299 NcmZQz7zIRz0003i00961 diff --git a/skill/yg-rules-pipeline/references/local-pipeline.md b/skill/yg-rules-pipeline/references/local-pipeline.md index ad45267cf04300964d972ee47ff6a3fa073ba737..e18c3d6e57b778997d29df156d68d9d8b5bdb6af 100644 GIT binary patch literal 1319 zcmb7^O==rK5QX=1iUMyO$c*+`WMdN}a6nkztJ~crsqLQbp?_p4A&^~;kzG!Zl{Yz! z!NT{;PWR)hnIQrB~9@%yevxW4huc2X>09>g0rGIdnea_f>Y3)=a!L zF&Vd_F8EtkiImq&_a?1v^16}u<}92a_?}kkWSiNG;w@*l`UVe;~#t>ZVf44x>t<`?_CKz-y42Vsn)WrGo2dMT!>+2XfhnqBxK#8$OH^9&abtNBm zz!HF}CUKxrG>G>v*5jp$8!UZzzECiV5@FA=576Iu-ssN{{3eim-uK{$l&tr6xuYB* zleZEr9rVz%QYTxE4NaFM4~J+$+0`VT{``1+`1SPr=i~PW=<6Gf_C?ALT_2g@C}R9# zGH{&1CUGqT0(RaS1v>wZv5?m8-@>NzBoou;j4xOK{u_#%gR@+56Xk{%d&;Np1kBS} zsUT5kndD@D(%VopbiGD#<>L~&5)b2nUZM8E$h8h;!;V6B4N}c}506v5kz!loR`6GzFD$^riZ2QNfC2j(;1c9sXkuk`?!j60{+!8@PfmYIh( z@#b(gD^3d#NI9PFClX!BfQ=W!z9=2QWH=VRp_dYV&;mNH1It8Wzk#G^j2eW2KnYji y!VWj^RN$0@Bj?>04xX05w{&(nMK16`g1Ux}{C$0hR;th%am?^{x6F9YP4yQk$>1LV literal 1319 XcmZQz7zLvtFd71*Aut*OctQXG1t$Oj diff --git a/skill/yg-rules-pipeline/scripts/run_pipeline.py b/skill/yg-rules-pipeline/scripts/run_pipeline.py index 07bf775cab1db5b5e23645320365cb352c3e94e4..b8d112567153c4703f45bfe893cba3708a3d1fc9 100644 GIT binary patch literal 6884 zcmb7JZExGi5&o`UvEV1FwV34YQ+-tdH*rz}7bmsv4p#^U!H_GN7mCYr$=Isu|K4Y2 zcFCnBE2sfm)N*EaUZ0s=m)pj)oyyuxleJdQO8H(I|MZ77wSTrd>mR#vt7q%hY*mwW z_f`2tInK}cDlfWSQ`Q^5eo^mcv)PAVuijl;zr9Q^fB)t3`u6J6^{rZ}eUx;MU38|R zq$$??S(w~^KJvr1h@NKeK7G8nx}Gw}QSw+>A;JR_=k^bKVw_W`DY~=EW ztjoGc>ujqFRyHo{rti|CY|q&S;?Uc3;yY9NvD39JO>NIr*Ef}3@p6(RcY_zyf7Ph{ z+O#7R=@>|0J4nkstBbP8It@FA-PJ3#j`pLglnD+pMhP;Z5KTdBqN6r?A}>wqH>S+=&Jhb+~9;hGnZe z-k&_OHdUcpmO(y=qcp23Bw`>tFh!^#AykLlGfD})BFlqI6rAfwlhRULpSy{b1wBGr z#DgSpq2jVVSR^AT(>UvZ3%ZEiw(X`eU*hOb(R_Zug^&>wsX=?9a7Z^^vi*8pJ|>lU z(9n;>9zlSKKoRdk%qF;SK4fLbL2P@JUYFUgF>?P~nd@@}a5+=7l$M1{X#yzIcjwr% zJEK3K&8l;?u1to~LTMLe-btQ=-37SNSy7cWWh@Cu=nwS%Gk=3PR<+7(m)Z`Aef~^{ zs}XQ>9+Iyg?%|S&u)iw5%b3l$*TvOe8su z=zVV^4#++#P%{LV>kO&_W~YM52p5j2Say)Dv~GYc;$9cLth8GFA_2H;Thqqth`tsI zE>sjqY7CTY6iW`A+B-X+67@6uD<+(){b<({kX$etfn;1sA9|(lBP#2YK>p?q#TYpz0VubL{aRL4DsLbuz;NcEw-G(m z+Lz1|ZVM;dpa%i`^QTC#Go_RrgTuQyVaK$IIdslm03XbBy}Pf|rff7-aEy@#Q0)hs z9WUI7_Tnm{#;BaINP z-5BBuZEQd&Ul~yRo5MELG7`K8tX!M!z3J=1!@(781@vq&8ku&-lGa3k%oz0IiYNS$ z1}g0Zx$@#@0}ykhz_Wv4QP2rBM{0*6gA{&I;g6-Ygj$XdIsm!Q&yHyOP@;o|@)OhO zI*!^eKwK0Jv5s2`Ax6#z3)2oVDkf?_LWl%4SYdGf?& z-?STwY#b=!guBecjN4ZMS2;LXQDF>Az45_xj`4LyQPy%6sSc2%a>iJF$7Pk={4oSgq#*eG8e_kcsZTK zBmYj?n*bRO41U>-y3MFUgUu%r3rMvhA}+UDS~M!tP%pO2 zeY9z_y05af>~_$MAuU*XnwriQ;*hb7g5nj&W9pF3!Xj|+GY@HP20ccF1+9L|s$TnU zcx{F{VvItMpkAo(i(z9wWFBg4=!x#AfMh*7NyIs@qtmJVceP}V#_ytUSz`>(FvikZ z0aE9k>GNCtB z7{Ui)M<CW9qqVBHr$$m z&fB4OvD3x%J|O)5X)du4YPy75-OX{l#BG*Lua1@#q%mSFtLUJ%Cz~C-4Rxfnf;WN~ z267KF0F(!7LjU9r5PUnt2Lz;~RID5Lc|zvroU6OYxS=W z3#v%#rrT<#4P8J+Tiv^RyjXW*Tc?UgDuQSYHOFsQb z7Dn?kb+4;t8C?aUTYa&u3gxgnp@6D|wNeoIdXt`6I%cZ2W_n~57fxH~_(k8HD? z&s%{GiTV`t`FQ13Uubpv&!6d1gw937QW}4-t2WZ{L5?HY>UGv8&zEW9}J2KGz-~K74xsuwhRg^a_-G zO-+JiKD(J*F6k_f(wC+NTV^0k`EotQg%Mt-DdBaRMuOBbSKaRDe+!q7Wfu#Y&u9Mw Du`-Vg literal 6884 zcmeIu0Sy2E0K%a6Pi+o2h(KY$fB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFks+oU>f8A A0RR91 diff --git a/skill/yg-rules-pipeline/skill.json b/skill/yg-rules-pipeline/skill.json index 02e419976b270c52dda5edf8339ecd2948d38e71..6becb9b5fcb7291ee191ad15ad12decf76dcb455 100644 GIT binary patch literal 1518 zcmbVM&ubJh6u$Sb2y>LqE_xIZL`xAXNX0`bWeAhEv*~7%X_9GoDZQ!fK}7ro+JhIx zTaSfW^snjk$A95VGTEKB3gTsVlK16(-+S*%w&w^*Og@B?W}Bc5S2DRx5?X+?sTpx0 zdYdwBi*AE+K>&H;EwWO_lS)x0RMP^@GXtHQcYj$b$XKbnKjryqAujt`r!M`!Q9obJ6j|Ngw$ z`{Yj{>SA~IV*lm&uXoLhZ)f`l&Cd_b(P03B<80o(DqF^QM0abu)GW*w3sbZ5gU|$3 zt@(!I2=t^~K#XJzQGqm24Uiv}S&i_m}QH zd$7<6`9AVIE2-oIFxJy}6RaCF1}fO`%8=4>?}k>@meM0Gi!97X>4`h3p;CrhTxD7* z8~Fv5MU4h?kZNLwnAj!7o@m&palj@U2x>-|0gaYK*nkQHErvk_l7Y;*!*Su$vs0HU)wU}H@dCNmY}-dT+ldh2Itj+Dr{RXWT0?hyb literal 1518 XcmZQz7zLvtFd71*Aut*O!#@N71?~U= diff --git a/tests/conftest.py b/tests/conftest.py deleted file mode 100644 index b83d2018862d6a012b1184ed4f81af70ba5dec55..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 65 LcmZQzpb!8606_o& diff --git a/tests/test_domain_routes.py b/tests/test_domain_routes.py index 576b3fe7b0ec09ef2e899a2fb1d78dbf95ae7d70..92f97e30eebe59d2db9e70a52283e8cefb2116a7 100644 GIT binary patch literal 1809 zcma)7L2DE-6u!@|2szEbcD57`QrL@D!INO?NlQp)-fUB6k}=6_Eyb&d2l1+i6|0Dz z6g+t7&uL40@-LW7lG&MEEge{P=jG+g_rCYNEURiEHEKB18kCL-DJsMSVlIB`z(nue zcj1tfRw8>6GHR-`-N+>rB~{(RUHjq}XkDjLGzKed%SA;QM^qvAi@0TnGfz)_o~Pq; zcj_pLGJ~(sMvL>nVs9D#amUfV-KGkX^$3|KhXN_k59?S#S@@t`u&=2(5KU0aI3|SC z3J6Ksef^YF!jvfulI)ZX)RJ)>cZ?R&vyuVV1~lNOrg%+UI8LIDln(=y#9=8yOC?OE z2`QqoU8v|H>3{R>2=6n!i>!#|Lo&fNJkxQnW?NL7(>5>0Hr46x^-i6vn_5UZ1)TKy zq+HDKQ%+e67M`m?H``hUpsqY}C8!1WGWYUKGjt<4nNib=v{lOpR}R8P{xzp`AQ-+S zs9JCZBcwFdjWR0bVAB0LUJQro+Y*{)AzV|H0;%sjZD<+yP)2BNb#?BB>oYfYHh3g6 zRX|Pz&wyAx&AEZ~vRZ?3(;Q0BKnhkudJVMJ`Mn~#bL@FRp>ztG>?y(H zVg_WHPHt( zOmNkdn$=Y5aUo>2(zb5M#`nN(Uov#4JRLauM&H^0-_y5D1xndFWZM*Q`uo-C$;Y$L zKQDfL`E&B_{QdWfugB*f-kiPsae4gu^6j_FPcP1nj_};^%MBVjUeOr@(*(;K1^p1& ck&Re^!j+CD6NCw||2%|X*Xr&M!$!@9zjT;bSO5S3 literal 983 ScmZQz7zLvtFd72GECc`p*8l+k diff --git a/tests/test_guidance_analysis.py b/tests/test_guidance_analysis.py index 0351950e0f63acc713c50d798708928cc3d745ca..d3f707867304fec2c6a95b168c139d1a4374b900 100644 GIT binary patch literal 7222 zcmdT}-A@x)6o2Qhm`t)s$zp@L4;vC6Hv3^V+3b^Vl}yH&+jiFJOm{v+G$f!PSg_!_ zE-DJ*2WS*3Qq6*_8InbG*&(W=l5_aZa0u97r(jjK zxf6F&n?Sd4YKPWTH+1{Na3v^@ z*ETBt!wqliYH)8fn7iq}nXGM;8;?foD@(Qaw}RJI5H9v4jqujqwMnVJ9jkARhueb6 z7RU-sscnwbHtv1goboDv2Gvb(X2P4e=FiW7m0)*h#P;w=u(0CaUkJZ?e@q3{>H5r5 zf4%CJo(1Jsjq#h__^|(Gq%l4ntX%h}#{GxmNwfMR10&yq?^^Co+eKYt!xDSAyDQqM z$c75of#@c-(l|@;%ajNw^(srDwPKGT!oNr>BM)Pr27nREIc*V;YyJ4UE9)tp7^zrX zcaLx)4n4EyX9G0RNJg;&Me)W=Z+}K~$VEr&=k7maxrEU}mltG5$pcEylfePgQf=Hy z&mX}W)Z9^QEzI@pM1GJT&iuXcu!VCg!rY~ za8|%y@ZfO>T(2|_>$is|0S~Ykz+J19z0yN(v%*3v;i1Zs|6l>I2MF=jHvQ4*`tk@! zK&ZrF#?!C?Zk~9@fzft;G%+%r+YdoQmE0ILB^~8(k@#dBi^L!hNg6*@D-grRNEX2o zV%d_CN6rGgONwbYmZ?jM?tTus3ZskkLn9Z4HkrDV)?h{Oe5)}$U0=KAO}y|{=Nos& z{PMCl@wQf}07LlqhlA>bH$5B7mEZ~Rm^WRjuP^x%{{RGlA%GsdnVY~gfHi;NX|3|a zzjF(S%D;{X3fDAdSAsIKB|~WaF*4%ZV(}3YeUbpyA9jc3@dTlln%{@o zsiAo|DF@I3WD#3BCqsReFi{Ry=n#BRD#6>Sh=nN}j+pTNopP|a3YhZ$z5>xcYlunl zpSFGhyu6VusHXL+@4eDoT%IDO-D&6sOqHZW*U29HmJPi{Y*$AQM9^vek-98~t%cYJ zfoZEahUpM|E)D@ULMKA_TCGpofug{NS6G2Ur5Vw7WXFXf0DD!_Ag~9$j~}KECAX-= zRxGVZd8H^r3uYN0fTB`Usifx9W4*n{`2vyjIAQ>RExR~xLnT}TQC^J1BZ;w1*Miou zRn3nki<@_cJ!CQpMN`+5K`Co0&G3ae>upYB30+;}JN{SG3B^QV#!&C;^bG6W{$wlI z!RB_KG7`Aq{4!Q@AO~oU9L2Sic32&FfGax<$!9tCfac^=iT>#0<~^~Ss}F(hKUnl% ze!y~hEdL`MBPWB$I`_eUoj=CA~H0|hgp#Z%{j=-?s2zK6dbyYY=@cP6u zFAy~?#zQvUnuflQ7;3V0%Zfk14Txa5IuR~whDt6D^$7(NZfi_S2w&k)0_~0}IF^>n z!DYyRY#Ex769)3c5MYm{$hewZR0vV+mYA>7$u2GnOQ-_)UjXLFk<{@X;Ts?tL==AF zzhXuZAtlqlnVONJXE;=67AZg_Y<}SRfRRO}Jxi=TT3*npAE4I4X z5X*hNC)FV_6o}YPK(7OS5Wa>&$SC1@1R5Z$^gELhp%uY50j%(_J36fcoIDZ-tq1)( zx)IVzPKI8SAx!CljJE}n3`7LQyCCb@C88dTgd%+m6v8k@gHR-z)twR*Q?_iFRlpg$ zl6Gg33Pjc10+qBo$~zO41uor35G?`G;b3lt!5pu$;X01-ZG1j1HaZm&o`);qCt0^i zsslq@4qPMsSkQ56kYQ~S3zER67Ev! z>yK;IYIxUycRz<2#v{0*jV$HYxmQ7-qyTh6@P``&kzS%(pS?+!PWCjOdtEbkAcL9E z`ym2qbMnD}@TZ+GGY9VAP`2P=@bSZN)|au8JALhAX`%(?2-thFOH8Y6GblfPA#rwq n42~`Pj*?wkR*)n^E)Yq==2?^^`ZJs)hCkCqKi}a~_-XB5%8T@d literal 10760 zcmeIu0Sy2E0K%a6Pi+o2h(KY$fB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM R7%*VKfB^#r3>Yx*I4~**00961 diff --git a/tests/test_guidance_file_extraction.py b/tests/test_guidance_file_extraction.py new file mode 100644 index 0000000..a5b0cc0 --- /dev/null +++ b/tests/test_guidance_file_extraction.py @@ -0,0 +1,38 @@ +import io +import unittest +from unittest.mock import patch + +from app.utils.guidance_analysis import GuidanceAnalyzer + + +class GuidanceFileExtractionTest(unittest.TestCase): + def test_extracts_plain_text_and_markdown(self): + analyzer = GuidanceAnalyzer() + + txt = analyzer.extract_text("资产负债率预警。".encode("utf-8"), "guide.txt") + md = analyzer.extract_text("# 标题\n\n资产负债率预警。".encode("utf-8"), "guide.md") + + self.assertIn("资产负债率预警", txt["text"]) + self.assertIn("资产负债率预警", md["text"]) + self.assertEqual(txt["method"], "plain_text") + self.assertEqual(md["method"], "markdown") + + def test_extracts_docx_text(self): + from docx import Document + + document = Document() + document.add_paragraph("资产负债率预警。") + stream = io.BytesIO() + document.save(stream) + + result = GuidanceAnalyzer().extract_text(stream.getvalue(), "guide.docx") + + self.assertEqual(result["method"], "docx") + self.assertIn("资产负债率预警", result["text"]) + + def test_pdf_extractor_result_shape(self): + with patch.object(GuidanceAnalyzer, "_extract_pdf_text", return_value="资产负债率预警。"): + result = GuidanceAnalyzer().extract_text(b"%PDF", "guide.pdf") + + self.assertEqual(result["method"], "pdf") + self.assertIn("资产负债率预警", result["text"]) diff --git a/tests/test_guidance_routes.py b/tests/test_guidance_routes.py index 8da89c24070fd5f747bfbf06b5c42cfe17933093..9ba59e26fcc40fdb50b902ee1a7eb6539e7bafa6 100644 GIT binary patch literal 3924 zcmd^C&5qkP5Wf2<2m%IVU@hB=HfRj^kpAb;7HHZ-U@Qo(MA^(zq)Jk|br!xCIrRBZ{*87o^H^bpaSysk+QfukGaDGr&Qxa*24D+9EVD{;E zVLIntcv*_L7{_5Xsz^(d-9(X!`)oZ30)^tPTlf+O?EqxA3n>KWS(r{ngU+pHnukCb z&oWVY$6h$2nKw5=GnpUyT<{ygtZ=pR4h$^sX(5#WK{_YR-|;2A2>&n^ob{IHBK1Fe zT5>0Jgrin%#1MwnM%ro<@YC^Lsl$Ss#?0Jwgk{e|D7`RdWUn-HobxhZU$if zoi%#nxx%fpb0^P~63$(;!U|&V75f^#)bFdxU2q0AlK zKJe;oeB2c$A`nx%pnFx@)FfUHdwp0NTXH2|3dfXK@od9-$K(H64sFZpA%VTEka$}> z@On7afX@^J)(U<{Jt`idbl1?{-m>~YVb^M$IM;uycp)2o*gx}|N-SszL|sb9U8rCxM^n@bhlZ@LH97_0EPIokH)}vwX&;3f_96laU@9RHaz5es}zkm7l zuUEhIl=nLFx5hu!3A|Z$b$mhkByz_L0q*9>3S8O(*)2uVms`?)MWgZI^YO484|6j7 ldOrMSK70lq3YwA;BsIJs{jE2 diff --git a/tests/test_guidance_storage.py b/tests/test_guidance_storage.py index f352d691a431a6dd5f326578e753fa101d6e08a3..e39fdffc8c53afc5b9fd0e17c8acc9486ba26fac 100644 GIT binary patch literal 4387 zcmeHL-*4kK41UjFVd%*L8Y4}6xvW4Qw%uX4mkqex_L2mGV$rEuN6IX@Kd$Kiex&R; zvg0=0fDOYiqd;Yuq(q9}M=EN&Glh$k8K`P>V~yUAjopt*t(*hv23cXY(f%#jn)EiR z6?ej=*Mmwx>~=}%RBjXNOd&R~7y4kfLg`f>^*CK!X3SV%& zxLJzceiRmlSAz&230Y*p{kDrO4P#>2CS zN#O*;|K!|A`rX-4z3GHv!G?alu4%N|^2KkXwQj#&!tV>^Abx7Bl4Vw}%&wwE>jQmk zi_#1|%$Zxzs89_?=j`lA)5}$+NpM-tvh@A3dnO~#YyXnZ-EjK7S>SN^X@@%ebIxA`~eF?Q_V^qnA|F44=GyqGP^>Gb^KCCz`p zztzFr=i$JInKIXbC_b2b-A!JVHMt58$~xPVR#pC!>-1nY7qB&V&?6bHXB{thxe<~Z zoj-Cb?!fX)<-oV#1fih2mjY5#NX+vPQ3)yXO^sJ?AZ{hk3)!el^1~xy?9(qXrJ=mM zT$Yz0{4wp*a9O^;nBmNKvl)J!t*4lz7vu4SC7@FyAs!A7(Inp)?E@0`;DQsbqfFoZ z#*ts3aG!L{ythgs+AG&O0IdXnHeR;zP!JbcWdp6?6fvq^;A;>Qk8fMeqaqiXgQ5=p ze=o+FxP``7OqMp7nRUXImgqqm4Z$&0=T`__<^l=vkwkKH-<6PH(?ac>GMdO7BdN*S z;)(TqAscT`F7_OPvq|E6g(bt+vc#-!Aa!wz=dn~AA30@~PY_oYn%{}Mgn274!${bO ziY3T4d<(E;?raxj-K1(`jAFOXOKyB{?EHysj-%OO+kR|({G$|kT<>HtUM)PXs2(>5 z%T{Mm+o2|2l~+lH9-fLk$BJN3Iqt>R@nU;e;t~}u7Y$NZ!G`_0m>pD{*{ZZ>ktYbH zH*;3HY&2s&-dQ`;#BmsBs_6+4VVngUL{=lJBbh~0j92Yo&_*qz$;SDBVJgRn9%XL; zaWXg`bk?VPt0wfZ2`-9BZ~6L>`-0Dv?2^bSem+n#ws{Q=uMt6O$9xZj1J9yCK#=_P zTgbmQj@7ws+!aECx9&%^`6h6!WFp!)VhUvUAYO>nZJdf{7!e}?0RR91 diff --git a/tests/test_llm.py b/tests/test_llm.py index 980a0f9958db6f1750a43e584768fad70fe7820f..aba3df2e6044d8c5b1b30b2eac61eab1ed4c582c 100644 GIT binary patch literal 3883 zcmdT{O>Z1E7{2eX82L0SZ5+|45=5DZ&_-(1Y#N1dK-tJ~XT4b`GxpT>BpXGMDkQ2L z5O9DS7X(Ng+M-GzJ_Ub_SBk>}h8Fe!tK2zFrIh2ZqJTfJdx2*@kzis5-gJ6$_12Cz)Jf4#zS)EQGsspNC!e(6J7} zVXKwfSL{&=zI7{8rb&WR!y}EOC@z%O*SmKj&V=cB@VKg!R2@$n#S>zNTpV(--)gnO zh-z&GwwO^T+hEi$L$PmnsAlcOmIuGLT?{^Ic*BOr4C{!o1huD#6%pe^YLiR$*}$_U zBno_UrpeHlgxtRM76ixy(Pfg zXMs%$VMV!SWFQsMhMH7k&HIe7!2ntV7RsR6C}fG@U>M)q-rjV@^b1!(1hJ08k7(V#=&ON@--F0ro+!QMk&# zMRY@atjQg{r{TZmO}PdHLy8CW}?5zj@O9&lC!q`UJZd;u1|ikB-$R;p5y+= zWP?A;(EIPnvL<{4ZoQY^{doD}gNv_Uy!`$fU>htcKMw$xlNV-b5l1cdjBZu&>r{9( z_Bb!K%|!c}#4yh-DaC;A6T9z8qT~VW2*Sh>vFqJoxVDU3jVE`#?}}^36zOx-tZrcn zrjorr_=Qy4oA(fgQ&bkf7NQWx$BG+93>z80Az+12Pau3Cx$t);&fNKf&DD*SHL|j~ zM((e^AAr$0n@%=Yr>eZO^6n~mZ)-iUOIt6_&%_Q{ zb%GMP;zPK;kyJ&XIjv8#4LJ&cm0Gv*xJ#}y@0LIj1`F{BHh{f^wLa0yeK3X`p{8vUyznw&&S+xONs?k`_GefsB5k1wD9aQX4KSD!vv zn$JEr8ICTWeRc8MC;6?b!KA!2P!VV9myc?uip%}-n6;kR+uO6P7_Xo^sDx{9wA>J^ z552gdlGoOLLmE5ST}r@?+z3vSgem{}F`lc8m8DX?7N0exS^;J#*~l7oEd#vPhZP^g zN=?D_0bI2B ez#~M^m=WRyz)(VB$^{`P8+PSCNBb52b^Q$&+6?pn literal 1983 ccmZQz7zLvtFd71*Aut*OqaiRF0z)hW00+MS0RR91 diff --git a/tests/test_note_scope.py b/tests/test_note_scope.py deleted file mode 100644 index 93edf6c4064ca3dc70e184356e43db8eaeafd00b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3021 kcmeIu0Sy2E0K%a6Pi+o2h(KY$fB^#r3>YwAz`*6e01M3k0RR91 diff --git a/tests/test_response.py b/tests/test_response.py new file mode 100644 index 0000000..755fb60 --- /dev/null +++ b/tests/test_response.py @@ -0,0 +1,20 @@ +import unittest + +from flask import Flask + +from app.utils.response import success + + +class ResponseMessageTest(unittest.TestCase): + def test_success_message_defaults_to_chinese(self): + app = Flask(__name__) + + with app.app_context(): + response, status_code = success({"ok": True}) + + self.assertEqual(status_code, 200) + self.assertEqual(response.get_json()["message"], "操作成功") + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_route_messages.py b/tests/test_route_messages.py new file mode 100644 index 0000000..171af29 --- /dev/null +++ b/tests/test_route_messages.py @@ -0,0 +1,66 @@ +import unittest +from unittest.mock import patch + +from app import create_app + + +class RouteMessageTest(unittest.TestCase): + def setUp(self): + self.app = create_app("testing") + self.client = self.app.test_client() + + def test_success_messages_include_business_action(self): + response = self.client.get("/api/health") + + self.assertEqual(response.status_code, 200) + self.assertEqual(response.get_json()["message"], "健康检查成功") + + def test_failure_messages_include_business_action(self): + response = self.client.get("/api/rules/status") + + self.assertEqual(response.status_code, 400) + self.assertEqual(response.get_json()["message"], "查询失败:缺少 task_id") + + def test_clear_domains_message_is_delete_success(self): + with patch("app.routes.domain.DomainStorage") as domain_storage_cls: + with patch("app.routes.domain.SchemaStorage") as schema_storage_cls: + domain_storage_cls.return_value.clear_all.return_value = 3 + schema_storage_cls.return_value.delete_file.return_value = True + + response = self.client.post("/api/domains/clear") + + self.assertEqual(response.status_code, 200) + self.assertEqual(response.get_json()["message"], "删除成功") + self.assertEqual(response.get_json()["data"]["deleted_count"], 3) + + def test_generate_rules_returns_compact_async_task_info(self): + with patch("app.routes.rules.RuleGenerationService") as service_cls: + service_cls.return_value.start.return_value = { + "task_id": "task-1", + "status": "running", + "limit": 3, + "generated_count": 0, + "output_file": "/app/output/rules-task-1/rules-task-1.xlsx", + "markdown_file": "/app/output/rules-task-1/rules-task-1.md", + "files": { + "excel": "/app/output/rules-task-1/rules-task-1.xlsx", + "markdown": "/app/output/rules-task-1/rules-task-1.md", + }, + } + + response = self.client.post("/api/rules/generate", json={"limit": 3}) + + body = response.get_json() + self.assertEqual(response.status_code, 200) + self.assertEqual(body["message"], "规则生成任务创建成功") + self.assertEqual(body["data"], { + "task_id": "task-1", + "status": "running", + "async": True, + "limit": 3, + "status_url": "/api/rules/status?task_id=task-1", + }) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_rule_generation.py b/tests/test_rule_generation.py index e84b9bf677a00d8f9cb60f0d1274c4a067756bc4..5521246eb18e338363f3383cc355bc14656966b9 100644 GIT binary patch literal 30440 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 literal 27932 zcmeIuF#!Mo0K%a4Pi+Wah(KY$fB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* o1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<_~&U~L=#0RR91 diff --git a/tests/test_schema_descriptions.py b/tests/test_schema_descriptions.py index c72cf8ceece98042c083b67755d900b80a415460..5dead55867a68fe8fb1c0f296d2824d3e59d4d06 100644 GIT binary patch literal 4304 zcmbtXTTc{86n>vyG3lqqkXi9*V{{V)HZeg=M6=l-=@dOR&`wWR+tnkm#$<503@Zqz zL|Lz6q7q#}jIJ9l%a2*AXXa`D!k+5tOLa5oxX#OTRh>HL)OXHz>XcEkiQ{Gsk}<>= zq2ZT{OLoC9aX2nphU;SLW-SMTs zH0lxujpA_6pg%h(CNr7Lx%0i3`unn{v)40O_$eilFPm7iPzft1vr5-Lm8s_4KO41$ z#)p?)^^?*m#0myB^Ase8{4w8pT?sdN^A)!Br1@}`J$$Zof==WVvBTAkI;3n5aNRKN z;HzcB!Fj&G_Geh_jXw+K{h8VuHoGR2u;s=2t9Qx`VLWM!?N-1qwzzt*x0p1Bbe)tf z_q;ROt~GH+;eMd8rOgNtwgiaC2MlZukakTbRJAlF4k+Z3#zv4;{2DM5np)fXYpVV# z1*2Ye9Bk>6?Vd=0$b_brR)oaC-dgkdrBq>-FW?#{OJ={nn}P#9|a{NZ3Ygy?$@~VEcA`qs9e& zcCn}1^;+d%zvfMC{!_WBMBL&=b8sN+xP4d4$W)WmSGgA*kceMxp(E4k;AKlU3B~!( z9sEl!g@~}F*WROf8IFH<7rgg1KKZCp->KH$-t%fzg}bkSJ3-_`o$AF@he)^vu?7)T zMB^7IbYBc1#qK3L9Vp-5uo#}sl94M|cXOI%;c-n<6J;?C3V`b%-KAQ=u#l-;EfW{8 z$;ZB>Z8@0Q#G)7yLycm{vqfPq_UgY+a|Eg@Y^KVpv)+?s_V&KF@eu-k*@{E%i(hUX z(ZM~n-APSb80dhKlNwzSf#$z&2T#u0w3Q@yIoNV!_=MG4)pgjfWUkrBp;*HcIyN;M zz`)KmOf`FKlKP3~qLHALPUoE8(-Rw8_T+>aw&p((r#M1LF%HLgFaz-j7gY(HF^qZd z5lZFYjxw&{D43M5=iudlt-Ly-DW2_T*MP zZm#aL?U(TwI(KN*8?UBWb?wmX%PDW`CZA=y+iZ7B)O|$`anjAOvVQXZ`1@$FE>OtZ zU(F=Q;@TS@_=dQr9K6^)(A#~Xx98G@3w;AUKcDID?;hys3*2LsUH;Yeedh_^HF1EH ziug?euE&1I___{8B?y2)a%U!?Z#;WmicS<2imqYauYs%-JAa&`7#G#!5_1Hx=^+A2 znHK4a9Z7eGffk=waS|%S3D6{GKDR%3=?RtwFFCI0D1g(=Qy%**G=JMdy(kgRkf0)8 zp~OlvW884Zps5y*Vd&5KI~h5Xz3@=fp`cHy9a%(u0WEJhqHPbWSD@BLpaMEPn&V%& zE5xv%K`z;R12`_Ea@;udo8eymA9sg?@+(=D^h%-fcf`nDbjnx_ZQ=>IerRH2%2aA& zU^*wErFI;-Ji=NgV-&K`5ySgj)3T@GRikMoWLTP}2%w{P6Q6}#{||Ys BneYGr literal 4304 pcmeIu0Sy2E0K%a6Pi+o2h(KY$fB^#r3>YwAz<>b*1`HVZ8W<4J00961 diff --git a/tests/test_schema_routes.py b/tests/test_schema_routes.py new file mode 100644 index 0000000..a3cf73d --- /dev/null +++ b/tests/test_schema_routes.py @@ -0,0 +1,32 @@ +import unittest +from unittest.mock import patch + +from flask import Flask + +from app.routes.schema import schema_bp + + +class SchemaRouteTest(unittest.TestCase): + def setUp(self): + self.app = Flask(__name__) + self.app.register_blueprint(schema_bp) + self.client = self.app.test_client() + + def test_schema_status_returns_processing_summary(self): + with patch("app.routes.schema.SchemaStorage") as storage_cls: + storage_cls.return_value.status.return_value = { + "processing_status": "done", + "module_count": 2, + "uploaded_at": "2026-06-10 15:50:00", + } + + response = self.client.get("/api/schema/status") + + self.assertEqual(response.status_code, 200) + self.assertEqual(response.get_json()["message"], "查询成功") + self.assertEqual(response.get_json()["data"]["processing_status"], "done") + self.assertEqual(response.get_json()["data"]["module_count"], 2) + + +if __name__ == "__main__": + unittest.main()