From a7b959c8fc0e5d05c566fbbfeaea214a4174ba13 Mon Sep 17 00:00:00 2001 From: Jim Myhrberg Date: Sun, 15 Feb 2026 23:35:28 +0000 Subject: [PATCH] refactor: remove AI agent config management from siren script Agent configurations (CLAUDE.md, commands, skills, cursor rules) have been extracted to a separate repo (jimeh/agentic). Remove all related symlink logic, helper functions, and stale-link cleanup from siren. - Delete claude/ directory (CLAUDE.md, settings, statusline, commands, skills) - Delete cursor/user-rules.md and cursor commands - Delete ai/references/ directory - Remove _add_command_symlinks, _add_skill_symlinks, _cleanup_stale_commands, _cleanup_stale_skills functions - Remove Claude conditional block from define_settings() - Trim Cursor conditional block to only mcp.json symlink - Remove stale-symlink cleanup calls from do_config() Co-Authored-By: Claude Opus 4.6 --- .../a-complete-guide-to-agents.md.md | 290 ----------------- ...le-for-building-plans-you-actually-read.md | 69 ----- .../plan-loop-diagram.png | Bin 37400 -> 0 bytes claude/CLAUDE.md | 113 ------- claude/commands/claude-to-agents.md | 85 ----- claude/commands/clean-gone-branches.md | 55 ---- claude/commands/commit-push-pr.md | 46 --- claude/commands/commit.md | 26 -- claude/commands/generate-agents.md.md | 291 ------------------ claude/commands/rebase.md | 33 -- claude/commands/refactor-agents.md.md | 34 -- claude/settings.json | 118 ------- .../skills/frontend-design-systems/SKILL.md | 139 --------- claude/statusline.sh | 245 --------------- cursor/commands/generate-agentsmd.md | 265 ---------------- cursor/user-rules.md | 1 - siren | 136 -------- 17 files changed, 1946 deletions(-) delete mode 100644 ai/references/a-complete-guide-to-agents.md.md delete mode 100644 ai/references/my-agents.md-file-for-building-plans-you-actually-read.md delete mode 100644 ai/references/my-agents.md-file-for-building-plans-you-actually-read/plan-loop-diagram.png delete mode 100644 claude/CLAUDE.md delete mode 100644 claude/commands/claude-to-agents.md delete mode 100644 claude/commands/clean-gone-branches.md delete mode 100644 claude/commands/commit-push-pr.md delete mode 100644 claude/commands/commit.md delete mode 100644 claude/commands/generate-agents.md.md delete mode 100644 claude/commands/rebase.md delete mode 100644 claude/commands/refactor-agents.md.md delete mode 100644 claude/settings.json delete mode 100644 claude/skills/frontend-design-systems/SKILL.md delete mode 100755 claude/statusline.sh delete mode 100644 cursor/commands/generate-agentsmd.md delete mode 120000 cursor/user-rules.md diff --git a/ai/references/a-complete-guide-to-agents.md.md b/ai/references/a-complete-guide-to-agents.md.md deleted file mode 100644 index 711c8d7..0000000 --- a/ai/references/a-complete-guide-to-agents.md.md +++ /dev/null @@ -1,290 +0,0 @@ ---- -source: https://www.aihero.dev/a-complete-guide-to-agents-md ---- - -# A Complete Guide To AGENTS.md - -Have you ever felt concerned about the size of your `AGENTS.md` file? - -Maybe you should be. A bad `AGENTS.md` file can confuse your agent, become a -maintenance nightmare, and cost you tokens on every request. - -So you'd better know how to fix it. - -## What is AGENTS.md? - -An `AGENTS.md` file is a markdown file you check into Git that customizes how AI -coding agents behave in your repository. It sits at the top of the conversation -history, right below the system prompt. - -Think of it as a configuration layer between the agent's base instructions and -your actual codebase. The file can contain two types of guidance: - -- **Personal scope**: Your commit style preferences, coding patterns you prefer -- **Project scope**: What the project does, which package manager you use, your - architecture decisions - -The `AGENTS.md` file is an open standard supported by many - though not all - -tools. - -
- CLAUDE.md - -Notably, Claude Code doesn't use `AGENTS.md` - it uses `CLAUDE.md` instead. You -can symlink between them to keep all your tools working the same way: - -```bash -# Create a symlink from AGENTS.md to CLAUDE.md -ln -s AGENTS.md CLAUDE.md -``` - -
- -## Why Massive `AGENTS.md` Files are a Problem - -There's a natural feedback loop that causes `AGENTS.md` files to grow -dangerously large: - -1. The agent does something you don't like -2. You add a rule to prevent it -3. Repeat hundreds of times over months -4. File becomes a "ball of mud" - -Different developers add conflicting opinions. Nobody does a full style pass. -The result? An unmaintainable mess that actually hurts agent performance. - -Another culprit: auto-generated `AGENTS.md` files. Never use initialization -scripts to auto-generate your `AGENTS.md`. They flood the file with things that -are "useful for most scenarios" but would be better progressively disclosed. -Generated files prioritize comprehensiveness over restraint. - -### The Instruction Budget - -Kyle from Humanlayer's -[article](https://www.humanlayer.dev/blog/writing-a-good-claude-md) mentions the -concept of an "instruction budget": - -> Frontier thinking LLMs can follow ~ 150-200 instructions with reasonable -> consistency. Smaller models can attend to fewer instructions than larger -> models, and non-thinking models can attend to fewer instructions than thinking -> models. - -Every token in your `AGENTS.md` file gets loaded on **every single request**, -regardless of whether it's relevant. This creates a hard budget problem: - -| Scenario | Impact | -| -------------------------- | ----------------------------------------------------- | -| Small, focused `AGENTS.md` | More tokens available for task-specific instructions | -| Large, bloated `AGENTS.md` | Fewer tokens for the actual work; agent gets confused | -| Irrelevant instructions | Token waste + agent distraction = worse performance | - -Taken together, this means that **the ideal `AGENTS.md` file should be as small -as possible.** - -### Stale Documentation Poisons Context - -Another issue for large `AGENTS.md` files is staleness. - -Documentation goes out of date quickly. For human developers, stale docs are -annoying, but the human usually has enough built-in memory to be skeptical about -bad docs. For AI agents that read documentation on every request, stale -information actively _poisons_ the context. - -This is especially dangerous when you document file system structure. File paths -change constantly. If your `AGENTS.md` says "authentication logic lives in -`src/auth/handlers.ts`" and that file gets renamed or moved, the agent will -confidently look in the wrong place. - -Instead of documenting structure, describe capabilities. Give hints about where -things _might_ be and the overall shape of the project. Let the agent generate -its own just-in-time documentation during planning. - -Domain concepts (like "organization" vs "group" vs "workspace") are more stable -than file paths, so they're safer to document. But even these can drift in -fast-moving AI-assisted codebases. Keep a light touch. - -## Cutting Down Large `AGENTS.md` Files - -Be ruthless about what goes here. Consider this the absolute minimum: - -- **One-sentence project description** (acts like a role-based prompt) -- **Package manager** (if not npm; or use `corepack` for warnings) -- **Build/typecheck commands** (if non-standard) - -That's honestly it. Everything else should go elsewhere. - -### The One-Liner Project Description - -This single sentence gives the agent context about _why_ they're working in this -repository. It anchors every decision they make. - -Example: - -```markdown -This is a React component library for accessible data visualization. -``` - -That's the foundation. The agent now understands its scope. - -### Package Manager Specification - -If you're In a JavaScript project and using anything other than npm, tell the -agent explicitly: - -```markdown -This project uses pnpm workspaces. -``` - -Without this, the agent might default to `npm` and generate incorrect commands. - -
- Corepack is also great -You could also use [`corepack`](https://github.com/nodejs/corepack) to let the system handle warnings automatically, saving you precious instruction budget. -
- -### Use Progressive Disclosure - -Instead of cramming everything into `AGENTS.md`, use **progressive disclosure**: -give the agent only what it needs right now, and point it to other resources -when needed. - -Agents are fast at navigating documentation hierarchies. They understand context -well enough to find what they need. - -#### Move Language-Specific Rules to Separate Files - -If your `AGENTS.md` currently says: - -```markdown -Always use const instead of let. -Never use var. -Use interface instead of type when possible. -Use strict null checks. -... -``` - -Move that to a separate file instead. In your root `AGENTS.md`: - -```markdown -For TypeScript conventions, see docs/TYPESCRIPT.md -``` - -Notice the light touch, no "always," no all-caps forcing. Just a conversational -reference. - -The benefits: - -- TypeScript rules only load when the agent writes TypeScript -- Other tasks (CSS debugging, dependency management) don't waste tokens -- File stays focused and portable across model changes - -#### Nest Progressive Disclosure - -You can go even deeper. Your `docs/TYPESCRIPT.md` can reference -`docs/TESTING.md`. Create a discoverable resource tree: - -``` -docs/ -├── TYPESCRIPT.md -│ └── references TESTING.md -├── TESTING.md -│ └── references specific test runners -└── BUILD.md - └── references esbuild configuration -``` - -You can even link to external resources, Prisma docs, Next.js docs, etc. The -agent will navigate these hierarchies efficiently. - -#### Use Agent Skills - -Many tools support "agent skills" - commands or workflows the agent can invoke -to learn how to do something specific. These are another form of progressive -disclosure: the agent pulls in knowledge only when needed. - -We'll cover agent skills in-depth in a separate article. - -## `AGENTS.md` in Monorepos - -You're not limited to a single `AGENTS.md` at the root. You can place -`AGENTS.md` files in subdirectories, and they **merge with the root level**. - -This is powerful for monorepos: - -### What Goes Where - -| Level | Content | -| ----------- | -------------------------------------------------------------------------- | -| **Root** | Monorepo purpose, how to navigate packages, shared tools (pnpm workspaces) | -| **Package** | Package purpose, specific tech stack, package-specific conventions | - -Root `AGENTS.md`: - -```markdown -This is a monorepo containing web services and CLI tools. -Use pnpm workspaces to manage dependencies. -See each package's AGENTS.md for specific guidelines. -``` - -Package-level `AGENTS.md` (in `packages/api/AGENTS.md`): - -```markdown -This package is a Node.js GraphQL API using Prisma. -Follow docs/API_CONVENTIONS.md for API design patterns. -``` - -**Don't overload any level.** The agent sees all merged `AGENTS.md` files in its -context. Keep each level focused on what's relevant at that scope. - -## Fix A Broken `AGENTS.md` With This Prompt - -If you're starting to get nervous about the `AGENTS.md` file in your repo, and -you want to refactor it to use progressive disclosure, try copy-pasting this -prompt into your coding agent: - -```txt -I want you to refactor my AGENTS.md file to follow progressive disclosure principles. - -Follow these steps: - -1. **Find contradictions**: Identify any instructions that conflict with each other. For each contradiction, ask me which version I want to keep. - -2. **Identify the essentials**: Extract only what belongs in the root AGENTS.md: - - One-sentence project description - - Package manager (if not npm) - - Non-standard build/typecheck commands - - Anything truly relevant to every single task - -3. **Group the rest**: Organize remaining instructions into logical categories (e.g., TypeScript conventions, testing patterns, API design, Git workflow). For each group, create a separate markdown file. - -4. **Create the file structure**: Output: - - A minimal root AGENTS.md with markdown links to the separate files - - Each separate file with its relevant instructions - - A suggested docs/ folder structure - -5. **Flag for deletion**: Identify any instructions that are: - - Redundant (the agent already knows this) - - Too vague to be actionable - - Overly obvious (like "write clean code") -``` - -## Don't Build A Ball Of Mud - -When you're about to add something to your `AGENTS.md`, ask yourself where it -belongs: - -| Location | When to use | -| ------------------------- | -------------------------------------------------- | -| Root `AGENTS.md` | Relevant to every single task in the repo | -| Separate file | Relevant to one domain (TypeScript, testing, etc.) | -| Nested documentation tree | Can be organized hierarchically | - -The ideal `AGENTS.md` is small, focused, and points elsewhere. It gives the -agent just enough context to start working, with breadcrumbs to more detailed -guidance. - -Everything else lives in progressive disclosure: separate files, nested -`AGENTS.md` files, or skills. - -This keeps your instruction budget efficient, your agent focused, and your setup -future-proof as tools and best practices evolve. diff --git a/ai/references/my-agents.md-file-for-building-plans-you-actually-read.md b/ai/references/my-agents.md-file-for-building-plans-you-actually-read.md deleted file mode 100644 index 0d678cf..0000000 --- a/ai/references/my-agents.md-file-for-building-plans-you-actually-read.md +++ /dev/null @@ -1,69 +0,0 @@ -# My AGENTS.md file for building plans you actually read - -Most developers are skeptical about AI code generation at first. It seems -impossible that an AI could understand your codebase the way you do, or match -the instincts you've built up over years of experience. - -But there's a technique that changes everything: the planning loop. Instead of -asking AI to write code directly, you work through a structured cycle that -dramatically improves the quality of what you get. - -This approach transforms AI from an unreliable code generator into an -indispensable coding partner. - -## The Plan Loop: A Four-Step Process - -Every piece of code now goes through the same cycle. - -![Plan Loop -Diagram](./my-agents.md-file-for-building-plans-you-actually-read/plan-loop-diagram.png) - -**Plan** with the AI first. Think through the approach together before writing -any code. Discuss the strategy and get alignment on what you're building. - -**Execute** by asking the AI to write the code that matches the plan. You're not -asking it to figure out what to build—you've already done that together. - -**Test** the code together. Run unit tests, check type safety, or perform manual -QA. Validate that the implementation matches what you planned. - -**Commit** the code and start the cycle again for the next piece. - -## Why This Matters - -This loop is completely indispensable for getting decent outputs from an AI. - -If you drop the planning step altogether, you're really hampering yourself. -You're asking the AI to guess what you want, and you'll end up fighting with -hallucinations and misunderstandings. - -Planning forces clarity. It makes the AI's job easier and your code better. - -## Rules for Creating Great Plans - -Here are the key rules from my `CLAUDE.md` file that make plan mode effective: - -```md -## Plan Mode - -- Make the plan extremely concise. Sacrifice grammar for the sake of concision. -- At the end of each plan, give me a list of unresolved questions to answer, if any. -``` - -These simple guidelines transform verbose plans into scannable, actionable -documents that keep both you and the AI aligned. - -Copy them into your `CLAUDE.md` or `AGENTS.md` file, and enjoy simpler, more -readable plans. - -Or, run this script to append them to your `~/.claude/CLAUDE.md` file: - -```bash -mkdir -p ~/.claude && cat >> ~/.claude/CLAUDE.md << 'EOF' - -## Plan Mode - -- Make the plan extremely concise. Sacrifice grammar for the sake of concision. -- At the end of each plan, give me a list of unresolved questions to answer, if any. -EOF -``` diff --git a/ai/references/my-agents.md-file-for-building-plans-you-actually-read/plan-loop-diagram.png b/ai/references/my-agents.md-file-for-building-plans-you-actually-read/plan-loop-diagram.png deleted file mode 100644 index d31473b199ca418c65f4245ecde402e5346a8c85..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37400 zcmeFZWmH^E_dN)KK=5E8K!D&50Xnz^Z#+nFcXw^vCAhma5Zv8DaBH9mBzS<}u8lLz z^Sm?joBvw#X=crQdDntP-OIgIb<57FefF+MWkqQ$bP{v~1OzOgjD!jT0&*w}zFqJxGUvc!M|4M&q4tmHYR7tpO z6D?%ffm#XDusYVe>~?7C(r)T$szK>C)3Tv=k)qVXKtJ{`QN)6AB!!4B%`f!Uw@JCsbofVVj5r~{6|gsNAHV& zQZzY_n4$mPM2|0s|0kt_$Vu@06b+C`G)(N@)XQOInSWAc2*l|BzDf9AobsO(_=PFM zzgegS{5P}zwpk+0e}@Jz@xRlF2KfKsszH#+Sd1w9>$C?;@{f4yfa-fpZqWH-?0By1ybS%ARp)6LT5q;>+zzZz;7JA?w| z8%-1s@-&AQxq4%X-q+ReX}Zd0Mby;M#0-tApJ%jL`_*bD(t!gVEhodsPzFeN#0zHR zcN_Vw+3w%EJRO|(G66F`pahj&rRDBF!L+=uc*s^#!9|}{R0o3=A$g8nfizYu@K549 z87DoMucg+c#TrxI0dQ{oh;zE4KSF;a2em4)@aJOp-*yQTPaK?B`ILw*=^)3`akR2N z#TgS>FlCkRs!e9$zfMsmxc$R0g(fHUO8D+Whu_J^@OB_c(#w_{f6t@$KqlmQLrZ3O zLm*dxDXEH!&7PEMmGQ?4dv2Nou4C*s6sgwxMaL;@Dt5l$ zg+ws+Mehe2BjlFnM*Tlp_y4VgfF@BjQ_0`T`bYnT?%Qb5D%J-xu9a{^z)vKP>$H{ZvVCAcZSP z5?^W>S=c>b9qqo`i_72+-h-Q=0#AaPEI?{(QUOl~{H_|;m(jFVKO)r#xo+w+y!r}O zQtg}d&KnHtT+<7tkh!;&L_`jlOh&G{`db7g7aMSpD`<9;d0sOS4p}plR~ntI!&JV& zn*Z2`cR6lLlS$E8MMMp#v$P)K1P>teQ_PD`o*(ua12d(-(h1s~)3uH0SUR)O=^ws2*e zE{R_O`B~kBn?y8`AH=PS*WRKlC{J58^%nMF1MU}V=@kYto?9wY06$ddq{NIg`>pq`of*2jsL|x za@F3o+eLd5C_Y3395rG9d}_O>r`cr6IkG5%mjd_#&kT%K%KHVM<=Nu`DE^!ID{P7+ zwQsW4qd}5*Z~u1}jP8HBV8yE7#4Z|;_s-#NNelg_dUhaF4)zh_F2QFtK59)GVEART zD{3@?jDU}PBA600)b#+$n5c)k!(SWyFtKR0+!oqZV{dlMtYc}l0D0uefR0nq(@MI-<5zCp|Tk&i{lpACbHy}sqN$MYdYV|PdKr2`YZRpL3z z2zJ#nU74_U0UPaMsftOmB{G-AGPJ7Tq_WfH$Hrv39QlMjxx|BA>gicI2PKNGE}+T? zAcF&t%T-2DW_oqyD+Kfg-O5}Q%M_zO4x|833K&((2Twj1sZLNl!VI?byxTTU{r~H^wdVr1Y>9O18arKGiR*Pa%HTmDANQ07ar-omS3 znMjf;0lFO)ajkqZU=rsg2vQD_@%l(u=lrAK&!aT6UjYh*>j+;bu z*b$+>6}5-1FYCTXDt?v+HX*I}elRpL*tMx8VMi|M0R;y)RGGx&Eeiu11 z_-x(jAt{J*p2zy;sL!QrrQ~=Mx>BtqEhi4Oop=&8I<>9V8lek?4roToP#Q=w7&p*_vu z=`KwZ^z?-xukY)E)jJSPBGvR6-rXYJPv3iT?xoJ4_D2Nfy#CnmR`Ypn?vy!B6UEEg zxIEztCXhQtNK4Ju+`dRZREzdt`B89E`1bXF?t&~GUXk;aAk%1AM>ry5yMcdTGlc(( z-y_9!{~eJ^{gW5@?V0wGKc$%D@?x3m8p3WPW@svlmKe*MqUPpQPeDkt-Qw?dH$i&j zM3gZiboj~^2PwTmjb4?oQV|kzZ5h}-*r81sox#KjMN3Qm{Fy5hm=wiJ=$z;}&vmc~cC!h7v|cVl@)u zE7;yH5LR}VMmm~daha#Y?BAH!N*g38F?PPhIXxVvq&vQ_DsN)0H*gY|qbLw2M#2tX zH1|xy#72Gd0(AF+Y{B7rKKN#y`m#F z4_TA*O}4q$8)~-eD5}?%9^Ih$VBb&pq8sZYFTVcU|w-y#VS_K;BavM^FlkbpR}f-M`)tHMrfjoVhrDhhGhO^ zBwFjP!PwYhg1pJX{Yz&5%JP9oe27SEHtC}~Au}Z8P-$t>&R|gnpSB;8Ehz~JPUt#3 z;`#0W;iZ3Vrj7`Raho;!)A12XxBvD;r9a}2q>|5i8VTpR|BPFY#GQiz9=_KX7oa=N zFKiKrs=Rk`5EDiJtR~YfpEru63js05ez{@(21D@gezB(so5^c%UWwO>4Mx^E;>!|w z7_>E4i#sESS`8@6Y?#4K6BZGA7u+Xs<>`9MBJ7t~)z}S{U!`q1AMeqJ1a%rT7s&wX z*J{|d!bg+H%#Xn!n1kirZzS8Bp0q0u-@{+`yc)XKTHJZ3isf`z)o+7c=})&b zcJ?OXDRUmq{9uQI=Z8-3K>jA%X~D5>-+1lVj}32glx9xqUiOYwB4I6^o-%8}#QZ-1 z82vvaTRWH@uP`ok?`~ISinP)x_Dwi!L`iRRfl3PE(HD2|&W+>mKUlxZqKn{*OI^d)1gQgaXc^E2RquHtFZ&~smb3|k}#RH2^rxzbPhgx zlKr|Ld(iFZ#C8`M3uD(Cuv0?(>C`t^s&x+WIn4jUt>-UXK>-n(li&8c;&yW!w4nHN z+Jn=0j1nmVB8}Eqmi~N6{8OIP6?FtT$1Vp9ji;2407#560LlM;?_TL7x>=uG8H`eg zO#{668zAY)=Yn@v+|vuGB}WZ7C%+ep)o}dm@T&wLXV2TVvXuE7Qms@`7Hok09^H^$ z^7I*s9o8Im1qD5<>EQ%r2cOK}*F;2hTNaLYO8O?Ve7(0ODP2!JcfNl<&RR{vd;a56 z(+kF$Zls!-w6cx4$vA2?v?w;iS&=1(q^Pq$b0nr{kQz_?v6vK#l+e3bn%NA9kn07_ z&4tjDzy8t{-lG2Vrv_(u-FuoareLiVG-ZK}JQ$5; z9=OO1itxzoRre5@*m!ci+zEUQ@4(5`R~PX+XkV~*s8^Px9L$MZp8nn~-6n{>M^+}F z{Q_cR7WUxD%JmH(eR8GKtLaf3TgerzDWvg5`!i#(xq!p={tG!Rw?FZ(`~9b_K`&+4 zO-CD@1N`NQby&?fyzAJ*uUzA|tnHr;P6A(x+MaS&BPK3KQrlI@2VH5v937u-eAb^H zQQ~~g_m}QRHq{QT*1mV^xBhjX+upq->u~&Nvzikqo^ye`ppyZ4IB<~b8#>yq>%l=5 zLzuSyazFc^i%5g*?&MjPaKw8keuXPqvM4YM?x6By#+22|XH1dP2)|JYr&3FLb*2&O31b<~!)Nr?r&L@U(Nu z;rP12qu%&bl10RUEUP1^$&KaS62;qF2BiXFM*wR1cI0QV?p;bnnOw{C9LXg92U?j+ z1plT8zFsMGR)EmUjGw1=oHF>IPhX8qOP6ly6APqZhI}H@J*hTK0naFuXEkfUrgO9h zV@Un`tHS9K$&1=0b@5q94c3JtBhbq-K3oxxG4L9(@RlUFe zYW~891gbx*f$o~F92DJ~QuZCrQ}I`V<&(OyWbr$~P))g}mg#BKu}8Cya;4bwLK?Q% z+j__}iP8&dzG!%it?P>(j(yUp_18FQb$c!z=htBsWhTU{t!Awl$!^)80ZCCFp`73- zF0^$A*Z6g7^7}h8Wa(bAFJ0+`6l0=FJYC|@$nL(_fHuUmuv}*^3so$4w(5yfl zUq`20b|`Pwaa&aAaeF%R1>>;tF@JzNg*UC#8F9V^?TY`eafZ$@C`rv`op@ddWyx&~LcF1p1kwY@~-t9L!{p z_80&CjI^{W#&Q{d^}Hj`uTHM*EZ?tUe=D66_6ih@i_LFaXbKCV7~g!#E!K~5Nl zuigTYj~zr^5i5>-0&HYvn&=e`!VVkR@85c?tu%}fS~_4LomEX%{6^@O-Gci{>y(ZU`ckCO1%ROAe= zmXlKvh}{s%Y)%{Id(awQen)WiPbqsJ-qlcu-;MrB^_=ZwUSOVqo$&_JzUEzT%V}U% z!{OHOPh$BzJxR&Rua;W41&&w7JGgKs(hK7f6ZD?)$G~SM^9kdv4Asckjt7>qsb@^$ zhAu;R4J!0q*4nwcn&$WILHmJO>0hT*ZUlbg>^wG|G9d-Bzehsx~a9q<(eLVDT{>$BKxTo^vX^eBnrgTG@KrWe;lFrQg4C%QY#_Za>hs4<^O`!mzu_cZ0Xa3pCZ8vmbdB)@(XnYC#{Aw1*h;>Fjg}-DH%qUtvCZPc z{z2Qg_n5AEPjT2mrWwYFo+r2B9jWMNTCNq&w0UvAtq(4b^2RB&8x8_;OfvAzNrx%= zw-K%a{h*^OTb%8kuWiX#KJ#Hw5sFNKuhq8DxYq9)400&jclLwiSK3?+e>L9);K>dy z-Zhm5lmE%|Y7=rmkg;Er<`F>_oxW&OlOJUhT1XyuDK0HfofYLjmiO)R-yQUCN(jpi zQ%W9ScGyJcbR~bgq+@wqY^rlrNiUJSzLfTviB~eE?>qI?&byjav1LIvWWv#>55FfXINxwbfX^5QeL@M9&;6=`yY~q|0=x{@kU!#9k!=pn2 z90@@UBOI2$lRY`$heR6Z-)b7LG)JJJZ7}rs>k0g&M*LUms#@yk$;t#MB(N=a zEVdwq_`Q)C$G4wst#NF68u(hWTrWd??zi}N7UV1-OJaSI?`At?6Ib5VX?`7J>-Y-m zI_~N%=OBI+{Lj8H1sqAWtRO9jl=ny~{6Rz$O(9Nyj1Xo@&yJ~-JNPx!yG4cFfL-+?YwmtNDvtuzEc#d!#*Me zDJeZNCBtgmem5QfC<|;W?;9WpeV+$xI zp$wtJpQBP|x+FoC8G#QDq9OHMd+ANJsl*l&=C_^m@>yKbyXWSrE_3p9gl3CTeT>!B zCWH6d=Gh;kt(s;c)l>0fV$Zzk@4~wkn8&=xC_ljz^IK^wMj3%5HJ^oJ!1;DwHAkjq zGB6Ji(4(c+e+avM#!dG;Wwy=W2cT{fG|#@auFMWJ-2Ab$Z`H_sR+NXhnZ!u^Yakvu zGM1(j^b*6F9UZX>jtcW5L{(VeVNHwVeEh3t%)%Y~G6S;BPy7{cnBZ)b~76c#0A?I6Ps9BkK2o;i16cWtsaUUthGHhurDqG0PQI+am=Yr1iLU-!}Vy7rN0KILLGgUV&+z-y4ON2?SU$uTBG84COGVjzW8 z&gQSC3@rb}@3(0lFKr?ebY7Y62)(6GX^Uv`@8oU8PT*|U=wln6^M2IKhzcXRL zqf}9m2U>B!F)>-$=mw!KXderKvmr&COR|M-SEOxCnO5DBGDCOTq3E~%)B>;x(Q}~d ziM~P6>bUzj1`Z=S*j~d2HakjmTwH9L*G7z@{ptlt#S4ud5{mS(Gj_4o)?{V=PfRI+ zEj8xLzn)<$K7)kX4a#cG=2R5fvTw38)6JQvElb1D@70m3l_qPW0%!_C;aW2;+MoL5 zjx3&-JHEA@TagHJfAE-oFTmqG0IDuVe1%KJ)f#xVi~8I79QvIIgdb<%fhtm%=9@(^ zS&jU~8|9jFlVhCcUqfJn7r{R#68(#ek;f5khwNt9@% zbXvL8ce5Yr5Eq*tAV$VamO3q4T9NC#>Fqw;F4YrQh~5Uf>wmiXV3>SgBA09GdLF#V z?;bL zam{4gY6;w~?Yhkaqs7e#lhfX)YO8;0q!HX{uDvkug9KAx>IT38pyK1U)VYN=HF9fX zhr8ADB8_T@$T4K@l10zSg}c@pCIqN{KGHlq#E=|Zgbj%RH_Ua)_dtRj~2 z|Le!SN@y8Q+fwUyljk@?d$ZshW1H^6VN;}<;k#uSjqKWR3}YQ{-QNcI&|GI9n?Rx# zBjzAx+5=PN)20g^4ImHpUw^HLusi2OvfWX*%FiF_)P`jtOctXb+lUr%1kX|6AwxWt zRCwT~JP8l|^1v8Y?d#*+_r@OGhmY3XVeQxCv7rIGDB8^a0olO{+4kU&!A52_v-;GxvlrD$|5WXi)HRy>vTkzm4_7Q={lM0U^OHy+8^NX6Dd&2p# zq!j*{HhV}gk=L>6Y=&1~AqnCIO{y7nhSkd<>L=xForz^~PgI(i4#o_C4{8UNUkH+1 zB?SE<>=v8JV7bop^aQfd)6xC@8lU$(`EajcrQtC|hs%g*Yc{4r0SRrvU_pH7>Bg5t zgy?PJY*U87%9+ue*?V0r@ri@_B}GO(R8Ny%l-CDv;Op+Y(*S9!-D%2_|DY}%g-^^w z&ds6;CUz5*DAS~$UX~Ut6~_ftP75}Js>$czXx6L%3)HFa*~a3(6)$j{B_7ZIjO^<2 z2gZ8w*UG@G>1^C>+hw*0!7H}(scjjf^7g2vO{jKHb6vxu{-nsGuasgOAN^z9sSr_} zxyDN_NG`YYA~SJmab1kkmY3qZ`=6FF-iFlQnwjarVC~G`p!XA4qz2{_0xpYj;z)qq zSK^d08W30*pwbbSQp{E$zJp)Gb&f+9%%RaAM2 zN-~K(Ue|$-7$wu&bJ>G3w)U%!&~|!k-N_pZ6p!KZ4o9~u-qr4am**9cDbho4UnLyc z`;N?3(g95UdTgv+@_KO;S_2&l<=DG^ zipua~8`q8KI`(#G)|&!rtzYa>&ttGaxW0b#LfsEko+n@$Bz$Eyq)N+mQgGXzZ6pzy zMxu$T%pbbja0UlfHVKo%DH}d2+GDUWC&^F$;?V_R<|nYO+P@G>mK6W)jxrIQqfTB# zGTeE`&d2lm)pS#a!b9LxZMjVw$}sp&M|}6-?5e_ION2_h<>WycRjO!{FE^0VP7BzTEKNiH(W1UB<9Qob{ zJH3egLq5xL*U$QM8hF=D&iU7%jP+PhI#DrdVPT;N9>aj1ykXUrU`Yk3_%?=RsqRRS zvh_#woKh)>o+h6qfO7sO$wN`Ig;-&iR$fAjedVqTf7dkX3PY6NigkqL@iOGdT5N}A zt7ec|A~tfHg+s!b7-GT#R|M^nNcM!WC~o_2_$sPtn}z$x5DK833f;Y&z7HNtX`^AR zN#~8x0oPY3+~xu6Cm&q&&Evu+eFM&emCD^PlmwTa?&NNM)H9f+h|=-dk{;JSx*M`g z26+fM1-u$4651718NqbKP4UY0^LcU?lP2aabIhrnl+3vubS`H#3$2%{u{e`w<1LrK z&+5K1N`1V%Jc^ua3e){ou1gfz!a;xd$Ua$*8%uj&LV{D1lfEDED!TvKw! zKSe2{L=eR6y2aC274ivruM`h|{~%P1SU;8+r}Md4M6UblQ(*;Sgt8ikSd#EEkQ1#k zUD2IsTX)SdafRTg!bFdBp%(@zB3;_&FJF)=OUqbWHNFyKux(TOzdlGwGTc{chz5m} zN}(nAU)CQKlEeGDT*tQyTxO!EesqrVyXjDvlae7r_XS`oIq9H3{WO)|-q$}@eJZyj z4(lQh?SW-dVn!lz;>8X%hfiv1$~ZzrSq1u+ek*^n2!c40kj*3@5{q$vrR(qa%87&a zAr7w@8N_%2kmEe07=WN77xNqa{=FI;c{(jc$>kSJw-)l)h>eXn6o6usRHVZ+#i`{5 znX%X>V;D1gZHE&E$h~v88$uQ3MQ`!zWzX#pW5W9cmrLeF7pt)b949z5?D*tdKfh*D zCZTjCtLPpW_X#D;H|2FzX3in&#idV$zgojVjs13^GWxe776TB+%aFKJFJNip`aj`x zlB8iYeP3JNx>4f!*+vy=n83)z)ztEeWMNTsZY*2-h7jfwm^PPG@8|eEFR=>PJLseI z#i5AI3r#pm$6R<>6HCYjLD6P5-@*yi*7uFTR94X!a~}cx&gIg_ux8Wk3+c(n1m za0{RsHJQd$6lTgeowl9)1`y>(>df0!4Zh>Bj0&WZ9g}^Pur{#FhsCnDcWmSZSxTH& zpW+mqekHd!_fsDW3`EH+_*Aw+pqyCx3ly}%&AV_UNZq4~@Pi;HyQKj;G=w&KXzT;h_wH0B6~<= z&IB~hEZ>Iy?y5Oq$9iLGC2fADHKw_l@qR?aC#%%|K|tTn2!FNB`%Tv=63zVhm_l1j z2_+ud`a}%i(HftW!Z*T=$6ze8r#rFOWsB1SqPxW+n6)V~%!Ot)qMxhRlnTnTqe=>t z+0>F}3wHJ3F-`rPUm zVJl5amA{Hx({*WJ!znY%0OySyKT6N_0DI(i>=U0gy+yi2$cbZ@Aw)3lqv-LY_g#USsuPMXWhsje2G$%m3%n`MRl zM;cvcoQlT}uyvK0)NsoeKgvv-Jrwnw-0iHWB+?V1uLz_gMOXOfOwOIRg{+r56F`CT zr!=EQ0|b%*tDF07(;|v8dM;lTsL({lpib zLO1C}%4OdFYDUrn)l|4WfVh`gLaz$&NWc(@M=3v_Y%M0*cS&kF+;+}@A$;pLw_2av z5F8VAt=}x}-h>0B*Apb)hR4-t$VCV$6I}_K?e3PH415nv(U1felNV7KMbgwgScCgN zU3I(1OPmc8`_oMi^pYtw9vrTH73m12csQ}2(``#s&+7?u1J0KkDy2o{^J0eysHoL{PBxt3_leX=PYcwftmXpU}m7 zsZdXZS|sY^&a2iJJGZnkGCdkC;`3@)S+F>WYM2c=J(soJ{JDJF0Qq8iadB0S-{JR* zcfZG65Q>Wl2nki+1&x=K^x3to(Rw~cW?4}o*P+Ws_kG7d5O}@BE^vBj{eC`SSkWz> zT7f?!NG4tWk?ehvo@Q|=^(Q3@_AVh`8jvbjYL|l!=s=eS&dXOEO}r4@hOABr-`SJ+ zwR29jTAKD{M{CLPC6x>^Ffmc8=}G}eXx~L*Y85jx)LC%dZMd}h&P-~36wwrrnuv25 z2=yOg-=zY+TJgofdP-eHu=X)z8|z7b5F%hJV9=I51v3)BX$jieVhq_}o9*KWdWXN# zHM$e)qElS8{XX-=$6#v}cjx^s0fX%z{~JCWzYiyt0zCB>Lch*#f4Zdeb-k0Bs&gSd z>~fsWQ93tV*;GHb^vh;uyJzW1Z;l|I3Hr4P{sG@_9jA9*CmM1fz&V8cSHc1xKs%9y z(F5OVYPN$gRtPIe8tfMRq+MKGYBibO>a<{EvWj$X>2{=-jai^Z1Dh`Eo+@gPqvMij z$ZEP31)ca{BK`tn!F}IkrY`!)Dj&{#ACkCnDzjg9J~-Py+8VujAzfWbN zBeO1|cH!F(Z(E%+5E|s^ZjJ@zkwr-EX?kyN`rMDIv-pGD6pzUQu9X~2PW?NGs8qk@ zCK<0*komaH*tFTz1r{$ySEO@@NQLOHvmb9wK|!9}N;)aAW@o_c^m1R&oH-)6ES z3M(WXV1b>o`)0-RXe(22Y(yMC?rA{MXUig~OkY`X{X3=iy3hq}c=a0{k2Q2ij@FoT zwSO=fI(6j6wwq@YVP{Lx@YNyepv#RO)!gC1RnTKY;hNJHhhku+Nxri7KC$ z?OQ9qt?1sff?`VQKITl~-iD3(xnUKUvU-o#pz+`_y0=2k62`+vK;l@rHYLg)xxwcu z#pH@%FOU~Cz_(GSR3-XwDe%~kgbnilb-(a+!Xd2{cgU{*|zyJpi`bW>3{MG?W zXWZ4Eh9s&~cYL0&{zGf&jj$`0cu`1wh~StXxG3yO3p)xKZk!)y5E&*_&|Au7C)n#5 zo&}VJ&AXY2W*$9nnHrP2L5zsBvVQF{Ai}U!4l?CfD5*y$+ zBT#Mn0N#~15xEoS$>br3db%**ds_6CHUIUQ3}fckg8cp?0gtUu#>eA#k0TVqx$Cml zTS^5C(~uPn9L_sPsnxJco&6Zk_F14#J_Dxju9+_AxXH)!^u=C@ROHq}R?KG&{H&w) zpjp@fJk@BnTSnL!2A3Z!`55%1 z3gik!B^4rJ`D|>3*Y^-9l~}f#99SEV6^R0E`)QA&W$BX&BHct5@hXFUFKS*{{ZY;q z4p4icIkE25ONI}(`$De|4cb341FYWE;SHa>uIM?re%sF1a<(shOf8O^@aF^oEDeFv zqg*D1hFZEW4~sHwET;=woafEb>P$xx;Q?E;5>Mxs1+M}3hu$P-SilzyQFvKR0WY^% z4B-*#K4h`)5QU{Xh4(3R+9`TDRcjbL=MQPlsQOsk-tQYTKsA#nViHX0oUBSz9GVt# z?kfd5-~EiD3UU7kb05E5(@fOyEb$lH-uVd(XMYKS|$QesIy7-)ztaz z(wUVUf|O0uBTJG@hr%c((6yd@9>l5su8J>CL;in>x$-oE=7_kRXNDTEvXs9?SrSks z7|~VRTN#U^Fo-}ujL@sRDSB(!euI{Kj6OHWd-o$Hex&*%cA-9B9Px;eBAzpv9JN!=Y-w_@5Q?X3`i)!% zhBsN`FNr#%mEhsPFmWiF>kkbI<~(^x4%5~+=4$_lLEJAdNk98w>^rojDj-Z7Q*Ck> z7ssQ0ti9^WGkTay(8lSLJMhWQ623692cf^0pRZ&pG|FcH9PHJfUL7DqB!fu=Owf$* zdc1K}Q1#k4iS?n`JlR4Elt>{Q14-~d5e2u(y8+>y~4=Uu0jw9^y^W!%U zeQnM4M;kQ<%o>yF|uguBT3E!->8mYW{l(f=Kp&s zGj-k9(MFnY%qh-E8BniXqA)=xnALr6#P+m6mw5&-#GA-!-PmgaAgC!)^Xu9uFnt)P zQw0HUt8`k>7|I7xd zh$LRik+$uQima8CB1A5$a5NBWDR_WoJpP;bXnYwv=!?N#@ zXa}0eRhSjk#Al+zY~0ei>h_()7mXPHBWU;YbxDc^g*Ix)D}@X}*I_@c-H4Vd0Sj7$ zUB_3gaaDYJp6iXrFBsNjwu@CpM;q)~YDAJ;kYsGv?pg$seaUB-P|1{Vr=zIy1Dl@a z;z0$~-;&?H#P>U@=u z=b_twhNC}XVSkhd#?Aj0HQMeCXN>7yB5Dr(^8f7#9{OCEK(XvEqAcq=}p!&SooVV9$kl zHFb&iNIE@!gmSBAh+kGaW3l3%2{QX_8#OhiH=!C%$BM(sij_T!t>8$bllb}~tZ=rD z15Rrjn_%@sMW+JbOuGKeY8Ncjt+M;Xxcd4`ikoMM*xl`1B72UA++z8X!tfM?%H|mw z38^eG&M$QYe%<3Lh1IMt^xy73hMd3g3ut=kOb8<)v5LWIkC-DYb(5yfdNL96@Hs;o z_Zk|g>^7rT5Tzq1Ha;R&8$dA_9BclIW&f|P=e)LcCU zy9y3A)>d)nGawP*=McQ)T)OR2XvFqg*3Pro@ZfwMg~^`~smxvcPONsf#=*ER-pCG( zglA>Mt|n3MQ?vEXX8Zc+TS?PDSsL|QYXw6y=g@Oo8gYKY^#Y~ptyp@Jk&y|!V11Y; za}4`O?5Fbz1>4RixKTbHsPtv(m+2d#8kp~|SnHke3TrkCh^Kc>jK!eO%ngt&ojnaV z81YX$UFgcAnO~iNh3qU(tmJe6H)HtoZRaSIXGO}+re*1|p|gGgN8;f!C0wQ`HRr_W zxKv`FwO-N^&M?$`%jf+Nsk}8+aj@e1p@YMLkr@($yL#{G9|4H5vX~@x3L31WW)2Mv zxRsl$-AiPMQ4)gOmNvgomlpt$Pp=3y9{5mqtZOOn694=;tDIbl9v~mp-z|03cW%fyx?FD|KGpL4V0VeR(#vR~Xi+ z-!MG^rS``Z#+k85|PX9*15I$xxinM;-6inSYQX zs{Oj?e}?rXXJ)ls_8+#T`Jt-l4ZwVS_n7bFaKhr8)5H@zMAdEa2XVvpahuR*r(z;` zGFNIZ=7A=l9iwI|Gp;L!@sw!(B=AfhqCqGx+Kyw1BRl7fb zxpeAyMTo62VY>CzkokjxF>L?9;W&@z{AAT)YLyN-V|?1+?wz93gl%~#HW#>V`#s3L zIjJyq(&z3@*B|KC98QQvLUD~e)_t9)misX)Dw}PW$yE_hb;?PQ8K7v*fDG=?v2s`z zS7HwlBNkhGl_8(LuF0xCL!WnF@g{?uKhsZIaFX|Neb=Gb+xkz`tfM!q!T%Q<-pv+- z?H~HMM1XvK^hz~(Vi`?=as(#s58BP-)Re0@R0>Ic$@{-o z;*Opq8DK~iCWfh9Y&%^j*>7xe`~VxKembhZgz|Q6)WKdxV}lyRD2M%q=ofIDcSKRU z`Y`eNsU&!{r6eZ^=u(K{R>EXp2@xJsvn!HHRFZULmeBC`YHDIul6=J}gvnCW)Jqmo zkerD|7{bqn18R&2ENn@t6gBqjAMw}5GOv&>(<)6r**Xr-_8fq2{*Ydd{X-C!Ua)pB z7#w|Bd?4V1i!*Ay&v5J+{D7(&?11+0U@B`d$7v_~-d?uf%D0KN4-V=juj});%sB`aYSG0R5%@{_6tAS3hv0qU7LkpyDpr5)wL5a2s*# zX)?9nk%^f^B19%! zmVvl#I}JVKxs8={;Tk1s{wg*&5*;6s0L(-Gp^3=x%qX3@N(Q&E%n41|*_ za3v)Zrjat0(;YvD$UOgizFM8O=aP926zfWWzdiX4IxPmh##U9+mjVLO1_(C^(o%3) zKfX?My}vGF210>9mzKt<;{<=i`QPKikr_Sz`Tcu1Q^oanx+_6gmZ5ec&E~VdTj8x_ zU8do*6(xCGgWLX>T%R-G<0-}QdV)0hTHAIm#t|J{yF{k(kNAk+F8Sxz&QVLSbvo^L z+W&i5INjI(ptL_COK5>40&r;o1AiAcTzdppGO6enO|+E!F#Eq~#qp&+Z|=6ybito+ z<@`t1wA;wBkS%7E22P{d{qR5KO~6F(%%G(ZT&)hpeU?bgNbO#9`&VpxP4;mc^anq3pF-^^G~ANwfB?@Oq$peh3$mbI1*mK0CU zRwrk9&fc-t!$D4|R^|m<^uqX$Xj3zRUOo|B^KNYNIg3PeDR4QjCbFo5oX0;;%_t?n zYm_qx-|oI)At|&lP<@t>?f!m#Zn)SD zSc(M_m*xMGP;ML^4`kwn^POVhlCzZGc_IW%<=LNRLp4yIWrA6PvO8U{`S4)LM0Dk$ zRHWX*cS-D7#PABEIY4P=!pMZVwb^9}+2E~RZt-+-jy~|l;K$Eme_WPSFj|%Q!0OBB zu-}(G-EUYD)dB`NGpxbo>A*C347fxzgnKt}7cO8^dzM#m_KM})n(JP3Kpy+`deD*}D-|L`VJcS1@NBhPp!Do#VN`uK8_nkeEnXX1ujUNFSYiZUcG z4`28nY%h`*9C>zg52?aQ0cUV>069yl+IREn%t^QqHF$uUJ&;rR6AvXMN`&sXrM@sxz<80YI6*DmD{CWN=C3&IevQMN;^<`@MKlTk#c0(vXrSgS?Pib&Z+I+nioz@g`Fg`;|Lpmi%? zrVPA&o>j-yoFz_N1pE`27bKa^5WK>fear}{sfHd#P1m1zcd-xM-mx#MGg4ZViLpsO|qGh zg*E&JLHb!fc;B%Yhpk51!E8$U+_A zMcizNJc@)ROBQ|J+uQqHXM!3jVJwpaU)d?qQN%7=oWF4y!JQh1}n!R6BCtFMNq zMs>gc;)+uPy&K?bJHP!u=ZgICJq9_{G7J?;I=J;>1L<@AJ+Op~z7MNu(n9b~78+^z zuXP#vWM_96PpB=uk^MDMk^5gW!jBzmo|})s*7_d4_BxRK=cZJV0-I2_rfq%SFij5N z-%fV@8e2T1WM@~Eq$tPF`0tq}yKh;v>O(YboohYEbqn>OBgX$J>d!M6&O*|%u)uY| zO0%nA@$Y@<-TE;$j5lN-x8EdQm~;Jeq6)YuJ_p0{K1mK|h<1;*YyLkuGh|121;m>D zum-}_c>kQKLQ-0!7vu+E`^>&O@gMc@hAS25qE(^`%oF|ZXUFu_v3(LDN&A*|Vb1Yy z_8d_I#zkzODB>sz+iormPhZ2CQEZxk5V@an-dz8RhM{j`%)0aF^L#iplQ*92{F}|U zV0>OdB#wm^B(*I4^WMxh5gICrWPNK9fZT0Y514}8{r3% zG`k__3K=RX|BUR%qvL9LN6jtW-#S?lzz1Q@DBLe}b91A<`qOq$KPHu(eoOImT5X7n z*?wG7LbrbES*x8G%M3St@RFds{TrvaNChSwj;knQi7S}@=Q{CkO=$jmWDZ;t{@;^< z{_ox9XKV7`BXjI{WgVj%viK9zQBRL`VBnH*;| zMMaTQoU-gY{J*L?AgS7PO^ZMV~JIko3zW33CC?zE!k|WXrf^?&x z!q6R(N(?0+oiie(Al=;{A>AobQbTtMNDK`FGxXfU_xtV zp1{}_AP>t`du7N;>R5RxnXe-W}@5 zUK;*G8@$Q?k5zzbu&ZORcC9Pr4p;a0EA4YGH%Ut_;QW>f zS6_bE@5HQIj7Z+sj{hF;App*>oLB7>OF5@yMZ5ymU_mRxdIyHe2mfB7 z0rP2ET`LPh8yF)SBfv)QYw7$AOj~^-aIce7!L0-eiM;Lb|6j7`KZfl; z7bYm}VjKGTb#9857CkrZl;=K7PbntT5kc}$N$x+|(Ov!wGc)cU3Pqwv!_Oze&6lx( zj}Tx7sOjQ4hFoBVPC!Z=cavXAMAk^vW6nw1%2ya6lEX;t$%z;XJv)$$Pi1PkgY|vg zlAr%#^5j=MGr1XuzMd;YY#uQTfv>G`GY%Bk{|2aC1-J#&<7Mppp}?qP!toqQsmbrw z_fpW_tw#bTiRX1*ZewOUu{OFh-TS z`EASv-eH}b^EJ!`|jS)9JB1J-u*?omU&13nG`(a)4 zML?Oaaa_QBr<(@6-qFcNuQz(cp{1T-cx``MR4Sl(qih`M^^rE@$8g=N&#z-#e;L&@ ze1kRC^}LggA?zQncSRP8v_0U~#ePmHt^(8nPxJ2I*9DISPA<^o6mfNxMeq&R27A@9 zI?n~0#i(Xr+~(~=LckOY`*mwRZ<{xN9<{cwdHI@))g^1m4Hgp~!OwFeanDnm4L$!P z%XPe`!UwM7=jP5OQ2+~7;0BzG&V*;x&M@-8qBMpu(Lbukr%F13;<%&71+&)b_-XNj zIf$kLGE!;5f9?~Gw}V@Uw~X=>T|yVG43!cd`6HQqkNwW))l_)EOVA;^f4`q#-)F#^ z(EUqN-ml3Cn$;!@_s1{EdFIZ*oZL)*s1E36@Amv0fW1aQ*5iX&Yjo_PQRb5seXziY z&(%Zm_#4EuC~6S+@&lMDEwEYubK79#=MVVDe@YAU_DwHO(g9QR`Kb0s_d+8pMu!(n zI|N&l@R+fj_o%l#8;TJ0A+eZQOt4Zj3|?HrS0rL%Ne`7iUwSWn-nK9-wfXR=5#Y0! z*&k>I6l)Yq6=ns)WzxTtv3nq(sJ3j02YI8myot-VM(GDFyxb|%(sO})8J;y)7}I!U z6JP0w5$&sot&aGD3p0~-n5M3E;tX`;Hmw&XWB!uT%j!k}&eQMBH{TNnhUsr!T{Wv{ zojD-m%qj)5Ta&YA2CZX=&h@hB9DEM-cJv)Ct%7YFd(0UQetKC6_JO**KX;3zh|67# zlBScs8au0z5(aouKT~|judI5{f@Q&Dud4Q|M_VY=_57^mD-`bi1YFZi6>Qz;1lG^p zA%4&ug#ArST|B)ypk5c=*V{G0ovI3!+;vVG&2U#?nPq}&vP^OpxsrnU#z*#Zn^&<+Ik+%}v`BoUI z-mm?~G#P8Sm33_NK5rC(_j=)gl_Iz@_>B#4F9N6b^Z^c))mw2nHtLdN1J=y`*S7o* z3^b1b5-i0GtoIT9gGH#&iCa(X?UM0d)Ze|_GOM%6`w$(f7vrMo1-!{@qlH-Ev*&Nut2%!SPOdRb~t5ZW*C46 z1VFf4HPk)<;Aw^Fg$cVv53%`nvX22bFR_N6R@Z$roEWGH+5@qlqtq@wcT;GJ$LG}- zCd#ER(r@oGM=Qswl1@xjo&;?2w^|TFFr!|BoI?pc+uKE9rw1`J1E`_Yv;F#m+;@cfp#A+#XeENeB{<2JU=k_O-XWmObWV< z*)WNJMOfNgkb}K70c+P4)qpL_Bpdi8Q0_%iOpY%?BiMppMH~p)1QXFbR@Tt?;*^&J zj%9o9r$`X}XDIIugd?v5czPcJiV>hhxt^$6aZF5qj57Wqb&@ZTM^XsFX2Qn?VruGq zczqTMkjDapD!KVgMx2~d=6nb(0c+{cHZ(%R|ZZa66{czxRONhg0_;^k2SI-L3tbcek z13fzNl^lCRsRo#HJA-zLf~g^^sqf$fZGEC3!CMfX0Fzv{a@|U-GFrq!lZHQ#tQ>fEODlPH6S36o06J3 z+vH~Flt{3i7bKhPkU~3eomrm(YdY{=GEIz)vpB68nMlD;AbIekEVqC%XZ;#II@z`6 zVbTR@Bk=vpn9*)`Z?c1qA)qIOclFv-wZiFb#SCfc4c!;6o&G#^HkTnx+w8v=sL64%SitF9@1G^0N#%^4%yQ06V%&CA?_DCG0!3D`7wUnu0qoSfuu zfeRE01@eAJf#o>ppU_9BYif7p9rHgO2<6Dg>d+Mj0$6=fsxQTHY#!6I(f#_yS}|a; zMThTnf!SEO!72nw`8y60Gw!DMQA)LPYOZ;fzeoz@jGyQU-6Jsp6plO*H9tS81D|D| zkT}3^GE?_~4zLFnqK?15&r{zzGA%qClWXl*U1Of@hU<|Y<6%x*gwsBe1^z%k-@G=> z-lAAuudnB3HEmDL9h>|40o3~0$0ay2AK_qUKHYW~ylvn&y|{1)x&LLoFZ_6$G)Pgn z<+lnoV|}g^_sw{!!BrxufCrR{D!0}$?~eJuH*nH@J566lgPRh0M@5dfzLD|8p$@r4 zdiu>i-)mMb1HLVZc8_5zMpzxe1v1yEoARN`(6y5|6F<#Gj2|$x&fg0Y%Q9H{1{<79 zvw!6erZcQ@Y?w-Z)uf-P&Rk^wzIUH2S-UT-it>o!5Spy3W$tl!2Z&g;iUIdh=EVei zKz9f*5T3_<>^2T?4CYANZA_MFY}e-lDfI%IBiB6=>+h2TVc?K zoXxg0RAi@}??l3f`)#KFfY-ESSCEJFP;evW<{EhcDo+VyuRJ=PH$Ez}u=UW)y|t&$?1?!}xhn@pLW zzF0%QUBK>@r#EDlt&mi8OlZ}u$Vu!T&}XqVV1W;*av`$dClgP|*7i%cUtR>)Aq;Q1 zbE3{VADx(;lyP;R_c?UaiButic3be12fuo?$LXq=-~9a(mM43NSIO9>+s>{JxYNcy z)&ef>e{EKJz@r(lnc)-R>06U*s!GhxLrMEc8dZ5Y>$_RCCf*YEika?a`@MrFp)Ac~ z?crkHQmge$-!J*d;9xnN&f*?+<;h)ID>XtK8*x<4;aka}D%hFyjGgO%w{&5|_QEVqZ=oB72vF)7sgm6DSsw$w$zlR$^NoN4zlo;V zm_18T4tC;D=7?nyupmh>S(HxXirVE_=JlnXs@ZPqXR2LEQw(z}qbbCutmF%zm zbOIWS#KD`NUG(x~m>DHTc*SL#W1uEG3Y!I7+4$onh5WgK`p+NBd0deV;rU#2W_EU~ zYb$>&j%-s~9!A32zimGk>>@XAJZQZt*GmgFT!UHY|`dBwLm-SdTUZTfvnqd&3f`JMXf zECLQT+HK}&>?J>m;nMcBdva}DssCY3U8gePhcHvh|B8DR#u-YfK~A7W&y&MJ&qhz8 zL5TpVE-iNA}CAkqN zyGyz>Ty-vIn%5PfB6(!mK~@!FjA@J}CM9b6PLqJ%69sHy&D*zSP`f_I8dK2HGz*&fL_EWXO!ptj;F#St?(^fXp6%S5 zTtWi7fV5uHTkM#-clo&+2!Sx@oo`Uk4!yz;QGLttDy423efUPNqGkC7@4AwM*&-f} z3(1~unvjQ-bj>#t6tNBI3&aWSM&O)hV{KxIh<#sr31r7Rp{yafV1xz!RvkP$GBX-z$64BIJg7jKY-!C9G1vnKa282cnRM* zVMDOWU3U1t_#TlDGV1G(EVbwkx(?4(2Kk^FX~`eudy`a}qoZGZ2Si-y)o;QC_)htO zq=M3&tiWRMyR-iA(wojTN_^tqEMGlH9Y!p+q&+_+lH$ppmbUG{kXI1Y%%GI5~&<`{gcgOS1G+WPy_cw<=`&-WFSFhq~`P^KZ4>EN-#Q^ zNT>^_%(?&DU&9>Q&35ZyTm{Hxl(n_B9ou)P3v5x!8!EiHH5_Ww@zlbVN2B4&Uv+Tp z9#h>`hT+Hr+{t!&t|MS4TK#k|Th5Q~Kv()ozT>|14@qQts?8n6VzzJ@vO8OBLR>T({KKKd)w-G>Rz>ht1dCpN>|;$L^-eF+pL>FktttT zeVSP8Jr_IC68ERo1>N5>C~>!wwBk4YFM^bEl%GZNH|BgRil-X*bRr#WkgHIjFEqWyDUo$-uDx7+6D5VLb7! ze$SqaR|+0x-C=6cO=NlIP;hu*7G#mvJUg99nBTN!?}&g0vmHMjN5$$ z(y+%IKo}avQ4mq9_l!Z%=&9l&tH@z^YIUVLq|JhTR-T&78@*TB?!|h)043w8A+!nI zwbjKTdk^F+TMxM)%^xf``Ip0_E-xwA|6XgpvP|ZY0*j9VI1w=@;K9TVlcx$(*{B-0 zNdroi7sZv&`CxLZz24!3xp5BL`F(-IWCc7>8X|@a2+f0sH=ld*vX-_Ca;Jb*y zk{>IjO|%aOQ~PF-5Dl63l-bxYeD-Fs863Av$;j>wlqw){58izuFVMl|>Mal%y!;JRPp{VGjF4qqmm!tduPp~fbA#)jC3PnYJpB?MOt9Ja>oFbu>(F1XltMYUxGc9P z2n*tZ{Lun_woVXh8#s#mX}WN@7)03|Ui#E(vMb5NK-JzkF6JFbA%^nrVI{$a_9N-K z!up7k{iamAn=_+r=eF;LvsXWH+c25)vqF5chh|JwE;tXK&=XJ)$aC;Kd-B$#XJQQh z-Q%S(*>O`?=H7HV-PSv23swR}w(6{^$n+mlEZ7^yLl+?qX0xR~c`}+3kkaSORv8-I zH45%$GaX*j)kh(Aq9XM}Zu&V~*it-#wQO6n?dc3Y-qq%l083*aAh-f#@}R_;90^g$ z5u5;N*P^2C+!loWLyujk8~;KJ${0AtlzhH0SRa{(AE12GVDrw*N&&qsr_vjx4aEJ0 z>N0!-$WIp3^UGUi-Sx;)XL83sb=`W-j_z#=o|m=`*Sq;?^-j3?uj3~MLm9mGT^_h4a%wds>E}hF+RXjhEj9ziub`Zq+0M>1ROe+?#g9dOmA#SwCwek` zTboYP{Wv%>ywqcvv96wHg>G2-XXp#|5__MG5ampf02+U$lYrCOgU$5>S_i+Y&C)W^ z+v$@|E`y6{Vm`4q#x_YA8PCKo`A<$yqm?1l!T5wha)Dt=MMXsxwl+yibr0(fF8POd zo6@p(g1T+aj)9DK#!pX*tyC>H{^poBT`W|4h)ArO4k7gkgkjhA(kDVmf_D7e}MT zu3 zH9AW3l@Zr7zl?7PB8<|6y+(rBYsL3pMKn zFrgS!n}~H(W=l`8OR(K zqc!CC!RJ7(V}F{KM?}EEiXj$-`_>{)`v+k5y>1 zKJs=5v0~*M_{!A72cFe?i;`WK+`Pai-}PpqGqMPYe2K`b+KoX=tnAKqIEYlN%k2Nz ze3c|!5_};h#9dsnk|t2_9JWDeTc}#VrVBp_C1*>d($EDa7D$hj|6N8tH3h;S0${lZ z^lW5`Y}S77fEr}u;U*aLORp)u^tdQb`!Fg7J4uO_77i*@km;!kYgJU^Fpv36<<-}+hgnID*Ow$WUUqxhw&tvH zfjt*c&TMa6u~?<5@_Zn~Qwt z7r~aLyq8(XVzU6OpU+y2rB29m_7l)94u_ww;E+c2yH8a&eb|w20%P9)F|DuUT9y=f z9d>@GS4Ht$z>#&Q%>_pZhdCFQ#a*(8!SoKtJ53nb()^?hW~8@lyvro#?9e`(NWGWXw4KROJ$~j~RK#z~9)9^p$LJDv)9!nXs`cHdqz=I~`!QU7 zl==d!A^ek2K#`dYpR~T$cDwkqI=a;f#S`LMH@3&{(Qx*HlQ zf3q~i0?zxBQ$O5i%+|*7=Ct(DXp4t*l{J`i<@k8_4nsCsMKqm=L!X4H+37s*=2WlA z1~9Helbb3K^p4NjVuUWL=Tafu#a@<;7=V~w8j;+mI0f=s83aNiRruIF&h*_?vs+vL z1+CEF>(t4##I0vK7FZlx6f5z&x}A=s`nTP3>Q%%Ato1cHBzB8M-}cA#tt<0Nkv}SHs%=;;y`&m&5b&>JQ(Z0zz>7#$o2GuCU);r|(sURl(4A zD_u$j##IkTS0sYCvDeqrAuC348-i;Rb_T6uy!wm3I3lM#RBYwGgvH&xG>xw2b@R!1 zwt9`kT`+|InhUjeil5eB;%!bAZ~a`Q{PYqEhHR-oe*g7rf5nlit>{*o24=1cb!%#V z*C7qK+wmWErb_zS1JQIKfXFyW&lOXp+7nf!<#MJUGwo61bVxy3v5q0BV*=>H`(gUk z%`q2^%*t8g(|t-3^XC?As9zdkw>&(jZYdss|M1nlPRK1LJHk%*%6g*r>w)zj`JMJI zVzeVG<E)WuLtavPSADyJu-0T$Fn3{x@!Rg+9*VBHMJ*t zJ&kVHQjU2Tqa~0{cH&0A8jiz2zY89VR~SoFj-~betme*n;wr9^(;U{ygEuR(^$T{C zr}_S86U;04=9KHsdv0SNv?vbK<8dVjDOppBWmrIX(p|$$V|n~7TM316f4NH>B}XQpA7EPD(#{M_rPc6{NDD&iyw>B76O7{d>m|qjbXi3|qm{ z)?eO6P%d)*SqxxHV=Tqv2>rG|MmK)R`g;Bb#e9&sMA`RlnHMZh>Q+%*%QZi*B>okE z+y4S80tWzE&Kn%Le%1ID3xSg0>-Ul!F((E7E!4K;uI<7jN)Q%K{-2*0jv#A^%4Ex} zLE$3htD!zsKPp`bInoD9ojV^>In}1KO&vLA#>H?bgFFyHJBJ(v0t`ha2*X8&ucCQPVmpWY9DqF{{~eW z+!sY(PrHokeOev63GR82AFq|9L6ln7{FPYZje|A4dzQb1^hX{#4=bE(0X#g}7vi(> zp+s&61~1@(uUZB4kLD9+rLFJu7-BY@b)goAEZ=ZsHmg>V9*5zPf#10g)I2X@POy~9 z_0#A+)kqF_INE$3dnC}0lUOUuq^P9C5&7n8{6h^BU0EBms`aHM!3zH2u2{0=OyZ%? zo@PlO%zmedt8)Gpj;v$fxTp$>4DU%No1y_Q1)7?SwGZ_FSY>Qs`BK9DpD@6HoF0rL zaUsSh@sMK(Wnnd={{6JjqiO@F@k69Fa{CV4j&nCR>>$Lz4+wHJ?psYsHAROSL1tvpMx`fF`wLqIT&|3wy{&!V!q8a>zp6}ghB2g+uI^s9IY0`=Xj zGRl6hPfny>cN3&I9%8ZhLF>O2aW4v3?qliQkf>gwbC)8s$XWpVp z@v<63&+H>L#9!0uryMxWO{(4}qp{4d0GtzGS9W@7Hn8}Rh0oT;B&JoOc=hm*x!Bv| zXoi$7m}r1B=vQ3aLxH0AqM%sN(*OZ0pL0S60 zc~u*TR!cU|ai|C`xbT2Hr)NtWpbU}iaggo_=%~vx$RehNcFY){2MN58rhIajJIP9& z1I#}6Q95=4!98!j{y}@wU}*b03+?&oo2s3GO$yE&7NXsjNG=Cxnq)~P<5ZI+MI@S3 zzW>B^WGr@5dK^p1K;4h>-K!CQ>RDGz7JwBJbP{r_{w&esbuJ@9o)gEJ-_i8EAB%f% zT#MtSugHrpzEb^{JYCl6zK`D4{kQ)Z`B|ANL%%y7>v| zP<}Y2BjBjZItf@zLPderACp#d4j-wJ$;K&X{Q6aG#b4gEdq^K>2x^NRZb5(GHg=<< z3n2)3PYwNIxcSm!nD5#@v}%}jGv{49k@=PwP)0)`qatLLOceE1BZd9bqeKe;BMwyA zpO@%g3S{MRL(U#0Q(nF$As@!#UPHATW=QQmkx<3j*+ul+#nserQ6xa@el6}#oL`?}#8%N5~2?=J3PG0A$}u(N9+ zG&YuL-ht0=dP}(nD6(pWs-bz=kZaY6%lw*OE9T;jt4E@dlE(@a`ePcQy`<-`Q2XJe zmRr7M;4#nB=dXkZ8$BQy(AUUke+5AIqa*6ag_TE~_1Waaaexr_;eq^ij4R`I&b7M8 zUb<9GZ!xEy$789>s^qoGsGv>8iR8gqZ z*K88R=RAM*K8wAU1)<-_a(!1|43IF1l8M!W;~&Ro$9}4Q;(c*^uQizh9ILWQPJcD zdfiDH8Gzs*t*L5VEAdKjbOb;!>!rkr)fMi?hwt97$*DbgX)6AT4JX?vSe-@jHTcWY z^$+`lL67B+v<_Z$dcG8FI@5fPPTO$^b4M4tOMa1KfGKHp6lG@h$Gv+nS*!bRhYk)2 zgPEOS%)CfzPw}6wSqaAX@Tywvi3vWBz$LZb%WLw`IKCgY{FCdAayUBrH=B(^op7!b zt7l*kP%BVUB4Mek5~CWd&+V>Ua`<5$C2^Z&W_Cm%^v^(EqZ!>np4F+n#=A4nsEkyM zNV9aSsQUEpU@>ZBP^j(0AzGWq-k&%2E^T1wMS%O-zaU29;b3v(c-geB+i zGT{fw2FlIyagJk-CyhM;np{(`-BSDGiWHl)VBXent~QDA3*XMcSO$BT5L}1OWbgwH z2{#y&E_C0F-($>$_$5;x<}G^lc|(=?uFLr2I?%__{U4^NRP`s(=ia<$l^DD!J{8+5?Ck z5X6zqK58+QW%@!%r9sY_(^B&#M}c6Sl_~TW)2|h$eIwkb)@nR7XIXuxRzQkswjp4h zX_R+S{~x=hxcy2`$yWcIK93$hzcor+4&N(c&?s2M!_O?U(=~~$QZ5arN14@4()y%d z(<5Exm!S!#ycYAeOjYKU{8-3@s_o+e1FycIG{CcIJ(?v(hgQplddKLQeArxoU5Jt1 z08Ay$2afqR9+z42*zbjaB`us!&zx)6$U|CBN-X?h_S}7YWpWQM$$fg*=1k%75>UzY zgo;~|OZe)Z2)L8>8KpOn^K~_}=;ckfUGq?~K0cU=^G@5e>>oQBuA93u%LLiSif|xL z%+HwEF}S?qWqd&GY%IU*-4gD$&_afi`WK2~lNh=3pU~cVIB?}UQgH$S znxu2ckzTdgxhB?}A$oKoS$vFGBDO#P8nr9}lBCCdn=@>%Bc@cxtn|{!i z%YD{aQr*rbKC`sYvme2Ts@osHmHk-nY+To9GU6b4Fz8U|Kz&h4F@^XB&E{qJ|OJ+H`ap=;+rRjZrko$Sga12_IQ zPubb~63h1e0!6N@l`fwx&nX{p@#3a5Abg0u=E0+0Tn(oo<(1d0NJ)lf2GklX5-5qtIW4~3cpJ75F%Y_d{Vz75H)i|X1CQ}0@P^?NM;PXq(P8&M&@HPP_M@2Wr=Q>+V~eBiVxx#fZz0;fBDXed|0nrlgli}~ zLaycF&3!`;;_KPE!T@cJ=QR7~J0tN%*xxVL+E-G%UU10yVxZ9Jg z7O&k`_@qV0EWR6>ML_<6DTj47jw9Be-K2kfh9(jSiaRtW;6By{)Ur@@6Cz*7%P6Yx z;4RZ^B}E0|qNKsR z0axvx?OBd@4_d+A{xLE3cdI`7WNdV|pj~#-2e1^-u7~|QJoa`DE9fDNDG=k!oi)@fqVI}a=XFEKwlK*~f2i6*Vz?nRYW^ncwAMs}C+ygV6OxsdSI2gW=nJkSFTBWa zbl)4U{8~jN%C@)YgWb~>h4chI|m0iuo1!3f>USl zcrmEP@ACfneEW3@pS7%zjkSX2KHQj8_vDzyQ+l3Jr6-f&eO!u|O=@D^L~QLe^yy9} z&E@f|_9@2Mobe29MgkH~Av)Ro^Wu0$YNyJk7qRGgAdp&xYH#5x0jc!or=*F%S_ZTx zi+(5_@21!<{$tnr22bovn9dCvTWatmtRN!`$Vk{4ngZ$0sgcH`DEk=s7wqRZU~9#EquBO{B~q z1zx1%VagPj^R<-BZ=@PVaxwCXgAR1AA$+qlj65k9*)+^-6<6Xi-Ot!Ne}^l;7nN5a zJtWk(;UjD{@F-i`Hl_N+Ph|7HsUP3sup_*_&0F39x@>8~z)Ys-=+TC5%wVZC;4@*VBPAQKy6H+lhv1j*Oq_x)s{>nEb@@l-7dmDa(CEwc6SGfMM}l@ zvfnS?pk)5e1HZ)t7OxuZRkh4DpB8T3>^Ki?f)vrQ^HqC&`=#yXZqg#~MtGlM^1Qpr zh8}BQL8*zC)|7M|J2Nvv?e#(Ij`L1<$++>ebUxqGt6iMN8=1wpW>^EOPmlN}&4(r3zBuE^PF%A;3lw)SttmD%_ymB3qK#PZFnw#%W*s(r51 zVA~UxzI85_Q>yk%ssp2FszhEjy#YI$*O)21V>o&_*$=rr?vW+axP`j<6HVtb3-*5l ztGm8d@!I^68dDr>M5k9MLs z1c}FYg6SL-T#!jf?TC_k^otDd?IM>t$cRNyfn!^{4CWyD$aXR9^}7G=Vw*%WNjQ<0 zjE1?L{4)c-eaC$Y2E>5CaI3Q<(c7DBiK>epnZfxtgbI;`?IKcY?wdZOKl%V((n)G# z+MKJ=M9S;hzRG~|ztg-Y>w$IxiRFWn?8b}YF|BHnS95n+a&@LHH4K&JHdT+`;*xC4 zF1Mt$^`joRJp4<%Io$UOS&40~Wt}n_C@U~%kv+m=C~;i9L{JbYE;ml0`i);Qplex3 zcXK4$yb-k{(`O8Ga%M=oF_n&sG;S1MECOGyCUDbA<2*`kx>;L3^KyX6cN6seOek&r z8|e($Ti`a7gnWmpV*IZz%jCpR`^{A!(^hl}Ertsgt}a0Xk%seQv!2{O9&K^y@=ea; zB5kSj%O8(-k`@kkZD1EK>O_P#Jst`Xoj&9xwV00Zo0X{G_mDcCZbW&go_<9aZeE%W z)@B+dW=!N)yL24tbbX}X8z^@_S?2-f(oqKr@64Q?W+x7UPu)2CwZU#=v(;a=7M(lo z8@E+gor`9ZDQAu+8}FLlteXzc@>zEQ13(QDj|qVt8`2g^ibm;~A_lmwd->H>6$94e zN=nA~APx_QO41eOm!^s6`@`nZ5R8J}-n)TisW+tSCsy+wZ;Z2OG>kL5(|K%Yl9vSK zT4AXDy`g;^`9f*ml45a}jiDj0q44B+b)lQrMTF+T>R`>{z8v^ejYwKQ-JNe_gwN-+ zBm02ehSMc@!)#+zGOreBBDK_FZXlWcb1WgaN??bE0!D0aXpLrjdQ*< zBF9n$&#Aj-Q?%VT7wO9}&B$>_gEqw_8u9R~1prJ^$CdW>fH>G3VM{uZ{nInXMl zR$cUyZtR25-?S`zh_0m&ZJ2`6v%gIzd2C^Gn`-p)%(*u{IyM1r&gFR5qTaWg;csI(!<^8^fAG0P-*=8 zySIj*#VF$CqAL+`vSP&#=H_$5jspiKzDr;I)q{g;dAF^H4tNY>mRs|f9UCfm5?yQ8 zbCA^QpIO74UqbAjA#4Z6!o-h*m8c=-RjdY38=q$mc8W;OyRu+SDF`%y$B^F@l#Ai{ zK!J~~9IGYvtnPcHQnE=n0s z3)|3fCFPv71YaH^4bIDa&)Ulef)6C)gzBMuTsK$Q*;!UEJHMB8=MR3Mq3v8k>P@fX zU_QvzrRydKWM_y>W4bruwl_9fq9Y`9+zgy=ybKl&WreS%W%?~a`sr>mO9@gGl5a3= z9}v((xbIni{br|!{qM5IA%i+kla#0J>9sD-eKGe8w5wU|q%Tmw=E!bSSBGEi=SNd- z`XjU3Wm@O!Tin}C7vd%a^LDNhYNpjzSc#OiRDc-w%v6 z#DYf@O<-$^Y|-mI&39O8F>+mr;Wlj&b!=&1R^qiEU`_wgXx*p&#YJON{d@JvYDCLN z1aQJsw214o!5lH6Sh$3Sj&b~4Q;MMQM4pYR@rKZ(rHT0mS~^=zQ^WYVzJ07u%i^8A zR!PgK!^#J}B%t5r9-#i{(!sr*_NblZDK|wSS8rG&lgILLQK=7qk%P4=#LqOt$5N-Q zb{$pvh>GY`+8we48^S?w3gwkliw(uU?E7+TMuG-`F+WEL)ZKLW^`GTuS3ZlUZg?|w zuvjl6<<}b%ru%m-^Tyu68*OPL#Ti#TvYh%s#!qzTz%aHp@|49*r7`aZXSlg!c}H$Y zH3ZYKy94@dCMG8kZtV8@Au%4Uyt{OC2#D^Pm$6Q|n2L(Qf>CBLrx78&q&LeY3H{(r zfV_*v7Q9!xxJ=dDPwt_hh!u3P$T(f%xL?WZBHrA!{egxpKNFO6T=>hdlc&ibaUnDhAoneE6WbeqQ@O)vbk=_Q3& zVMru)3kea(Trhit$fYb$793+9f?O?I+65^%p9?ka4VMpHF4qVe^9&V%uBl-#*hSE?;p;zwD&uc18c{ls&vCCJMH4ekAz5N`1=? zBN4WP-R_SS}PM6~dOKIKsS+j}u;Ii^q3 z1M(84aQSAFGJ9!Nj=RclIPOxWtA81V_i1op0Y7QRvP@W5kLnt_oh-3JDxvKb0PIkG#qszrcZGH2%&I+BbLYnxp)<1xYaKuw@6x*svM{i13m_cN=GI|!wA=r6x zqT(AfrXlmkR-BJZtPXoT-)CT@zkp(k^X}jq$F>^VUm3E)C5^fYYX=X~V!bceFu#pd z@T_wCB0gX|(0_a7Ke2d0(W3v+ee6>a@Ua&+y%*Qw0ib8~s4~7zTEhpn^ z4csh0+^kd+8=PjO^sA`yjXsZ_{ZV7q@ypqgd9$v!Ts*F<;7Fz}{aUEe(oWv}RPCx8 zFNt$*2k&@@t4>ci^G^m(ZKFp?$>q-pzjdt-jr-}yr>SaH<}fh{biCG6*7X&wim^ld z>aPj%&@v;&*8Pa<^>0MFbOx=0+dw5;<~G5!(1|s1J=blz&mvEa9YLpzY5i*v3w38i%bfzX zUIW=zM|-@w!dhg&ly8Cb7~%7CY&Vu?)l0z(RkgWQG-hv_JkH@QMP944k29ey&q%M| zJR(sx)-zPeF!Fh4De&T-FQApyHG?n?95?ycd$?JSgO?_Ny&xOj`$*57JFf!+{l@3| zXWX4^<)ayVzPH2s{zf-Po0NL@2zQir&;)^ms%qIZ-%Ed!-#J7W zgO|mII!6n9Jm+1d+YwNQpA$9HqJznvE z511OwYkE=qEIrLXy__JI^1$T0d0L&nJFZ>VKi#%ry1KmlNvHkbMq1PMvWil4=)9$n&JoI z=T&R=e;@B0iKP|G%xaexk~#HAyX?t!kn!z&SaRloxi32a5VR+hDV5@>{paxhPKt+V zz&^+!P_0-s856x(BB!@abGFXuCUQTy1qG3-ZITT~FVSYdeb0I1pQd6H zS{}){JWa)d&)oYUblzV$cZ?dK<#Jr*PK{W)KYSov&3FpApogCv2^b-ZC5!7Ff_-*@ zj?Olt8;x;#A^nQMRs*z-UZu&kJ%%EkD+td>iBXqQBWb#M_gWRx@>7KC%lRD%x$WQ5 zGp*}R8S{REQji8U0Uv@OE78v1pK`VlTmYhLnnoBm&5gQd^6%%mIoI0BZ*=4;^7v7l zcd^Z{nIyfvavqzN%3N_J`k-1+;%q(ue`zf_m=mj|El{@lg`Sp}DO3rQH$H(g_z-Ph zG}LNny3FMO2%35PAggG@1kjKWHR*SOyMu3U=d%!0uBNuUwKI-|^%FrxIKEp7(6W_^~ZE$~#_OmFRHB2kSmf z3~>N9oBI3DlQXn6&8Iqj7@aB5ckDTz5kCCR0+hM+vDZ5yet=oVLx@-v(VEhKxgZAF z!W2Q z&!03F$~(X-$74XmVqv|&{?Gdg9Cv{~)nEKyf*LrQ_32gwV`1Iic%axkFSIL|to-*?DwA2aZ4)mLS*W}p8TJx_u> diff --git a/claude/CLAUDE.md b/claude/CLAUDE.md deleted file mode 100644 index e70c0b3..0000000 --- a/claude/CLAUDE.md +++ /dev/null @@ -1,113 +0,0 @@ -# Rules to Always Follow - -Below are rules to follow with everything you do. - -## Communication Style - -- Be casual unless otherwise specified. -- Be terse. Give the answer immediately, with details afterward if needed. -- Be accurate and thorough. -- Provide direct code solutions or detailed technical explanations rather than - general advice. No introductory phrases like "Here's how you can..." -- Value good arguments over authorities; the source is irrelevant. -- If your content policy is an issue, provide the closest acceptable response - and explain the content policy issue afterward. -- Cite sources at the end when possible, not inline. -- Don't mention your knowledge cutoff. -- Don't disclose you're an AI. -- If clarification is needed, make reasonable assumptions and note them. - -## Code Style - -- Try to keep line length to 80 characters or fewer when possible. -- Check and fix linting errors. -- Follow code style and conventions already present in the project when - reasonable, including choice of libraries, test frameworks, etc. -- Break from conventions when existing patterns don't fit the new context, but - only with sound reasoning. -- Respect my formatting preferences when you provide code. - -## Code Comments - -- Respect existing code comments; they're usually there for a reason. Remove - them ONLY if completely irrelevant after a code change. If unsure, keep them. -- New comments must be relevant and specific to the code. They should NOT refer - to specific instructions like "use new X function". -- Generate or update documentation comments for new code. - -## Code Quality - -- Include robust error handling and highlight potential edge cases. -- Flag security concerns and performance impacts in solutions. -- Suggest appropriate naming conventions and code structure improvements. -- Handle changes across multiple files with proper import/dependency management. -- Provide test examples for new functionality when relevant. - -## Technical Considerations - -- Consider version constraints and backward compatibility of libraries and - frameworks. -- Consider build environment constraints and platform-specific issues. -- Check Makefile and similar for common project tasks like lint, format, test, - etc. -- If commands fail due to a missing file you expect to exist, double check the - current directory with `pwd`, and `cd` to the project root if needed. -- Do not execute `git` with the `-C` flag. Instead, verify you're not already - in the target directory, then `cd` to it. -- When investigating third-party libraries, use deepwiki to look up information - if available. - -## Git Commits - -- Prefer conventional commits format (e.g., `feat:`, `fix:`, `refactor:`), but - defer to project conventions if they differ. -- Lead with "why" over "what". The diff shows what changed; the message should - explain the motivation and purpose behind the change. If the "why" is not - clear, ask me before committing. -- The commit body should start with the reason for the change. Technical - overview/details and implementation notes come after. - -## Pull Requests - -- PR descriptions should lead with "why" context, same as commits. Explain the - motivation and purpose before diving into technical details. -- Use conventional commits format for PR titles when the repo follows - conventional commits. - -## Dependencies - -- Use well-respected, well-maintained dependencies when they solve the problem - cleanly without workarounds or excessive accommodation. -- If the work to implement it yourself is minimal, skip the dependency. - -## Documenting Discoveries - -When you encounter surprising, unexpected, or non-obvious findings while -working on a project, document them in the project's agent instructions file: - -- If `AGENTS.md` already exists, add findings there. -- If only `CLAUDE.md` exists (project-level, not this global one), add there. -- If neither exists, propose creating an `AGENTS.md` file. - -What to document: - -- Non-obvious project conventions or patterns that aren't apparent from the - code structure alone. -- Surprising behaviors, gotchas, or workarounds discovered during development. -- Implicit dependencies or ordering constraints between components. -- Environment-specific quirks (e.g., platform differences, tool version - sensitivities). -- Undocumented requirements or constraints found through trial and error. - -Keep entries concise and actionable. Group them under a relevant existing -section or create a new section like `## Discoveries` or `## Gotchas`. The -goal is to prevent future agents (or yourself in a future session) from -re-discovering the same things the hard way. - -## Plan Mode - -- Make the plan extremely concise. Sacrifice grammar for the sake of concision. -- Plans must include testing: comprehensive tests for all changes, covering edge - cases, error conditions, and integration points. -- At the end of each plan, give me a list of unresolved questions to answer, if - any. diff --git a/claude/commands/claude-to-agents.md b/claude/commands/claude-to-agents.md deleted file mode 100644 index 0c1aa13..0000000 --- a/claude/commands/claude-to-agents.md +++ /dev/null @@ -1,85 +0,0 @@ ---- -description: Convert a project's CLAUDE.md into an agent-agnostic AGENTS.md file, keeping CLAUDE.md as a thin @-reference ---- - -## Context - -- Check if `CLAUDE.md` and `AGENTS.md` exist in the project root. -- Check if `CLAUDE.md` is a symlink (e.g., `ls -la CLAUDE.md`). - -## Your Task - -Convert this project's `CLAUDE.md` into an `AGENTS.md` file, and replace -`CLAUDE.md` with a thin reference to it. - -## Steps - -1. **Verify preconditions**: - - If `CLAUDE.md` is a symlink pointing to `AGENTS.md`, skip to step 8. - - If neither `CLAUDE.md` nor `AGENTS.md` exist, abort with an error message. - - If `CLAUDE.md` does not exist but `AGENTS.md` does, skip to step 7. - - If both exist, abort — suggest using `AGENTS.md` directly or removing it - first. - - Otherwise, `CLAUDE.md` exists and `AGENTS.md` does not — proceed. - -2. **Read `CLAUDE.md`** content in full. - -3. **Review content for references that need updating**: - - **Filename references**: - - Headings like `# CLAUDE.md` → `# AGENTS.md` - - Self-references like "this CLAUDE.md file" → "this AGENTS.md file" - - Any other mentions of the filename that refer to the file itself and should - change to reflect the new name - - **Generalize Claude-specific agent language**: - - The title and opening paragraph often describe the file's purpose in - Claude-specific terms (e.g., "This file provides guidance to Claude..."). - Rewrite these to be generic (e.g., "This file provides guidance to LLM - agents..."). - - "Claude" (when referring to the AI agent performing tasks) → "LLM agents" - or "agents" - - "Tell Claude to..." → "Instruct agents to..." - - "Claude should..." → "Agents should..." - - "When Claude encounters..." → "When agents encounter..." - - Similar phrasing that assumes a specific AI agent — rewrite to be - agent-agnostic - - **Do NOT change**: - - "Claude Code" — it's a proper product name (CLI tool) - - References to Claude Code features, documentation, or capabilities (e.g., - `@`-references, slash commands) - - "Claude" as part of a filename or path (e.g., `.claude/`, `CLAUDE.md` - referring to other projects) - - References to CLAUDE.md that refer to other projects' files or external - concepts - -4. **Write `AGENTS.md`** with the updated content. - -5. **Replace `CLAUDE.md`** contents with just: - ``` - @AGENTS.md - ``` - This makes Claude Code load `AGENTS.md` via the `@`-reference. - -6. **Summary**: Report what was done, including any references that were updated - in step 3. Stop here. - -7. **Create `CLAUDE.md` reference** (only reached when `CLAUDE.md` doesn't exist - but `AGENTS.md` does): - - Write a new `CLAUDE.md` in the project root containing just: - ``` - @AGENTS.md - ``` - - Report that `CLAUDE.md` was created as a reference to the existing - `AGENTS.md`. - -8. **Replace symlink with `@`-reference** (only reached when `CLAUDE.md` is a - symlink to `AGENTS.md`): - - Remove the `CLAUDE.md` symlink. - - Write a new `CLAUDE.md` file containing just: - ``` - @AGENTS.md - ``` - - Report that the symlink was replaced with an `@`-reference to - `AGENTS.md`. diff --git a/claude/commands/clean-gone-branches.md b/claude/commands/clean-gone-branches.md deleted file mode 100644 index e993e3f..0000000 --- a/claude/commands/clean-gone-branches.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -description: Cleans up all git branches marked as [gone] (branches that have been deleted on the remote but still exist locally), including removing associated worktrees. -source: https://github.com/anthropics/claude-plugins-official/blob/main/plugins/commit-commands/commands/clean_gone.md ---- - -## Your Task - -You need to execute the following bash commands to clean up stale local branches -that have been deleted from the remote repository. - -## Commands to Execute - -1. **First, list branches to identify any with [gone] status** Execute this - command: - ```bash - git branch -v - ``` - - Note: Branches with a '+' prefix have associated worktrees and must have - their worktrees removed before deletion. - -2. **Next, identify worktrees that need to be removed for [gone] branches** - Execute this command: - ```bash - git worktree list - ``` - -3. **Finally, remove worktrees and delete [gone] branches (handles both regular - and worktree branches)** Execute this command: - ```bash - # Process all [gone] branches, removing '+' prefix if present - git branch -v | grep '\[gone\]' | sed 's/^[+* ]//' | awk '{print $1}' | while read branch; do - echo "Processing branch: $branch" - # Find and remove worktree if it exists - worktree=$(git worktree list | grep "\\[$branch\\]" | awk '{print $1}') - if [ ! -z "$worktree" ] && [ "$worktree" != "$(git rev-parse --show-toplevel)" ]; then - echo " Removing worktree: $worktree" - git worktree remove --force "$worktree" - fi - # Delete the branch - echo " Deleting branch: $branch" - git branch -D "$branch" - done - ``` - -## Expected Behavior - -After executing these commands, you will: - -- See a list of all local branches with their status -- Identify and remove any worktrees associated with [gone] branches -- Delete all branches marked as [gone] -- Provide feedback on which worktrees and branches were removed - -If no branches are marked as [gone], report that no cleanup was needed. diff --git a/claude/commands/commit-push-pr.md b/claude/commands/commit-push-pr.md deleted file mode 100644 index cbf0505..0000000 --- a/claude/commands/commit-push-pr.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -allowed-tools: Bash(git checkout --branch:*), Bash(git branch -m:*), Bash(git add:*), Bash(git diff:*), Bash(git log:*), Bash(git status:*), Bash(git push:*), Bash(git commit:*), Bash(gh pr create:*) -description: Commit, push, and open a PR, rename branch appropriately if needed -source: https://github.com/anthropics/claude-plugins-official/blob/main/plugins/commit-commands/commands/commit-push-pr.md ---- - -## Context - -- Current git status: !`git status` -- Current git diff (staged and unstaged changes): !`git diff HEAD` -- Current branch: !`git branch --show-current` -- Recent commits: !`git log --oneline -10` - -## Your Task - -Based on the above changes: - -1. **Check agent docs**: Read the project's AGENTS.md and/or CLAUDE.md if they - exist. Review their content against the current changes. If the changes - introduce new conventions, commands, architecture, or development patterns - that should be documented (or invalidate existing documentation), update the - relevant file as part of this commit. Only update if clearly warranted — - don't add noise. -2. Create a new branch if on main or master. If already on a non-main/master - branch, check if the branch name looks randomly generated (e.g. UUIDs, hex - strings, meaningless character sequences, or 1-3 random unrelated words like - "brave-fox" or "purple-mountain") rather than descriptive of the changes. If - so, rename it to something that aligns with the changes using: - `git branch -m `. -3. Create a single commit with an appropriate message. If asked to commit only - staged changes, run `git diff --staged` to see exactly what is staged, and - base the commit message solely on those changes. Do NOT stage additional - files. Otherwise, stage all relevant changes. -4. Push the branch to origin -5. Create a pull request using `gh pr create`. Use `git log` and - `git diff main...HEAD` (or master) to understand all changes on the branch. - The PR description should clearly explain *what* changed and *why*, covering - the full scope of changes since main/master. Do NOT include a list of - commits — the PR already shows those. Focus on a cohesive summary that - helps a reviewer understand the purpose and impact of the changes. Check for - a PR template at `.github/PULL_REQUEST_TEMPLATE.md` — if one exists, use it - as the base for the PR body and fill in the sections appropriately. -6. You have the capability to call multiple tools in a single response. You MUST - do all of the above in a single message. Do not use any other tools or do - anything else. Do not send any other text or messages besides these tool - calls. diff --git a/claude/commands/commit.md b/claude/commands/commit.md deleted file mode 100644 index 452b433..0000000 --- a/claude/commands/commit.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -allowed-tools: Bash(git add:*), Bash(git diff:*), Bash(git status:*), Bash(git commit:*) -description: Create a git commit -source: https://github.com/anthropics/claude-plugins-official/blob/main/plugins/commit-commands/commands/commit.md ---- - -## Context - -- Current git status: !`git status` -- Current git diff (staged and unstaged changes): !`git diff HEAD` -- Current branch: !`git branch --show-current` -- Recent commits: !`git log --oneline -10` - -## Your task - -Based on the above changes, create a single git commit. - -If asked to commit only staged changes, run `git diff --staged` to see exactly -what is staged, and base the commit message solely on those changes. Do NOT -stage additional files. - -Otherwise, stage all relevant changes and create the commit. - -You have the capability to call multiple tools in a single response. Do not use -any other tools or do anything else. Do not send any other text or messages -besides these tool calls. diff --git a/claude/commands/generate-agents.md.md b/claude/commands/generate-agents.md.md deleted file mode 100644 index 2e08c73..0000000 --- a/claude/commands/generate-agents.md.md +++ /dev/null @@ -1,291 +0,0 @@ ---- -description: Analyze the codebase and generate a minimal, hierarchical AGENTS.md structure with progressive disclosure -sources: - - https://github.com/RayFernando1337/llm-cursor-rules/blob/main/generate-agents.md - - https://www.aihero.dev/a-complete-guide-to-agents-md ---- - -# Task: Analyze this codebase and generate a hierarchical AGENTS.md structure - -## Important Caveats - -Auto-generated AGENTS.md files tend to be too comprehensive. Use this as a -**starting point only** - then aggressively trim. Target: smallest possible file -that provides value. Most instructions should move to progressive disclosure -(docs/agents/*.md files). - -Remember: - -- Stale docs actively poison agent context -- File paths go stale quickly - describe capabilities instead -- Each instruction must earn its token cost -- LLMs have ~150-200 instruction limit before degradation - ---- - -## Paths vs Hints - -**Bad (goes stale):** - -- `Auth logic: src/auth/provider.tsx` -- `API routes: apps/api/src/routes/**` - -**Good (survives refactors):** - -- `Auth: Uses React Context pattern, look for *Provider or *Context` -- `API routes: Next.js app router convention, check for route.ts files` -- `Models: Prisma schema defines domain entities` - -### Anti-Pattern: Static File References - -Never document: - -- `User model is in src/models/user.ts` -- `Auth handler lives at lib/auth/handlers.ts` - -Instead document: - -- `User model: Prisma schema, look for "model User"` -- `Auth: middleware pattern, grep for "authenticate" or "withAuth"` - ---- - -## Document Domain Concepts - -**Stable (document these):** - -- "Organization" vs "Workspace" vs "Team" terminology -- Core domain entities and their relationships -- Business rules that aren't obvious from code - -**Unstable (avoid documenting):** - -- Specific file paths -- Directory structure -- Import paths - ---- - -## Context & Principles - -You are going to help me create a **hierarchical AGENTS.md system** for this -codebase. This is critical for AI coding agents to work efficiently with minimal -token usage. - -### Core Principles - -1. **Minimal root AGENTS.md** - Only universal guidance, links to sub-files -2. **Nearest-wins hierarchy** - Agents read closest AGENTS.md to edited file -3. **Pattern hints over paths** - Describe grep-able patterns, not file - locations -4. **Token efficiency** - Small, actionable guidance over encyclopedic docs -5. **Progressive disclosure** - Link to docs/agents/*.md for detailed rules -6. **Domain concepts** - Document terminology and business rules, not structure - ---- - -## Your Process - -### Phase 1: Repository Analysis - -First, analyze the codebase and provide me with: - -1. **Repository type**: Monorepo, multi-package, or simple single project? -2. **Primary technology stack**: Languages, frameworks, key tools -3. **Major packages** that warrant their own AGENTS.md: - - Only for areas with significantly different tech/patterns - - Skip if root guidance suffices - - Prefer fewer, more focused files over many small ones -4. **Build system**: pnpm/npm/yarn workspaces? Turborepo? Or simple? -5. **Testing conventions**: Framework and colocated vs separate? -6. **Key patterns to document** (as grep-able hints): - - What conventions are used (not where files are) - - Domain terminology agents should understand - - Anti-patterns to avoid - -Present this as a **structured map** before generating any AGENTS.md files. - ---- - -### Phase 2: Generate Root AGENTS.md - -Create a **minimal root AGENTS.md** (~50-100 lines max, ideally under 50). - -Per the guide, root AGENTS.md needs only: - -1. One-sentence project description -2. Package manager (if not npm) -3. Build/typecheck commands (if non-standard) - -#### Required Sections - -**1. Project Overview** (3-5 lines) - -- One-sentence description of what this project does -- Package manager and key build commands (only if non-standard) - -**2. Navigation** (5-10 lines) - -Link to sub-AGENTS.md files and describe how to find things: - -``` -## Navigation - -### Sub-package Docs -Each major package has its own AGENTS.md. Look for them in package roots. - -### Finding Things -- Components: exported from *.tsx, usually named after component -- API routes: follow framework conventions (route.ts, [...slug], etc.) -- Config: root-level *.config.* files -- Tests: colocated *.test.* or in __tests__ directories -``` - -**3. Progressive Disclosure** (2-5 lines) - -Link to detailed docs instead of inlining them: - -``` -## Detailed Docs -- TypeScript conventions: see docs/agents/TYPESCRIPT.md -- Testing patterns: see docs/agents/TESTING.md -``` - -#### Optional Sections (include only if truly needed) - -**Conventions** - Only if non-obvious (commit format, unusual style rules) - -**Security** - Only if project has specific secret handling beyond standard -`.env` patterns - ---- - -### Phase 3: Generate Sub-Folder AGENTS.md Files - -Only create for directories with significantly different tech/patterns. Each -file should be ~30-50 lines max. - -#### Required Sections (3-4 essentials) - -**1. Package Identity** (1-2 lines) - -- What this package/app/service does -- Primary tech if different from root - -**2. Setup & Run** (only if different from root) - -- Dev, build, test commands for this package - -**3. Patterns & Conventions** (5-15 lines) - -Describe patterns agents can grep for, not paths they should navigate to: - -``` -## Patterns - -- Auth: Context provider pattern → grep for createContext, Provider -- API calls: Centralized client → grep for fetchClient, apiClient -- Validation: Zod schemas → grep for z.object, .parse -- State: React Query → grep for useQuery, useMutation - -### Do/Don't -- DO: Use functional components with hooks -- DON'T: Use class components (legacy only) -``` - -**4. Pre-PR Check** (1-2 lines) - -Single copy-paste command: - -``` -pnpm --filter @repo/web typecheck && pnpm --filter @repo/web test -``` - -#### Optional Sections (include only if critical) - -- **Gotchas**: Only truly non-obvious issues (1-3 lines max) -- **Quick Find**: Package-specific search commands - ---- - -### Phase 4: Special Considerations - -Add these ONLY if the package has them and they're non-obvious: - -**Design System** (if exists) - -``` -## Design System -- Use design tokens (never hardcode colors) -- Component patterns: functional, composable, typed props -``` - -**Database** (if exists) - -``` -## Database -- ORM: [name], migrations via `pnpm db:migrate` -- Never run migrations in tests -``` - -**API** (if exists) - -``` -## API Patterns -- Validation: Zod schemas -- Errors: Throw typed ApiError -``` - ---- - -## Output Format - -Provide files in this order: - -1. **Analysis Summary** (from Phase 1) -2. **Root AGENTS.md** (complete, ready to copy) -3. **Each Sub-Folder AGENTS.md** (with file path) - -Use this format: - -``` ---- -File: `AGENTS.md` (root) ---- -[content] - ---- -File: `apps/web/AGENTS.md` ---- -[content] -``` - ---- - -## Maintenance Warning - -AGENTS.md files go stale. Review quarterly: - -- Remove any file paths that crept in -- Verify pattern hints still match codebase conventions -- Update commands that changed -- Delete rules the agent already knows -- Question if each instruction earns its token cost - ---- - -## Quality Checks - -Before generating, verify: - -- [ ] Root AGENTS.md under 50 lines? (100 max) -- [ ] Sub-folder files under 50 lines each? -- [ ] **No static file paths in documentation?** -- [ ] **Patterns described as grep-able hints?** -- [ ] **Domain concepts over implementation details?** -- [ ] Progressive disclosure used for detailed rules? -- [ ] Does each instruction earn its token cost? -- [ ] Would this survive a major refactor? -- [ ] Commands are copy-paste ready? -- [ ] No duplication between root and sub-files? -- [ ] Not every directory gets its own file? diff --git a/claude/commands/rebase.md b/claude/commands/rebase.md deleted file mode 100644 index 3f49b7b..0000000 --- a/claude/commands/rebase.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -allowed-tools: Bash(git fetch:*), Bash(git rebase:*), Bash(git stash:*), Bash(git status:*), Bash(git diff:*), Bash(git log:*), Bash(git add:*), Bash(git branch:*), Bash(git rev-parse:*), Read, Edit -description: Rebase current branch onto upstream main/master ---- - -## Context - -- Current branch: !`git branch --show-current` -- Default branch: !`git rev-parse --abbrev-ref origin/HEAD 2>/dev/null` -- Uncommitted changes: !`git status --short` - -## Your Task - -Rebase the current branch onto the upstream default branch (main or master). - -1. If there are uncommitted changes, stash them first with - `git stash push -m "auto-stash before rebase"`. -2. Fetch the latest from origin: `git fetch origin`. -3. Rebase onto the default branch using the value from context above: - `git rebase `. -4. If the rebase succeeds and changes were stashed in step 1, run - `git stash pop`. -5. Show the result with `git log --oneline -10`. - -If the rebase fails due to conflicts, attempt to resolve them yourself. -If you have low confidence in the resolution, abort the rebase with -`git rebase --abort`, restore any stashed changes with `git stash pop`, -and ask the user to resolve manually — leaving the working tree as it -was found. - -You have the capability to call multiple tools in a single response. Do not -use any other tools or do anything else. Do not send any other text or -messages besides these tool calls. diff --git a/claude/commands/refactor-agents.md.md b/claude/commands/refactor-agents.md.md deleted file mode 100644 index a95fa87..0000000 --- a/claude/commands/refactor-agents.md.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -description: Refactor an existing AGENTS.md to follow progressive disclosure principles, extracting detailed rules into separate docs -source: https://www.aihero.dev/a-complete-guide-to-agents-md ---- - -# Task: Refactor my AGENTS.md - -I want you to refactor my AGENTS.md file to follow progressive disclosure -principles. If there is no AGENTS.md file, look for a CLAUDE.md file instead. - -Follow these steps: - -1. **Find contradictions**: Identify any instructions that conflict with each - other. For each contradiction, ask me which version I want to keep. - -2. **Identify the essentials**: Extract only what belongs in the root AGENTS.md: - - One-sentence project description - - Package manager (if not npm) - - Non-standard build/typecheck commands - - Anything truly relevant to every single task - -3. **Group the rest**: Organize remaining instructions into logical categories - (e.g., TypeScript conventions, testing patterns, API design, Git workflow). - For each group, create a separate Markdown file. - -4. **Create the file structure**: Output: - - A minimal root AGENTS.md with Markdown links to the separate files - - Each separate file with its relevant instructions - - A suggested docs/agents/ folder structure - -5. **Flag for deletion**: Identify any instructions that are: - - Redundant (the agent already knows this) - - Too vague to be actionable - - Overly obvious (like "write clean code") diff --git a/claude/settings.json b/claude/settings.json deleted file mode 100644 index 5b06c2d..0000000 --- a/claude/settings.json +++ /dev/null @@ -1,118 +0,0 @@ -{ - "env": { - "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1" - }, - "permissions": { - "allow": [ - "Bash(awk:*)", - "Bash(bat:*)", - "Bash(bundle check:*)", - "Bash(bundle info:*)", - "Bash(bundle install:*)", - "Bash(bundle list:*)", - "Bash(cargo build:*)", - "Bash(cargo clippy:*)", - "Bash(cargo fmt:*)", - "Bash(cargo test:*)", - "Bash(cat:*)", - "Bash(du:*)", - "Bash(fd:*)", - "Bash(find:*)", - "Bash(gem list:*)", - "Bash(gh issue view:*)", - "Bash(gh pr diff:*)", - "Bash(gh pr list:*)", - "Bash(gh pr view:*)", - "Bash(gh repo view:*)", - "Bash(git add:*)", - "Bash(git branch:*)", - "Bash(git diff:*)", - "Bash(git fetch:*)", - "Bash(git log:*)", - "Bash(git rev-parse:*)", - "Bash(git show:*)", - "Bash(git status:*)", - "Bash(go build:*)", - "Bash(go get:*)", - "Bash(go mod download:*)", - "Bash(go mod init:*)", - "Bash(go mod tidy:*)", - "Bash(go test:*)", - "Bash(golangci-lint run:*)", - "Bash(grep:*)", - "Bash(helm create:*)", - "Bash(helm lint:*)", - "Bash(helm template:*)", - "Bash(ls:*)", - "Bash(npm run build:*)", - "Bash(npm run check-types:*)", - "Bash(npm run compile)", - "Bash(npm run compile-tests:*)", - "Bash(npm run format:*)", - "Bash(npm run lint:*)", - "Bash(npm run lint:fix:*)", - "Bash(npm run test:*)", - "Bash(pnpm build:*)", - "Bash(pnpm check-types:*)", - "Bash(pnpm compile)", - "Bash(pnpm compile-tests:*)", - "Bash(pnpm exec prettier:*)", - "Bash(pnpm format:*)", - "Bash(pnpm install:*)", - "Bash(pnpm lint:*)", - "Bash(pnpm lint:fix:*)", - "Bash(pnpm run build:*)", - "Bash(pnpm run check-types:*)", - "Bash(pnpm run compile)", - "Bash(pnpm run compile-tests:*)", - "Bash(pnpm run format:*)", - "Bash(pnpm run lint:*)", - "Bash(pnpm run lint:fix:*)", - "Bash(pnpm run test:*)", - "Bash(pnpm test:*)", - "Bash(pnpm typecheck:*)", - "Bash(rg:*)", - "Bash(tail:*)", - "Bash(tree:*)", - "Bash(wc:*)", - "Skill(commit-commands:commit:*)", - "WebSearch", - "mcp__context7__get-library-docs", - "mcp__context7__resolve-library-id", - "mcp__deepwiki__ask_question", - "mcp__deepwiki__read_wiki_contents", - "mcp__deepwiki__read_wiki_structure" - ], - "deny": [ - "Read(./.env)", - "Read(./.env*)", - "Read(./mcp.json)", - "Read(./secrets/**)" - ] - }, - "statusLine": { - "type": "command", - "command": "~/.claude/statusline.sh", - "padding": 0 - }, - "enabledPlugins": { - "code-review@claude-plugins-official": true, - "code-simplifier@claude-plugins-official": true, - "commit-commands@claude-plugins-official": false, - "feature-dev@claude-plugins-official": true, - "frontend-design@claude-plugins-official": true, - "gopls-lsp@claude-plugins-official": true, - "lua-lsp@claude-plugins-official": false, - "playwright@claude-plugins-official": false, - "plugin-dev@claude-plugins-official": true, - "pr-review-toolkit@claude-plugins-official": false, - "ralph-loop@claude-plugins-official": false, - "rust-analyzer-lsp@claude-plugins-official": true, - "security-guidance@claude-plugins-official": false, - "sentry@claude-plugins-official": false, - "swift-lsp@claude-plugins-official": false, - "typescript-lsp@claude-plugins-official": true - }, - "autoUpdatesChannel": "latest", - "teammateMode": "auto" -} diff --git a/claude/skills/frontend-design-systems/SKILL.md b/claude/skills/frontend-design-systems/SKILL.md deleted file mode 100644 index e83f885..0000000 --- a/claude/skills/frontend-design-systems/SKILL.md +++ /dev/null @@ -1,139 +0,0 @@ ---- -name: Frontend Design Systems -description: >- - This skill should be used when the user asks to "build a design system", - "create consistent UI", "define color ratios", "set up typography system", - "normalize geometry tokens", "validate visual hierarchy", "apply design - constraints", or when generating frontend UI that requires systematic - visual consistency. Augments the frontend-design skill with system-level - visual decision rules for consistency, hierarchy, and scalable UI - decision-making. -version: 0.1.0 -inspired_by: https://www.youtube.com/watch?v=eVnQFWGDEdY ---- - -# Frontend Design Systems - -## Purpose - -Augment the `frontend-design` skill with system-level visual decision rules -derived from practical graphic design heuristics. Focus on consistency, -hierarchy, and scalable UI decision-making rather than aesthetic -experimentation. - -Apply this skill *after* layout, accessibility, and interaction logic are -established by `frontend-design`. - -## Core Principle - -Design quality emerges from repeatable systems: ratios, constraints, typography -systems, geometry rules, and hierarchy validation. - -Prefer deterministic structure over stylistic improvisation. - -## Heuristics - -### 1. Color Ratio System - -Do not distribute colors evenly. Use proportional dominance: - -- 70-90% neutral base -- 10-25% supporting color -- 1-8% accent color - -Map accent color to: primary actions, alerts, focus states, brand signals. If -accent overuse occurs, reduce until hierarchy is restored. - -### 2. Typography Superfamily Strategy - -Default to a Single System: One Family, multiple Weights, Limited Width/Style -Variation. - -Express hierarchy via: size, weight, spacing, rhythm. - -Introduce additional typefaces only when semantic separation is required (e.g., -code vs marketing content). - -### 3. Geometry Consistency Rule - -All UI must inherit a shared structural language: border radius, angle logic, -stroke thickness, elevation system, spacing cadence. - -Do not introduce new geometry tokens unless: - -- Existing tokens cannot express the requirement -- Functional clarity would otherwise degrade - -Consistency > variety. - -### 4. Dual-Scale Validation - -Evaluate every interface at two levels: - -**Macro (~10% scale):** Hierarchy clarity, scanning flow, section priority. - -**Micro (~200-300% scale):** Spacing, alignment, typography precision, component -polish. - -Reject designs that succeed at only one scale. - -### 5. Constraint-First Brand Framing - -Before generating UI styles, define negative constraints. Example: - -- not playful -- not aggressive -- not corporate -- not experimental -- not premium -- not youthful - -Use constraints to filter: color choices, typography decisions, motion styles, -component density. If a design decision conflicts with constraints, discard it. - -### 6. Non-Designer Reality Bias - -Assume users: are distracted, scroll quickly, use mobile, operate under low -brightness, do not analyze details. - -Optimize for: instant comprehension, strong primary action visibility, minimal -cognitive load, clear visual hierarchy within <2 seconds. - -Design for use, not inspection. - -### 7. Repetition over Novelty - -When uncertain: repeat existing visual rules, reinforce hierarchy, reduce -variation. - -Allow novelty only after: clarity is achieved, hierarchy is stable, interaction -affordances are obvious. - -## Integration Behavior - -When layered after `frontend-design`: - -1. Convert layout decisions into visual systems: derive color ratios, apply - typography hierarchy, normalize geometry tokens. -2. Run constraint filtering before rendering UI variants. -3. Evaluate macro structure first, micro polish second. -4. Optimize for comprehension speed over stylistic uniqueness. -5. Prefer consistency, predictability, clarity, and restraint over visual - experimentation. - -## Failure Modes to Avoid - -- Evenly distributed color usage -- Mixing multiple unrelated typefaces -- Inconsistent border radii and spacing logic -- Hierarchy visible only at high zoom -- Designing for designers instead of users -- Novelty introduced without structural justification - -## Output Expectations - -UI generated with this skill should feel: intentional, cohesive, restrained, -hierarchy-driven, fast to parse, and visually consistent across components and -pages. - -Bias toward clarity and repetition until interaction goals are fully satisfied. diff --git a/claude/statusline.sh b/claude/statusline.sh deleted file mode 100755 index fd86fb7..0000000 --- a/claude/statusline.sh +++ /dev/null @@ -1,245 +0,0 @@ -#!/bin/bash - -# --- Color Constants --- -COLOR_DIR=245 # directory -COLOR_GIT_BRANCH=153 # light blue pastel -COLOR_GIT_STATUS=182 # pink pastel -COLOR_DIM=243 # dimmer text (lines, cost) -COLOR_SEP=242 # separators - -# --- Utility Functions --- - -# Print text in specified 256-color -colored() { - printf "\033[38;5;%sm%s\033[0m" "$1" "$2" -} - -# Print separator -sep() { - colored $COLOR_SEP " · " -} - -# Format token counts (e.g., 50k, 1.2M) -format_tokens() { - local tokens=$1 - if [ "$tokens" -ge 1000000 ]; then - awk "BEGIN {printf \"%.1fM\", $tokens/1000000}" - elif [ "$tokens" -ge 1000 ]; then - awk "BEGIN {printf \"%.0fk\", $tokens/1000}" - else - echo "$tokens" - fi -} - -# Return color code based on percentage threshold -# Args: $1 = percentage, $2 = base color (used when below warning threshold) -get_percentage_color() { - local percent=$1 - local base_color=$2 - - # 229 = light yellow, 221 = yellow, 214 = gold, 208 = orange - if [ "$percent" -ge 98 ]; then - echo 208 - elif [ "$percent" -ge 95 ]; then - echo 214 - elif [ "$percent" -ge 90 ]; then - echo 221 - elif [ "$percent" -ge 85 ]; then - echo 229 - else - echo "$base_color" - fi -} - -# --- Data Extraction --- - -# Read stdin, save JSON, extract all fields into globals -parse_input() { - INPUT=$(cat) - - MODEL=$(echo "$INPUT" | jq -r '.model.display_name') - CWD=$(echo "$INPUT" | jq -r '.workspace.current_dir') - PERCENT=$(echo "$INPUT" | jq -r '.context_window.used_percentage // 0' | - xargs printf "%.0f") - TOTAL_INPUT=$(echo "$INPUT" | jq -r '.context_window.total_input_tokens // 0') - TOTAL_OUTPUT=$(echo "$INPUT" | jq -r '.context_window.total_output_tokens // 0') - TOTAL_TOKENS=$((TOTAL_INPUT + TOTAL_OUTPUT)) - CONTEXT_SIZE=$(echo "$INPUT" | jq -r '.context_window.context_window_size // 0') - # Calculate currently loaded tokens from percentage - CURRENT_TOKENS=$((CONTEXT_SIZE * PERCENT / 100)) - - # Extract cost info - COST_USD=$(echo "$INPUT" | jq -r '.cost.total_cost_usd // 0') - LINES_ADDED=$(echo "$INPUT" | jq -r '.cost.total_lines_added // 0') - LINES_REMOVED=$(echo "$INPUT" | jq -r '.cost.total_lines_removed // 0') -} - -# --- Component Builders --- - -# Get CWD, replace $HOME with ~ -get_directory() { - if [ -n "$CWD" ]; then - DIR="$CWD" - else - DIR=$(pwd) - fi - - # Replace home directory with tilde - DIR="${DIR/#$HOME/~}" -} - -# Get branch, status indicators, ahead/behind -get_git_info() { - GIT_BRANCH="" - GIT_STATUS="" - GIT_AHEAD_BEHIND="" - - # Skip if not in a git repo (skip optional locks to avoid blocking) - if [ ! -d "${CWD:-.}/.git" ] && - ! git -C "${CWD:-.}" rev-parse --git-dir > /dev/null 2>&1; then - return - fi - - # Get branch name - GIT_BRANCH=$(git -C "${CWD:-.}" branch --show-current 2> /dev/null || - git -C "${CWD:-.}" rev-parse --short HEAD 2> /dev/null) - - [ -z "$GIT_BRANCH" ] && return - - # Get status indicators - local git_dirty="" git_staged="" git_untracked="" - - # Check for staged changes - if ! git -C "${CWD:-.}" diff --cached --quiet 2> /dev/null; then - git_staged="+" - fi - - # Check for unstaged changes - if ! git -C "${CWD:-.}" diff --quiet 2> /dev/null; then - git_dirty="!" - fi - - # Check for untracked files - if [ -n "$(git -C "${CWD:-.}" ls-files --others --exclude-standard 2> /dev/null)" ]; then - git_untracked="?" - fi - - # Combine status indicators - GIT_STATUS="${git_staged}${git_dirty}${git_untracked}" - - # Get ahead/behind counts - local upstream ahead behind - upstream=$(git -C "${CWD:-.}" rev-parse --abbrev-ref '@{upstream}' 2> /dev/null) - if [ -n "$upstream" ]; then - ahead=$(git -C "${CWD:-.}" rev-list --count '@{upstream}..HEAD' 2> /dev/null) - behind=$(git -C "${CWD:-.}" rev-list --count 'HEAD..@{upstream}' 2> /dev/null) - - if [ "$ahead" -gt 0 ]; then - GIT_AHEAD_BEHIND="↑${ahead}" - fi - if [ "$behind" -gt 0 ]; then - GIT_AHEAD_BEHIND="${GIT_AHEAD_BEHIND}↓${behind}" - fi - fi -} - -# Build braille progress bar from PERCENT -build_progress_bar() { - # Braille characters with 7 levels per cell - # ⣀ (2) -> ⣄ (3) -> ⣤ (4) -> ⣦ (5) -> ⣶ (6) -> ⣷ (7) -> ⣿ (8 dots) - local braille_chars=("⣀" "⣄" "⣤" "⣦" "⣶" "⣷" "⣿") - local bar_width=10 - local levels=7 - local total_gradations=$((bar_width * levels)) - local current_gradation=$((PERCENT * total_gradations / 100)) - - PROGRESS_BAR="" - for ((i = 0; i < bar_width; i++)); do - local cell_start=$((i * levels)) - local cell_fill=$((current_gradation - cell_start)) - - if [ $cell_fill -le 0 ]; then - # Empty cell - PROGRESS_BAR+="${braille_chars[0]}" - elif [ $cell_fill -ge $levels ]; then - # Full cell - PROGRESS_BAR+="${braille_chars[$((levels - 1))]}" - else - # Partial cell - PROGRESS_BAR+="${braille_chars[$cell_fill]}" - fi - done -} - -# --- Output --- - -# Print the final formatted statusline -print_statusline() { - local current_display total_display cost_display context_color - - current_display=$(format_tokens "$CURRENT_TOKENS") - total_display=$(format_tokens "$TOTAL_TOKENS") - - # Determine context color based on percentage (ramps to warning colors) - context_color=$(get_percentage_color "$PERCENT" $COLOR_DIM) - - # Format cost as $X.XX - cost_display=$(awk "BEGIN {printf \"$%.2f\", $COST_USD}") - - # Directory - colored $COLOR_DIR "$DIR" - - # Git info - if [ -n "$GIT_BRANCH" ]; then - printf " " - colored $COLOR_GIT_BRANCH "$GIT_BRANCH" - - # Status indicators - if [ -n "$GIT_STATUS" ]; then - colored $COLOR_GIT_STATUS "$GIT_STATUS" - fi - - # Ahead/behind - if [ -n "$GIT_AHEAD_BEHIND" ]; then - printf " " - colored $COLOR_GIT_STATUS "$GIT_AHEAD_BEHIND" - fi - fi - - sep - - # Model (only if not default Opus 4.6) - if [ "$MODEL" != "Opus 4.6" ]; then - colored $COLOR_DIR "$MODEL" - sep - fi - - # Lines added/removed - colored $COLOR_DIM "+$LINES_ADDED" - colored $COLOR_SEP "/" - colored $COLOR_DIM "-$LINES_REMOVED" - sep - - # Progress bar and percentage (dynamic color based on context usage) - colored "$context_color" "$PROGRESS_BAR $PERCENT%" - sep - - # Token counts (dynamic color based on context usage) - colored "$context_color" "$current_display/$total_display" - sep - - # Cost - colored $COLOR_DIM "$cost_display" -} - -# --- Entry Point --- - -main() { - parse_input - get_directory - get_git_info - build_progress_bar - print_statusline -} - -main "$@" diff --git a/cursor/commands/generate-agentsmd.md b/cursor/commands/generate-agentsmd.md deleted file mode 100644 index 79bf63c..0000000 --- a/cursor/commands/generate-agentsmd.md +++ /dev/null @@ -1,265 +0,0 @@ ---- -source: https://github.com/RayFernando1337/llm-cursor-rules/blob/main/generate-agents.md ---- - -# Task: Analyze this codebase and generate a hierarchical AGENTS.md structure - -## Context & Principles - -You are going to help me create a **hierarchical AGENTS.md system** for this codebase. This is critical for AI coding agents to work efficiently with minimal token usage. - -### Core Principles - -1. **Root AGENTS.md is LIGHTWEIGHT** - Only universal guidance, links to sub-files -2. **Nearest-wins hierarchy** - Agents read the closest AGENTS.md to the file being edited -3. **JIT (Just-In-Time) indexing** - Provide paths/globs/commands, NOT full content -4. **Token efficiency** - Small, actionable guidance over encyclopedic documentation -5. **Sub-folder AGENTS.md files have MORE detail** - Specific patterns, examples, commands - -## Your Process - -### Phase 1: Repository Analysis - -First, analyze the codebase structure and provide me with: - -1. **Repository type**: Monorepo, multi-package, or simple single project? -2. **Primary technology stack**: Languages, frameworks, key tools -3. **Major directories/packages** that should have their own AGENTS.md: - - Apps (e.g., `apps/web`, `apps/api`, `apps/mobile`) - - Services (e.g., `services/auth`, `services/transcribe`) - - Packages/libs (e.g., `packages/ui`, `packages/shared`) - - Workers/jobs (e.g., `workers/queue`, `workers/cron`) - -4. **Build system**: pnpm/npm/yarn workspaces? Turborepo? Lerna? Or simple? -5. **Testing setup**: Jest, Vitest, Playwright, pytest? Where are tests? -6. **Key patterns to document**: - - Code organization patterns - - Important conventions (naming, styling, commits) - - Critical files that serve as good examples - - Anti-patterns to avoid - -Present this as a **structured map** before generating any AGENTS.md files. - ---- - -### Phase 2: Generate Root AGENTS.md - -Create a **lightweight root AGENTS.md** (~100-200 lines max) that includes: - -#### Required Sections - -**1. Project Snapshot** (3-5 lines) - -- Repo type (monorepo/simple) -- Primary tech stack -- Note that sub-packages have their own AGENTS.md files - -**2. Root Setup Commands** (5-10 lines) - -- Install dependencies (root level) -- Build all -- Typecheck all -- Test all - -**3. Universal Conventions** (5-10 lines) - -- Code style (TypeScript strict? Prettier? ESLint?) -- Commit format (Conventional Commits?) -- Branch strategy -- PR requirements - -**4. Security & Secrets** (3-5 lines) - -- Never commit tokens -- Where secrets go (.env patterns) -- PII handling if applicable - -**5. JIT Index - Directory Map** (10-20 lines) -Structure like: - -``` -## JIT Index (what to open, not what to paste) - -### Package Structure -- Web UI: `apps/web/` → [see apps/web/AGENTS.md](apps/web/AGENTS.md) -- API: `apps/api/` → [see apps/api/AGENTS.md](apps/api/AGENTS.md) -- Auth service: `services/auth/` → [see services/auth/AGENTS.md](services/auth/AGENTS.md) -- Shared packages: `packages/**/` → [see packages/README.md for details] - -### Quick Find Commands -- Search for a function: `rg -n "functionName" apps/** packages/**` -- Find a component: `rg -n "export.*ComponentName" apps/web/src` -- Find API routes: `rg -n "export const (GET|POST)" apps/api` -``` - -**6. Definition of Done** (3-5 lines) - -- What must pass before a PR is ready -- Minimal checklist - ---- - -### Phase 3: Generate Sub-Folder AGENTS.md Files - -For EACH major package/directory identified in Phase 1, create a **detailed AGENTS.md** that includes: - -#### Required Sections - -**1. Package Identity** (2-3 lines) - -- What this package/app/service does -- Primary tech/framework for THIS package - -**2. Setup & Run** (5-10 lines) - -- Install command (if different from root) -- Dev server command -- Build command -- Test command -- Lint/typecheck commands - -**3. Patterns & Conventions** (10-20 lines) -**THIS IS THE MOST IMPORTANT SECTION** - -- File organization rules (where things go) -- Naming conventions specific to this package -- Preferred patterns with **file examples**: - ``` - - ✅ DO: Use functional components like `src/components/Button.tsx` - - ❌ DON'T: Use class components like `src/legacy/OldButton.tsx` - - ✅ Forms: Copy pattern from `src/components/forms/ContactForm.tsx` - - ✅ API calls: Use `src/lib/api/client.ts` wrapper, see example in `src/hooks/useUser.ts` - ``` - -**4. Touch Points / Key Files** (5-10 lines) -Point to the most important files to understand this package: - -``` -- Auth logic: `src/auth/provider.tsx` -- API client: `src/lib/api.ts` -- Types: `src/types/index.ts` -- Config: `src/config.ts` -``` - -**5. JIT Index Hints** (5-10 lines) -Specific search commands for this package: - -``` -- Find a React component: `rg -n "export function .*" src/components` -- Find a hook: `rg -n "export const use" src/hooks` -- Find route handlers: `rg -n "export async function (GET|POST)" src/app` -- Find tests: `find . -name "*.test.ts"` -``` - -**6. Common Gotchas** (3-5 lines, if applicable) - -- "Auth requires `NEXT_PUBLIC_` prefix for client-side use" -- "Always use `@/` imports for absolute paths" -- "Database migrations must be run before tests: `pnpm db:migrate`" - -**7. Pre-PR Checks** (2-3 lines) -Package-specific command to run before creating a PR: - -``` -pnpm --filter @repo/web typecheck && pnpm --filter @repo/web test && pnpm --filter @repo/web build -``` - ---- - -### Phase 4: Special Considerations - -For each AGENTS.md file, also consider: - -**A. Design System / UI Package** -If there's a design system or UI library: - -```markdown -## Design System -- Components: `packages/ui/src/components/**` -- Use design tokens from `packages/ui/src/tokens.ts` (never hardcode colors) -- See component gallery: `pnpm --filter @repo/ui storybook` -- Examples: - - Buttons: Copy `packages/ui/src/components/Button/Button.tsx` - - Forms: Copy `packages/ui/src/components/Input/Input.tsx` -``` - -**B. Database / Data Layer** -If there's a database service: - -```markdown -## Database -- ORM: Prisma / Drizzle / TypeORM -- Schema: `prisma/schema.prisma` -- Migrations: `pnpm db:migrate` -- Seed: `pnpm db:seed` -- **NEVER** run migrations in tests; use `test-db` script -- Connection: via `src/lib/db.ts` singleton -``` - -**C. API / Backend Service** - -```markdown -## API Patterns -- REST routes: `src/routes/**/*.ts` -- Auth middleware: `src/middleware/auth.ts` (apply to protected routes) -- Validation: Use Zod schemas in `src/schemas/**` -- Error handling: All errors thrown as `ApiError` from `src/lib/errors.ts` -- Example endpoint: See `src/routes/users/get.ts` for full pattern -``` - -**D. Testing Package** - -```markdown -## Testing -- Unit tests: `*.test.ts` colocated with source -- Integration tests: `tests/integration/**` -- E2E tests: `tests/e2e/**` (Playwright) -- Run single test: `pnpm test -- path/to/file.test.ts` -- Coverage: `pnpm test:coverage` (aim for >80%) -- Mock external APIs using `src/test/mocks/**` -``` - ---- - -## Output Format - -Provide the files in this order: - -1. **Analysis Summary** (from Phase 1) -2. **Root AGENTS.md** (complete, ready to copy) -3. **Each Sub-Folder AGENTS.md** (one at a time, with file path) - -For each file, use this format: - -``` ---- -File: `AGENTS.md` (root) ---- -[full content here] - ---- -File: `apps/web/AGENTS.md` ---- -[full content here] - ---- -File: `services/auth/AGENTS.md` ---- -[full content here] -``` - ---- - -## Constraints & Quality Checks - -Before generating, verify: - -- [ ] Root AGENTS.md is under 200 lines -- [ ] Root links to all sub-AGENTS.md files -- [ ] Each sub-file has concrete examples (actual file paths) -- [ ] Commands are copy-paste ready (no placeholders unless unavoidable) -- [ ] No duplication between root and sub-files -- [ ] JIT hints use actual patterns from the codebase (ripgrep, find, glob) -- [ ] Every "✅ DO" has a real file example -- [ ] Every "❌ DON'T" references a real anti-pattern or legacy file -- [ ] Pre-PR checks are single copy-paste commands diff --git a/cursor/user-rules.md b/cursor/user-rules.md deleted file mode 120000 index e96d484..0000000 --- a/cursor/user-rules.md +++ /dev/null @@ -1 +0,0 @@ -../claude/CLAUDE.md \ No newline at end of file diff --git a/siren b/siren index 6aa3aa0..488e796 100755 --- a/siren +++ b/siren @@ -43,19 +43,9 @@ define_settings() { STATIC_SYMLINKS["harper-ls/file_dictionaries"]="$(harper_config_dir)/file_dictionaries" STATIC_SYMLINKS["harper-ls/ignored_lints"]="$(harper_config_dir)/ignored_lints" - # Conditionally add symlinks for Claude (only if CLI is installed). - if command -v claude &>/dev/null; then - STATIC_SYMLINKS["claude/CLAUDE.md"]="${HOME}/.claude/CLAUDE.md" - STATIC_SYMLINKS["claude/settings.json"]="${HOME}/.claude/settings.json" - STATIC_SYMLINKS["claude/statusline.sh"]="${HOME}/.claude/statusline.sh" - _add_command_symlinks "claude" "${HOME}/.claude" - _add_skill_symlinks "claude" "${HOME}/.claude" - fi - # Conditionally add symlinks for Cursor. if [[ "${SETUP_EDITOR}" == "cursor" ]]; then STATIC_SYMLINKS["cursor/mcp.json"]="${HOME}/.cursor/mcp.json" - _add_command_symlinks "cursor" "${HOME}/.cursor" fi } @@ -429,123 +419,6 @@ symlink_static_config() { done } -# Add symlinks for all markdown files in a commands directory. -# Args: $1 = source subdir (e.g., "claude"), $2 = target dir (e.g., ~/.claude) -_add_command_symlinks() { - local source_subdir="$1" - local target_base="$2" - local cmd_file - - for cmd_file in "${SCRIPT_DIR}/${source_subdir}/commands/"*.md; do - if [[ -f "${cmd_file}" ]]; then - local filename - filename="$(basename "${cmd_file}")" - STATIC_SYMLINKS["${source_subdir}/commands/${filename}"]="${target_base}/commands/${filename}" - fi - done -} - -# Add symlinks for all skill directories (containing SKILL.md) in a skills -# directory. -# Args: $1 = source subdir (e.g., "claude"), $2 = target dir (e.g., ~/.claude) -_add_skill_symlinks() { - local source_subdir="$1" - local target_base="$2" - local skills_dir="${SCRIPT_DIR}/${source_subdir}/skills" - - if [[ ! -d "${skills_dir}" ]]; then - return - fi - - local skill_dir - for skill_dir in "${skills_dir}"/*/; do - # Skip if glob didn't match anything (returns literal pattern). - [[ -d "${skill_dir}" ]] || continue - - # Only treat directories containing SKILL.md as skills. - if [[ -f "${skill_dir}/SKILL.md" ]]; then - local skill_name - skill_name="$(basename "${skill_dir}")" - STATIC_SYMLINKS["${source_subdir}/skills/${skill_name}"]="${target_base}/skills/${skill_name}" - fi - done -} - -# Remove stale symlinks in a commands directory that point to source files that -# no longer exist. -# Args: $1 = source subdir (e.g., "claude"), $2 = target dir (e.g., ~/.claude) -_cleanup_stale_commands() { - local source_subdir="$1" - local target_base="$2" - local commands_dir="${target_base}/commands" - local source_dir="${SCRIPT_DIR}/${source_subdir}/commands" - - if [[ ! -d "${commands_dir}" ]]; then - return - fi - - local link - for link in "${commands_dir}"/*; do - # Skip if glob didn't match anything (returns literal pattern). - [[ -e "${link}" || -L "${link}" ]] || continue - - # Skip if not a symlink. - if [[ ! -L "${link}" ]]; then - continue - fi - - local target - target="$(readlink "${link}")" - - # Check if the symlink points to our source directory. - if [[ "${target}" == "${source_dir}/"* ]]; then - # If the target file no longer exists, remove the symlink. - if [[ ! -e "${target}" ]]; then - info "Removing stale symlink: ${link}" - rm -f "${link}" - fi - fi - done -} - -# Remove stale symlinks in a skills directory that point to source -# directories that no longer exist. Only touches symlinks pointing into our -# source tree; symlinks managed by other tools are left untouched. -# Args: $1 = source subdir (e.g., "claude"), $2 = target dir (e.g., ~/.claude) -_cleanup_stale_skills() { - local source_subdir="$1" - local target_base="$2" - local skills_dir="${target_base}/skills" - local source_dir="${SCRIPT_DIR}/${source_subdir}/skills" - - if [[ ! -d "${skills_dir}" ]]; then - return - fi - - local link - for link in "${skills_dir}"/*; do - # Skip if glob didn't match anything (returns literal pattern). - [[ -e "${link}" || -L "${link}" ]] || continue - - # Skip if not a symlink. - if [[ ! -L "${link}" ]]; then - continue - fi - - local target - target="$(readlink "${link}")" - - # Check if the symlink points to our source directory. - if [[ "${target}" == "${source_dir}/"* ]]; then - # If the target directory no longer exists, remove the symlink. - if [[ ! -e "${target}" ]]; then - info "Removing stale symlink: ${link}" - rm -f "${link}" - fi - fi - done -} - # Find the editor CLI command. # # Returns: Editor command path via `STDOUT`. @@ -1342,15 +1215,6 @@ do_config() { symlink_editor_config symlink_static_config - # Clean up stale command and skill symlinks. - if command -v claude &>/dev/null; then - _cleanup_stale_commands "claude" "${HOME}/.claude" - _cleanup_stale_skills "claude" "${HOME}/.claude" - fi - if [[ "${SETUP_EDITOR}" == "cursor" ]]; then - _cleanup_stale_commands "cursor" "${HOME}/.cursor" - fi - info "Symlink setup complete!" }