Skip to content

Implement NotionDbSide for schema-agnostic Notion Database synchronization with annotations, 1:n status mapping, and relation support#1

Open
Copilot wants to merge 10 commits intomasterfrom
copilot/implement-notion-db-side
Open

Implement NotionDbSide for schema-agnostic Notion Database synchronization with annotations, 1:n status mapping, and relation support#1
Copilot wants to merge 10 commits intomasterfrom
copilot/implement-notion-db-side

Conversation

Copy link

Copilot AI commented Nov 22, 2025

Description

Adds bidirectional sync between Notion Databases and TaskWarrior with configurable schema mapping, addressing the need for flexible database-level synchronization beyond the existing page-level todo block sync. Supports synchronization of title, status, due date, project, priority, and annotations with flexible property type mappings and advanced features including 1:n status mapping, automatic relation title lookup, and intelligent page rendering for annotations.

Fixes # (N/A - New feature implementation)

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

Core Implementation

  • NotionDbSide class: Full SyncSide implementation with pagination, CRUD operations, and configurable property mappings for title, status, due date, project, priority, and annotations
  • NotionSideConfig dataclass: Injectable schema configuration supporting multiple property types:
    • Status: Status/Select/Checkbox for completion tracking with unified key-value mapping and 1:n support
    • Project: Select/Multi-select/Relation for project assignment with automatic title lookup for relations and bidirectional relation ID support
    • Priority: Select with configurable H/M/L mappings
    • Annotations: Field or Page mode for extracting task annotations from Notion content
  • Converter utilities: Bidirectional TaskWarrior ↔ NotionDb item transformation with datetime, project, priority, and annotation handling
  • 1:n Status Mapping: Multiple Notion status values can map to a single TaskWarrior status (e.g., "Done", "Complete", "Finished" all map to "completed")
  • Relation Title Lookup: Automatic fetching of related page titles for Relation-type project properties with graceful fallback to ID on failure
  • Bidirectional Relation Support: Can both read and write relation IDs for proper synchronization
  • TaskWarrior Annotations: Supports extracting annotations from Notion in two modes:
    • Field Mode: Extract annotation from a specific Notion property (Rich Text or Title)
    • Page Mode (default): Render entire Notion page content as formatted annotation, preserving structure (headings, lists, code blocks, checkboxes)

CLI Integration

  • tw_notion_db_sync script: New command with options for runtime schema customization:
    tw_notion_db_sync \
      --database-id "..." \
      --map-title "Task Name" \
      --map-status "State" \
      --map-project "Project" \
      --map-priority "Priority" \
      --map-description "Notes" \
      --description-kind field \
      --status-map "completed:Done" --status-map "completed:Complete" \
      --status-map "pending:Not started" --status-map "pending:To Do" \
      --status-kind select \
      --project-kind relation \
      --priority-map "H:High" --priority-map "M:Medium" --priority-map "L:Low"
  • Extended CLI options in cli.py for field mapping configuration including project, priority, and annotations
  • Configuration persistence via existing combination caching mechanism (including tw_sync_all_tasks)
  • Unified mapping approach: Both status and priority use consistent key-value pair format
  • 1:n mapping support: Multiple --status-map entries with the same TaskWarrior status are automatically grouped

Field Support

  • Title: Notion Title property ↔ TW task description
  • Status: Notion Status/Select/Checkbox ↔ TW task completion status
    • Unified mapping format: --status-map "TW_STATUS:NOTION_VALUE"
    • 1:n mapping: Multiple Notion values can map to same TW status
    • Default: pending:["Not started"], completed:["Done"]
  • Due Date: Notion Date property ↔ TW task due date
  • Project: Notion Select/Multi-select/Relation ↔ TW task project
    • Select: Single project selection (recommended)
    • Multi-select: Multiple projects (syncs first value only)
    • Relation: Links to another database with automatic title lookup via API call and bidirectional relation ID support
  • Priority: Notion Select ↔ TW task priority (H/M/L)
    • Configurable mapping format: --priority-map "TW_PRIORITY:NOTION_VALUE"
    • Default: H:High, M:Medium, L:Low
  • Annotations: Notion property or page content ↔ TW task annotations
    • Field mode (--description-kind field): Extract from specific property via --map-description
    • Page mode (--description-kind page, default): Render entire page with support for paragraphs, headings, lists, code blocks, and checkboxes

Design Decisions

  • Schema agnostic by default: No hardcoded column names; all mappings injectable via config
  • Unified mapping interface: Consistent key-value pair format for both status and priority mappings
  • 1:n status mapping: Supports multiple Notion status values for the same TaskWarrior status to accommodate diverse naming conventions
  • Smart relation handling: Automatically fetches related page titles with error handling and ID fallback, plus bidirectional relation ID support for proper sync
  • Intelligent page rendering: Converts Notion block structure to human-readable text annotations preserving formatting
  • Pagination: Handles databases >100 items via cursor-based iteration
  • Archive handling: Filters archived pages server-side, deletes via archive API (no true deletion available)
  • Type safety: Full mypy compliance with explicit type annotations for Notion API responses
  • Flexible property types: Supports multiple Notion property types for the same logical field
  • Optimized comparison: Includes all synced fields (description, status, due, project, priority) in identity checks to prevent unnecessary updates

Documentation

  • User documentation: Comprehensive README in docs/readme-tw-notion-db.md following the same structure as other integrations
  • Main README update: Added link to new documentation in the integrations table
  • Documentation includes usage examples for all field types, installation instructions, Notion setup guidance, and CLI options reference
  • Examples for project synchronization with all three property types (Select, Multi-select, Relation)
  • Examples for both status and priority synchronization with custom mappings using unified format
  • 1:n mapping examples: Demonstrates how to map multiple Notion values to single TW status
  • Relation lookup documentation: Explains automatic title fetching and fallback behavior
  • Annotation examples: Shows both field and page modes with usage scenarios

How Has This Been Tested?

  • Unit tests: 34 comprehensive tests covering property parsing, CRUD operations, pagination, and all property types (status, project, priority, annotations)
  • Type checking: Full mypy compliance with no type errors
  • Code formatting: Black formatting applied and verified
  • Security scan: CodeQL analysis with 0 vulnerabilities detected
  • Integration verification: Converter utilities tested with sample data including project, priority, and annotation fields
  • Import validation: All new modules import successfully
  • Project property tests: All three types (Select, Multi-select, Relation) tested
  • Priority mapping tests: Custom mappings and bidirectional conversion tested
  • Status mapping tests: Updated to use new unified key-value format with 1:n support
  • 1:n status mapping test: Validates multiple Notion values mapping to same TW status
  • Relation title lookup test: Validates successful API call and title extraction
  • Relation fallback test: Validates graceful fallback to ID when API call fails
  • Bidirectional relation test: Validates relation IDs can be written back to Notion
  • Items comparison test: Validates all fields including project and priority are compared correctly
  • Code review feedback: All bot review suggestions implemented (unused imports removed, test assertions fixed, config persistence corrected)

Breaking Changes

Status mapping refactored: The CLI options --status-done and --status-todo have been replaced with a unified --status-map option that uses the same key-value pair format as priority mapping. Users will need to update their commands:

Old format:

--status-done "Complete" --status-done "Finished"

New format:

--status-map "completed:Complete" --status-map "pending:In Progress"

New capability (1:n mapping):

--status-map "completed:Done" \
--status-map "completed:Complete" \
--status-map "completed:Finished"

This provides a more consistent and intuitive interface across all field mappings, while also enabling advanced use cases like 1:n status relationships.

Checklist

  • My code follows the style guidelines of this project
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • Any dependent changes have been merged and published in downstream modules
Original prompt

Technical Specification: NotionDbSide Implementation
Version: 1.0 Target Framework: taskwarrior-syncall (Python) Dependency: notion-client (Official SDK)

  1. Overview
    The NotionDbSide class implements the Side abstract base class from syncall. It facilitates bidirectional synchronization between a specific Notion Database and the syncall internal Item representation.

Key Design Philosophy:

Schema Agnostic: The code must not hardcode column names (e.g., "Status" or "Due Date"). All column names must be injectable parameters.

Type flexibility: The implementation must handle various Notion property types for the same logical field (e.g., "Status" can be a Checkbox, Select, or native Status property).

Sensible Defaults: If no configuration is provided, the system assumes standard Notion template naming conventions.

  1. Configuration & Initialization
    To achieve maximum flexibility, the class constructor will accept a configuration object (or individual parameters) defining the schema mapping.

2.1 Class Signature

Python
class NotionDbSide(Side):
def init(
self,
client: notion_client.Client,
database_id: str,
config: NotionSideConfig = DEFAULT_CONFIG
):
...
2.2 NotionSideConfig Data Structure

This structure holds the dynamic parameters.

Parameter Type Default Value Description
map_field_title str "Name" The name of the Title property in Notion.
map_field_status str "Status" The name of the property tracking completion.
map_field_due str "Due Date" The name of the property tracking the deadline.
map_field_url str None (Optional) Property to store the URL/Link if needed.
status_mapping_kind enum status_prop Defines how status is stored: checkbox, select, or status_prop.
val_status_todo str/list "Not started" Value(s) considered as pending.
val_status_done str/list "Done" Value(s) considered as completed.
3. Data Mapping Logic
This section defines how Notion API responses are parsed into syncall.Item objects and vice versa.

Shutterstock
Explore

3.1 Property: Title (description)

Notion Type: title (Rich Text array).

Read Logic: Concatenate plain_text of all objects in the rich text array.

Write Logic: Create a single Text object: [{"text": {"content": item.description}}].

3.2 Property: Status (status)

This is the most complex field due to the variety of Notion property types. The implementation must switch logic based on status_mapping_kind or auto-detect the type.

Case A: Native Status Property (Recommended default)

Read: Check page['properties'][map_field_status]['status']['name'].

Compare: If name exists in val_status_done, mark as completed. Else pending.

Write: {'status': {'name': val_status_done}}.

Case B: Select / Dropdown

Read: Check page['properties'][map_field_status]['select']['name'].

Write: {'select': {'name': val_status_done}}.

Case C: Checkbox

Read: Check boolean value page['properties'][map_field_status]['checkbox'].

Write: {'checkbox': True} (if done) or False.

3.3 Property: Due Date (due)

Notion Type: date.

Read: Parse start ISO 8601 string to Python datetime. Ignore end date for now.

Write:

If item.due is present: {'date': {'start': item.due.isoformat()}}.

If item.due is None: {'date': None} (to clear the date).

  1. Method Implementation Details
    4.1 get_all_items(self, **kargs) -> List[Item]

Pagination: Must implement a while has_more loop using the start_cursor to ensure databases with >100 items are fully synced.

Filtering: (Optional but recommended) Apply a filter to the API query to exclude archived pages immediately to save bandwidth, though syncall handles logic, fetching only non-archived is safer.

Parsing: Iterate through results. If a required property (e.g., Title) is missing or the page is empty, log a warning and skip the item rather than crashing.

ID Handling: Use page['id'] (UUID) as the item.id.

4.2 add_item(self, item: Item) -> Item

Construct the properties dictionary using the keys defined in NotionSideConfig.

Call client.pages.create.

Important: Return a fresh Item object parsed from the response of the create call. This ensures the local ID database gets the correct UUID assigned by Notion.

4.3 update_item(self, item_id: str, item: Item)

Identify which fields have changed (conceptually). In practice, syncall often pushes the whole state.

Construct properties dictionary.

Optimization: Only include fields that map to description, status, or due. Do not send other properties to avoid overwriting manual changes in Notion.

Call client.pages.update(page_id=item_id, properties=...).

4.4 delete_item(self, item_id: str)

Notion does not "delete" in the traditional sense via API usually.

Action: Set archived: True.

Python
client.pages.update(page_id=item_id, archived=True)
5. Error Handling & Edge Cases
Scenario Behavior
Missing Property If the user configures map_field_due="Deadline" but the column doesn't exist in Notion, the API will throw a 400. Catch this and raise a readable SyncallC...


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@Eckii24
Copy link
Owner

Eckii24 commented Nov 22, 2025

@copilot please add a readme, like we have it for the others as well

Copilot AI changed the title [WIP] Implement NotionDbSide class for bidirectional sync Implement NotionDbSide for schema-agnostic Notion Database synchronization Nov 22, 2025
Copilot AI requested a review from Eckii24 November 22, 2025 13:53
Copy link
Author

Copilot AI commented Nov 22, 2025

@copilot please add a readme, like we have it for the others as well

Added comprehensive documentation in docs/readme-tw-notion-db.md following the same structure as other integrations. The README includes:

  • Description and key features
  • Usage examples with different configurations
  • Installation and setup instructions
  • Notion database setup guidance
  • CLI options reference

Also updated the main README.md to link to the new documentation. See commit 7bc5084.

@Eckii24
Copy link
Owner

Eckii24 commented Nov 22, 2025

I would like to support two more fields:

  • project
  • priority

priority is a simple "select" in notion, but we need to map the values for Medium, high and low.

project is a bit more complex. I would like to support project column of type "select", "multi-select" or "relation".
If the latter is selected, we have to select the relation item based on the title.

@copilot please implement and also provide tests for all of it. Also update the readme accordingly

Copy link
Author

Copilot AI commented Nov 22, 2025

I would like to support two more fields:

  • project
  • priority
    ...

Implemented support for project and priority fields:

Project field:

  • Supports Select, Multi-select, and Relation property types
  • Configured via --map-project and --project-kind options
  • Multi-select takes the first value only
  • Relation stores the relation ID (title lookup would require additional API calls)

Priority field:

  • Maps TaskWarrior priority (H/M/L) to Notion Select values
  • Default mapping: H→High, M→Medium, L→Low
  • Fully customizable via --priority-map option (e.g., --priority-map "H:High" --priority-map "M:Medium")

Added 12 comprehensive tests covering all property types and scenarios. Documentation updated with usage examples. See commit 5f9b5e6.

Copilot AI changed the title Implement NotionDbSide for schema-agnostic Notion Database synchronization Implement NotionDbSide for schema-agnostic Notion Database synchronization with project and priority support Nov 22, 2025
--database-id <database-uuid> \
-t mytasks \
--status-kind select \
--status-done "Complete" \
Copy link
Owner

Choose a reason for hiding this comment

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

I want to have the same logic as for priority: : to add mappings for status.

For both, we need to support 1:n mappings. 1 tw value can be mapped to multiple notion values

@copilot please take over

Copy link
Author

Choose a reason for hiding this comment

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

Could you clarify what you'd like to change? The priority field uses --priority-map to map TaskWarrior values (H/M/L) to custom Notion select values.

Are you asking to:

  1. Change status to use a similar mapping approach (e.g., --status-map "completed:Done" --status-map "pending:Not started") instead of the current --status-done and --status-todo options?
  2. Or something else?

Please let me know so I can implement the correct solution.

Copy link
Owner

Choose a reason for hiding this comment

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

Yes that's exactly what I was asking for @copilot

Copy link
Author

Choose a reason for hiding this comment

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

Implemented! Status mapping now uses the same key-value pair approach as priority mapping.

Changes:

  • Replaced --status-done and --status-todo with unified --status-map option
  • Format: --status-map "completed:Done" --status-map "pending:Not started"
  • Default mapping: pending:Not started, completed:Done

Example:

tw_notion_db_sync \
  --database-id <id> \
  -t mytasks \
  --status-map "completed:Complete" \
  --status-map "pending:In Progress"

This provides a consistent interface across both status and priority mappings. See commit d4da52b.

@Eckii24 Eckii24 marked this pull request as ready for review November 22, 2025 20:04
Copilot AI review requested due to automatic review settings November 22, 2025 20:04
Copy link
Owner

@Eckii24 Eckii24 left a comment

Choose a reason for hiding this comment

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

@copilot Take over

for mapping in status_map:
if ":" in mapping:
tw_status, notion_value = mapping.split(":", 1)
parsed_status_map[tw_status.strip()] = notion_value.strip()
Copy link
Owner

Choose a reason for hiding this comment

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

We should support a 1:n relationship, because we can have multiple notion states for a single tw state

Copy link
Author

Choose a reason for hiding this comment

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

Implemented 1:n status mapping! Now multiple Notion status values can map to the same TaskWarrior status.

Example usage:

--status-map "completed:Done" \
--status-map "completed:Complete" \
--status-map "completed:Finished" \
--status-map "pending:Not started" \
--status-map "pending:To Do"

The CLI automatically groups multiple values for the same TW status. When creating items, it uses the first value from the list. See commit 92d7234.

prop_type == "relation"
or self._config.project_mapping_kind == ProjectMappingKind.RELATION
):
# Relation - we need to fetch the related page to get its title
Copy link
Owner

Choose a reason for hiding this comment

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

Implement this right away!!

Copy link
Author

Choose a reason for hiding this comment

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

Implemented! Relation-type project properties now automatically fetch the related page and extract its title.

How it works:

  • Makes API call to retrieve the related page
  • Extracts the title property from the page
  • Falls back to relation ID if API call fails or title not found
  • Includes proper error handling and logging

The feature works automatically when using --project-kind relation. See commit 92d7234.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR implements NotionDbSide, a new bidirectional synchronization integration between Notion Databases and TaskWarrior. Unlike the existing tw_notion_sync which syncs to-do blocks within a page, this provides database-level synchronization with flexible, schema-agnostic configuration.

Key Changes:

  • Full SyncSide implementation with pagination, CRUD operations, and configurable property mappings for title, status, due date, project, and priority fields
  • New CLI command tw_notion_db_sync with runtime schema customization options
  • Support for multiple Notion property types (Status/Select/Checkbox for completion, Select/Multi-select/Relation for projects)
  • Unified mapping format for both status and priority using key-value pairs

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
syncall/notion/notion_db_side.py Core NotionDbSide class implementing schema-agnostic database synchronization with flexible property type support
syncall/tw_notion_db_utils.py Bidirectional converter utilities for TaskWarrior ↔ NotionDb item transformation
syncall/scripts/tw_notion_db_sync.py New CLI script with configuration parsing, mapping options, and sync orchestration
tests/test_notion_db_side.py Comprehensive test suite with 31 tests covering CRUD operations, pagination, and all property types
syncall/cli.py Extended CLI options for database ID and field mapping configuration
syncall/notion/__init__.py Updated module exports to include new NotionDbSide classes and enums
pyproject.toml Added tw_notion_db_sync entry point
docs/readme-tw-notion-db.md Comprehensive user documentation with usage examples and setup instructions
README.md Added link to NotionDb integration documentation

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

ignore_keys = []

# Compare relevant keys
keys_to_compare = ["description", "status", "due"]
Copy link

Copilot AI Nov 22, 2025

Choose a reason for hiding this comment

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

The items_are_identical method doesn't include project and priority fields in the comparison, even though these fields are now being synchronized. This could cause unnecessary updates when only these fields change. Consider adding them to keys_to_compare:

keys_to_compare = ["description", "status", "due", "project", "priority"]
Suggested change
keys_to_compare = ["description", "status", "due"]
keys_to_compare = ["description", "status", "due", "project", "priority"]

Copilot uses AI. Check for mistakes.
Comment on lines 166 to 180
config_args={
"database_id": database_id,
"tw_filter_li": tw_filter_li,
"tw_project": tw_project,
"tw_tags": tw_tags,
"map_title": map_title,
"map_status": map_status,
"map_due": map_due,
"map_project": map_project,
"map_priority": map_priority,
"status_map": list(status_map),
"status_kind": status_kind,
"project_kind": project_kind,
"priority_map": list(priority_map),
},
Copy link

Copilot AI Nov 22, 2025

Choose a reason for hiding this comment

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

The tw_sync_all_tasks parameter is missing from the config_args dictionary when caching the configuration. This means if a user saves a configuration with --tw-sync-all-tasks, it won't be persisted and will need to be specified again on subsequent runs. Add "tw_sync_all_tasks": tw_sync_all_tasks to the config_args dictionary.

Copilot uses AI. Check for mistakes.
Comment on lines 356 to 362
# For relation, we would need to search for the page by title
# This requires additional API calls and database ID of the related database
# For now, we'll log a warning
logger.warning(
"Relation project mapping not yet fully implemented - requires page lookup"
)
return None
Copy link

Copilot AI Nov 22, 2025

Choose a reason for hiding this comment

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

The relation project mapping has asymmetric behavior: it can read relation IDs (line 257) but cannot write them back (lines 355-362). When a project is synced from Notion using a relation property, it stores the relation ID. However, when updating or creating an item with that relation ID, the code just logs a warning and doesn't set the relation.

To fix this for write operations, the code should attempt to create a relation using the provided ID:

elif self._config.project_mapping_kind == ProjectMappingKind.RELATION:
    # Assume project is a relation ID
    return {"relation": [{"id": project}]}

This would allow bidirectional sync to work properly with relation properties.

Suggested change
# For relation, we would need to search for the page by title
# This requires additional API calls and database ID of the related database
# For now, we'll log a warning
logger.warning(
"Relation project mapping not yet fully implemented - requires page lookup"
)
return None
# Assume project is a relation ID
return {"relation": [{"id": project}]}

Copilot uses AI. Check for mistakes.
"priority": "M",
}

result = side.add_item(new_item)
Copy link

Copilot AI Nov 22, 2025

Choose a reason for hiding this comment

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

Variable result is not used.

Suggested change
result = side.add_item(new_item)
result = side.add_item(new_item)
assert result == mock_response

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,600 @@
"""Tests for NotionDbSide implementation."""
import datetime
from unittest.mock import Mock, MagicMock
Copy link

Copilot AI Nov 22, 2025

Choose a reason for hiding this comment

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

Import of 'MagicMock' is not used.

Suggested change
from unittest.mock import Mock, MagicMock
from unittest.mock import Mock

Copilot uses AI. Check for mistakes.
Comment on lines 6 to 7
from dateutil.tz import tzutc

Copy link

Copilot AI Nov 22, 2025

Choose a reason for hiding this comment

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

Import of 'tzutc' is not used.

Suggested change
from dateutil.tz import tzutc

Copilot uses AI. Check for mistakes.
Copilot AI changed the title Implement NotionDbSide for schema-agnostic Notion Database synchronization with project and priority support Implement NotionDbSide for schema-agnostic Notion Database synchronization with 1:n status mapping and relation title lookup Nov 22, 2025
Copilot AI requested a review from Eckii24 November 22, 2025 20:13
@Eckii24
Copy link
Owner

Eckii24 commented Nov 22, 2025

@copilot

I want to have support for task warrior annotations.
Please add for this a new parameter with description-kind with possible values "field" and "page".
if field is selected, the field with the name of new parameter map-description is added as annotation.

if page is selected (also the default) the page needs to be rendered and added as annotation to the task.

Copy link
Author

Copilot AI commented Nov 22, 2025

@copilot

I want to have support for task warrior annotations.
...

Implemented TaskWarrior annotations support with both modes:

Field mode:

--description-kind field --map-description "Notes"

Extracts annotation from a Notion property (supports Rich Text and Title types).

Page mode (default):

--description-kind page

Renders the entire Notion page content as annotation, preserving structure:

  • Headings (# prefix)
  • Lists (• and -)
  • Checkboxes ([x]/[ ])
  • Code blocks (```)
  • Paragraphs

The page content is intelligently converted to formatted text that works well as TaskWarrior annotations. See commit 8a06b9f.

Copilot AI changed the title Implement NotionDbSide for schema-agnostic Notion Database synchronization with 1:n status mapping and relation title lookup Implement NotionDbSide for schema-agnostic Notion Database synchronization with annotations, 1:n status mapping, and relation support Nov 22, 2025
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