Skip to content

fix(intent): mirror 'expired' status predicate in roux_ingest ON CONFLICT - #117

Merged
chitcommit merged 1 commit into
mainfrom
fix/intent-on-conflict-expired-predicate
Jun 10, 2026
Merged

chitcommit merged 1 commit into
mainfrom
fix/intent-on-conflict-expired-predicate

Conversation

@chitcommit

@chitcommit chitcommit commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Summary

PR #115 / migration 0018_intent_decay.sql added AND status <> 'expired' to the partial unique index cc_intents_roux_ingest_message_id_uidx but did not update the matching ON CONFLICT WHERE clause in createRouxIngestIntentIdempotent (meta/intent.ts).

PostgreSQL requires predicate equality between the index and the ON CONFLICT clause — the drift caused the upsert to fail with 42P10: there is no unique or exclusion constraint matching the ON CONFLICT specification, breaking the Roux ingest path.

Change

One-line addition to the WHERE clause:

     ON CONFLICT ((payload->'source'->>'message_id'))
       WHERE intent_type = 'roux_ingest'
         AND payload->'source'->>'message_id' IS NOT NULL
+        AND status <> 'expired'
       DO NOTHING

Validation

Verified against a fresh Neon branch (br-curly-art-akoofx5s) on project cool-bar-13270800:

  • Pre-fix upsert (old predicate): NeonDbError: there is no unique or exclusion constraint matching the ON CONFLICT specification (SQLSTATE 42P10)
  • Post-fix upsert (matched predicate): ON CONFLICT resolves cleanly to the index; statement parses and executes against the constraint as intended.

Note on workspace-studio-ingest tests

The 4 failing tests in tests/routes/workspace-studio-ingest.spec.ts fail with Error: This context has no ExecutionContext (Hono c.executionCtx.waitUntil in test env) — this is an unrelated test-infra issue, not the ON CONFLICT bug. The same 4 tests fail on main and on this branch with the fix applied (7/11 pass in both cases). Scope of this PR is intentionally limited to the predicate mirror per instructions; the executionCtx issue can be addressed separately.

Test plan

  • Confirm pre-fix SQL fails with 42P10 against migration 0018 schema
  • Confirm post-fix SQL parses and resolves to the index
  • CI green

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Improved handling of duplicate Gmail messages by excluding expired items from the deduplication logic, ensuring more accurate message processing.

…LICT

PR #115 / migration 0018 added `AND status <> 'expired'` to the partial
unique index `cc_intents_roux_ingest_message_id_uidx` but did not update
the upsert's ON CONFLICT WHERE clause in createRouxIngestIntentIdempotent.

PostgreSQL requires predicate equality to match an index to ON CONFLICT —
the mismatch caused the upsert to fail with "no unique or exclusion
constraint matching the ON CONFLICT specification", breaking the Roux
ingest path. Verified against a fresh Neon branch:
  - pre-fix: SQLSTATE 42P10 (no matching constraint)
  - post-fix: ON CONFLICT resolves cleanly to the index

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
  1. @coderabbitai review
  2. @copilot review
  3. @codex review
  4. @claude review
    Adversarial review request: evaluate security, policy bypass paths, regression risk, and merge-gating bypass attempts.

@chitcommit
chitcommit merged commit e858de1 into main Jun 10, 2026
11 of 13 checks passed
@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b0a8da83-f971-41de-b9d2-39523382a7da

📥 Commits

Reviewing files that changed from the base of the PR and between 16db06f and 0c6a8ff.

📒 Files selected for processing (1)
  • meta/intent.ts

📝 Walkthrough

Walkthrough

The createRouxIngestIntentIdempotent function's ON CONFLICT clause now excludes intents with an 'expired' status from triggering conflict resolution, allowing duplicate Gmail message_ids to be inserted when the existing row is expired.

Changes

Roux ingest conflict predicate

Layer / File(s) Summary
Conflict predicate update for expired status exclusion
meta/intent.ts
The ON CONFLICT clause extends its predicate with AND status <> 'expired' to exclude expired intents from conflict detection, allowing re-insertion for the same Gmail message_id when the existing intent has expired.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • chittyos/chittycommand#115: Introduces the 'expired' status and updates the DB uniqueness guard to exclude status = 'expired', which works in concert with this PR's conflict predicate update.

Poem

🐰 When intents grow old and their time expires,
Let fresh messages rise from the database fires—
No conflict shall block what has passed its prime,
New hope for that message_id, just once more, this time! ✨

✨ 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 fix/intent-on-conflict-expired-predicate

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.

@chitcommit
chitcommit deleted the fix/intent-on-conflict-expired-predicate branch June 10, 2026 02:13
@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@chitcommit
chitcommit restored the fix/intent-on-conflict-expired-predicate branch June 10, 2026 07:00
@chitcommit
chitcommit deleted the fix/intent-on-conflict-expired-predicate branch June 10, 2026 07:05
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.

1 participant