From 85fa1d607cfd42db8c9a1307fef314664dc9ee2b Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 2 Nov 2026 13:09:07 +0000 Subject: [PATCH] Rating: a clip the Shot camera learned from is no longer reported as untaught Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_01Tw9fjXtFiTrX7ixo9tG11y --- modules/system/taste/__init__.py | 11 ++++++++++- modules/system/taste/tests/test_taste_routes.py | 13 +++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/modules/system/taste/__init__.py b/modules/system/taste/__init__.py index 36873b7d..28cc35d3 100644 --- a/modules/system/taste/__init__.py +++ b/modules/system/taste/__init__.py @@ -239,13 +239,22 @@ def routes(table, base, web): except (ValueError, AttributeError) as exc: return web.json_response({"why": str(exc)}, status=400) # any module that learns from ratings (provides "on_rating") hears of it; one failing never loses the rating + taught = [] for spec in _core.registry.current().specs.values(): hear = spec.provides.get("on_rating") if hear: try: - hear(body.get("prompt_id"), body.get("rating"), body.get("axis")) + if hear(body.get("prompt_id"), body.get("rating"), body.get("axis")): + taught.append(spec.id) except Exception as exc: _core.log.once(f"on_rating:{spec.id}", _core.log.ALERT, spec.title, f"could not learn from this rating: {exc}") + if taught: + # something else learned from it (the camera keeps its own memory): the rating did teach, so the + # "captured nothing" notice would be wrong + out["taught"] = taught + if not out.get("recorded") and not out.get("updated"): + out.pop("why", None) + out.pop("reason", None) return web.json_response(out) @table.post(base + "/generation") diff --git a/modules/system/taste/tests/test_taste_routes.py b/modules/system/taste/tests/test_taste_routes.py index 52791647..18089c31 100644 --- a/modules/system/taste/tests/test_taste_routes.py +++ b/modules/system/taste/tests/test_taste_routes.py @@ -145,3 +145,16 @@ def test_the_generation_route_forgets_unrated_runs_over_http(server): # noqa: F assert status == 200 and out == {"dropped": 2} status, out = _request(server, "POST", "/fun/api/m/taste/rate", {"prompt_id": "p1", "rating": "liked"}) assert status == 200 and out["recorded"] == [] and "new Generate" in out["why"] + + +def test_a_rating_the_camera_learned_from_is_not_called_untaught(server, tmp_path, monkeypatch): # noqa: F811 + """Only Shot camera is on: Taste captured nothing, but the camera keeps its own memory and learned.""" + from modules.conditioning.shot_camera import memory + monkeypatch.setenv("SHOT_CAMERA_MEMORY", str(tmp_path / "m.json")) + memory.record_run("c1", {"views": [{"view": "side view", "traits": ["none"]}], "arms": ["a1"]}) + status, out = _request(server, "POST", "/fun/api/m/taste/rate", {"prompt_id": "c1", "rating": "liked"}) + assert status == 200 and "why" not in out and "reason" not in out, out + assert out["taught"] == ["conditioning_shot_camera"], out + assert memory.view_stats()["side view"] == (1.0, 0.0) + status, out = _request(server, "POST", "/fun/api/m/taste/rate", {"prompt_id": "nobody", "rating": "liked"}) + assert out["why"] and out["reason"] == "nothing" and "taught" not in out, out