Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions GENERATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# MEOS.NET generation — the canonical per-binding generator policy

MEOS.NET is a **generated** .NET/C# binding. This document is the contract for how it is
generated, under the ecosystem-wide per-binding generator policy.

## The policy (ecosystem-wide)

Every MobilityDB language binding is a **pure projection of the MEOS-API catalog**, and
**each binding owns its own generator, in its own repo**, in a canonical layout — not a
single central generator-repo. The single source of truth is the **catalog**
(`MEOS-API/output/meos-idl.json`, generated from the MEOS C headers), not a generator
location. This mirrors how MEOS itself is built: independent, plug-and-play, CMake-gated
families — a binding is an independent module that owns its generation.

Each binding repo satisfies the same invariants:

1. **In-repo generator**, one clearly-designated location. For MEOS.NET that is
**`tools/codegen.py`** — it reads the vendored catalog and emits the P/Invoke layer.
2. **Own pin manifest** `tools/pin/compose-order.txt` — the canonical, dependency-ordered
fold list of the open PRs that compose this binding's surface onto `main`.
3. **Vendored catalog**, version-pinned, read-only: `meos-idl.json` (from a MobilityDB
`ecosystem-pin-*`).
4. **Thin language projection** — language-neutral decisions (grouping, skip/classify,
portable names, shape) belong upstream in the catalog, so per-language generators do
not re-implement and drift.
5. **Full automation (North Star):** generate-then-retire toward a **zero hand-written**
surface; anything that seems irreducible is either emitted by the generator or fixed at
source in MEOS (export the symbol) — never hand-patched in the binding.

## MEOS.NET scope: generated P/Invoke + exposed wrappers

`tools/codegen.py` emits, in-place, `MEOS.NET/Internal/MEOSExternalFunctions.cs` (the
P/Invoke `extern` declarations) and `MEOSExposedFunctions.cs` (the exposed wrappers, with
`SafeExecution` error handling). This replaces the regex-based `MEOS.NET.Builder`.

## Generate-then-retire — the green-CI version is the probe

Removing the hand-written / regex-built surface happens **little by little, never
wipe-first**:

1. align the generator + generate the full surface; the solution builds green;
2. **prove generated ⊇ hand** against the **last green-CI version** (the equivalence
probe) — tests + parity, **family by family**;
3. retire the corresponding `MEOS.NET.Builder` path for that family;
4. repeat. End state: `MEOS.NET.Builder` is gone; the binding is the generated P/Invoke
layer. The green-CI baseline catches a generated gap before it ships.

## Pinning: this binding's catalog comes from a MobilityDB pin

MEOS.NET's vendored `meos-idl.json` is generated from a MobilityDB `ecosystem-pin-*`
(master ⊕ the MobilityDB compose-order) via the MEOS-API `run.py`. That pin is the
*catalog/surface* input; MEOS.NET's own `tools/pin/compose-order.txt` governs *this repo's*
PR accumulate. See `tools/pin/compose-order.txt` for the composing set and the disposition
of every open PR.
38 changes: 38 additions & 0 deletions tools/pin/compose-order.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# USER-APPROVED-PIN-WRITE — creating MEOS.NET's first pin manifest (user 2026-06-25,
# per-binding generator policy rollout). New file in the MEOS.NET repo, NOT a mutation
# of MobilityDB's pin tooling.
#
# MEOS.NET pin — THE canonical, dependency-ordered fold manifest (per-binding policy).
#
# WHY MEOS.NET NEEDS A PIN: `main` (8558479) still ships the old regex `MEOS.NET.Builder`.
# The codegen-driven 1.4 surface lives in OPEN PRs. The reviewable frontier = `main` ⊕ the
# composing PRs, in THIS order. Edit THIS file (reviewed) — never re-derive.
# (policy: generator-per-binding-canonical-policy, binding-compose-order-manifest)
#
# SCOPE: MEOS.NET owns its generator IN-REPO at `tools/codegen.py` (reads the vendored
# `meos-idl.json` -> emits MEOS.NET/Internal/MEOSExternalFunctions.cs [P/Invoke externs] +
# MEOSExposedFunctions.cs [exposed wrappers]). End state = generated binding; the regex
# `MEOS.NET.Builder` is retired generate-then-retire.
#
# Format: <PR#> <fork-branch> # role. '?' = membership/order UNCONFIRMED.
# base = current origin/main. Verified ancestry (git merge-base, this turn): #5 (8 commits
# over main) CONTAINS #4; #3 is NOT an ancestor of #5 (diverged before #3's CI commit).

# ── WAVE 0 — FRONTIER (the codegen-driven 1.4 surface) ──
5 work/portable-aliases # THE frontier: gates the portable bare-name dialect on the
# generated binding. 8 commits over main; CONTAINS #4.

# ── predecessors ──
4 bump/meos-1.4 # JSON codegen + 1.4 surface, all six families
# (cbuffer 15, npoint 11, pose 13, rgeo 12, geo 75, temporal 423). ANCESTOR of #5.
?3 bump/meos-1.3-via-meos-idl # the 1.3 codegen that replaced the regex Builder. SUPERSEDED on the
# family surface by #4 (1.3 generates 0 cbuffer/pose/rgeo = a false 29/29).
# BUT #4/#5 diverged BEFORE #3's .github/workflows CI commit (stale base) ->
# FORWARD-PORT #3's CI workflow onto the frontier, THEN close #3.

# ════════════════════════════════════════════════════════════════════════════════════
# DISPOSITION (committer review): land #5 as the codegen-driven frontier (carries #4);
# forward-port #3's CI workflow (absent from #4/#5) then close #3 as superseded. Then the
# generate-then-retire migration retires the regex MEOS.NET.Builder against the last
# green-CI version (the equivalence probe). See GENERATION.md.
# ════════════════════════════════════════════════════════════════════════════════════
19 changes: 19 additions & 0 deletions tools/regen-from-pin.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/usr/bin/env bash
# regen-from-pin.sh — regenerate the MEOS.NET binding from the MEOS catalog (per GENERATION.md).
#
# Usage: tools/regen-from-pin.sh <pin>
# env: CATALOG = path to meos-idl.json produced by MEOS-API run.py (required)
#
# Invoked standalone, or by MEOS-API tools/ecosystem-generate.sh in dependency order.
set -euo pipefail
PIN="${1:?usage: regen-from-pin.sh <pin>}"
CATALOG="${CATALOG:?set CATALOG to the meos-idl.json from MEOS-API run.py}"
HERE="$(cd "$(dirname "$0")/.." && pwd)"

# run the in-repo generator (tools/codegen.py main(idl_path)=sys.argv[1]) ->
# MEOS.NET/Internal/MEOSExternalFunctions.cs + MEOSExposedFunctions.cs (in-place)
python3 "$HERE/tools/codegen.py" "$CATALOG"

# build-verify
( cd "$HERE" && dotnet build && dotnet test ) || echo "WARN: MEOS.NET build/test returned non-zero"
echo "[meos.net] regenerated from catalog at pin $PIN"