feat(afk): scheduler skips issues blocked by another open issue #136
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Cloonar/coding-lab#136
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
The AFK scheduler selects issues purely by `open + ready-for-agent, minus claim-branched, lowest number first`. The
## Blocked bysection that the to-issues skill puts in every issue body is prose only — the scheduler happily schedules an issue whose blocker is still open, racing unmerged work.Decision (from 2026-07-11 grill)
Promote the
## Blocked bybody section to a machine-read contract: the scheduler must not schedule an issue while any issue it references there is still open.Source of truth
The
## Blocked bymarkdown section in the issue body. Not Forgejo-native dependencies, not a label — bodies already arrive withReadyIssueson all three tracker backends (forgejo, github, builtin), so this needs zero new tracker API surface.Grammar
Blocked byheading, any heading level; section text runs to the next heading.#(\d+)in that section is a blocker. Refs elsewhere in the body ("relates to #12") never block.owner/repo#N) and full-URL refs: ignored by the filter (unevaluable per-repo) but logged, so a real cross-repo dependency doesn't silently schedule.closesDirectiveReininternal/tracker/closes.go.Semantics
Placement
internal/afkbeside the existing decision functions (decide.gostyle):ParseBlockedBy(body) []intand a filter taking the set of open issue numbers.FilterClaimable(internal/afk/launch.go:252) — the choke point shared by auto scheduling,StartManualAFK, andClaimableIssuesFor— so scheduler, manual starts, and the UI's claimable queue all agree. Manual starts skip blocked issues identically (there is no targeted-issue start today).Tracker.Issues(ctx, tracker.StateOpen), fetched only when at least one ready issue actually contains blocker refs — zero added forge calls for repos not using the convention.Edge behavior
afk: repo X skipped blocked issues: #87 (blocked by #74)). No UI change in this slice (a "blocked" badge is a candidate follow-up issue).Issues(StateOpen)fetch failure → skip that repo's tick, per the existing Tracker contract (fail-closed on infrastructure errors, fail-open only on data ambiguity).Docs contract
docs/adr/: source of truth, grammar, semantics, placement (precedent: claim-is-the-branch ADR).assets/skills/to-issues/SKILL.md: note the## Blocked bysection is machine-read by the AFK scheduler; blockers must be written as#N— prose-only blockers do not block scheduling.ready-for-agent+ live## Blocked byrefs is a valid combination — triage should not hold the label back waiting on blockers; the scheduler handles ordering.Acceptance criteria
ParseBlockedByand the filter indecide_test.gostyle: section-scoped extraction, none-case, multiple refs, refs outside the section ignored, heading-level/case tolerance.Issues(StateOpen)call when no ready issue contains blocker refs.Blocked by
None - can start immediately
Landing audit — PR #138 → VERDICT: PASS
ci / nativesuccess (run 143, 5m36s) — relied on as the verification signal; build/tests/lint/vet not re-run.origin/main(merge-tree clean).feat(afk): scheduler skips issues blocked by another open issueis Conventional Commits; headafk/136carries a workingCloses #136.## Blocked bygrammar mirroringclosesDirectiveRe; open-blocks / closed-&-dangling-unblock / claimed-still-blocks semantics; singleFilterClaimablechoke point shared by launch, scheduler pre-tick,ClaimableIssuesFor, andGET /repos/{id}/ready; lazyIssues(StateOpen)fetch armed only when a claimable issue carries a local#Nref; fail-closed (*TrackerError) on infra, fail-open on data ambiguity; structuredafk: skipped blocked issues …log line.No blockers. Awaiting free-text merge go-ahead from the operator.