Skip to content
Merged
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
2 changes: 1 addition & 1 deletion bundles/ramble/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "ramble",
"name": "Ramble",
"version": "0.9.3",
"version": "0.9.4",
"type": "mcp-server",
"author": "Crow",
"category": "social",
Expand Down
2 changes: 1 addition & 1 deletion bundles/ramble/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "crow-ramble",
"version": "0.9.3",
"version": "0.9.4",
"description": "Ramble MCP server — proximity marks, caws, privacy grid, egg and bird companion, gifts and swaps",
"type": "module",
"main": "server/index.js",
Expand Down
25 changes: 18 additions & 7 deletions bundles/ramble/panel/static/ramble.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@
* the pip list. */
var MIN_CELL_DETAIL_ZOOM = 15;
var hereLayer = null, hereDot = null, hereRing = null;
/* The opening frame is a WALK, not a survey. At 15 the map showed about
* 1.5 km across a phone, which put most of the visible seed beyond any
* reasonable walk and out along roads with no footpath; 16 is about 730 m,
* which is the range Kevin marked as somewhere he would actually go. */
var WALK_ZOOM = 16;
var following = false, mapWatch = null, lastPanAt = null;
var currentCells = [];
var lastFix = null; /* the most recent REAL geolocation fix */
Expand Down Expand Up @@ -306,11 +311,17 @@
hereDot.setLatLng(ll);
}
if (!following) return;
/* A pan fires moveend, which posts the area and refetches nests: pan only
* when the dot has actually moved AND left the middle of the view. */
var moved = !lastPanAt || haversineMeters(lastPanAt, fix) > 10;
var inside = map.getBounds().pad(-0.3).contains(ll);
if (moved && !inside) {
/* Following means the map scrolls under you and you stay in the middle of
* it. The first version only panned once you had drifted out of the middle
* 40% of the view, which reads as the map lurching every few hundred metres
* rather than travelling with you.
*
* 10 m is the same floor the waddle uses: it clears typical high-accuracy
* GPS jitter (3-15 m), so standing still does not creep the map. Frequent
* pans are cheap here — the moveend work is debounced 500 ms and coalesces,
* and the area post has its own independent 75 m ratchet in the watch, so
* a continuous walk still reports itself even while pans keep collapsing. */
if (!lastPanAt || haversineMeters(lastPanAt, fix) > 10) {
lastPanAt = { lat: fix.lat, lon: fix.lon };
map.panTo(ll, { animate: true });
}
Expand Down Expand Up @@ -986,7 +997,7 @@
if (!following) return;
here().then(function (pos) {
paintHere(pos);
if (map) map.setView([pos.lat, pos.lon], Math.max(map.getZoom(), 15));
if (map) map.setView([pos.lat, pos.lon], Math.max(map.getZoom(), WALK_ZOOM));
}).catch(function () { /* stay put */ });
});
}
Expand Down Expand Up @@ -2279,7 +2290,7 @@
/* The markup ships the chip lit; nothing follows until the first fix says so. */
setFollowing(false);
here().then(function (pos) {
map.setView([pos.lat, pos.lon], 15);
map.setView([pos.lat, pos.lon], WALK_ZOOM);
paintHere(pos);
setFollowing(true);
}).catch(function () {
Expand Down
2 changes: 1 addition & 1 deletion registry/add-ons.json
Original file line number Diff line number Diff line change
Expand Up @@ -4887,7 +4887,7 @@
{
"id": "ramble",
"name": "Ramble",
"version": "0.9.3",
"version": "0.9.4",
"type": "mcp-server",
"author": "Crow",
"category": "social",
Expand Down
17 changes: 16 additions & 1 deletion tests/ramble-panel.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -732,7 +732,22 @@ test("GET /ramble/static/ramble.js serves the client script as JavaScript", asyn
assert.ok(body.includes('map.createPane("rb-here")') && body.includes('getPane("rb-here").style.zIndex = 650'));
assert.ok(body.includes("function startMapWatch(") && body.includes("function paintHere(") && body.includes("function setFollowing("));
assert.ok(body.includes('map.on("dragstart"'), "a user drag ends follow mode");
assert.ok(body.includes("getBounds().pad(-0.3)"), "follow pans only when the dot leaves the middle of the view");
// CONTRACT CHANGED 2026-09-09: following now keeps you CENTRED. It used to
// pan only once you had drifted out of the middle 40% of the view, which
// reads as the map lurching every few hundred metres instead of travelling
// with you.
assert.ok(!body.includes("getBounds().pad(-0.3)"), "the leave-the-middle gate is gone");
assert.ok(body.includes("if (!lastPanAt || haversineMeters(lastPanAt, fix) > 10) {"),
"follow recentres on any real move, using the same 10 m jitter floor as the waddle");
assert.ok(body.includes('map.on("dragstart", function () { setFollowing(false); });'),
"and a manual scroll still releases it, so the user is never fighting the map");

// The opening frame has to be a walk, not a survey.
assert.ok(body.includes("var WALK_ZOOM = 16;"), "the default frame is walkable, not a survey of the county");
assert.ok(body.includes("map.setView([pos.lat, pos.lon], WALK_ZOOM);"), "and the first fix uses it");
assert.ok(body.includes("Math.max(map.getZoom(), WALK_ZOOM)"),
"re-centring never zooms you back OUT past walkable, but keeps a tighter zoom you chose");
assert.ok(!/setView\(\[pos\.lat, pos\.lon\], 15\)/.test(body), "no hard-coded 15 survives");
assert.ok(body.includes("reach_m: CLAIM_M") && body.includes("UNLOCK_M : null"));
assert.ok(body.includes("function drawEggSeed(") && body.includes("art: nestArt(nest)"));
assert.ok(body.includes('collectFx(nest.cell, "start")') && body.includes('collectFx(nest.cell, "done")') && body.includes('collectFx(nest.cell, "clear")'));
Expand Down
Loading