-
Notifications
You must be signed in to change notification settings - Fork 0
feat: integrate disputes with Notion Task Triager and TriageAgent #26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| # Notion Task Triager — ChittyCommand Dispute Integration | ||
|
|
||
| Add the following to the Task Triager agent's instructions in Notion Settings > Connections > Task Triager > Edit instructions. | ||
|
|
||
| --- | ||
|
|
||
| ## Dispute & Legal Task Classification | ||
|
|
||
| When you receive an email or message related to any of the following topics, classify it as a **legal task** so it automatically syncs into ChittyCommand's dispute tracker: | ||
|
|
||
| - Disputes with vendors, landlords, tenants, contractors, or counterparties | ||
| - Insurance claims or denials | ||
| - Court filings, summons, motions, or docket updates | ||
| - Property damage, water damage, or maintenance disputes | ||
| - Legal deadlines, statute of limitations, or response due dates | ||
| - Demand letters, cease & desist, or settlement offers | ||
| - Payment disputes, chargebacks, or billing errors | ||
| - Government notices (IRS, county, city violations) | ||
|
|
||
| ### Required Properties for Legal Tasks | ||
|
|
||
| When creating a task page in the **Business Task Tracker** database for dispute/legal items: | ||
|
|
||
| | Property | Value | Notes | | ||
| |----------|-------|-------| | ||
| | **Title** | Clear, descriptive title | e.g. "Water damage claim — 123 Main St — Allstate denial" | | ||
| | **Type** | `Legal` | MUST be "Legal" for ChittyCommand to pick it up as a dispute | | ||
| | **Source** | `Email` | Use "Email" for email-ingested items, "Mention" for @-mentions | | ||
| | **Priority 1** | 1-10 (number) | 1 = most urgent. Use 1-3 for court deadlines, 4-6 for active disputes, 7-10 for monitoring | | ||
| | **Tags** | One or more from the list below | Helps categorize the dispute type | | ||
| | **Description** | Summarize the key facts | Include: who, what, amounts, dates, and any deadlines mentioned | | ||
| | **Due Date** | Set if there's an explicit deadline | Court dates, response deadlines, filing windows | | ||
|
|
||
| ### Tag Guidelines | ||
|
|
||
| Apply one or more of these tags based on the content: | ||
|
|
||
| - `Dispute` — General disputes with any counterparty | ||
| - `Insurance-claim` — Insurance claims, denials, appeals | ||
| - `Court-filing` — Court documents, motions, hearings, docket activity | ||
| - `Property-issue` — Property damage, maintenance, HOA issues | ||
| - `Vendor-dispute` — Contractor, vendor, or service provider disputes | ||
| - `Legal-deadline` — Time-sensitive legal obligations | ||
| - `Payment` — Payment disputes, chargebacks, billing errors | ||
| - `Tax` — IRS notices, property tax disputes, assessments | ||
| - `Utility` — Utility billing disputes (ComEd, Peoples Gas, etc.) | ||
|
|
||
| ### Priority Guidance | ||
|
|
||
| | Priority | Use When | | ||
| |----------|----------| | ||
| | 1-2 | Court deadline within 7 days, active hearing, imminent statute expiry | | ||
| | 3-4 | Response needed within 30 days, active negotiations, pending insurance decision | | ||
| | 5-6 | Monitoring active disputes, follow-up needed, no immediate deadline | | ||
| | 7-8 | Informational notices, early-stage inquiries, low-stakes items | | ||
| | 9-10 | Archive-worthy, resolved but tracking, general awareness | | ||
|
|
||
| ### What Happens After Creation | ||
|
|
||
| Once you create a legal task in the Business Task Tracker: | ||
|
|
||
| 1. **ChittyCommand's daily cron** (6 AM CT) syncs new legal tasks into `cc_disputes` | ||
| 2. **TriageAgent** automatically scores the dispute for severity and priority | ||
| 3. **ChittyLedger** creates a case record for chain-of-custody tracking | ||
| 4. The dispute appears in the ChittyCommand dashboard for action tracking | ||
|
|
||
| You do NOT need to create anything in ChittyCommand directly — the sync is automatic. | ||
|
|
||
| ### Examples | ||
|
|
||
| **Email**: "Allstate denied claim #CLM-2024-8847 for water damage at 4521 S Drexel..." | ||
| → Type: `Legal` | Priority 1: `3` | Tags: `Insurance-claim`, `Property-issue` | Due Date: appeal deadline if mentioned | ||
|
|
||
| **Email**: "Cook County Circuit Court — Notice of hearing, Case 2024D007847, March 15..." | ||
| → Type: `Legal` | Priority 1: `1` | Tags: `Court-filing`, `Legal-deadline` | Due Date: `2026-03-15` | ||
|
|
||
| **Email**: "Mr. Cooper mortgage — escrow shortage notice, payment increase effective..." | ||
| → Type: `Legal` | Priority 1: `5` | Tags: `Payment`, `Property-issue` | Due Date: effective date | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,19 @@ | ||||||||||||||
| -- 0012_dispute_sync_indexes.sql | ||||||||||||||
| -- Indexes for dispute ↔ Notion ↔ TriageAgent sync lookups. | ||||||||||||||
|
|
||||||||||||||
| -- Fast lookup: find disputes by notion_task_id (loop guard in reconcileNotionDisputes) | ||||||||||||||
| CREATE INDEX IF NOT EXISTS idx_cc_disputes_notion_task_id | ||||||||||||||
| ON cc_disputes ((metadata->>'notion_task_id')) | ||||||||||||||
| WHERE metadata->>'notion_task_id' IS NOT NULL; | ||||||||||||||
|
Comment on lines
+5
to
+7
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Enforce one dispute per Notion page. The reconciliation flow does an existence check and then inserts. Without a uniqueness guarantee on 💡 Suggested migration tweak-CREATE INDEX IF NOT EXISTS idx_cc_disputes_notion_task_id
+CREATE UNIQUE INDEX IF NOT EXISTS idx_cc_disputes_notion_task_id
ON cc_disputes ((metadata->>'notion_task_id'))
WHERE metadata->>'notion_task_id' IS NOT NULL;Please pair this with duplicate-key handling in 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||
|
|
||||||||||||||
| -- Fast lookup: find tasks by dispute_id (loop guard) | ||||||||||||||
| CREATE INDEX IF NOT EXISTS idx_cc_tasks_dispute_id | ||||||||||||||
| ON cc_tasks ((metadata->>'dispute_id')) | ||||||||||||||
| WHERE metadata->>'dispute_id' IS NOT NULL; | ||||||||||||||
|
|
||||||||||||||
| -- Partial index for the reconciliation query (legal tasks not yet linked to disputes) | ||||||||||||||
| CREATE INDEX IF NOT EXISTS idx_cc_tasks_legal_unlinked | ||||||||||||||
| ON cc_tasks (priority ASC, created_at ASC) | ||||||||||||||
| WHERE task_type = 'legal' | ||||||||||||||
| AND backend_status NOT IN ('done', 'verified') | ||||||||||||||
| AND (metadata->>'dispute_id') IS NULL; | ||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,6 +6,7 @@ import { matchTransactions } from './matcher'; | |
| import { generateProjections } from './projections'; | ||
| import { discoverRevenueSources } from './revenue'; | ||
| import { generatePaymentPlan, savePaymentPlan } from './payment-planner'; | ||
| import { reconcileNotionDisputes } from './dispute-sync'; | ||
|
|
||
| /** | ||
| * Cron sync orchestrator. | ||
|
|
@@ -120,6 +121,18 @@ export async function runCronSync( | |
| } catch (err) { | ||
| console.error('[cron:notion_tasks] failed:', err); | ||
| } | ||
|
|
||
| // Phase 10: Dispute-Notion reconciliation | ||
| // Auto-creates cc_disputes from legal tasks not yet linked. | ||
| try { | ||
| const disputesSynced = await reconcileNotionDisputes(env, sql); | ||
| if (disputesSynced > 0) { | ||
| recordsSynced += disputesSynced; | ||
| console.log(`[cron:dispute_reconcile] created ${disputesSynced} disputes from Notion legal tasks`); | ||
| } | ||
| } catch (err) { | ||
| console.error('[cron:dispute_reconcile] failed:', err); | ||
| } | ||
|
Comment on lines
+125
to
+135
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add a DB-enforced dedupe guard before running this on cron.
🤖 Prompt for AI Agents |
||
| } | ||
|
|
||
| if (source === 'utility_scrape') { | ||
|
|
@@ -637,7 +650,7 @@ export async function syncNotionTasks(env: Env, sql: NeonQueryFunction<false, fa | |
|
|
||
| const description = extractNotionRichText(props['Description']); | ||
| const taskType = extractNotionSelect(props['Type']) || 'general'; | ||
| const priority = extractNotionNumber(props['Priority']) || 5; | ||
| const priority = extractNotionNumber(props['Priority 1']) || extractNotionNumber(props['Priority']) || 5; | ||
| const dueDate = extractNotionDate(props['Due Date']); | ||
| const source = extractNotionSelect(props['Source']) || 'notion'; | ||
| const verificationType = extractNotionSelect(props['Verification']) || 'soft'; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Document the counterparty limitation.
The required properties table does not mention that the
counterpartyfield will be auto-populated as'Unknown'when disputes are created from Notion legal tasks. Users may expect this to be extracted from Notion task properties (e.g., from the Description or a dedicated field), but context snippet 2 (src/lib/dispute-sync.ts:123) shows it is hardcoded. Consider adding a row or note explaining this limitation so users understand they may need to update the counterparty field manually in ChittyCommand after sync.📝 Suggested addition to the table
Add a note below the table:
📝 Committable suggestion
🤖 Prompt for AI Agents