Merge pull request 'Playbook 03 takes an issue's number from the issue tracker' (#274) from process/issue-numbers-from-the-tracker into main
This commit was merged in pull request #274.
This commit is contained in:
@@ -21,9 +21,28 @@ Opens a numbered issue. **Authoritative playbook:**
|
||||
there, this is not an issue — it is a lookup. If the answer is a general lesson, it belongs in
|
||||
both.
|
||||
|
||||
## The number comes from the issue tracker
|
||||
|
||||
Every issue is opened in the issue tracker (seat `issue-tracker`, module `mesh-issues`, ADR 0275). **Never take a
|
||||
number by reading `main` or the open pull requests** — that is how numbers collided. If the tracker cannot be
|
||||
reached, take no number and say so.
|
||||
|
||||
Decide the shape first:
|
||||
|
||||
- **Design or governance issue** — its narrative belongs in hq: it gets a folder `04-ISSUES/NNN-short-name/`.
|
||||
- **Anything else** — it lives wholly in the tracker, and nothing is written in hq.
|
||||
|
||||
## Steps
|
||||
|
||||
1. Next free number. Create `04-ISSUES/NNN-short-name/00-report.md` with:
|
||||
1. Load `mesh_call` and `mesh_describe` (deferred tools of the `mesh` MCP server) and open the issue:
|
||||
`mesh_call issue-tracker.open` with `title` (the symptom in one line), `report` (what was seen, what was expected,
|
||||
how it was found — the evidence: what was run, what came back, when), optionally `located-in` when the owner is
|
||||
already known, and — **only for an issue with a folder** — `record: short-name` (lower-case words joined by
|
||||
hyphens, no number). The answer carries the number `NNN`.
|
||||
2. **Issue wholly in the tracker:** done. Its trail goes in `issue-tracker.note`, its status changes through
|
||||
`issue-tracker.move`, its links through `issue-tracker.link`.
|
||||
3. **Issue with a folder:** on a branch off `origin/main`, create `04-ISSUES/NNN-short-name/00-report.md`, `NNN` being
|
||||
exactly the tracker's number and `short-name` exactly the `record` passed:
|
||||
|
||||
```yaml
|
||||
---
|
||||
@@ -35,13 +54,15 @@ both.
|
||||
---
|
||||
```
|
||||
|
||||
2. Write the symptom **as observed**, in plain terms, with the evidence that it happened —
|
||||
what was run, what came back, when.
|
||||
3. Say why it matters beyond the instance. An issue that is only one occurrence is a knowledge
|
||||
Its status stays in this frontmatter until slice 3 of to-be 53 imports the folders (ADR 0275);
|
||||
`issue-tracker.move` refuses it until then. Notes and links may still go to the tracker.
|
||||
4. Write the symptom **as observed**, in plain terms, with the evidence that it happened.
|
||||
5. Say why it matters beyond the instance. An issue that is only one occurrence is a knowledge
|
||||
base entry.
|
||||
4. End with open questions rather than a proposed fix. Diagnosis is a separate step.
|
||||
6. End with open questions rather than a proposed fix. Diagnosis is a separate step.
|
||||
|
||||
## Do not
|
||||
|
||||
- Do not name nodes, domains, addresses or paths. This repository is public.
|
||||
- Do not guess the owner — `located-in:` is filled by diagnosis, not by opening.
|
||||
- Do not renumber a folder or reuse a number: a number never moves.
|
||||
|
||||
@@ -19,14 +19,36 @@ The knowledge base already holds the operational record and is indexed on sympto
|
||||
folder is not a second copy of it. An issue here is a question HQ must **answer**, not an
|
||||
incident someone must **clear**.
|
||||
|
||||
## The issue tracker holds the number
|
||||
|
||||
Every issue is opened in the **issue tracker**, the module `mesh-issues` holding the seat `issue-tracker` on the
|
||||
control-node ([ADR 0275](../../02-DECISIONS/0275-the-mesh-numbers-and-tracks-its-issues-in-a-module-of-its-own-and-hq-keeps-only-the-narrative-of-a-design-or-governance-issue.md),
|
||||
[to-be 53](../../03-DESIGN/01-to-be/53-the-issue-tracker.md)). Its number comes from one counter advanced by
|
||||
compare-and-set, so two authors opening at the same moment never get the same one. **A number is never taken by
|
||||
reading `main` or the open pull requests** — that is how numbers collided (issue 155: two records sharing a number
|
||||
reached `main` with every check passing). A session that cannot reach the tracker takes no number and says so.
|
||||
|
||||
An issue takes one of two shapes:
|
||||
|
||||
- **With a folder here** — a design or governance issue, whose narrative belongs in this public record and is
|
||||
reviewed in a pull request. The tracker holds its number, title, notes and links; its status stays in the folder's
|
||||
frontmatter until slice 3 of to-be 53 has imported the folders and been checked, and until then the tracker's
|
||||
`move` refuses it, saying its status lives in its folder.
|
||||
- **Wholly in the tracker** — every other issue. Its status, owner, notes and links live in the tracker from the
|
||||
start, and nothing is written here.
|
||||
|
||||
No status is ever kept in two places for one issue.
|
||||
|
||||
## Steps
|
||||
|
||||
1. Take the next free number — **across `main` and every open pull request**, not `main` alone.
|
||||
Work sits on unmerged branches for days, so two people both reading `main` allocate the same
|
||||
number; it happened twice in one hour between two machines, and the second collision reached
|
||||
`main` with every check passing (issue 155). `cycle.py` now refuses two records sharing a number,
|
||||
which catches a collision but does not prevent one. Create
|
||||
`04-ISSUES/NNN-short-name/00-report.md`:
|
||||
1. Open the issue in the tracker, through the mesh MCP server:
|
||||
`mesh_call issue-tracker.open` with `title`, `report` (the symptom **as observed**, in plain terms, with the
|
||||
evidence that it happened), optionally `located-in` (entries of the tracker's registered list of owners), and, for
|
||||
an issue that gets a folder here, `record` — the folder's name without its number, `short-name`. The tracker
|
||||
answers with the number `NNN`; a refused open spends none.
|
||||
|
||||
**An issue with a folder** then creates `04-ISSUES/NNN-short-name/00-report.md` under exactly that number, on a
|
||||
branch:
|
||||
|
||||
```yaml
|
||||
---
|
||||
@@ -38,15 +60,21 @@ incident someone must **clear**.
|
||||
---
|
||||
```
|
||||
|
||||
Then the symptom **as observed**, in plain terms, with the evidence that it happened.
|
||||
2. Investigate in `01-diagnosis.md` in the same folder — the trail, dated, including what was
|
||||
ruled out. Move `status:` to `diagnosing`, then `located` once the owner is known.
|
||||
3. Resolve. Set `status: resolved`, fill `fixed-by:`, and if the root cause was a design gap,
|
||||
Then the symptom as observed, as in the tracker's report.
|
||||
|
||||
**An issue wholly in the tracker** is done at this step: what follows happens through the tracker's verbs.
|
||||
2. Investigate. For a folder-backed issue, the trail goes in `01-diagnosis.md` in the same folder — dated,
|
||||
including what was ruled out — and `status:` moves to `diagnosing`, then `located` once the owner is known. For an
|
||||
issue wholly in the tracker, the trail goes in `issue-tracker.note` and the status changes through
|
||||
`issue-tracker.move`, which refuses `located` without a registered owner in `located-in`.
|
||||
3. Resolve. Set `status: resolved` (in the frontmatter, or through `issue-tracker.move` for an issue wholly in the
|
||||
tracker), fill `fixed-by:`, and if the root cause was a design gap,
|
||||
run playbook [02](02-graduation.md) and fill `amended-design:`. **A core issue** — its `located-in`
|
||||
names the controller, the node-engine, the tool runner, the SDK, or the catalogue's bus, forge or build
|
||||
agent — resolves with `replay:`, the id of its replay in mesh-lab's replays register, proved to fail on
|
||||
the commit before the fix and pass on it, or with `replay-none:` saying why none is possible
|
||||
([ADR 0237](../../02-DECISIONS/0237-a-change-is-judged-against-the-mesh-that-runs-before-it-merges-on-the-build-seat.md); `cycle.py` checks it).
|
||||
([ADR 0237](../../02-DECISIONS/0237-a-change-is-judged-against-the-mesh-that-runs-before-it-merges-on-the-build-seat.md);
|
||||
`cycle.py` checks it on a folder, and `issue-tracker.move` refuses the move without it).
|
||||
|
||||
## Rules
|
||||
|
||||
@@ -57,8 +85,9 @@ incident someone must **clear**.
|
||||
- A fix that turns out to have broken something else is written back into the record that asked for
|
||||
it, pointing at the new issue. Somebody arriving at a record to learn why the code is the way it
|
||||
is must not have to already know there was a sequel.
|
||||
- Renumbering a collision happens once, in the branch that lands last. Renumbering a branch whose
|
||||
author is still pushing only moves the race.
|
||||
- A number never moves. A folder carries the number the tracker gave; a folder whose number collides with
|
||||
another (one numbered before the tracker, or by hand) is a fault, and `cycle.py` refuses two records
|
||||
sharing a number.
|
||||
- An issue whose answer is a general lesson should also be written to the knowledge base, so
|
||||
the next person searching a symptom finds it. Both, not either.
|
||||
- `status: wontfix` is legitimate and requires a sentence saying why.
|
||||
|
||||
@@ -73,6 +73,14 @@ read to the state interface (small, and every module with a counter gains it), o
|
||||
instance and number inside it. **Recommended: the first.** One instance is also right for v1, but the
|
||||
counter should not depend on it.
|
||||
|
||||
> **Correction — 2026-10-10.** The finding above is wrong about the SDK. Version v0.1.9, the one read, had no
|
||||
> compare-and-set, but the SDK's Go state interface already had it from go/v0.1.10: `Create` (writes a key only if it
|
||||
> does not exist) and `Update` (writes only at the revision the caller read), with the runtime's matching state
|
||||
> verbs, both from [ADR 0259](../../02-DECISIONS/0259-an-ask-is-a-message-on-the-bus-any-channel-answers-it-and-the-asker-acts-on-a-warrant.md).
|
||||
> What the tracker's counter needed and slice 1 added is `Increment`, in go/v0.1.12, which reads a counter and writes
|
||||
> the next number with `Create` or `Update` at the revision it read, retrying a bounded number of times. The
|
||||
> recommendation stands; the work it named was smaller than stated. ADR 0275 carries the same correction.
|
||||
|
||||
**Explicitly left out of v1:** decision and research numbers (slice 2), any change to playbook 03 or
|
||||
the hq checks (slice 2), duplicate finding beyond links (slice 3), opening an issue from a condition
|
||||
(slice 4), a web view (slice 5), full-text or semantic search, priorities, claims, notifications, and
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
layer: to-be
|
||||
status: in-progress
|
||||
code: [mesh-catalog, mesh-sdk]
|
||||
code: [mesh-catalog modules/mesh-issues, mesh-sdk]
|
||||
updated: 2026-10-10
|
||||
decisions:
|
||||
- 02-DECISIONS/0275-the-mesh-numbers-and-tracks-its-issues-in-a-module-of-its-own-and-hq-keeps-only-the-narrative-of-a-design-or-governance-issue.md
|
||||
|
||||
Reference in New Issue
Block a user