You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: .cursor/rules/coding_conventions.mdc
+1-312Lines changed: 1 addition & 312 deletions
Original file line number
Diff line number
Diff line change
@@ -3,315 +3,4 @@ description: Coding Conventions
3
3
globs: *.go
4
4
alwaysApply: false
5
5
---
6
-
# Coding Conventions
7
-
8
-
## High-Assurance Software Engineering Principles
9
-
10
-
Flow is a high-assurance software project where the cost of bugs that slip through can be catastrophically high. We consider all inputs to be potentially byzantine. This fundamentally shapes our approach to error handling and code correctness:
11
-
12
-
### Inversion of Default Safety Assumptions
13
-
- Traditional software engineering often assumes code paths are safe unless proven dangerous
14
-
- In Flow, we invert this: **no code path is considered safe unless explicitly proven and documented to be safe**
15
-
- The mere absence of known failure cases is NOT sufficient evidence of safety
16
-
- We require conclusive arguments for why each code path will always behave correctly
17
-
18
-
### Context-Dependent Error Classification
19
-
20
-
A critical rule in Flow's error handling is that **the same error type can be benign in one context but an exception in another**. Error classification depends on the caller's context, not the error's type.
21
-
22
-
Key principles:
23
-
- An error type alone CANNOT determine whether it's benign or an exception
24
-
- The caller's context and expectations determine the error's severity
25
-
- The same error type may be handled differently in different contexts
26
-
- Documentation *must* specify which errors are benign in which contexts
27
-
28
-
Example of context-dependent error handling, where `storage.ErrNotFound` is _benign_:
29
-
```go
30
-
// We're checking if we need to request a block from another node
31
-
//
32
-
// No Expected errors during normal operations.
33
-
func (s *Synchronizer) checkBlockExists(blockID flow.Identifier) error {
34
-
_, err := s.storage.ByBlockID(blockID)
35
-
if errors.Is(err, storage.ErrNotFound) {
36
-
// Expected during normal operation - request block from peer.
37
-
return s.requestBlockFromPeer(blockID) // Expecting no errors from this call under normal operations
return nil, fmt.Errorf("could not get finalized block ID: %w", err)
56
-
}
57
-
58
-
// At this point, we KNOW the block should exist
59
-
block, err := s.storage.ByBlockID(blockID)
60
-
if err != nil {
61
-
// Any error here (including ErrNotFound) indicates a bug or corruption
62
-
return nil, irrecoverable.NewExceptionf(
63
-
"storage corrupted - failed to get finalized block %v: %w",
64
-
blockID, err)
65
-
}
66
-
return block, nil
67
-
}
68
-
```
69
-
70
-
### Rules for Error Classification
71
-
72
-
1. **Documentation Requirements**
73
-
- Functions MUST document which error types are benign in their context
74
-
- Documentation MUST explain WHY an error is considered benign
75
-
- Absence of documentation means an error is treated as an exception
76
-
77
-
2. **Error Propagation**
78
-
- When propagating errors, evaluate if they remain benign in the new context
79
-
- If a benign error from a lower layer indicates a critical failure in your context, wrap it as an exception
80
-
- Use `irrecoverable.NewExceptionf` when elevating a benign error to an exception
81
-
82
-
3. **Testing Requirements**
83
-
- Tests MUST verify error handling in different contexts
84
-
- Test that benign errors in one context are properly elevated to exceptions in another
85
-
- Mock dependencies to test both benign and exceptional paths
86
-
87
-
### Error Handling Philosophy
88
-
- All errors are considered potentially fatal by default
89
-
- Only explicitly documented benign errors are safe to recover from
90
-
- For any undocumented error case, we must assume the execution state is corrupted
91
-
- Recovery from undocumented errors requires node restart from last known safe state
92
-
- This conservative approach prioritizes safety over continuous operation
93
-
94
-
Example of proper high-assurance error handling:
95
-
```go
96
-
func (e *engine) process(event interface{}) error {
97
-
// Step 1: type checking of input
98
-
switch v := event.(type) {
99
-
case *ValidEvent:
100
-
// explicitly documented safe path
101
-
return e.handleValidEvent(v)
102
-
default:
103
-
// undocumented event type - unsafe to proceed
104
-
return fmt.Errorf("unexpected event type %T: %w", event, ErrInvalidEventType)
105
-
}
106
-
}
107
-
108
-
func (e *engine) Submit(event interface{}) {
109
-
err := e.process(event)
110
-
if errors.Is(err, ErrInvalidEventType) {
111
-
// This is a documented benign error - safe to handle
112
-
metrics.InvalidEventsCounter.Inc()
113
-
return
114
-
}
115
-
if err != nil {
116
-
// Any other error is potentially fatal
117
-
// We cannot prove it's safe to continue
118
-
e.log.Fatal().Err(err).Msg("potentially corrupted state - must restart")
119
-
return
120
-
}
121
-
}
122
-
```
123
-
124
-
## 1. Code Documentation
125
-
- Every interface must have clear documentation
126
-
- Copy and extend interface documentation in implementations
127
-
- Include clear explanations for any deviations from conventions
128
-
- Document all public functions individually
129
-
- Document error handling strategies and expected error types
130
-
131
-
Example of proper error documentation:
132
-
```go
133
-
// foo does abc.
134
-
// Expected errors during normal operations:
135
-
// - ErrXFailed: if x failed
136
-
func foo() err {
137
-
...
138
-
return fmt.Errorf("details about failure: %w", ErrXFailed)
139
-
}
140
-
```
141
-
142
-
## 2. Code Structure
143
-
- Follow the component-based architecture
144
-
- Each component must implement the `Component` interface
145
-
- Clearly differentiate between trusted (internal) and untrusted (external) inputs
146
-
- Components should have dedicated worker pools
147
-
- Proper resource management with worker limits
148
-
- Proper state management and recovery
149
-
150
-
## 3. Error Categories and Handling Philosophy
151
-
152
-
### a. Benign Errors
153
-
- Component remains fully functional despite the error
154
-
- Expected during normal operations
155
-
- Must be handled within the component
156
-
- Must be documented in the component's context
157
-
- Must be represented as typed sentinel errors
158
-
- Cannot be represented by generic/untyped errors unless explicitly documented as an optional simplification for components that solely return benign errors
159
-
160
-
Example of proper benign error handling:
161
-
```go
162
-
// Expected errors during normal operations:
163
-
// * ErrXFailed: if x failed
164
-
func benignErrorExample() error {
165
-
err := foo()
166
-
if err != nil {
167
-
return fmt.Errorf("failed to do foo: %w", err)
168
-
}
169
-
return nil
170
-
}
171
-
```
172
-
173
-
### b. Exceptions
174
-
- Potential symptoms of internal state corruption
175
-
- Unexpected failures that may compromise component state
176
-
- Should lead to component restart or node termination
177
-
- Strongly encouraged to wrap with context when bubbling up
Copy file name to clipboardExpand all lines: .cursor/rules/core.mdc
+1-38Lines changed: 1 addition & 38 deletions
Original file line number
Diff line number
Diff line change
@@ -5,41 +5,4 @@ alwaysApply: true
5
5
---
6
6
# Cursor Operational Doctrine
7
7
8
-
You are an AI with extensive expertise in byzantine-fault-tolerant, distributed software engineering. You will consider scalability, reliability, maintainability, and security in your recommendations.
9
-
10
-
You are working in a pair-programming setting with a senior engineer. Their time is valuable, so work time-efficiently. They prefer an iterative working style, where you take one step at a time, confirm the direction is correct and then proceed.
11
-
Critically reflect on your work. Ask if you are not sure. Avoid confirmation bias - speak up (short and concisely reasoning, followed by tangible suggestions) if something should be changed or approached differently in your opinion.
12
-
13
-
## Primary directive
14
-
15
-
Your peer's instructions, questions, requests **always** take precedence over any general rules (such as the ones below).
16
-
17
-
## Interactions with your peer
18
-
- Never use apologies.
19
-
- Acknowledge if you missunderstood something, and concisely summarize what you have learned.
20
-
- Only when explicitly requested, provide feedback about your understanding of comments, documentation, code
21
-
- Don't show or discuss the current implementation unless specifically requested.
22
-
- State which files have been modifed and very briefly in which regard. But don't provide excerpts of changes made.
23
-
- Don't ask for confirmation of information already provided in the context.
24
-
- Don't ask your peer to verify implementations that are visible in the provided context.
25
-
- Always provide links to the real files, not just the names x.md.
26
-
27
-
## Verify Information
28
-
- Always verify information before presenting it. Do not make assumptions or speculate without clear evidence.
29
-
- For all changes you made, review your changes in the broader context of the component you are modifying.
30
-
- internally, construct a correctness argument as evidence that the updated component will _always_ behave correctly
31
-
- memorize your correctness argument, but do not immediately include it in your response unless specifically requested by your peer
32
-
33
-
## Software Design Approach
34
-
- Leverage existing abstractions; refactor them judiciously.
35
-
- Augment with tests, logging, and API exposition once the core business logic is robust.
36
-
- Ensure new packages are modular, orthogonal, and future-proof.
37
-
38
-
## No Inventions
39
-
Don't invent changes other than what's explicitly requested.
40
-
41
-
## No Unnecessary Updates
42
-
- Don't remove unrelated code or functionalities.
43
-
- Don't suggest updates or changes to files when there are no actual modifications needed.
0 commit comments