# The tracker becomes an issue tracker

2026-08-11

Ernest asked for the bug tracker to be "a 1:1 clone of Jira — something more
polished and feature rich."

## What that means here, and what it does not

It means the **capabilities**. Issue keys, issue types, a real workflow, a
resolution that is not a status, sub-tasks and epics, links, components,
versions, estimates, history, boards, sprints, a query language, dashboards.
Those are ideas about how software teams track work, and there is nothing to
stop anybody building them well.

It does not mean Atlassian's interface or their branding. Two reasons, and the
second is the one that matters:

1. I do not have their source or their design files, so "1:1" is not something
   I could verify even if I aimed at it. A claim nobody can check is not a
   specification.
2. Convoro is a product Ernest sells. Reproducing a live competitor's trade
   dress is a risk with no upside — and the fit-and-finish standard for this
   project is *"does it look decided?"*, which a traced interface never does.

So: match what Jira **does**, in Convoro's own tokens and controls. Exactly the
rule the IPS ports already run under.

🚨 **And Jira's interface is not the thing to copy anyway.** It is dense,
modal-heavy and slow to learn — the standing complaint about it, from the people
who use it every day, is that a five-field bug takes four screens. "More
polished" and "just like Jira's UI" are pulling in opposite directions. Where
they conflict, this follows polish.

## What the tracker is today

A good small community bug tracker: projects, reports, votes, a seven-state
status, four severities, `found_in` / `fixed_in`, an assignee, and comments
borrowed from `discussions` as a hidden topic. Around 1,850 lines.

It is built for **your users reporting bugs to you**. Jira is built for **a team
running work**. Those are different products, and the gap is not a matter of
adding fields — it is the model underneath.

## The gap, in dependency order

Nothing below can be built before the thing above it.

1. **Issue keys** — `CONV-142`. A project key plus a per-project counter. This
   is the single most-used thing in Jira: it is what people paste into chat, put
   in branch names and say out loud. Everything else references it.
2. **Issue types** — Bug, Task, Story, Epic, Sub-task. Per project, because a
   support project and a product project do not want the same list.
3. **Status categories** — To Do / In Progress / Done. A status belongs to a
   category, and the category is what boards colour by and what "open" honestly
   means.
4. **Resolution, separate from status.** See below; this is the important one.
5. **Workflow** — statuses plus the transitions between them, assigned per
   project and issue type.
6. **History** — every field change, who made it and when.
7. Then, and only then: links, sub-tasks, epics, components, versions,
   estimates, worklogs, custom fields, watchers.
8. Then the views over all of it: boards, sprints, a query language,
   dashboards.

## 🚨 The decision that matters: resolution is not a status

Today's tracker has seven statuses, and four of them — `fixed`, `wont-fix`,
`duplicate`, `cannot-reproduce` — are not states of work at all. They are
**reasons the work stopped**. The state in every one of those cases is the same:
done.

Conflating them is not a tidiness complaint, it breaks three ordinary questions:

- *"How many did we close last month?"* becomes a query that has to name every
  terminal status, and silently undercounts the day somebody adds a new one.
- *"What is still open?"* has the same problem, inverted, in every filter,
  count, badge and board on the site.
- *"Why was this closed?"* cannot be asked separately from *"is this closed?"*,
  so a report reopened after being marked a duplicate loses the fact that anyone
  ever thought it was one.

Jira gets this right and it is worth taking. **Status** answers *where is this*.
**Resolution** answers *why did it stop*, is null while open, and is set on the
transition that closes it.

## 🚨 The migration decision: additive, nothing rewritten

The existing `status` column is a short string — `open`, `confirmed`, `fixed`.
Rather than convert it to a foreign key and rewrite every row, the new
`tracker_statuses` table is **keyed by that same string**. Each existing value
gets a row carrying what it was always missing: a category, a colour, a
position, and whether it wants a resolution.

The consequence is worth stating plainly: **no existing report is touched, and
no existing query stops working.** Same for `severity`, which becomes a row in
`tracker_priorities` under its own name.

That matters because of the standing rule that customers must always be able to
roll back. A destructive migration makes the previous version unreachable no
matter how many zips stay on the CDN.

Old terminal statuses keep their meaning and are marked `done`. They are not
retro-fitted into resolutions — a row that says `fixed` was filed by somebody
who meant `fixed`, and inventing a resolution it never had would be putting
words in their mouth.

## What is not in this phase

Named, because a plan that quietly omits things reads as finished when it is
not:

- Boards, backlogs, sprints, burndown, velocity
- The query language and saved filters
- Dashboards and gadgets
- Permission schemes, notification schemes, issue security levels
- Screens and screen schemes
- Bulk change, CSV import, automation rules

Each depends on the model this phase builds. None of them is hard *after* it,
and several are nearly free once history and status categories exist.

## What Convoro will not match, and why

Honesty here rather than a stub that disappoints later:

- **Screen schemes.** Jira lets an administrator decide which fields appear on
  which screen, per issue type, per project, per operation. It is the single
  most-complained-about part of configuring Jira. Convoro will have per-project
  field configuration — required, optional, hidden, default — and stop there.
  The remaining flexibility costs more in confusion than it returns.
- **Sub-task-level workflow schemes.** One workflow per project and issue type
  is the useful part; a scheme that maps schemes to schemes is not.
- **Time tracking as a billing system.** Estimates and worklogs, yes. Rates,
  invoicing and approval chains belong to a different product.

## Phasing

| | |
|---|---|
| **1** | Issue model and workflow engine — keys, types, statuses, categories, resolutions, priorities, transitions, history, links, parents, components, versions, labels, watchers, estimates, custom fields |
| **2** | The screens: issue view, create, edit, the project queue, admin for types and workflows |
| **3** | Boards — Kanban columns from status categories, WIP limits, swimlanes, quick filters |
| **4** | Scrum — backlog, sprints, story points, burndown, velocity |
| **5** | Query language, saved filters, subscriptions |
| **6** | Dashboards and gadgets |
| **7** | Bulk change, CSV import, REST endpoints, automation via the existing Workflows extension |

Phase 1 ships with tests and no interface, which is deliberate: the model is
what everything else is built on, and getting it wrong is expensive in a way
that a screen never is. The existing tracker keeps working throughout, because
nothing it depends on is being taken away.
