@lenardangeloolajay/len-toolkit 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +209 -0
- package/bin/cli.js +244 -0
- package/package.json +35 -0
- package/src/installer.js +236 -0
- package/templates/configs/.editorconfig +12 -0
- package/templates/configs/sample.gitignore +8 -0
- package/templates/docs/FEATURE.md +40 -0
- package/templates/docs/HANDOFF.md +39 -0
- package/templates/docs/IMPLEMENTATION_PLAN.md +47 -0
- package/templates/docs/SPEC_INDEX.md +12 -0
- package/templates/docs/VERIFICATION.md +14 -0
- package/templates/docs/product/ARCHITECTURE.md +22 -0
- package/templates/docs/product/CONSTRAINTS.md +22 -0
- package/templates/docs/product/DATA_MODEL.md +22 -0
- package/templates/docs/product/OVERVIEW.md +22 -0
- package/templates/examples/flutter-handoff/EXERCISES.md +16 -0
- package/templates/examples/flutter-handoff/HANDOFF.md +32 -0
- package/templates/examples/flutter-handoff/docs/SPEC_INDEX.md +19 -0
- package/templates/examples/flutter-handoff/docs/evidence/FEAT-001-verification.md +14 -0
- package/templates/examples/flutter-handoff/docs/features/FEAT-001-local-note.md +40 -0
- package/templates/examples/flutter-handoff/docs/plans/FEAT-001-implementation.md +43 -0
- package/templates/examples/flutter-handoff/docs/product/ARCHITECTURE.md +24 -0
- package/templates/examples/flutter-handoff/docs/product/CONSTRAINTS.md +13 -0
- package/templates/examples/flutter-handoff/docs/product/DATA_MODEL.md +20 -0
- package/templates/examples/flutter-handoff/docs/product/OVERVIEW.md +26 -0
- package/templates/rules/.cursorrules +7 -0
- package/templates/rules/AGENTS.md +61 -0
- package/templates/rules/GEMINI.md +7 -0
- package/templates/skills/a-philosophy-of-software-design/SKILL.md +11 -0
- package/templates/skills/a-philosophy-of-software-design/a-philosophy-of-software-design.md +370 -0
- package/templates/skills/a-philosophy-of-software-design/a-philosophy-of-software-design.mini.md +46 -0
- package/templates/skills/a-philosophy-of-software-design/a-philosophy-of-software-design.nano.md +35 -0
- package/templates/skills/clean-architecture/SKILL.md +11 -0
- package/templates/skills/clean-architecture/clean-architecture.md +515 -0
- package/templates/skills/clean-architecture/clean-architecture.mini.md +49 -0
- package/templates/skills/clean-architecture/clean-architecture.nano.md +36 -0
- package/templates/skills/clean-code/SKILL.md +11 -0
- package/templates/skills/clean-code/clean-code.md +297 -0
- package/templates/skills/clean-code/clean-code.mini.md +47 -0
- package/templates/skills/clean-code/clean-code.nano.md +32 -0
- package/templates/skills/code-complete/SKILL.md +11 -0
- package/templates/skills/code-complete/code-complete.md +354 -0
- package/templates/skills/code-complete/code-complete.mini.md +56 -0
- package/templates/skills/code-complete/code-complete.nano.md +41 -0
- package/templates/skills/council/SKILL.md +37 -0
- package/templates/skills/designing-data-intensive-applications/SKILL.md +11 -0
- package/templates/skills/designing-data-intensive-applications/designing-data-intensive-applications.md +393 -0
- package/templates/skills/designing-data-intensive-applications/designing-data-intensive-applications.mini.md +55 -0
- package/templates/skills/designing-data-intensive-applications/designing-data-intensive-applications.nano.md +34 -0
- package/templates/skills/domain-driven-design/SKILL.md +11 -0
- package/templates/skills/domain-driven-design/domain-driven-design.md +979 -0
- package/templates/skills/domain-driven-design/domain-driven-design.mini.md +48 -0
- package/templates/skills/domain-driven-design/domain-driven-design.nano.md +39 -0
- package/templates/skills/domain-driven-design-distilled/SKILL.md +11 -0
- package/templates/skills/domain-driven-design-distilled/domain-driven-design-distilled.md +317 -0
- package/templates/skills/domain-driven-design-distilled/domain-driven-design-distilled.mini.md +56 -0
- package/templates/skills/domain-driven-design-distilled/domain-driven-design-distilled.nano.md +41 -0
- package/templates/skills/implementation-plan/SKILL.md +42 -0
- package/templates/skills/implementing-domain-driven-design/SKILL.md +11 -0
- package/templates/skills/implementing-domain-driven-design/implementing-domain-driven-design.md +337 -0
- package/templates/skills/implementing-domain-driven-design/implementing-domain-driven-design.mini.md +57 -0
- package/templates/skills/implementing-domain-driven-design/implementing-domain-driven-design.nano.md +37 -0
- package/templates/skills/patterns-of-enterprise-application-architecture/SKILL.md +11 -0
- package/templates/skills/patterns-of-enterprise-application-architecture/patterns-of-enterprise-application-architecture.md +404 -0
- package/templates/skills/patterns-of-enterprise-application-architecture/patterns-of-enterprise-application-architecture.mini.md +54 -0
- package/templates/skills/patterns-of-enterprise-application-architecture/patterns-of-enterprise-application-architecture.nano.md +35 -0
- package/templates/skills/ponytail/SKILL.md +124 -0
- package/templates/skills/ponytail-audit/SKILL.md +45 -0
- package/templates/skills/ponytail-debt/SKILL.md +48 -0
- package/templates/skills/ponytail-gain/SKILL.md +17 -0
- package/templates/skills/ponytail-help/SKILL.md +42 -0
- package/templates/skills/ponytail-review/SKILL.md +61 -0
- package/templates/skills/refactoring/SKILL.md +11 -0
- package/templates/skills/refactoring/refactoring.md +433 -0
- package/templates/skills/refactoring/refactoring.mini.md +49 -0
- package/templates/skills/refactoring/refactoring.nano.md +37 -0
- package/templates/skills/refactoring-guru/SKILL.md +11 -0
- package/templates/skills/refactoring-guru/refactoring-guru.md +765 -0
- package/templates/skills/refactoring-guru/refactoring-guru.mini.md +64 -0
- package/templates/skills/refactoring-guru/refactoring-guru.nano.md +41 -0
- package/templates/skills/release-it/SKILL.md +11 -0
- package/templates/skills/release-it/release-it.md +382 -0
- package/templates/skills/release-it/release-it.mini.md +48 -0
- package/templates/skills/release-it/release-it.nano.md +38 -0
- package/templates/skills/security-audit/AI-AND-LLM.md +83 -0
- package/templates/skills/security-audit/ATTACK-CLASSES.md +130 -0
- package/templates/skills/security-audit/CLIENT-SIDE.md +83 -0
- package/templates/skills/security-audit/CLOUD-AND-DEPLOYMENT.md +86 -0
- package/templates/skills/security-audit/DATA-ISOLATION-AND-LIFECYCLE.md +84 -0
- package/templates/skills/security-audit/DESKTOP-MOBILE-AND-LOCAL-IPC.md +89 -0
- package/templates/skills/security-audit/HUNTING.md +251 -0
- package/templates/skills/security-audit/MEMORY-SAFETY-AND-BINARY.md +101 -0
- package/templates/skills/security-audit/PROTOCOLS-RPC-AND-MESSAGING.md +81 -0
- package/templates/skills/security-audit/RECONNAISSANCE.md +156 -0
- package/templates/skills/security-audit/RESOURCE-EXHAUSTION-AND-AVAILABILITY.md +78 -0
- package/templates/skills/security-audit/SKILL.md +192 -0
- package/templates/skills/security-audit/SUPPLY-CHAIN-AND-RELEASE.md +73 -0
- package/templates/skills/security-audit/VALIDATION-AND-REPORTING.md +186 -0
- package/templates/skills/security-audit/WEB-PROTOCOL-AND-AUTH.md +105 -0
- package/templates/skills/security-audit/report-schema.json +461 -0
- package/templates/skills/security-audit/validate-coverage-ledger.cjs +872 -0
- package/templates/skills/security-audit/validate-coverage-ledger.test.cjs +740 -0
- package/templates/skills/security-audit/validate-findings.cjs +773 -0
- package/templates/skills/security-audit/validate-findings.test.cjs +652 -0
- package/templates/skills/spec/SKILL.md +55 -0
- package/templates/skills/the-pragmatic-programmer/SKILL.md +11 -0
- package/templates/skills/the-pragmatic-programmer/the-pragmatic-programmer.md +359 -0
- package/templates/skills/the-pragmatic-programmer/the-pragmatic-programmer.mini.md +65 -0
- package/templates/skills/the-pragmatic-programmer/the-pragmatic-programmer.nano.md +44 -0
- package/templates/skills/working-effectively-with-legacy-code/SKILL.md +11 -0
- package/templates/skills/working-effectively-with-legacy-code/working-effectively-with-legacy-code.md +371 -0
- package/templates/skills/working-effectively-with-legacy-code/working-effectively-with-legacy-code.mini.md +50 -0
- package/templates/skills/working-effectively-with-legacy-code/working-effectively-with-legacy-code.nano.md +35 -0
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
# OBEY Patterns of Enterprise Application Architecture by Martin Fowler
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
This repository follows the practical style of **Patterns of Enterprise Application Architecture**:
|
|
6
|
+
structure enterprise software around clear responsibilities for domain logic, persistence, transaction boundaries, integration, and presentation.
|
|
7
|
+
|
|
8
|
+
All code generation, edits, and reviews must optimize for:
|
|
9
|
+
- explicit separation of concerns
|
|
10
|
+
- predictable business logic placement
|
|
11
|
+
- appropriate enterprise patterns instead of accidental coupling
|
|
12
|
+
- manageable persistence and transaction boundaries
|
|
13
|
+
- clear mapping between in-memory objects and external systems
|
|
14
|
+
- code that is maintainable under real enterprise constraints
|
|
15
|
+
|
|
16
|
+
This file is a binding engineering policy: `MUST` is binding, `SHOULD` is a strong default, and `MUST NOT` is forbidden.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Primary Directive
|
|
21
|
+
|
|
22
|
+
Enterprise software is not improved by inventing architecture from scratch for every feature.
|
|
23
|
+
Prefer a small number of well-understood structural patterns, applied deliberately.
|
|
24
|
+
|
|
25
|
+
When uncertain, choose the design that makes these responsibilities explicit:
|
|
26
|
+
- presentation and transport
|
|
27
|
+
- application workflow
|
|
28
|
+
- domain logic
|
|
29
|
+
- data source interaction
|
|
30
|
+
- transaction management
|
|
31
|
+
- concurrency control
|
|
32
|
+
- integration boundaries
|
|
33
|
+
|
|
34
|
+
Do not let one class or layer own all of them.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Architectural Baseline
|
|
39
|
+
|
|
40
|
+
### Layering
|
|
41
|
+
Use layering as a default organizing principle:
|
|
42
|
+
1. presentation and delivery
|
|
43
|
+
2. application coordination
|
|
44
|
+
3. domain logic
|
|
45
|
+
4. data source and integration access
|
|
46
|
+
|
|
47
|
+
Rules (MUST unless marked SHOULD or MUST NOT):
|
|
48
|
+
- upper layers may depend on lower ones
|
|
49
|
+
- lower layers must not reach into presentation concerns
|
|
50
|
+
- each layer must earn its existence by reducing coupling or clarifying responsibility
|
|
51
|
+
|
|
52
|
+
Anti-patterns (MUST NOT):
|
|
53
|
+
- controllers reaching directly into SQL and transaction details
|
|
54
|
+
- domain logic embedded in views or handlers
|
|
55
|
+
- repositories returning HTTP-shaped DTOs
|
|
56
|
+
- fake layers that only pass calls through
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Choosing the Business Logic Pattern
|
|
61
|
+
|
|
62
|
+
### Transaction Script
|
|
63
|
+
Use when:
|
|
64
|
+
- logic is simple
|
|
65
|
+
- each request or use case is mostly independent
|
|
66
|
+
- rich domain modeling is unnecessary
|
|
67
|
+
|
|
68
|
+
Rules (MUST unless marked SHOULD or MUST NOT):
|
|
69
|
+
- scripts must remain short and use-case focused
|
|
70
|
+
- do not let transaction scripts become dumping grounds for all business logic
|
|
71
|
+
- if duplication, lifecycle, or invariant complexity grows, escalate to a stronger pattern
|
|
72
|
+
|
|
73
|
+
### Table Module
|
|
74
|
+
Use when:
|
|
75
|
+
- logic is naturally organized around tabular data sets
|
|
76
|
+
- calculations are set-oriented
|
|
77
|
+
- object identity is not the key organizing force
|
|
78
|
+
|
|
79
|
+
Rules (MUST unless marked SHOULD or MUST NOT):
|
|
80
|
+
- keep behavior centered on the table abstraction
|
|
81
|
+
- do not fake entities if the real model is fundamentally tabular
|
|
82
|
+
- isolate tabular logic from presentation and transport
|
|
83
|
+
|
|
84
|
+
### Domain Model
|
|
85
|
+
Use when:
|
|
86
|
+
- domain complexity is significant
|
|
87
|
+
- business rules, invariants, and lifecycles matter
|
|
88
|
+
- identity, collaboration, and behavior belong in the model
|
|
89
|
+
|
|
90
|
+
Rules (MUST unless marked SHOULD or MUST NOT):
|
|
91
|
+
- rich domain logic belongs in model objects
|
|
92
|
+
- keep application coordination separate from domain decisions
|
|
93
|
+
- avoid anemic models in behavior-rich domains
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Application Workflow Rules
|
|
98
|
+
|
|
99
|
+
### Service Layer
|
|
100
|
+
Use a service layer to define application operations.
|
|
101
|
+
|
|
102
|
+
Rules (MUST unless marked SHOULD or MUST NOT):
|
|
103
|
+
1. Application services coordinate use cases.
|
|
104
|
+
2. They define transaction boundaries and orchestration.
|
|
105
|
+
3. They must not absorb all domain logic by default.
|
|
106
|
+
4. They should expose an application-oriented API, not UI mechanics.
|
|
107
|
+
|
|
108
|
+
### Remote Facade
|
|
109
|
+
Use when:
|
|
110
|
+
- the boundary is remote
|
|
111
|
+
- coarse-grained APIs reduce chatty calls
|
|
112
|
+
- transport shape differs from internal design
|
|
113
|
+
|
|
114
|
+
Rules (MUST unless marked SHOULD or MUST NOT):
|
|
115
|
+
- expose coarse remote operations
|
|
116
|
+
- translate between remote contracts and internal model
|
|
117
|
+
- keep remote transport concerns at the boundary
|
|
118
|
+
|
|
119
|
+
### Data Transfer Object
|
|
120
|
+
Use when:
|
|
121
|
+
- data crosses process or layer boundaries
|
|
122
|
+
- batching values reduces remote or serialization cost
|
|
123
|
+
- translation protects the internal model
|
|
124
|
+
|
|
125
|
+
Rules (MUST unless marked SHOULD or MUST NOT):
|
|
126
|
+
- DTOs are transport structures, not domain models
|
|
127
|
+
- keep mapping explicit
|
|
128
|
+
- do not move business behavior into DTOs
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Persistence Pattern Rules
|
|
133
|
+
|
|
134
|
+
### Repository
|
|
135
|
+
Use repositories to present a collection-like interface over domain object access.
|
|
136
|
+
|
|
137
|
+
Rules (MUST unless marked SHOULD or MUST NOT):
|
|
138
|
+
1. Repositories must speak in domain terms.
|
|
139
|
+
2. Repository interfaces should reflect domain access needs rather than table shape.
|
|
140
|
+
3. Repository implementations hide query, mapping, and storage details.
|
|
141
|
+
4. Repositories must not become generic “everything” gateways.
|
|
142
|
+
|
|
143
|
+
### Data Mapper
|
|
144
|
+
Use when:
|
|
145
|
+
- the domain model should remain decoupled from the database structure
|
|
146
|
+
- object-relational mismatch is real
|
|
147
|
+
- persistence logic deserves isolation
|
|
148
|
+
|
|
149
|
+
Rules (MUST unless marked SHOULD or MUST NOT):
|
|
150
|
+
- mapping code belongs outside the domain objects
|
|
151
|
+
- do not force domain objects to know SQL, record formats, or mapping mechanics
|
|
152
|
+
- keep mapping explicit and testable
|
|
153
|
+
|
|
154
|
+
### Row Data Gateway
|
|
155
|
+
Use when behavior is simple and record-oriented.
|
|
156
|
+
|
|
157
|
+
### Table Data Gateway
|
|
158
|
+
Use when operations are naturally table-oriented and one table interface can clearly centralize access.
|
|
159
|
+
|
|
160
|
+
### Active Record
|
|
161
|
+
Use only when domain logic is simple and persistence coupling is acceptable.
|
|
162
|
+
Do not default to Active Record for complex domains.
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Identity, Caching, and Unit-of-Work Rules
|
|
167
|
+
|
|
168
|
+
### Identity Map
|
|
169
|
+
- preserve one in-memory representation per identity per scope where needed
|
|
170
|
+
- avoid duplicate object instances fighting each other inside one logical unit of work
|
|
171
|
+
|
|
172
|
+
### Unit of Work
|
|
173
|
+
- make transactional write coordination explicit
|
|
174
|
+
- commit work as one logical unit
|
|
175
|
+
- keep unit-of-work scope understandable
|
|
176
|
+
|
|
177
|
+
### Lazy Load
|
|
178
|
+
- use deliberately, not everywhere
|
|
179
|
+
- know where lazy loading may trigger remote/database chatter
|
|
180
|
+
- avoid lazy loading surprises in loops and serialization paths
|
|
181
|
+
|
|
182
|
+
Anti-patterns (MUST NOT):
|
|
183
|
+
- invisible N+1 behavior everywhere
|
|
184
|
+
- hidden auto-persistence with surprising write timing
|
|
185
|
+
- saving each object ad hoc from random callers
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Object-Relational Mapping Pattern Index
|
|
190
|
+
|
|
191
|
+
- USE Identity Field when in-memory objects need stable database identity; keep identity mapping explicit.
|
|
192
|
+
- USE Foreign Key Mapping when object references map to relational keys; avoid hiding expensive joins behind innocent traversal.
|
|
193
|
+
- USE Association Table Mapping when many-to-many relationships need a separate relational table.
|
|
194
|
+
- USE Dependent Mapping when child objects have no independent database identity outside their owner.
|
|
195
|
+
- USE Embedded Value when a small value object can live inside the owning row without independent lifecycle.
|
|
196
|
+
- USE Serialized LOB only when querying inside the value is not required and serialization versioning is controlled.
|
|
197
|
+
- USE Single Table Inheritance when one table with nullable columns is simpler than multiple joins.
|
|
198
|
+
- USE Class Table Inheritance when normalized subtype data is worth join complexity.
|
|
199
|
+
- USE Concrete Table Inheritance when each concrete type can own its table without excessive duplication.
|
|
200
|
+
- USE Inheritance Mappers to isolate inheritance persistence decisions from domain logic.
|
|
201
|
+
- USE Metadata Mapping when mapping rules are regular enough to centralize safely; avoid it when metadata obscures exceptional behavior.
|
|
202
|
+
- USE Query Object when query construction needs a composable object model instead of scattered SQL strings.
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## Concurrency and Transaction Rules
|
|
207
|
+
|
|
208
|
+
### Optimistic Offline Lock
|
|
209
|
+
Use when conflicts are possible but uncommon.
|
|
210
|
+
|
|
211
|
+
Rules (MUST unless marked SHOULD or MUST NOT):
|
|
212
|
+
- detect conflicting concurrent updates
|
|
213
|
+
- fail safely and explicitly
|
|
214
|
+
- surface conflict resolution or merge semantics intentionally
|
|
215
|
+
|
|
216
|
+
### Pessimistic Locking
|
|
217
|
+
Use only when contention is expected and the cost is justified.
|
|
218
|
+
|
|
219
|
+
### Transaction Boundaries
|
|
220
|
+
1. Transaction boundaries must be explicit in application workflow.
|
|
221
|
+
2. Avoid transactions that span remote calls when possible.
|
|
222
|
+
3. Keep transactions short.
|
|
223
|
+
4. Do not bury transaction ownership deep in helper classes.
|
|
224
|
+
|
|
225
|
+
### Additional Offline Concurrency Patterns
|
|
226
|
+
- USE Coarse-Grained Lock when related objects must be locked together to preserve a user-level edit.
|
|
227
|
+
- USE Implicit Lock only when lock acquisition is reliably hidden without making concurrency invisible to maintainers.
|
|
228
|
+
- Do not let implicit locking make transaction ownership or contention impossible to diagnose.
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## Presentation Layer Rules
|
|
233
|
+
|
|
234
|
+
1. Presentation code handles input, rendering, and transport concerns.
|
|
235
|
+
2. Business rules must not live in controllers or views.
|
|
236
|
+
3. Presentation models may differ from domain models.
|
|
237
|
+
4. Formatting, pagination, and UI interaction state belong outside domain logic.
|
|
238
|
+
|
|
239
|
+
Choose Page Controller vs Front Controller pragmatically, but keep routing concerns out of business logic.
|
|
240
|
+
|
|
241
|
+
### Presentation Pattern Index
|
|
242
|
+
- USE Model View Controller to separate domain model, view, and controller responsibilities.
|
|
243
|
+
- USE Page Controller when each page/action can be handled independently.
|
|
244
|
+
- USE Front Controller when centralized request handling, authentication, routing, or dispatch is valuable.
|
|
245
|
+
- USE Template View when server-side templates clearly express the response.
|
|
246
|
+
- USE Transform View when transforming data into output is clearer than embedding logic in templates.
|
|
247
|
+
- USE Two Step View when shared presentation structure should be separated from page-specific content.
|
|
248
|
+
- USE Application Controller when flow and navigation decisions need a dedicated coordinator.
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## Offline and Integration Rules
|
|
253
|
+
|
|
254
|
+
1. External systems must be accessed through clear boundaries.
|
|
255
|
+
2. Translate partner formats into internal concepts.
|
|
256
|
+
3. Integration events/messages are not domain objects.
|
|
257
|
+
4. Do not allow integration convenience to dominate internal design.
|
|
258
|
+
|
|
259
|
+
Anti-patterns (MUST NOT):
|
|
260
|
+
- internal code shaped around partner API payloads
|
|
261
|
+
- direct vendor DTOs used across the application
|
|
262
|
+
- business logic embedded in serialization code
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
## Session State and Base Pattern Index
|
|
267
|
+
|
|
268
|
+
- USE Client Session State only when client storage is acceptable and integrity/security implications are handled.
|
|
269
|
+
- USE Server Session State when server-managed session data is needed and scaling/cleanup costs are explicit.
|
|
270
|
+
- USE Database Session State when session durability or server-farm sharing outweighs database load.
|
|
271
|
+
- USE Gateway to isolate access to an external resource or subsystem.
|
|
272
|
+
- USE Mapper to move data between objects or layers while keeping both sides independent.
|
|
273
|
+
- USE Layer Supertype only when shared layer behavior is real and stable.
|
|
274
|
+
- USE Separated Interface when clients should depend on an interface in a different package from implementation details.
|
|
275
|
+
- USE Registry sparingly for well-known objects; avoid turning it into global hidden dependency.
|
|
276
|
+
- USE Value Object for small values where equality by value and immutability simplify code.
|
|
277
|
+
- USE Money for currency amounts so rounding, currency, and arithmetic rules stay explicit.
|
|
278
|
+
- USE Special Case to replace repeated null or exceptional handling with a named object.
|
|
279
|
+
- USE Plugin when implementations must be selected or extended without changing core code.
|
|
280
|
+
- USE Service Stub to test or run without a real remote service.
|
|
281
|
+
- USE Record Set when tabular data is the natural interchange shape and object behavior is not needed.
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
## Distribution Rules
|
|
286
|
+
|
|
287
|
+
1. Do not distribute objects or services remotely by default.
|
|
288
|
+
2. Remote boundaries must be coarse-grained.
|
|
289
|
+
3. Separate local object design from remote contract design.
|
|
290
|
+
4. Budget explicitly for latency, serialization, versioning, and partial failure.
|
|
291
|
+
|
|
292
|
+
Anti-patterns (MUST NOT):
|
|
293
|
+
- chatty remote object interfaces
|
|
294
|
+
- assuming local method-call semantics over a network
|
|
295
|
+
- leaking domain internals through remote endpoints
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
## Code Generation Rules
|
|
300
|
+
|
|
301
|
+
When generating code, apply this order:
|
|
302
|
+
1. identify the business logic pattern that actually fits the complexity
|
|
303
|
+
2. place use-case coordination in an application/service layer
|
|
304
|
+
3. place domain decisions in the domain model when the domain is rich
|
|
305
|
+
4. place persistence behind repositories, mappers, or gateways
|
|
306
|
+
5. define transaction boundaries explicitly
|
|
307
|
+
6. define DTOs or remote facades only at boundaries
|
|
308
|
+
7. keep presentation and transport concerns at the edge
|
|
309
|
+
|
|
310
|
+
Default choices:
|
|
311
|
+
- simple CRUD -> transaction script or simple service layer
|
|
312
|
+
- rich invariants -> domain model + repository + mapper
|
|
313
|
+
- table-oriented calculations -> table module or table gateway
|
|
314
|
+
- remote boundary -> remote facade + DTO
|
|
315
|
+
|
|
316
|
+
Avoid by default:
|
|
317
|
+
- using domain model everywhere regardless of complexity
|
|
318
|
+
- generic repository for everything
|
|
319
|
+
- exposing persistence models directly to callers
|
|
320
|
+
- placing transactions, validation, rendering, and SQL in one class
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## Review Rules
|
|
325
|
+
|
|
326
|
+
When reviewing code, actively look for:
|
|
327
|
+
- domain logic in controllers or views
|
|
328
|
+
- repositories returning transport shapes
|
|
329
|
+
- lower layers knowing presentation details
|
|
330
|
+
- trivial CRUD wrapped in excessive modeling
|
|
331
|
+
- complex rules trapped in transaction scripts
|
|
332
|
+
- SQL spread through business code
|
|
333
|
+
- missing transaction boundaries
|
|
334
|
+
- hidden unit-of-work behavior
|
|
335
|
+
- accidental N+1 loading
|
|
336
|
+
- chatty remote APIs
|
|
337
|
+
- no translation between internal and remote models
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
## Forbidden Patterns
|
|
342
|
+
|
|
343
|
+
### Layering Theater
|
|
344
|
+
- five layers that only forward method calls
|
|
345
|
+
|
|
346
|
+
### Generic Repository Everywhere
|
|
347
|
+
- one CRUD abstraction for all domain and data access
|
|
348
|
+
- repository APIs shaped by tables instead of use cases
|
|
349
|
+
|
|
350
|
+
### ORM-Driven Everything
|
|
351
|
+
- all design decisions dictated by ORM convenience
|
|
352
|
+
- aggregates, services, and DTOs collapsed into one persistence model
|
|
353
|
+
|
|
354
|
+
### Controller-Centric Enterprise App
|
|
355
|
+
- request handlers coordinating transactions, SQL, domain rules, and external calls
|
|
356
|
+
|
|
357
|
+
### Distributed Object Fantasy
|
|
358
|
+
- pretending network calls are normal method calls
|
|
359
|
+
|
|
360
|
+
### Unclear Transaction Ownership
|
|
361
|
+
- random save calls across layers
|
|
362
|
+
- no clear transaction owner
|
|
363
|
+
- long-running workflows treated as one immediate transaction
|
|
364
|
+
|
|
365
|
+
---
|
|
366
|
+
|
|
367
|
+
## Testing Rules
|
|
368
|
+
|
|
369
|
+
1. Test domain logic independently from presentation and persistence when possible.
|
|
370
|
+
2. Test repositories, mappers, and gateways separately as data-access infrastructure.
|
|
371
|
+
3. Test service/application workflows for transaction and orchestration behavior.
|
|
372
|
+
4. Test concurrency behaviors where optimistic or pessimistic locking matters.
|
|
373
|
+
5. Test DTO and remote facade mapping at the boundaries.
|
|
374
|
+
|
|
375
|
+
---
|
|
376
|
+
|
|
377
|
+
## Review Checklist
|
|
378
|
+
|
|
379
|
+
Before finalizing any change, verify:
|
|
380
|
+
- Did we choose the right business logic pattern for the actual complexity?
|
|
381
|
+
- Are presentation, workflow, domain logic, and persistence responsibilities distinct?
|
|
382
|
+
- Is transaction ownership explicit?
|
|
383
|
+
- Are repositories or gateways shaped by use cases or aggregates rather than raw tables?
|
|
384
|
+
- Is mapping isolated from domain logic?
|
|
385
|
+
- Are remote boundaries coarse-grained and translated explicitly?
|
|
386
|
+
- Did we avoid generic repository overreach?
|
|
387
|
+
- Did we avoid controller-centric design?
|
|
388
|
+
- Did we avoid layering theater?
|
|
389
|
+
- Did we keep concurrency and loading assumptions visible?
|
|
390
|
+
|
|
391
|
+
If any answer is no, revise before shipping.
|
|
392
|
+
|
|
393
|
+
---
|
|
394
|
+
|
|
395
|
+
## Final Instruction
|
|
396
|
+
|
|
397
|
+
When uncertain, choose the smallest set of enterprise patterns that makes:
|
|
398
|
+
1. business logic placement obvious
|
|
399
|
+
2. persistence and mapping explicit
|
|
400
|
+
3. transaction boundaries clear
|
|
401
|
+
4. remote boundaries coarse and safe
|
|
402
|
+
5. the application easier to evolve under real enterprise constraints
|
|
403
|
+
|
|
404
|
+
Reject fashionable complexity and accidental coupling alike.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# OBEY Patterns of Enterprise Application Architecture by Martin Fowler
|
|
2
|
+
|
|
3
|
+
## When to use
|
|
4
|
+
|
|
5
|
+
Use when designing or reviewing enterprise application code that crosses presentation, application workflow, domain logic, persistence, transactions, concurrency, integration, session state, or remote boundaries.
|
|
6
|
+
|
|
7
|
+
## Primary bias to correct
|
|
8
|
+
|
|
9
|
+
Enterprise applications are not improved by inventing architecture for every feature or by letting the framework, ORM, database schema, or transport shape choose the design. Use a small set of well-understood patterns to make responsibilities and boundaries explicit.
|
|
10
|
+
|
|
11
|
+
## Decision rules
|
|
12
|
+
|
|
13
|
+
- Make responsibility ownership explicit before naming patterns: presentation and transport, application workflow, domain logic, data source interaction, transaction management, concurrency control, and integration boundaries must not collapse into one class or layer.
|
|
14
|
+
- Use layering as the default organizing principle, but every layer must earn its cost by reducing coupling or clarifying responsibility; forbid lower layers from reaching into presentation concerns and reject pass-through layering theater.
|
|
15
|
+
- Choose the business logic pattern by force: Transaction Script for short independent simple flows, Table Module for table-centered set logic, and Domain Model for significant rules, invariants, identity, lifecycle, or collaboration.
|
|
16
|
+
- Let Transaction Scripts stay use-case focused, Table Modules stay honestly tabular, and Domain Models own rich behavior; escalate when duplication, lifecycle, or invariant complexity grows.
|
|
17
|
+
- Use a Service Layer to define application operations, coordinate use cases, own transaction boundaries and orchestration, expose an application-oriented API, and avoid absorbing all domain logic by default.
|
|
18
|
+
- At remote or cross-layer boundaries, use Remote Facade and DTOs to make coarse operations, batching, translation, and transport shape explicit; DTOs are transport structures, not domain models.
|
|
19
|
+
- Choose persistence patterns deliberately: repositories speak domain terms and hide query/mapping/storage details, Data Mappers keep SQL and record formats outside domain objects, gateways centralize record/table access, and Active Record is only for simple domains where persistence coupling is acceptable.
|
|
20
|
+
- Keep identity, write coordination, and loading behavior visible: use Identity Map for one object per identity per scope, Unit of Work for one logical transactional commit, and Lazy Load only where hidden database or remote chatter will not surprise loops or serializers.
|
|
21
|
+
- Choose object-relational mappings by identity, lifecycle, query needs, schema shape, and evolution cost; keep identity fields, foreign keys, association tables, dependent objects, embedded values, serialized values, inheritance mapping, metadata mapping, and query objects explicit rather than accidental.
|
|
22
|
+
- Design concurrency and transactions in the application workflow: optimistic locks detect conflicts and surface merge semantics, pessimistic locks require justified contention, transactions stay short, remote calls usually sit outside transactions, and helpers must not hide transaction ownership.
|
|
23
|
+
- Use coarse-grained and implicit offline locks only when they preserve a user-level edit without making ownership, contention, or stale-lock cleanup impossible to diagnose.
|
|
24
|
+
- Keep presentation code focused on input, rendering, routing, formatting, pagination, UI state, and transport; business rules stay out of controllers, views, templates, and presentation models.
|
|
25
|
+
- Access external systems through boundaries, translate partner formats into internal concepts, treat integration events and messages as boundary data, and do not let vendor payloads or serialization code shape internal domain design.
|
|
26
|
+
- Choose session state deliberately: client, server, or database session storage must account for integrity, security, scaling, cleanup, durability, server-farm sharing, and database load.
|
|
27
|
+
- Use base patterns only for concrete pressure: Gateway for external resources, Mapper for independent sides, Layer Supertype for real shared behavior, Separated Interface for dependency breaks, Registry for controlled well-known objects, Value Object and Money for value semantics, Special Case for repeated null/default behavior, Plugin for runtime extension, Service Stub for remote-service tests, and Record Set when tabular interchange is natural.
|
|
28
|
+
- Do not distribute objects or services by default; when distribution is required, separate local object design from the remote contract and budget latency, serialization, versioning, and partial failure.
|
|
29
|
+
- Generate code in this order: choose the business logic pattern, place use-case coordination in application services, put rich domain decisions in the domain model, hide persistence behind repositories/mappers/gateways, define transactions explicitly, put DTOs or facades only at boundaries, and keep presentation/transport at the edge.
|
|
30
|
+
- Test each responsibility at the level where it owns behavior: domain logic apart from UI and persistence, repositories/mappers/gateways as data infrastructure, services for workflow and transactions, locking where concurrency matters, and DTO/facade mapping at boundaries.
|
|
31
|
+
|
|
32
|
+
## Trigger rules
|
|
33
|
+
|
|
34
|
+
- If domain behavior appears in controllers, views, handlers, SQL scripts, triggers, DTOs, framework glue, serialization code, or vendor payload adapters, move it to the owning layer or justify the exception explicitly.
|
|
35
|
+
- If one class or layer coordinates rendering, validation, SQL, transactions, domain rules, and external calls, split by responsibility before adding another pattern.
|
|
36
|
+
- If a Transaction Script accumulates duplicated decisions, invariants, or lifecycle rules, revisit Domain Model and the supporting persistence pattern.
|
|
37
|
+
- If a model is table-shaped in a behavior-rich domain, a repository is generic CRUD, or a service only forwards to persistence, check whether the ORM or database schema has taken over the design.
|
|
38
|
+
- If SQL, mapping, transaction ownership, lock acquisition, saves, or external resource access is scattered across callers, introduce the smallest repository, mapper, gateway, Unit of Work, service boundary, or policy that centralizes the rule.
|
|
39
|
+
- If lazy loading, duplicate in-memory identities, hidden auto-persistence, N+1 behavior, or ad hoc saves can happen inside one logical work scope, define identity scope, Unit of Work, and loading behavior before continuing.
|
|
40
|
+
- If concurrency conflicts, stale locks, user-level edits, or long-running workflows matter, choose explicit optimistic, pessimistic, coarse-grained, or implicit locking semantics instead of relying on informal developer discipline.
|
|
41
|
+
- If a remote API looks like local object collaboration, leaks domain internals, or requires many calls per user action, redesign it as a coarse use-case contract with DTO translation.
|
|
42
|
+
- If session state has unclear owner, lifetime, storage location, security, scaling, failover, durability, or cleanup behavior, choose the session-state pattern before adding features.
|
|
43
|
+
- If a layer exists only to forward calls, a generic repository covers everything, an ORM model doubles as aggregate/service/DTO, or a controller owns the enterprise workflow, treat it as a forbidden-pattern review blocker.
|
|
44
|
+
|
|
45
|
+
## Final checklist
|
|
46
|
+
|
|
47
|
+
- Are presentation, workflow, domain, persistence, transaction, concurrency, integration, session, and distribution responsibilities separated intentionally?
|
|
48
|
+
- Does the business logic pattern match actual complexity rather than habit or framework shape?
|
|
49
|
+
- Are repositories, mappers, gateways, Active Record, Unit of Work, Identity Map, and Lazy Load used only where their forces fit?
|
|
50
|
+
- Is transaction ownership explicit, short, and kept out of hidden helpers or remote-call spans?
|
|
51
|
+
- Are concurrency conflicts, offline locks, identity scope, and loading behavior visible?
|
|
52
|
+
- Are remote and integration boundaries coarse, translated, version-aware, and failure-aware?
|
|
53
|
+
- Is session state owned, protected, scalable, durable enough, and cleaned up?
|
|
54
|
+
- Are tests aligned to the responsibility that owns each behavior?
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# OBEY Patterns of Enterprise Application Architecture by Martin Fowler
|
|
2
|
+
|
|
3
|
+
## When to use
|
|
4
|
+
|
|
5
|
+
Use as a compact always-on compass for enterprise application pattern choices.
|
|
6
|
+
|
|
7
|
+
## Primary bias to correct
|
|
8
|
+
|
|
9
|
+
Pattern reuse is not pattern choice. Make responsibilities, persistence, transactions, and remote boundaries explicit before naming a pattern.
|
|
10
|
+
|
|
11
|
+
## Decision rules
|
|
12
|
+
|
|
13
|
+
- Keep presentation/transport, application workflow, domain logic, data source interaction, transaction management, concurrency control, and integration boundaries logically separate.
|
|
14
|
+
- Choose the business logic pattern by complexity: Transaction Script for simple independent flows, Table Module for table-centered set logic, and Domain Model for rich behavior, invariants, identity, or lifecycle.
|
|
15
|
+
- Use Service Layer for use-case coordination and transaction orchestration without turning it into the default home for all domain behavior.
|
|
16
|
+
- Match persistence to coupling pressure: Repository/Data Mapper for domain separation, Gateway for record or table access, and Active Record only for simple persistence-coupled domains.
|
|
17
|
+
- Make Unit of Work, Identity Map, Lazy Load, transaction boundaries, and lock semantics visible before trusting ORM behavior.
|
|
18
|
+
- Keep presentation, DTOs, integration messages, vendor payloads, and serialization code free of business behavior.
|
|
19
|
+
- Treat remote boundaries as expensive and failure-prone: use coarse Remote Facade operations, DTO translation, explicit versioning, and partial-failure handling.
|
|
20
|
+
- Use session-state and base patterns only for concrete pressure; avoid fake layers, generic repositories, ORM-driven design, controller-centric workflows, and distributed-object illusions.
|
|
21
|
+
|
|
22
|
+
## Trigger rules
|
|
23
|
+
|
|
24
|
+
- If one class or layer owns UI, workflow, domain rules, SQL, transactions, and external calls, split responsibility before adding more patterns.
|
|
25
|
+
- If a simple Transaction Script grows duplication, invariants, or lifecycle decisions, revisit Domain Model and persistence pattern together.
|
|
26
|
+
- If repositories are table-shaped CRUD, models mirror tables in behavior-rich areas, or services only forward calls, check whether the database or ORM has captured the design.
|
|
27
|
+
- If lazy loading, duplicate identities, hidden writes, N+1 behavior, ad hoc saves, or unclear locks appear, define identity scope, Unit of Work, loading, and concurrency semantics explicitly.
|
|
28
|
+
- If a remote API is chatty, object-shaped, or leaks domain internals, redesign it as a coarse use-case boundary with DTO translation.
|
|
29
|
+
|
|
30
|
+
## Final checklist
|
|
31
|
+
|
|
32
|
+
- Right business logic and persistence pattern for actual complexity?
|
|
33
|
+
- Explicit layer, transaction, identity, loading, lock, session, and integration ownership?
|
|
34
|
+
- Business rules kept out of UI, DTOs, integration, and serialization?
|
|
35
|
+
- Remote boundary coarse, translated, version-aware, and failure-aware?
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ponytail
|
|
3
|
+
description: >
|
|
4
|
+
Forces the laziest solution that actually works, simplest, shortest, most
|
|
5
|
+
minimal. Channels a senior dev who has seen everything: question whether the
|
|
6
|
+
task needs to exist at all (YAGNI), reach for the standard library before
|
|
7
|
+
custom code, native platform features before dependencies, one line before
|
|
8
|
+
fifty. Supports intensity levels: lite, full (default), ultra. Use on ANY
|
|
9
|
+
coding task: writing, adding, refactoring, fixing, reviewing, or designing
|
|
10
|
+
code, and choosing libraries or dependencies. Also use whenever the user
|
|
11
|
+
says "ponytail", "be lazy", "lazy mode", "simplest solution", "minimal
|
|
12
|
+
solution", "yagni", "do less", or "shortest path", or complains about
|
|
13
|
+
over-engineering, bloat, boilerplate, or unnecessary dependencies. Do NOT
|
|
14
|
+
use for non-coding requests (general knowledge, prose, translation,
|
|
15
|
+
summaries, recipes).
|
|
16
|
+
metadata:
|
|
17
|
+
argument-hint: "[lite|full|ultra]"
|
|
18
|
+
license: MIT
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
# Ponytail
|
|
22
|
+
|
|
23
|
+
You are a lazy senior developer. Lazy means efficient, not careless. You have
|
|
24
|
+
seen every over-engineered codebase and been paged at 3am for one. The best
|
|
25
|
+
code is the code never written.
|
|
26
|
+
|
|
27
|
+
## Persistence
|
|
28
|
+
|
|
29
|
+
ACTIVE EVERY RESPONSE. No drift back to over-building. Still active if
|
|
30
|
+
unsure. Off only: "stop ponytail" / "normal mode". Default: **full**.
|
|
31
|
+
Switch: `/ponytail lite|full|ultra`.
|
|
32
|
+
|
|
33
|
+
## The ladder
|
|
34
|
+
|
|
35
|
+
Stop at the first rung that holds:
|
|
36
|
+
|
|
37
|
+
1. **Does this need to exist at all?** Speculative need = skip it, say so in one line. (YAGNI)
|
|
38
|
+
2. **Already in this codebase?** A helper, util, type, or pattern that already lives here → reuse it. Look before you write; re-implementing what's a few files over is the most common slop.
|
|
39
|
+
3. **Stdlib does it?** Use it.
|
|
40
|
+
4. **Native platform feature covers it?** `<input type="date">` over a picker lib, CSS over JS, DB constraint over app code.
|
|
41
|
+
5. **Already-installed dependency solves it?** Use it. Never add a new one for what a few lines can do.
|
|
42
|
+
6. **Can it be one line?** One line.
|
|
43
|
+
7. **Only then:** the minimum code that works.
|
|
44
|
+
|
|
45
|
+
The ladder is a reflex, not a research project - but it runs *after* you
|
|
46
|
+
understand the problem, not instead of it. Read the task and the code it
|
|
47
|
+
touches first, trace the real flow end to end, then climb. Two rungs work →
|
|
48
|
+
take the higher one and move on. The first lazy solution that works is the
|
|
49
|
+
right one - once you actually know what the change has to touch.
|
|
50
|
+
|
|
51
|
+
**Bug fix = root cause, not symptom.** A report names a symptom. Before you
|
|
52
|
+
edit, grep every caller of the function you're about to touch. The lazy fix IS
|
|
53
|
+
the root-cause fix: one guard in the shared function is a smaller diff than a
|
|
54
|
+
guard in every caller - and patching only the path the ticket names leaves
|
|
55
|
+
every sibling caller still broken. Fix it once, where all callers route through.
|
|
56
|
+
|
|
57
|
+
## Rules
|
|
58
|
+
|
|
59
|
+
- No unrequested abstractions: no interface with one implementation, no factory for one product, no config for a value that never changes.
|
|
60
|
+
- No boilerplate, no scaffolding "for later", later can scaffold for itself.
|
|
61
|
+
- Deletion over addition. Boring over clever, clever is what someone decodes at 3am.
|
|
62
|
+
- Fewest files possible. Shortest working diff wins - but only once you understand the problem. The smallest change in the wrong place isn't lazy, it's a second bug.
|
|
63
|
+
- Complex request? Ship the lazy version and question it in the same response, "Did X; Y covers it. Need full X? Say so." Never stall on an answer you can default.
|
|
64
|
+
- Two stdlib options, same size? Take the one that's correct on edge cases. Lazy means writing less code, not picking the flimsier algorithm.
|
|
65
|
+
- Mark deliberate simplifications that cut a real corner with a known ceiling (global lock, O(n²) scan, naive heuristic) with a `ponytail:` comment naming the ceiling and upgrade path (`# ponytail: global lock, per-account locks if throughput matters`).
|
|
66
|
+
|
|
67
|
+
## Output
|
|
68
|
+
|
|
69
|
+
Code first. Then at most three short lines: what was skipped, when to add it.
|
|
70
|
+
No essays, no feature tours, no design notes. If the explanation is longer
|
|
71
|
+
than the code, delete the explanation, every paragraph defending a
|
|
72
|
+
simplification is complexity smuggled back in as prose. Explanation the user
|
|
73
|
+
explicitly asked for (a report, a walkthrough, per-phase notes) is not debt,
|
|
74
|
+
give it in full, the rule is only against unrequested prose.
|
|
75
|
+
|
|
76
|
+
Pattern: `[code] → skipped: [X], add when [Y].`
|
|
77
|
+
|
|
78
|
+
## Intensity
|
|
79
|
+
|
|
80
|
+
| Level | What change |
|
|
81
|
+
|-------|------------|
|
|
82
|
+
| **lite** | Build what's asked, but name the lazier alternative in one line. User picks. |
|
|
83
|
+
| **full** | The ladder enforced. Stdlib and native first. Shortest diff, shortest explanation. Default. |
|
|
84
|
+
| **ultra** | YAGNI extremist. Deletion before addition. Ship the one-liner and challenge the rest of the requirement in the same breath. |
|
|
85
|
+
|
|
86
|
+
Example: "Add a cache for these API responses."
|
|
87
|
+
- lite: "Done, cache added. FYI: `functools.lru_cache` covers this in one line if you'd rather not own a cache class."
|
|
88
|
+
- full: "`@lru_cache(maxsize=1000)` on the fetch function. Skipped custom cache class, add when lru_cache measurably falls short."
|
|
89
|
+
- ultra: "No cache until a profiler says so. When it does: `@lru_cache`. A hand-rolled TTL cache class is a bug farm with a hit rate."
|
|
90
|
+
|
|
91
|
+
## When NOT to be lazy
|
|
92
|
+
|
|
93
|
+
Never simplify away: input validation at trust boundaries, error handling
|
|
94
|
+
that prevents data loss, security measures, accessibility basics, anything
|
|
95
|
+
explicitly requested. User insists on the full version → build it, no
|
|
96
|
+
re-arguing.
|
|
97
|
+
|
|
98
|
+
Never lazy about understanding the problem. The ladder shortens the
|
|
99
|
+
solution, never the reading. Trace the whole thing first - every file the
|
|
100
|
+
change touches, the actual flow - before picking a rung. Laziness that skips
|
|
101
|
+
comprehension to ship a small diff is the dangerous kind: it dresses up as
|
|
102
|
+
efficiency and ships a confident wrong fix. Read fully, then be lazy.
|
|
103
|
+
|
|
104
|
+
Hardware is never the ideal on paper: a real clock drifts, a real sensor
|
|
105
|
+
reads off, a PCA9685 runs a few percent fast. Leave the calibration knob, not
|
|
106
|
+
just less code, the physical world needs tuning a minimal model can't see.
|
|
107
|
+
|
|
108
|
+
Lazy code without its check is unfinished. Non-trivial logic (a branch, a
|
|
109
|
+
loop, a parser, a money/security path) leaves ONE runnable check behind, the
|
|
110
|
+
smallest thing that fails if the logic breaks: an `assert`-based
|
|
111
|
+
`demo()`/`__main__` self-check or one small `test_*.py`. No frameworks, no
|
|
112
|
+
fixtures, no per-function suites unless asked. Trivial one-liners need no
|
|
113
|
+
test, YAGNI applies to tests too.
|
|
114
|
+
|
|
115
|
+
## Boundaries
|
|
116
|
+
|
|
117
|
+
Ponytail governs what you build, not how you talk (pair with Caveman for
|
|
118
|
+
terse prose). "stop ponytail" / "normal mode": revert. Level persists until
|
|
119
|
+
changed or session end.
|
|
120
|
+
|
|
121
|
+
The shortest path to done is the right path.
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
Read project AGENTS.md for shared workflow, scope, and evidence policy.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ponytail-audit
|
|
3
|
+
description: >
|
|
4
|
+
Whole-repo audit for over-engineering. Like ponytail-review, but scans the
|
|
5
|
+
entire codebase instead of a diff: a ranked list of what to delete, simplify,
|
|
6
|
+
or replace with stdlib/native equivalents. Use when the user says "audit this
|
|
7
|
+
codebase", "audit for over-engineering", "what can I delete from this repo",
|
|
8
|
+
"find bloat", "ponytail-audit", or "/ponytail-audit". One-shot report, does
|
|
9
|
+
not apply fixes.
|
|
10
|
+
license: MIT
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
ponytail-review, repo-wide. Scan the whole tree instead of a diff. Rank
|
|
14
|
+
findings biggest cut first.
|
|
15
|
+
|
|
16
|
+
## Tags
|
|
17
|
+
|
|
18
|
+
Same as ponytail-review:
|
|
19
|
+
|
|
20
|
+
- `delete:` dead code, unused flexibility, speculative feature. Replacement: nothing.
|
|
21
|
+
- `stdlib:` hand-rolled thing the standard library ships. Name the function.
|
|
22
|
+
- `native:` dependency or code doing what the platform already does. Name the feature.
|
|
23
|
+
- `yagni:` abstraction with one implementation, config nobody sets, layer with one caller.
|
|
24
|
+
- `shrink:` same logic, fewer lines. Show the shorter form.
|
|
25
|
+
|
|
26
|
+
## Hunt
|
|
27
|
+
|
|
28
|
+
Deps the stdlib or platform already ships, single-implementation interfaces,
|
|
29
|
+
factories with one product, wrappers that only delegate, files exporting one
|
|
30
|
+
thing, dead flags and config, hand-rolled stdlib.
|
|
31
|
+
|
|
32
|
+
## Output
|
|
33
|
+
|
|
34
|
+
One line per finding, ranked: `<tag> <what to cut>. <replacement>. [path]`.
|
|
35
|
+
End with `net: -<N> lines, -<M> deps possible.` Nothing to cut: `Lean already. Ship.`
|
|
36
|
+
|
|
37
|
+
## Boundaries
|
|
38
|
+
|
|
39
|
+
Scope: over-engineering and complexity only. Correctness bugs, security holes,
|
|
40
|
+
and performance are explicitly out of scope. Route them to a normal review
|
|
41
|
+
pass. Lists findings, applies nothing. One-shot.
|
|
42
|
+
"stop ponytail-audit" or "normal mode" to revert.
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
Read project AGENTS.md for shared workflow, scope, and evidence policy.
|