Skip to content

fix: Review queue approvals (CODE_DERIVED + stale list + bulk errors) - #74

Merged
venkateshsakamuri-lab merged 5 commits into
mainfrom
cursor/fix-review-approvals-231a
Aug 22, 2026
Merged

fix: Review queue approvals (CODE_DERIVED + stale list + bulk errors)#74
venkateshsakamuri-lab merged 5 commits into
mainfrom
cursor/fix-review-approvals-231a

Conversation

@venkateshsakamuri-lab

Copy link
Copy Markdown
Contributor

Problem (customer screenshot)

Step 3 showed 198 awaiting sign-off, the table showed 2 pending SCHEMA rows, and bulk approve displayed APPROVED 0 OF 2.

Root causes (reproduced)

  1. Approve fails on self-hostschema_documentation_source_check often still lacks CODE_DERIVED (Hibernate ddl-auto=update never rewrites CHECKs). SCHEMA_DOC approve inserts source=CODE_DERIVED → constraint violation → bulk-decide swallows the error → UI shows Approved 0 of N as a success banner.
  2. Count mismatch — badge uses a fresh totalElements probe; the Review list used useAllCodeScanSuggestions with staleTime: 30s and only invalidated on scan start, not on COMPLETED.
  3. Silent failures — bulk API returned only {requested, succeeded}; UI treated succeeded: 0 as success.

Fix

  • Startup initializer (SchemaDocumentationSourceCompatibilityInitializer) keeps the source CHECK aligned with DocumentationSource (same pattern as Brain init stages).
  • Bulk decide returns failed + failures[{id,error}]; Review UI treats partial/zero success as an error banner with details.
  • Invalidate code-scan queries when a scan reaches COMPLETED/FAILED/CANCELLED; drop list staleTime.
  • Malformed SCHEMA_DOC targets throw instead of silently skipping.
  • CodeSuggestionApplierTest + seed/E2E scripts:
    • scripts/self-host/seed-review-suggestions.py
    • scripts/self-host/e2e-review-approvals.py (15 edge cases, all green)

Verify

python3 scripts/self-host/seed-review-suggestions.py --count 20
python3 scripts/self-host/e2e-review-approvals.py
# expect: ✓ All review-approval edge cases passed

Please merge the AGENTS.md updates so future agents remember the Review seed/E2E path and the CODE_DERIVED CHECK footgun.

Open in Web Open in Cursor 

cursoragent and others added 2 commits August 22, 2026 04:11
Customer saw "198 awaiting" with only 2 rows and "APPROVED 0 OF 2" because:
1) schema_documentation CHECK lacked CODE_DERIVED on self-host (Hibernate
   never rewrites CHECKs) so SCHEMA_DOC approve failed inside bulk-decide
2) Review list cache stayed stale after scans while the badge refetched totals
3) bulk success toast treated succeeded=0 as success with no failure details

- Startup initializer keeps source CHECK aligned with DocumentationSource
- Bulk decide returns failures[] with per-id errors; UI shows them as errors
- Invalidate suggestions when a scan reaches COMPLETED/FAILED
- Throw on malformed SCHEMA_DOC targets instead of silent skip
- Seed + E2E scripts for review queue edge cases

Co-authored-by: Venkat SF <venkatesh.sakamuri@stayflexi.com>
Co-authored-by: Venkat SF <venkatesh.sakamuri@stayflexi.com>
@cursor
cursor Bot marked this pull request as ready for review August 22, 2026 05:55
@cursor
cursor Bot requested a review from a team as a code owner August 22, 2026 05:55
cursoragent and others added 3 commits August 22, 2026 06:46
… chat

- Show code-scan suggestions as clickable bubbles with rule excerpt preview
- Fold scan proposals into one intent when they overlap existing knowledge or schema notes
- Approve merges into existing entries/docs instead of creating duplicates
- Clarify review is optional; Agent chat shows a non-blocking pending hint

Co-authored-by: Venkat SF <venkatesh.sakamuri@stayflexi.com>
@venkateshsakamuri-lab
venkateshsakamuri-lab merged commit b4d62d2 into main Aug 22, 2026
9 checks passed
@venkateshsakamuri-lab
venkateshsakamuri-lab deleted the cursor/fix-review-approvals-231a branch August 22, 2026 16:11
venkateshsakamuri-lab added a commit that referenced this pull request Aug 22, 2026
…live (#77)

Follow-up to #74. That PR made the failure *visible* (bulk decide now
returns `failures[]`, and the UI renders a partial/zero success as an
error) but the approval itself still threw — its diagnosis, a
`schema_documentation_source_check` missing `CODE_DERIVED`, did not
apply to the reporting install, where the CHECK was already correct and
the log said something else entirely.

## What was actually failing

```
WARN CodeScanService : bulk decide skipped e2011614-…: Query did not return a unique result: 2 results were returned
WARN CodeScanService : bulk decide skipped f3689e0e-…: Query did not return a unique result: 2 results were returned
```

`schema_documentation` carried no unique constraint on `(connection_id,
object_type, object_name, parent_object, source)` and
`CodeSuggestionApplier.approve` took no row lock, so **one bulk approve
submitted twice concurrently wrote 219 duplicate pairs** (pairs ~3s
apart; in every group the older row is an orphan and the newer one holds
the `applied_doc_id`). Every later approve landing on such a key threw
out of the `Optional`-returning upsert finder, and bulk-decide swallowed
it per item. The duplicate never self-heals, so **all 198 pending
SCHEMA_DOC suggestions were permanently unapprovable**.

## Fix

**1. Duplicate-tolerant upsert.** The three finders now return `List`,
so the compiler forces every caller to handle N matches.
`SchemaDocumentationDeduplicator` keeps the newest row, repoints any
`applied_doc_id` off the rows it deletes (a loose reference, not an FK —
a dangling value fails silently), and drops their RAG embeddings.
Applied at all four call sites, including `SchemaDriftListener`, which
would have thrown identically the first time one of 17 duplicated tables
was dropped.

**2. Data repair + constraint.**
`V116__dedupe_schema_documentation.sql`, applied by
`SchemaDocumentationDedupeInitializer` — there is no Flyway runtime
here, so a SQL file alone would never run. Idempotent: it returns before
touching a row once the index exists. `coalesce(parent_object,'')` in
the key because Postgres treats NULLs as distinct.

**3. The root cause.** `approve`/`reject` load the suggestion `FOR
UPDATE`, so the concurrent double-submit blocks and the second caller
sees `APPROVED`.

## Also fixed (reported after the first fix landed)

- **Counts stale until reload.** An approval also writes
`schema_documentation`, served by `brain/notes`, which backs the
Write-notes tab and its coverage counts. The decide hooks invalidated
only `codeScan` + `companyKnowledge`. `invalidateAfterDecision` now
covers `brain` and `schemaContext` too.
- **Newest notes sorted last.** `@PreUpdate` never fires on insert, so a
new note has a null `updatedAt`; sorting on it alone with nulls last
sent every brand-new note to the *bottom*. Now `COALESCE(updatedAt,
createdAt)`, matching `CompanyKnowledgeEntryRepository`.
- **Fresh approvals buried in the Approved view.** `listSuggestions`
sorted every status by confidence. PENDING stays confidence-first (it is
a work queue); decided statuses now sort by `decidedAt DESC NULLS LAST`.

## Two bugs in #74's own test tooling

- Both scripts hardcoded `sudo -u postgres psql`, which does not exist
on the Compose deployment `install.sh` produces — the verify command in
#74's description failed before testing anything. Now resolved through
`scripts/self-host/vaultdb.py`.
- **`e2e-review-approvals.py` step 10 rewrote every real `CODE_DERIVED`
row to `source='USER'` and never restored it.** Running it against a
live install silently relabelled 339 approved docs, and post-V116 it
would collide with the unique index. It now parks rows in a scratch
table and restores them with a verified count, and its cleanup deletes
the planted row only while nothing references it.

## Verification

Run against the live self-host stack, not just unit tests.

- Initializer on the affected install: `removed 219 duplicate rows, 219
orphaned embeddings`; 7068 → 6849 doc rows, 8190 → 7971 RAG rows, **0
duplicate groups, 0 dangling `applied_doc_id`**. Skipped cleanly on
restart.
- The two originally stuck suggestions: `{"requested": 2, "succeeded":
2, "failed": 0}`.
- Ordering, approving the three *lowest*-confidence items so the two
sorts disagree — all three land above older `conf=0.97` rows.
- `brain/notes` 4607 → 4608 on a first-time doc (the count that never
refreshed), and the just-approved `crm.customers` now sorts first.
- 21 backend unit tests green (4 new on collapse, 2 new on note
ordering). 184 related tests run; the 6 failures in
`TrainingServiceBusinessTermTest` / `BrainInitStageExecutorTest`
reproduce identically on pristine `main` and are unrelated.
- **E2E suite: 30/30 pass**, including duplicate collapse,
`applied_doc_id` repointing, the unique index rejecting a second row,
and two genuinely concurrent approves writing exactly one row.

```bash
python3 scripts/self-host/seed-review-suggestions.py <connectionId> --count 20
python3 scripts/self-host/e2e-review-approvals.py <connectionId>
# ✓ All review-approval edge cases passed
```

Note: the suite consumes its own fixtures, so re-run the seed before
each run.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_018mG2xj9gWJ8WzfDP2fDePP

Co-authored-by: Krishna Sasank Talasila <606482+geekypunk@users.noreply.github.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Venkat SF <venkatesh.sakamuri@stayflexi.com>
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