@clipboard-health/ai-rules 2.8.6 → 2.9.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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@clipboard-health/ai-rules",
3
3
  "description": "Pre-built AI agent rules for consistent coding standards.",
4
- "version": "2.8.6",
4
+ "version": "2.9.0",
5
5
  "bugs": "https://github.com/ClipboardHealth/core-utils/issues",
6
6
  "keywords": [
7
7
  "ai",
@@ -94,9 +94,26 @@ throw new ServiceError({
94
94
 
95
95
  - Use `@clipboard-health/date-time` for all user-facing date formatting and all timezone-dependent operations (start-of-day-in-timezone, business hours, `setHours`, etc.) with an explicit `timeZone` parameter
96
96
  - Use `date-fns` only for timezone-agnostic timestamp math and parsing
97
+ - Use `date-fns` comparison functions (`isBefore`, `isAfter`, `isEqual`, `isSameDay`, `compareAsc`, `compareDesc`) for all date comparisons — never use raw JS comparison operators (`>`, `<`, `===`, `>=`, `<=`) or `.getTime()` for equality/inequality checks
97
98
  - Never import `date-fns-tz`, `@date-fns/tz`, `moment`, or `moment-timezone`
98
99
  - In contracts, use `dateTimeSchema()` from `contract-core` for date fields — not `z.coerce.date()`, `z.string().datetime()`, or `z.date()`
99
100
 
101
+ ```typescript
102
+ import { isBefore, isAfter, isSameDay } from "date-fns";
103
+
104
+ // ✅ Good — explicit, readable, handles edge cases
105
+ if (isBefore(shiftStart, now)) {
106
+ }
107
+ if (isSameDay(createdAt, today)) {
108
+ }
109
+
110
+ // ❌ Bad — raw JS comparison, implicit coercion risks
111
+ if (shiftStart < now) {
112
+ }
113
+ if (shiftStart.getTime() === today.getTime()) {
114
+ }
115
+ ```
116
+
100
117
  ## Internal Libraries
101
118
 
102
119
  - Use object arguments and object return types in library APIs; wrap exported responses in `ServiceResult`; prefer `ServiceResult` for expected errors and reserve throwing for unexpected/unrecoverable failures
@@ -25,6 +25,14 @@ await expect(page.getByText("Submit")).toBeVisible();
25
25
  await expect(page.getByText("Submit")).toBeAttached();
26
26
  ```
27
27
 
28
+ ## E2E vs Component Test Decision
29
+
30
+ Before adding an E2E test:
31
+
32
+ 1. Check if existing E2E tests already cover the API calls and flows being tested — avoid duplicating coverage
33
+ 2. Confirm the flow is a core user journey (auth, payments, onboarding, multi-page navigation) — non-core flows belong in component tests even if they call backend APIs or touch API contracts
34
+ 3. Verify the test requires real cross-service integration or multi-page navigation — if it can be asserted with `render()` + `screen.getByRole()` or mocked API responses, write a component test instead
35
+
28
36
  ## Avoid
29
37
 
30
38
  - Hard-coded timeouts (`page.waitForTimeout`)
@@ -86,3 +86,13 @@ return <Input onChange={(e) => setValue(e.target.value)} />;
86
86
  const handleSave = useCallback(async () => { ... }, [deps]);
87
87
  return <MemoizedChild onSave={handleSave} />;
88
88
  ```
89
+
90
+ ## Component Reuse
91
+
92
+ Before creating a new component, search for existing ones in this order:
93
+
94
+ 1. **Shared UI libraries**: `@clipboard-health/ui-components`, `@clipboard-health/ui-react`, MUI
95
+ 2. **App-level shared directories**: e.g., `src/appV2/lib/`, `src/lib/components/`, `src/shared/`
96
+ 3. **Sibling features**: search for `*Card`, `*Modal`, `*Form`, `*EmptyState`, `*Page` patterns in other features
97
+
98
+ If an existing component covers >70% of the need, extend it (prefer composition over boolean flags). Only create a new component when behavior is fundamentally different — document why in the PR.