This commit is contained in:
Tiara Rodney 2026-02-10 18:59:59 +01:00
commit 76266cedc6
No known key found for this signature in database
GPG key ID: 5CD8EC1D46106723
23 changed files with 4041 additions and 0 deletions

308
src/README.rst Normal file
View file

@ -0,0 +1,308 @@
############
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::
--ISSUE
Content-Type: <mime-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::
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::
--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::
Sprints:
followed by one or more sprint entries.
Sprint Entry Forms
------------------
Both compact and expanded forms are valid.
Compact form::
- Name: Sprint 1
Range: 2026-02-01..2026-02-14
Expanded form::
-
Name: Sprint 1
Range: 2026-02-01..2026-02-14
Sprint Entry Grammar
--------------------
A sprint entry begins at a line matching::
^\s*-\s*(Name:.*)?$
Keyvalue lines inside an entry match::
^\s+[A-Za-z][A-Za-z0-9]*:\s*(.*)$
Required keys:
* ``Name: <string>``
* ``Range: <YYYY-MM-DD>..<YYYY-MM-DD>``
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::
ID: <integer>
Type: <feature|bugfix|hotfix>
Title: <short title>
Status: <open|in-progress|done|hold|cancelled>
Priority: <low|medium|high>
Created: <YYYY-MM-DD>
Relationships: <comma-separated list or empty>
DueStart: <YYYY-MM-DD> # OPTIONAL
DueEnd: <YYYY-MM-DD> # OPTIONAL
Description: <first line>
<continuation lines>
Field Semantics
---------------
* **ID**: unique integer, strictly increasing.
* **Type**: one of ``feature``, ``bugfix``, ``hotfix``.
* **Status**: one of ``open``, ``in-progress``, ``done``, ``hold``, ``cancelled``.
* **Priority**: one of ``low``, ``medium``, ``high``.
* **Created**: ISO date.
* **Relationships**:
* Empty::
Relationships:
* Or list::
Relationships: dependsOn:43, relatesTo:10
* Valid kinds: ``dependsOn``, ``relatesTo``, ``blocks``.
* **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::
<Type>/<ID>
Examples::
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 ``<Type>/<ID>``.
* 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::
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::
--ISSUE
Content-Type: <type>
<body>
* Final boundary::
--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::
{
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::
application/<subtype>
Examples:
* ``application/metadata``
* ``application/changelog``
* ``application/epilog``
The preprocessor MUST preserve unknown part types but MUST NOT reorder them.
Always determine first, whether the issue must immediately resolve on the
production branch, or whether it can be resolved by introducing it through the
development branch.
Ensure to switch to the branch impacted by the issue.
Add a new issue to the TODO file.
Issues first applied to the development branch
MUST either be of type ``feature``, or ``bugfix``. Issues applied to the
production branch MUST be of type ``hotfix``.
Define a

62
src/conf.py Normal file
View file

@ -0,0 +1,62 @@
import datetime
from sphinx.util import logging
logger = logging.getLogger(__name__)
extensions = [
'sphinx.ext.intersphinx',
'sphinx.ext.todo',
'sphinx_last_updated_by_git',
'sphinx_markdown_builder',
]
templates_path = ["_templates"]
project = "MIME TODO"
copyright = "2026, Tiara Rodney"
html_title = project
html_theme = 'bizstyle'
html_sidebars = {}
html_show_sphinx = False
html_show_sourcelink = False
html_context = {
"bitbucket_url": "https://bitbucket.org",
"bitbucket_user": "byteb4rb1e",
"bitbucket_repo": "ai-mime-todo",
"bitbucket_version": "master",
"doc_path": "src/"
}
language = 'en'
todo_include_todos = True
rst_prolog = f"""
.. |build-time| replace:: {datetime.datetime.now().strftime("%d %B %Y, %H:%M")}
"""
html_last_updated_fmt = "%d %B %Y, %H:%M"
root_doc = "README"
from pathlib import Path
import shutil
def on_build_finished(app, exception):
if exception is not None:
return # skip on build failure
ilicense = Path(app.confdir) / '..' / 'LICENSE'
olicense = Path(app.outdir) / 'LICENSE'
if ilicense.exists():
shutil.copyfile(ilicense, olicense)
logger.info(f"copied {ilicense}{olicense}")
def setup(app):
app.connect("build-finished", on_build_finished)