Context
Sub of #12186 (P2). Two IssueSyncer efficiency/correctness bugs, grounded against the code. (The wgr9t499x investigation mislocated the O(N²) at :990; corrected here to :1007.)
Findings (grounded)
1. needsUpdate reads a non-existent field → every issue re-rendered every sync.
IssueSyncer.mjs:624 compares oldIssue.updated !== issue.updatedAt, but the persisted metadata field is updatedAt (MetadataManager.mjs:83; IssueSyncer.mjs:156/664/830/1013 all write updatedAt, never updated). So oldIssue.updated is always undefined → needsUpdate is always true → every delta issue is re-formatted, re-hashed and re-written every run; the content-hash short-circuit never engages.
→ Fix: :624 → oldIssue.updatedAt !== issue.updatedAt.
2. #planBuckets recomputed per-iteration in the reconcile loop (loop-invariant → O(N²)).
IssueSyncer.mjs:1007 calls this.#planBuckets(metadata) inside the per-issue reconcile loop, but its only input (metadata) is loop-invariant, so the identical plan is rebuilt for every archived issue. The main pull path is already correct (:572 precomputes once; the loop does O(1) planBuckets.get()) — the reconcile path should mirror it.
→ Fix: hoist the :1007 #planBuckets(metadata) above its loop.
(:808 in refetchIssuesByNumber also calls per-iteration, but with a changing [issue] arg and typically small K — minor; verify at implementation.)
Acceptance Criteria
Related
Retrieval Hint: grep planBuckets + needsUpdate + oldIssue.updated in IssueSyncer.mjs.
Context
Sub of #12186 (P2). Two
IssueSyncerefficiency/correctness bugs, grounded against the code. (The wgr9t499x investigation mislocated the O(N²) at:990; corrected here to:1007.)Findings (grounded)
1.
needsUpdatereads a non-existent field → every issue re-rendered every sync.IssueSyncer.mjs:624comparesoldIssue.updated !== issue.updatedAt, but the persisted metadata field isupdatedAt(MetadataManager.mjs:83;IssueSyncer.mjs:156/664/830/1013all writeupdatedAt, neverupdated). SooldIssue.updatedis alwaysundefined→needsUpdateis alwaystrue→ every delta issue is re-formatted, re-hashed and re-written every run; the content-hash short-circuit never engages. → Fix::624→oldIssue.updatedAt !== issue.updatedAt.2.
#planBucketsrecomputed per-iteration in the reconcile loop (loop-invariant → O(N²)).IssueSyncer.mjs:1007callsthis.#planBuckets(metadata)inside the per-issue reconcile loop, but its only input (metadata) is loop-invariant, so the identical plan is rebuilt for every archived issue. The main pull path is already correct (:572precomputes once; the loop does O(1)planBuckets.get()) — the reconcile path should mirror it. → Fix: hoist the:1007#planBuckets(metadata)above its loop. (:808inrefetchIssuesByNumberalso calls per-iteration, but with a changing[issue]arg and typically small K — minor; verify at implementation.)Acceptance Criteria
:624comparesoldIssue.updatedAt; unchanged issues skip re-render/re-hash (content-hash short-circuit verified to engage).#planBuckets(metadata)computed once per reconcile run (:1007hoisted), not per issue.:572) unchanged.updatedAtshort-circuit (unchanged issue → not re-pulled).Related
Retrieval Hint: grep
planBuckets+needsUpdate+oldIssue.updatedinIssueSyncer.mjs.