Compare commits

...

1 Commits

Author SHA1 Message Date
freemo c090f72875 docs: update CHANGELOG and reference docs for session 3377
CI / lint (pull_request) Failing after 28s
CI / typecheck (pull_request) Successful in 57s
CI / security (pull_request) Successful in 1m18s
CI / quality (pull_request) Successful in 52s
CI / coverage (pull_request) Has been skipped
CI / build (pull_request) Successful in 34s
CI / helm (pull_request) Successful in 36s
CI / push-validation (pull_request) Successful in 22s
CI / e2e_tests (pull_request) Successful in 3m15s
CI / unit_tests (pull_request) Successful in 5m32s
CI / docker (pull_request) Has been skipped
CI / integration_tests (pull_request) Failing after 5m33s
CI / status-check (pull_request) Failing after 1s
CI / benchmark-publish (pull_request) Has been skipped
CI / benchmark-regression (pull_request) Has been skipped
- 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
2026-04-09 03:52:47 +00:00
3 changed files with 86 additions and 1 deletions
+21 -1
View File
@@ -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-<job>`), 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-<PREFIX>]`
@@ -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)
+43
View File
@@ -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 <PAT>' \
'https://git.cleverthis.com/api/v1/repos/cleveragents/cleveragents-core/actions/artifacts'
# Download a specific artifact
curl -H 'Authorization: token <PAT>' \
'https://git.cleverthis.com/api/v1/repos/cleveragents/cleveragents-core/actions/artifacts/<ID>/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).
+22
View File
@@ -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.