From 0e61346d20c0afc5979ac839e66982cd6126f637 Mon Sep 17 00:00:00 2001 From: Mikhail Chusavitin Date: Fri, 6 Mar 2026 18:07:47 +0300 Subject: [PATCH] feat: add KISS and task-discipline contracts Co-Authored-By: Claude Sonnet 4.6 --- rules/patterns/kiss/contract.md | 56 ++++++++++++++++++++++ rules/patterns/task-discipline/contract.md | 21 ++++++++ 2 files changed, 77 insertions(+) create mode 100644 rules/patterns/kiss/contract.md create mode 100644 rules/patterns/task-discipline/contract.md diff --git a/rules/patterns/kiss/contract.md b/rules/patterns/kiss/contract.md new file mode 100644 index 0000000..e2bce98 --- /dev/null +++ b/rules/patterns/kiss/contract.md @@ -0,0 +1,56 @@ +# Contract: Keep It Simple + +Version: 1.0 + +## Principle + +Working solutions do not need to be interesting. + +Prefer the simplest solution that correctly solves the problem. Complexity must be justified by a real, present requirement — not by anticipation of future needs or desire to use a particular technique. + +## Rules + +- Choose boring technology. A well-understood, dull solution beats a clever one. +- Do not introduce abstractions, patterns, or frameworks before they are needed by at least two concrete use cases. +- Do not design for hypothetical future requirements. Build for what exists now. +- Prefer sequential, readable code over clever one-liners. +- If you can delete code and the system still works, delete it. +- Extra configurability, generalization, and extensibility are costs, not features. Add them only when explicitly required. + +## Anti-patterns + +- Adding helpers or utilities for one-time operations. +- Wrapping simple logic in interfaces "for testability" when a direct call works. +- Using a framework or library to solve a problem the standard library already handles. +- Writing error handling, fallbacks, or validation for scenarios that cannot happen. +- Refactoring working code because it "could be cleaner." + +## Bulletproof features + +A feature must be correct by construction, not by circumstance. + +Do not write mechanisms that silently rely on: +- another feature being in a specific state, +- input data having a particular shape that "usually" holds, +- a certain call order or timing, +- a global flag, ambient variable, or external condition being set upstream. + +Such mechanisms are thin: they work only when the world cooperates. When any surrounding assumption shifts, they break in ways that are hard to trace. This is the primary source of bugs. + +**Design rules:** + +- A feature owns its preconditions. If it requires data in a certain state, it must enforce or produce that state itself — not inherit it silently from a caller. +- Never write logic that only works if a sibling feature runs first and succeeds. If coordination is needed, make it explicit (a parameter, a return value, a clear contract). +- Avoid implicit state machines — sequences where operations must happen in the right order with no enforcement. Either enforce the order structurally or eliminate the dependency. +- Prefer thick, unconditional logic over thin conditional chains that assume stable context. A mechanism that always does the right thing is more reliable than one that does the right thing only when conditions are favorable. + +A feature is done when it is correct on its own, not when it is correct given that everything else is also correct. + +## Checklist before committing + +1. Could this be done with fewer lines without losing clarity? +2. Does every abstraction here have more than one caller? +3. Is any of this code handling a case that cannot actually occur? +4. Did I add anything beyond what was asked? + +If the answer to any of 1–4 is "yes," simplify before committing. diff --git a/rules/patterns/task-discipline/contract.md b/rules/patterns/task-discipline/contract.md new file mode 100644 index 0000000..fcee1e0 --- /dev/null +++ b/rules/patterns/task-discipline/contract.md @@ -0,0 +1,21 @@ +# Contract: Task Discipline + +Version: 1.0 + +## Principle + +Finish before switching. A task is not done until it reaches a logical end. + +## Rules + +- Do not start a new task while the current one is unfinished. Switching mid-task leaves half-done work that is harder to recover than if it had never been started. +- If a new idea or requirement surfaces during work, note it and address it after the current task is complete. +- "Logical end" means: the change works, is committed, and leaves the codebase in a coherent state — not just "the immediate code compiles." +- Do not open new files, refactor adjacent code, or fix unrelated issues while implementing a specific task. Stay focused on the defined scope. +- If the current task is blocked, resolve the blocker or explicitly hand off — do not silently pivot to something else. + +## Anti-patterns + +- Starting a refactor while in the middle of a bug fix. +- Leaving a feature half-implemented because something more interesting came up. +- Responding to a new requirement by abandoning the current one without documenting what was left unfinished.