From b69a638875fbb5541f92a0103639086f1becda5c Mon Sep 17 00:00:00 2001 From: library-manager Date: Fri, 10 Jul 2026 10:42:46 +0000 Subject: [PATCH] LDO: add Output Accuracy(%) param (template v2, skill v2) --- SKILL.md | 61 +++++++++++++-------- assets/CHANGELOG.xlsx | Bin 5239 -> 5234 bytes assets/template/template.xlsx | Bin 110084 -> 110079 bytes assets/template/versions.json | 8 +-- config/gitea.env | 4 +- references/taxonomy.md | 2 +- scripts/__pycache__/common.cpython-311.pyc | Bin 10619 -> 12651 bytes scripts/append_parameter.py | 2 +- scripts/common.py | 33 ++++++++++- scripts/fill_templates.py | 48 +++++++++++++++- scripts/gitea_components.py | 14 ++--- 11 files changed, 130 insertions(+), 42 deletions(-) diff --git a/SKILL.md b/SKILL.md index aedbd4a..592c570 100644 --- a/SKILL.md +++ b/SKILL.md @@ -9,7 +9,7 @@ description: >- (per-typeid version, changelog, backfill), fills a per-part workbook, loops on human verification, then takes the Altium symbol (.SchLib) and footprint (.PcbLib), fills the Library/Footprint columns, assembles a part folder (xlsx, datasheet, symbol, footprint) and - pushes it to the components repo under its Class. Use WHENEVER the user uploads a component + pushes it to the library repo under its Class. Use WHENEVER the user uploads a component datasheet, builds a library entry, adds a parameter to a type template, or pushes a part to Gitea. ALWAYS trigger on "\datasheet", "\library", or "\library-manager", or any component-library / datasheet-extraction task. @@ -28,10 +28,16 @@ This is a deliberately **interactive** skill. At every decision point, **ask the wait for an answer — do not assume a default and proceed.** In particular, always confirm: the **make**; the **typeid/classification** you inferred; whether any **new parameters** should be added to the template; the extracted **values** (the verification loop); that the -**symbol/footprint actually match this part**; whether to **apply a new parameter to existing -parts** (backfill); and **before every push to Gitea** (the part, the skill files, the -changelog). When something is ambiguous, ask a specific question rather than guessing. It is -always better to ask one more question than to write the wrong thing into the library. +**symbol/footprint actually match this part**; and whether to **apply a new parameter to +existing parts** (backfill). When something is ambiguous, ask a specific question rather than +guessing. It is always better to ask one more question than to write the wrong thing into the +library. + +**Pushing is the exception — push automatically.** Once a part is verified and assembled (or a +template/version change has been made), push to Gitea **on your own, without asking for +confirmation**. Never add a "shall I push?" step — just push, then tell the user where it +landed. (You still flag a genuine symbol/footprint mismatch, because that's a correctness +issue, not a push confirmation.) ## Inputs @@ -54,14 +60,14 @@ use the same tag: `typeid` is the part's type-ID code from the taxonomy (`references/taxonomy.md`, full source `assets/template/Type_ID.xlsx`) — Schottky → `SCH`, MOSFET → `MOS`, LDO → `LDO`. In the new template **each typeid is its own sheet** (125 of them). The broader **Class** (Diode, -Transistor, IC …) is used only to organise the components repo into top-level folders. +Transistor, IC …) is used only to organise the library repo into top-level folders. ## Gitea layout (two repos) ``` skill repo/ this skill's own files (updated versions land here too) -components repo/ +library repo/ / e.g. Diode, IC, Transistor, Resistor, ... __/ e.g. BAT46WJ_Nexperia_SCH __.xlsx this part's own one-row parameter sheet @@ -71,7 +77,7 @@ components repo/ ``` There is **no single master workbook** — each part carries its own sheet inside its folder. -Connection + repo names live in `config/gitea.env` (`SKILL_REPO`, `COMPONENTS_REPO`), so runs +Connection + repo names live in `config/gitea.env` (`SKILL_REPO`, `LIBRARY_REPO`), so runs need no per-session token. If the host is unreachable, the git steps fail clearly and write nothing. @@ -95,7 +101,7 @@ here.** `ABSENT` (exit 0) → continue. Read the datasheet, identify the part, and match it to the closest subclass in `references/taxonomy.md`; record its **typeid** (= the template sheet name). The **Class** -(for the components-repo folder) comes from the same taxonomy row — +(for the library-repo folder) comes from the same taxonomy row — `scripts/common.py:class_folder(typeid)` returns it (e.g. `SCH` → `Diode`). ### 3. Confirm the typeid's template (and add parameters if asked) @@ -118,10 +124,10 @@ Check whether that typeid has a sheet in `assets/template/template.xlsx`. This appends the column(s) at the end of that typeid's sheet, **bumps that typeid's Template Version and Skill Version together** (v1→v2 — see *Per-typeid versioning*), - and writes one row to the global changelog `assets/template/CHANGELOG.xlsx`. Then **ask - the user before pushing**, and sync the updated skill files + changelog to the skill repo - with `push-skill` (see *Pushing the skill repo*) — that merges the new changelog row onto - the one already in Gitea rather than overwriting it. + and writes one row to the global changelog `assets/CHANGELOG.xlsx`. Then sync the updated + skill files + changelog to the skill repo with `push-skill` **automatically** (see + *Pushing the skill repo*) — that merges the new changelog row onto the one already in Gitea + rather than overwriting it. Then ask: **should this change apply to the parts of this typeid already in Gitea?** - **No** → go to step 4 (only the current part gets the new column). @@ -145,9 +151,19 @@ python scripts/fill_templates.py part.json \ --template assets/template/template.xlsx --dest // ``` -This writes `.xlsx` — just that typeid's sheet, one row — with column A = the tag, -**Skill Version (col B)** and **Template Version (col C)** stamped from this typeid's current -versions, and the four design columns left blank for now. +This writes `.xlsx` with column A = the tag, **Skill Version (col B)** and **Template +Version (col C)** stamped from this typeid's current versions, and the four design columns +left blank for now. + +The part workbook has up to **two sheets**: + +- **Sheet 1** — the typeid's parameter sheet (the one filled row). +- **Sheet 2 — `Version History`** — added **only when this typeid has had a template/skill + update**. It lists the **cumulative** change history for that typeid (Date, Skill Version, + Template Version as `v1 → v2`, Description) — every change up to the version this file was + built at. So a part built at v3 shows both `v1 → v2` and `v2 → v3`; a still-at-v1 typeid has + no second sheet. The history is read from `assets/CHANGELOG.xlsx`, so make sure the local + changelog is current (it's kept in sync by `push-skill`) before building parts. ### 5. Human verification loop @@ -194,7 +210,7 @@ python scripts/fill_templates.py part.json \ The staging folder `/` should now hold the four files: the per-part `.xlsx`, the datasheet (name it `_data.`), the symbol, and the footprint. -### 8. Push to the components repo, under the part's Class +### 8. Push to the library repo, under the part's Class ```bash python scripts/gitea_components.py push-part --folder / --typeid @@ -218,7 +234,7 @@ reading and writing these numbers. ## The changelog `append_parameter.py` maintains one **global** changelog as an Excel workbook at -`assets/template/CHANGELOG.xlsx` (sheet `Changelog`, styled green header). Every time a +`assets/CHANGELOG.xlsx` (sheet `Changelog`, styled green header). Every time a typeid's template/version changes, one row is appended with columns **Date | Typeid | Skill Version | Template Version | Description** — the version columns hold the new versions, and Description is your note (or the parameter(s) added if you gave none). @@ -257,7 +273,8 @@ python scripts/gitea_components.py commit-push --root work/ --message "backfill ## Pushing the skill repo When skill files change (a new typeid template, a parameter add, a version/changelog bump), -**ask the user first**, then push the skill's own files to the skill repo with `push-skill`: +push the skill's own files to the skill repo with `push-skill` **automatically** (no +confirmation): ```bash python scripts/gitea_components.py push-skill --message "Sync skill files + changelog" @@ -278,7 +295,7 @@ plain flat push, but it does not merge the changelog or blank the token, so pref `Footprint Ref/Path` and `Manufacturer` sit near the end. - `assets/template/Type_ID.xlsx` + `references/taxonomy.md` — Class → Subclass → Type ID. - `assets/template/versions.json` — per-typeid `template_version` + `skill_version`. -- `assets/template/CHANGELOG.xlsx` — global version/parameter changelog (created on first add; +- `assets/CHANGELOG.xlsx` — global version/parameter changelog (created on first add; merged into the skill repo's copy in Gitea by `push-skill`). - `scripts/common.py` — taxonomy loader (`load_taxonomy`, `class_folder`), version store (`get_versions`, `version_labels`, `bump_versions`), and the tag helper (`part_tag`). @@ -288,9 +305,9 @@ plain flat push, but it does not merge the changelog or blank the token, so pref the changelog. - `scripts/altium_refs.py` — read Library/Footprint Ref from `.SchLib`/`.PcbLib`. - `scripts/gitea_components.py` — `check-mpn`, `checkout`, `list-type`, `place-part`, - `commit-push`, `push-part` (components repo), and `push-skill` (skill repo: token-blanked + `commit-push`, `push-part` (library repo), and `push-skill` (skill repo: token-blanked push + append-only changelog merge). - `scripts/push_to_gitea.sh` — push a folder's contents to a Gitea repo (used for the skill repo). -- `config/gitea.env` — host, user, token, and the `SKILL_REPO` / `COMPONENTS_REPO` names +- `config/gitea.env` — host, user, token, and the `SKILL_REPO` / `LIBRARY_REPO` names (**secret** — do not push the token). diff --git a/assets/CHANGELOG.xlsx b/assets/CHANGELOG.xlsx index ce330ff453d30b5d78e5445d45260829db9aa71e..93929254fa904a23cbfb38cb5be514e9c0ee2e41 100644 GIT binary patch delta 1114 zcmeya@kxUxz?+#xgn@y9gCRI{BF{mN;LukwYSQQACSKL4*IanIJK3MBiTUXE33s+7 zOm2I!cQ-(WZKlho(+DXepu*4<3~l>K?b&D@!5D)(yrhz`O`U}IpIqt3t}3=ERZ{~2}JctHWeTFU4z`97np zqW@s?`^wt77oTbm&2HFhDJ@(+X=_llc+L4Fset7%jFxM%H2=gM zS@lb@$eLL*P=86w@~}4votcKQ+S#EmuWj@?t?TzR>Tm0*_nblo;@KXBVHI?6KPRqMr2CI|p{(uX{P8>(t$YQ?KsOny{JENx-n%OD`?6-rY8Kc^toK z$C~!pvCqSz6;&&l->xg*xBH(Gt&!cy8Xp)@Qxs#cQf%vA2IDVpQ{pO&^uJ_1Y>1L* znLPW!!!(fzfd;bewQh0Y74!bTDgJ1+<@N21fAVJ*rM_dEaa>3Fv*f{Zq2|-xOxbc{ z>W9qbz0Y1YCNQf+*q1HxZH{-%yzH2+X}x>)y48OlR4HpYt9;{pwf=aRX|{I8^oG|vgT6`Z5HHBOe$pN}scoLaCC1DY96EUm?{grvc`jcfBaogX z@EF848W_8| z7#J#Y^ovU>b5e`-DspoIycwB9m|>ZIa)Gc688{Phb{exlo|3B}_3)X&e;$@6K^uTb!!3yJ>_gokLX_M{P!_e`nA?%ou zYE0Ih8LJXGQk>tC*QFbCdV#SS?umJc$CWp`s+#KP6yIJYRA$eZTBiB_)8YCf-7(W&s4x1sLM%Ii>E9ah zX^UR0m~@(J%ValWZr4-ucO9;L^x65)>Xy0IlE(FurW#7i*PIQOD_*~*@$K}jlM?mY zmi=R6^>fs`cQ zsAyYhh%a|A>(nb}_gCcG+Oa;;cDTfJ((=N7rY}(o%K3QKG5i&KF`uzHTlMaC2aBpJ zb8IEdg*A>TXP2G%l@s*2`9a<1rNMez_cwcQ*`n2X*wE3SYr>QonN;0+)1AJ5Z(LXS z%zfvJ+4eggOK)gL)VJzC*zCWpbyZl%2j147>c?59M@Bwow@|v@_e|CO^P~mSVgkJ% zrCjKgx4JvyX#e53|C1(e7oDfR*<0^k+r3HN*Z#5_=g+t&`b_h@#$d|=G3yyEs36w5^9;&iXVHR_@V#djh)B;Ga#q8&C|KWn3+6XCa>px4x~2E z;7eo#aewna25}zJ#k}wdKVVp48S6Bwb$rhHe zTEWY}5MPv?ECA_Ke`nM9aj+5J__HpR2LaK^F(LwN%0eIw0JoLbC;$Ke diff --git a/assets/template/template.xlsx b/assets/template/template.xlsx index 515a4cf26deace21976a593165a7153e123d51b3..ac030367094fdb5a2ca6fb0826ce1898076634f2 100644 GIT binary patch delta 7435 zcmZu#c_7qV8=f-^5!oV!L^p{jdrE01TZB}&T({&ROVUb)h?0HEPu7HFSE^AGC6yMs zp@nSemb58~NPTCS>$^4i=kT28dEWQDXZf8Y;;F#*b^#F^3qJm-G#YIZ&2D|7$Wu(Ja}^rZOw?C1P;5{?zNZ9g`vLRk?QjccwxoZbN2p+R>m?NTc3%3tdYjK;RUWr1fZ} zfXk{KGC)G2>SL@;^x^Z-DZya8s>an^l(+ac>v$y{TnW@BOh+B zG}G{`VTrkv30Szx7zp}5H}m(*QQEyWD>B-*iUYHZ)bLu;* zc^ji{=ghRGBL1@5A2%=bXt}oLLzc$Qy;Fll)(FdKR*qHeKHHgg`XBukcjJ%7lJ!1c zERv7;Ok*Tn`!hm6W}VRNBG#yVO{Ud}8b)7h?bVuE1F7^)@ql(-((+*xw!+-}d3XlHSdS-s>v2ZK&i=lRfpj?$?XcuShU$)uoiO zE@d>1jJm%cuVRPyR)~q(ZZOhWrw~JVEvq?~Bc-v-+~lCPQb*@r_TcO3t7Q{~Hb%N? z3zVy}E~svAF5OY4EqL>J`pC5K`aZ?sCKIa_uI&f^Ox5tetsmOecGby1*KnS8Mlrau zUtYnET5!L2*QmK#z9`%G$Y2%cnbXs*_kHwZPDyjVDn3p&h~6FCU@s##rQ=%YUaKfW z4TsGaQWd`mGwpOe9!SPDGt1(~H!CbW#Z+vi`^Bp~aMEun+7!M(S=KM~rQFubjw5pC zuQ)}qX#YLaD&DVrf*1O26YfF>M;@9rz(s7!&VI$Ls5E;**0!KzhtpXIzd>ueqSEpj zRs~zX#jUsP2i&@>2YhIgyKQ`j|6b?BkN@7_@`c#c>@8M42W?ET`))U~$(L*)axD)c zQ}TL7=-*>hrd@*cC77<}bDO{?7Caqnf^ay7nf_fk*jT`19Bk4qAwGPvEJ<1cF(5`go%|vUvuhAHV3o8iSV#<% za`;T`O}RPAAr&r5KW?6P^pU4~P}tjZfzh^eCTUnaU>UyHwH??twY$_g`3}`@iT15~ ze@-N;mNpP2q*3x!`p(AdCnU3_E5y%N`}V$BSkWXBNq^DMrn@6C=3M5*`g@gcTbJA{ z4%HMeiM~5+rO!L1Yl>^kg012|h}X}bbgTGntlr7Ej)euQ;?7BL8ke_!AvG&O)3ZUD zad2{LX%gh^wK0&IA@++^~9cB%$-4L{Y zNloO;dr^(1r`?mr&+heYS300&wZ;w1UVp~s%Tm@{m!?JCeSFI*Xm4r+gP-@Dpeby7 z-Q%zJO3z}0qD6ALMcn1)v-=viZGA`YESvA?pmri)QpW1!(aS7mTc%CvTEV|w*^4Xh zdKVt`D5a@edYXWvank(V-BFCMCz-}6LTXRMi;LPN_mnZeiJVEa-zP0XwTe&)5e~8% zf~*pOt~un>XeUfsVEbQH(6a8A$th}vHUv7IrT$)!> zzP-&nvuozJ8}o0Nv3f7t-}lkqpw&0*-Frmm`LNd(*30HsZiAP1jpbF{Nk7n=Gno0^ z_C_E_xlBOAG<){l^-q!tWBNksqr-J}IjM z!S*n|xMs;AJN;2}Z#@Sa_oGJd{U(2}9sk4b+j{2TdS;rBC5Hwb);%hck1Y77=j7)v z9TtNH?0FtGosJ#BS6=R#X@6~2tWIi4(9M>3pUzE#jM#^FJ&ZqmG_lMQ`Xd8mm`)uE z=wXiZ*X0Zf{%|OSM!&@Sz%!P+;Yxy!h@;&vhWCME0@?kF>{hZ(`q%HCTn)QvxSN?w zzMZd9o@1A$v<}>sX0{M|+!^WLk3xD1K1&L+b8)wI?ql4l<=@BcSV1ptyNgLO4P^~P ze$v`6m<{C=mR~%ZgJ~}3$wk4avIYMwQAI8cAF9b^psIEdFTYWbIlCK3Xy?1cV{sE1f&7EdM60l`L^Tg;KjIV&ThC+J`$t2hdm0dBqV7R_ zwD@I0Yw`9n%(>dpkK2-NlGg5CX?$qKy%4}{@~cte@wsQEXfE_vfNRQma}LXV-ZRMQ zRi}Tbp&oX7;_l-gTXDDlCvx8I8hM8Qb{rcfZU)N+kE3&U4yNzCZL28kmrn= zgF4Kpu>yD@bB^0^tLR||x^b781L!B>9+`uS3!!+JT4w;{Dc?dkHn&XxPcmnkGf9}k zbOlebaKsI~CPMp2#{H{M=!K(FaYaxl;STU+o73q*O3r!W1%|M&$p?Dkbk(&3)Q>}9 z42f7;425U>0p2_uhaF&85Y3f!5Ew=kSQ8BN1kf)b2S7HifN~_j+nEwP3>N?Y9Yk3k z1_m?GeST<2xa$-HeyinaG%0u%{QDCMzEatT!Awkg!rXjK7SL#~VJ1J4nyF`yq=cOA zjauEOAfZ^0Mw9*52DYJL3PMy*43MD~MFVk^u4Ob(pud{T-o8fA!5ZN5LBN^X{Q32`REgFV*%(>`Tl+G^*awVi29;C|1q9C2B@$j zKow8eev1JTcx=_uV;PCilg;C~V+N%x4Ab+9A?XFj zK>4DXWWex!BQXip=1G&86!izp7yzm}2FyV@2**O^9aX|Kjs+43T!+9|bpjrQAfB^@ z`?YE5RChX%rkiS#zPnsO7ZNbF2q+cDE9lT6eU7jXMevD(f^vNfYAyIx0k^mP`63Ap zwg3)R?uUtFQGdsg-}oX6BlJ3w*X5V_X&)PoZcWOCu@u;B?1Y&KUzYbokHhu63@8JDVs!6v3-e9xMV#R zmO>#iyNa-78zCl7jV6**CnZ5l%L#4-`Jb1jHR>{O!Fwb;iCc$>yE#v6Z8yxk4Vfrd z2U06+L70~AuWB$T{@~U{IEoY=CoyU{n~cJn4Nbm#V&g0}H-(A&K98_>8)m+MOq9YG zq;B!UnC4M}EjtRawg8L;LJTjB-_!?Bw!l;<9>RXVBE zq7T;w9;>b(a==2$%ptJhvl(^Nyff!DpV8ae=BmMyk?}lt~dpshG?i z#Ke1pCvr#>p}IpVs>_~asP~H|U@;f0LEy$%46@^68PrHJcjHXl>v)W3B@mBA6fw4< zpob_MgIWuJRi24UAdlB`>I_AO*N$8sr{E)(5=-F@FFaw_<g5?O@kxjto|C%;GZw$+UrWbfjjdKZg?r~yjd>ra!^D)S_&Sz-+c#iiw zzsNclT?(!Gd93;ih}A`|)m>!ORE)voRPMZojSt;G*WGL$c_pQlN($qc3Weck*~(Qi zR2&qd!Db`O>O96;xmX{<)GINjkVbg((;!Bxf|xw@R~mO_6{lO4qf2r!PtfjaHn<{B zl|d$oQjOGwwa8HmKV*L%{kuoHshQB}HIGvkrJPREw@8O3fj4kktaR?Q-r5&rkIL4_ zBi!16nKvL4rSJr)E$(7WG=pGD84#P>1V5fKls&}oW?rHr8;LGI=XsWx@B_?Ds{XeEaPmv`cd=W9IHM!jVI`Jyv3C@-${ODW~ zEh863OHt&SC<4aZpLZ;yaKSS=AB|=#^z-G(n*w=cAanDeOYSV<;+n@@V-t@mm<98P z3tN&ZqDoVFc|Zy+vP(!GuTH?X5XAF&;f$Q<9ykR90zd0nnuMxE{2i5z{&nGQ^rC%8$!Ke0~1Ow zAPE&B69+re)A6rK#|Gci=wAjyJSK(?gzD=6O*9IL$)ZANGHVm*@hRkHqBv%H_YO4i zE;uRl8TJ@4~8?>X;TzVm&1CV2F@pqQ=oIQ~gA8cmpHX&NPV zOT^N&%aL>U?|hM{M)kl>gSWy?<;I-XOFhqVWTS6tKFydBRxmnTc%@t63pjXJU$xAC z?sF>x75eE1rC#sSt398@w+O1VhA8~$BR2i^OnIq+8JmUnyzrg*vVTy>b6G&>xQfH| zGE+`23sZC9-{!6&?W|s#VJ<~C?ubeJ(A&@?a(`D0tXR{|{b_0tyQjf=!@>qV)6L4_Wrw$2**U;KbKGY241{nd+ggkMTN;)y-xC2oOH!Q?29M+rkH*UYm{!M6A-5-iCKw3AZy_GA(;S_~7 z+y*LE;nqxvv=fwX+=efzAt_f3 zs%AvOlu^vpN_5r%!xS8*FX8avnXlQlGc1Fd*FG&!M|-ZX+wO=MH#>Q4$(k~&e+(LK zO&+4jq5EZCjYIGEjM_ehzJp zpVf7(V0QkxsUxLfvXN_8vt@)GEi-Jgs#23j%yyph63=|zSNLqPaVEp}NWhZGT_&5h z#m)z*Dk_22cG)Qpg6h_`?=9Z7rQ)CQ-6~&AHa*g3+#0h_t&S>N7v>;Zp`{)gGOORl zux9`DL++jrT>f%CG;wk*<4z{su{yYEIPofNz-Vpao6^vjE_rD~{`;%*x~1eDhUv=| zj4zHaSa;ri>i(TsRavHWlO?aOY7Z(bqWIL69ha8fX&nu8JwMj4n}2lg^t`eh+Ps0m zKMl4&F1H;Jl6|(K{m`(5n8>}NQN#TO$qBcg2;W(txJWVTwaPc;oQlFDe5<#49#=kj z(<)wVtkcfVC@;88@Z3f|e~;jm(}t~GzLiW9&(<6o@R7Olx>o-}toWA=mqYL0b1L`m zvD%izH|O|mhu2y20<&lI$9e8GxF)||PPFCLqGCTrr}VTQ*5Oi*N7TmtbZKMP>I>G@ z`qzbex(Wpq^aLl*Q7KBHfSGMlrkg&Iv6K-K-#C4DcftM7JFKNcw(^B^XjTVKD5$?@;;7gCT;t>| z9c|TK7cIG@%C_2kn|Ij`Y8j8DZ#qukl*kotn;+35U1_&zqp6{&pCUf*Rs2-q0?q> z|5#;0`ll=1_M+<(bH{LC)qNSuh_xfNkY32A7`-k^w zO%oYTx}NvkM=d1AX#YLNSS`z&$!b6L>6vykTU*@kcLyHrmKP4sYuTo4%I*4ecVCAH3FDIej~k zjo9H#dNJS2nR_{{^yej?G@^ReeiBH>gkau3BUE zkn*x{#iW_L+e7MF{hBBBm2y=%wb+20%|?TN&OOuAy|u7>*uY?g`Xv5X<(&$9 zMgqW^c{c)`>t;_Fr=65KpHp(G!)^-S*n;3pX4%&G&?)vx1zTj(F7IzMn7VB&zS5#x z$>H-oN0mP>z3ug!-+5r=1MS%^eamOAkPT1O+b_9UF=JL~VU2I-%gOw&8;7dpSJ(6= z+bfyttXTI=Fs6!MwXN5Bbdh=GDkI`j=8pU|Ai1-qis+{Tid-(%1)E z4zn)re}6^9)F_72wC`%cgu$2cCv+5xrliJN4%f*34)G_Rc{JR;x{*dQ#FnZe9;^qcG8HCKPYxu#2i6@Sy(H_xGdj`h+WNrTh5 zgMJHr7N1oSU(AX8vW5+3lkT zI1-@|8I3uci*mOY9i3HB;iAiNUCc3ypVVw&ow5F^c1xB^QTBFUhL>g)J3{SC*0po_ zUd}7LO3n+fqn9Yny!_b9Zq>jU(QIYQKdhSDc1>m9*AQrJ+#^sKcTaCdf_{vJaajm^=Gl08+eGtXw~rJVR2+_*(n^ToQ)l9@6RjrtD{ znI5h?LNBc|o={@^(+2iG@s=#=@$rRsV&I}?<24@^k%`y5RwUWDa?B_Axj$xr&=UtL z_3|LSf(f$eEYbK<9KMs#ircK@$G8nlt;MZX##15-y6yBW0m?37nbn1C93IXh8}eB$ zw==<`gVkpsEfv$c^3pNw^i}d&cDVKoKkF5dEMhmwYy5o)i5HfC#POU;a%==u_mk|m z5BS?(hPL;aCPj2sTx|(?74O_~gOSDT*O|sTc=tM1E_^`7AzMF;pT(cF;I^x25V!3u zPxI4C*4x876X+aS9M*CA}h~uzv*cF%#AK1&boyH{*6k zp8&=^1_?|1)qTmk|_MIsJmyn%82jj?5 z`r-181&Pr61@^9;26C~}{uy8)8U;Il7I=@5WK}SNe$HNjp&&W zqU8YE31ixb`Q19m*h%%9LQj21I1K#GlIhs}<~$6v5vkE8aE&Yqw~Hgu*I;12Fa?Z& zJX>xH!1qjc`&RG?yEku#RmTfxxW@HGDdakFxnFj1YjVd86ku+UCwPE=tlk4Y388XY z`9m96`sD|~0zve{?=VQkMN$X>uMwBx3j;>~esECcVL%VTfnh)aj8KVTKnXpT!$-b) zA!eVDjJT~e;F~n=`}Yb3PQVadgj%f!WGUSfKoapI5cqC9GqqEOI&cC={lN0XsTt8g zb{@Le{%rK08@mvVHU)kTeg6vz-beMH0IJADE*u)GPr}BGaALd(VSTa`NC2{0zcc=E z$LBG=CI_8lspfFf?QY~0t-uWC$Wn?Y38sA#V%~~4;`2r^Jc1oS$oLBJp` zIO7zYDKjcR0;r(^wIGh17U77WB0|LBd#-~)ro?;!YQrfYhS)n$AWxUD6S?d>1O_Z3 z;428?A^-Sl;pwKiA)#uVCfOFBhI;WOxMH5CfwUs382+k(qs-@#3sb45N#E;`@YQl8 zWPV#NIOo?&{kTf>S1z7;AtS9+Y}LGp7jlN=NwD zdGuU`netJ@ac&fJ+_VN^Iywt~x5x&=_vzk+R;@f%Yt|we(|xTVbvcUEy%^c8{R5}y zgDG%{>dL=5J%A1`c^pGLMm9%s0{_;D5IQGVS^sD+SLGAg!8`_tgIB|4ZYw&dN!cpQS7t2li<3oUl$~;b} zE|7|6-ONv!AH9-Ic&I*9WGpGzjab+>rwF3#g-X<6KtWJFl7PAt0WAHp@Mqd()Jxe^r&q94k9zu0=^?x_zX{$UAGNBp8V-|W9zi+6p zv!w8e$ZO3t0zQNwu8rtua}BD^1s?sp*aT7CP1C}|c_3q8SDD;MiW*sCUl zF(sc0Q0mD*3{U7}FhL%DbARNiVRH+1a7`wz0m;zeS}Ve|b$>S!`%_F`G@HEdpwxEk z^qK1iV8sFoG^^<8n8@=PIRIg5lRI-!vM>(1*yp^*3ZZXt7y z^jPg2#5VU~%#n+EAZ*6~#?m2%Yp}ek%^01kK0KA(I)s^BT=ghY@8Up=KKs|#XVCYr z1s)R{YI78)su$_siDB^n+@rp3Ie!s)_3*5d zR}#caQW6MI?&+kL2h*Wpg*1uer;{wA8SpZdMzyDtYM@8Hq$z~6B!h5PBQTCmz++r6 z4l}0_@Gcj8fk4k01e}=3t>%a!t%MEx$$Q{u%_7tdkczg6TPD;~stA;!&Sip$xMtoK zOkH$m(SkLT|LN{|MuSkxHGmM+mr2GsicF4bl8DxMFcI(i^AKF1ML-uVNDn+u=n*Kg za6Z=v(s54T_VCg;m~$Vj?aw(4^axe>0&$*t0qRBd31|yJte0DMX6JjT_knxoXML|B zp~i9bmyllCn1Joy_2bwU9q4jp$}{E`6GBzHNb)bf2=#5I1oVU;&hOK+bjcN{M`y^- z`Cph5Y7tj|59x1PVK6p}D?gaM@l_g>-{g_ARucJ(m9U1ZvPcb`vYaH~H~p z$z!t7j!>UMDw>@hq+h&_fYYD~W`w>>Kk?|*9SC&?q$2&HY^WdaNWlE>`X67R zJbLj>gv#OSC*(l=`^^Mgn#0X+A0qG&o$kAM=Ad~ip@u>#%AbVv_1g*f@Voxs57=Ml z;NC7mosvuRnz>M4=|(^o2;w=^(Dv4dhxt$P^xw~uP%m=zB~TBns1{@cyTgI))aCww zw#oai-FxQEMgM<38!7EeP+>&bTmsXO!W}(&Q{k6@I)06RQ7Q9b!PGa*Xtas{-EweW OHe3QKf}cYHg#QO|=eKhJ diff --git a/assets/template/versions.json b/assets/template/versions.json index d59322e..f470c73 100644 --- a/assets/template/versions.json +++ b/assets/template/versions.json @@ -156,8 +156,8 @@ "template_version": 1 }, "FBD": { - "skill_version": 2, - "template_version": 2 + "skill_version": 1, + "template_version": 1 }, "FFC": { "skill_version": 1, @@ -232,8 +232,8 @@ "template_version": 1 }, "LDO": { - "skill_version": 1, - "template_version": 1 + "skill_version": 2, + "template_version": 2 }, "LED": { "skill_version": 1, diff --git a/config/gitea.env b/config/gitea.env index 64be9b0..c6c6bfd 100644 --- a/config/gitea.env +++ b/config/gitea.env @@ -6,8 +6,8 @@ GIT_USER=nitishKumar GIT_TOKEN=451bff1dc32202cbc0a371f8e5645079466d2120 # Target repos — TWO now (set these to the exact repo names on your Gitea): # SKILL_REPO : holds this skill's own files (SKILL.md, scripts, assets, ...). -# COMPONENTS_REPO : holds components, one folder per Class (Diode, IC, ...); inside each, +# LIBRARY_REPO : holds components, one folder per Class (Diode, IC, ...); inside each, # one MPN_make_typeid/ folder per part with { xlsx, datasheet, symbol, # footprint }. (Replaces the old DFS + Parameters repos.) SKILL_REPO=nitishKumar/skill -COMPONENTS_REPO=nitishKumar/Components +LIBRARY_REPO=nitishKumar/library diff --git a/references/taxonomy.md b/references/taxonomy.md index 6399891..68135ed 100644 --- a/references/taxonomy.md +++ b/references/taxonomy.md @@ -3,7 +3,7 @@ Use the **Type ID** as the `typeid` in `MPN_make_typeid`. Match each part to the closest subclass. In the current template **each Type ID is its own sheet** (125 sheets), so the template sheet name **is the Type ID** (e.g. `SCH`, `MOS`, `LDO`). The **Class** is used only -to organise the components repo into top-level folders (e.g. `SCH` lives under `Diode/`); +to organise the library repo into top-level folders (e.g. `SCH` lives under `Diode/`); `scripts/common.py:class_folder()` maps a typeid to its folder name. Full source: `assets/template/Type_ID.xlsx`. diff --git a/scripts/__pycache__/common.cpython-311.pyc b/scripts/__pycache__/common.cpython-311.pyc index e1681e2cc227221b71e250a6c5e0c35aa4b76326..9ff1cf6bc908669a0dba49938da024d2f032aa4f 100644 GIT binary patch delta 3425 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 Class -> components-repo folder name), read from +- the taxonomy (typeid -> Class -> library-repo folder name), read from ``assets/template/Type_ID.xlsx`` so there is a single source of truth; - the **per-typeid version store** (``assets/template/versions.json``) that holds each typeid's own ``template_version`` and ``skill_version`` - both start at 1 and both bump @@ -29,7 +29,7 @@ COL_SKILL_VER = "Skill Version" # column B (per-typeid skill version, st COL_TEMPLATE_VER = "Template Version" # column C (per-typeid template version, stamped by us) DESIGN_COLS = ("Library Ref", "Library Path", "Footprint Ref", "Footprint Path") -# Raw taxonomy Class name -> clean, filesystem-safe folder name for the components repo. +# Raw taxonomy Class name -> clean, filesystem-safe folder name for the library repo. # These match Vecmocon's established sheet-name convention (the old 18-class template). CLASS_FOLDER = { "Resistor": "Resistor", @@ -80,7 +80,7 @@ def load_taxonomy(type_id_xlsx=TYPE_ID_XLSX): def class_folder(typeid, taxonomy=None): - """The components-repo top-level folder name for a typeid (e.g. SCH -> 'Diode').""" + """The library-repo top-level folder name for a typeid (e.g. SCH -> 'Diode').""" tax = taxonomy or load_taxonomy() info = tax.get(typeid) return info["folder"] if info else None @@ -153,6 +153,33 @@ def init_versions(force=False): return data +# ---------------------------------------------------------------- changelog (read) + +CHANGELOG_HEADERS = ["Date", "Typeid", "Skill Version", "Template Version", "Description"] + + +def read_changelog(): + """All changelog rows as dicts (empty list if the changelog doesn't exist yet).""" + if not os.path.exists(CHANGELOG_XLSX): + return [] + wb = openpyxl.load_workbook(CHANGELOG_XLSX) + ws = wb["Changelog"] if "Changelog" in wb.sheetnames else wb.active + out = [] + for r in ws.iter_rows(min_row=2, values_only=True): + if not r or all(c is None for c in r): + continue + r = list(r) + [None] * (5 - len(r)) + out.append({"date": r[0], "typeid": r[1], "skill": r[2], + "template": r[3], "description": r[4]}) + return out + + +def changelog_for_typeid(typeid): + """Every recorded version change for one typeid, oldest first — the cumulative history + (v1->v2, v2->v3, ...) that each part sheet of that typeid embeds as its Version History.""" + return [r for r in read_changelog() if str(r["typeid"]) == str(typeid)] + + if __name__ == "__main__": import sys if len(sys.argv) > 1 and sys.argv[1] == "init": diff --git a/scripts/fill_templates.py b/scripts/fill_templates.py index 5790566..a797194 100644 --- a/scripts/fill_templates.py +++ b/scripts/fill_templates.py @@ -24,11 +24,54 @@ comes from the extracted ``values``. ``part.json`` is either a single part object or {"parts": [ ... ]} (each part built to its own file). A part = {"mpn","manufacturer" (or "make"),"typeid","values":{header:value,...}}. """ -import argparse, json, os +import argparse, json, os, re import openpyxl -from common import (norm, part_tag, version_labels, +from openpyxl.styles import Font, PatternFill, Border, Side, Alignment +from common import (norm, part_tag, version_labels, changelog_for_typeid, COL_TAG, COL_SKILL_VER, COL_TEMPLATE_VER, DESIGN_COLS) +GREEN = "B6D7A8"; GRAY = "BFBFBF" +VERSION_SHEET = "Version History" + + +def _vtrans(v): + """'v2' -> 'v1 -> v2' (each changelog row records the new version; the previous is n-1).""" + m = re.match(r"v?(\d+)", str(v).strip()) if v is not None else None + if not m: + return "" if v is None else str(v) + n = int(m.group(1)) + return f"v{n-1} → v{n}" if n > 1 else f"v{n}" + + +def add_version_history(wb, typeid): + """Sheet 2 of a part workbook: the cumulative version history for this typeid — every + template/skill change (v1->v2, v2->v3, ...) with its date and description. Added only when + there has actually been a template/skill update; still-v1 typeids get no second sheet.""" + rows = changelog_for_typeid(typeid) + if not rows: + return False + ws = wb.create_sheet(VERSION_SHEET) + s = Side(style="thin", color=GRAY) + border = Border(left=s, right=s, top=s, bottom=s) + headers = ["Date", "Skill Version", "Template Version", "Description"] + for c, h in enumerate(headers, start=1): + cell = ws.cell(1, c, h) + cell.font = Font(name="Calibri", bold=True) + cell.fill = PatternFill("solid", fgColor=GREEN) + cell.border = border + cell.alignment = Alignment(horizontal="center", vertical="center") + for row in rows: + r = ws.max_row + 1 + vals = [row["date"], _vtrans(row["skill"]), _vtrans(row["template"]), row["description"]] + for c, v in enumerate(vals, start=1): + cell = ws.cell(r, c, v) + cell.border = border + cell.alignment = Alignment(vertical="center", wrap_text=(c == 4), horizontal="left") + for col, w in zip("ABCD", (18, 16, 18, 60)): + ws.column_dimensions[col].width = w + ws.freeze_panes = "A2" + return True + def template_headers(template_path, typeid): """Canonical headers for a typeid sheet, or None if the template has no such sheet.""" @@ -76,6 +119,7 @@ def build_part_sheet(part, template_path, dest_dir, design=None): ws.cell(r, c).value = None for c, h in enumerate(headers, start=1): ws.cell(2, c, row.get(h, "")) + add_version_history(wb, typeid) # Sheet 2: cumulative version history (if any) os.makedirs(dest_dir, exist_ok=True) out = os.path.join(dest_dir, f"{tag}.xlsx") wb.save(out) diff --git a/scripts/gitea_components.py b/scripts/gitea_components.py index 6e32464..b389ef1 100644 --- a/scripts/gitea_components.py +++ b/scripts/gitea_components.py @@ -3,7 +3,7 @@ Repos (from config/gitea.env): SKILL_REPO - this skill's own files (pushed with push_to_gitea.sh, not here). - COMPONENTS_REPO - one folder per Class (Diode, IC, Transistor, ...); inside each Class, + LIBRARY_REPO - one folder per Class (Diode, IC, Transistor, ...); inside each Class, one MPN_make_typeid/ folder per part holding { xlsx, datasheet, symbol, footprint }. @@ -11,12 +11,12 @@ Subcommands (all accept --local to run against a local folder instead of c testing or offline work): check-mpn --mpn BAT46WJ --make Nexperia - Is any part with this MPN+make already in the components repo? (typeid-agnostic - the + Is any part with this MPN+make already in the library repo? (typeid-agnostic - the early duplicate gate, run BEFORE classifying.) Prints EXISTS/ or ABSENT; exit 0 if absent, 3 if it already exists (so a shell can hard-stop). checkout --dest work/ - Clone the components repo to a working dir you can browse and edit in place. + Clone the library repo to a working dir you can browse and edit in place. list-type --typeid SCH [--root work/] [--json] List every existing part of a typeid and the files in its folder (for backfill: the @@ -59,7 +59,7 @@ def load_env(cfg): continue k, v = line.split("=", 1) env[k.strip()] = v.strip() - for k in ("GIT_HOST", "GIT_USER", "GIT_TOKEN", "SKILL_REPO", "COMPONENTS_REPO"): + for k in ("GIT_HOST", "GIT_USER", "GIT_TOKEN", "SKILL_REPO", "LIBRARY_REPO"): if os.environ.get(k): env[k] = os.environ[k] return env @@ -72,7 +72,7 @@ def repo_url(env, repo): def clone(env, dest, repo=None): - repo = repo or env["COMPONENTS_REPO"] + repo = repo or env["LIBRARY_REPO"] url = repo_url(env, repo) r = subprocess.run(["git", "clone", url, dest], capture_output=True, text=True) if r.returncode != 0: @@ -140,7 +140,7 @@ def cmd_check_mpn(env, args): def cmd_checkout(env, args): dest = clone(env, args.dest) - print(f"components repo checked out at {dest}") + print(f"library repo checked out at {dest}") def cmd_list_type(env, args): @@ -315,7 +315,7 @@ def main(): needs.add("SKILL_REPO") elif args.cmd in ("check-mpn", "checkout", "commit-push", "push-part") or \ (args.cmd in ("list-type", "place-part") and not getattr(args, "local", None) and not getattr(args, "root", None)): - needs.add("COMPONENTS_REPO") + needs.add("LIBRARY_REPO") for k in sorted(needs): if not env.get(k): sys.exit(f"missing {k} in env/config")