placeroot 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- placeroot-0.3.0/.gitignore +8 -0
- placeroot-0.3.0/LICENSE +21 -0
- placeroot-0.3.0/PKG-INFO +103 -0
- placeroot-0.3.0/PLAN.md +180 -0
- placeroot-0.3.0/README.md +78 -0
- placeroot-0.3.0/ROADMAP.md +94 -0
- placeroot-0.3.0/benchmarks/README.md +116 -0
- placeroot-0.3.0/benchmarks/results.md +51 -0
- placeroot-0.3.0/benchmarks/token_benchmark.py +583 -0
- placeroot-0.3.0/docs/METRICS.md +69 -0
- placeroot-0.3.0/docs/MIRROR.md +178 -0
- placeroot-0.3.0/docs/launch/outreach.md +66 -0
- placeroot-0.3.0/docs/launch/post-why-agents-are-bad-at-maps.md +150 -0
- placeroot-0.3.0/docs/launch/registry-submissions.md +128 -0
- placeroot-0.3.0/docs/launch/show-hn.md +42 -0
- placeroot-0.3.0/examples/site_selection/README.md +178 -0
- placeroot-0.3.0/examples/site_selection/run_demo.py +355 -0
- placeroot-0.3.0/pyproject.toml +77 -0
- placeroot-0.3.0/scripts/build_fixture.py +378 -0
- placeroot-0.3.0/scripts/build_geocode_fixture.py +237 -0
- placeroot-0.3.0/scripts/build_routing_fixture.py +343 -0
- placeroot-0.3.0/scripts/geocode_benchmark.py +184 -0
- placeroot-0.3.0/scripts/mirror_theme.py +495 -0
- placeroot-0.3.0/site/_headers +13 -0
- placeroot-0.3.0/site/demo-map.html +320 -0
- placeroot-0.3.0/site/index.html +316 -0
- placeroot-0.3.0/site/style.css +319 -0
- placeroot-0.3.0/src/placeroot/budget.py +90 -0
- placeroot-0.3.0/src/placeroot/buildings.py +395 -0
- placeroot-0.3.0/src/placeroot/cache.py +428 -0
- placeroot-0.3.0/src/placeroot/db.py +152 -0
- placeroot-0.3.0/src/placeroot/divisions.py +129 -0
- placeroot-0.3.0/src/placeroot/errors.py +35 -0
- placeroot-0.3.0/src/placeroot/geo.py +124 -0
- placeroot-0.3.0/src/placeroot/geocode.py +1069 -0
- placeroot-0.3.0/src/placeroot/mapview.py +911 -0
- placeroot-0.3.0/src/placeroot/overture.py +657 -0
- placeroot-0.3.0/src/placeroot/release.py +95 -0
- placeroot-0.3.0/src/placeroot/routing.py +1137 -0
- placeroot-0.3.0/src/placeroot/server.py +541 -0
- placeroot-0.3.0/src/placeroot/simplify.py +325 -0
- placeroot-0.3.0/tests/__init__.py +0 -0
- placeroot-0.3.0/tests/_geo.py +17 -0
- placeroot-0.3.0/tests/_routing_fixture.py +12 -0
- placeroot-0.3.0/tests/conftest.py +79 -0
- placeroot-0.3.0/tests/fixtures/addresses.parquet +0 -0
- placeroot-0.3.0/tests/fixtures/buildings.parquet +0 -0
- placeroot-0.3.0/tests/fixtures/division_areas.parquet +0 -0
- placeroot-0.3.0/tests/fixtures/divisions.parquet +0 -0
- placeroot-0.3.0/tests/fixtures/places.parquet +0 -0
- placeroot-0.3.0/tests/fixtures/transportation.parquet +0 -0
- placeroot-0.3.0/tests/test_admin_lookup.py +79 -0
- placeroot-0.3.0/tests/test_budget.py +90 -0
- placeroot-0.3.0/tests/test_buildings.py +213 -0
- placeroot-0.3.0/tests/test_cache.py +368 -0
- placeroot-0.3.0/tests/test_compare_areas.py +85 -0
- placeroot-0.3.0/tests/test_demo.py +54 -0
- placeroot-0.3.0/tests/test_find_places.py +83 -0
- placeroot-0.3.0/tests/test_geocode.py +363 -0
- placeroot-0.3.0/tests/test_geometry.py +121 -0
- placeroot-0.3.0/tests/test_http.py +130 -0
- placeroot-0.3.0/tests/test_launch_docs.py +138 -0
- placeroot-0.3.0/tests/test_live.py +68 -0
- placeroot-0.3.0/tests/test_mapview.py +448 -0
- placeroot-0.3.0/tests/test_mirror_theme.py +267 -0
- placeroot-0.3.0/tests/test_place_details.py +215 -0
- placeroot-0.3.0/tests/test_release.py +130 -0
- placeroot-0.3.0/tests/test_resilience.py +97 -0
- placeroot-0.3.0/tests/test_resolve_place.py +101 -0
- placeroot-0.3.0/tests/test_routing.py +503 -0
- placeroot-0.3.0/tests/test_security.py +262 -0
- placeroot-0.3.0/tests/test_server.py +134 -0
- placeroot-0.3.0/tests/test_simplify.py +121 -0
- placeroot-0.3.0/tests/test_site.py +99 -0
- placeroot-0.3.0/tests/test_summarize_area.py +58 -0
- placeroot-0.3.0/tests/test_token_benchmark.py +91 -0
- placeroot-0.3.0/tests/test_tool_registry.py +40 -0
- placeroot-0.3.0/tests/test_upstream_mirror.py +129 -0
- placeroot-0.3.0/tests/test_within_distance.py +53 -0
- placeroot-0.3.0/uv.lock +1048 -0
placeroot-0.3.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Vibe Mapper
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
placeroot-0.3.0/PKG-INFO
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: placeroot
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Ground AI agents in open map data. MCP server for Overture Maps — compact answers, no API key.
|
|
5
|
+
Project-URL: Homepage, https://placeroot.dev
|
|
6
|
+
Project-URL: Repository, https://github.com/chuofringer/placeroot
|
|
7
|
+
Project-URL: Issues, https://github.com/chuofringer/placeroot/issues
|
|
8
|
+
Author-email: Vibe Mapper <chuo.fringer@gmail.com>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: ai-agents,duckdb,geospatial,mcp,openstreetmap,overture-maps
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: GIS
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
21
|
+
Requires-Python: >=3.11
|
|
22
|
+
Requires-Dist: duckdb>=1.5.5
|
|
23
|
+
Requires-Dist: mcp[cli]>=2.0.0
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
|
|
26
|
+
# PlaceRoot
|
|
27
|
+
|
|
28
|
+
**Ground AI agents in open map data.**
|
|
29
|
+
|
|
30
|
+
PlaceRoot is an MCP server that answers spatial questions from [Overture Maps](https://overturemaps.org) — queried live with DuckDB, no API key, no signup, no vendor platform.
|
|
31
|
+
|
|
32
|
+
- **Answers, not data dumps.** Every tool returns compact, ranked results that fit in an agent's context window (~2K tokens), never raw GeoJSON.
|
|
33
|
+
- **Fresh, rich place data.** Operating status, confidence scores, and brands from Overture (contributed by Meta, Uber, TomTom, and others).
|
|
34
|
+
- **Zero setup.** Queries run directly against Overture's public GeoParquet on S3 — no ETL, no database, no key.
|
|
35
|
+
|
|
36
|
+
## Quick start
|
|
37
|
+
|
|
38
|
+
Add to Claude Desktop / Claude Code:
|
|
39
|
+
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"mcpServers": {
|
|
43
|
+
"placeroot": {
|
|
44
|
+
"command": "uvx",
|
|
45
|
+
"args": ["placeroot"]
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Or run it directly:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
uv run placeroot # stdio MCP server
|
|
55
|
+
uv run placeroot --http # streamable-HTTP endpoint at http://127.0.0.1:8321/mcp
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
`--http` serves plain HTTP with no TLS or auth — put a reverse proxy in front for anything beyond local use.
|
|
59
|
+
|
|
60
|
+
## Tools
|
|
61
|
+
|
|
62
|
+
| Tool | Answers |
|
|
63
|
+
|---|---|
|
|
64
|
+
| `find_places` | Named places near a point, nearest first, with category, confidence, and operating status |
|
|
65
|
+
| `summarize_area` | What's in an area: total places and top categories |
|
|
66
|
+
| `place_details` | One place in full: addresses, contacts, brand, sources, confidence |
|
|
67
|
+
| `admin_lookup` | The admin hierarchy containing a point: neighborhood up to country |
|
|
68
|
+
| `compare_areas` | 2–5 areas side by side: category mix, density, and what differs most |
|
|
69
|
+
| `within_distance` | Is the nearest matching place within N meters of a point? |
|
|
70
|
+
| `geocode` | Free-text place name → ranked candidates with coordinates and admin context |
|
|
71
|
+
| `resolve_place` | Free-text place reference → ranked, typed GERS ids an agent can hold onto |
|
|
72
|
+
| `reverse_geocode` | Point → nearest address plus its containing division chain |
|
|
73
|
+
| `summarize_buildings` | Building stock in an area: count, footprint area, height and use mix |
|
|
74
|
+
| `buildings_at` | Nearest building footprints to a point |
|
|
75
|
+
| `isochrone` | The area reachable within N minutes on foot, bike, or car — on PlaceRoot's own routing graph |
|
|
76
|
+
| `render_map` | Any result → a self-contained interactive HTML map |
|
|
77
|
+
| `simplify_geometry` | Any GeoJSON geometry → simplified to a token budget |
|
|
78
|
+
|
|
79
|
+
More on the way — see [ROADMAP.md](ROADMAP.md).
|
|
80
|
+
|
|
81
|
+
## Why
|
|
82
|
+
|
|
83
|
+
Agents are bad at maps. Existing map tools either require vendor API keys or return raw GeoJSON far too large for a context window. PlaceRoot's design rule: every answer fits in ~2K tokens, and anything bigger returns a summary plus a link.
|
|
84
|
+
|
|
85
|
+
A few things that make it work:
|
|
86
|
+
|
|
87
|
+
- **GERS ids everywhere.** Every place carries its stable Overture [GERS](https://docs.overturemaps.org/gers/) id, so an agent can hold onto a place across turns and look it up again with `place_details(id=...)` instead of re-searching.
|
|
88
|
+
- **Keyless geocoding.** `geocode`/`reverse_geocode` are built entirely on Overture's divisions and addresses themes — deterministic matching, no third-party geocoding API. 100% hit@1 on a ~113-query real-world benchmark (`scripts/geocode_benchmark.py`).
|
|
89
|
+
- **Local caching.** Hot data is cached on first use, so repeat queries answer in milliseconds and keep working offline. Set `PLACEROOT_CACHE=off` to always query upstream.
|
|
90
|
+
- **Self-hostable end to end.** Optionally mirror the data to your own S3-compatible storage and point PlaceRoot at it — see [docs/MIRROR.md](docs/MIRROR.md).
|
|
91
|
+
|
|
92
|
+
## Development
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
uv sync # installs pytest + ruff (dev dependency group)
|
|
96
|
+
uv run pytest # offline tests against committed fixtures
|
|
97
|
+
uv run pytest -m live # also run opt-in tests against real Overture S3
|
|
98
|
+
uv run ruff check .
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## License
|
|
102
|
+
|
|
103
|
+
MIT
|
placeroot-0.3.0/PLAN.md
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# PlaceRoot — Product Plan
|
|
2
|
+
|
|
3
|
+
**One-liner:** An open-source MCP server that grounds AI agents in the real world using
|
|
4
|
+
Overture Maps / OSM open data — answering spatial questions in compact, token-efficient
|
|
5
|
+
form, with no API key and no vendor platform.
|
|
6
|
+
|
|
7
|
+
**Repo:** https://github.com/chuofringer/placeroot
|
|
8
|
+
|
|
9
|
+
## Positioning
|
|
10
|
+
|
|
11
|
+
| Against | They are | PlaceRoot is |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| Google Maps grounding (Gemini-native + Maps Grounding Lite hosted MCP, GA Oct–Dec 2025) | Keyed + billed ($14–25/1K prompts), no-caching/no-training terms, Google-data-only | Keyless, open data you may store, cache, and train on |
|
|
14
|
+
| Mapbox / TomTom / Esri / CARTO / HERE / Precisely MCP servers | Funnels into paid platforms (API keys, metered) | Open data, keyless |
|
|
15
|
+
| srivinod1/overture-mcp-server (the one near-clone) | Same architecture (DuckDB over Overture S3, keyless), but 4★, dormant since Mar 2026, pinned six releases stale; budgets tool *schemas*, not answers; punts geocoding/routing/display to other MCPs | Maintained, honest geometry, token-budgeted *responses*, current release |
|
|
16
|
+
| New Overture adjacents (thatapicompany/overture-maps-mcp, Jul 2026; soapboxbuild/overture-mcp, Jun 2026) | Keyed wrappers over hosted APIs or buildings-only slices; 0★ each; thatapicompany claims "token-efficient summaries" qualitatively, no budgets, no GERS in responses beyond soapboxbuild's buildings lookups | Keyless, full theme coverage, measured budgets, GERS everywhere |
|
|
17
|
+
| gis-mcp and GIS-function servers (176★, active) | Raw computation toolboxes (geometry ops, data out) | Answers, not data |
|
|
18
|
+
| OSM MCP servers (largest 215★, abandoned >1yr; no *active* successor over 30★ — wiseman/osm-mcp has 86★ but is equally dead since Mar 2025) | Overpass/Nominatim wrappers: rate limits, usage policies, stale data | Overture GeoParquet direct: operating status, confidence, brands |
|
|
19
|
+
| geowire (multi-provider gateway, launched 2026-07-18) | BYOK vendor-API aggregator; "keyless" floor is rate-limited Nominatim/OSRM (incl. a keyless OSRM isochrone); 0★ as of 2026-08-06 | Truly keyless at scale; Overture-native; own routing graph |
|
|
20
|
+
| Camino AI (getcamino.ai) | Pure-play "location intelligence for agents" startup with a native MCP server — but API-keyed, metered, "17x cheaper than Google Places" as the pitch | Keyless and free; open data you may store and train on |
|
|
21
|
+
| ORATOR (Overture's experimental knowledge-graph MCP, built by Wherobots) | Regional prototype (SF Bay Area) on proprietary Wherobots/Iceberg infra, explicitly a proof-of-concept | Keyless, self-hostable, global today |
|
|
22
|
+
| GeoLibre / GeoAgent (opengeos) | An app for humans / a Strands-based agent that drives GIS software; no MCP layer, no Overture focus | Plumbing for agents (and a future GeoLibre bridge) |
|
|
23
|
+
|
|
24
|
+
Market context (extensive study 2026-08-05; superseding the initial Aug 2026 scan):
|
|
25
|
+
~40 location MCP servers across the registries; the official MCP registry returns **zero
|
|
26
|
+
results for "overture"**. Nobody ships token-budgeted answers as the headline feature —
|
|
27
|
+
the closest is Google Grounding Lite's "AI-generated place data summaries" (keyed,
|
|
28
|
+
billed) and srivinod1's tool-schema "progressive disclosure" (dormant). The payload
|
|
29
|
+
problem is now publicly named — Mapbox's "GeoAI in 2026" post (Dec 2025) calls large
|
|
30
|
+
geospatial payloads MCP's biggest challenge; a Geoawesome essay (June 2026) shows a
|
|
31
|
+
45K-token GeoJSON collapsing to a 25-token reference — but no one ships the fix as a
|
|
32
|
+
product. Overture itself now markets our thesis: "50 members converge on open data to
|
|
33
|
+
ground AI" (July 2026), with GERS pitched as the anti-hallucination anchor and headed
|
|
34
|
+
toward OGC standardization. Foursquare's open places data is flowing *into* Overture
|
|
35
|
+
(~6M POIs merged in 2025), while FSQ's own MCP server targets its paid API and is
|
|
36
|
+
near-dormant. OpenAI and Anthropic have picked no maps partner — Claude's connector
|
|
37
|
+
directory lists only TomTom; the "default maps tool" slot in both ecosystems is open.
|
|
38
|
+
Category traction ceiling remains low (Mapbox official: 350★; only geo-MCP story with
|
|
39
|
+
real HN traction: 105 points).
|
|
40
|
+
|
|
41
|
+
Re-verification sweep 2026-08-06 (three-track: open-source registry sweep, commercial
|
|
42
|
+
vendor survey, claim-by-claim check): **all ten claims of the 2026-08-05 study stand.**
|
|
43
|
+
The registry search for "overture" is still empty; the near-clone is still dormant
|
|
44
|
+
(last commit 2026-02-28); nobody ships numeric token budgets, GERS ids in responses,
|
|
45
|
+
keyless global isochrones, or self-contained offline map artifacts. The token-payload
|
|
46
|
+
pain point gained a second corporate validator: HERE's "Location Reasoning" (announced
|
|
47
|
+
May 2026) is an entire enterprise product marketed on reducing token usage. New since
|
|
48
|
+
the study, all adjacent rather than head-on: thatapicompany/overture-maps-mcp
|
|
49
|
+
(2026-07-16, keyed wrapper over a hosted API, 0★ — first competitor to even gesture at
|
|
50
|
+
token efficiency), capan/isochrone (registered to the official MCP registry
|
|
51
|
+
**2026-08-06**, keyless own-graph isochrones — but Berlin-only, pedestrian-only, one
|
|
52
|
+
tool), and sparkgeo/geo-mcp-servers (2026-08-02, 36★) — a curated tracker of 77
|
|
53
|
+
geospatial MCP servers whose only Overture entry is the dormant near-clone. The
|
|
54
|
+
sparkgeo tracker is both a listing target and the best ongoing competitive radar for
|
|
55
|
+
this category. Discoverability hazard: "Overture" searches are polluted by an
|
|
56
|
+
unrelated 629★ coding-agent tool of the same name (SixHq/Overture). The `placeroot`
|
|
57
|
+
name remained unclaimed on PyPI, npm, and GitHub as of 2026-08-06 — re-verified, but
|
|
58
|
+
verification is not a reservation; only #16's publishes are.
|
|
59
|
+
|
|
60
|
+
## Design rules
|
|
61
|
+
|
|
62
|
+
1. **Answers, not data.** Every tool response fits in ~2K tokens. Big results return a
|
|
63
|
+
summary + retrievable artifact, never raw GeoJSON dumps.
|
|
64
|
+
2. **Open data, keyless by default.** Overture S3 GeoParquet via DuckDB (no ETL, no
|
|
65
|
+
database); OSM services that permit anonymous use.
|
|
66
|
+
3. **No hard dependency on anyone else.** Nothing on the critical path may be gated on
|
|
67
|
+
another project's roadmap, another service's rate limit, or another team's willingness
|
|
68
|
+
to integrate. External systems may make PlaceRoot faster or fresher; none may make it
|
|
69
|
+
stop working. Consequences: geocoding is built on Overture rather than wrapping
|
|
70
|
+
Nominatim; the map viewer is a self-contained artifact rather than a bridge to someone
|
|
71
|
+
else's app; routing is our own graph rather than a hosted Valhalla; the upstream release
|
|
72
|
+
is discovered, pinned, cached, and mirrorable.
|
|
73
|
+
4. **Permanent scope exclusion: hazard- and property-risk scoring.** No flood/fire/wind
|
|
74
|
+
risk scores, property risk ratings, or insurance-flavored analytics — ever.
|
|
75
|
+
|
|
76
|
+
## Naming
|
|
77
|
+
|
|
78
|
+
"placeroot" chosen 2026-08-05 after availability research: PyPI, npm, GitHub repo names,
|
|
79
|
+
and .com/.io/.dev/.ai all unclaimed; no company, product, social account, or trademark
|
|
80
|
+
found under the name. Runners-up rejected: geoplinth (SEO collision with Geoplin),
|
|
81
|
+
groundfact (social channels exist), 15 others (registered domains or package collisions).
|
|
82
|
+
|
|
83
|
+
## Phases
|
|
84
|
+
|
|
85
|
+
### Phase 1 — MVP (in progress)
|
|
86
|
+
|
|
87
|
+
- [x] DuckDB query layer over Overture S3 (release 2026-07-22.0), bbox pushdown
|
|
88
|
+
- [x] `find_places` — nearest named places; taxonomy, confidence, operating_status
|
|
89
|
+
(verified live: downtown Austin, 8 results ≈ 390 tokens, 5.6s cold)
|
|
90
|
+
- [x] `summarize_area` — category mix (1,944 places ≈ 320 tokens)
|
|
91
|
+
- [x] MCP server (Python SDK 2.0), `uv run placeroot`
|
|
92
|
+
- [x] Fix radius geometry and count correctness (#1, #2, #3)
|
|
93
|
+
- [x] Overture release auto-discovery + graceful degradation (#4, #5)
|
|
94
|
+
- [x] Offline test suite and CI (#6); measured token budget (#7)
|
|
95
|
+
- [x] Local tile cache — warm ~21ms, cold under ~5s, works offline (#8, #31)
|
|
96
|
+
- [x] `place_details`, `compare_areas`, `within_distance` (#9, #12, #13, #41)
|
|
97
|
+
- [x] `geocode` / `reverse_geocode` on Overture data (hit@1 100% live, saturated set), `admin_lookup` (#10, #11, #43, #46, #47)
|
|
98
|
+
- [x] `simplify_geometry` (the payload tool) (#14)
|
|
99
|
+
- [x] Expose GERS ids in every tool response (#25)
|
|
100
|
+
- [x] Register domains: placeroot.dev (canonical) + placeroot.com (redirect), done
|
|
101
|
+
2026-08-05; .io intentionally skipped (#27)
|
|
102
|
+
- [ ] Publish PyPI + npm (#16 — P0 as of 2026-08-05: the architecture is replicable
|
|
103
|
+
and the registry search is empty)
|
|
104
|
+
|
|
105
|
+
Full triage on the [project board](https://github.com/users/chuofringer/projects/2).
|
|
106
|
+
|
|
107
|
+
### Phase 2 — Distribution (weeks 8–13)
|
|
108
|
+
|
|
109
|
+
- [x] Self-contained map artifact — any result opens as a live HTML map we ship
|
|
110
|
+
ourselves (#15). A GeoLibre bridge is an additional output target and a community
|
|
111
|
+
relationship, not a dependency; engage opengeos early either way.
|
|
112
|
+
- [x] placeroot.dev landing page built (#28) — deploy awaits DNS/Pages setup (yours)
|
|
113
|
+
- [x] Listing entries drafted for all 8 registries (docs/launch/registry-submissions.md,
|
|
114
|
+
incl. the sparkgeo/geo-mcp-servers curated tracker found 2026-08-06);
|
|
115
|
+
submission itself is owner-side, gated on #16's publishes
|
|
116
|
+
- [x] Show HN text + community outreach notes drafted (docs/launch/); posting is owner-side
|
|
117
|
+
- [x] "Why agents are bad at maps" essay drafted (docs/launch/), Mapbox/Geoawesome cited
|
|
118
|
+
- [x] Tokens-per-correct-answer benchmark shipped and run live (#26): 90% accuracy,
|
|
119
|
+
median 2,543x fewer tokens than raw payloads (benchmarks/results.md)
|
|
120
|
+
- [x] Flagship demo: site-selection agent entirely on open data (#17 — live-verified, ~5.9K tokens for a 17-call analysis)
|
|
121
|
+
|
|
122
|
+
**Traction bar (~week 14):** judged on signals we own (#19, defined with
|
|
123
|
+
collection methods and the decision rule in [docs/METRICS.md](docs/METRICS.md)) — download trend over four
|
|
124
|
+
weeks, distinct connecting clients, inbound issues/PRs from people we did not contact, and
|
|
125
|
+
named real uses. Stars are reported, not a gate: they measure other people's attention, not
|
|
126
|
+
whether this is worth building.
|
|
127
|
+
|
|
128
|
+
### Phase 3 — Hosted tier (months 4–7, gated on Phase 2 bar)
|
|
129
|
+
|
|
130
|
+
- Free: local server forever. Hosted $0/$29/$99: remote streamable-HTTP endpoint,
|
|
131
|
+
pre-warmed indexes, monthly Overture refresh, isochrones/routing on our own graph (#17).
|
|
132
|
+
The hosted tier sells latency and convenience — never access.
|
|
133
|
+
- Infra <$100/mo (Cloudflare Workers + R2, or single box + DuckDB).
|
|
134
|
+
- Expectation: $500–3K MRR year one; primary value is audience + substrate for what's next.
|
|
135
|
+
|
|
136
|
+
### Phase 4 — Demand-driven expansions
|
|
137
|
+
|
|
138
|
+
GERS id resolution service; live layers (transit, weather context — not hazard risk);
|
|
139
|
+
buildings/transportation themes; team features; white-label for agent platforms.
|
|
140
|
+
|
|
141
|
+
## Risks
|
|
142
|
+
|
|
143
|
+
(Reassessed 2026-08-05 against the extensive competitive study.)
|
|
144
|
+
|
|
145
|
+
1. **opengeos ships an MCP layer first** — *downgraded*. Verified: no MCP layer in
|
|
146
|
+
GeoLibre or GeoAgent; their agent effort targets GIS analysis via Strands, not place
|
|
147
|
+
grounding. Still engage their community; still structurally defused (#15). Watch
|
|
148
|
+
GeoAgent's roadmap — one Overture tool factory would change this.
|
|
149
|
+
2. **Foundation labs bake maps in via one big partner** — *partially materialized, at
|
|
150
|
+
Google only*: Gemini has native Maps grounding and Maps Grounding Lite exports it to
|
|
151
|
+
any MCP client — but keyed, billed ($14–25/1K), rate-limited, no-caching/no-training
|
|
152
|
+
terms. OpenAI (Yelp/Zillow verticals via Apps SDK) and Anthropic (TomTom connector
|
|
153
|
+
only) picked no horizontal partner. Keyless open data remains the wedge; Google's
|
|
154
|
+
pricing gives us a concrete cost comparison.
|
|
155
|
+
3. **Attention, not code, is the bottleneck** → Phase 2 checklist is scheduled work;
|
|
156
|
+
half of weekly hours in weeks 8–13 go to distribution.
|
|
157
|
+
4. **Upstream Overture changes layout, schedule, or access** → release discovery with a
|
|
158
|
+
pinned fallback (#4), a schema probe that degrades per-tool rather than failing all
|
|
159
|
+
(#5), a local cache that answers offline (#8), and eventually our own mirror (#20).
|
|
160
|
+
5. **The near-clone revives, or someone wraps existing pieces** — *escalating on a
|
|
161
|
+
weeks timescale, not months*. srivinod1's overture-mcp-server has our architecture
|
|
162
|
+
(dormant, 4★), and the DuckDB `overture` community extension (geocode, place
|
|
163
|
+
readers, category normalization) is one wrapper away from being an MCP server.
|
|
164
|
+
Two adjacents appeared within three weeks of the 2026-08-05 study and one more
|
|
165
|
+
the day after (thatapicompany 2026-07-16, capan/isochrone registered 2026-08-06);
|
|
166
|
+
none is head-on yet, but each occupies a fragment of our combination. Moat is
|
|
167
|
+
execution: maintenance, honest geometry, token-budgeted answers, GERS ids (#22),
|
|
168
|
+
current releases — and shipping #16 before the empty "overture" registry search
|
|
169
|
+
fills. Standing radar: watch sparkgeo/geo-mcp-servers for new entrants.
|
|
170
|
+
6. **Foursquare ships keyless agent tooling on FSQ OS Places** — license permits it;
|
|
171
|
+
today their MCP server is API-keyed and near-dormant, and FSQ open data flows into
|
|
172
|
+
Overture, strengthening our substrate. Monitor.
|
|
173
|
+
7. **Overture-official tooling subsumes third parties** — ORATOR (Wherobots) is the
|
|
174
|
+
foundation's experimental MCP prototype. Treat as opportunity first: engage the
|
|
175
|
+
Product Council discussion, adopt GERS, stay the keyless self-hostable option
|
|
176
|
+
ORATOR is not.
|
|
177
|
+
|
|
178
|
+
## Cadence
|
|
179
|
+
|
|
180
|
+
Solo, ~6–8 hrs/week alongside day job. Phase 1 ≈ 35–45 focused hours.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# PlaceRoot
|
|
2
|
+
|
|
3
|
+
**Ground AI agents in open map data.**
|
|
4
|
+
|
|
5
|
+
PlaceRoot is an MCP server that answers spatial questions from [Overture Maps](https://overturemaps.org) — queried live with DuckDB, no API key, no signup, no vendor platform.
|
|
6
|
+
|
|
7
|
+
- **Answers, not data dumps.** Every tool returns compact, ranked results that fit in an agent's context window (~2K tokens), never raw GeoJSON.
|
|
8
|
+
- **Fresh, rich place data.** Operating status, confidence scores, and brands from Overture (contributed by Meta, Uber, TomTom, and others).
|
|
9
|
+
- **Zero setup.** Queries run directly against Overture's public GeoParquet on S3 — no ETL, no database, no key.
|
|
10
|
+
|
|
11
|
+
## Quick start
|
|
12
|
+
|
|
13
|
+
Add to Claude Desktop / Claude Code:
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"mcpServers": {
|
|
18
|
+
"placeroot": {
|
|
19
|
+
"command": "uvx",
|
|
20
|
+
"args": ["placeroot"]
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Or run it directly:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
uv run placeroot # stdio MCP server
|
|
30
|
+
uv run placeroot --http # streamable-HTTP endpoint at http://127.0.0.1:8321/mcp
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`--http` serves plain HTTP with no TLS or auth — put a reverse proxy in front for anything beyond local use.
|
|
34
|
+
|
|
35
|
+
## Tools
|
|
36
|
+
|
|
37
|
+
| Tool | Answers |
|
|
38
|
+
|---|---|
|
|
39
|
+
| `find_places` | Named places near a point, nearest first, with category, confidence, and operating status |
|
|
40
|
+
| `summarize_area` | What's in an area: total places and top categories |
|
|
41
|
+
| `place_details` | One place in full: addresses, contacts, brand, sources, confidence |
|
|
42
|
+
| `admin_lookup` | The admin hierarchy containing a point: neighborhood up to country |
|
|
43
|
+
| `compare_areas` | 2–5 areas side by side: category mix, density, and what differs most |
|
|
44
|
+
| `within_distance` | Is the nearest matching place within N meters of a point? |
|
|
45
|
+
| `geocode` | Free-text place name → ranked candidates with coordinates and admin context |
|
|
46
|
+
| `resolve_place` | Free-text place reference → ranked, typed GERS ids an agent can hold onto |
|
|
47
|
+
| `reverse_geocode` | Point → nearest address plus its containing division chain |
|
|
48
|
+
| `summarize_buildings` | Building stock in an area: count, footprint area, height and use mix |
|
|
49
|
+
| `buildings_at` | Nearest building footprints to a point |
|
|
50
|
+
| `isochrone` | The area reachable within N minutes on foot, bike, or car — on PlaceRoot's own routing graph |
|
|
51
|
+
| `render_map` | Any result → a self-contained interactive HTML map |
|
|
52
|
+
| `simplify_geometry` | Any GeoJSON geometry → simplified to a token budget |
|
|
53
|
+
|
|
54
|
+
More on the way — see [ROADMAP.md](ROADMAP.md).
|
|
55
|
+
|
|
56
|
+
## Why
|
|
57
|
+
|
|
58
|
+
Agents are bad at maps. Existing map tools either require vendor API keys or return raw GeoJSON far too large for a context window. PlaceRoot's design rule: every answer fits in ~2K tokens, and anything bigger returns a summary plus a link.
|
|
59
|
+
|
|
60
|
+
A few things that make it work:
|
|
61
|
+
|
|
62
|
+
- **GERS ids everywhere.** Every place carries its stable Overture [GERS](https://docs.overturemaps.org/gers/) id, so an agent can hold onto a place across turns and look it up again with `place_details(id=...)` instead of re-searching.
|
|
63
|
+
- **Keyless geocoding.** `geocode`/`reverse_geocode` are built entirely on Overture's divisions and addresses themes — deterministic matching, no third-party geocoding API. 100% hit@1 on a ~113-query real-world benchmark (`scripts/geocode_benchmark.py`).
|
|
64
|
+
- **Local caching.** Hot data is cached on first use, so repeat queries answer in milliseconds and keep working offline. Set `PLACEROOT_CACHE=off` to always query upstream.
|
|
65
|
+
- **Self-hostable end to end.** Optionally mirror the data to your own S3-compatible storage and point PlaceRoot at it — see [docs/MIRROR.md](docs/MIRROR.md).
|
|
66
|
+
|
|
67
|
+
## Development
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
uv sync # installs pytest + ruff (dev dependency group)
|
|
71
|
+
uv run pytest # offline tests against committed fixtures
|
|
72
|
+
uv run pytest -m live # also run opt-in tests against real Overture S3
|
|
73
|
+
uv run ruff check .
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## License
|
|
77
|
+
|
|
78
|
+
MIT
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# PlaceRoot Roadmap
|
|
2
|
+
|
|
3
|
+
Tracked on the [project board](https://github.com/users/chuofringer/projects/2).
|
|
4
|
+
|
|
5
|
+
## Design rules
|
|
6
|
+
|
|
7
|
+
1. **Answers, not data.** Every tool response fits in ~2K tokens. Large results
|
|
8
|
+
return a summary plus a retrievable artifact, never raw GeoJSON dumps.
|
|
9
|
+
2. **Open data only, keyless by default.** Overture Maps GeoParquet and
|
|
10
|
+
OpenStreetMap services that permit anonymous use.
|
|
11
|
+
3. **No hard dependency on anyone else.** Nothing on the critical path may be
|
|
12
|
+
gated on another project's roadmap, another service's rate limit, or another
|
|
13
|
+
team's willingness to integrate. External systems may make PlaceRoot faster
|
|
14
|
+
or fresher; none may make it stop working.
|
|
15
|
+
4. **Out of scope, permanently: hazard- and property-risk scoring.** PlaceRoot
|
|
16
|
+
answers "what is where" questions. It will not ship flood/fire/wind risk
|
|
17
|
+
scores, property risk ratings, or insurance-flavored analytics.
|
|
18
|
+
|
|
19
|
+
## v0.1
|
|
20
|
+
|
|
21
|
+
- [x] `find_places` — nearest named places with taxonomy, confidence, operating status
|
|
22
|
+
- [x] `summarize_area` — category mix for an area
|
|
23
|
+
|
|
24
|
+
## v0.2 — correct, resilient, useful (shipped 2026-08-06)
|
|
25
|
+
|
|
26
|
+
Correctness and independence first: the query layer has known geometry bugs, no
|
|
27
|
+
tests, and a hardcoded upstream release.
|
|
28
|
+
|
|
29
|
+
- [x] Fix radius geometry: circular distance in SQL, honest counts (#1, #2, #3)
|
|
30
|
+
- [x] Overture release auto-discovery with pinned fallback (#4)
|
|
31
|
+
- [x] Graceful degradation when upstream is slow, down, or renamed (#5)
|
|
32
|
+
- [x] Offline test suite and CI on committed fixtures (#6)
|
|
33
|
+
- [x] Measured token-budget enforcement with visible truncation (#7)
|
|
34
|
+
- [x] Local row-group cache — warm queries under 500ms, works offline (#8)
|
|
35
|
+
- [x] `place_details` — one place in full (#9)
|
|
36
|
+
- [x] `geocode` / `reverse_geocode` built on Overture, not Nominatim (#10) —
|
|
37
|
+
live benchmark hit@1 100% over 113 queries (saturated set), warm under 0.3s (#43, #46, #47, #53)
|
|
38
|
+
- [x] `admin_lookup` — point → admin hierarchy (#11)
|
|
39
|
+
- [x] `compare_areas`, `within_distance` (#12, #13)
|
|
40
|
+
- [x] `simplify_geometry` — the payload tool (#14)
|
|
41
|
+
- [x] Expose GERS ids in every tool response — stable place references, no
|
|
42
|
+
competitor surfaces them (#25)
|
|
43
|
+
|
|
44
|
+
## v0.3 — capabilities nobody else has keyless (core shipped 2026-08-06)
|
|
45
|
+
|
|
46
|
+
- [x] Self-contained map artifact: any result renders as a live HTML map, no
|
|
47
|
+
CDN, no tile key, no external viewer (#15)
|
|
48
|
+
- [x] Own routing stack, walking MVP: routable graph and isochrones from
|
|
49
|
+
Overture transportation, no hosted routing service on the critical path
|
|
50
|
+
(#18; drive/cycle, concave hulls, graph caching tracked in #36–#39)
|
|
51
|
+
- [x] Buildings and transportation themes (#23; transportation via the routing
|
|
52
|
+
stack, buildings via summarize_buildings / buildings_at)
|
|
53
|
+
- [ ] Hosted streamable-HTTP endpoint — sells latency, never access (#24;
|
|
54
|
+
transport code shipped — `placeroot --http` — hosting/TLS/DNS is the
|
|
55
|
+
owner-side remainder)
|
|
56
|
+
|
|
57
|
+
## Later, demand-driven
|
|
58
|
+
|
|
59
|
+
- [x] GERS id resolution — `resolve_place`: free-text place references →
|
|
60
|
+
GERS ids, divisions and places merged (#22, #25)
|
|
61
|
+
- [ ] Own mirror of the places theme (#20; tooling + switchover shipped —
|
|
62
|
+
scripts/mirror_theme.py, PLACEROOT_UPSTREAM_BASE, docs/MIRROR.md —
|
|
63
|
+
bucket + the 10.5 GB transfer are the owner-side remainder)
|
|
64
|
+
- [ ] Live layers: transit feeds, weather context
|
|
65
|
+
|
|
66
|
+
## Competitive watch (verified 2026-08-06)
|
|
67
|
+
|
|
68
|
+
A three-track market re-verification (details in [PLAN.md](PLAN.md)) confirmed the
|
|
69
|
+
category position: no other project ships token-budgeted answers, GERS ids in every
|
|
70
|
+
response, keyless Overture geocoding, keyless global own-graph isochrones, or
|
|
71
|
+
self-contained offline map artifacts. The position is features, not a moat — two
|
|
72
|
+
adjacent projects appeared within three weeks and one the day of the check. Standing
|
|
73
|
+
watch items, none blocking:
|
|
74
|
+
|
|
75
|
+
- **sparkgeo/geo-mcp-servers** — curated tracker of 77 geo MCP servers; our listing
|
|
76
|
+
target and the category radar. Check on each release.
|
|
77
|
+
- **capan/isochrone** — keyless own-graph isochrones (Berlin-only, pedestrian-only);
|
|
78
|
+
the nearest conceptual neighbor to our routing stack.
|
|
79
|
+
- **thatapicompany/overture-maps-mcp** — keyed hosted-API wrapper claiming
|
|
80
|
+
"token-efficient summaries"; first competitor gesturing at our headline.
|
|
81
|
+
- **Camino AI** — commercial "location intelligence for agents" startup, keyed/metered.
|
|
82
|
+
- **Google Maps Grounding Lite** — free while Experimental; a GA pricing decision
|
|
83
|
+
($2.80–7.00/1K published as potential) changes the cost-comparison story.
|
|
84
|
+
- **Overture first-party tooling** — ORATOR is still an SF-Bay prototype; any move
|
|
85
|
+
toward an official Overture MCP server changes risk 7 in PLAN.md.
|
|
86
|
+
|
|
87
|
+
The empty "overture" search in the official MCP registry is the clock: #16 ships
|
|
88
|
+
before someone else fills it.
|
|
89
|
+
|
|
90
|
+
## Relationships, not dependencies
|
|
91
|
+
|
|
92
|
+
A GeoLibre bridge and upstream contributions to Overture tooling are both
|
|
93
|
+
worth doing and actively wanted. Neither blocks a release. If a partner ships
|
|
94
|
+
first, PlaceRoot still works the same day.
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Token benchmark (issue #26)
|
|
2
|
+
|
|
3
|
+
## Reality check first
|
|
4
|
+
|
|
5
|
+
[GeoBenchX](https://github.com/Solirinai/GeoBenchX) and GeoAgentBench are
|
|
6
|
+
*agent-with-LLM* benchmarks: they measure whether an LLM correctly chooses
|
|
7
|
+
and chains geospatial tools across a conversation. Running either faithfully
|
|
8
|
+
needs LLM API calls, which this repo has no credentials for and won't fake.
|
|
9
|
+
|
|
10
|
+
What's here instead is something narrower, but real and runnable today:
|
|
11
|
+
`token_benchmark.py` runs 30 spatial questions — inspired by GeoBenchX's own
|
|
12
|
+
task categories (nearest-POI, area comparison, point-in-admin,
|
|
13
|
+
within-distance, isochrone reachability) — directly against **live**
|
|
14
|
+
Overture data, checks each answer programmatically, and measures **tokens
|
|
15
|
+
per correct answer**: placeroot's compact tool response vs. the token cost
|
|
16
|
+
of the equivalent *raw* payload (unprocessed rows / full geometry) an agent
|
|
17
|
+
would have had to fetch and read itself without placeroot's tool doing the
|
|
18
|
+
filtering, ranking, point-in-polygon, or graph-building.
|
|
19
|
+
|
|
20
|
+
No LLM is called anywhere in this benchmark. It measures the *data* side of
|
|
21
|
+
the "answers, not data dumps" design rule (README.md), not an agent's tool
|
|
22
|
+
choice — that's what a real GeoBenchX/GeoAgentBench integration would add.
|
|
23
|
+
The task format here (`Task(name, category, fn)`, where `fn()` calls the
|
|
24
|
+
placeroot tool(s) and returns a checked `Outcome`) is deliberately generic
|
|
25
|
+
enough that a future LLM-driven harness could reuse the same task
|
|
26
|
+
definitions and checkers, swapping in an agent's own tool calls for the
|
|
27
|
+
direct calls used here — that integration is tracked as future work under
|
|
28
|
+
this issue's lineage, not solved here.
|
|
29
|
+
|
|
30
|
+
## Running it
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
uv run python benchmarks/token_benchmark.py
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Hits live Overture S3 (no fixture, no mock — same posture as
|
|
37
|
+
`scripts/geocode_benchmark.py`). Each task is 1-3 tool calls; with a warm
|
|
38
|
+
tile cache this finishes in a couple of minutes, longer cold (the isochrone
|
|
39
|
+
tasks build a street graph from scratch and are the slowest part). Prints
|
|
40
|
+
the report and overwrites `benchmarks/results.md` with the run's actual
|
|
41
|
+
output — every number in `results.md` comes from that run, nothing hand-
|
|
42
|
+
edited in.
|
|
43
|
+
|
|
44
|
+
The harness itself (task definitions, the `Outcome`/`run_task` scoring
|
|
45
|
+
machinery, the raw-payload comparator helpers) is also exercised offline in
|
|
46
|
+
`tests/test_token_benchmark.py`, against the same committed fixtures the
|
|
47
|
+
rest of the test suite uses — `uv run pytest` runs that as part of the
|
|
48
|
+
normal suite, no network required.
|
|
49
|
+
|
|
50
|
+
## Task categories and what "raw" means per category
|
|
51
|
+
|
|
52
|
+
Every task calls placeroot's tool(s) through `placeroot.server`'s plain
|
|
53
|
+
Python functions directly (the same functions the MCP server exposes, see
|
|
54
|
+
`server.py`), not over an MCP client transport — this measures response
|
|
55
|
+
payload size, which doesn't depend on the transport. Both the placeroot
|
|
56
|
+
side and the raw side are measured with the same `len(json)//4` heuristic
|
|
57
|
+
`placeroot.budget.estimate_tokens` uses, so every ratio below is directly
|
|
58
|
+
comparable to the server's own token-budget accounting.
|
|
59
|
+
|
|
60
|
+
- **point_in_admin** (`admin_lookup`): does the containing-division chain
|
|
61
|
+
include the point's real county and state? Raw side: every division
|
|
62
|
+
polygon that actually contains the point, with full unsimplified GeoJSON
|
|
63
|
+
geometry (`ST_AsGeoJSON`) — the full division polygon, not the tool's
|
|
64
|
+
`{name, type, id}` chain entry.
|
|
65
|
+
- **within_distance**: is a place matching a category within N meters,
|
|
66
|
+
true/false. Raw side: every place row (every column, not the curated
|
|
67
|
+
id/name/category/distance the tool returns) inside the same search
|
|
68
|
+
window (`max_distance_m * 2`, matching the tool's own search radius).
|
|
69
|
+
- **nearest_poi** (`find_places`): does a coffee_shop search near an iconic
|
|
70
|
+
downtown core turn up a Starbucks in the top 3 (top-3, not top-1,
|
|
71
|
+
specifically to tolerate ordinary data drift between Overture releases)?
|
|
72
|
+
Raw side: every place row in the same radius/category predicate.
|
|
73
|
+
- **area_comparison** (`compare_areas`): does a permanently dense downtown
|
|
74
|
+
core show more total places than a permanently rural/wilderness point at
|
|
75
|
+
the same radius — a coarse, durable fact, not a fragile exact-count
|
|
76
|
+
check. Raw side: every place row in both areas' radii, combined.
|
|
77
|
+
- **isochrone**: sanity checks (a well-connected urban point reaches a
|
|
78
|
+
nonzero area) plus two durable physical invariants — a longer time budget
|
|
79
|
+
reaches an equal-or-larger area than a shorter one, and a faster mode
|
|
80
|
+
(drive/cycle) reaches an equal-or-larger area than walking in the same
|
|
81
|
+
time, at the same point. Raw side: every transportation segment row
|
|
82
|
+
(with WKT geometry) in the same auto-derived graph-extraction radius the
|
|
83
|
+
tool itself used — i.e. the raw street-network edges an agent would have
|
|
84
|
+
had to fetch and read to answer the question itself, not the tool's
|
|
85
|
+
compact polygon + stats.
|
|
86
|
+
|
|
87
|
+
## Honesty rules
|
|
88
|
+
|
|
89
|
+
- A task whose checker fails is counted in the aggregate, not dropped —
|
|
90
|
+
`results.md`'s table includes every task that ran, correct or not, and a
|
|
91
|
+
"Failure detail" section spells out exactly what each miss got instead of
|
|
92
|
+
what it expected.
|
|
93
|
+
- The raw-payload methodology is documented per category above rather than
|
|
94
|
+
left implicit; where it undercounts the true raw payload (isochrone's raw
|
|
95
|
+
segments use WKT text in place of the raw binary WKB geometry column, so
|
|
96
|
+
the row stays JSON-serializable without a custom encoder), that's called
|
|
97
|
+
out in the code, not smoothed over.
|
|
98
|
+
- No number in this file is asserted without `benchmarks/results.md`
|
|
99
|
+
backing it — `results.md` is regenerated by, and only by, actually running
|
|
100
|
+
the script above against live data.
|
|
101
|
+
|
|
102
|
+
## A finding from running this
|
|
103
|
+
|
|
104
|
+
The first live run of this benchmark hit a real, reproducible-at-the-time
|
|
105
|
+
tile-cache incompleteness: `find_places` near Times Square returned zero
|
|
106
|
+
results (with `PLACEROOT_CACHE` at its default, on) even though the same
|
|
107
|
+
query with `PLACEROOT_CACHE=off` found a restaurant 10m away. Clearing
|
|
108
|
+
`~/.cache/placeroot` and rerunning made it disappear — a fresh cache
|
|
109
|
+
answered the very first query correctly, and stayed correct on repeat
|
|
110
|
+
queries. That points to a one-off race in cache.py's background tile
|
|
111
|
+
materialization (see its module docstring: a cache miss should always fall
|
|
112
|
+
back to a direct upstream scan for *that* query, so this shouldn't be
|
|
113
|
+
possible even before the background fetch resolves) rather than a
|
|
114
|
+
systematic data gap, but it wasn't chased further here — flagged as a
|
|
115
|
+
follow-up worth its own issue, not fixed in this one. The committed
|
|
116
|
+
`results.md` reflects the rerun against a cleared cache.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Token benchmark results (issue #26)
|
|
2
|
+
|
|
3
|
+
- Run date: 2026-08-06
|
|
4
|
+
- Overture release: 2026-07-22.0
|
|
5
|
+
- Tasks: 30
|
|
6
|
+
- Accuracy: 27/30 (90.0%)
|
|
7
|
+
- Median tokens ratio (raw / placeroot), over 30 scored tasks: 2543.0x
|
|
8
|
+
- Mean tokens ratio: 11246.6x
|
|
9
|
+
|
|
10
|
+
Every task that ran is in the table below, including failures — nothing is dropped from the aggregate.
|
|
11
|
+
|
|
12
|
+
## Per-task results
|
|
13
|
+
|
|
14
|
+
| task | category | correct | placeroot tokens | raw tokens | ratio |
|
|
15
|
+
|---|---|---|---:|---:|---:|
|
|
16
|
+
| austin_texas_capitol | point_in_admin | yes | 90 | 2349639 | 26107.1x |
|
|
17
|
+
| brooklyn_borough_hall | point_in_admin | yes | 113 | 1819534 | 16102.1x |
|
|
18
|
+
| la_city_hall | point_in_admin | yes | 94 | 1880981 | 20010.4x |
|
|
19
|
+
| chicago_willis_tower | point_in_admin | yes | 135 | 1806458 | 13381.2x |
|
|
20
|
+
| seattle_space_needle | point_in_admin | yes | 91 | 1807274 | 19860.2x |
|
|
21
|
+
| miami_downtown | point_in_admin | yes | 92 | 2000858 | 21748.5x |
|
|
22
|
+
| denver_state_capitol | point_in_admin | yes | 93 | 1752816 | 18847.5x |
|
|
23
|
+
| times_square_restaurant | within_distance | yes | 71 | 766290 | 10792.8x |
|
|
24
|
+
| chicago_loop_coffee | within_distance | yes | 75 | 42024 | 560.3x |
|
|
25
|
+
| hollywood_highland_restaurant | within_distance | yes | 74 | 167766 | 2267.1x |
|
|
26
|
+
| eiffel_tower_restaurant | within_distance | yes | 69 | 153342 | 2222.3x |
|
|
27
|
+
| yellowstone_lake_grocery | within_distance | yes | 13 | 0 | 0.0x |
|
|
28
|
+
| pacific_ocean_any_place | within_distance | yes | 13 | 0 | 0.0x |
|
|
29
|
+
| sahara_desert_any_place | within_distance | yes | 13 | 0 | 0.0x |
|
|
30
|
+
| grand_canyon_remote_restaurant | within_distance | yes | 13 | 0 | 0.0x |
|
|
31
|
+
| times_square_coffee | nearest_poi | **NO** | 181 | 40841 | 225.6x |
|
|
32
|
+
| chicago_loop_coffee | nearest_poi | yes | 185 | 20348 | 110.0x |
|
|
33
|
+
| seattle_downtown_coffee | nearest_poi | yes | 183 | 35743 | 195.3x |
|
|
34
|
+
| sf_union_square_coffee | nearest_poi | **NO** | 181 | 23338 | 128.9x |
|
|
35
|
+
| la_downtown_coffee | nearest_poi | **NO** | 190 | 20250 | 106.6x |
|
|
36
|
+
| boston_downtown_coffee | nearest_poi | yes | 183 | 28713 | 156.9x |
|
|
37
|
+
| manhattan_vs_rural_upstate_ny | area_comparison | yes | 526 | 17410408 | 33099.6x |
|
|
38
|
+
| chicago_loop_vs_rural_il | area_comparison | yes | 526 | 5454757 | 10370.3x |
|
|
39
|
+
| sf_union_sq_vs_sierra_backcountry | area_comparison | yes | 514 | 5916508 | 11510.7x |
|
|
40
|
+
| austin_6th_st_vs_hill_country | area_comparison | yes | 491 | 2550036 | 5193.6x |
|
|
41
|
+
| times_square_walk_15min | isochrone | yes | 2044 | 2836060 | 1387.5x |
|
|
42
|
+
| times_square_drive_ge_walk_15min | isochrone | yes | 3325 | 239697321 | 72089.4x |
|
|
43
|
+
| chicago_loop_walk_10min_vs_20min | isochrone | yes | 3371 | 4687640 | 1390.6x |
|
|
44
|
+
| sf_union_sq_cycle_ge_walk_15min | isochrone | yes | 3770 | 10627117 | 2818.9x |
|
|
45
|
+
| austin_downtown_drive_15min | isochrone | yes | 2039 | 95251683 | 46714.9x |
|
|
46
|
+
|
|
47
|
+
## Failure detail
|
|
48
|
+
|
|
49
|
+
- **times_square_coffee** (nearest_poi): expected one of ['Starbucks'] in top-3, got ['Joe Coffee Company', "Dunkin'", 'Central Perk']
|
|
50
|
+
- **sf_union_square_coffee** (nearest_poi): expected one of ['Starbucks'] in top-3, got ['Bancarella', 'Lux Cafe Club', 'Hyatt Coffee Bar']
|
|
51
|
+
- **la_downtown_coffee** (nearest_poi): expected one of ['Starbucks'] in top-3, got ['Barista Society Coffee Boutique', 'Aquarela Coffee', 'The Coffee Bean & Tea Leaf']
|