rhachet-roles-ehmpathy 1.15.21 → 1.15.23

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.
Files changed (56) hide show
  1. package/dist/domain.roles/mechanic/briefs/.archive/_mech.compressed.md +1 -1
  2. package/dist/domain.roles/mechanic/briefs/practices/code.prod/consistent.contracts/ref.package.as-command.[ref].md +1 -1
  3. package/dist/domain.roles/mechanic/briefs/practices/code.prod/evolvable.architecture/rule.require.bounded-contexts.md +3 -3
  4. package/dist/domain.roles/mechanic/briefs/practices/code.prod/evolvable.architecture/rule.require.domain-driven-design.md +7 -7
  5. package/dist/domain.roles/mechanic/briefs/practices/code.prod/evolvable.domain.objects/rule.forbid.undefined-attributes.md +1 -1
  6. package/dist/domain.roles/mechanic/briefs/practices/code.prod/evolvable.domain.operations/define.domain-operation-core-variants.md +122 -0
  7. package/dist/domain.roles/mechanic/briefs/practices/code.prod/evolvable.procedures/rule.forbid.positional-args.md.pt1.md +2 -2
  8. package/dist/domain.roles/mechanic/briefs/practices/code.prod/evolvable.procedures/rule.require.arrow-only.md +4 -4
  9. package/dist/domain.roles/mechanic/briefs/practices/code.prod/evolvable.procedures/rule.require.clear-contracts.md +8 -8
  10. package/dist/domain.roles/mechanic/briefs/practices/code.prod/evolvable.procedures/rule.require.dependency-injection.md.pt1.md +16 -16
  11. package/dist/domain.roles/mechanic/briefs/practices/code.prod/evolvable.procedures/rule.require.dependency-injection.md.pt2.md +1 -1
  12. package/dist/domain.roles/mechanic/briefs/practices/code.prod/evolvable.procedures/rule.require.input-context-pattern.md.pt1.md +2 -2
  13. package/dist/domain.roles/mechanic/briefs/practices/code.prod/evolvable.procedures/rule.require.input-context-pattern.md.pt2.md +5 -5
  14. package/dist/domain.roles/mechanic/briefs/practices/code.prod/evolvable.procedures/rule.require.named-args.md +2 -2
  15. package/dist/domain.roles/mechanic/briefs/practices/code.prod/evolvable.procedures/rule.require.single-responsibility.md +2 -2
  16. package/dist/domain.roles/mechanic/briefs/practices/code.prod/evolvable.repo.structure/rule.forbid.barrel-exports.md +2 -2
  17. package/dist/domain.roles/mechanic/briefs/practices/code.prod/evolvable.repo.structure/rule.require.directional-deps.md +3 -3
  18. package/dist/domain.roles/mechanic/briefs/practices/code.prod/pitofsuccess.errors/rule.forbid.error-hiding.md.pt1.md +2 -2
  19. package/dist/domain.roles/mechanic/briefs/practices/code.prod/pitofsuccess.errors/rule.prefer.helpful-error-wrap.md +1 -1
  20. package/dist/domain.roles/mechanic/briefs/practices/code.prod/pitofsuccess.errors/rule.require.fail-fast.md +11 -11
  21. package/dist/domain.roles/mechanic/briefs/practices/code.prod/pitofsuccess.procedures/rule.require.idempotency.[seed].md +1 -1
  22. package/dist/domain.roles/mechanic/briefs/practices/code.prod/pitofsuccess.procedures/rule.require.idempotent-procedures.md +5 -5
  23. package/dist/domain.roles/mechanic/briefs/practices/code.prod/pitofsuccess.procedures/rule.require.immutable-vars.md +3 -3
  24. package/dist/domain.roles/mechanic/briefs/practices/code.prod/pitofsuccess.procedures/rule.require.pitofsuccess.md +5 -5
  25. package/dist/domain.roles/mechanic/briefs/practices/code.prod/pitofsuccess.typedefs/define.bivariance-for-generics.[lesson].md +6 -6
  26. package/dist/domain.roles/mechanic/briefs/practices/code.prod/pitofsuccess.typedefs/rule.forbid.as-cast.md +6 -6
  27. package/dist/domain.roles/mechanic/briefs/practices/code.prod/pitofsuccess.typedefs/rule.require.shapefit.md +11 -11
  28. package/dist/domain.roles/mechanic/briefs/practices/code.prod/readable.comments/rule.require.what-why-headers.md +4 -4
  29. package/dist/domain.roles/mechanic/briefs/practices/code.prod/readable.comments/rule.require.what-why-headers.v1.md +6 -6
  30. package/dist/domain.roles/mechanic/briefs/practices/code.prod/readable.narrative/rule.prefer.transformers-over-conditionals.[lesson].md +3 -3
  31. package/dist/domain.roles/mechanic/briefs/practices/code.prod/readable.narrative/rule.require.narrative-flow.md +3 -3
  32. package/dist/domain.roles/mechanic/briefs/practices/code.test/consistent.contracts/ref.package.test-fns.[ref].md +8 -8
  33. package/dist/domain.roles/mechanic/briefs/practices/code.test/frames.behavior/howto.write-bdd.[lesson].md +9 -9
  34. package/dist/domain.roles/mechanic/briefs/practices/code.test/frames.behavior/howto.write-bdd.[lesson].pt2.md +1 -1
  35. package/dist/domain.roles/mechanic/briefs/practices/code.test/frames.behavior/rule.require.given-when-then.md +2 -2
  36. package/dist/domain.roles/mechanic/briefs/practices/code.test/frames.caselist/rule.prefer.data-driven.md +1 -1
  37. package/dist/domain.roles/mechanic/briefs/practices/code.test/lessons.howto/howto.diagnose.[lesson].md +2 -2
  38. package/dist/domain.roles/mechanic/briefs/practices/code.test/lessons.howto/howto.use.[lesson].md +1 -1
  39. package/dist/domain.roles/mechanic/briefs/practices/code.test/lessons.howto/howto.write.[lesson].md.pt2.md +1 -1
  40. package/dist/domain.roles/mechanic/briefs/practices/code.test/lessons.howto/rule.require.snapshots.[lesson].md +2 -2
  41. package/dist/domain.roles/mechanic/briefs/practices/lang.terms/define.exec-vs-apply.md +9 -9
  42. package/dist/domain.roles/mechanic/briefs/practices/lang.terms/rule.forbid.gerunds.md +84 -0
  43. package/dist/domain.roles/mechanic/briefs/practices/lang.terms/rule.forbid.term-script.md.pt2.md +1 -1
  44. package/dist/domain.roles/mechanic/briefs/practices/lang.terms/rule.require.order.noun_adj.md.pt2.md +76 -0
  45. package/dist/domain.roles/mechanic/briefs/practices/lang.terms/rule.require.treestruct.md +8 -8
  46. package/dist/domain.roles/mechanic/briefs/practices/lang.terms/rule.require.ubiqlang.md +8 -8
  47. package/dist/domain.roles/mechanic/briefs/practices/lang.tones/.readme.md +1 -1
  48. package/dist/domain.roles/mechanic/briefs/practices/lang.tones/rule.prefer.lowercase.md +4 -4
  49. package/dist/domain.roles/mechanic/briefs/practices/work.flow/diagnose/howto.bisect.[lesson].md +4 -4
  50. package/dist/domain.roles/mechanic/briefs/practices/work.flow/diagnose/rule.forbid.trust-vscode-diagnostics.md +1 -1
  51. package/dist/domain.roles/mechanic/briefs/practices/work.flow/refactor/rule.prefer.sedreplace-for-renames.md +10 -10
  52. package/dist/domain.roles/mechanic/briefs/practices/work.flow/refactor/rule.require.review-test-changes.md +1 -1
  53. package/dist/domain.roles/mechanic/briefs/practices/work.flow/tools/rule.require.externalized-knowledge.md +1 -1
  54. package/dist/domain.roles/mechanic/inits/init.claude.permissions.jsonc +5 -0
  55. package/package.json +4 -2
  56. package/readme.md +1 -1
@@ -14,7 +14,7 @@
14
14
  - ### **funcs:arrow-only**
15
15
  - **rule**: all procedures must be declared as arrow functions
16
16
  - `function` keyword is **disallowed**, even for exports
17
- - object methods are allowed only inside class or API contracts
17
+ - object methods are allowed only inside class or api contracts
18
18
  - always destructure `input` as first argument when applicable
19
19
  - **example:**
20
20
  ```ts
@@ -1,4 +1,4 @@
1
- when using `@ehmpathy/as-command`, no need to manage output dirs yourslef
1
+ with `@ehmpathy/as-command`, no need to manage output dirs yourself
2
2
 
3
3
  simply use context.out.write()
4
4
 
@@ -1,6 +1,6 @@
1
1
  .tactic = arch:bounded-contexts
2
2
 
3
- .what = enforce clear separation of concerns using bounded contexts — each domain must own its logic, models, and procedures
3
+ .what = enforce clear separation of concerns via bounded contexts — each domain must own its logic, models, and procedures
4
4
 
5
5
  .scope:
6
6
  - applies to all modules, folders, stitched routes, domain objects, and services
@@ -8,7 +8,7 @@
8
8
 
9
9
  .why:
10
10
  - upholds the **single responsibility principle** at the system level:
11
- - each context owns exactly one domain concern (e.g. invoicing, job management, customer data)
11
+ - each context owns exactly one domain concern (e.g. invoice, job, customer data)
12
12
  - enforces **low-trust contracts** between contexts:
13
13
  - no assumptions about internal structures or invariants of other domains
14
14
  - all interaction must happen through **explicit, versionable contracts**
@@ -40,7 +40,7 @@
40
40
  .positive:
41
41
  - `job/JobQuote.ts` imports `CustomerPhoneUpdate` from `contracts/`, not from `customer/logic/`
42
42
  - `invoice/` has its own `InvoiceDraft`, `InvoiceFinal`, and `generateInvoice.ts`
43
- - `routes/submitJob.ts` orchestrates job + invoice by stitching, not by importing both
43
+ - `routes/submitJob.ts` orchestrates job + invoice via stitch, not via import of both
44
44
 
45
45
  .negative:
46
46
  - `job.ts` imports `from '../../invoice/utils.ts'` ⛔ reach-in
@@ -1,6 +1,6 @@
1
1
  .tactic = arch:domain-driven-design
2
2
 
3
- .what = model all business logic using well-defined domain objects, procedures, and contracts — never loose bags of properties
3
+ .what = model all business logic via well-defined domain objects, procedures, and contracts — never loose bags of properties
4
4
 
5
5
  .scope:
6
6
  - applies to all business logic, application services, types, data flows, and stateful modules
@@ -28,16 +28,16 @@
28
28
  - if a `Customer`, `Invoice`, or `Quote` already exists, reuse it — don’t make a new shape
29
29
  - support **runtime validation** with schemas (Zod, Joi, Yup)
30
30
  - all domain objects with external inputs must be validated on instantiation
31
- - define `.unique` and `.updatable` fields for identity and change tracking
32
- - expose immutable behaviors using `.clone()` and `.build()` for safe updates
33
- - procedures with more than 2 scalar arguments representing **data** should be refactored to use a domain object
31
+ - define `.unique` and `.updatable` fields for identity and change detection
32
+ - expose immutable behaviors via `.clone()` and `.build()` for safe updates
33
+ - procedures with more than 2 scalar arguments that represent **data** should be refactored to use a domain object
34
34
  - control/options args are acceptable when clearly scoped (e.g. `{ dryRun: true }`)
35
35
 
36
36
  .enforcement:
37
37
  - code reviews must block untyped or loosely typed `{}` logic
38
38
  - procedures with more than 2 scalar arguments should be refactored to use domain objects
39
39
  - stitched routes and service layers must pass domain objects explicitly
40
- - tests should validate domain behavior, not just JSON shape
40
+ - tests should validate domain behavior, not just json shape
41
41
  - imports from `domain-objects` are required for any core domain concept
42
42
 
43
43
  .examples:
@@ -52,8 +52,8 @@
52
52
  .negative:
53
53
  - `{ name, email, address }` passed between modules without a domain object
54
54
  - `function updateUser(name, email, phone)` instead of `updateCustomerInfo(Customer)`
55
- - `type UserData = { ... }` duplicating `Customer` shape
56
- - storing JSON blobs that replicate existing domain models
55
+ - `type UserData = { ... }` that duplicates `Customer` shape
56
+ - stored json blobs that replicate prior domain models
57
57
  - `update()` method used on raw DTOs
58
58
 
59
59
  .links:
@@ -4,7 +4,7 @@ never allow "undefined" attributes for domain objects UNLESS they are database-g
4
4
  i.e.,
5
5
  - ids, createdAt, updatedAt, etc - these are allowed to be undefined, since they're metadata, and only known on read
6
6
 
7
- however, everything else should be explicitly knowable
7
+ however, all else should be explicitly knowable
8
8
  - if we know that it is null, then set it as null
9
9
  - however, we should be really clear as to WHY it can be null; if there is no good domain reason for null, forbid it
10
10
  - otherwise, define the exact type
@@ -0,0 +1,122 @@
1
+ ### .define = domain-operation-core-variants
2
+
3
+ #### .what
4
+ domain.operations contains two fundamental variants of leaf operations:
5
+ - **compute*** = deterministic computed work (pure functions, no external dependencies)
6
+ - **imagine*** = probabilistic creative work via `context.brain.repl.imagine({ role })`
7
+
8
+ #### .when
9
+ - most projects only have deterministic operations — no `brain.repl` invocations
10
+ - in these cases, the `compute*` prefix is **not required** (no ambiguity exists)
11
+ - enforcement becomes **mandatory** when a project contains both variants
12
+ - once `imagine*` operations exist in a codebase, `compute*` prefixes become required for clarity
13
+
14
+ #### .scope
15
+ - the `compute*`/`imagine*` prefix applies only to **leaf operations**
16
+ - leaf operations = the ones that actually perform the computation or imagination
17
+ - **composer operations** that orchestrate leaf operations use normal names (e.g., `getInvoice`, `setCustomerPhone`, `syncUserFromProvider`)
18
+ - the prefix signals *what kind of work is done*, not *what kind of work is called*
19
+
20
+ #### .why
21
+ when both variants exist in a codebase, the prefix:
22
+ - clarifies the nature of each leaf operation at a glance
23
+ - sets expectations for testability (deterministic vs probabilistic)
24
+ - signals dependency requirements (pure vs requires brain context)
25
+ - enables appropriate error strategies for each type
26
+ - guides code review focus (logic correctness vs prompt quality)
27
+
28
+ #### .how
29
+
30
+ ##### compute* leaf operations
31
+ - prefix with `compute` (e.g., `computeInvoiceTotal`, `computeHashFromContent`)
32
+ - must be **pure functions** — same input always produces same output
33
+ - **no external dependencies** — no network, no database, no randomness
34
+ - trivially testable with simple input/output assertions
35
+ - can be safely memoized or cached
36
+
37
+ ##### imagine* leaf operations
38
+ - prefix with `imagine` (e.g., `imagineChapterOutline`, `imagineCodeReview`)
39
+ - invoke `context.brain.repl.imagine({ role })` for LLM-powered generation
40
+ - **probabilistic** — same input may produce different valid outputs
41
+ - require snapshot tests or semantic assertions
42
+ - depend on `context.brain` provision
43
+
44
+ ##### composer operations
45
+ - use normal verb prefixes (e.g., `get*`, `set*`, `sync*`, ...)
46
+ - orchestrate one or more leaf operations
47
+ - no special prefix required — their behavior is defined by what they compose
48
+
49
+ #### .examples
50
+
51
+ **✅ good — leaf operations with proper prefixes**
52
+ ```ts
53
+ // computeInvoiceTotal.ts — leaf, deterministic
54
+ export const computeInvoiceTotal = (input: { lineItems: LineItem[] }) => {
55
+ return input.lineItems.reduce((sum, item) => sum + item.amount, 0);
56
+ };
57
+
58
+ // imagineChapterSummary.ts — leaf, probabilistic
59
+ export const imagineChapterSummary = async (
60
+ input: { chapter: string },
61
+ context: { brain: Brain },
62
+ ) => {
63
+ return context.brain.repl.imagine({
64
+ role: 'summarizer',
65
+ prompt: `summarize this chapter: ${input.chapter}`,
66
+ });
67
+ };
68
+ ```
69
+
70
+ **✅ good — composer operation with normal name**
71
+ ```ts
72
+ // getInvoiceWithSummary.ts — composes both variants
73
+ export const getInvoiceWithSummary = async (
74
+ input: { invoiceId: string },
75
+ context: { brain: Brain; invoiceDao: InvoiceDao },
76
+ ) => {
77
+ const invoice = await context.invoiceDao.findById(input.invoiceId);
78
+ const total = computeInvoiceTotal({ lineItems: invoice.lineItems });
79
+ const summary = await imagineChapterSummary({ chapter: invoice.notes }, context);
80
+ return { ...invoice, total, summary };
81
+ };
82
+ ```
83
+
84
+ **⛔ bad — prefix misleads**
85
+ ```ts
86
+ // computeResponse.ts — "compute" but actually calls LLM
87
+ export const computeResponse = async (input, context) => {
88
+ return context.brain.repl.imagine({ ... }); // ⛔ prefix misleads
89
+ };
90
+ ```
91
+
92
+ **⛔ bad — ambiguous leaf name (only when both variants exist)**
93
+ ```ts
94
+ // generateTotal.ts — unclear if deterministic or probabilistic
95
+ export const generateTotal = (...) => { ... }
96
+
97
+ // processChapter.ts — verb doesn't signal operation type
98
+ export const processChapter = (...) => { ... }
99
+ ```
100
+
101
+ #### .enforcement
102
+ - leaf operations that call `context.brain` must use `imagine*` prefix
103
+ - leaf operations prefixed with `compute*` must be pure and deterministic
104
+ - prefix mismatch vs implementation = **BLOCKER**
105
+ - ambiguous leaf names in a codebase with both variants = **BLOCKER**
106
+
107
+ ---
108
+
109
+ #### .appendix: brain terminology
110
+
111
+ ##### brain.atom
112
+ - the atomic unit of LLM interaction
113
+ - a single LLM api call (e.g., one completion request)
114
+ - stateless, no memory of prior calls
115
+ - e.g., **Claude api** = one `messages.create()` call
116
+
117
+ ##### brain.repl
118
+ - **r**ead, **e**xecute, **p**rint, **l**oop
119
+ - orchestrates `brain.atom` calls within a tooluse loop
120
+ - enables multi-turn reason with tool execution between steps
121
+ - `brain.repl.imagine({ role })` = invoke the repl to imagine/generate via the specified role
122
+ - e.g., **Claude Code** = agentic loop that reads files, executes tools, prints results, loops until done
@@ -36,8 +36,8 @@ vs
36
36
 
37
37
 
38
38
 
39
- - Self-documenting: You can see what each parameter is at the call site
39
+ - Self-documented: You can see what each parameter is at the call site
40
40
  - Order-independent: Arguments can be passed in any order
41
- - Easier to maintain: Adding new optional parameters won't break existing calls
41
+ - Easier to maintain: New optional parameters won't break prior calls
42
42
  - Validation: Each function validates required parameters
43
43
  - Usage examples: Included in function headers
@@ -1,16 +1,16 @@
1
1
  ### .tactic = funcs:arrow-only
2
2
 
3
3
  #### .what
4
- enforce that all procedures are declared using arrow functions
4
+ enforce that all procedures are declared via arrow functions
5
5
  disallow use of `function` keyword for any procedure
6
6
 
7
7
  #### .where
8
8
  - applies to all exported and internal functions across codebase
9
9
  - required in modules, utilities, hooks, logic, and test declarations
10
- - exempt only for class methods or dynamic `this` binding (rare)
10
+ - exempt only for class methods or dynamic `this` bind (rare)
11
11
 
12
12
  #### .why
13
- - enforces lexical `this` binding for predictable behavior
13
+ - enforces lexical `this` bind for predictable behavior
14
14
  - aligns code structure with uniform declaration style
15
15
  - improves visual clarity and reduces syntactic noise
16
16
  - simplifies use with higher-order functions, closures, and composability
@@ -20,7 +20,7 @@ disallow use of `function` keyword for any procedure
20
20
  ##### .rules
21
21
  - use arrow syntax (`const fn = (input) => {}`) for all functions
22
22
  - never use `function` keyword for standalone or inline functions
23
- - use object methods only when tied to a `class` or API contract
23
+ - use object methods only when tied to a `class` or api contract
24
24
  - always destructure input as the first arg if applicable
25
25
 
26
26
  ##### .examples
@@ -1,20 +1,20 @@
1
1
 
2
2
  .tactic = mech:contract-before-implementation
3
3
 
4
- .what = declare the shape and expectations of behavior (the contract) before writing its implementation
4
+ .what = declare the shape and expectations of behavior (the contract) before the implementation is written
5
5
 
6
6
  .why:
7
- - forces clarity about what is being built and why
8
- - prevents premature optimization and over-engineering
7
+ - forces clarity about what to build and why
8
+ - prevents premature optimization and over-engineer
9
9
  - creates a shared agreement for both the builder and consumer
10
10
  - enables parallel work (e.g., backend + frontend, or logic + UI)
11
11
 
12
12
  .scope:
13
13
  - applies to procedures, stitched flows, and any domain mechanisms
14
- - applies at both macro (API endpoint, service) and micro (function, component) levels
14
+ - applies at both macro (api endpoint, service) and micro (function, component) levels
15
15
 
16
16
  .how:
17
- - always begin with a **procedure type** that defines:
17
+ - always start with a **procedure type** that defines:
18
18
  - function signature or interface
19
19
  - expected inputs and output shape
20
20
  - error modes and invariants
@@ -27,7 +27,7 @@
27
27
 
28
28
  /**
29
29
  * .what = sends an invoice to the customer and marks it as sent
30
- * .why = required for customer billing compliance and automation
30
+ * .why = required for customer bill compliance and automation
31
31
  */
32
32
  export const sendInvoice = async ({
33
33
  invoice,
@@ -43,11 +43,11 @@
43
43
  // logic/sendInvoice.ts
44
44
 
45
45
  export const sendInvoice = async (invoice, customer) => {
46
- // suddenly starts doing 4 things and mutates stuff randomly
46
+ // suddenly starts to do 4 tasks and mutates stuff randomly
47
47
  };
48
48
 
49
49
  .enforcement:
50
50
  - if a PR implements logic without any visible contract: **blocker**
51
51
  - if types are vague or inferred (e.g. `any`, `unknown`): **blocker**
52
- - if behavior differs from contract or lacks a test: **blocker**
52
+ - if behavior differs from contract or a test is absent: **blocker**
53
53
 
@@ -1,22 +1,22 @@
1
1
  ## 🧠 `.brief.designer.dependency-injection`
2
2
 
3
3
  ### 🧠 topic: dependency injection
4
- **why we pass in dependencies instead of hardcoding them**
4
+ **why we pass in dependencies instead of hardcode them**
5
5
 
6
6
  ---
7
7
 
8
8
  ### 🎯 goal
9
9
  build software that is **flexible, testable, and decoupled**,
10
- by making dependencies **explicit, swappable, and controlled from the outside**.
10
+ via dependencies that are **explicit, swappable, and controlled from the outside**.
11
11
 
12
12
  ---
13
13
 
14
14
  ### 🛠 what it is
15
15
 
16
- > **dependency injection** = giving a function, class, or module what it needs from the outside,
17
- > rather than letting it construct or look up those tools internally.
16
+ > **dependency injection** = to give a function, class, or module what it needs from the outside,
17
+ > rather than to let it construct or look up those tools internally.
18
18
 
19
- for example, instead of having a function reach for its own dependencies:
19
+ for example, instead of a function that reaches for its own dependencies:
20
20
 
21
21
  ```ts
22
22
  // ❌ tightly coupled and side-effect prone
@@ -46,12 +46,12 @@ export const upsert = async (
46
46
  ```
47
47
 
48
48
  - the function doesn’t reach into globals or construct its own tools
49
- - everything it needs is **passed in from the outside**, making it testable, predictable, and side-effect free
49
+ - all it needs is **passed in from the outside**, which makes it testable, predictable, and side-effect free
50
50
 
51
51
  ---
52
52
 
53
53
  ### 🔑 paved pattern: `(input, context)`
54
- dependency injection is best done by following the **standard procedure contract**:
54
+ dependency injection is best done via the **standard procedure contract**:
55
55
 
56
56
  ```ts
57
57
  export const doThing = async (
@@ -62,7 +62,7 @@ export const doThing = async (
62
62
 
63
63
  - all dependencies go in the `context` argument
64
64
  - keeps `input` clean, and `context` flexible
65
- - enables composition, tracing, and full test control
65
+ - enables composition, trace, and full test control
66
66
 
67
67
 
68
68
  ---
@@ -70,9 +70,9 @@ export const doThing = async (
70
70
  ### 🤝 why it matters
71
71
 
72
72
  - **testability** — swap real dependencies with mocks/fakes
73
- - **flexibility** — easily change implementations without changing core logic
74
- - **separation of concerns** — business logic doesn't manage its own plumbing
75
- - **explicitness** — makes system wiring visible and intentional
73
+ - **flexibility** — easily change implementations without core logic change
74
+ - **separation of concerns** — business logic doesn't manage its own plumb
75
+ - **explicitness** — makes system wires visible and intentional
76
76
  - **reusability** — same logic can be reused with different behaviors
77
77
 
78
78
  ---
@@ -88,7 +88,7 @@ you keep **policies and tools separate from behaviors**.
88
88
 
89
89
  ### 🔍 mental model
90
90
 
91
- > dependency injection is like **plugging in a tool** instead of **building one every time**.
91
+ > dependency injection is like to **plug in a tool** instead of to **build one every time**.
92
92
 
93
93
  your procedures say:
94
94
  > “give me what I need — I don’t care where it came from.”
@@ -100,7 +100,7 @@ your procedures say:
100
100
  | without DI | with DI |
101
101
  |----------------------------------------|--------------------------------------------|
102
102
  | hardcoded database inside procedures | database passed in as via parameters |
103
- | requires real API in tests | can inject mock/fake API for testing |
103
+ | requires real api in tests | can inject mock/fake api for tests |
104
104
  | logic tied to concrete tools | logic works with any compatible tool |
105
105
  | hard to switch infra/tools | swappable with config or environment setup |
106
106
 
@@ -110,9 +110,9 @@ your procedures say:
110
110
 
111
111
  we inject dependencies to build systems that are easier to **test**, **scale**, and **evolve**.
112
112
 
113
- > dependency injection is about building **pure, decoupled, and testable** systems.
113
+ > dependency injection is about to build **pure, decoupled, and testable** systems.
114
114
  > it eliminates shared state, surfaces side effects, and makes your logic portable and composable.
115
115
  > it enables **modularity**, **testability**, and **control**,
116
- > by making **dependencies external** instead of hidden inside.
116
+ > via **external dependencies** instead of hidden inside.
117
117
 
118
- done right, it's **invisible during use**, and **invaluable during testing, scaling, and evolution**.
118
+ done right, it's **invisible when used**, and **invaluable for tests, scale, and evolution**.
@@ -1,6 +1,6 @@
1
1
  todo: declare why dependency injection leads to a pit of success && why global shared state should be avoided
2
2
 
3
- via dependency injection, you always know what's referncing what. no side effects
3
+ via dependency injection, you always know what references what. no side effects
4
4
 
5
5
  persistance is the only global shared state that should exist - and even that should be managed cautiously (e.g., to avoid race conditions)
6
6
 
@@ -8,7 +8,7 @@ enforce hard requirement that all procedure args to follow the canonical pattern
8
8
  - prevents positional argument confusion
9
9
  - supports context injection without argument churn
10
10
  - aligns with domain patterns: input = upstream data, context = runtime environment
11
- - enables safe refactoring and consistent documentation across codebase
11
+ - enables safe refactors and consistent documentation across codebase
12
12
 
13
13
  #### .where
14
14
  - applies to **all function definitions** (sync or async)
@@ -26,7 +26,7 @@ enforce hard requirement that all procedure args to follow the canonical pattern
26
26
  - **hard requirement** — applies even to trivial utilities, pure transforms, and data extractors
27
27
 
28
28
  - `input` does **not** need to be destructured at the function boundary; shape like `(input: { ... })` is fine
29
- - `function` keyword is forbidden unless implementing class methods (see `.tactic:funcs:arrow-only`)
29
+ - `function` keyword is forbidden unless to implement class methods (see `.tactic:funcs:arrow-only`)
30
30
 
31
31
  ##### ❌ forbidden
32
32
  - more than 2 positional args
@@ -17,22 +17,22 @@ export const doSomething = (input: { foo: string; bar: number }): void => {
17
17
  ## .why
18
18
  this pattern maximizes **maintainability** and **readability** by:
19
19
 
20
- 1. **keeping type info local**
20
+ 1. **keep type info local**
21
21
  - no need to jump to another file or scroll to find the interface/type definition.
22
22
  - changes to argument structure are quick and visible in one place.
23
23
 
24
- 2. **reinforcing origin clarity**
25
- - variables from `input` are always referenced as `input.foo` or `input.bar`, making their provenance explicit.
24
+ 2. **reinforce origin clarity**
25
+ - variables from `input` are always referenced as `input.foo` or `input.bar`, which makes their provenance explicit.
26
26
  - this avoids ambiguity in larger scopes, especially when a function mixes locals, constants, and context values.
27
27
 
28
- 3. **avoiding premature fragmentation**
28
+ 3. **avoid premature fragmentation**
29
29
  - not all shapes deserve a named type. we only extract to `type` or `interface` when the same shape is reused across multiple functions or modules.
30
30
 
31
31
  ---
32
32
 
33
33
  ## 📏 rules
34
34
  - declare the first parameter as `(input: { ... })` with inline types by default.
35
- - destructuring is allowed **inside** the function body, never in the parameter list.
35
+ - to destructure is allowed **inside** the function body, never in the parameter list.
36
36
  - optional `context` parameter follows the same pattern `(context?: { ... })` and is always second.
37
37
  - if the type is reused in 3+ places, extract to a named `type` but keep the `input` wrapper.
38
38
 
@@ -1,6 +1,6 @@
1
1
  always used named arguments on inputs
2
2
 
3
- they make it clear when reading what the arguments are used for
3
+ they make it clear when you read what the arguments are used for
4
4
 
5
- they also make it possible to reorder arguments without breaking the contract (great for refactors, deprecations, renames, etc)
5
+ they also make it possible to reorder arguments without to break the contract (great for refactors, deprecations, renames, etc)
6
6
 
@@ -6,7 +6,7 @@ enforce that every code file and procedure has a singular, clearly-defined respo
6
6
  #### .why
7
7
  - makes code easier to locate, understand, and test
8
8
  - ensures separation of concerns between logic, validation, and orchestration
9
- - prevents files from bloating with unrelated logic or creeping concerns
9
+ - prevents files from bloat with unrelated logic or creep concerns
10
10
 
11
11
  #### .rules
12
12
 
@@ -18,7 +18,7 @@ enforce that every code file and procedure has a singular, clearly-defined respo
18
18
 
19
19
  ❌ forbidden
20
20
  - more than one exported procedure per file
21
- - co-locating validation, parsing, or orchestration logic alongside domain logic
21
+ - co-located validation, parse, or orchestration logic alongside domain logic
22
22
  - runtime type assertions or guards inside general-purpose logic
23
23
  - dead code, TODOs, or unrelated comments in the file
24
24
  - guards that apply redundant runtime typechecks (we trust typescript)
@@ -22,9 +22,9 @@ they add zero value
22
22
 
23
23
  ---
24
24
 
25
- the only thing that's allowed is
25
+ the only case that's allowed is
26
26
 
27
- within an index.ts file, exporting one object
27
+ within an index.ts file, to export one object
28
28
 
29
29
  e.g.,
30
30
 
@@ -39,11 +39,11 @@ src/
39
39
  - `contract/` may depend on `domain.objects/` and `domain.operations/`
40
40
  - `access/` may depend on `domain.objects/` and `domain.operations/`
41
41
  - `domain.operations/` may depend on `domain.objects/` or `infra/`
42
- - `domain.objects/` must not depend on anything outside its own layer
43
- - `infra/` must not depend on anything outside its own layer
42
+ - `domain.objects/` must not depend on any module outside its own layer
43
+ - `infra/` must not depend on any module outside its own layer
44
44
 
45
45
  - stitched flows live in `domain.operations/` or `contract/commands/` and orchestrate downstream only
46
- - never import upward across layers (e.g., `domain.objects/` importing `access/`)
46
+ - never import upward across layers (e.g., `domain.objects/` that imports `access/`)
47
47
  - shared types must follow the same directional rules
48
48
 
49
49
  .enforcement
@@ -6,9 +6,9 @@ try/catch
6
6
 
7
7
  ---
8
8
 
9
- the only cases where a trycatch is allowed is if the catch has an allowlist of the errors it catches and CAREFULLY handles those, while throwing the rest up
9
+ the only cases where a trycatch is allowed is if the catch has an allowlist of the errors it catches and CAREFULLY handles those, while it throws the rest up
10
10
 
11
- otherwise, its a failhide hazard, where real errors will be silently hidden, leading to defects or hours of pointless debugging
11
+ otherwise, its a failhide hazard, where real errors will be silently hidden, which leads to defects or hours of pointless debug
12
12
 
13
13
  never failhide
14
14
 
@@ -10,7 +10,7 @@ e.g.,
10
10
 
11
11
  ```ts
12
12
  try {
13
- // do something that throws
13
+ // do task that throws
14
14
  await doSomething({ userUuid })
15
15
  } catch (error) {
16
16
  if (!(error instanceof Error)) throw error;
@@ -1,32 +1,32 @@
1
1
  .tactic = flow:fail-fast
2
2
 
3
- .what = enforce fail-fast logic using early exits and HelpfulError subclasses to reject invalid state or input immediately
3
+ .what = enforce fail-fast logic via early exits and HelpfulError subclasses to reject invalid state or input immediately
4
4
 
5
5
  .scope:
6
6
  - required in all stitched logic, business procedures, and service flows
7
- - applies to guard checks, validations, and branching paths
7
+ - applies to guard checks, validations, and branch paths
8
8
 
9
9
  .why:
10
- - improves readability by collapsing failure paths early
10
+ - improves readability via early collapse of failure paths
11
11
  - eliminates nested branches and lets core logic shine
12
- - increases safety by clearly documenting and halting on invalid input
13
- - makes bugs easier to debug with rich context using `helpful-errors`
12
+ - increases safety via clear documentation and halt on invalid input
13
+ - makes bugs easier to debug with rich context via `helpful-errors`
14
14
 
15
15
  .how:
16
16
  - use **early returns or throws** for all guard clauses
17
- - never use `if (...) else` or deep nesting to control flow
17
+ - never use `if (...) else` or deep nested blocks to control flow
18
18
  - prefer `UnexpectedCodePathError.throw(...)` for internal invariant violations
19
19
  - these signal logic errors that “should never happen”
20
- - prefer `BadRequestError.throw(...)` for rejecting invalid input or user requests
20
+ - prefer `BadRequestError.throw(...)` to reject invalid input or user requests
21
21
  - these signal invalid calls, not system failures
22
22
  - use `.throw(...)` syntax for clean 1-liners inside nullish chains or short circuits
23
- - include **context objects** in all thrown errors to aid debugging
24
- - validate error behavior in tests using `getError(...)`
23
+ - include **context objects** in all thrown errors to aid debug
24
+ - validate error behavior in tests via `getError(...)`
25
25
 
26
26
  .code structure:
27
27
  - treat each guard block as a **code paragraph**
28
- - must be preceded by a comment summarizing *why* the guard exists
29
- - blank line after each guard before continuing main logic
28
+ - must be preceded by a comment that summarizes *why* the guard exists
29
+ - blank line after each guard before main logic continues
30
30
 
31
31
  ```ts
32
32
  // reject if user does not exist
@@ -9,7 +9,7 @@ idempotency means that the same request duplicated will succeed as if it only ra
9
9
 
10
10
  ---
11
11
 
12
- the main methods of doing so are via
12
+ the main methods to do so are via
13
13
 
14
14
  - findsert = find or insert
15
15
  - const before = dao.findByRef()
@@ -1,6 +1,6 @@
1
1
  .tactic = proc:require-idempotency
2
2
 
3
- .what = all procedures must be idempotent unless explicitly marked otherwise — calling the same logic twice must not cause double effects
3
+ .what = all procedures must be idempotent unless explicitly marked otherwise — to call the same logic twice must not cause double effects
4
4
 
5
5
  .scope:
6
6
  - applies to all stitched procedures, exports, and service logic
@@ -13,10 +13,10 @@
13
13
 
14
14
  .how:
15
15
  - all procedures must **guard against re-entry**
16
- - check whether the action has already occurred before executing
16
+ - check whether the action has already occurred before execute
17
17
  - e.g., `if (invoice.status === 'FINAL') return invoice;`
18
- - any **side-effect-producing operation** must:
19
- - check for an existing result (e.g. existing record, idempotency key, state flag)
18
+ - any **side-effect-produce operation** must:
19
+ - check for a prior result (e.g. prior record, idempotency key, state flag)
20
20
  - return early if already complete
21
21
  - **external writes** (db, api, fs, queues) must be safe to call multiple times without duplication
22
22
  - use upserts, conflict-ignore inserts, or external idempotency tokens
@@ -29,7 +29,7 @@
29
29
  - procedures with `set`, `push`, `post`, or other side-effect verbs must show idempotency check
30
30
  - non-idempotent procedures must be annotated with a `.note`
31
31
  - workflows and retry logic must assume re-entry and prove safety
32
- - test cases must show repeat-calling has no additional effect
32
+ - test cases must show repeat-call has no additional effect
33
33
 
34
34
  .examples:
35
35