# Pureline Specification 1.5: Emvus + Core

## Definition

**Pureline** is an opinionated coding style focused on linear control flow, explicit intent, compact formatting, small units, clear ownership, and minimal syntactic or architectural noise.

Pureline does not aim to minimize characters. It aims to minimize **unnecessary code**.

The preferred reading direction is:

```text
Input
↓
Validation
↓
Transformation
↓
Execution
↓
Result
```

Not:

```text
if
 └─ if
     └─ else
         └─ if
             └─ callback
                 └─ branch
```

The central Pureline principles are:

> **Linear Flow. Explicit Intent. Minimal Noise. Small Units. Clear Ownership. Cohesion over Size.**

**Version 1.5:** Adds the idiomatic Rust profile (`PL-RS-001` through `PL-RS-020`) while preserving all existing rule IDs and the 1.4 Cohesion over Size principle.

---

> Extract of the complete specification (pureline-1.5-full.md): Emvus + Core.

# 1. Pureline Core

These rules apply to all supported languages where the language allows them naturally.

| ID | Rule |
|---|---|
| PL-CORE-001 | Control flow should be as linear as possible |
| PL-CORE-002 | Avoid `else` |
| PL-CORE-003 | Prefer guard clauses |
| PL-CORE-004 | Use the clearest control-flow form for the language; brace-based languages use explicit blocks |
| PL-CORE-005 | Idiomatic language-native shorthand is allowed when it remains immediately readable |
| PL-CORE-006 | Functions should be small and focused |
| PL-CORE-007 | Names must carry meaning |
| PL-CORE-008 | Avoid unnecessary abstractions |
| PL-CORE-009 | Avoid God Classes and God Modules |
| PL-CORE-010 | Prefer immutable state |
| PL-CORE-011 | Prefer modern language features where they improve clarity |
| PL-CORE-012 | Avoid unnecessary vertical formatting |
| PL-CORE-013 | Comments must not compensate for unclear code |
| PL-CORE-014 | Handle invalid and error states early |
| PL-CORE-015 | Keep important side effects visible |
| PL-CORE-016 | Resources must have a clear lifecycle |
| PL-CORE-017 | Prefer framework-native APIs |
| PL-CORE-018 | Avoid magic values |
| PL-CORE-019 | Make dependencies explicit |
| PL-CORE-020 | Optimize hot paths deliberately, not accidentally |
| PL-CORE-021 | Keep packages and source folders small enough to scan at a glance |
| PL-CORE-022 | Cohesion over Size: prefer one coherent responsibility over arbitrary class line limits |

---

# 2. Control Flow

Control flow is one of the most important parts of Pureline.

Pureline standardizes **clarity and structure, not identical syntax across languages**. Java, JavaScript, TypeScript, Go, and Emvus use explicit blocks for control flow. Languages with established readable shorthand, such as Crystal postfix guards, may use that shorthand when the condition and action remain simple.

## PL-CF-001 — Prefer Guard Clauses

Preferred:

```java
if (request == null) {
    return Result.empty();
}

if (!request.valid()) {
    return Result.invalid();
}

var session = sessions.create(request.user());
return executor.execute(session, request);
```

Avoid:

```java
if (request != null) {
    if (request.valid()) {
        var session = sessions.create(request.user());
        return executor.execute(session, request);
    } else {
        return Result.invalid();
    }
}

return Result.empty();
```

The happy path should remain as close to the base indentation level as possible.

## PL-CF-002 — Avoid `else`

Avoid:

```java
if (valid) {
    execute();
} else {
    reject();
}
```

Prefer:

```java
if (!valid) {
    reject();
    return;
}

execute();
```

A ternary expression may be used for simple value selection:

```java
var state = valid ? State.READY : State.INVALID;
```

Complex nested ternaries are not Pureline.

## PL-CF-003 — Explicit Blocks in Brace-Based Languages

In Java, JavaScript, TypeScript, Go, and other brace-based languages, control-flow bodies use explicit blocks.

Not Pureline:

```java
if (!valid) return;
```

Also not Pureline:

```java
if (!valid)
    return;
```

Pureline:

```java
if (!valid) {
    return;
}
```

The same principle applies to `for`, `while`, and comparable control-flow constructs.

This rule does **not** ban idiomatic shorthand in languages where that shorthand is a normal, readable part of the language. Crystal postfix guards such as `return unless valid` are Pureline-compliant when kept simple.

---

# 3. Naming

## PL-NAME-001 — Names Must Be Meaningful

Good:

```text
request
session
player
packet
handler
storage
result
connection
worker
```

Avoid:

```text
r
s
p
x
tmp
obj
data2
thing
```

Also avoid names that are unnecessarily long:

```text
currentIncomingPlayerConnectionRequestObject
```

The rule is:

> **As short as possible, as explicit as necessary.**

Exceptions are allowed for established local conventions such as loop counters:

```java
for (int i = 0; i < size; i++) {
}
```

---

# 4. Functions

## PL-FN-001 — One Clear Responsibility

Preferred names:

```text
validateRequest()
createSession()
sendPacket()
loadUser()
closeConnection()
```

Avoid vague names:

```text
handleEverything()
process()
doStuff()
executeAll()
```

A function should normally represent one clearly identifiable action.

### Size guidance

```text
~5–30 lines  → normal
~30–50 lines → review
50+ lines    → usually split
```

These are heuristics, not absolute limits.

---

# 5. Classes and Modules

## PL-STRUCT-001 — One Clear Responsibility

Avoid structures like:

```text
ServerManager
 ├─ database
 ├─ players
 ├─ packets
 ├─ commands
 ├─ configuration
 ├─ HTTP
 └─ logging
```

Prefer:

```text
server/
    ServerRuntime

network/
    Connection
    PacketRegistry
    PacketDispatcher

session/
    Session
    SessionService

storage/
    UserStorage
    SessionStorage
```

A class has one clear responsibility when its members and internal state contribute to one cohesive concern. **Line count alone does not determine whether a class is well designed.** See `PL-STRUCT-003` for size guidance.

# 5.1 Package and Folder Density

## PL-STRUCT-002 — Keep Namespaces Small Enough to Scan

Pureline treats file and type density as part of code readability.

A package or source folder should be small enough that a developer can understand its contents at a glance without searching through a long flat list of unrelated files.

When the limit is exceeded, split the package or folder by responsibility instead of allowing it to become a dumping ground.

### Default limits

| Language | Pureline default |
|---|---|
| Java | Maximum 8 production top-level types/source files per package |
| Emvus | Maximum 8 production `.ev` source files per package/source folder |
| JavaScript | Maximum 10 production source modules per feature/source folder |
| TypeScript | Maximum 10 production source modules per feature/source folder |
| Go | Maximum 12 non-test, non-generated `.go` files per package directory |
| Crystal | Maximum 10 production `.cr` files per source/namespace folder |
| Rust | Maximum 10 hand-maintained production `.rs` files per feature/source folder |

These files do not count toward the limit:

- tests and specs
- generated source files
- metadata-only files
- `package-info.java`
- `module-info.java`
- JavaScript/TypeScript barrel files such as `index.ts` or `index.js`
- generated bindings or protocol output
- migration snapshots and comparable machine-generated artifacts

The purpose of this rule is not to force arbitrary folder nesting. A split should introduce a real responsibility boundary.

Bad:

```text
network/
    Connection.java
    ConnectionFactory.java
    ConnectionState.java
    Packet.java
    PacketCodec.java
    PacketDecoder.java
    PacketEncoder.java
    PacketRegistry.java
    PacketDispatcher.java
    PacketHandler.java
    PacketQueue.java
    PacketMetrics.java
    SocketConfig.java
    SocketRuntime.java
```

Preferred:

```text
network/
    Connection.java
    ConnectionFactory.java
    ConnectionState.java

network/packet/
    Packet.java
    PacketCodec.java
    PacketDecoder.java
    PacketEncoder.java
    PacketRegistry.java
    PacketDispatcher.java

network/runtime/
    PacketQueue.java
    PacketMetrics.java
    SocketConfig.java
    SocketRuntime.java
```

A project may override these thresholds through a future Pureline configuration file, but the default rule should remain intentionally strict.

---

# 5.2 Cohesion over Size

## PL-STRUCT-003 — Cohesion over Size (Zusammengehörigkeit vor Zeilenbegrenzung)

> **Cohesion over Size — Zusammengehörigkeit vor Zeilenbegrenzung.**

The preferred maximum class size is **guidance, never a hard limit**. Keep strongly related logic together when splitting it would make the code harder to read, maintain, test, or reason about. A larger cohesive class is preferable to multiple artificial classes connected by unnecessary delegation.

### Class size guidance

| Class size | Pureline recommendation |
|---|---|
| Up to 200 lines | Preferred normal case |
| 201–400 lines | Unproblematic when the class has a clear responsibility |
| 401–600 lines | Deliberate architectural decision; keep its cohesion understandable |
| More than 600 lines | Review recommended, **not prohibited** |

The ranges are **heuristics, not hard limits**. Crossing a threshold must not, by itself, produce a style violation or require a split.

### When larger classes are justified

- **Parsers and lexers:** A cohesive state machine may become more complicated when its states and transitions are scattered across artificial abstractions.
- **Algorithms:** Tightly coupled processing phases can be easier to understand and optimize when kept together.
- **Central data structures:** Methods sharing the same invariants and internal state can belong in one class.
- **Complex but cohesive logic:** Splitting is counterproductive when it adds indirection, unnecessary delegation, or more coordination than clarity.

### When to split anyway

Split by **real responsibility boundaries**, not by line count. Indicators include distinct subsystems evolving independently, unrelated reasons to change, weak coupling among groups of methods, or separate lifecycles that are obscured by one class.

**Tooling rule:** Pureline Checker and IDE inspections may show an informational size notice with a cohesion-review suggestion, particularly above 600 lines. They must not treat the number of lines as sufficient evidence of a violation, automatically extract classes, or require suppressions merely to keep a cohesive class intact.

This principle applies to **all Pureline language profiles**, including Java, JavaScript, TypeScript, Go, Crystal, Rust, and Emvus. Language-specific syntax and idioms continue to take precedence.

---

# 6. Formatting

## PL-FMT-001 — Prefer Compact Horizontal Calls

Preferred:

```java
var box = Block.box(min, min, max, max, max, 16);
```

Avoid unnecessary vertical expansion:

```java
var box = Block.box(
    min,
    min,
    max,
    max,
    max,
    16
);
```

Vertical formatting is allowed when it reveals meaningful semantic structure.

Example:

```java
var server = Server.builder()
    .host(config.host())
    .port(config.port())
    .executor(executor)
    .build();
```

Pureline distinguishes between unnecessary vertical expansion and meaningful semantic grouping.

---

# 7. Comments

## PL-DOC-001 — Comments Explain Why, Not What

Avoid:

```java
// Check if the player exists
if (player == null) {
    return;
}
```

Useful comments explain things such as protocol constraints, workarounds, external bugs, non-obvious mathematical behavior, or unusual performance constraints.

Code should explain **what** happens. Comments should explain **why** something unusual is necessary.

---

# 13. Emvus Profile

Pureline Emvus follows the **current Emvus language design**. This is a style profile for intended `.ev` syntax, not a claim that every showcased feature is already implemented by Ring 1.

## PL-EV-001 — Native Method Declarations

Declare methods with `method` and, when needed, a return type in `method<Type>`. Generic type variables are introduced through `where`, not by attaching another generic parameter list to the method name.

```java
method<Int> square(Int value) {
    return value * value
}

method<T> first(List<T> items) where T {
    return items.get(0)
}
```

A method without an explicit return type returns `Void`.

## PL-EV-002 — Empty Declaration Parentheses Are Optional; Call Parentheses Are Not

Both parameterless declarations are Pureline-compliant:

```java
method refresh {
    updateCache()
}

method shutdown() {
    closeConnections()
}
```

Both spellings declare zero-argument methods; the difference is cosmetic, **not** an overload distinction. Always write `refresh()` or `shutdown()` to execute the method; `object.refresh` is not a method call. Formatters should preserve or consistently configure either valid declaration style without marking the other as an error.

## PL-EV-003 — Braces Required; Semicolons Optional

Use explicit `{ ... }` blocks for `if`, loops, and comparable control flow. Prefer omitting optional semicolons in idiomatic Emvus, but do not reject existing valid semicolon-terminated code.

```java
method process(Int value) {
    if (value < 0) {
        return
    }

    println(value)
}
```

Brace-free inline guards and unnecessary `else` blocks are not Pureline. Keep continuation lines and long expressions unambiguous.

## PL-EV-004 — Naming, Imports, and Visibility

- Types: `PascalCase`; interfaces: `I` prefix (`IStorage`, `IConnection`).
- Methods, fields, properties, parameters, and locals: `camelCase`.
- Constants: `UPPER_SNAKE_CASE`.
- Packages: lower-case dotted paths.
- Source filenames: **camelCase**, for example `sessionService.ev`, even if the primary class is `SessionService`.
- The default visibility is `public`; specify `private` or `protected` when required.
- Symbol resolution is case-insensitive but source spelling is preserved: use the **declared spelling** consistently and do not define names that differ only in case.

```java
package app.session

use {
    std.collections.[IList, IIterator],
    app.storage.userStorage as Storage
}
```

Use explicit imports and aliases instead of relying on confusing collisions.

## PL-EV-005 — Types Should Communicate Intent

Emvus is statically typed by default. `var` performs **static type inference**; `dynamic` explicitly requests runtime-typed behavior.

```java
Person person = Person("Jason", 20)
var current = person.copy()
dynamic payload = receiveUnknownPayload()
```

Use `dynamic` at genuinely dynamic boundaries, not to bypass normal type checks. Both explicit and inferred static local types are Pureline-compliant.

## PL-EV-006 — Handle Nullability Through Stable Flow

Emvus does not require a `T?` annotation. It tracks null states through control flow. Guard a possibly-null value early and prefer a stable local snapshot of mutable properties before reasoning about their nullability.

```java
method<String> displayName(Profile profile) {
    final var nickname = profile.nickname

    if (nickname == null) {
        return "Unknown"
    }

    return nickname
}
```

Never rely on repeated unsynchronized reads of a mutable property having the same value. Make required field initialization explicit.

## PL-EV-007 — Prefer Typed Result Handling for Expected Failures

Emvus has no `try/catch/finally` syntax. Use `Result<T, E>`, `success`, `fail`, `?`, and `switch` as the language specifies.

```java
method<Result<Int, RangeException>> validatePort(Int port) {
    if (port < 1 || port > 65535) {
        fail RangeException(port, 1, 65535)
    }

    success port
}

method showPort(Int port) {
    switch (validatePort(port)) {
        success(value) -> println(value)
        error(problem) -> errprintln(problem.message)
    }
}
```

- `?` is for deliberate error propagation where types permit it.
- `!` causes a panic on error; reserve it for established invariants or boundary checks that truly cannot recover.
- Do not discard a `Result` or hide expected failure behind `panic`.
- Keep `success`, `fail`, and `return` distinct rather than wrapping every operation unnecessarily.

## PL-EV-008 — Make Resource Lifetimes Visible with `scoped`

Use Emvus's `scoped` construct for resources that must be closed when their scope ends.

```java
method<String> readFile(String path) {
    scoped var file = Files.open(path)
    return file.readAll()
}
```

Do not replace `scoped` with Java `try-with-resources`, Go `defer`, or a nonexistent Emvus `finally`. A resource's lifetime should remain clear even when the compiler optimizes memory.

## PL-EV-009 — Prefer Data Classes to Boilerplate

Use `data class` for small, named, data-centric types with the built-in generated behavior.

```java
data class Member(String name, Int age)

data class Server(String host, Int port = 25565)
```

Primary data properties are read-only outside initialization. `copy()` and `withX(...)` express modified copies and are shallow by default. Prefer generated equality, hashing, and textual representation where appropriate rather than rewriting them manually. Keep larger behavior-rich types as regular classes.

**Do not introduce a separate `record` style requirement:** the agreed Emvus design uses `data class` for named data models and `Dictionary` for dictionary/object-literal data.

## PL-EV-010 — Lists, Tuples, and Dictionaries Retain Their Defined Semantics

For `[...]` literals, **all element types exactly equal** implies a `List`; otherwise the expression is a tuple. Do not make Pureline overwrite the language's type-driven rule with a stylistic preference.

```java
var numbers = [10, 20, 30]        // List<Int>
var response = [200, "Success"]   // [Int, String]
```

Dictionary literals use `{ key: value }`; inferred mixed value types use `dynamic` where required by the language model. Dictionaries are accessed by **keys**, not structural-record dot notation.

```java
var server = {
    "name": "Emvus",
    "port": 25565
}

println(server["name"])
```

A changing element type can legitimately change list-versus-tuple inference. Keep that behavior visible at API boundaries through explicit declared types where appropriate.

## PL-EV-011 — Destructuring Is Positional

Use `{ ... }` to destructure tuple or data-class components in declaration order. `_` may skip an element.

```java
var { status, message } = [200, "OK"]
var { first, _ } = loadPair()
```

Do not reinterpret destructuring as named record matching. Prefer short meaningful bindings, not indiscriminate unpacking.

## PL-EV-012 — `switch` Should Expose Complete Branching

Use `switch` statements or expressions for real state alternatives. Expressions must be exhaustive or have a defined catch-all / failure arm.

```java
method<String> rankLabel(Rank rank) {
    return switch (rank) {
        MEMBER -> "Member"
        MODERATOR -> "Moderator"
        ADMIN -> "Admin"
    }
}
```

Prefer clear `success(...)` and `error(...)` patterns to nested conditions for `Result`. Keep catch-all patterns deliberate, not a way to hide forgotten cases.

## PL-EV-013 — Use Cascades Only When They Clarify a Single Receiver

Cascades with `..` are useful for a short sequence of operations on the same receiver.

```java
Person person = Person("Anna", 20)
    ..birthday()
    ..age = 21
```

Avoid chains that conceal unrelated effects, mutate several objects implicitly, or stretch across many statements.

## PL-EV-014 — Fibers and Threads Need Clear Lifecycles

`fiber {}`, `virtual {}`, and `thread {}` are distinct execution constructs with a common task-result pattern. Choose based on the actual workload, not because concurrency looks compact.

```java
var task = fiber {
    return calculate(10)
}

Int result = task.await()
```

- Await results and failures that matter.
- Make cancellation and ownership clear for long-lived tasks.
- Synchronize shared mutable state; `@Synchronized` is available where appropriate.
- Do not assume a task's captured object is stack-local or can be released when the spawning method returns.
- Avoid hidden fire-and-forget work in ordinary business methods.

## PL-EV-015 — Macros Must Improve Discoverability, Not Obscure It

Emvus macros are compile-time AST transformations with target declarations, `quote`, `$(...)` substitution, and AST builder APIs.

```java
macro Trace on Method {
    target.body.prepend(quote statement {
        println("Method entered")
    })
}
```

Pureline requires:

- Small macros with clearly stated responsibilities and supported targets.
- Deterministic expansion; source-order behavior and resulting members remain discoverable.
- Hygiene to avoid accidental name collisions.
- Compiler diagnostics when expansion creates conflicting or invalid code.
- Ordinary methods instead of macros when no substantial compile-time benefit exists.
- No reliance on unreviewed macro-time I/O, network, clock, or random side effects.

Generated code must satisfy semantic checks; checker/formatter tooling should not treat generated locations as ordinary hand-maintained files.

## PL-EV-016 — Do Not Program Against HyperAlloc Flow Internals

Emvus code may be optimized through Sublang, Optimind, and HyperAlloc Flow. Developers should express **semantics and lifetimes**, not manually guess a future allocation strategy.

- Favor straightforward object lifecycles and stable ownership.
- Keep shared mutable state explicit, especially across tasks.
- Prefer immutable data classes for simple values when they fit the domain.
- Do not build APIs around assumptions that an object is always stack-allocated, scalar-replaced, or pooled.
- Evaluate hot-path allocation and escape behavior through measurement and diagnostics, not folklore.

## PL-EV-017 — Package Density and Source Organization

A package/source folder should contain at most **8** production `.ev` modules by default. Tests, generated sources, and metadata-only files do not count. Split by actual feature responsibility rather than mechanically creating arbitrary subpackages.

A package name and a filename are different concepts: `app.session` remains lower-case, while `sessionService.ev` is `camelCase`.

## PL-EV-018 — Language-Native Rules Override Cross-Language Imitation

Pureline tooling must not report a violation merely because Emvus differs from Java, Rust, or Go:

- Optional `()` in **parameterless method declarations** are valid; calls always require `()`.
- Optional semicolons are valid.
- `where` is the native generic declaration syntax.
- `var` is statically inferred; `dynamic` is explicitly dynamic.
- `success`, `fail`, `?`, `!`, `scoped`, and AST macros have Emvus-specific meanings.
- `{ ... }` has valid context-dependent uses, including dictionaries and positional destructuring.
- `[ ... ]` is typed as a list or tuple according to Emvus's exact-element-type rule.

The formatter should be AST-aware, preserve meaning, and never apply `::` namespaces or semicolon requirements from other languages to `.ev` files.

---

# 15. Abstraction Rules

## PL-ARCH-001 — Abstraction Requires a Reason

Avoid abstractions such as:

```text
AbstractBaseFactoryManagerProvider
```

merely to reduce duplication.

Good reasons for abstraction include:

```text
multiple real implementations
clear API boundaries
platform-specific implementations
test seams
dependency inversion
shared domain contracts
```

---

# 16. Architecture

Pureline prefers clear dependency direction.

Example:

```text
domain
↓
service
↓
infrastructure
```

or feature-oriented modules:

```text
session/
network/
storage/
command/
runtime/
api/
```

Avoid cycles such as:

```text
network → session → storage → network
```

---

# 17. Side Effects

Important side effects should remain visible.

Preferred:

```java
var user = users.load(id);
var session = sessions.create(user);

sessions.save(session);
events.publish(new SessionCreated(session.id()));
```

Potentially misleading:

```java
sessions.createAndPersistAndNotify(user);
```

if persistence and event publication are important externally observable actions.

Pureline does not require exposing every internal operation. It requires avoiding surprising hidden behavior.

---

# 18. Immutability

Prefer immutable values by default.

Mutation should be intentional, local, and easy to identify.

Preferred examples include Java records, TypeScript readonly data, `const` in JavaScript, immutable value objects, and short-lived mutable local state.

Avoid shared mutable state where practical.

---

# 19. Dependencies

Dependencies should be visible in constructors, function parameters, or explicit module wiring.

Avoid hidden global access patterns and unnecessary service locators.

Dependency injection is encouraged where it improves architecture, but Pureline does not require a heavy DI framework.

---

# 20. Performance

Pureline prioritizes readability by default, but performance-sensitive paths should be written deliberately.

In hot paths:

- avoid unnecessary allocations
- avoid repeated reflection
- cache expensive resolution
- use appropriate collections
- avoid hidden blocking
- reduce unnecessary copying
- keep ownership clear

Performance optimizations must remain understandable.

---

# 23. Pureline Summary

Pureline code should feel:

- linear
- explicit
- compact
- modern
- low-noise
- modular
- cohesive regardless of line count
- predictable
- easy to scan
- easy to refactor
- hard to misunderstand

The core rule remains:

> **Code without noise.**

A second principle governs every language profile:

> **Pureline standardizes principles, not syntax.**

A language should remain idiomatic. Pureline removes unnecessary noise without stripping away the features that make Java, JavaScript, TypeScript, Go, Crystal, Rust, or Emvus effective in the first place.
