2026-05-21 12:28:09 +02:00
|
|
|
# AGENTS.md
|
|
|
|
|
|
|
|
|
|
This file provides guidance to coding agents collaborating on this repository.
|
|
|
|
|
|
|
|
|
|
## Mission
|
|
|
|
|
|
2026-06-05 13:51:26 +02:00
|
|
|
`storage-engine-playground` is an experimental Rust project for prototyping query engines and storage engines.
|
2026-05-21 12:28:09 +02:00
|
|
|
|
2026-05-21 15:56:29 +02:00
|
|
|
The goal is not production software. The goal is a clear, runnable playground for small prototypes that help answer concrete architecture questions:
|
2026-05-21 12:28:09 +02:00
|
|
|
|
2026-06-05 13:51:26 +02:00
|
|
|
- how a query language should be parsed, cataloged, planned, and optimized
|
|
|
|
|
- how a query planner and a query executor should be separated, and what intermediate representation sits between them
|
|
|
|
|
- how a query executor's operators (scans, joins, antijoins, projections) compose into a working snapshot evaluator
|
|
|
|
|
- how a storage engine should expose a backend-neutral interface (relations, rows, transactions, scans), and how that interface holds up across
|
|
|
|
|
different backends (in-process, file-backed, CRDT, and so on)
|
2026-05-21 12:28:09 +02:00
|
|
|
|
2026-05-21 15:56:29 +02:00
|
|
|
Priorities, in order:
|
2026-05-21 12:28:09 +02:00
|
|
|
|
2026-05-21 15:56:29 +02:00
|
|
|
1. Correctness: prototypes must have clear expected outputs and tests.
|
|
|
|
|
2. Clarity: each module and test should answer one research or engineering question.
|
|
|
|
|
3. Small scope: prefer narrow experiments over broad engine rewrites.
|
|
|
|
|
4. Explainability: planners should emit inspectable plans, not only executable structures.
|
|
|
|
|
5. Reproducibility: examples should use committed fixtures, deterministic tests, and documented commands.
|
2026-05-21 12:28:09 +02:00
|
|
|
|
2026-05-21 15:56:29 +02:00
|
|
|
## Core Rules
|
2026-05-21 12:28:09 +02:00
|
|
|
|
2026-05-21 15:56:29 +02:00
|
|
|
- Use English for code, comments, tests, and prose.
|
|
|
|
|
- Treat ignored local reference material as source material only. Do not import copied code into durable modules without an explicit decision.
|
|
|
|
|
- Prefer implementing small vertical slices: parse a subset, build a catalog, plan one rule shape, and test it.
|
|
|
|
|
- Do not build a full Datalog engine before the planning layer is useful and tested.
|
|
|
|
|
- Keep source language, relational planning, and backend execution separated.
|
|
|
|
|
- Prefer backend-neutral intermediate structures until a specific backend API requires specialization.
|
|
|
|
|
- Add comments only when they explain non-obvious planning, recursion, delta, or storage behavior.
|
|
|
|
|
- Treat tests and fixtures as part of the design, not as afterthoughts.
|
2026-05-21 12:28:09 +02:00
|
|
|
|
|
|
|
|
## Writing Style
|
|
|
|
|
|
|
|
|
|
- Use Oxford commas in inline lists: "a, b, and c" not "a, b, c".
|
|
|
|
|
- Do not use em dashes. Restructure the sentence, or use a colon or semicolon instead.
|
2026-05-21 15:56:29 +02:00
|
|
|
- Avoid colorful adjectives and adverbs. Write "storage engine" not "lightweight storage engine", "planner" not "clever planner".
|
|
|
|
|
- Use noun phrases for checklist items, not imperative verbs. Write "rule catalog construction" not "construct rule catalogs".
|
|
|
|
|
- Headings in Markdown files must be in title case: "Query Planning" not "Query planning". Minor words (a, an, the, and, but, or, for, in, on, at, to,
|
|
|
|
|
by, of) stay lowercase unless they are the first word.
|
2026-05-21 12:28:09 +02:00
|
|
|
|
|
|
|
|
## Repository Layout
|
|
|
|
|
|
2026-06-05 13:51:26 +02:00
|
|
|
Discover the current layout from the filesystem before editing.
|
|
|
|
|
The shape today is:
|
2026-05-21 12:28:09 +02:00
|
|
|
|
2026-06-05 13:51:26 +02:00
|
|
|
- `crates/`: Rust workspace.
|
|
|
|
|
See [`crates/README.md`](crates/README.md) for the responsibilities and dependency edges between the four crates (`storage`, `query-ops`,
|
|
|
|
|
`plan-runner`, `geomerge-demo`).
|
|
|
|
|
Each crate keeps its own `src/`, `tests/`, and (where relevant) `fixtures/`, `benches/`, and `docs/diagrams/` subdirectories.
|
|
|
|
|
- `tools/exporter/`: Haskell tool that consumes hand-authored `.scenario.json` files in `tools/exporter/examples/` and emits the runner-IR JSON
|
|
|
|
|
consumed by `crates/plan-runner`.
|
|
|
|
|
See [`tools/exporter/README.md`](tools/exporter/README.md).
|
2026-06-11 15:50:41 +02:00
|
|
|
- `tools/plan-viewer/`: static HTML viewer for `plan-runner` fixtures.
|
|
|
|
|
It evaluates a fixture in the browser and renders the plan DAG, per-node relations, input facts, and oracle comparison.
|
|
|
|
|
See [`tools/plan-viewer/README.md`](tools/plan-viewer/README.md).
|
2026-06-05 13:51:26 +02:00
|
|
|
- `external/`: git submodules.
|
|
|
|
|
`external/geolog` provides the Haskell query planner used by the exporter; `external/geomerge` is the Rust CRDT crate consumed by
|
|
|
|
|
`storage::adapters::geomerge`.
|
|
|
|
|
- Top-level configuration: `Makefile`, `flake.nix`, `Cargo.toml` (workspace), `pyproject.toml`, `.pre-commit-config.yaml`, `rust-toolchain.toml`.
|
2026-05-21 12:28:09 +02:00
|
|
|
|
2026-06-05 13:51:26 +02:00
|
|
|
Do not assume this list is exhaustive.
|
|
|
|
|
If the project grows a different structure, follow the actual codebase and update this file when conventions stabilize.
|
2026-05-21 12:28:09 +02:00
|
|
|
|
2026-05-21 15:56:29 +02:00
|
|
|
## Technical Direction
|
2026-05-21 12:28:09 +02:00
|
|
|
|
2026-05-21 15:56:29 +02:00
|
|
|
The main experimental architecture is:
|
2026-05-21 12:28:09 +02:00
|
|
|
|
2026-05-21 15:56:29 +02:00
|
|
|
```text
|
|
|
|
|
Datalog-like rules or Geolog-shaped laws
|
|
|
|
|
-> dependency analysis and strata
|
|
|
|
|
-> rule catalog
|
|
|
|
|
-> join graph
|
|
|
|
|
-> relational plan
|
|
|
|
|
-> FlowLog-style optimization
|
|
|
|
|
-> backend lowering
|
2026-06-05 13:51:26 +02:00
|
|
|
-> snapshot outputs
|
2026-05-21 15:56:29 +02:00
|
|
|
```
|
2026-05-21 12:28:09 +02:00
|
|
|
|
2026-05-21 15:56:29 +02:00
|
|
|
Keep these layers explicit:
|
2026-05-21 12:28:09 +02:00
|
|
|
|
2026-06-05 13:51:26 +02:00
|
|
|
- **Source Layer**: Datalog-like test programs and Geomerge-style laws.
|
2026-05-21 15:56:29 +02:00
|
|
|
- **Catalog Layer**: rule heads, body atoms, variables, constants, comparisons, negation, and projections.
|
|
|
|
|
- **Planning Layer**: join graphs, join order, antijoin placement, SIP-style filtering, subplan sharing, and physical key choice.
|
2026-06-05 13:51:26 +02:00
|
|
|
- **Execution Layer**: snapshot evaluator.
|
2026-05-21 15:56:29 +02:00
|
|
|
- **Storage Layer**: facts, transactions, rollback, preview state, and violation output integration.
|
|
|
|
|
|
|
|
|
|
## FlowLog-Inspired Planning
|
|
|
|
|
|
|
|
|
|
FlowLog should be treated as a planning reference, not as an automatic dependency.
|
|
|
|
|
|
|
|
|
|
Reusable ideas:
|
|
|
|
|
|
|
|
|
|
- rule catalog construction
|
|
|
|
|
- dependency graph and stratification
|
|
|
|
|
- per-rule join graph extraction
|
|
|
|
|
- width-oriented structural planning
|
|
|
|
|
- sideways information passing
|
|
|
|
|
- antijoin scheduling
|
|
|
|
|
- physical key and payload selection
|
|
|
|
|
- shared subplan detection
|
|
|
|
|
|
|
|
|
|
When adapting an idea, write the smallest test that demonstrates the behavior. For example:
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
rule with three positive atoms
|
|
|
|
|
-> catalog variables
|
|
|
|
|
-> join graph
|
|
|
|
|
-> planned join tree
|
|
|
|
|
-> expected textual plan
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Geomerge-Style Validation Experiments
|
2026-05-21 12:28:09 +02:00
|
|
|
|
2026-05-21 15:56:29 +02:00
|
|
|
The first Geomerge-style target is maintained violation detection for supported relational laws.
|
2026-05-21 12:28:09 +02:00
|
|
|
|
2026-05-21 15:56:29 +02:00
|
|
|
A useful lowering shape is:
|
2026-05-21 12:28:09 +02:00
|
|
|
|
2026-05-21 15:56:29 +02:00
|
|
|
```text
|
|
|
|
|
required_consequent(x) :- antecedent(x).
|
|
|
|
|
violation(x) :- required_consequent(x), not consequent(x).
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Start with:
|
|
|
|
|
|
|
|
|
|
- foreign-key-style laws
|
|
|
|
|
- totality-as-validation laws
|
|
|
|
|
- equality-as-violation laws
|
|
|
|
|
- multi-atom antecedents without existential witnesses
|
|
|
|
|
|
|
|
|
|
Exclude at first:
|
|
|
|
|
|
|
|
|
|
- existential witness generation
|
|
|
|
|
- disjunctive consequents
|
|
|
|
|
- equality saturation
|
|
|
|
|
- model branching
|
|
|
|
|
- full chase behavior
|
|
|
|
|
|
|
|
|
|
Violation rows should carry enough context for diagnostics:
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
law_id
|
|
|
|
|
violation_kind
|
|
|
|
|
relation_or_consequent
|
|
|
|
|
bound_variable_values
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Rust Conventions
|
|
|
|
|
|
|
|
|
|
- Prefer small modules with explicit data structures over large generic abstractions.
|
|
|
|
|
- Use enums and structs to model rule syntax, catalog entries, plan nodes, and execution results.
|
|
|
|
|
- Prefer typed identifiers for relation names, variable names, rule ids, and field positions when it improves clarity.
|
|
|
|
|
- Keep parser errors and unsupported-feature errors explicit.
|
|
|
|
|
- Avoid panics in library code except for internal invariants that tests already cover.
|
|
|
|
|
- Use deterministic ordering for plans and diagnostics so tests are stable.
|
|
|
|
|
- Prefer simple snapshot evaluators as correctness oracles before optimizing.
|
2026-05-21 12:28:09 +02:00
|
|
|
|
|
|
|
|
## Testing Expectations
|
|
|
|
|
|
2026-05-21 15:56:29 +02:00
|
|
|
Add tests for every non-trivial behavior.
|
|
|
|
|
|
|
|
|
|
Recommended test groups:
|
|
|
|
|
|
|
|
|
|
- parser acceptance and rejection
|
|
|
|
|
- rule catalog construction
|
|
|
|
|
- dependency graph and strata
|
|
|
|
|
- join graph construction
|
|
|
|
|
- structural planning
|
|
|
|
|
- antijoin scheduling
|
|
|
|
|
- SIP-style filtering
|
|
|
|
|
- snapshot evaluation
|
2026-06-05 13:51:26 +02:00
|
|
|
- storage-backend adapter parity (in-process, file-backed, and CRDT)
|
2026-05-21 15:56:29 +02:00
|
|
|
- Geomerge-style violation fixtures
|
|
|
|
|
|
|
|
|
|
Tests should prefer small facts with readable expected outputs. Avoid large benchmark fixtures unless the test is explicitly performance-oriented.
|
|
|
|
|
|
|
|
|
|
## Required Validation
|
|
|
|
|
|
2026-05-21 16:16:14 +02:00
|
|
|
Use the repository's actual tooling.
|
|
|
|
|
The `Makefile` wraps the standard Rust commands and skips Rust checks with a clear message if no `Cargo.toml` exists yet.
|
2026-05-21 15:56:29 +02:00
|
|
|
|
|
|
|
|
For Rust changes, prefer:
|
|
|
|
|
|
2026-05-29 15:06:44 +02:00
|
|
|
1. `make format-check`
|
|
|
|
|
2. `make lint`
|
2026-05-21 16:16:14 +02:00
|
|
|
3. `make test`
|
2026-05-21 15:56:29 +02:00
|
|
|
|
2026-05-21 16:16:14 +02:00
|
|
|
These map to `cargo fmt --all --check`, `cargo clippy --all-targets --all-features -- -D warnings`, and `cargo test --all-targets --all-features`.
|
|
|
|
|
If the project does not yet have a `Cargo.toml`, `make check` should still pass by skipping Rust-specific checks.
|
2026-05-21 15:56:29 +02:00
|
|
|
|
2026-06-05 13:51:26 +02:00
|
|
|
For changes that touch the cross-language pipeline (Haskell exporter and Rust runner), also run:
|
|
|
|
|
|
|
|
|
|
1. `make export-fixtures`: rebuilds `crates/plan-runner/fixtures/*.json` from `tools/exporter/examples/*.scenario.json` using the Haskell exporter.
|
|
|
|
|
Requires the Nix dev shell (`make shell` or `nix develop`) so GHC and Cabal are available.
|
|
|
|
|
2. `make examples`: runs `export-fixtures` and then `cargo test -p plan-runner --test examples`, which walks every regenerated fixture and verifies it
|
|
|
|
|
against its `expected_bindings` oracle.
|
|
|
|
|
|
2026-06-12 12:42:46 +02:00
|
|
|
For changes that touch `tools/plan-viewer`, run `make viewer-test`.
|
|
|
|
|
It checks the viewer's JavaScript engine against every fixture oracle under Node; the Rust crates remain the correctness oracle.
|
|
|
|
|
|
2026-05-21 15:56:29 +02:00
|
|
|
For Markdown-only changes, run a manual read-through and check that headings follow the writing style.
|
2026-05-21 12:28:09 +02:00
|
|
|
|
|
|
|
|
## Change Design Checklist
|
|
|
|
|
|
|
|
|
|
Before coding:
|
|
|
|
|
|
2026-05-21 15:56:29 +02:00
|
|
|
1. Problem statement and target question
|
|
|
|
|
2. Existing module or new module decision
|
|
|
|
|
3. Snapshot oracle or expected output
|
|
|
|
|
4. Supported and unsupported feature boundary
|
|
|
|
|
5. Small fixture or example shape
|
2026-05-21 12:28:09 +02:00
|
|
|
|
|
|
|
|
Before submitting:
|
|
|
|
|
|
2026-05-21 15:56:29 +02:00
|
|
|
1. Formatting status
|
|
|
|
|
2. Test status
|
|
|
|
|
3. Unsupported cases documented
|
|
|
|
|
4. No durable references to ignored local paths
|
|
|
|
|
5. Notes or examples updated when behavior changes
|
2026-05-21 12:28:09 +02:00
|
|
|
|
2026-05-21 15:56:29 +02:00
|
|
|
## Review Guidelines
|
2026-05-21 12:28:09 +02:00
|
|
|
|
2026-05-21 15:56:29 +02:00
|
|
|
Review output should prioritize correctness and experiment quality.
|
2026-05-21 12:28:09 +02:00
|
|
|
|
2026-05-21 15:56:29 +02:00
|
|
|
- `P0`: must-fix defects, such as incorrect query results, invalid rollback behavior, unsupported syntax accepted silently, or tests that cannot run.
|
|
|
|
|
- `P1`: high-priority defects, such as nondeterministic plans, unclear unsupported-feature errors, missing snapshot oracle for a planner change, or
|
|
|
|
|
misleading notes.
|
|
|
|
|
- `P2`: useful follow-up, such as additional fixtures, clearer diagnostics, or broader benchmark coverage.
|
2026-05-21 12:28:09 +02:00
|
|
|
|
|
|
|
|
Use this review format:
|
|
|
|
|
|
2026-05-21 15:56:29 +02:00
|
|
|
1. `Severity` (`P0`/`P1`/`P2`)
|
2026-05-21 12:28:09 +02:00
|
|
|
2. `File:line`
|
|
|
|
|
3. `Issue`
|
|
|
|
|
4. `Why it matters`
|
|
|
|
|
5. `Minimal fix direction`
|
|
|
|
|
|
|
|
|
|
## Practical Notes for Agents
|
|
|
|
|
|
2026-05-21 15:56:29 +02:00
|
|
|
- Read the relevant durable project notes before changing architecture.
|
|
|
|
|
- Treat copied papers, cloned repositories, and generated files in ignored local paths as reference material only.
|
|
|
|
|
- Prefer a planning-only prototype before backend integration.
|
|
|
|
|
- Prefer textual plan explanations in early tests. They make the planner easier to debug.
|
|
|
|
|
- Keep backend comparison fair: same rule, same input facts, same expected output.
|
|
|
|
|
- Keep transaction and rollback behavior explicit for validation experiments.
|
2026-05-21 16:16:14 +02:00
|
|
|
- Keep project tooling aligned with this file when new commands or checks are added.
|
2026-05-21 12:28:09 +02:00
|
|
|
|
|
|
|
|
## Commit and PR Hygiene
|
|
|
|
|
|
2026-05-21 15:56:29 +02:00
|
|
|
- Keep commits scoped to one logical change: parser, catalog, planner, evaluator, fixture, note, or tooling.
|
|
|
|
|
- Do not mix broad formatting churn with semantic changes.
|
2026-05-21 12:28:09 +02:00
|
|
|
- PR descriptions should include:
|
2026-05-21 15:56:29 +02:00
|
|
|
1. the experiment or feature being tested,
|
|
|
|
|
2. the source rules or fixtures affected,
|
|
|
|
|
3. the expected behavior,
|
|
|
|
|
4. validation commands and results,
|
|
|
|
|
5. known unsupported cases.
|
2026-05-21 12:28:09 +02:00
|
|
|
|
|
|
|
|
Suggested PR checklist:
|
|
|
|
|
|
2026-05-29 15:06:44 +02:00
|
|
|
- [ ] `make format-check` passes, if applicable
|
|
|
|
|
- [ ] `make lint` passes, if applicable
|
2026-05-21 16:16:14 +02:00
|
|
|
- [ ] `make test` passes, if applicable
|
2026-05-21 15:56:29 +02:00
|
|
|
- [ ] Snapshot oracle or expected output included for planner behavior
|
|
|
|
|
- [ ] Unsupported cases documented
|