atdata-app 0.1.0b1__tar.gz
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.
- atdata_app-0.1.0b1/.chainlink/issues.db +0 -0
- atdata_app-0.1.0b1/.chainlink/rules/c.md +43 -0
- atdata_app-0.1.0b1/.chainlink/rules/cpp.md +39 -0
- atdata_app-0.1.0b1/.chainlink/rules/csharp.md +51 -0
- atdata_app-0.1.0b1/.chainlink/rules/elixir-phoenix.md +57 -0
- atdata_app-0.1.0b1/.chainlink/rules/elixir.md +39 -0
- atdata_app-0.1.0b1/.chainlink/rules/global.md +103 -0
- atdata_app-0.1.0b1/.chainlink/rules/go.md +44 -0
- atdata_app-0.1.0b1/.chainlink/rules/java.md +42 -0
- atdata_app-0.1.0b1/.chainlink/rules/javascript-react.md +44 -0
- atdata_app-0.1.0b1/.chainlink/rules/javascript.md +36 -0
- atdata_app-0.1.0b1/.chainlink/rules/kotlin.md +44 -0
- atdata_app-0.1.0b1/.chainlink/rules/odin.md +53 -0
- atdata_app-0.1.0b1/.chainlink/rules/php.md +46 -0
- atdata_app-0.1.0b1/.chainlink/rules/project.md +5 -0
- atdata_app-0.1.0b1/.chainlink/rules/python.md +44 -0
- atdata_app-0.1.0b1/.chainlink/rules/ruby.md +47 -0
- atdata_app-0.1.0b1/.chainlink/rules/rust.md +48 -0
- atdata_app-0.1.0b1/.chainlink/rules/sanitize-patterns.txt +22 -0
- atdata_app-0.1.0b1/.chainlink/rules/scala.md +45 -0
- atdata_app-0.1.0b1/.chainlink/rules/swift.md +50 -0
- atdata_app-0.1.0b1/.chainlink/rules/typescript-react.md +39 -0
- atdata_app-0.1.0b1/.chainlink/rules/typescript.md +93 -0
- atdata_app-0.1.0b1/.chainlink/rules/web.md +80 -0
- atdata_app-0.1.0b1/.chainlink/rules/zig.md +48 -0
- atdata_app-0.1.0b1/.claude/hooks/post-edit-check.py +404 -0
- atdata_app-0.1.0b1/.claude/hooks/pre-web-check.py +111 -0
- atdata_app-0.1.0b1/.claude/hooks/prompt-guard.py +578 -0
- atdata_app-0.1.0b1/.claude/hooks/session-start.py +196 -0
- atdata_app-0.1.0b1/.claude/hooks/work-check.py +81 -0
- atdata_app-0.1.0b1/.claude/mcp/safe-fetch-server.py +302 -0
- atdata_app-0.1.0b1/.claude/settings.json +62 -0
- atdata_app-0.1.0b1/.dockerignore +26 -0
- atdata_app-0.1.0b1/.github/workflows/ci.yml +36 -0
- atdata_app-0.1.0b1/.github/workflows/publish.yml +19 -0
- atdata_app-0.1.0b1/.gitignore +210 -0
- atdata_app-0.1.0b1/.mcp.json +12 -0
- atdata_app-0.1.0b1/.python-version +1 -0
- atdata_app-0.1.0b1/.vscode/settings.json +7 -0
- atdata_app-0.1.0b1/CHANGELOG.md +23 -0
- atdata_app-0.1.0b1/CLAUDE.md +98 -0
- atdata_app-0.1.0b1/Dockerfile +41 -0
- atdata_app-0.1.0b1/PKG-INFO +156 -0
- atdata_app-0.1.0b1/README.md +140 -0
- atdata_app-0.1.0b1/docs/api-reference.md +44 -0
- atdata_app-0.1.0b1/docs/data-model.md +27 -0
- atdata_app-0.1.0b1/pyproject.toml +37 -0
- atdata_app-0.1.0b1/railway.toml +9 -0
- atdata_app-0.1.0b1/src/atdata_app/__init__.py +15 -0
- atdata_app-0.1.0b1/src/atdata_app/auth.py +57 -0
- atdata_app-0.1.0b1/src/atdata_app/config.py +39 -0
- atdata_app-0.1.0b1/src/atdata_app/database.py +565 -0
- atdata_app-0.1.0b1/src/atdata_app/identity.py +24 -0
- atdata_app-0.1.0b1/src/atdata_app/ingestion/__init__.py +0 -0
- atdata_app-0.1.0b1/src/atdata_app/ingestion/backfill.py +148 -0
- atdata_app-0.1.0b1/src/atdata_app/ingestion/jetstream.py +81 -0
- atdata_app-0.1.0b1/src/atdata_app/ingestion/processor.py +61 -0
- atdata_app-0.1.0b1/src/atdata_app/main.py +64 -0
- atdata_app-0.1.0b1/src/atdata_app/models.py +209 -0
- atdata_app-0.1.0b1/src/atdata_app/sql/schema.sql +114 -0
- atdata_app-0.1.0b1/src/atdata_app/xrpc/__init__.py +0 -0
- atdata_app-0.1.0b1/src/atdata_app/xrpc/procedures.py +270 -0
- atdata_app-0.1.0b1/src/atdata_app/xrpc/queries.py +347 -0
- atdata_app-0.1.0b1/src/atdata_app/xrpc/router.py +10 -0
- atdata_app-0.1.0b1/tests/__init__.py +0 -0
- atdata_app-0.1.0b1/tests/conftest.py +12 -0
- atdata_app-0.1.0b1/tests/test_config.py +23 -0
- atdata_app-0.1.0b1/tests/test_identity.py +54 -0
- atdata_app-0.1.0b1/tests/test_ingestion.py +156 -0
- atdata_app-0.1.0b1/tests/test_models.py +251 -0
- atdata_app-0.1.0b1/uv.lock +966 -0
|
Binary file
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
### C Best Practices
|
|
2
|
+
|
|
3
|
+
#### Memory Safety
|
|
4
|
+
- Always check return values of malloc/calloc
|
|
5
|
+
- Free all allocated memory (use tools like valgrind)
|
|
6
|
+
- Initialize all variables before use
|
|
7
|
+
- Use sizeof() with the variable, not the type
|
|
8
|
+
|
|
9
|
+
```c
|
|
10
|
+
// GOOD: Safe memory allocation
|
|
11
|
+
int *arr = malloc(n * sizeof(*arr));
|
|
12
|
+
if (arr == NULL) {
|
|
13
|
+
return -1; // Handle allocation failure
|
|
14
|
+
}
|
|
15
|
+
// ... use arr ...
|
|
16
|
+
free(arr);
|
|
17
|
+
|
|
18
|
+
// BAD: Unchecked allocation
|
|
19
|
+
int *arr = malloc(n * sizeof(int));
|
|
20
|
+
arr[0] = 1; // Crash if malloc failed
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
#### Buffer Safety
|
|
24
|
+
- Always bounds-check array access
|
|
25
|
+
- Use `strncpy`/`snprintf` instead of `strcpy`/`sprintf`
|
|
26
|
+
- Validate string lengths before copying
|
|
27
|
+
|
|
28
|
+
```c
|
|
29
|
+
// GOOD: Safe string copy
|
|
30
|
+
char dest[64];
|
|
31
|
+
strncpy(dest, src, sizeof(dest) - 1);
|
|
32
|
+
dest[sizeof(dest) - 1] = '\0';
|
|
33
|
+
|
|
34
|
+
// BAD: Buffer overflow risk
|
|
35
|
+
char dest[64];
|
|
36
|
+
strcpy(dest, src); // No bounds check
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
#### Security
|
|
40
|
+
- Never use `gets()` (use `fgets()`)
|
|
41
|
+
- Validate all external input
|
|
42
|
+
- Use constant-time comparison for secrets
|
|
43
|
+
- Avoid integer overflow in size calculations
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
### C++ Best Practices
|
|
2
|
+
|
|
3
|
+
#### Modern C++ (C++17+)
|
|
4
|
+
- Use smart pointers (`unique_ptr`, `shared_ptr`) over raw pointers
|
|
5
|
+
- Use RAII for resource management
|
|
6
|
+
- Prefer `std::string` and `std::vector` over C arrays
|
|
7
|
+
- Use `auto` for complex types, explicit types for clarity
|
|
8
|
+
|
|
9
|
+
```cpp
|
|
10
|
+
// GOOD: Modern C++ with smart pointers
|
|
11
|
+
auto config = std::make_unique<Config>();
|
|
12
|
+
auto users = std::vector<User>{};
|
|
13
|
+
|
|
14
|
+
// BAD: Manual memory management
|
|
15
|
+
Config* config = new Config();
|
|
16
|
+
// ... forgot to delete
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
#### Error Handling
|
|
20
|
+
- Use exceptions for exceptional cases
|
|
21
|
+
- Use `std::optional` for values that may not exist
|
|
22
|
+
- Use `std::expected` (C++23) or result types for expected failures
|
|
23
|
+
|
|
24
|
+
```cpp
|
|
25
|
+
// GOOD: Optional for missing values
|
|
26
|
+
std::optional<User> findUser(const std::string& id) {
|
|
27
|
+
auto it = users.find(id);
|
|
28
|
+
if (it == users.end()) {
|
|
29
|
+
return std::nullopt;
|
|
30
|
+
}
|
|
31
|
+
return it->second;
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
#### Security
|
|
36
|
+
- Validate all input boundaries
|
|
37
|
+
- Use `std::string_view` for non-owning string references
|
|
38
|
+
- Avoid C-style casts; use `static_cast`, `dynamic_cast`
|
|
39
|
+
- Never use `sprintf`; use `std::format` or streams
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
### C# Best Practices
|
|
2
|
+
|
|
3
|
+
#### Code Style
|
|
4
|
+
- Follow .NET naming conventions (PascalCase for public, camelCase for private)
|
|
5
|
+
- Use `var` when type is obvious from right side
|
|
6
|
+
- Use expression-bodied members for simple methods
|
|
7
|
+
- Enable nullable reference types
|
|
8
|
+
|
|
9
|
+
```csharp
|
|
10
|
+
// GOOD: Modern C# style
|
|
11
|
+
public class UserService
|
|
12
|
+
{
|
|
13
|
+
private readonly IUserRepository _repository;
|
|
14
|
+
|
|
15
|
+
public UserService(IUserRepository repository)
|
|
16
|
+
=> _repository = repository;
|
|
17
|
+
|
|
18
|
+
public async Task<User?> GetUserAsync(string id)
|
|
19
|
+
=> await _repository.FindByIdAsync(id);
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
#### Error Handling
|
|
24
|
+
- Use specific exception types
|
|
25
|
+
- Never catch and swallow exceptions silently
|
|
26
|
+
- Use `try-finally` or `using` for cleanup
|
|
27
|
+
|
|
28
|
+
```csharp
|
|
29
|
+
// GOOD: Proper async error handling
|
|
30
|
+
public async Task<Result<User>> GetUserAsync(string id)
|
|
31
|
+
{
|
|
32
|
+
try
|
|
33
|
+
{
|
|
34
|
+
var user = await _repository.FindByIdAsync(id);
|
|
35
|
+
return user is null
|
|
36
|
+
? Result<User>.NotFound()
|
|
37
|
+
: Result<User>.Ok(user);
|
|
38
|
+
}
|
|
39
|
+
catch (DbException ex)
|
|
40
|
+
{
|
|
41
|
+
_logger.LogError(ex, "Database error fetching user {Id}", id);
|
|
42
|
+
throw;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
#### Security
|
|
48
|
+
- Use parameterized queries (never string interpolation for SQL)
|
|
49
|
+
- Validate all input with data annotations or FluentValidation
|
|
50
|
+
- Use ASP.NET's built-in anti-forgery tokens
|
|
51
|
+
- Store secrets in Azure Key Vault or similar
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Phoenix & LiveView Rules
|
|
2
|
+
|
|
3
|
+
## HEEx Template Syntax (Critical)
|
|
4
|
+
- **Attributes use `{}`**: `<div id={@id}>` — never `<%= %>` in attributes
|
|
5
|
+
- **Body values use `{}`**: `{@value}` — use `<%= %>` only for blocks (if/for/cond)
|
|
6
|
+
- **Class lists require `[]`**: `class={["base", @flag && "active"]}` — bare `{}` is invalid
|
|
7
|
+
- **No `else if`**: Use `cond` for multiple conditions
|
|
8
|
+
- **Comments**: `<%!-- comment --%>`
|
|
9
|
+
- **Literal curlies**: Use `phx-no-curly-interpolation` on parent tag
|
|
10
|
+
|
|
11
|
+
## Phoenix v1.8
|
|
12
|
+
- Wrap templates with `<Layouts.app flash={@flash}>` (already aliased)
|
|
13
|
+
- `current_scope` errors → move routes to proper `live_session`, pass to Layouts.app
|
|
14
|
+
- `<.flash_group>` only in layouts.ex
|
|
15
|
+
- Use `<.icon name="hero-x-mark">` for icons, `<.input>` for form fields
|
|
16
|
+
|
|
17
|
+
## LiveView
|
|
18
|
+
- Use `<.link navigate={}>` / `push_navigate`, not deprecated `live_redirect`
|
|
19
|
+
- Hooks with own DOM need `phx-update="ignore"`
|
|
20
|
+
- Avoid LiveComponents unless necessary
|
|
21
|
+
- No inline `<script>` tags — use assets/js/app.js
|
|
22
|
+
|
|
23
|
+
## Streams (Always use for collections)
|
|
24
|
+
```elixir
|
|
25
|
+
stream(socket, :items, items) # append
|
|
26
|
+
stream(socket, :items, items, at: -1) # prepend
|
|
27
|
+
stream(socket, :items, items, reset: true) # filter/refresh
|
|
28
|
+
```
|
|
29
|
+
Template: `<div id="items" phx-update="stream">` with `:for={{id, item} <- @streams.items}`
|
|
30
|
+
- Streams aren't enumerable — refetch + reset to filter
|
|
31
|
+
- Empty states: `<div class="hidden only:block">Empty</div>` as sibling
|
|
32
|
+
|
|
33
|
+
## Forms
|
|
34
|
+
```elixir
|
|
35
|
+
# LiveView: always use to_form
|
|
36
|
+
assign(socket, form: to_form(changeset))
|
|
37
|
+
```
|
|
38
|
+
```heex
|
|
39
|
+
<%!-- Template: always @form, never @changeset --%>
|
|
40
|
+
<.form for={@form} id="my-form" phx-submit="save">
|
|
41
|
+
<.input field={@form[:name]} type="text" />
|
|
42
|
+
</.form>
|
|
43
|
+
```
|
|
44
|
+
- Never `<.form let={f}>` or `<.form for={@changeset}>`
|
|
45
|
+
|
|
46
|
+
## Router
|
|
47
|
+
- Scope alias is auto-prefixed: `scope "/", AppWeb do` → `live "/users", UserLive` = `AppWeb.UserLive`
|
|
48
|
+
|
|
49
|
+
## Ecto
|
|
50
|
+
- Preload associations accessed in templates
|
|
51
|
+
- Use `Ecto.Changeset.get_field/2` to read changeset fields
|
|
52
|
+
- Don't cast programmatic fields (user_id) — set explicitly
|
|
53
|
+
|
|
54
|
+
## Testing
|
|
55
|
+
- Use `has_element?(view, "#my-id")`, not raw HTML matching
|
|
56
|
+
- Debug selectors: `LazyHTML.filter(LazyHTML.from_fragment(render(view)), "selector")`
|
|
57
|
+
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Elixir Core Rules
|
|
2
|
+
|
|
3
|
+
## Critical Mistakes to Avoid
|
|
4
|
+
- **No early returns**: Last expression in a block is always returned
|
|
5
|
+
- **No list indexing with brackets**: Use `Enum.at(list, i)`, not `list[i]`
|
|
6
|
+
- **No struct access syntax**: Use `struct.field`, not `struct[:field]` (structs don't implement Access)
|
|
7
|
+
- **Rebinding in blocks doesn't work**: `socket = if cond, do: assign(socket, :k, v)` - bind the result, not inside
|
|
8
|
+
- **`%{}` matches ANY map**: Use `map_size(map) == 0` guard for empty maps
|
|
9
|
+
- **No `String.to_atom/1` on user input**: Memory leak risk
|
|
10
|
+
- **No nested modules in same file**: Causes cyclic dependencies
|
|
11
|
+
|
|
12
|
+
## Pattern Matching & Functions
|
|
13
|
+
- Match on function heads over `if`/`case` in bodies
|
|
14
|
+
- Use guards: `when is_binary(name) and byte_size(name) > 0`
|
|
15
|
+
- Use `with` for chaining `{:ok, _}` / `{:error, _}` operations
|
|
16
|
+
- Predicates end with `?` (not `is_`): `valid?/1` not `is_valid/1`
|
|
17
|
+
- Reserve `is_thing` names for guard macros
|
|
18
|
+
|
|
19
|
+
## Data Structures
|
|
20
|
+
- Prepend to lists: `[new | list]` not `list ++ [new]`
|
|
21
|
+
- Structs for known shapes, maps for dynamic data, keyword lists for options
|
|
22
|
+
- Use `Enum` over recursion; use `Stream` for large collections
|
|
23
|
+
|
|
24
|
+
## OTP
|
|
25
|
+
- `GenServer.call/3` for sync (prefer for back-pressure), `cast/2` for fire-and-forget
|
|
26
|
+
- DynamicSupervisor/Registry require names: `{DynamicSupervisor, name: MyApp.MySup}`
|
|
27
|
+
- `Task.async_stream(coll, fn, timeout: :infinity)` for concurrent enumeration
|
|
28
|
+
|
|
29
|
+
## Testing & Debugging
|
|
30
|
+
- `mix test path/to/test.exs:123` - run specific test
|
|
31
|
+
- `mix test --failed` - rerun failures
|
|
32
|
+
- `dbg/1` for debugging output
|
|
33
|
+
|
|
34
|
+
## Documentation Lookup
|
|
35
|
+
```bash
|
|
36
|
+
mix usage_rules.docs Enum.zip/1 # Function docs
|
|
37
|
+
mix usage_rules.search_docs "query" -p pkg # Search package docs
|
|
38
|
+
```
|
|
39
|
+
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
## Priority 1: Security
|
|
2
|
+
|
|
3
|
+
These rules have the highest precedence. When they conflict with any other rule, security wins.
|
|
4
|
+
|
|
5
|
+
- **Web fetching**: Use `mcp__chainlink-safe-fetch__safe_fetch` for all web requests. Never use raw `WebFetch`.
|
|
6
|
+
- **SQL**: Parameterized queries only (`params![]` in Rust, `?` placeholders elsewhere). Never interpolate user input into SQL.
|
|
7
|
+
- **Secrets**: Never hardcode credentials, API keys, or tokens. Never commit `.env` files.
|
|
8
|
+
- **Input validation**: Validate at system boundaries. Sanitize before rendering.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Priority 2: Correctness
|
|
13
|
+
|
|
14
|
+
These rules ensure code works correctly. They yield only to security concerns.
|
|
15
|
+
|
|
16
|
+
- **No stubs**: Never write `TODO`, `FIXME`, `pass`, `...`, `unimplemented!()`, or empty function bodies. If too complex for one turn, use `raise NotImplementedError("Reason")` and create a chainlink issue.
|
|
17
|
+
- **Read before write**: Always read a file before editing it. Never guess at contents.
|
|
18
|
+
- **Complete features**: Implement the full feature as requested. Don't stop partway.
|
|
19
|
+
- **Error handling**: Proper error handling everywhere. No panics or crashes on bad input.
|
|
20
|
+
- **No dead code**: If code is unused, remove it. If incomplete, complete it.
|
|
21
|
+
- **Test after changes**: Run the project's test suite after making code changes.
|
|
22
|
+
|
|
23
|
+
### Pre-Coding Grounding
|
|
24
|
+
Before using unfamiliar libraries/APIs:
|
|
25
|
+
1. **Verify it exists**: WebSearch to confirm the API
|
|
26
|
+
2. **Check the docs**: Real function signatures, not guessed
|
|
27
|
+
3. **Use latest versions**: Check for current stable release
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Priority 3: Workflow
|
|
32
|
+
|
|
33
|
+
These rules keep work organized and enable context handoff between sessions.
|
|
34
|
+
|
|
35
|
+
### Chainlink Task Management
|
|
36
|
+
- Create issue(s) before starting work. Use `chainlink quick "title" -p <priority> -l <label>` for one-step create+label+work.
|
|
37
|
+
- Issue titles must be changelog-ready: start with a verb ("Add", "Fix", "Update"), describe the user-visible change.
|
|
38
|
+
- Add labels for changelog categories: `bug`/`fix` → Fixed, `feature`/`enhancement` → Added, `breaking` → Changed, `security` → Security.
|
|
39
|
+
- For multi-part features: create parent issue + subissues. Work one at a time.
|
|
40
|
+
- Add context as you discover things: `chainlink comment <id> "..."`
|
|
41
|
+
|
|
42
|
+
### Labels for Changelog Categories
|
|
43
|
+
- `bug`, `fix` → **Fixed**
|
|
44
|
+
- `feature`, `enhancement` → **Added**
|
|
45
|
+
- `breaking`, `breaking-change` → **Changed**
|
|
46
|
+
- `security` → **Security**
|
|
47
|
+
- `deprecated` → **Deprecated**
|
|
48
|
+
- `removed` → **Removed**
|
|
49
|
+
- (no label) → **Changed** (default)
|
|
50
|
+
|
|
51
|
+
### Quick Reference
|
|
52
|
+
```bash
|
|
53
|
+
# One-step create + label + start working
|
|
54
|
+
chainlink quick "Fix auth timeout" -p high -l bug
|
|
55
|
+
|
|
56
|
+
# Or use create with flags
|
|
57
|
+
chainlink create "Add dark mode" -p medium --label feature --work
|
|
58
|
+
|
|
59
|
+
# Multi-part feature
|
|
60
|
+
chainlink create "Add user auth" -p high --label feature
|
|
61
|
+
chainlink subissue 1 "Add registration endpoint"
|
|
62
|
+
chainlink subissue 1 "Add login endpoint"
|
|
63
|
+
|
|
64
|
+
# Track progress
|
|
65
|
+
chainlink session work <id>
|
|
66
|
+
chainlink comment <id> "Found existing helper in utils/"
|
|
67
|
+
|
|
68
|
+
# Close (auto-updates CHANGELOG.md)
|
|
69
|
+
chainlink close <id>
|
|
70
|
+
chainlink close <id> --no-changelog # Skip changelog for internal work
|
|
71
|
+
chainlink close-all --no-changelog # Batch close
|
|
72
|
+
|
|
73
|
+
# Quiet mode for scripting
|
|
74
|
+
chainlink -q create "Fix bug" -p high # Outputs just the ID number
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Session Management
|
|
78
|
+
Sessions auto-start. You must end them properly:
|
|
79
|
+
```bash
|
|
80
|
+
chainlink session work <id> # Mark current focus
|
|
81
|
+
chainlink session end --notes "..." # Save handoff context
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
End sessions when: context is getting long, user indicates stopping, or you've completed significant work.
|
|
85
|
+
|
|
86
|
+
Handoff notes must include: what was accomplished, what's in progress, what's next.
|
|
87
|
+
|
|
88
|
+
### Priority Guide
|
|
89
|
+
- `critical`: Blocking other work, security issue, production down
|
|
90
|
+
- `high`: User explicitly requested, core functionality
|
|
91
|
+
- `medium`: Standard features, improvements
|
|
92
|
+
- `low`: Nice-to-have, cleanup, optimization
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Priority 4: Style
|
|
97
|
+
|
|
98
|
+
These are preferences, not hard rules. They yield to all higher priorities.
|
|
99
|
+
|
|
100
|
+
- Write code, don't narrate. Skip "Here is the code" / "Let me..." / "I'll now..."
|
|
101
|
+
- Brief explanations only when the code isn't self-explanatory.
|
|
102
|
+
- For implementations >500 lines: create parent issue + subissues, work incrementally.
|
|
103
|
+
- When conversation is long: create a tracking issue with `chainlink comment` notes for context preservation.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
### Go Best Practices
|
|
2
|
+
|
|
3
|
+
#### Code Style
|
|
4
|
+
- Use `gofmt` for formatting
|
|
5
|
+
- Use `golint` and `go vet` for linting
|
|
6
|
+
- Follow effective Go guidelines
|
|
7
|
+
- Keep functions short and focused
|
|
8
|
+
|
|
9
|
+
#### Error Handling
|
|
10
|
+
```go
|
|
11
|
+
// GOOD: Check and handle errors
|
|
12
|
+
func readConfig(path string) (*Config, error) {
|
|
13
|
+
data, err := os.ReadFile(path)
|
|
14
|
+
if err != nil {
|
|
15
|
+
return nil, fmt.Errorf("reading config: %w", err)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
var config Config
|
|
19
|
+
if err := json.Unmarshal(data, &config); err != nil {
|
|
20
|
+
return nil, fmt.Errorf("parsing config: %w", err)
|
|
21
|
+
}
|
|
22
|
+
return &config, nil
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// BAD: Ignoring errors
|
|
26
|
+
func readConfig(path string) *Config {
|
|
27
|
+
data, _ := os.ReadFile(path) // Don't ignore errors
|
|
28
|
+
var config Config
|
|
29
|
+
json.Unmarshal(data, &config)
|
|
30
|
+
return &config
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
#### Concurrency
|
|
35
|
+
- Use channels for communication between goroutines
|
|
36
|
+
- Use `sync.WaitGroup` for waiting on multiple goroutines
|
|
37
|
+
- Use `context.Context` for cancellation and timeouts
|
|
38
|
+
- Avoid shared mutable state; prefer message passing
|
|
39
|
+
|
|
40
|
+
#### Security
|
|
41
|
+
- Use `html/template` for HTML output (auto-escaping)
|
|
42
|
+
- Use parameterized queries for SQL
|
|
43
|
+
- Validate all input at API boundaries
|
|
44
|
+
- Use `crypto/rand` for secure random numbers
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
### Java Best Practices
|
|
2
|
+
|
|
3
|
+
#### Code Style
|
|
4
|
+
- Follow Google Java Style Guide or project conventions
|
|
5
|
+
- Use meaningful variable and method names
|
|
6
|
+
- Keep methods short (< 30 lines)
|
|
7
|
+
- Prefer composition over inheritance
|
|
8
|
+
|
|
9
|
+
#### Error Handling
|
|
10
|
+
```java
|
|
11
|
+
// GOOD: Specific exceptions with context
|
|
12
|
+
public Config readConfig(Path path) throws ConfigException {
|
|
13
|
+
try {
|
|
14
|
+
String content = Files.readString(path);
|
|
15
|
+
return objectMapper.readValue(content, Config.class);
|
|
16
|
+
} catch (IOException e) {
|
|
17
|
+
throw new ConfigException("Failed to read config: " + path, e);
|
|
18
|
+
} catch (JsonProcessingException e) {
|
|
19
|
+
throw new ConfigException("Invalid JSON in config: " + path, e);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// BAD: Catching generic Exception
|
|
24
|
+
public Config readConfig(Path path) {
|
|
25
|
+
try {
|
|
26
|
+
return objectMapper.readValue(Files.readString(path), Config.class);
|
|
27
|
+
} catch (Exception e) {
|
|
28
|
+
return null; // Swallowing error
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
#### Security
|
|
34
|
+
- Use PreparedStatement for SQL (never string concatenation)
|
|
35
|
+
- Validate all user input
|
|
36
|
+
- Use secure random (SecureRandom) for security-sensitive operations
|
|
37
|
+
- Never log sensitive data (passwords, tokens)
|
|
38
|
+
|
|
39
|
+
#### Testing
|
|
40
|
+
- Use JUnit 5 for unit tests
|
|
41
|
+
- Use Mockito for mocking dependencies
|
|
42
|
+
- Aim for high coverage on business logic
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
### JavaScript/React Best Practices
|
|
2
|
+
|
|
3
|
+
#### Component Structure
|
|
4
|
+
- Use functional components with hooks
|
|
5
|
+
- Keep components small and focused (< 200 lines)
|
|
6
|
+
- Extract custom hooks for reusable logic
|
|
7
|
+
- Use PropTypes for runtime type checking
|
|
8
|
+
|
|
9
|
+
```javascript
|
|
10
|
+
// GOOD: Clear component with PropTypes
|
|
11
|
+
import PropTypes from 'prop-types';
|
|
12
|
+
|
|
13
|
+
const UserCard = ({ user, onSelect }) => {
|
|
14
|
+
return (
|
|
15
|
+
<div onClick={() => onSelect(user.id)}>
|
|
16
|
+
{user.name}
|
|
17
|
+
</div>
|
|
18
|
+
);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
UserCard.propTypes = {
|
|
22
|
+
user: PropTypes.shape({
|
|
23
|
+
id: PropTypes.string.isRequired,
|
|
24
|
+
name: PropTypes.string.isRequired,
|
|
25
|
+
}).isRequired,
|
|
26
|
+
onSelect: PropTypes.func.isRequired,
|
|
27
|
+
};
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
#### State Management
|
|
31
|
+
- Use `useState` for local state
|
|
32
|
+
- Use `useReducer` for complex state logic
|
|
33
|
+
- Lift state up only when needed
|
|
34
|
+
- Consider context for deeply nested prop drilling
|
|
35
|
+
|
|
36
|
+
#### Performance
|
|
37
|
+
- Use `React.memo` for expensive pure components
|
|
38
|
+
- Use `useMemo` and `useCallback` appropriately
|
|
39
|
+
- Avoid inline object/function creation in render
|
|
40
|
+
|
|
41
|
+
#### Security
|
|
42
|
+
- Never use `dangerouslySetInnerHTML` with user input
|
|
43
|
+
- Sanitize URLs before using in `href` or `src`
|
|
44
|
+
- Validate props at component boundaries
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
### JavaScript Best Practices
|
|
2
|
+
|
|
3
|
+
#### Code Style
|
|
4
|
+
- Use `const` by default, `let` when needed, never `var`
|
|
5
|
+
- Use arrow functions for callbacks
|
|
6
|
+
- Use template literals over string concatenation
|
|
7
|
+
- Use destructuring for object/array access
|
|
8
|
+
|
|
9
|
+
#### Error Handling
|
|
10
|
+
```javascript
|
|
11
|
+
// GOOD: Proper async error handling
|
|
12
|
+
async function fetchUser(id) {
|
|
13
|
+
try {
|
|
14
|
+
const response = await fetch(`/api/users/${id}`);
|
|
15
|
+
if (!response.ok) {
|
|
16
|
+
throw new Error(`HTTP ${response.status}`);
|
|
17
|
+
}
|
|
18
|
+
return await response.json();
|
|
19
|
+
} catch (error) {
|
|
20
|
+
console.error('Failed to fetch user:', error);
|
|
21
|
+
throw error; // Re-throw or handle appropriately
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// BAD: Ignoring errors
|
|
26
|
+
async function fetchUser(id) {
|
|
27
|
+
const response = await fetch(`/api/users/${id}`);
|
|
28
|
+
return response.json(); // No error handling
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
#### Security
|
|
33
|
+
- Never use `eval()` or `innerHTML` with user input
|
|
34
|
+
- Validate all input on both client and server
|
|
35
|
+
- Use `textContent` instead of `innerHTML` when possible
|
|
36
|
+
- Sanitize URLs before navigation or fetch
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
### Kotlin Best Practices
|
|
2
|
+
|
|
3
|
+
#### Code Style
|
|
4
|
+
- Follow Kotlin coding conventions
|
|
5
|
+
- Use `val` over `var` when possible
|
|
6
|
+
- Use data classes for simple data holders
|
|
7
|
+
- Leverage null safety features
|
|
8
|
+
|
|
9
|
+
```kotlin
|
|
10
|
+
// GOOD: Idiomatic Kotlin
|
|
11
|
+
data class User(val id: String, val name: String)
|
|
12
|
+
|
|
13
|
+
class UserService(private val repository: UserRepository) {
|
|
14
|
+
fun findUser(id: String): User? =
|
|
15
|
+
repository.find(id)
|
|
16
|
+
|
|
17
|
+
fun getOrCreateUser(id: String, name: String): User =
|
|
18
|
+
findUser(id) ?: repository.create(User(id, name))
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
#### Null Safety
|
|
23
|
+
- Avoid `!!` (force non-null); use safe calls instead
|
|
24
|
+
- Use `?.let {}` for conditional execution
|
|
25
|
+
- Use Elvis operator `?:` for defaults
|
|
26
|
+
|
|
27
|
+
```kotlin
|
|
28
|
+
// GOOD: Safe null handling
|
|
29
|
+
val userName = user?.name ?: "Unknown"
|
|
30
|
+
user?.let { saveToDatabase(it) }
|
|
31
|
+
|
|
32
|
+
// BAD: Force unwrapping
|
|
33
|
+
val userName = user!!.name // Crash if null
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
#### Coroutines
|
|
37
|
+
- Use structured concurrency with `CoroutineScope`
|
|
38
|
+
- Handle exceptions in coroutines properly
|
|
39
|
+
- Use `withContext` for context switching
|
|
40
|
+
|
|
41
|
+
#### Security
|
|
42
|
+
- Use parameterized queries
|
|
43
|
+
- Validate input at boundaries
|
|
44
|
+
- Use sealed classes for exhaustive error handling
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
### Odin Best Practices
|
|
2
|
+
|
|
3
|
+
#### Code Style
|
|
4
|
+
- Follow Odin naming conventions
|
|
5
|
+
- Use `snake_case` for procedures and variables
|
|
6
|
+
- Use `Pascal_Case` for types
|
|
7
|
+
- Prefer explicit over implicit
|
|
8
|
+
|
|
9
|
+
```odin
|
|
10
|
+
// GOOD: Clear Odin code
|
|
11
|
+
User :: struct {
|
|
12
|
+
id: string,
|
|
13
|
+
name: string,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
find_user :: proc(id: string) -> (User, bool) {
|
|
17
|
+
user, found := repository[id]
|
|
18
|
+
return user, found
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
#### Error Handling
|
|
23
|
+
- Use multiple return values for errors
|
|
24
|
+
- Use `or_return` for early returns
|
|
25
|
+
- Create explicit error types when needed
|
|
26
|
+
|
|
27
|
+
```odin
|
|
28
|
+
// GOOD: Explicit error handling
|
|
29
|
+
Config_Error :: enum {
|
|
30
|
+
File_Not_Found,
|
|
31
|
+
Parse_Error,
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
load_config :: proc(path: string) -> (Config, Config_Error) {
|
|
35
|
+
data, ok := os.read_entire_file(path)
|
|
36
|
+
if !ok {
|
|
37
|
+
return {}, .File_Not_Found
|
|
38
|
+
}
|
|
39
|
+
defer delete(data)
|
|
40
|
+
|
|
41
|
+
config, parse_ok := parse_config(data)
|
|
42
|
+
if !parse_ok {
|
|
43
|
+
return {}, .Parse_Error
|
|
44
|
+
}
|
|
45
|
+
return config, nil
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
#### Memory Management
|
|
50
|
+
- Use explicit allocators
|
|
51
|
+
- Prefer temp allocator for short-lived allocations
|
|
52
|
+
- Use `defer` for cleanup
|
|
53
|
+
- Be explicit about ownership
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
### PHP Best Practices
|
|
2
|
+
|
|
3
|
+
#### Code Style
|
|
4
|
+
- Follow PSR-12 coding standard
|
|
5
|
+
- Use strict types: `declare(strict_types=1);`
|
|
6
|
+
- Use type hints for parameters and return types
|
|
7
|
+
- Use Composer for dependency management
|
|
8
|
+
|
|
9
|
+
```php
|
|
10
|
+
<?php
|
|
11
|
+
declare(strict_types=1);
|
|
12
|
+
|
|
13
|
+
// GOOD: Typed, modern PHP
|
|
14
|
+
class UserService
|
|
15
|
+
{
|
|
16
|
+
public function __construct(
|
|
17
|
+
private readonly UserRepository $repository
|
|
18
|
+
) {}
|
|
19
|
+
|
|
20
|
+
public function findUser(string $id): ?User
|
|
21
|
+
{
|
|
22
|
+
return $this->repository->find($id);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
#### Error Handling
|
|
28
|
+
- Use exceptions for error handling
|
|
29
|
+
- Create custom exception classes
|
|
30
|
+
- Never suppress errors with `@`
|
|
31
|
+
|
|
32
|
+
#### Security
|
|
33
|
+
- Use PDO with prepared statements (never string interpolation)
|
|
34
|
+
- Use `password_hash()` and `password_verify()` for passwords
|
|
35
|
+
- Validate and sanitize all user input
|
|
36
|
+
- Use CSRF tokens for forms
|
|
37
|
+
- Set secure cookie flags
|
|
38
|
+
|
|
39
|
+
```php
|
|
40
|
+
// GOOD: Prepared statement
|
|
41
|
+
$stmt = $pdo->prepare('SELECT * FROM users WHERE id = :id');
|
|
42
|
+
$stmt->execute(['id' => $id]);
|
|
43
|
+
|
|
44
|
+
// BAD: SQL injection vulnerability
|
|
45
|
+
$result = $pdo->query("SELECT * FROM users WHERE id = '$id'");
|
|
46
|
+
```
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<!-- Project-Specific Rules -->
|
|
2
|
+
<!-- Add rules specific to your project here. Examples: -->
|
|
3
|
+
<!-- - Don't modify the /v1/ API endpoints without approval -->
|
|
4
|
+
<!-- - Always update CHANGELOG.md when adding features -->
|
|
5
|
+
<!-- - Database migrations must be backward-compatible -->
|