Skip to content

Expand Notion cyclic e2e coverage#18

Open
misrasaurabh1 wants to merge 18 commits into
mainfrom
e2e/notion-cyclic-coverage
Open

Expand Notion cyclic e2e coverage#18
misrasaurabh1 wants to merge 18 commits into
mainfrom
e2e/notion-cyclic-coverage

Conversation

@misrasaurabh1

@misrasaurabh1 misrasaurabh1 commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Render valid Notion link_to_page blocks and page/database mentions as normal Markdown links to Notion URLs instead of internal AFS directives.
  • Render URL-shaped blocks as Markdown where safe: bookmark, embed, link_preview, and URL-backed media blocks.
  • Expand live mounted Notion cyclic tests to cover diverse block read/no-op integrity, supported block edit/push/verify behavior, mounted database row read/edit/create cycles, and rich frontmatter property round trips.
  • Add writable support for existing bookmark/embed URL blocks, existing URL-backed image/video/file/pdf/audio media blocks, existing stable-width/header-mode Notion tables with row add/delete, external URL files properties, explicit-ID people properties, explicit-ID relation properties, explicit @date(...) and @user(...) mentions, explicit @page(...) / @database(...) typed page/database mentions, and rich-text properties using the same inline Markdown parser as page bodies.
  • Preserve typed database mentions when editing rendered Markdown database links whose target ID is unchanged.
  • Keep link_to_page target edits blocked with a specific guardrail after live testing showed Notion accepts direct target PATCHes but returns the original target unchanged.
  • Keep rich-text link-preview mentions read-only after live testing showed Notion rejects mention.link_preview in page child rich-text write payloads.
  • Fix bugs discovered by cyclic tests: residual same-shape diff alignment, database row create preflight metadata lookup, Notion media update payload shape, live unique-ID prefix collisions, live fixture schema selection across multiple databases, and silent link_to_page target PATCH behavior.
  • Document the new support behavior, Markdown examples, bug findings, and remaining limitations in the Notion support matrix/journals.

Markdown Contract Examples

  • Page link block or mention: [Linked page](https://www.notion.so/<page-id>)
  • Database link block or mention: [Tasks](https://www.notion.so/<database-id>)
  • Explicit page mention write: @page(<notion-page-id>) or @page(Name <notion-page-id>)
  • Explicit database mention write: @database(<notion-database-id>) or @database(Name <notion-database-id>)
  • Explicit date mention write: @date(2026-06-14) or @date(2026-06-14 to 2026-06-21, tz=America/Chicago)
  • Explicit user mention write: @user(<notion-user-id>) or @user(Name <notion-user-id>)
  • Rich-text property frontmatter: Notes: "Created **row** notes and [docs](https://example.com/created-notes)"
  • Bookmark/embed/link preview: [Caption](https://example.com/resource)
  • Image media: ![Caption](https://example.com/image.png)
  • Other media: [Caption](https://example.com/file.pdf)
  • External file property frontmatter:
Files:
  - Spec <https://example.com/spec.pdf>
  - https://example.com/diagram.png
  • People property frontmatter:
People:
  - Ada <11111111-1111-1111-1111-111111111111>
  • Relation property frontmatter:
Related:
  - "22222222-2222-2222-2222-222222222222"
  • Same-shape table edit with row add/delete:
| Name | Status |
| --- | --- |
| Updated task | Done |
| Added task | Next |

Media uploads and appending new media blocks are still deferred; this PR only supports edits to existing URL-backed media blocks and external URL file properties. People property writes and explicit user mentions require explicit Notion user IDs; name/email lookup is deferred. Relation writes require explicit Notion page IDs; path/title resolution is deferred. Plain Notion URLs remain ambiguous for newly-authored database mentions without a preimage, so @database(...) is the canonical creation syntax. Direct link_to_page retargeting remains blocked until AFS has undo-aware block replacement. Link-preview blocks and rich-text link-preview mentions are read-only because live Notion write validation rejected those shapes. Table width changes and header-mode changes are still blocked.

Verification

Local:

  • cargo fmt --all -- --check
  • cargo test --workspace --all-targets
  • cargo test -p afs-core --test block_diff
  • cargo test -p afs-notion --test apply -p afs-notion --test fetch_render
  • cargo test -p afs-cli --test e2e_push_workflow
  • cargo test -p afs-cli --test e2e_push_workflow live_cyclic_supported_block_edits_push_and_verify_notion -- --ignored --test-threads=1 --nocapture
  • cargo test -p afs-cli --test e2e_push_workflow live_cyclic_database_rows_mount_edit_create_and_verify_notion -- --ignored --test-threads=1 --nocapture

Live Notion scratch workspace:

  • cargo test -p afs-cli --test e2e_push_workflow live_ -- --ignored --test-threads=1 --nocapture
  • cargo test -p afs-notion --test live_integrity -- --ignored --test-threads=1 --nocapture

Remote:

  • PR CI Linux/macOS checks pass for a843025.
  • Manual notion-live-e2e workflow dispatch passes for e2e/notion-cyclic-coverage at code head 4a03c31 (run 27469672789); the newer a843025 commit is documentation-only.

Notes

  • The live tests create scratch pages/databases under the configured e2e Notion root and archive them during cleanup.
  • Database mention retargeting from an existing rendered link is supported only when the preimage identifies the target as a database mention; otherwise use @database(...).
  • link_to_page target replacement is intentionally deferred because it requires append/delete replacement and journal/undo support for changed block identity.
  • Local filesystem-relative links between projected Notion pages still need a store-aware render context and should be designed separately from connector-only Markdown rendering.

@misrasaurabh1

Copy link
Copy Markdown
Contributor Author

Verification update: normal PR CI is green on Linux/macOS. I also dispatched notion-live-e2e on this branch (run 27461193648), and both live connector integrity plus mounted workflow live e2e passed against the scratch Notion workspace.

@misrasaurabh1

Copy link
Copy Markdown
Contributor Author

Follow-up verification update: added mounted database-row cyclic coverage. The live mounted workflow now hydrates an existing database row, no-op pushes with unchanged Notion state, edits row frontmatter/body and verifies through the Notion API, then creates a new row from a Markdown file under the database directory. Local cargo test --workspace --all-targets passes, PR Linux/macOS CI passes, and manual notion-live-e2e run 27462030389 passes on this branch.

@misrasaurabh1

Copy link
Copy Markdown
Contributor Author

Follow-up verification update: bookmark and embed blocks now render as editable Markdown links instead of AFS directives. Existing bookmark/embed blocks preserve their Notion block kind when the Markdown link label or URL is edited. Local cargo test --workspace --all-targets passes; live mounted workflow and connector live integrity pass locally; PR Linux/macOS CI passes; manual notion-live-e2e run 27462726443 passes on this branch.

@misrasaurabh1

Copy link
Copy Markdown
Contributor Author

Updated this PR with external media URL block edit support. Existing image/video/file/pdf/audio blocks now round-trip as Markdown image/link syntax and can be edited/pushed back as Notion external media URLs.\n\nVerification on commit faf7f88:\n- cargo fmt --all -- --check\n- cargo test --workspace --all-targets\n- cargo test -p afs-notion --test apply -p afs-notion --test fetch_render\n- cargo test -p afs-cli --test e2e_push_workflow\n- live: cargo test -p afs-cli --test e2e_push_workflow live_ -- --ignored --test-threads=1 --nocapture\n- live: cargo test -p afs-notion --test live_integrity -- --ignored --test-threads=1 --nocapture\n- remote PR CI Linux/macOS: pass\n- manual notion-live-e2e workflow dispatch: pass\n\nLive testing caught one real bug: Notion accepts type: external when creating media blocks, but rejects that field on block update. The writer now sends only external.url and caption for media updates, and the journal records the finding.

@misrasaurabh1

Copy link
Copy Markdown
Contributor Author

Follow-up pushed as 3e19410: the live supported-edit cycle now changes media URLs as well as captions for image/video/file/pdf/audio blocks, then verifies the updated Markdown projection from a fresh Notion API render.\n\nAdditional verification:\n- local focused: cargo fmt --all -- --check\n- local focused: cargo test -p afs-cli --test e2e_push_workflow\n- live focused: cargo test -p afs-cli --test e2e_push_workflow live_cyclic_supported_block_edits_push_and_verify_notion -- --ignored --test-threads=1 --nocapture\n- remote PR CI Linux/macOS on 3e19410: pass\n- manual notion-live-e2e workflow dispatch on 3e19410: pass

@misrasaurabh1

Copy link
Copy Markdown
Contributor Author

Follow-up pushed as 572d745: link-preview blocks now render as ordinary Markdown links instead of AFS directives when Notion returns a URL. Writes remain blocked because live create-page testing rejected link_preview child blocks.\n\nVerification on latest head:\n- cargo fmt --all -- --check\n- cargo test -p afs-notion --test fetch_render\n- cargo test --workspace --all-targets\n- remote PR CI Linux/macOS: pass\n- manual notion-live-e2e workflow dispatch: pass

@misrasaurabh1

Copy link
Copy Markdown
Contributor Author

Follow-up pushed as 99390cd: same-shape Notion table cell edits are now supported. The planner emits a table block update, the Notion connector updates the corresponding table_row.cells, and the live mounted edit cycle verifies the rendered result from the Notion API.\n\nThis also fixes a live-test fixture bug where a fixed unique-ID prefix could collide across repeated scratch database runs.\n\nVerification on latest head:\n- cargo fmt --all -- --check\n- cargo test --workspace --all-targets\n- cargo test -p afs-core --test block_diff\n- cargo test -p afs-notion --test apply -p afs-notion --test fetch_render\n- cargo test -p afs-cli --test e2e_push_workflow\n- live: cargo test -p afs-cli --test e2e_push_workflow live_ -- --ignored --test-threads=1 --nocapture\n- live: cargo test -p afs-notion --test live_integrity -- --ignored --test-threads=1 --nocapture\n- remote PR CI Linux/macOS: pass\n- manual notion-live-e2e workflow dispatch: pass

@misrasaurabh1

Copy link
Copy Markdown
Contributor Author

Follow-up pushed as 7918377: external URL file properties are now writable from page/database frontmatter. Agents can use either https://example.com/file.pdf or Name <https://example.com/file.pdf> entries; AFS writes those as Notion external file property objects. Hosted/uploaded Notion files remain read-only/deferred.

Verification on latest head:

  • cargo fmt --all -- --check
  • cargo test --workspace --all-targets
  • cargo test -p afs-notion --test apply -p afs-notion --test fetch_render
  • cargo test -p afs-cli --test e2e_push_workflow
  • live: cargo test -p afs-cli --test e2e_push_workflow live_ -- --ignored --test-threads=1 --nocapture
  • live: cargo test -p afs-notion --test live_integrity -- --ignored --test-threads=1 --nocapture
  • remote PR CI Linux/macOS: pass
  • manual notion-live-e2e workflow dispatch: pass

@misrasaurabh1

Copy link
Copy Markdown
Contributor Author

Follow-up pushed as 7dd37c5: relation properties are now writable using explicit Notion page IDs. Frontmatter can use a string, a YAML list, or an empty/null value to clear; path/title lookup remains deferred. Live testing also caught two fixture-level details: current Notion relation schemas require single_property: {} or dual_property, and unique-ID prefixes must start with a letter.

Verification on latest head:

  • cargo fmt --all -- --check
  • cargo test --workspace --all-targets
  • cargo test -p afs-notion --test apply -p afs-notion --test fetch_render
  • cargo test -p afs-cli --test e2e_push_workflow
  • live: cargo test -p afs-cli --test e2e_push_workflow live_ -- --ignored --test-threads=1 --nocapture
  • live: cargo test -p afs-notion --test live_integrity -- --ignored --test-threads=1 --nocapture
  • remote PR CI Linux/macOS: pass
  • manual notion-live-e2e workflow dispatch: pass

@misrasaurabh1

Copy link
Copy Markdown
Contributor Author

Follow-up pushed as 70a3bdf: people properties are now writable using explicit Notion user IDs. Rendered people entries now use Name <user-id> when Notion provides both, and the writer accepts that emitted shape, raw user IDs, empty strings, null, or empty lists for clearing. Name/email lookup remains intentionally deferred.

Verification on latest head:

  • cargo fmt --all -- --check
  • cargo test --workspace --all-targets
  • cargo test -p afs-notion --test apply -p afs-notion --test fetch_render
  • cargo test -p afs-cli --test e2e_push_workflow
  • live: cargo test -p afs-cli --test e2e_push_workflow live_ -- --ignored --test-threads=1 --nocapture
  • live: cargo test -p afs-notion --test live_integrity -- --ignored --test-threads=1 --nocapture
  • remote PR CI Linux/macOS: pass
  • manual notion-live-e2e workflow dispatch: pass

@misrasaurabh1

Copy link
Copy Markdown
Contributor Author

Follow-up pushed as 0551db8: database mention Markdown links now preserve their typed mention.database payload when the rendered link label changes but the target ID stays the same. The live diverse cyclic page now creates both a rich-text database mention and a database link_to_page block and verifies read/no-op integrity against live Notion.

Verification on latest head:

  • cargo fmt --all -- --check
  • cargo test --workspace --all-targets
  • cargo test -p afs-notion --test apply -p afs-notion --test fetch_render
  • cargo test -p afs-cli --test e2e_push_workflow
  • live: cargo test -p afs-cli --test e2e_push_workflow live_ -- --ignored --test-threads=1 --nocapture
  • live: cargo test -p afs-notion --test live_integrity -- --ignored --test-threads=1 --nocapture
  • remote PR CI Linux/macOS: pass
  • manual notion-live-e2e workflow dispatch: pass

@misrasaurabh1

Copy link
Copy Markdown
Contributor Author

Follow-up pushed as 0311905: explicit rich-text date mention writes are now supported with @date(YYYY-MM-DD) and range/timezone syntax such as @date(2026-06-14 to 2026-06-21, tz=America/Chicago). The live supported-edit cycle now edits a real Notion date mention through mounted Markdown and verifies the fresh Notion render.

This also adds a specific guardrail for link_to_page retargeting. A live scratch API probe showed Notion accepts PATCH /blocks/{link_to_page} with a new target but returns the original target unchanged, so AFS blocks that edit before mutation until we add undo-aware block replacement.

Verification on latest head:

  • cargo fmt --all -- --check
  • cargo test --workspace --all-targets
  • cargo test -p afs-notion --test apply -- --nocapture
  • live focused: cargo test -p afs-cli --test e2e_push_workflow live_cyclic_supported_block_edits_push_and_verify_notion -- --ignored --test-threads=1 --nocapture
  • live full mounted workflow before final syntax validation: cargo test -p afs-cli --test e2e_push_workflow live_ -- --ignored --test-threads=1 --nocapture
  • live connector integrity before final syntax validation: cargo test -p afs-notion --test live_integrity -- --ignored --test-threads=1 --nocapture

@misrasaurabh1

Copy link
Copy Markdown
Contributor Author

Remote verification update for 0311905: PR CI is now green on Linux and macOS after rerunning a flaky macOS daemon runtime test. The manual notion-live-e2e workflow dispatch also passed on the latest branch head (run 27468559779).

@misrasaurabh1

Copy link
Copy Markdown
Contributor Author

Follow-up pushed as 186492e: explicit rich-text user mention writes are now supported with @user(<notion-user-id>) and @user(Name <notion-user-id>). The live supported-edit cycle now rewrites a real Notion user mention through mounted Markdown using the token bot user ID from /v1/users/me and verifies the line survives a fresh Notion render.

Verification before push:

  • cargo fmt --all -- --check
  • cargo test -p afs-notion --test apply -- --nocapture
  • cargo test --workspace --all-targets
  • live focused: cargo test -p afs-cli --test e2e_push_workflow live_cyclic_supported_block_edits_push_and_verify_notion -- --ignored --test-threads=1 --nocapture

I dispatched CI and will dispatch/watch the remote live workflow for this new head as well.

@misrasaurabh1

Copy link
Copy Markdown
Contributor Author

Remote verification update for 186492e: PR CI is green on Linux and macOS, and manual notion-live-e2e workflow dispatch passed on the latest branch head (run 27468792596).

@misrasaurabh1

Copy link
Copy Markdown
Contributor Author

Follow-up pushed as ceaf555: existing Notion tables now support stable-width/header-mode row additions and trailing row deletions. The table updater now updates existing row cells, appends new table_row children for additional Markdown rows, and archives removed trailing row blocks.

Verification before push:

  • cargo fmt --all -- --check
  • cargo test -p afs-notion --test apply -- --nocapture
  • cargo test --workspace --all-targets
  • live focused: cargo test -p afs-cli --test e2e_push_workflow live_cyclic_supported_block_edits_push_and_verify_notion -- --ignored --test-threads=1 --nocapture

The live supported-edit cycle now appends a real row to a Notion table and verifies it from a fresh Notion render.

@misrasaurabh1

Copy link
Copy Markdown
Contributor Author

Remote verification update for ceaf555: PR CI is green on Linux and macOS, and manual notion-live-e2e workflow dispatch passed on the latest branch head (run 27468998239).

@misrasaurabh1

Copy link
Copy Markdown
Contributor Author

Update pushed: ccc890d adds explicit Notion page/database mention write syntax (@page(...), @database(...)) with fixture coverage, live supported-edit coverage, and docs updates.

Verification:

  • cargo fmt --all -- --check
  • cargo test -p afs-notion --test apply -- --nocapture
  • focused live supported-edit Notion cycle
  • cargo test --workspace --all-targets
  • remote Linux/macOS PR CI pass
  • manual notion-live-e2e pass: run 27469259554

@misrasaurabh1 misrasaurabh1 deployed to notion-live-e2e June 13, 2026 14:35 — with GitHub Actions Active
@misrasaurabh1

Copy link
Copy Markdown
Contributor Author

Update pushed: 4a03c31 preserves rich-text Markdown in Notion page/database-row properties. Rich-text frontmatter now renders/writes with the same inline parser used for page bodies, including annotations, links, and supported explicit mentions.

Verification:

  • cargo fmt --all -- --check
  • cargo test -p afs-notion --test apply -p afs-notion --test fetch_render -- --nocapture
  • live mounted database-row edit/create cycle
  • cargo test --workspace --all-targets
  • remote Linux/macOS PR CI pass
  • manual notion-live-e2e pass: run 27469672789

@misrasaurabh1

Copy link
Copy Markdown
Contributor Author

Update pushed: a843025 documents the live Notion result for rich-text link-preview mentions: the API currently rejects mention.link_preview in page child rich-text write payloads, so the connector keeps that shape read-only rather than adding fixture-only writer support.

Remote Linux/macOS PR CI passes for a843025. The latest manual live workflow still applies to code head 4a03c31; a843025 is documentation-only.

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