Skip to content

Issue tracking

MIP-0063 puts the backlog into GitHub issues and milestones instead of files, in every marola repo. This doc is the short version; the design and its verification are MIP-0063. Where an issue lives when work spans repos is WORKING-ACROSS-REPOS.

The object model

Object Means Carried by
Milestone one deliverable / use case, spanning many issues and possibly several MIPs native milestone + its progress bar
Issue a story or task — the claimable, PR-closable unit labels, assignee, milestone
Sub-issue a subtask, only when a story genuinely splits native sub-issues

Milestones are named descriptively, carry no sequence, and order between them is a board decision. A milestone and a MIP are n:m — one deliverable can span several MIPs, one MIP files its tasks into one milestone.

Kroki

The three tiers

Pick the tier, then the matching issue form:

  • Tier 1 — bug, chore, docs. One issue, no milestone, no spec. Use Bug report (bug_report.yml) for something broken in what a user touches — the pipeline, the CLI, the Telegram bot, the site. Use Task (task.yml) for everything else, including something broken in the repo's own tooling: a script, a hook, CI. bug_report.yml asks which LLM backend was running and for the command that triggers it, neither of which a broken shell script has.
  • Tier 2 — small enhancement (roughly two tasks or fewer, no new dependency). One issue whose body is the spec, sub-issues if it splits, no MIP file. Use Story (story.yml).
  • Tier 3 — initiative (a new data source, a scoring change, a new integration, anything paid). MIP proposal issue → MIP PR → Accepted → milestone → N issues. Use MIP proposal (mip_proposal.yml); it is relabelled, not replaced, once the MIP PR opens, so the design discussion stays attached to it.

The Definition of Ready

An issue becomes agent-ready only once all five rules hold:

  1. Acceptance criteria, as testable checkboxes (### Acceptance criteria).
  2. A named test — file plus test name (### Named test).
  3. area/* and layer/* set.
  4. size/* set — S < 100 changed lines, M 100–400, L means split it.
  5. No open blocked by dependency, read from the API rather than from a label.

A heading whose field the author left blank renders as _No response_ and does not count. AGENTS.md carries the rule that an agent may only begin implementation on an issue holding agent-ready.

The rules follow the tier, because the forms do. A MIP proposal is a design request rather than claimable work, so it is never agent-ready. A bug report is claimed on its own two fields: What you expected instead stands for the acceptance criteria, and Failing test for the named test.

A bug report with no failing test is filed, and is not yet claimable. The field is optional on purpose — someone who cannot write Scala should still be able to report a bug, and losing that report costs more than the missing line. So issue-ready answering "rule 2: named test" on such an issue is the checker working, not a contradiction to fix: rule 2 exists so that what proves the bug fixed is decided before someone claims it, and nobody has decided it yet. A maintainer owes the report a named test — the test that is red today — and the issue becomes agent-ready when they add it.

A merged task PR closes its issue. The closing keyword that works here is the one in the squash-merge commit that lands on main. In this repo a PR-body-only line did not close anything:

514–#519 carried one and their issues #502–#507 stayed open past merge and were closed by hand,

while #511/#512 closed on a commit-body Closes #N (cause unknown, #524). cost-fill, run by stack pr (itself run by just pr, or directly per /marola-devkit:mip-tasks's step 2), writes Closes #N into the branch's own commit body, above the Tested:/Cost:/Co-Authored-By: trailers, for the issue that row k of MIP-NNNN.tasks.md links; the merge into main then closes it, and that clears rule 5 for every task blocked by it. uprd still copies the same line into the PR body so the link is visible on GitHub, but that copy closes nothing by itself. Set TASK_PARTIAL=1 before just pr for a task that only delivers part of its row — cost-fill then writes no Closes #N at all, since the task-partial label a PR would otherwise carry doesn't exist yet at first push; the issue stays open. Once a Closes #N line is written, a later task-partial label does not stop the close: amend the commit to remove the line. GitHub's built-in board workflow then moves a closed issue's card to Done (configured in the project UI, MIP-0063 §4.4).

The commands

issues is the whole surface: the queue, the readiness check, claiming, filing a MIP's task table, milestones, labels and the board. Every subcommand and recipe is on the devkit's tools page. board setup and board gates are one-time bootstraps with no recipe, because reshaping a shared board or filing issues is not something just should make easy.

tasks-to-issues sets no area/*, layer/* or size/*: which they are is a human's call, so a freshly filed row is not agent-ready until someone labels it and issue-ready passes.

Readiness and the board

The agent-ready label (Definition of Ready, above) and the board's Status field (Triage / Spec / Ready / In progress / In review / Done, MIP-0063 §5.2) move together, driven by the commands above. The mapping board-sync uses on a card's first contact with the board (MIP-0063 §5.2): an assigned issue goes to In progress, an issue carrying agent-ready goes to Ready, otherwise it goes to Triage.

Kroki

board-sync sets a new card's Status once, on first contact with the board, and never overwrites it again — except Done, which it sets whenever an issue is closed and its card isn't there already. From there, a move into Spec or into In review is "someone's decision"; a move into In progress is issue-claim; and a move into Done is GitHub's built-in "Item closed" workflow first, with board-sync as the fallback when that workflow doesn't fire — observed missing 8 of 9 closes on 2026-09-30 (MIP-0063 §4.4).

What no command can do

  • Filing an issue is human-gated (MIP §5.6, Decision 2). The /marola-devkit:triage skill drafts one and runs the readiness check; a person invokes it and a person files.
  • The board — org project Marola — is private, and §5.2 wants it public. There is no API for the switch.
  • The Agent queue view is not sorted by the script. ProjectV2View.sortByFields is readable but not writable, so size-then-priority ordering is a UI action; just issue-queue sorts the same list from the terminal and needs no project scope.