The igris plan format (formats 1 to 3)

This is the format of the markdown plans igris runs: how a plan is split into phases and tasks, what each column means, and what igris changes when it runs one. It is written for people writing plans by hand and for tools that produce them. It describes format 1, format 2 (since igris 1.2: format 1 plus includes) and format 3 (since igris 1.5: format 2 plus parallel phases), all frozen for igris 1.x (SPEC §19). SPEC §3–4 is the normative text; this page says the same with more examples. If they ever disagree, the SPEC wins and this page is fixed.

igris check validates a plan against all of this and prints every problem at once as file:line: message. A plan in another format can be converted with igris adapt.

A complete example

# Shop backend

<!-- igris:format 1 -->

Anything outside the task tables is ignored: notes, legends, working rules.

## M0 — Foundation

| ID | Task | Deps | Status | Model | Owner | Mode | Spec |
|---|---|---|---|---|---|---|---|
| M0-01 | **Go module** — init module, pin the Go version | — | done | sonnet | agent | — | §1 |
| M0-02 | **Config loader** — read `shop.toml` | M0-01 | ready | sonnet | agent | — | §2 |
| M0-03 | **Wire format** — `v1 \| nonce \| ciphertext` | M0-01 | ready | opus | agent | plan | §3 |
| M0-04 | **Create the GitHub repository** | — | ready | — | user | — | — |

## Phase 2 — API

| ID | Task | Deps | Status | Model | Owner | Timeout | Verify |
|---|---|---|---|---|---|---|---|
| A-01 | **Wait for API keys from the client** | — | ready | — | user | — | — |
| A-02 | **Orders endpoint** | M0-02…M0-03, A-01 | blocked | sonnet | agent | 45m | — |
| A-03 | **Docs pass** | A-02 | blocked | haiku | agent | — | none |
| A-04 | **Old importer** | — | skipped (not needed) | — | agent | — | — |
| A-G | **API gate** — owner smoke test | A-02, A-03 | blocked | sonnet | agent + user | — | — |

This plan has two phases, M0 and Phase-2, and 9 tasks. M0-02 and M0-03 are ready; A-02 waits on them and on your own task A-01.

Format marker

A plan may declare its format on a line of its own before the first ## heading:

<!-- igris:format 1 -->
  • It is optional, and stays optional: a plan without a marker is format 1, in every igris 1.x and later.
  • Spaces inside the comment don't matter (<!--igris:format 1--> is the same). A marker inside a fenced code block is not one.
  • A marker that isn't a whole number, a second marker, or a marker after the first ## heading is a validation error.
  • <!-- igris:format 2 --> declares format 2, which a plan that includes other files needs. A format-2 plan without includes is valid too.
  • <!-- igris:format 3 --> declares format 3, which a plan with parallel phases needs. It may include files too.
  • A plan marked with a format igris doesn't know (<!-- igris:format 4 -->) is refused with plan format 4 needs a newer igris, and nothing else about it is reported or changed. igris 1.0 and 1.1 read format 1 only, so they refuse a format-2 plan this way, and igris 1.2–1.4 refuse a format-3 plan. A future format will need its marker, so an unmarked plan never has to be edited.

Split plans (format 2)

Since igris 1.2 a plan may be split across files. The main plan is the file igris reads (tasks.md, or plan in igris.toml); a line <!-- igris:include PATH --> in it pulls in another file's phases at that point:

tasks.md

# Shop backend

<!-- igris:format 2 -->

## M0 — Foundation

| ID | Task | Deps | Status | Model | Owner |
|---|---|---|---|---|---|
| M0-01 | **Go module** | — | done | sonnet | agent |

<!-- igris:include phases/v2.md -->

## M9 — Release

| ID | Task | Deps | Status | Model | Owner |
|---|---|---|---|---|---|
| M9-01 | **Tag 2.0** | V2-01…V2-02 | blocked | sonnet | agent |

phases/v2.md

# Version 2, planned apart

## V2 — Payments

| ID | Task | Deps | Status | Model | Owner |
|---|---|---|---|---|---|
| V2-01 | **Stripe client** | M0-01 | ready | opus | agent |
| V2-02 | **Webhooks** | V2-01 | blocked | sonnet | agent |

The phases run M0, V2, M9: plan order is the main plan with each include line replaced by its file, and "file order" everywhere on this page means plan order.

  • Format 2. A plan with an include line declares <!-- igris:format 2 --> (or 3); without it (or with 1) each include line is an error saying to add it. Only the main plan's marker counts; an included file may declare format 1, 2 or 3, so it can be checked on its own.
  • The line. <!-- igris:include PATH --> on a line of its own, outside a fenced code block, spaces inside the comment ignored. PATH is everything between igris:include and -->, trimmed, without quotes, and ends in .md.
  • Where. Anywhere in the main plan, before or between phases. An include line ends the section above it, so a task table right after it, before the next ## heading, is an error. Text in an included file before its first ## heading is prose.
  • One level. Only the main plan includes files; an include line in an included file is an error. Each file is included once: including a file a second time, or the main plan itself, is an error naming the first.
  • Paths are relative to the main plan's directory, like a markdown link. Not absolute, not starting with ~, no ... Once symlinks are followed, the file must be inside the project (the project root for arise and the home screen, the working directory for check, phases and status), must not be the main plan and must not be under .igris/. It must be a regular file.
  • Limits. Each file, and all files of the plan together, at most 16 MiB; at most 32 files, the main plan included.
  • IDs are unique across all files; a clash names both places (phases/v2.md:12: task V2-01 is also in tasks.md:40). Dependencies may point into any file, and a range follows plan order.
  • Errors are file:line: message in the file the line is in, sorted in plan order. A problem with an include (missing, outside the project, not .md, too large, too many files, included twice, nested, no format 2) is reported at the include line.
  • --json of check, phases and status lists the plan's files (the main plan first) and each phase's file.
  • Context paths stay relative to the project root, whichever file the row is in.
  • When igris runs it, each Status cell is written in the file its row is in; include lines and every other byte of every file stay as they are. Every file is re-read whenever igris looks at the plan, so an edit to any of them holds the run, as does a row moved to another file or an include added or removed. The task prompt names the file the row is in.
  • igris adapt converts one file: it refuses a split plan. Inline the included files first, or adapt one of them on its own with --plan.

Parallel phases (format 3)

Since igris 1.5 the tasks of a phase may run at the same time. A line <!-- igris:parallel --> in a phase's section marks it parallel; the plan declares <!-- igris:format 3 -->:

# Shop backend

<!-- igris:format 3 -->

## M1 — Storage

<!-- igris:parallel -->

| ID | Task | Deps | Status | Model | Owner | Group |
|---|---|---|---|---|---|---|
| M1-01 | **Orders table** | — | ready | sonnet | agent | db |
| M1-02 | **Users table** | — | ready | sonnet | agent | db |
| M1-03 | **Cache client** | — | ready | sonnet | agent | — |
| M1-04 | **Orders store** — on the orders table | M1-01 | blocked | opus | agent | — |
| M1-G | **Storage gate** — the owner approves the schema | M1-01…M1-04 | blocked | sonnet | agent + user | — |

M1-01 and M1-03 start together. M1-02 waits for M1-01, since both are in group db, and M1-04 waits for its dependency. The gate runs last, alone.

  • What the marker means. The phase's Deps are complete: any two of its tasks of which neither depends on the other, directly or through other tasks, may run at the same time, each in a git worktree of its own. File order no longer orders them. A phase without the marker runs one task at a time, as always.
  • The line. <!-- igris:parallel --> on a line of its own, anywhere in the phase's section (after its ## heading, before the next ## heading or include line), outside a fenced code block, spaces inside the comment ignored. In a split plan, a phase in an included file is marked in that file.
  • Errors: a marker in a plan that doesn't declare format 3, a marker with a value (<!-- igris:parallel 4 -->: how many tasks run at once is [parallel] max in igris.toml), a marker before the first ## heading, after an include line, in a section without a task table, or twice in one phase.
  • Group. Tasks with the same Group never run at the same time, whatever their Deps say: use it for tasks that touch one shared thing (a database schema, a lockfile, a port). A Group is one name (letters, digits, ., _, -), compared without regard to case; empty, — or - is none. A task is in at most one group, so db, cache is an error. In a phase without the marker Group changes nothing, and igris check says so. In a format-1 or format-2 plan, a Group column is an ordinary extra column.
  • Implied dependencies. A plan written to run in order often leaves the order unsaid. In a parallel phase, igris check warns when a task's text names an earlier task of the phase (builds on M1-02) and neither depends on the other: add the dependency if it must finish first.
  • Who runs alone. user and agent + user tasks, gates included, run with nothing beside them ([parallel] exclusive_owner_tasks).

Phases

  • A phase is a level-2 heading (## ) whose section has a task table. ### and deeper headings stay inside the current phase. ## sections without a task table are ignored.
  • The phase ID is the first word of the heading: ## M0 — Foundation is M0. When the first word is alphabetic and the second is all digits, both make the ID with a hyphen: ## Phase 2 — API is Phase-2 (but ## Phase 2: API is Phase, since 2: isn't all digits).
  • Phase IDs are unique within a plan, compared without regard to case (## m0 and ## M0 clash). Wherever a phase is named (the command line, [phases.<id>] in igris.toml), case doesn't matter either.
  • Phases run in file order (plan order in a split plan). Headings and tables inside fenced code blocks (``` or ~~~) are ignored.
  • A plan needs at least one task table.

Task tables

A task table is a GitHub-flavored markdown table whose header has at least ID, Status and Model. A phase has at most one task table; other tables next to it (a legend, say) are ignored. A task table before the first ## heading is an error.

ColumnRequiredValues
IDyesUnique across the plan: a letter or digit, then letters, digits, ., _ or - (M0-01, A.3, 42).
TaskrecommendedThe description. Its first **bold** span is the task's title; without one, its first 80 characters.
DepsnoDependencies, below. Without the column, no task has any.
StatusyesBelow.
ModelyesA rank from [models] in igris.toml (sonnet, opus, fable, haiku by default), or — for none.
Ownernoagent, user or agent + user. Without the column, or empty: agent.
Modenodefault, accept, auto, plan, plan:default, plan:accept, plan:auto, plan:yolo, yolo, manual (since 1.2), or —: the run mode for this task's session. A plan:<mode> session plans first and continues in <mode> once you approve the plan in igris; plain plan continues in [plan_mode] then. yolo and plan:yolo need the typed confirmation every run.
VerifynoA verify profile from igris.toml, none to skip verification, or —/empty for the default. Never a command.
TimeoutnoA Go duration of at least 1s (45m, 1h30m) after which the task is reported overdue.
ContextnoUp to 20 comma-separated paths inside the project that the session is told to read first.
GroupnoFormat 3: a name; tasks of a parallel phase with the same Group never run at the same time.

Reading the header and cells:

  • Column names are matched without regard to case, with surrounding spaces, tabs, * and backticks ignored (**Status** is Status). igris.toml can alias other names ([columns], e.g. "Depends on" = "Deps"). A header that names a column twice is an error.
  • A table with a column that looks like dependencies (Depends on, Requires, Blocked by, …) but no Deps column is valid; igris check warns that igris reads no dependencies from it.
  • Extra columns (Spec above) are kept as they are and given to the session as context.
  • Cells are split on unescaped pipes only: \| in a cell is a literal |.
  • In Model, Mode and Deps, an empty cell, —, - and none (any case) all mean "none". In Verify, Timeout and Context, empty, — and - mean "not set"; in Verify, none means "don't verify".
  • Owner, Mode and Verify values are read in any case (Agent + User, YOLO, Fast). Model ranks are case-sensitive (Sonnet is not sonnet; igris check suggests the right one).
  • Backticks around a Model, Mode, Verify, Timeout or Status value are ignored.
  • A control character (other than tab) in a task row or a phase heading is an error.

Rules that tie the columns together:

  • user tasks have Model —. agent and agent + user tasks need a Model that [models] resolves, unless they are done or skipped.
  • Verify, Timeout and Context are checked only on tasks that aren't done or skipped. On a user task they are ignored, with a warning.
  • A Context path must exist inside the project: no absolute paths, no .., not . itself, no trailing / on a file, no symlink out of the project.

Status

ready, blocked, in progress, done, skipped, in any case, optionally in backticks. Anything after the word is kept and ignored: skipped (not needed) is skipped. Any other value is an error.

  • done and skipped satisfy a dependency.
  • A task whose dependencies are all satisfied should be ready, otherwise blocked. igris keeps this true as it runs; igris check warns where the file disagrees.

Dependencies

  • Empty, —, - or none: no dependencies. Otherwise a comma-separated list of task IDs, from any phase.
  • A range A…B (or A...B, A..B) is every task from A to B in file order (plan order in a split plan). Both ends must exist and A must come first. An entry that is itself a task ID is never read as a range, since IDs may contain dots.
  • Duplicates are ignored. An unknown ID, a task depending on itself and a cycle are errors (a cycle is shown as its path, a → b → a).
  • To wait on something outside the plan (keys from a client, a deploy, a date), depend on a user task that names it, like A-01 above.

What igris changes in a plan

  • Only Status cells. igris writes in progress, done and skipped, and moves tasks between ready and blocked as dependencies are met. Every other byte stays as it is: other cells, whitespace, line endings (CRLF too), the trailing newline, a UTF-8 byte order mark, the format marker.
  • In a Status cell, the padding and backticks are kept (`ready` becomes `done`); text after the old word is dropped, since it described the old status.
  • igris never adds, removes or reorders rows. The only exception is igris adapt, which replaces the plan only after you accept its proposal.
  • Writes are atomic, and a plan someone else changed in the meantime is re-read rather than overwritten. In a split plan each file is replaced atomically, one after the other; a change to any file of the plan before then discards the write and re-reads them all.

What can change in igris 1.x

New optional columns may be added to format 1. An older igris 1.x keeps such a column as an extra column, so a plan that uses one still runs. Nothing else in this page changes in 1.x: no column, status word, rule or value is removed or changes meaning.