rhachet-roles-ehmpathy 1.17.17 → 1.17.18

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 (30) hide show
  1. package/dist/domain.roles/mechanic/briefs/.archive/_mech.compressed.md +4 -4
  2. package/dist/domain.roles/mechanic/briefs/.archive/patterns.directional-dependencies.md +5 -5
  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.domain.objects/ref.package.domain-objects.[ref].md +13 -13
  5. package/dist/domain.roles/mechanic/briefs/practices/code.prod/evolvable.domain.operations/define.domain-operation-core-variants.md +5 -5
  6. package/dist/domain.roles/mechanic/briefs/practices/code.prod/evolvable.procedures/rule.forbid.io-as-domain-objects.md +7 -7
  7. package/dist/domain.roles/mechanic/briefs/practices/code.prod/evolvable.procedures/rule.forbid.io-as-interfaces.md +8 -8
  8. package/dist/domain.roles/mechanic/briefs/practices/code.prod/evolvable.procedures/rule.require.arrow-only.md +2 -2
  9. package/dist/domain.roles/mechanic/briefs/practices/code.prod/evolvable.procedures/rule.require.clear-contracts.md +2 -2
  10. package/dist/domain.roles/mechanic/briefs/practices/code.prod/evolvable.procedures/rule.require.dependency-injection.md.pt1.md +2 -2
  11. package/dist/domain.roles/mechanic/briefs/practices/code.prod/evolvable.procedures/rule.require.hook-wrapper-pattern.md +4 -4
  12. package/dist/domain.roles/mechanic/briefs/practices/code.prod/evolvable.procedures/rule.require.input-context-pattern.md.pt1.md +7 -7
  13. package/dist/domain.roles/mechanic/briefs/practices/code.prod/evolvable.procedures/rule.require.input-context-pattern.md.pt2.md +4 -4
  14. package/dist/domain.roles/mechanic/briefs/practices/code.prod/evolvable.procedures/rule.require.single-responsibility.md +9 -9
  15. package/dist/domain.roles/mechanic/briefs/practices/code.prod/evolvable.repo.structure/rule.require.directional-deps.md +5 -5
  16. package/dist/domain.roles/mechanic/briefs/practices/code.prod/pitofsuccess.procedures/rule.require.idempotent-procedures.md +2 -2
  17. package/dist/domain.roles/mechanic/briefs/practices/code.prod/pitofsuccess.procedures/rule.require.immutable-vars.md +3 -3
  18. package/dist/domain.roles/mechanic/briefs/practices/code.prod/pitofsuccess.typedefs/define.bivariance-for-generics.[lesson].md +2 -2
  19. package/dist/domain.roles/mechanic/briefs/practices/code.prod/pitofsuccess.typedefs/rule.forbid.as-cast.md +3 -3
  20. package/dist/domain.roles/mechanic/briefs/practices/code.prod/readable.comments/rule.require.what-why-headers.md +5 -5
  21. package/dist/domain.roles/mechanic/briefs/practices/code.prod/readable.comments/rule.require.what-why-headers.v1.md +4 -4
  22. package/dist/domain.roles/mechanic/briefs/practices/code.test/frames.behavior/howto.write-bdd.[lesson].md +4 -4
  23. package/dist/domain.roles/mechanic/briefs/practices/code.test/frames.behavior/howto.write-bdd.[lesson].pt2.md +8 -8
  24. package/dist/domain.roles/mechanic/briefs/practices/code.test/frames.behavior/rule.require.given-when-then.md +1 -1
  25. package/dist/domain.roles/mechanic/briefs/practices/lang.terms/rule.forbid.gerunds.md +3 -3
  26. package/dist/domain.roles/mechanic/briefs/practices/lang.terms/rule.require.order.noun_adj.md.pt2.md +3 -3
  27. package/dist/domain.roles/mechanic/briefs/practices/lang.terms/rule.require.treestruct.md +5 -5
  28. package/dist/domain.roles/mechanic/briefs/practices/lang.tones/rule.prefer.lowercase.md +5 -5
  29. package/dist/domain.roles/mechanic/briefs/practices/lang.tones/rule.require.term-human.md +2 -2
  30. package/package.json +3 -3
@@ -5,8 +5,8 @@
5
5
  - inline callbacks may be exempt if anonymous + tightly scoped
6
6
  - **example:**
7
7
  ```ts
8
- export const doWork = async (input, context) => { ... } //
9
- export function legacyFunc(a, b) {} //
8
+ export const doWork = async (input, context) => { ... } // 👍
9
+ export function legacyFunc(a, b) {} // 👎
10
10
  ```
11
11
 
12
12
  ---
@@ -18,8 +18,8 @@
18
18
  - always destructure `input` as first argument when applicable
19
19
  - **example:**
20
20
  ```ts
21
- const getName = ({ name }) => name; //
22
- export function getName(name) { return name } //
21
+ const getName = ({ name }) => name; // 👍
22
+ export function getName(name) { return name } // 👎
23
23
  ```
24
24
 
25
25
  ---
@@ -56,7 +56,7 @@ src/
56
56
 
57
57
  .examples
58
58
 
59
- positive
59
+ 👍 positive
60
60
  \`\`\`ts
61
61
  // contract/endpoints/sendInvoice.ts
62
62
  import { generateInvoice } from '@/domain.operations/generateInvoice';
@@ -69,14 +69,14 @@ import { Job } from '@/domain.objects/Job';
69
69
  import { LineItem } from '@/domain.objects/LineItem';
70
70
  \`\`\`
71
71
 
72
- negative
72
+ 👎 negative
73
73
  \`\`\`ts
74
74
  // domain.objects/Customer.ts
75
- import { customerDao } from '@/access/daos/customerDao'; // illegal upward import
75
+ import { customerDao } from '@/access/daos/customerDao'; // 👎 illegal upward import
76
76
 
77
77
  // domain.operations/InvoiceOps.ts
78
- import { runFlow } from '@/contract/commands'; // direction violation
78
+ import { runFlow } from '@/contract/commands'; // 👎 direction violation
79
79
 
80
80
  // access/svcs/sdkWrapper.ts
81
- import { dispatchFlow } from '@/contract/'; // bottom-up reference
81
+ import { dispatchFlow } from '@/contract/'; // 👎 bottom-up reference
82
82
  \`\`\`
@@ -43,9 +43,9 @@
43
43
  - `routes/submitJob.ts` orchestrates job + invoice via stitch, not via import of both
44
44
 
45
45
  .negative:
46
- - `job.ts` imports `from '../../invoice/utils.ts'` reach-in
47
- - `invoiceService.ts` directly updates `customer.email` cross-context mutation
48
- - `customer.ts` imports `JobQuote` and infers state ownership violation
46
+ - `job.ts` imports `from '../../invoice/utils.ts'` 👎 reach-in
47
+ - `invoiceService.ts` directly updates `customer.email` 👎 cross-context mutation
48
+ - `customer.ts` imports `JobQuote` and infers state 👎 ownership violation
49
49
 
50
50
 
51
51
 
@@ -298,16 +298,16 @@ class SeaTurtle extends DomainEntity<SeaTurtle> implements SeaTurtle {
298
298
  public static unique = ['seawaterSecurityNumber'] as const;
299
299
  }
300
300
 
301
- // valid
301
+ // 👍 valid
302
302
  const primaryRef: RefByPrimary<typeof SeaTurtle> = { uuid: 'beefbeef...' };
303
303
 
304
- // invalid - must be a string
304
+ // 👎 invalid - must be a string
305
305
  const wrongType: RefByPrimary<typeof SeaTurtle> = { uuid: 8335 };
306
306
 
307
- // invalid - wrong key
307
+ // 👎 invalid - wrong key
308
308
  const wrongKey: RefByPrimary<typeof SeaTurtle> = { guid: 'beefbeef...' };
309
309
 
310
- // invalid - missing primary key
310
+ // 👎 invalid - missing primary key
311
311
  const missing: RefByPrimary<typeof SeaTurtle> = {};
312
312
  ```
313
313
 
@@ -328,16 +328,16 @@ class SeaTurtle extends DomainEntity<SeaTurtle> implements SeaTurtle {
328
328
  public static unique = ['seawaterSecurityNumber'] as const;
329
329
  }
330
330
 
331
- // valid
331
+ // 👍 valid
332
332
  const uniqueRef: RefByUnique<typeof SeaTurtle> = { seawaterSecurityNumber: 'ABC-999' };
333
333
 
334
- // invalid - wrong type
334
+ // 👎 invalid - wrong type
335
335
  const wrongType: RefByUnique<typeof SeaTurtle> = { seawaterSecurityNumber: 999 };
336
336
 
337
- // invalid - wrong key
337
+ // 👎 invalid - wrong key
338
338
  const wrongKey: RefByUnique<typeof SeaTurtle> = { saltwaterSecurityNumber: 'ABC-999' };
339
339
 
340
- // invalid - empty object
340
+ // 👎 invalid - empty object
341
341
  const empty: RefByUnique<typeof SeaTurtle> = {};
342
342
  ```
343
343
 
@@ -359,22 +359,22 @@ class EarthWorm extends DomainEntity<EarthWorm> implements EarthWorm {
359
359
  public static unique = ['soilSecurityNumber', 'wormSegmentNumber'] as const;
360
360
  }
361
361
 
362
- // primary
362
+ // 👍 primary
363
363
  const byPrimary: Ref<typeof EarthWorm> = { uuid: 'beefbeef...' };
364
364
 
365
- // unique
365
+ // 👍 unique
366
366
  const byUnique: Ref<typeof EarthWorm> = {
367
367
  soilSecurityNumber: 'SOIL-001',
368
368
  wormSegmentNumber: 'SEG-42',
369
369
  };
370
370
 
371
- // invalid - missed part of unique key
371
+ // 👎 invalid - missed part of unique key
372
372
  const incompleteUnique: Ref<typeof EarthWorm> = { soilSecurityNumber: 'SOIL-001' };
373
373
 
374
- // invalid - not related to either key
374
+ // 👎 invalid - not related to either key
375
375
  const wrongKey: Ref<typeof EarthWorm> = { guid: 'beefbeef...' };
376
376
 
377
- // invalid - empty object
377
+ // 👎 invalid - empty object
378
378
  const empty: Ref<typeof EarthWorm> = {};
379
379
  ```
380
380
 
@@ -48,7 +48,7 @@ when both variants exist in a codebase, the prefix:
48
48
 
49
49
  #### .examples
50
50
 
51
- **✅ good — leaf operations with proper prefixes**
51
+ **👍 good — leaf operations with proper prefixes**
52
52
  ```ts
53
53
  // computeInvoiceTotal.ts — leaf, deterministic
54
54
  export const computeInvoiceTotal = (input: { lineItems: LineItem[] }) => {
@@ -67,7 +67,7 @@ export const imagineChapterSummary = async (
67
67
  };
68
68
  ```
69
69
 
70
- **✅ good — composer operation with normal name**
70
+ **👍 good — composer operation with normal name**
71
71
  ```ts
72
72
  // getInvoiceWithSummary.ts — composes both variants
73
73
  export const getInvoiceWithSummary = async (
@@ -81,15 +81,15 @@ export const getInvoiceWithSummary = async (
81
81
  };
82
82
  ```
83
83
 
84
- **⛔ bad — prefix misleads**
84
+ **👎 bad — prefix misleads**
85
85
  ```ts
86
86
  // computeResponse.ts — "compute" but actually calls LLM
87
87
  export const computeResponse = async (input, context) => {
88
- return context.brain.repl.imagine({ ... }); // prefix misleads
88
+ return context.brain.repl.imagine({ ... }); // 👎 prefix misleads
89
89
  };
90
90
  ```
91
91
 
92
- **⛔ bad — ambiguous leaf name (only when both variants exist)**
92
+ **👎 bad — ambiguous leaf name (only when both variants exist)**
93
93
  ```ts
94
94
  // generateTotal.ts — unclear if deterministic or probabilistic
95
95
  export const generateTotal = (...) => { ... }
@@ -30,12 +30,12 @@ forbid domain objects for procedure inputs and outputs; declare them inline on t
30
30
 
31
31
  #### .how
32
32
 
33
- ##### required
33
+ ##### 👍 required
34
34
  - declare input types inline: `(input: { invoice: Invoice; customer: Customer })`
35
35
  - declare return types inline: `): Promise<{ success: boolean; invoice: Invoice }>`
36
36
  - use domain objects as **properties** within inline types, not as the type itself
37
37
 
38
- ##### forbidden
38
+ ##### 👎 forbidden
39
39
  - `class SendInvoiceInput extends DomainLiteral<...>`
40
40
  - `interface GenerateReportOutput { ... }` in a separate file
41
41
  - `type SyncCustomerArgs = { ... }` outside the procedure file
@@ -47,7 +47,7 @@ forbid domain objects for procedure inputs and outputs; declare them inline on t
47
47
 
48
48
  #### .examples
49
49
 
50
- ##### positive
50
+ ##### 👍 positive
51
51
  ```ts
52
52
  /**
53
53
  * .what = sends an invoice to the customer
@@ -74,9 +74,9 @@ export const generateMonthlyReport = async (
74
74
  };
75
75
  ```
76
76
 
77
- ##### negative
77
+ ##### 👎 negative
78
78
  ```ts
79
- // input as domain object — SendInvoiceInput is not a domain concept
79
+ // 👎 input as domain object — SendInvoiceInput is not a domain concept
80
80
  interface SendInvoiceInput {
81
81
  invoice: Invoice;
82
82
  customer: Customer;
@@ -88,7 +88,7 @@ export const sendInvoice = async (input: SendInvoiceInput, context: Context) =>
88
88
  ```
89
89
 
90
90
  ```ts
91
- // output as separate type — pollutes type namespace with transient shapes
91
+ // 👎 output as separate type — pollutes type namespace with transient shapes
92
92
  type GenerateReportResult = {
93
93
  report: Report;
94
94
  generatedAt: string;
@@ -98,7 +98,7 @@ export const generateMonthlyReport = async (input: {...}): Promise<GenerateRepor
98
98
  ```
99
99
 
100
100
  ```ts
101
- // args file pattern — fragments the contract across files
101
+ // 👎 args file pattern — fragments the contract across files
102
102
  // file: generateReport.args.ts
103
103
  export interface GenerateReportArgs { ... }
104
104
 
@@ -32,12 +32,12 @@ forbid separate `interface` or `type` declarations for procedure inputs and outp
32
32
 
33
33
  #### .how
34
34
 
35
- ##### required
35
+ ##### 👍 required
36
36
  - declare input types inline on the procedure signature
37
37
  - declare return types inline on the procedure signature
38
38
  - use domain objects as **properties** within inline types when appropriate
39
39
 
40
- ##### forbidden
40
+ ##### 👎 forbidden
41
41
  - `interface DoThingInput { ... }` declarations
42
42
  - `interface DoThingOutput { ... }` declarations
43
43
  - `type DoThingArgs = { ... }` declarations
@@ -51,7 +51,7 @@ forbid separate `interface` or `type` declarations for procedure inputs and outp
51
51
 
52
52
  #### .examples
53
53
 
54
- ##### positive
54
+ ##### 👍 positive
55
55
  ```ts
56
56
  /**
57
57
  * .what = syncs customer phone from external provider
@@ -77,15 +77,15 @@ export const calculateInvoiceTotal = (
77
77
  };
78
78
  ```
79
79
 
80
- ##### negative
80
+ ##### 👎 negative
81
81
  ```ts
82
- // separate interface for input
82
+ // 👎 separate interface for input
83
83
  interface SyncCustomerPhoneInput {
84
84
  customerId: string;
85
85
  provider: 'whodis' | 'twilio';
86
86
  }
87
87
 
88
- // separate interface for output
88
+ // 👎 separate interface for output
89
89
  interface SyncCustomerPhoneOutput {
90
90
  updated: boolean;
91
91
  phoneBefore: string | null;
@@ -99,7 +99,7 @@ export const syncCustomerPhone = async (
99
99
  ```
100
100
 
101
101
  ```ts
102
- // type aliases for single-use shapes
102
+ // 👎 type aliases for single-use shapes
103
103
  type CalculateTotalArgs = {
104
104
  lineItems: LineItem[];
105
105
  taxRate: number;
@@ -115,7 +115,7 @@ export const calculateInvoiceTotal = (input: CalculateTotalArgs): CalculateTotal
115
115
  ```
116
116
 
117
117
  ```ts
118
- // file fragmentation pattern
118
+ // 👎 file fragmentation pattern
119
119
  // file: syncCustomerPhone.input.ts
120
120
  export interface SyncCustomerPhoneInput { ... }
121
121
 
@@ -37,11 +37,11 @@ const getName = (input) => input.name;
37
37
 
38
38
  ###### .negative
39
39
  ```ts
40
- function setCustomerPhone({ customer, phone }) { // function keyword
40
+ function setCustomerPhone({ customer, phone }) { // 👎 function keyword
41
41
  return { ...customer, phone };
42
42
  }
43
43
 
44
- export function doWork() { // export with function
44
+ export function doWork() { // 👎 export with function
45
45
  ...
46
46
  }
47
47
  ```
@@ -22,7 +22,7 @@
22
22
 
23
23
  .examples:
24
24
 
25
- good
25
+ 👍 good
26
26
  // domain/procedures/sendInvoice.ts
27
27
 
28
28
  /**
@@ -39,7 +39,7 @@
39
39
  // ...
40
40
  };
41
41
 
42
- bad
42
+ 👎 bad
43
43
  // logic/sendInvoice.ts
44
44
 
45
45
  export const sendInvoice = async (invoice, customer) => {
@@ -19,7 +19,7 @@ via dependencies that are **explicit, swappable, and controlled from the outside
19
19
  for example, instead of a function that reaches for its own dependencies:
20
20
 
21
21
  ```ts
22
- // tightly coupled and side-effect prone
22
+ // 👎 tightly coupled and side-effect prone
23
23
  import { log } from '@/utils/logger';
24
24
  import { getDatabaseConnection } from '@/utils/database';
25
25
 
@@ -33,7 +33,7 @@ export const upsert = async ({ cost }: { cost: JobLeadCost }) => {
33
33
  you inject those dependencies via the standard `(input, context)` pattern:
34
34
 
35
35
  ```ts
36
- // dependency injection via context
36
+ // 👍 dependency injection via context
37
37
  export const upsert = async (
38
38
  { cost }: { cost: JobLeadCost },
39
39
  context: { dbConnection: DatabaseConnection, log: LogMethods }, // note how the .context pattern cleanly separates inputs from dependencies
@@ -24,7 +24,7 @@ the alternative — inline wrapping at the function declaration — causes the e
24
24
 
25
25
  #### .examples
26
26
 
27
- ##### good — wrapper pattern
27
+ ##### 👍 good — wrapper pattern
28
28
 
29
29
  ```ts
30
30
  /**
@@ -43,7 +43,7 @@ const _sendInvoice = async (
43
43
  export const sendInvoice = withLogTrail(_sendInvoice);
44
44
  ```
45
45
 
46
- ##### good — multiple hooks composed
46
+ ##### 👍 good — multiple hooks composed
47
47
 
48
48
  ```ts
49
49
  const _processPayment = async (
@@ -59,10 +59,10 @@ export const processPayment = withLogTrail(
59
59
  );
60
60
  ```
61
61
 
62
- ##### bad — inline decoration
62
+ ##### 👎 bad — inline decoration
63
63
 
64
64
  ```ts
65
- // adding/removing the wrapper shifts the entire function body
65
+ // 👎 adding/removing the wrapper shifts the entire function body
66
66
  export const sendInvoice = withLogTrail(async (
67
67
  input: { invoice: Invoice },
68
68
  context: { log: LogMethods },
@@ -18,7 +18,7 @@ enforce hard requirement that all procedure args to follow the canonical pattern
18
18
 
19
19
  #### .how
20
20
 
21
- ##### required
21
+ ##### 👍 required
22
22
  - every function must accept exactly:
23
23
  - one `input` arg — a destructurable object
24
24
  - optional second `context` arg — also a destructurable object
@@ -28,7 +28,7 @@ enforce hard requirement that all procedure args to follow the canonical pattern
28
28
  - `input` does **not** need to be destructured at the function boundary; shape like `(input: { ... })` is fine
29
29
  - `function` keyword is forbidden unless to implement class methods (see `.tactic:funcs:arrow-only`)
30
30
 
31
- ##### forbidden
31
+ ##### 👎 forbidden
32
32
  - more than 2 positional args
33
33
  - non-destructurable inputs
34
34
  - context blended into input
@@ -39,7 +39,7 @@ enforce hard requirement that all procedure args to follow the canonical pattern
39
39
 
40
40
  ### .examples
41
41
 
42
- ##### positive
42
+ ##### 👍 positive
43
43
  ```ts
44
44
  // standard function
45
45
  export const genRoute = async (input: { slug: string }, context?: { traceId?: string }) => { ... }
@@ -51,11 +51,11 @@ const updateUser = ({ userId }: { userId: string }, context: { userDao: UserDao
51
51
  expect(hasChanges({ before, after })).toBe(true);
52
52
  ```ts
53
53
 
54
- ##### negative
54
+ ##### 👎 negative
55
55
  ```ts
56
- export function doThing(a, b, c) {} // positional args & function keyword
56
+ export function doThing(a, b, c) {} // 👎 positional args & function keyword
57
57
 
58
- handleRequest(input, options, env) // more than two args
58
+ handleRequest(input, options, env) // 👎 more than two args
59
59
 
60
- export const getTotal = (invoice) => ... // input not typed
60
+ export const getTotal = (invoice) => ... // 👎 input not typed
61
61
  ```
@@ -38,7 +38,7 @@ this pattern maximizes **maintainability** and **readability** by:
38
38
 
39
39
  ---
40
40
 
41
- ## example
41
+ ## 👍 example
42
42
 
43
43
  \`\`\`ts
44
44
  export const sendEmail = (
@@ -52,12 +52,12 @@ export const sendEmail = (
52
52
 
53
53
  ---
54
54
 
55
- ## anti-pattern
55
+ ## 👎 anti-pattern
56
56
 
57
57
  \`\`\`ts
58
- // loses "input" provenance
58
+ // 👎 loses "input" provenance
59
59
  export const sendEmail = ({ to, subject, body }: { to: string; subject: string; body: string }) => {};
60
60
 
61
- // type drift — must look up the type definition elsewhere for basic usage
61
+ // 👎 type drift — must look up the type definition elsewhere for basic usage
62
62
  export const sendEmail = (input: EmailInput) => {};
63
63
  \`\`\`
@@ -10,13 +10,13 @@ enforce that every code file and procedure has a singular, clearly-defined respo
10
10
 
11
11
  #### .rules
12
12
 
13
- required
13
+ 👍 required
14
14
  - every file must export **exactly one** named procedure
15
15
  - filename must match the exported procedure
16
- - all logic in the file must directly support the procedures **domain intent**
16
+ - all logic in the file must directly support the procedure's **domain intent**
17
17
  - runtime typechecks are only allowed **if** the file's sole purpose is validation
18
18
 
19
- forbidden
19
+ 👎 forbidden
20
20
  - more than one exported procedure per file
21
21
  - co-located validation, parse, or orchestration logic alongside domain logic
22
22
  - runtime type assertions or guards inside general-purpose logic
@@ -26,7 +26,7 @@ enforce that every code file and procedure has a singular, clearly-defined respo
26
26
 
27
27
  #### .examples
28
28
 
29
- **✅ good**
29
+ **👍 good**
30
30
  ```ts
31
31
  // getCustomerInvoices.ts
32
32
  /**
@@ -40,25 +40,25 @@ export const getCustomerInvoices = ({ customerId }: { customerId: string }) => {
40
40
 
41
41
 
42
42
 
43
- **⛔ bad**
43
+ **👎 bad**
44
44
  ```ts
45
45
  // customerUtils.ts
46
46
  // utility file that contains many things
47
47
 
48
48
  export const getCustomerInvoices = (...) => { ... }
49
49
 
50
- export const validateCustomer = (...) => { ... } // multiple responsibilities
50
+ export const validateCustomer = (...) => { ... } // 👎 multiple responsibilities
51
51
 
52
- // random comment about edge cases — unrelated noise
52
+ // random comment about edge cases — 👎 unrelated noise
53
53
 
54
54
  ```
55
55
 
56
56
 
57
- **⛔ bad**
57
+ **👎 bad**
58
58
  ```ts
59
59
  // getCustomerInvoices.ts
60
60
  export const getCustomerInvoices = ({ customerId }: { customerId: string }) => {
61
- if (typeof customerId !== 'string') // redundant runtime check
61
+ if (typeof customerId !== 'string') // 👎 redundant runtime check
62
62
  throw new Error('bad id');
63
63
 
64
64
  return invoiceDao.findMany({ customerId });
@@ -56,7 +56,7 @@ src/
56
56
 
57
57
  .examples
58
58
 
59
- positive
59
+ 👍 positive
60
60
  \`\`\`ts
61
61
  // contract/endpoints/sendInvoice.ts
62
62
  import { generateInvoice } from '@/domain.operations/generateInvoice';
@@ -69,14 +69,14 @@ import { Job } from '@/domain.objects/Job';
69
69
  import { LineItem } from '@/domain.objects/LineItem';
70
70
  \`\`\`
71
71
 
72
- negative
72
+ 👎 negative
73
73
  \`\`\`ts
74
74
  // domain.objects/Customer.ts
75
- import { customerDao } from '@/access/daos/customerDao'; // illegal upward import
75
+ import { customerDao } from '@/access/daos/customerDao'; // 👎 illegal upward import
76
76
 
77
77
  // domain.operations/InvoiceOps.ts
78
- import { runFlow } from '@/contract/commands'; // direction violation
78
+ import { runFlow } from '@/contract/commands'; // 👎 direction violation
79
79
 
80
80
  // access/svcs/sdkWrapper.ts
81
- import { dispatchFlow } from '@/contract/'; // bottom-up reference
81
+ import { dispatchFlow } from '@/contract/'; // 👎 bottom-up reference
82
82
  \`\`\`
@@ -54,10 +54,10 @@
54
54
 
55
55
  .negative:
56
56
  ```ts
57
- await sendEmail(input); // no check for previous send
57
+ await sendEmail(input); // 👎 no check for previous send
58
58
  ```
59
59
 
60
60
  ```ts
61
- const saved = await insertLog({ ... }) // may insert duplicate on retry
61
+ const saved = await insertLog({ ... }) // 👎 may insert duplicate on retry
62
62
  ```
63
63
 
@@ -40,9 +40,9 @@
40
40
 
41
41
  .negative:
42
42
  - `let count = 0; count++`
43
- - `input.customer.name = 'bob'` // input mutation
44
- - `config.debug = false` // shared singleton mutation
45
- - `arr.push(1)` // in-place array mutation
43
+ - `input.customer.name = 'bob'` // 👎 input mutation
44
+ - `config.debug = false` // 👎 shared singleton mutation
45
+ - `arr.push(1)` // 👎 in-place array mutation
46
46
 
47
47
  .links:
48
48
  - see also: `arch:immutable-core`, `args:input-context`, `domain-objects.withImmute`
@@ -41,7 +41,7 @@ const specificDao: DeclastructDao<typeof MyResource> = { ... };
41
41
  // generic dao shape where RefByPrimary<any> resolves to {}
42
42
  type GenericDao = DeclastructDao<any>;
43
43
 
44
- // fails: {uuid: string} is not assignable to {}
44
+ // 👎 fails: {uuid: string} is not assignable to {}
45
45
  const generic: GenericDao = specificDao;
46
46
  ```
47
47
 
@@ -59,7 +59,7 @@ interface DeclastructDao<TResourceClass> {
59
59
  };
60
60
  }
61
61
 
62
- // works: bivariance allows assignment in either direction
62
+ // 👍 works: bivariance allows assignment in either direction
63
63
  const generic: GenericDao = specificDao;
64
64
  ```
65
65
 
@@ -51,13 +51,13 @@
51
51
 
52
52
  .negative:
53
53
  ```ts
54
- // undocumented cast
54
+ // 👎 undocumented cast
55
55
  const user = data as User;
56
56
 
57
- // cast to silence error
57
+ // 👎 cast to silence error
58
58
  const result = badFunction() as ExpectedType;
59
59
 
60
- // any-cast escape hatch
60
+ // 👎 any-cast escape hatch
61
61
  const x = (y as any) as SomeType;
62
62
  ```
63
63
 
@@ -16,11 +16,11 @@ require oneliner summaries of .what and why comments to precede every code parag
16
16
 
17
17
  comments are a hard requirement — they must follow precise structure and length:
18
18
 
19
- required
19
+ 👍 required
20
20
  - /** .what, .why */ block above all named procedures
21
21
  - // one-liner before every logical paragraph of code
22
22
 
23
- forbidden
23
+ 👎 forbidden
24
24
  - absent .what or .why above a procedure
25
25
  - multiline // paragraph comments
26
26
  - vague, redundant, or “code-shaped” comments
@@ -79,14 +79,14 @@ export const proposeCode = async ({ threads }) => {
79
79
 
80
80
  forbidden, negative examples
81
81
  ```ts
82
- // absent .what/.why above export blocker
82
+ // absent .what/.why above export 👎 blocker
83
83
  export const doStuff = () => { ... }
84
84
 
85
- // vague comment no intent
85
+ // vague comment 👎 no intent
86
86
  // run flow
87
87
  const r = run();
88
88
 
89
- // multiline paragraph comment must extract into procedure
89
+ // multiline paragraph comment 👎 must extract into procedure
90
90
  // handle logic for retries because retries are complicated
91
91
  // and they sometimes need to be skipped on failure
92
92
  const result = retry(input);
@@ -48,7 +48,7 @@ const invoice = await getInvoiceById(invoiceId);
48
48
 
49
49
  #### .examples
50
50
 
51
- ##### positive
51
+ ##### 👍 positive
52
52
 
53
53
  ```ts
54
54
  /**
@@ -64,13 +64,13 @@ export const proposeCode = async ({ threads }) => {
64
64
  };
65
65
  ```
66
66
 
67
- ##### negative
67
+ ##### 👎 negative
68
68
 
69
69
  ```ts
70
- // run flow unclear
70
+ // run flow 👎 unclear
71
71
  const r = await run();
72
72
 
73
- return r.artifact; // what is this? why return this?
73
+ return r.artifact; // 👎 what is this? why return this?
74
74
 
75
75
  // very long comment that describes why this block exists
76
76
  // and what it does and why it's written in this particular way
@@ -57,7 +57,7 @@ Instead of `let` + `beforeAll` + `afterAll`:
57
57
 
58
58
  e.g.,
59
59
  ```typescript
60
- // Don't do this
60
+ // 👎 Don't do this
61
61
  let dbConnection: DatabaseConnection;
62
62
  beforeAll(async () => {
63
63
  dbConnection = await getDatabaseConnection();
@@ -66,7 +66,7 @@ afterAll(async () => {
66
66
  await dbConnection.end();
67
67
  });
68
68
 
69
- // Do this
69
+ // 👍 Do this
70
70
  const dbConnection = useBeforeAll(() => getDatabaseConnection());
71
71
  afterAll(async () => dbConnection.end());
72
72
  ```
@@ -102,7 +102,7 @@ given('[case2] second scenario', () => {
102
102
  Each `then` block should test a single behavioral assertion. This makes test failures more precise and test names more descriptive:
103
103
 
104
104
  ```typescript
105
- // Don't do this - multiple assertions in one then
105
+ // 👎 Don't do this - multiple assertions in one then
106
106
  when('[t0] command executed in PLAN mode', () => {
107
107
  then('decision is UPDATE and doer remains unchanged', async () => {
108
108
  const result = await command({ mode: 'PLAN' });
@@ -114,7 +114,7 @@ when('[t0] command executed in PLAN mode', () => {
114
114
  });
115
115
  });
116
116
 
117
- // Do this - separate then blocks for each behavioral assertion
117
+ // 👍 Do this - separate then blocks for each behavioral assertion
118
118
  when('[t0] command executed in PLAN mode', () => {
119
119
  then('decision is "UPDATE"', async () => {
120
120
  const result = await command({ mode: 'PLAN' });
@@ -74,12 +74,12 @@ given('[case1] prose-author example repo', () => {
74
74
  don't split related scenarios across multiple `given` blocks:
75
75
 
76
76
  ```ts
77
- // bad - fragmented
77
+ // 👎 bad - fragmented
78
78
  given('[case8] prose-author rule enumeration', () => { ... });
79
79
  given('[case9] prose-author chapter enumeration', () => { ... });
80
80
  given('[case10] prose-author review works', () => { ... });
81
81
 
82
- // good - consolidated
82
+ // 👍 good - consolidated
83
83
  given('[case8] prose-author example repo', () => {
84
84
  when('[t0] before any changes', () => {
85
85
  then('rules glob matches', ...);
@@ -93,24 +93,24 @@ given('[case8] prose-author example repo', () => {
93
93
  ### when describes state/time, not action
94
94
 
95
95
  ```ts
96
- // bad - describes action
96
+ // 👎 bad - describes action
97
97
  when('[t0] assets are checked', () => { ... });
98
98
 
99
- // good - describes state/time
99
+ // 👍 good - describes state/time
100
100
  when('[t0] before any changes', () => { ... });
101
101
  ```
102
102
 
103
103
  ### use afterEach for cleanup
104
104
 
105
105
  ```ts
106
- // bad - inline cleanup
106
+ // 👎 bad - inline cleanup
107
107
  then('creates output file', async () => {
108
108
  const result = await doThing();
109
109
  await fs.rm(outputPath); // cleanup inside then
110
110
  expect(result).toBeDefined();
111
111
  });
112
112
 
113
- // good - afterEach cleanup
113
+ // 👍 good - afterEach cleanup
114
114
  when('[t1] operation runs', () => {
115
115
  const outputPath = path.join(os.tmpdir(), 'output.md');
116
116
  afterEach(async () => fs.rm(outputPath, { force: true }));
@@ -125,13 +125,13 @@ when('[t1] operation runs', () => {
125
125
  ### preconditions shouldn't expect errors
126
126
 
127
127
  ```ts
128
- // bad - precondition expects error then checks it's not a validation error
128
+ // 👎 bad - precondition expects error then checks it's not a validation error
129
129
  then('does not throw validation errors', async () => {
130
130
  const error = await getError(doThing());
131
131
  expect(error.message).not.toContain('validation');
132
132
  });
133
133
 
134
- // good - precondition checks assets directly
134
+ // 👍 good - precondition checks assets directly
135
135
  then('rules glob matches 2 files', async () => {
136
136
  const files = await enumFiles({ glob: 'rules/*.md' });
137
137
  expect(files).toHaveLength(2);
@@ -56,7 +56,7 @@ given('a mechanic with ask, claim, and coderefs', () => {
56
56
  ```
57
57
 
58
58
  ```ts
59
- when('executed', async () => { // async not allowed in when()
59
+ when('executed', async () => { // 👎 async not allowed in when()
60
60
  const result = await doSomething();
61
61
  });
62
62
  ```
@@ -40,7 +40,7 @@ gerund usage = **BLOCKER**
40
40
 
41
41
  #### .alternatives
42
42
 
43
- | gerund | alternative | .why |
43
+ | 👎 gerund | 👍 alternative | .why |
44
44
  |-----------|----------------|------|
45
45
  | `existing` | `found`, `current`, `prior` | state, not action |
46
46
  | `processing` | `process`, `processor`, `processed` | verb, agent, or result |
@@ -56,7 +56,7 @@ gerund usage = **BLOCKER**
56
56
 
57
57
  #### .examples
58
58
 
59
- **⛔ bad**
59
+ **👎 bad**
60
60
  ```ts
61
61
  const existingUser = await findUser(); // gerund
62
62
  const processingQueue = []; // gerund
@@ -64,7 +64,7 @@ const handlingErrors = true; // gerund
64
64
  // we are currently loading the data // gerund in comment
65
65
  ```
66
66
 
67
- **✅ good**
67
+ **👍 good**
68
68
  ```ts
69
69
  const userFound = await findUser(); // past participle = result
70
70
  const processQueue = []; // noun
@@ -19,7 +19,7 @@ always use `[noun][state/adjective]` order for variable and property names
19
19
  #### .categories
20
20
 
21
21
  ##### temporal qualifiers
22
- | bad | good |
22
+ | 👎 bad | 👍 good |
23
23
  |--------|---------|
24
24
  | `previousValue` | `valuePrevious` |
25
25
  | `currentOwner` | `ownerCurrent` |
@@ -28,7 +28,7 @@ always use `[noun][state/adjective]` order for variable and property names
28
28
  | `afterState` | `stateAfter` |
29
29
 
30
30
  ##### state qualifiers (past participles)
31
- | bad | good |
31
+ | 👎 bad | 👍 good |
32
32
  |--------|---------|
33
33
  | `existingUser` | `userFound` |
34
34
  | `foundRecord` | `recordFound` |
@@ -38,7 +38,7 @@ always use `[noun][state/adjective]` order for variable and property names
38
38
  | `matchingResult` | `resultMatched` |
39
39
 
40
40
  ##### descriptive qualifiers
41
- | bad | good |
41
+ | 👎 bad | 👍 good |
42
42
  |--------|---------|
43
43
  | `validInput` | `inputValid` |
44
44
  | `emptyList` | `listEmpty` |
@@ -41,8 +41,8 @@
41
41
  - `invoice` // base noun with implicit sense
42
42
 
43
43
  .negative:
44
- - `stepImagineGenFromTemplate` // wrong order — verb must come first
45
- - `customerSet` // vague mechanism — better as `setCustomer` or `setCustomerPhone`
46
- - `FoundContent` // reversed word order and PascalCase — should be `contentFound`
47
- - `submitQuoteJob` // noun hierarchy flipped — should be `submitJobQuote`
48
- - `update()` // unscoped verb — must include noun domain (e.g., `updateInvoice`)
44
+ - `stepImagineGenFromTemplate` // 👎 wrong order — verb must come first
45
+ - `customerSet` // 👎 vague mechanism — better as `setCustomer` or `setCustomerPhone`
46
+ - `FoundContent` // 👎 reversed word order and PascalCase — should be `contentFound`
47
+ - `submitQuoteJob` // 👎 noun hierarchy flipped — should be `submitJobQuote`
48
+ - `update()` // 👎 unscoped verb — must include noun domain (e.g., `updateInvoice`)
@@ -29,8 +29,8 @@
29
29
  - `// pass into StitchStepImagine to generate`
30
30
  - `// openai prompt requires flattened string`
31
31
  .negative:
32
- - `// Returns a new invoice` // capitalized sentence start
33
- - `// This is handled in GitRepo` // capitalized sentence + verb
34
- - `// Submit the job for approval` // capitalized imperative
35
- - `// Customer must exist first` // capitalized domain noun
36
- - `// GitHub Repository` // capitalized generic noun
32
+ - `// Returns a new invoice` // 👎 capitalized sentence start
33
+ - `// This is handled in GitRepo` // 👎 capitalized sentence + verb
34
+ - `// Submit the job for approval` // 👎 capitalized imperative
35
+ - `// Customer must exist first` // 👎 capitalized domain noun
36
+ - `// GitHub Repository` // 👎 capitalized generic noun
@@ -19,14 +19,14 @@ the mechanic always refers to the person they work with as "the human", never "t
19
19
 
20
20
  ## .examples
21
21
 
22
- ### good
22
+ ### 👍 good
23
23
 
24
24
  - "the human asked for..."
25
25
  - "waiting for the human to confirm"
26
26
  - "the human's request"
27
27
  - "let me check with the human"
28
28
 
29
- ### bad
29
+ ### 👎 bad
30
30
 
31
31
  - "the user asked for..."
32
32
  - "waiting for the user to confirm"
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "rhachet-roles-ehmpathy",
3
3
  "author": "ehmpathy",
4
4
  "description": "empathetic software construction roles and skills, via rhachet",
5
- "version": "1.17.17",
5
+ "version": "1.17.18",
6
6
  "repository": "ehmpathy/rhachet-roles-ehmpathy",
7
7
  "homepage": "https://github.com/ehmpathy/rhachet-roles-ehmpathy",
8
8
  "keywords": [
@@ -89,9 +89,9 @@
89
89
  "esbuild-register": "3.6.0",
90
90
  "husky": "8.0.3",
91
91
  "jest": "30.2.0",
92
- "rhachet": "1.20.7",
92
+ "rhachet": "1.21.5",
93
93
  "rhachet-roles-bhrain": "0.5.9",
94
- "rhachet-roles-bhuild": "0.5.6",
94
+ "rhachet-roles-bhuild": "0.6.4",
95
95
  "rhachet-roles-ehmpathy": "link:.",
96
96
  "test-fns": "1.6.0",
97
97
  "tsc-alias": "1.8.10",