|
| 1 | +# task-dates Specification |
| 2 | + |
| 3 | +## Purpose |
| 4 | + |
| 5 | +TBD - created by archiving change task-due-date. Update Purpose after archive. |
| 6 | + |
| 7 | +## Requirements |
| 8 | + |
| 9 | +### Requirement: タスクは frontmatter `date` で単一の期日を保持できる |
| 10 | + |
| 11 | +タスクの Markdown ファイルは YAML frontmatter キー `date` に `YYYY-MM-DD` 形式(時刻なし、ゼロ埋めの月日)の文字列で単一の期日を保持できる (SHALL)。`date` が未定義 / `null` / 空文字 / 正準形 `YYYY-MM-DD` 以外の値の場合、システムは当該タスクを「期日なし」状態として扱わなければならない (MUST)。 |
| 12 | + |
| 13 | +#### Scenario: 正準形の日付をパースして読み出せる |
| 14 | + |
| 15 | +- **GIVEN** ワークスペース直下の `task-a.md` の frontmatter に `date: 2026-06-15` が記述されている |
| 16 | +- **WHEN** フロントエンドが `list_tasks` または `get_task` を invoke する |
| 17 | +- **THEN** 当該タスクの `Task.date` は文字列 `"2026-06-15"` で返る |
| 18 | + |
| 19 | +#### Scenario: `date` キー欠落は期日なしとして扱われる |
| 20 | + |
| 21 | +- **GIVEN** タスクの frontmatter に `date` キーが存在しない |
| 22 | +- **WHEN** `list_tasks` または `get_task` が当該タスクを返す |
| 23 | +- **THEN** `Task.date` は `null` として返る |
| 24 | +- **AND** フロントエンドは「期日なしタスク」として扱う(カードの期日バッジが非表示になる) |
| 25 | + |
| 26 | +#### Scenario: `date: null` は期日なしとして扱われる |
| 27 | + |
| 28 | +- **GIVEN** タスクの frontmatter に `date: null` が記述されている |
| 29 | +- **WHEN** `list_tasks` または `get_task` が当該タスクを返す |
| 30 | +- **THEN** `Task.date` は `null` として返る |
| 31 | +- **AND** ファイル読み取りは失敗しない |
| 32 | + |
| 33 | +#### Scenario: 正準形でない日付値は期日なしにフォールバックする |
| 34 | + |
| 35 | +- **GIVEN** タスクの frontmatter に `date: 2026/6/5`(スラッシュ区切り・非ゼロ埋め)が記述されている |
| 36 | +- **WHEN** `list_tasks` または `get_task` が当該タスクを返す |
| 37 | +- **THEN** 当該タスクの `Task.date` は `null` として返る |
| 38 | +- **AND** タスク自体は無視されず、他フィールド(title / status / body / tags)は通常通り読み出される |
| 39 | + |
| 40 | +#### Scenario: 日付の serialize / parse がラウンドトリップする |
| 41 | + |
| 42 | +- **GIVEN** アプリ経由で `date` に `"2026-06-15"` が書き込まれる |
| 43 | +- **WHEN** 当該ファイルを再度パースする |
| 44 | +- **THEN** `Task.date` は文字列 `"2026-06-15"` に戻る |
| 45 | +- **AND** YAML の date 型や数値ではなく、文字列として安定的に往復する |
| 46 | + |
| 47 | +### Requirement: `create_task` コマンドは期日を受け取って frontmatter に書き出す |
| 48 | + |
| 49 | +`create_task` Tauri コマンドは、オプションパラメータ `date: Option<String>` を受け付けなければならない (MUST)。`Some(_)` で正準形 `YYYY-MM-DD` が渡された場合、frontmatter キー `date` に書き出さなければならない (MUST)。`None` または空文字の場合、frontmatter に `date` キーを出力してはならない (MUST NOT)。 |
| 50 | + |
| 51 | +#### Scenario: 期日付きでタスクを作成する |
| 52 | + |
| 53 | +- **WHEN** `create_task` が `title="Ship release"`, `status="Doing"`, `date=Some("2026-06-20")` で呼ばれる |
| 54 | +- **THEN** 新規 `.md` ファイルが作成され、その frontmatter に `date: 2026-06-20` が含まれる |
| 55 | +- **AND** 戻り値の `Task.date` も `"2026-06-20"` である |
| 56 | + |
| 57 | +#### Scenario: 期日未指定でタスクを作成する |
| 58 | + |
| 59 | +- **WHEN** `create_task` が `date=None` で呼ばれる |
| 60 | +- **THEN** 新規ファイルの frontmatter に `date:` キーは含まれない |
| 61 | +- **AND** 戻り値の `Task.date` は `null` である |
| 62 | + |
| 63 | +### Requirement: `update_task` コマンドは期日を Keep / Set / Clear の 3 状態で更新する |
| 64 | + |
| 65 | +`update_task` Tauri コマンドは、オプションパラメータ `date: Option<String>` を受け付けなければならない (MUST)。値は `tags` と同一のセマンティクスで解釈される: |
| 66 | + |
| 67 | +- `None`(未指定): 既存の `date` を維持する (Keep)。 |
| 68 | +- `Some("")`(空文字): frontmatter の `date` キーを物理削除する (Clear)。 |
| 69 | +- `Some(canonical)`(正準形 `YYYY-MM-DD`): frontmatter の `date` を当該値に設定する (Set)。 |
| 70 | + |
| 71 | +frontmatter の他フィールド(status / order / tags / body)および body は、`date` の更新によって変化してはならない (MUST NOT)。 |
| 72 | + |
| 73 | +#### Scenario: 期日を新規設定する |
| 74 | + |
| 75 | +- **GIVEN** `date` キーを持たないタスク |
| 76 | +- **WHEN** `update_task` が `date=Some("2026-07-01")` で呼ばれる |
| 77 | +- **THEN** frontmatter に `date: 2026-07-01` が追加される |
| 78 | +- **AND** 戻り値の `Task.date` は `"2026-07-01"` |
| 79 | + |
| 80 | +#### Scenario: 期日を別の日付に変更する |
| 81 | + |
| 82 | +- **GIVEN** `date: 2026-06-15` を持つタスク |
| 83 | +- **WHEN** `update_task` が `date=Some("2026-06-20")` で呼ばれる |
| 84 | +- **THEN** frontmatter の `date` が `2026-06-20` に更新される |
| 85 | + |
| 86 | +#### Scenario: 期日をクリアする |
| 87 | + |
| 88 | +- **GIVEN** `date: 2026-06-15` を持つタスク |
| 89 | +- **WHEN** `update_task` が `date=Some("")` で呼ばれる |
| 90 | +- **THEN** frontmatter から `date` キーが削除される |
| 91 | +- **AND** 戻り値の `Task.date` は `null` |
| 92 | +- **AND** status / tags / order / body は変化しない |
| 93 | + |
| 94 | +#### Scenario: 期日を維持する(未指定) |
| 95 | + |
| 96 | +- **GIVEN** `date: 2026-06-15` を持つタスク |
| 97 | +- **WHEN** `update_task` が `date=None`(他フィールドのみ変更)で呼ばれる |
| 98 | +- **THEN** frontmatter の `date` は `2026-06-15` のまま維持される |
| 99 | + |
| 100 | +### Requirement: ダイアログは期日入力欄とカレンダーポップオーバーを提供する |
| 101 | + |
| 102 | +タスク作成ダイアログおよびタスク詳細ダイアログは、サイドバーに「Date」フィールドを持たなければならない (MUST)。当該フィールドはテキスト入力欄を持ち、フォーカス時にカレンダーをポップオーバーとして表示する (SHALL)。ユーザーはカレンダーからの日付選択、`YYYY-MM-DD` の直接入力、設定済み期日のクリアのいずれも行える (SHALL)。 |
| 103 | + |
| 104 | +#### Scenario: 入力欄フォーカスでカレンダーが開く |
| 105 | + |
| 106 | +- **WHEN** ユーザーが「Date」フィールドの入力欄にフォーカスする |
| 107 | +- **THEN** カレンダーがポップオーバーとして表示される |
| 108 | +- **AND** ポップオーバーはモーダルダイアログの背景より前面に表示される |
| 109 | + |
| 110 | +#### Scenario: カレンダーから日付を選択する |
| 111 | + |
| 112 | +- **WHEN** ユーザーがカレンダー上の日をクリックする |
| 113 | +- **THEN** 入力欄に選択日が `YYYY-MM-DD` 形式で反映される |
| 114 | +- **AND** ポップオーバーが閉じる |
| 115 | + |
| 116 | +#### Scenario: 期日を直接入力する |
| 117 | + |
| 118 | +- **WHEN** ユーザーが入力欄に `2026-06-20` と直接入力して確定する |
| 119 | +- **THEN** 当該日付が期日として受理される |
| 120 | +- **AND** カレンダーの選択状態も同じ日付を示す |
| 121 | + |
| 122 | +#### Scenario: 不正な入力は受理されない |
| 123 | + |
| 124 | +- **WHEN** ユーザーが入力欄に `2026-13-40` や `abc` のような不正値を入力して確定する |
| 125 | +- **THEN** 当該値は期日として受理されない |
| 126 | +- **AND** フィールドは直前の有効値(または未設定)に戻る |
| 127 | + |
| 128 | +#### Scenario: 期日をクリアする |
| 129 | + |
| 130 | +- **GIVEN** 期日が設定済みのフィールド |
| 131 | +- **WHEN** ユーザーがクリア操作(× ボタン等)を行う |
| 132 | +- **THEN** 期日が未設定になる |
| 133 | +- **AND** 詳細ダイアログでは `update_task` が `date=""`(Clear)で auto-save される |
| 134 | + |
| 135 | +#### Scenario: 詳細ダイアログでの期日変更が auto-save される |
| 136 | + |
| 137 | +- **GIVEN** タスク詳細ダイアログが開いている |
| 138 | +- **WHEN** ユーザーが期日を変更する |
| 139 | +- **THEN** `tags` / `status` と同様に変更が即座に `update_task` で保存される |
| 140 | + |
| 141 | +### Requirement: Kanban カードは期日を相対表示する |
| 142 | + |
| 143 | +Kanban ボードのカードは、期日が設定されたタスクに対して、今日からの相対距離に応じたラベルと色で期日バッジを表示しなければならない (MUST)。期日が未設定のタスクには期日バッジを表示してはならない (MUST NOT)。相対距離 `diff`(= 期日 − 今日、ローカルカレンダー日単位)に基づくカテゴリ・ラベル・色は以下に従う: |
| 144 | + |
| 145 | +| カテゴリ | 条件 | ラベル | 色 | |
| 146 | +| -------- | ---------------- | --------------------- | --------------- | |
| 147 | +| overdue | `diff < 0` | 実日付(例 `Jun 5`) | danger 赤 | |
| 148 | +| today | `diff == 0` | `Today` | 緑 | |
| 149 | +| tomorrow | `diff == 1` | `Tomorrow` | オレンジ | |
| 150 | +| soon | `2 <= diff <= 6` | 曜日名(例 `Monday`) | 紫(accent 系) | |
| 151 | +| far | `diff >= 7` | 実日付(例 `Jun 20`) | muted | |
| 152 | + |
| 153 | +曜日名表示は `diff <= 6` までに限定する。`diff == 7` 以降は今日と同じ曜日名になり曖昧なため far として実日付を表示する。 |
| 154 | + |
| 155 | +#### Scenario: 今日が期日のカード |
| 156 | + |
| 157 | +- **GIVEN** 期日が今日のタスク |
| 158 | +- **WHEN** カードが描画される |
| 159 | +- **THEN** バッジに `Today` が緑で表示される |
| 160 | + |
| 161 | +#### Scenario: 明日が期日のカード |
| 162 | + |
| 163 | +- **GIVEN** 期日が明日のタスク |
| 164 | +- **WHEN** カードが描画される |
| 165 | +- **THEN** バッジに `Tomorrow` がオレンジで表示される |
| 166 | + |
| 167 | +#### Scenario: 数日以内の期日のカード |
| 168 | + |
| 169 | +- **GIVEN** 期日が今日から 3 日後(例: 月曜)のタスク |
| 170 | +- **WHEN** カードが描画される |
| 171 | +- **THEN** バッジに曜日名(例 `Monday`)が紫系で表示される |
| 172 | + |
| 173 | +#### Scenario: 期日超過のカード |
| 174 | + |
| 175 | +- **GIVEN** 期日が過去のタスク |
| 176 | +- **WHEN** カードが描画される |
| 177 | +- **THEN** バッジに実日付が danger 赤で表示される |
| 178 | + |
| 179 | +#### Scenario: 遠い未来の期日のカード |
| 180 | + |
| 181 | +- **GIVEN** 期日が今日から 7 日以上後のタスク |
| 182 | +- **WHEN** カードが描画される |
| 183 | +- **THEN** バッジに実日付(例 `Jun 20`)が muted で表示される |
| 184 | + |
| 185 | +#### Scenario: 別の暦年の期日は年も表示する |
| 186 | + |
| 187 | +- **GIVEN** 期日が今日と異なる暦年(過去・未来いずれも)のタスク |
| 188 | +- **WHEN** カードが描画される |
| 189 | +- **THEN** バッジの実日付に年が付与される(例 今日が 2026 年で期日 2027-01-05 → `Jan 5, 2027`) |
| 190 | +- **AND** 今日と同じ暦年の実日付には年が付かない(例 `Jun 20`) |
| 191 | + |
| 192 | +#### Scenario: 期日なしのカード |
| 193 | + |
| 194 | +- **GIVEN** 期日が未設定のタスク |
| 195 | +- **WHEN** カードが描画される |
| 196 | +- **THEN** 期日バッジは表示されない |
0 commit comments