fix: Fix critical path to exclude done tasks and weight by priority#88
Open
ulascanzorer wants to merge 5 commits into
Open
fix: Fix critical path to exclude done tasks and weight by priority#88ulascanzorer wants to merge 5 commits into
ulascanzorer wants to merge 5 commits into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR bundles three changes that landed on the same branch. Each commit is self-contained and can be reviewed or reverted independently.
1. [MYMR-208]
getCriticalPath: exclude done tasks, weight by prioritygetCriticalPath(lib/data/traversal.ts) had two bugs that degraded the "what should I work on" recommendation derived fromready ∩ critical_path:buildDepAdjacencyonly excludedcancelled, so done tasks landed ingraph.activeTasksand the DP counted them as full chain nodes. Result: the bottleneck skewed toward historical rather than remaining work.+1weight ignored priority. A 3-chain of threebacklogtasks (score 3) outranked a 2-chain of twourgenttasks (score 2), even though the latter is the actual prioritization bottleneck.The fix is surgical and scoped to
getCriticalPath:getCriticalPath: the DP builds adpNodesmap that drops done fromgraph.activeTasks, then rebuildsdpDeps/dpDependentsfromgraph.effectiveDeps.buildDepAdjacency's!== "cancelled"filter andgetBlockedTasks' manual done-skip stay (HOTL decision: surgical placement, not graph-wide).priorityWeight(info.priority)with a doubling ladderPRIORITY_WEIGHTS = { urgent: 8, core: 4, normal: 2, backlog: 1 }. Null or unrecognized priority falls back to thenormalweight (2) so the DP never seesundefined/NaN.listTasksForGraph(lib/data/task.ts) now selectstasks.priority;ActiveTaskInfo(lib/graph/effective-deps.ts) carriesPriority | null. One substrate fetch shared by every graph analyzer, no extra DB round-trip ingetCriticalPath.The returned
CriticalPathTaskshape is unchanged (id,taskRef,title,status), soformatCriticalPathkeeps rendering[status]per task without modification.2.
mymir_contextbundle memory regression (follow-up to #85)loadBundleDepsinlib/graph/effective-deps.tswas loading every task and everydepends_onedge for the project on each call (viabuildDepAdjacency), then walking the substrate in JS viawalkEffectiveDepsBounded. On a dogfooded mymir project this allocated near 1.8 GB on a singlemymir_contextrequest at depthsagent/planning/review, captured by ad-hocprocess.memoryUsage()probes around the MCP route handler.Fix:
fetchEffectiveDepChainandfetchEffectiveDownstream, underlib/db/raw/. Each CTE carries aneffective_depthcounter that increments only on active walls; cancelled middles pass through without consuming a depth slot. Postgres'sCYCLEclause terminates recursion on cancelled-loop cycles. The query returns the depth-bounded effective subgraph, not the whole project graph.loadBundleDepsnow orchestrates the two SQL calls in parallel and maps rows to the existing{ id }shape. Its signature is unchanged, soagent.ts/planning.ts/review.tswere not touched.walkEffectiveDepsBoundedis deleted.buildDepAdjacency,buildEffectiveDepGraph, andwalkEffectiveDepsare kept; they back the analyzer tools that load the whole-project graph by design.The three "cancelled middle is transparent: C surfaces, B does not" integration tests from #85 still pass against the new SQL implementation.
3. Pin
bun run devto webpackTurbopack (Next.js 16's default dev bundler) has documented dev-mode memory growth (see vercel/next.js#93451, vercel/next.js#66326). Independent of fix #2, this was filling RAM under unauthenticated Claude Code retry traffic in development. Bisected by A/B:
node --run dev(Bun out, Turbopack in) still leaked;bun next dev --webpack(Bun in, Turbopack out) was flat. Pinningdevto--webpackmatches the existingbuild: next build --webpackscript.Side benefit: the
webpack(...)hook innext.config.ts(driver / brokerNormalModuleReplacementPlugin) now actually runs in dev. Turbopack was silently ignoring those aliases; the indirection re-exports from_driver.node/_broker.nodeshims made it work by coincidence.This is an environmental workaround pending upstream Turbopack fixes; revert the line when upstream stabilizes.
Type of change
Testing
bun run lint)bun run typecheck)tests/data/traversal.test.tscovers MYMR-208's four ACs plus regression and fragmentation guards (7 tests):A(done) → B(planned) → C(draft)reports onlyB → C.urgent(16) outranks 3-chain of threebacklog(3).urgent(8) outranks 3-chain of threenormal(6).normalweight (2); a parallel single urgent task still wins."weird", persisted via service-role insert; column is plain nullabletext) defaults tonormal.A → M(cancelled) → CreportsA → C).A → B(done) → Cdoes NOT connect A and C. Locks the FILTER semantic vs the WALK semantic so a future "make done transparent like cancelled" refactor flags itself loudly.Context-bundle integration tests (
tests/context/agent.test.ts,tests/context/planning.test.ts,tests/context/review.test.ts) still pass against the new SQL CTE implementation.bun test tests/data/ tests/graph/ tests/context/is green.Notes for reviewer
getCriticalPathonly, not inbuildDepAdjacency. ThewalkEffectiveDepstransparency rule (cancelled-only) andgetBlockedTasks' explicitdone-skip both stay. ChangingbuildDepAdjacencyto drop done would ripple to every analyzer that consumes the shared substrate, out of scope for this fix.{8, 4, 2, 1}were picked so a single urgent task (8) dominates a chain of three normals (6). This is what makes the recommendation surface prefer working on the most important blocker over the longest dependency tail.loadBundleDepsrewrite (section 2) and the dev script pin (section 3) were folded in because both were diagnosed while validating MYMR-208 on the same branch; splitting would have churned three reviewers' worth of context. Each commit is self-contained.priorityis already returned on every task-detail read path; adding it tolistTasksForGraph's SELECT does not cross a trust boundary.