From 544767fa16b51d65d1900bb6cc5cba4d8ecd0c4c Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Thu, 25 Jun 2026 20:47:35 +0200 Subject: [PATCH] Add the MEOS.NET pin manifest and per-binding generator policy doc main still ships the regex MEOS.NET.Builder; the codegen-driven 1.4 surface lives in open PRs. Add tools/pin/compose-order.txt (the canonical fold manifest with the disposition of every open PR; #5 is the verified frontier containing #4) and GENERATION.md (the per-binding generator policy: MEOS.NET owns its generator in-repo at tools/codegen.py emitting the P/Invoke layer; the regex Builder is retired generate-then-retire). --- GENERATION.md | 54 +++++++++++++++++++++++++++++++++++++ tools/pin/compose-order.txt | 38 ++++++++++++++++++++++++++ tools/regen-from-pin.sh | 19 +++++++++++++ 3 files changed, 111 insertions(+) create mode 100644 GENERATION.md create mode 100644 tools/pin/compose-order.txt create mode 100755 tools/regen-from-pin.sh diff --git a/GENERATION.md b/GENERATION.md new file mode 100644 index 0000000..042ebff --- /dev/null +++ b/GENERATION.md @@ -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. diff --git a/tools/pin/compose-order.txt b/tools/pin/compose-order.txt new file mode 100644 index 0000000..874b228 --- /dev/null +++ b/tools/pin/compose-order.txt @@ -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: # 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. +# ════════════════════════════════════════════════════════════════════════════════════ diff --git a/tools/regen-from-pin.sh b/tools/regen-from-pin.sh new file mode 100755 index 0000000..668ec8d --- /dev/null +++ b/tools/regen-from-pin.sh @@ -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 +# 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 }" +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"