# Jira Issues Specification

How Quber Jira tickets are structured so they read clearly and stay truthful as
work progresses.

**Project:** `QUE` (Quberai) · **Jira:** https://mandeng.atlassian.net ·
**Tracker:** Jira only (no GitHub Issues) · **Issue types:** Epic (team-only),
Story, Task, Bug, Sub-task.

This document defines **what a ticket contains and how it evolves**. The
universal standards every ticket inherits — functional evidence, Definition of
Done, technical expectations — live once in
[ENGINEERING_STANDARDS.md](ENGINEERING_STANDARDS.md) and are *not* repeated in
each ticket. The mechanics of *creating* tickets are handled by the
`jira-workflow` agent.

## Contents

- [The Lifecycle: requirement first, design later](#the-lifecycle-requirement-first-design-later)
- [The Core Model: frozen Ask + living Current State](#the-core-model-frozen-ask--living-current-state)
- [Ticket Anatomy](#ticket-anatomy)
- [Worked Example: QUE-262 in two timelines](#worked-example-que-262-in-two-timelines)
- [Issue Types and Selection](#issue-types-and-selection)
- [Title Conventions](#title-conventions)
- [Status and Decision Conventions](#status-and-decision-conventions)
- [Epics and Known Epics](#epics-and-known-epics)
- [Sub-tasks](#sub-tasks)
- [Validation](#validation)
- [Priority Defaults](#priority-defaults)

---

## The Lifecycle: requirement first, design later

A ticket starts as a **requirement only**. The plan and design reviews come
*later*, as the product of ideation and internal discovery. This is the normal
sequence — not a shortcut.

```
Requirement  →  Ticket created (lean — the Ask, provisional ACs)
                      │
                      ▼
              plan-review / design review   ← ideation + hard discovery
                      │
                      ▼
              Current State updated in place  ← decisions land here
                      │
                      ▼
              Implementation → PR → evidence folded into ACs / Current State
```

**Create the ticket at the requirement stage. Do not invent an approach to fill
a template.** When the *how* is unknown, that is the honest, expected state at
creation — say so in Current State and let the design review settle it.

QUE-262 is the canonical example: at birth it was simply *"two stacked
reconciliations on page 11 got fused into one table — split them."* The
detection method, the subdivision rule, the re-extraction strategy, the
"Camelot stands on disagreement" decision, the descope to QUE-263 — all of it
was **discovered during plan-review and design**, and folded into Current State
afterward. See the [worked example](#worked-example-que-262-in-two-timelines).

---

## The Core Model: frozen Ask + living Current State

Two parts of every ticket, with opposite edit rules. This split is what keeps a
ticket honest and readable from creation through done.

### The Ask is frozen

Written once, at creation. It states the requirement and why it matters, in
plain language. It is **never rewritten** — it stays as the honest record of
what was originally asked. If the requirement itself genuinely changes, that is
a new ticket or an explicit, dated amendment — not a silent edit.

### Current State is living

A single section, **edited in place** as discovery happens. It is the one source
of truth for: current status, the settled approach (with links to the
plan-review / design doc), what was descoped and where it went, validation
results, and what is still open.

> **The rule that keeps tickets from contradicting themselves: supersede in
> place, never append.** When discovery reverses an earlier decision, rewrite
> Current State and note the old idea as superseded. Do **not** staple a second,
> conflicting plan onto the bottom of the ticket. (This is exactly the failure
> that left QUE-262 with a top section and an appended plan that disagreed, and
> QUE-233 with two halves prescribing opposite verification guards.)

---

## Ticket Anatomy

The same skeleton for Story, Task, and Bug. The *Ask* phrasing differs by type;
the structure does not.

| Section | Written | Edited later? | Purpose |
|---|---|---|---|
| **Title** | creation | rarely | Plain, descriptive, no `[STORY]`-style prefix |
| **The Ask** | creation | **frozen** | The requirement and why it matters, in human terms |
| **Why now / What's open** | creation | frozen | Honest statement of what isn't known yet |
| **Acceptance Criteria** | creation (provisional) | sharpened after design | Start rough; tighten to match the settled approach |
| **Current State** | after discovery | **living** | Status · settled approach (+ links) · descoped · validated · still-open |
| **Links** | ongoing | ongoing | Epic · plan-review · design doc · PR · related tickets · Standards |

What is **not** in a ticket body anymore (it lives in
[ENGINEERING_STANDARDS.md](ENGINEERING_STANDARDS.md) and is referenced with one
line):

- Functional evidence requirements
- The Definition of Done checklist
- Boilerplate "Technical Notes" (PydanticAI / Logfire / pyright / frozen models)
- Static evidence/DoD checkboxes — the **PR** carries evidence; the checklists
  were scaffolding for less-mature automation and are removed.

### Acceptance Criteria format

Each criterion names how it is verified — keep this; it is what makes evidence
checkable:

```
h3. AC1: <capability>
* *Verify by:* <how to verify — real document, real workflow>
* *Expected:* <concrete, measurable outcome>
* *Show:* <what to demonstrate — page, bbox, counts, accuracy>
```

At creation, ACs are *provisional* (rough, may not know the mechanism yet).
After design they are *sharpened* to match the settled approach, and the actual
result is recorded against each (e.g. `AC2 ✓ — 8 kept as 1, 0 false splits`).

### The Ask, by type

- **Story** — user value. Lead with `As a … I want … So that …`, then the
  problem/context. (User-story phrasing goes in the body, never the title.)
- **Task** — technical/infra/refactor/doc work with no user-visible change.
  Lead with what work is needed and why.
- **Bug** — the defect *is* the requirement. The Ask holds repro steps, expected
  vs. actual behavior, environment, and severity. Fix evidence (reproduce → fix
  → no regression) goes in the PR per the standards doc.
- **Sub-task** — a piece of a parent. The Ask is scoped to this piece; it names
  its parent. Use only when [warranted](#sub-tasks).

---

## Worked Example: QUE-262 in two timelines

The reference model. Same ticket, two moments in its life. The **Ask** is
identical in both — only **Current State** and the **ACs** evolve.

### ① At creation — requirement only (all that existed)

> **Title:** Split over-merged Set-of-Mark tables back into their real tables
> **Type:** Story · **Epic:** QUE-1 · **Priority:** Medium
>
> **The Ask** — On `VISA_991_Q126.pdf` page 11, two stacked Non-GAAP
> reconciliations ("Three Months Ended December 31, **2025**" and "...**2024**")
> were located as **one** region and emitted as a single fused table. The numbers
> are right, but the two tables' period labels, headers, and footnotes get
> crossed or lost. On a financial filing, a reconciliation stamped with the
> wrong quarter is a **material defect**. Over-merged regions must be split back
> into their real constituent tables.
>
> **Why now / open** — The locator prompt already says to split stacked tables
> and merged anyway, so a prompt tweak is probably not the fix. *How* to detect
> and split is open — needs a design review.
>
> **Acceptance Criteria (provisional)** — AC1: page 11 → 2 tables, each with its
> 2025 / 2024 subtitle. AC2: genuinely-single tables never split. AC3: nothing
> dropped (rows, footnotes).
>
> **Current State** — *To Do. Needs plan/design review; detection method and
> split mechanism both open.*
>
> **Links** — Epic QUE-1 · Standards: docs/ENGINEERING_STANDARDS.md

### ② After plan-review + design (same ticket, later)

The Ask is unchanged. Discovery rewrote **Current State** and sharpened the ACs:

> **Current State** — **Done (PR #134).**
> Approach settled in [plan-review] / [design]:
> - **Detection = confluence** of two count signals (docling region count + a
>   minimal vision probe). Split **only** when both agree N>1; vision confirms a
>   count, never produces coordinates.
> - **Otherwise Camelot stands** — any disagreement, or agree-on-1, passes the
>   region through unchanged. **No review queue.** *(Supersedes the early
>   "surface for review" idea.)*
> - **Subdivision is deterministic and never drops** — docling seam + Camelot
>   outer extent; union of sub-regions == original (keeps footnotes that sit
>   below docling's tight box).
> - **Re-extract each sub-region from the source PDF**, never post-processed
>   output.
> - **Descoped:** unit-attribution capture → **QUE-263**.
> - **Validated:** page 11 → 2 tables (97.4 / 98.0 accuracy, footnotes
>   recovered); across 10 regions, 1 split, 0 false splits.
> - **Still open:** different-header stacked pair untested; only N=2 validated.
>
> **Acceptance Criteria** — AC1 ✓ · AC2 ✓ (8 kept as 1; Contacts disagreement →
> not split) · AC3 ✓ · AC4 (re-extract from source) ✓

Note how the early "surface for review" idea is recorded as *superseded* inside
Current State, rather than left standing in a contradictory appended plan.

---

## Issue Types and Selection

| Type | Purpose | Signals |
|---|---|---|
| **Epic** | Large initiative spanning many Stories/Tasks | *Team-managed — agents cannot create; they link.* |
| **Story** | User-facing feature or capability | "as a user", "feature", "enable", "upload", "view" |
| **Task** | Technical / infra / refactor / docs; no user-visible change | "refactor", "upgrade", "migrate", "set up", "optimize" |
| **Bug** | Defect, error, regression, broken behavior | "fix", "broken", "fails", "incorrect", "regression" |
| **Sub-task** | A piece under a parent (see [Sub-tasks](#sub-tasks)) | only when warranted |

**Selection order:** strategic initiative → Epic (cannot create); delivers user
value → Story; fixes broken behavior → Bug; technical work with no user-visible
change → Task; a piece under an existing parent → Sub-task. If it is genuinely
ambiguous (e.g. a refactor that also changes UX), ask rather than guess.

---

## Title Conventions

Clear and descriptive, with **no redundant type prefix** — Jira already shows
the type.

| | |
|---|---|
| ✅ | `Upgrade Python to 3.13` · `PDF extraction fails on rotated pages` |
| ❌ | `[TASK] Upgrade Python...` · `[BUG] PDF extraction...` · `As a user, I want…` (user-story phrasing belongs in the body) |

---

## Status and Decision Conventions

This is how a ticket communicates **where it stands**, not just what was asked.

- **Current State carries the status narrative**, in prose — where work landed,
  what's decided, what's descoped — so a reader doesn't reconstruct it from the
  status field plus scattered comments.
- **Supersede in place** (the [core-model](#the-core-model-frozen-ask--living-current-state)
  rule): a reversed decision is rewritten and the old idea marked superseded;
  never appended alongside.
- **No decorative checklists** in the ticket body. The Definition of Done lives
  in [ENGINEERING_STANDARDS.md](ENGINEERING_STANDARDS.md) as the universal bar;
  the PR carries the evidence.
- **Descopes are explicit** — "moved to QUE-XXX" in Current State (as QUE-262
  did for unit-attribution → QUE-263), so dropped scope stays visible and never
  silently disappears.

### Jira status field

`To Do → In Progress → In Review → Done`, mirrored from Git activity by
automation (branch → In Progress, PR → In Review, merge → Done). Agents treat
the status field as **read-only awareness** and do **not** transition tickets
unless a human explicitly asks. The narrative in Current State is the human-
readable companion to the field.

---

## Epics and Known Epics

**Agents cannot create Epics** — they are team-managed strategic tools. Agents
**link** issues to existing Epics. If Epic creation is requested, say so and ask
the team to create it manually, then offer to link.

**Known Epics** (verified against Jira):

| Key | Epic | Typical scope signal |
|---|---|---|
| QUE-89 | Development Infrastructure | tooling, CI, pyright, pre-commit, process/docs |
| QUE-1 | Document Processing | PDF, docling, table extraction/splitting |
| QUE-2 | Metrics Search | matching, heuristics, LLM search |
| QUE-91 | Extraction & Validation | extraction, PydanticAI, value grounding |
| QUE-92 | Pipeline & Web UI | pipeline, FastAPI, UI |
| QUE-99 | Excel Processing | Excel, xlsx, spreadsheets |

Link by explicit instruction, or by obvious scope match. If unclear, leave blank
and note "Epic assignment pending — team to assign during planning."

---

## Sub-tasks

Optional and situational — not required for every ticket.

**Use when:** the parent has 3+ distinct, independently-shippable pieces, work
can be parallelized across PRs, or a complex bug needs multiple separate fixes.

**Don't use when:** a single cohesive change, only 1–2 steps, or steps that must
ship together — use a checklist inside the parent's Current State instead.

A Sub-task follows the same anatomy as its parent, scoped to its own piece, and
names its parent in the Ask.

---

## Validation

Before creating a ticket, confirm:

- Type determined (Story / Task / Bug / Sub-task — never Epic).
- Title is clear, descriptive, no redundant prefix.
- **The Ask** is present and states the requirement + why it matters.
- **Acceptance Criteria** present (provisional is fine at creation), each with
  Verify / Expected / Show.
- **Current State** present — even if it only says "To Do; approach open."
- Standards referenced (one line), not pasted.
- Parent specified for a Sub-task; Epic linked or explicitly left blank.
- Project key is `QUE`.

Type-specific: a **Story** has `As a … I want … So that …` in the body; a
**Bug** has repro / expected / actual / severity inside the Ask.

If validation fails, state the specific gap and what's needed rather than
creating a malformed ticket.

---

## Priority Defaults

| Type | Default |
|---|---|
| Story | Medium |
| Task | Medium |
| Bug | From severity — Critical/High → High, Medium → Medium, Low → Low |
| Sub-task | Inherit from parent |

New issues open as `To Do`, unassigned (team assigns during planning).

---

## Related Documents

- [ENGINEERING_STANDARDS.md](ENGINEERING_STANDARDS.md) — functional evidence,
  Definition of Done, and technical standards every ticket inherits
- [GITHUB_WORKFLOW_SPEC.md](GITHUB_WORKFLOW_SPEC.md) — branch naming, PR title/
  body format, PR-side evidence, merge strategy
- [CLAUDE.md](../CLAUDE.md) — project instructions and delegation rules
