# Introduction This document defines the canonical format, semantics, and processing rules for the repository-root `TODO` file. The file is a human-friendly, append-only (allowing modifications) issue tracker that is parsed by TypeScript tooling using a MIME envelope added at parse time. The raw `TODO` file is not a MIME document. A preprocessor wraps it into a valid `multipart/mixed` MIME message before parsing. ## Raw File Structure The raw `TODO` file consists of a sequence of *parts*, each beginning with: ```default --ISSUE Content-Type: ``` Valid part types are: * `application/sprints` — defines sprint metadata * `application/issue` — defines a single issue Parts may appear in any order in the raw file. The preprocessor will reorder them so that the `application/sprints` part appears first. ## MIME Envelope (Added by Preprocessor) Before parsing, the preprocessor wraps the raw file into a MIME multipart message. Prolog added by the preprocessor: ```default MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="ISSUE" ``` Each raw `--ISSUE` boundary becomes a MIME boundary. The preprocessor extracts each part’s `Content-Type` and body, reorders parts, and emits a final closing boundary: ```default --ISSUE-- ``` The resulting MIME message is parsed using a standard MIME parser. ## Part: `application/sprints` This part defines sprint metadata. The body MUST begin with: ```default Sprints: ``` followed by one or more sprint entries. ### Sprint Entry Forms Both compact and expanded forms are valid. Compact form: ```default - Name: Sprint 1 Range: 2026-02-01..2026-02-14 ``` Expanded form: ```default - Name: Sprint 1 Range: 2026-02-01..2026-02-14 ``` ### Sprint Entry Grammar A sprint entry begins at a line matching: ```default ^\s*-\s*(Name:.*)?$ ``` Key–value lines inside an entry match: ```default ^\s+[A-Za-z][A-Za-z0-9]*:\s*(.*)$ ``` Required keys: * `Name: ` * `Range: ..` The `Range` defines a closed interval `[start, end]`. ## Part: `application/issue` Each issue is represented as a structured block with strict field ordering. ### Required Field Order The following fields MUST appear in exactly this order: ```default ID: Type: Title: Status: Priority: Created: Relationships: DueStart: # OPTIONAL DueEnd: # OPTIONAL Description: ``` ### Field Semantics * **ID**: unique integer, strictly increasing. * **Type**: one of `feature`, `bugfix`, `hotfix`. \* `feature` and `bugfix` issues target the integration branch (`develop`). \* `hotfix` issues target the stable branch (`main` or `master`). * **Status**: one of `open`, `in-progress`, `done`, `hold`, `cancelled`. * **Priority**: one of `low`, `medium`, `high`. * **Created**: ISO date. * **Relationships**: \* Empty: ```default Relationships: ``` * Or list: ```default Relationships: dependsOn:43, relatesTo:10 ``` * Valid kinds: `dependsOn`, `relatesTo`, `blocks`, `causedBy`. * **DueStart / DueEnd**: \* Optional. \* If only one is present, the other is implicitly equal to it. ### Description Block * The first line appears on the same line as `Description:`. * Continuation lines: \* Must begin with whitespace. \* Must align indentation consistently. * No blank lines allowed inside the description block. ### Body Any lines after the description block are considered free-form body text. The body MUST NOT contain another `ID:` field or a MIME boundary. ## Git Workflow Rules ### Branch Naming Branches for issues MUST follow: ```default / ``` Examples: ```default feature/12 bugfix/7 ``` ### Modification Rules * All edits to `TODO` MUST occur on `develop`. * Feature/bugfix/hotfix branches MUST rebase changes from `develop`. ### Branch Lifecycle * A branch MUST NOT exist before its issue is created. * A branch MUST be named exactly `/`. * A branch MAY merge only when the issue status is `done`. ## Sprint Membership Logic Given: * Sprint interval `[S_start, S_end]` * Issue interval `[I_start, I_end]` ### Normalization * Only `DueEnd` → `I_start = I_end = DueEnd` * Only `DueStart` → `I_start = I_end = DueStart` * Neither → issue is not sprint-bound ### Membership Condition An issue belongs to a sprint if: ```default I_start ≤ S_end AND I_end ≥ S_start ``` ### Current Sprint for Date D 1. All sprints where `S_start ≤ D ≤ S_end`. 2. If multiple match, choose the one with the latest `S_start`. 3. If none match, no active sprint. ## Preprocessor Requirements The preprocessor MUST: * Read the raw `TODO` file. * Split into parts using `--ISSUE`. * Extract each part’s `Content-Type` and body. * Reorder parts so that: \* `application/sprints` appears first (if present) \* All `application/issue` parts follow in original order * Emit a MIME message with: \* `MIME-Version: 1.0` \* `Content-Type: multipart/mixed; boundary="ISSUE"` \* Each part wrapped as: ```default --ISSUE Content-Type: ``` * Final boundary: ```default --ISSUE-- ``` ## Parser Requirements The parser MUST: * Use a MIME parser to extract parts. * Dispatch based on `Content-Type`: \* `application/sprints` → sprint parser \* `application/issue` → issue parser * Enforce: \* Field order \* Required fields \* Description indentation rules \* Sprint entry grammar * Produce a `TodoFile` object: ```default { sprints: Sprint[], issues: Issue[] } ``` ## Error Handling The parser MUST reject: * Missing or malformed `Content-Type` headers * Unknown MIME types * Missing required issue fields * Incorrect field order * Invalid sprint ranges * Invalid date formats * Multiple `application/sprints` parts * Duplicate issue IDs Errors SHOULD include line numbers when possible. ## Extensibility Future part types MAY be added using: ```default application/ ``` Examples: * `application/metadata` * `application/changelog` * `application/epilog` The preprocessor MUST preserve unknown part types but MUST NOT reorder them.