From 2eb3a62a3f201f0f73c86e1869334d454caee4a4 Mon Sep 17 00:00:00 2001 From: kmontemayor Date: Thu, 19 Mar 2026 17:56:57 +0000 Subject: [PATCH 1/3] Try to get the robots to not be astronaut architects --- CLAUDE.md | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/CLAUDE.md b/CLAUDE.md index b4f785f87..26ea77812 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -124,6 +124,79 @@ development. - Use OOP for model architectures, functional style for data transforms/pipelines. - Re-use and refactor existing code as a priority instead of implementing new code. +### K.I.S.S. (Keep It Simple, Stupid) + +- Prefer the simplest implementation that solves the current concrete use case. Do not add abstraction for hypothetical + reuse, extensibility, or future configuration. +- Reduce indirection. If a helper is only called once or twice and is only a few lines, inline it unless extracting it + clearly improves readability, testability, or error handling. +- Keep workflows easy to follow from top to bottom. Avoid splitting a linear flow across many tiny functions, classes, + or files just to make each unit smaller. +- Keep internal data shapes lightweight. For short-lived internal plumbing, prefer tuples, dicts, or existing objects + over tiny dataclasses, wrapper classes, or new types. +- Avoid one-off layers. Do not introduce builders, factories, registries, strategy objects, or config classes unless + they remove real duplication or support multiple active implementations. +- Defer generalization until there is a second real use case. Solve today's problem directly first, then extract shared + structure only when repetition becomes concrete. +- Prefer explicit parameter passing over stateful objects when the workflow is local and sequential. +- Avoid boolean soup. If a function starts accumulating mode flags, optional callbacks, or branching setup paths, + consider splitting it by use case instead of growing a generic entry point. + +**Small examples** + +Prefer inlining tiny one-off helpers: + +```python +# Avoid +def _normalized_node_id(node_id: str) -> str: + return node_id.strip().lower() + + +def load_node(node_id: str) -> Node: + return node_store[_normalized_node_id(node_id)] + + +# Prefer +def load_node(node_id: str) -> Node: + normalized_node_id = node_id.strip().lower() + return node_store[normalized_node_id] +``` + +Prefer lightweight internal data over tiny one-off types: + +```python +# Avoid +@dataclass(frozen=True) +class BatchBounds: + start_index: int + end_index: int + + +batch_bounds = BatchBounds(start_index=0, end_index=128) + + +# Prefer +batch_bounds: tuple[int, int] = (0, 128) +start_index, end_index = batch_bounds +``` + +Prefer separate simple entry points over one generic function with flags: + +```python +# Avoid +def write_output(records: list[Record], *, validate: bool, compress: bool, upload: bool) -> None: + ... + + +# Prefer +def write_local_output(records: list[Record]) -> None: + ... + + +def write_uploaded_output(records: list[Record]) -> None: + ... +``` + ### Fail Fast on Invalid State - Use `dict[key]` (bracket access) when the key **must** exist. Only use `.get(key, default)` when absence is a valid, @@ -134,7 +207,8 @@ development. - Always use type annotations for function parameters and return values. - Prefer native types (`dict[str, str]`, `list[int]`) over `typing.Dict`, `typing.List`. -- Use `Final` for constants. Use `@dataclass(frozen=True)` for immutable data containers. +- Use `Final` for constants. Use `@dataclass(frozen=True)` for immutable data containers when named fields and a stable + shape add real clarity; do not introduce a dataclass for tiny internal-only plumbing. - Always annotate empty containers: `names: list[str] = []` not `names = []`. ### Docstrings From 282c45d42be4d9920341362becaabfc168c65de5 Mon Sep 17 00:00:00 2001 From: Kyle Montemayor Date: Thu, 19 Mar 2026 16:02:56 -0700 Subject: [PATCH 2/3] Update CLAUDE.md --- CLAUDE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CLAUDE.md b/CLAUDE.md index 26ea77812..7e105c3a9 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -141,6 +141,7 @@ development. - Prefer explicit parameter passing over stateful objects when the workflow is local and sequential. - Avoid boolean soup. If a function starts accumulating mode flags, optional callbacks, or branching setup paths, consider splitting it by use case instead of growing a generic entry point. +- Don't re-invent the wheel. Check the code base for utilities that solve the task at hand. **Small examples** From 275cc9bc79d4f879693c26170d991826b8f972b2 Mon Sep 17 00:00:00 2001 From: kmontemayor Date: Fri, 20 Mar 2026 20:50:01 +0000 Subject: [PATCH 3/3] move to skill --- .claude/skills/pragmatic/SKILL.md | 146 ++++++++++++++++++++++++++++++ AGENTS.md | 7 +- CLAUDE.md | 9 +- 3 files changed, 158 insertions(+), 4 deletions(-) create mode 100644 .claude/skills/pragmatic/SKILL.md diff --git a/.claude/skills/pragmatic/SKILL.md b/.claude/skills/pragmatic/SKILL.md new file mode 100644 index 000000000..a6ed8de20 --- /dev/null +++ b/.claude/skills/pragmatic/SKILL.md @@ -0,0 +1,146 @@ +______________________________________________________________________ + +## description: Apply KISS and pragmatic simplification to the current task, plan, or code. Invoke when the user says kiss, keep it simple, be pragmatic, don't overcomplicate, simplify this, reduce abstraction, avoid overengineering, or asks for the smallest correct change. argument-hint: "[optional focus]" + +# Pragmatic + +Use the K.I.S.S. guidance from `CLAUDE.md` to simplify the current task, plan, or code without dropping correctness. + +## Instructions + +When this skill is invoked with `$ARGUMENTS`, execute the following sections in order. + +______________________________________________________________________ + +### 1. Anchor on the concrete need + +Identify the current concrete use case before proposing changes. + +- Optimize for today's requirement, not hypothetical future reuse. +- If `$ARGUMENTS` names a specific area, use it as the simplification target. +- If the request is broad, infer the narrowest immediate objective from the conversation and code. + +______________________________________________________________________ + +### 2. Inspect existing code before inventing structure + +Look for existing utilities, patterns, and nearby implementations before proposing new abstractions. + +- Reuse or lightly refactor existing code when it already solves most of the problem. +- Do not introduce new layers just because they look architecturally neat. +- Prefer local edits over cross-cutting reorganization unless the current shape is clearly blocking correctness. + +______________________________________________________________________ + +### 3. Prefer the smallest direct implementation + +Bias toward the simplest implementation that cleanly solves the current problem. + +- Avoid abstraction for hypothetical extensibility or configuration. +- Keep linear workflows easy to follow from top to bottom. +- Inline tiny one-off helpers when extraction does not materially improve readability, testability, or error handling. +- Prefer explicit parameter passing over stateful helper objects when the workflow is local and sequential. + +______________________________________________________________________ + +### 4. Keep data and control flow lightweight + +Reduce indirection in both data shapes and function structure. + +- Prefer tuples, dicts, or existing objects over tiny one-off dataclasses, wrappers, or config classes. +- Avoid one-off builders, factories, registries, or strategy objects unless they remove real duplication or support + multiple active implementations. +- If a function is accumulating mode flags, optional callbacks, or branching setup paths, prefer separate simple entry + points over one generic function. + +______________________________________________________________________ + +### 5. Preserve correctness while simplifying + +Do not simplify away behavior that is required for safe and correct code. + +- Keep validation, error handling, and required invariants intact. +- Do not remove tests, guards, or explicit exceptions that protect against invalid state. +- Do not churn stable public APIs or established shared abstractions unless they are part of the actual problem. +- Defer generalization until a second real use case exists, but do not delete real reuse that is already paying for + itself. + +______________________________________________________________________ + +### 6. Produce a pragmatic answer + +When responding to the user, structure the output around the simplest viable path. + +- State the recommended simple approach first. +- Name the specific complexity to avoid and why it is unnecessary for the current use case. +- If editing code, make the smallest coherent change set that solves the problem. +- If reviewing a plan, call out where the plan is over-generalized and replace it with a narrower implementation path. + +______________________________________________________________________ + +### 7. Apply these default heuristics + +Use these checks when deciding whether to simplify: + +- A helper called once or twice and only a few lines long usually should be inlined. +- A short-lived internal type with two small fields usually should be a tuple, dict, or existing object. +- A function with several boolean flags usually should become separate entry points by use case. +- A new abstraction justified only by "we might need this later" usually should not be added. +- If the codebase already has a utility that solves the problem, use it instead of re-implementing it. + +______________________________________________________________________ + +### 8. Keep these examples in mind + +Prefer inlining tiny one-off helpers: + +```python +# Avoid +def _normalized_node_id(node_id: str) -> str: + return node_id.strip().lower() + + +def load_node(node_id: str) -> Node: + return node_store[_normalized_node_id(node_id)] + + +# Prefer +def load_node(node_id: str) -> Node: + normalized_node_id = node_id.strip().lower() + return node_store[normalized_node_id] +``` + +Prefer lightweight internal data over tiny one-off types: + +```python +# Avoid +@dataclass(frozen=True) +class BatchBounds: + start_index: int + end_index: int + + +batch_bounds = BatchBounds(start_index=0, end_index=128) + + +# Prefer +batch_bounds: tuple[int, int] = (0, 128) +start_index, end_index = batch_bounds +``` + +Prefer separate simple entry points over one generic function with flags: + +```python +# Avoid +def write_output(records: list[Record], *, validate: bool, compress: bool, upload: bool) -> None: + ... + + +# Prefer +def write_local_output(records: list[Record]) -> None: + ... + + +def write_uploaded_output(records: list[Record]) -> None: + ... +``` diff --git a/AGENTS.md b/AGENTS.md index d704b8407..811e2ecae 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -5,7 +5,8 @@ This file provides guidance to coding agents working in this repository. ## Coordination With CLAUDE.md - CLAUDE.md is the canonical source of truth for project context, architecture intent, and workflow conventions. - - At the start of every session: read [CLAUDE.md](CLAUDE.md) together with this file before making repository changes. - -- This file should *only* say to read CLAUDE.md, and make no other statements about this repository. +- At the start of every session: discover available skills under [.claude/skills](.claude/skills). +- When a relevant skill exists under `.claude/skills`, use it. +- This file should only direct agents to read CLAUDE.md and discover/use `.claude/skills`, and make no other statements + about this repository. diff --git a/CLAUDE.md b/CLAUDE.md index 7e105c3a9..436f7a250 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -5,7 +5,14 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Coordination With AGENTS.md - CLAUDE.md is the canonical source of truth for project context, architecture intent, and workflow conventions. -- AGENTS.md should only say to load CLAUDE.md. +- AGENTS.md should direct agents to read CLAUDE.md and discover/use skills under `.claude/skills`. + +## Skills + +- Repository-local skills live under `.claude/skills/`. +- At the start of every session, discover available skills under `.claude/skills` along with reading AGENTS.md and + CLAUDE.md. +- When a relevant skill exists for the task, use it and follow its instructions. ## Project Overview