Design 53: milestones are records of the tracker, an issue's milestone is its own link, and the seed reads the design's table once (ADR 0493, issue 1781)

This commit is contained in:
2026-10-26 18:00:18 +01:00
parent 97d600650a
commit 973182cdf9
+34 -4
View File
@@ -2,7 +2,7 @@
layer: to-be
status: in-progress
code: [mesh-catalog modules/mesh-issues, mesh-catalog modules/claude-code, mesh-catalog modules/messenger, mesh-sdk]
updated: 2026-10-11
updated: 2026-10-26
decisions:
- "ADR 0275"
- "ADR 0278"
@@ -13,6 +13,7 @@ decisions:
- "ADR 0291"
- "ADR 0294"
- "ADR 0300"
- "ADR 0493"
---
# 53 — The issue tracker
@@ -81,7 +82,10 @@ agent finds them with `mesh_search` ("open an issue") and calls them as `issue-t
| `set` | a number and any of `severity`, `needs`, `suggested-owner` | changes them as a person decides (§ 10) |
| `tracking` | optionally condition keys | for every condition key an issue links, the issues that link it and where each stands: status, needs, worker, fix (§ 12) |
| `groom` | optionally `confirm` and a pass's id | the duplicate check over the backlog (§ 9): without `confirm`, starts a dry run in the background and answers its id; with the id alone, its progress and findings; with `confirm` and the id, applies exactly that pass's findings, each checked again |
| `import` (slice 3) | optionally `dry-run`, a commit | reads every issue folder of hq through the records module and writes each as an issue at its own number; creates what is absent, fills a status the tracker holds empty, never overwrites, never advances the counter; run again, changes nothing and says so |
| `import` (slice 3) | optionally `dry-run`, a commit, and `milestones` with a design's number | reads every issue folder of hq through the records module and writes each as an issue at its own number; creates what is absent, fills a status the tracker holds empty, never overwrites, never advances the counter; run again, changes nothing and says so. With `milestones`, it seeds that design's milestone records from its table instead (§ 13) |
| `milestones` | optionally a design, a status, or one milestone as design/id | the milestone records, each with its issues and their count by status; one milestone with its issues' rows and its history (§ 13) |
| `milestone-set` | a design, an id, an outcome, optionally an order, or `announce` | makes a milestone record, or changes its outcome or order; with `announce`, says the record again as its event (§ 13) |
| `milestone-move` | a milestone as design/id, a status and a reason | opens or closes a milestone; closing is refused while an issue linked to it is neither resolved nor wontfix (§ 13) |
Each verb's description says in plain words what it does and what it refuses, without the mesh's internal names, so
an agent picks the right one from `mesh_search` alone. A refusal says what was wrong and what would be accepted.
@@ -100,8 +104,8 @@ the issue's worker, who works on it, as the worker states it
- `located-in`: entries of the registered list of owners (repositories and modules), never free text;
- `fixed-by` (pull requests or commits), `amended-design`, `replay` or `replay-none`, and a reason for `wontfix`;
- `notes`: appended, each with who wrote it, when, and the text;
- `links`, typed: to another issue (`duplicates`, `relates-to`), a pull request, a decision record, a design, a
condition key (the issue **tracks** that condition, § 12) or a delivery;
- `links`, typed: to another issue (`duplicates`, `relates-to`), a pull request, a commit, a decision record, a design,
a condition key (the issue **tracks** that condition, § 12), a delivery, or the one milestone it belongs to (§ 13);
- `documents`: the report, and a diagnosis and a resolution when written, each with its author and date, revised in
place with its history kept (ADR 0291);
- `record`: the path of the issue's folder in hq, while one exists; none is opened any more, and the folders are
@@ -203,6 +207,7 @@ worker; one that stops moves the issue on, or is stale a day later.
| The triage fills only what is empty, links no cycle, and an issue is ready only when its dependencies' fixes are delivered | the rows of ADR 0279's "How it is checked" |
| The duplicate check acts only on a clear duplicate, never on an older or a resolved issue, once per issue, loudly when it cannot judge | the rows of ADR 0278's "How it is checked" |
| An issue's documents are kept whole, with author, date and history, and the import of hq's folders loses nothing (ADR 0291) | the module's tests of `documents` and of the import, one case per document kind; the comparison of every issue with its folder before the folders are removed, written on issue 427. Tracked by issue 427 |
| An issue belongs to at most one milestone, linked only by the verb, and only to an open one (ADR 0493 §2 to §4) | the module's table test of the `milestone` and `commit` link kinds, one case per refusal; the test that the triage and the duplicate check never add a `milestone`, `pull-request` or `commit` link; one integration test that starts the module whole on a real bus and makes, links and refuses |
| Live | on the mesh, an agent calls `issue-tracker.open` and gets the next number; two sessions on two nodes open at the same moment and get two different numbers; `list` shows both |
## 8. The slices after the first
@@ -312,6 +317,31 @@ with no pull request open is **abandoned**.
**tracking line** in every condition's message; the words and the verdict it changes are its own (to-be 45 § 5).
The controller learns nothing of issues.
## 13. Milestones
**A milestone is a record of the tracker, made from its design's table** (ADR 0493 §1). The state `milestones`, which the
manifest declares beside `issues`, keeps one value per milestone, keyed by its design's number and its id: the id as the
design's table writes it, the outcome, its order in the table, its status (`open` or `closed`, with a reason), who made
and who last moved it and when, and the hq commit and path it was seeded from. It is written by compare-and-set at the
revision read, and its history is the key's kept values with the events `milestone-set` and `milestone-moved`.
**An issue's milestone is the issue's own link, not a list on the milestone.** The link kind `milestone` (its target
design/id, such as 47/R6) is written in the issue's log like any link, so the rule that an issue belongs to at most one
milestone (ADR 0493 §2) is checked inside that issue's one write, refused naming the milestone it is in; a link to a
milestone that does not exist or is closed is refused (§3: a fix found on the way joins the open milestone). A milestone's
issues are read from the issues in memory. Pull requests and commits are linked to the issue they fix the same way, with
the kinds `pull-request` and `commit` (§4); nothing reads them from a description, and the triage never adds one.
**The seed** is `import` with `milestones` and a design's number: it reads the table through the records module, makes
each record that is absent in the table's order, links each issue it names that has no milestone, refuses (and names)
an issue another milestone holds or two rows name, closes a milestone whose issues are all resolved with their fixes
delivered, and run again changes nothing. Once a design is seeded, the tracker is the only list of its milestones'
issues: the design's table keeps its rows without an Issues column, and the knowledge base's `progress` reads
`milestones` (issue 1781).
Readiness, the one ask per milestone and its release are the delivery seat's (ADR 0493 §7 to §11, issue 1783); the
tracker gives them the records and links they read.
## What it leaves out
Priorities beyond severity, notifications beyond the `ready` and `ready-to-verify` events and the stuck-fix warning, full-text or semantic search, the forge's own issue lists, and an index of any kind: