From 864eaeb3c83bccd6303d200f386ed8b18e1bdd5c Mon Sep 17 00:00:00 2001 From: Evan Date: Fri, 18 Sep 2026 13:24:52 +0800 Subject: [PATCH 1/3] fix: start self-learning worker from TUI Fixes #164 --- tests/test_tui_protocol.py | 24 ++++++++++++++++++++++++ tui_backend.py | 2 ++ 2 files changed, 26 insertions(+) diff --git a/tests/test_tui_protocol.py b/tests/test_tui_protocol.py index 5c2c040..af568ee 100644 --- a/tests/test_tui_protocol.py +++ b/tests/test_tui_protocol.py @@ -82,6 +82,30 @@ def test_provider_setup_emits_ready_and_masks_key_flow(self): self.assertEqual(events[1]["event"], "status") self.assertNotIn("sk-test-secret", self.output.getvalue()) + def test_start_launches_detached_learning_worker_when_provider_is_ready(self): + context = type("Context", (), { + "active_root": Path("/tmp/openkyrozen-tui-workspace"), + "is_global": True, + })() + config = type("Config", (), { + "provider": "deepseek", + "model_simple": "deepseek-v4-flash", + })() + plugin = type("Plugin", (), {"load_once": lambda self: None})() + with patch.object(tui_backend.agent, "configure_launch_context", return_value=context), \ + patch.object(tui_backend.agent, "detect_provider", return_value=config), \ + patch.object(tui_backend.agent, "_prompt_and_init_deepseek", return_value=True), \ + patch.object(tui_backend.agent, "_plugin_runtime_for_surface", return_value=plugin), \ + patch.object(tui_backend.agent, "_run_recovered_tasks", return_value=[]), \ + patch.object(tui_backend.agent, "_load_project_files_into_memory"), \ + patch.object(tui_backend.agent, "_ensure_detached_learning_worker", return_value=True) as ensure_worker: + self.backend.start({"command": "start", "global": True}, "start-1") + + ensure_worker.assert_called_once_with() + events = [json.loads(line) for line in self.output.getvalue().splitlines()] + self.assertEqual(events[-1]["event"], "status") + self.assertEqual(events[-1]["state"], "ready") + def test_approval_response_requires_a_correlated_request_id(self): payload, error = self.backend.validate({"command": "approval_response", "approved": True}) self.assertIsNone(payload) diff --git a/tui_backend.py b/tui_backend.py index 68d57e9..82f6da1 100644 --- a/tui_backend.py +++ b/tui_backend.py @@ -136,6 +136,8 @@ def start(self, payload: dict[str, Any], request_id: str) -> None: self.status("starting", "Restoring tasks and memory…", request_id) task_results = self._quiet_call(agent._run_recovered_tasks) self._quiet_call(agent._load_project_files_into_memory) + if configured and not self._quiet_call(agent._ensure_detached_learning_worker): + threading.Thread(target=agent._background_learning_loop, daemon=True).start() self.emit("tasks", request_id, tasks=[ {"id": item["id"], "description": item["description"], "status": item["status"]} for item in agent.tasks.tasks From 6a30d45d7ef7b4e68e1a15b2ed4beb475ff34640 Mon Sep 17 00:00:00 2001 From: Evan Date: Fri, 18 Sep 2026 13:30:18 +0800 Subject: [PATCH 2/3] test: inspect wheel entry points in isolated env --- scripts/wheel_smoke.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/scripts/wheel_smoke.py b/scripts/wheel_smoke.py index ed4d781..b5be1b2 100755 --- a/scripts/wheel_smoke.py +++ b/scripts/wheel_smoke.py @@ -4,7 +4,7 @@ from __future__ import annotations import glob -import importlib.metadata +import json import os import subprocess import sys @@ -66,11 +66,10 @@ def main() -> int: "KYROZEN_PROVIDER": "ollama", "KYROZEN_DISABLE_VECTOR_INDEX": "1", }) - entry_points = { - entry.name: entry.value - for entry in importlib.metadata.entry_points(group="console_scripts") - if entry.name in {"kyrozen", "kyrozen-backend"} - } + entry_points = json.loads(_run([ + str(python), "-c", + "import importlib.metadata, json; print(json.dumps({e.name: e.value for e in importlib.metadata.entry_points(group='console_scripts') if e.name in {'kyrozen', 'kyrozen-backend'}}))", + ], cwd=caller, env=env).stdout) if entry_points.get("kyrozen") != "tui_launcher:main" or entry_points.get("kyrozen-backend") != "tui_backend:main": raise RuntimeError(f"installed entry points did not target the TUI bridge: {entry_points}") version = _run([str(kyrozen), "--version"], cwd=caller, env=env) From 696f06834534e8364aa3c166e47975d44bb2fd96 Mon Sep 17 00:00:00 2001 From: Evan Date: Fri, 18 Sep 2026 15:29:02 +0800 Subject: [PATCH 3/3] docs: update self-learning test count --- docs/self-evolution.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/self-evolution.md b/docs/self-evolution.md index a55a117..ce7dc3f 100644 --- a/docs/self-evolution.md +++ b/docs/self-evolution.md @@ -9,7 +9,7 @@ Historical verification snapshot: `51be33361422e55e1f2f00c33a0e0f8c56132a91` (the post-#54 `main` revision, captured before this #55 documentation-only update). Snapshot date: 2026-09-04. -Current repository test count at this snapshot: **211 unittest cases**. +Current repository test count at this snapshot: **212 unittest cases**. ## Verified surface