こんにちは。エンジニアのダマルです。
このブログはギークフィードアドベントカレンダー2025の14日目の記事です。
他の記事もぜひチェックしてみてください!
目次
自己紹介
クラウド開発事業部所属のダマルです。
普段はAPI-データベース連携の開発、AWSクラウドの設計を担当しています。エンジニア歴は3年で、主にAWS、Node.js、Pythonを使った開発をしています。
最近写真を撮ったり、野球(メージャー)を見たりするのが好きです。
普段使ってるAIツール
日常的に以下のAIツールを活用しています。
- ChatGPT:タスクの整理や調査に利用しています。特に、参考リンクを見つけたり、自分の理解を深めるために議論してもらうときにとても役立ちます。
- Cursor:開発時のコーディング支援やコードレビューで使用しています。既存コードの内容を理解したり、そのコードに基づいてテストコードを自動生成してくれる点が非常に便利です。
企画概要とゴール
今回、「フルAI開発バトル」という企画に参加しました。
ルールはシンプルかつ過酷です。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
# 禁止事項:エディタで直接コードを書く・修正すること - 許されるのは「AIへの指示」のみ。人間の役割は「Architect/Reviewer」、つまりAIをマネジメントして成果物を判断することです。 # お題 社員の生産性を上げる日々の業務管理ツールを作ってください。 ## 必須要件: - KiroとPlaywright MCPを使うこと - スペック駆動開発を行うこと(vibe codingはNG) - Todoを追加・編集・削除できること - 追加は画面上部のフォームから可能 - 編集・削除は各行の操作ボタンで行う - 一覧でTodoを確認できること - 一覧にはタイトル、担当者、期限を表示 - サクサク軽く操作できること - 画面は1ページで完結 - PlaywrightでCRUD周りのテストをすること |
詳しいルールや目的はアドベントカレンダー1日目の記事で紹介しております。
作業プロセス
要件の理解と整理
まず最初にやったのは、渡された要件を丁寧に読み込み、どの部分があえて曖昧にされているのかを整理することでした。
具体的には、以下の点について自分なりの前提を決めて進めました。
-
「今日やること」 の定義:
「期限が今日のタスク」だけでなく、「期限が未設定だが今日中に片付けたいタスク」も含める。 -
完了タスクの扱い:
一覧から完全に削除するのではなく、打ち消し線で残し、誤操作を防ぎつつUndo機能で戻せるようにする。 -
データの保存方法:
高速な操作レスポンスを優先し、LocalStorageを使用してブラウザ内で永続化する。 -
UI構成:
1ページ完結型で、上部に追加フォーム、下部にタスク一覧を配置するシンプルな構成を想定。
また、今回のKiroへの指示はすべて英語で行いました。
英語の方が自分の考えをより正確に表現できるし、インターネットで見つけた「AIに単に同意させず、対話的に批判してもらうためのプロンプト(いわゆる“intellectual sparring partner”スタイル)」を参考にしました。
この設定を最初に明示することで、Kiroが単に「はい、わかりました」と従うのではなく、曖昧な要件を自ら指摘し、より深い議論をしてくれると感じています。
運営への質問事項
理由としては、イベント当日に参加することができず、週末に個人で進めていたためです。
Specs定義
指示に至るまでの思考プロセス
Kiroへの指示
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
Title: Today's task Manager (1-page, AI built) Steering Rules (Sparring Partner) - You are my intellectual sparring partner. Do not simply affirm or assume I’m correct. - For every idea: analyze assumptions, provide counterpoints, test reasoning, offer alternatives, and prioritize truth over agreement. - Call out vague, conflicting, or risky requirements. Ask me targeted questions before proceeding. Goal - Build a lightweight 1-page app to help an office worker focus on “today’s tasks”. - Persona: Sato-san — dislikes complexity; prefers 1-click flows; avoids settings screens. User Outcomes - Can add/edit/delete a task in under 10s. - Can clearly see what’s due “today”. - Changes persist after closing the browser. Functional Scope - Add/Edit/Delete/List tasks with fields: title, assignee, dueDate. - Toggle complete state, visibly distinguish completed items. - Sort by title/assignee/dueDate (asc/desc). - Persist locally (initially LocalStorage). - Responsive single page. Constraints - No login, roles, or multi-user sync. - No separate “archive” screen unless justified. - Keep bundle small, avoid heavy dependencies. Assumptions to be tested - “Today” = dueDate is today OR no due date (assumption). Challenge this if confusing. - Completed items remain visible with strikethrough. Consider a simple “Hide completed” filter if needed. Critical Design Questions (debate before build) 1) “Today” definition: filter vs. default sort vs. dedicated view? 2) Sorting + completion: should completed items float bottom automatically? UX Principles - 1-page, no navigation. - Primary actions are visible and reachable on mobile. - Zero-config; sensible defaults. Deployment Strategy - Target: AWS Amplify (build: `npm run build`, output: `dist`, Node 18+). - Fallback: S3 + CloudFront static hosting if Amplify is blocked. Risk Register & Mitigations - Tailwind not applied → verify config/imports; auto-fix. - Flaky tests → enforce data-testid; wait for stable states (no arbitrary sleeps). |
Kiroの出力
- requirements.md
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
# Requirements Document ## Introduction The Today Task Manager is a lightweight, single-page web application designed to help office workers focus on their daily tasks. The application prioritizes simplicity and speed, enabling users to manage tasks in under 10 seconds per action. It targets users like Sato-san who prefer minimal complexity, one-click workflows, and avoid configuration screens. The system persists data locally in the browser and requires no authentication or multi-user synchronization. ## Glossary - **Task Manager**: The web application system that manages task data and user interactions - **Task**: A work item with a title, optional assignee, optional due date, and completion status - **Today's Tasks**: Tasks with a due date matching the current calendar date in the user's browser timezone - **LocalStorage**: Browser-based persistent storage mechanism for task data - **Completed Task**: A task marked as done by the user - **Sort Preference**: User's chosen ordering of tasks by title, assignee, or due date in ascending or descending order ## Requirements ### Requirement 1: Task Creation **User Story:** As a user, I want to add new tasks quickly with minimal input, so that I can capture work items in under 10 seconds. #### Acceptance Criteria 1. WHEN a user enters a non-empty title and submits the form, THEN the Task Manager SHALL create a new task with a unique identifier and current timestamp 2. WHEN a user attempts to create a task with an empty or whitespace-only title, THEN the Task Manager SHALL reject the creation and display an error message 3. WHEN a new task is created, THEN the Task Manager SHALL persist the task to LocalStorage immediately 4. WHEN a new task is created without a due date, THEN the Task Manager SHALL store the task with a null due date value 5. WHEN a new task is created, THEN the Task Manager SHALL clear the input form and return focus to the title field ### Requirement 2: Task Display and Prioritization **User Story:** As a user, I want to clearly see which tasks are due today, so that I can focus on urgent work without manual filtering. #### Acceptance Criteria 1. WHEN the Task Manager displays the task list, THEN the Task Manager SHALL visually highlight tasks with a due date matching the current date 2. WHEN sorting tasks, THEN the Task Manager SHALL position today's tasks at the top of the list before other tasks 3. WHEN displaying tasks, THEN the Task Manager SHALL show the title, assignee, due date, and completion status for each task 4. WHEN the task list is empty, THEN the Task Manager SHALL display a helpful empty state message 5. WHEN the page loads, THEN the Task Manager SHALL retrieve all tasks from LocalStorage and display them within 2 seconds ### Requirement 3: Task Editing **User Story:** As a user, I want to edit task details quickly, so that I can correct mistakes or update information as work evolves. #### Acceptance Criteria 1. WHEN a user activates edit mode for a task, THEN the Task Manager SHALL display an inline editing form with current values pre-filled 2. WHEN a user saves edited task data with a non-empty title, THEN the Task Manager SHALL update the task and persist changes to LocalStorage immediately 3. WHEN a user attempts to save a task with an empty or whitespace-only title, THEN the Task Manager SHALL reject the update and maintain the previous value 4. WHEN a user cancels editing, THEN the Task Manager SHALL discard changes and restore the original display 5. WHEN a task is updated, THEN the Task Manager SHALL update the task's updatedAt timestamp ### Requirement 4: Task Deletion **User Story:** As a user, I want to delete tasks I no longer need, so that my task list remains relevant and uncluttered. #### Acceptance Criteria 1. WHEN a user initiates task deletion, THEN the Task Manager SHALL remove the task from the display and LocalStorage immediately 2. WHEN a user deletes a task, THEN the Task Manager SHALL display an undo notification for 10 seconds 3. WHEN a user clicks undo within the 10-second window, THEN the Task Manager SHALL restore the deleted task to its original position and persist it to LocalStorage 4. WHEN the undo window expires without user action, THEN the Task Manager SHALL permanently remove the task data 5. WHEN a task is deleted, THEN the Task Manager SHALL maintain the current sort order for remaining tasks ### Requirement 5: Task Completion **User Story:** As a user, I want to mark tasks as complete and visually distinguish them, so that I can track my progress throughout the day. #### Acceptance Criteria 1. WHEN a user toggles a task to completed, THEN the Task Manager SHALL update the completion status and persist the change to LocalStorage immediately 2. WHEN a task is marked complete, THEN the Task Manager SHALL display the task with strikethrough text styling 3. WHEN a user toggles a completed task back to incomplete, THEN the Task Manager SHALL remove the strikethrough styling and persist the change 4. WHEN a user completes a task, THEN the Task Manager SHALL display an undo notification for 10 seconds 5. WHEN a user clicks undo within the 10-second window, THEN the Task Manager SHALL revert the completion status and persist the change to LocalStorage ### Requirement 6: Completed Task Visibility **User Story:** As a user, I want to hide completed tasks to reduce clutter, so that I can focus on remaining work without distraction. #### Acceptance Criteria 1. WHEN a user activates the hide completed toggle, THEN the Task Manager SHALL remove completed tasks from the display while maintaining them in LocalStorage 2. WHEN a user deactivates the hide completed toggle, THEN the Task Manager SHALL display all tasks including completed ones 3. WHEN the hide completed toggle is active and a task is marked complete, THEN the Task Manager SHALL remove the task from view immediately 4. WHEN the hide completed toggle state changes, THEN the Task Manager SHALL persist the preference to LocalStorage 5. WHEN the page loads, THEN the Task Manager SHALL restore the hide completed toggle state from LocalStorage ### Requirement 7: Task Sorting **User Story:** As a user, I want to sort tasks by different criteria, so that I can organize my work according to my current priorities. #### Acceptance Criteria 1. WHEN a user clicks a sortable column header, THEN the Task Manager SHALL sort tasks by that column in ascending order 2. WHEN a user clicks the same column header again, THEN the Task Manager SHALL reverse the sort order to descending 3. WHEN tasks are sorted, THEN the Task Manager SHALL maintain today's tasks at the top regardless of sort criteria 4. WHEN the sort order changes, THEN the Task Manager SHALL persist the sort preference to LocalStorage 5. WHEN the page loads, THEN the Task Manager SHALL restore the sort preference from LocalStorage and apply it to the task list ### Requirement 8: Data Persistence **User Story:** As a user, I want my tasks to persist after closing the browser, so that I don't lose my work when I end my session. #### Acceptance Criteria 1. WHEN any task data changes, THEN the Task Manager SHALL serialize the task list to JSON and store it in LocalStorage within 100 milliseconds 2. WHEN the page loads, THEN the Task Manager SHALL deserialize task data from LocalStorage and reconstruct the task list 3. WHEN LocalStorage contains invalid or corrupted data, THEN the Task Manager SHALL initialize with an empty task list and log an error 4. WHEN LocalStorage is unavailable, THEN the Task Manager SHALL display a warning message and operate in memory-only mode 5. WHEN serializing tasks, THEN the Task Manager SHALL preserve all task fields including id, title, assignee, dueDate, completed, createdAt, and updatedAt ### Requirement 9: Responsive Design **User Story:** As a user, I want to use the task manager on any device, so that I can manage tasks whether I'm at my desk or on mobile. #### Acceptance Criteria 1. WHEN the Task Manager is displayed on a mobile device, THEN the Task Manager SHALL render all interactive elements with touch-friendly sizing of at least 44x44 pixels 2. WHEN the viewport width is below 768 pixels, THEN the Task Manager SHALL adapt the layout to a single-column mobile view 3. WHEN the viewport width is 768 pixels or above, THEN the Task Manager SHALL display the task list in a multi-column table layout 4. WHEN the Task Manager is displayed on any screen size, THEN the Task Manager SHALL ensure all primary actions are visible without horizontal scrolling 5. WHEN the Task Manager is displayed, THEN the Task Manager SHALL use responsive typography that scales appropriately for the viewport size ### Requirement 10: Accessibility **User Story:** As a user who relies on keyboard navigation or assistive technology, I want to access all task management features, so that I can work efficiently regardless of my input method. #### Acceptance Criteria 1. WHEN a user navigates with the keyboard, THEN the Task Manager SHALL provide a logical focus order through all interactive elements 2. WHEN interactive elements receive focus, THEN the Task Manager SHALL display a visible focus indicator with at least 3:1 contrast ratio 3. WHEN a user activates task actions with the keyboard, THEN the Task Manager SHALL respond to Enter and Space key presses 4. WHEN form fields are displayed, THEN the Task Manager SHALL associate each input with a descriptive label using proper ARIA attributes 5. WHEN the task list updates, THEN the Task Manager SHALL announce changes to screen readers using ARIA live regions ### Requirement 11: Performance **User Story:** As a user, I want the application to load and respond quickly, so that task management doesn't slow down my workflow. #### Acceptance Criteria 1. WHEN the page initially loads, THEN the Task Manager SHALL deliver the initial JavaScript bundle under 150 kilobytes gzipped 2. WHEN a user performs any task operation, THEN the Task Manager SHALL update the UI within 100 milliseconds 3. WHEN the task list contains up to 1000 tasks, THEN the Task Manager SHALL render the list within 500 milliseconds 4. WHEN LocalStorage operations execute, THEN the Task Manager SHALL complete read and write operations within 50 milliseconds 5. WHEN the page loads, THEN the Task Manager SHALL display interactive content within 2 seconds on a standard 3G connection ### Requirement 12: Input Validation **User Story:** As a user, I want clear feedback when I enter invalid data, so that I understand what corrections are needed. #### Acceptance Criteria 1. WHEN a user submits a form with validation errors, THEN the Task Manager SHALL display error messages adjacent to the invalid fields 2. WHEN a user corrects an invalid field, THEN the Task Manager SHALL remove the error message immediately 3. WHEN a date field receives invalid input, THEN the Task Manager SHALL reject the input and display a format example 4. WHEN a user enters a title exceeding 200 characters, THEN the Task Manager SHALL truncate the input and display a character count warning 5. WHEN validation errors are present, THEN the Task Manager SHALL prevent form submission and maintain focus on the first invalid field ### Requirement 13: Localization **User Story:** As a Japanese-speaking user, I want all interface text displayed in Japanese, so that I can use the application in my native language. #### Acceptance Criteria 1. WHEN the Task Manager displays any UI element, THEN the Task Manager SHALL render all labels, buttons, and headings in Japanese text 2. WHEN the Task Manager displays error messages, THEN the Task Manager SHALL present validation feedback in Japanese 3. WHEN the Task Manager displays the empty state, THEN the Task Manager SHALL show the placeholder message in Japanese 4. WHEN the Task Manager displays notifications, THEN the Task Manager SHALL render undo prompts and confirmations in Japanese 5. WHEN the Task Manager displays date formats, THEN the Task Manager SHALL use Japanese date formatting conventions |
- design.md
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 |
# Design Document ## Overview The Today Task Manager is a client-side single-page application built with React, TypeScript, and Tailwind CSS. The architecture prioritizes simplicity, performance, and maintainability while delivering a responsive, accessible task management experience. The application uses browser LocalStorage for persistence, eliminating the need for backend infrastructure in the initial version. The design follows a component-based architecture with clear separation between UI components, business logic, and data persistence. State management uses React hooks (useState, useEffect, useReducer) to avoid heavy dependencies while maintaining predictable data flow. ## Architecture ### Technology Stack - **Framework**: React 18 with TypeScript for type safety and component composition - **Styling**: Tailwind CSS for utility-first responsive design with minimal bundle size - **Build Tool**: Vite for fast development and optimized production builds - **Testing**: Vitest for unit tests, Playwright for end-to-end testing - **Property Testing**: fast-check for property-based testing of core logic - **Date Handling**: Native JavaScript Date API (no external library needed for simple date comparisons) - **State Management**: React hooks (no Redux/Zustand needed for this scope) ### Application Structure ``` src/ ├── components/ # React UI components │ ├── TaskList.tsx # Main task list container │ ├── TaskItem.tsx # Individual task row │ ├── TaskForm.tsx # Add/edit task form │ ├── Toast.tsx # Undo notification component │ └── EmptyState.tsx # Empty list placeholder ├── hooks/ # Custom React hooks │ ├── useTasks.ts # Task CRUD operations and state │ ├── useLocalStorage.ts # LocalStorage persistence │ └── useUndo.ts # Undo functionality ├── lib/ # Business logic and utilities │ ├── task.ts # Task type definitions and validation │ ├── storage.ts # LocalStorage serialization │ ├── sorting.ts # Sort logic with today prioritization │ └── i18n.ts # Japanese text constants ├── App.tsx # Root component └── main.tsx # Application entry point ``` ### Data Flow 1. **Initialization**: App loads → `useLocalStorage` reads from LocalStorage → `useTasks` initializes state 2. **User Action**: User interacts with UI → Event handler in component → Hook updates state → `useEffect` persists to LocalStorage 3. **Rendering**: State changes → React re-renders affected components → UI updates within 100ms ## Components and Interfaces ### Core Types ```typescript interface Task { id: string; // UUID v4 title: string; // 1-200 characters, non-empty assignee?: string; // Optional, 0-100 characters dueDate?: string; // ISO 8601 date string (YYYY-MM-DD) or null completed: boolean; // Completion status createdAt: string; // ISO 8601 timestamp updatedAt: string; // ISO 8601 timestamp } interface SortConfig { field: 'title' | 'assignee' | 'dueDate'; direction: 'asc' | 'desc'; } interface AppState { tasks: Task[]; sortConfig: SortConfig; hideCompleted: boolean; undoAction: UndoAction | null; } interface UndoAction { type: 'delete' | 'complete'; task: Task; expiresAt: number; // Timestamp for 10-second window } ``` ### Component Interfaces **TaskList Component** - Props: `tasks: Task[]`, `onEdit`, `onDelete`, `onToggleComplete`, `onSort`, `sortConfig`, `hideCompleted` - Responsibilities: Render task table, handle sort clicks, display empty state - Accessibility: Semantic table markup, sortable column headers with ARIA sort attributes **TaskItem Component** - Props: `task: Task`, `onEdit`, `onDelete`, `onToggleComplete`, `isToday: boolean` - Responsibilities: Render single task row, inline editing, visual highlighting for today's tasks - Accessibility: Keyboard navigation, focus management, ARIA labels for actions **TaskForm Component** - Props: `onSubmit`, `initialValues?` - Responsibilities: Input validation, form submission, error display - Accessibility: Associated labels, error announcements, focus management **Toast Component** - Props: `message: string`, `onUndo`, `onDismiss`, `duration: number` - Responsibilities: Display undo notification, countdown timer, auto-dismiss - Accessibility: ARIA live region for screen reader announcements ### Custom Hooks **useTasks Hook** ```typescript function useTasks() { const [tasks, setTasks] = useState<Task[]>([]); const [sortConfig, setSortConfig] = useState<SortConfig>({ field: 'dueDate', direction: 'asc' }); const [hideCompleted, setHideCompleted] = useState(false); // CRUD operations const addTask = (taskData: Omit<Task, 'id' | 'createdAt' | 'updatedAt' | 'completed'>) => Task; const updateTask = (id: string, updates: Partial<Task>) => void; const deleteTask = (id: string) => void; const toggleComplete = (id: string) => void; // Filtering and sorting const visibleTasks = useMemo(() => filterAndSort(tasks, sortConfig, hideCompleted), [tasks, sortConfig, hideCompleted]); return { tasks: visibleTasks, addTask, updateTask, deleteTask, toggleComplete, sortConfig, setSortConfig, hideCompleted, setHideCompleted }; } ``` **useLocalStorage Hook** ```typescript function useLocalStorage<T>(key: string, initialValue: T): [T, (value: T) => void] { // Reads from LocalStorage on mount // Writes to LocalStorage on state changes // Handles serialization/deserialization // Handles errors gracefully } ``` **useUndo Hook** ```typescript function useUndo(duration: number = 10000) { const [undoAction, setUndoAction] = useState<UndoAction | null>(null); const registerUndo = (action: UndoAction) => void; const executeUndo = () => void; const clearUndo = () => void; // Auto-clear after duration useEffect(() => { if (undoAction && Date.now() > undoAction.expiresAt) { clearUndo(); } }, [undoAction]); return { undoAction, registerUndo, executeUndo, clearUndo }; } ``` ## Data Models ### Task Model The Task model represents a single work item with validation rules: - **id**: Generated using `crypto.randomUUID()` for uniqueness - **title**: Required, trimmed, 1-200 characters - **assignee**: Optional, trimmed, 0-100 characters - **dueDate**: Optional ISO 8601 date string (YYYY-MM-DD format), validated against date format - **completed**: Boolean, defaults to false - **createdAt**: ISO 8601 timestamp, set on creation - **updatedAt**: ISO 8601 timestamp, updated on any modification ### Validation Functions ```typescript function validateTitle(title: string): boolean { const trimmed = title.trim(); return trimmed.length > 0 && trimmed.length <= 200; } function validateDueDate(date: string | undefined): boolean { if (!date) return true; // Optional field const parsed = new Date(date); return !isNaN(parsed.getTime()) && /^\d{4}-\d{2}-\d{2}$/.test(date); } function isToday(date: string | undefined): boolean { if (!date) return false; const taskDate = new Date(date); const today = new Date(); return taskDate.toDateString() === today.toDateString(); } ``` ### Storage Schema LocalStorage stores two keys: - `today-tasks`: JSON array of Task objects - `today-tasks-preferences`: JSON object with `{ sortConfig, hideCompleted }` Serialization handles: - Date string preservation (no conversion to Date objects during storage) - Graceful handling of corrupted data (fallback to empty array) - Atomic writes (serialize entire array on each change) ## Correctness Properties *A property is a characteristic or behavior that should hold true across all valid executions of a system—essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.* ### Property 1: Task creation generates unique identifiers *For any* set of task creation operations with valid titles, each created task should have a unique ID that differs from all other tasks. **Validates: Requirements 1.1** ### Property 2: Whitespace-only titles are rejected *For any* string composed entirely of whitespace characters (spaces, tabs, newlines), attempting to create or update a task with that title should be rejected and leave the task list unchanged. **Validates: Requirements 1.2, 3.3** ### Property 3: Task creation persists to storage *For any* valid task creation, the task should immediately appear in LocalStorage with all fields intact. **Validates: Requirements 1.3** ### Property 4: Form clears after task creation *For any* successful task creation, the input form should be cleared and focus should return to the title field. **Validates: Requirements 1.5** ### Property 5: Today's tasks are visually highlighted *For any* task list containing tasks with various due dates, tasks with a due date matching the current date should be visually distinguished from other tasks. **Validates: Requirements 2.1** ### Property 6: Today's tasks appear first regardless of sort *For any* sort configuration (field and direction) and task list, tasks with today's due date should appear at the top of the sorted list before all other tasks. **Validates: Requirements 2.2, 7.3** ### Property 7: Task rendering includes all fields *For any* task, the rendered output should contain the title, assignee (if present), due date (if present), and completion status. **Validates: Requirements 2.3** ### Property 8: Edit mode displays current values *For any* task, activating edit mode should display a form pre-filled with the task's current field values. **Validates: Requirements 3.1** ### Property 9: Task updates persist to storage *For any* valid task update, the changes should be immediately reflected in LocalStorage and the updatedAt timestamp should be newer than the previous value. **Validates: Requirements 3.2, 3.5** ### Property 10: Edit cancellation restores original values *For any* task being edited, canceling the edit should restore the original field values without persisting any changes. **Validates: Requirements 3.4** ### Property 11: Task deletion removes from storage *For any* task, deleting it should immediately remove it from both the UI and LocalStorage. **Validates: Requirements 4.1** ### Property 12: Deletion triggers undo notification *For any* task deletion, an undo notification should appear and remain visible for 10 seconds. **Validates: Requirements 4.2** ### Property 13: Undo restores deleted task *For any* deleted task, clicking undo within the 10-second window should restore the task to its original state in both UI and LocalStorage. **Validates: Requirements 4.3** ### Property 14: Deletion preserves sort order *For any* sorted task list, deleting a task should maintain the relative order of all remaining tasks. **Validates: Requirements 4.5** ### Property 15: Completion toggle persists to storage *For any* task, toggling its completion status should immediately update both the UI (with strikethrough styling) and LocalStorage. **Validates: Requirements 5.1, 5.2** ### Property 16: Completion undo restores original state *For any* task marked complete, clicking undo within the 10-second window should restore the task to incomplete status and remove strikethrough styling. **Validates: Requirements 5.3, 5.5** ### Property 17: Hide completed filter affects display only *For any* task list, toggling the hide completed filter should remove completed tasks from the display while maintaining them in LocalStorage unchanged. **Validates: Requirements 6.1, 6.2** ### Property 18: Completing task while filter active hides it *For any* task, marking it complete while the hide completed filter is active should immediately remove it from view. **Validates: Requirements 6.3** ### Property 19: Filter preference persists across sessions *For any* hide completed toggle state, the preference should be saved to LocalStorage and restored on page reload. **Validates: Requirements 6.4, 6.5** ### Property 20: Column click sorts ascending *For any* sortable column and task list, clicking the column header should sort tasks by that field in ascending order. **Validates: Requirements 7.1** ### Property 21: Second click reverses sort order *For any* sorted column, clicking the same column header again should reverse the sort direction to descending. **Validates: Requirements 7.2** ### Property 22: Sort preference persists across sessions *For any* sort configuration, the preference should be saved to LocalStorage and restored on page reload with the same sort applied. **Validates: Requirements 7.4, 7.5** ### Property 23: Serialization round-trip preserves data *For any* task list, serializing to JSON and then deserializing should produce an equivalent task list with all fields preserved. **Validates: Requirements 8.2, 8.5** ### Property 24: Corrupted storage data handled gracefully *For any* invalid or corrupted JSON data in LocalStorage, the application should initialize with an empty task list without crashing. **Validates: Requirements 8.3** ### Property 25: Responsive layout adapts to viewport *For any* viewport width, the layout should display in single-column mobile view below 768px and multi-column table view at 768px or above. **Validates: Requirements 9.2, 9.3** ### Property 26: Validation errors display adjacent to fields *For any* form submission with invalid fields, error messages should appear next to the invalid inputs. **Validates: Requirements 12.1** ### Property 27: Error messages clear when corrected *For any* field that transitions from invalid to valid, the associated error message should be removed immediately. **Validates: Requirements 12.2** ### Property 28: Invalid dates are rejected *For any* string that doesn't match the ISO 8601 date format (YYYY-MM-DD), the date field should reject the input and display a format example. **Validates: Requirements 12.3** ### Property 29: Long titles are truncated *For any* title string exceeding 200 characters, the input should be truncated to 200 characters with a warning displayed. **Validates: Requirements 12.4** ### Property 30: Invalid forms prevent submission *For any* form containing validation errors, the submit action should be blocked and focus should move to the first invalid field. **Validates: Requirements 12.5** ### Property 31: Dates formatted in Japanese conventions *For any* date value, the displayed format should follow Japanese date conventions (YYYY年MM月DD日). **Validates: Requirements 13.5** ## Error Handling ### Input Validation Errors - Empty or whitespace-only titles: Display inline error "タイトルを入力してください" (Please enter a title) - Title exceeding 200 characters: Truncate and display warning "タイトルは200文字以内です" (Title must be within 200 characters) - Invalid date format: Display error "日付形式が正しくありません (YYYY-MM-DD)" (Date format is incorrect) - Form submission with errors: Prevent submission, focus first invalid field, display all error messages ### Storage Errors - LocalStorage unavailable: Display warning banner "ブラウザストレージが利用できません。変更は保存されません。" (Browser storage is unavailable. Changes will not be saved.) Continue in memory-only mode. - Corrupted data in LocalStorage: Log error to console, initialize with empty task list, display toast "データの読み込みに失敗しました。新しいリストで開始します。" (Failed to load data. Starting with a new list.) - Storage quota exceeded: Display error "ストレージ容量が不足しています。古いタスクを削除してください。" (Storage capacity is insufficient. Please delete old tasks.) ### Runtime Errors - Failed to generate UUID: Fallback to timestamp-based ID with random suffix - Date parsing errors: Treat as invalid input, display format error - Unexpected component errors: React error boundary catches and displays "エラーが発生しました。ページを再読み込みしてください。" (An error occurred. Please reload the page.) ## Testing Strategy ### Unit Testing with Vitest Unit tests verify specific examples, edge cases, and component behavior: **Task Model Tests** - Validate title requirements (empty, whitespace, max length) - Validate date format (valid ISO 8601, invalid formats, null) - Test task creation with all field combinations - Test task update with partial field updates **Storage Tests** - Serialize and deserialize task arrays - Handle corrupted JSON data - Handle missing LocalStorage - Verify atomic writes **Sorting Tests** - Sort by each field (title, assignee, dueDate) in both directions - Verify today's tasks always appear first - Handle null/undefined values in sort fields - Maintain stable sort for equal values **Component Tests** - TaskForm validation and submission - TaskItem rendering and interactions - Toast notification display and auto-dismiss - EmptyState display when list is empty ### Property-Based Testing with fast-check Property-based tests verify universal properties across randomly generated inputs. Each test should run a minimum of 100 iterations. **Configuration** ```typescript import fc from 'fast-check'; // Run each property test with 100 iterations const testConfig = { numRuns: 100 }; ``` **Test Tagging Convention** Each property-based test must include a comment linking it to the design document: ```typescript // Feature: today-task-manager, Property 1: Task creation generates unique identifiers test('unique IDs for all created tasks', () => { fc.assert(fc.property(fc.array(fc.string()), (titles) => { // Test implementation }), testConfig); }); ``` **Generators** - `taskTitleArb`: Generates valid task titles (1-200 characters, non-whitespace) - `whitespaceArb`: Generates whitespace-only strings (spaces, tabs, newlines) - `dateStringArb`: Generates valid ISO 8601 date strings - `taskArb`: Generates complete Task objects with all fields - `sortConfigArb`: Generates valid sort configurations **Key Properties to Test** 1. Unique ID generation (Property 1) 2. Whitespace rejection (Property 2) 3. Persistence round-trip (Property 3, 23) 4. Today's tasks prioritization (Property 6) 5. Sort order preservation after deletion (Property 14) 6. Completion toggle idempotence (Property 15) 7. Filter doesn't affect storage (Property 17) 8. Serialization preserves all fields (Property 23) 9. Corrupted data handling (Property 24) ### End-to-End Testing with Playwright E2E tests verify complete user workflows and accessibility: **Test Selectors** All interactive elements must have `data-testid` attributes: - `data-testid="task-title-input"` - `data-testid="task-assignee-input"` - `data-testid="task-duedate-input"` - `data-testid="add-task-button"` - `data-testid="task-item-{id}"` - `data-testid="edit-task-{id}"` - `data-testid="delete-task-{id}"` - `data-testid="toggle-complete-{id}"` - `data-testid="sort-header-{field}"` - `data-testid="hide-completed-toggle"` - `data-testid="undo-button"` **Test Scenarios** 1. CRUD operations: Create, read, update, delete tasks 2. Completion toggle: Mark complete, verify strikethrough, undo 3. Sorting: Click headers, verify order, verify today's tasks stay on top 4. Filtering: Toggle hide completed, verify display changes 5. Persistence: Add tasks, reload page, verify tasks restored 6. Validation: Submit empty title, verify error message 7. Empty state: Start with no tasks, verify placeholder message 8. Undo: Delete task, click undo within 10s, verify restoration 9. Keyboard navigation: Tab through elements, activate with Enter/Space 10. Responsive design: Test at mobile (375px) and desktop (1024px) widths **Accessibility Tests** - Focus order follows logical reading order - All interactive elements have visible focus indicators - Form inputs have associated labels - ARIA live regions announce task list changes - Keyboard shortcuts work for all actions ### Test Coverage Goals - Unit tests: 80% code coverage minimum - Property tests: All 31 correctness properties implemented - E2E tests: All acceptance criteria from requirements document - Accessibility: WCAG 2.1 Level AA compliance ## Deployment ### Build Configuration **Vite Configuration** ```typescript // vite.config.ts export default defineConfig({ build: { outDir: 'dist', sourcemap: true, rollupOptions: { output: { manualChunks: { vendor: ['react', 'react-dom'] } } } }, optimizeDeps: { include: ['react', 'react-dom'] } }); ``` **Build Command**: `npm run build` **Output Directory**: `dist` **Node Version**: 18+ ### AWS Amplify Gen2 Deployment **amplify.yml** ```yaml version: 1 frontend: phases: preBuild: commands: - npm ci build: commands: - npm run build artifacts: baseDirectory: dist files: - '**/*' cache: paths: - node_modules/**/* ``` **Environment Variables**: None required (client-side only app) **Custom Headers** (for security): ```yaml customHeaders: - pattern: '**/*' headers: - key: 'X-Content-Type-Options' value: 'nosniff' - key: 'X-Frame-Options' value: 'DENY' - key: 'X-XSS-Protection' value: '1; mode=block' ``` ### Fallback: S3 + CloudFront If Amplify is unavailable: 1. **S3 Bucket Configuration** - Enable static website hosting - Set index document: `index.html` - Set error document: `index.html` (for SPA routing) - Upload `dist` folder contents 2. **CloudFront Distribution** - Origin: S3 bucket website endpoint - Default root object: `index.html` - Custom error response: 404 → 200 → `/index.html` - Compress objects automatically: Yes - Price class: Use only North America and Europe (or as needed) 3. **Deployment Script** ```bash # Build npm run build # Sync to S3 aws s3 sync dist/ s3://your-bucket-name --delete # Invalidate CloudFront cache aws cloudfront create-invalidation --distribution-id YOUR_DIST_ID --paths "/*" ``` ## Performance Optimization ### Bundle Size Optimization - Tree-shaking: Vite automatically removes unused code - Code splitting: Vendor chunk separated from app code - Minification: Terser minifies production builds - Compression: Enable gzip/brotli on CDN ### Runtime Optimization - React.memo: Memoize TaskItem components to prevent unnecessary re-renders - useMemo: Memoize filtered/sorted task lists - useCallback: Memoize event handlers passed to child components - Debounce: Debounce LocalStorage writes if performance issues arise (currently atomic writes are acceptable) ### Loading Optimization - Lazy loading: Not needed for single-page app with small bundle - Preload critical resources: Font files, CSS - Service worker: Consider for offline support in future version ## Future Enhancements ### Backend Migration Criteria Consider adding a backend when: - Users request multi-device sync - Task count exceeds LocalStorage limits (typically 5-10MB) - Users request collaboration features - Users request task history/audit log ### Potential Features - Task categories/tags - Recurring tasks - Task priority levels - Subtasks/checklists - File attachments - Search and advanced filtering - Dark mode - Keyboard shortcuts - Export to CSV/JSON - Task templates |
- tasks.md
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
/** * Core task model and validation functions */ export interface Task { id: string; // UUID v4 title: string; // 1-200 characters, non-empty assignee?: string; // Optional, 0-100 characters dueDate?: string; // ISO 8601 date string (YYYY-MM-DD) or undefined completed: boolean; // Completion status createdAt: string; // ISO 8601 timestamp updatedAt: string; // ISO 8601 timestamp } /** * Validates a task title * @param title - The title to validate * @returns true if the title is valid (non-empty after trimming, <= 200 chars) */ export function validateTitle(title: string): boolean { const trimmed = title.trim(); return trimmed.length > 0 && trimmed.length <= 200; } /** * Validates a due date string * @param date - The date string to validate (optional) * @returns true if the date is valid ISO 8601 format (YYYY-MM-DD) or undefined */ export function validateDueDate(date: string | undefined): boolean { if (!date) return true; // Optional field // Check format first if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) { return false; } // Parse the date const parsed = new Date(date); // Check if it's a valid date if (isNaN(parsed.getTime())) { return false; } // Check that the parsed date matches the input (to catch invalid dates like 2024-02-30) const [year, month, day] = date.split('-').map(Number); return ( parsed.getFullYear() === year && parsed.getMonth() === month - 1 && // Month is 0-indexed parsed.getDate() === day ); } /** * Checks if a date string represents today's date * @param date - The date string to check (optional) * @returns true if the date matches today's date */ export function isToday(date: string | undefined): boolean { if (!date) return false; // Parse the date string (YYYY-MM-DD format) const [year, month, day] = date.split('-').map(Number); const taskDate = new Date(year, month - 1, day); const today = new Date(); const todayDate = new Date(today.getFullYear(), today.getMonth(), today.getDate()); return taskDate.getTime() === todayDate.getTime(); } /** * Creates a new task with generated ID and timestamps * @param taskData - The task data (without id, createdAt, updatedAt, completed) * @returns A new Task object with all fields populated * @throws Error if validation fails */ export function createTask( taskData: Omit<Task, 'id' | 'createdAt' | 'updatedAt' | 'completed'> ): Task { // Validate title if (!validateTitle(taskData.title)) { throw new Error('Invalid title: must be non-empty and <= 200 characters'); } // Validate due date if provided if (!validateDueDate(taskData.dueDate)) { throw new Error('Invalid due date: must be in YYYY-MM-DD format'); } // Validate assignee length if provided if (taskData.assignee && taskData.assignee.trim().length > 100) { throw new Error('Invalid assignee: must be <= 100 characters'); } const now = new Date().toISOString(); const trimmedAssignee = taskData.assignee?.trim(); return { id: crypto.randomUUID(), title: taskData.title.trim(), assignee: trimmedAssignee === '' ? undefined : trimmedAssignee, dueDate: taskData.dueDate, completed: false, createdAt: now, updatedAt: now, }; } |
出力の判定と修正
判定結果
最初のspecの定義時に、要件定義について少し調整する必要はありましたが、問題なし。
良かった点
- 今日やること」定義やUndo仕様など、曖昧な部分を自動的に質問、整理してくれました。
- テストケース、テストコードの実装、修正、Playwrightでの実施まで無事にやってくれました。
問題点
- 一部の文体が冗長で、要件書として不要な説明が多かったと感じています。
- コードの内容は把握していない、エラーが発生したら自分で理解するまでには手間がかかります。
Kiroとの対話
Kiroとのやり取りでは、曖昧な前提を1つずつ確認しながら仕様を整理しました。
特に「Today」ビューや完了タスクの扱いなど、細かい設計判断で良い議論ができました。
-
「Today」ビュー:
単一リストにして、今日のタスクを上部で強調表示(切替なし)。 -
Assignee:
単なるラベル扱い(マルチユーザー機能なし)。 -
ソート設定:
LocalStorageに保存して永続化。 - 完了タスクとUndo:
自動非表示はやめ、手動の非表示トグル + 10秒トーストUndoに統一。
これらを最終決定として、requirements.md、 design.md、tasks.md生成を依頼しました。
テスト実装
Fast-checkでのプロパティテスト(26件)と、PlaywrightでのE2Eテスト(約25件)を組み合わせ、UIとロジックの両面から安定性を確認しました。
主な流れは以下の通りです:
-
実装構成:React + TypeScript + Tailwind + Playwright + Vitest
-
ドメインロジック:タスク生成、検証、Undo、LocalStorage永続化
-
UI機能:日本語対応フォーム、今日のタスク強調、Hide Completedトグル、レスポンシブ対応
-
テスト範囲:
-
プロパティテスト:一意ID生成、日付検証、Undo復元、フィルタ動作など
-
E2Eテスト:CRUD操作、ソート、Undo、バリデーション、アクセシビリティ、レスポンシブ
-
-
最終結果:全テスト成功。1000件規模のタスクでもパフォーマンス良好。
成果物

412dac14fdc23902bc116abd68314cac
所要時間
約3時間
主な機能
-
タスクの追加・編集・削除・完了切替
-
Hide Completedトグル機能(非表示)
-
今日のタスクを自動的に上位表示
- Undo(10秒トースト通知付き)
工夫点など
- 一部のAI出力が冗長で、仕様として不要な説明が多く、取捨選択に時間がかかりました。
- コードの動作を完全に理解するために、テストやデバッグを繰り返す必要がありました。
発見と学び
- AIを任せて、この程度のクオリティのアプリがそのままデプロイできるのは勉強になりました。
- ただ、AIの出力をそのまま使うのではなく、自分の考えの重要性を感じました。
感想
良かった点
- 要件定義からテストまでの流れをKiroと一緒に体験ができました。
- AIとの対話を通じて、自分の考えを言語化する練習になりました。
苦労した点
- 出力内容の意図を正確に読み取るのに時間がかかりました。
今後に活かせること
-
AIを設計の早い段階から使うことで、ドキュメント作成やテスト設計を効率化できると感じました。
-
チーム開発では、AIをレビューやテスト支援に使うことで、品質とスピードを両立できそうです。
-
また、コードの理解を深めたり、その内容を他のメンバーにわかりやすく伝えるのにも役立つと感じました。
この記事が、少しでもみなさんのにお役に立てば幸いです。
ここまでお読みいただき、ありがとうございました!
- 【Kiro・Playwright】社内でフルAI開発バトル!!「1行も書かずに」Todoアプリを完成させた話〜Damarの場合〜 - 2025-12-14
- My Journey as a Japan AWS Jr. Champion - 2025-09-29
- Synology NASとAmazon CLIの連携を試してみました! - 2024-12-21
- NLCSを活用したNatWestのAI最適化術ーAmazon Connect事例「re:Invent 2024」 - 2024-12-13
- AWS Builder Cards:楽しみながらAWSを学ぶカードゲーム - 2024-09-17
【採用情報】一緒に働く仲間を募集しています



