Skip to content

Project Rules

This page is a compact reference index for the canonical project rules.

The source of truth is docs/PROJECT_RULES.md. Do not treat this page as a full replacement for that file.

Rule categories

CategorySummary
Core principlespreserve universality, layering, determinism and composition boundaries
Language/commentsEnglish-only comments, XML docs, diagnostics and technical text
NamingPascalCase types/members, _camelCase private fields, I... interfaces
File layoutone main public type per file, file-scoped namespaces
FormattingAllman braces, readable wrapping, guard clauses
Asyncasync methods use Async; async void only for true event handlers
Null handlinguse Thrower-based guards; validate at public boundaries
Exceptionsall project exceptions go through Thrower or approved helpers
Public API docsnon-trivial public APIs should have XML documentation
Data flowprefer read-only abstractions and boundary input normalization
Parser/ASTuse safe child access, local parser mutations and processed-node markers
Type stack/IRpreserve stack order, type inference and backend intrinsic contracts
Architectureavoid hidden authorities and concrete Wist/profile coupling in framework layers
DI/reflectioncentralize reflection and keep behavior deterministic
Testingadd tests for non-trivial parsing, binding, intrinsic, optimizer, parity and DI changes
Hardcode controlbehavior-selection strings need a clear owner and must not leak into generic framework layers
Fitness checksnew architecture rules need practical tests, scripts, CI checks, or review checklist coverage

High-impact rules for documentation work

When updating documentation, preserve these rules:

  • write English technical text in code and docs that behave as project references;
  • do not document implementation details as stable public API unless tests support them;
  • distinguish framework-level UniversalToolchain behavior from Wist convenience behavior;
  • avoid implying that restricted dialect composition is a hardened sandbox;
  • avoid performance claims without benchmark evidence;
  • document current implementation details honestly when they are not yet stable contracts.

High-impact rules for module work

When adding or changing modules:

  • use stable aliases and runtime exports;
  • keep syntax owned by lexer/parser/AST stages;
  • use SafeGet where child access may be out of range;
  • do not mutate ancestors outside allowed parser scope;
  • mark processed nodes when required by parser flow;
  • self-filter AST visitors;
  • preserve bytecode/AIR stack discipline;
  • add interpreter/compiler parity tests when both backends are supported.

High-impact rules for backend and optimizer work

When changing backend or optimizer behavior:

  • do not add intrinsics without backend support analysis;
  • register type-stack behavior where required;
  • check backend capabilities before emitting backend-specific intrinsic forms;
  • keep optimizers semantics-preserving;
  • avoid making optimizer output required for base correctness;
  • test unsupported backend/intrinsic paths explicitly.

Forbidden practices summary

The canonical rules forbid, among other things:

  • direct exception throwing outside Thrower or approved Thrower helpers;
  • non-English comments or XML docs;
  • mixed null-check styles;
  • hidden parser mutations outside allowed local scope;
  • unsafe indexing where SafeGet is required;
  • scattered reflection logic;
  • magic strings for protocol-like behavior without a clear shared contract;
  • stateful mutable static fields in new code;
  • convenience layers that become hidden framework authorities;
  • framework-level branching on concrete shipped profile ids when a general path exists.
  • hardcoded product, profile, module, backend, rule, intrinsic, or function names in generic framework layers.

Contributor checklist

Before merging non-trivial code changes, verify:

  • naming and formatting match project style;
  • exceptions/null checks use project-approved mechanisms;
  • public APIs are documented when non-trivial;
  • parser/visitor/IR stack invariants are preserved;
  • intrinsics have backend and type-processing support;
  • tests cover behavior and parity where applicable;
  • the change preserves universality rather than narrowing architecture for a local case.

Built for developers who want to use, extend, or understand UniversalToolchain.