diff --git a/protoagent.plugin.yaml b/protoagent.plugin.yaml index 4f07141..7c03672 100644 --- a/protoagent.plugin.yaml +++ b/protoagent.plugin.yaml @@ -2,7 +2,7 @@ # Keep `version` in lockstep with pyproject.toml (tests/test_version.py asserts it). id: github name: GitHub (read/write tools) -version: 0.1.2 +version: 0.1.3 description: >- Read AND write GitHub tools over the `gh` CLI, with PER-AGENT write gating. The read tools (PRs, issues, diffs, CI, repo files/contents) are always on; the write diff --git a/pyproject.toml b/pyproject.toml index 2699f81..cf2fc98 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "github-plugin" -version = "0.1.2" +version = "0.1.3" description = "Read/write GitHub tools for protoAgent over the gh CLI, with per-agent write gating." requires-python = ">=3.11" diff --git a/tests/test_board_view.py b/tests/test_board_view.py index 3a4e732..8440efa 100644 --- a/tests/test_board_view.py +++ b/tests/test_board_view.py @@ -89,6 +89,16 @@ def test_board_page_is_read_only(): assert "/api/plugins/github/issues" in PAGE and "/api/plugins/github/prs" in PAGE # reads only +def test_pages_boot_once(): + """#13 regression — each page boots via the kit ONCE. A second direct ``boot();`` ran two + overlapping config+load sequences → the list flicker/thrash on mount.""" + from ghplugin.view import NEW_ISSUE_PAGE, PAGE + + for page in (PAGE, NEW_ISSUE_PAGE): + assert "kit.initPluginView(boot)" in page # booted via the handshake callback + assert "boot();" not in page # …and NOT also called directly + + def test_config_route_returns_repos_and_default(): c = TestClient(_app()) body = c.get("/api/plugins/github/config").json() diff --git a/view.py b/view.py index 9b2cdb5..31ff2c7 100644 --- a/view.py +++ b/view.py @@ -101,7 +101,12 @@ + ' '+labelPills(it.labels)+''; } + // A monotonic token so an in-flight load() whose fetch resolves AFTER a newer load() + // started (rapid tab/filter clicks, or any double-trigger) drops its stale result instead + // of clobbering the fresh list — no thrash. + let loadSeq = 0; async function load(){ + const my = ++loadSeq; const repo = $("repo").value, list = $("list"); if(!repo){ list.innerHTML = '