From 7ac486f9183597cc115ed4cd196595728ee49609 Mon Sep 17 00:00:00 2001 From: Aster Seker Date: Sun, 24 May 2026 06:12:34 +0300 Subject: [PATCH 1/4] docs(agents): reference git-workflow.md in Read First and Critical Defaults Add explicit link to Git workflow rules in AGENTS.md Read First and Critical Defaults sections. Replace inline Git section in critical-defaults.md with a pointer to the canonical guide. Co-Authored-By: Claude Opus 4.7 --- AGENTS.md | 3 +++ guides/critical-defaults.md | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index 0f8ef13..a876ff7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -56,6 +56,8 @@ Determine the task type and apply the corresponding format: - [Critical defaults](guides/critical-defaults.md) - mandatory rules for every repository task. +- [Git workflow](guides/git-workflow.md) - branch policy, PR-only workflow, + branch naming, and rules for AI agents before editing. - [Coding agent workflow](.claude/rules/delegation.md) - default workflow for all file-editing tasks (delegation, model routing, verification). - [Project overview](guides/project-overview.md) - domain model, public API @@ -73,6 +75,7 @@ Determine the task type and apply the corresponding format: See [guides/critical-defaults.md](guides/critical-defaults.md) for the full list of mandatory pre-edit, compatibility, testing, and git rules. +For branch and PR policy, also see [guides/git-workflow.md](guides/git-workflow.md). ## Provenance and Honesty diff --git a/guides/critical-defaults.md b/guides/critical-defaults.md index e8dc73d..b13ed1d 100644 --- a/guides/critical-defaults.md +++ b/guides/critical-defaults.md @@ -28,4 +28,4 @@ Mandatory rules for every repository task. ## Git -- All changes reach `main` through PRs; do not push directly to `main` unless the user explicitly overrides this rule. +See [Git workflow](git-workflow.md) for the full branch and PR policy. From a49183b078c261b125c1fc17a2c925a5d317e088 Mon Sep 17 00:00:00 2001 From: Aster Seker Date: Sun, 24 May 2026 06:12:44 +0300 Subject: [PATCH 2/4] feat(auth): add auth provider getter, has, and clear helpers Add clear_auth_provider(), has_auth_provider(), and auth_provider() to HttpClient for inspecting and resetting the current IAuthProvider without explicitly passing nullptr. Co-Authored-By: Claude Opus 4.7 --- include/kurlyk/http/HttpClient.hpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/include/kurlyk/http/HttpClient.hpp b/include/kurlyk/http/HttpClient.hpp index c8b6db6..e199522 100644 --- a/include/kurlyk/http/HttpClient.hpp +++ b/include/kurlyk/http/HttpClient.hpp @@ -200,6 +200,21 @@ namespace kurlyk { void set_auth_provider(std::shared_ptr provider) { m_auth_provider = provider; } + + /// \brief Removes the current authentication provider from this client. + void clear_auth_provider() { + m_auth_provider.reset(); + } + + /// \brief Returns whether this client has an active authentication provider. + bool has_auth_provider() const { + return m_auth_provider != nullptr; + } + + /// \brief Returns the current authentication provider, or nullptr if none is set. + std::shared_ptr auth_provider() const { + return m_auth_provider; + } #endif /// \brief Assigns an existing rate limit to future requests by ID. From f937782d4f895a445451091b56f747064da4c06c Mon Sep 17 00:00:00 2001 From: Aster Seker Date: Sun, 24 May 2026 06:12:57 +0300 Subject: [PATCH 3/4] fix(http): prevent cancel_requests deadlock on empty group If cancel_requests() (called from ~HttpClient) was invoked on a group with zero pending/active/failed requests while no processor was running, the callback was queued in m_groups_to_cancel but never processed, causing future.get() to block forever. Mirror the immediate-invoke pattern already used in wait_requests_by_group_id() for empty groups. Co-Authored-By: Claude Opus 4.7 --- include/kurlyk/http/HttpRequestManager.hpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/include/kurlyk/http/HttpRequestManager.hpp b/include/kurlyk/http/HttpRequestManager.hpp index 68aa7f6..ebad7b5 100644 --- a/include/kurlyk/http/HttpRequestManager.hpp +++ b/include/kurlyk/http/HttpRequestManager.hpp @@ -239,8 +239,18 @@ namespace kurlyk { if (callback) callback(); return; } - std::lock_guard lock(m_mutex); - m_groups_to_cancel[group_id].push_back(std::move(callback)); + bool invoke_now = false; + { + std::lock_guard lock(m_mutex); + if (group_request_count_unlocked(group_id) == 0) { + invoke_now = true; + } else { + m_groups_to_cancel[group_id].push_back(std::move(callback)); + } + } + if (invoke_now && callback) { + callback(); + } } /// \brief Processes all requests in the manager. From 3863683e407e1285602df71e31a1c9ef546bc277 Mon Sep 17 00:00:00 2001 From: Aster Seker Date: Sun, 24 May 2026 06:13:09 +0300 Subject: [PATCH 4/4] test(http): add wait_requests idle-group coverage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add Test 9 (wait_requests returns immediately on empty group) and Test 10 (wait_requests_for returns true immediately on empty group). Test 10 uncovered a deadlock in cancel_requests_by_group_id when no processor is running and the group is empty — fixed in prior commit. Co-Authored-By: Claude Opus 4.7 --- .../http_client_wait_requests_main.cpp | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/integration/http_client_wait_requests_main.cpp b/tests/integration/http_client_wait_requests_main.cpp index 4413177..017ebce 100644 --- a/tests/integration/http_client_wait_requests_main.cpp +++ b/tests/integration/http_client_wait_requests_main.cpp @@ -321,6 +321,26 @@ int main() { client.reset(); } + // --- Test 9: wait_requests() on empty group returns immediately --- + { + ProcessorGuard pg; + auto client = std::make_unique(base_url); + auto t0 = std::chrono::steady_clock::now(); + client->wait_requests(); + auto dt = std::chrono::steady_clock::now() - t0; + require(dt < std::chrono::milliseconds(50), + "wait_requests() on empty group must return immediately"); + client.reset(); + } + + // --- Test 10: wait_requests_for() on empty group returns true immediately --- + { + auto client = std::make_unique(base_url); + bool done = client->wait_requests_for(std::chrono::milliseconds(10)); + require(done, "wait_requests_for() on empty group must return true immediately"); + client.reset(); + } + server.stop(); server_thread.join();