multica-ai / multica-ai/multica
[Feature]: block child issue scheduling until parent issue is completed
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 50.4k
- Forks
- 6.5k
- Avg merge
- 1d 36m
- Merged PRs (30d)
- 500
Description
What do you want and why?
Problem
When issues have parent-child relationships (parent_issue_id), the daemon's task scheduler ignores these dependencies entirely. Child issues are scheduled and executed in parallel with their parent issues.
Example scenario:
- Parent:
[Infra] Set up Next.js project(Phase 1 — must complete first) - Child:
[Feature] Build salary calculator page(Phase 2 — depends on Phase 1) - Expected: Child waits for parent to reach
donestatus before starting - Actual: Both are picked up and executed simultaneously by agents
This defeats the purpose of the parent/sub-issue hierarchy, which users rely on to model task dependencies.
Root Cause
1. SQL query has no parent-status filter
server/pkg/db/queries/agent.sql:168-171:
-- name: ListPendingTasksByRuntime :many
SELECT * FROM agent_task_queue
WHERE runtime_id = $1 AND status IN ('queued', 'dispatched')
ORDER BY priority DESC, created_at ASC;
The query only filters by runtime_id and task status. It does not join against the issue table to check whether the task's parent issue is complete.
2. ClaimTaskForRuntime has no dependency check
server/internal/service/task.go:211-235:
func (s *TaskService) ClaimTaskForRuntime(ctx context.Context, runtimeID pgtype.UUID) (*db.AgentTaskQueue, error) {
tasks, err := s.Queries.ListPendingTasksByRuntime(ctx, runtimeID)
// ... iterates candidates, only checks agent concurrency limit
}
No validation that the candidate task's issue has a completed parent before claiming it.
Proposed solution (optional)
Option A: Filter at the SQL level (recommended)
Modify ListPendingTasksByRuntime to exclude tasks whose issue has an incomplete parent:
-- name: ListPendingTasksByRuntime :many
SELECT atq.* FROM agent_task_queue atq
JOIN issue i ON atq.issue_id = i.id
LEFT JOIN issue parent ON i.parent_issue_id = parent.id
WHERE atq.runtime_id = $1
AND atq.status IN ('queued', 'dispatched')
AND (i.parent_issue_id IS NULL OR parent.status IN ('done', 'cancelled'))
ORDER BY atq.priority DESC, atq.created_at ASC;
Pros: Single query, no extra round-trips, clean
Cons: Requires sqlc regeneration
Option B: Filter at the service level
Add a parent-status check in ClaimTaskForRuntime after fetching candidates:
for _, candidate := range tasks {
// Check if parent issue is done
issue, _ := s.Queries.GetIssue(ctx, candidate.IssueID)
if issue.ParentIssueID.Valid {
parent, _ := s.Queries.GetIssue(ctx, issue.ParentIssueID)
if parent.Status != "done" && parent.Status != "cancelled" {
continue // skip — parent not finished
}
}
// ... existing claim logic
}
Impact
- Who is affected: All users who set parent/sub-issue relationships expecting sequential execution
- Severity: Medium — feature exists in UI but doesn't work as expected
- Scope:
server/pkg/db/queries/agent.sql,server/internal/service/task.go,server/pkg/db/(sqlc generated)
Acceptance Criteria
- Tasks with a parent issue in
todo,in_progress,in_review, orblockedstatus are NOT scheduled - Tasks with a parent issue in
doneorcancelledstatus ARE scheduled normally - Tasks with no parent issue (
parent_issue_id IS NULL) are unaffected - Existing tests pass, new test covers the blocking behavior
Pros: No SQL changes
Cons: Extra DB queries per candidate, less efficient
Screenshots / mockups (optional)
No response
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with server/pkg/db/queries/agent.sql and server/internal/service/task.go, following ListPendingTasksByRuntime into ClaimTaskForRuntime. Review the sqlc-generated files under server/pkg/db/ and the existing task tests before choosing the filtering layer. Done means parentless tasks and tasks with done or cancelled parents schedule normally, while tasks with incomplete parents remain blocked and the existing tests still pass.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, postgresql
- Domain
- backend, databases
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 66/100