Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 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
3 changes: 3 additions & 0 deletions .claude/harvest/osm-website-rs/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/target
**/*.rs.bk
Cargo.lock
8 changes: 8 additions & 0 deletions .claude/harvest/osm-website-rs/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[workspace]
resolver = "2"
members = ["crates/osm-domain"]

[workspace.package]
edition = "2021"
license = "GPL-2.0-or-later"
repository = "https://github.com/AdaWorldAPI/openstreetmap-website-rs"
67 changes: 67 additions & 0 deletions .claude/harvest/osm-website-rs/NEXT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# OSM transpile — status of the three autoattended next-steps (2026-07-04)

## ✅ 1. classid mint — DONE (OGAR side)

Allocated **`ConceptDomain::Geo` (`0x0FXX`)** in `ogar-vocab` and minted the 10
OSM geodata concepts: `osm_node` `0x0F01`, `osm_way` `0x0F02`, `osm_relation`
`0x0F03`, `osm_changeset` `0x0F04`, `osm_element_tag` `0x0F05`,
`osm_relation_member` `0x0F06`, `osm_way_node` `0x0F07`, `osm_note` `0x0F08`,
`osm_gpx_trace` `0x0F09`, `osm_user` `0x0F0A`.

Full codebook contract satisfied (all `ogar-vocab` tests green, 96):
`CODEBOOK` + `class_ids::{consts,ALL}` + `all_promoted_classes()` constructors +
`ConceptDomain::Geo` + `canonical_concept_domain(0x0F)` + `COUNT_FUSE` pin
`68→78`.

The render now emits `CLASS_ID` for the 20 grounded geodata files
(`Node → 0x0F01`, …) via the Rails-name→concept grounding map in
`render_osm.rs`.

### ⏳ Sequenced follow-up (post-merge, NOT doable now)

The **lance-graph mirror** (`lance-graph-contract::ogar_codebook::CODEBOOK`) +
`lance-graph-ogar::parity::COUNT_FUSE` must be bumped `68→78` **after** this
OGAR `ogar-vocab` change merges to OGAR `main` — because `lance-graph-ogar`'s
`COUNT_FUSE` is a compile-time assert `contract::CODEBOOK.len() ==
ogar_vocab::class_ids::ALL.len()`, and lance-graph pulls `ogar_vocab` via **git
main** (still 68). Bumping the mirror first would break that assert against the
unmerged ogar-vocab. This is the E-CODEBOOK-MINT-IS-A-CROSS-REPO-ARC lockstep.

**Operator:** confirm the `0x0F` / Geo domain allocation before merge.

## ✅ 2. lance-graph wiring — DONE (manifest)

`harvest/osm_graph.spo` — the OSM association graph as **154 classid-keyed SPO
edges**. node/way/relation is a graph; each grounded subject carries its
`CLASS_ID` and every association is an edge to a target concept (classid where
the target grounds), e.g.:

```
osm_node[0x0F01] --BelongsTo:changeset--> changeset[0x0F04]
osm_node[0x0F01] --HasMany:element_tags--> NodeTag[0x0F05]
osm_node[0x0F01] --HasMany:containing_relations--> Relation[0x0F03]
osm_changeset[0x0F04] --BelongsTo:user--> user[0x0F0A]
```

Targets shown `[----]` are ungrounded (plural relation names that don't
normalise to a minted concept, or non-geodata app entities) — an honest gap in
the simple grounding, not a lift error. This manifest is the feed a
`lance-graph` graph loader consumes.

## ⛔ 3. DO-arm methods — CAPABILITY GAP (honestly scoped, not faked)

The render *supports* behaviour methods — `render_class_with_methods(class,
mask, actions: &[ActionDef])` lifts each `ActionDef` into a struct method. But
**there are no `ActionDef`s to pass**:

- `ruff_ruby_spo::extract` walks **`app/models` only**; `app/controllers` (where
Rails request behaviour lives) is never parsed.
- The `Class` IR carries `associations` / `enums` / `mixins` / `attributes` —
**no methods / callbacks / actions field**.

So the DO-arm is empty by construction today. Closing it needs a **new
capability**: a Ruby controller/action harvester (`ruff_ruby_spo` extended to
`app/controllers`, or a `ruff_ruby_action_spo`) that lifts controller actions →
`ActionDef { predicate, object_class, body_source, on_enter }`. That is a ruff
feature, filed as the honest next brick — not something to synthesise from the
model tree.
29 changes: 29 additions & 0 deletions .claude/harvest/osm-website-rs/PARKED.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# PARKED — belongs in `AdaWorldAPI/openstreetmap-website-rs`

This tree is the ruff → OGAR transcode of `openstreetmap/openstreetmap-website`
(Rails). Its real home is the empty repo **`AdaWorldAPI/openstreetmap-website-rs`**.

It is parked here **only** because that repo is not in this session's write
allowlist: `git clone`/`fetch` of it succeed, but `git push` returns `403`
(the GUI "add repository to current session" did not update the proxy
allowlist — a backend bug). Pushing to an in-scope repo (OGAR) is the durable
save until the target repo becomes writable.

## Relocation (when `openstreetmap-website-rs` is in scope)

```sh
git clone <proxy>/AdaWorldAPI/openstreetmap-website-rs /tmp/osm-rs
cp -r harvest/osm-website-rs/. /tmp/osm-rs/ # (excluding this PARKED.md)
cd /tmp/osm-rs && git add -A && git commit && git push
```

## Provenance

| Input | Pin |
|---|---|
| OSM source (`openstreetmap/openstreetmap-website`) | `173885c17d91c4a2ceb70f7a4e911f2b250628ef` |
| ruff (`AdaWorldAPI/ruff`) | `61ce2b490fc3c432d36c44eceed08125f838b405` |
| OGAR | `4037e88` |

Regenerate the IR with the harvest driver committed alongside:
`cargo run -p ogar-from-rails --example harvest_osm -- <osm-website-root> --ir`.
58 changes: 58 additions & 0 deletions .claude/harvest/osm-website-rs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# openstreetmap-website-rs

A Rust transcode of [`openstreetmap/openstreetmap-website`](https://github.com/openstreetmap/openstreetmap-website)
(Ruby on Rails) produced through the **ruff → OGAR** transpile pipeline.

The Ruby source is canonical; this repo is the target. The domain model is
harvested mechanically from the Rails `app/models` tree — not hand-ported — so
the Rust structure tracks the Ruby structure by construction.

## Pipeline

```
openstreetmap-website/app/models/*.rb (Ruby, canonical)
│ ruff_ruby_spo::extract
ruff_spo_triplet::ModelGraph (language-agnostic IR)
│ ogar_from_ruff::lift_model_graph
Vec<ogar_vocab::Class> (OGAR canonical vocab — the transpile)
│ render (ogar-render-askama → Rust struct + methods) [next]
crates/osm-domain/ (Rust domain types)
```

The node / way / relation / changeset / tag model is a graph, so the harvested
`Class` set drops directly onto `lance-graph`.

## Status

- ✅ **Harvest** — 50 classes lifted from real OSM source. Full IR in
[`harvest/osm_ir.txt`](harvest/osm_ir.txt) (associations, mixins, STI parents).
- ✅ **Render** — all 50 `Class`es rendered to Rust in
[`crates/osm-domain/src/generated/`](crates/osm-domain/src/generated/) via
`ogar-render-askama` (`render_class_with_methods`): associations become typed
edge fields (`belongs_to → Option<u64>`, `has_many → Vec<u64>`) + a `new(..)`
constructor. **Compiles + tests green** (`cargo build` / `cargo test`).
Regenerate: `cargo run -p ogar-render-askama --example render_osm -- <osm-root> <out>`.
- ⏳ **Next** — classid mint (OSM concepts into the codebook so `CLASS_ID`
emits), `ActionDef` DO-arm (behaviour methods) once controller/model actions
are harvested, and lance-graph wiring (node/way/relation as a graph).

## Provenance (regenerate deterministically)

| Input | Pin |
|---|---|
| OSM source (`openstreetmap/openstreetmap-website`) | `173885c17d91c4a2ceb70f7a4e911f2b250628ef` |
| ruff (`AdaWorldAPI/ruff`) | `61ce2b490fc3c432d36c44eceed08125f838b405` |
| OGAR (`AdaWorldAPI/OGAR`) | `4037e88` |

Harvest driver: `ogar-from-rails/examples/harvest_osm.rs` —
`cargo run -p ogar-from-rails --example harvest_osm -- <osm-website-root> --ir`.

## The 50 harvested classes

Core geodata: `Node` `Way` `Relation` `Changeset` + `*Tag` / `RelationMember` /
`WayNode` + the `Old*` versioned mirrors. Plus `User` (the 32-association hub),
`Note` / `Trace` / `DiaryEntry` / `Message` / `Issue` and their comment /
subscription satellites. See `harvest/osm_ir.txt` for the complete graph.
9 changes: 9 additions & 0 deletions .claude/harvest/osm-website-rs/crates/osm-domain/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
name = "osm-domain"
version = "0.0.0"
edition.workspace = true
license.workspace = true
repository.workspace = true
description = "OSM domain types, transcoded from openstreetmap-website Rails app/models via the ruff → OGAR pipeline."

[dependencies]
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// @generated by ogar-render-askama — ruff → OGAR transpile
// source class: Acl (openstreetmap-website app/models)





//! `Acl` — canonical class generated from `ogar_vocab::acl()`.
//! Fields are the ClassView × FieldMask projection; methods are the OGAR
//! `ActionDef` DO-arm (behaviour is Rust, never SurrealQL DDL).
//! DO NOT EDIT BY HAND. Re-render via `ogar-render-askama`.

/// Canonical concept name as in the OGAR codebook.
pub const CANONICAL_CONCEPT: &str = "acl";

#[derive(Debug, Clone, Default, PartialEq)]
pub struct Acl {
}

impl Acl {

/// Struct-of-methods constructor over the ClassView × FieldMask field set.
pub fn new() -> Self {
Self { }
}
}
Loading
Loading