Frontmatter
| id | 7948 |
| title | Enhancement: Timeline-Based Relationship Discovery for Issue Sync |
| state | Closed |
| labels | enhancementai |
| assignees | tobiu |
| createdAt | Nov 30, 2025, 1:28 PM |
| updatedAt | Nov 30, 2025, 1:41 PM |
| githubUrl | https://github.com/neomjs/neo/issues/7948 |
| author | tobiu |
| commentsCount | 0 |
| parentIssue | null |
| subIssues | [] |
| subIssuesCompleted | 0 |
| subIssuesTotal | 0 |
| blockedBy | [] |
| blocking | [] |
| closedAt | Nov 30, 2025, 1:41 PM |
Enhancement: Timeline-Based Relationship Discovery for Issue Sync
tobiu assigned to @tobiu on Nov 30, 2025, 1:29 PM
tobiu closed this issue on Nov 30, 2025, 1:41 PM
tobiu cross-referenced by PR #10091 on Apr 19, 2026, 1:35 PM
tobiu cross-referenced by #10092 on Apr 19, 2026, 1:44 PM
tobiu cross-referenced by PR #10093 on Apr 19, 2026, 2:00 PM
tobiu cross-referenced by #10094 on Apr 19, 2026, 2:20 PM
tobiu cross-referenced by #10110 on Apr 19, 2026, 11:40 PM
tobiu cross-referenced by PR #10111 on Apr 19, 2026, 11:53 PM
Context
We recently implemented a "Child-Triggered Parent Refresh" strategy to fix sync gaps where adding a sub-issue didn't update the parent's
updatedAttimestamp. This works well for parent-child relationships.Problem
The current logic only checks
issue.parent. It does not handle:updatedAt.Proposed Solution: Timeline-Based Discovery
Extend the post-processing logic in
IssueSyncer.mjsto scan thetimelineItemsof all fetched issues.allIssues(the ones just pulled).SUB_ISSUE_ADDED,BLOCKED_BY_ADDED, etc.) that occurred since the last sync.event.subIssue.number,event.blockingIssue.number, etc.).forceUpdateset (merging with the existingissue.parentlogic).Implementation
Refactor the
parentIdsToUpdatelogic into a broaderrelatedIssuesToUpdateset.const relatedIssuesToUpdate = new Set(); allIssues.forEach(issue => { // 1. Existing Parent Check if (issue.parent) { relatedIssuesToUpdate.add(issue.parent.number); } // 2. New Timeline Scan const relationshipEvents = issue.timelineItems?.nodes.filter(event => ['SUB_ISSUE_ADDED_EVENT', 'BLOCKED_BY_ADDED_EVENT', /* ... all types */].includes(event.__typename) && new Date(event.createdAt) > new Date(metadata.lastSync) ); relationshipEvents?.forEach(event => { if (event.subIssue) relatedIssuesToUpdate.add(event.subIssue.number); if (event.parent) relatedIssuesToUpdate.add(event.parent.number); if (event.blockingIssue) relatedIssuesToUpdate.add(event.blockingIssue.number); if (event.blockedIssue) relatedIssuesToUpdate.add(event.blockedIssue.number); }); });This ensures complete referential integrity for all relationship types.