Skip to content

feat: flatmates matching/profiles enhancements and property search updates#15

Merged
saksham1991999 merged 5 commits into
mainfrom
feature/flatmates-search-updates
May 17, 2026
Merged

feat: flatmates matching/profiles enhancements and property search updates#15
saksham1991999 merged 5 commits into
mainfrom
feature/flatmates-search-updates

Conversation

@RaviSahu1520
Copy link
Copy Markdown
Collaborator

@RaviSahu1520 RaviSahu1520 commented May 16, 2026

Summary

  • Enhanced flatmates matching with improved query logic and N+1 fix
  • Added profile enhancements in the flatmates service
  • Updated property search with refined filtering logic
  • Import cleanup, proper enum usage, and improved logging per PR review feedback

Files Changed (6 files, +93 / -17)

  • \�pp/api/api_v1/endpoints/flatmates.py\ — endpoint updates
  • \�pp/services/flatmates/matching.py\ — matching logic improvements
  • \�pp/services/flatmates/profiles.py\ — profile enhancements
  • \�pp/services/property/search.py\ — search filter updates
  • \�pp/core/config.py\ — config adjustments
  • \�pp/services/flatmates/init.py\ — re-exports

Summary by cubic

Adds a GET /flatmates/outgoing-likes API and improves flatmates discovery by filtering blocked and already-swiped users in SQL. Also fixes N+1 queries, hardens property search parsing, tunes DB pool settings, and runs a startup migration to add floor_plan to image_category.

  • New Features

    • Added GET /flatmates/outgoing-likes with pagination and SQL-side block filtering (both directions).
    • Discovery excludes profiles you’ve swiped and anyone blocked, using SQL subqueries before pagination.
  • Bug Fixes

    • Fixed N+1 in flatmates matching via eager loading of related user/property data.
    • Property search: safer Property row mapping with deduped mapping lookup and float casts for score fields; avoids text filter when semantic search is active; debug logs on cast failures.
    • Startup migration at boot adds floor_plan to image_category if missing.
    • Consistent enum usage and minor import cleanup.
    • Increased DB pool size/overflow and adjusted timeouts/recycle to reduce contention.

Written for commit 45700be. Summary will update on new commits. Review in cubic

Summary by CodeRabbit

  • New Features

    • New API endpoint to retrieve a paginated list of sent likes.
    • Discovery now excludes profiles previously swiped on.
  • Improvements

    • Updated database connection pool configuration for better resource management.
    • Enhanced robustness of property search result parsing.

Review Change Stack

Greptile Summary

This PR pushes block filtering in list_outgoing_likes into the SQL WHERE clause (fixing the previously identified pagination truncation), fixes an N+1 by adding selectinload for related user/property data, pre-fetches the SQLAlchemy _mapping once per row in the property search loop, and introduces _apply_pending_migrations to add the floor_plan enum value at startup.

  • matching.py: Block subqueries are now applied before LIMIT/OFFSET, resolving the page-size shrinkage reported in the prior review. Eager loading with selectinload eliminates the N+1 on target-user and context-property relations.
  • search.py: Single upfront mapping fetch and isinstance guard tighten the row-resolution logic; non-Property rows are now correctly excluded rather than appended via a bare type cast.
  • lifespan.py: New _apply_pending_migrations runs DDL at startup; the DDL-in-transaction concern flagged in the prior review thread remains unaddressed.

Confidence Score: 4/5

The flatmates matching and property search changes are safe; the startup migration in lifespan.py carries a known risk where a DDL failure aborts the transaction and causes the commit to throw, potentially skipping scheduler startup.

The block-filter and N+1 fixes in matching.py are correct and address the prior review findings. The search.py row-mapping cleanup is a net improvement. The _apply_pending_migrations function wraps an ALTER TYPE … ADD VALUE DDL statement inside engine.begin(): if the DDL raises, the caught exception leaves the connection in an aborted-transaction state, and the subsequent commit by the context manager fails — this secondary exception escapes the function and is caught by the outer startup handler, which will skip _start_schedulers.

app/infrastructure/lifespan.py — the startup migration function needs attention due to the DDL-in-transaction behaviour.

Important Files Changed

Filename Overview
app/infrastructure/lifespan.py Adds _apply_pending_migrations that runs ALTER TYPE ... ADD VALUE DDL inside engine.begin() — this statement cannot execute in a transaction block on PostgreSQL < 12, and a DDL failure leaves the transaction in an aborted state before the context-manager commit (flagged in prior review threads).
app/services/flatmates/matching.py Block filtering in list_outgoing_likes correctly pushed to SQL WHERE clause, fixing the earlier pagination truncation issue; N+1 addressed with selectinload; already-matched likes still included in outgoing list (flagged in prior review).
app/services/property/search.py Eliminates redundant mapping fetch and moves properties.append inside the isinstance(prop, Property) guard; non-Property rows are now silently dropped without a trace log entry, making result-set size discrepancies harder to diagnose.

Sequence Diagram

sequenceDiagram
    participant App as FastAPI App
    participant LP as lifespan.py
    participant DB as PostgreSQL
    participant Sched as Schedulers

    App->>LP: startup
    LP->>LP: _initialize_cache()
    LP->>DB: "engine.begin() -> ALTER TYPE image_category ADD VALUE IF NOT EXISTS 'floor_plan'"
    alt DDL succeeds
        DB-->>LP: OK
        LP->>DB: COMMIT
    else DDL fails
        DB-->>LP: Exception (transaction aborted)
        LP->>LP: logger.warning (exception swallowed)
        LP->>DB: COMMIT (fails - aborted txn)
        DB-->>LP: commit error propagates
        LP-->>App: Exception escapes _apply_pending_migrations
    end
    LP->>Sched: _start_schedulers(app)
Loading

Reviews (4): Last reviewed commit: "merge: resolve conflicts with origin/mai..." | Re-trigger Greptile

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 16, 2026

📝 Walkthrough

Walkthrough

This PR adds the outgoing likes endpoint to retrieve profiles the current user has liked, filters discoverable profiles to exclude already-swiped users, hardens defensive parsing for computed property search fields, and adjusts database pool configuration parameters.

Changes

User Interactions and Infrastructure

Layer / File(s) Summary
Outgoing likes feature
app/services/flatmates/matching.py, app/services/flatmates/__init__.py, app/api/api_v1/endpoints/flatmates.py
list_outgoing_likes service queries UserSwipe records for liked targets, eagerly loads target user and context property, excludes blocked users, and returns swipe metadata. The function is re-exported through the flatmates module and exposed via a new GET /outgoing-likes endpoint with limit/offset pagination.
Discovery profile swipe exclusion
app/services/flatmates/profiles.py
list_discoverable_profiles now excludes users the requesting user has already swiped on by adding a UserSwipe subquery filter that checks target user IDs.
Database pool configuration adjustment
app/core/config.py
Connection pool DB_POOL_SIZE and DB_MAX_OVERFLOW increased to 5, DB_POOL_TIMEOUT increased to 15 seconds, and DB_POOL_RECYCLE reduced to 180 seconds.
Property search computed field parsing robustness
app/services/property/search.py
When query results include computed columns, the code now defensively extracts the Property instance from the row mapping, explicitly casts score fields to float, and logs debug information on type conversion errors instead of propagating exceptions.

Sequence Diagram

sequenceDiagram
  participant Client
  participant API as GET /outgoing-likes
  participant Service as list_outgoing_likes
  participant DB as AsyncSession
  Client->>API: limit, offset, auth
  API->>Service: user_id, limit, offset
  Service->>DB: query UserSwipe (liked)
  Service->>DB: load target User + context
  Service->>DB: fetch UserBlock records
  Service->>Service: filter out blocked targets
  Service->>API: list[dict] with peer + context
  API->>Client: list[IncomingLikeSummary]
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • 360ghar/backend#14: Introduces the same outgoing likes feature and swipe-exclusion filtering with identical core logic changes across matching.py, profiles.py, and the API endpoints.

Poem

🐰 A rabbit hops through swipes and likes so true,
Filters out the blocked ones, keeps the view fresh and new,
Pool connections grow while properties parse with care,
Each discovery refined—a feature beyond compare! 💕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 37.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes across all modified files: flatmates matching/profiles enhancements and property search updates.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/flatmates-search-updates

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@qodo-code-review
Copy link
Copy Markdown

Review Summary by Qodo

Flatmates outgoing likes, profile filtering, and search improvements

✨ Enhancement 🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Added outgoing likes endpoint and service function for flatmates
• Excluded already-swiped profiles from discoverable profiles list
• Improved property search result mapping with type safety and error handling
• Enhanced database pool configuration for better connection management
• Fixed N+1 query and import cleanup in matching service
Diagram
flowchart LR
  A["Flatmates Endpoint"] -->|"new route"| B["GET /outgoing-likes"]
  B -->|"calls"| C["list_outgoing_likes"]
  C -->|"filters"| D["UserSwipe + UserBlock"]
  E["list_discoverable_profiles"] -->|"excludes"| F["Already swiped users"]
  G["Property Search"] -->|"improved"| H["Result mapping & casting"]
  H -->|"error handling"| I["Type safety"]
  J["Database Config"] -->|"optimized"| K["Pool settings"]
Loading

Grey Divider

File Changes

1. app/api/api_v1/endpoints/flatmates.py ✨ Enhancement +11/-0

Added outgoing likes endpoint

• Added import for list_outgoing_likes function
• Created new GET endpoint /outgoing-likes with pagination support
• Endpoint returns list of profiles user has liked with same response model as incoming likes

app/api/api_v1/endpoints/flatmates.py


2. app/services/flatmates/__init__.py ✨ Enhancement +2/-0

Exported outgoing likes service function

• Added list_outgoing_likes to imports from matching module
• Exported list_outgoing_likes in __all__ for public API

app/services/flatmates/init.py


3. app/services/flatmates/matching.py ✨ Enhancement +50/-1

Implemented outgoing likes service function

• Added UserBlock import for blocking logic
• Implemented new list_outgoing_likes function that returns profiles user has liked
• Function filters out blocked users and users who blocked the current user
• Uses selectinload to prevent N+1 queries on target_user and context_property

app/services/flatmates/matching.py


View more (3)
4. app/services/flatmates/profiles.py ✨ Enhancement +9/-1

Exclude swiped profiles from discovery

• Added imports for SwipeTargetType enum and UserSwipe model
• Created subquery to exclude already-swiped profiles from discovery results
• Added filter to prevent showing profiles user has already interacted with

app/services/flatmates/profiles.py


5. app/services/property/search.py 🐞 Bug fix +17/-11

Improved property search result mapping

• Improved property result mapping with type checking before accessing attributes
• Added explicit float casting for distance_km, vector_distance, and relevance_score fields
• Added try-except error handling for type conversion failures with debug logging
• Enhanced robustness when handling complex query result structures

app/services/property/search.py


6. app/core/config.py ⚙️ Configuration changes +4/-4

Optimized database pool configuration

• Increased DB_POOL_SIZE from 3 to 5 for main HTTP/MCP request traffic
• Increased DB_MAX_OVERFLOW from 3 to 5 for better connection overflow handling
• Increased DB_POOL_TIMEOUT from 10 to 15 seconds for longer wait times
• Decreased DB_POOL_RECYCLE from 300 to 180 seconds for more frequent connection refresh

app/core/config.py


Grey Divider

ⓘ You are approaching your monthly quota for Qodo. Upgrade your plan

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown

qodo-code-review Bot commented May 16, 2026

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider


Action required

1. Pagination skips unblocked likes ✓ Resolved 🐞 Bug ≡ Correctness
Description
list_outgoing_likes applies limit/offset in SQL and only then filters out blocked users in
Python, so returned pages can be short/empty and can skip valid (unblocked) likes. This breaks
pagination correctness for /outgoing-likes whenever a user has many blocked relationships among
their outgoing swipes.
Code

app/services/flatmates/matching.py[R320-348]

+    stmt = (
+        select(UserSwipe)
+        .options(selectinload(UserSwipe.target_user), selectinload(UserSwipe.context_property))
+        .where(
+            UserSwipe.user_id == user_id,
+            UserSwipe.target_type == SwipeTargetType.user.value,
+            UserSwipe.is_liked.is_(True),
+            UserSwipe.target_user_id.is_not(None),
+        )
+        .order_by(UserSwipe.created_at.desc())
+        .limit(limit)
+        .offset(offset)
+    )
+    outgoing_swipes = list((await db.execute(stmt)).scalars().all())
+
+    blocked_ids_stmt = select(UserBlock.blocked_user_id).where(
+        UserBlock.blocker_user_id == user_id,
+    )
+    blocker_ids_stmt = select(UserBlock.blocker_user_id).where(
+        UserBlock.blocked_user_id == user_id,
+    )
+    blocked_ids = set((await db.execute(blocked_ids_stmt)).scalars().all())
+    blocker_ids = set((await db.execute(blocker_ids_stmt)).scalars().all())
+    excluded_ids = blocked_ids | blocker_ids
+
+    items: list[dict[str, Any]] = []
+    for swipe in outgoing_swipes:
+        if swipe.target_user is None or swipe.target_user_id in excluded_ids:
+            continue
Evidence
The function paginates the outgoing swipes query with .limit(limit).offset(offset) and only
afterwards removes blocked users via a Python continue, so excluded rows still count toward the
offset/limit window and can cause missing results across pages.

app/services/flatmates/matching.py[311-357]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`list_outgoing_likes()` paginates (`LIMIT/OFFSET`) before removing blocked users, which breaks pagination semantics (valid outgoing likes can be skipped or never reachable via paging).
## Issue Context
The SQL query fetches a page of `UserSwipe` rows, then `excluded_ids` (blocker/blocked) are applied as a Python-side filter.
## Fix Focus Areas
- Apply `excluded_ids` filtering inside the SQL query (preferred) so `LIMIT/OFFSET` operate on the final visible set.
- Alternatively, over-fetch (e.g., `limit * 2` loop) and trim after filtering, but SQL-side filtering is simpler and more correct.
### Concrete approach (SQL-side)
1. Compute `excluded_ids` first (existing two queries are fine) and if non-empty add `UserSwipe.target_user_id.notin_(excluded_ids)` to the `where()` clause.
2. Remove the Python-side `swipe.target_user_id in excluded_ids` check (keep the `swipe.target_user is None` guard).
## Fix Focus Areas (code references)
- app/services/flatmates/matching.py[311-357]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment thread app/services/flatmates/matching.py
Comment thread app/services/flatmates/matching.py
Comment thread app/services/flatmates/matching.py
Comment thread app/services/flatmates/profiles.py
Comment thread app/services/property/search.py Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
app/services/flatmates/matching.py (1)

320-348: ⚡ Quick win

Apply block exclusion in SQL before pagination.

limit/offset is applied before blocked users are removed, so clients can get sparse pages and shifted pagination. Push block filtering into the query so pagination is based on visible rows.

Proposed change
     stmt = (
         select(UserSwipe)
         .options(selectinload(UserSwipe.target_user), selectinload(UserSwipe.context_property))
+        .where(
+            UserSwipe.user_id == user_id,
+            UserSwipe.target_type == SwipeTargetType.user.value,
+            UserSwipe.is_liked.is_(True),
+            UserSwipe.target_user_id.is_not(None),
+            ~UserSwipe.target_user_id.in_(
+                select(UserBlock.blocked_user_id).where(UserBlock.blocker_user_id == user_id)
+            ),
+            ~UserSwipe.target_user_id.in_(
+                select(UserBlock.blocker_user_id).where(UserBlock.blocked_user_id == user_id)
+            ),
+        )
-        .where(
-            UserSwipe.user_id == user_id,
-            UserSwipe.target_type == SwipeTargetType.user.value,
-            UserSwipe.is_liked.is_(True),
-            UserSwipe.target_user_id.is_not(None),
-        )
         .order_by(UserSwipe.created_at.desc())
         .limit(limit)
         .offset(offset)
     )
     outgoing_swipes = list((await db.execute(stmt)).scalars().all())
-
-    blocked_ids_stmt = select(UserBlock.blocked_user_id).where(
-        UserBlock.blocker_user_id == user_id,
-    )
-    blocker_ids_stmt = select(UserBlock.blocker_user_id).where(
-        UserBlock.blocked_user_id == user_id,
-    )
-    blocked_ids = set((await db.execute(blocked_ids_stmt)).scalars().all())
-    blocker_ids = set((await db.execute(blocker_ids_stmt)).scalars().all())
-    excluded_ids = blocked_ids | blocker_ids
@@
     items: list[dict[str, Any]] = []
     for swipe in outgoing_swipes:
-        if swipe.target_user is None or swipe.target_user_id in excluded_ids:
+        if swipe.target_user is None:
             continue
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/services/flatmates/matching.py` around lines 320 - 348, The query
currently paginates outgoing_swipes then filters out blocked users in Python,
which breaks pagination; change the select(UserSwipe) stmt so it excludes
blocked/blocker users in SQL by adding WHERE conditions that target_user_id NOT
IN (select UserBlock.blocked_user_id where blocker_user_id == user_id) and
target_user_id NOT IN (select UserBlock.blocker_user_id where blocked_user_id ==
user_id) or equivalent NOT EXISTS subqueries; keep the selectinload options and
limit/offset on this filtered stmt, then remove the post-query excluded_ids
filtering loop (the for loop should assume swipe.target_user is not None and
target_user_id already filtered).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/services/property/search.py`:
- Around line 609-610: The code currently guards appending by truthiness (if
prop) which can allow non-Property values into the properties list and later
break PropertySchema.model_validate; change the condition to only append when
the extracted value is an instance of the Property class (use isinstance(prop,
Property)) so only concrete Property objects are appended to properties, leaving
other fallback results out.
- Around line 599-607: The Property model instance is being assigned computed
fields (distance_km, vector_distance, relevance_score) coming from row._mapping
but mypy raises attr-defined errors; update the three assignment statements that
set prop.distance_km, prop.vector_distance, and prop.relevance_score to append
the mypy suppression comment "# type: ignore[attr-defined]" to each assignment
so static checking is satisfied (these fields are validated later by
PropertySchema.model_validate(prop)); locate these assignments within the try
block that reads mapping = row._mapping and the subsequent checks for
"distance_km", "vector_distance", and "relevance_score".

---

Nitpick comments:
In `@app/services/flatmates/matching.py`:
- Around line 320-348: The query currently paginates outgoing_swipes then
filters out blocked users in Python, which breaks pagination; change the
select(UserSwipe) stmt so it excludes blocked/blocker users in SQL by adding
WHERE conditions that target_user_id NOT IN (select UserBlock.blocked_user_id
where blocker_user_id == user_id) and target_user_id NOT IN (select
UserBlock.blocker_user_id where blocked_user_id == user_id) or equivalent NOT
EXISTS subqueries; keep the selectinload options and limit/offset on this
filtered stmt, then remove the post-query excluded_ids filtering loop (the for
loop should assume swipe.target_user is not None and target_user_id already
filtered).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: eaf761ec-a76c-46be-96a5-64e0fee5b4e1

📥 Commits

Reviewing files that changed from the base of the PR and between 9f18ca1 and 55112a8.

📒 Files selected for processing (6)
  • app/api/api_v1/endpoints/flatmates.py
  • app/core/config.py
  • app/services/flatmates/__init__.py
  • app/services/flatmates/matching.py
  • app/services/flatmates/profiles.py
  • app/services/property/search.py

Comment thread app/services/property/search.py
Comment thread app/services/property/search.py Outdated
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 6 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="app/services/flatmates/matching.py">

<violation number="1" location="app/services/flatmates/matching.py:327">
P2: Filter blocked users in the SQL query before applying `limit/offset`; post-pagination filtering causes short pages and inconsistent pagination.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
Re-trigger cubic

Comment thread app/services/flatmates/matching.py
@qodo-code-review
Copy link
Copy Markdown

CI Feedback 🧐

A test triggered by this PR failed. Here is an AI-generated analysis of the failure:

Action: test

Failed stage: Run tests [❌]

Failed test name: tests/api/test_blog_endpoints.py::TestBlogPostEndpoints::test_get_blog_post

Failure summary:

The GitHub Action failed because the test run exited with code 1 due to multiple test
failures/errors and an unmet coverage threshold:
- Coverage gate failed: total coverage was ~44.90%
(reported as TOTAL ... 45%), which is below --fail-under=90 (ERROR: Coverage failure: total of 45 is
less than fail-under=90, FAIL Required test coverage of 90% not reached).
- Pytest had 36 failed, 2
errors (and many passes), so the suite did not succeed even aside from coverage.
- Key setup errors:

- tests/pm/test_authz.py:18 and tests/pm/test_rent.py:14 errored during setup because fixture
test_db was not found (E fixture 'test_db' not found), indicating fixture rename/removal or missing
import/plugin registration.
- Representative failing tests and root causes shown in the log:
-
tests/api/test_blog_endpoints.py::TestBlogPostEndpoints::test_get_blog_post failed because the
endpoint returned 404 instead of 200 (assert 404 == 200).
- Booking cancel endpoint error in
app/api/api_v1/endpoints/bookings.py:167: AttributeError: Mock object has no attribute
'property_id', implying a mocked booking object is missing required attributes used by the handler.

- Property details endpoint error in app/api/api_v1/endpoints/properties.py:350: AttributeError:
'dict' object has no attribute 'property_type', implying code expects an object with attributes but
receives a dict.
- tests/e2e/test_pm_lifecycle_flow.py:34 failed with NameError: name 'Decimal' is
not defined (missing import of Decimal).
-
tests/unit/services/test_property_service.py::TestCreateProperty::test_create_property_success
failed in app/services/property/crud.py:161 because a MagicMock was awaited (TypeError: object
MagicMock can't be used in 'await' expression), meaning an async dependency was mocked with a
non-async mock.
-
tests/unit/services/test_property_service.py::TestDeleteProperty::test_delete_property_success
failed in app/services/property/crud.py:380 due to ModuleNotFoundError: No module named
'app.models.visits' (broken import path/module removed).
- Config default mismatch:
tests/unit/core/test_config.py::TestSettings::test_default_cache_settings expected
settings.CACHE_DISK_DIR == /tmp/ghar360_cache but got ./cache.
Overall, the workflow failed because
the test suite contains numerous regressions (missing fixtures, incorrect mocks, broken imports, API
behavior mismatches) and the repository does not meet the required coverage threshold of 90%.

Relevant error logs:
1:  ##[group]Runner Image Provisioner
2:  Hosted Compute Agent
...

351:  #6 0.333 Get:6 http://deb.debian.org/debian-security bullseye-security/main amd64 Packages [455 kB]
352:  #6 0.420 Get:7 http://deb.debian.org/debian bullseye-updates/main amd64 Packages [18.8 kB]
353:  #6 0.476 Get:8 http://apt.postgresql.org/pub/repos/apt bullseye-pgdg/main amd64 Packages [547 kB]
354:  #6 0.485 Get:9 http://apt.postgresql.org/pub/repos/apt bullseye-pgdg/15 amd64 Packages [6,585 B]
355:  #6 1.245 Fetched 9,421 kB in 1s (8,443 kB/s)
356:  #6 1.245 Reading package lists...
357:  #6 1.621 Reading package lists...
358:  #6 2.008 Building dependency tree...
359:  #6 2.106 Reading state information...
360:  #6 2.213 The following additional packages will be installed:
361:  #6 2.213   binutils binutils-common binutils-x86-64-linux-gnu bzip2 clang-16 cpp cpp-10
362:  #6 2.213   dpkg-dev g++ g++-10 gcc gcc-10 git-man icu-devtools lib32gcc-s1 lib32stdc++6
363:  #6 2.213   libasan6 libatomic1 libbinutils libc-dev-bin libc6 libc6-dev libc6-i386
364:  #6 2.213   libcc1-0 libclang-common-13-dev libclang-common-16-dev libclang-cpp13
365:  #6 2.213   libclang-cpp16 libclang1-13 libclang1-16 libcrypt-dev libctf-nobfd0 libctf0
366:  #6 2.213   libcurl4 libdpkg-perl liberror-perl libffi-dev libgc1 libgcc-10-dev libgomp1
367:  #6 2.213   libicu-dev libicu67 libisl23 libitm1 libllvm16 liblsan0 libmpc3 libmpdec3
...

384:  #6 2.215   diffutils-doc python3-doc python3-tk python3-venv python3-setuptools
385:  #6 2.215   python-pygments-doc ttf-bitstream-vera python3.9-venv python3.9-doc
386:  #6 2.215   binfmt-support
387:  #6 2.215 Recommended packages:
388:  #6 2.215   llvm-13-dev fakeroot libalgorithm-merge-perl ssh-client manpages
389:  #6 2.215   manpages-dev libc-devtools libnss-nis libnss-nisplus libclang-rt-16-dev
390:  #6 2.215   libfile-fcntllock-perl liblocale-gettext-perl libgpm2 binfmt-support
391:  #6 2.215   binfmt-support | systemd
392:  #6 2.521 The following NEW packages will be installed:
393:  #6 2.521   binutils binutils-common binutils-x86-64-linux-gnu build-essential bzip2
394:  #6 2.521   clang-13 clang-16 cpp cpp-10 dpkg-dev g++ g++-10 gcc gcc-10 git git-man
395:  #6 2.521   icu-devtools lib32gcc-s1 lib32stdc++6 libasan6 libatomic1 libbinutils
396:  #6 2.521   libc-dev-bin libc6-dev libc6-i386 libcc1-0 libclang-common-13-dev
397:  #6 2.521   libclang-common-16-dev libclang-cpp13 libclang-cpp16 libclang1-13
398:  #6 2.521   libclang1-16 libcrypt-dev libctf-nobfd0 libctf0 libcurl4 libdpkg-perl
399:  #6 2.521   liberror-perl libffi-dev libgc1 libgcc-10-dev libgomp1 libicu-dev libisl23
400:  #6 2.522   libitm1 libllvm16 liblsan0 libmpc3 libmpdec3 libncurses-dev libncurses6
...

468:  #6 2.999 Get:55 http://deb.debian.org/debian-security bullseye-security/main amd64 libc6-i386 amd64 2.31-13+deb11u13 [2,618 kB]
469:  #6 3.009 Get:56 http://deb.debian.org/debian bullseye/main amd64 lib32gcc-s1 amd64 10.2.1-6 [49.4 kB]
470:  #6 3.009 Get:57 http://deb.debian.org/debian bullseye/main amd64 lib32stdc++6 amd64 10.2.1-6 [510 kB]
471:  #6 3.012 Get:58 http://deb.debian.org/debian bullseye/main amd64 libclang-common-13-dev amd64 1:13.0.1-6~deb11u1 [5,602 kB]
472:  #6 3.040 Get:59 http://deb.debian.org/debian bullseye/main amd64 llvm-13-linker-tools amd64 1:13.0.1-6~deb11u1 [1,253 kB]
473:  #6 3.047 Get:60 http://deb.debian.org/debian bullseye/main amd64 libclang1-13 amd64 1:13.0.1-6~deb11u1 [6,187 kB]
474:  #6 3.078 Get:61 http://deb.debian.org/debian bullseye/main amd64 clang-13 amd64 1:13.0.1-6~deb11u1 [123 kB]
475:  #6 3.089 Get:62 http://deb.debian.org/debian-security bullseye-security/main amd64 libicu67 amd64 67.1-7+deb11u1 [8,624 kB]
476:  #6 3.118 Get:63 http://deb.debian.org/debian-security bullseye-security/main amd64 libxml2 amd64 2.9.10+dfsg-6.7+deb11u9 [694 kB]
477:  #6 3.121 Get:64 http://deb.debian.org/debian bullseye/main amd64 libllvm16 amd64 1:16.0.6-15~deb11u2 [23.0 MB]
478:  #6 3.240 Get:65 http://deb.debian.org/debian bullseye/main amd64 libclang-cpp16 amd64 1:16.0.6-15~deb11u2 [11.5 MB]
479:  #6 3.297 Get:66 http://deb.debian.org/debian bullseye/main amd64 libclang-common-16-dev all 1:16.0.6-15~deb11u2 [683 kB]
480:  #6 3.301 Get:67 http://deb.debian.org/debian bullseye/main amd64 llvm-16-linker-tools amd64 1:16.0.6-15~deb11u2 [1,258 kB]
481:  #6 3.308 Get:68 http://deb.debian.org/debian bullseye/main amd64 libclang1-16 amd64 1:16.0.6-15~deb11u2 [6,575 kB]
482:  #6 3.341 Get:69 http://deb.debian.org/debian bullseye/main amd64 clang-16 amd64 1:16.0.6-15~deb11u2 [137 kB]
483:  #6 3.342 Get:70 http://deb.debian.org/debian bullseye/main amd64 liberror-perl all 0.17029-1 [31.0 kB]
484:  #6 3.343 Get:71 http://deb.debian.org/debian-security bullseye-security/main amd64 git-man all 1:2.30.2-1+deb11u5 [1,831 kB]
...

814:  #6 16.48 Selecting previously unselected package libclang-cpp16.
815:  #6 16.48 Preparing to unpack .../51-libclang-cpp16_1%3a16.0.6-15~deb11u2_amd64.deb ...
816:  #6 16.49 Unpacking libclang-cpp16 (1:16.0.6-15~deb11u2) ...
817:  #6 17.42 Selecting previously unselected package libclang-common-16-dev.
818:  #6 17.42 Preparing to unpack .../52-libclang-common-16-dev_1%3a16.0.6-15~deb11u2_all.deb ...
819:  #6 17.42 Unpacking libclang-common-16-dev (1:16.0.6-15~deb11u2) ...
820:  #6 17.51 Selecting previously unselected package llvm-16-linker-tools.
821:  #6 17.51 Preparing to unpack .../53-llvm-16-linker-tools_1%3a16.0.6-15~deb11u2_amd64.deb ...
822:  #6 17.51 Unpacking llvm-16-linker-tools (1:16.0.6-15~deb11u2) ...
823:  #6 17.63 Selecting previously unselected package libclang1-16.
824:  #6 17.63 Preparing to unpack .../54-libclang1-16_1%3a16.0.6-15~deb11u2_amd64.deb ...
825:  #6 17.63 Unpacking libclang1-16 (1:16.0.6-15~deb11u2) ...
826:  #6 18.08 Selecting previously unselected package clang-16.
827:  #6 18.08 Preparing to unpack .../55-clang-16_1%3a16.0.6-15~deb11u2_amd64.deb ...
828:  #6 18.09 Unpacking clang-16 (1:16.0.6-15~deb11u2) ...
829:  #6 18.11 Selecting previously unselected package liberror-perl.
830:  #6 18.11 Preparing to unpack .../56-liberror-perl_0.17029-1_all.deb ...
831:  #6 18.11 Unpacking liberror-perl (0.17029-1) ...
832:  #6 18.13 Selecting previously unselected package git-man.
...

904:  #6 26.03 Preparing to unpack .../81-postgresql-server-dev-15_15.18-1.pgdg11+1_amd64.deb ...
905:  #6 26.03 Unpacking postgresql-server-dev-15 (15.18-1.pgdg11+1) ...
906:  #6 26.21 Setting up media-types (4.0.0) ...
907:  #6 26.22 Setting up libz3-dev:amd64 (4.8.10-1) ...
908:  #6 26.22 Setting up libicu67:amd64 (67.1-7+deb11u1) ...
909:  #6 26.22 Setting up libyaml-0-2:amd64 (0.2.2-1) ...
910:  #6 26.22 Setting up binutils-common:amd64 (2.35.2-2) ...
911:  #6 26.23 Setting up libpq5:amd64 (18.4-1.pgdg11+1) ...
912:  #6 26.23 Setting up linux-libc-dev:amd64 (5.10.251-5) ...
913:  #6 26.23 Setting up libctf-nobfd0:amd64 (2.35.2-2) ...
914:  #6 26.23 Setting up libgomp1:amd64 (10.2.1-6) ...
915:  #6 26.24 Setting up bzip2 (1.0.8-4) ...
916:  #6 26.24 Setting up libffi-dev:amd64 (3.3-6) ...
917:  #6 26.24 Setting up libasan6:amd64 (10.2.1-6) ...
918:  #6 26.24 Setting up llvm-13-linker-tools (1:13.0.1-6~deb11u1) ...
919:  #6 26.25 Setting up liberror-perl (0.17029-1) ...
920:  #6 26.25 Setting up libclang1-13 (1:13.0.1-6~deb11u1) ...
...

1000:  #6 28.39 You are in 'detached HEAD' state. You can look around, make experimental
1001:  #6 28.39 changes and commit them, and you can discard any commits you make in this
1002:  #6 28.39 state without impacting any branches by switching back to a branch.
1003:  #6 28.39 
1004:  #6 28.39 If you want to create a new branch to retain commits you create, you may
1005:  #6 28.39 do so (now or later) by using -c with the switch command. Example:
1006:  #6 28.39 
1007:  #6 28.39   git switch -c <new-branch-name>
1008:  #6 28.39 
1009:  #6 28.39 Or undo this operation with:
1010:  #6 28.39 
1011:  #6 28.39   git switch -
1012:  #6 28.39 
1013:  #6 28.39 Turn off this advice by setting config variable advice.detachedHead to false
1014:  #6 28.39 
1015:  #6 28.44 gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wcast-function-type -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fno-omit-frame-pointer -march=native -ftree-vectorize -fassociative-math -fno-signed-zeros -fno-trapping-math -fPIC -I. -I./ -I/usr/include/postgresql/15/server -I/usr/include/postgresql/internal  -Wdate-time -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -I/usr/include/libxml2   -c -o src/bitutils.o src/bitutils.c
1016:  #6 28.65 gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wcast-function-type -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fno-omit-frame-pointer -march=native -ftree-vectorize -fassociative-math -fno-signed-zeros -fno-trapping-math -fPIC -I. -I./ -I/usr/include/postgresql/15/server -I/usr/include/postgresql/internal  -Wdate-time -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -I/usr/include/libxml2   -c -o src/bitvec.o src/bitvec.c
1017:  #6 28.70 gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wcast-function-type -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fno-omit-frame-pointer -march=native -ftree-vectorize -fassociative-math -fno-signed-zeros -fno-trapping-math -fPIC -I. -I./ -I/usr/include/postgresql/15/server -I/usr/include/postgresql/internal  -Wdate-time -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -I/usr/include/libxml2   -c -o src/halfutils.o src/halfutils.c
1018:  #6 28.95 gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wcast-function-type -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fno-omit-frame-pointer -march=native -ftree-vectorize -fassociative-math -fno-signed-zeros -fno-trapping-math -fPIC -I. -I./ -I/usr/include/postgresql/15/server -I/usr/include/postgresql/internal  -Wdate-time -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -I/usr/include/libxml2   -c -o src/halfvec.o src/halfvec.c
1019:  #6 29.42 gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wcast-function-type -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fno-omit-frame-pointer -march=native -ftree-vectorize -fassociative-math -fno-signed-zeros -fno-trapping-math -fPIC -I. -I./ -I/usr/include/postgresql/15/server -I/usr/include/postgresql/internal  -Wdate-time -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -I/usr/include/libxml2   -c -o src/hnsw.o src/hnsw.c
1020:  #6 29.53 gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wcast-function-type -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fno-omit-frame-pointer -march=native -ftree-vectorize -fassociative-math -fno-signed-zeros -fno-trapping-math -fPIC -I. -I./ -I/usr/include/postgresql/15/server -I/usr/include/postgresql/internal  -Wdate-time -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -I/usr/include/libxml2   -c -o src/hnswbuild.o src/hnswbuild.c
1021:  #6 29.79 gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wcast-function-type -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fno-omit-frame-pointer -march=native -ftree-vectorize -fassociative-math -fno-signed-zeros -fno-trapping-math -fPIC -I. -I./ -I/usr/include/postgresql/15/server -I/usr/include/postgresql/internal  -Wdate-time -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -I/usr/include/libxml2   -c -o src/hnswinsert.o src/hnswinsert.c
1022:  #6 29.99 gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wcast-function-type -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fno-omit-frame-pointer -march=native -ftree-vectorize -fassociative-math -fno-signed-zeros -fno-trapping-math -fPIC -I. -I./ -I/usr/include/postgresql/15/server -I/usr/include/postgresql/internal  -Wdate-time -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -I/usr/include/libxml2   -c -o src/hnswscan.o src/hnswscan.c
1023:  #6 30.09 gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wcast-function-type -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fno-omit-frame-pointer -march=native -ftree-vectorize -fassociative-math -fno-signed-zeros -fno-trapping-math -fPIC -I. -I./ -I/usr/include/postgresql/15/server -I/usr/include/postgresql/internal  -Wdate-time -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -I/usr/include/libxml2   -c -o src/hnswutils.o src/hnswutils.c
1024:  #6 30.74 gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wcast-function-type -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fno-omit-frame-pointer -march=native -ftree-vectorize -fassociative-math -fno-signed-zeros -fno-trapping-math -fPIC -I. -I./ -I/usr/include/postgresql/15/server -I/usr/include/postgresql/internal  -Wdate-time -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -I/usr/include/libxml2   -c -o src/hnswvacuum.o src/hnswvacuum.c
1025:  #6 30.95 gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wcast-function-type -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fno-omit-frame-pointer -march=native -ftree-vectorize -fassociative-math -fno-signed-zeros -fno-trapping-math -fPIC -I. -I./ -I/usr/include/postgresql/15/server -I/usr/include/postgresql/internal  -Wdate-time -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -I/usr/include/libxml2   -c -o src/ivfbuild.o src/ivfbuild.c
1026:  #6 31.19 gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wcast-function-type -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fno-omit-frame-pointer -march=native -ftree-vectorize -fassociative-math -fno-signed-zeros -fno-trapping-math -fPIC -I. -I./ -I/usr/include/postgresql/15/server -I/usr/include/postgresql/internal  -Wdate-time -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -I/usr/include/libxml2   -c -o src/ivfflat.o src/ivfflat.c
1027:  #6 31.30 gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wcast-function-type -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fno-omit-frame-pointer -march=native -ftree-vectorize -fassociative-math -fno-signed-zeros -fno-trapping-math -fPIC -I. -I./ -I/usr/include/postgresql/15/server -I/usr/include/postgresql/internal  -Wdate-time -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -I/usr/include/libxml2   -c -o src/ivfinsert.o src/ivfinsert.c
1028:  #6 31.40 gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wcast-function-type -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fno-omit-frame-pointer -march=native -ftree-vectorize -fassociative-math -fno-signed-zeros -fno-trapping-math -fPIC -I. -I./ -I/usr/include/postgresql/15/server -I/usr/include/postgresql/internal  -Wdate-time -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -I/usr/include/libxml2   -c -o src/ivfkmeans.o src/ivfkmeans.c
1029:  #6 31.84 gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wcast-function-type -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fno-omit-frame-pointer -march=native -ftree-vectorize -fassociative-math -fno-signed-zeros -fno-trapping-math -fPIC -I. -I./ -I/usr/include/postgresql/15/server -I/usr/include/postgresql/internal  -Wdate-time -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -I/usr/include/libxml2   -c -o src/ivfscan.o src/ivfscan.c
1030:  #6 31.98 gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wcast-function-type -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fno-omit-frame-pointer -march=native -ftree-vectorize -fassociative-math -fno-signed-zeros -fno-trapping-math -fPIC -I. -I./ -I/usr/include/postgresql/15/server -I/usr/include/postgresql/internal  -Wdate-time -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -I/usr/include/libxml2   -c -o src/ivfutils.o src/ivfutils.c
1031:  #6 32.26 gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wcast-function-type -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fno-omit-frame-pointer -march=native -ftree-vectorize -fassociative-math -fno-signed-zeros -fno-trapping-math -fPIC -I. -I./ -I/usr/include/postgresql/15/server -I/usr/include/postgresql/internal  -Wdate-time -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -I/usr/include/libxml2   -c -o src/ivfvacuum.o src/ivfvacuum.c
1032:  #6 32.36 gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wcast-function-type -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fno-omit-frame-pointer -march=native -ftree-vectorize -fassociative-math -fno-signed-zeros -fno-trapping-math -fPIC -I. -I./ -I/usr/include/postgresql/15/server -I/usr/include/postgresql/internal  -Wdate-time -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -I/usr/include/libxml2   -c -o src/sparsevec.o src/sparsevec.c
1033:  #6 32.83 gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wcast-function-type -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fno-omit-frame-pointer -march=native -ftree-vectorize -fassociative-math -fno-signed-zeros -fno-trapping-math -fPIC -I. -I./ -I/usr/include/postgresql/15/server -I/usr/include/postgresql/internal  -Wdate-time -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -I/usr/include/libxml2   -c -o src/vector.o src/vector.c
1034:  #6 33.44 gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wcast-function-type -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fno-omit-frame-pointer -march=native -ftree-vectorize -fassociative-math -fno-signed-zeros -fno-trapping-math -fPIC -shared -o vector.so src/bitutils.o src/bitvec.o src/halfutils.o src/halfvec.o src/hnsw.o src/hnswbuild.o src/hnswinsert.o src/hnswscan.o src/hnswutils.o src/hnswvacuum.o src/ivfbuild.o src/ivfflat.o src/ivfinsert.o src/ivfkmeans.o src/ivfscan.o src/ivfutils.o src/ivfvacuum.o src/sparsevec.o src/vector.o -L/usr/lib/x86_64-linux-gnu  -Wl,-z,relro -Wl,-z,now -L/usr/lib/llvm-13/lib  -Wl,--as-needed  
1035:  #6 33.47 cp sql/vector.sql sql/vector--0.7.0.sql
...

1104:  #6 37.54 /usr/bin/install -c -m 644 src/ivfscan.bc '/usr/lib/postgresql/15/lib/bitcode'/vector/src/
1105:  #6 37.54 /usr/bin/install -c -m 644 src/ivfutils.bc '/usr/lib/postgresql/15/lib/bitcode'/vector/src/
1106:  #6 37.54 /usr/bin/install -c -m 644 src/ivfvacuum.bc '/usr/lib/postgresql/15/lib/bitcode'/vector/src/
1107:  #6 37.55 /usr/bin/install -c -m 644 src/sparsevec.bc '/usr/lib/postgresql/15/lib/bitcode'/vector/src/
1108:  #6 37.55 /usr/bin/install -c -m 644 src/vector.bc '/usr/lib/postgresql/15/lib/bitcode'/vector/src/
1109:  #6 37.55 cd '/usr/lib/postgresql/15/lib/bitcode' && /usr/lib/llvm-13/bin/llvm-lto -thinlto -thinlto-action=thinlink -o vector.index.bc vector/src/bitutils.bc vector/src/bitvec.bc vector/src/halfutils.bc vector/src/halfvec.bc vector/src/hnsw.bc vector/src/hnswbuild.bc vector/src/hnswinsert.bc vector/src/hnswscan.bc vector/src/hnswutils.bc vector/src/hnswvacuum.bc vector/src/ivfbuild.bc vector/src/ivfflat.bc vector/src/ivfinsert.bc vector/src/ivfkmeans.bc vector/src/ivfscan.bc vector/src/ivfutils.bc vector/src/ivfvacuum.bc vector/src/sparsevec.bc vector/src/vector.bc
1110:  #6 37.58 Reading package lists...
1111:  #6 37.99 Building dependency tree...
1112:  #6 38.11 Reading state information...
1113:  #6 38.20 The following packages were automatically installed and are no longer required:
1114:  #6 38.20   binutils binutils-common binutils-x86-64-linux-gnu bzip2 clang-16 cpp cpp-10
1115:  #6 38.20   dpkg-dev g++ g++-10 gcc gcc-10 git-man icu-devtools lib32gcc-s1 lib32stdc++6
1116:  #6 38.20   libasan6 libatomic1 libbinutils libc-dev-bin libc6-dev libc6-i386 libcc1-0
1117:  #6 38.20   libclang-common-13-dev libclang-common-16-dev libclang-cpp13 libclang-cpp16
1118:  #6 38.20   libclang1-13 libclang1-16 libcrypt-dev libctf-nobfd0 libctf0 libcurl4
1119:  #6 38.20   libdpkg-perl liberror-perl libffi-dev libgc1 libgcc-10-dev libgomp1
1120:  #6 38.20   libicu-dev libisl23 libitm1 libllvm16 liblsan0 libmpc3 libmpdec3
...

1155:  #6 38.37 Removing build-essential (12.9) ...
1156:  #6 38.38 Removing clang-13 (1:13.0.1-6~deb11u1) ...
1157:  #6 38.39 Removing git (1:2.30.2-1+deb11u5) ...
1158:  #6 38.45 Removing llvm-13 (1:13.0.1-6~deb11u1) ...
1159:  #6 38.47 Removing postgresql-server-dev-15 (15.18-1.pgdg11+1) ...
1160:  #6 38.52 dpkg: warning: while removing postgresql-server-dev-15, directory '/usr/include/postgresql/15/server/extension' not empty so not removed
1161:  #6 38.55 Reading package lists...
1162:  #6 38.98 Building dependency tree...
1163:  #6 39.09 Reading state information...
1164:  #6 39.19 The following packages will be REMOVED:
1165:  #6 39.19   binutils binutils-common binutils-x86-64-linux-gnu bzip2 clang-16 cpp cpp-10
1166:  #6 39.19   dpkg-dev g++ g++-10 gcc gcc-10 git-man icu-devtools lib32gcc-s1 lib32stdc++6
1167:  #6 39.19   libasan6 libatomic1 libbinutils libc-dev-bin libc6-dev libc6-i386 libcc1-0
1168:  #6 39.19   libclang-common-13-dev libclang-common-16-dev libclang-cpp13 libclang-cpp16
1169:  #6 39.19   libclang1-13 libclang1-16 libcrypt-dev libctf-nobfd0 libctf0 libcurl4
1170:  #6 39.19   libdpkg-perl liberror-perl libffi-dev libgc1 libgcc-10-dev libgomp1
1171:  #6 39.19   libicu-dev libisl23 libitm1 libllvm16 liblsan0 libmpc3 libmpdec3
...

1224:  #6 39.82 Removing libatomic1:amd64 (10.2.1-6) ...
1225:  #6 39.83 Removing libncurses-dev:amd64 (6.2+20201114-2+deb11u2) ...
1226:  #6 39.85 Removing libc6-dev:amd64 (2.31-13+deb11u13) ...
1227:  #6 39.88 Removing libc-dev-bin (2.31-13+deb11u13) ...
1228:  #6 39.89 Removing libc6-i386 (2.31-13+deb11u13) ...
1229:  #6 39.92 Removing libcc1-0:amd64 (10.2.1-6) ...
1230:  #6 39.93 Removing libclang-common-16-dev (1:16.0.6-15~deb11u2) ...
1231:  #6 39.95 Removing libclang-cpp13 (1:13.0.1-6~deb11u1) ...
1232:  #6 39.97 Removing libclang-cpp16 (1:16.0.6-15~deb11u2) ...
1233:  #6 39.98 Removing libclang1-13 (1:13.0.1-6~deb11u1) ...
1234:  #6 39.99 Removing libclang1-16 (1:16.0.6-15~deb11u2) ...
1235:  #6 40.01 Removing libcrypt-dev:amd64 (1:4.4.18-4) ...
1236:  #6 40.02 Removing llvm-16 (1:16.0.6-15~deb11u2) ...
1237:  #6 40.04 Removing libcurl4:amd64 (7.74.0-1.3+deb11u16) ...
1238:  #6 40.05 Removing libdpkg-perl (1.20.13) ...
1239:  #6 40.08 Removing liberror-perl (0.17029-1) ...
1240:  #6 40.09 Removing libffi-dev:amd64 (3.3-6) ...
...

1301:  �[36;1m  -e POSTGRES_PASSWORD=test_password \�[0m
1302:  �[36;1m  -e POSTGRES_DB=test_db \�[0m
1303:  �[36;1m  -p 5432:5432 \�[0m
1304:  �[36;1m  test-postgres�[0m
1305:  �[36;1m�[0m
1306:  �[36;1m# Wait for PostgreSQL to accept connections FROM THE HOST�[0m
1307:  �[36;1mecho "Waiting for PostgreSQL to accept host connections..."�[0m
1308:  �[36;1mfor i in {1..30}; do�[0m
1309:  �[36;1m  if pg_isready -h localhost -p 5432 -U test_user; then�[0m
1310:  �[36;1m    echo "PostgreSQL is ready and accepting host connections"�[0m
1311:  �[36;1m    exit 0�[0m
1312:  �[36;1m  fi�[0m
1313:  �[36;1m  echo "Waiting for PostgreSQL... ($i/30)"�[0m
1314:  �[36;1m  sleep 2�[0m
1315:  �[36;1mdone�[0m
1316:  �[36;1mecho "ERROR: PostgreSQL failed to become ready"�[0m
1317:  �[36;1mdocker logs test-postgres�[0m
...

1743:  tests/api/test_agent_endpoints.py::TestUpdateAgentAvailabilityEndpoint::test_update_availability PASSED [  1%]
1744:  tests/api/test_agent_endpoints.py::TestUpdateAgentAvailabilityEndpoint::test_update_availability_not_found PASSED [  1%]
1745:  tests/api/test_agent_endpoints.py::TestGetAgentMeEndpoint::test_get_agent_profile PASSED [  2%]
1746:  tests/api/test_amenity_endpoints.py::TestListAmenitiesEndpoint::test_list_amenities PASSED [  2%]
1747:  tests/api/test_amenity_endpoints.py::TestListAmenitiesEndpoint::test_list_amenities_empty PASSED [  2%]
1748:  tests/api/test_auth_endpoints.py::test_legacy_auth_endpoint_returns_not_found[/api/v1/auth/login/-payload0] PASSED [  2%]
1749:  tests/api/test_auth_endpoints.py::test_legacy_auth_endpoint_returns_not_found[/api/v1/auth/register/-payload1] PASSED [  2%]
1750:  tests/api/test_auth_endpoints.py::test_legacy_auth_endpoint_returns_not_found[/api/v1/auth/otp/request-payload2] PASSED [  2%]
1751:  tests/api/test_auth_endpoints.py::test_legacy_auth_endpoint_returns_not_found[/api/v1/auth/otp/verify-payload3] PASSED [  2%]
1752:  tests/api/test_auth_endpoints.py::test_legacy_auth_endpoint_returns_not_found[/api/v1/auth/refresh-payload4] PASSED [  2%]
1753:  tests/api/test_auth_endpoints.py::test_legacy_auth_endpoint_returns_not_found[/api/v1/auth/logout-payload5] PASSED [  2%]
1754:  tests/api/test_auth_endpoints.py::test_legacy_auth_endpoint_returns_not_found[/api/v1/auth/forgot-password-payload6] PASSED [  2%]
1755:  tests/api/test_auth_endpoints.py::test_legacy_auth_endpoint_returns_not_found[/api/v1/auth/verify-payload7] PASSED [  2%]
1756:  tests/api/test_blog_endpoints.py::TestBlogPostEndpoints::test_list_blog_posts PASSED [  2%]
1757:  tests/api/test_blog_endpoints.py::TestBlogPostEndpoints::test_list_blog_posts_with_filters PASSED [  2%]
1758:  tests/api/test_blog_endpoints.py::TestBlogPostEndpoints::test_list_blog_posts_returns_503_for_transient_db_error PASSED [  2%]
1759:  tests/api/test_blog_endpoints.py::TestBlogPostEndpoints::test_get_blog_post FAILED [  3%]
1760:  tests/api/test_blog_endpoints.py::TestBlogPostEndpoints::test_get_blog_post_not_found PASSED [  3%]
...

1834:  tests/api/test_oauth_endpoints.py::TestTokenResponseResource::test_token_response_omits_resource_when_absent PASSED [  8%]
1835:  tests/api/test_oauth_endpoints.py::TestTokenResponseResource::test_refresh_token_response_includes_resource PASSED [  8%]
1836:  tests/api/test_oauth_endpoints.py::TestWellKnownEndpoints::test_protected_resource_metadata_root PASSED [  8%]
1837:  tests/api/test_oauth_endpoints.py::TestWellKnownEndpoints::test_protected_resource_metadata_mcp PASSED [  8%]
1838:  tests/api/test_oauth_endpoints.py::TestWellKnownEndpoints::test_authorization_server_metadata_root PASSED [  8%]
1839:  tests/api/test_oauth_endpoints.py::TestWellKnownEndpoints::test_authorization_server_metadata_mcp_oauth PASSED [  8%]
1840:  tests/api/test_oauth_endpoints.py::TestWellKnownEndpoints::test_root_and_mcp_oauth_metadata_are_consistent PASSED [  8%]
1841:  tests/api/test_property_endpoints.py::TestCreateProperty::test_create_property_success PASSED [  8%]
1842:  tests/api/test_property_endpoints.py::TestCreateProperty::test_create_pg_property_rejects_non_rent_purpose PASSED [  9%]
1843:  tests/api/test_property_endpoints.py::TestCreateProperty::test_create_property_unauthenticated PASSED [  9%]
1844:  tests/api/test_property_endpoints.py::TestListProperties::test_list_properties_public PASSED [  9%]
1845:  tests/api/test_property_endpoints.py::TestListProperties::test_list_properties_with_filters PASSED [  9%]
1846:  tests/api/test_property_endpoints.py::TestListProperties::test_list_properties_with_location PASSED [  9%]
1847:  tests/api/test_property_endpoints.py::TestListProperties::test_list_properties_with_ids_filter PASSED [  9%]
1848:  tests/api/test_property_endpoints.py::TestListProperties::test_list_properties_with_listing_preference_filters PASSED [  9%]
1849:  tests/api/test_property_endpoints.py::TestListProperties::test_list_properties_returns_503_for_transient_db_error PASSED [  9%]
1850:  tests/api/test_property_endpoints.py::TestRecommendations::test_recommendations_returns_503_for_transient_db_error PASSED [  9%]
1851:  tests/api/test_property_endpoints.py::TestGetProperty::test_get_property_success PASSED [  9%]
...

1913:  tests/api/test_vastu_endpoints.py::TestVastuAnalyzeEndpoint::test_analyze_with_glm_provider PASSED [ 14%]
1914:  tests/api/test_vastu_endpoints.py::TestVastuHealthEndpoint::test_vastu_health_check PASSED [ 14%]
1915:  tests/api/test_visit_endpoints.py::TestCreateVisitEndpoint::test_create_visit_success PASSED [ 14%]
1916:  tests/api/test_visit_endpoints.py::TestCreateVisitEndpoint::test_create_visit_unauthorized PASSED [ 14%]
1917:  tests/api/test_visit_endpoints.py::TestGetVisitEndpoint::test_get_visit_success PASSED [ 14%]
1918:  tests/api/test_visit_endpoints.py::TestGetVisitEndpoint::test_get_visit_not_found PASSED [ 14%]
1919:  tests/api/test_visit_endpoints.py::TestGetUserVisitsEndpoint::test_get_user_visits PASSED [ 14%]
1920:  tests/api/test_visit_endpoints.py::TestGetUpcomingVisitsEndpoint::test_get_upcoming_visits PASSED [ 14%]
1921:  tests/api/test_visit_endpoints.py::TestGetPastVisitsEndpoint::test_get_past_visits PASSED [ 14%]
1922:  tests/api/test_visit_endpoints.py::TestCancelVisitEndpoint::test_cancel_visit_success PASSED [ 14%]
1923:  tests/api/test_visit_endpoints.py::TestCancelVisitEndpoint::test_cancel_visit_not_found PASSED [ 14%]
1924:  tests/api/test_visit_endpoints.py::TestRescheduleVisitEndpoint::test_reschedule_visit_success PASSED [ 14%]
1925:  tests/api/test_visit_endpoints.py::TestMarkVisitCompletedEndpoint::test_mark_visit_completed PASSED [ 15%]
1926:  tests/api/test_visit_endpoints.py::TestMarkVisitCompletedEndpoint::test_mark_visit_completed_forbidden PASSED [ 15%]
1927:  tests/e2e/test_booking_complete_flow.py::TestBookingCompleteFlow::test_search_check_book_flow PASSED [ 15%]
1928:  tests/e2e/test_booking_complete_flow.py::TestBookingManagementFlow::test_view_and_cancel_booking FAILED [ 15%]
1929:  tests/e2e/test_booking_complete_flow.py::TestBookingListingFlow::test_list_all_bookings PASSED [ 15%]
1930:  tests/e2e/test_booking_complete_flow.py::TestBookingListingFlow::test_list_upcoming_bookings PASSED [ 15%]
1931:  tests/e2e/test_booking_complete_flow.py::TestBookingStatusTransitions::test_confirm_booking PASSED [ 15%]
1932:  tests/e2e/test_booking_complete_flow.py::TestBookingStatusTransitions::test_check_in_booking PASSED [ 15%]
1933:  tests/e2e/test_pm_lifecycle_flow.py::TestPMLifecycleFlow::test_lease_to_rent_to_maintenance_flow FAILED [ 15%]
1934:  tests/e2e/test_property_listing_flow.py::TestPropertyListingFlow::test_create_and_list_property PASSED [ 15%]
1935:  tests/e2e/test_property_listing_flow.py::TestPropertySearchFlow::test_search_properties_by_location PASSED [ 15%]
1936:  tests/e2e/test_property_listing_flow.py::TestPropertySearchFlow::test_search_properties_by_filters PASSED [ 15%]
1937:  tests/e2e/test_property_listing_flow.py::TestPropertyViewFlow::test_view_property_details FAILED [ 15%]
1938:  tests/e2e/test_property_listing_flow.py::TestPropertyViewFlow::test_view_increments_counter FAILED [ 15%]
1939:  tests/e2e/test_property_listing_flow.py::TestPropertySwipeFlow::test_swipe_like_and_view_likes PASSED [ 16%]
...

1953:  tests/integration/test_full_text_search.py::TestSearchFilters::test_search_with_price_filter PASSED [ 17%]
1954:  tests/integration/test_full_text_search.py::TestSearchFilters::test_search_with_property_type_filter PASSED [ 17%]
1955:  tests/integration/test_geospatial_queries.py::TestPostGISRadiusSearch::test_properties_within_radius PASSED [ 17%]
1956:  tests/integration/test_geospatial_queries.py::TestPostGISRadiusSearch::test_properties_sorted_by_distance PASSED [ 17%]
1957:  tests/integration/test_geospatial_queries.py::TestPostGISRadiusSearch::test_no_properties_outside_radius PASSED [ 17%]
1958:  tests/integration/test_geospatial_queries.py::TestPostGISBoundingBox::test_properties_in_bounding_box PASSED [ 17%]
1959:  tests/integration/test_geospatial_queries.py::TestPostGISDistanceCalculation::test_st_distance_calculation PASSED [ 17%]
1960:  tests/integration/test_geospatial_queries.py::TestPostGISDistanceCalculation::test_st_dwithin_filter PASSED [ 17%]
1961:  tests/integration/test_geospatial_queries.py::TestLocationIndexing::test_spatial_index_exists PASSED [ 17%]
1962:  tests/integration/test_property_search.py::TestPropertySearchCombinations::test_city_and_purpose_filter PASSED [ 17%]
1963:  tests/integration/test_property_search.py::TestPropertySearchCombinations::test_city_and_type_filter PASSED [ 17%]
1964:  tests/integration/test_property_search.py::TestPropertySearchCombinations::test_purpose_and_type_filter PASSED [ 17%]
1965:  tests/integration/test_property_search.py::TestPropertySearchCombinations::test_price_range_filter PASSED [ 17%]
1966:  tests/integration/test_property_search.py::TestPropertySearchCombinations::test_bedroom_filter PASSED [ 17%]
1967:  tests/integration/test_property_search.py::TestPropertySearchCombinations::test_empty_results PASSED [ 18%]
1968:  tests/integration/test_property_search.py::TestPropertySearchCombinations::test_pagination FAILED [ 18%]
1969:  tests/integration/test_property_search.py::TestPropertySearchCombinations::test_special_listing_filters PASSED [ 18%]
1970:  tests/mcp/test_admin_mcp_server.py::TestAgentPropertyTools::test_agent_properties_list_authenticated FAILED [ 18%]
1971:  tests/mcp/test_admin_mcp_server.py::TestAgentPropertyTools::test_agent_properties_list_unauthorized FAILED [ 18%]
1972:  tests/mcp/test_admin_mcp_server.py::TestAgentLeaseTools::test_agent_leases_list FAILED [ 18%]
1973:  tests/mcp/test_admin_mcp_server.py::TestAgentLeaseTools::test_agent_leases_create FAILED [ 18%]
1974:  tests/mcp/test_admin_mcp_server.py::TestAgentRentTools::test_agent_rent_list_due FAILED [ 18%]
1975:  tests/mcp/test_admin_mcp_server.py::TestAgentRentTools::test_agent_rent_record_payment FAILED [ 18%]
1976:  tests/mcp/test_admin_mcp_server.py::TestAgentMaintenanceTools::test_agent_maintenance_list FAILED [ 18%]
1977:  tests/mcp/test_admin_mcp_server.py::TestAgentMaintenanceTools::test_agent_maintenance_update_status FAILED [ 18%]
1978:  tests/mcp/test_admin_mcp_server.py::TestAgentDashboardTools::test_agent_dashboard_overview FAILED [ 18%]
1979:  tests/mcp/test_admin_mcp_server.py::TestAdminTools::test_admin_system_status PASSED [ 18%]
1980:  tests/mcp/test_admin_mcp_server.py::TestAdminTools::test_admin_system_status_non_admin PASSED [ 18%]
1981:  tests/mcp/test_admin_mcp_server.py::TestAgentBookingTools::test_agent_bookings_list_all FAILED [ 19%]
1982:  tests/mcp/test_admin_mcp_server.py::TestAgentBookingTools::test_agent_bookings_update_status FAILED [ 19%]
1983:  tests/mcp/test_mcp_integration.py::TestMCPServerIntegration::test_mcp_endpoint_mounted PASSED [ 19%]
...

1990:  tests/mcp/test_mcp_integration.py::TestMCPToolsIntegration::test_discovery_amenities PASSED [ 19%]
1991:  tests/mcp/test_mcp_integration.py::TestMCPAuthIntegration::test_token_verifier_valid_oauth_token PASSED [ 19%]
1992:  tests/mcp/test_mcp_integration.py::TestMCPAuthIntegration::test_token_verifier_invalid_token_format PASSED [ 19%]
1993:  tests/mcp/test_mcp_integration.py::TestMCPAuthIntegration::test_token_verifier_expired_token PASSED [ 19%]
1994:  tests/mcp/test_mcp_integration.py::TestMCPAuthIntegration::test_token_verifier_audience_mismatch PASSED [ 19%]
1995:  tests/mcp/test_mcp_integration.py::TestMCPAuthIntegration::test_token_verifier_missing_scope PASSED [ 20%]
1996:  tests/mcp/test_mcp_integration.py::TestMCPOAuthTokenStore::test_store_and_retrieve_auth_code PASSED [ 20%]
1997:  tests/mcp/test_mcp_integration.py::TestMCPOAuthTokenStore::test_store_and_retrieve_tokens PASSED [ 20%]
1998:  tests/mcp/test_mcp_integration.py::TestMCPOAuthTokenStore::test_revoke_token PASSED [ 20%]
1999:  tests/mcp/test_mcp_integration.py::TestMCPOAuthTokenStore::test_refresh_token_rotation PASSED [ 20%]
2000:  tests/mcp/test_mcp_integration.py::TestMCPWidgetIntegration::test_widget_registration PASSED [ 20%]
2001:  tests/mcp/test_mcp_integration.py::TestMCPWidgetIntegration::test_widget_tool_mapping PASSED [ 20%]
2002:  tests/mcp/test_mcp_integration.py::TestMCPWidgetIntegration::test_get_widget_for_tool PASSED [ 20%]
2003:  tests/mcp/test_mcp_integration.py::TestMCPWidgetIntegration::test_all_discovery_tools_have_widgets PASSED [ 20%]
2004:  tests/mcp/test_mcp_integration.py::TestMCPEndToEnd::test_complete_property_workflow PASSED [ 20%]
2005:  tests/mcp/test_mcp_integration.py::TestMCPEndToEnd::test_agent_property_management_workflow FAILED [ 20%]
2006:  tests/mcp/test_mcp_integration.py::TestMCPEndToEnd::test_owner_property_workflow PASSED [ 20%]
2007:  tests/mcp/test_mcp_integration.py::TestMCPEndToEnd::test_tenant_workflow PASSED [ 20%]
2008:  tests/mcp/test_user_mcp_server.py::TestOwnerPropertyTools::test_owner_properties_list_authenticated FAILED [ 20%]
2009:  tests/mcp/test_user_mcp_server.py::TestOwnerPropertyTools::test_owner_properties_list_unauthenticated PASSED [ 21%]
2010:  tests/mcp/test_user_mcp_server.py::TestOwnerPropertyTools::test_owner_properties_list_www_authenticate_meta PASSED [ 21%]
2011:  tests/mcp/test_user_mcp_server.py::TestOwnerPropertyTools::test_tools_list_includes_security_schemes_and_template PASSED [ 21%]
2012:  tests/mcp/test_user_mcp_server.py::TestOwnerPropertyCreate::test_create_property_success FAILED [ 21%]
2013:  tests/mcp/test_user_mcp_server.py::TestTenantTools::test_tenant_lease_current PASSED [ 21%]
2014:  tests/mcp/test_user_mcp_server.py::TestTenantTools::test_tenant_rent_history PASSED [ 21%]
2015:  tests/mcp/test_user_mcp_server.py::TestBookingTools::test_bookings_list FAILED [ 21%]
2016:  tests/mcp/test_user_mcp_server.py::TestBookingTools::test_bookings_check_availability FAILED [ 21%]
2017:  tests/mcp/test_user_mcp_server.py::TestMCPErrorResponses::test_unauthorized_response PASSED [ 21%]
2018:  tests/mcp/test_user_mcp_server.py::TestMCPErrorResponses::test_not_found_response PASSED [ 21%]
2019:  tests/mcp/test_user_mcp_server.py::TestMCPErrorResponses::test_invalid_input_response PASSED [ 21%]
2020:  tests/middleware/test_rate_limit_middleware.py::TestRateLimitMiddleware::test_middleware_initialization PASSED [ 21%]
...

2033:  tests/middleware/test_security_middleware.py::TestXSSProtection::test_xss_protection_header PASSED [ 22%]
2034:  tests/middleware/test_security_middleware.py::TestContentTypeOptions::test_x_content_type_options_header PASSED [ 22%]
2035:  tests/middleware/test_security_middleware.py::TestFrameOptions::test_x_frame_options_header PASSED [ 22%]
2036:  tests/middleware/test_security_middleware.py::TestContentSecurityPolicy::test_csp_header PASSED [ 23%]
2037:  tests/middleware/test_security_middleware.py::TestHSTS::test_hsts_header_in_production PASSED [ 23%]
2038:  tests/middleware/test_trailing_slash_middleware.py::TestMCPMountPaths::test_mcp_mount_paths_do_not_include_sse PASSED [ 23%]
2039:  tests/middleware/test_trailing_slash_middleware.py::TestTrailingSlashAddition::test_adds_trailing_slash_for_mcp PASSED [ 23%]
2040:  tests/middleware/test_trailing_slash_middleware.py::TestTrailingSlashAddition::test_adds_trailing_slash_for_mcp_admin PASSED [ 23%]
2041:  tests/middleware/test_trailing_slash_middleware.py::TestTrailingSlashAddition::test_mcp_subpaths_unchanged PASSED [ 23%]
2042:  tests/middleware/test_trailing_slash_middleware.py::TestTrailingSlashStripping::test_strips_trailing_slash_for_api_routes PASSED [ 23%]
2043:  tests/middleware/test_trailing_slash_middleware.py::TestTrailingSlashStripping::test_preserves_api_root PASSED [ 23%]
2044:  tests/middleware/test_trailing_slash_middleware.py::TestTrailingSlashStripping::test_no_trailing_slash_unchanged PASSED [ 23%]
2045:  tests/middleware/test_trailing_slash_middleware.py::TestTrailingSlashStripping::test_deep_api_path_stripped PASSED [ 23%]
2046:  tests/middleware/test_trailing_slash_middleware.py::TestNonHTTPScopes::test_websocket_scope_unchanged PASSED [ 23%]
2047:  tests/middleware/test_trailing_slash_middleware.py::TestNonHTTPScopes::test_lifespan_scope_unchanged PASSED [ 23%]
2048:  tests/pm/test_authz.py::test_pm_authz_owner_agent_tenant_property_access ERROR [ 23%]
2049:  tests/pm/test_rent.py::test_generate_rent_charges_idempotent_and_payment_status ERROR [ 23%]
2050:  tests/unit/api/test_agent_chat_endpoint.py::test_agent_chat_persists_widget_and_assistant_messages PASSED [ 24%]
2051:  tests/unit/api/test_agent_chat_endpoint.py::test_agent_chat_persists_empty_assistant_when_only_widget_event PASSED [ 24%]
2052:  tests/unit/api/test_agent_chat_endpoint.py::test_agent_chat_ignores_malformed_widget_event PASSED [ 24%]
2053:  tests/unit/api/test_agent_chat_endpoint.py::test_agent_chat_stream_error_emits_error_event PASSED [ 24%]
2054:  tests/unit/api/test_agent_chat_endpoint.py::test_list_conversations_delegates_to_store_and_respects_pagination PASSED [ 24%]
...

2077:  tests/unit/api/test_flatmates_admin.py::TestModerateListingReject::test_reject_sets_listing_rejected PASSED [ 25%]
2078:  tests/unit/api/test_flatmates_admin.py::TestModerateListingReject::test_reject_emits_sse_event PASSED [ 26%]
2079:  tests/unit/api/test_flatmates_admin.py::TestModerateListingRequestEdit::test_request_edit_sets_pending_review PASSED [ 26%]
2080:  tests/unit/api/test_flatmates_admin.py::TestModerateListingNotFound::test_not_found_raises_404 PASSED [ 26%]
2081:  tests/unit/api/test_flatmates_admin.py::TestModerateListingApprovalBoost::test_first_approval_grants_boost PASSED [ 26%]
2082:  tests/unit/api/test_flatmates_admin.py::TestModerateReportDismiss::test_dismiss_sets_status PASSED [ 26%]
2083:  tests/unit/api/test_flatmates_admin.py::TestModerateReportWarnUser::test_warn_user_sets_status_actioned PASSED [ 26%]
2084:  tests/unit/api/test_flatmates_admin.py::TestModerateReportSuspendUser::test_suspend_user_deactivates_account PASSED [ 26%]
2085:  tests/unit/api/test_flatmates_admin.py::TestModerateReportEscalate::test_escalate_sets_status_reviewed PASSED [ 26%]
2086:  tests/unit/api/test_flatmates_admin.py::TestModerateReportNotFound::test_not_found_raises_404 PASSED [ 26%]
2087:  tests/unit/api/test_flatmates_admin.py::TestGetPendingListingsPagination::test_returns_listings_with_pagination PASSED [ 26%]
2088:  tests/unit/api/test_flatmates_admin.py::TestGetPendingReportsPagination::test_returns_reports_with_pagination PASSED [ 26%]
2089:  tests/unit/api/test_flatmates_admin.py::TestGetPendingReportsPagination::test_empty_reports PASSED [ 26%]
2090:  tests/unit/api/test_flatmates_admin.py::TestPrescreenListing::test_admin_can_prescreen PASSED [ 26%]
2091:  tests/unit/api/test_flatmates_admin.py::TestPrescreenListing::test_non_admin_gets_403 PASSED [ 26%]
2092:  tests/unit/app/test_app_composition.py::test_openapi_paths_match_refactor_baseline FAILED [ 27%]
2093:  tests/unit/app/test_app_composition.py::test_mcp_mount_paths_are_registered PASSED [ 27%]
2094:  tests/unit/app/test_app_composition.py::test_base_api_exception_envelope_is_preserved PASSED [ 27%]
2095:  tests/unit/app/test_app_composition.py::test_legacy_request_id_filter_import_remains_compatible PASSED [ 27%]
2096:  tests/unit/app/test_app_composition.py::test_canonical_domain_modules_expose_existing_property_service PASSED [ 27%]
2097:  tests/unit/core/test_auth.py::TestGetSupabaseClients::test_get_supabase_auth_client_creates_singleton PASSED [ 27%]
2098:  tests/unit/core/test_auth.py::TestGetSupabaseClients::test_get_supabase_auth_client_requires_publishable_key PASSED [ 27%]
2099:  tests/unit/core/test_auth.py::TestGetSupabaseClients::test_get_supabase_service_client_creates_singleton PASSED [ 27%]
2100:  tests/unit/core/test_auth.py::TestGetSupabaseClients::test_get_supabase_storage_client_creates_singleton PASSED [ 27%]
2101:  tests/unit/core/test_auth.py::TestVerifySupabaseToken::test_verify_token_success PASSED [ 27%]
2102:  tests/unit/core/test_auth.py::TestVerifySupabaseToken::test_verify_token_failure_returns_none PASSED [ 27%]
2103:  tests/unit/core/test_auth.py::TestVerifySupabaseToken::test_verify_token_missing_id_returns_none PASSED [ 27%]
2104:  tests/unit/core/test_auth.py::TestVerifySupabaseToken::test_verify_token_network_error_returns_none PASSED [ 27%]
2105:  tests/unit/core/test_auth.py::TestAdminFindUserByPhone::test_find_user_success PASSED [ 27%]
...

2126:  tests/unit/core/test_cache_manager.py::TestNullCacheBackend::test_is_available_returns_false PASSED [ 29%]
2127:  tests/unit/core/test_cache_manager.py::TestCacheBackendType::test_memory_backend_type PASSED [ 29%]
2128:  tests/unit/core/test_cache_manager.py::TestCacheBackendType::test_redis_backend_type PASSED [ 29%]
2129:  tests/unit/core/test_cache_manager.py::TestCacheBackendType::test_disk_backend_type PASSED [ 29%]
2130:  tests/unit/core/test_cache_manager.py::TestCacheManager::test_create_from_config_memory PASSED [ 29%]
2131:  tests/unit/core/test_cache_manager.py::TestCacheManager::test_create_from_config_disk PASSED [ 29%]
2132:  tests/unit/core/test_cache_manager.py::TestCacheManager::test_create_from_config_redis PASSED [ 29%]
2133:  tests/unit/core/test_cache_manager.py::TestCacheManager::test_get_delegates_to_backend PASSED [ 30%]
2134:  tests/unit/core/test_cache_manager.py::TestCacheManager::test_set_delegates_to_backend PASSED [ 30%]
2135:  tests/unit/core/test_cache_manager.py::TestCacheManager::test_delete_delegates_to_backend PASSED [ 30%]
2136:  tests/unit/core/test_cache_manager.py::TestCacheManager::test_delete_pattern_delegates_to_backend PASSED [ 30%]
2137:  tests/unit/core/test_cache_manager.py::TestCacheManager::test_exists_delegates_to_backend PASSED [ 30%]
2138:  tests/unit/core/test_cache_manager.py::TestCacheManager::test_clear_delegates_to_backend PASSED [ 30%]
2139:  tests/unit/core/test_cache_manager.py::TestCacheManager::test_is_available_checks_backend PASSED [ 30%]
2140:  tests/unit/core/test_cache_manager.py::TestCacheManager::test_uses_fallback_when_primary_unavailable PASSED [ 30%]
2141:  tests/unit/core/test_cache_manager.py::TestCacheManager::test_connect_sets_fallback_on_primary_failure PASSED [ 30%]
2142:  tests/unit/core/test_cache_manager.py::TestCacheManager::test_disconnect_closes_all_backends PASSED [ 30%]
...

2145:  tests/unit/core/test_cache_manager.py::TestCacheModuleFunctions::test_get_cache_manager_creates_singleton PASSED [ 30%]
2146:  tests/unit/core/test_cache_manager.py::TestCacheModuleFunctions::test_set_cache_manager PASSED [ 30%]
2147:  tests/unit/core/test_cache_manager.py::TestCacheModuleFunctions::test_initialize_cache PASSED [ 31%]
2148:  tests/unit/core/test_cache_manager.py::TestCacheModuleFunctions::test_shutdown_cache PASSED [ 31%]
2149:  tests/unit/core/test_cache_manager.py::TestPropertyCacheManager::test_generate_cache_key PASSED [ 31%]
2150:  tests/unit/core/test_cache_manager.py::TestPropertyCacheManager::test_generate_cache_key_different_filters PASSED [ 31%]
2151:  tests/unit/core/test_cache_manager.py::TestPropertyCacheManager::test_generate_cache_key_different_users PASSED [ 31%]
2152:  tests/unit/core/test_cache_manager.py::TestPropertyCacheManager::test_invalidate_property_caches PASSED [ 31%]
2153:  tests/unit/core/test_cache_manager.py::TestPropertyCacheManager::test_get_cached_properties PASSED [ 31%]
2154:  tests/unit/core/test_cache_manager.py::TestPropertyCacheManager::test_cache_properties PASSED [ 31%]
2155:  tests/unit/core/test_cache_manager.py::TestDiskCacheBackend::test_round_trip_and_delete_pattern PASSED [ 31%]
2156:  tests/unit/core/test_cache_manager.py::TestDiskCacheBackend::test_rejects_oversized_entries PASSED [ 31%]
2157:  tests/unit/core/test_config.py::TestSettings::test_async_database_url_from_postgresql PASSED [ 31%]
2158:  tests/unit/core/test_config.py::TestSettings::test_async_database_url_from_postgres PASSED [ 31%]
2159:  tests/unit/core/test_config.py::TestSettings::test_async_database_url_already_async PASSED [ 31%]
2160:  tests/unit/core/test_config.py::TestSettings::test_default_cache_settings FAILED [ 31%]
2161:  tests/unit/core/test_config.py::TestSettings::test_cache_ttl_settings PASSED [ 32%]
...

2164:  tests/unit/core/test_config.py::TestSettings::test_vastu_default_provider PASSED [ 32%]
2165:  tests/unit/core/test_config.py::TestSettings::test_supabase_client_key_returns_publishable_key PASSED [ 32%]
2166:  tests/unit/core/test_config.py::TestSettings::test_auto_blog_defaults PASSED [ 32%]
2167:  tests/unit/core/test_config.py::TestSettings::test_auto_blog_publisher_user_id_blank_string_is_treated_as_none PASSED [ 32%]
2168:  tests/unit/core/test_constants.py::TestVisionConstants::test_valid_vision_providers PASSED [ 32%]
2169:  tests/unit/core/test_constants.py::TestVisionConstants::test_default_vision_provider_is_glm PASSED [ 32%]
2170:  tests/unit/core/test_constants.py::TestVisionConstants::test_default_vision_model_gemini PASSED [ 32%]
2171:  tests/unit/core/test_constants.py::TestVisionConstants::test_default_vision_model_glm PASSED [ 32%]
2172:  tests/unit/core/test_constants.py::TestVisionConstants::test_valid_providers_are_tuple PASSED [ 32%]
2173:  tests/unit/core/test_constants.py::TestVisionConstants::test_fallback_provider_default PASSED [ 32%]
2174:  tests/unit/core/test_constants.py::TestConstantsDeriveFromSettings::test_gemini_model_fallback_when_settings_none PASSED [ 32%]
2175:  tests/unit/core/test_constants.py::TestConstantsDeriveFromSettings::test_glm_model_fallback_when_settings_none PASSED [ 33%]
2176:  tests/unit/core/test_constants.py::TestConstantsDeriveFromSettings::test_fallback_provider_empty_when_not_set PASSED [ 33%]
2177:  tests/unit/core/test_db_resilience.py::test_execute_with_transient_retry_succeeds_on_second_attempt PASSED [ 33%]
2178:  tests/unit/core/test_db_resilience.py::test_execute_with_transient_retry_does_not_retry_non_transient PASSED [ 33%]
2179:  tests/unit/core/test_db_resilience.py::test_transient_db_error_detection_and_code_extraction PASSED [ 33%]
2180:  tests/unit/core/test_docs_contracts.py::test_docs_contract_validation_passes_for_current_repo PASSED [ 33%]
...

2182:  tests/unit/core/test_exceptions.py::TestBaseAPIException::test_default_status_code PASSED [ 33%]
2183:  tests/unit/core/test_exceptions.py::TestBaseAPIException::test_default_detail PASSED [ 33%]
2184:  tests/unit/core/test_exceptions.py::TestBaseAPIException::test_custom_detail PASSED [ 33%]
2185:  tests/unit/core/test_exceptions.py::TestBaseAPIException::test_custom_headers PASSED [ 33%]
2186:  tests/unit/core/test_exceptions.py::TestBaseAPIException::test_extra_kwargs PASSED [ 33%]
2187:  tests/unit/core/test_exceptions.py::TestNotFoundExceptions::test_not_found_exception PASSED [ 33%]
2188:  tests/unit/core/test_exceptions.py::TestNotFoundExceptions::test_property_not_found PASSED [ 33%]
2189:  tests/unit/core/test_exceptions.py::TestNotFoundExceptions::test_property_not_found_custom_message PASSED [ 34%]
2190:  tests/unit/core/test_exceptions.py::TestNotFoundExceptions::test_user_not_found PASSED [ 34%]
2191:  tests/unit/core/test_exceptions.py::TestNotFoundExceptions::test_agent_not_found PASSED [ 34%]
2192:  tests/unit/core/test_exceptions.py::TestNotFoundExceptions::test_booking_not_found PASSED [ 34%]
2193:  tests/unit/core/test_exceptions.py::TestNotFoundExceptions::test_visit_not_found PASSED [ 34%]
2194:  tests/unit/core/test_exceptions.py::TestAuthExceptions::test_unauthorized_exception PASSED [ 34%]
2195:  tests/unit/core/test_exceptions.py::TestAuthExceptions::test_forbidden_exception PASSED [ 34%]
2196:  tests/unit/core/test_exceptions.py::TestAuthExceptions::test_insufficient_permissions PASSED [ 34%]
2197:  tests/unit/core/test_exceptions.py::TestAuthExceptions::test_property_ownership_error PASSED [ 34%]
2198:  tests/unit/core/test_exceptions.py::TestValidationExceptions::test_validation_exception PASSED [ 34%]
2199:  tests/unit/core/test_exceptions.py::TestValidationExceptions::test_bad_request_exception PASSED [ 34%]
2200:  tests/unit/core/test_exceptions.py::TestConflictExceptions::test_conflict_exception PASSED [ 34%]
2201:  tests/unit/core/test_exceptions.py::TestConflictExceptions::test_booking_conflict_error PASSED [ 34%]
2202:  tests/unit/core/test_exceptions.py::TestConflictExceptions::test_duplicate_swipe_error PASSED [ 34%]
2203:  tests/unit/core/test_exceptions.py::TestRateLimitException::test_rate_limit_exception PASSED [ 35%]
2204:  tests/unit/core/test_exceptions.py::TestServiceUnavailableException::test_service_unavailable_exception PASSED [ 35%]
2205:  tests/unit/core/test_exceptions.py::TestPayloadExceptions::test_file_too_large_exception PASSED [ 35%]
2206:  tests/unit/core/test_exceptions.py::TestPayloadExceptions::test_invalid_file_exception PASSED [ 35%]
2207:  tests/unit/core/test_exceptions.py::TestExternalAndStorageExceptions::test_external_service_error PASSED [ 35%]
2208:  tests/unit/core/test_exceptions.py::TestExternalAndStorageExceptions::test_storage_exception PASSED [ 35%]
...

2212:  tests/unit/core/test_exceptions.py::TestBlogExceptions::test_blog_not_found PASSED [ 35%]
2213:  tests/unit/core/test_exceptions.py::TestBlogExceptions::test_category_not_found PASSED [ 35%]
2214:  tests/unit/core/test_exceptions.py::TestBlogExceptions::test_tag_not_found PASSED [ 35%]
2215:  tests/unit/core/test_exceptions.py::TestPMExceptions::test_lease_not_found PASSED [ 35%]
2216:  tests/unit/core/test_exceptions.py::TestPMExceptions::test_maintenance_request_not_found PASSED [ 36%]
2217:  tests/unit/core/test_exceptions.py::TestExceptionInheritance::test_domain_exceptions_inherit_from_base PASSED [ 36%]
2218:  tests/unit/core/test_exceptions.py::TestExceptionInheritance::test_exceptions_are_http_exceptions PASSED [ 36%]
2219:  tests/unit/core/test_logging.py::TestColorFormatter::test_format_returns_string PASSED [ 36%]
2220:  tests/unit/core/test_logging.py::TestColorFormatter::test_format_with_colors_enabled PASSED [ 36%]
2221:  tests/unit/core/test_logging.py::TestColorFormatter::test_format_without_colors PASSED [ 36%]
2222:  tests/unit/core/test_logging.py::TestColorFormatter::test_name_map_cleans_logger_names PASSED [ 36%]
2223:  tests/unit/core/test_logging.py::TestColorFormatter::test_extras_appended_as_key_value PASSED [ 36%]
2224:  tests/unit/core/test_logging.py::TestColorFormatter::test_level_color_mapping[DEBUG-\x1b[36m] PASSED [ 36%]
2225:  tests/unit/core/test_logging.py::TestColorFormatter::test_level_color_mapping[INFO-\x1b[32m] PASSED [ 36%]
2226:  tests/unit/core/test_logging.py::TestColorFormatter::test_level_color_mapping[WARNING-\x1b[33m] PASSED [ 36%]
2227:  tests/unit/core/test_logging.py::TestColorFormatter::test_level_color_mapping[ERROR-\x1b[31m] PASSED [ 36%]
2228:  tests/unit/core/test_logging.py::TestStructuredFormatter::test_format_returns_valid_json PASSED [ 36%]
...

2249:  tests/unit/core/test_utils.py::TestUtcNow::test_returns_timezone_aware_datetime PASSED [ 38%]
2250:  tests/unit/core/test_utils.py::TestUtcNow::test_returns_utc_timezone PASSED [ 38%]
2251:  tests/unit/core/test_utils.py::TestUtcNow::test_returns_recent_time PASSED [ 38%]
2252:  tests/unit/core/test_utils.py::TestUtcNowIso::test_returns_string PASSED [ 38%]
2253:  tests/unit/core/test_utils.py::TestUtcNowIso::test_is_parseable_as_iso8601 PASSED [ 38%]
2254:  tests/unit/core/test_utils.py::TestMakeTzAware::test_none_returns_none PASSED [ 38%]
2255:  tests/unit/core/test_utils.py::TestMakeTzAware::test_naive_datetime_gets_utc PASSED [ 38%]
2256:  tests/unit/core/test_utils.py::TestMakeTzAware::test_aware_datetime_stays_in_utc PASSED [ 38%]
2257:  tests/unit/core/test_utils.py::TestMakeTzAware::test_non_utc_timezone_converted_to_utc PASSED [ 38%]
2258:  tests/unit/core/test_utils.py::TestMakeTzAware::test_various_naive_dates[2024-1-1-0] PASSED [ 39%]
2259:  tests/unit/core/test_utils.py::TestMakeTzAware::test_various_naive_dates[2025-6-15-12] PASSED [ 39%]
2260:  tests/unit/core/test_utils.py::TestMakeTzAware::test_various_naive_dates[2025-12-31-23] PASSED [ 39%]
2261:  tests/unit/core/test_websocket.py::TestJobConnections::test_connect_job PASSED [ 39%]
2262:  tests/unit/core/test_websocket.py::TestJobConnections::test_disconnect_job PASSED [ 39%]
2263:  tests/unit/core/test_websocket.py::TestJobConnections::test_disconnect_job_removes_empty_set PASSED [ 39%]
2264:  tests/unit/core/test_websocket.py::TestJobConnections::test_disconnect_nonexistent_job_no_error PASSED [ 39%]
2265:  tests/unit/core/test_websocket.py::TestJobConnections::test_multiple_connections_same_job PASSED [ 39%]
2266:  tests/unit/core/test_websocket.py::TestJobConnections::test_send_job_update PASSED [ 39%]
2267:  tests/unit/core/test_websocket.py::TestJobConnections::test_send_job_update_no_connections PASSED [ 39%]
2268:  tests/unit/core/test_websocket.py::TestJobConnections::test_send_job_update_dead_connection_cleaned_up PASSED [ 39%]
2269:  tests/unit/core/test_websocket.py::TestJobConnections::test_get_job_connection_count PASSED [ 39%]
2270:  tests/unit/core/test_websocket.py::TestUserConnections::test_connect_user PASSED [ 39%]
2271:  tests/unit/core/test_websocket.py::TestUserConnections::test_disconnect_user PASSED [ 39%]
2272:  tests/unit/core/test_websocket.py::TestUserConnections::test_send_user_notification PASSED [ 40%]
2273:  tests/unit/core/test_websocket.py::TestUserConnections::test_send_user_notification_no_connections PASSED [ 40%]
2274:  tests/unit/core/test_websocket.py::TestUserConnections::test_get_user_connection_count PASSED [ 40%]
2275:  tests/unit/core/test_websocket.py::TestBroadcasts::test_broadcast_job_completion PASSED [ 40%]
2276:  tests/unit/core/test_websocket.py::TestBroadcasts::test_broadcast_job_error PASSED [ 40%]
2277:  tests/unit/mcp/test_apps_sdk.py::TestResourceMimeType::test_mime_type_format PASSED [ 40%]
2278:  tests/unit/mcp/test_apps_sdk.py::TestResourceMimeType::test_mime_type_contains_html PASSED [ 40%]
2279:...

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 issues found across 2 files (changes from recent commits).

Requires human review: This PR adds a new API endpoint, modifies core flatmates discovery logic to exclude swiped profiles, and tunes database pool settings—each change carries moderate risk and requires human review for correctness and unintended side effects.
Re-trigger cubic

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 1 file (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="app/infrastructure/lifespan.py">

<violation number="1" location="app/infrastructure/lifespan.py:79">
P1: Do not swallow startup migration errors; logging and continuing can leave the app running against an outdated schema.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic

await conn.execute(text(sql))
logger.info("Startup migration applied: %s", label)
except Exception as exc:
logger.warning("Startup migration skipped (%s): %s", label, exc)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Do not swallow startup migration errors; logging and continuing can leave the app running against an outdated schema.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At app/infrastructure/lifespan.py, line 79:

<comment>Do not swallow startup migration errors; logging and continuing can leave the app running against an outdated schema.</comment>

<file context>
@@ -60,6 +61,24 @@ async def lifespan(app: FastAPI) -> AsyncIterator[None]:
+                await conn.execute(text(sql))
+                logger.info("Startup migration applied: %s", label)
+            except Exception as exc:
+                logger.warning("Startup migration skipped (%s): %s", label, exc)
+
+
</file context>

Tip: Review your code locally with the cubic CLI to iterate faster.

Comment on lines +64 to +79
async def _apply_pending_migrations() -> None:
"""Run lightweight one-off DDL that cannot be applied via Supabase CLI migrations."""
from sqlalchemy import text

async with engine.begin() as conn:
for label, sql in (
(
"image_category: add floor_plan",
"ALTER TYPE image_category ADD VALUE IF NOT EXISTS 'floor_plan'",
),
):
try:
await conn.execute(text(sql))
logger.info("Startup migration applied: %s", label)
except Exception as exc:
logger.warning("Startup migration skipped (%s): %s", label, exc)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 DDL failure leaves transaction aborted, propagating a commit error despite the inner try/except

When conn.execute(text(sql)) raises (e.g., permission denied, PG version restriction), the exception is caught and logged as a warning. However, the PostgreSQL connection is now in an aborted-transaction state. When engine.begin()'s context manager exits normally (no exception was propagated), SQLAlchemy calls conn.commit(). PostgreSQL rejects the commit with "current transaction is aborted, commands ignored until end of transaction block," and this exception escapes _apply_pending_migrations entirely. The caller in create_lifespan catches it at the outer except Exception level and logs "Application startup failed," which silently skips _start_schedulers.

The defensive try/except creates a false sense of safety: the migration appears to be handled gracefully, but a DDL failure will still cause all schedulers to be omitted on that startup. The fix is to use engine.connect() with await conn.execution_options(isolation_level="AUTOCOMMIT") for DDL, or to wrap the entire async with engine.begin() block in a separate try/except in _apply_pending_migrations so failures stay contained.

@saksham1991999 saksham1991999 merged commit 670dd10 into main May 17, 2026
3 of 5 checks passed
@RaviSahu1520 RaviSahu1520 deleted the feature/flatmates-search-updates branch May 17, 2026 13:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants