From c090f728756e1918d50ee4d7ee87952f4b387d62 Mon Sep 17 00:00:00 2001 From: Jeffrey Phillips Freeman Date: Sun, 5 Apr 2026 16:22:57 +0000 Subject: [PATCH] docs: update CHANGELOG and reference docs for session 3377 - CHANGELOG: add CI log artifacts (PR #2782), provider benchmarks (PR #3022) to [Unreleased] Added section - CHANGELOG: add LSP restart_server() deadlock fix (PR #3165) to [Unreleased] Fixed section - docs/reference/lsp.md: document LspLifecycleManager 3-phase lock concurrency model for restart_server() thread safety - docs/development/ci-cd.md: document CI log artifact names, download API, and agent usage patterns ISSUES CLOSED: #3377 --- CHANGELOG.md | 22 +++++++++++++++++++- docs/development/ci-cd.md | 43 +++++++++++++++++++++++++++++++++++++++ docs/reference/lsp.md | 22 ++++++++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 885d0e7ba..1a6882e32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,17 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ## [Unreleased] ### Added +- **CI — Log artifacts for all nox jobs**: All 8 nox-running CI jobs now capture + their stdout/stderr output as named Forgejo artifacts (`ci-logs-`), uploaded + with `if: always()` so logs are available even on failure. Agent definition files + updated to download the relevant artifact before falling back to running nox locally. + 30-day retention, consistent with existing coverage artifact policy. (PR #2782) +- **Benchmarks — Provider module ASV suite**: 68 new ASV benchmark methods across 5 + files covering `ProviderCostTable`, `CostTracker`, `FallbackSelector`, + `ProviderRegistry`, and LLM adapter instantiation (`LangChainChatProvider`, + `AnthropicChatProvider`, `GoogleChatProvider`, `OpenAIChatProvider`, + `OpenRouterChatProvider`). All benchmarks are hermetic (mock `Settings`, no live + API calls). (PR #3022) - **Automation Tracking System**: Replaced shared session state issue tracking with individual per-agent tracking issues. Each agent now creates its own `[AUTO-]` @@ -76,7 +87,6 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). - **JSON-RPC 2.0 A2A wire format**: `A2aRequest`/`A2aResponse` fields renamed to standard JSON-RPC 2.0 names (`method`, `id`, `result`, `error`). The `A2aVersionNegotiator` handles backward compatibility. - - **Database resource handler**: Full CRUD and checkpoint/rollback support for SQLite, PostgreSQL, MySQL, and DuckDB resources via the resource DAG. @@ -113,6 +123,16 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ### Fixed +- **LSP — `LspLifecycleManager.restart_server()` deadlock**: `restart_server()` previously + held `self._lock` across all blocking I/O operations (`transport.stop()`, + `transport.start()`, `client.initialize()`). Under concurrent access this caused a + deadlock: any thread calling `health_check()`, `list_running()`, or `stop_server()` + would block for up to 60 seconds. Refactored to use the same 3-phase lock pattern + already employed by `start_server()`: lock is held only for short state-mutation + phases, released during all blocking I/O. The `ref_count` from the original managed + server is preserved across the restart. Three new BDD scenarios verify the fix. + Closes #3026. (PR #3165) + - `LangChainChatProvider.name` and `model_id` are now mutable properties with setters, fixing an `AttributeError` when `PlanService` attempted to resolve provider names after instantiation. (#1553) diff --git a/docs/development/ci-cd.md b/docs/development/ci-cd.md index b75667bb2..4432b906c 100644 --- a/docs/development/ci-cd.md +++ b/docs/development/ci-cd.md @@ -399,3 +399,46 @@ bash scripts/setup-dev.sh pre-commit install pre-commit install --hook-type commit-msg ``` + +## CI Log Artifacts + +All 8 nox-running CI jobs capture their stdout/stderr output as named Forgejo +artifacts. This makes CI logs immediately downloadable without scraping the UI. + +| Artifact Name | CI Job | Contents | +|---------------|--------|----------| +| `ci-logs-lint` | `lint` | Ruff format + lint output | +| `ci-logs-typecheck` | `typecheck` | Pyright output | +| `ci-logs-security` | `security` | Bandit + Vulture output (combined) | +| `ci-logs-quality` | `quality` | Radon complexity output | +| `ci-logs-unit-tests` | `unit_tests` | Behave BDD test output | +| `ci-logs-integration-tests` | `integration_tests` | Robot Framework output | +| `ci-logs-e2e-tests` | `e2e_tests` | End-to-end test output | +| `ci-logs-coverage` | `coverage` | Coverage measurement output | + +**Key properties:** + +- Artifacts are uploaded with `if: always()` so they are available even when + the job fails — which is precisely when they are most needed. +- Multi-session jobs (e.g., `lint` runs both `lint` and `format`) append to a + single log file using `tee -a`, keeping one artifact per CI job. +- Retention: 30 days, consistent with the existing `coverage-reports` policy. + +### Downloading Artifacts via API + +```bash +# List artifacts for a workflow run +curl -H 'Authorization: token ' \ + 'https://git.cleverthis.com/api/v1/repos/cleveragents/cleveragents-core/actions/artifacts' + +# Download a specific artifact +curl -H 'Authorization: token ' \ + 'https://git.cleverthis.com/api/v1/repos/cleveragents/cleveragents-core/actions/artifacts//zip' \ + -o ci-logs-lint.zip +``` + +### Agent Usage + +Agent definition files (`ca-pr-checker.md`, `ca-lint-fixer.md`, etc.) are +configured to download the relevant artifact first, then fall back to running +nox locally if the artifact is unavailable (e.g., on a first-run PR). diff --git a/docs/reference/lsp.md b/docs/reference/lsp.md index 1f0916cf0..c39ed4c4e 100644 --- a/docs/reference/lsp.md +++ b/docs/reference/lsp.md @@ -122,3 +122,25 @@ LSP server names follow the project-wide namespacing pattern: `[[server:]namespa - `local/pyright` — a locally-defined Pyright server - `devops/clangd` — a clangd server in the devops namespace + +## `LspLifecycleManager` — Concurrency Model + +The `LspLifecycleManager` uses a 3-phase lock pattern for all server lifecycle +operations to prevent deadlocks under concurrent access: + +| Phase | Lock held? | What happens | +|-------|-----------|------| +| 1 | ✅ short | Read current state, snapshot fields, mutate `_servers` dict | +| 2 | ❌ none | All blocking I/O: `transport.stop()`, `transport.start()`, `client.initialize()` | +| 3 | ✅ short | Insert updated `_ManagedServer` into `_servers` | + +This pattern applies to both `start_server()` and `restart_server()`. Releasing +the lock during Phase 2 ensures that concurrent callers of `health_check()`, +`list_running()`, or `stop_server()` are never blocked for the duration of +blocking I/O (which can take up to 60 seconds on timeout). + +During a `restart_server()` call, the server is removed from `_servers` in +Phase 1 and re-inserted in Phase 3. Concurrent callers will see the server as +absent during the restart window — this is consistent with the `start_server()` +contract. The `ref_count` from the original `_ManagedServer` is carried forward +to the new instance. -- 2.52.0