Skip to content

Dependency-aware dispatch ordering - #138

Merged
kjgbot merged 9 commits into
mainfrom
factory/133-agentworkforce-factory-fa7edb58
Jul 20, 2026
Merged

Dependency-aware dispatch ordering#138
kjgbot merged 9 commits into
mainfrom
factory/133-agentworkforce-factory-fa7edb58

Conversation

@kjgbot

@kjgbot kjgbot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Parse a Blocked by: #123, owner/repo#456 line from issue body/description at discovery time (v1 text convention, per issue notes).
  • Resolve dependency references to the same composite repo+number identity issueKey() uses elsewhere, so a bare #123 only matches within the routed repo.
  • Add a second admission predicate to BatchTracker (start()/queue()): issues with unresolved blockers are parked, distinct from capacity queuing (ParkedIssue.capacityBlocked tracks both independently).
  • Post an issue comment naming the specific unresolved blocker(s) when an issue parks, and surface a distinct hold.kind: 'dependency' / 'dependency-cycle' reason in dispatch skip reporting so it's never confused with a safety-gate skip.
  • Detect dependency cycles (direct or transitive) via findDependencyCycle and fail closed with an operator-visible error/comment instead of deadlocking.
  • Reconcile parked issues when a blocker reaches a terminal state (GitHub issue close / Linear done / merged PR), promoting newly-unblocked issues on the next cycle through the existing dispatch path — no new promotion mechanism.

Fixture

Exercised against the exact #128#131#132 chain from the issue: a single discovery sweep dispatches only #128; #131 and #132 park with Blocked by: AgentWorkforce/pear#128 / #131 respectively; closing #128 promotes #131 on the next cycle. See factory.test.ts: "dispatches a dependency chain in order and promotes the next issue after its blocker closes".

Test plan

Closes #133

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@kjgbot, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 31 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7f02a0f2-efa4-446d-9fe7-a11c4f2b2914

📥 Commits

Reviewing files that changed from the base of the PR and between df47b1d and 92ac91a.

📒 Files selected for processing (5)
  • README.md
  • src/index.ts
  • src/orchestrator/factory.test.ts
  • src/orchestrator/factory.ts
  • src/ports/state.ts
📝 Walkthrough

Walkthrough

Factory now supports Blocked by: dependencies across GitHub and Linear issues. It parses and resolves blockers, detects cycles, parks blocked dispatches, reports structured holds, and re-dispatches dependents when blockers become terminal.

Changes

Dependency-aware dispatch

Layer / File(s) Summary
Dependency contracts and graph utilities
README.md, src/orchestrator/dependencies.ts, src/orchestrator/batch-tracker.test.ts
Documents and implements strict Blocked by: parsing, repository-aware resolution, identity generation, deduplication, and cycle detection.
Parked batch admission and public state
src/orchestrator/batch-tracker.ts, src/ports/state.ts, src/types.ts, src/orchestrator/index.ts, src/index.ts, src/orchestrator/batch-tracker.test.ts
Adds dependency admission types and parked issue state, updates batch lifecycle methods, exposes parked queries, and extends public dispatch/status contracts and exports.
Factory dependency admission and reconciliation
src/orchestrator/factory.ts
Indexes dependencies, computes dependency holds, parks blocked work, reports parked status, detects terminal dependencies, reconciles parked dispatches, and normalizes repository-specific PR resolution.
Dependency dispatch and lifecycle validation
src/orchestrator/factory.test.ts
Tests ordered dependency dispatch, Linear extraction, cross-repository identity resolution, cycle refusal, reopened blockers, and merged-PR unblocking.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant IssueProvider
  participant FactoryLoop
  participant BatchTracker
  participant AgentSpawner
  IssueProvider->>FactoryLoop: provide issue and blocker declarations
  FactoryLoop->>BatchTracker: submit dependency admission
  BatchTracker-->>FactoryLoop: park blocked issue
  IssueProvider->>FactoryLoop: report blocker terminal
  FactoryLoop->>BatchTracker: clear parked state
  FactoryLoop->>AgentSpawner: dispatch dependent issue
Loading

Possibly related issues

  • AgentWorkforce/factory issue 133: Covers the dependency-aware dispatch ordering implemented across parsing, admission, cycle detection, and reconciliation.

Suggested reviewers: khaliqgant, miyaontherelay

Poem

A bunny found blockers in lines neat and clear,
Parked waiting issues till paths reappear.
Cycles were caught before agents could roam,
Closed work freed queues for dependents to come.
Hop, hop—dispatch flows onward!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: dependency-aware dispatch ordering.
Description check ✅ Passed The description is clearly related and matches the dependency-aware dispatch and parking changes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch factory/133-agentworkforce-factory-fa7edb58

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a dependency-aware issue sequencing and admission mechanism to the orchestrator, allowing issues to be parked until their declared blockers are resolved. Feedback on the changes highlights critical issues, including potential runtime crashes due to unhandled null/undefined values in parseBlockedBy and #indexDependencyIssue, and a potential ReferenceError from using the undefined githubIssueIdentity function. Additionally, opportunities for code simplification and optimization were identified, such as refactoring the parsing logic in parseBlockedBy and avoiding duplicate asynchronous calls to retrieve the batch instance.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/orchestrator/dependencies.ts Outdated
Comment thread src/orchestrator/factory.ts Outdated
Comment thread src/orchestrator/factory.ts Outdated
Comment thread src/orchestrator/dependencies.ts Outdated
Comment thread src/orchestrator/factory.ts Outdated
…uplicate batch() call

- parseBlockedBy is now a public API export; accept null/undefined
  description text and return no dependencies instead of throwing.
- Hoist the single #batch() lookup in the queued-lifecycle dependency
  check instead of calling it separately on both branches.

Addresses gemini-code-assist review on PR #138.
kjgbot added 2 commits July 20, 2026 23:29
…force-factory-fa7edb58

# Conflicts:
#	src/orchestrator/batch-tracker.test.ts
#	src/orchestrator/batch-tracker.ts
@kjgbot

kjgbot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/orchestrator/factory.ts (1)

3955-4020: 🚀 Performance & Scalability | 🔵 Trivial | ⚖️ Poor tradeoff

Dependency blocker discovery can trigger a full ISSUE_ROOT tree scan per blocked dispatch.

When a declared blocker is not already indexed and the GitHub by-id probe misses, #loadMissingDependencyIssues falls back to #githubIssuePaths() and a full #listRelayfileTree(ISSUE_ROOT) scan. These are memoized within a single call, but blockers are commonly non-ready (closed/in-progress/unlabeled) and therefore absent from the ready set, so a runOnce with several blocked issues can repeat the Linear/GitHub tree scans once per issue. Consider hoisting the closure-load caches (or the resolved-dependency index) across a single dispatch pass to keep this off the O(issues × tree) path on large boards.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/orchestrator/factory.ts` around lines 3955 - 4020, Hoist the closure-load
caches used by `#loadMissingDependencyIssues`—githubPathsByIdentity and
linearTreeLoaded, or an equivalent resolved-dependency index—to the surrounding
dispatch/runOnce scope so multiple blocked issues share each GitHub and Linear
tree scan. Initialize them once per dispatch pass, reuse them across calls to
`#loadMissingDependencyIssues`, and reset them before the next pass.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/orchestrator/factory.ts`:
- Around line 2330-2348: Clear the dependency-park notice deduplication entry
whenever a dispatch successfully calls clearPark, starting at the shown dispatch
path and applying the same cleanup at the other clearPark sites near the related
flows. Reuse the existing `#dependencyParkNotices` state and ensure a later
identical blocker or cycle signature can be reported again after the issue
re-parks.

---

Nitpick comments:
In `@src/orchestrator/factory.ts`:
- Around line 3955-4020: Hoist the closure-load caches used by
`#loadMissingDependencyIssues`—githubPathsByIdentity and linearTreeLoaded, or an
equivalent resolved-dependency index—to the surrounding dispatch/runOnce scope
so multiple blocked issues share each GitHub and Linear tree scan. Initialize
them once per dispatch pass, reuse them across calls to
`#loadMissingDependencyIssues`, and reset them before the next pass.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 0c3f1fd9-9229-4469-8b80-acac84b6b325

📥 Commits

Reviewing files that changed from the base of the PR and between 726d66b and df47b1d.

📒 Files selected for processing (10)
  • README.md
  • src/index.ts
  • src/orchestrator/batch-tracker.test.ts
  • src/orchestrator/batch-tracker.ts
  • src/orchestrator/dependencies.ts
  • src/orchestrator/factory.test.ts
  • src/orchestrator/factory.ts
  • src/orchestrator/index.ts
  • src/ports/state.ts
  • src/types.ts

Comment thread src/orchestrator/factory.ts Outdated
@kjgbot

kjgbot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor Author

Addressed the CodeRabbit scalability note in fd642de: GitHub fallback-path discovery and the Linear tree-loaded flag are now shared across a dependency discovery pass and reset at the next runOnce, so multiple blocked issues reuse the same provider scans. Added the regression "shares missing-blocker tree scans across one discovery pass". Validation: npm run build and npm test (50 files, 1,021 tests) pass.

@kjgbot
kjgbot merged commit 19b45a8 into main Jul 20, 2026
2 of 3 checks passed
@kjgbot
kjgbot deleted the factory/133-agentworkforce-factory-fa7edb58 branch July 20, 2026 22:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dependency-aware dispatch ordering: let Factory sequence and reconcile issues that block each other

1 participant