Skip to content

Latest commit

 

History

History
186 lines (143 loc) · 9.57 KB

File metadata and controls

186 lines (143 loc) · 9.57 KB

Coding Agent Instructions (repository-wide, language-agnostic)

These instructions guide coding agents to generate changes consistent with this repository's conventions, regardless of programming language.

Glossary

  • Tunables: user-adjustable parameters that shape behavior, exposed via options or configuration files.
  • Canonical defaults: the single, authoritative definition of all tunables and their defaults.

Implementation guidance

  • Before coding:
    • Perform a comprehensive inventory of the codebase. Search for and read:
      • README.md, CONTRIBUTING.md, and all other documentation files.
      • code files related to the task.
    • Identify existing code architecture, design patterns, canonical defaults, naming patterns and coding styles.
  • When coding:
    • Follow the core principles, TypeScript/Node.js and OCPP-specific conventions below.
    • Follow identified design patterns, naming patterns and coding styles.
  • After coding:
    • Ensure changes pass quality gates below.
  • When adding a tunable:
    • Add to canonical defaults with safe value.
    • Ensure the options and configuration section below is respected.
    • Update documentation and serialization.
  • When implementing analytical methods:
    • Follow statistical conventions below.
  • When refactoring:
    • Keep public APIs stable; provide aliases if renaming unless explicitly requested.
    • Update code, tests, and documentation atomically.
  • When documenting:
    • Follow documentation conventions below.

Monorepo structure

4 TypeScript packages (pnpm workspace: /, /ui/common, /ui/cli, /ui/web) + 1 Python project (/tests/ocpp-server). Each has its own quality gates — see sub-project READMEs.

UI Common (ui-common) is the shared library for CLI and Web UI. No re-exports between packages.

Core principles

  • Design patterns: prefer established patterns (e.g., factory, singleton, strategy) for code organization and extensibility.
  • Algorithmic: prefer algorithms or heuristics solving the problem while minimizing time and space complexity.
  • DRY: avoid duplication of logic, data, and naming. Factor out commonalities.
  • Single source of truth: maintain a canonical defaults map for configuration tunables. Derive all user-facing options automatically.
  • Naming coherence: prefer semantically accurate names across code, documentation, directories, and outputs. Avoid synonyms that create ambiguity.
  • English-only: code, tests, logs, comments, and documentation must be in English.
  • Small, verifiable changes: prefer minimal diffs that keep public behavior stable unless explicitly requested.
  • Tests-first mindset: add or update minimal tests before refactoring or feature changes. Follow test conventions in tests/TEST_STYLE_GUIDE.md.
  • Documentation standards: must follow established standards for programming languages.

Options and configuration

  • Dynamic generation: derive CLI and configuration options automatically from canonical defaults. Avoid manual duplication.
  • Merge precedence: defaults < user options < explicit overrides (highest precedence). Never silently drop user-provided values.
  • Validation: enforce constraints (choices, ranges, types) at the option layer with explicit typing.
  • Help text: provide concrete examples for complex options, especially override mechanisms.

Statistical conventions

  • Hypothesis testing: use a single test statistic (e.g., t-test) when possible.
  • Divergence metrics: document direction explicitly (e.g., KL(A||B) vs KL(B||A)); normalize distributions; add numerical stability measures.
  • Effect sizes: report alongside test statistics and p-values; use standard formulas; document directional interpretation.
  • Distribution comparisons: use multiple complementary metrics (parametric and non-parametric).
  • Multiple testing: document corrections or acknowledge their absence.

Reporting conventions

  • Structure: start with run configuration, then stable section order for comparability.
  • Format: use structured formats (e.g., tables) for metrics; avoid free-form text for data.
  • Interpretation: include threshold guidelines; avoid overclaiming certainty.
  • Artifacts: timestamp outputs; include configuration metadata.

Documentation conventions

  • Clarity: plain, unambiguous language; avoid marketing jargon and speculation.
  • Concision: remove boilerplate; state facts directly without redundant phrasing.
  • Structure: use consistent section ordering; follow stable patterns for comparable content.
  • Timeliness: document current state; exclude historical evolution (except brief API breaking change notes).
  • Terminology: use correct and consistent terminology; distinguish clearly between related concepts.
  • Exhaustivity: cover all user-facing behavior and constraints; omit internal implementation details unless necessary for usage.
  • Pertinence: include information that aids understanding or usage; remove tangential content.
  • No duplication: maintain single authoritative documentation source; reference other sources rather than copying.

Documentation serves as an operational specification, not narrative prose.

TypeScript conventions

  • Naming: Use camelCase for variables/functions/methods, PascalCase for classes/types/enums/interfaces.
  • Async operations: Prefer async/await over raw Promises; handle rejections explicitly with try/catch.
  • Error handling: Use typed errors (BaseError, OCPPError) with structured properties; avoid generic Error.
  • Worker communication: Use broadcast channels for decoupled worker<->main thread messaging.
  • Null safety: Avoid non-null assertions (!); use optional chaining (?.) and nullish coalescing (??).
  • Type safety: Prefer explicit types over any; use type guards and discriminated unions where appropriate.
  • Promise patterns: Return Promises from async operations; store resolvers/rejectors in Maps for request/response flows.
  • Immutability: Avoid mutating shared state; clone objects before modification when needed.

Python conventions

  • Naming: Use snake_case for variables/functions/methods/modules, PascalCase for classes, SCREAMING_SNAKE_CASE for constants.
  • Type hints: Annotate all function signatures; use mypy with the strict-like configuration defined in pyproject.toml.
  • Enumerations: Prefer StrEnum for string-valued enumerations.
  • Async operations: Prefer async/await with asyncio; handle CancelledError and cleanup explicitly.
  • Error handling: Use specific exception types; avoid bare except.
  • Formatting and linting: Use ruff for formatting and linting; follow rules configured in pyproject.toml.
  • Testing: Use pytest with pytest-asyncio; use async def test_* naming, plain assert, and pytest.raises for error cases.

OCPP-specific conventions

  • Command naming: Follow OCPP standard naming exactly (e.g., RemoteStartTransaction, BootNotification, StatusNotification).
  • Enumeration naming: Use standard OCPP specifications enumeration names and values exactly (e.g., ConnectorStatusEnumType with values Available, Occupied). Avoid string literals when an enumeration exists.
  • Version handling: Clearly distinguish between OCPP 1.6 and 2.0.x implementations in separate namespaces/files.
  • Payload validation: Validate against OCPP JSON schemas when ocppStrictCompliance is enabled.
  • Message format: Use standard SRPC format: [messageTypeId, messageId, action, payload] or [messageTypeId, messageId, payload].
  • UUID tracking: Use UUIDs to correlate requests with responses; store pending operations in Maps with UUID keys.
  • Response handling: Ensure to wait for all expected responses before resolving broadcast requests.

Quality gates

Each sub-project has its own quality gates (format, typecheck, lint, build, test). See sub-project READMEs for exact commands. Run gates for every sub-project affected by your changes.

  • Logs use appropriate levels (error, warn, info, debug).
  • Pull request title and commit messages follow Conventional Commits format.

Examples

Naming coherence

Good (consistent style, clear semantics):

const thresholdValue = 0.06
const processingMode = 'piecewise'
type ChargingStationStatus = 'Available' | 'Preparing' | 'Charging'

Bad (mixed styles, ambiguous):

const threshold_value = 0.06    // inconsistent case style
const thresholdAim = 0.06       // synonym creates ambiguity
type charging_station_status    // wrong casing for type

Promise-based request/response pattern

Good (proper async flow):

protected handleProtocolRequest(
  uuid: string,
  procedureName: ProcedureName,
  payload: RequestPayload
): Promise<ResponsePayload> {
  return new Promise<ResponsePayload>((resolve, reject) => {
    this.pendingRequests.set(uuid, { reject, resolve })
    this.sendBroadcastChannelRequest(uuid, procedureName, payload)
  })
}

Bad (returns void, no Promise):

protected handleProtocolRequest(
  uuid: string,
  procedureName: ProcedureName,
  payload: RequestPayload
): void {
  this.sendBroadcastChannelRequest(uuid, procedureName, payload)
  // Response never reaches caller!
}

Statistical reporting

| Metric      | Value | Interpretation        |
| ----------- | ----- | --------------------- |
| KL(A‖B)     | 0.023 | < 0.1: low divergence |
| Effect size | 0.12  | small to medium       |

By following these instructions, coding agents should propose changes that are consistent and maintainable across languages.