Skip to content
Skills Library
Programming · Planning

code-designing

/code-designing

FORWARD view over rules/ — domain type design and architectural planning for Python code BEFORE it exists. Use when planning new features, designing self-validating types, preventing primitive obsession, or when refactoring reveals need for new types. Dispatches into the Design guidance sections of rules/R1-R8 and R10-R12.

Licence
Apache-2.0
Last repository change
26.10.2026

Assessment and security

92/ 100Class: good
Format25 / 25
Frontmatter with name and description, valid name, description up to 1,024 characters, name matching the folder.
Discoverability25 / 25
Description explains when to use the skill, has a reasonable length and uses third person.
Content27 / 35
At least 150 words and at most 500 lines, headings, step lists, examples or code.
Hygiene15 / 15
No placeholders such as TODO, no Windows paths, with a licence.
Riskno signals detected in the scan
Files in this package
1
Scripts
0
HTML comments
0
URLs in SKILL.md
0
Deprecation

No signals detected. Repository changed on 26.10.2026, without references to retired models or APIs.

Licence

Apache-2.0, otwarta: można używać i zmieniać, z zachowaniem licencji i informacji o zmianach.

What it does and when to use it

FORWARD view over rules/ — domain type design and architectural planning for Python code BEFORE it exists. Use when planning new features, designing self-validating types, preventing primitive obsession, or when refactoring reveals need for new types. Dispatches into the Design guidance sections of rules/R1-R8 and R10-R12.

Original author description

FORWARD view over rules/ — domain type design and architectural planning for Python code BEFORE it exists. Use when planning new features, designing self-validating types, preventing primitive obsession, or when refactoring reveals need for new types. Dispatches into the Design guidance sections of rules/R1-R8 and R10-R12.

How it works

SKILL.md has no level-two headings · 169 lines, 1,461 words

SKILL.md preview
---
name: code-designing
description: |
  FORWARD view over rules/ — domain type design and architectural planning for Python code BEFORE it exists.
  Use when planning new features, designing self-validating types, preventing primitive obsession, or when refactoring reveals need for new types.
  Dispatches into the Design guidance sections of rules/R1-R8 and R10-R12.
allowed-tools:
  - Skill(python-linter-driven-development:testing)
---

<objective>
The design phase applied BEFORE code exists. This skill is a thin directional view:
every design principle lives exactly once in `../../rules/` — this protocol says
which rule to open at which design step, and what shape the output takes.

Backward counterpart (fixing code that already fails lint/review): @refactoring.
</objective>

<skill_invocation>
**CRITICAL**: When this skill says "Use @skill-name", you MUST invoke it with the
**Skill tool** — do not just mention it.

| Notation | Skill Tool Call |
|----------|-----------------|
| @testing | `Skill(python-linter-driven-development:testing)` |
</skill_invocation>

<when_to_use>
- Planning a new feature (before writing code)
- Refactoring reveals need for new types (@refactoring escalates here)
- Linter failures that need a design decision, not a mechanical fix:
  - `PLR0913` (too many arguments) → design a frozen dataclass of the parameters that travel together (score it per `../../rules/R1-primitive-obsession.md`); a keyword-only `*` marker tidies the call sites but leaves the clump
  - `PLR0911` (too many returns), or a tuple return carrying a `bool` or an error member → design a named result type, or raise (same R1 scoring)
  - a module over the file-length limit (pylint's `max-module-lines` where set, else the gap linter's 450 code lines; ruff has no file-length rule) → split juicy types into their own modules (juiciness per R1; module-per-type per `../../rules/R5-vertical-slice.md`); a single god class routes to @refactoring's god-object decomposition procedure first
  - Package-size yellow/red zone → re-model with sub-packages *before* the zone escalates (`<package_decomposition>` in @refactoring's `reference.md` (`sed -n '/^<package_decomposition>/,/^<\/package_decomposition>/p; /^### Package decomposition/,$p'`))
- A Phase 4 review CLUSTER (≥2 hunters converging on one anchor —
  @linter-driven-development routes it here) → **cluster-scoped mode**: skip
  `<architecture_scan>` and the user-OK step (acceptance was inherited when the
  findings were accepted); design only the one concept the cluster names — its
  type or dispatch shape (R11), constructor (R2), mutation surface (R12), and
  placement (R4) — so every member finding resolves as a consequence of that one
  design. Return the mini DESIGN PLAN to the caller; @refactoring implements it.
</when_to_use>

<protocol>

<architecture_scan priority="FIRST_STEP">
**Default: vertical slice architecture** — `../../rules/R5-vertical-slice.md`.

Scan the codebase structure: vertical (`app/feature/{handler,service}.py`, one
package per feature) vs horizontal (`app/{handlers,services}/feature.py`, or one
`models.py`/`views.py`/`services.py` per layer)?

1. **Pure vertical** → continue the pattern: implement as `internal/<new-feature>/`.
2. **Pure horizontal** → propose starting migration (template in R5's Design
   guidance); implement the new feature as the first vertical slice.
3. **Mixed** → check `docs/architecture/vertical-slice-migration.md`, continue as a slice.

Architecture advises, it doesn't veto (R5's advisory posture). Ask the user:
Option A — vertical slice (recommended); Option B — match the existing pattern
(time pressure and team conventions are valid reasons).
</architecture_scan>

<understand_domain>
What is the problem domain? The main concepts/entities? The invariants and rules?
How does this fit the existing architecture?
</understand_domain>

<maxim_interrogation>
Design happens before a diff exists — no detection command can run yet, so questions
are the tool. Interrogate the plan with `../../maxims.md` (the questions live there,
once; ask them, don't restate them):

- Every function that receives another type's data → **Tell, don't ask**: does the
  decision it makes belong on that type?
- Every planned interface → **The bigger the interface, the weaker the abstraction**:
  could it be one method?
- Every planned type → **Make illegal states unrepresentable** vs **Make the zero
  value useful**: validated domain type (constructor) or mechanism type (useful
  zero)? Pick a family.
- Every planned check → **Parse, don't validate**: does it return a more-typed value
  or a boolean someone must remember?
- Every planned signature that returns or accepts a container of primitives →
  **Tell, don't ask**: what will the receiver do with it? Each operation is a method
  of a type that does not exist yet (`../../rules/R1-primitive-obsession.md`,
  "Containers of primitives").
- Every shared helper → **A little copying is better than a little dependency**: is
  the third strike actually here?

Answers shape the plan; they are never findings. Maxims propose, evidence disposes —
the review phases convict only via rules (`maxims.md`, contract section).
</maxim_interrogation>

<rule_dispatch>
For each concept in the design, open the rule that owns the question and apply its
**Design guidance** section:

| Rule | When designing, apply... |
|------|--------------------------|
| `../../rules/R1-primitive-obsession.md` | Which primitives become types — score every candidate with R1's juiciness scorecard; reject ceremony wrappers (over-abstraction trap). |
| `../../rules/R2-self-validating-types.md` | Constructor-only entry, validation ownership, trusting composed values, None is not a value, no defensive checks in methods. |
| `../../rules/R3-storifying.md` | Plan orchestration functions as 3–5 named steps at one conceptual level; honest names for mutators. |
| `../../rules/R4-helper-placement.md` | WHERE each helper/type lands — the placement ladder (underscore-prefixed → feature sub-package → shared domain package). |
| `../../rules/R5-vertical-slice.md` | Package structure and naming: feature slices with roles inside, flatcase domain vocabulary, migration template. |
| `../../rules/R6-test-only-interfaces.md` | Default dependencies to concrete types; an interface must be earned by a second production implementation or a grep-verified import cycle. |
| `../../rules/R7-test-placement.md` | The test plan per type: leaf types 100% unit coverage via public constructors, checked by a mutation run over the leaf's package; orchestrators integration-tested over real collaborators, never mutated. |
| `../../rules/R8-no-globals.md` | Dependencies injected via constructors, cancellation passed down from callers, globals only at entry points. |
| `../../rules/R10-concurrency-safety.md` | Every planned concurrent task gets an owner (stop + wait) and an exit path at construction time; shared state designed with its guard on one type — or designed away via handoff/confinement. |
| `../../rules/R11-conditional-dispatch.md` | How each kind/variant family dispatches: behavior-heavy or open set → interface chosen once at the boundary; single-behavior variance → strategy map; single-site closed enum → one exhaustive switch (named enum per R1). |
| `../../rules/R12-mutation-discipline.md` | Each type's mutation surface: constructors copy slice/map arguments; queries return copies or iterators, never internal references; no setters around validating constructors; query and modifier as separate methods. |
</rule_dispatch>

<design_checklist>
Before presenting the plan, verify against the rules (cite, don't restate):

- [ ] No primitive obsession; every proposed type scored, ceremony rejected (R1)
- [ ] Every planned signature names its types: no nested container, no flat container of primitives crossing a function boundary that its receivers operate on; a product result has a name and field names (R1, Name the Container)
- [ ] Types are self-validating; composed types trusted, never re-validated (R2)
- [ ] Orchestration planned as a story; most logic pushed into leaf types (R3, R7)
- [ ] **Placement decided** for every helper and type via the ladder — underscore-prefixed helper vs feature sub-package vs domain package (`../../rules/R4-helper-placement.md`)
- [ ] Vertical slice structure; package names are flatcase domain vocabulary, never roles/containers (R5)
- [ ] No test-only interfaces: every interface has a second production implementation OR breaks a real import cycle, verified by grepping the import direction (detection command in `../../rules/R6-test-only-interfaces.md`); otherwise depend on the concrete type
- [ ] Import direction strictly downward: leaf types ← sub-packages ← parent ← cmd/ (cycle-breaking move in `<package_decomposition>` in @refactoring's `reference.md` (`sed -n '/^<package_decomposition>/,/^<\/package_decomposition>/p; /^### Package decomposition/,$p'`))
- [ ] Dependencies constructor-injected and validated; cancellation flows down; no new globals (R8, R2)
- [ ] Every concurrent task has an owner and exit path; shared state guarded where it lives, or confined (R10)
- [ ] Every kind/variant family has ONE dispatch owner — interface, strategy map, or a single exhaustive switch; no discriminator inspected in two places (R11)
- [ ] Every validated type's mutation surface is closed: slice/map arguments copied in, internal collections never returned by reference, no unvalidated setters (R12)
</design_checklist>

</protocol>

<output_format>
```
DESIGN PLAN

Feature: [Feature Name]

Core Domain Types (leaf):
- [Type] ([underlying]) — invariant it owns; juiciness verdict (R1)
- [Type] — the container it names and the receiver operations that become its methods (R1, Name the Container)

Orchestrating Types:
- [Type] — dependencies (concrete unless R6-justified), methods

Package Structure:
[feature]/
  ├── __init__.py      # the public surface: what a consumer imports
  ├── [type].py        # each juicy type in its own module
  ├── service.py
  └── handler.py

Placement Decisions (R4):
- [helper/type] → rung 1/2/3 and why

Design Decisions:
- [decision] — rationale, citing the owning rule

Integration Points:
- Consumed by / depends on / events

Next Steps:
1. Create types with validating constructors
2. Write unit tests for each leaf type → use @testing skill
3. Implement orchestrators; integration tests over real collaborators
```
</output_format>

<success_criteria>
Design phase is complete when ALL are true:

- [ ] Architecture pattern analyzed (vertical/horizontal/mixed) and user chose an option
- [ ] Core domain types identified, each with its validation rules and R1 score
- [ ] Placement decision recorded for every new type/helper (R4 ladder)
- [ ] Package structure follows R5 (slices, naming, downward imports)
- [ ] Design checklist answered satisfactorily (every box cites its rule)
- [ ] Design plan presented in the output format above
</success_criteria>

Versions

RepositoryScoreLicence
This page · buzzdan/ai-coding-rules92Apache-2.0
buzzdan/ai-coding-rules92Apache-2.0
buzzdan/ai-coding-rules92Apache-2.0
buzzdan/ai-coding-rules92Apache-2.0
buzzdan/ai-coding-rules92Apache-2.0

Database snapshot: 13.11.2026 · package version d07f14130c13 (SHA-256 digest of the entire package)

Downloads in the last 30 days: 0 · ranking

Report a problem with this skill: harmful content, incorrect descriptions or an author’s removal request.

Similar skills

  • 100122-java-type-design
    Use when you need to review, improve, or refactor Java code for type design quality — including establishing clear type hierarchies, applying consistent naming conventions, eliminating primitive obsession with domain-specific value objects, leveraging generic type parameters,…
  • 100refactor-extract-value-object
    Extract value objects from primitive fields in Protean aggregates, entities, and commands. Detects primitive obsession (raw String/Float/Integer fields representing domain concepts that deserve their own type) and refactors them into proper value objects. Use when the user says…
  • 95python-design-pattern
    Python design patterns and anti-patterns. Use when designing new components, refactoring, reviewing code for common mistakes, choosing abstractions, or evaluating pull requests for structural issues like tight coupling, leaking internal types, or error handling problems.
  • 100domain-modeling
    Use this skill when the user asks about domain modeling, primitive obsession, parse-don't-validate, semantic types, value objects, or making invalid states unrepresentable. Triggers on: "review for domain issues", "primitive obsession", "design domain types", "value object",…
  • 90Python Code Review with Modern Typing
    Review Python code ensuring strict type safety with Python 3.12+ conventions. Use when reviewing Python code, writing new Python code, or refactoring existing Python code.
  • 100python-design
    Python design patterns for CLI scripts and utilities — type-first development, deep modules, complexity management, and red flags. Use when reading, writing, reviewing, or refactoring Python files, especially in .trellis/scripts/ or any CLI/scripting context. Also activate when…

Feedback and reports

Your message goes to Bartosz Sokoliński. An email address is needed only for a reply. See the privacy policy.