mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-15 09:56:06 +00:00
* fix(workboard): resolve parent dependency status via targeted lookups, not a full-corpus scan dependencyTargetStatus() called the fully unscoped store.list() (every card, every board, fully materialized via entries()+readCard()) just to look up the status of a card's own parent id(s) -- almost always exactly one. dispatch() calls promoteDependencyReady() once per card in its board-scoped pass, so every parented card in that pass re-paid for a full-corpus re-scan. Confirmed via a live CDP CPU profile of a real "openclaw workboard dispatch" call (--inspect attached to a running gateway, Profiler.start/stop scoped to the repro, elapsed 161.8s matching a known 160s+ stall): 93.3% of the time (142s + 8.7s of 162s) was inside native SQLite all()/prepare() bindings, all funneling through dispatch -> promoteDependencyReady -> dependencyTargetStatus -> list -> entries -> readCard (readCard issues 4 separate synchronous SQL statements per card). On a corpus of ~5770 cards, this is O(parented_cards_in_pass x corpus_size x 4_queries) -- a genuine algorithmic defect, not event-loop starvation from a concurrent session as originally suspected for this symptom. Replace the unscoped list()+Map lookup with targeted get(parentId) calls (already a single indexed-row lookup used everywhere else in this file) -- O(parents.length), normally O(1), instead of O(corpus size). Behavior is unchanged: parent?.status === "done" on the get() result is exactly what cards.get(parentId)?.status === "done" computed from the unscoped list(). Adds a regression test asserting the underlying store's entries() is called at most once while promoting 8 parented cards together in one dispatch pass (would have been 9 calls before this fix -- 1 outer scoped list() + 1 inner unscoped list() per parented card). * fix(workboard): address review feedback on dependency-target-status fastpath Two findings from the automated PR review, both confirmed real: - Remove an incomplete, unrelated active-owner fast-path (listActiveOwnerIds() in store.ts + its cross-board test in store.test.ts) that leaked into this commit from separate, still-in-progress local work. It imported WorkboardActiveOwnerQueryable, a type that isn't defined anywhere in this PR's tree, breaking typecheck and the bundled-extension lint check. Not part of the dependencyTargetStatus fix this PR is scoped to. - Replace the comparator-free, mutating .sort() calls in the new dependency regression test with .toSorted() plus an explicit localeCompare comparator, per the repo's lint rules. Re-ran locally against just these two files (the actual PR diff, review WIP set aside): pnpm lint --threads=8, pnpm format:check, pnpm tsgo:prod, pnpm check:test-types, pnpm run lint:extensions:bundled all pass; full workboard extension suite 111/111 (two removed tests belonged to the unrelated active-owner code, not this fix). --------- Co-authored-by: ClawBox <clawbox@cayk.ca>