Lane 11 PR 2: the sheet language — expressions, evaluator, dice, definitions, validator, conformance fixtures (#737) #961

Merged
claude-bot merged 3 commits from build/lane11-2-evaluator into main 2026-09-30 07:59:55 +00:00
Collaborator

Lane 11 (#737) PR 2. This is the engine every sheet is computed with (IS-405 server, IS-431, IS-425). It adds no database, no routes and no UI; nothing outside app/sheets/ imports it yet.

webapp/backend/app/sheets/:

  • expr.py: the expression language from the contract's §3.4. It is total and side-effect free.
    • Syntax: paths @a.b.c, [*] lists, repeat keys, and row./entry. locals.
    • Functions: if, the math functions, lookup, rank (plus a two-argument form), has, and sum/count/any/all/min/max.
    • Numbers: floored %, round half away from zero, and normalised output.
    • Nulls: a missing path is null, arithmetic treats null as 0, and a comparison with null is false.
    • Errors: typed, with their offsets. There are limits of 2,000 characters and 64 levels of nesting.
    • Dice are rejected here; they belong to generators only.
  • evaluator.py: evaluates a definition over data/entries/resources/overrides/ext.
    • Derivations: the terms a sheet prints under a value.
    • Declarative modifiers: add, multiply, upgrade, downgrade, cap and override, stacked bonus (best per type) or flat.
    • Also: when, repeat groups, entries with provenance and a snapshot, derived rows, resources and tracks.
    • Order and caching: evaluation follows the dependency order, with a cycle guard, and compiled definitions are cached by digest.
  • dice.py: NdM, keep/drop, an injectable RNG, and the individual dice kept. It's for creation and levelling only (D85).
  • definition_model.py and definition.schema.json: the Pydantic model and the published JSON Schema.
  • validator.py: the §3.2 checks.
    • Every @path/ref resolves, with did-you-mean.
    • No cycles; no dice in computed fields, when or max_expr; when parses; generators and views are well-formed.
    • Fixtures evaluate to their expected values.
    • It returns a structured report (errors, warnings, fixtures n of m) for the upload report (IS-430).
  • builtin/generic/: the generic character and creature (§3.6, owner answer L2).
  • conformance/: 309 expression cases and 13 sheet cases, language-neutral, plus a README spelling out every semantic. PR 4's JavaScript evaluator runs these same files, so the two can't drift.

Tests:

  • tests/sheets/ passes: 442. That covers every conformance case, parser limits, totality over random inputs, overflow, dice with a scripted RNG, every validator check, did-you-mean, schema staleness, and the generic definitions validating clean.
  • ruff check and format are clean over the full lint set, and changelog.py check passes.

Stacked on it (in progress): PR 3 (the server), PR 4 (the JS evaluator), and PRs 5a and 5b (the PF2e and 5e definitions).

Changelog: changelog.d/737-lane11-evaluator.added.md.

🤖 Generated with Claude Code

Lane 11 (#737) PR 2. This is the engine every sheet is computed with (IS-405 server, IS-431, IS-425). It adds no database, no routes and no UI; nothing outside `app/sheets/` imports it yet. **`webapp/backend/app/sheets/`:** - **`expr.py`:** the expression language from the contract's §3.4. It is total and side-effect free. - **Syntax:** paths `@a.b.c`, `[*]` lists, repeat keys, and `row.`/`entry.` locals. - **Functions:** `if`, the math functions, `lookup`, `rank` (plus a two-argument form), `has`, and `sum/count/any/all/min/max`. - **Numbers:** floored `%`, round half away from zero, and normalised output. - **Nulls:** a missing path is null, arithmetic treats null as 0, and a comparison with null is false. - **Errors:** typed, with their offsets. There are limits of 2,000 characters and 64 levels of nesting. - **Dice** are rejected here; they belong to generators only. - **`evaluator.py`:** evaluates a definition over `data`/`entries`/`resources`/`overrides`/`ext`. - **Derivations:** the terms a sheet prints under a value. - **Declarative modifiers:** add, multiply, upgrade, downgrade, cap and override, stacked `bonus` (best per type) or `flat`. - **Also:** `when`, repeat groups, entries with provenance and a snapshot, derived rows, resources and tracks. - **Order and caching:** evaluation follows the dependency order, with a cycle guard, and compiled definitions are cached by digest. - **`dice.py`:** `NdM`, keep/drop, an injectable RNG, and the individual dice kept. It's for creation and levelling only (D85). - **`definition_model.py` and `definition.schema.json`:** the Pydantic model and the published JSON Schema. - **`validator.py`:** the §3.2 checks. - Every `@path`/`ref` resolves, with **did-you-mean**. - No cycles; no dice in computed fields, `when` or `max_expr`; `when` parses; generators and views are well-formed. - Fixtures evaluate to their expected values. - It returns a structured report (errors, warnings, fixtures n of m) for the upload report (IS-430). - **`builtin/generic/`:** the generic character and creature (§3.6, owner answer L2). - **`conformance/`:** **309 expression cases and 13 sheet cases**, language-neutral, plus a README spelling out every semantic. PR 4's JavaScript evaluator runs these same files, so the two can't drift. **Tests:** - `tests/sheets/` passes: **442**. That covers every conformance case, parser limits, totality over random inputs, overflow, dice with a scripted RNG, every validator check, did-you-mean, schema staleness, and the generic definitions validating clean. - ruff check and format are clean over the full lint set, and `changelog.py check` passes. Stacked on it (in progress): PR 3 (the server), PR 4 (the JS evaluator), and PRs 5a and 5b (the PF2e and 5e definitions). Changelog: `changelog.d/737-lane11-evaluator.added.md`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Lane 11 PR 2: iterative evaluation of long chains, unit tests, ruff format, changelog (#737)
All checks were successful
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 1m2s
CI / Backend lint (ruff) (pull_request) Successful in 38s
CI / Bot/backend version sync (pull_request) Successful in 29s
CI / Bot tests and audit (pull_request) Successful in 2m4s
CI / Feedback site tests (pull_request) Successful in 50s
CI / Docker image build (pull_request) Successful in 22s
CI / Does this change touch the recording path? (pull_request) Successful in 43s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Has been skipped
CI / Frontend (shard 2/2) (pull_request) Successful in 6m0s
CI / Frontend (shard 1/2) (pull_request) Successful in 7m37s
CI / End-to-end journeys (desktop) (pull_request) Successful in 8m24s
CI / End-to-end journeys (keyboard) (pull_request) Successful in 7m28s
CI / End-to-end journeys (phone) (pull_request) Successful in 7m7s
CI / Backend migration, tests, and audit (pull_request) Successful in 17m34s
b83621dfcb
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign in to join this conversation.
No description provided.