Skip to content

Commit 9ce1b9a

Browse files
gisk0chapati23
authored andcommitted
docs: add stateful data PR operating rule and checklist
Codify the lesson from PR #116: - add a repo-level operating rule for cross-layer/stateful data changes - add a dedicated checklist for schema/query/UI/degraded-mode/test review - point root + package AGENTS files at the checklist so agents see it early
1 parent fd1e39d commit 9ce1b9a

File tree

4 files changed

+245
-0
lines changed

4 files changed

+245
-0
lines changed

AGENTS.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,26 @@ pnpm monorepo with three packages:
88
- `indexer-envio/` — Envio HyperIndex indexer for Celo v3 FPMM pools
99
- `ui-dashboard/` — Next.js 16 + Plotly.js monitoring dashboard
1010

11+
## Operating Rule (read this before opening PRs)
12+
13+
> **Any PR that adds or changes stateful data flow across layers must ship with explicit invariants, degraded-mode behavior, and interaction tests before opening.**
14+
15+
This repo has already paid the tax for learning this the hard way.
16+
17+
If your change touches any combination of:
18+
19+
- Envio schema/entities
20+
- event handlers / entity writers
21+
- generated types / GraphQL queries / dashboard types
22+
- paginated or sortable UI state
23+
- partial failure behavior (missing counts, stale RPC, missing txHash, etc.)
24+
25+
then you are expected to run the dedicated PR checklist before opening or updating the PR:
26+
27+
- **Checklist:** `docs/pr-checklists/stateful-data-ui.md`
28+
29+
Do not rely on PR review to finish the design. Reviews should catch misses, not define the invariants for the first time.
30+
1131
## Quick Commands
1232

1333
```bash
@@ -165,6 +185,10 @@ pnpm indexer:codegen # Validates Envio can parse handler entry point + module
165185
pnpm --filter @mento-protocol/ui-dashboard test:coverage
166186
```
167187

188+
Before pushing any cross-layer or stateful UI change, also read and apply:
189+
190+
- **`docs/pr-checklists/stateful-data-ui.md`**
191+
168192
**Common traps:**
169193

170194
- `codespell` flags short variable names that match common abbreviations (e.g. a two-letter loop var that looks like a misspelling). Use descriptive names like `netData` to avoid this.
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
# Stateful Data + UI PR Checklist
2+
3+
Use this checklist for any PR that changes stateful data flow across layers.
4+
5+
## Operating rule
6+
7+
> **Any PR that adds or changes stateful data flow across layers must ship with explicit invariants, degraded-mode behavior, and interaction tests before opening.**
8+
9+
If the change touches any combination of:
10+
11+
- Envio schema/entities
12+
- event handlers / entity writers
13+
- generated types / GraphQL queries / dashboard types
14+
- paginated, sortable, filterable, or searchable UI state
15+
- partial failure behavior (count query failure, stale RPC, missing metadata, old rows after schema rollout)
16+
17+
then this checklist is mandatory.
18+
19+
---
20+
21+
## 1. Define invariants first
22+
23+
Write down the rules the system must obey before coding.
24+
25+
Examples:
26+
27+
- Every event/snapshot entity must persist `txHash`
28+
- Charts must not depend on paginated table slices
29+
- Paginated tables must have deterministic ordering
30+
- Aggregate-query failure must degrade visibly, not silently
31+
- Client-side search over large datasets must be bounded and disclosed
32+
33+
If you cannot state the invariant in one sentence, the design is not ready.
34+
35+
---
36+
37+
## 2. Cross-layer audit
38+
39+
For every new field / changed field / changed behavior, walk the full path:
40+
41+
### Schema / source of truth
42+
43+
- [ ] `schema.graphql` updated if entity shape changed
44+
- [ ] field names/types/nullability are intentional
45+
- [ ] backward-compatibility / rollout behavior considered for old rows
46+
47+
### Writers
48+
49+
- [ ] every entity constructor / writer is updated consistently
50+
- [ ] all event handlers that produce the entity were checked, not just the obvious one
51+
- [ ] generated/codegen artifacts refreshed where applicable
52+
53+
### Readers
54+
55+
- [ ] GraphQL queries updated
56+
- [ ] dashboard/runtime types updated
57+
- [ ] derived formatting / rendering logic updated
58+
- [ ] search/sort/filter fields updated intentionally
59+
60+
### Tests
61+
62+
- [ ] producer/indexer tests updated
63+
- [ ] consumer/UI tests updated
64+
- [ ] fixtures reflect the new schema reality
65+
66+
If one layer is missing, stop and fix it before opening the PR.
67+
68+
---
69+
70+
## 3. Stateful table rubric
71+
72+
If the PR touches a table with pagination, sort, filter, search, or linked charts, answer all of these explicitly.
73+
74+
### Sorting
75+
76+
- [ ] Is sorting server-side, client-side, or hybrid?
77+
- [ ] Are page boundaries deterministic for non-unique sort fields?
78+
- [ ] Is there a unique tiebreaker (`id`, tx hash, composite key, etc.)?
79+
- [ ] Do headers expose sort state accessibly (`aria-sort`)?
80+
81+
### Pagination
82+
83+
- [ ] What determines total row count?
84+
- [ ] What happens when count/aggregate fails?
85+
- [ ] Does pagination remain usable after transient failure?
86+
- [ ] Are controls actual buttons with `type="button"`?
87+
88+
### Search / filtering
89+
90+
- [ ] Does search operate on current page, fetched window, or full dataset?
91+
- [ ] Is that behavior documented in code comments and PR notes?
92+
- [ ] If bounded, is the cap explicit and user-visible?
93+
- [ ] If unbounded, can the backend/query path actually support it?
94+
95+
### Coupled visualizations
96+
97+
- [ ] Do charts use dedicated queries instead of inheriting paginated/sorted table state?
98+
- [ ] If not, is that coupling intentional and documented?
99+
100+
### URL / local state
101+
102+
- [ ] Is table state URL-backed or intentionally local?
103+
- [ ] If local-only, is that explicitly called out as an intentional scope decision?
104+
105+
---
106+
107+
## 4. Degraded-mode checklist
108+
109+
For each non-happy path, decide the behavior explicitly.
110+
111+
- [ ] count query fails
112+
- [ ] chart query fails
113+
- [ ] some rows predate a new schema field
114+
- [ ] RPC-derived metadata is missing
115+
- [ ] total dataset is much larger than the current happy-path sample
116+
- [ ] search term matches data outside the currently fetched window
117+
- [ ] empty state vs loading state vs partial-data state are distinct
118+
119+
The key question:
120+
121+
> What will the user see, and will they understand that the data is partial or degraded?
122+
123+
Silent degradation is not acceptable.
124+
125+
---
126+
127+
## 5. Required test matrix
128+
129+
For nontrivial stateful data/UI changes, tests must cover all 3 buckets:
130+
131+
### Happy path
132+
133+
- [ ] normal render / query wiring
134+
- [ ] new field is displayed/used correctly
135+
136+
### State transition
137+
138+
- [ ] sort toggle changes query/order state
139+
- [ ] page transition changes offset/page state
140+
- [ ] search input resets/updates the right state
141+
- [ ] links/actions resolve to the expected target
142+
143+
### Failure / degraded mode
144+
145+
- [ ] count error fallback
146+
- [ ] capped search behavior
147+
- [ ] missing field / legacy row behavior
148+
- [ ] user-visible warning or fallback state
149+
150+
If the risky behavior is interactive, a static markup assertion is not enough.
151+
152+
---
153+
154+
## 6. PR description requirements
155+
156+
Before opening the PR, include these sections:
157+
158+
### What this PR changes
159+
160+
Short factual summary.
161+
162+
### Invariants
163+
164+
List the system rules this PR relies on or introduces.
165+
166+
### Degraded behavior
167+
168+
What happens on count/query/RPC failure, old rows, large datasets, etc.
169+
170+
### Intentional non-goals
171+
172+
Examples:
173+
174+
- URL-backed sort/page state deferred
175+
- full server-side search deferred
176+
- abstraction cleanup out of scope
177+
178+
This prevents reviews from repeatedly rediscovering scope boundaries.
179+
180+
---
181+
182+
## 7. Repo-specific lessons already paid for
183+
184+
These are not theoretical.
185+
186+
- New UI fields must not assume schema support without verifying all writers.
187+
- Shared presentational components should forward DOM props unless intentionally constrained.
188+
- Count fallback must preserve prior total, not collapse to current page length.
189+
- Search behavior must be bounded and disclosed when not truly global.
190+
- Charts and tables should usually be decoupled.
191+
- Cross-layer features need both indexer and UI regression coverage.
192+
193+
---
194+
195+
## 8. Final pre-PR questions
196+
197+
If you answer “no” to any of these, do not open yet.
198+
199+
- [ ] Could another engineer explain the invariants from the PR description alone?
200+
- [ ] Would a transient backend failure produce a sensible UI instead of a misleading one?
201+
- [ ] Are the largest-cardinality paths still bounded?
202+
- [ ] Do tests prove behavior, not just markup?
203+
- [ ] Did review stop being the place where design gets finished?
204+
205+
If not, one more local pass is cheaper than three more review rounds.

indexer-envio/AGENTS.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@
44

55
Envio HyperIndex indexer for Mento v3 FPMM (Fixed Product Market Maker) pools on Celo + Monad (multichain).
66

7+
## Before Opening PRs
8+
9+
If your indexer change propagates into Hasura/UI behavior — schema changes, entity additions, new fields on existing entities, degraded RPC/error handling, or any stateful dashboard behavior fed by indexer data — read and apply:
10+
11+
- `../docs/pr-checklists/stateful-data-ui.md`
12+
13+
This is mandatory for cross-layer/stateful data work. Do not assume the UI/query layer will “just catch up” later.
14+
715
## Key Files
816

917
- `config.multichain.mainnet.yaml`**Default** mainnet config (Celo + Monad)

ui-dashboard/AGENTS.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@
44

55
Next.js 16 monitoring dashboard for Mento v3 pools. Displays real-time pool data (reserves, swaps, mints, burns) using Plotly.js charts, sourced from Hasura GraphQL.
66

7+
## Before Opening PRs
8+
9+
If your dashboard change touches stateful data flow — pagination, sort, search, charts tied to table state, GraphQL shape changes, degraded/error behavior, or any indexer→query→UI field path — read and apply:
10+
11+
- `../docs/pr-checklists/stateful-data-ui.md`
12+
13+
This is mandatory for cross-layer/stateful UI work. The checklist exists because this repo repeatedly burned review cycles on exactly these failure modes.
14+
715
## Key Files
816

917
- `src/app/` — Next.js App Router pages and layouts

0 commit comments

Comments
 (0)