agnes-the-ai-analyst/tests
ZdenekSrotyr 28430ced09
Keboola cutover: native parquet path + sync correctness + auto-discover protection (#190)
* fix: cutover regressions + parallel Keboola legacy fallback

Bundled fixes from a fresh-deploy run on a Keboola Storage backend with
the block-shared-snowflake-access feature flag — DuckDB Keboola
extension's per-table scan can't access bucket schemas, so the legacy
kbcstorage Storage-API client is the only working path.

CUTOVER REGRESSIONS

- agnes pull hash mismatch on every Keboola local-mode table —
  src/orchestrator.py:_update_sync_state stored md5(mtime+size)[:12]
  while the CLI compares against full 32-char content MD5. Now stores
  the same content MD5 the materialized SQL path already used.

- Trailing-slash sanitization in connectors/keboola/access.py and
  extractor.py — DuckDB Keboola extension's ATTACH fails when the URL
  ends in / (canonical form).

- src/profiler.py:TableInfo.description becomes optional — two call
  sites instantiated without it, crashing the profiler pass.

- scripts/ops/agnes-auto-upgrade.sh: chown on UID change — older images
  ran as root, current runs as agnes (uid 999). Reads target uid:gid
  from /etc/passwd inside the new image and chowns ${STATE_DIR},
  /data/extracts, /data/analytics when the digest moves.

- POST /api/sync/trigger is now singleton per process — two
  near-simultaneous trigger calls each forked an extractor subprocess,
  fought for extract.duckdb's file lock, starved uvicorn, flipped the
  container to unhealthy. Trigger now returns 409
  (sync_already_in_progress) when held; _run_sync acquires non-blocking.

PARALLEL LEGACY FALLBACK

- Process pool fan-out for the _extract_via_legacy queue (default 8
  workers, override via AGNES_KEBOOLA_PARALLELISM). Process pool, not
  thread pool, because connectors/keboola/client.py:export_table does
  os.chdir(temp_dir) — process-global, so threads raced and slice files
  landed in the wrong directory ("[Errno 2] No such file or directory:
  '<job_id>.csv_X_Y_Z.csv'").

- Extractor subprocess timeout 1800s -> 3600s (configurable via
  AGNES_EXTRACTOR_TIMEOUT_SEC). 28+ tables × multi-minute Keboola export
  jobs need the headroom on telemetry-class projects.

- Process group cleanup on timeout — Popen(start_new_session=True) puts
  the extractor in its own group. On timeout the parent SIGTERMs the
  group (10s grace) then SIGKILLs stragglers. Without this, the pool
  workers were reparented to PID 1 and continued holding open Keboola
  Storage export jobs. Inline extractor script also installs a SIGTERM
  -> sys.exit(143) handler so the with ProcessPoolExecutor(...) block
  __exit__ runs cleanly.

Tests: existing tests that patched subprocess.run updated to patch
subprocess.Popen with a _FakePopen stand-in (same exit-code-injection
contract). Two tests that exercised the parallel path forced
AGNES_KEBOOLA_PARALLELISM=1 to keep mocks alive (mocks don't ride into
ProcessPoolExecutor subprocesses).

Squashed onto current main (was 7 commits + multi-commit CHANGELOG +
agnes-auto-upgrade.sh conflicts; squash avoids per-commit conflict
resolution against main's flat-mount STATE_DIR refactor and 0.38.0
release cut).

* feat(keboola): Storage API direct extract path; drop extension data path

The DuckDB Keboola extension's COPY routes through Keboola QueryService,
which is unreliable on linked-bucket projects (extension v0.1.6 fixes
that case but isn't yet in the community CDN, and pre-fix any project
with the block-shared-snowflake-access feature flag couldn't see bucket
schemas at all). Move the extract path off the extension entirely and
talk to the Storage API directly via signed-URL download — works on any
project, regardless of extension state.

connectors/keboola/storage_api.py (NEW)
  Lightweight client built on requests.Session. Three endpoints:
  - POST /v2/storage/tables/{id}/export-async        (kicks off job)
  - GET  /v2/storage/jobs/{id}                        (poll until done)
  - GET  /v2/storage/files/{id}?federationToken=1     (signed URL detail)
  - GET  <signed_url>                                 (download bytes)
  Supports sliced exports (manifest + per-slice signed URLs) and gzipped
  payloads. ExportFilter dataclass mirrors the Keboola filter spec
  (whereFilters / columns / changedSince / limit) and handles JSON
  round-trip with the registry's source_query column. Token redaction
  in error messages. Bounded exponential backoff on job polling.
  No cloud-SDK dependency on the data path; thread-safe.

connectors/keboola/extractor.py
  - materialize_query() rewritten: takes bucket/source_table/source_query
    (JSON filter spec), exports via KeboolaStorageClient, converts CSV
    to parquet via DuckDB, atomic os.replace. Same return shape so
    sync.py downstream code stays uniform with the BQ branch.
  - _extract_via_legacy() also moved to Storage API direct (kept the
    name for caller compatibility with _legacy_worker / the parallel
    batch extractor). Per-call temp directories — no os.chdir, threads
    don't race.

app/api/sync.py
  _run_materialized_pass for source_type='keboola' rows now constructs a
  KeboolaStorageClient (replaces KeboolaAccess) and passes
  bucket/source_table/source_query to materialize_query. Reuses one
  client across rows for HTTP keep-alive. Sources keboola URL from env
  too (KEBOOLA_STACK_URL) when instance.yaml doesn't have stack_url
  configured.

cli/commands/admin.py
  discover-and-register defaults Keboola rows to query_mode='materialized'
  (NULL source_query = full table), matching the v26 migration's
  unification of the local/materialized split for Keboola. BigQuery and
  Jira keep their per-source defaults.

src/db.py
  Schema bump 25 → 26. Migration: UPDATE table_registry SET
  query_mode='materialized' WHERE source_type='keboola' AND
  query_mode='local'. NULL source_query on those rows means "full table
  export" — same effective behavior the local mode provided, but now
  via Storage API instead of the extension.

pyproject.toml
  kbcstorage dep stays (admin-side bucket/table list still uses the
  SDK in app/api/admin.py / connectors/keboola/client.py); only the
  data path is migrated off the SDK. Comment updated to reflect the
  new boundary.

tests
  - test_keboola_storage_api.py (NEW, 19 tests): ExportFilter parsing,
    HTTP client (token redaction, retry logic, polling), download_file
    (single, gzipped, sliced), end-to-end export_table_to_csv.
  - test_keboola_materialize.py rewritten: mocks KeboolaStorageClient
    instead of FakeAccess; same atomic-write + zero-rows + unsafe-id
    contracts.
  - test_sync_trigger_keboola_materialized.py: registry rows now carry
    bucket+source_table+JSON-shape source_query.

114+ Keboola-impacted tests green locally.

* test: schema version assertion bumped to 26 alongside the keboola query_mode migration

* fix(keboola): cutover hot-patches surfaced on agnes-dev

Five small fixes that were applied as in-container hot-patches during
agnes-dev cutover and need to be on the source-of-truth image so a fresh
upgrade does not undo them.

- app/api/sync.py: auto-discover gate considers the WHOLE registry (any
  source, any mode), not just rows where source matches and query_mode
  is local. After the v25→v26 keboola materialized migration an
  instance can have 30 materialized rows and zero local rows; the
  previous gate kept re-firing _discover_and_register_tables every
  scheduler tick, creating duplicate auto-discovered rows with the
  wrong bucket prefix every time.

- app/api/admin.py: _discover_and_register_tables reassembles the
  bucket as <stage>.<bucket-id> (e.g. in.c-finance) instead of
  dropping the stage prefix; default query_mode for keboola is now
  materialized (the v26 contract); validator allows NULL source_query
  for keboola materialized rows (full-table export via Storage API
  export-async, no SQL needed).

- cli/commands/admin.py: register-table mirrors the server validator
  (NULL source_query allowed for source_type=keboola); --bucket help
  text generalized to cover both BQ dataset and Keboola bucket id.

- connectors/keboola/extractor.py: max_line_size=64 MiB on
  read_csv_auto so embedded JSON / SQL cells (kbc_component_configuration
  in particular) do not trip the default 2 MiB ceiling.

- connectors/keboola/storage_api.py: GCP backend support — when the
  Storage API returns a manifest whose slice URLs are gs://
  references with a gcsCredentials block, rewrite to the JSON REST
  download endpoint and authenticate with the issued OAuth bearer
  token; redact tokens in any surfaced error string.

* test: align with new keboola materialized + auto-discover-gate contracts

- test_admin_keboola_materialized: rename
  test_register_keboola_materialized_rejects_missing_source_query →
  test_register_keboola_materialized_accepts_missing_source_query.
  v25→v26 introduced 'keboola materialized with NULL source_query
  means full-table export via Storage API export-async' as the
  default registration shape; the rejection case is no longer the
  contract.

- test_sync_filter: add list_all() to _StubRegistry. The auto-discover
  gate in _run_sync now keys off the WHOLE registry (not just local
  rows) so materialized-only Keboola instances do not re-trigger
  discovery on every tick.

* feat(keboola): native parquet export — skip CSV roundtrip

Storage API export-async accepts fileType={csv,parquet}. Switching the
materialized sync to parquet eliminates the CSV → DuckDB COPY → parquet
roundtrip that pinned a single uvicorn worker over 4 GiB on multi-GB
tables (read_csv with all_varchar + max_line_size=64MB has to
materialize the whole CSV in memory before COPY can stream out a
parquet). Snowflake UNLOAD on Keboola's side already produces typed,
self-contained parquet files; the extractor downloads them and renames
into place.

Two cases:

- **Single-file** export (small table): file_info.url points at one
  signed URL; download_file streams chunks straight to .parquet.tmp
  and we're done. No DuckDB.

- **Sliced** export (Snowflake UNLOAD respects MAX_FILE_SIZE — 16 MiB
  default — so anything larger arrives as N parquet slices): each
  slice is a complete parquet file with its own footer; naive concat
  would corrupt them. download_file_slices keeps the slices as
  separate files in a tempdir, then DuckDB COPY (SELECT * FROM
  read_parquet([slice0, slice1, ...])) merges them into one
  consolidated parquet. DuckDB streams row groups during this — peak
  memory bounded to one row group (~1 MiB) regardless of source size.

The legacy CSV path stays as the explicit opt-in via source_query=
'{"file_type":"csv"}' for projects whose backend can't UNLOAD
parquet (none known today; cheap escape hatch). Backward-compat alias
KeboolaStorageClient.export_table_to_csv kept.

Also fixes a latent bug in download_file's gzip detection: previous
heuristic flagged any unencrypted file as gzipped, which would have
corrupted parquet downloads at gunzip time. Name-suffix-only now.

* fix: tempdir leak cleanup, every 0m schedule, /sync/trigger body shapes

Three small self-contained fixes uncovered during agnes-dev cutover.

- connectors/keboola/extractor.py: tempfile.TemporaryDirectory now uses
  ignore_cleanup_errors=True so a worker death mid-write doesn't leave
  multi-GiB stale slice trees on the boot disk. (12 GiB seen after a
  disk-full crash where TemporaryDirectory's own cleanup also raised
  and got swallowed.)

- src/scheduler.py: is_valid_schedule accepts 'every 0m' (interval=0
  = always due). Force-resync of an errored row no longer requires
  waiting out the default 'every 1h' interval — admin can flip the
  schedule, trigger, then flip back.

- app/api/sync.py: POST /api/sync/trigger accepts both ['table_id']
  (legacy bare-array body) and {'tables': ['table_id']} (matches the
  response payload shape, more discoverable for clients building
  requests by hand). Malformed bodies return 422 with a structured
  detail; null/missing means 'sync everything' as before.

Tests cover: tempdir cleanup on raise (sliced parquet path),
is_valid_schedule + is_table_due 'every 0m' acceptance, and trigger
body parametrized matrix (8 valid shapes + 6 rejection cases).

* fix: targeted-trigger filter in materialized pass + auto-upgrade defer

Two operational gaps observed during agnes-dev cutover, in the same
sync-routing area.

- _run_materialized_pass now takes a 'tables' arg and skips rows not in
  the target set with reason='not_in_target'. POST /api/sync/trigger
  with a body of tables previously only scoped the legacy extractor
  subprocess — the materialized pass kept iterating every due
  materialized row, so an admin asking to re-sync kbc_job re-ran
  every other due materialized row alongside it. Match on registry id
  OR name (admins commonly pass either form). tables=None preserves
  the no-filter behavior.

- New GET /api/sync/status (public, no auth) returns {locked: bool}
  off _sync_lock.locked(). agnes-auto-upgrade.sh probes this before
  docker compose up -d and exits 0 with a 'deferred recreate' log
  line if a sync is in flight — the next 5-min cron tick retries.
  Pre-fix, an auto-upgrade triggered mid-sync would recreate the
  uvicorn worker and kill the in-flight extractor / Snowflake-UNLOAD
  download (observed when kbc_job's first 7-day retry got SIGKILLed).
  Connection failures in the probe fall through to the upgrade —
  being stuck on a wedged image is worse than interrupting a
  hypothetical sync.

* fix: auto-discover protects admin overrides + surfaces drift

Two real-world incidents on agnes-dev drove this:

1. kbc_job was registered manually with the correct
   (in.c-kbc_telemetry, kbc_job) coordinates. A naive auto-discover
   re-run would have inserted a SECOND kbc_job row at the slugified
   id 'in_c-keboola-storage_kbc_job' (where Keboola's discovery
   places it) — and that row's Storage API export-async 404s.

2. An earlier auto-discover bug stripped the stage prefix from
   bucket ids ('c-finance' instead of 'in.c-finance'), inserting
   137 rows whose syncs all failed.

Fix:

- _discover_and_register_tables now builds a plan first
  (_build_keboola_discovery_plan) classifying each discovered table
  into one of new / existing_match / existing_drift / invalid, then
  executes only the 'new' bucket. Drift rows are reported with both
  sides of the disagreement plus drift_kind:
  - same_id_diff_coords: registry has the same id but different
    bucket / source_table (admin migrated coords inline).
  - name_collision: discovery's slugified id differs from any
    registry id, but the discovered .name matches an existing row's
    .name (case-insensitive). Catches the kbc_job case.

- Bucket detection now prefers the API's authoritative bucket_id
  field (separate field on the Keboola tables.list response,
  normalised by KeboolaClient.discover_all_tables). Falls back to
  id-string parsing only when bucket_id is missing (older fallback
  path inside discover_all_tables).

- Endpoint POST /api/admin/discover-and-register?dry_run=true
  returns the plan without writing — would_register, drift,
  invalid lists. Lets an operator audit before merging discovery
  with a registry that has admin overrides.

Removed 'every 0m' from test_register_request_rejects_malformed_sync_schedule
— the runtime started accepting it in the previous commit (force-resync
override) and the validator follows suit.

* feat(keboola): AGNES_TEMP_DIR routes tempfiles off overlayfs /tmp

The container's /tmp lives on the boot disk's overlayfs (29 GiB on
agnes-dev, shared with /var). Snowflake UNLOAD of a wide table writes
slices into per-call /tmp tempdirs that fill multi-GiB / many-slice
exports long before the dedicated data disk fills. agnes-dev hit
100% boot-disk while the 20 GiB data disk had 15 GiB free.

connectors.keboola.storage_api.get_temp_root() reads AGNES_TEMP_DIR;
mkdirs the target on first use; unset / empty / unwritable falls
back to None (system tempdir, OSS-pre-fix behaviour). Both
materialize_query (parquet path) and _extract_via_legacy (CSV
fallback) and the sliced-CSV concat path in storage_api use the
helper now.

docker-compose.yml defaults AGNES_TEMP_DIR=/data/tmp on app, scheduler,
and extract services. The data volume is the dedicated disk in
production layouts and a plain docker volume in single-disk
dev/laptop setups — same blast radius as the previous /tmp default
on the latter, no regression.
2026-05-07 12:12:14 +02:00
..
fixtures chore(lint): drop unused imports from new test files (ruff F401) 2026-05-04 19:32:31 +02:00
helpers feat(scheduler): re-wire sync_schedule + script.schedule; tune via env; OpenMetadata TLS (#135) 2026-04-29 22:06:30 +02:00
snapshots feat(api,web,cli): /admin/workspace-prompt + /api/welcome restored + da analyst writes CLAUDE.md 2026-05-03 22:44:14 +02:00
__init__.py Initial commit: OSS data distribution platform 2026-03-08 23:31:28 +01:00
conftest.py merge: pull #174 (BQ materialize view fix + concurrency, 0.33.0) into bootstrap branch 2026-05-04 20:53:00 +02:00
test_access_control.py feat(rbac): drop dataset_permissions + users.role + is_public; v19 migration (#150) 2026-04-30 22:02:16 +02:00
test_admin_bigquery_test_connection.py test(admin): #160 RED tests for BQ test-connection + server-config placeholder 2026-05-04 10:31:35 +02:00
test_admin_bq_register.py Keboola cutover: native parquet path + sync correctness + auto-discover protection (#190) 2026-05-07 12:12:14 +02:00
test_admin_configure_api.py feat(scheduler): re-wire sync_schedule + script.schedule; tune via env; OpenMetadata TLS (#135) 2026-04-29 22:06:30 +02:00
test_admin_discover_bigquery.py feat(materialized): query_mode='materialized' for BigQuery + Keboola — admin SELECT → parquet → analyst 2026-05-01 20:25:56 +02:00
test_admin_discover_keboola_plan.py Keboola cutover: native parquet path + sync correctness + auto-discover protection (#190) 2026-05-07 12:12:14 +02:00
test_admin_keboola_materialized.py Keboola cutover: native parquet path + sync correctness + auto-discover protection (#190) 2026-05-07 12:12:14 +02:00
test_admin_phase_c_deprecation.py feat(materialized): query_mode='materialized' for BigQuery + Keboola — admin SELECT → parquet → analyst 2026-05-01 20:25:56 +02:00
test_admin_put_preservation.py feat(materialized): query_mode='materialized' for BigQuery + Keboola — admin SELECT → parquet → analyst 2026-05-01 20:25:56 +02:00
test_admin_register_materialized_server_generated_sql.py feat(admin): server-generate materialized source_query, allow BQ backticks 2026-05-04 18:37:27 +02:00
test_admin_register_source_type_validation.py feat(admin-api): reject register-table for source_type not configured on instance 2026-05-01 23:04:51 +02:00
test_admin_run_endpoints.py fix(session-collector-api): mirror sibling endpoints' audit-on-exception (Devin Review on #179) 2026-05-05 09:31:33 +02:00
test_admin_server_config.py fix(query): #168 review iter 3 — RBAC name-vs-id, placeholder dead code 2026-05-04 13:51:36 +02:00
test_admin_server_config_corp_memory.py feat(admin-ui): /admin/server-config known-fields registry + structured nested editor 2026-05-01 20:27:01 +02:00
test_admin_server_config_known_fields.py refactor(bq): #160 remove legacy_wrap_views config knob (always-wrap) 2026-05-04 10:31:35 +02:00
test_admin_server_config_materialize_section.py feat(config): expose materialize.lock_ttl_seconds in server-config 2026-05-04 18:52:54 +02:00
test_admin_server_config_placeholder.py test(admin): #160 RED tests for BQ test-connection + server-config placeholder 2026-05-04 10:31:35 +02:00
test_admin_server_config_renderer_depth.py feat(admin-ui): /admin/server-config known-fields registry + structured nested editor 2026-05-01 20:27:01 +02:00
test_admin_tables_tab_ui.py feat(admin-ui): /admin/tables per-connector tabs + Keboola materialized parity + form cleanup + Manage access deep link 2026-05-01 20:26:29 +02:00
test_admin_tables_ui_materialized.py feat(admin-ui): /admin/tables per-connector tabs + Keboola materialized parity + form cleanup + Manage access deep link 2026-05-01 20:26:29 +02:00
test_admin_tokens_ui.py feat(rbac): drop dataset_permissions + users.role + is_public; v19 migration (#150) 2026-04-30 22:02:16 +02:00
test_admin_unescape_shell_quoting.py Merge remote-tracking branch 'origin/main' into pr198-review 2026-05-06 11:35:45 +02:00
test_admin_unregister_cleanup.py chore(docs): replace stale da verbs and vendor-specific install paths 2026-05-04 21:22:19 +02:00
test_admin_user_capabilities_ui.py feat(rbac): drop dataset_permissions + users.role + is_public; v19 migration (#150) 2026-04-30 22:02:16 +02:00
test_admin_validator_backtick_relaxed_for_materialized.py tests: rename 'prj-grp' placeholder to 'my-project' for vendor-agnostic OSS 2026-05-04 20:38:47 +02:00
test_api.py feat(rbac): drop dataset_permissions + users.role + is_public; v19 migration (#150) 2026-04-30 22:02:16 +02:00
test_api_admin_materialized.py merge: pull #174 (BQ materialize view fix + concurrency, 0.33.0) into bootstrap branch 2026-05-04 20:53:00 +02:00
test_api_complete.py feat(rbac): drop dataset_permissions + users.role + is_public; v19 migration (#150) 2026-04-30 22:02:16 +02:00
test_api_query_guardrail.py feat(query): registry-gate full backtick BigQuery paths (#201) 2026-05-06 18:02:53 +02:00
test_api_query_quota.py fix(query): #168 review iter 2 — quota user_id parity + concurrent-slot 429 2026-05-04 13:38:31 +02:00
test_api_query_rbac_bq_path.py sec(query): #160 BQ_PATH catches quoted "bq" catalog token (Phase 3 review) 2026-05-04 10:31:35 +02:00
test_api_scripts.py feat(rbac): drop dataset_permissions + users.role + is_public; v19 migration (#150) 2026-04-30 22:02:16 +02:00
test_app_version.py feat(server): expose APP_VERSION + MIN_COMPAT_CLI_VERSION on /api/* response headers 2026-05-06 23:23:23 +02:00
test_auth_providers.py feat(rbac): drop dataset_permissions + users.role + is_public; v19 migration (#150) 2026-04-30 22:02:16 +02:00
test_auth_rate_limit.py security(auth): per-IP rate limit + last-admin guard (#165) 2026-05-02 21:08:33 +02:00
test_auth_scheduler_token.py fix(scheduler): HTTP marketplaces job + SCHEDULER_API_TOKEN shared secret (#127) 2026-04-29 11:44:00 +02:00
test_auto_profiling.py Add self-service data onboarding system 2026-03-09 14:25:37 +01:00
test_bigquery_auth.py feat(v2): claude-driven fetch primitives + 0.14.0 (#102) 2026-04-29 01:07:19 +02:00
test_bigquery_extractor.py refactor(bq): #160 remove legacy_wrap_views config knob (always-wrap) 2026-05-04 10:31:35 +02:00
test_bigquery_extractor_full.py feat(v2): claude-driven fetch primitives + 0.14.0 (#102) 2026-04-29 01:07:19 +02:00
test_bootstrap.py feat(rbac): drop dataset_permissions + users.role + is_public; v19 migration (#150) 2026-04-30 22:02:16 +02:00
test_bq_access.py fix(bq): map 'Response too large' to its own error class instead of generic bad_request 2026-05-06 13:09:31 +02:00
test_bq_cost_guardrail.py fix(bq-materialize): code-review follow-ups for d8a22996 2026-05-04 16:52:18 +02:00
test_bq_init_extract_skips.py feat(materialized): query_mode='materialized' for BigQuery + Keboola — admin SELECT → parquet → analyst 2026-05-01 20:25:56 +02:00
test_bq_materialize.py release: 0.40.0 — materialize_query writes _meta + inner view so master views appear 2026-05-06 16:04:58 +02:00
test_bq_materialize_concurrency.py fix(bq-materialize): TTL reclaim was dead code (Devin Review on extractor.py:166) 2026-05-04 22:36:56 +02:00
test_bq_materialize_query_wrapping.py fix(bq-materialize): wrap admin SQL in bigquery_query() so views work 2026-05-04 16:40:40 +02:00
test_bq_query_timeout.py fix(bigquery): apply bq_query_timeout_ms on every BQ-extension attach + surface silent failures 2026-05-06 11:24:14 +04:00
test_catalog_export.py chore(oss): isolate customer-specific deploy bits from scripts/grpn/ (#88, wave 1) (#94) 2026-04-27 20:24:34 +02:00
test_check_access_endpoint.py feat(caddy): file_server for parquet downloads — bypass uvicorn 2026-05-05 16:41:33 +02:00
test_claude_md_api.py feat(api,web,cli): /admin/workspace-prompt + /api/welcome restored + da analyst writes CLAUDE.md 2026-05-03 22:44:14 +02:00
test_claude_md_renderer.py fix(claude_md): RBAC-filter tables; align today with now (UTC) 2026-05-04 05:57:22 +02:00
test_claude_md_template_repo.py feat(db,repo,renderer): schema v23 + claude_md_template + ClaudeMd renderer 2026-05-03 22:43:56 +02:00
test_claude_sessions.py fix(push): read sessions from ~/.claude/projects/<encoded-cwd>/ 2026-05-04 20:29:59 +02:00
test_clean_install_integration.py test: clean-install integration suite (minimal/zero grants, force, pre-init) 2026-05-04 19:22:24 +02:00
test_cli.py chore(docs): replace stale da verbs and vendor-specific install paths 2026-05-04 21:22:19 +02:00
test_cli_admin.py release: 0.45.0 — easy-wins bundle (#84 #164 #177 #178 #203 #204) 2026-05-07 11:43:16 +02:00
test_cli_admin_materialized.py fix(admin): register-table real-world UX gaps for materialized BQ 2026-05-04 23:06:17 +02:00
test_cli_admin_metrics.py chore(docs): replace stale da verbs and vendor-specific install paths 2026-05-04 21:22:19 +02:00
test_cli_artifacts.py refactor(cli): hard-cutover env vars + config dir to AGNES_* 2026-05-04 16:35:44 +02:00
test_cli_auth.py refactor(cli): hard-cutover env vars + config dir to AGNES_* 2026-05-04 16:35:44 +02:00
test_cli_binary_rename.py feat(cli): rename binary from da to agnes (BREAKING) 2026-05-04 16:05:14 +02:00
test_cli_catalog.py refactor(cli): hard-cutover env vars + config dir to AGNES_* 2026-05-04 16:35:44 +02:00
test_cli_catalog_metrics.py chore(docs): replace stale da verbs and vendor-specific install paths 2026-05-04 21:22:19 +02:00
test_cli_diagnose.py refactor(cli): hard-cutover env vars + config dir to AGNES_* 2026-05-04 16:35:44 +02:00
test_cli_diagnose_system.py fix(tests): strip ANSI escapes from --help output before substring asserts 2026-05-04 19:43:47 +02:00
test_cli_disk_info.py refactor(cli): hard-cutover env vars + config dir to AGNES_* 2026-05-04 16:35:44 +02:00
test_cli_error_render.py fix: update legacy-string assertions in tests + onboarding template 2026-05-04 20:08:07 +02:00
test_cli_explore.py refactor(cli): hard-cutover env vars + config dir to AGNES_* 2026-05-04 16:35:44 +02:00
test_cli_init.py release: 0.45.0 — easy-wins bundle (#84 #164 #177 #178 #203 #204) 2026-05-07 11:43:16 +02:00
test_cli_pull.py fix(tests): strip ANSI escapes from --help output before substring asserts 2026-05-04 19:43:47 +02:00
test_cli_push.py fix(tests): strip ANSI escapes from --help output before substring asserts 2026-05-04 19:43:47 +02:00
test_cli_query.py fix(cli): bump --remote query timeout to 300s, add AGNES_QUERY_TIMEOUT 2026-05-05 16:40:54 +04:00
test_cli_query_render.py fix(post-merge): clean up stale da verbs introduced via #174 merge 2026-05-04 20:57:36 +02:00
test_cli_refresh_marketplace.py fix(refresh-marketplace): align manual-mode hint with hook JSON 2026-05-07 06:59:13 +02:00
test_cli_server.py refactor(cli): hard-cutover env vars + config dir to AGNES_* 2026-05-04 16:35:44 +02:00
test_cli_snapshot.py refactor(cli): hard-cutover env vars + config dir to AGNES_* 2026-05-04 16:35:44 +02:00
test_cli_snapshot_create.py fix(post-merge): clean up stale da verbs introduced via #174 merge 2026-05-04 20:57:36 +02:00
test_cli_status.py fix(tests): strip ANSI escapes from --help output before substring asserts 2026-05-04 19:43:47 +02:00
test_cli_store.py refactor(cli-store): pull/info → agnes admin store; add agnes store mine 2026-05-05 13:49:18 +02:00
test_cli_update_check.py feat(cli): add agnes self-upgrade with smoke test + rollback 2026-05-06 23:23:23 +02:00
test_client_version_check.py perf+test(cli): cache User-Agent at module scope; pin local==min boundary 2026-05-06 23:23:23 +02:00
test_column_metadata.py feat: add ColumnMetadataRepository with CRUD and proposal import 2026-04-10 19:41:53 +02:00
test_connector_kit_poc.py User management + PAT + CLI distribution + HTML auth redirect (#9 #10 #11 #12) (#28) 2026-04-22 14:24:28 +02:00
test_corporate_memory_collector.py test: add Block C services tests (68 tests across 6 files) 2026-04-12 11:11:48 +02:00
test_corporate_memory_page.py fix(ui): admin pending-review banner on /corporate-memory (#176) 2026-05-05 00:01:22 +02:00
test_corporate_memory_relations.py feat(admin): users/groups UI polish + SSO lock + v18 migration (#142) 2026-04-30 15:16:04 +02:00
test_corporate_memory_v1.py feat(memory): corporate memory v1+v1.5 + 0.15.0 (#72) 2026-04-29 07:16:22 +02:00
test_db.py feat(rbac): drop dataset_permissions + users.role + is_public; v19 migration (#150) 2026-04-30 22:02:16 +02:00
test_db_remote_attach_security.py fix(security): #81 Group A — orchestrator attach hardening (squashed) (#95) 2026-04-27 21:34:04 +02:00
test_db_schema_version.py Keboola cutover: native parquet path + sync correctness + auto-discover protection (#190) 2026-05-07 12:12:14 +02:00
test_diagnose_billing.py release: 0.45.0 — easy-wins bundle (#84 #164 #177 #178 #203 #204) 2026-05-07 11:43:16 +02:00
test_docker_compose.py fix(compose): drop corporate-memory + session-collector services (#176) 2026-05-04 23:59:44 +02:00
test_docker_full.py fix(tests): align docker-e2e health asserts with current /api/health shape 2026-05-03 11:21:19 +02:00
test_duckdb_manager.py chore(oss): isolate customer-specific deploy bits from scripts/grpn/ (#88, wave 1) (#94) 2026-04-27 20:24:34 +02:00
test_duckdb_panel.py feat(observability): request_id end-to-end + dev debug toolbar + centralized logging (#136) 2026-04-29 22:54:21 +02:00
test_e2e_api.py feat(rbac): drop dataset_permissions + users.role + is_public; v19 migration (#150) 2026-04-30 22:02:16 +02:00
test_e2e_corporate_memory.py feat(memory): corporate memory v1+v1.5 + 0.15.0 (#72) 2026-04-29 07:16:22 +02:00
test_e2e_docker.py fix(tests): drop stale 'healthy' from /api/health status assert 2026-05-03 15:40:41 +02:00
test_e2e_extract.py fix: use SCHEMA_VERSION constant in e2e migration test 2026-04-10 19:39:19 +02:00
test_extractor_identifier_validation.py fix(security): #81 Group D — extractor-side identifier validation (squashed) (#97) 2026-04-27 21:46:17 +02:00
test_fixtures_smoke.py test: clean-bootstrap fixtures (fastapi_test_server, test_pat, zero_grants_workspace) 2026-05-04 19:11:54 +02:00
test_generate_sample_data.py Add --format parquet using project's ParquetManager 2026-03-10 21:46:20 +01:00
test_google_group_prefix_sync.py feat(rbac): drop dataset_permissions + users.role + is_public; v19 migration (#150) 2026-04-30 22:02:16 +02:00
test_group_sync.py feat(auth): Google Workspace group prefix filter + system mapping (#131) 2026-04-29 14:08:04 +02:00
test_groups_mapped_email.py feat(rbac): drop dataset_permissions + users.role + is_public; v19 migration (#150) 2026-04-30 22:02:16 +02:00
test_health_schema_gate.py release: 0.45.0 — easy-wins bundle (#84 #164 #177 #178 #203 #204) 2026-05-07 11:43:16 +02:00
test_health_session_pipeline.py fix(health): session-pipeline staleness check (#176) 2026-05-05 00:04:28 +02:00
test_instance_config.py fix: address code review findings — duplicate fixture, JWT key length, async deprecation 2026-04-13 13:47:51 +02:00
test_instance_config_overlay.py fix(config): overlay-aware LLM consumers + env-ref resolution (#179 review) 2026-05-05 05:57:22 +02:00
test_jira_incremental.py test: add connector test suite (Block D) — 5 files, 58 tests 2026-04-12 11:12:50 +02:00
test_jira_service.py test: add missing coverage for web UI, Jira extract, instance config, and concurrent rebuild 2026-04-09 07:15:14 +02:00
test_jira_service_full.py fix(security): close Jira webhook fail-open + path traversal (#83) (#93) 2026-04-27 19:53:55 +02:00
test_jira_validation.py fix(security): close Jira webhook fail-open + path traversal (#83) (#93) 2026-04-27 19:53:55 +02:00
test_jira_webhooks.py feat(ci+tests): deploy safety audit — linting, rollback, smoke tests, 50+ new tests (#120) 2026-04-29 09:18:55 +02:00
test_journey_analyst.py test: add E2E journey tests (J1-J8) covering full user flows 2026-04-12 11:13:51 +02:00
test_journey_bootstrap_auth.py fix(security+ops) + release(0.12.1): #82 #85 #87 hardening + cut 0.12.1 (#104) 2026-04-28 19:57:30 +02:00
test_journey_hybrid.py test: add E2E journey tests (J1-J8) covering full user flows 2026-04-12 11:13:51 +02:00
test_journey_jira.py fix(security): close Jira webhook fail-open + path traversal (#83) (#93) 2026-04-27 19:53:55 +02:00
test_journey_memory.py test: add E2E journey tests (J1-J8) covering full user flows 2026-04-12 11:13:51 +02:00
test_journey_multisource.py test: add E2E journey tests (J1-J8) covering full user flows 2026-04-12 11:13:51 +02:00
test_journey_rbac.py feat(rbac): drop dataset_permissions + users.role + is_public; v19 migration (#150) 2026-04-30 22:02:16 +02:00
test_journey_sync_query.py fix(admin-api): keep source_type validator permissive when primary is 'local' (bootstrap) 2026-05-01 23:09:15 +02:00
test_keboola_access.py feat(materialized): query_mode='materialized' for BigQuery + Keboola — admin SELECT → parquet → analyst 2026-05-01 20:25:56 +02:00
test_keboola_extension_query_passthrough.py feat(materialized): query_mode='materialized' for BigQuery + Keboola — admin SELECT → parquet → analyst 2026-05-01 20:25:56 +02:00
test_keboola_extractor.py Keboola cutover: native parquet path + sync correctness + auto-discover protection (#190) 2026-05-07 12:12:14 +02:00
test_keboola_extractor_exit_codes.py Keboola cutover: native parquet path + sync correctness + auto-discover protection (#190) 2026-05-07 12:12:14 +02:00
test_keboola_extractor_full.py Keboola cutover: native parquet path + sync correctness + auto-discover protection (#190) 2026-05-07 12:12:14 +02:00
test_keboola_init_extract_skips.py feat(materialized): query_mode='materialized' for BigQuery + Keboola — admin SELECT → parquet → analyst 2026-05-01 20:25:56 +02:00
test_keboola_materialize.py Keboola cutover: native parquet path + sync correctness + auto-discover protection (#190) 2026-05-07 12:12:14 +02:00
test_keboola_materialized_e2e.py chore(docs): replace stale da verbs and vendor-specific install paths 2026-05-04 21:22:19 +02:00
test_keboola_storage_api.py Keboola cutover: native parquet path + sync correctness + auto-discover protection (#190) 2026-05-07 12:12:14 +02:00
test_legacy_strings_scan.py feat(admin): yellow banner for legacy CLI verbs in workspace-prompt override 2026-05-04 17:46:50 +02:00
test_lib_hooks.py test(hooks): pin v0.43.0 chained-entry → v0.44.0 two-entry upgrade path 2026-05-07 07:00:00 +02:00
test_lib_pull.py fix(pull): re-download parquet when file missing despite matching hash 2026-05-04 21:12:06 +02:00
test_live_bigquery.py test: add Docker E2E and live connector test files 2026-04-12 11:10:06 +02:00
test_live_jira.py test: add Docker E2E and live connector test files 2026-04-12 11:10:06 +02:00
test_live_keboola.py test: add Docker E2E and live connector test files 2026-04-12 11:10:06 +02:00
test_llm_connector.py fix(anthropic): strict json_schema (additionalProperties=false) + add /admin/scheduler-runs UI 2026-05-05 08:00:57 +02:00
test_llm_provider_env_fallback.py fix(setup): seed default ai: block + env-var fallback (#176) 2026-05-04 23:55:19 +02:00
test_llm_providers_full.py test: add connector test suite (Block D) — 5 files, 58 tests 2026-04-12 11:12:50 +02:00
test_logging_config.py feat(observability): request_id end-to-end + dev debug toolbar + centralized logging (#136) 2026-04-29 22:54:21 +02:00
test_marketplace.py feat(rbac+marketplace): RBAC v13 + Claude Code marketplace + #81/#83/#44 hardening 2026-04-28 14:25:04 +02:00
test_marketplace_filter.py fix(marketplace): use plugin.json name in synth marketplace.json (#133) 2026-04-29 19:25:57 +02:00
test_marketplace_filter_store.py feat(store): /store + /my-ai-stack — community marketplace + per-user composition 2026-05-05 02:53:49 +02:00
test_marketplace_server_git.py feat(rbac): drop dataset_permissions + users.role + is_public; v19 migration (#150) 2026-04-30 22:02:16 +02:00
test_marketplace_server_zip.py feat(rbac): drop dataset_permissions + users.role + is_public; v19 migration (#150) 2026-04-30 22:02:16 +02:00
test_materialized_e2e.py fix(bq-materialize): wrap admin SQL in bigquery_query() so views work 2026-05-04 16:40:40 +02:00
test_me_debug.py feat(rbac): drop dataset_permissions + users.role + is_public; v19 migration (#150) 2026-04-30 22:02:16 +02:00
test_memory_api.py feat(rbac): drop dataset_permissions + users.role + is_public; v19 migration (#150) 2026-04-30 22:02:16 +02:00
test_metadata_api.py feat(admin): #108 M1 — BigQuery table registration in UI + CLI (#119) 2026-04-29 13:18:31 +02:00
test_metrics.py fix: address code review — path injection, multi-table search, metrics import API, error handling 2026-04-10 19:56:00 +02:00
test_migration.py fix: replace os.environ direct assignment with monkeypatch.setenv in test fixtures 2026-04-09 07:11:36 +02:00
test_no_override_file.py fix(security+ops) + release(0.12.1): #82 #85 #87 hardening + cut 0.12.1 (#104) 2026-04-28 19:57:30 +02:00
test_openapi_snapshot.py feat: multi-instance deployment — all 14 must-have items from spec 2026-04-10 11:57:42 +02:00
test_openmetadata_client.py feat(scheduler): re-wire sync_schedule + script.schedule; tune via env; OpenMetadata TLS (#135) 2026-04-29 22:06:30 +02:00
test_openmetadata_enricher.py chore(oss): isolate customer-specific deploy bits from scripts/grpn/ (#88, wave 1) (#94) 2026-04-27 20:24:34 +02:00
test_openmetadata_transformer.py chore(oss): isolate customer-specific deploy bits from scripts/grpn/ (#88, wave 1) (#94) 2026-04-27 20:24:34 +02:00
test_orchestrator.py fix(0.41.0): orphan parquet skip in filesystem fallback (CI regression) 2026-05-06 17:06:20 +02:00
test_orchestrator_remote_attach_security.py feat(v2): claude-driven fetch primitives + 0.14.0 (#102) 2026-04-29 01:07:19 +02:00
test_orchestrator_sync_state_hash.py Keboola cutover: native parquet path + sync correctness + auto-discover protection (#190) 2026-05-07 12:12:14 +02:00
test_packaging.py fix(deps): promote anthropic + openai to core dependencies (#176) 2026-05-04 23:52:30 +02:00
test_password_flows.py feat(rbac): drop dataset_permissions + users.role + is_public; v19 migration (#150) 2026-04-30 22:02:16 +02:00
test_pat.py refactor(cli): hard-cutover env vars + config dir to AGNES_* 2026-05-04 16:35:44 +02:00
test_profiler.py Initial commit: OSS data distribution platform 2026-03-08 23:31:28 +01:00
test_pull_chunked.py fix: devil's advocate R3 — reap PID-suffixed leftovers from dead processes 2026-05-06 14:04:47 +02:00
test_pull_progress.py release: 0.45.0 — easy-wins bundle (#84 #164 #177 #178 #203 #204) 2026-05-07 11:43:16 +02:00
test_pull_shared_client.py perf(cli): persistent HTTP/2 client across pull invocation 2026-05-06 13:06:36 +02:00
test_query_bigquery_query_blocked.py test(query): #160 RED tests for guardrail+quota+RBAC+blocklist 2026-05-04 10:31:35 +02:00
test_query_bq_regex.py sec(query): #160 BQ_PATH catches quoted "bq" catalog token (Phase 3 review) 2026-05-04 10:31:35 +02:00
test_query_materialized_error_message.py chore(docs): replace stale da verbs and vendor-specific install paths 2026-05-04 21:22:19 +02:00
test_query_remote_rewrite.py fix: Devin Review #1 — apply backtick mask to wrapping rewriter 2026-05-06 21:06:21 +02:00
test_rbac.py feat(rbac): drop dataset_permissions + users.role + is_public; v19 migration (#150) 2026-04-30 22:02:16 +02:00
test_reader_smoke_matrix.py fix(tests): smoke matrix asserts no-traceback only (per-command rc varies) 2026-05-04 19:47:18 +02:00
test_remote_query.py fix(v2): #134 BigQuery cross-project errors return structured 502/400 + BqAccess facade (#138) 2026-04-30 10:11:20 +02:00
test_remote_query_error_details.py feat(cli): #160 shared structured error renderer for BQ-typed responses 2026-05-04 10:31:35 +02:00
test_repositories.py feat(rbac): drop dataset_permissions + users.role + is_public; v19 migration (#150) 2026-04-30 22:02:16 +02:00
test_request_id_middleware.py feat(observability): request_id end-to-end + dev debug toolbar + centralized logging (#136) 2026-04-29 22:54:21 +02:00
test_resource_types.py feat(rbac): drop dataset_permissions + users.role + is_public; v19 migration (#150) 2026-04-30 22:02:16 +02:00
test_router_ca_pem.py feat(setup): cross-platform TLS bootstrap + marketplace plugin install (#137) 2026-04-30 08:56:45 +02:00
test_run_due_scripts.py feat(scheduler): re-wire sync_schedule + script.schedule; tune via env; OpenMetadata TLS (#135) 2026-04-29 22:06:30 +02:00
test_run_materialized_pass_in_flight_skip.py Keboola cutover: native parquet path + sync correctness + auto-discover protection (#190) 2026-05-07 12:12:14 +02:00
test_scheduler.py Keboola cutover: native parquet path + sync correctness + auto-discover protection (#190) 2026-05-07 12:12:14 +02:00
test_scheduler_full.py test: add Block C services tests (68 tests across 6 files) 2026-04-12 11:11:48 +02:00
test_scheduler_sidecar.py feat(scheduler): re-wire sync_schedule + script.schedule; tune via env; OpenMetadata TLS (#135) 2026-04-29 22:06:30 +02:00
test_schema_v24_source_query_rewrite.py fix(schema-v24): raise on deferred migration so retry path actually runs (Devin Review on db.py:1757) 2026-05-04 23:11:34 +02:00
test_scripts_api.py feat(scheduler): re-wire sync_schedule + script.schedule; tune via env; OpenMetadata TLS (#135) 2026-04-29 22:06:30 +02:00
test_security.py feat(rbac): drop dataset_permissions + users.role + is_public; v19 migration (#150) 2026-04-30 22:02:16 +02:00
test_selective_gzip.py feat(web): rename /install → /setup; nav label 'Setup local agent' 2026-05-03 16:12:13 +02:00
test_self_upgrade.py feat(cli): add agnes self-upgrade with smoke test + rollback 2026-05-06 23:23:23 +02:00
test_session_collector.py fix(session-collector): argv-free run() helper, drop SystemExit footgun (Devin Review on #179) 2026-05-05 06:31:55 +02:00
test_settings_api.py feat(rbac): drop dataset_permissions + users.role + is_public; v19 migration (#150) 2026-04-30 22:02:16 +02:00
test_setup_ai_block.py fix(setup): seed default ai: block + env-var fallback (#176) 2026-05-04 23:55:19 +02:00
test_setup_hooks_template.py chore(docs): replace stale da verbs and vendor-specific install paths 2026-05-04 21:22:19 +02:00
test_setup_instructions.py feat(marketplace): clone-based plugin setup + auto-refresh SessionStart hook 2026-05-07 06:59:13 +02:00
test_setup_page_unified.py feat(marketplace): clone-based plugin setup + auto-refresh SessionStart hook 2026-05-07 06:59:13 +02:00
test_snapshot_meta.py feat(v2): claude-driven fetch primitives + 0.14.0 (#102) 2026-04-29 01:07:19 +02:00
test_sql_safe.py feat(v2): claude-driven fetch primitives + 0.14.0 (#102) 2026-04-29 01:07:19 +02:00
test_store_api.py refactor(cli-store): pull/info → agnes admin store; add agnes store mine 2026-05-05 13:49:18 +02:00
test_store_naming.py chore(store): genericize email examples in docstring + test 2026-05-05 05:48:32 +02:00
test_store_repositories.py feat(store): /store + /my-ai-stack — community marketplace + per-user composition 2026-05-05 02:53:49 +02:00
test_sync_filter.py Keboola cutover: native parquet path + sync correctness + auto-discover protection (#190) 2026-05-07 12:12:14 +02:00
test_sync_manifest.py feat(rbac): drop dataset_permissions + users.role + is_public; v19 migration (#150) 2026-04-30 22:02:16 +02:00
test_sync_trigger_keboola_materialized.py Keboola cutover: native parquet path + sync correctness + auto-discover protection (#190) 2026-05-07 12:12:14 +02:00
test_sync_trigger_materialized.py Keboola cutover: native parquet path + sync correctness + auto-discover protection (#190) 2026-05-07 12:12:14 +02:00
test_sync_trigger_singleton.py Keboola cutover: native parquet path + sync correctness + auto-discover protection (#190) 2026-05-07 12:12:14 +02:00
test_table_registry_find_by_bq_path.py feat(repo): #160 add find_by_bq_path lookup for direct bq.* RBAC enforcement 2026-05-04 10:31:35 +02:00
test_table_registry_source_query.py feat(materialized): query_mode='materialized' for BigQuery + Keboola — admin SELECT → parquet → analyst 2026-05-01 20:25:56 +02:00
test_tagger.py feat(memory): corporate memory v1+v1.5 + 0.15.0 (#72) 2026-04-29 07:16:22 +02:00
test_telegram_api.py test: add telegram API endpoint tests (verify, unlink, status) 2026-04-12 14:12:28 +02:00
test_telegram_bot.py fix: address code review findings — duplicate fixture, JWT key length, async deprecation 2026-04-13 13:47:51 +02:00
test_telegram_bot_runner.py release: 0.45.0 — easy-wins bundle (#84 #164 #177 #178 #203 #204) 2026-05-07 11:43:16 +02:00
test_telegram_storage.py release: 0.45.0 — easy-wins bundle (#84 #164 #177 #178 #203 #204) 2026-05-07 11:43:16 +02:00
test_tokens_bootstrap_scope.py test(tokens): tighten scope-default + add precedence + audit + reserved-key tests 2026-05-04 17:07:02 +02:00
test_toolbar_integration.py feat(web): rename /install → /setup; nav label 'Setup local agent' 2026-05-03 16:12:13 +02:00
test_upload_api.py test: add 132 API gap tests across 8 endpoint modules 2026-04-12 11:13:24 +02:00
test_user_management.py security(auth): per-IP rate limit + last-admin guard (#165) 2026-05-02 21:08:33 +02:00
test_users_sso_flag.py feat(rbac): drop dataset_permissions + users.role + is_public; v19 migration (#150) 2026-04-30 22:02:16 +02:00
test_v2_arrow.py feat(v2): claude-driven fetch primitives + 0.14.0 (#102) 2026-04-29 01:07:19 +02:00
test_v2_cache.py feat(v2): claude-driven fetch primitives + 0.14.0 (#102) 2026-04-29 01:07:19 +02:00
test_v2_catalog.py feat(rbac): drop dataset_permissions + users.role + is_public; v19 migration (#150) 2026-04-30 22:02:16 +02:00
test_v2_client.py feat(v2): claude-driven fetch primitives + 0.14.0 (#102) 2026-04-29 01:07:19 +02:00
test_v2_quota.py feat(v2): claude-driven fetch primitives + 0.14.0 (#102) 2026-04-29 01:07:19 +02:00
test_v2_sample.py perf: Tier 1 event-loop unblocking — async def → def on BQ-bound handlers 2026-05-05 17:44:08 +02:00
test_v2_scan.py perf: Tier 1 event-loop unblocking — async def → def on BQ-bound handlers 2026-05-05 17:44:08 +02:00
test_v2_scan_estimate.py perf: Tier 1 event-loop unblocking — async def → def on BQ-bound handlers 2026-05-05 17:44:08 +02:00
test_v2_schema.py perf: Tier 1 event-loop unblocking — async def → def on BQ-bound handlers 2026-05-05 17:44:08 +02:00
test_version_headers_middleware.py feat(server): expose APP_VERSION + MIN_COMPAT_CLI_VERSION on /api/* response headers 2026-05-06 23:23:23 +02:00
test_view_collision_detection.py fix: #81 Group C — view-name collision detection (schema v10, squashed) (#100) 2026-04-27 22:09:49 +02:00
test_web_ui.py fix(profile-sessions): tolerate stat() failures on individual jsonl (Devin Review on #179) 2026-05-05 09:53:06 +02:00
test_welcome_template_api.py refactor(welcome-template): drop role param; resolve plugins per-user unconditionally 2026-05-04 22:13:46 +02:00
test_welcome_template_migration.py feat(db): schema v15 — welcome_template singleton table 2026-05-03 16:10:48 +02:00
test_welcome_template_renderer.py refactor(welcome-template): drop role param; resolve plugins per-user unconditionally 2026-05-04 22:13:46 +02:00
test_welcome_template_repo.py feat(repo): WelcomeTemplateRepository singleton CRUD 2026-05-03 16:10:48 +02:00
test_where_validator.py feat(v2): claude-driven fetch primitives + 0.14.0 (#102) 2026-04-29 01:07:19 +02:00
test_ws_gateway.py test: add Block C services tests (68 tests across 6 files) 2026-04-12 11:11:48 +02:00