feat: preserve full Note Tweets across sync and rendering - #134
Conversation
|
🦞👀 Pull request received. I will update this pull request when review starts. |
|
Codex review: found issues before merge. Reviewed September 1, 2026, 7:39 AM ET / 11:39 UTC. ClawSweeper reviewWhat this changesThe PR stores full X Note Tweet text and entities through local ingestion, search, backups, read models, exports, and an expandable 280-code-point presentation. Merge readinessKeep open: the Note Tweet retention work has credible real-data proof, but its introduced schema-v9 writer breaks existing shared-backup sync with v0.12.1 readers unless maintainers choose and implement a compatibility or coordinated-migration contract. Priority: P1 Review scores
Verification
How this fits togetherBirdclaw fetches tweet data from Xurl, stores and indexes it locally, then exposes it through timeline views, exports, and Git-backed backups. This PR changes the canonical tweet representation and the backup interchange format consumed by other Birdclaw installations. flowchart LR
A[Xurl tweet payload] --> B[Canonical tweet storage]
B --> C[Full-text search]
B --> D[Timeline and exports]
B --> E[Git backup]
E --> F[Other Birdclaw installations]
D --> G[Expandable tweet rendering]
Decision needed
Why: The PR documents a simultaneous-upgrade requirement but does not prevent an upgraded device from making an existing shared repository unreadable to another supported installation. Before merge
Findings
Agent review detailsSecurityNone. Review metrics
Merge-risk optionsMaintainer options:
Technical reviewBest possible solution: Adopt a maintainer-approved backup upgrade contract that either preserves supported shared-repository compatibility or visibly gates a coordinated migration with recovery, then add mixed-version sync coverage. Do we have a high-confidence way to reproduce the issue? Yes—source proves the deterministic path: this PR writes schema v9 while the unchanged v0.12.1 reader rejects every manifest above v8 before importing rows. Is this the best way to solve the issue? No—the retention implementation is broadly coherent, but a documentation-only simultaneous-upgrade instruction is not a safe replacement for an explicit shared-backup compatibility or migration contract. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: not found in the target repository. Codex review notes: model internal, reasoning high; reviewed against 658b979c7e93. LabelsLabel justifications:
EvidenceWhat I checked:
Likely related people:
Rank-up movesOptional improvements that raise the rating; they are not merge blockers.
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
HistoryReview history (19 earlier review cycles; latest 8 shown)
|
Problem
Birdclaw currently stores Xurl's top-level
textfor every tweet. For a Note Tweet, that field is only a compatibility preview; the complete body and its entities live undernote_tweet.This truncates Note Tweets in the database, full-text search, exports, profile analysis, research, replies, quotes, and retweets.
note_tweet.textand its matching entitiesChange
Xurl tweet requests now include
note_tweet. A shared content helper chooses the Note Tweet body and entities when present.The canonical representation is stored as:
tweets.text: complete Note Tweet bodytweets.entities_json: entities belonging to the complete bodytweets.note_tweet_json: durable marker containing the Note Tweet body and entitiestweets_fts: indexed from the canonical stored textThe marker lets ingestion distinguish a complete Note Tweet from a later payload that carries only the top-level preview. Archive and backup merges use the same rule: the richer marked representation wins.
Read models propagate the marker through primary timeline items, replies, quotes, retweets, and conversations. Backup schema version 9 carries it through export, replace, and merge.
New readers continue importing schemas 1–8. Birdclaw 0.12.1 and older reject v9 backups, so every installation sharing a backup repository must be upgraded before its first v9 export or sync.
The shared rich-text renderer uses that marker to reproduce X's browsing behavior:
Scope
Xurl's
note_tweetfield is the source of the Note Tweet marker.Archive imports continue to use archive tweet text. When an archive row meets an Xurl-marked Note Tweet, the marked full body remains canonical.
Tweet edit histories continue through the existing revision path.
Ordinary tweets continue rendering their complete stored text. Note Tweets use the shared collapsed renderer everywhere
TimelineCard,EmbeddedTweetCard, orConversationThreadis used.Real behavior proof
This was exercised against a personal Likes database populated through Xurl.
The following read-only query compares the retained raw Xurl payload with the canonical tweet row and FTS entry:
{ "xurl_note_tweets": 1511, "stored_full_text": 1511, "full_text_longer_than_preview": 1425, "fts_contains_full_text": 1511 }All 1,511 raw Xurl Note Tweets use the complete
note_tweet.textas their canonical stored and indexed body. In 1,425 cases, that body is longer than Xurl's top-level preview.Tests
Backend coverage verifies:
note_tweetarrivesnote_tweetfieldFrontend coverage verifies: