add development conventions
This commit is contained in:
194
CONVENTIONS.md
Normal file
194
CONVENTIONS.md
Normal file
@@ -0,0 +1,194 @@
|
||||
# Yonexus.Client — Development Conventions
|
||||
|
||||
This document defines implementation conventions for the client repository.
|
||||
|
||||
## 1. Naming Conventions
|
||||
|
||||
### Files
|
||||
- use `camelCase.ts` for source files
|
||||
- use descriptive module names matching responsibility
|
||||
- avoid generic names like `utils.ts` unless the scope is extremely narrow and justified
|
||||
|
||||
Examples:
|
||||
- `localState.ts`
|
||||
- `keys.ts`
|
||||
- `heartbeat.ts`
|
||||
- `onGatewayStart.ts`
|
||||
|
||||
### Types / Interfaces
|
||||
- use `PascalCase`
|
||||
|
||||
Examples:
|
||||
- `LocalClientState`
|
||||
- `ClientRuntimeState`
|
||||
- `AuthProofPayload`
|
||||
|
||||
### Functions
|
||||
- use `camelCase`
|
||||
|
||||
Examples:
|
||||
- `loadLocalState`
|
||||
- `signProofPayload`
|
||||
- `startHeartbeatLoop`
|
||||
|
||||
### Constants
|
||||
- use `UPPER_SNAKE_CASE` for exported constants
|
||||
|
||||
Examples:
|
||||
- `HEARTBEAT_INTERVAL_MS`
|
||||
- `RECONNECT_MAX_DELAY_MS`
|
||||
|
||||
---
|
||||
|
||||
## 2. Module Boundaries
|
||||
|
||||
### `plugin/index.ts`
|
||||
- wiring only
|
||||
- no business logic
|
||||
|
||||
### `plugin/core/`
|
||||
- reusable domain logic
|
||||
- local state handling
|
||||
- key generation/signing
|
||||
- pairing/auth/heartbeat rules
|
||||
- dispatch behavior
|
||||
|
||||
### `servers/`
|
||||
- runtime/service bootstrap code
|
||||
- WebSocket client lifecycle
|
||||
- reconnect/backoff orchestration
|
||||
|
||||
### `plugin/hooks/`
|
||||
- OpenClaw lifecycle integration
|
||||
- should call into core/runtime modules, not reimplement logic
|
||||
|
||||
### `plugin/tools/`
|
||||
- thin wrappers over core/runtime capabilities
|
||||
- no duplication of business rules already implemented in core
|
||||
|
||||
### `plugin/commands/`
|
||||
- operator-facing orchestration layer
|
||||
- should not directly mutate local state bypassing core rules
|
||||
|
||||
---
|
||||
|
||||
## 3. Error Conventions
|
||||
|
||||
### Error Shape
|
||||
Use structured errors rather than throwing untyped strings.
|
||||
|
||||
Recommended shape:
|
||||
|
||||
```ts
|
||||
interface YonexusClientError extends Error {
|
||||
code: string;
|
||||
details?: Record<string, unknown>;
|
||||
}
|
||||
```
|
||||
|
||||
### Error Code Style
|
||||
- uppercase snake case
|
||||
- stable once published in logs/tools/docs
|
||||
|
||||
Examples:
|
||||
- `INVALID_CONFIG`
|
||||
- `CONNECTION_FAILED`
|
||||
- `AUTH_FAILED`
|
||||
- `NOT_AUTHENTICATED`
|
||||
|
||||
### Error Messages
|
||||
- concise
|
||||
- operator-readable
|
||||
- do not leak secrets, private keys, raw proofs, or unsafe internal details
|
||||
|
||||
---
|
||||
|
||||
## 4. Logging Conventions
|
||||
|
||||
### General Rule
|
||||
Logs should help operators debug connection/auth issues without exposing secrets.
|
||||
|
||||
### Must Never Log in Plaintext
|
||||
- `notifyBotToken`
|
||||
- local `secret`
|
||||
- private key material
|
||||
- raw signed proof payload
|
||||
- human-provided pairing code
|
||||
|
||||
### Preferred Log Fields
|
||||
When possible, log structured context such as:
|
||||
- `identifier`
|
||||
- event type
|
||||
- connection state transition
|
||||
- reason code
|
||||
- timestamp
|
||||
|
||||
### Example Good Logs
|
||||
- `connecting to mainHost for identifier=client-a`
|
||||
- `auth failed identifier=client-a reason=STALE_TIMESTAMP`
|
||||
- `heartbeat loop started identifier=client-a`
|
||||
|
||||
---
|
||||
|
||||
## 5. Protocol Usage Conventions
|
||||
|
||||
- treat `protocol/` submodule as the source of truth
|
||||
- do not implement local protocol deviations without updating `Yonexus.Protocol`
|
||||
- if client behavior reveals a protocol gap, fix protocol docs rather than hiding the difference in client-only logic
|
||||
|
||||
---
|
||||
|
||||
## 6. Local State Conventions
|
||||
|
||||
- keep persisted local state explicit and versionable
|
||||
- separate long-lived trust data from transient connection runtime state
|
||||
- avoid implicit mutation of local state from multiple unrelated modules
|
||||
- persist changes through explicit state APIs rather than ad-hoc file writes
|
||||
|
||||
---
|
||||
|
||||
## 7. Reconnect Conventions
|
||||
|
||||
- reconnect behavior should be explicit and observable
|
||||
- use bounded backoff
|
||||
- stop background timers cleanly on disconnect
|
||||
- avoid overlapping reconnect attempts
|
||||
|
||||
---
|
||||
|
||||
## 8. Pairing / Auth Conventions
|
||||
|
||||
- treat pairing, auth, and re-pair transitions as explicit states
|
||||
- do not silently reuse stale secrets after `re_pair_required`
|
||||
- proof construction and signing should be deterministic and testable
|
||||
- keep signing and local key handling isolated in dedicated modules
|
||||
|
||||
---
|
||||
|
||||
## 9. Command / Tool Conventions
|
||||
|
||||
- commands and tools should surface operator-safe summaries
|
||||
- commands should call core/runtime services, not modify raw state directly
|
||||
- sending before authentication should fail clearly unless explicit queueing is designed later
|
||||
|
||||
---
|
||||
|
||||
## 10. Testing Conventions
|
||||
|
||||
- write unit tests for local state, signing, and routing first
|
||||
- reserve integration tests for connection/pairing/auth flows
|
||||
- test negative paths deliberately:
|
||||
- connection failure
|
||||
- invalid auth response
|
||||
- forced re-pair
|
||||
- heartbeat stop/start
|
||||
- malformed builtin payload
|
||||
|
||||
---
|
||||
|
||||
## 11. Change Discipline
|
||||
|
||||
When implementing:
|
||||
- update docs when behavior changes
|
||||
- avoid silent divergence from `PLAN.md`, `TASKS.md`, and `protocol/PROTOCOL.md`
|
||||
- keep runtime code understandable; do not spread core state transitions across too many files
|
||||
Reference in New Issue
Block a user