# Renga Specification

> Japanese version: [spec.ja.md](spec.ja.md)

---

## Directory structure

```
issues/
  README.md           Issue list (auto-generated by renga)
  open/
    N-name.md         Open issues
  in-progress/
    N-name.md         In-progress issues
  pending/
    N-name.md         Pending (blocked or deferred) issues
  done/
    N-name.md         Closed issues
  unknown/
    N-name.md         Issues with missing or unparseable frontmatter
```

## File naming

Two storage layouts are supported and may be mixed freely:

**Flat file** (default):
```
N-short-name.md
```

**Directory** (use `--dir=true` to create; allows placing attachments or notes alongside the issue):
```
N-short-name/
  README.md     Issue content (same format as the flat file)
  ...           Any additional files
```

- `N`: Plain positive integer, no zero-padding. Assigned by `renga create` as max existing number + 1.
- `short-name`: Kebab-case short description (Unicode alphanumeric and hyphens only, up to 80 bytes).

**The ID lives only in the filename / directory name — not in frontmatter or body.**

**Backward compatibility**: Legacy zero-padded IDs (`0042-*.md`, `00042-*.md`) are supported. All tools read them; new issues are always created without padding.

Use `renga update <ID> --dir=true` to expand a flat file to a directory, and `--dir=false` to collapse it back (fails if the directory contains files other than `README.md`).

## Frontmatter

```markdown
---
schema_version: 1           # optional (absent in files created before this field was introduced)
status: open
priority: high|medium|low   # optional
area: area-name             # optional (e.g. core, cli, docs)
labels: []
milestone: v1.0             # optional (e.g. v1.0, 2026-Q3, sprint-3)
assignee: alice             # optional (who is responsible for this issue)
---
```

Frontmatter is optional for normal read/list operations. When absent, `status` is `unknown`, `priority` is `-` (unknown), and `area` is empty (no group). `renga validate` is stricter: missing or unparseable frontmatter, and frontmatter without a `status` field, are reported as errors so malformed issue files can be found before closing work.

The `status` frontmatter field is the authoritative source of issue status. Per-status directories (`open/`, `pending/`, `in-progress/`, `done/`) are a synchronized layout for discoverability. `renga validate` reports an error when a file is stored outside the directory named by its frontmatter status. `renga validate --auto-correct` moves mismatched files to the directory declared by frontmatter.

`schema_version` identifies the frontmatter format version. New files include `schema_version: 1`. Files without this field (created before the field was introduced) are treated as absent (`None` internally); tools handle them the same as version 1.

`area`, `priority`, `milestone`, and `assignee` fields are optional even when frontmatter is present. Omitting `area` places the issue in no group (shown without a heading in `issues/README.md`). Omitting `priority` defaults to `medium`. Omitting `milestone` means the issue belongs to no milestone. Omitting `assignee` means no one is assigned.

**status values**

| Value | Meaning |
|---|---|
| `open` | Needs action. |
| `pending` | Blocked or deferred. |
| `in-progress` | Actively being worked on. |
| `done` | Closed (moved to `done/`). |
| `unknown` | Frontmatter is absent or unparseable. Read-only — not writable by renga. |

**priority values**

| Value | Meaning |
|---|---|
| `high` | Needs immediate attention. |
| `medium` | Needs action but not urgent. |
| `low` | Suggestion or improvement opportunity. |
| `-` | Unknown — frontmatter is absent or the field is missing. Read-only. |

## Title

**The title is extracted from the first `# Heading` line in the body — not from frontmatter.**

Falls back to the file stem if no heading is found.

## Issue file template

```markdown
---
schema_version: 1
status: open
priority: medium
area: area-name
labels: []
---

# Title

Brief description of what needs to be done.
```

## Commands

```
renga init
renga create <title> [--id <N>] [--slug <slug>] [--priority high|medium|low] [--area <area>] [--body <text|-\>] [--milestone <milestone>] [--assignee <assignee>] [--label <label>]... [--dir=true|false]
renga create --json
renga done <ID>...
renga pending <ID>...
renga in-progress <ID>...
renga reopen <ID>...
renga list [--status open|pending|in-progress|done|unknown] [--area <area>] [--label <label>] [--milestone <milestone>] [--assignee <assignee>] [--json]
renga show <ID> [--json]
renga edit <ID>
renga update <ID> [<title>] [--priority high|medium|low] [--area <area>] [--status open|pending|in-progress] [--milestone <milestone>] [--assignee <assignee>] [--label <label>]... [--add-label <label>]... [--remove-label <label>]... [--body <text|->]
renga update <ID> --dir=true|false
renga update <ID> --json
renga info
renga migrate
renga validate [ID]... [--auto-correct]
renga completions <bash|zsh|fish>
renga help [command]
```

`N` is the plain integer issue ID (e.g. `42`). Legacy zero-padded IDs (e.g. `00042`) are also accepted.

`renga create --json` reads one JSON object from stdin. Supported fields are
`title` (required), `id`, `slug`, `priority`, `area`, `body`, `milestone`,
`assignee`, and `labels`. It cannot be combined with positional or field flags.

`renga update <ID> --json` reads one JSON object from stdin. Supported fields
are `title`, `priority`, `area`, `status`, `milestone`, `assignee`, `labels`,
`add_labels`, `remove_labels`, and `body`. It cannot be combined with positional
or field flags; `<ID>` remains the issue selector.

Passing an empty string to `--milestone` or `--assignee` removes the field from
frontmatter entirely (e.g. `renga update 1 --assignee ''`).

`renga validate` without IDs checks every issue file under `issues/`. Passing
one or more IDs restricts validation to those issue IDs while still detecting
duplicate files for the selected IDs. `--auto-correct` fixes status directory
mismatches by moving files to the directory declared by frontmatter status.

If an issue file is stored under `done/` but its frontmatter status is active
(`open`, `pending`, or `in-progress`), active-issue commands may still operate
on it because frontmatter status is authoritative. Such commands print a
warning and recommend `renga validate <ID> --auto-correct`. A normal
`status: done` issue remains outside the status-transition commands (`done`,
`pending`, `in-progress`, `reopen`) unless reopened. `update` and `edit` are
exceptions: they can edit a done issue's fields directly, since `update` never
accepts `--status done` and cannot transition an issue to done.

## `.renga.yml`

Optional configuration file placed in the project root.

```yaml
issues_dir: issues    # default: issues

area_order:           # display order in the list (alphabetical if omitted)
  - backend
  - frontend
  - misc

area_labels:          # display names for areas (area name used as-is if omitted)
  backend: "Backend"
  frontend: "Frontend"
  misc: "Other"
```

## Project root discovery

When any `renga` command runs, it walks up from the current directory toward the filesystem root, stopping at the first directory that matches either condition:

1. A `.renga.yml` file is present — the `issues_dir` value is used as the issues directory.
2. An `issues/` subdirectory is present.

Falls back to `issues/` relative to the current directory if nothing is found.
