From 0eb7dd1d7c7c1a72f678e528634b63780ef75441 Mon Sep 17 00:00:00 2001 From: vitya Date: Tue, 5 May 2026 17:41:11 +0300 Subject: [PATCH] feat(interns-skills-mvp): ship setup-interns + using-interns v0.1.0; project-bootstrap 1.5.0 -> 1.6.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit setup-interns (v0.1.0) — 8-phase install of the local `interns` MCP server: detect `.common/lib/interns-mcp/` source, `pip install -e`, write `.common/secrets/interns.env` with endpoint API keys (gitignored), register `mcpServers.interns` in `~/.claude.json` with absolute Python interpreter path + `cwd` so the runtime resolves config relative to project root. Mirrors setup-projects-meta / setup-context7 confirmation-gate shape. Description 899 chars (under the 900 budget per feedback_skill_description_length_limit). using-interns (v0.1.0) — runtime policy for `mcp__interns__*`. Per-session permission grant mirrors project-discipline Rule 4: ask-mode default, conversational grant ("разреши интернов" / "allow interns"), conversational revoke, always-ask paths for `**/.env`, `**/secrets/**`, `**/*.key`, `**/.ssh/**`, `**/.aws/credentials` etc with transitive rule (Claude can't bypass by reading the file with the local Read tool and forwarding content), cost-cap >$0.10 always asks, session-end automatic reset. Routing hints for `bulk_text_read` (3+ files or one file >400 lines) and `transcript_distill` (before .wiki/log.md updates / session summaries). Description 814 chars. project-bootstrap (1.5.0 -> 1.6.0, MINOR — capability added): * assets/CLAUDE.md.template: insert `delegate to interns when allowed` between `follow project discipline` and `we're on Windows`. * SKILL.md Step 5: same insertion in inline template + new commentary paragraph explaining the trigger, no-op semantics, install pointer. * SKILL.md Step 5.5: bootstrap-manifest table extended with `setup-interns`, `using-interns`, `project-discipline` rows. * README.md: Workflow Step 5.5 description + See also section both pick up the new skills. Root CLAUDE.md dogfood: `delegate to interns when allowed` line added. .wiki/log.md decision entry. .tasks/STATUS.md task moved to 🟢 done. .tasks/interns-skills-mvp.md per-task file with goal / key-files / decisions log / open questions. Build + install verified: `dist/{setup-interns,using-interns, project-bootstrap}.skill` rebuilt; `bash scripts/install.sh ...` succeeded; harness skill listing shows full descriptions for all three (no H1 fallback) — confirms the description budget held. Versioning per project-discipline Rule 3: * setup-interns: 0.1.0 (first edit of unversioned artifact, MAJOR=0). * using-interns: 0.1.0 (first edit of unversioned artifact, MAJOR=0). * project-bootstrap: 1.5.0 -> 1.6.0 (MINOR — adds capability without breaking existing CLAUDE.md merge or manifest consumers). Server runtime itself (`.common/lib/interns-mcp/`) is out of scope for this task — the skills land lifecycle, policy, and bootstrap integration so any machine where the MCP server is later installed already has Claude's policy in place. Co-Authored-By: Claude Opus 4.7 (1M context) --- .tasks/STATUS.md | 12 +- .tasks/interns-skills-mvp.md | 38 +++ .wiki/log.md | 1 + CLAUDE.md | 1 + dist/project-bootstrap.skill | Bin 9013 -> 9559 bytes dist/setup-interns.skill | Bin 0 -> 7627 bytes dist/using-interns.skill | Bin 0 -> 7007 bytes skills/project-bootstrap/README.md | 8 +- skills/project-bootstrap/SKILL.md | 18 +- .../assets/CLAUDE.md.template | 1 + skills/setup-interns/README.md | 74 ++++++ skills/setup-interns/SKILL.md | 228 ++++++++++++++++++ skills/using-interns/README.md | 68 ++++++ skills/using-interns/SKILL.md | 191 +++++++++++++++ 14 files changed, 632 insertions(+), 8 deletions(-) create mode 100644 .tasks/interns-skills-mvp.md create mode 100644 dist/setup-interns.skill create mode 100644 dist/using-interns.skill create mode 100644 skills/setup-interns/README.md create mode 100644 skills/setup-interns/SKILL.md create mode 100644 skills/using-interns/README.md create mode 100644 skills/using-interns/SKILL.md diff --git a/.tasks/STATUS.md b/.tasks/STATUS.md index c71591e..a8beb0b 100644 --- a/.tasks/STATUS.md +++ b/.tasks/STATUS.md @@ -1,5 +1,5 @@ # Task Board -_Updated: 2026-05-01_ +_Updated: 2026-05-05_ ## 🟢 [shared-wiki-skill-catalog] — публикация каталога claude-skills в shared projects-wiki **Status:** done @@ -164,12 +164,12 @@ _Updated: 2026-05-01_ --- -## ⚪ [interns-skills-mvp] — Ship `setup-interns` + `using-interns` skills (v0.1.0) and bump `project-bootstrap` 1.5.0 → 1.6.0 with `delegate to interns when allowed` CLAUDE.md trigger, manifest entry, Step 5 commentary paragraph, idempotent merge into existing CLAUDE.md files. Two-skill pair following the setup-X / using-X prior art (setup-context7/using-context7, setup-projects-meta/using-projects-meta). Per-session permission grant policy mirroring project-discipline Rule 4 (ask-mode default, conversational grant/revoke, always-ask paths for secrets even with active grant, session-end reset). +## 🟢 [interns-skills-mvp] — Ship `setup-interns` + `using-interns` skills (v0.1.0) and bump `project-bootstrap` 1.5.0 → 1.6.0 with `delegate to interns when allowed` CLAUDE.md trigger, manifest entry, Step 5 commentary paragraph, idempotent merge into existing CLAUDE.md files. Two-skill pair following the setup-X / using-X prior art (setup-context7/using-context7, setup-projects-meta/using-projects-meta). Per-session permission grant policy mirroring project-discipline Rule 4 (ask-mode default, conversational grant/revoke, always-ask paths for secrets even with active grant, session-end reset). -**Status:** ready -**Where I stopped:** (not started) -**Next action:** Read design at `claude-skills/.wiki/concepts/interns-design.md` (just ingested) — Layer 3 section. Scaffold `skills/setup-interns/SKILL.md` and `skills/using-interns/SKILL.md` following setup-context7 / using-context7 structure. Then patch `skills/project-bootstrap/SKILL.md` Step 5 + `assets/CLAUDE.md.template` + `bootstrap-manifest.md`, bump to 1.6.0. -**Branch:** n/a +**Status:** done +**Where I stopped:** `skills/setup-interns/` v0.1.0 shipped (8-phase install: detect `.common/lib/interns-mcp/` source, `pip install -e`, write `.common/secrets/interns.env` with endpoint API keys + ensure `.gitignore` covers it, register `mcpServers.interns` in `~/.claude.json` with absolute Python interpreter path + `cwd` to project root); `skills/using-interns/` v0.1.0 shipped (runtime policy mirroring project-discipline Rule 4: ask-mode default, conversational grant/revoke, always-ask paths for `.env` / `**/secrets/**` / `**/*.key` / `**/.ssh/**` / `**/.aws/credentials` etc with transitive rule + cost-cap >$0.10, session-end reset; routing hints for `bulk_text_read` + `transcript_distill`); `project-bootstrap` 1.5.0→1.6.0 with canonical CLAUDE.md trigger `delegate to interns when allowed` inserted between `follow project discipline` and `we're on Windows`, new Step 5 commentary paragraph, Step 5.5 manifest table extended with `setup-interns` + `using-interns` + `project-discipline` rows; root `CLAUDE.md` dogfood line added; both READMEs written; descriptions verified within budget (setup-interns 899 / using-interns 814 / ≤900); both archives rebuilt + installed; harness listing confirms full descriptions (no H1 fallback) for all three skills +**Next action:** (none — kept until merged) +**Branch:** master --- diff --git a/.tasks/interns-skills-mvp.md b/.tasks/interns-skills-mvp.md new file mode 100644 index 0000000..0c130de --- /dev/null +++ b/.tasks/interns-skills-mvp.md @@ -0,0 +1,38 @@ +# interns-skills-mvp + +## Goal +Ship the first version of the `setup-interns` + `using-interns` skill pair (v0.1.0 each) and roll the canonical `delegate to interns when allowed` CLAUDE.md trigger into `project-bootstrap` (1.5.0 → 1.6.0). The pair exposes the local `interns` MCP server (Layer 2 of `.wiki/concepts/interns-design.md`) to Claude Code under a per-session permission grant that mirrors `project-discipline` Rule 4 — ask-mode by default, conversational grant/revoke, always-ask paths for secrets even with an active grant, session-end reset. The runtime server itself is out of scope for this task; the skills land their full lifecycle (install procedure, runtime policy, bootstrap integration) so that on every machine where the MCP server is later installed, Claude already knows the policy. + +## Key files +- `.wiki/concepts/interns-design.md` — Layer 3 Skills section is the primary spec +- `skills/setup-interns/SKILL.md` — to be created (mirror `skills/setup-projects-meta/SKILL.md` 8-phase shape) +- `skills/setup-interns/README.md` — to be created (mirror `skills/setup-projects-meta/README.md`) +- `skills/using-interns/SKILL.md` — to be created (mirror `skills/using-projects-meta/SKILL.md` two-class shape; grant mechanism mirrors `skills/project-discipline/SKILL.md` Rule 4) +- `skills/using-interns/README.md` — to be created +- `skills/project-bootstrap/SKILL.md` — Step 5 commentary + Step 5.5 manifest table; bump `version:` 1.5.0 → 1.6.0 +- `skills/project-bootstrap/assets/CLAUDE.md.template` — append `delegate to interns when allowed` between `follow project discipline` and `we're on Windows` +- `CLAUDE.md` (root, dogfood) — same line addition +- `.wiki/log.md` — `## [2026-05-05] decision | interns-skills-mvp shipped` entry +- `dist/setup-interns.skill`, `dist/using-interns.skill`, `dist/project-bootstrap.skill` — rebuilt archives + +## Decisions log +- 2026-05-05: ship as a pair (setup-X + using-X) following the validated prior-art pattern — same shape as setup-context7/using-context7 and setup-projects-meta/using-projects-meta. Rationale: clean separation of one-time install (mutates user-level config; needs confirmation gates) from runtime policy (read every session; no mutations). Cross-reference between the two via the `Prerequisites` section. +- 2026-05-05: setup-interns assumes inline `.common/lib/interns-mcp/` layout per design's "current склонение". Open question (Gitea repo + subtree) deferred — v0.1.0 documents the inline path; if a separate repo lands later, a 0.2.0 minor adds the alternate clone branch. +- 2026-05-05: grant mechanism mirrors project-discipline Rule 4 verbatim — ask-mode default per session, conversational grant ("разреши интернов" / "allow interns"), conversational revoke, always-ask paths even under an active grant, session-end automatic reset. Rationale: same security posture, same UX vocabulary the user already trained on. +- 2026-05-05: always-ask path list copied from design Layer 3 verbatim plus the transitive rule (Claude reading a matched file and forwarding content also triggers the gate). Plus cost-based ask: any call with estimated cost > $0.10 (sanity bound). +- 2026-05-05: `description:` budget — keep ≤ 900 chars per `feedback_skill_description_length_limit` memory. Verify char count before shipping; if over, trim trigger phrases first, never the policy summary. + +## Open questions +- [ ] How does the user's actual `.common/` layout look on disk? Setup skill currently assumes `/.common/lib/interns-mcp/` and `/.common/secrets/interns.env`. If the convention is `~/projects/.common/`, the discovery phase needs to widen. +- [ ] Should `setup-interns` ship a scaffolding sub-step that writes a placeholder `.common/lib/interns-mcp/` from a template if the source isn't there? Probably not — kicks the can to a separate "build the runtime" task. + +## Completed steps +- [x] Read design `.wiki/concepts/interns-design.md` Layer 3 section +- [x] Survey prior art: setup-context7, setup-projects-meta, using-context7, using-projects-meta, project-bootstrap@1.5.0, project-discipline (Rule 4 grant mechanism) +- [x] Mark 🔴 active in `.tasks/STATUS.md`, create this file + +## Notes +- Char-count check after writing each `description:` — paste into a quick `wc -c` PowerShell snippet (or count manually). 1024 is the hard ceiling, 900 is the safety margin. +- Restart-Claude-Code caveat goes in setup-interns Phase 8, identical to setup-projects-meta and setup-context7. +- `using-interns` does NOT mention restart — it's a policy skill, no MCP install side. +- Bootstrap-manifest table gets `setup-interns` and `using-interns` rows. diff --git a/.wiki/log.md b/.wiki/log.md index 9a266e6..b00be12 100644 --- a/.wiki/log.md +++ b/.wiki/log.md @@ -42,3 +42,4 @@ Parseable: `grep "^## \[" .wiki/log.md | tail -20`. ## [2026-05-01] ingest | shared-wiki packages/claude-skills — каталог всех 20 скиллов опубликован в projects-wiki (3 commits: page + index + log on Gitea, ae2cc9a..001cdd0); группировка bootstrap / wiki+tasks / MCP / caveman / discovery+platform; cross-link с concepts/setup-using-skill-pair и packages/projects-meta-mcp ## [2026-05-05] ingest | concepts/interns-design +## [2026-05-05] decision | interns-skills-mvp — shipped `setup-interns` v0.1.0 (8-phase install: detect `.common/lib/interns-mcp/`, `pip install -e`, `.common/secrets/interns.env` write, `mcpServers.interns` registration with absolute Python interpreter + `cwd`) and `using-interns` v0.1.0 (runtime policy mirroring project-discipline Rule 4: ask-mode default, conversational grant/revoke, always-ask paths for `.env`/secrets/keys/SSH/credentials with transitive rule, cost-cap >$0.10, session-end reset; routing hints for `bulk_text_read` + `transcript_distill`); `project-bootstrap` 1.5.0→1.6.0 with canonical CLAUDE.md trigger `delegate to interns when allowed` between `follow project discipline` and `we're on Windows`, Step 5 commentary paragraph, manifest table extended with both new skills + `project-discipline` row; root `CLAUDE.md` dogfood updated; both READMEs written; descriptions verified (setup-interns 899 chars, using-interns 814 chars, both under 900 budget); all three rebuilt + installed + listed by harness with full descriptions (no H1 fallback) diff --git a/CLAUDE.md b/CLAUDE.md index 8e9866d..dd42cb0 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -8,4 +8,5 @@ use task management system check across all projects pull remote before work follow project discipline +delegate to interns when allowed we're on Windows diff --git a/dist/project-bootstrap.skill b/dist/project-bootstrap.skill index 4692735ebe727a7a9fabd0c6dfa0a5847875ec6c..bc0187b509603219269c6868d976c65a39b6b8ea 100644 GIT binary patch delta 9130 zcmZviWlY^s*X1u-v{-R>TA;`+?(R_Bin|uOIQ`>N+zS_Xm*Vd3QrumOyG@@-=6NTX zImu2=_Q~EK)~A*8TXmB2vLs*S;NU-iKp-U0enkGa3pIYMRU{Bd_g{+`6#td#Lo6#Q zaB9EGiTzSpNI)ZGO|04MU{YAupj#GO>#N-G{^Y}hG82`4ShH~jO$p5|F@8VQS(Q() zPZj@A2IWV+huoG`ge|R{!OhW>6fpRQV%rqC>E?9e+&C}wBMr}4f@+R(hm73PN+Ya;!+4!V>p<)KW7q^dq^>Y&^5xIyZ^u z^o2s6<(tn_P=0tg`5|diF;;`8!&B=Ra!Yk=(}!QR0IeWV!Oc5Vo;Tk0f$UuQcmGY)T^RhwvIJi@+?5u$(`iipsVl zv05Yagyap!e20T*5XR@V^KR7Hv|bxJ!mO)!q?2NaSUXL-s~ccaTlC65FUJT zQFe2-}#+WL~+>mYbY0{fIEWGH*CF$s4Fb6_+ z(Q^%g0F)}opv*-~$Y)n<>hS?tIjJ{;JhRQ~#r!zX@v1zA>z&)dOT8rfSEHI=-!0HH zDUGXFv;+uIERC8vJL*nIJ`&IdR}^h}iwF8nw(nX9@Q&Hb`YsOk=M-BWx}`Y$mTp9s4Igjxabj9>M#^!>Lqf%o zsA@pRjJXz(lpm%9(v0yDlO@7jd}_yDwPegPG1TRZ$O*=y#iy zn%LhB%I`i!mJrA{B>tA$>PsqsdKF;Us;VOlP}ine8)<*k?D1sQ03u0nFreJD0lP9z zQs1)(R;TL7&@8W_eoUhc={Y4A99{?bWC+5bWSk3=Y&<))DZe_Y$Hum0NSh?*m`Tn& zNOv&7_cEpH{nY@!leNj3gR9OWAsif*l;Jz-AIIaWbAUp6jygz5ws)fXDLxavd8}+M zYr&CefXKn%C@J_Npdx{M+c|gsB5defa>&k`!? zO-AQc(KSJok_{;p3Aup+)`^YE;&NuCfSM0jEA>d@75z=t4qVo8lSx>PRj5t6 z>|w3reNdzwmfJ>RD&g8G(6(kA#JrVXED9b(jjI^E1vj4nox*yL@41i4^L2VOQGe@B zJ>`uyT%uB^aBjWdp$Ub9w=!S`q+w)C-U;jtmOAtP{^|;50_j?MvM!$u8 zAshkxD~(i+0p&1i>9BD>FG3XqMCx}Du3qI7h{?{Ms2C{fo$fnl1@Jl}DojzvQHlA| zk6wQmDzdTV1CS+uEk-N7YlM>E?-a8921BCIY02N{eK>v=T@i0$ln zd3VUVio6nFR{5>6YSkjw=!T4fKU29Nw?l>|Wz*d1_uZ6o0xot`KLya*!5UXTp)_$F z=inVslI_ee)jZHVWpfodoMUdUI#||~`);V`hL0702h=SYnZir1ClkXPdo8nW;d8ti zt>I)$hmvh4OAp8hoWnLAA)qyo<0kQ-*BEMiF3VeISPN+&LN6tenQfSVN8gh4j>@Hf zz5!psMbAX$tH&r;pk$;R6Qc-rKIUm=1ZnAJvyc(qz7K6b_-24me9m%iQRg-Cj@eW#p+b&ZnvwfZMS|?H#7tz^9bePS_}tX?j%Yq8wPL zV`k`*`g(w-HN=nrEle8Q$;@t$mt`J-`2?+Qx@C6c2YH@6Q(Y>l7t!I=Ai^r?2glg! z?h+)o7GY%+wkR4cMK@#%qaqVo2%?wM&pUj}j=YoNf68*s$P}L+b=;JR9Xs0LWY{tT zqNov3;g}3txB|+3G^1a9O;WME*Bl0h*^<3?+lblIBk%Pg4)n+7qPS!;uSP#iX!kgO zz5jw}^?PTT?;-Xk$>$)TA~?7u^Lq2TyZqq`{=@6$)EBVDHTQI$%baZ=^WTaa&Ph9J z*U_wy9J2TU6K7P3CEI2_2$y^+b#uN8AZj#d%-59c=|r+U(={~n4N*(TVStqKVqdJt z9sT*{obA0@HlBZ;7Fr7p5;Cn#8aG}1MW5%f3+Rkr+&IpA0>>OPe0+kUdvbuBB;t?v z8M?(9gc)l7cD(^omCgt;-N`qlbzs?3?Zah}bPLWO2oM^t{${YRyyxRsC?F^V4DBYr zsT;R1$Avst%~@euBeQ}q3Yj=_!ABc^iDhQ0*U0vY;D=aFP8E}W3~vB_S%q^pnHoqG z8MV*S=D#}3;m&?7v==T{D{UO@Qm;0#v<7OT^WqplSiLLqQAe>EyPuB9$5}pCtak`@ zJRZk+X+Kh13IdOsWUZde`I+j#+X)TldmoB$=AT_}0s#VXR}PQHBH4&1vx{v~Y?h_` z`?o}tUdKZr0>f7LzF|jWePh?D%+FSS$`ce9VR3s1Li(BJ6COC`{N&l5y&YZ&{H{;$ z8>i8ADoJ@xcB04jNsg*z$2+6sMqc_%@7wh5lKh>%=HU!3jFAMn-FP8eMi?TP)=vhw?FFSD5&b6Gp8p-%;_6%B`{Aykjcn;|1dcXw}hmEri@qvf6T|M5ff z|NKz)4>O<^nE(U|5CnmU{$q$pfHvLLC}Jts_OrqwQn=$3Ht4sZxEeCl%TIBnjEsvv zC8Mz1Ng+x#()ERl3T_aLzM!f>iMUb_GAta7KfI(<$}zlj#TDHTzZ2@6r}5$=^7m3U zCIOc7*o$SnkfY}x`)Ux90p*m6)0D;8Kl7Y6Tj3?v-&6~s2g7rpD~G|(fX(CDwZ+s* zbJ;joB!4qG;Z@@(l%M(1K-Z#VsTOLMZX6>6#~hzrpsgKW2eBLJXDTtaKL*!~Lc>zF z&b+lX>e7GhlMA?CU*{fr3c@TNa(0Yb6hJ(hzI4bRD=d|{e&?&HA1g^UF^+GRl>({D-D3Zo6`b;9K|QWy&+Pc< z;l~?@r*+gv9HA>foW{}fD6!jsPdSKkX7K7IiRb%C|MRH#8~%E#lpz*ly!!`%Z;L0` zoN-Q-bqf1@iH*w*#~%778tP}`ISev!;j`sA-6@UI)C5h%r|PXTHox>qw!I=Y_ikSn zSMe5|&bc!M8+67q>NFPt4^Au(HfZV9rJ zu_=om)5aU(0Um_%j`nwSk0Gn0+m5lBHYoUqtg2^Hy!BbPmdD zlkm7SOA7_>IcJiP5FgXqy+}vjw2Q4LIkr&=L_!}#;JZ2JtVC!JUJV11 zudH>cnpaVkhX!=$#-4sJ1%#K_<#-8&nFL}K45Fep8FdfOU3-&0)7!n5OR6eSB})!X zw37rBxTg$PlW5gBXu1|fnuRpppAB;>lwdJ!#WJ77JxN4u5QUl6{OX`j#WTX%W4jMF z!o{5XU5~eC9Nr|0lBOu1l%$UAN7;Du+hAr@I_#M z0WOg5x1`uy!Je{u`&j3px>&bFb3mGrmBf3194p(&1RWNHjk`V2I*xDZRZ~sN9{g*| z!8sjQ>{-HSf3n8k50cu&=PRbDq^D|E<+B(`>weC52oi+#TCWX#wr?F~+kd3rdKi-F zFkM*m&+vv>5M|E0a#uG?cPN~lc5dl>KZ2%mZNIvpiO&7m_4nyZWUP{A9S5D7^Z^7| zE>j$@!je(_0AzGkwV}nz@)?>%C9@WQYphcv`JiL>k%EoZECtd_HF84suKVMs*KOf_ zt1WKp9gzL~vksf}w}+>O-?|Nd*E|9H^^Tg!JSdW_YP&bdZGlBF8|U-GYvtQGx7I1| zDZ&XS=Lo(B-9{MSJ6WtdP*`i)vL--{B1$Dkxn@07u3AMbObfpfo^Itz?8OcPp8{t4 zy6Imd{EnIkv$u?mhn9i!OSHrat3?Da*rAB!4Gq{TRN9t`Zr{3^56=3fg|1fV)IvHL zS8kLJ+rLyX!(PCWhc9vV#|V3G{xAufXfGIs@Ku&}{}{3y)BDc4A)I7(PaT-Umf&$j zz|5{qU4f;HuBVB16X7J*g^5;(phiuB;23A%{ry3;7c>}NT^k^0!$pC@Vd^?_f^!o+ z7U3_v&@ZGtp3_z79D`?gKntwq?vi&{73kbMKTx6DuF`aH! z@qQO^VP5kL6JAlL!8+}>kP2@4X!4*tSh6LRjzc+Jw4ZiTSi*9^wSNh< zZIjazv=DgGi{j*%Fej|%tP92GHSZr83I&y;W3DGlPyB6 zJKSO@H9WfVAX-bTP7crq|Kgd$_S=HsG^xwb?ux4>2poqkZOg`!qLXT@MI=Mlq#;cK zH;s0@OGZ*?+CI8c zjXT&3_vZdA;2Ku=xhGigP$j-TBlxn!EsV3Q$wqjDBZ>Xofi{&AJdi^-q0zPn|5xFl z%^KOG4zYTp6?QvI$NI_t_rcT_g>7JO3JDrs^aCTxnj_I_$(?^t@dH{CMQ1o(rv(m@ zZAwxZLWEMSODQl}Fd1=NZqIUBf+mEzh*9$FWQb%yiqUS#*__16^G1Euvpoh^o&@hA9!2uW5T4PS0vC-6Hh9Au@i@2aLCYAg zYPJ&lm1QY}@~&je2NdhI!Gwp7{^)YoL$fZJou4tqcm*K7Znec{(kx!U&5*v8pHi90 z1!RiV`b|)o&5dLG`=X%)MDjd3vtF07M2~)j-+1TP#Cma>NgLp~GvcMdp_D>mNpjZ_ z_Z!Q^OS)WJ2kq>W62>*norGWn1y_=7+})Qf2p-L&x4p6O=C_cm3da}z)msfW&qr=UK@Btc5hQpQ zI+J~mTr&E-1a_Dn{8&W-yxHHK)l}MuQL{96%Gd=8$Cy$1`Iid1)wEnk{!5y~;xfI$ zlcwvUP-n%xl-k`ARyZtTPFP%f9r5Z4GBG2l1p<&i!}|Oa^I~@~H~NC>irTtHeYaHe z2}P0)^}!ZZ!f%T;29twNLTr=_Ot4cwPN?&RZFd@5981j>Z!e4>4)fAr!XqYU?v|j88Ih|VQM3ltsi~rhne!5Eu6B0VVB&( zMqr4wry`I2y!%1AGdyI~NDAj8WG^mP3r()sESIJh?+*be`kW~kBP5p@+Zk{=pUEs; z)SNDDESLqc2gMEHqiVEFM;>yiN&~EVtUL5EN4z3>F<)@wKZ{_$WNZ;12h=1O%oO`? zb`htjxgwb@TIZNQDM0a<;PR@qabJ7ojKA6`kIRx(9tmS&%0<;KvD@evBzW=g6Whl) zaT_{^)C;Utf2JY%oq8-y@*PO*Kla~yCBoBhiWi4Sca9 zc~EB89M*NUE9-v$MBlbh(GZyv2&Isw)4~+rHUmvxcM)J5TdVFTJW4nHw1;od9G0yS z4Q7YkGd-R;Sp8^?U<#A*ygMGW%D1Usz#bmJ>wa3k6tT2SHTs*Kp&tk;!DGoYc7Xx zv|w)IprGct#n9h;@n=K`iP=6axo~jHmo3IrbLxg#FP?yFHeHo!nRY9+M(awc%Pqu9h6?DW0}6 zD3vpfHM*sX&PgH^$ab;BSsYS~HCg#J?5P6HHRCgkRKWZ_Jbl9$n8h zib(RVmbe$CxCwAY=Z@+$CUIu_Gp#nCK~~Lu8FmbR2~2iDSP3?E`A{_KT*1iJ83qEW zH_i5usYNx&*v7%GYc-(I>$I-K`kss==Vr4QWYA4Ys9XBqjdR{$cZhU^?2dIMG`^33 zWZ8OPTM^4Sz>{(tol^F0yI051NsG1~l*Qw~wb@V&SO9;73$l(}&G0U2$FS|fV#zNS zr;w?>9G_7veJwmJN8O424Bzr~JA_lFR>6kH;->54iky|VlQ4p$?Qm!pLJYH*8qLoF2YOt^*OGQ`(8HrZqc~J04$(B?})DsOa zY6|E+{RH60Kbv#@VI%;jL=T_AsbbODIT!k|1xBt&L#$CVb z5y(`VR?M;!ii+b=wBfTmHyNA2tYhmX zwsjF+#sh;eMlVirPOU_PQHBq7z_&JZSkt$#T0p8>zFN7)SkT|q#q2eC%F#wyne$bg zZI;25aM!lO)HEz&FxvC0rg3`n(4wMqTyL7*c43&IV;=3ttWduzM76WD`w16QP?3zd z^M!}Pq{RTHWnY&Ytbx#A$$N&Qx3QuhnxEWN)$X?MMoTtGYeKr&^4b|bvBH{iO@OVS zA^?wcM6^Yw6~ko4R3*n+IJ(4uxTDL9+xpb)WMKW;&XyPAq%)7LS^D5=bD{!Q20-S* z6E=)?C?Qds=u#%=bI%lbZ4%l0TA0i-v>+$inrupuBJS037v6sToHbshz$tKn9>y5D zFM`ain=Q(DvYQ`K*wF-e`U|`TIEdj40hZ{U`w^keLHLrkc*e1NOSAmMTG$2Bf`)Dg zXqZ^@5QKAwN&Ac%N~isZqAz>-O&h^D0>s7XNJQAmI^eaS($A+fvf*~k&TQZ+wFg++ zxMJo?Eq=aRr>wb@rdqyN=O3@gEi%ro-70y^O-)5uZ4utfqDj93U9fdOy2Ua8fF=={ z4dWvlawF88_2w_*wc#`eIhgvg)X!zx%1&SMc zs}UEkgZpw&--}4e1Q7Q9gCc{&I(XLRD}Mc=4z~>G#|!01|M0ZW!|IL=z&TaC8SdJY z&=brM7aVnMBRYE9hv>ocw!2NQBq~(ScN-*9r8z*{F&&uC9`6v&&o-#UT+-E~rsuoh zOs4%;Q&KG~tuq7t!^IZ{|A7dL%{iH!%A2&5izbyF=1N`{n`8VtezCirwq3Z9^H21D z@)Rbmvy#Y*agmi{B=p^6fr1k;hU^{6qj||WaOGI0r})JZeINUjj{k%|PdORhZF}U^!Pd z2tTuLkccR{3O`*zAp^aCr8h`WImc^qlXWU}$j}as>nx(`PhG@4u(a-t9QoDw>n#;g zn*ty$5vQ=Af^I1vh4Udryw%*gTSbIH@g>rnhD@QsKJVac>!Q z`XNOc^Y6JU4I8~uuJ9qv#vf&`{(aO&5ncTxhxN}q2$pH;5-pzz)9+nmX2q*^oY2|5 zVD1IlYHaFgM{N>(fIF(qhd%6`=o4oJ^Q^%x@K>jFnvQ3J}s|(@KT7 z!NiD)(04rbi+rPeAk5C6sWN_iFhj`C@7b8zoLK%?`u690)ngFX@{#VTqy8=tZWf}8 zH$T$oX2@@UH#~-vpwz>Mp8diShkoJXdkay9eLry|_h$N72W&5Pm~t3%EJjmQ%m0;? z55*S>+KRxYie}->Zlg`X=(82 z?t8EI&oxSIz!TRvUU+-y$9GEY)lmo7gh05WzM)~ZlnKhf+O@SSWi{EaE}f;Rgr{rU zr=*q&qCMk*1qo<4w-$L;A~VZUltPMc_#TsXjUa9MyA=ejxP*dZKb{i(+e~US0hrFZQx){+;4n z_|sk05ue!j0V#Y}d@MeWBu~>^M~Y{@RAFHz2z*F*tq&bi-IICt5D7WL;=&|5iId0@ z|8W{64(N#3$dKe9oTW(5LpS>j0xmAMHp@?Ss9ISW&~4gEbZ}^_-4C|p++Ju{ZpQP~ z{CK6O<>$DntH(k&n=%M|F2wX5eYO9b0F%255v{+oajWpl@~bxMbBspkD>BkBKJP^4 zbQk241*+u53MCP7v)34jn8!Xw*$kcrYHGRn0zX|GcED?~cv4Q-y+@X75oRsXsa-cH;6s))KH1nVHY<)pR8#dXDhr&gZ|Bt zVAY2mU73p|5;I2WTiZ^hP$tiV$+_DiF|5s0Ik)aQ+5L>9D=xX93W~ta>X~a^&v!PX zKwSGgA+MVc=*ZxKu(iVZ*GtlGKF{qhEh z;gWvO$gsl;qprhBurZ9G^P$lzMASe*AWXiYWixL|u4L1D_wg7rE?M$>S)4u#^v72? zYEuTJPP*pTHD7W~@ZZ71_SW?N=`;6h;B#)eoMpoN_NaShkRF;oY?g zKNFzu4a-0cW15~^uU>8$wAsh_Cd_O6DA4?HerU-%N7o{+i1Sd0eGR*{H*|YY^|zq? z^qfHTfIsFHhsD~iC&*W&=^Dw%y}#sL%)BK7OVbKW5}bdl!;g9)HKZKE4nf{npdGsM z$$R;b6v)1F*ic{fiV`cl?A<3a6=z%1)WcD1`1jX`X(Amb;~xP=KXLDq;TvN5s|Pic z9uBX^T)m`%WpSOiYVe{@$XJ~XZl^PtpylwQsln{H=05Dny%_l^<^A!?qrv}Rke_O4 z-wvoW*K_}cMArUQJQ~F+_R>E#0$Xk$*Y~eM0RsXt{_m_vJO(8x(8G!*;g;?%9Bkh% zHfcVhMby1ClsEa&-lz?%!%GS|DC)lOA#3Af4~ zM(>r3ZNB6eJEWAYPPZ+?O(}CIS4AQVze0Flc;8E;yMS)`gt%%dd^!pp#!xBj3Yrj! z))+kGHWB!8GS55rEe0=7l&$#JdgTo;)m`tUQZ_BJ?m#(-$-GHfH|$P2XdBkB9T20; zCN` zR87@XO~1@M^-TAoe3J~BssbVsJ{%kzDx8T|j=>reGPX7<9Na7}92{8^CmKNl2L`b1 zxWV*je)+x{)lP{82-*_@6zX5qpI%B6Y zwmHelF|QsQUcw2bGC>4x$H(}&y_KQ7ROZ{WO`IFv%H8#)k;T2{ za+@Ljre)dFdb+j&!R>smxmzL0s=zml6V195`pAteZ7;2ek~Sfg#N^mme867xQ^92J zn_T_*3k6wqajlJSg`$Rh)-*G7uz@%8IkYBaL)Ah_p}NOU8j7rkXk6GDH{!h^5Rf)) zcYM7#T}?;{7x7MFROqIu5dtqjwuTZ+UPC8EHr@8a|A2XTD;KI&iJ%YaeE-W%GhdiM zMrWknL9@sT7X6FOwD9e}rU0sIsyeCz&*6yCb$Z#dqIRt*8%ySWZgEUW+)mJ{vu3=*+bzCqoqgtxDP|NE*=`kKD5e8Ox@kOg(e&) zAGiHvQDqjgyIb)gNKz?krFz4t^VNbN?<8|$TC?TG38r$A>3?hZG-e$mFn+SMp)tE- z_GMh2oMP`iGeqR#cnrjB4`x>)$P_ngtWyCPzOx-v zHIl^^;(m$8T?zIfnNfX*0wO*KeHF)KJJgg?6|>*J4lMIw2_RV?!p|n+w@u2tFfmr< z(V1?62rb` z%C*cGXI#dHN{0rA6JLf&RyZId)sSh}PfAuu07Bcknik&;*}~{$5Stir*LSsu-YmUJTx86cGLF%Za-Sg>rf$c#&Ltc^DEuX}7~VZYX0keB*0JmoBy zo3u5*Il4)5j?MIE9aC?$N?V9}ugh<^Mu7F^Q;0arW#!)cWTCv&n7z$z*D)5>QFvDS zL6G2G({Fg^Y*4f;jaELL;vKP`fH%o*y+ewX!A*h859sCSYa^ADU!W+C!B`RT^B1=M z*1n~!-0ic%2Ty<8Ds~}$4zjG`eYTId=CQ5_7>F!+mHb^5l6JAL0cN&$l2@*)!$4rt z%Lgz15@xdN;2CGeQ%kcC6t0ghiKZ5^s#655s59onEq1Vk`&2`FOUJ)q`ssJqsC}>Z zJZm8gTf?$krTZpqa>oVBkwR;RS%!OKGH0`^chVx3Vm$|-sK#Ztj+vG*U)uKKI|&nY zQ=vBMzdMS5N(+-px6y0;x0<~J=z#3Fd|V#X#ovPhs(*ssm6&jzB{I=1Kwa$96$glj zD!IX(qr{PNH;8eOYAh@K(WsK#{%$;}d%^tK-W6Z@#E%{ z3pnc}sX5A*0)r6AI+-dEK_=+wg)Z&en@%LmUx6|_Pp?Ca3AG2#JhOi32f!x#d%Y#G z#0)AlA$~YqbLPN0%JK0^#eBI8_*BG;5HVQHp`&+Dvpn~S!NYp&;S3MW6DH;9cu~Er z75zYy3{s3IJEm>GY<%;--`$^|KY2YJ&HBvVMqRuad~jO|>`zxPfB4-4`!ZPO0zuR} z>pA-O`2JpMViz2Rd~eWa1)Q91qHrF?ARKzUqxK;h3Kto%Aqpg!%ZkoA=GA}tjesJe zx0CjEYK2HBh;r|%@3Yx&6$#dT8q{Yx6*U^qi)Xd${w9*e6;h%$|tp?$Hcu1t9erA)^rvTU6t{_onzI z_5i-|JJh@`wHl~Pc)!v#H(ve8{p7{}P?Ixu_ot%g!`htEebe~LQ+@f@MLrt}!_|R( zEpNvQR!SCs(kh^GG_%ujf4Xoe-O6I)z$W2en|q0^qK;E0ey}2`bw(%8`9fx;9jSh^ zr6B?HYIc^=#>6-RaF|tZd$!j3a&ItL}A^T78li6FqujC41#6k{% z6{jl5lHe+F8fA9I{%ds~pQS7JX>lL>M6;pD3wk^EFW7amn>1hb&6VC#>aoL0<8DHp z6-$vHoZXVE4u+C_jcfN+m(Zvd}OwKBKDhfeiK=kb}nQ*nfEp4IoJO!gQV%oSY{Rt8#2 zYEvZ-1Tw$pCdQXZ?%h2sm6`B9-)hpicpRkkeFJ>dLaC#NZeLT|tQ{QuZM$EiH`7av z!OTfs_#(?IXXt#1keV1J9h8(-q2^Pq4P)(j@`*wwxx~>qhr+&$R#{r&Hk&hdgHkL- z_SkEY0q5I^!u=5=_EC_;%XM7Lcymg|_TX)>JNNCu_>r96cmca&r}`krH_$HZ)jCL+ z6tIjKk0~7rE)@Jbrt&o|+nR?x_(S#CwA8=a+~tmIF9zfmp`2qX2m{hP$z|>5UQCVM z_H{M~P%jc&GQyy3@bw8e+)RcJA8% zhFXsI@zAcx?2X2+q@&0wIuh7!Y24c#H&7T|(U}@(pvXD_&8!`}GRD#HDv|K|p*yhd zKdV=&=JC*3&Ova|?(ms|NWXo}C`i%r{3JLdLaIwthab1b$>YNzdqD%Y#b$C!SgJy_ zxW}iHv$G+B3$*3WW2;Qxn^VW%8wUlENbK60A9KO|I%43UC6Vwk)lQiouGh-1v<0|M zOI9)#XxOgw5!k;p>VjN}wp+}_%e~1u<9N`sjPylMN19J?XmtibudzSK@Q-cQ#<6K| zn(GuWK8io0kad35dd8hTH;IrJUEs12O`NCvrfo&qc+WIKd~*W8?cc)IoZ z0-{?Vq6NLFl&U=Avh9m}msQPDRt|8YO@L-z^C4b312*b0#$Xi(6aF=J2-2b~UDlr$ zk?BU%XpYGqe$0x1TE3X3|CUgxslMgrSl?JFkBSMeO*MrsS6#VNJ}?>K!ANa8vZYa* zZWi3J!?AdmZHA3=(NBt{r=MP`1>-|3)xkm|I);aY6%z>lM~Fvano!|n0nHy&6%5~! z&fA;mxx&(Syj;5oBwwUWbfy}D0u3{Jg#sieCJglFm%7geaD|`J-7rKEd^X)8UL4y; z&<_7H?!bnRYt5IIGjn{=mLynv}{p!)OOm;@Ca zcPs`?*(0SzN0rGsu$%@y0Oa)6c3~#S`xsj&^Kq28HaM)VK-tq?WT@6W(lF@G_fx1^ zI)Q)CJFB!)6l}^)&&#*TO`pZ?$J@sXi^mI**2j&JZcm^}jvu^K;tLZvQ=0r?X8&}1 z{_P*srFO;e6YA1D-{_(@!&amaiahucF0#{Lc@Ym?f<}RQ!}d2&rBTb9hl_Br-`g0z zk~0A>uC0iv*}BCt)f+*G#Azq5j24AeWeVmWBPpD~B0q`#{3rKmH*U97<=5UVe^_3+ zE|zAEYX{YIVwDLLVPNHahO30VDDBVIyb10B|8Wj3>0ua{bxB!rH&3v#NUcz!0hmDu~EyV9G|#2X=j zl~J{7R`6D*r;dZV`ouV@$MfXwSd2{k{m-{JYuMl>uLi5Hu$m>8&AWcFRqb<$%?(<| zeER7-WbG&nT`B5XH^cW4*++YV4bH)`q1LIzeS(?AFQ z@9SI#2^Na2+D}g6Zmb*ML&es#_n+Ugl0P1&xP#C8tiFV`A)CSUhst-pbm39Y{5;I2 zEG?fr<|n$zvhPwc6t(Jl$|ZL&G3wKv9}qT`9SsImAcfndfByr2gD(f}bKQlU!*1hJ z@Pw@$G;(Nx^4FSR%(@X~hN{(KELxP74EFTzP)a)|lOb=qIHog(Z+iUdzm4iKx~b^+ z3A`7ga51rDOrsMRJAzD5{~X>=g41 zy2R8o&rn=58)BWOuPY>@dh7P?vD<_PM@dU;SyXB;K|^={KA~h2pcS5 zm~0L{K)M(|?y^PmZbGcv>O|Ph`)d1~SWi5)!(<=QpRq>Dl5?$t-#N?Eu5*cufpPnR zMLd9rHDK}pXNiGT4}&<@`dB+(DW7Cfe_ah&(IW9Dt*6q2{TagP7AEnVws)g7fxLxp zz&iI-?I4U;Bk-*J+Ksz?&jF60h42@PiWC94;LZxjGyxgLt~zh-Jn&U=E~1 z?j;Ii8!dw5OxeXBL#K!0#U17?wcI3wEYok0|-}-COPE~nvcBa?k zTRD=R3PwFr9H_q07EvDiV1W?EP6Op&`DqboCS8w7UM5HR-*K=yK~1ipu%A_Js^B<- z+*D&HCD$)DWxgqq<*Iy;(YRaAfe0q!Lm*h7DA4^DmtQ;H5Hw>$;x8TXbOY=he|gG+ zft!|_Z{{ofuxOJ)eVaoI#9YW_BQl`{)RuAdn2^mqOxDbFhz%MIDns<2`bnd&apifM zG{iCjQro*Q!;&*e`){Grg z!aOoXHJN-R%ka5xU3w*H)xgL01-7=C`YPcZKnY)&f45SYO3 zJr2;>Le}FzleMZSK?P{o6iV%`}cyJ&LDfZ4uTR%m*zq+zcv&=Q3 zGqtTOFL&p8IXI>(?H+m_qoO_bml#Yh5PuTawjsgwBy_>R1$GWX{&Yv4m>e3*yq%3+ z4TX7NF^WIEcZemMh`XYb=l|f%qsYweu;x~r+P0I7P2^halS38?ND;TdIe)IUog1Z1 zl|lYtuDs7*f$s$T$)sW>s$8(|2|0dUsHpLGHp!6ia>JO3zoO|Gle5|9lJLIpNXoNSm&jls@Gs4Gv6v9*!yKg`>8c%t4kE1V zC)xv18E!+@qP^-UP%LXR`ZUz>nh+%7I^PmR07^A!co% zV_3x-5GR_{IwY!dWi@N!r~LuC25>ALyoAe zJISFYOi0l*zFmD!%sFNjS6PN%Wop?14A#|=%s79ZVvF=weRyFMuJ2KO25CmLCG{&&)*vb4 zvvDLVv5#%!zH)&H9+=W!qKt$B?j->IK0MJ~LmAZAzezS@_XJ1+2`|;8DfNqH1IK)5 zBI-Rvr_I|vQJ(y`@vkQp!&5cgpA@zZwen%B&og}rFQEH%HYZR?zq@fIqQ&T~Y=S-Fwc3rrM?|q>o~Uu~bBm+N{4HC1Q#`KKl}=xwfFUuq!Iw zobF3F>9SaeqIWzhN#i$8LI;2@90CZDU^9=NLJev^56*k&s8{e`4TIG|^txc7^?Q)Q zRaN?RYb3RK{+JQ%9Yq_>DTAk@@&)wa6wAiVCRUlRzycU#b~~)Aa9<&)xvxwAx&(4afq&x$9v$tM zCNgIo9M#X?&@3|ftXjt8Vj&*kxd#YM3GPLrH2vfHs$Iaz=h=k7xC8L`pHf!%G!e-> z0+dZOUqAMWc4@VLPBQL@<{P#OU#$kQ>4}wC26vbeK?+FGD@v`nAUaC$k|=QCnmZU7^jnnsQ%gtcqH4%R5aSZ>^0*f6NvVE#wwJ#bbkye+Lhqm5yF=9i8M*pzqiU5=+Pj9Vg?|LcWok-@@j#p39ZL(!e%=oyq zsC2NNC|Rj+s~b{}P;%&C*GZ}b!@?}2D~QaTR-455J%BF~dnprnR6h+ts(TJoZT&>O z(!yHL{>p2cxAKDz>=MWMmO2jt_fMcC!Mf;iiH7B;0=!!cve7&@Qpjx4%ndbh>U@e0 zy)X@0S9<)rhVmm1dWsws{#tz&A83cc>jP8Ct76Tj-ucCq%$#ZjoxQZ9*c;M3gjv-^ zG)yb!8qmnqlv(fSZlK{$2`>42pa9Xlrh~MvAbP}`4OUJ%(T;(93x>5C0gE2 zl}t?dn!Vvvx3CdUhB=N-5^`;uH97P34#`agSY5=iiN5xC0H^kKl%)7Gk`E&Fo#u8@ z0DJ$Cp?T0JQVoIL0-c8ZfcqZIg_(m8gBS~xQsKLyv}hCdfvMRT*aQ2&+h1?HPUBl2 z6kV6A<0%N!fxD6&$o1(lx$9)MEg_3y9c-W4<{Sj|KSC#e!pdmENvEH#f zbRzM(EBqDim(ZG18CxUtkQP5vzs^Sx5Tfso5;zz%^Sk^riL1=z`|50!&h(-FVXXD< z+bNV#=qmz;R9sT5yu36*t=}8^eQD~sA8&nEX*IjnS@ig@MT(P4WdtC zIbXYwKU#O~>>$Z~$fT=K)#D(&n_ffE+4y(y1|nuMt3JuYG&AIx{v~$IUN>H^s5|K$ zL}=fJM@1nXWGT8k-nbE8!iE9F9*6x&)8n>?k>V9}K4rg&Z0?lWO+m6iAFk%(OPp2c z%2>-yQFY=FKJKo*T`c*vaEO>f=`Uv@(4{l^7)E$AoECFEF;>q?=OenqC`EWqRWJd) zXQIj0eH=e=XuoO9{zb>&hD?nV3oTh3KE>Bay(6enEyjkoZteQq?hOD!&tIGr*Ny#y z82weex~3|uJ9}lTs5eJKSubjAULDN3yRPvqU~ywfJ^ugXmz{0g+{$EYkK_P~ubW&# zF^a!Bu8W4BE%UX$-&!{86%UVE74Z*Q63_LalAt5hMmie7KkSkYPze4^B2v;-f+`v* z)H9>S+>}ITTr}05PLlx$YIkVZgdByUk3@#CMtWk|#I5l|G~*qJLPDpVF5PYDGvL|F zvkTE1d(Qa-1&<(}1b{}I{k&HvJ>=kfTc;#({(gTL!H z-?W`4AA~}dYL=*oYo2Yh)w7De!fV=f*3KfSZsZwylxh{#S-4#EdI44a?xHh#9Of&M zHg~3IN$qcQ`V_o;*HuWec^UOamV`j_2&Vb(-;P{H|GVKo6TrX!lKFpR|0F6}3ILH4 z6UnDLC?MMH5rx*}kWY5}=!lzE9$yw3`XYJ*?;_aG;^E!*cnZ7StxqOU_S$ImNG4r> zocm+T;+60AC1r#uFl60gb?MqNRuel-)BDd*K|7q{*zBb6z7#f_rU~}I5}8j!FC_|p z3zafOxVaz*O0(N&vwM>b{x#huCg1KlB0J1#`RfGW$U9HUj&>h#$_XY8_YTV{Tk#^O z#FbmQMI?UVqpx_PcW(k;p{OdrBjCgR|I7?YM07&$|BtZn-?0B1ai~cUIvIo;sw7Gp hwxlCE%=iCiG5-txuiAY7ACN4Gou201D)s+#{vRzbl2ZTx diff --git a/dist/setup-interns.skill b/dist/setup-interns.skill new file mode 100644 index 0000000000000000000000000000000000000000..a5efedca33438b6dd0a6cfbe5feddcea7d385a1b GIT binary patch literal 7627 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 Z{2wn@Lm3h2KlkANRrJ4~jr>2m{{X_MkedJi literal 0 HcmV?d00001 diff --git a/dist/using-interns.skill b/dist/using-interns.skill new file mode 100644 index 0000000000000000000000000000000000000000..eec6d165b086b73f1cc26ef4a7a963f15716d7cf GIT binary patch literal 7007 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 diff --git a/skills/project-bootstrap/SKILL.md b/skills/project-bootstrap/SKILL.md index 3a46c3d..f925d68 100644 --- a/skills/project-bootstrap/SKILL.md +++ b/skills/project-bootstrap/SKILL.md @@ -1,6 +1,6 @@ --- name: project-bootstrap -version: 1.5.0 +version: 1.6.0 description: > Initializes or upgrades a project in the current folder: git, .gitignore, README.md, .wiki/ using Karpathy's method, .tasks/ for task tracking, CLAUDE.md with skill triggers. @@ -265,6 +265,7 @@ use task management system check across all projects pull remote before work follow project discipline +delegate to interns when allowed we're on Windows ``` @@ -291,6 +292,19 @@ push only after explicit per-session approval. Install the skill on the host if `project-discipline` is not in `~/.claude/skills/`; otherwise the trigger is silently dead like any other absent skill. +The `delegate to interns when allowed` line activates the `using-interns` skill, +which lets Claude offload predictable bulk I/O and summarization tasks +(reading 3+ files, distilling long transcripts) to cheap intern LLMs via the +local `interns` MCP server (`mcp__interns__bulk_text_read`, +`mcp__interns__transcript_distill`, etc.) — saves Anthropic quota at ~125× the +per-call cost reduction on bulk reads. Per-session permission grant mirrors +`project-discipline` Rule 4: ask-mode default, conversational grant / revoke, +always-ask paths for `.env` / secrets / keys / SSH credentials even with an +active grant, session-end reset. The skill is a no-op until the `interns` MCP +server is registered — install via `setup-interns` on a fresh machine if +`mcp__interns__*` tools are missing. Full design at +`.wiki/concepts/interns-design.md` in the `claude-skills` repo. + The `we're on Windows` line activates the `active-platform` skill and pins the project's default platform to Windows / PowerShell — so generated commands and README quick-starts use PS-native syntax. Bootstrapping on a Linux or macOS @@ -322,6 +336,8 @@ Skills used to initialize this project's `.wiki/` and `.tasks/` layout, with the | `setup-wiki` | | wiki canonical layout | | `setup-tasks` | | tasks canonical layout | | `project-discipline` | | cross-project policy | +| `setup-interns` | | interns MCP server install (one-time, per machine) | +| `using-interns` | | interns runtime policy + per-session permission grant | This file is overwritten if `project-bootstrap` is re-run on the same project. For history, use `git log .wiki/concepts/bootstrap-manifest.md`. ``` diff --git a/skills/project-bootstrap/assets/CLAUDE.md.template b/skills/project-bootstrap/assets/CLAUDE.md.template index 8e9866d..dd42cb0 100644 --- a/skills/project-bootstrap/assets/CLAUDE.md.template +++ b/skills/project-bootstrap/assets/CLAUDE.md.template @@ -8,4 +8,5 @@ use task management system check across all projects pull remote before work follow project discipline +delegate to interns when allowed we're on Windows diff --git a/skills/setup-interns/README.md b/skills/setup-interns/README.md new file mode 100644 index 0000000..a5e06e1 --- /dev/null +++ b/skills/setup-interns/README.md @@ -0,0 +1,74 @@ +# setup-interns + +One-time skill that brings up the local `interns` MCP server on a new (or freshly broken) machine. Detects the runtime source at `/.common/lib/interns-mcp/`, runs `pip install -e`, writes `.common/secrets/interns.env` with the endpoint API keys, and registers `mcpServers.interns` in `~/.claude.json`. + +The runtime policy for *using* the resulting tools lives in [`using-interns`](../using-interns/) — `setup-interns` is the only place that touches user-level config or the project's secrets directory. + +Full design (Layer 1 / 2 / 3, MVP catalog, always-ask paths, routing hints): +`.wiki/concepts/interns-design.md` (in this repo). + +## When it triggers + +- User says: "install interns", "set up interns", "configure interns", + "настрой интернов", "установи интернов", "interns не работает", + "interns isn't working". +- [`using-interns`](../using-interns/) detects missing `mcp__interns__*` tools and delegates here via its Prerequisites section. +- A new machine in the multi-machine fleet — install once per machine that wants delegation. + +## What it touches + +| Path | Role | +|---|---| +| `/.common/lib/interns-mcp/` | server source (must already exist; not created here) | +| `/.common/config/interns/config.yaml` | catalog of interns + endpoints (read-only here) | +| `/.common/secrets/interns.env` | endpoint API keys (gitignored) | +| `~/.claude.json` (`mcpServers.interns`) | MCP registration | +| `pip` site-packages | editable install of `interns_mcp` | + +## Hard rules + +- **Never auto-mutate.** Phase 1 (discovery) and Phase 2 (plan) always pause for explicit confirmation. A trigger phrase grants permission to inspect, not to run `pip install` or write secrets. +- **Never echo endpoint API keys in chat.** Edit / Write tool calls inevitably contain them (that's how they land in `.env`); chat output must not. +- **Never run on absent source.** If `.common/lib/interns-mcp/pyproject.toml` is missing, stop and tell the user — initializing a fresh runtime is a separate task. +- **Always `chmod 600` `.env` on Linux / macOS.** Token leak otherwise. +- **Pin the absolute Python interpreter path** in `mcpServers.interns.command`. A bare `python` resolves to whatever shadows it on `PATH` at session start. + +## Procedure (high-level) + +1. **Phase 0** — environment sanity (`python` ≥ 3.11, `pip`, network to endpoints). +2. **Phase 1** — discovery (source / module / config / keys / MCP registration / `.gitignore`). +3. **Phase 2** — plan + confirm. Wait for explicit "ok" / "go" / "поехали". +4. **Phase 3** — backup (`~/.claude.json`, existing `.common/secrets/interns.env`). +5. **Phase 4** — `pip install -e .common/lib/interns-mcp/`. +6. **Phase 5** — write `.common/secrets/interns.env` (per-key, missing-only) + ensure `.gitignore` rule. +7. **Phase 6** — register `mcpServers.interns` in `~/.claude.json` with absolute interpreter path + `cwd`. +8. **Phase 7** — best-effort smoke test (in-session caveat: real verification is after restart). +9. **Phase 8** — restart guidance + final report. + +Full procedure with shell snippets and templates lives in [`SKILL.md`](SKILL.md). + +## Rollback + +1. Stop. Don't fix forward. +2. `cp .bak- ` for `~/.claude.json` and `.common/secrets/interns.env`. +3. Optional: `pip uninstall interns-mcp` to undo the editable install. +4. Restart Claude Code. +5. Confirm `mcp__interns__*` tools are gone (or back to the prior version). + +## Install + +From the repo root: + +```bash +bash scripts/install.sh setup-interns +``` + +Works on Windows under git-bash, Linux, macOS. + +## See also + +- [`using-interns`](../using-interns/) — runtime policy + per-session permission grant for the `mcp__interns__*` tools. +- [`setup-projects-meta`](../setup-projects-meta/) — companion pattern, similar 8-phase shape. +- [`setup-context7`](../setup-context7/) — sister setup-skill for the context7 MCP plugin. +- [`project-discipline`](../project-discipline/) — Rule 4 (per-session push grant) is the prior art for the grant mechanism in `using-interns`. +- `.wiki/concepts/interns-design.md` — full architecture spec. diff --git a/skills/setup-interns/SKILL.md b/skills/setup-interns/SKILL.md new file mode 100644 index 0000000..8395564 --- /dev/null +++ b/skills/setup-interns/SKILL.md @@ -0,0 +1,228 @@ +--- +name: setup-interns +version: 0.1.0 +description: Installs and configures the local `interns` MCP server — a FastMCP stdio app at `/.common/lib/interns-mcp/` that delegates bulk reads, transcript distillation, and other predictable I/O to cheap intern LLMs (DeepSeek / Kimi / Ollama) so Claude saves Anthropic quota. Procedure: detect the server source, `pip install -e` it, write `.common/secrets/interns.env` with the endpoint API keys, register `mcpServers.interns` in `~/.claude.json`. Use this skill when the user says "install interns", "set up interns", "configure interns", "настрой интернов", "установи интернов", "interns не работает", "interns isn't working", or whenever the `mcp__interns__*` tools are missing in a session that needs delegation. Cross-platform — Windows / Linux / macOS. Mutates user-level config and writes secrets; pauses for confirmation before every write. +--- + +# setup-interns + +> One-time skill that gets the local `interns` MCP server running with the user's endpoint API keys and a registered `mcpServers.interns` entry in `~/.claude.json`. Stops at confirmation gates because the procedure runs `pip install`, writes a secret-bearing `.env` file, and edits user-level config. + +Reference: full design lives in this repo at `.wiki/concepts/interns-design.md` (Layer 1/2/3 architecture, MVP catalog, always-ask paths, routing hints). + +## When to use + +- User explicitly asks: install / set up / configure interns. +- A `using-interns`-driven task fails because `mcp__interns__*` tools aren't available in the session. +- New machine in the user's multi-machine fleet — install once per machine that wants delegation. +- Migrating a stale install (endpoint key rotated, server source moved, broken `dist/` artifact) — same procedure, Phase 1 detects what's already in place. + +## Out of scope + +- Building or scaffolding the `.common/lib/interns-mcp/` source tree itself. The skill expects the source already in place per the inline `.common/` convention from the design (or a future Gitea repo when that branch lands). If the source is absent, Phase 1 stops with a clear message — initializing a fresh runtime is a separate task. +- Issuing or rotating endpoint API keys (Ollama Cloud, OpenRouter, etc.). The skill *uses* keys the user already has; if there is none, it points at the provider's settings page and stops. +- Running `interns-mcp` itself — the Claude Code harness spawns it on session start. +- Authoring new interns or editing `.common/config/interns/config.yaml` — that's a content task, not a setup task. +- Any other MCP server. + +## Hard rule: don't auto-mutate config + +The procedure runs `pip install`, writes `.common/secrets/interns.env` (carries endpoint API keys), and edits `~/.claude.json`. **Always pause for explicit confirmation between Phase 1 (discovery, read-only) and Phase 2 (plan), and again before Phase 3 (backup + writes).** A trigger phrase grants permission to inspect, not to install or write secrets. + +## Procedure + +### Phase 0 — Environment sanity + +- Confirm Claude Code is the current harness (need `mcpServers` registration in `~/.claude.json`). +- Confirm `python` ≥ 3.11 and `pip` are on `PATH`. Report the resolved interpreter path (`python -c "import sys; print(sys.executable)"`); the skill will pin this exact path in the MCP registration so a later `python` shadowed by another env doesn't silently take over. +- Confirm network reachability to the configured endpoints (default: `https://ollama.com/v1`). On HTTP 401 / 403 later, the API key is dead — stop and ask for a new one. +- Pick paths: `/.common/lib/interns-mcp/` (source), `/.common/config/interns/config.yaml` (catalog), `/.common/secrets/interns.env` (keys, gitignored), `~/.claude.json` (MCP registration). POSIX-style paths resolve correctly under git-bash on Windows. + +### Phase 1 — Discovery (read-only) + +Search, in order. Report only "found at ", never echo key values. + +**Server source.** Check whether `/.common/lib/interns-mcp/pyproject.toml` exists. If absent, **stop** — the runtime source must be in place before this skill runs. Report: + +``` +.common/lib/interns-mcp/ not found. +This skill expects the inline interns-mcp source per the +.common/ layout (see .wiki/concepts/interns-design.md). Initialize +the runtime first, then re-run setup-interns. +``` + +**Build artifact.** Run `python -c "import interns_mcp" 2>&1` against the candidate interpreter. If it fails with `ModuleNotFoundError`, Phase 4 will run `pip install -e .common/lib/interns-mcp/`. If it succeeds, capture the installed location and skip the install in Phase 4. + +**Config catalog.** Read `/.common/config/interns/config.yaml`. Extract the unique set of `endpoints..api_key_env` values — these are the env var names the runtime expects to find. Capture for Phase 2. + +**Existing endpoint keys.** Look in priority order, per `api_key_env` name from the config: + +1. `/.common/secrets/interns.env` (`=...` lines). +2. Process env (`os.environ[]`). +3. `~/.config/projects-mcp/auth.toml` — only if the user has explicitly noted the key is shared with another local MCP server (rare). + +The first hit wins per key. **Never echo key values in chat.** + +**MCP registration.** Read `~/.claude.json` and check `mcpServers.interns`. Note the `command` and `args`. If args point at a stale interpreter, Phase 6 will fix it. + +**Gitignore sanity.** Check `.gitignore` (project root). If `.common/secrets/` (or `.common/secrets/*.env`) is not listed, flag for Phase 2 — the skill will offer to add it before writing the file. + +### Phase 2 — Plan + confirm + +Present a single-block plan to the user: + +``` +Source: +Module: +Config: — endpoints: +Missing keys: not yet present in interns.env | none> +Gitignore: +MCP entry: +Backups: ~/.claude.json.bak-, .common/secrets/interns.env.bak- (if exists) +``` + +Wait for explicit confirmation ("ok", "go", "поехали"). Anything else → stop. + +For each missing key, ask: "Paste a value for `` (endpoint: `` — provider settings page: ``), or skip and we'll leave the entry blank for you to fill later." Don't proceed past Phase 2 without resolving every required key — the runtime won't start with a missing API key. + +### Phase 3 — Backup + +Copy each file we will modify to `.bak-YYYYMMDD-HHMMSS`: + +```bash +TS=$(date +%Y%m%d-%H%M%S) +[ -f ~/.claude.json ] && cp ~/.claude.json ~/.claude.json.bak-$TS +[ -f .common/secrets/interns.env ] && cp .common/secrets/interns.env .common/secrets/interns.env.bak-$TS +``` + +Confirm both backups exist (when their source existed) before any further edit. + +### Phase 4 — Install Python module + +```bash +# from project root +python -m pip install -e .common/lib/interns-mcp/ +``` + +Capture the resolved `python` from Phase 0; use the same interpreter for both `pip install` and the later MCP `command:` field. Verify post-install: + +```bash +python -c "import interns_mcp; print(interns_mcp.__file__)" +``` + +If import fails — abort. Ask the user to paste the `pip install` output so the failure mode is visible. + +### Phase 5 — Write `interns.env` + gitignore + +If Phase 1 flagged a missing `.gitignore` rule, append it first: + +``` +# interns endpoint API keys +.common/secrets/*.env +``` + +Then write `.common/secrets/interns.env`. Per-key behavior: + +- Existing key in the file with a non-empty value — leave it alone. +- Missing key — append `=` if the user pasted one, or `=` (blank) if the user skipped. A blank entry will fail at runtime with a clear `KeyError`; that's acceptable for the "I'll fill it later" path. + +Permissions: on Linux / macOS run `chmod 600 .common/secrets/interns.env`. On Windows the default ACL is per-user, no extra step. + +### Phase 6 — Register in `~/.claude.json` + +Edit `~/.claude.json`. Add or update the `mcpServers.interns` block: + +```json +{ + "mcpServers": { + "interns": { + "command": "", + "args": ["-m", "interns_mcp.server"], + "cwd": "" + } + } +} +``` + +`cwd` is set so the runtime resolves `.common/config/interns/config.yaml` and `.common/secrets/interns.env` relative to project root regardless of where Claude Code was launched. + +Absolute interpreter path comes from Phase 0 (`sys.executable`). Forward slashes work in JSON on Windows without escaping. + +After each edit, validate JSON: + +```bash +# Windows (git-bash) +powershell.exe -NoProfile -c "Get-Content '' -Raw | ConvertFrom-Json | Out-Null" +# Linux / macOS +jq empty +# fallback +python -c "import json; json.load(open(''))" +``` + +If validation fails → restore from `.bak-*` and abort. + +### Phase 7 — Smoke test (best-effort) + +Best-effort: ask the user to call `mcp__interns__bulk_text_read` against a tiny benign input (e.g. read this file's `Phase 7` section, ask "what is this section about?"). A response that is structurally valid (text + usage) means the server is reachable. + +**Important caveat to relay to the user:** in the *same* session that just ran setup, the active MCP connection was bound at session start. So a passing in-session smoke test only proves "an interns server is alive" — not "the registration we just wrote is what's serving it". The real test is after Claude Code restart. + +If `mcp__interns__*` tools aren't registered in this session at all, skip the smoke test and rely on Phase 8. + +### Phase 8 — Restart guidance + final report + +Tell the user: + +``` +✅ Setup complete. Restart Claude Code so the new mcpServers.interns + registration binds to a fresh stdio session. + +After restart: + • mcp__interns__* tools serve from -m interns_mcp.server + • Endpoint keys live in .common/secrets/interns.env (gitignored) + • Config catalog at .common/config/interns/config.yaml + • Backups saved at ~/.claude.json.bak- (and interns.env.bak- + if it existed before) + +Runtime policy lives in `using-interns`. CLAUDE.md trigger: + delegate to interns when allowed +project-bootstrap 1.6.0+ adds it to new projects automatically. + +If something breaks after restart: + • Restore from .bak-* and tell me — we'll roll back together. +``` + +## Rollback procedure + +If a problem surfaces (now or after restart): + +1. Stop. Don't try to fix forward. +2. Find the most recent `.bak-YYYYMMDD-HHMMSS` next to `~/.claude.json` and `.common/secrets/interns.env`. +3. `cp .bak- ` for each. +4. Optional: `pip uninstall interns-mcp` if you want to remove the editable install. +5. Restart Claude Code. +6. Confirm `mcp__interns__*` is gone (or back to its pre-existing version). +7. Report what went wrong so we can fix the procedure. + +## Cross-platform notes + +The procedure is platform-agnostic. Only auxiliary tooling differs: + +| | JSON validate | Backup | Permissions on `.env` | +|---|---|---|---| +| Windows (git-bash) | `powershell.exe -NoProfile -c "Get-Content '' -Raw \| ConvertFrom-Json \| Out-Null"` | `cp` | per-user ACL by default | +| Linux | `jq empty ` (or `python -c "import json; json.load(open(''))"`) | `cp` | `chmod 600` | +| macOS | same as Linux | `cp` | `chmod 600` | + +POSIX-style paths (`.common/...`, `~/.claude.json`) work on all three. + +## Common mistakes + +- **Skipping Phase 1.** "User just said 'install interns' — let's go." No — find existing source / module / keys first; clobbering an existing `.env` over a working one loses keys you can't recover. +- **Echoing endpoint keys.** They're secrets. Edit / Write tool calls inevitably contain them (that's how they land in `.env`), but no chat output should. +- **Pinning `python` instead of ``.** A bare `python` in the MCP `command:` resolves to whatever interpreter is first on `PATH` at session start — often a different env without the `interns_mcp` module. Always use the absolute interpreter path captured in Phase 0. +- **Forgetting `cwd:`.** Without it the runtime can't find `.common/config/interns/config.yaml` and bombs at startup with a config-not-found error that looks like a Claude Code bug. +- **Writing `.env` with `0644` perms on Linux/macOS.** Token leak. Always `chmod 600` after write. +- **Missing the gitignore rule.** Tokens commit to the repo on the next `git add .`. Always check `.gitignore` covers `.common/secrets/*.env` before writing — Phase 5 does it but it's worth double-checking. +- **Treating in-session smoke test as proof.** Same as the context7 / projects-meta caveat — the active MCP connection was bound at session start. Real verification happens after restart. +- **Auto-running on every "use interns".** This skill is intrusive. Trigger only on explicit "install / set up / configure interns", or when MCP tools are missing and the user is blocked. diff --git a/skills/using-interns/README.md b/skills/using-interns/README.md new file mode 100644 index 0000000..c68eb2b --- /dev/null +++ b/skills/using-interns/README.md @@ -0,0 +1,68 @@ +# using-interns + +Runtime policy for the local `interns` MCP server. Delegates predictable bulk I/O and summarization tasks to cheap intern LLMs (DeepSeek / Kimi / Ollama-hosted) so Claude saves Anthropic quota. + +`using-interns` governs *usage* of an installed server. Initial setup (`pip install`, `.env` write, MCP registration) is owned by [`setup-interns`](../setup-interns/). + +Full design: `.wiki/concepts/interns-design.md` (in this repo) — Layer 1 / 2 / 3 architecture, MVP catalog, always-ask paths, routing hints. + +## When it triggers + +- CLAUDE.md contains `delegate to interns when allowed` (added by `project-bootstrap` 1.6.0+). +- User says: "use interns", "delegate to an intern", "разреши интернов", "allow interns", "go ahead with interns". +- Claude is about to read 3+ files, or one file > 400 lines, just to build context. +- Claude is about to update `.wiki/log.md` or write a session summary from a long transcript. +- If `mcp__interns__*` tools are missing, this skill delegates to [`setup-interns`](../setup-interns/) before doing anything else. + +## What it does + +- **Picks the right intern** for the task from a routing table (`bulk_text_read` for reads, `transcript_distill` for summaries; future interns added in `.common/config/interns/config.yaml`). +- **Guards every call** with a per-session permission grant that mirrors `project-discipline` Rule 4 — ask-mode default, conversational grant / revoke, session-end reset. +- **Enforces always-ask paths** — `.env`, `**/secrets/**`, `**/*.key`, `**/*.pem`, `**/.ssh/**`, `**/.aws/credentials`, `**/.netrc` etc. — even when delegation is granted. Server-side enforcement plus a transitive rule: Claude can't bypass by reading the file with the local `Read` tool and forwarding the content. +- **Caps cost** — calls with estimated cost > $0.10 always go to ask-mode regardless of grant. +- **Tells Claude what NOT to delegate** — architecture, debugging, auth / payments, final commit messages, final user-facing answers. + +## Permission grant cheat-sheet + +| Phrase | Effect | +|---|---| +| (default) | Ask before every `mcp__interns__*` call. | +| "разреши интернов" / "allow interns" | Free delegation until session end (subject to always-ask paths + cost cap). | +| "отзови интернов" / "revoke interns" | Back to ask-mode. | +| (session ends) | Reset to ask-mode. The next session asks again. | + +## Tool quick reference + +| Tool | Required args | Optional | Purpose | +|---|---|---|---| +| `mcp__interns__bulk_text_read` | `paths: list[str]`, `question: str` | `max_tokens: int` | Read N files, answer with file:line citations. | +| `mcp__interns__transcript_distill` | `paths: list[str]`, `question: str` | `max_tokens: int` | Distill transcript / log into structured action list. | + +Pass **paths**, not file contents. The MCP server reads and applies the always-ask matcher server-side; forwarding content as a string arg bypasses the gate. + +## When NOT to use + +- Architecture / design decisions — Claude's job. +- Debugging — cheap models miss subtle bugs. +- Auth / payments / PII / production data — recommendation, not enforced, but obvious. +- Final commit messages, PR descriptions, user-facing answers — don't sub-delegate the deliverable. +- A single 50-line file you can read yourself for free. + +Full policy and examples in [`SKILL.md`](SKILL.md). + +## Install + +From the repo root: + +```bash +bash scripts/install.sh using-interns +``` + +Works on Windows under git-bash, Linux, macOS. + +## See also + +- [`setup-interns`](../setup-interns/) — companion, owns the server install + `mcpServers.interns` registration. +- [`project-discipline`](../project-discipline/) — Rule 4 (per-session push grant) is the prior art for the grant mechanism here. +- [`using-projects-meta`](../using-projects-meta/), [`using-context7`](../using-context7/) — sister `using-X` skills for other MCP servers (same shape). +- `.wiki/concepts/interns-design.md` — full architecture spec. diff --git a/skills/using-interns/SKILL.md b/skills/using-interns/SKILL.md new file mode 100644 index 0000000..198aa80 --- /dev/null +++ b/skills/using-interns/SKILL.md @@ -0,0 +1,191 @@ +--- +name: using-interns +version: 0.1.0 +description: Use when delegating predictable bulk reads or summarization to cheap intern LLMs via the local `interns` MCP server (`mcp__interns__bulk_text_read`, `mcp__interns__transcript_distill`, etc.) so Claude saves Anthropic quota. Activated by `delegate to interns when allowed` in CLAUDE.md or explicit phrases like "use interns", "delegate to an intern", "разреши интернов", "allow interns". Per-session permission grant mirrors `project-discipline` Rule 4: ask-mode default, conversational grant / revoke, always-ask paths for `.env` / secrets / keys / SSH / credentials even with active grant, transitive rule (Claude can't bypass by reading the file itself and forwarding content), session-end reset. Skip for architecture, debugging, auth / payments, final commit messages, or final user-facing text. +--- + +# Using the `interns` MCP server + +## Overview + +`interns` is a local stdio MCP server that exposes a catalog of cheap-LLM "interns" — DeepSeek, Kimi, Ollama-hosted models, etc. — so Claude can delegate predictable bulk I/O and summarization tasks instead of paying Anthropic quota for them. The pattern (~23× cheaper end-to-end on summarization, ~125× per-call on bulk reads) is sourced from a Reddit thread + Medium follow-up; see `.wiki/concepts/interns-design.md` for the full design and the cost numbers. + +Two MVP interns: + +| Tool | What it does | When to call | +|---|---|---| +| `mcp__interns__bulk_text_read` | Reads N files end-to-end and answers a focused question with file:line citations. | Claude was about to read 3+ files or one file > 400 lines just to extract context. | +| `mcp__interns__transcript_distill` | Compresses a session transcript / log into a structured action list (decisions / open questions / next steps). | Before updating `.wiki/log.md` or producing a session summary. | + +Both currently run on Ollama Cloud (`deepseek-v4-flash`, ~$0.002 / call). Adding a new intern is a config-only change — see `.wiki/concepts/interns-design.md` § "Как добавить нового интерна". + +## Prerequisites + +This skill assumes `mcp__interns__*` tools are available. If they aren't (tools missing from the session, or calls fail with a connection error), the server isn't running for this session. Trigger the **`setup-interns`** skill to `pip install -e` the runtime, write `.common/secrets/interns.env`, and register `mcpServers.interns` in `~/.claude.json`. It's a one-time procedure with confirmation gates. + +## When to use + +- A read that's **bulky and not central to editing**: scanning long config files, log dumps, transcript files, generated docs — anything where Claude would burn input tokens summarizing for itself. +- A read across **3+ files** to assemble context. +- A read of **one file > 400 lines** that won't be edited. +- **Transcript / session distillation** before writing a wiki log entry, summary, or post-mortem. +- Any future intern documented in `.common/config/interns/config.yaml` (PDF extraction via Marker, repo packaging via Repomix, JS-rendered web fetches via Firecrawl, etc.) — same trigger / grant rules apply. + +## When NOT to use + +- **Architecture / design decisions.** Cheap models miss subtle trade-offs. +- **Debugging.** Cheap models hallucinate in ways that turn a 5-minute fix into a 1-hour wild goose chase. +- **Auth / payments / PII / production data / deletion.** Recommendation, not enforced — but obvious. +- **Final commit messages, PR descriptions, user-facing answers.** The task explicitly delegated *to* Claude. Don't sub-delegate the deliverable. +- **Anything that fits into Claude's own working context cheaply.** A 50-line file to skim is not a delegation candidate; it's just a Read. + +## Per-session permission grant (mirrors `project-discipline` Rule 4) + +The grant mechanism is identical in shape to the push-grant in `project-discipline`. Reuse the same vocabulary so the user doesn't have to learn two policies. + +### Default — ask-mode + +Every session starts in ask-mode. Before the first `mcp__interns__*` call, ask: + +> Я бы делегировал чтение `` интерну `bulk_text_read` (DeepSeek Flash via Ollama Cloud, ~$0.002 за вызов). Ок? + +(or its English equivalent if the user is communicating in English) and wait for explicit `yes` / `да` / `go` / `поехали`. Without confirmation — don't call. + +### Conversational grant + +When the user says any of: + +- "разреши интернов" / "разреши интерна" / "разреши делегировать" +- "allow interns" / "use interns freely" / "go ahead with interns" + +— grant the right to call `mcp__interns__*` without further confirmation **for the rest of the session**, subject to always-ask paths below. Acknowledge the grant in one short line ("ок, делегирую интернам без подтверждения, кроме secrets-путей" / "got it, free delegation except secrets"). + +### Conversational revoke + +When the user says any of: + +- "отзови интернов" / "снова спрашивай" / "делай сам" +- "revoke interns" / "stop using interns" / "ask me again every time" + +— return to ask-mode for the rest of the session. Acknowledge in one short line. + +### Session-end reset + +The next session starts in ask-mode regardless of prior grants. Same reasoning as `project-discipline` Rule 4: a grant is given for the current context (user nearby, attention available), and should not survive a context switch. + +### Always-ask paths (even with active grant) + +These never go to an intern silently, even when delegation is granted: + +- `**/.env`, `**/.env.*` +- `**/secrets/**` (including `.common/secrets/`, `~/.config/projects-mcp/`) +- `**/credentials*`, `**/credentials.json` +- `**/*.key`, `**/*.pem` +- `**/.ssh/**` +- `**/.aws/credentials`, `**/.aws/config` +- `**/.netrc`, `**/.npmrc`, `**/.pypirc` + +The `interns` MCP server enforces this server-side: matched paths return `BlockedByPolicy{path, pattern, reason}` instead of going out to the endpoint. Claude's job: **don't try to bypass** by reading the file with the local `Read` tool and forwarding the content as a string argument. The transitive rule applies — once a file matched, its content stays out of every intern call for the rest of the session unless the user explicitly grants per-path. + +When a path is blocked, ask the user explicitly: + +> Файл `` matched always-ask pattern `` (reason: ``). Передавать интерну на endpoint `` несмотря на это? + +Wait for an explicit per-path "yes". Don't generalize the answer to other paths in the same call. + +### Cost-based always-ask + +Any call with estimated cost > $0.10 (per the `tokens × price_per_M` config in `.common/config/interns/config.yaml`) goes to ask-mode regardless of grant state. Sanity bound — catches a misrouted huge-payload request before it bills. + +## Routing hints (when to pick which intern) + +| Situation | Intern | +|---|---| +| File > 400 lines, not editing it | `bulk_text_read` | +| Need to read 3+ files for context | `bulk_text_read` | +| Updating `.wiki/log.md` or session-summary doc | `transcript_distill` | +| Compressing a long brainstorm transcript before quoting in a design doc | `transcript_distill` | +| (Future interns in `config.yaml`) | per the description in the catalog | + +## Workflow + +``` +1. Identify the candidate task (read-heavy, bulk, predictable). +2. Pick the intern from the routing table. +3. Check grant state: + • ask-mode → ask before calling + • granted → check always-ask paths; if any matched, ask per-path +4. Call the intern with `paths` (list of file paths — the server reads them) + and `question` (focused, specific). +5. Cite the response (file:line refs come from the intern's reply). +``` + +Don't pass file *contents* as arguments — only paths. The MCP server reads and applies the always-ask matcher before any path content reaches an endpoint. If you forward content yourself, the gate is bypassed and the user can't trust the policy. + +## Tool quick reference + +| Tool | Required args | Optional | Purpose | +|---|---|---|---| +| `mcp__interns__bulk_text_read` | `paths: list[str]`, `question: str` | `max_tokens: int` | Read N files end-to-end, answer the question with citations. | +| `mcp__interns__transcript_distill` | `paths: list[str]`, `question: str` | `max_tokens: int` | Distill transcript / log into structured action list. | + +(Future interns expose tools at `mcp__interns__` as the catalog grows.) + +## Examples + +### Read-bulk delegation + +User: "summarize what these four config files do for the build pipeline." + +``` +1. Routing → bulk_text_read (4 files, context only). +2. Grant state → ask-mode (session start). +3. Ask: "Bulk-read these 4 files via bulk_text_read (~$0.002)? Ок?" +4. User: "ok" +5. Call mcp__interns__bulk_text_read + paths: ["build/config.ts", "build/plugins.ts", "build/env.ts", "build/output.ts"] + question: "What does each file contribute to the build pipeline? Cite file:line." +6. Cite the response. Done. +``` + +### Always-ask path triggered + +User: "scan all `.env*` files in the repo and tell me which keys are duplicated." + +``` +1. Routing → bulk_text_read. +2. Grant state → granted (user said "allow interns" earlier). +3. Path matcher → every input matches `**/.env`. Server returns BlockedByPolicy. +4. Ask user: "These are .env files (always-ask). Pass them to bulk_text_read despite the secrets exposure?" +5. Wait for explicit per-path yes/no. +``` + +### Transcript distill + +User: "compress this brainstorm transcript into action items before I ingest it into the wiki." + +``` +1. Routing → transcript_distill. +2. Call mcp__interns__transcript_distill + paths: [".meeting-room/.brainstorm/foo.md"] + question: "Extract decisions, open questions, and next steps. Output structured markdown." +3. Quote the result in the wiki ingest commit. +``` + +## Common mistakes + +| Mistake | Fix | +|---|---| +| Calling an intern in ask-mode without asking first | Ask before the first call every session, even for trivial reads. | +| Forwarding file *content* instead of *path* | Pass paths. The server reads. The matcher only sees paths. | +| Trying to bypass always-ask by reading the file with `Read` and pasting content | Transitive rule — that path stays out of intern calls for the session unless user says otherwise per-path. | +| Sub-delegating final deliverables (commit messages, user-facing answers) | Those are Claude's job. Interns are for predictable bulk I/O, not for the answer that ships. | +| Using an intern for debugging | Cheap models miss subtle bugs. Pay the Anthropic call for debugging — the savings aren't worth a wrong fix. | +| Persistent grant across sessions | The next session resets to ask-mode. By design — same as project-discipline Rule 4. | + +## Red flags + +- "I'll just paste the content as a string arg" → no. The matcher only sees paths. If you're tempted to bypass it, you're about to leak a secret. +- "This grant should survive the session" → no. The next session asks again. The grant is bound to the current context where the user is paying attention. +- "It's just a small file, why ask?" → small files don't need an intern. Read them yourself. The ask is *because* the call goes to a third-party endpoint, not because of size. +- "Estimated cost is fine, $0.08 < $0.10" → still ask if the call is novel or the file set is unfamiliar. The cost gate is a hard ceiling, not the only signal.