Compare commits

...
Author SHA1 Message Date
Tirsvad da4a16c572 Resolve pending commit link of RC-080 2026-10-15 10:17:53 +08:00
Tirsvad 6e3fcf8aa3 MIL-013: Windows Sandbox run of the executable passed
The Windows executable passed the smoke test in Windows Sandbox: 5 of 5
runs (window, list override, known button, progress file). Review record
RC-080 (Go) closes criterion 7 of MIL-013 and the open condition of RC-072
on the smoke test.

Task: MIL-013#8
2026-10-15 10:17:52 +08:00
Tirsvad a4e55541c1 Merge pull request 'MIL-013: Debian container and Windows Sandbox checks' (#107) from mil-013-container-checks into main
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Successful in 6s
2026-10-15 04:10:24 +02:00
Tirsvad 1785dc9635 Resolve pending commit links of the MIL-013 results 2026-10-15 10:10:11 +08:00
Tirsvad 2f192b6936 MIL-013: results of the container and sandbox checks
Review record RC-079 (Go-with-conditions): the Debian checks and the Linux
smoke tests pass; the Windows Sandbox run is pending because it opens a
window on the host.

Task: MIL-013#8
2026-10-15 10:10:10 +08:00
Tirsvad f8ccfca02e MIL-013: Debian container and Windows Sandbox checks
A Debian image (python:3.13-slim-bookworm with Xvfb and GNOME's window
manager) runs the linters, the whole test suite, the screenshots and the
smoke test of a PyInstaller Linux binary and of the source program, so no
window opens on the development machine. The screenshot tool works on
Linux, a smoke driver presses the known button with the virtual mouse, and
Windows Sandbox scripts are written (not run, they open a window on the
host). README and the wiki Install pages describe it. Review records
RC-077 (Python) and RC-078 (shell).

Task: MIL-013#2
Task: MIL-013#3
Task: MIL-013#4
Task: MIL-013#5
Task: MIL-013#6
Task: MIL-013#7
Task: MIL-013#9
Task: MIL-013#10
2026-10-15 10:09:48 +08:00
Tirsvad a72ddb9175 Merge pull request 'MIL-013 plan and documents: container and sandbox checks' (#96) from plan-mil-013-container into main
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Successful in 6s
2026-10-15 03:55:36 +02:00
Tirsvad bc4395df43 Resolve pending commit links of the MIL-013 plan 2026-10-15 09:55:23 +08:00
Tirsvad f86bc9136e MIL-013 plan and documents: container and sandbox checks
Milestone MIL-013 (Debian container with GNOME, Windows Sandbox for the
executable), ADR-0005, BC-001 and PP-001 updated. Review records RC-073 to
RC-076, all Go (autonomous mode, not independent).

Task: MIL-013#1
2026-10-15 09:55:21 +08:00
Tirsvad 99858fb13b Merge pull request 'MIL-012 results: release v0.2.0' (#95) from mil-012-results into main
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Successful in 6s
2026-10-15 03:49:23 +02:00
Tirsvad c1a92ce34f Resolve pending commit link of RC-072 2026-10-15 09:48:58 +08:00
Tirsvad 5345fd77d4 MIL-012: release v0.2.0 results
The tag v0.2.0 and the release page exist (lightweight tag, no executable
attached: the host refuses the upload). Review record RC-072
(Go-with-conditions): the executable smoke test is incomplete and the tag
is not annotated.

Task: MIL-012#5
Task: MIL-012#6
Task: MIL-012#7
2026-10-15 09:48:57 +08:00
Tirsvad d7ca24dc69 Merge pull request 'MIL-012: version 0.2.0, CHANGELOG and links' (#94) from mil-012-version-0-2-0 into main
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Successful in 6s
2026-10-15 03:39:35 +02:00
Tirsvad 2d94678899 Resolve pending commit link of RC-071 2026-10-15 09:39:25 +08:00
Tirsvad 7c1f1b6423 MIL-012: version 0.2.0, CHANGELOG and links
Version 0.2.0 in pyproject.toml, flash_card.__version__ and the Doxyfile
with a test that keeps the three equal; CHANGELOG entry for 0.2.0; README
and the wiki Install pages link the release pages. The upload limit probe
refused a 1 MB file (413), so the executable is not attached. Review
record RC-071 (Go).

Task: MIL-012#2
Task: MIL-012#3
Task: MIL-012#4
Task: MIL-012#8
2026-10-15 09:39:16 +08:00
Tirsvad f9ca635a15 Merge pull request 'MIL-012 plan and documents: release v0.2.0' (#85) from plan-mil-012-release-0-2-0 into main
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Successful in 8s
2026-10-15 03:36:10 +02:00
Tirsvad 08c11b2108 Resolve pending commit links of the MIL-012 plan 2026-10-15 09:35:54 +08:00
Tirsvad 0264b6084f MIL-012 plan and documents: release v0.2.0
Milestone MIL-012; BC-001, US-001 (US-001.08 names the latest release)
and PP-001 updated. Review records RC-067 to RC-070, all Go (autonomous
mode, not independent).

Task: MIL-012#1
2026-10-15 09:35:52 +08:00
Tirsvad f13f32052b Merge pull request 'MIL-011: Menu bar' (#84) from mil-011-menu-bar into main
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Successful in 6s
2026-10-15 03:07:08 +02:00
Tirsvad 6c6fd723bf Resolve pending commit links of MIL-011 2026-10-15 09:07:04 +08:00
Tirsvad ce4aacb4bc MIL-011: Menu bar
Review record RC-066 (Go, autonomous mode, not independent).

Task: MIL-011#1
Task: MIL-011#2
Task: MIL-011#3
Task: MIL-011#4
Task: MIL-011#5
Task: MIL-011#6
Task: MIL-011#7
Task: MIL-011#8
2026-10-15 09:06:47 +08:00
Tirsvad 5d626dc890 Merge pull request 'MIL-011 plan and design: menu bar' (#75) from plan-mil-011-menu-bar into main
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Successful in 5s
2026-10-15 02:53:02 +02:00
Tirsvad 9693ed6c79 Resolve pending commit links of the MIL-011 plan 2026-10-15 08:52:17 +08:00
Tirsvad 2211d0f4cb MIL-011 plan and design: menu bar
Milestone MIL-011 with stories US-001.09 to US-001.12, and the documents
updated for the menu bar: BC-001, PP-001, US-001, UC-001, SSD-001, OC-001,
SD-001, DCD-001, DICT-001 and the wireframe. Review records RC-056 to
RC-065, all Go (autonomous mode, not independent).

Task: MIL-011#1
2026-10-15 08:52:13 +08:00
Tirsvad 9ab490e520 Merge pull request 'MIL-010 results: release v0.1.0, executable not attached' (#74) from mil-010-release-results into main
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Successful in 5s
2026-10-15 02:43:22 +02:00
Tirsvad 60bcd2c9fb Resolve pending commit links of the MIL-010 results 2026-10-15 08:43:13 +08:00
Tirsvad db87a6d33b MIL-010: release v0.1.0 results, the executable is not attached
The tag v0.1.0 and the release exist and the executable was rebuilt and
smoke-tested from the tagged commit, but the server's reverse proxy rejects
the upload (413). README, CHANGELOG and the wiki Install pages now say that
the executable is built from source until the limit is raised. Review
record RC-055 (Go-with-conditions).

Task: MIL-010#2
Task: MIL-010#3
Task: MIL-010#4
Task: MIL-010#6
2026-10-15 08:43:12 +08:00
Tirsvad 2c580ccaae Merge pull request 'MIL-010 plan and documents: release v0.1.0' (#67) from plan-mil-010-release into main
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Successful in 7s
2026-10-15 02:37:55 +02:00
Tirsvad aae09befcd Resolve pending commit links of the MIL-010 plan 2026-10-15 08:37:40 +08:00
Tirsvad 9c8e294021 MIL-010 plan and documents: release v0.1.0
Milestone MIL-010, story US-001.08, BC-001 and PP-001 amended (the release
of the executable is in scope), CHANGELOG.md for 0.1.0, and links to the
release page in README and the Install page of the wiki. Review records
RC-051 to RC-054, all Go (autonomous mode, not independent).

Task: MIL-010#1
Task: MIL-010#2
2026-10-15 08:37:38 +08:00
Tirsvad 3532e82d86 Merge pull request 'MIL-009 task 9: fix a flaky unit test that created a real Tk root' (#66) from fix-flaky-unit-test into main
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Successful in 5s
2026-10-14 18:44:10 +02:00
Tirsvad fc9c5ea3c1 Fix a flaky unit test that created a real Tk root
test_main_returns_one_when_word_list_is_missing_with_level called
app.main without a fake root, so a real tk.Tk() was created in a unit
test and failed about 1 in 6 full runs. An autouse fixture now patches
app.tk.Tk with the module's fake root. Review record RC-049 (Go).

Task: MIL-009#9
2026-10-15 00:43:54 +08:00
Tirsvad f311e71bde Resolve pending commit links of the MIL-009 amendment 2026-10-15 00:43:15 +08:00
Tirsvad 061b4f48b5 MIL-009: add task 9, fix a flaky unit test (plan and review)
Task row 9 added to MIL-009 after the merge; review records RC-049
(the fix) and RC-050 (MIL-009 re-review), both Go.
2026-10-15 00:43:13 +08:00
Tirsvad 7bf6d5804b Merge pull request 'MIL-009: Executable with PyInstaller' (#64) from mil-009-executable into main
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Successful in 7s
2026-10-14 18:32:37 +02:00
Tirsvad 4ae4ece10f Resolve pending commit links of MIL-009 2026-10-15 00:32:30 +08:00
Tirsvad bc513810ec MIL-009: Executable with PyInstaller
Review record RC-048 (Go, autonomous mode, not independent).

Task: MIL-009#1
Task: MIL-009#2
Task: MIL-009#3
Task: MIL-009#4
Task: MIL-009#5
Task: MIL-009#6
Task: MIL-009#7
Task: MIL-009#8
2026-10-15 00:32:14 +08:00
Tirsvad 5934c396c2 Merge pull request 'MIL-009 plan and documents: executable with PyInstaller' (#55) from plan-mil-009-executable into main
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Successful in 7s
2026-10-14 18:17:43 +02:00
Tirsvad d37f165c19 Resolve pending commit links of the MIL-009 plan 2026-10-15 00:17:31 +08:00
Tirsvad 768ca344c9 MIL-009 plan and documents: executable with PyInstaller
Milestone MIL-009, story US-001.07, ADR-0004, and the amended BC-001,
DCD-001 and PP-001. Review records RC-042 to RC-047, all Go (autonomous
mode, not independent).

Task: MIL-009#1
2026-10-15 00:17:27 +08:00
Tirsvad d5873748cf Merge pull request 'MIL-008: Choose level' (#54) from mil-008-choose-level into main
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Successful in 6s
2026-10-14 17:58:52 +02:00
Tirsvad 6745f98c27 Resolve pending commit links of MIL-008 2026-10-14 23:58:46 +08:00
Tirsvad f45d6036e4 MIL-008: Choose level
Review record RC-041 (Go, autonomous mode, not independent).

Task: MIL-008#1
Task: MIL-008#2
Task: MIL-008#3
Task: MIL-008#4
Task: MIL-008#5
Task: MIL-008#6
Task: MIL-008#7
Task: MIL-008#8
2026-10-14 23:58:31 +08:00
Tirsvad ee9c531ea6 Merge pull request 'MIL-008 plan and design: choose level' (#45) from plan-mil-008-level into main
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Successful in 9s
2026-10-14 17:45:16 +02:00
Tirsvad f4d8267da1 Resolve pending commit links of the MIL-008 plan 2026-10-14 23:45:04 +08:00
Tirsvad 0b983b7fda MIL-008 plan and design: choose level (100, 1000 or all words)
New milestone MIL-008 with story US-001.06, and the design documents
updated for the level choice: BC-001, PP-001, US-001, UC-001, DM-001,
DICT-001, SSD-001, OC-001, SD-001, DCD-001 and the wireframe. Review
records RC-030 to RC-040, all Go (autonomous mode, not independent).

Task: MIL-008#1
2026-10-14 23:44:59 +08:00
Tirsvad 13673b2c48 Merge pull request 'MIL-007: Documentation and publication' (#44) from mil-007-documentation-and-publication into main
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Successful in 8s
2026-10-14 16:42:44 +02:00
Tirsvad ff4f2655c4 Resolve pending commit links of MIL-007 2026-10-14 22:42:37 +08:00
Tirsvad 92894268c5 MIL-007: Documentation and publication
Review record RC-029 (Go, autonomous mode, not independent).

Task: MIL-007#1
Task: MIL-007#2
Task: MIL-007#3
Task: MIL-007#4
Task: MIL-007#5
Task: MIL-007#6
Task: MIL-007#7
Task: MIL-007#8
2026-10-14 22:42:26 +08:00
Tirsvad b2cc709031 Merge pull request 'MIL-006: Spoken Malay word' (#43) from mil-006-malay-speech into main
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Successful in 9s
2026-10-14 16:39:51 +02:00
Tirsvad bc055e3c05 Resolve pending commit links of MIL-006 2026-10-14 22:39:44 +08:00
Tirsvad b3c5116110 MIL-006: Spoken Malay word
Review record RC-028 (Go, autonomous mode, not independent).

Task: MIL-006#1
Task: MIL-006#2
Task: MIL-006#3
Task: MIL-006#4
Task: MIL-006#5
2026-10-14 22:39:36 +08:00
Tirsvad 5900fda90a Merge pull request 'MIL-005: Step 4 - Save progress' (#42) from mil-005-step4-save-progress into main
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Successful in 9s
2026-10-14 16:30:13 +02:00
Tirsvad 9e56a6b787 Resolve pending commit links of MIL-005 2026-10-14 22:30:05 +08:00
Tirsvad 8dbaaa3059 MIL-005: Step 4 - Save progress
Review record RC-027 (Go, autonomous mode, not independent).

Task: MIL-005#1
Task: MIL-005#2
Task: MIL-005#3
Task: MIL-005#4
Task: MIL-005#5
2026-10-14 22:29:58 +08:00
Tirsvad da4e9382cf Merge pull request 'MIL-004: Step 3 - Flip the cards' (#41) from mil-004-step3-flip-cards into main
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Successful in 8s
2026-10-14 16:05:58 +02:00
171 changed files with 12736 additions and 1807 deletions
+15
View File
@@ -0,0 +1,15 @@
.git
.venv
.env
.env.*
.codex
**/__pycache__
**/*.pyc
.pytest_cache
.mypy_cache
.ruff_cache
.import_linter_cache
build
dist
docs/doxygen
data/words_to_learn*.csv
+9
View File
@@ -0,0 +1,9 @@
*.py text eol=lf
*.md text eol=lf
*.toml text eol=lf
*.csv text eol=lf
*.png binary
*.sh text eol=lf
*.Dockerfile text eol=lf
.dockerignore text eol=lf
*.ps1 text eol=crlf
+3
View File
@@ -75,3 +75,6 @@ dmypy.json
*.swp
.DS_Store
Thumbs.db
# PyInstaller spec files
*.spec
+64
View File
@@ -0,0 +1,64 @@
# Changelog
All notable changes of the flash card program. The format follows
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/); the version follows
[Semantic Versioning](https://semver.org/).
## [0.2.0] - 2026-10-15
Adds the classic menu bar and keeps the progress of each word list apart.
### Added
- A menu bar. File: Open... (another word list from a CSV file with a header
of two language codes), Change level... (the level choice without a restart),
Reset word list... (after a confirmation the progress of the open list is
removed and all its words are to learn again), Exit. About: Contact (the
author's name and title, and a link to the author's LinkedIn page).
- The progress of each word list is a file of its own: `words_to_learn.csv` for
`ms-da.csv` (unchanged) and `words_to_learn_<name>.csv` for another list.
### Fixed
- A word list that is not UTF-8 text gives a message that names the file,
instead of an error.
- The level screen has the same window title, padding and background as the
card screen.
### Known limits
- The executable is not signed; Windows SmartScreen may warn about it.
- The executable is not attached to the release: the upload limit of the git
host rejects a file of its size (HTTP 413, already at 1 MB). Build it with
`python tools/build_executable.py`.
- An opened word list is not remembered after a restart.
## [0.1.0] - 2026-10-15
First release. The solution of day 31 of Udemy's *100 Days of Code: The Complete
Python Pro Bootcamp*, for Malay words with Danish translations.
### Added
- The four assignment steps: the window with a card and two buttons, a random
card on every press, the flip to the translation after 3 seconds, and the
progress file `data/words_to_learn.csv`.
- A choice of level before learning: the first 100 words, the first 1000 words
or all words of the frequency ordered word list; `--level 100|1000|all`.
- The spoken Malay word through the optional extra `speech` (gTTS and
playsound); `--no-speech`.
- A single Windows executable built with PyInstaller (`python
tools/build_executable.py`); the progress is kept in a `data/` folder next to
it, and a `data/ms-da.csv` next to it replaces the word list inside it.
- README, a wiki in English, Danish and Bahasa Malaysia, and Doxygen comments.
### Known limits
- The executable is not signed; Windows SmartScreen may warn about it.
- The executable is not attached to the release: the upload limit of the server rejects a file of its size. Build it with `python tools/build_executable.py`.
- The executable is built for Windows (x64); on Linux and macOS run the program
from source or build it on that system.
- The Danish column of the word list is machine translated.
[0.1.0]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/releases/tag/v0.1.0
[0.2.0]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/releases/tag/v0.2.0
+1 -1
View File
@@ -4,7 +4,7 @@
PROJECT_NAME = "Flash Card"
PROJECT_BRIEF = "Malay to Danish flash cards (Udemy 100 Days of Code, day 31)"
PROJECT_NUMBER = 0.1.0
PROJECT_NUMBER = 0.2.0
OUTPUT_DIRECTORY = docs/doxygen
CREATE_SUBDIRS = NO
+95 -3
View File
@@ -15,18 +15,42 @@ A flash card program for learning the most frequent Malay words with their Danis
## 🧭 Overview
The program shows a Malay word on a card. After three seconds the card turns over and shows the Danish translation. You press the green tick when you know the word and the red cross when you do not. A known word is removed from the words to learn, and the words still to learn are saved, so the next start continues where you stopped.
The program first asks for a level: the first 100 words, the first 1000 words or all words of the word list, which is ordered from the most to the least frequent word. Then it shows a Malay word on a card. After three seconds the card turns over and shows the Danish translation. You press the green tick when you know the word and the red cross when you do not. A known word is removed from the words to learn, and the words still to learn are saved, so the next start continues where you stopped.
| Part | What it is for |
| --- | --- |
| `src/flash_card/` | The program, in four layers: `domain`, `application`, `infrastructure`, `presentation` |
| `tests/` | `pytest` tests: `unit`, `integration`, `e2e` |
| `data/` | The word list `ms-da.csv` and, after the first known word, your own `words_to_learn.csv` |
| `docs/` | Project documents (business case, plan, design, review records) |
| `docs/` | Project documents (business case, plan, design, review records), `docs/wiki/` and `docs/images/` |
| `tools/` | Helper scripts: `generate_images.py`, `capture_screenshots.py` and `build_executable.py` |
| `Doxyfile` | Doxygen configuration for the source code documentation |
The core program uses only the Python standard library. Spoken Malay words are an optional extra.
### Screenshots
| Choose your level | Front: the Malay word | Back: the Danish translation after 3 seconds |
| --- | --- | --- |
| ![The level screen][screenshot-level] | ![The front of a card][screenshot-front] | ![The back of a card][screenshot-back] |
### Where is each assignment step?
| Assignment step | Code |
| --- | --- |
| 1. User interface | `FlashCardView.__init__` in `src/flash_card/presentation/features/flash_card/flash_card_view.py`; images made by `tools/generate_images.py` |
| 2. New flash cards | `CsvVocabularyRepository` (the standard library `csv` instead of `pandas`), `Deck.draw`, `StudySession.next_card`, `FlashCardView.next_card` |
| 3. Flip the cards | `FlashCardView.flip_card` and `FlashCardView.flip_timer` (`after`, `after_cancel`), `FlashCardViewModel.flip_card` |
| 4. Save your progress | `FlashCardView.is_known`, `StudySession.mark_known`, `CsvProgressRepository` |
| Extra: level choice | `LevelView`, `LevelViewModel`, `Level`, `Deck.within`, `StudySession.next_card`, `open_study_session` |
| Extra: spoken word | `GttsSpeech`, `NullSpeech`, `build_speech` in `presentation/app.py` |
The wiki ([English][wiki-en], [Dansk][wiki-da], [Bahasa Malaysia][wiki-ms]) explains the same in three languages.
### Data
`data/ms-da.csv` holds 1000 frequent Malay words with a Danish machine translation; see [data/README.md][data-readme] for the format and origin.
## 📋 Requirements
| Need | Why |
@@ -34,6 +58,7 @@ The core program uses only the Python standard library. Spoken Malay words are a
| Python 3.13 or later, with Tkinter | The program and its window (Tkinter is part of the standard Python installers for Windows and macOS; on Debian or Ubuntu install `python3-tk`) |
| `git` | To clone the repository |
| Doxygen (optional) | To build the source code documentation |
| `pyinstaller` (optional, extra `build`) | To build a single executable file (see Run) |
| `gTTS` and `playsound==1.2.2` (optional, extra `speech`) | To hear the Malay word; needs a network connection |
## 🛠️ Setup
@@ -69,7 +94,40 @@ python -m pip install -e ".[dev]"
python -m flash_card
```
The program is run from the activated `.venv`. The window opens with the first card; the program is built step by step and the pull requests and milestones show each step.
The program is run from the activated `.venv`. The window opens with the level screen: choose 100 words, 1000 words or All words. Then a card appears. Press the green tick for a word you know and the red cross for a word you do not. Options:
| Option | Meaning |
| --- | --- |
| `--data-dir <folder>` | Folder with `ms-da.csv` and `words_to_learn.csv` |
| `--level {100,1000,all}` | Start at that level and skip the level screen |
| `--no-speech` | Do not speak the Malay word |
Known words stay known at every level: the level only limits which of the words you do not know yet come up. To start again, delete `data/words_to_learn.csv` or use the menu.
### Menu bar
![The window with the menu bar][screenshot-menu]
| Menu | Command | What it does |
| --- | --- | --- |
| File | Open... | Opens another word list from a CSV file (header with two language codes, for example `en;da`). Progress is kept apart for each list |
| File | Change level... | Shows the level choice again without a restart; known words stay known |
| File | Reset word list... | After a confirmation removes the progress of the open list, so all its words are to learn again; the list file is not changed |
| File | Exit | Closes the program |
| About | Contact | The author, Jens Tirsvad Nielsen, Software engineer; opens the LinkedIn page in your browser |
The progress of the delivered `ms-da.csv` is `data/words_to_learn.csv`; another list gets `data/words_to_learn_<name>.csv`. The opened list is not remembered after a restart.
### Executable (Windows, no Python needed to run it)
The release pages of [v0.2.0][release-0-2-0] and [v0.1.0][release-0-1-0] have the release notes. The executable is not attached there yet, because the server's upload limit rejects a file of this size (HTTP 413). Build it yourself:
```powershell
python -m pip install -e ".[build,speech]"
python tools/build_executable.py
```
The script builds `dist/flash-card.exe`: one file, no console window, with the images, the word list and the spoken word inside. Open it by double-clicking. It keeps your progress in a `data/` folder next to the executable (`data/words_to_learn.csv`); a `data/ms-da.csv` next to it replaces the word list inside. Add `--no-speech` to the build script to leave the speech packages out. The executable is a build output and is not committed; build it on the system you want to run it on (Windows, Linux or macOS).
## 🧪 Tests
@@ -87,6 +145,28 @@ lint-imports
The window test in `tests/e2e/` is skipped when no display is available.
Build the source code documentation (Doxygen comments) with `doxygen Doxyfile`; the HTML is written to `docs/doxygen/html/`. The screenshots are made with `python tools/capture_screenshots.py` after `python -m pip install -e ".[tools]"` (Pillow, tool only).
### Checks without a desktop (Docker)
The tests, the linters, the screenshots and a smoke test of a Linux binary run in a Debian container on a virtual screen, so no window opens on your own desktop.
```bash
docker build -f docker/debian.Dockerfile -t flash-card-debian .
# linters and the whole test suite, including the real window tests
docker run --rm -v "$PWD:/repo:ro" flash-card-debian bash /repo/tools/docker/in-container.sh run-checks.sh
# screenshots into ./build/container-out
docker run --rm -v "$PWD:/repo:ro" -v "$PWD/build/container-out:/out" flash-card-debian bash /repo/tools/docker/in-container.sh screenshots.sh /out
# build the Linux binary and press the known button 5 times (binary and source)
docker run --rm -v "$PWD:/repo:ro" flash-card-debian bash /repo/tools/docker/in-container.sh smoke-binary.sh 5
```
On Windows PowerShell write `${PWD}` for `$PWD`. The repository is mounted read-only and copied inside the container.
- The desktop is Xvfb with GNOME's window manager (mutter). GNOME Shell is tried first and does not start in a container (it needs a login manager), so the scripts fall back to mutter and print which one ran.
- The Windows executable is checked in **Windows Sandbox** (Windows 11 Pro, feature enabled; the version 0.2.0 build passed 5 of 5 runs, see RC-080): `powershell -File tools\sandbox\run.ps1 -Runs 5` after `python tools/build_executable.py`. The sandbox shows its own window while it runs; the click is made inside the sandbox.
- Not covered: macOS (it cannot be run in Docker on Windows or Linux and Apple's licence allows it only on Apple hardware), and Windows itself in the Debian container.
## 📄 License
GNU Affero General Public License v3.0 or later. See [LICENSE][license].
@@ -96,6 +176,7 @@ GNU Affero General Public License v3.0 or later. See [LICENSE][license].
- [Repository][repository]
- [Documentation][documentation]
- [Issue tracker][issues]
- [Releases][releases] (v0.2.0 and v0.1.0: release notes; the executable is built from source, see Run)
## 📎 Appendix: Project documents
@@ -117,9 +198,20 @@ The documents a newcomer needs, in reading order.
---
[license]: ./LICENSE
[screenshot-level]: ./docs/images/screenshot-level.png
[screenshot-front]: ./docs/images/screenshot-front.png
[screenshot-menu]: ./docs/images/screenshot-menu.png
[screenshot-back]: ./docs/images/screenshot-back.png
[wiki-en]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/wiki/Home
[wiki-da]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/wiki/Home-da
[wiki-ms]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/wiki/Home-ms
[data-readme]: ./data/README.md
[repository]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card
[documentation]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/wiki
[issues]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/issues
[releases]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/releases
[release-0-1-0]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/releases/tag/v0.1.0
[release-0-2-0]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/releases/tag/v0.2.0
[agents]: ./AGENTS.md
[BC-001]: ./docs/business-case.md
[SA-001]: ./docs/stakeholder-analysis.md
+45
View File
@@ -0,0 +1,45 @@
# Debian based image for the flash card checks (ADR-0005).
#
# Build (from the repository root):
# docker build -f docker/debian.Dockerfile -t flash-card-debian .
# Run the linters and the tests on a virtual desktop:
# docker run --rm -v "$PWD:/app" flash-card-debian
#
# The base image is the official Python image (Debian bookworm), because the
# program needs Python 3.13. The desktop is a virtual X screen (Xvfb) with
# GNOME Shell when it can start in a container, else GNOME's window manager.
FROM python:3.13-slim-bookworm
ENV DEBIAN_FRONTEND=noninteractive \
PYTHONUNBUFFERED=1 \
PIP_DISABLE_PIP_VERSION_CHECK=1 \
DISPLAY=:99
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
xvfb xauth x11-utils x11-xserver-utils xdotool dbus dbus-x11 \
procps ca-certificates \
libgl1-mesa-dri libegl1 libgles2 \
mutter gnome-session gnome-shell gnome-settings-daemon \
adwaita-icon-theme gsettings-desktop-schemas \
tk fonts-liberation fonts-dejavu-core \
&& rm -rf /var/lib/apt/lists/*
# PyInstaller on Linux needs objdump (binutils).
RUN apt-get update \
&& apt-get install -y --no-install-recommends binutils \
&& rm -rf /var/lib/apt/lists/*
RUN useradd --create-home --shell /bin/bash flash
WORKDIR /app
# Dependencies first, so a change of the sources does not rebuild this layer.
COPY pyproject.toml README.md LICENSE ./
COPY src ./src
RUN python -m pip install --upgrade pip \
&& python -m pip install -e ".[dev,speech,tools,build]" \
&& chown -R flash:flash /app
USER flash
ENV PATH="/app/tools/docker:${PATH}"
CMD ["bash", "tools/docker/run-checks.sh"]
@@ -0,0 +1,55 @@
# ADR-0004: Windows executable built with PyInstaller
## Metadata
| Key | Value |
| --- | --- |
| ID | ADR-0004 |
| CrossReference | [BC-001], [US-001], [DCD-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [768ca34] |
Allowed Status values: `Proposed`, `Accepted`, `Rejected`, `Deprecated`, `Superseded by ADR-NNNN`.
---
## Context
The Product Owner (S01) wants an executable file, so that the program can be started without a Python installation (US-001.07). The program has images, a word list, a progress file that must survive restarts, and an optional speech extra. Options:
1. A one-directory build (a folder with the executable and its libraries): starts faster and the data can sit beside the files, but it is a folder of hundreds of files to hand over.
2. A one-file build (a single `flash-card.exe` that unpacks itself to a temporary folder): one file to hand over, slower start; resources are in a temporary folder, so progress needs a place beside the executable.
3. Another packager (Nuitka, cx_Freeze) or an installer: more tooling and a larger change for the same result.
## Decision
Build a one-file, windowed (no console) Windows executable with PyInstaller by `tools/build_executable.py`. The images and the word list are inside the executable. The progress file and an optional word list are in a `data/` folder beside the executable (found with `sys.executable` when `sys.frozen` is set), and `--data-dir` still overrides it. PyInstaller is only in the optional extra `build`, so `dependencies` stays empty (ADR-0001). The executable is a build output and is not committed.
## Consequences
**Positive:**
- One file to hand over, and no Python, `.venv` or pip needed to run it.
- The source run is unchanged; only the path rule differs when frozen, and it is tested without PyInstaller.
- The word list stays editable beside the executable.
**Negative:**
- PyInstaller cannot cross-compile: the executable must be built on Windows (and on Linux or macOS for those systems).
- A one-file executable unpacks to a temporary folder at each start and is larger with the speech packages; unsigned executables can trigger Windows SmartScreen or antivirus warnings.
- The Windows Store Python can cause Tcl/Tk path problems with PyInstaller; a build with it must be checked by a real start.
## Affected Artifacts
- [BC-001] — scope: the executable is in scope; installer, signing and release upload are out
- [US-001] — US-001.07 Start without Python
- [DCD-001] — packaging support and the choice of the word list file in the composition root
---
[BC-001]: ../business-case.md
[US-001]: ../user-stories.md
[DCD-001]: ../dcd.md
[768ca34]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/768ca344c95d4f21e565e37ac96661c2f8dc8f54
@@ -0,0 +1,55 @@
# ADR-0005: Container and sandbox checks without the user's desktop
## Metadata
| Key | Value |
| --- | --- |
| ID | ADR-0005 |
| CrossReference | [BC-001], [ADR-0004] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [f86bc91] |
Allowed Status values: `Proposed`, `Accepted`, `Rejected`, `Deprecated`, `Superseded by ADR-NNNN`.
---
## Context
Smoke tests of the program drive a real window. Run on the Product Owner's own Windows desktop they open windows, take the focus and move the mouse, which interrupts the Product Owner's work (RC-072). The checks must run somewhere else. Options:
1. A Windows hidden desktop (a second Win32 desktop of the same session): invisible, but still the host's session and a place where a mistake can reach the host.
2. A Debian Docker container with a virtual X screen and GNOME for the Linux checks, and Windows Sandbox for the Windows executable: both are isolated from the host's input and desktop; the Debian check is not a Windows check.
3. A Wine container for the Windows executable, or a real Windows virtual machine run in Docker with KVM: Wine is an emulation of the Windows interface; the Windows virtual machine needs a Microsoft evaluation image of tens of gigabytes and licence terms the Product Owner has not accepted.
4. macOS in Docker: not possible on a Windows host, and Apple's licence allows macOS only on Apple hardware.
## Decision
Run the Linux checks (linters, tests including the real window, screenshots, a Linux binary and its smoke test) in a Debian image based on `python:3.13-slim-bookworm` with Xvfb, GNOME's window manager and, if it runs in a container, the GNOME session. Run the Windows executable in Windows Sandbox of Windows 11 Pro through a `.wsb` configuration and a script that presses the known button inside the sandbox and writes the result to a mapped folder. Do not run macOS, and state that in the documents.
## Consequences
**Positive:**
- No check takes the focus or the mouse of the host any more.
- The container checks are repeatable on any machine with Docker and need no Python installation.
- The sandbox is a real Windows, thrown away after each run.
**Negative:**
- The Debian image is large (a desktop and a Python image) and the first build takes time.
- A full GNOME session may not run in a container; the fallback (GNOME's window manager) is a weaker statement, and the record says which one ran.
- Windows Sandbox needs Windows 11 Pro with the feature enabled and shows its own window on the host while it runs.
- macOS stays untested.
## Affected Artifacts
- [BC-001] — In Scope and Out of Scope lists
- [ADR-0004] — the executable that the sandbox runs
---
[BC-001]: ../business-case.md
[ADR-0004]: ./adr-0004-pyinstaller-executable.md
[f86bc91]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/f86bc9136e7719fbcd049a4f803959019b7d2df3
+70 -70
View File
@@ -1,70 +1,70 @@
# Artifact Registry
This project's artifact state. Types, short names and `CrossReference
Candidates` come from the framework catalog
(`framework/registry/artifact-catalog.md`); this file only records where
each document lives in *this* project and the next version to use.
Delete rows for types you don't use. Add a row the first time you create a
document of a type. `Primary File` may contain a glob (e.g.
`docs/uc-*/uc.md`); `framework/scripts/find-crossreferences.sh` reads it.
| Short Name | Artifact Type | Primary File | Next Available Version |
| --- | --- | --- | --- |
| BC | Business Case | docs/business-case.md | 002 |
| SA | Stakeholder Analysis | docs/stakeholder-analysis.md | 002 |
| PP | Project Plan | docs/project-plan.md | 002 |
| MIL | Milestone / Gateway | docs/milestones/*.md | 008 |
| UCD | Use Case Diagram | docs/use-case-diagram.md | 002 |
| US | User Story | docs/user-stories.md | 002 |
| UC | Use Case | docs/uc-*/uc.md | 002 |
| OC | Operation Contract | docs/uc-*/oc.md | 002 |
| SD | Sequence Diagram | docs/uc-*/sd.md | 002 |
| DM | Domain Model | docs/domain-model.md | 002 |
| SSD | System Sequence Diagram | docs/uc-*/ssd.md | 002 |
| DCD | Design Class Diagram | docs/dcd.md | 002 |
| DICT | Domain Dictionary | docs/dictionary.md | 002 |
| ADR | Architecture Decision Record | docs/adr/adr-NNNN-*.md | 0004 |
| RC | SQA Review Record | docs/sqa/reviews/rc-*.md | 027 |
| TM | Traceability Matrix | docs/sqa/traceability-matrix.md | 002 |
## Languages
Set the PO language when the project starts; `project-planning` asks for it
if it is missing. An artifact of a type marked "Written in the PO language"
exists once, in that language, under its normal name (`business-case.md`); the
`artifact` skill ("One file per artifact") has the rule.
| Setting | Value |
| --- | --- |
| PO language | en |
| PO domain | it |
| High-level register | IT Executive English |
| Technical register | IT Professional English |
| Wiki languages | en, da and ms (`framework/process/wiki.md`: en and the PO language at minimum; da and ms added by the Product Owner) |
Every artifact of a type marked "Yes" below states its language and domain in
its `Language` and `Domain` Metadata rows; `new-artifact.sh` fills them from
`PO language` and `PO domain`. `Language` is a BCP 47 code (`da`, `en`).
`Domain` is a value from this list; add a row to introduce a domain, so a
reviewer can see at once which professional vocabulary a document uses.
| Domain | Meaning |
| --- | --- |
| it | Software and IT |
| medical | Healthcare and medical devices |
| construction | Construction and civil engineering |
| Artifact types | Register | Written in the PO language |
| --- | --- | --- |
| BC, KPI, PP, MIL | IT Executive English | Yes |
| SA, BMC, BPMN, UCD, US, UC, SSD, DM, RA, GOV, DICT | IT Professional English | Yes |
| OC, SD, DCD, ERD, ADR, TM, RC, QC, source code | IT Professional English | No |
## Notes
- "Next Available Version" is the zero-padded (3-digit) version to use the
*next* time a new document of that type is created. Increment it only when
a brand-new document is created, not when an existing document's
`## Version History` gets a row.
- `ADR` uses 4 digits (`0001`); `RC` is sequential across all artifact types.
# Artifact Registry
This project's artifact state. Types, short names and `CrossReference
Candidates` come from the framework catalog
(`framework/registry/artifact-catalog.md`); this file only records where
each document lives in *this* project and the next version to use.
Delete rows for types you don't use. Add a row the first time you create a
document of a type. `Primary File` may contain a glob (e.g.
`docs/uc-*/uc.md`); `framework/scripts/find-crossreferences.sh` reads it.
| Short Name | Artifact Type | Primary File | Next Available Version |
| --- | --- | --- | --- |
| BC | Business Case | docs/business-case.md | 002 |
| SA | Stakeholder Analysis | docs/stakeholder-analysis.md | 002 |
| PP | Project Plan | docs/project-plan.md | 002 |
| MIL | Milestone / Gateway | docs/milestones/*.md | 014 |
| UCD | Use Case Diagram | docs/use-case-diagram.md | 002 |
| US | User Story | docs/user-stories.md | 002 |
| UC | Use Case | docs/uc-*/uc.md | 002 |
| OC | Operation Contract | docs/uc-*/oc.md | 002 |
| SD | Sequence Diagram | docs/uc-*/sd.md | 002 |
| DM | Domain Model | docs/domain-model.md | 002 |
| SSD | System Sequence Diagram | docs/uc-*/ssd.md | 002 |
| DCD | Design Class Diagram | docs/dcd.md | 002 |
| DICT | Domain Dictionary | docs/dictionary.md | 002 |
| ADR | Architecture Decision Record | docs/adr/adr-NNNN-*.md | 0006 |
| RC | SQA Review Record | docs/sqa/reviews/rc-*.md | 081 |
| TM | Traceability Matrix | docs/sqa/traceability-matrix.md | 002 |
## Languages
Set the PO language when the project starts; `project-planning` asks for it
if it is missing. An artifact of a type marked "Written in the PO language"
exists once, in that language, under its normal name (`business-case.md`); the
`artifact` skill ("One file per artifact") has the rule.
| Setting | Value |
| --- | --- |
| PO language | en |
| PO domain | it |
| High-level register | IT Executive English |
| Technical register | IT Professional English |
| Wiki languages | en, da and ms (`framework/process/wiki.md`: en and the PO language at minimum; da and ms added by the Product Owner) |
Every artifact of a type marked "Yes" below states its language and domain in
its `Language` and `Domain` Metadata rows; `new-artifact.sh` fills them from
`PO language` and `PO domain`. `Language` is a BCP 47 code (`da`, `en`).
`Domain` is a value from this list; add a row to introduce a domain, so a
reviewer can see at once which professional vocabulary a document uses.
| Domain | Meaning |
| --- | --- |
| it | Software and IT |
| medical | Healthcare and medical devices |
| construction | Construction and civil engineering |
| Artifact types | Register | Written in the PO language |
| --- | --- | --- |
| BC, KPI, PP, MIL | IT Executive English | Yes |
| SA, BMC, BPMN, UCD, US, UC, SSD, DM, RA, GOV, DICT | IT Professional English | Yes |
| OC, SD, DCD, ERD, ADR, TM, RC, QC, source code | IT Professional English | No |
## Notes
- "Next Available Version" is the zero-padded (3-digit) version to use the
*next* time a new document of that type is created. Increment it only when
a brand-new document is created, not when an existing document's
`## Version History` gets a row.
- `ADR` uses 4 digits (`0001`); `RC` is sequential across all artifact types.
+157 -149
View File
@@ -1,149 +1,157 @@
# Business Case: Flash Card
## Metadata
| Key | Value |
| --- | --- |
| ID | BC-001 |
| CrossReference | [SA-001] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [c3fbcbc] |
---
## Executive Summary
The Day 31 assignment of Udemy's *100 Days of Code: The Complete Python Pro Bootcamp* asks the course participant to build a flash card program that helps learn the most frequent words of a foreign language. The program shows a word in the target language, flips the card after three seconds to show its translation, and keeps only the words the learner does not yet know. This project delivers that program for a Malay to Danish word list, built from the four assignment steps (user interface, new flash cards, flipping the cards, saving progress) and extended with spoken Malay words. It is delivered as readable, tested, documented code that other course participants can run and compare with their own solution.
## Methodological and Standards Foundation
- Method: the SQA and QC framework of this repository (plan first, review every artifact against its QC checklist, one pull request per milestone); Larman, *Applying UML and Patterns*, for the use of layers and the presentation pattern.
- Architecture: clean architecture (domain, application, infrastructure, presentation) with MVVM for the user interface, as the `clean-architecture` skill sets out.
- Quality standard: ISO/IEC 25010:2023 product quality characteristics, as every QC criterion is tagged.
- Code: PEP 8, PEP 257 and type hints; Python 3.13 or later; Doxygen comments; `pytest` for tests.
## Problem Statement
- A learner who memorises vocabulary from a plain list has no way to see which words are already known, so time is spent on words that are mastered.
- The course assignment gives a step-by-step description, not a finished and tested reference that a participant can read, run and compare against.
- The supplied starting data is French to English. The Product Owner learns Malay and reads Danish, so the program must work with a Malay to Danish list and pronounce the Malay word.
## Business Opportunity
A small, well-structured reference solution gives the Product Owner a language learning tool for daily use, shows how clean architecture applies to a Tkinter program, and gives other course participants and repository visitors an example to learn from.
## Objectives
1. Deliver the four assignment steps as working behaviour: the window with a card and two buttons; a random card per button press; a flip to the translation after 3000 ms; and persistence of the unknown words in `words_to_learn.csv`.
2. Use the Malay to Danish frequency word list (`data/ms-da.csv`, 1000 words) instead of the French to English list, and speak the Malay word through text to speech without making that a requirement of the core program.
3. Keep the core program free of third-party runtime dependencies.
4. Provide a repository others can use: README, wiki in English, Danish and Bahasa Malaysia, screenshots, a repository description and topics.
5. Keep track of the work step by step, with one reviewed milestone and one pull request per step.
## Scope
### In Scope
- Python 3.13 or later Tkinter program with the assignment's function names (`next_card`, `flip_card`, `is_known`).
- Reading the Malay to Danish list from `data/ms-da.csv` (semicolon separated, header `ms;da`).
- Saving the words still to learn to `data/words_to_learn.csv` and using that file on the next start.
- Optional spoken Malay word (text to speech) as an extra that can be installed.
- `pyproject.toml`, `.gitignore`, `Doxyfile`, virtual environment instructions, `pytest` tests and `constants.py`.
- README from the framework template, screenshots, and a wiki in English, Danish and Bahasa Malaysia.
- Repository description and topics on the git host.
- The framework documents of the baseline: Business Case, Stakeholder Analysis, Project Plan, milestones, review records and traceability matrix.
### Out of Scope
- Other languages: the user interface labels are Malay and Danish only; another word list works by changing the data file but is not delivered.
- Spaced repetition scheduling, statistics, accounts, cloud synchronisation and mobile apps.
- Packaging for distribution on PyPI or as an installer.
- Redistribution of the course's own image files; the card and button images are generated for this project.
- A translation quality review of the word list.
## Expected Benefits
### Tangible Benefits
- A working flash card program for 1000 Malay words with progress that survives a restart.
- A test suite that protects the behaviour of every assignment step.
- A repository other participants can run in five commands or fewer.
### Intangible Benefits
- A worked example of clean architecture and MVVM in a small Tkinter program.
- Practice of the plan-first workflow with reviews and pull requests per step.
- Learning material in three languages for readers of the wiki.
## Strategic Alignment
The project supports the Product Owner's goal of completing the 100 Days of Code course with understood, well-documented solutions, and the goal of a public repository that shows disciplined engineering practice to its viewers.
## Success Criteria
| # | Criterion | Target | Measure |
| --- | --- | --- | --- |
| 1 | Assignment steps delivered | 4 of 4 steps work as described in the assignment | Acceptance checks listed in each step's milestone are all passed |
| 2 | Tests | `pytest` exits with 0 and every behaviour of steps 1 to 4 has at least one test | `pytest` run on a clean `.venv`, and the milestone's task list |
| 3 | Runtime dependencies of the core program | 0 third-party packages | `dependencies` in `pyproject.toml` is empty; speech is an optional extra |
| 4 | Time to run for a newcomer | 5 commands or fewer from clone to running window | Command count in the README's Setup and Run sections |
| 5 | Wiki coverage | 3 languages (en, da, ms) with the same page set | File list of `docs/wiki/` |
| 6 | Repository presentation | A description and at least 5 topics are set on the repository | Read back from the git host API |
| 7 | Review coverage | Every artifact and every milestone's code has an `RC-*` record with verdict Go | `docs/sqa/reviews/` and the Traceability Matrix |
| 8 | Delivery window | Everything merged by 2026-10-21 | Date of the last merged pull request |
## Risks
| Risk | Impact | Mitigation |
| --- | --- | --- |
| Text to speech needs network access and an audio player that may not work on every machine | Spoken word missing for some users | Speech is an optional extra behind a port; the program starts and works without it, and a failure is logged, not raised |
| The `playsound` package is unmaintained and fails on some Python versions | Install of the extra fails | Pin the version known to work (1.2.2), keep the player behind a port so it can be replaced |
| Tkinter cannot be tested without a display on a build machine | Presentation code untested in CI | The view model holds the behaviour and is tested without Tkinter; the view test skips when no display exists |
| The word list has translation errors (machine translated) | Learner learns a wrong meaning | Out of scope for this project; the README says the list is machine translated and may be edited |
| Course images are copyrighted | Redistribution not allowed in a public repository | Images are generated by a script in this repository |
## Assumptions
- S01 is the Product Owner, the developer and the reviewer; no other person reviews, so the AI acts as stand-in reviewer in autonomous mode and the review records say so.
- S01 can reach S02 and S03 only through the public repository; no interviews are held.
- A display and Tkinter are available on the machine where the program runs.
- Network access is available when the optional speech extra is used.
- The git host `git.tirsystem.com` is used for the repository, the wiki and the pull requests.
## Constraints
- Python 3.13 or later, with a virtual environment in `.venv`.
- The folder structure is `src/`, `tests/` and `docs/`.
- Constants are defined in `constants.py`.
- The assignment's function names are kept so that participants can compare solutions.
- The Product Owner's language is English and the domain is IT; the wiki is in English, Danish and Bahasa Malaysia.
- Delivery by 2026-10-21 (self-set, one week).
## Cost–Benefit Assessment
| Costs | Benefits |
| --- | --- |
| About one working week of the Product Owner's time to review the plan and the result | A reusable learning tool and a reference solution. Qualitative on purpose: no revenue is expected, so a quantitative return does not apply; the benefit is learning and portfolio value |
| No licence or hosting cost; the git host and Python are already available | Documentation and tests reusable for the next course day |
| Maintenance of the optional speech extra | An example of clean architecture for S02 and S03 |
## Stakeholders
| Stakeholder ID (SA) | Interest in this project |
| --- | --- |
| S01 | Owns the product, builds it and reviews it; wants a working tool and a learning record |
| S02 | Wants readable, runnable code with the assignment's function names and run instructions |
| S03 | Wants a clear repository description, topics and README, and no runtime dependencies |
## Recommendation
Proceed — the scope is small, the risks are mitigated, and the result serves the Product Owner and two groups of readers at no cost beyond the Product Owner's time.
---
[SA-001]: ./stakeholder-analysis.md
[c3fbcbc]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/c3fbcbcfaf799e0ae34aed7e14d3bc8a62f03db3
# Business Case: Flash Card
## Metadata
| Key | Value |
| --- | --- |
| ID | BC-001 |
| CrossReference | [SA-001] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Deprecated | Jens Tirsvad Nielsen | AI as stand-in for S01 | Scope: tagged releases v0.1.0 and v0.2.0 (new request of S01) | [0264b60] |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Scope: container and sandbox checks (new request of S01) | [f86bc91] |
---
## Executive Summary
The Day 31 assignment of Udemy's *100 Days of Code: The Complete Python Pro Bootcamp* asks the course participant to build a flash card program that helps learn the most frequent words of a foreign language. The program shows a word in the target language, flips the card after three seconds to show its translation, and keeps only the words the learner does not yet know. This project delivers that program for a Malay to Danish word list, built from the four assignment steps (user interface, new flash cards, flipping the cards, saving progress) and extended with spoken Malay words. It is delivered as readable, tested, documented code that other course participants can run and compare with their own solution.
## Methodological and Standards Foundation
- Method: the SQA and QC framework of this repository (plan first, review every artifact against its QC checklist, one pull request per milestone); Larman, *Applying UML and Patterns*, for the use of layers and the presentation pattern.
- Architecture: clean architecture (domain, application, infrastructure, presentation) with MVVM for the user interface, as the `clean-architecture` skill sets out.
- Quality standard: ISO/IEC 25010:2023 product quality characteristics, as every QC criterion is tagged.
- Code: PEP 8, PEP 257 and type hints; Python 3.13 or later; Doxygen comments; `pytest` for tests.
## Problem Statement
- A learner who memorises vocabulary from a plain list has no way to see which words are already known, so time is spent on words that are mastered.
- The course assignment gives a step-by-step description, not a finished and tested reference that a participant can read, run and compare against.
- The supplied starting data is French to English. The Product Owner learns Malay and reads Danish, so the program must work with a Malay to Danish list and pronounce the Malay word.
## Business Opportunity
A small, well-structured reference solution gives the Product Owner a language learning tool for daily use, shows how clean architecture applies to a Tkinter program, and gives other course participants and repository visitors an example to learn from.
## Objectives
1. Deliver the four assignment steps as working behaviour: the window with a card and two buttons; a random card per button press; a flip to the translation after 3000 ms; and persistence of the unknown words in `words_to_learn.csv`.
2. Use the Malay to Danish frequency word list (`data/ms-da.csv`, 1000 words) instead of the French to English list, and speak the Malay word through text to speech without making that a requirement of the core program.
3. Keep the core program free of third-party runtime dependencies.
4. Provide a repository others can use: README, wiki in English, Danish and Bahasa Malaysia, screenshots, a repository description and topics.
5. Keep track of the work step by step, with one reviewed milestone and one pull request per step.
## Scope
### In Scope
- Python 3.13 or later Tkinter program with the assignment's function names (`next_card`, `flip_card`, `is_known`).
- Reading the Malay to Danish list from `data/ms-da.csv` (semicolon separated, header `ms;da`).
- Saving the words still to learn to `data/words_to_learn.csv` and using that file on the next start.
- Optional spoken Malay word (text to speech) as an extra that can be installed.
- A choice of level (the first 100 words, the first 1000 words or all words of the frequency ordered word list) before learning starts.
- A menu bar with the commands to open another word list (CSV), change the level, reset a word list, exit, and the author's contact.
- Checks that do not use the user's desktop: a Debian based Docker image with a virtual GNOME desktop for the tests, headless screenshots and a Linux binary, and Windows Sandbox for the Windows executable.
- A single Windows executable file, built with PyInstaller by a script of this repository, that runs without an installed Python.
- Tagged releases of the repository (`v0.1.0`, `v0.2.0`), each with release notes and, when the git host accepts the upload, the executable and its SHA-256 checksum attached.
- `pyproject.toml`, `.gitignore`, `Doxyfile`, virtual environment instructions, `pytest` tests and `constants.py`.
- README from the framework template, screenshots, and a wiki in English, Danish and Bahasa Malaysia.
- Repository description and topics on the git host.
- The framework documents of the baseline: Business Case, Stakeholder Analysis, Project Plan, milestones, review records and traceability matrix.
### Out of Scope
- Other languages: the user interface labels are Malay and Danish only; another word list works by changing the data file but is not delivered.
- Spaced repetition scheduling, statistics, accounts, cloud synchronisation and mobile apps.
- Running macOS or a Windows virtual machine other than Windows Sandbox in the checks (macOS is not run in Docker: Apple's licence allows it only on Apple hardware).
- Packaging for distribution on PyPI, an installer and a signed executable (the executable built with PyInstaller and its release on the git host are in scope; the file itself is not committed to the repository).
- Redistribution of the course's own image files; the card and button images are generated for this project.
- A translation quality review of the word list.
## Expected Benefits
### Tangible Benefits
- A working flash card program for 1000 Malay words with progress that survives a restart.
- A test suite that protects the behaviour of every assignment step.
- A repository other participants can run in five commands or fewer.
### Intangible Benefits
- A worked example of clean architecture and MVVM in a small Tkinter program.
- Practice of the plan-first workflow with reviews and pull requests per step.
- Learning material in three languages for readers of the wiki.
## Strategic Alignment
The project supports the Product Owner's goal of completing the 100 Days of Code course with understood, well-documented solutions, and the goal of a public repository that shows disciplined engineering practice to its viewers.
## Success Criteria
| # | Criterion | Target | Measure |
| --- | --- | --- | --- |
| 1 | Assignment steps delivered | 4 of 4 steps work as described in the assignment | Acceptance checks listed in each step's milestone are all passed |
| 2 | Tests | `pytest` exits with 0 and every behaviour of steps 1 to 4 has at least one test | `pytest` run on a clean `.venv`, and the milestone's task list |
| 3 | Runtime dependencies of the core program | 0 third-party packages | `dependencies` in `pyproject.toml` is empty; speech is an optional extra |
| 4 | Time to run for a newcomer | 5 commands or fewer from clone to running window | Command count in the README's Setup and Run sections |
| 5 | Wiki coverage | 3 languages (en, da, ms) with the same page set | File list of `docs/wiki/` |
| 6 | Repository presentation | A description and at least 5 topics are set on the repository | Read back from the git host API |
| 7 | Review coverage | Every artifact and every milestone's code has an `RC-*` record with verdict Go | `docs/sqa/reviews/` and the Traceability Matrix |
| 8 | Delivery window | Everything merged by 2026-10-21 | Date of the last merged pull request |
## Risks
| Risk | Impact | Mitigation |
| --- | --- | --- |
| Text to speech needs network access and an audio player that may not work on every machine | Spoken word missing for some users | Speech is an optional extra behind a port; the program starts and works without it, and a failure is logged, not raised |
| The `playsound` package is unmaintained and fails on some Python versions | Install of the extra fails | Pin the version known to work (1.2.2), keep the player behind a port so it can be replaced |
| Tkinter cannot be tested without a display on a build machine | Presentation code untested in CI | The view model holds the behaviour and is tested without Tkinter; the view test skips when no display exists |
| The word list has translation errors (machine translated) | Learner learns a wrong meaning | Out of scope for this project; the README says the list is machine translated and may be edited |
| Course images are copyrighted | Redistribution not allowed in a public repository | Images are generated by a script in this repository |
## Assumptions
- S01 is the Product Owner, the developer and the reviewer; no other person reviews, so the AI acts as stand-in reviewer in autonomous mode and the review records say so.
- S01 can reach S02 and S03 only through the public repository; no interviews are held.
- A display and Tkinter are available on the machine where the program runs.
- Network access is available when the optional speech extra is used.
- The git host `git.tirsystem.com` is used for the repository, the wiki and the pull requests.
## Constraints
- Python 3.13 or later, with a virtual environment in `.venv`.
- The folder structure is `src/`, `tests/` and `docs/`.
- Constants are defined in `constants.py`.
- The assignment's function names are kept so that participants can compare solutions.
- The Product Owner's language is English and the domain is IT; the wiki is in English, Danish and Bahasa Malaysia.
- Delivery by 2026-10-21 (self-set, one week).
## Cost–Benefit Assessment
| Costs | Benefits |
| --- | --- |
| About one working week of the Product Owner's time to review the plan and the result | A reusable learning tool and a reference solution. Qualitative on purpose: no revenue is expected, so a quantitative return does not apply; the benefit is learning and portfolio value |
| No licence or hosting cost; the git host and Python are already available | Documentation and tests reusable for the next course day |
| Maintenance of the optional speech extra | An example of clean architecture for S02 and S03 |
## Stakeholders
| Stakeholder ID (SA) | Interest in this project |
| --- | --- |
| S01 | Owns the product, builds it and reviews it; wants a working tool and a learning record |
| S02 | Wants readable, runnable code with the assignment's function names and run instructions |
| S03 | Wants a clear repository description, topics and README, and no runtime dependencies |
## Recommendation
Proceed — the scope is small, the risks are mitigated, and the result serves the Product Owner and two groups of readers at no cost beyond the Product Owner's time.
---
[SA-001]: ./stakeholder-analysis.md
[0264b60]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/0264b6084f26bac5af716ea71596ce3be961fec8
[f86bc91]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/f86bc9136e7719fbcd049a4f803959019b7d2df3
+267 -194
View File
@@ -1,194 +1,267 @@
# Design Class Diagram: Flash Card
## Metadata
| Key | Value |
| --- | --- |
| ID | DCD-001 |
| CrossReference | [DM-001], [SD-001], [DICT-001], [ADR-0002] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [c3fbcbc] |
---
## Purpose and Scope
The design classes of the program in `src/flash_card/`, in four layers (domain, application, infrastructure, presentation) with the presentation pattern MVVM ([ADR-0002]). The classes refine the concepts of [DM-001]; names are the IT terms of [DICT-001]. Methods trace to the operation contracts of [OC-001] and the sequence diagrams of [SD-001] (the SSD messages are in [SSD-001]).
## Diagram
```plantuml
@startuml
package domain {
class Card <<frozen>> {
+front : str
+back : str
}
class LanguagePair <<frozen>> {
+front_code : str
+back_code : str
}
class Vocabulary <<frozen>> {
+language_pair : LanguagePair
+cards : tuple[Card, ...]
}
class Deck {
+language_pair : LanguagePair
-_cards : list[Card]
+from_vocabulary(vocabulary : Vocabulary) : Deck
+cards : tuple[Card, ...]
+is_empty : bool
+draw(choose, exclude : Card | None) : Card
+remove(card : Card) : None
}
interface VocabularyRepository {
+load() : Vocabulary
}
interface ProgressRepository {
+load() : Deck | None
+save(deck : Deck) : None
}
class VocabularyError
class VocabularyFormatError
class VocabularyNotFoundError
class EmptyDeckError
}
package application {
class CardDto <<frozen>> {
+front_text : str
+back_text : str
+front_language : str
+back_language : str
}
interface SpeechPort {
+speak(text : str, language_code : str) : None
}
class StudySession {
-_deck : Deck
-_progress : ProgressRepository
-_speech : SpeechPort
+current_card : CardDto | None
+remaining : int
+next_card() : CardDto | None
+mark_known() : None
}
class open_study_session <<function>>
}
package infrastructure {
class CsvVocabularyRepository {
-_path : Path
+load() : Vocabulary
}
class CsvProgressRepository {
-_path : Path
+load() : Deck | None
+save(deck : Deck) : None
}
class GttsSpeech {
+speak(text : str, language_code : str) : None
}
class NullSpeech {
+speak(text : str, language_code : str) : None
}
}
package presentation {
class FlashCardViewModel {
-_session : StudySession
+side : Side
+language_name : str
+text : str
+next_card() : None
+flip_card() : None
+is_known() : None
}
class FlashCardView {
+flip_timer : str | None
+next_card() : None
+flip_card() : None
+is_known() : None
}
class "app.main" as Main <<function>>
}
Vocabulary "1" *-- "1..*" Card
Vocabulary "1" --> "1" LanguagePair
Deck "1" o-- "0..*" Card
Deck ..> Vocabulary : built from
Deck ..> EmptyDeckError : raises
VocabularyFormatError --|> VocabularyError
VocabularyNotFoundError --|> VocabularyError
EmptyDeckError --|> VocabularyError
StudySession "1" --> "1" Deck
StudySession "1" --> "1" ProgressRepository
StudySession "1" --> "1" SpeechPort
StudySession ..> CardDto : returns
open_study_session ..> VocabularyRepository
open_study_session ..> ProgressRepository
open_study_session ..> StudySession : creates
CsvVocabularyRepository ..|> VocabularyRepository
CsvProgressRepository ..|> ProgressRepository
GttsSpeech ..|> SpeechPort
NullSpeech ..|> SpeechPort
FlashCardViewModel "1" --> "1" StudySession
FlashCardView "1" --> "1" FlashCardViewModel
Main ..> CsvVocabularyRepository : composes
Main ..> CsvProgressRepository : composes
Main ..> GttsSpeech : composes
Main ..> FlashCardView : composes
@enduml
```
## Class Table
| Class | Refines (Domain Model concept) | Responsibility | Attributes | Operations |
| --- | --- | --- | --- | --- |
| `Card` | Flash Card | Holds a word and its translation | `front`, `back` | none |
| `LanguagePair` | Word List (first and second language) | Names the two languages of a word list by code | `front_code`, `back_code` | none |
| `Vocabulary` | Word List | Holds all cards of a language pair as delivered | `language_pair`, `cards` | none |
| `Deck` | Words To Learn | Holds the cards still to learn and picks and removes cards | `language_pair`, `_cards` | `from_vocabulary`, `draw`, `remove` |
| `VocabularyRepository` | Word List | Port: load the delivered word list | none | `load` |
| `ProgressRepository` | Words To Learn | Port: load and save the words to learn | none | `load`, `save` |
| `StudySession` | Study Session | Runs one session: draws cards, marks cards known, saves progress, asks for speech | `_deck`, `_progress`, `_speech`, `_current` | `next_card`, `mark_known` |
| `CardDto` | Flash Card | Plain data that crosses to the presentation layer | four text fields | none |
| `SpeechPort` | (none: external service) | Port: speak a text in a language | none | `speak` |
| `CsvVocabularyRepository`, `CsvProgressRepository` | Word List, Words To Learn | Adapters that read and write the semicolon separated CSV file | `_path` | `load`, `save` |
| `GttsSpeech`, `NullSpeech` | (none) | Adapters for speech: the gTTS service, and silence | none | `speak` |
| `FlashCardViewModel` | Study Session | Exposes the side, language name and text of the card shown, and the three commands | `_session`, `side`, `language_name`, `text` | `next_card`, `flip_card`, `is_known` |
| `FlashCardView` | (none: user interface) | Draws the window, forwards the buttons, owns the 3000 ms timer | `flip_timer`, widgets | `next_card`, `flip_card`, `is_known` |
## Method Traceability
| Method signature | Operation Contract / SD message |
| --- | --- |
| `open_study_session(vocabulary_repository, progress_repository, speech, choose) -> StudySession` | [OC-001] `startStudySession`, [SD-001] sequence startStudySession (loads the words to learn) |
| `StudySession.next_card() -> CardDto \| None` | [OC-001] `startStudySession` (first card), `markUnknown`; [SD-001] |
| `StudySession.mark_known() -> None` | [OC-001] `markKnown` (remove and save); [SD-001] |
| `FlashCardViewModel.next_card() -> None` | [OC-001] `markUnknown`; [SD-001] |
| `FlashCardViewModel.is_known() -> None` | [OC-001] `markKnown`; [SD-001] |
| `FlashCardViewModel.flip_card() -> None` | [SSD-001] timer turn-over (no contract: started by the system's timer) |
| `FlashCardView.next_card()`, `.is_known()`, `.flip_card()` | the same three operations, forwarded from buttons and the timer; names are the assignment's |
## Pattern Annotations
| Pattern | Classes | Rationale |
| --- | --- | --- |
| Repository | `VocabularyRepository`, `ProgressRepository`, CSV adapters | The domain does not know the CSV file |
| Ports and adapters | `SpeechPort`, `GttsSpeech`, `NullSpeech` | Speech is an optional extra; the core runs without it |
| Null Object | `NullSpeech` | No `if speech:` checks in the use case |
| MVVM | `FlashCardView`, `FlashCardViewModel` | Behaviour is tested without Tkinter ([ADR-0002]) |
| Composition root | `app.main` | The one place that names the adapters |
## Dependency Check
Imports point inward: `domain` imports nothing from the other packages; `application` imports `domain`; `infrastructure` imports `application` and `domain`; `presentation` imports `application` and `domain`, and `app.main` additionally imports `infrastructure`. There is no cycle. `constants.py` imports nothing from the packages.
---
[DM-001]: ./domain-model.md
[DICT-001]: ./dictionary.md
[SSD-001]: ./uc-001/ssd.md
[OC-001]: ./uc-001/oc.md
[SD-001]: ./uc-001/sd.md
[ADR-0002]: ./adr/adr-0002-clean-architecture-and-mvvm.md
[c3fbcbc]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/c3fbcbcfaf799e0ae34aed7e14d3bc8a62f03db3
# Design Class Diagram: Flash Card
## Metadata
| Key | Value |
| --- | --- |
| ID | DCD-001 |
| CrossReference | [DM-001], [SD-001], [DICT-001], [ADR-0002], [ADR-0004] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Deprecated | Jens Tirsvad Nielsen | AI as stand-in for S01 | Scope note: runtime path rules and the executable build are packaging support, not design classes | [768ca34] |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Added the menu classes, Application and ProgressRepository.reset | [2211d0f] |
---
## Purpose and Scope
The design classes of the program in `src/flash_card/`, in four layers (domain, application, infrastructure, presentation) with the presentation pattern MVVM ([ADR-0002]). The classes refine the concepts of [DM-001]; names are the IT terms of [DICT-001]. Methods trace to the operation contracts of [OC-001] and the sequence diagrams of [SD-001] (the SSD messages are in [SSD-001]). The module `flash_card/runtime.py` (where the resources and the data folder are when the program is frozen by PyInstaller) and the scripts in `tools/` are packaging support ([ADR-0004]): they have no system operation and are not design classes; `app.main` is still the only place that names the adapters, and it chooses the word list file.
## Diagram
```plantuml
@startuml
package domain {
class Card <<frozen>> {
+front : str
+back : str
}
class LanguagePair <<frozen>> {
+front_code : str
+back_code : str
}
class Level <<frozen>> {
+limit : int | None
+first(cards : Sequence[Card]) : tuple[Card, ...]
}
class Vocabulary <<frozen>> {
+language_pair : LanguagePair
+cards : tuple[Card, ...]
}
class Deck {
+language_pair : LanguagePair
-_cards : list[Card]
+from_vocabulary(vocabulary : Vocabulary) : Deck
+cards : tuple[Card, ...]
+is_empty : bool
+within(cards : Sequence[Card]) : tuple[Card, ...]
+draw(choose, exclude : Card | None, among : Sequence[Card] | None) : Card
+remove(card : Card) : None
}
interface VocabularyRepository {
+load() : Vocabulary
}
interface ProgressRepository {
+load() : Deck | None
+save(deck : Deck) : None
+reset() : None
}
class VocabularyError
class VocabularyFormatError
class VocabularyNotFoundError
class EmptyDeckError
}
package application {
class CardDto <<frozen>> {
+front_text : str
+back_text : str
+front_language : str
+back_language : str
}
interface SpeechPort {
+speak(text : str, language_code : str) : None
}
class StudySession {
-_deck : Deck
-_progress : ProgressRepository
-_speech : SpeechPort
-_level_cards : tuple[Card, ...]
+current_card : CardDto | None
+remaining : int
+next_card() : CardDto | None
+mark_known() : None
}
class open_study_session <<function>>
}
package infrastructure {
class CsvVocabularyRepository {
-_path : Path
+load() : Vocabulary
}
class CsvProgressRepository {
-_path : Path
+load() : Deck | None
+save(deck : Deck) : None
}
class GttsSpeech {
+speak(text : str, language_code : str) : None
}
class NullSpeech {
+speak(text : str, language_code : str) : None
}
}
package presentation {
class MenuEntry <<frozen>> {
+label : str
+command : str
}
class MenuViewModel {
+file_entries : tuple[MenuEntry, ...]
+contact_label : str
+contact_url : str
}
class MenuView {
+open_word_list() : None
+change_level() : None
+reset_word_list() : None
+show_contact() : None
+exit_program() : None
}
class Application {
+start(level : Level) : None
+open_word_list(path : Path) : None
+change_level() : None
+reset_word_list() : None
+exit_application() : None
}
class LevelChoice <<frozen>> {
+label : str
+level : Level
}
class LevelViewModel {
+title : str
+choices : tuple[LevelChoice, ...]
}
class LevelView {
+choose(level : Level) : None
}
class FlashCardViewModel {
-_session : StudySession
+side : Side
+language_name : str
+text : str
+next_card() : None
+flip_card() : None
+is_known() : None
}
class FlashCardView {
+flip_timer : str | None
+next_card() : None
+flip_card() : None
+is_known() : None
}
class "app.main" as Main <<function>>
}
Vocabulary "1" *-- "1..*" Card
Vocabulary "1" --> "1" LanguagePair
Level ..> Card : selects the first
Deck ..> Level : filtered by the cards of
Deck "1" o-- "0..*" Card
Deck ..> Vocabulary : built from
Deck ..> EmptyDeckError : raises
VocabularyFormatError --|> VocabularyError
VocabularyNotFoundError --|> VocabularyError
EmptyDeckError --|> VocabularyError
StudySession "1" --> "1" Deck
StudySession "1" --> "1" ProgressRepository
StudySession "1" --> "1" SpeechPort
StudySession ..> CardDto : returns
open_study_session ..> VocabularyRepository
open_study_session ..> ProgressRepository
open_study_session ..> Level
open_study_session ..> StudySession : creates
CsvVocabularyRepository ..|> VocabularyRepository
CsvProgressRepository ..|> ProgressRepository
GttsSpeech ..|> SpeechPort
NullSpeech ..|> SpeechPort
FlashCardViewModel "1" --> "1" StudySession
FlashCardView "1" --> "1" FlashCardViewModel
LevelViewModel "1" *-- "3" LevelChoice
LevelChoice "1" --> "1" Level
LevelView "1" --> "1" LevelViewModel
Main ..> LevelView : composes
Main ..> CsvVocabularyRepository : composes
Main ..> CsvProgressRepository : composes
Main ..> GttsSpeech : composes
Main ..> FlashCardView : composes
Main ..> Application : creates
Main ..> MenuView : composes
MenuView "1" --> "1" MenuViewModel
MenuViewModel "1" *-- "5" MenuEntry
MenuView "1" --> "1" Application
Application ..> ProgressRepository : resets
@enduml
```
## Class Table
| Class | Refines (Domain Model concept) | Responsibility | Attributes | Operations |
| --- | --- | --- | --- | --- |
| `Card` | Flash Card | Holds a word and its translation | `front`, `back` | none |
| `LanguagePair` | Word List (first and second language) | Names the two languages of a word list by code | `front_code`, `back_code` | none |
| `Level` | Level | Names how many of the first words of the word list a session uses and selects them | `limit` | `first` |
| `Vocabulary` | Word List | Holds all cards of a language pair as delivered | `language_pair`, `cards` | none |
| `Deck` | Words To Learn | Holds the cards still to learn and picks and removes cards | `language_pair`, `_cards` | `from_vocabulary`, `within`, `draw`, `remove` |
| `VocabularyRepository` | Word List | Port: load the delivered word list | none | `load` |
| `ProgressRepository` | Words To Learn | Port: load and save the words to learn | none | `load`, `save` |
| `StudySession` | Study Session | Runs one session: draws cards of the level, marks cards known, saves progress, asks for speech | `_deck`, `_progress`, `_speech`, `_level_cards`, `_current` | `next_card`, `mark_known` |
| `CardDto` | Flash Card | Plain data that crosses to the presentation layer | four text fields | none |
| `SpeechPort` | (none: external service) | Port: speak a text in a language | none | `speak` |
| `CsvVocabularyRepository`, `CsvProgressRepository` | Word List, Words To Learn | Adapters that read and write the semicolon separated CSV file | `_path` | `load`, `save` |
| `GttsSpeech`, `NullSpeech` | (none) | Adapters for speech: the gTTS service, and silence | none | `speak` |
| `FlashCardViewModel` | Study Session | Exposes the side, language name and text of the card shown, and the three commands | `_session`, `side`, `language_name`, `text` | `next_card`, `flip_card`, `is_known` |
| `LevelChoice`, `LevelViewModel` | Level | Plain data and view model of the level screen: the title and the three choices with their labels | `title`, `choices` | none |
| `MenuEntry`, `MenuViewModel` | (none: user interface) | Plain data and view model of the menu bar: the labels and the order of the File entries, the contact label and link | `file_entries`, `contact_label`, `contact_url` | none |
| `MenuView` | (none: user interface) | Draws the menu bar, asks the dialogs (file, confirmation, messages) and forwards the command | menus | `open_word_list`, `change_level`, `reset_word_list`, `show_contact`, `exit_program` |
| `Application` | Study Session | Holds the window, the word list and the progress in use; starts, drops and replaces sessions on level choice and menu commands | `root`, `view`, `exit_code` | `start`, `open_word_list`, `change_level`, `reset_word_list`, `exit_application` |
| `LevelView` | (none: user interface) | Draws the level screen and forwards the chosen level | buttons | `choose` |
| `FlashCardView` | (none: user interface) | Draws the window, forwards the buttons, owns the 3000 ms timer | `flip_timer`, widgets | `next_card`, `flip_card`, `is_known` |
## Method Traceability
| Method signature | Operation Contract / SD message |
| --- | --- |
| `open_study_session(vocabulary_repository, progress_repository, speech, choose, level) -> StudySession` | [OC-001] `chooseLevel`, [SD-001] sequence chooseLevel (loads the words to learn and the level's cards) |
| `Level.first(cards) -> tuple[Card, ...]`, `Deck.within(cards) -> tuple[Card, ...]` | [OC-001] `chooseLevel` postcondition (the level's cards); [SD-001] |
| `LevelViewModel.choices -> tuple[LevelChoice, ...]` | [OC-001] `startStudySession`; [SD-001] sequence startStudySession |
| `Application.open_word_list(path) -> None` | [OC-001] `openWordList`; [SD-001] sequence openWordList |
| `Application.change_level() -> None` | [OC-001] `changeLevel` |
| `Application.reset_word_list() -> None`, `ProgressRepository.reset() -> None` | [OC-001] `resetWordList`; [SD-001] sequence resetWordList |
| `MenuView.show_contact() -> None` | [OC-001] `showContact` |
| `Application.exit_application() -> None`, `MenuView.exit_program() -> None` | [OC-001] `exit` |
| `LevelView.choose(level) -> None` | [OC-001] `chooseLevel` (forwards the level to the composition root) |
| `StudySession.next_card() -> CardDto \| None` | [OC-001] `chooseLevel` (first card), `markUnknown`; [SD-001] |
| `StudySession.mark_known() -> None` | [OC-001] `markKnown` (remove and save); [SD-001] |
| `FlashCardViewModel.next_card() -> None` | [OC-001] `markUnknown`; [SD-001] |
| `FlashCardViewModel.is_known() -> None` | [OC-001] `markKnown`; [SD-001] |
| `FlashCardViewModel.flip_card() -> None` | [SSD-001] timer turn-over (no contract: started by the system's timer) |
| `FlashCardView.next_card()`, `.is_known()`, `.flip_card()` | the same three operations, forwarded from buttons and the timer; names are the assignment's |
## Pattern Annotations
| Pattern | Classes | Rationale |
| --- | --- | --- |
| Repository | `VocabularyRepository`, `ProgressRepository`, CSV adapters | The domain does not know the CSV file |
| Ports and adapters | `SpeechPort`, `GttsSpeech`, `NullSpeech` | Speech is an optional extra; the core runs without it |
| Null Object | `NullSpeech` | No `if speech:` checks in the use case |
| MVVM | `FlashCardView`, `FlashCardViewModel`, `LevelView`, `LevelViewModel`, `MenuView`, `MenuViewModel` | Behaviour is tested without Tkinter ([ADR-0002]) |
| Composition root | `app.main` | The one place that names the adapters, shows the level screen and chooses the word list file (beside the executable, else inside it) |
| Controller (GRASP) | `Application` | One object receives the menu and level commands and coordinates repositories and sessions |
| Value object | `Level`, `Card`, `LanguagePair` | Immutable data with its own rule (`Level.first`) |
## Dependency Check
Imports point inward: `domain` imports nothing from the other packages; `application` imports `domain`; `infrastructure` imports `application` and `domain`; `presentation` imports `application` and `domain`, and `app.main` additionally imports `infrastructure`. There is no cycle. `constants.py` imports nothing from the packages.
---
[DM-001]: ./domain-model.md
[DICT-001]: ./dictionary.md
[SSD-001]: ./uc-001/ssd.md
[OC-001]: ./uc-001/oc.md
[SD-001]: ./uc-001/sd.md
[ADR-0002]: ./adr/adr-0002-clean-architecture-and-mvvm.md
[ADR-0004]: ./adr/adr-0004-pyinstaller-executable.md
[768ca34]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/768ca344c95d4f21e565e37ac96661c2f8dc8f54
[2211d0f]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/2211d0f4cbd8182314d18cbdefd939ae50c39e6d
+49 -45
View File
@@ -1,45 +1,49 @@
# Domain Dictionary: Flash Card
## Metadata
| Key | Value |
| --- | --- |
| ID | DICT-001 |
| CrossReference | [BC-001], [SA-001], [DM-001] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [c3fbcbc] |
---
## Purpose and Scope
Maps each Product Owner (PO) term to its professional IT term. PO language: English (`en`), domain: Software and IT (`it`), from the registry's `Languages` section. The PO terms are the words of a language learner; the IT terms are the class and function names of the code.
## Dictionary
| PO term | Language | IT term | Definition | Used as PO term in | Used as IT term in |
| --- | --- | --- | --- | --- | --- |
| Flash card | en | `Card` | A word in one language together with its translation in another language. | DM, UC, US | DCD |
| Word list | en | `Vocabulary` | The complete set of flash cards of one language pair, as delivered with the program. | DM, UC, US | DCD |
| Words to learn | en | `Deck` | The flash cards the learner does not yet know; it starts as the word list and only gets smaller. | DM, UC, US | DCD |
| Study session | en | `StudySession` | One run of the program in which the learner is shown cards one by one. | DM, UC, US | DCD |
| Language pair | en | `LanguagePair` | The two languages of a word list, the language learned and the language of the translation. | DM, UC | DCD |
| Progress file | en | `ProgressRepository` | The file `words_to_learn.csv` that keeps the words to learn between runs. | UC, US | DCD |
| Spoken word | en | `SpeechPort` | The Malay word read aloud when its card is shown. | UC, US | DCD |
## Rules
- The Domain Model, use cases and user stories use the PO term; the Operation Contract, Sequence Diagram, Design Class Diagram and ERD use the IT term.
- One IT term per PO term and one PO term per IT term; no synonyms.
- "Card" alone means a flash card; "front" is its word in the language learned and "back" is its translation, and the card on screen shows one of them at a time.
---
[BC-001]: ./business-case.md
[SA-001]: ./stakeholder-analysis.md
[DM-001]: ./domain-model.md
[c3fbcbc]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/c3fbcbcfaf799e0ae34aed7e14d3bc8a62f03db3
# Domain Dictionary: Flash Card
## Metadata
| Key | Value |
| --- | --- |
| ID | DICT-001 |
| CrossReference | [BC-001], [SA-001], [DM-001] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Deprecated | Jens Tirsvad Nielsen | AI as stand-in for S01 | Added the term Level | [0b983b7] |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Added the term Reset | [2211d0f] |
---
## Purpose and Scope
Maps each Product Owner (PO) term to its professional IT term. PO language: English (`en`), domain: Software and IT (`it`), from the registry's `Languages` section. The PO terms are the words of a language learner; the IT terms are the class and function names of the code.
## Dictionary
| PO term | Language | IT term | Definition | Used as PO term in | Used as IT term in |
| --- | --- | --- | --- | --- | --- |
| Flash card | en | `Card` | A word in one language together with its translation in another language. | DM, UC, US | DCD |
| Word list | en | `Vocabulary` | The complete set of flash cards of one language pair, as delivered with the program. | DM, UC, US | DCD |
| Words to learn | en | `Deck` | The flash cards the learner does not yet know; it starts as the word list and only gets smaller. | DM, UC, US | DCD |
| Study session | en | `StudySession` | One run of the program in which the learner is shown cards one by one. | DM, UC, US | DCD |
| Level | en | `Level` | The number of the most frequent words of the word list that a study session uses: 100, 1000 or all. | DM, UC, US | DCD |
| Language pair | en | `LanguagePair` | The two languages of a word list, the language learned and the language of the translation. | DM, UC | DCD |
| Progress file | en | `ProgressRepository` | The file `words_to_learn.csv` that keeps the words to learn between runs. | UC, US | DCD |
| Reset | en | `reset` | Removing the kept progress of a word list so that all its words are to learn again. | UC, US | DCD, OC |
| Spoken word | en | `SpeechPort` | The Malay word read aloud when its card is shown. | UC, US | DCD |
## Rules
- The Domain Model, use cases and user stories use the PO term; the Operation Contract, Sequence Diagram, Design Class Diagram and ERD use the IT term.
- One IT term per PO term and one PO term per IT term; no synonyms.
- "Card" alone means a flash card; "front" is its word in the language learned and "back" is its translation, and the card on screen shows one of them at a time.
---
[BC-001]: ./business-case.md
[SA-001]: ./stakeholder-analysis.md
[DM-001]: ./domain-model.md
[0b983b7]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/0b983b7fdadf6958717c1d0227d0f2ebe037f7b1
[2211d0f]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/2211d0f4cbd8182314d18cbdefd939ae50c39e6d
+90 -80
View File
@@ -1,80 +1,90 @@
# Domain Model: Flash Card
## Metadata
| Key | Value |
| --- | --- |
| ID | DM-001 |
| CrossReference | [UC-001], [UCD-001], [SSD-001], [DICT-001] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [c3fbcbc] |
---
## Purpose and Scope
Covers: [UC-001] Study Flash Cards. The model holds the concepts a Learner talks about: the flash card, the word list, the words to learn and the study session. The project-level model is this document; no other use case exists.
## Diagram
Concepts, attributes and associations only — no operations.
```plantuml
@startuml
class "Flash Card" as FlashCard {
word in the first language
translation in the second language
}
class "Word List" as WordList {
first language
second language
}
class "Words To Learn" as WordsToLearn
class "Study Session" as StudySession {
card shown
side shown
}
WordList "1" o-- "1..*" FlashCard : holds
WordsToLearn "1" o-- "0..*" FlashCard : holds
WordsToLearn "1" --> "1" WordList : starts as a copy of
StudySession "1" --> "1" WordsToLearn : works through
StudySession "1" --> "0..1" FlashCard : shows
@enduml
```
## Concept Table
| Concept | Definition | Attributes | Source (use case / glossary) |
| --- | --- | --- | --- |
| Flash Card | A word in one language with its translation in another | word, translation | UC-001 steps 3 and 4 ("card", "translation") |
| Word List | The complete set of flash cards of a language pair, as delivered with the program | first language, second language | UC-001 step 2 ("word list") |
| Words To Learn | The flash cards the Learner does not yet know; starts as the word list and only gets smaller | none | UC-001 steps 2 and 6 ("words to learn") |
| Study Session | One run of the program in which the Learner is shown cards | card shown, side shown | UC-001 main scenario |
## Association Table
| From | Association (reading direction) | To | Multiplicity |
| --- | --- | --- | --- |
| Word List | holds | Flash Card | 1 to 1..* |
| Words To Learn | holds | Flash Card | 1 to 0..* |
| Words To Learn | starts as a copy of | Word List | 1 to 1 |
| Study Session | works through | Words To Learn | 1 to 1 |
| Study Session | shows | Flash Card | 1 to 0..1 |
## Generalizations
| General | Specializations | Is-a justification |
| --- | --- | --- |
| none | none | no generalization exists in this domain |
---
[UC-001]: ./uc-001/uc.md
[UCD-001]: ./use-case-diagram.md
[SSD-001]: ./uc-001/ssd.md
[DICT-001]: ./dictionary.md
[c3fbcbc]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/c3fbcbcfaf799e0ae34aed7e14d3bc8a62f03db3
# Domain Model: Flash Card
## Metadata
| Key | Value |
| --- | --- |
| ID | DM-001 |
| CrossReference | [UC-001], [UCD-001], [SSD-001], [DICT-001] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Deprecated | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [c3fbcbc] |
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Added the concept Level | [0b983b7] |
---
## Purpose and Scope
Covers: [UC-001] Study Flash Cards. The model holds the concepts a Learner talks about: the flash card, the word list, the words to learn, the level and the study session. The project-level model is this document; no other use case exists.
## Diagram
Concepts, attributes and associations only — no operations.
```plantuml
@startuml
class "Flash Card" as FlashCard {
word in the first language
translation in the second language
}
class "Word List" as WordList {
first language
second language
}
class "Words To Learn" as WordsToLearn
class "Level" as Level {
number of words, or all words
}
class "Study Session" as StudySession {
card shown
side shown
}
WordList "1" o-- "1..*" FlashCard : holds
WordsToLearn "1" o-- "0..*" FlashCard : holds
WordsToLearn "1" --> "1" WordList : starts as a copy of
StudySession "1" --> "1" WordsToLearn : works through
StudySession "1" --> "0..1" FlashCard : shows
StudySession "1" --> "1" Level : is limited to
Level "1" --> "1" WordList : takes the first words of
@enduml
```
## Concept Table
| Concept | Definition | Attributes | Source (use case / glossary) |
| --- | --- | --- | --- |
| Flash Card | A word in one language with its translation in another | word, translation | UC-001 steps 3 and 4 ("card", "translation") |
| Word List | The complete set of flash cards of a language pair, as delivered with the program | first language, second language | UC-001 step 2 ("word list") |
| Words To Learn | The flash cards the Learner does not yet know; starts as the word list and only gets smaller | none | UC-001 steps 2 and 6 ("words to learn") |
| Level | The part of the word list a study session uses: its first 100 or 1000 words, or all words | number of words, or all words | UC-001 steps 2, 3 and 5 ("level") |
| Study Session | One run of the program in which the Learner is shown cards | card shown, side shown | UC-001 main scenario |
## Association Table
| From | Association (reading direction) | To | Multiplicity |
| --- | --- | --- | --- |
| Word List | holds | Flash Card | 1 to 1..* |
| Words To Learn | holds | Flash Card | 1 to 0..* |
| Words To Learn | starts as a copy of | Word List | 1 to 1 |
| Study Session | works through | Words To Learn | 1 to 1 |
| Study Session | shows | Flash Card | 1 to 0..1 |
| Study Session | is limited to | Level | 1 to 1 |
| Level | takes the first words of | Word List | 1 to 1 |
## Generalizations
| General | Specializations | Is-a justification |
| --- | --- | --- |
| none | none | no generalization exists in this domain |
---
[UC-001]: ./uc-001/uc.md
[UCD-001]: ./use-case-diagram.md
[SSD-001]: ./uc-001/ssd.md
[DICT-001]: ./dictionary.md
[c3fbcbc]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/c3fbcbcfaf799e0ae34aed7e14d3bc8a62f03db3
[0b983b7]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/0b983b7fdadf6958717c1d0227d0f2ebe037f7b1
Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

+82
View File
@@ -0,0 +1,82 @@
# MIL-008: Choose level
## Metadata
| Key | Value |
| --- | --- |
| ID | MIL-008 |
| CrossReference | [BC-001], [US-001], [UC-001], [DCD-001] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [0b983b7] |
---
## Purpose
Decide whether the Learner can choose a level before learning: the program asks for 100 words, 1000 words or all words, and then uses the first N words of the word list, which is ordered from the most to the least frequent word.
## Deliverable
At start the window shows the choice "100 words", "1000 words" and "All words". After a choice the card window of the earlier milestones opens and every card comes from the first N words of the word list that the Learner does not yet know. Known words stay known across levels because there is still one progress file. The design documents, README, wiki (English, Danish, Bahasa Malaysia) and screenshots describe the choice.
## Go / No-Go Criteria
| # | Criterion (objectively checkable) | Go | No-Go |
| --- | --- | --- | --- |
| 1 | Choosing 100 draws only cards that are among the first 100 rows of `data/ms-da.csv`, for every card of a full run through the deck | Integration test passes on the real word list | A card from row 101 or later appears |
| 2 | Choosing 1000 words or All words uses every word of the list; with a list of fewer than N words all are used | Unit and integration tests pass | Any word is missing |
| 3 | Marking words known at level 100 and then choosing All words leaves those words known, and `words_to_learn.csv` still holds every word that is not known (also those outside level 100) | Integration test passes | A word outside the level is lost from the file |
| 4 | When every word of the chosen level is known the card shows the message that nothing is left to learn, and the program does not fail | Unit and e2e tests pass | Exception or empty window |
| 5 | The level screen holds no rule: the labels and the choice come from the level view model, which imports no Tkinter | View model unit tests pass | A rule is in the view |
| 6 | `python -m flash_card --level 100` (also `1000`, `all`) skips the screen and starts at that level; an unknown value is refused by the argument parser | Unit tests pass | The screen appears or the program starts |
| 7 | The updated UC-001, DM-001, DICT-001, SSD-001, OC-001, SD-001, DCD-001, BC-001, wireframe, README and the wiki in three languages mention the level choice, and each changed document has a new Version History row and a `Go` review | Review records `Go`; `check-readme.sh` exit 0 | A document is not updated |
| 8 | Code review against QC-PY-001 has no failed Mandatory criterion; `pytest` exits with 0 and `ruff`, `mypy --strict`, `lint-imports` and `doxygen` are clean | `RC-*` verdict Go and exit codes 0 | Otherwise |
## Dependencies
| Depends on | Reason |
| --- | --- |
| MIL-007 | The finished program, README, wiki and screenshots that this milestone extends |
## Traceability
| Business Case objective / KPI / user story | Reference |
| --- | --- |
| Objective 1 (learning with the word list) and success criterion 1, extended by the new request of S01 | [BC-001] |
| US-001.06 Choose my level | [US-001] |
## Ownership
| Role | Stakeholder ID (SA) |
| --- | --- |
| Owner | S01 |
| Approving reviewer | S01 (AI as stand-in in autonomous mode) |
## Target Date
2026-10-20 — within the delivery window that ends 2026-10-21 ([BC-001] constraint).
## Tasks
| # | Task | Summary | Needs its own Use Case/User Story? | Reference |
| --- | --- | --- | --- | --- |
| 1 | Update the design documents for the level choice | Add the level to UC-001 (a first step before the cards, and the finished-level extension), to DM-001 and DICT-001 (concept Level), to SSD-001, OC-001 and SD-001 (operation chooseLevel and the level in startStudySession) and to DCD-001; draw the wireframe of the level screen in wireframe.md; add the level choice to the In Scope list of BC-001. Every changed document gets a Version History row and a new review. | No | UC-001, DCD-001 |
| 2 | Add the Level value object and the level choices | `Level` (limit as a number of words, or none for all words) in the domain and the three choices 100, 1000 and all words in constants.py with their labels, so that the choices are defined once. | No | DCD-001 |
| 3 | Draw cards from the chosen level | `StudySession` draws only from the first N words of the word list that are still to learn, and removes a known card from the whole words to learn and saves the whole deck, so that words of other levels are never lost. | Yes | US-001.06 |
| 4 | Open the session with a level | `open_study_session` gets the level, loads the word list for its order and the progress file for what is left, and builds the session; a level with nothing left gives a finished session. | Yes | US-001.06 |
| 5 | Add the level screen | `LevelViewModel` (the choices and their labels, no Tkinter) and `LevelView` in `presentation/features/level/` with the title "Choose your level" and three buttons on the window background. | Yes | US-001.06 |
| 6 | Show the level screen before the cards | The composition root shows the level screen first and builds the card view on the same window after the choice; the option `--level 100`, `--level 1000` or `--level all` skips the screen. | Yes | US-001.06 |
| 7 | Test the level choice | Unit tests of the level, the filter, the session and the view model; integration tests on the real word list and the progress file across levels; e2e test of the level screen and the flow to the first card. | No | |
| 8 | Update the README, the wiki and the screenshots | README, Usage and Home pages of the wiki in English, Danish and Bahasa Malaysia, and a new screenshot of the level screen made by tools/capture_screenshots.py; republish the wiki after the merge. | No | |
---
[BC-001]: ../business-case.md
[US-001]: ../user-stories.md
[UC-001]: ../uc-001/uc.md
[DCD-001]: ../dcd.md
[0b983b7]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/0b983b7fdadf6958717c1d0227d0f2ebe037f7b1
+86
View File
@@ -0,0 +1,86 @@
# MIL-009: Executable with PyInstaller
## Metadata
| Key | Value |
| --- | --- |
| ID | MIL-009 |
| CrossReference | [BC-001], [US-001], [UC-001], [DCD-001] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Deprecated | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [768ca34] |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Added task 9 (fix a flaky unit test found after the merge) | [061b4f4] |
---
## Purpose
Decide whether the Learner can start the program from one executable file without a Python installation: the program is packaged with PyInstaller by a script of this repository, and behaves in the executable as it does from the source.
## Deliverable
`python tools/build_executable.py` builds `dist/flash-card.exe` (one file, no console window, an icon, the images and the word list inside, the speech extra included). The executable shows the level screen, keeps the progress in `data/words_to_learn.csv` next to it and prefers a `data/ms-da.csv` next to it over the word list inside. The executable itself is not committed to git; README and wiki (English, Danish, Bahasa Malaysia) explain how to build and use it.
## Go / No-Go Criteria
| # | Criterion (objectively checkable) | Go | No-Go |
| --- | --- | --- | --- |
| 1 | `python tools/build_executable.py` ends with exit code 0 and produces `dist/flash-card.exe` | File exists and is larger than 1 MB | No file or a build error |
| 2 | The executable starts on this machine with the virtual environment not activated and shows the level screen without a console window | A window titled "Flashy" exists after 5 seconds and the process is a Windows GUI program | The process ends or shows a console |
| 3 | With a `data/ms-da.csv` copied next to the executable it uses that file; without it the word list inside the executable is used | Smoke test with a marked list of two words, then without | The wrong list is used |
| 4 | Marking a word known in the executable writes `data/words_to_learn.csv` next to it and the next start continues from it | Smoke test reads the file after the run | No file or progress lost |
| 5 | The four images and the icon are inside the executable and are found when frozen | Card and button images are visible in a captured screenshot of the executable | A missing image or an exception |
| 6 | Path resolution when frozen (`sys.frozen`, `sys._MEIPASS`) is tested without PyInstaller | Unit tests pass | Not covered |
| 7 | `dependencies` in `pyproject.toml` is still empty; PyInstaller is only in the extra `build` | File check | A runtime dependency was added |
| 8 | BC-001, DCD-001 and ADR-0004 are updated and reviewed `Go`; README and wiki in three languages describe the build | Review records `Go`; `check-readme.sh` exit 0 | A document is missing |
| 9 | Code review against QC-PY-001 has no failed Mandatory criterion; `pytest`, `ruff`, `mypy --strict`, `lint-imports` and `doxygen` are clean | `RC-*` verdict Go and exit codes 0 | Otherwise |
## Dependencies
| Depends on | Reason |
| --- | --- |
| MIL-008 | The finished program, with the level screen, that is packaged |
## Traceability
| Business Case objective / KPI / user story | Reference |
| --- | --- |
| Objective 4 (a repository others can use), extended by the new request of S01; success criterion 4 (time to run) | [BC-001] |
| US-001.07 Start without Python | [US-001] |
## Ownership
| Role | Stakeholder ID (SA) |
| --- | --- |
| Owner | S01 |
| Approving reviewer | S01 (AI as stand-in in autonomous mode) |
## Target Date
2026-10-16 — within the delivery window that ends 2026-10-21 ([BC-001] constraint).
## Tasks
| # | Task | Summary | Needs its own Use Case/User Story? | Reference |
| --- | --- | --- | --- | --- |
| 1 | Update the documents for the executable | Amend BC-001 (In Scope: an executable built with PyInstaller; Out of Scope: an installer and a signed release stay out), add ADR-0004 (PyInstaller one-file windowed build, word list inside and a `data` folder beside the executable for progress, Windows only), and add the runtime path resolution to DCD-001. Every changed document gets a Version History row and a review. | No | BC-001, DCD-001 |
| 2 | Resolve resource and data paths when frozen | The images are found under `sys._MEIPASS` and the default data folder is `data/` next to the executable when `sys.frozen` is set; the source run keeps its paths. The rule is one function used by `constants.py`, tested by simulating the frozen state. | Yes | US-001.07 |
| 3 | Prefer the word list next to the executable | When the data folder has no `ms-da.csv` the program uses the copy inside the executable; the progress file is always written to the data folder; `--data-dir` still overrides both. | Yes | US-001.07 |
| 4 | Add the build script and the build extra | `tools/build_executable.py` calls PyInstaller (one file, windowed, name `flash-card`, the assets and the word list as data, the icon, the speech packages as hidden imports); `pyproject.toml` gets the extra `build`; `build/`, `dist/` and `*.spec` are ignored. | No | ADR-0004 |
| 5 | Generate the application icon | `tools/generate_images.py` also writes `flash_card.ico` (the card with the tick) from the same drawing code, so no external asset is used. | No | |
| 6 | Build and smoke-test the executable | Build it, start it with the virtual environment not active, check the window, the images, the level choice, the progress file next to it, the word list override and the speech import; record the result in the review record. | Yes | US-001.07 |
| 7 | Test the path rules and the build arguments | Unit tests for the frozen and source path rules and for the argument list the build script gives PyInstaller (without running PyInstaller). | No | |
| 8 | Update README and wiki | README and the Install page of the wiki in English, Danish and Bahasa Malaysia: how to build, where the executable and the data folder are, that Python is not needed to run it. The wiki is republished after the merge. | No | |
| 9 | Fix a flaky unit test | After the merge a unit test of `app.main` failed in about 1 of 6 full runs because it created a real Tk root; it uses the module's fake root instead, so the unit tests never need a display. Found by running the suite repeatedly. | No | RC-049 |
---
[BC-001]: ../business-case.md
[US-001]: ../user-stories.md
[UC-001]: ../uc-001/uc.md
[DCD-001]: ../dcd.md
[768ca34]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/768ca344c95d4f21e565e37ac96661c2f8dc8f54
[061b4f4]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/061b4f48b5d49e6800656c95d79df707e07ec0f3
+79
View File
@@ -0,0 +1,79 @@
# MIL-010: Release v0.1.0
## Metadata
| Key | Value |
| --- | --- |
| ID | MIL-010 |
| CrossReference | [BC-001], [US-001], [UC-001], [ADR-0004] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [9c8e294] |
---
## Purpose
Decide whether the project can be handed out as a release: the version 0.1.0 is tagged, and the executable built from exactly that commit is attached to a release page with its checksum and release notes.
## Deliverable
A tag `v0.1.0` on the head of `main`, and a release on the git host with the assets `flash-card.exe` and `flash-card.exe.sha256`, and release notes. `CHANGELOG.md` holds the same notes. The README and the wiki (English, Danish, Bahasa Malaysia) link to the release page.
## Go / No-Go Criteria
| # | Criterion (objectively checkable) | Go | No-Go |
| --- | --- | --- | --- |
| 1 | The executable is rebuilt from the head of `main` that gets the tag, in a clean build folder, and passes the smoke test of MIL-009 (window, embedded list, progress file beside it, list override) | Smoke test output recorded in the review record | A failing case |
| 2 | The tag `v0.1.0` is an annotated tag on that commit and `pyproject.toml` and `flash_card.__version__` say `0.1.0` | `git show v0.1.0` and the two files agree | A different version or commit |
| 3 | The release has the assets `flash-card.exe` and `flash-card.exe.sha256` | Listed by the host API | An asset is missing |
| 4 | The SHA-256 of the file downloaded from the release equals the value in `flash-card.exe.sha256` and in the release notes | Hash compared after a download | A difference |
| 5 | The release notes say that the file is an unsigned Windows build, what the `data` folder next to it holds, the SHA-256, and how to build it | Notes read back from the API | A statement is missing |
| 6 | `CHANGELOG.md`, README and the Install page of the wiki in three languages link the release; `check-readme.sh` exit 0 | Exit code 0 | A link is missing |
| 7 | BC-001, US-001 and PP-001 are updated (the release upload leaves Out of Scope) and reviewed `Go` | Review records `Go` | A document is not updated |
## Dependencies
| Depends on | Reason |
| --- | --- |
| MIL-009 | The executable and its build script |
## Traceability
| Business Case objective / KPI / user story | Reference |
| --- | --- |
| Objective 4 (a repository others can use), extended by the new request of S01 | [BC-001] |
| US-001.08 Download the executable | [US-001] |
## Ownership
| Role | Stakeholder ID (SA) |
| --- | --- |
| Owner | S01 |
| Approving reviewer | S01 (AI as stand-in in autonomous mode) |
## Target Date
2026-10-16 — within the delivery window that ends 2026-10-21 ([BC-001] constraint).
## Tasks
| # | Task | Summary | Needs its own Use Case/User Story? | Reference |
| --- | --- | --- | --- | --- |
| 1 | Update the documents for the release | Amend BC-001 (the upload of the executable to a release leaves Out of Scope and the release becomes In Scope; signing and an installer stay out), add US-001.08 and the gateway to PP-001; each changed document gets a Version History row and a review. | No | BC-001, US-001 |
| 2 | Write the release notes and CHANGELOG.md | `CHANGELOG.md` (Keep a Changelog layout) with the version 0.1.0: what the program does, the four assignment steps, the level choice, the executable, known limits (unsigned, Windows only, Python 3.13 or later to build); the notes are reused for the release body. | No | |
| 3 | Rebuild and smoke-test the executable from the tagged commit | Build `dist/flash-card.exe` from a clean tree of the head of `main`, run the smoke test of MIL-009, compute the SHA-256 and write `flash-card.exe.sha256` (not committed). | Yes | US-001.08 |
| 4 | Tag v0.1.0 | Create an annotated tag `v0.1.0` on the head of `main` and push it; a tag cannot be undone without deleting it on the host, so it is made only after the documents are merged. | No | |
| 5 | Create the release and attach the files | Create the release `v0.1.0` through the host API with the notes, attach `flash-card.exe` and `flash-card.exe.sha256`, download the asset again and compare the hash. The token is read from `.env` and is never printed or put on a command line. | Yes | US-001.08 |
| 6 | Link the release | README, the Install page of the wiki in English, Danish and Bahasa Malaysia and `CHANGELOG.md` link the release page; the wiki is republished. | No | |
---
[BC-001]: ../business-case.md
[US-001]: ../user-stories.md
[UC-001]: ../uc-001/uc.md
[ADR-0004]: ../adr/adr-0004-pyinstaller-executable.md
[9c8e294]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/9c8e2940217e615f82eda2d48aca9b2fd58f3687
+84
View File
@@ -0,0 +1,84 @@
# MIL-011: Menu bar
## Metadata
| Key | Value |
| --- | --- |
| ID | MIL-011 |
| CrossReference | [BC-001], [US-001], [UC-001], [DCD-001] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [2211d0f] |
---
## Purpose
Decide whether the program has the classic menu bar the Product Owner asked for: a File menu (open a word list, change the level, reset a word list, exit) and an About menu (contact), and whether the commands keep the progress of every word list safe.
## Deliverable
The window has a menu bar. File: Open (a CSV word list), Change level, Reset word list, Exit. About: Contact with the author's name and title and a link to the author's LinkedIn page. The progress of each word list is kept in its own file. README, the Usage page of the wiki in three languages and a screenshot show the menu.
## Go / No-Go Criteria
| # | Criterion (objectively checkable) | Go | No-Go |
| --- | --- | --- | --- |
| 1 | The menu bar has File (Open, Change level, Reset word list, separator, Exit) and About (Contact, LinkedIn entry) with the labels of the wireframe | e2e test reads the menu entries and their order | A different structure |
| 2 | Opening a valid CSV word list switches the cards to it after the level choice; opening an invalid file shows a message and keeps the earlier list; cancelling changes nothing | Unit and e2e tests with a faked file dialog and message box | A wrong list in use or a crash |
| 3 | The progress of each word list is a file of its own: `words_to_learn.csv` for the delivered `ms-da.csv` and `words_to_learn_<name>.csv` for another list; known words of one list never appear in another | Integration test with two lists | Progress mixed or lost |
| 4 | Change level shows the level choice again without a restart and keeps the known words | Unit and e2e tests | Restart needed or progress lost |
| 5 | Reset word list asks to confirm; on yes only the progress file of the open list is deleted and the level choice is shown; on no nothing changes; the word list file is never changed | Unit, integration and e2e tests | Another file touched |
| 6 | About, Contact opens `https://www.linkedin.com/in/tirsvad74` through `webbrowser` and shows "Jens Tirsvad Nielsen, Software engineer" | Unit test with a faked `webbrowser.open` | Another address |
| 7 | Exit closes the window, cancels the pending timer and ends the program with exit code 0 | e2e test | A leftover timer or an error |
| 8 | The menu logic is in a view model without Tkinter; the commands are one use case or application call each | View model unit tests without a display | A rule in the view |
| 9 | The documents of the plan (BC-001, US-001, UC-001, SSD-001, OC-001, SD-001, DCD-001, DICT-001, wireframe, PP-001) and README and wiki in three languages describe the menu, each reviewed `Go` | Review records `Go`; `check-readme.sh` exit 0 | A document is missing |
| 10 | Code review against QC-PY-001 has no failed Mandatory criterion; `pytest`, `ruff`, `mypy --strict`, `lint-imports` and `doxygen` are clean | `RC-*` verdict Go and exit codes 0 | Otherwise |
## Dependencies
| Depends on | Reason |
| --- | --- |
| MIL-009 | The program with the level screen, the executable and the data folder rules; MIL-010 (release) is independent and may be done before or after |
## Traceability
| Business Case objective / KPI / user story | Reference |
| --- | --- |
| Objective 1 and 2 (learning with word lists), extended by the new request of S01 | [BC-001] |
| US-001.09 to US-001.12 | [US-001] |
## Ownership
| Role | Stakeholder ID (SA) |
| --- | --- |
| Owner | S01 |
| Approving reviewer | S01 (AI as stand-in in autonomous mode) |
## Target Date
2026-10-17 — within the delivery window that ends 2026-10-21 ([BC-001] constraint).
## Tasks
| # | Task | Summary | Needs its own Use Case/User Story? | Reference |
| --- | --- | --- | --- | --- |
| 1 | Update the documents for the menu bar | Amend BC-001 (In Scope: a menu bar with the commands), UC-001 (the menu commands as extensions at any card), SSD-001, OC-001 and SD-001 (`openWordList`, `changeLevel`, `resetWordList`, `exit`), DCD-001 (`ProgressRepository.reset`, the menu classes, `Application` commands), DICT-001 and the wireframe (menu bar and dialogs); each changed document gets a Version History row and a review. | No | UC-001, DCD-001 |
| 2 | Keep the progress of every word list apart | `progress_file_name(list_path)` in one place (`words_to_learn.csv` for `ms-da.csv`, `words_to_learn_<name>.csv` for another list) and `ProgressRepository.reset()` with its CSV adapter (deletes the file, no error when it is absent). | Yes | US-001.09, US-001.11 |
| 3 | Open another word list | The application loads a CSV chosen in the file dialog (starting in the data folder), validates it before it replaces the list in use, and shows the level choice for it; an invalid file gives a message and no change. | Yes | US-001.09 |
| 4 | Change level while learning | The application shows the level choice again on the same window and starts the session at the chosen level with the progress kept. | Yes | US-001.10 |
| 5 | Reset a word list | After a confirmation the application resets the progress of the open list and shows the level choice; the word list file is never changed. | Yes | US-001.11 |
| 6 | Add the menu bar and the About menu | `MenuViewModel` (entries, labels, order, no Tkinter) and `MenuView` (the Tk menu bar on the window, mnemonics, Exit that cancels the timer, About, Contact entry that opens the LinkedIn page); the contact data and labels are constants. | Yes | US-001.12 |
| 7 | Test the menu and the commands | Unit tests (progress file names, reset, view model, application commands with faked dialogs and `webbrowser`), integration tests with two word lists, e2e test of the real menu bar. | No | |
| 8 | Update README, wiki and screenshots | README and the Usage page of the wiki in English, Danish and Bahasa Malaysia, and a screenshot that includes the menu bar; the wiki is republished after the merge. | No | |
---
[BC-001]: ../business-case.md
[US-001]: ../user-stories.md
[UC-001]: ../uc-001/uc.md
[DCD-001]: ../dcd.md
[2211d0f]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/2211d0f4cbd8182314d18cbdefd939ae50c39e6d
+84
View File
@@ -0,0 +1,84 @@
# MIL-012: Release v0.2.0
## Metadata
| Key | Value |
| --- | --- |
| ID | MIL-012 |
| CrossReference | [BC-001], [US-001], [UC-001], [ADR-0004] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [0264b60] |
---
## Purpose
Decide whether the project can be handed out as version 0.2.0: the version is raised, the tag `v0.2.0` is made on the commit that is built, and the release page has notes and, when the git host accepts the upload, the executable with its checksum. Version 0.2.0 is the minor release that adds the menu bar and the progress per word list to 0.1.0.
## Deliverable
`pyproject.toml`, `flash_card.__version__` and the `Doxyfile` say `0.2.0`; `CHANGELOG.md` has the entry for 0.2.0; the annotated tag `v0.2.0` is on the head of `main`; the release `v0.2.0` exists with notes; `flash-card.exe` and `flash-card.exe.sha256` are attached if the upload limit of the git host allows it, otherwise the notes say how to build the executable and the open issue stays open.
## Go / No-Go Criteria
| # | Criterion (objectively checkable) | Go | No-Go |
| --- | --- | --- | --- |
| 1 | The three version places say `0.2.0` and a test fails when `flash_card.__version__` and `pyproject.toml` differ | Test passes; grep shows the same version | A different version |
| 2 | `CHANGELOG.md` has a `[0.2.0]` entry listing the menu bar, the progress per word list and the message for a file that is not UTF-8, and `[0.1.0]` is unchanged | File read in the review record | A missing or changed entry |
| 3 | The upload limit of the git host is probed before the build with a draft release that is deleted afterwards, and the result is recorded | Result in the review record | No probe |
| 4 | The executable is built with `--clean` from the commit to be tagged and passes the smoke test of MIL-009 (window, embedded list, progress beside it, list override) | Smoke test output in the review record | A failing case |
| 5 | The tag `v0.2.0` is an annotated tag on that commit; `v0.1.0` is not moved | `git show v0.2.0` and `git rev-parse v0.1.0` | A moved or lightweight tag |
| 6 | The release `v0.2.0` is published with notes that state what is new, that the file is unsigned, the `data` folder rule and how to build | Notes read back from the API | A statement is missing |
| 7 | When the probe allowed it: the release has `flash-card.exe` and `flash-card.exe.sha256`, and the SHA-256 of the downloaded file equals the checksum; when the probe did not allow it: the notes say so and the issue "attach the files" stays open | Hash compared, or the statement is present | A wrong or unverifiable hash |
| 8 | README, CHANGELOG and the Install page of the wiki in three languages link `v0.2.0` and say whether the executable is attached; `check-readme.sh` exit 0 | Exit code 0 | A link is missing |
| 9 | `pytest`, `ruff`, `mypy --strict`, `lint-imports` and `doxygen` are clean after the version change; BC-001, US-001 and PP-001 are reviewed `Go` | `RC-*` verdict Go and exit codes 0 | Otherwise |
## Dependencies
| Depends on | Reason |
| --- | --- |
| MIL-011 | The menu bar that makes this release |
| MIL-010 | The release procedure and its open issue about the upload limit |
## Traceability
| Business Case objective / KPI / user story | Reference |
| --- | --- |
| Objective 4 (a repository others can use) | [BC-001] |
| US-001.08 Download the executable | [US-001] |
## Ownership
| Role | Stakeholder ID (SA) |
| --- | --- |
| Owner | S01 |
| Approving reviewer | S01 (AI as stand-in in autonomous mode) |
## Target Date
2026-10-18 — within the delivery window that ends 2026-10-21 ([BC-001] constraint).
## Tasks
| # | Task | Summary | Needs its own Use Case/User Story? | Reference |
| --- | --- | --- | --- | --- |
| 1 | Update the documents for the release | BC-001 (releases in plural), US-001.08 (the latest release instead of v0.1.0) and PP-001; each changed document gets a Version History row and a review. | No | BC-001, US-001 |
| 2 | Raise the version to 0.2.0 | `pyproject.toml`, `flash_card.__version__` in `src/flash_card/__init__.py` and `PROJECT_NUMBER` of the `Doxyfile`; one unit test compares the version of the package with `pyproject.toml`, so the places cannot drift. | No | |
| 3 | Write the CHANGELOG entry and the release notes | `[0.2.0]` with Added (menu bar: open another word list, change level, reset word list, exit, contact; progress kept apart for each word list), Fixed (a file that is not UTF-8 gives a message) and the known limits; the same text is the release body. | No | |
| 4 | Probe the upload limit of the git host | Create a draft release, try uploads of 1, 5, 10 and 30 MB random files one after another and stop at the first refusal, delete the draft and its tag; record the largest accepted size. The token is read inside the script. | No | |
| 5 | Build and smoke-test the executable from the tagged commit | `python tools/build_executable.py --clean` from a clean tree of the head of `main` after the version change, the smoke test, and the SHA-256. | Yes | US-001.08 |
| 6 | Tag v0.2.0 | Annotated tag `v0.2.0` on the head of `main` and push it; `v0.1.0` stays where it is. | No | |
| 7 | Create the release and attach the files | Create the release `v0.2.0` with the notes through the API; attach `flash-card.exe` and `flash-card.exe.sha256` when the probe allows it and compare the hash after a download; otherwise say so in the notes and leave the issue open. | Yes | US-001.08 |
| 8 | Link the release | README, CHANGELOG and the Install page of the wiki in English, Danish and Bahasa Malaysia link `v0.2.0`; the wiki is republished. | No | |
---
[BC-001]: ../business-case.md
[US-001]: ../user-stories.md
[UC-001]: ../uc-001/uc.md
[ADR-0004]: ../adr/adr-0004-pyinstaller-executable.md
[0264b60]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/0264b6084f26bac5af716ea71596ce3be961fec8
@@ -0,0 +1,88 @@
# MIL-013: Container checks
## Metadata
| Key | Value |
| --- | --- |
| ID | MIL-013 |
| CrossReference | [BC-001], [DCD-001], [ADR-0004] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [f86bc91] |
---
## Purpose
Decide whether the program can be built, tested and run without touching the Product Owner's own desktop: a Docker container gives a Debian desktop (GNOME) on a virtual screen, and Windows Sandbox (a disposable Windows virtual machine of Windows 11 Pro) runs the Windows executable on a desktop of its own. The checks that earlier took over the Windows desktop (mouse clicks, windows opening) move into the containers.
## Deliverable
- A Debian image (`python:3.13-slim-bookworm`) with GNOME's window manager and session, a virtual X screen, Tk and fonts, that runs the linters and the whole test suite (including the e2e tests of the real window), the headless run with screenshots, and a PyInstaller build of a Linux binary with its smoke test.
- A Windows Sandbox check of the Windows executable: a `.wsb` configuration and a PowerShell script (`tools/sandbox/`) that start a disposable Windows 11 virtual machine with the built `dist/` mapped read-only and an output folder mapped read-write, start the executable on the sandbox's own desktop, press the known button inside the sandbox, check the progress file, take screenshots, write the results to the output folder and shut the sandbox down. The mouse and the keyboard used are those of the sandbox, not of the host.
- macOS is not covered, and the documents say why (see ADR-0005).
## Go / No-Go Criteria
| # | Criterion (objectively checkable) | Go | No-Go |
| --- | --- | --- | --- |
| 1 | `docker build` of the Debian image succeeds on the Product Owner's Docker Desktop (Linux containers) | Exit code 0 | A build error |
| 2 | In the Debian image the linters and the whole test suite run on the virtual screen with the GNOME window manager and end with exit code 0, with the e2e tests counted as passed (not skipped) | Output and exit code | A skipped or failing test |
| 3 | The full GNOME session (`gnome-session` with its shell) is tried in the container; the result is recorded; when it cannot run in a container the checks use GNOME's window manager (mutter) and the record says so | Result in the review record | An unstated fallback |
| 4 | During the container runs nothing opens or moves on the host desktop; during a sandbox run the only host effect is the sandbox's own window, and the sandbox is closed by its script | Nothing else seen on the host | A host window other than the sandbox or any host click |
| 5 | The screenshot script writes the level screen, the card front, the card back and the window with the menu bar as PNG files to a mounted folder, from the Debian image | Four readable PNG files | A missing or blank file |
| 6 | A Linux binary is built in the container and its smoke test passes: the window appears, the level screen is shown, a known word is pressed through the virtual input of the screen and the progress file has one card less, the list override is used | Script output and exit code 0 for 5 consecutive runs | A failing run |
| 7 | The Windows executable passes the same smoke test inside Windows Sandbox (window titled Flashy, embedded list, list override, known button writes the progress file), 5 consecutive sandbox runs, with the results read from the mapped output folder | Result files of 5 runs | A failing run, or a run that needs the host mouse |
| 8 | The lost-click symptom of RC-072 is investigated with the container test (a repeated press of the known button on the same executable) and the finding is recorded: program defect or test harness | Finding in the review record | No finding |
| 9 | README and the wiki Install page in three languages describe the commands and state that macOS is not covered, that the sandbox needs Windows 11 Pro with Windows Sandbox enabled, and that the Debian check is not a Windows check; `check-readme.sh` exit 0 | Exit code 0 | A missing statement |
| 10 | BC-001 and PP-001 are updated and ADR-0005 records the decision and its limits (including why macOS is not run in Docker); each reviewed `Go`; code review against QC-PY-001 has no failed Mandatory criterion; the linters are clean | `RC-*` verdict Go | Otherwise |
## ## Dependencies
| Depends on | Reason |
| --- | --- |
| MIL-012 | The version 0.2.0 of the program, the built executable and the open condition (RC-072) about its smoke test |
## Traceability
| Business Case objective / KPI / user story | Reference |
| --- | --- |
| Objective 4 (a repository others can use) and success criterion 2 (tests run on a clean environment) | [BC-001] |
| The condition of RC-072 on the executable smoke test (Linux part) | [MIL-012] |
## Ownership
| Role | Stakeholder ID (SA) |
| --- | --- |
| Owner | S01 |
| Approving reviewer | S01 (AI as stand-in in autonomous mode) |
## Target Date
2026-10-19 — within the delivery window that ends 2026-10-21 ([BC-001] constraint).
## Tasks
| # | Task | Summary | Needs its own Use Case/User Story? | Reference |
| --- | --- | --- | --- | --- |
| 1 | Update the documents for the container checks | BC-001 (In Scope: Docker images for tests and headless runs; Out of Scope: macOS, a signed or installed Windows setup), PP-001 and a new ADR-0005 (the Debian image with GNOME, Windows Sandbox for the Windows executable, what is covered and why macOS is not run in Docker: Apple's licence allows macOS only on Apple hardware); each changed document gets a Version History row and a review. | No | BC-001, ADR-0004 |
| 2 | Add the Debian image with GNOME | `docker/debian.Dockerfile` and `.dockerignore`: `python:3.13-slim-bookworm`, `xvfb`, `xauth`, `dbus-x11`, `mutter`, `gnome-session` and `gnome-shell`, `tk`, `fonts-liberation`, `x11-utils`, `xdotool`, a non-root user; the project installed with `[dev,speech,tools,build]`. | No | ADR-0005 |
| 3 | Start a GNOME session on the virtual screen | `tools/docker/start-desktop.sh` starts `dbus`, Xvfb and `gnome-session` (or, if the session cannot run in a container, mutter alone) and waits until the desktop is up; the choice is printed and recorded. | No | |
| 4 | Add the check scripts | `tools/docker/run-checks.sh`, `screenshots.sh` and `smoke-binary.sh`; each one purpose, `set -euo pipefail`, shellcheck clean, all run under the desktop of task 3. | No | |
| 5 | Make the screenshot tool work on Linux | `tools/capture_screenshots.py` chooses the platform: Windows as now, Linux grabs the X screen with Pillow and crops to the window; the pure parts are unit tested. | No | |
| 6 | Add the headless smoke driver | A script that starts the program or the binary, finds the window with `xdotool`, presses the known button with the virtual input of the screen, and checks the progress file, with a repeat count so the lost-click symptom of RC-072 can be measured; the sandbox script does the same with the sandbox's input. | No | |
| 7 | Add the Windows Sandbox check | `tools/sandbox/flash-card.wsb` (mapped folders: `dist` read-only, `out` read-write; logon command), `tools/sandbox/smoke.ps1` (runs inside the sandbox: copy the executable, start it, wait for the window, press the known button with the sandbox's own input, read the progress file, take screenshots, write a result file and shut the sandbox down) and `tools/sandbox/run.ps1` on the host (starts the sandbox with the generated configuration and waits for the result file). | No | ADR-0005 |
| 8 | Run and record the checks | Build the image, run the scripts and the smoke tests 5 times each in the container and 5 times in the sandbox, record counts, sizes, durations and the GNOME session result; record the finding on the lost click. | No | |
| 9 | Test the pure parts | Unit tests for the platform choice and the box calculation of the capture tool and for the argument handling of the smoke driver. | No | |
| 10 | Update README and wiki | README and the Install page of the wiki in English, Danish and Bahasa Malaysia: the commands, the output folders, the limits (the Debian check is not a Windows check, the sandbox needs Windows 11 Pro, macOS is not covered); the wiki is republished after the merge. | No | |
---
[BC-001]: ../business-case.md
[DCD-001]: ../dcd.md
[ADR-0004]: ../adr/adr-0004-pyinstaller-executable.md
[MIL-012]: ./mil-012-release-0-2-0.md
[f86bc91]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/f86bc9136e7719fbcd049a4f803959019b7d2df3
+147 -108
View File
@@ -1,108 +1,147 @@
# Project Plan: Flash Card
## Metadata
| Key | Value |
| --- | --- |
| ID | PP-001 |
| CrossReference | [BC-001], [SA-001], [US-001], [MIL-001], [MIL-002], [MIL-003], [MIL-004], [MIL-005], [MIL-006], [MIL-007] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [c3fbcbc] |
---
## Purpose
This plan schedules the seven phases (gateways) that deliver the flash card program inside the delivery window of one week that the Business Case sets as a constraint (2026-10-14 to 2026-10-21). Each phase is one milestone and is delivered by one pull request, so the Product Owner (S01) can follow the work step by step.
## Planning Assumptions
- Week 1 starts 2026-10-14; the plan ends by 2026-10-21, per the Business Case constraint.
- One phase takes one day; the last phase (documentation and publication) has three days because the wiki exists in three languages and the screenshots need the finished program.
- The baseline documents (Business Case, Stakeholder Analysis, Project Plan, use case documents, ADRs) are accepted before MIL-001 starts, in a pull request of their own.
- Phases 2 to 5 follow the four steps of the course assignment in order; phase 6 is the Product Owner's extra.
- S01 is owner and approving reviewer of every phase; in autonomous mode the AI acts as stand-in and the review records say so.
## Gateway Schedule
| Gateway | Document | Window | Decision date | Owner | Stories | Main deliverable | Milestone |
| --- | --- | --- | --- | --- | --- | --- | --- |
| Project foundation | [MIL-001] | 2026-10-14 | 2026-10-14 | S01 | none | pyproject, gitignore, skeleton, Doxyfile, first README, word list | |
| Step 1 - User interface | [MIL-002] | 2026-10-15 | 2026-10-15 | S01 | US-001.01 | The window with card and buttons | |
| Step 2 - New flash cards | [MIL-003] | 2026-10-16 | 2026-10-16 | S01 | US-001.02 | Random cards from the word list | |
| Step 3 - Flip the cards | [MIL-004] | 2026-10-17 | 2026-10-17 | S01 | US-001.03 | Flip after 3000 ms | |
| Step 4 - Save progress | [MIL-005] | 2026-10-18 | 2026-10-18 | S01 | US-001.04 | words_to_learn.csv | |
| Spoken Malay word | [MIL-006] | 2026-10-19 | 2026-10-19 | S01 | US-001.05 | Text to speech as optional extra | |
| Documentation and publication | [MIL-007] | 2026-10-19 to 2026-10-21 | 2026-10-21 | S01 | none | README, screenshots, wiki in 3 languages, description and topics | |
```plantuml
@startgantt
Project starts 2026-10-14
[Foundation] starts 2026-10-14 and ends 2026-10-14
[Step 1 UI] starts 2026-10-15 and ends 2026-10-15
[Step 2 Cards] starts 2026-10-16 and ends 2026-10-16
[Step 3 Flip] starts 2026-10-17 and ends 2026-10-17
[Step 4 Progress] starts 2026-10-18 and ends 2026-10-18
[Speech] starts 2026-10-19 and ends 2026-10-19
[Documentation] starts 2026-10-19 and ends 2026-10-21
[Foundation Go/No-Go] happens 2026-10-14
[Step 1 Go/No-Go] happens 2026-10-15
[Step 2 Go/No-Go] happens 2026-10-16
[Step 3 Go/No-Go] happens 2026-10-17
[Step 4 Go/No-Go] happens 2026-10-18
[Speech Go/No-Go] happens 2026-10-19
[Documentation Go/No-Go] happens 2026-10-21
@endgantt
```
## Scope Coverage
| Business Case scope item | Gateway |
| --- | --- |
| Tkinter program with the assignment's function names | MIL-002, MIL-003, MIL-004, MIL-005 |
| Reading `data/ms-da.csv` | MIL-003 |
| Saving and using `words_to_learn.csv` | MIL-005 |
| Optional spoken Malay word | MIL-006 |
| `pyproject.toml`, `.gitignore`, `Doxyfile`, `.venv` instructions, `pytest`, `constants.py` | MIL-001 |
| README, screenshots, wiki in three languages | MIL-007 |
| Repository description and topics | MIL-007 |
| Framework documents of the baseline | Baseline pull request before MIL-001 |
## Dependencies
```
Baseline → MIL-001 → MIL-002 → MIL-003 → MIL-004 → MIL-005 → MIL-006 → MIL-007
```
A No-Go on a phase moves every later date by the days the rework takes; the buffer is the 2026-10-20 working day, which has no phase of its own.
## Plan Risks
| Risk | Impact | Mitigation |
| --- | --- | --- |
| No display on the machine that runs the review, so the e2e tests skip | Window behaviour is checked by the view model tests only | The review record states whether the e2e tests ran; the screenshots in MIL-007 prove the window on a machine with a display |
| The git host's CI is not available | The publish workflows cannot run | Milestones are published with `sync-project.sh` and the wiki by SSH push (MIL-007) |
| The speech extra cannot be installed on the build machine | MIL-006 cannot be demonstrated end to end | The adapter is tested with fakes; the manual check is recorded as not done |
## Open Issues
- No Governance document (GOV): see ADR-0003. S01 is the only approver.
- The git host's `sync-milestones` workflow is not installed; whether to install it is S01's decision.
---
[BC-001]: ./business-case.md
[SA-001]: ./stakeholder-analysis.md
[US-001]: ./user-stories.md
[MIL-001]: ./milestones/mil-001-foundation.md
[MIL-002]: ./milestones/mil-002-step1-user-interface.md
[MIL-003]: ./milestones/mil-003-step2-new-flash-cards.md
[MIL-004]: ./milestones/mil-004-step3-flip-cards.md
[MIL-005]: ./milestones/mil-005-step4-save-progress.md
[MIL-006]: ./milestones/mil-006-malay-speech.md
[MIL-007]: ./milestones/mil-007-documentation-and-publication.md
[c3fbcbc]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/c3fbcbcfaf799e0ae34aed7e14d3bc8a62f03db3
# Project Plan: Flash Card
## Metadata
| Key | Value |
| --- | --- |
| ID | PP-001 |
| CrossReference | [BC-001], [SA-001], [US-001], [MIL-001], [MIL-002], [MIL-003], [MIL-004], [MIL-005], [MIL-006], [MIL-007], [MIL-008], [MIL-009], [MIL-010], [MIL-011], [MIL-012], [MIL-013] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Deprecated | Jens Tirsvad Nielsen | AI as stand-in for S01 | Added gateway MIL-012 Release v0.2.0 (new request of S01) | [0264b60] |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Added gateway MIL-013 Container checks (new request of S01) | [f86bc91] |
---
## Purpose
This plan schedules the seven phases (gateways) that deliver the flash card program inside the delivery window of one week that the Business Case sets as a constraint (2026-10-14 to 2026-10-21). Each phase is one milestone and is delivered by one pull request, so the Product Owner (S01) can follow the work step by step.
## Planning Assumptions
- Week 1 starts 2026-10-14; the plan ends by 2026-10-21, per the Business Case constraint.
- One phase takes one day; the last phase (documentation and publication) has three days because the wiki exists in three languages and the screenshots need the finished program.
- The baseline documents (Business Case, Stakeholder Analysis, Project Plan, use case documents, ADRs) are accepted before MIL-001 starts, in a pull request of their own.
- Phases 2 to 5 follow the four steps of the course assignment in order; phase 6 is the Product Owner's extra.
- S01 is owner and approving reviewer of every phase; in autonomous mode the AI acts as stand-in and the review records say so.
## Gateway Schedule
| Gateway | Document | Window | Decision date | Owner | Stories | Main deliverable | Milestone |
| --- | --- | --- | --- | --- | --- | --- | --- |
| Project foundation | [MIL-001] | 2026-10-14 | 2026-10-14 | S01 | none | pyproject, gitignore, skeleton, Doxyfile, first README, word list | [Milestone MIL-001][MS-001] |
| Step 1 - User interface | [MIL-002] | 2026-10-15 | 2026-10-15 | S01 | US-001.01 | The window with card and buttons | [Milestone MIL-002][MS-002] |
| Step 2 - New flash cards | [MIL-003] | 2026-10-16 | 2026-10-16 | S01 | US-001.02 | Random cards from the word list | [Milestone MIL-003][MS-003] |
| Step 3 - Flip the cards | [MIL-004] | 2026-10-17 | 2026-10-17 | S01 | US-001.03 | Flip after 3000 ms | [Milestone MIL-004][MS-004] |
| Step 4 - Save progress | [MIL-005] | 2026-10-18 | 2026-10-18 | S01 | US-001.04 | words_to_learn.csv | [Milestone MIL-005][MS-005] |
| Spoken Malay word | [MIL-006] | 2026-10-19 | 2026-10-19 | S01 | US-001.05 | Text to speech as optional extra | [Milestone MIL-006][MS-006] |
| Documentation and publication | [MIL-007] | 2026-10-19 to 2026-10-21 | 2026-10-21 | S01 | none | README, screenshots, wiki in 3 languages, description and topics | [Milestone MIL-007][MS-007] |
| Choose level | [MIL-008] | 2026-10-20 | 2026-10-20 | S01 | US-001.06 | A level choice (100, 1000, all words) before the cards; documents, wiki and screenshots updated | |
| Executable with PyInstaller | [MIL-009] | 2026-10-16 | 2026-10-16 | S01 | US-001.07 | One Windows executable that runs without Python, built by a script; documents, wiki and README updated | |
| Release v0.1.0 | [MIL-010] | 2026-10-16 | 2026-10-16 | S01 | US-001.08 | Tag v0.1.0 and a release with `flash-card.exe`, its checksum and release notes | |
| Menu bar | [MIL-011] | 2026-10-17 | 2026-10-17 | S01 | US-001.09 to US-001.12 | File menu (open word list, change level, reset word list, exit) and About menu (contact); documents, wiki and screenshots updated | |
| Release v0.2.0 | [MIL-012] | 2026-10-18 | 2026-10-18 | S01 | US-001.08 | Version 0.2.0, tag `v0.2.0` and a release with the menu bar, notes and, if the host accepts it, the executable | |
| Container checks | [MIL-013] | 2026-10-19 | 2026-10-19 | S01 | none | A Debian (GNOME) container and Windows Sandbox that run the tests, screenshots and the smoke tests without the host desktop | |
```plantuml
@startgantt
Project starts 2026-10-14
[Foundation] starts 2026-10-14 and ends 2026-10-14
[Step 1 UI] starts 2026-10-15 and ends 2026-10-15
[Step 2 Cards] starts 2026-10-16 and ends 2026-10-16
[Step 3 Flip] starts 2026-10-17 and ends 2026-10-17
[Step 4 Progress] starts 2026-10-18 and ends 2026-10-18
[Speech] starts 2026-10-19 and ends 2026-10-19
[Documentation] starts 2026-10-19 and ends 2026-10-21
[Foundation Go/No-Go] happens 2026-10-14
[Step 1 Go/No-Go] happens 2026-10-15
[Step 2 Go/No-Go] happens 2026-10-16
[Step 3 Go/No-Go] happens 2026-10-17
[Step 4 Go/No-Go] happens 2026-10-18
[Speech Go/No-Go] happens 2026-10-19
[Documentation Go/No-Go] happens 2026-10-21
[Choose level] starts 2026-10-20 and ends 2026-10-20
[Choose level Go/No-Go] happens 2026-10-20
[Executable] starts 2026-10-16 and ends 2026-10-16
[Executable Go/No-Go] happens 2026-10-16
[Release] starts 2026-10-16 and ends 2026-10-16
[Release Go/No-Go] happens 2026-10-16
[Menu bar] starts 2026-10-17 and ends 2026-10-17
[Menu bar Go/No-Go] happens 2026-10-17
[Release 0.2.0] starts 2026-10-18 and ends 2026-10-18
[Release 0.2.0 Go/No-Go] happens 2026-10-18
[Container checks] starts 2026-10-19 and ends 2026-10-19
[Container checks Go/No-Go] happens 2026-10-19
@endgantt
```
## Scope Coverage
| Business Case scope item | Gateway |
| --- | --- |
| Tkinter program with the assignment's function names | MIL-002, MIL-003, MIL-004, MIL-005 |
| Reading `data/ms-da.csv` | MIL-003 |
| Saving and using `words_to_learn.csv` | MIL-005 |
| Optional spoken Malay word | MIL-006 |
| `pyproject.toml`, `.gitignore`, `Doxyfile`, `.venv` instructions, `pytest`, `constants.py` | MIL-001 |
| README, screenshots, wiki in three languages | MIL-007 |
| Repository description and topics | MIL-007 |
| Choice of level (new request after MIL-007) | MIL-008 |
| Executable built with PyInstaller (new request after MIL-008) | MIL-009 |
| Release with the executable attached (new request after MIL-009) | MIL-010 |
| Menu bar with File and About menus (new request after MIL-009) | MIL-011 |
| Release v0.2.0 with the menu bar (new request after MIL-011) | MIL-012 |
| Debian container for tests and headless runs (new request after MIL-012) | MIL-013 |
| Framework documents of the baseline | Baseline pull request before MIL-001 |
## Dependencies
```
Baseline → MIL-001 → MIL-002 → MIL-003 → MIL-004 → MIL-005 → MIL-006 → MIL-007 → MIL-008 → MIL-009 → MIL-010 → MIL-011 → MIL-012 → MIL-013
```
A No-Go on a phase moves every later date by the days the rework takes; MIL-008 was added after MIL-007 and takes the unplanned day 2026-10-20, so no buffer is left inside the window; a No-Go moves the end date past 2026-10-21 and S01 decides whether to accept that.
## Plan Risks
| Risk | Impact | Mitigation |
| --- | --- | --- |
| No display on the machine that runs the review, so the e2e tests skip | Window behaviour is checked by the view model tests only | The review record states whether the e2e tests ran; the screenshots in MIL-007 prove the window on a machine with a display |
| The git host's CI is not available | The publish workflows cannot run | Milestones are published with `sync-project.sh` and the wiki by SSH push (MIL-007) |
| The speech extra cannot be installed on the build machine | MIL-006 cannot be demonstrated end to end | The adapter is tested with fakes; the manual check is recorded as not done |
## Open Issues
- No Governance document (GOV): see ADR-0003. S01 is the only approver.
- The git host's `sync-milestones` workflow is not installed; whether to install it is S01's decision.
---
[BC-001]: ./business-case.md
[SA-001]: ./stakeholder-analysis.md
[US-001]: ./user-stories.md
[MIL-001]: ./milestones/mil-001-foundation.md
[MIL-002]: ./milestones/mil-002-step1-user-interface.md
[MIL-003]: ./milestones/mil-003-step2-new-flash-cards.md
[MIL-004]: ./milestones/mil-004-step3-flip-cards.md
[MIL-005]: ./milestones/mil-005-step4-save-progress.md
[MIL-006]: ./milestones/mil-006-malay-speech.md
[MIL-007]: ./milestones/mil-007-documentation-and-publication.md
[MIL-008]: ./milestones/mil-008-choose-level.md
[MIL-009]: ./milestones/mil-009-executable.md
[MIL-010]: ./milestones/mil-010-release.md
[MIL-011]: ./milestones/mil-011-menu-bar.md
[MIL-012]: ./milestones/mil-012-release-0-2-0.md
[MIL-013]: ./milestones/mil-013-container-checks.md
[MS-001]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/milestone/165
[MS-002]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/milestone/166
[MS-003]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/milestone/167
[MS-004]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/milestone/168
[MS-005]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/milestone/169
[MS-006]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/milestone/170
[MS-007]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/milestone/171
[0264b60]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/0264b6084f26bac5af716ea71596ce3be961fec8
[f86bc91]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/f86bc9136e7719fbcd049a4f803959019b7d2df3
+64
View File
@@ -0,0 +1,64 @@
# RC-027: Review of PY-MIL-005
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-027 |
| CrossReference | [PY-MIL-005], [QC-PY-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [8dbaaa3] |
---
## Artifact Under Review
- Instance reviewed: [PY-MIL-005]
- Checklist used: [QC-PY-001]
- Scope: full review
- Language and domain: n/a (technical type)
- Language reviewer: none
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Packages, modules, functions, variables, classes and constants follow PEP 8 casing (`snake_case`, `PascalCase`, `UPPER_SNAKE`) | Pass | PEP 8 casing holds; ruff rule set N passes. |
| 2 | Names state purpose in the domain's language; no unexplained abbreviations, no single-letter names outside tiny scopes | Pass | Names are the dictionary's IT terms and the assignment's (`is_known`, `mark_known`, `ProgressRepository`). |
| 3 | Code is produced by the project's formatter and passes its linter with no unexplained suppressions | Pass | `ruff check` and `ruff format --check` pass on 47 files with no suppressions; `[tool.ruff.format] line-ending = "lf"` and `.gitattributes` fix the line endings. |
| 4 | Every function and method signature is type-annotated, including `-> None` | Pass | Every signature is annotated; `mypy --strict` passes on 33 source files. |
| 5 | No bare `except:`, no swallowed exceptions; specific exceptions are raised and the cause is kept (`raise ... from`) | Pass | A malformed progress file raises `VocabularyFormatError` and is never overwritten; the temporary file is removed when a write fails (re-raise, no swallow); no bare `except`. |
| 6 | No mutable default arguments and no shadowed builtins | Pass | No mutable defaults, no builtin shadowed. |
| 7 | Files, locks and connections are managed with context managers | Pass | Reading uses `with`; the write goes through a temporary file that is replaced atomically. |
| 8 | Public modules, classes and functions have docstrings that say what, not how | Pass | New and changed members have Doxygen docstrings; `doxygen Doxyfile` ends with 0 warnings. |
| 9 | Logging uses `logging`, not `print`; no secrets or personal data in log output | Pass | No `print`; no secret or personal data is logged. |
| 10 | Classes and operations trace to the Design Class Diagram they implement; deviations are recorded | Pass | `ProgressRepository`, `CsvProgressRepository`, `StudySession.mark_known` and `is_known` are in DCD-001 and OC-001 (`markKnown`); `open_study_session` takes no speech port until MIL-006, as DCD-001 shows for the final design. |
| 11 | Tests exist for new behaviour, are named for the behaviour, and do not depend on order or the network | Pass | 107 tests (6 consecutive full runs all green) include the assignment's 3 record example, restart, round trip, finished state and e2e on the real window over `tmp_path`; none uses the network. |
| 12 | Type checker runs in strict mode without errors; `Any` is justified in a comment | Pass | `mypy --strict` reports no issue; no `Any`. |
| 13 | Dependencies are declared and pinned in the project's dependency file, none unused | Pass | `dependencies` stays empty. |
| 14 | Each piece of knowledge (a business rule, constant, format, validation or query) is defined in one place; code is merged only where it expresses the same knowledge, not where it merely looks alike | Pass | Reader and writer share `CSV_DELIMITER`, `CSV_ENCODING` and the row width in `csv_word_list.py`; the removal rule is only in `Deck.remove`. |
| 15 | Imports point inward: business-rule modules import no framework, database, UI or delivery-mechanism code, and there are no import cycles | Pass | `lint-imports` reports `Layers point inward` kept; the `ProgressRepository` Protocol is in `domain`, its adapter in `infrastructure`. |
| 16 | SOLID holds: a class or module has one reason to change; new behaviour is added by extension, not by editing a type test in several places; subclasses honour the contract of their base; protocols are narrow; high-level code depends on protocols or abstract types and receives its implementations | Pass | The use case depends on the Protocol and receives the adapter; the view model sequences two session calls only. |
| 17 | Source is laid out in the layers and folders of the clean architecture folder structure (`domain`, `application`, `infrastructure`, `presentation` packages under `src/`, and `unit`, `integration` and `e2e` under `tests/`), in `snake_case`, and imports between the layers point inward | Pass | New files are in the layer folders of the clean-architecture skill; tests in `unit`, `integration`, `e2e`. |
| 18 | File and folder names are English, contain no space and no character outside letters, digits, `-`, `_` and `.`, and follow the casing of the language for files | Pass | File and folder names follow the rule. |
## Overall Verdict
Go — every Mandatory criterion passes. Reviewed by AI as stand-in for S01; not independent of the author.
Milestone MIL-005 Go criteria: 1 the 3 record example leaves the other two cards in order with the header (integration test); 2 a start uses the progress file when it exists and the word list otherwise (integration test); 3 the wrong button never writes (unit and e2e); 4 the last card known gives a finished state (unit); 5 a malformed progress file raises `VocabularyFormatError` and stays untouched (unit); 6 round trip readable as a word list (integration); 7 this record, `pytest` 107 passed. A manual run on a copy of `ms-da.csv` removed the known word and wrote 999 cards. Defect found and fixed in this milestone: a flaky `TclError` caused by pytest's descriptor capture and Tcl file handles; the view now loads image bytes with `Path.read_bytes()` and `PhotoImage(data=...)`. All Go.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| none | - | - |
---
[PY-MIL-005]: ../../../src/flash_card
[QC-PY-001]: ../../../framework/qc/code/qc-programming-python.md
[8dbaaa3]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/8dbaaa30595a3650bc85006a2188f81ab903125e
+64
View File
@@ -0,0 +1,64 @@
# RC-028: Review of PY-MIL-006
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-028 |
| CrossReference | [PY-MIL-006], [QC-PY-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [b3c5116] |
---
## Artifact Under Review
- Instance reviewed: [PY-MIL-006]
- Checklist used: [QC-PY-001]
- Scope: full review
- Language and domain: n/a (technical type)
- Language reviewer: none
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Packages, modules, functions, variables, classes and constants follow PEP 8 casing (`snake_case`, `PascalCase`, `UPPER_SNAKE`) | Pass | PEP 8 casing holds; ruff rule set N passes. |
| 2 | Names state purpose in the domain's language; no unexplained abbreviations, no single-letter names outside tiny scopes | Pass | Names are the DCD-001 IT terms (`SpeechPort`, `GttsSpeech`, `NullSpeech`, `build_speech`). |
| 3 | Code is produced by the project's formatter and passes its linter with no unexplained suppressions | Pass | `ruff check` and `ruff format --check` pass on 55 files with no suppressions. |
| 4 | Every function and method signature is type-annotated, including `-> None` | Pass | Every signature is annotated; `mypy --strict` passes on 38 source files; third-party modules are imported with `importlib.import_module`, so no `type: ignore` is needed. |
| 5 | No bare `except:`, no swallowed exceptions; specific exceptions are raised and the cause is kept (`raise ... from`) | Pass | The one broad `except Exception` in `GttsSpeech` is at the thread boundary, is commented, and logs with `exc_info`; it is not silent. No bare `except`. |
| 6 | No mutable default arguments and no shadowed builtins | Pass | No mutable defaults, no builtin shadowed. |
| 7 | Files, locks and connections are managed with context managers | Pass | Audio is written to a `tempfile.TemporaryDirectory` used as a context manager, so the file is always removed. |
| 8 | Public modules, classes and functions have docstrings that say what, not how | Pass | New members have Doxygen docstrings; `doxygen Doxyfile` ends with 0 warnings. |
| 9 | Logging uses `logging`, not `print`; no secrets or personal data in log output | Pass | Failures are logged with `logging`, not printed; only the spoken text (a word) is in the log context, no personal data. |
| 10 | Classes and operations trace to the Design Class Diagram they implement; deviations are recorded | Pass | `SpeechPort`, `GttsSpeech`, `NullSpeech`, `open_study_session(vocabulary_repository, progress_repository, speech, choose)` and `build_speech` match DCD-001 and SD-001 (the `speak` message of `startStudySession` and `markUnknown`). |
| 11 | Tests exist for new behaviour, are named for the behaviour, and do not depend on order or the network | Pass | 124 tests (3 consecutive runs green) with fakes for the synthesiser and player; no test uses the network or plays a sound. |
| 12 | Type checker runs in strict mode without errors; `Any` is justified in a comment | Pass | `mypy --strict` reports no issue; no `Any`. |
| 13 | Dependencies are declared and pinned in the project's dependency file, none unused | Pass | `dependencies` is still empty; the extra `speech` pins `playsound==1.2.2` and `gTTS>=2.5`, and no module imports them outside `GttsSpeech`. |
| 14 | Each piece of knowledge (a business rule, constant, format, validation or query) is defined in one place; code is merged only where it expresses the same knowledge, not where it merely looks alike | Pass | The speak rule is only in `StudySession.next_card`; the unused `SPEECH_LANGUAGE_CODE` constant was removed. |
| 15 | Imports point inward: business-rule modules import no framework, database, UI or delivery-mechanism code, and there are no import cycles | Pass | `lint-imports` reports `Layers point inward` kept; the port is in `application`, the adapters in `infrastructure`, the choice in the composition root. |
| 16 | SOLID holds: a class or module has one reason to change; new behaviour is added by extension, not by editing a type test in several places; subclasses honour the contract of their base; protocols are narrow; high-level code depends on protocols or abstract types and receives its implementations | Pass | `StudySession` depends on the `SpeechPort` Protocol and receives the adapter; `NullSpeech` honours the same contract (Null Object), so no `if speech` test exists. |
| 17 | Source is laid out in the layers and folders of the clean architecture folder structure (`domain`, `application`, `infrastructure`, `presentation` packages under `src/`, and `unit`, `integration` and `e2e` under `tests/`), in `snake_case`, and imports between the layers point inward | Pass | `application/ports/` and `infrastructure/speech/` follow the folder structure of the clean-architecture skill. |
| 18 | File and folder names are English, contain no space and no character outside letters, digits, `-`, `_` and `.`, and follow the casing of the language for files | Pass | File and folder names follow the rule. |
## Overall Verdict
Go — every Mandatory criterion passes. Reviewed by AI as stand-in for S01; not independent of the author.
Milestone MIL-006 Go criteria: 1 `speak(text, front_code)` once per drawn card and never when empty (unit tests); 2 `gtts` and `playsound` imported only when speaking, temporary file removed (unit tests with fakes); 3 service or player failure is logged and not raised (unit tests with caplog); 4 `build_speech` returns `NullSpeech` when the extra is missing or `--no-speech` is given (unit tests); 5 `dependencies` empty, extra pins `playsound==1.2.2` (pyproject.toml); 6 `speak` returns before a blocked player is released (unit test with an Event); 7 this record, `pytest` 124 passed. A manual check with the extra installed synthesised an mp3 of `kata` in Malay (7872 bytes) and `build_speech(True)` returned `GttsSpeech`; the audio was not played on this machine. All Go.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| none | - | - |
---
[PY-MIL-006]: ../../../src/flash_card
[QC-PY-001]: ../../../framework/qc/code/qc-programming-python.md
[b3c5116]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/b3c51161107b4cdcbc4c5334e28608423a299638
+64
View File
@@ -0,0 +1,64 @@
# RC-029: Review of PY-MIL-007
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-029 |
| CrossReference | [PY-MIL-007], [QC-PY-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [9289426] |
---
## Artifact Under Review
- Instance reviewed: [PY-MIL-007]
- Checklist used: [QC-PY-001]
- Scope: full review
- Language and domain: n/a (technical type)
- Language reviewer: none
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Packages, modules, functions, variables, classes and constants follow PEP 8 casing (`snake_case`, `PascalCase`, `UPPER_SNAKE`) | Pass | PEP 8 casing holds in `tools/capture_screenshots.py` and the changed view; ruff rule set N passes. |
| 2 | Names state purpose in the domain's language; no unexplained abbreviations, no single-letter names outside tiny scopes | Pass | Names state purpose (`capture`, `_make_dpi_aware`, `SCREENSHOT_SEED`). |
| 3 | Code is produced by the project's formatter and passes its linter with no unexplained suppressions | Pass | `ruff check` and `ruff format --check` pass on 56 files; the one `type: ignore` is for a Windows-only attribute and says which error it silences. |
| 4 | Every function and method signature is type-annotated, including `-> None` | Pass | Every signature is annotated; `mypy --strict` passes on `src` (38 files) and on both tool scripts. |
| 5 | No bare `except:`, no swallowed exceptions; specific exceptions are raised and the cause is kept (`raise ... from`) | Pass | No exception handling was added. |
| 6 | No mutable default arguments and no shadowed builtins | Pass | No mutable defaults, no builtin shadowed. |
| 7 | Files, locks and connections are managed with context managers | Pass | The data copy uses `tempfile.TemporaryDirectory` as a context manager; the Tk root is destroyed. |
| 8 | Public modules, classes and functions have docstrings that say what, not how | Pass | Module, functions and constants have Doxygen comments; `doxygen Doxyfile` ends with 0 warnings. |
| 9 | Logging uses `logging`, not `print`; no secrets or personal data in log output | Pass | The tool writes the two output paths with `sys.stdout.write`; no `print`, no secret. |
| 10 | Classes and operations trace to the Design Class Diagram they implement; deviations are recorded | Pass | The only source change is the button background in `FlashCardView`, which follows `wireframe.md`; the tool is outside the design classes and is not part of the program. |
| 11 | Tests exist for new behaviour, are named for the behaviour, and do not depend on order or the network | Pass | 125 tests, 2 consecutive full runs green; one e2e assertion was added for the button background; the tool is checked by running it and reading both images. |
| 12 | Type checker runs in strict mode without errors; `Any` is justified in a comment | Pass | `mypy --strict` reports no issue on the touched files; no `Any`. |
| 13 | Dependencies are declared and pinned in the project's dependency file, none unused | Pass | `dependencies` stays empty; Pillow is the optional extra `tools` and is imported only by the tool. |
| 14 | Each piece of knowledge (a business rule, constant, format, validation or query) is defined in one place; code is merged only where it expresses the same knowledge, not where it merely looks alike | Pass | The seed, output folder and delay come from one definition each; the delay is `FLIP_DELAY_MS`. |
| 15 | Imports point inward: business-rule modules import no framework, database, UI or delivery-mechanism code, and there are no import cycles | Pass | `lint-imports` reports `Layers point inward` kept; the tool imports the composition root only. |
| 16 | SOLID holds: a class or module has one reason to change; new behaviour is added by extension, not by editing a type test in several places; subclasses honour the contract of their base; protocols are narrow; high-level code depends on protocols or abstract types and receives its implementations | Pass | The tool has one purpose (capture); the view change adds no rule. |
| 17 | Source is laid out in the layers and folders of the clean architecture folder structure (`domain`, `application`, `infrastructure`, `presentation` packages under `src/`, and `unit`, `integration` and `e2e` under `tests/`), in `snake_case`, and imports between the layers point inward | Pass | `tools/` holds helper scripts outside `src/`; the layers are unchanged. |
| 18 | File and folder names are English, contain no space and no character outside letters, digits, `-`, `_` and `.`, and follow the casing of the language for files | Pass | File and folder names follow the rule (`docs/images`, `docs/wiki` pages are exceptions for wiki names). |
## Overall Verdict
Go — every Mandatory criterion passes. Reviewed by AI as stand-in for S01; not independent of the author.
Milestone MIL-007 Go criteria: 1 `check-readme.sh` exit 0 and both screenshots linked from the README; 2 `docs/wiki/` holds Home, Install, Usage and Architecture as `<Page>.md`, `<Page>-da.md`, `<Page>-ms.md` (12 pages) and `_Sidebar.md` listing the three languages; 3 the screenshots are captured from the running program by `tools/capture_screenshots.py` and were inspected; 4 the README Setup and Run need 5 commands (create `.venv`, activate, upgrade pip, install, run); 5 the repository has a description and 10 topics (read back from the API); 6 `doxygen Doxyfile` 0 warnings; 7 `docs/sqa/traceability-matrix.md` has a row for every created artifact with its latest `RC-*`, and the plan links each milestone; 8 `check-languages.sh` exit 0 (`check-plan.sh` is a commit-message hook and was not run). The wiki is pushed to the host's wiki after this merge. The Danish and Malay wiki pages were written by the AI and have not been read by a native speaker; this is stated in the end-of-run summary. All Go.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| none | - | - |
---
[PY-MIL-007]: ../../../tools
[QC-PY-001]: ../../../framework/qc/code/qc-programming-python.md
[9289426]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/92894268c51ec77d56cff48d968566e6265795a2
@@ -0,0 +1,70 @@
# RC-030: Review of BC-001
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-030 |
| CrossReference | [BC-001], [QC-BC-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [0b983b7] |
---
## Artifact Under Review
- Instance reviewed: [BC-001]
- Checklist used: [QC-BC-001], and [QC-LANG-001] (language and domain)
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in for S01 reads the language and knows the domain)
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | ROI/Cost-Benefit analysis is quantitative, or where qualitative, is explicitly justified | Pass | The Cost-Benefit table is qualitative and says why: no revenue is expected, so a quantitative return does not apply. |
| 2 | Risks are identified with documented impact and mitigation | Pass | The Risks table has 5 risks, each with an impact and a mitigation. |
| 3 | Success criteria are measurable, stating explicit targets rather than vague aspirations | Pass | The Success Criteria table has 8 rows with numeric targets and a measure each (for example 0 third-party packages; 5 commands or fewer). |
| 4 | Scope explicitly separates In Scope vs Out of Scope | Pass | Scope has `### In Scope` and `### Out of Scope` subsections. |
| 5 | Stakeholders are cross-referenced to Stakeholder Analysis IDs rather than re-described inline | Pass | The Stakeholders table cites S01, S02 and S03 and does not re-describe their roles. |
| 6 | Methodology and quality-standard foundation are stated explicitly (e.g. ISO/IEC 25010, Larman) | Pass | Methodological and Standards Foundation names the framework, Larman, ISO/IEC 25010:2023 and PEP 8. |
| 7 | Assumptions and constraints are explicit and clearly distinguished from one another | Pass | Assumptions and Constraints are separate sections. |
| 8 | Document supports executive decision-making with a clear, unambiguous recommendation | Pass | Recommendation reads `Proceed` with a one-sentence rationale. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Metadata of BC-001 has `Language | en` and `Domain | it`; neither is a placeholder. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code and `it` is a value of the registry's domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | Prose and table cells are English; Malay and Danish words and file names appear only as quoted data. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | The registry gives `IT Executive English` for this type; the text is written for that reader. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The PO terms of DICT-001 (flash card, word list, words to learn, study session) are used and no synonym replaces them. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists beside the document (checked in `docs/`). |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no change of language or domain since an earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer is the stand-in for S01, the Product Owner, who reads English and knows the IT domain; no second language reviewer is needed (review-checklist-process step 2). Open to challenge by S01 in the end-of-run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | CSV, MVVM, UI, PO and similar abbreviations are not all spelled out at first use; Optional, deferred. |
## Overall Verdict
Go — every Mandatory criterion passes; the failed Optional criteria are deferred with an action item. Reviewed by AI as stand-in for S01; not independent of the author.
Full review (not a delta) after the level choice was added for MIL-008.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Criterion LANG 10 (Optional) failed: Abbreviations are spelled out on first use, in the stated language; fix or accept the deferral | S01 | 2026-10-21 |
---
[BC-001]: ../../../docs/business-case.md
[QC-BC-001]: ../../../framework/qc/artifacts/qc-business-case.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[0b983b7]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/0b983b7fdadf6958717c1d0227d0f2ebe037f7b1
@@ -0,0 +1,70 @@
# RC-031: Review of US-001
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-031 |
| CrossReference | [US-001], [QC-US-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [0b983b7] |
---
## Artifact Under Review
- Instance reviewed: [US-001]
- Checklist used: [QC-US-001], and [QC-LANG-001] (language and domain)
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in for S01 reads the language and knows the domain)
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Follows INVEST criteria (Independent, Negotiable, Valuable, Estimable, Small, Testable) | Pass | INVEST Check section confirms the six properties for all six stories and states one dependency exception. |
| 2 | Written in "As a / I want / So that" form | Pass | All six stories use `As a / I want / so that`. |
| 3 | Clear, testable acceptance criteria are included | Pass | Every story, including US-001.06, has Given/When/Then acceptance criteria. |
| 4 | Traceable to a use case or epic | Pass | Every story traces to a milestone and to UC-001. |
| 5 | Story is sized to fit within a single iteration | Pass | Each story is one milestone, which fits one iteration. |
| 6 | Story statement avoids technical implementation detail | Fail | Acceptance criteria name `words_to_learn.csv`, `ms-da.csv` and 3000 ms, which are assignment-mandated names and values rather than pure behaviour. |
| 7 | Role named in the story matches an actor defined in the Use Case Diagram | Pass | The role `Learner` is the actor of UCD-001. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Metadata of US-001 has `Language | en` and `Domain | it`; neither is a placeholder. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code and `it` is a value of the registry's domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | Prose and table cells are English; Malay and Danish words and file names appear only as quoted data. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | The registry gives `IT Professional English` for this type; the text is written for that reader. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The PO terms of DICT-001 (flash card, word list, words to learn, study session) are used and no synonym replaces them. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists beside the document (checked in `docs/`). |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no change of language or domain since an earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer is the stand-in for S01, the Product Owner, who reads English and knows the IT domain; no second language reviewer is needed (review-checklist-process step 2). Open to challenge by S01 in the end-of-run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | CSV, MVVM, UI, PO and similar abbreviations are not all spelled out at first use; Optional, deferred. |
## Overall Verdict
Go — every Mandatory criterion passes; the failed Optional criteria are deferred with an action item. Reviewed by AI as stand-in for S01; not independent of the author.
Full review (not a delta) after the level choice was added for MIL-008.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Criterion 6 (Optional) failed: Story statement avoids technical implementation detail; fix or accept the deferral | S01 | 2026-10-21 |
| Criterion LANG 10 (Optional) failed: Abbreviations are spelled out on first use, in the stated language; fix or accept the deferral | S01 | 2026-10-21 |
---
[US-001]: ../../../docs/user-stories.md
[QC-US-001]: ../../../framework/qc/artifacts/qc-user-story.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[0b983b7]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/0b983b7fdadf6958717c1d0227d0f2ebe037f7b1
@@ -0,0 +1,54 @@
# RC-032: Review of PP-001
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-032 |
| CrossReference | [PP-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [0b983b7] |
---
## Artifact Under Review
- Instance reviewed: [PP-001]
- Checklist used: none exists for this type, and [QC-LANG-001] (language and domain)
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in for S01 reads the language and knows the domain)
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Metadata of PP-001 has `Language | en` and `Domain | it`; neither is a placeholder. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code and `it` is a value of the registry's domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | Prose and table cells are English; Malay and Danish words and file names appear only as quoted data. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | The registry gives `IT Executive English` for this type; the text is written for that reader. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The PO terms of DICT-001 (flash card, word list, words to learn, study session) are used and no synonym replaces them. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists beside the document (checked in `docs/`). |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no change of language or domain since an earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer is the stand-in for S01, the Product Owner, who reads English and knows the IT domain; no second language reviewer is needed (review-checklist-process step 2). Open to challenge by S01 in the end-of-run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | CSV, MVVM, UI, PO and similar abbreviations are not all spelled out at first use; Optional, deferred. |
## Overall Verdict
Go — no checklist exists for the Project Plan type; the plan now schedules MIL-008 on 2026-10-20 inside the Business Case constraint (delivery by 2026-10-21) and the language checklist passes. Accepted as the Product Owner's stand-in, after the Product Owner accepted the MIL-008 plan in chat. Reviewed by AI as stand-in for S01; not independent of the author.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Criterion LANG 10 (Optional) failed: Abbreviations are spelled out on first use, in the stated language; fix or accept the deferral | S01 | 2026-10-21 |
---
[PP-001]: ../../../docs/project-plan.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[0b983b7]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/0b983b7fdadf6958717c1d0227d0f2ebe037f7b1
+74
View File
@@ -0,0 +1,74 @@
# RC-033: Review of UC-001
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-033 |
| CrossReference | [UC-001], [QC-UC-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [0b983b7] |
---
## Artifact Under Review
- Instance reviewed: [UC-001]
- Checklist used: [QC-UC-001], and [QC-LANG-001] (language and domain)
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in for S01 reads the language and knows the domain)
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Consists of a single, concise paragraph summarizing only the primary success scenario | N-A | The format is Fully Dressed; the Brief format criterion does not apply. |
| 2 | Written as an informal multi-paragraph narrative; may mention some alternate flows without formal structure | N-A | The format is Fully Dressed; the Casual format criterion does not apply. |
| 3 | All standard sections are present: actors, preconditions, postconditions, main success scenario, alternative/exception flows | Pass | Scope, level, actor, stakeholders, pre- and postconditions, main success scenario and extensions are present. |
| 4 | Preconditions and postconditions are explicitly defined | Pass | Preconditions and postconditions are listed. |
| 5 | Primary actor is explicitly stated | Pass | Primary actor is `Learner`. |
| 6 | Stakeholders and their interests are stated | Pass | Stakeholders S01 and S02 and their interests are stated. |
| 7 | Main success scenario is written as clear, numbered steps | Pass | Main success scenario has 9 numbered steps, including the level choice (steps 2 and 3). |
| 8 | Alternative/exception flows correctly reference `<<include>>`/`<<extend>>` use cases where relevant, per UML 2.5.1 | Pass | UCD-001 has no include or extend relationship, so no extension needs to reference one; the extensions (3a, 4a, 5a, 7a, 7b, 9a) are plain alternative flows. |
| 9 | Explicit business rules are captured per step where applicable, rather than embedded loosely in narrative text | Pass | The Business Rules table gives a rule per step. |
| 10 | Naming of actors and use case title is consistent with the corresponding Use Case Diagram and User Stories | Pass | Title and actor match UCD-001 and US-001; the level step matches US-001.06. |
| 11 | Scope/level (e.g. summary, user-goal, subfunction) is explicitly stated | Pass | `Level: user-goal` and `Scope: Flash Card program`. |
| 12 | Use case is written from the actor's goal perspective, free of UI or implementation detail | Pass | Steps are written as goals and answers; buttons, files and milliseconds are in the wireframe and milestones. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Metadata of UC-001 has `Language | en` and `Domain | it`; neither is a placeholder. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code and `it` is a value of the registry's domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | Prose and table cells are English; Malay and Danish words and file names appear only as quoted data. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | The registry gives `IT Professional English` for this type; the text is written for that reader. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The PO terms of DICT-001 (flash card, word list, words to learn, study session) are used and no synonym replaces them. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists beside the document (checked in `docs/`). |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no change of language or domain since an earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer is the stand-in for S01, the Product Owner, who reads English and knows the IT domain; no second language reviewer is needed (review-checklist-process step 2). Open to challenge by S01 in the end-of-run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | CSV, MVVM, UI, PO and similar abbreviations are not all spelled out at first use; Optional, deferred. |
## Overall Verdict
Go — every Mandatory criterion passes; the failed Optional criteria are deferred with an action item. Reviewed by AI as stand-in for S01; not independent of the author.
Full review (not a delta) after the level choice was added for MIL-008.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Criterion LANG 10 (Optional) failed: Abbreviations are spelled out on first use, in the stated language; fix or accept the deferral | S01 | 2026-10-21 |
---
[UC-001]: ../../../docs/uc-001/uc.md
[QC-UC-001]: ../../../framework/qc/artifacts/qc-use-case.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[0b983b7]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/0b983b7fdadf6958717c1d0227d0f2ebe037f7b1
@@ -0,0 +1,69 @@
# RC-034: Review of DM-001
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-034 |
| CrossReference | [DM-001], [QC-DM-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [0b983b7] |
---
## Artifact Under Review
- Instance reviewed: [DM-001]
- Checklist used: [QC-DM-001], and [QC-LANG-001] (language and domain)
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in for S01 reads the language and knows the domain)
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Uses ubiquitous/business language throughout; no technical or implementation jargon (e.g. no "table", "class", "pointer") | Pass | Concepts are Flash Card, Word List, Words To Learn, Level and Study Session; no table or class names. |
| 2 | Multiplicities on associations are correct and complete (e.g. `1..*`, `0..1`) | Pass | Association table gives both multiplicities for all 7 associations. |
| 3 | No operation/method signatures shown — attributes and associations only | Pass | The diagram has attributes and associations only. |
| 4 | Associations are named with an unambiguous reading direction | Pass | Every association is named with a reading direction (`holds`, `works through`, `is limited to`, `takes the first words of`). |
| 5 | Generalization/specialization used correctly, reflecting true "is-a" relationships, not misused for code reuse | Pass | Generalization table says none exists, and why. |
| 6 | Every concept traces to a noun phrase found in the use cases or glossary | Pass | Concept table gives a source noun phrase in UC-001 for every concept. |
| 7 | Attributes are simple domain data (no foreign-key-like references or object pointers modeled as attributes) | Pass | Attributes are plain data (word, translation, first language, card shown). |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Metadata of DM-001 has `Language | en` and `Domain | it`; neither is a placeholder. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code and `it` is a value of the registry's domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | Prose and table cells are English; Malay and Danish words and file names appear only as quoted data. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | The registry gives `IT Professional English` for this type; the text is written for that reader. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The PO terms of DICT-001 (flash card, word list, words to learn, study session) are used and no synonym replaces them. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists beside the document (checked in `docs/`). |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no change of language or domain since an earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer is the stand-in for S01, the Product Owner, who reads English and knows the IT domain; no second language reviewer is needed (review-checklist-process step 2). Open to challenge by S01 in the end-of-run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | CSV, MVVM, UI, PO and similar abbreviations are not all spelled out at first use; Optional, deferred. |
## Overall Verdict
Go — every Mandatory criterion passes; the failed Optional criteria are deferred with an action item. Reviewed by AI as stand-in for S01; not independent of the author.
Full review (not a delta) after the level choice was added for MIL-008.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Criterion LANG 10 (Optional) failed: Abbreviations are spelled out on first use, in the stated language; fix or accept the deferral | S01 | 2026-10-21 |
---
[DM-001]: ../../../docs/domain-model.md
[QC-DM-001]: ../../../framework/qc/artifacts/qc-domain-model.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[0b983b7]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/0b983b7fdadf6958717c1d0227d0f2ebe037f7b1
@@ -0,0 +1,69 @@
# RC-035: Review of DICT-001
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-035 |
| CrossReference | [DICT-001], [QC-DICT-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [0b983b7] |
---
## Artifact Under Review
- Instance reviewed: [DICT-001]
- Checklist used: [QC-DICT-001], and [QC-LANG-001] (language and domain)
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in for S01 reads the language and knows the domain)
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Every row has a PO term, its language, an IT term and a definition | Pass | All 8 rows have PO term, language, IT term and definition. |
| 2 | Each PO term maps to exactly one IT term and the reverse (no synonyms) | Pass | One IT term per PO term; no synonym appears. |
| 3 | Every Domain Model concept has a row, and the Domain Model uses its PO term | Pass | The 5 concepts of DM-001 have a row (`Level` added) and DM-001 uses the PO term. |
| 4 | The Operation Contracts, Sequence Diagrams, Design Class Diagrams and ERD use the IT term, not the PO term | Pass | DCD-001, OC-001 and SD-001 use `Card`, `Vocabulary`, `Deck`, `StudySession`. |
| 5 | Definitions are written in the PO language and are one sentence | Pass | Definitions are one English sentence each. |
| 6 | "Used as PO term in" and "Used as IT term in" name artifact types that exist in the project | Pass | Artifact types named in both columns exist in the project. |
| 7 | The dictionary's `Language` and `Domain` rows, and the language of every row, match the PO language and domain in the project registry | Pass | `Language | en` and `Domain | it` match the registry; every row says `en`. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Metadata of DICT-001 has `Language | en` and `Domain | it`; neither is a placeholder. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code and `it` is a value of the registry's domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | Prose and table cells are English; Malay and Danish words and file names appear only as quoted data. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | The registry gives `IT Professional English` for this type; the text is written for that reader. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The PO terms of DICT-001 (flash card, word list, words to learn, study session) are used and no synonym replaces them. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists beside the document (checked in `docs/`). |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no change of language or domain since an earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer is the stand-in for S01, the Product Owner, who reads English and knows the IT domain; no second language reviewer is needed (review-checklist-process step 2). Open to challenge by S01 in the end-of-run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | CSV, MVVM, UI, PO and similar abbreviations are not all spelled out at first use; Optional, deferred. |
## Overall Verdict
Go — every Mandatory criterion passes; the failed Optional criteria are deferred with an action item. Reviewed by AI as stand-in for S01; not independent of the author.
Full review (not a delta) after the level choice was added for MIL-008.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Criterion LANG 10 (Optional) failed: Abbreviations are spelled out on first use, in the stated language; fix or accept the deferral | S01 | 2026-10-21 |
---
[DICT-001]: ../../../docs/dictionary.md
[QC-DICT-001]: ../../../framework/qc/artifacts/qc-dictionary.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[0b983b7]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/0b983b7fdadf6958717c1d0227d0f2ebe037f7b1
@@ -0,0 +1,69 @@
# RC-036: Review of SSD-001
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-036 |
| CrossReference | [SSD-001], [QC-SSD-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [0b983b7] |
---
## Artifact Under Review
- Instance reviewed: [SSD-001]
- Checklist used: [QC-SSD-001], and [QC-LANG-001] (language and domain)
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in for S01 reads the language and knows the domain)
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Input/output messages match the corresponding Use Case's main success scenario step-for-step | Pass | System Operations table maps each message to steps of the main success scenario (1 to 9); the timer step is the one stated deviation. |
| 2 | Actor and System are treated strictly as black boxes (system shown as `:System`) | Pass | The system is `:System`; no internal object appears. |
| 3 | Object creation/destruction of the System instance handled explicitly where relevant | Pass | Lifecycle Notes state that the system lives for one run. |
| 4 | Return values are shown for operations that produce one, using dashed return arrows | Pass | Dashed return arrows are drawn for `startStudySession`, `chooseLevel`, the turn-over, `markKnown` and `markUnknown`. |
| 5 | Alternate/exceptional flows are represented separately (or explicitly out of scope noted) | Pass | The Alternate Flows section names extensions 3a, 4a, 5a, 7b and 9a, states that they add no operation, and says they are out of scope. |
| 6 | Message names are verb phrases consistent with the use case's system responsibilities | Pass | `startStudySession`, `markKnown` and `markUnknown` are verb phrases. |
| 7 | Diagram references the specific Use Case (name and ID) it depicts | Pass | Source Use Case section names UC-001 and the scenario. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Metadata of SSD-001 has `Language | en` and `Domain | it`; neither is a placeholder. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code and `it` is a value of the registry's domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | Prose and table cells are English; Malay and Danish words and file names appear only as quoted data. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | The registry gives `IT Professional English` for this type; the text is written for that reader. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The PO terms of DICT-001 (flash card, word list, words to learn, study session) are used and no synonym replaces them. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists beside the document (checked in `docs/`). |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no change of language or domain since an earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer is the stand-in for S01, the Product Owner, who reads English and knows the IT domain; no second language reviewer is needed (review-checklist-process step 2). Open to challenge by S01 in the end-of-run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | CSV, MVVM, UI, PO and similar abbreviations are not all spelled out at first use; Optional, deferred. |
## Overall Verdict
Go — every Mandatory criterion passes; the failed Optional criteria are deferred with an action item. Reviewed by AI as stand-in for S01; not independent of the author.
Full review (not a delta) after the level choice was added for MIL-008.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Criterion LANG 10 (Optional) failed: Abbreviations are spelled out on first use, in the stated language; fix or accept the deferral | S01 | 2026-10-21 |
---
[SSD-001]: ../../../docs/uc-001/ssd.md
[QC-SSD-001]: ../../../framework/qc/artifacts/qc-ssd.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[0b983b7]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/0b983b7fdadf6958717c1d0227d0f2ebe037f7b1
@@ -0,0 +1,53 @@
# RC-037: Review of OC-001
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-037 |
| CrossReference | [OC-001], [QC-OC-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [0b983b7] |
---
## Artifact Under Review
- Instance reviewed: [OC-001]
- Checklist used: [QC-OC-001]
- Scope: full review
- Language and domain: n/a (technical type)
- Language reviewer: none
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Method signature is complete: operation name, parameter types, and return type | Pass | Each contract gives name, parameter list and return type (`startStudySession(): CardDto | None`). |
| 2 | Preconditions explicitly list required state before execution | Pass | Preconditions are listed per contract. |
| 3 | Postconditions explicitly describe resulting state using Larman's "instance created/associated/attribute modified" style | Pass | Postconditions use created / associated / destroyed / attribute set wording. |
| 4 | Exceptions and error conditions are documented, including the triggering precondition failure | Pass | Each contract has an Exceptions table with the failing precondition. |
| 5 | Operation is explicitly traceable to a single SSD message | Pass | Each of the four contracts (`startStudySession`, `chooseLevel`, `markKnown`, `markUnknown`) traces to exactly one SSD message; the timer step has none and says so. |
| 6 | Contract avoids specifying implementation/algorithmic details (declarative, not procedural) | Pass | Postconditions are declarative. |
| 7 | Cross-references the Domain Model classes/associations affected by pre/postconditions | Pass | Domain Model concepts and IT terms are cited per contract. |
## Overall Verdict
Go — every Mandatory criterion passes. Reviewed by AI as stand-in for S01; not independent of the author.
Full review (not a delta) after the level choice was added for MIL-008.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| none | - | - |
---
[OC-001]: ../../../docs/uc-001/oc.md
[QC-OC-001]: ../../../framework/qc/artifacts/qc-operation-contract.md
[0b983b7]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/0b983b7fdadf6958717c1d0227d0f2ebe037f7b1
@@ -0,0 +1,54 @@
# RC-038: Review of SD-001
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-038 |
| CrossReference | [SD-001], [QC-SD-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [0b983b7] |
---
## Artifact Under Review
- Instance reviewed: [SD-001]
- Checklist used: [QC-SD-001]
- Scope: full review
- Language and domain: n/a (technical type)
- Language reviewer: none
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Message passing strictly follows UML sync/async/return arrow syntax | Pass | Calls are solid arrows with dashed returns. |
| 2 | GRASP/GoF patterns applied and explicitly annotated where used (e.g. Controller, Observer, Mediator, Factory) | Pass | Each sequence has a Pattern Annotations table (Creator, Information Expert, Null Object, MVVM, Repository). |
| 3 | Lifelines show activation bars matching actual processing time/call nesting | Pass | Activations are drawn for the session and the view model. |
| 4 | Object creation and destruction shown with correct UML notation (`create`/`destroy` messages, X on lifeline) | Pass | `create` is used for `Deck` and `StudySession`; no object is destroyed during the program's life and that is stated by omission, the process ends. |
| 5 | Diagram realizes the postconditions of a specific Operation Contract | Pass | Each of the four sequences has a Postcondition Coverage table for its contract in OC-001. |
| 6 | Responsibility assignment favors low coupling/high cohesion (no god-object receiving all messages) | Pass | Responsibility Check notes state that no object receives all messages. |
| 7 | Loop, alt, and opt combined fragments used correctly for conditional/repeated behavior | Pass | `alt` and `opt` fragments are used for the progress file and the empty deck. |
| 8 | Each exception of the realized Operation Contract is shown as an `alt` or `opt` fragment, or its absence is justified | Fail | The exceptions of OC-001 (missing file, malformed file) are raised before the sequence starts and are not drawn as `alt` fragments; Optional, deferred. |
## Overall Verdict
Go — every Mandatory criterion passes; the failed Optional criteria are deferred with an action item. Reviewed by AI as stand-in for S01; not independent of the author.
Full review (not a delta) after the level choice was added for MIL-008.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Criterion 8 (Optional) failed: Each exception of the realized Operation Contract is shown as an `alt` or `opt` fragment, ; fix or accept the deferral | S01 | 2026-10-21 |
---
[SD-001]: ../../../docs/uc-001/sd.md
[QC-SD-001]: ../../../framework/qc/artifacts/qc-sequence-diagram.md
[0b983b7]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/0b983b7fdadf6958717c1d0227d0f2ebe037f7b1
@@ -0,0 +1,55 @@
# RC-039: Review of DCD-001
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-039 |
| CrossReference | [DCD-001], [QC-DCD-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [0b983b7] |
---
## Artifact Under Review
- Instance reviewed: [DCD-001]
- Checklist used: [QC-DCD-001]
- Scope: full review
- Language and domain: n/a (technical type)
- Language reviewer: none
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | SOLID principles applied; no god classes with excessive responsibilities | Pass | Each class has one responsibility (Class Table); view, view model, session, deck and adapters are separate. |
| 2 | Visibility markers correct and consistent (`+` public, `-` private, `#` protected) | Pass | Visibility markers are on all members. |
| 3 | Relationships correctly distinguished: Association vs Aggregation vs Composition vs Dependency | Pass | Composition (Vocabulary and Card), aggregation (Deck), composition (LevelViewModel and LevelChoice), association, dependency and realization are distinguished. |
| 4 | Multiplicities and navigability specified on all associations | Pass | Multiplicities are on the associations; dependencies are directed. |
| 5 | Applied design patterns are annotated explicitly (e.g. Singleton, Factory, Strategy) | Pass | Pattern Annotations table lists Repository, Ports and adapters, Null Object, MVVM, Composition root. |
| 6 | Method signatures are traceable to Operation Contracts and/or design Sequence Diagrams | Pass | Method Traceability table maps every operation, including `Level.first`, `Deck.within`, `LevelViewModel.choices` and `LevelView.choose`, to OC-001 and SD-001. |
| 7 | Class names and structure remain consistent with the Domain Model concepts they refine | Pass | The Class Table has a `Refines` column; `Level` refines the concept Level of DM-001; names match the dictionary's IT terms. |
| 8 | No circular dependencies between classes/packages unless explicitly justified | Pass | Dependency Check states there are no cycles. |
| 9 | Dependencies between classes and packages point inward: domain classes do not depend on infrastructure, delivery or framework classes | Pass | Domain imports nothing; infrastructure and presentation point inward (Dependency Check). |
## Overall Verdict
Go — every Mandatory criterion passes. Reviewed by AI as stand-in for S01; not independent of the author.
Full review (not a delta) after the level choice was added for MIL-008.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| none | - | - |
---
[DCD-001]: ../../../docs/dcd.md
[QC-DCD-001]: ../../../framework/qc/artifacts/qc-dcd.md
[0b983b7]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/0b983b7fdadf6958717c1d0227d0f2ebe037f7b1
+66
View File
@@ -0,0 +1,66 @@
# RC-040: Review of MIL-008
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-040 |
| CrossReference | [MIL-008], [QC-MIL-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [0b983b7] |
---
## Artifact Under Review
- Instance reviewed: [MIL-008]
- Checklist used: [QC-MIL-001], and [QC-LANG-001] (language and domain)
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in for S01 reads the language and knows the domain)
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | A concrete deliverable is defined for every gate | Pass | A concrete Deliverable section names the output evaluated at the gate. |
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | The Go / No-Go table has numbered criteria, each with an observable Go and No-Go. |
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Dependencies table names the milestone or documents it needs. |
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Traceability table maps to Business Case objectives and the user story. |
| 5 | Milestone owner and approving reviewer are identified | Pass | Ownership table names S01 as owner and approving reviewer. |
| 6 | Milestone has a defined target date consistent with project constraints | Pass | Target Date lies inside the 2026-10-14 to 2026-10-21 window of the Business Case. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Metadata of MIL-008 has `Language | en` and `Domain | it`; neither is a placeholder. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code and `it` is a value of the registry's domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | Prose and table cells are English; Malay and Danish words and file names appear only as quoted data. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | The registry gives `IT Executive English` for this type; the text is written for that reader. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The PO terms of DICT-001 (flash card, word list, words to learn, study session) are used and no synonym replaces them. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists beside the document (checked in `docs/`). |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no change of language or domain since an earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer is the stand-in for S01, the Product Owner, who reads English and knows the IT domain; no second language reviewer is needed (review-checklist-process step 2). Open to challenge by S01 in the end-of-run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | CSV, MVVM, UI, PO and similar abbreviations are not all spelled out at first use; Optional, deferred. |
## Overall Verdict
Go — every Mandatory criterion passes; the failed Optional criteria are deferred with an action item. Reviewed by AI as stand-in for S01; not independent of the author.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Criterion LANG 10 (Optional) failed: Abbreviations are spelled out on first use, in the stated language; fix or accept the deferral | S01 | 2026-10-21 |
---
[MIL-008]: ../../../docs/milestones/mil-008-choose-level.md
[QC-MIL-001]: ../../../framework/qc/artifacts/qc-milestones-gateways.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[0b983b7]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/0b983b7fdadf6958717c1d0227d0f2ebe037f7b1
+64
View File
@@ -0,0 +1,64 @@
# RC-041: Review of PY-MIL-008
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-041 |
| CrossReference | [PY-MIL-008], [QC-PY-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [f45d603] |
---
## Artifact Under Review
- Instance reviewed: [PY-MIL-008]
- Checklist used: [QC-PY-001]
- Scope: full review
- Language and domain: n/a (technical type)
- Language reviewer: none
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Packages, modules, functions, variables, classes and constants follow PEP 8 casing (`snake_case`, `PascalCase`, `UPPER_SNAKE`) | Pass | PEP 8 casing holds in all new modules (`level.py`, `level_view.py`, `window.py`); ruff rule set N passes. |
| 2 | Names state purpose in the domain's language; no unexplained abbreviations, no single-letter names outside tiny scopes | Pass | Names state purpose and are the dictionary's IT terms (`Level`, `Deck.within`, `LevelViewModel`, `LevelChoice`, `Application.start`). |
| 3 | Code is produced by the project's formatter and passes its linter with no unexplained suppressions | Pass | `ruff check` and `ruff format --check` pass on 67 files with no suppressions. |
| 4 | Every function and method signature is type-annotated, including `-> None` | Pass | Every signature is annotated; `mypy --strict` passes on 44 source files and on `tools/capture_screenshots.py`. |
| 5 | No bare `except:`, no swallowed exceptions; specific exceptions are raised and the cause is kept (`raise ... from`) | Pass | `Level` raises `ValueError` for a limit below 1; a failed session start after a click is logged, closes the window with exit code 1 and never swallows silently; no bare `except`. |
| 6 | No mutable default arguments and no shadowed builtins | Pass | No mutable defaults, no builtin shadowed. |
| 7 | Files, locks and connections are managed with context managers | Pass | No new file handling beyond the existing context managers. |
| 8 | Public modules, classes and functions have docstrings that say what, not how | Pass | New and changed members have Doxygen docstrings; `doxygen Doxyfile` ends with 0 warnings. |
| 9 | Logging uses `logging`, not `print`; no secrets or personal data in log output | Pass | No `print`; failures are logged with `logging`; no personal data is logged. |
| 10 | Classes and operations trace to the Design Class Diagram they implement; deviations are recorded | Pass | `Level`, `Deck.within`, `Deck.draw(among)`, `StudySession(level_cards)`, `open_study_session(..., level)`, `LevelChoice`, `LevelViewModel`, `LevelView` and `Application` match the revised DCD-001, OC-001 `chooseLevel` and SD-001. Deviations: `Application` (root, repositories, speech) with `start`, `show_level_screen` and `exit_code` is the composition root detail that DCD-001 shows as `app.main`; `StudySession.remaining_in_level` and `LevelView.frame` are additions. |
| 11 | Tests exist for new behaviour, are named for the behaviour, and do not depend on order or the network | Pass | 191 tests (3 consecutive full runs green) cover `Level`, `Deck.within`, the level filter, the cross-level progress rules on the real word list, the view model, `--level` and the real level window flow; none uses the network. |
| 12 | Type checker runs in strict mode without errors; `Any` is justified in a comment | Pass | `mypy --strict` reports no issue; no `Any`. |
| 13 | Dependencies are declared and pinned in the project's dependency file, none unused | Pass | `dependencies` stays empty; no new package. |
| 14 | Each piece of knowledge (a business rule, constant, format, validation or query) is defined in one place; code is merged only where it expresses the same knowledge, not where it merely looks alike | Pass | The level rule exists only in `Level.first` and `Deck.within`; the choices, labels and sizes exist once in `constants.py`; both views use `configure_window`. |
| 15 | Imports point inward: business-rule modules import no framework, database, UI or delivery-mechanism code, and there are no import cycles | Pass | `lint-imports` reports `Layers point inward` kept; a grep finds no `tkinter`, `csv` or `random` import in `domain` or `application`; the level view model imports no Tkinter. |
| 16 | SOLID holds: a class or module has one reason to change; new behaviour is added by extension, not by editing a type test in several places; subclasses honour the contract of their base; protocols are narrow; high-level code depends on protocols or abstract types and receives its implementations | Pass | The view model owns the choices and the view draws them; the composition root only wires; the session depends on protocols and receives its collaborators. |
| 17 | Source is laid out in the layers and folders of the clean architecture folder structure (`domain`, `application`, `infrastructure`, `presentation` packages under `src/`, and `unit`, `integration` and `e2e` under `tests/`), in `snake_case`, and imports between the layers point inward | Pass | `presentation/features/level/` and `presentation/shared/` follow the clean-architecture folder structure; tests stay in `unit`, `integration`, `e2e` (with a session-scoped `tk_root` in `tests/e2e/conftest.py`). |
| 18 | File and folder names are English, contain no space and no character outside letters, digits, `-`, `_` and `.`, and follow the casing of the language for files | Pass | File and folder names follow the rule. |
## Overall Verdict
Go — every Mandatory criterion passes. Reviewed by AI as stand-in for S01; not independent of the author.
Milestone MIL-008 Go criteria: 1 level 100 draws exactly the first 100 rows over a full run of the real list (integration test); 2 levels 1000 and All use all 1000 words, and a shorter list is used whole (unit and integration tests); 3 words known at level 100 stay known at All and the progress file keeps every unknown word, also outside the level (integration test); 4 a level with nothing left gives the finished message and no failure (unit and e2e tests); 5 the level view model has no Tkinter import and its tests pass without a display; 6 `--level 100|1000|all` skips the screen and an unknown value exits with 2 (unit tests); 7 UC-001, DM-001, DICT-001, SSD-001, OC-001, SD-001, DCD-001, BC-001, US-001, PP-001 and MIL-008 were re-reviewed `Go` (RC-030 to RC-040), the wireframe has Screen 1, and the README and the wiki in en, da and ms describe the level; 8 this record, `pytest` 191 passed, ruff, mypy, lint-imports and doxygen clean. A real screenshot of the level screen was captured and inspected after fixing a too-small window. The Danish and Malay wiki additions were written by the AI and are not read by a native speaker. All Go.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| none | - | - |
---
[PY-MIL-008]: ../../../src/flash_card
[QC-PY-001]: ../../../framework/qc/code/qc-programming-python.md
[f45d603]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/f45d6036e4210e1fbe52f6a582c540a6e1877056
@@ -0,0 +1,70 @@
# RC-042: Review of BC-001
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-042 |
| CrossReference | [BC-001], [QC-BC-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [768ca34] |
---
## Artifact Under Review
- Instance reviewed: [BC-001]
- Checklist used: [QC-BC-001], and [QC-LANG-001] (language and domain)
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in for S01 reads the language and knows the domain)
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | ROI/Cost-Benefit analysis is quantitative, or where qualitative, is explicitly justified | Pass | The Cost-Benefit table is qualitative and says why: no revenue is expected, so a quantitative return does not apply. |
| 2 | Risks are identified with documented impact and mitigation | Pass | The Risks table has 5 risks, each with an impact and a mitigation. |
| 3 | Success criteria are measurable, stating explicit targets rather than vague aspirations | Pass | The Success Criteria table has 8 rows with numeric targets and a measure each (for example 0 third-party packages; 5 commands or fewer). |
| 4 | Scope explicitly separates In Scope vs Out of Scope | Pass | Scope has `### In Scope` and `### Out of Scope`; the executable is added to In Scope and the installer, signing and release upload are named in Out of Scope. |
| 5 | Stakeholders are cross-referenced to Stakeholder Analysis IDs rather than re-described inline | Pass | The Stakeholders table cites S01, S02 and S03 and does not re-describe their roles. |
| 6 | Methodology and quality-standard foundation are stated explicitly (e.g. ISO/IEC 25010, Larman) | Pass | Methodological and Standards Foundation names the framework, Larman, ISO/IEC 25010:2023 and PEP 8. |
| 7 | Assumptions and constraints are explicit and clearly distinguished from one another | Pass | Assumptions and Constraints are separate sections. |
| 8 | Document supports executive decision-making with a clear, unambiguous recommendation | Pass | Recommendation reads `Proceed` with a one-sentence rationale. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Metadata of BC-001 has `Language | en` and `Domain | it`; neither is a placeholder. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code and `it` is a value of the registry's domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | Prose and table cells are English; Malay and Danish words and file names appear only as quoted data. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | The registry gives `IT Executive English` for this type; the text is written for that reader. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The PO terms of DICT-001 (flash card, word list, words to learn, study session) are used and no synonym replaces them. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists beside the document (checked in `docs/`). |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no change of language or domain since an earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer is the stand-in for S01, the Product Owner, who reads English and knows the IT domain; no second language reviewer is needed (review-checklist-process step 2). Open to challenge by S01 in the end-of-run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | CSV, MVVM, UI, PO and similar abbreviations are not all spelled out at first use; Optional, deferred. |
## Overall Verdict
Go — every Mandatory criterion passes; the failed Optional criteria are deferred with an action item. Reviewed by AI as stand-in for S01; not independent of the author.
Full review (not a delta) after the change for MIL-009 (executable).
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Criterion LANG 10 (Optional) failed: Abbreviations are spelled out on first use, in the stated language; fix or accept the deferral | S01 | 2026-10-21 |
---
[BC-001]: ../../../docs/business-case.md
[QC-BC-001]: ../../../framework/qc/artifacts/qc-business-case.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[768ca34]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/768ca344c95d4f21e565e37ac96661c2f8dc8f54
@@ -0,0 +1,70 @@
# RC-043: Review of US-001
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-043 |
| CrossReference | [US-001], [QC-US-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [768ca34] |
---
## Artifact Under Review
- Instance reviewed: [US-001]
- Checklist used: [QC-US-001], and [QC-LANG-001] (language and domain)
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in for S01 reads the language and knows the domain)
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Follows INVEST criteria (Independent, Negotiable, Valuable, Estimable, Small, Testable) | Pass | INVEST Check section confirms the six properties for all seven stories and states one dependency exception. |
| 2 | Written in "As a / I want / So that" form | Pass | All seven stories use `As a / I want / so that`. |
| 3 | Clear, testable acceptance criteria are included | Pass | Every story, including US-001.07, has Given/When/Then acceptance criteria. |
| 4 | Traceable to a use case or epic | Pass | Every story traces to a milestone and to UC-001. |
| 5 | Story is sized to fit within a single iteration | Pass | Each story is one milestone, which fits one iteration. |
| 6 | Story statement avoids technical implementation detail | Fail | Acceptance criteria name `words_to_learn.csv`, `ms-da.csv` and 3000 ms, which are assignment-mandated names and values rather than pure behaviour. |
| 7 | Role named in the story matches an actor defined in the Use Case Diagram | Pass | The role `Learner` is the actor of UCD-001. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Metadata of US-001 has `Language | en` and `Domain | it`; neither is a placeholder. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code and `it` is a value of the registry's domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | Prose and table cells are English; Malay and Danish words and file names appear only as quoted data. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | The registry gives `IT Professional English` for this type; the text is written for that reader. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The PO terms of DICT-001 (flash card, word list, words to learn, study session) are used and no synonym replaces them. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists beside the document (checked in `docs/`). |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no change of language or domain since an earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer is the stand-in for S01, the Product Owner, who reads English and knows the IT domain; no second language reviewer is needed (review-checklist-process step 2). Open to challenge by S01 in the end-of-run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | CSV, MVVM, UI, PO and similar abbreviations are not all spelled out at first use; Optional, deferred. |
## Overall Verdict
Go — every Mandatory criterion passes; the failed Optional criteria are deferred with an action item. Reviewed by AI as stand-in for S01; not independent of the author.
Full review (not a delta) after the change for MIL-009 (executable).
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Criterion 6 (Optional) failed: Story statement avoids technical implementation detail; fix or accept the deferral | S01 | 2026-10-21 |
| Criterion LANG 10 (Optional) failed: Abbreviations are spelled out on first use, in the stated language; fix or accept the deferral | S01 | 2026-10-21 |
---
[US-001]: ../../../docs/user-stories.md
[QC-US-001]: ../../../framework/qc/artifacts/qc-user-story.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[768ca34]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/768ca344c95d4f21e565e37ac96661c2f8dc8f54
@@ -0,0 +1,54 @@
# RC-044: Review of PP-001
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-044 |
| CrossReference | [PP-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [768ca34] |
---
## Artifact Under Review
- Instance reviewed: [PP-001]
- Checklist used: none exists for this type, and [QC-LANG-001] (language and domain)
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in for S01 reads the language and knows the domain)
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Metadata of PP-001 has `Language | en` and `Domain | it`; neither is a placeholder. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code and `it` is a value of the registry's domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | Prose and table cells are English; Malay and Danish words and file names appear only as quoted data. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | The registry gives `IT Executive English` for this type; the text is written for that reader. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The PO terms of DICT-001 (flash card, word list, words to learn, study session) are used and no synonym replaces them. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists beside the document (checked in `docs/`). |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no change of language or domain since an earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer is the stand-in for S01, the Product Owner, who reads English and knows the IT domain; no second language reviewer is needed (review-checklist-process step 2). Open to challenge by S01 in the end-of-run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | CSV, MVVM, UI, PO and similar abbreviations are not all spelled out at first use; Optional, deferred. |
## Overall Verdict
Go — no checklist exists for the Project Plan type; the plan now schedules MIL-009 on 2026-10-16 inside the Business Case constraint (delivery by 2026-10-21) and the language checklist passes. Accepted as the Product Owner's stand-in, after the Product Owner accepted the MIL-009 plan in chat. Reviewed by AI as stand-in for S01; not independent of the author.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Criterion LANG 10 (Optional) failed: Abbreviations are spelled out on first use, in the stated language; fix or accept the deferral | S01 | 2026-10-21 |
---
[PP-001]: ../../../docs/project-plan.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[768ca34]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/768ca344c95d4f21e565e37ac96661c2f8dc8f54
@@ -0,0 +1,55 @@
# RC-045: Review of DCD-001
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-045 |
| CrossReference | [DCD-001], [QC-DCD-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [768ca34] |
---
## Artifact Under Review
- Instance reviewed: [DCD-001]
- Checklist used: [QC-DCD-001]
- Scope: full review
- Language and domain: n/a (technical type)
- Language reviewer: none
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | SOLID principles applied; no god classes with excessive responsibilities | Pass | Each class has one responsibility (Class Table); view, view model, session, deck and adapters are separate. |
| 2 | Visibility markers correct and consistent (`+` public, `-` private, `#` protected) | Pass | Visibility markers are on all members. |
| 3 | Relationships correctly distinguished: Association vs Aggregation vs Composition vs Dependency | Pass | Composition (Vocabulary and Card), aggregation (Deck), association, dependency and realization are distinguished. |
| 4 | Multiplicities and navigability specified on all associations | Pass | Multiplicities are on the associations; dependencies are directed. |
| 5 | Applied design patterns are annotated explicitly (e.g. Singleton, Factory, Strategy) | Pass | Pattern Annotations table lists Repository, Ports and adapters, Null Object, MVVM, Composition root. |
| 6 | Method signatures are traceable to Operation Contracts and/or design Sequence Diagrams | Pass | Method Traceability table is unchanged; the packaging support (`runtime.py`, `tools/`) is stated in Purpose and Scope as having no system operation and not being a design class, so it needs no row. |
| 7 | Class names and structure remain consistent with the Domain Model concepts they refine | Pass | The Class Table has a `Refines` column; names match the dictionary's IT terms; no class was added. |
| 8 | No circular dependencies between classes/packages unless explicitly justified | Pass | Dependency Check states there are no cycles. |
| 9 | Dependencies between classes and packages point inward: domain classes do not depend on infrastructure, delivery or framework classes | Pass | Domain imports nothing; infrastructure and presentation point inward (Dependency Check). |
## Overall Verdict
Go — every Mandatory criterion passes. Reviewed by AI as stand-in for S01; not independent of the author.
Full review (not a delta) after the change for MIL-009 (executable).
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| none | - | - |
---
[DCD-001]: ../../../docs/dcd.md
[QC-DCD-001]: ../../../framework/qc/artifacts/qc-dcd.md
[768ca34]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/768ca344c95d4f21e565e37ac96661c2f8dc8f54
+55
View File
@@ -0,0 +1,55 @@
# RC-046: Review of ADR-0004
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-046 |
| CrossReference | [ADR-0004], [QC-ADR-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [768ca34] |
---
## Artifact Under Review
- Instance reviewed: [ADR-0004]
- Checklist used: [QC-ADR-001]
- Scope: full review
- Language and domain: n/a (technical type)
- Language reviewer: none
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The ID (`ADR-NNNN`, 4-digit) matches the filename number and is unique and sequential | Pass | ID `ADR-0004` matches the file name number. |
| 2 | Context states the problem, the forces (cost, risk, constraints) and the options evaluated | Pass | Context states the need (US-001.07), the forces and three options. |
| 3 | At least two options were considered, or the absence of alternatives is justified | Pass | Three options were considered. |
| 4 | Decision is stated in one or two unhedged sentences and matches one of the evaluated options | Pass | Decision is stated plainly and is option 2. |
| 5 | Consequences list both Positive and Negative outcomes | Pass | Consequences have Positive and Negative lists. |
| 6 | Quality-attribute impacts (performance, security, portability, etc.) are named where the decision affects them | Pass | Portability (Windows only, cross-compile limit), start-up time and size are named. |
| 7 | Affected Artifacts are listed as links, and each is also in CrossReference | Pass | Affected Artifacts BC-001, US-001 and DCD-001 are listed and in CrossReference. |
| 8 | Status changes are recorded as new Version History rows with a Change summary and Commit link; retained rows are never rewritten | Pass | First version; no status change yet. |
| 9 | A superseded or deprecated ADR names its successor, and the successor links back | N-A | Not superseded or deprecated. |
| 10 | Written in business or technical language of the domain, with no unexplained abbreviations | Pass | Written in plain technical English; `sys.frozen`, `sys.executable` are code names. |
| 11 | Status is one of `Proposed`, `Accepted`, `Rejected`, `Deprecated` or `Superseded by ADR-NNNN`, and every Version History row uses only these | Pass | Status `Proposed` before this review; uses an allowed value. |
## Overall Verdict
Go — every Mandatory criterion passes. Reviewed by AI as stand-in for S01; not independent of the author.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| none | - | - |
---
[ADR-0004]: ../../../docs/adr/adr-0004-pyinstaller-executable.md
[QC-ADR-001]: ../../../framework/qc/artifacts/qc-adr.md
[768ca34]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/768ca344c95d4f21e565e37ac96661c2f8dc8f54
+66
View File
@@ -0,0 +1,66 @@
# RC-047: Review of MIL-009
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-047 |
| CrossReference | [MIL-009], [QC-MIL-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [768ca34] |
---
## Artifact Under Review
- Instance reviewed: [MIL-009]
- Checklist used: [QC-MIL-001], and [QC-LANG-001] (language and domain)
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in for S01 reads the language and knows the domain)
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | A concrete deliverable is defined for every gate | Pass | A concrete Deliverable section names the output evaluated at the gate. |
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | The Go / No-Go table has numbered criteria, each with an observable Go and No-Go. |
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Dependencies table names the milestone or documents it needs. |
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Traceability table maps to Business Case objectives and the user story. |
| 5 | Milestone owner and approving reviewer are identified | Pass | Ownership table names S01 as owner and approving reviewer. |
| 6 | Milestone has a defined target date consistent with project constraints | Pass | Target Date lies inside the 2026-10-14 to 2026-10-21 window of the Business Case. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Metadata of MIL-009 has `Language | en` and `Domain | it`; neither is a placeholder. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code and `it` is a value of the registry's domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | Prose and table cells are English; Malay and Danish words and file names appear only as quoted data. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | The registry gives `IT Executive English` for this type; the text is written for that reader. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The PO terms of DICT-001 (flash card, word list, words to learn, study session) are used and no synonym replaces them. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists beside the document (checked in `docs/`). |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no change of language or domain since an earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer is the stand-in for S01, the Product Owner, who reads English and knows the IT domain; no second language reviewer is needed (review-checklist-process step 2). Open to challenge by S01 in the end-of-run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | CSV, MVVM, UI, PO and similar abbreviations are not all spelled out at first use; Optional, deferred. |
## Overall Verdict
Go — every Mandatory criterion passes; the failed Optional criteria are deferred with an action item. Reviewed by AI as stand-in for S01; not independent of the author.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Criterion LANG 10 (Optional) failed: Abbreviations are spelled out on first use, in the stated language; fix or accept the deferral | S01 | 2026-10-21 |
---
[MIL-009]: ../../../docs/milestones/mil-009-executable.md
[QC-MIL-001]: ../../../framework/qc/artifacts/qc-milestones-gateways.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[768ca34]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/768ca344c95d4f21e565e37ac96661c2f8dc8f54
+64
View File
@@ -0,0 +1,64 @@
# RC-048: Review of PY-MIL-009
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-048 |
| CrossReference | [PY-MIL-009], [QC-PY-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [bc51381] |
---
## Artifact Under Review
- Instance reviewed: [PY-MIL-009]
- Checklist used: [QC-PY-001]
- Scope: full review
- Language and domain: n/a (technical type)
- Language reviewer: none
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Packages, modules, functions, variables, classes and constants follow PEP 8 casing (`snake_case`, `PascalCase`, `UPPER_SNAKE`) | Pass | PEP 8 casing holds in `runtime.py`, `build_executable.py` and the changed modules; ruff rule set N passes. |
| 2 | Names state purpose in the domain's language; no unexplained abbreviations, no single-letter names outside tiny scopes | Pass | Names state purpose (`resource_root`, `executable_dir`, `build_arguments`, `resolve_data_files`). |
| 3 | Code is produced by the project's formatter and passes its linter with no unexplained suppressions | Pass | `ruff check` and `ruff format --check` pass on 71 files with no suppressions. |
| 4 | Every function and method signature is type-annotated, including `-> None` | Pass | Every signature is annotated; `mypy --strict` passes on 45 source files and on the three tool scripts. |
| 5 | No bare `except:`, no swallowed exceptions; specific exceptions are raised and the cause is kept (`raise ... from`) | Pass | `main` of the build tool returns 2 with a message when PyInstaller is not installed; no bare `except`; no swallowed exception. |
| 6 | No mutable default arguments and no shadowed builtins | Pass | No mutable defaults, no builtin shadowed. |
| 7 | Files, locks and connections are managed with context managers | Pass | No new file handling beyond the existing context managers; the ICO file is written with `Path.write_bytes`. |
| 8 | Public modules, classes and functions have docstrings that say what, not how | Pass | New and changed members have Doxygen docstrings; `doxygen Doxyfile` ends with 0 warnings. |
| 9 | Logging uses `logging`, not `print`; no secrets or personal data in log output | Pass | No `print` in `src`; the tools write results with `sys.stdout.write`; no secret. |
| 10 | Classes and operations trace to the Design Class Diagram they implement; deviations are recorded | Pass | The program classes are unchanged (DCD-001); `runtime.py` and `tools/` are packaging support outside the design classes, as ADR-0004 and the Scope note of DCD-001 state; `resolve_data_files` is a function of the composition root. |
| 11 | Tests exist for new behaviour, are named for the behaviour, and do not depend on order or the network | Pass | 216 tests (3 consecutive runs green): pure runtime helpers for the frozen and source cases, the argument list of the build, the ICO file, the bundled word list fallback, and the level screen window title; none starts PyInstaller or uses the network. The real executable was built and smoke-tested separately (note below). |
| 12 | Type checker runs in strict mode without errors; `Any` is justified in a comment | Pass | `mypy --strict` reports no issue; `sys._MEIPASS` is read with `getattr` and no `Any` is used. |
| 13 | Dependencies are declared and pinned in the project's dependency file, none unused | Pass | `dependencies` is still empty; PyInstaller is only in the extra `build` and Pillow only in `tools`. |
| 14 | Each piece of knowledge (a business rule, constant, format, validation or query) is defined in one place; code is merged only where it expresses the same knowledge, not where it merely looks alike | Pass | The frozen rule is one definition (`runtime.py`) used by `constants.py`; file names and sizes stay in `constants.py`. |
| 15 | Imports point inward: business-rule modules import no framework, database, UI or delivery-mechanism code, and there are no import cycles | Pass | `lint-imports` reports `Layers point inward` kept; `runtime.py` imports only the standard library. |
| 16 | SOLID holds: a class or module has one reason to change; new behaviour is added by extension, not by editing a type test in several places; subclasses honour the contract of their base; protocols are narrow; high-level code depends on protocols or abstract types and receives its implementations | Pass | The build tool has one purpose and a pure `build_arguments` that is tested; the composition root chooses the word list file. |
| 17 | Source is laid out in the layers and folders of the clean architecture folder structure (`domain`, `application`, `infrastructure`, `presentation` packages under `src/`, and `unit`, `integration` and `e2e` under `tests/`), in `snake_case`, and imports between the layers point inward | Pass | `tools/build_executable.py` and `runtime.py` sit outside the four layers as packaging support; layers and test folders are unchanged. |
| 18 | File and folder names are English, contain no space and no character outside letters, digits, `-`, `_` and `.`, and follow the casing of the language for files | Pass | File and folder names follow the rule. |
## Overall Verdict
Go — every Mandatory criterion passes. Reviewed by AI as stand-in for S01; not independent of the author.
Milestone MIL-009 Go criteria: 1 `python tools/build_executable.py` ended with exit code 0 and wrote `dist/flash-card.exe` (25.8 MB) with PyInstaller 6.22.3 on the Windows Store Python 3.13.14; 2 started from a temporary folder without the virtual environment, the executable showed a window titled `Flashy` after about 2 seconds and has no console (windowed bootloader); 3 with `data/ms-da.csv` beside it (3 words) one tick left 2 cards in the progress file, without it the embedded list was used (1000 words); 4 one tick wrote `data/words_to_learn.csv` next to the executable with 999 cards at level 100; 5 a captured screenshot of the executable shows the card and both button images; 6 unit tests of the frozen rule pass; 7 `dependencies` empty, extra `build`; 8 BC-001, DCD-001, ADR-0004, PP-001, US-001 and MIL-009 were reviewed Go (RC-042 to RC-047), README and the Install page of the wiki in three languages describe the build; 9 this record, `pytest` 216 passed, ruff, mypy, lint-imports and doxygen clean. Defects found by the smoke test and fixed in this milestone: the level screen window had the default title `tk` and no padding because `LevelView` did not call `configure_window`. Notes: the one-file build starts a second process (the bootloader), so a tool that watches a window must not match the first process id; the first start after a build took over 20 seconds on this machine (unpacking and a virus scan) and later starts about 2 seconds; the spoken word was not tested in the executable (the speech packages are collected into it, the network call was not exercised). All Go.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| none | - | - |
---
[PY-MIL-009]: ../../../src/flash_card
[QC-PY-001]: ../../../framework/qc/code/qc-programming-python.md
[bc51381]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/bc513810ece2506d5ab63c1d4c603803c2ad415e
+64
View File
@@ -0,0 +1,64 @@
# RC-049: Review of PY-FIX-001
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-049 |
| CrossReference | [PY-FIX-001], [QC-PY-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [061b4f4] |
---
## Artifact Under Review
- Instance reviewed: [PY-FIX-001]
- Checklist used: [QC-PY-001]
- Scope: full review
- Language and domain: n/a (technical type)
- Language reviewer: none
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Packages, modules, functions, variables, classes and constants follow PEP 8 casing (`snake_case`, `PascalCase`, `UPPER_SNAKE`) | Pass | The fixture and names follow PEP 8 (`fake_tk_root`). |
| 2 | Names state purpose in the domain's language; no unexplained abbreviations, no single-letter names outside tiny scopes | Pass | Names state purpose. |
| 3 | Code is produced by the project's formatter and passes its linter with no unexplained suppressions | Pass | `ruff check` and `ruff format --check` pass with no suppressions. |
| 4 | Every function and method signature is type-annotated, including `-> None` | Pass | The fixture is annotated `-> None`; `mypy --strict` passes on 45 source files. |
| 5 | No bare `except:`, no swallowed exceptions; specific exceptions are raised and the cause is kept (`raise ... from`) | Pass | No exception handling in the change. |
| 6 | No mutable default arguments and no shadowed builtins | Pass | No mutable defaults. |
| 7 | Files, locks and connections are managed with context managers | N-A | No file handling in the change. |
| 8 | Public modules, classes and functions have docstrings that say what, not how | N-A | Tests are excluded from the docstring rules; the fixture has a one-line docstring. |
| 9 | Logging uses `logging`, not `print`; no secrets or personal data in log output | Pass | No `print`, no logging in the change. |
| 10 | Classes and operations trace to the Design Class Diagram they implement; deviations are recorded | Pass | No class or operation changed; the change is in a test of `app.main`. |
| 11 | Tests exist for new behaviour, are named for the behaviour, and do not depend on order or the network | Pass | The change makes the test independent of a real Tk root: 20 consecutive full runs (216 tests) were green after 2 failures in 12 runs before; real Tk stays covered by `tests/e2e`. |
| 12 | Type checker runs in strict mode without errors; `Any` is justified in a comment | Pass | `mypy --strict` reports no issue. |
| 13 | Dependencies are declared and pinned in the project's dependency file, none unused | Pass | No dependency change. |
| 14 | Each piece of knowledge (a business rule, constant, format, validation or query) is defined in one place; code is merged only where it expresses the same knowledge, not where it merely looks alike | Pass | The fake root is the module's existing `_FakeRoot`, used once by an autouse fixture instead of per test. |
| 15 | Imports point inward: business-rule modules import no framework, database, UI or delivery-mechanism code, and there are no import cycles | Pass | No source import changed; `lint-imports` kept. |
| 16 | SOLID holds: a class or module has one reason to change; new behaviour is added by extension, not by editing a type test in several places; subclasses honour the contract of their base; protocols are narrow; high-level code depends on protocols or abstract types and receives its implementations | Pass | One fixture with one responsibility. |
| 17 | Source is laid out in the layers and folders of the clean architecture folder structure (`domain`, `application`, `infrastructure`, `presentation` packages under `src/`, and `unit`, `integration` and `e2e` under `tests/`), in `snake_case`, and imports between the layers point inward | Pass | Test file stays in `tests/unit`. |
| 18 | File and folder names are English, contain no space and no character outside letters, digits, `-`, `_` and `.`, and follow the casing of the language for files | Pass | File names unchanged. |
## Overall Verdict
Go — every Mandatory criterion passes. Reviewed by AI as stand-in for S01; not independent of the author.
Defect fixed: an unpatched `app.main` call created a real `tk.Tk()` inside a unit test, which failed in about 1 of 6 full runs (the only Tk process limit and Tcl handle problem seen in MIL-005). Found after the MIL-009 merge, outside any milestone task, so no issue is closed. Go.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| none | - | - |
---
[PY-FIX-001]: ../../../tests/unit/test_app.py
[QC-PY-001]: ../../../framework/qc/code/qc-programming-python.md
[061b4f4]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/061b4f48b5d49e6800656c95d79df707e07ec0f3
+68
View File
@@ -0,0 +1,68 @@
# RC-050: Review of MIL-009
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-050 |
| CrossReference | [MIL-009], [QC-MIL-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [061b4f4] |
---
## Artifact Under Review
- Instance reviewed: [MIL-009]
- Checklist used: [QC-MIL-001], and [QC-LANG-001] (language and domain)
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in for S01 reads the language and knows the domain)
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | A concrete deliverable is defined for every gate | Pass | A concrete Deliverable section names the output evaluated at the gate. |
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | The Go / No-Go table has numbered criteria, each with an observable Go and No-Go. |
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Dependencies table names the milestone or documents it needs. |
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Traceability table maps to Business Case objectives and the user story. |
| 5 | Milestone owner and approving reviewer are identified | Pass | Ownership table names S01 as owner and approving reviewer. |
| 6 | Milestone has a defined target date consistent with project constraints | Pass | Target Date lies inside the 2026-10-14 to 2026-10-21 window of the Business Case. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Metadata of MIL-009 has `Language | en` and `Domain | it`; neither is a placeholder. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code and `it` is a value of the registry's domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | Prose and table cells are English; Malay and Danish words and file names appear only as quoted data. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | The registry gives `IT Executive English` for this type; the text is written for that reader. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The PO terms of DICT-001 (flash card, word list, words to learn, study session) are used and no synonym replaces them. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists beside the document (checked in `docs/`). |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no change of language or domain since an earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer is the stand-in for S01, the Product Owner, who reads English and knows the IT domain; no second language reviewer is needed (review-checklist-process step 2). Open to challenge by S01 in the end-of-run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | CSV, MVVM, UI, PO and similar abbreviations are not all spelled out at first use; Optional, deferred. |
## Overall Verdict
Go — every Mandatory criterion passes; the failed Optional criteria are deferred with an action item. Reviewed by AI as stand-in for S01; not independent of the author.
Re-review of MIL-009 after task 9 was added (a flaky unit test fix); Go/No-Go criteria, deliverable and dates are unchanged.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Criterion LANG 10 (Optional) failed: Abbreviations are spelled out on first use, in the stated language; fix or accept the deferral | S01 | 2026-10-21 |
---
[MIL-009]: ../../../docs/milestones/mil-009-executable.md
[QC-MIL-001]: ../../../framework/qc/artifacts/qc-milestones-gateways.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[061b4f4]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/061b4f48b5d49e6800656c95d79df707e07ec0f3
@@ -0,0 +1,70 @@
# RC-051: Review of BC-001
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-051 |
| CrossReference | [BC-001], [QC-BC-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [9c8e294] |
---
## Artifact Under Review
- Instance reviewed: [BC-001]
- Checklist used: [QC-BC-001], and [QC-LANG-001] (language and domain)
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in for S01 reads the language and knows the domain)
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | ROI/Cost-Benefit analysis is quantitative, or where qualitative, is explicitly justified | Pass | The Cost-Benefit table is qualitative and says why: no revenue is expected, so a quantitative return does not apply. |
| 2 | Risks are identified with documented impact and mitigation | Pass | The Risks table has 5 risks, each with an impact and a mitigation. |
| 3 | Success criteria are measurable, stating explicit targets rather than vague aspirations | Pass | The Success Criteria table has 8 rows with numeric targets and a measure each (for example 0 third-party packages; 5 commands or fewer). |
| 4 | Scope explicitly separates In Scope vs Out of Scope | Pass | Scope has `### In Scope` and `### Out of Scope`; the release of the executable is In Scope, an installer and signing stay Out of Scope. |
| 5 | Stakeholders are cross-referenced to Stakeholder Analysis IDs rather than re-described inline | Pass | The Stakeholders table cites S01, S02 and S03 and does not re-describe their roles. |
| 6 | Methodology and quality-standard foundation are stated explicitly (e.g. ISO/IEC 25010, Larman) | Pass | Methodological and Standards Foundation names the framework, Larman, ISO/IEC 25010:2023 and PEP 8. |
| 7 | Assumptions and constraints are explicit and clearly distinguished from one another | Pass | Assumptions and Constraints are separate sections. |
| 8 | Document supports executive decision-making with a clear, unambiguous recommendation | Pass | Recommendation reads `Proceed` with a one-sentence rationale. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Metadata of BC-001 has `Language | en` and `Domain | it`; neither is a placeholder. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code and `it` is a value of the registry's domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | Prose and table cells are English; Malay and Danish words and file names appear only as quoted data. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | The registry gives `IT Executive English` for this type; the text is written for that reader. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The PO terms of DICT-001 (flash card, word list, words to learn, study session) are used and no synonym replaces them. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists beside the document (checked in `docs/`). |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no change of language or domain since an earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer is the stand-in for S01, the Product Owner, who reads English and knows the IT domain; no second language reviewer is needed (review-checklist-process step 2). Open to challenge by S01 in the end-of-run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | CSV, MVVM, UI, PO and similar abbreviations are not all spelled out at first use; Optional, deferred. |
## Overall Verdict
Go — every Mandatory criterion passes; the failed Optional criteria are deferred with an action item. Reviewed by AI as stand-in for S01; not independent of the author.
Full review (not a delta) after the change for MIL-010 (release).
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Criterion LANG 10 (Optional) failed: Abbreviations are spelled out on first use, in the stated language; fix or accept the deferral | S01 | 2026-10-21 |
---
[BC-001]: ../../../docs/business-case.md
[QC-BC-001]: ../../../framework/qc/artifacts/qc-business-case.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[9c8e294]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/9c8e2940217e615f82eda2d48aca9b2fd58f3687
@@ -0,0 +1,70 @@
# RC-052: Review of US-001
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-052 |
| CrossReference | [US-001], [QC-US-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [9c8e294] |
---
## Artifact Under Review
- Instance reviewed: [US-001]
- Checklist used: [QC-US-001], and [QC-LANG-001] (language and domain)
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in for S01 reads the language and knows the domain)
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Follows INVEST criteria (Independent, Negotiable, Valuable, Estimable, Small, Testable) | Pass | INVEST Check section confirms the six properties for all eight stories and states one dependency exception. |
| 2 | Written in "As a / I want / So that" form | Pass | All eight stories use `As a / I want / so that`. |
| 3 | Clear, testable acceptance criteria are included | Pass | Every story, including US-001.08, has Given/When/Then acceptance criteria. |
| 4 | Traceable to a use case or epic | Pass | Every story traces to a milestone and to UC-001. |
| 5 | Story is sized to fit within a single iteration | Pass | Each story is one milestone, which fits one iteration. |
| 6 | Story statement avoids technical implementation detail | Fail | Acceptance criteria name `words_to_learn.csv`, `ms-da.csv` and 3000 ms, which are assignment-mandated names and values rather than pure behaviour. |
| 7 | Role named in the story matches an actor defined in the Use Case Diagram | Pass | The role `Learner` is the actor of UCD-001. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Metadata of US-001 has `Language | en` and `Domain | it`; neither is a placeholder. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code and `it` is a value of the registry's domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | Prose and table cells are English; Malay and Danish words and file names appear only as quoted data. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | The registry gives `IT Professional English` for this type; the text is written for that reader. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The PO terms of DICT-001 (flash card, word list, words to learn, study session) are used and no synonym replaces them. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists beside the document (checked in `docs/`). |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no change of language or domain since an earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer is the stand-in for S01, the Product Owner, who reads English and knows the IT domain; no second language reviewer is needed (review-checklist-process step 2). Open to challenge by S01 in the end-of-run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | CSV, MVVM, UI, PO and similar abbreviations are not all spelled out at first use; Optional, deferred. |
## Overall Verdict
Go — every Mandatory criterion passes; the failed Optional criteria are deferred with an action item. Reviewed by AI as stand-in for S01; not independent of the author.
Full review (not a delta) after the change for MIL-010 (release).
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Criterion 6 (Optional) failed: Story statement avoids technical implementation detail; fix or accept the deferral | S01 | 2026-10-21 |
| Criterion LANG 10 (Optional) failed: Abbreviations are spelled out on first use, in the stated language; fix or accept the deferral | S01 | 2026-10-21 |
---
[US-001]: ../../../docs/user-stories.md
[QC-US-001]: ../../../framework/qc/artifacts/qc-user-story.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[9c8e294]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/9c8e2940217e615f82eda2d48aca9b2fd58f3687
@@ -0,0 +1,54 @@
# RC-053: Review of PP-001
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-053 |
| CrossReference | [PP-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [9c8e294] |
---
## Artifact Under Review
- Instance reviewed: [PP-001]
- Checklist used: none exists for this type, and [QC-LANG-001] (language and domain)
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in for S01 reads the language and knows the domain)
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Metadata of PP-001 has `Language | en` and `Domain | it`; neither is a placeholder. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code and `it` is a value of the registry's domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | Prose and table cells are English; Malay and Danish words and file names appear only as quoted data. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | The registry gives `IT Executive English` for this type; the text is written for that reader. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The PO terms of DICT-001 (flash card, word list, words to learn, study session) are used and no synonym replaces them. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists beside the document (checked in `docs/`). |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no change of language or domain since an earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer is the stand-in for S01, the Product Owner, who reads English and knows the IT domain; no second language reviewer is needed (review-checklist-process step 2). Open to challenge by S01 in the end-of-run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | CSV, MVVM, UI, PO and similar abbreviations are not all spelled out at first use; Optional, deferred. |
## Overall Verdict
Go — no checklist exists for the Project Plan type; the plan now schedules MIL-010 on 2026-10-16 inside the Business Case constraint (delivery by 2026-10-21) and the language checklist passes. Accepted as the Product Owner's stand-in, after the Product Owner asked for the release in chat. Reviewed by AI as stand-in for S01; not independent of the author.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Criterion LANG 10 (Optional) failed: Abbreviations are spelled out on first use, in the stated language; fix or accept the deferral | S01 | 2026-10-21 |
---
[PP-001]: ../../../docs/project-plan.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[9c8e294]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/9c8e2940217e615f82eda2d48aca9b2fd58f3687
+66
View File
@@ -0,0 +1,66 @@
# RC-054: Review of MIL-010
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-054 |
| CrossReference | [MIL-010], [QC-MIL-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [9c8e294] |
---
## Artifact Under Review
- Instance reviewed: [MIL-010]
- Checklist used: [QC-MIL-001], and [QC-LANG-001] (language and domain)
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in for S01 reads the language and knows the domain)
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | A concrete deliverable is defined for every gate | Pass | A concrete Deliverable section names the output evaluated at the gate. |
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | The Go / No-Go table has numbered criteria, each with an observable Go and No-Go. |
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Dependencies table names the milestone or documents it needs. |
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Traceability table maps to Business Case objectives and the user story. |
| 5 | Milestone owner and approving reviewer are identified | Pass | Ownership table names S01 as owner and approving reviewer. |
| 6 | Milestone has a defined target date consistent with project constraints | Pass | Target Date lies inside the 2026-10-14 to 2026-10-21 window of the Business Case. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Metadata of MIL-010 has `Language | en` and `Domain | it`; neither is a placeholder. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code and `it` is a value of the registry's domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | Prose and table cells are English; Malay and Danish words and file names appear only as quoted data. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | The registry gives `IT Executive English` for this type; the text is written for that reader. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The PO terms of DICT-001 (flash card, word list, words to learn, study session) are used and no synonym replaces them. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists beside the document (checked in `docs/`). |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no change of language or domain since an earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer is the stand-in for S01, the Product Owner, who reads English and knows the IT domain; no second language reviewer is needed (review-checklist-process step 2). Open to challenge by S01 in the end-of-run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | CSV, MVVM, UI, PO and similar abbreviations are not all spelled out at first use; Optional, deferred. |
## Overall Verdict
Go — every Mandatory criterion passes; the failed Optional criteria are deferred with an action item. Reviewed by AI as stand-in for S01; not independent of the author.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Criterion LANG 10 (Optional) failed: Abbreviations are spelled out on first use, in the stated language; fix or accept the deferral | S01 | 2026-10-21 |
---
[MIL-010]: ../../../docs/milestones/mil-010-release.md
[QC-MIL-001]: ../../../framework/qc/artifacts/qc-milestones-gateways.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[9c8e294]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/9c8e2940217e615f82eda2d48aca9b2fd58f3687
+50
View File
@@ -0,0 +1,50 @@
# RC-055: Review of the release v0.1.0
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-055 |
| CrossReference | [MIL-010] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [db87a6d] |
---
## Artifact Under Review
- Instance reviewed: [MIL-010] (the milestone's Go / No-Go criteria, checked against the release v0.1.0)
- Checklist used: none exists for a release; the seven criteria of MIL-010 are the checklist
- Scope: full review
- Language and domain: n/a (record of results)
- Language reviewer: none
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The executable is rebuilt from the head of `main` that gets the tag and passes the smoke test | Pass | Built with `--clean` from commit `2c580cc` after removing `build/` and `dist/`; four smoke cases passed (window "Flashy" after about 2 s, embedded list, progress file beside the exe with 999 cards, list override with a 2 word list) |
| 2 | The tag `v0.1.0` is an annotated tag on that commit and the version files say `0.1.0` | Pass | `git show v0.1.0` shows the annotated tag on `2c580cc`; `pyproject.toml` and `__version__` say `0.1.0` |
| 3 | The release has the assets `flash-card.exe` and `flash-card.exe.sha256` | Fail | The upload of `flash-card.exe` (25.8 MB) was rejected with `413 Request Entity Too Large` from the server's reverse proxy; a 1 MB test upload was reset as well; only an 82 byte file passed. The checksum asset alone was deleted again, because a checksum without its file is misleading |
| 4 | The SHA-256 of the file downloaded from the release equals the checksum | Fail | There is no downloadable file; the hash of the local build was `0ac22621ecb8ddad53c5f3d2a35278bebd34cefe458510971106ec52d5bdb47d`, which cannot be verified by others because PyInstaller builds are not bit-for-bit reproducible |
| 5 | The release notes say unsigned Windows build, the `data` folder and how to build, and give the SHA-256 | Fail | The notes say unsigned, the `data` folder and how to build, and state that the file is not attached; they give no SHA-256 because there is no file |
| 6 | CHANGELOG, README and the Install page of the wiki link the release; `check-readme.sh` exit 0 | Pass | Links present in all five files and corrected to say the file is not attached; `check-readme.sh` exit 0 |
| 7 | BC-001, US-001 and PP-001 are updated and reviewed `Go` | Pass | RC-051 to RC-053 |
## Overall Verdict
Go-with-conditions — the tag and the release page exist and the build was verified, but criteria 3, 4 and 5 fail because the server refuses the upload of the executable. The milestone MIL-010 stays open and issue "Create the release and attach the files" stays open until the executable is attached. Reviewed by AI as stand-in for S01; not independent of the author.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Raise the upload limit of the git host's reverse proxy (nginx `client_max_body_size`, and Gitea's attachment limit if set) to at least 50 MB, then ask for the attachment of `flash-card.exe` and its SHA-256 to v0.1.0 (or confirm another place to host the file) | S01 | 2026-10-21 |
---
[MIL-010]: ../milestones/mil-010-release.md
[db87a6d]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/db87a6d33bcaaef5a8bc62bf3f804502130b76a9
@@ -0,0 +1,70 @@
# RC-056: Review of BC-001
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-056 |
| CrossReference | [BC-001], [QC-BC-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [2211d0f] |
---
## Artifact Under Review
- Instance reviewed: [BC-001]
- Checklist used: [QC-BC-001], and [QC-LANG-001] (language and domain)
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in for S01 reads the language and knows the domain)
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | ROI/Cost-Benefit analysis is quantitative, or where qualitative, is explicitly justified | Pass | The Cost-Benefit table is qualitative and says why: no revenue is expected, so a quantitative return does not apply. |
| 2 | Risks are identified with documented impact and mitigation | Pass | The Risks table has 5 risks, each with an impact and a mitigation. |
| 3 | Success criteria are measurable, stating explicit targets rather than vague aspirations | Pass | The Success Criteria table has 8 rows with numeric targets and a measure each (for example 0 third-party packages; 5 commands or fewer). |
| 4 | Scope explicitly separates In Scope vs Out of Scope | Pass | Scope has `### In Scope` and `### Out of Scope`; the menu bar is added to In Scope. |
| 5 | Stakeholders are cross-referenced to Stakeholder Analysis IDs rather than re-described inline | Pass | The Stakeholders table cites S01, S02 and S03 and does not re-describe their roles. |
| 6 | Methodology and quality-standard foundation are stated explicitly (e.g. ISO/IEC 25010, Larman) | Pass | Methodological and Standards Foundation names the framework, Larman, ISO/IEC 25010:2023 and PEP 8. |
| 7 | Assumptions and constraints are explicit and clearly distinguished from one another | Pass | Assumptions and Constraints are separate sections. |
| 8 | Document supports executive decision-making with a clear, unambiguous recommendation | Pass | Recommendation reads `Proceed` with a one-sentence rationale. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Metadata of BC-001 has `Language | en` and `Domain | it`; neither is a placeholder. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code and `it` is a value of the registry's domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | Prose and table cells are English; Malay and Danish words and file names appear only as quoted data. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | The registry gives `IT Executive English` for this type; the text is written for that reader. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The PO terms of DICT-001 (flash card, word list, words to learn, study session) are used and no synonym replaces them. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists beside the document (checked in `docs/`). |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no change of language or domain since an earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer is the stand-in for S01, the Product Owner, who reads English and knows the IT domain; no second language reviewer is needed (review-checklist-process step 2). Open to challenge by S01 in the end-of-run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | CSV, MVVM, UI, PO and similar abbreviations are not all spelled out at first use; Optional, deferred. |
## Overall Verdict
Go — every Mandatory criterion passes; the failed Optional criteria are deferred with an action item. Reviewed by AI as stand-in for S01; not independent of the author.
Full review (not a delta) after the change for MIL-011 (menu bar).
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Criterion LANG 10 (Optional) failed: Abbreviations are spelled out on first use, in the stated language; fix or accept the deferral | S01 | 2026-10-21 |
---
[BC-001]: ../../../docs/business-case.md
[QC-BC-001]: ../../../framework/qc/artifacts/qc-business-case.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[2211d0f]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/2211d0f4cbd8182314d18cbdefd939ae50c39e6d
@@ -0,0 +1,70 @@
# RC-057: Review of US-001
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-057 |
| CrossReference | [US-001], [QC-US-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [2211d0f] |
---
## Artifact Under Review
- Instance reviewed: [US-001]
- Checklist used: [QC-US-001], and [QC-LANG-001] (language and domain)
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in for S01 reads the language and knows the domain)
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Follows INVEST criteria (Independent, Negotiable, Valuable, Estimable, Small, Testable) | Pass | INVEST Check section confirms the six properties for all twelve stories and states one dependency exception. |
| 2 | Written in "As a / I want / So that" form | Pass | All twelve stories use `As a / I want / so that`. |
| 3 | Clear, testable acceptance criteria are included | Pass | Every story, including US-001.09 to US-001.12, has Given/When/Then acceptance criteria. |
| 4 | Traceable to a use case or epic | Pass | Every story traces to a milestone and to UC-001. |
| 5 | Story is sized to fit within a single iteration | Pass | Each story is one milestone, which fits one iteration. |
| 6 | Story statement avoids technical implementation detail | Fail | Acceptance criteria name `words_to_learn.csv`, `ms-da.csv` and 3000 ms, which are assignment-mandated names and values rather than pure behaviour. |
| 7 | Role named in the story matches an actor defined in the Use Case Diagram | Pass | The role `Learner` is the actor of UCD-001. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Metadata of US-001 has `Language | en` and `Domain | it`; neither is a placeholder. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code and `it` is a value of the registry's domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | Prose and table cells are English; Malay and Danish words and file names appear only as quoted data. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | The registry gives `IT Professional English` for this type; the text is written for that reader. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The PO terms of DICT-001 (flash card, word list, words to learn, study session) are used and no synonym replaces them. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists beside the document (checked in `docs/`). |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no change of language or domain since an earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer is the stand-in for S01, the Product Owner, who reads English and knows the IT domain; no second language reviewer is needed (review-checklist-process step 2). Open to challenge by S01 in the end-of-run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | CSV, MVVM, UI, PO and similar abbreviations are not all spelled out at first use; Optional, deferred. |
## Overall Verdict
Go — every Mandatory criterion passes; the failed Optional criteria are deferred with an action item. Reviewed by AI as stand-in for S01; not independent of the author.
Full review (not a delta) after the change for MIL-011 (menu bar).
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Criterion 6 (Optional) failed: Story statement avoids technical implementation detail; fix or accept the deferral | S01 | 2026-10-21 |
| Criterion LANG 10 (Optional) failed: Abbreviations are spelled out on first use, in the stated language; fix or accept the deferral | S01 | 2026-10-21 |
---
[US-001]: ../../../docs/user-stories.md
[QC-US-001]: ../../../framework/qc/artifacts/qc-user-story.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[2211d0f]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/2211d0f4cbd8182314d18cbdefd939ae50c39e6d
+74
View File
@@ -0,0 +1,74 @@
# RC-058: Review of UC-001
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-058 |
| CrossReference | [UC-001], [QC-UC-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [2211d0f] |
---
## Artifact Under Review
- Instance reviewed: [UC-001]
- Checklist used: [QC-UC-001], and [QC-LANG-001] (language and domain)
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in for S01 reads the language and knows the domain)
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Consists of a single, concise paragraph summarizing only the primary success scenario | N-A | The format is Fully Dressed; the Brief format criterion does not apply. |
| 2 | Written as an informal multi-paragraph narrative; may mention some alternate flows without formal structure | N-A | The format is Fully Dressed; the Casual format criterion does not apply. |
| 3 | All standard sections are present: actors, preconditions, postconditions, main success scenario, alternative/exception flows | Pass | Scope, level, actor, stakeholders, pre- and postconditions, main success scenario and extensions are present. |
| 4 | Preconditions and postconditions are explicitly defined | Pass | Preconditions and postconditions are listed. |
| 5 | Primary actor is explicitly stated | Pass | Primary actor is `Learner`. |
| 6 | Stakeholders and their interests are stated | Pass | Stakeholders S01 and S02 and their interests are stated. |
| 7 | Main success scenario is written as clear, numbered steps | Pass | Main success scenario has 7 numbered steps. |
| 8 | Alternative/exception flows correctly reference `<<include>>`/`<<extend>>` use cases where relevant, per UML 2.5.1 | Pass | UCD-001 has no include or extend relationship, so no extension needs to reference one; the extensions (3a, 4a, 5a, 7a, 7b, 9a, *a) are plain alternative flows. |
| 9 | Explicit business rules are captured per step where applicable, rather than embedded loosely in narrative text | Pass | The Business Rules table gives a rule per step. |
| 10 | Naming of actors and use case title is consistent with the corresponding Use Case Diagram and User Stories | Pass | Title and actor match UCD-001 and US-001; the menu extension matches US-001.09 to US-001.12. |
| 11 | Scope/level (e.g. summary, user-goal, subfunction) is explicitly stated | Pass | `Level: user-goal` and `Scope: Flash Card program`. |
| 12 | Use case is written from the actor's goal perspective, free of UI or implementation detail | Pass | Steps are written as goals and answers; buttons, files and milliseconds are in the wireframe and milestones. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Metadata of UC-001 has `Language | en` and `Domain | it`; neither is a placeholder. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code and `it` is a value of the registry's domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | Prose and table cells are English; Malay and Danish words and file names appear only as quoted data. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | The registry gives `IT Professional English` for this type; the text is written for that reader. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The PO terms of DICT-001 (flash card, word list, words to learn, study session) are used and no synonym replaces them. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists beside the document (checked in `docs/`). |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no change of language or domain since an earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer is the stand-in for S01, the Product Owner, who reads English and knows the IT domain; no second language reviewer is needed (review-checklist-process step 2). Open to challenge by S01 in the end-of-run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | CSV, MVVM, UI, PO and similar abbreviations are not all spelled out at first use; Optional, deferred. |
## Overall Verdict
Go — every Mandatory criterion passes; the failed Optional criteria are deferred with an action item. Reviewed by AI as stand-in for S01; not independent of the author.
Full review (not a delta) after the change for MIL-011 (menu bar).
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Criterion LANG 10 (Optional) failed: Abbreviations are spelled out on first use, in the stated language; fix or accept the deferral | S01 | 2026-10-21 |
---
[UC-001]: ../../../docs/uc-001/uc.md
[QC-UC-001]: ../../../framework/qc/artifacts/qc-use-case.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[2211d0f]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/2211d0f4cbd8182314d18cbdefd939ae50c39e6d
@@ -0,0 +1,69 @@
# RC-059: Review of SSD-001
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-059 |
| CrossReference | [SSD-001], [QC-SSD-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [2211d0f] |
---
## Artifact Under Review
- Instance reviewed: [SSD-001]
- Checklist used: [QC-SSD-001], and [QC-LANG-001] (language and domain)
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in for S01 reads the language and knows the domain)
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Input/output messages match the corresponding Use Case's main success scenario step-for-step | Pass | System Operations table maps each message to steps of the main success scenario (1 to 9) or to the menu extension *a; the timer step is the one stated deviation. |
| 2 | Actor and System are treated strictly as black boxes (system shown as `:System`) | Pass | The system is `:System`; no internal object appears. |
| 3 | Object creation/destruction of the System instance handled explicitly where relevant | Pass | Lifecycle Notes state that the system lives for one run. |
| 4 | Return values are shown for operations that produce one, using dashed return arrows | Pass | Dashed return arrows are drawn for every message that returns something; `exit` returns nothing and ends the program. |
| 5 | Alternate/exceptional flows are represented separately (or explicitly out of scope noted) | Pass | The Alternate Flows section states the extensions that add no operation and that they are out of scope. |
| 6 | Message names are verb phrases consistent with the use case's system responsibilities | Pass | `startStudySession`, `markKnown` and `markUnknown` are verb phrases. |
| 7 | Diagram references the specific Use Case (name and ID) it depicts | Pass | Source Use Case section names UC-001 and the scenario. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Metadata of SSD-001 has `Language | en` and `Domain | it`; neither is a placeholder. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code and `it` is a value of the registry's domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | Prose and table cells are English; Malay and Danish words and file names appear only as quoted data. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | The registry gives `IT Professional English` for this type; the text is written for that reader. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The PO terms of DICT-001 (flash card, word list, words to learn, study session) are used and no synonym replaces them. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists beside the document (checked in `docs/`). |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no change of language or domain since an earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer is the stand-in for S01, the Product Owner, who reads English and knows the IT domain; no second language reviewer is needed (review-checklist-process step 2). Open to challenge by S01 in the end-of-run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | CSV, MVVM, UI, PO and similar abbreviations are not all spelled out at first use; Optional, deferred. |
## Overall Verdict
Go — every Mandatory criterion passes; the failed Optional criteria are deferred with an action item. Reviewed by AI as stand-in for S01; not independent of the author.
Full review (not a delta) after the change for MIL-011 (menu bar).
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Criterion LANG 10 (Optional) failed: Abbreviations are spelled out on first use, in the stated language; fix or accept the deferral | S01 | 2026-10-21 |
---
[SSD-001]: ../../../docs/uc-001/ssd.md
[QC-SSD-001]: ../../../framework/qc/artifacts/qc-ssd.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[2211d0f]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/2211d0f4cbd8182314d18cbdefd939ae50c39e6d
@@ -0,0 +1,53 @@
# RC-060: Review of OC-001
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-060 |
| CrossReference | [OC-001], [QC-OC-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [2211d0f] |
---
## Artifact Under Review
- Instance reviewed: [OC-001]
- Checklist used: [QC-OC-001]
- Scope: full review
- Language and domain: n/a (technical type)
- Language reviewer: none
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Method signature is complete: operation name, parameter types, and return type | Pass | Each contract gives name, parameter list and return type (`startStudySession(): CardDto | None`). |
| 2 | Preconditions explicitly list required state before execution | Pass | Preconditions are listed per contract. |
| 3 | Postconditions explicitly describe resulting state using Larman's "instance created/associated/attribute modified" style | Pass | Postconditions use created / associated / destroyed / attribute set wording. |
| 4 | Exceptions and error conditions are documented, including the triggering precondition failure | Pass | Each contract has an Exceptions table with the failing precondition. |
| 5 | Operation is explicitly traceable to a single SSD message | Pass | Each of the nine contracts traces to exactly one SSD message; the timer step has none and says so. |
| 6 | Contract avoids specifying implementation/algorithmic details (declarative, not procedural) | Pass | Postconditions are declarative. |
| 7 | Cross-references the Domain Model classes/associations affected by pre/postconditions | Pass | Domain Model concepts and IT terms are cited per contract. |
## Overall Verdict
Go — every Mandatory criterion passes. Reviewed by AI as stand-in for S01; not independent of the author.
Full review (not a delta) after the change for MIL-011 (menu bar).
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| none | - | - |
---
[OC-001]: ../../../docs/uc-001/oc.md
[QC-OC-001]: ../../../framework/qc/artifacts/qc-operation-contract.md
[2211d0f]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/2211d0f4cbd8182314d18cbdefd939ae50c39e6d
@@ -0,0 +1,54 @@
# RC-061: Review of SD-001
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-061 |
| CrossReference | [SD-001], [QC-SD-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [2211d0f] |
---
## Artifact Under Review
- Instance reviewed: [SD-001]
- Checklist used: [QC-SD-001]
- Scope: full review
- Language and domain: n/a (technical type)
- Language reviewer: none
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Message passing strictly follows UML sync/async/return arrow syntax | Pass | Calls are solid arrows with dashed returns. |
| 2 | GRASP/GoF patterns applied and explicitly annotated where used (e.g. Controller, Observer, Mediator, Factory) | Pass | Each sequence has a Pattern Annotations table (Creator, Information Expert, Null Object, MVVM, Repository). |
| 3 | Lifelines show activation bars matching actual processing time/call nesting | Pass | Activations are drawn for the session and the view model. |
| 4 | Object creation and destruction shown with correct UML notation (`create`/`destroy` messages, X on lifeline) | Pass | `create` is used for `Deck` and `StudySession`; no object is destroyed during the program's life and that is stated by omission, the process ends. |
| 5 | Diagram realizes the postconditions of a specific Operation Contract | Pass | Each of the six sequences has a Postcondition Coverage table for its contract in OC-001; `changeLevel`, `showContact` and `exit` are single calls and need no sequence. |
| 6 | Responsibility assignment favors low coupling/high cohesion (no god-object receiving all messages) | Pass | Responsibility Check notes state that no object receives all messages. |
| 7 | Loop, alt, and opt combined fragments used correctly for conditional/repeated behavior | Pass | `alt` and `opt` fragments are used for the progress file and the empty deck. |
| 8 | Each exception of the realized Operation Contract is shown as an `alt` or `opt` fragment, or its absence is justified | Fail | The exceptions of OC-001 (missing file, malformed file) are raised before the sequence starts and are not drawn as `alt` fragments; Optional, deferred. |
## Overall Verdict
Go — every Mandatory criterion passes; the failed Optional criteria are deferred with an action item. Reviewed by AI as stand-in for S01; not independent of the author.
Full review (not a delta) after the change for MIL-011 (menu bar).
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Criterion 8 (Optional) failed: Each exception of the realized Operation Contract is shown as an `alt` or `opt` fragment, ; fix or accept the deferral | S01 | 2026-10-21 |
---
[SD-001]: ../../../docs/uc-001/sd.md
[QC-SD-001]: ../../../framework/qc/artifacts/qc-sequence-diagram.md
[2211d0f]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/2211d0f4cbd8182314d18cbdefd939ae50c39e6d
@@ -0,0 +1,55 @@
# RC-062: Review of DCD-001
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-062 |
| CrossReference | [DCD-001], [QC-DCD-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [2211d0f] |
---
## Artifact Under Review
- Instance reviewed: [DCD-001]
- Checklist used: [QC-DCD-001]
- Scope: full review
- Language and domain: n/a (technical type)
- Language reviewer: none
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | SOLID principles applied; no god classes with excessive responsibilities | Pass | Each class has one responsibility (Class Table); `Application` is the controller of the commands and does not hold card rules. |
| 2 | Visibility markers correct and consistent (`+` public, `-` private, `#` protected) | Pass | Visibility markers are on all members. |
| 3 | Relationships correctly distinguished: Association vs Aggregation vs Composition vs Dependency | Pass | Composition (Vocabulary and Card, MenuViewModel and MenuEntry), aggregation (Deck), association, dependency and realization are distinguished. |
| 4 | Multiplicities and navigability specified on all associations | Pass | Multiplicities are on the associations; dependencies are directed. |
| 5 | Applied design patterns are annotated explicitly (e.g. Singleton, Factory, Strategy) | Pass | Pattern Annotations table lists Repository, Ports and adapters, Null Object, MVVM, Composition root. |
| 6 | Method signatures are traceable to Operation Contracts and/or design Sequence Diagrams | Pass | Method Traceability table maps every operation, including the menu and `Application` commands and `ProgressRepository.reset`, to OC-001 and SD-001. |
| 7 | Class names and structure remain consistent with the Domain Model concepts they refine | Pass | The Class Table has a `Refines` column; names match the dictionary's IT terms (`reset` added). |
| 8 | No circular dependencies between classes/packages unless explicitly justified | Pass | Dependency Check states there are no cycles. |
| 9 | Dependencies between classes and packages point inward: domain classes do not depend on infrastructure, delivery or framework classes | Pass | Domain imports nothing; infrastructure and presentation point inward (Dependency Check). |
## Overall Verdict
Go — every Mandatory criterion passes. Reviewed by AI as stand-in for S01; not independent of the author.
Full review (not a delta) after the change for MIL-011 (menu bar).
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| none | - | - |
---
[DCD-001]: ../../../docs/dcd.md
[QC-DCD-001]: ../../../framework/qc/artifacts/qc-dcd.md
[2211d0f]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/2211d0f4cbd8182314d18cbdefd939ae50c39e6d
@@ -0,0 +1,69 @@
# RC-063: Review of DICT-001
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-063 |
| CrossReference | [DICT-001], [QC-DICT-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [2211d0f] |
---
## Artifact Under Review
- Instance reviewed: [DICT-001]
- Checklist used: [QC-DICT-001], and [QC-LANG-001] (language and domain)
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in for S01 reads the language and knows the domain)
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Every row has a PO term, its language, an IT term and a definition | Pass | All 9 rows have PO term, language, IT term and definition. |
| 2 | Each PO term maps to exactly one IT term and the reverse (no synonyms) | Pass | One IT term per PO term; no synonym appears. |
| 3 | Every Domain Model concept has a row, and the Domain Model uses its PO term | Pass | The 5 concepts of DM-001 have a row and DM-001 uses the PO term; `Reset` was added. |
| 4 | The Operation Contracts, Sequence Diagrams, Design Class Diagrams and ERD use the IT term, not the PO term | Pass | DCD-001, OC-001 and SD-001 use `Card`, `Vocabulary`, `Deck`, `StudySession`. |
| 5 | Definitions are written in the PO language and are one sentence | Pass | Definitions are one English sentence each. |
| 6 | "Used as PO term in" and "Used as IT term in" name artifact types that exist in the project | Pass | Artifact types named in both columns exist in the project. |
| 7 | The dictionary's `Language` and `Domain` rows, and the language of every row, match the PO language and domain in the project registry | Pass | `Language | en` and `Domain | it` match the registry; every row says `en`. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Metadata of DICT-001 has `Language | en` and `Domain | it`; neither is a placeholder. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code and `it` is a value of the registry's domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | Prose and table cells are English; Malay and Danish words and file names appear only as quoted data. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | The registry gives `IT Professional English` for this type; the text is written for that reader. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The PO terms of DICT-001 (flash card, word list, words to learn, study session) are used and no synonym replaces them. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists beside the document (checked in `docs/`). |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no change of language or domain since an earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer is the stand-in for S01, the Product Owner, who reads English and knows the IT domain; no second language reviewer is needed (review-checklist-process step 2). Open to challenge by S01 in the end-of-run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | CSV, MVVM, UI, PO and similar abbreviations are not all spelled out at first use; Optional, deferred. |
## Overall Verdict
Go — every Mandatory criterion passes; the failed Optional criteria are deferred with an action item. Reviewed by AI as stand-in for S01; not independent of the author.
Full review (not a delta) after the change for MIL-011 (menu bar).
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Criterion LANG 10 (Optional) failed: Abbreviations are spelled out on first use, in the stated language; fix or accept the deferral | S01 | 2026-10-21 |
---
[DICT-001]: ../../../docs/dictionary.md
[QC-DICT-001]: ../../../framework/qc/artifacts/qc-dictionary.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[2211d0f]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/2211d0f4cbd8182314d18cbdefd939ae50c39e6d
@@ -0,0 +1,54 @@
# RC-064: Review of PP-001
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-064 |
| CrossReference | [PP-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [2211d0f] |
---
## Artifact Under Review
- Instance reviewed: [PP-001]
- Checklist used: none exists for this type, and [QC-LANG-001] (language and domain)
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in for S01 reads the language and knows the domain)
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Metadata of PP-001 has `Language | en` and `Domain | it`; neither is a placeholder. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code and `it` is a value of the registry's domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | Prose and table cells are English; Malay and Danish words and file names appear only as quoted data. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | The registry gives `IT Executive English` for this type; the text is written for that reader. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The PO terms of DICT-001 (flash card, word list, words to learn, study session) are used and no synonym replaces them. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists beside the document (checked in `docs/`). |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no change of language or domain since an earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer is the stand-in for S01, the Product Owner, who reads English and knows the IT domain; no second language reviewer is needed (review-checklist-process step 2). Open to challenge by S01 in the end-of-run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | CSV, MVVM, UI, PO and similar abbreviations are not all spelled out at first use; Optional, deferred. |
## Overall Verdict
Go — no checklist exists for the Project Plan type; the plan now schedules MIL-011 on 2026-10-17 inside the Business Case constraint (delivery by 2026-10-21) and the language checklist passes. Accepted as the Product Owner's stand-in, after the Product Owner accepted the MIL-011 plan in chat. Reviewed by AI as stand-in for S01; not independent of the author.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Criterion LANG 10 (Optional) failed: Abbreviations are spelled out on first use, in the stated language; fix or accept the deferral | S01 | 2026-10-21 |
---
[PP-001]: ../../../docs/project-plan.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[2211d0f]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/2211d0f4cbd8182314d18cbdefd939ae50c39e6d
+66
View File
@@ -0,0 +1,66 @@
# RC-065: Review of MIL-011
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-065 |
| CrossReference | [MIL-011], [QC-MIL-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [2211d0f] |
---
## Artifact Under Review
- Instance reviewed: [MIL-011]
- Checklist used: [QC-MIL-001], and [QC-LANG-001] (language and domain)
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in for S01 reads the language and knows the domain)
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | A concrete deliverable is defined for every gate | Pass | A concrete Deliverable section names the output evaluated at the gate. |
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | The Go / No-Go table has numbered criteria, each with an observable Go and No-Go. |
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Dependencies table names the milestone or documents it needs. |
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Traceability table maps to Business Case objectives and the user story. |
| 5 | Milestone owner and approving reviewer are identified | Pass | Ownership table names S01 as owner and approving reviewer. |
| 6 | Milestone has a defined target date consistent with project constraints | Pass | Target Date lies inside the 2026-10-14 to 2026-10-21 window of the Business Case. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Metadata of MIL-011 has `Language | en` and `Domain | it`; neither is a placeholder. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code and `it` is a value of the registry's domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | Prose and table cells are English; Malay and Danish words and file names appear only as quoted data. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | The registry gives `IT Executive English` for this type; the text is written for that reader. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The PO terms of DICT-001 (flash card, word list, words to learn, study session) are used and no synonym replaces them. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists beside the document (checked in `docs/`). |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no change of language or domain since an earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer is the stand-in for S01, the Product Owner, who reads English and knows the IT domain; no second language reviewer is needed (review-checklist-process step 2). Open to challenge by S01 in the end-of-run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | CSV, MVVM, UI, PO and similar abbreviations are not all spelled out at first use; Optional, deferred. |
## Overall Verdict
Go — every Mandatory criterion passes; the failed Optional criteria are deferred with an action item. Reviewed by AI as stand-in for S01; not independent of the author.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Criterion LANG 10 (Optional) failed: Abbreviations are spelled out on first use, in the stated language; fix or accept the deferral | S01 | 2026-10-21 |
---
[MIL-011]: ../../../docs/milestones/mil-011-menu-bar.md
[QC-MIL-001]: ../../../framework/qc/artifacts/qc-milestones-gateways.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[2211d0f]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/2211d0f4cbd8182314d18cbdefd939ae50c39e6d
+64
View File
@@ -0,0 +1,64 @@
# RC-066: Review of PY-MIL-011
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-066 |
| CrossReference | [PY-MIL-011], [QC-PY-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [ce4aacb] |
---
## Artifact Under Review
- Instance reviewed: [PY-MIL-011]
- Checklist used: [QC-PY-001]
- Scope: full review
- Language and domain: n/a (technical type)
- Language reviewer: none
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Packages, modules, functions, variables, classes and constants follow PEP 8 casing (`snake_case`, `PascalCase`, `UPPER_SNAKE`) | Pass | PEP 8 casing holds in the new modules (`menu_view.py`, `menu_view_model.py`, `progress_file_name.py`); ruff rule set N passes. |
| 2 | Names state purpose in the domain's language; no unexplained abbreviations, no single-letter names outside tiny scopes | Pass | Names state purpose and are the DCD-001 IT terms (`MenuView`, `MenuViewModel`, `Application.open_word_list`, `reset`). |
| 3 | Code is produced by the project's formatter and passes its linter with no unexplained suppressions | Pass | `ruff check` and `ruff format --check` pass on 79 files with no suppressions. |
| 4 | Every function and method signature is type-annotated, including `-> None` | Pass | Every signature is annotated; `mypy --strict` passes on 49 source files and on the three tool scripts. |
| 5 | No bare `except:`, no swallowed exceptions; specific exceptions are raised and the cause is kept (`raise ... from`) | Pass | Refused files raise `VocabularyFormatError` with `from` (also for bytes that are not UTF-8), a failed reset is logged and shown, a failed browser start is logged; no bare `except`, nothing swallowed silently. |
| 6 | No mutable default arguments and no shadowed builtins | Pass | No mutable defaults, no builtin shadowed. |
| 7 | Files, locks and connections are managed with context managers | Pass | Reading uses `with`; the delete uses `unlink(missing_ok=True)`; the Tk root is destroyed through `exit_application`. |
| 8 | Public modules, classes and functions have docstrings that say what, not how | Pass | New and changed members have Doxygen docstrings; `doxygen Doxyfile` ends with 0 warnings. |
| 9 | Logging uses `logging`, not `print`; no secrets or personal data in log output | Pass | No `print`; failures use `logging`; the contact data is public author information given by S01. |
| 10 | Classes and operations trace to the Design Class Diagram they implement; deviations are recorded | Pass | The new classes match the revised DCD-001 and OC-001/SD-001. Deviations: `MenuEntry` has a third field `underline`; `MenuViewModel` has `file_label` and `contact_menu_label`; `Application` has `word_list_folder` and takes a repository factory; `MenuView` depends on a small `MenuApplication` Protocol to avoid an import cycle. |
| 11 | Tests exist for new behaviour, are named for the behaviour, and do not depend on order or the network | Pass | 258 tests (5 consecutive full runs green): unit with fakes only, integration with two word lists, and e2e on the real menu bar with injected dialogs; none uses the network or a real browser. |
| 12 | Type checker runs in strict mode without errors; `Any` is justified in a comment | Pass | `mypy --strict` reports no issue; no `Any`. |
| 13 | Dependencies are declared and pinned in the project's dependency file, none unused | Pass | `dependencies` stays empty; `webbrowser`, `tkinter.filedialog` and `tkinter.messagebox` are standard library. |
| 14 | Each piece of knowledge (a business rule, constant, format, validation or query) is defined in one place; code is merged only where it expresses the same knowledge, not where it merely looks alike | Pass | The progress file rule is one function (`progress_file_name`); labels, contact data and dialog texts are constants once. |
| 15 | Imports point inward: business-rule modules import no framework, database, UI or delivery-mechanism code, and there are no import cycles | Pass | `lint-imports` reports `Layers point inward` kept; a grep finds no `tkinter`, `csv`, `random` or `webbrowser` import in `domain` or `application`; the menu view model imports no Tkinter. |
| 16 | SOLID holds: a class or module has one reason to change; new behaviour is added by extension, not by editing a type test in several places; subclasses honour the contract of their base; protocols are narrow; high-level code depends on protocols or abstract types and receives its implementations | Pass | The view model owns the entries and the view draws and asks dialogs; `Application` coordinates; the repositories own their files; dialogs and the browser are injected. |
| 17 | Source is laid out in the layers and folders of the clean architecture folder structure (`domain`, `application`, `infrastructure`, `presentation` packages under `src/`, and `unit`, `integration` and `e2e` under `tests/`), in `snake_case`, and imports between the layers point inward | Pass | `presentation/features/menu/` and `infrastructure/persistence/` follow the folder structure; tests stay in `unit`, `integration`, `e2e`. |
| 18 | File and folder names are English, contain no space and no character outside letters, digits, `-`, `_` and `.`, and follow the casing of the language for files | Pass | File and folder names follow the rule. |
## Overall Verdict
Go — every Mandatory criterion passes. Reviewed by AI as stand-in for S01; not independent of the author.
Milestone MIL-011 Go criteria: 1 the menu bar structure and order are read from the real `tk.Menu` (e2e); 2 open valid / invalid / cancelled covered (unit and e2e, including a Latin-1 file and invalid UTF-8 bytes); 3 two lists keep separate progress files, `ms-da.csv` keeps `words_to_learn.csv` (integration); 4 change level shows the level screen and keeps the known words (unit and e2e); 5 reset asks, deletes only the progress file of the open list, never the list file (unit, integration, e2e); 6 About, Contact opens `https://www.linkedin.com/in/tirsvad74` through an injected `webbrowser.open` (unit and e2e); 7 exit cancels the timer and destroys the window (e2e); 8 view model tested without Tkinter; 9 RC-056 to RC-065 `Go`, README and the Usage page of the wiki in three languages describe the menu; 10 this record, `pytest` 258 passed and linters clean. The executable was rebuilt with the menu and passes the smoke test (window, embedded list, list override, progress file). A real browser launch and the native file dialog were not exercised on this machine. Defect found by the reviewer and fixed in this milestone: a file that is not UTF-8 raised `UnicodeDecodeError` instead of a message. All Go.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| none | - | - |
---
[PY-MIL-011]: ../../../src/flash_card
[QC-PY-001]: ../../../framework/qc/code/qc-programming-python.md
[ce4aacb]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/ce4aacb4bc7ce742e3b2397e05a43572497402ef
@@ -0,0 +1,70 @@
# RC-067: Review of BC-001
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-067 |
| CrossReference | [BC-001], [QC-BC-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [0264b60] |
---
## Artifact Under Review
- Instance reviewed: [BC-001]
- Checklist used: [QC-BC-001], and [QC-LANG-001] (language and domain)
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in for S01 reads the language and knows the domain)
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | ROI/Cost-Benefit analysis is quantitative, or where qualitative, is explicitly justified | Pass | The Cost-Benefit table is qualitative and says why: no revenue is expected, so a quantitative return does not apply. |
| 2 | Risks are identified with documented impact and mitigation | Pass | The Risks table has 5 risks, each with an impact and a mitigation. |
| 3 | Success criteria are measurable, stating explicit targets rather than vague aspirations | Pass | The Success Criteria table has 8 rows with numeric targets and a measure each (for example 0 third-party packages; 5 commands or fewer). |
| 4 | Scope explicitly separates In Scope vs Out of Scope | Pass | Scope has `### In Scope` and `### Out of Scope`; the releases are In Scope, an installer and signing stay Out of Scope. |
| 5 | Stakeholders are cross-referenced to Stakeholder Analysis IDs rather than re-described inline | Pass | The Stakeholders table cites S01, S02 and S03 and does not re-describe their roles. |
| 6 | Methodology and quality-standard foundation are stated explicitly (e.g. ISO/IEC 25010, Larman) | Pass | Methodological and Standards Foundation names the framework, Larman, ISO/IEC 25010:2023 and PEP 8. |
| 7 | Assumptions and constraints are explicit and clearly distinguished from one another | Pass | Assumptions and Constraints are separate sections. |
| 8 | Document supports executive decision-making with a clear, unambiguous recommendation | Pass | Recommendation reads `Proceed` with a one-sentence rationale. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Metadata of BC-001 has `Language | en` and `Domain | it`; neither is a placeholder. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code and `it` is a value of the registry's domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | Prose and table cells are English; Malay and Danish words and file names appear only as quoted data. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | The registry gives `IT Executive English` for this type; the text is written for that reader. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The PO terms of DICT-001 (flash card, word list, words to learn, study session) are used and no synonym replaces them. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists beside the document (checked in `docs/`). |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no change of language or domain since an earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer is the stand-in for S01, the Product Owner, who reads English and knows the IT domain; no second language reviewer is needed (review-checklist-process step 2). Open to challenge by S01 in the end-of-run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | CSV, MVVM, UI, PO and similar abbreviations are not all spelled out at first use; Optional, deferred. |
## Overall Verdict
Go — every Mandatory criterion passes; the failed Optional criteria are deferred with an action item. Reviewed by AI as stand-in for S01; not independent of the author.
Full review (not a delta) after the change for MIL-012 (release v0.2.0).
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Criterion LANG 10 (Optional) failed: Abbreviations are spelled out on first use, in the stated language; fix or accept the deferral | S01 | 2026-10-21 |
---
[BC-001]: ../../../docs/business-case.md
[QC-BC-001]: ../../../framework/qc/artifacts/qc-business-case.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[0264b60]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/0264b6084f26bac5af716ea71596ce3be961fec8
@@ -0,0 +1,70 @@
# RC-068: Review of US-001
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-068 |
| CrossReference | [US-001], [QC-US-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [0264b60] |
---
## Artifact Under Review
- Instance reviewed: [US-001]
- Checklist used: [QC-US-001], and [QC-LANG-001] (language and domain)
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in for S01 reads the language and knows the domain)
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Follows INVEST criteria (Independent, Negotiable, Valuable, Estimable, Small, Testable) | Pass | INVEST Check section confirms the six properties for all twelve stories and states one dependency exception. |
| 2 | Written in "As a / I want / So that" form | Pass | All twelve stories use `As a / I want / so that`. |
| 3 | Clear, testable acceptance criteria are included | Pass | Every story, including US-001.08 in its new wording, has Given/When/Then acceptance criteria. |
| 4 | Traceable to a use case or epic | Pass | Every story traces to a milestone and to UC-001. |
| 5 | Story is sized to fit within a single iteration | Pass | Each story is one milestone, which fits one iteration. |
| 6 | Story statement avoids technical implementation detail | Fail | Acceptance criteria name `words_to_learn.csv`, `ms-da.csv` and 3000 ms, which are assignment-mandated names and values rather than pure behaviour. |
| 7 | Role named in the story matches an actor defined in the Use Case Diagram | Pass | The role `Learner` is the actor of UCD-001. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Metadata of US-001 has `Language | en` and `Domain | it`; neither is a placeholder. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code and `it` is a value of the registry's domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | Prose and table cells are English; Malay and Danish words and file names appear only as quoted data. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | The registry gives `IT Professional English` for this type; the text is written for that reader. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The PO terms of DICT-001 (flash card, word list, words to learn, study session) are used and no synonym replaces them. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists beside the document (checked in `docs/`). |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no change of language or domain since an earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer is the stand-in for S01, the Product Owner, who reads English and knows the IT domain; no second language reviewer is needed (review-checklist-process step 2). Open to challenge by S01 in the end-of-run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | CSV, MVVM, UI, PO and similar abbreviations are not all spelled out at first use; Optional, deferred. |
## Overall Verdict
Go — every Mandatory criterion passes; the failed Optional criteria are deferred with an action item. Reviewed by AI as stand-in for S01; not independent of the author.
Full review (not a delta) after the change for MIL-012 (release v0.2.0).
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Criterion 6 (Optional) failed: Story statement avoids technical implementation detail; fix or accept the deferral | S01 | 2026-10-21 |
| Criterion LANG 10 (Optional) failed: Abbreviations are spelled out on first use, in the stated language; fix or accept the deferral | S01 | 2026-10-21 |
---
[US-001]: ../../../docs/user-stories.md
[QC-US-001]: ../../../framework/qc/artifacts/qc-user-story.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[0264b60]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/0264b6084f26bac5af716ea71596ce3be961fec8
@@ -0,0 +1,54 @@
# RC-069: Review of PP-001
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-069 |
| CrossReference | [PP-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [0264b60] |
---
## Artifact Under Review
- Instance reviewed: [PP-001]
- Checklist used: none exists for this type, and [QC-LANG-001] (language and domain)
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in for S01 reads the language and knows the domain)
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Metadata of PP-001 has `Language | en` and `Domain | it`; neither is a placeholder. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code and `it` is a value of the registry's domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | Prose and table cells are English; Malay and Danish words and file names appear only as quoted data. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | The registry gives `IT Executive English` for this type; the text is written for that reader. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The PO terms of DICT-001 (flash card, word list, words to learn, study session) are used and no synonym replaces them. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists beside the document (checked in `docs/`). |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no change of language or domain since an earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer is the stand-in for S01, the Product Owner, who reads English and knows the IT domain; no second language reviewer is needed (review-checklist-process step 2). Open to challenge by S01 in the end-of-run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | CSV, MVVM, UI, PO and similar abbreviations are not all spelled out at first use; Optional, deferred. |
## Overall Verdict
Go — no checklist exists for the Project Plan type; the plan now schedules MIL-012 on 2026-10-18 inside the Business Case constraint (delivery by 2026-10-21) and the language checklist passes. Accepted as the Product Owner's stand-in, after the Product Owner accepted the MIL-012 plan in chat. Reviewed by AI as stand-in for S01; not independent of the author.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Criterion LANG 10 (Optional) failed: Abbreviations are spelled out on first use, in the stated language; fix or accept the deferral | S01 | 2026-10-21 |
---
[PP-001]: ../../../docs/project-plan.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[0264b60]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/0264b6084f26bac5af716ea71596ce3be961fec8
+66
View File
@@ -0,0 +1,66 @@
# RC-070: Review of MIL-012
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-070 |
| CrossReference | [MIL-012], [QC-MIL-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [0264b60] |
---
## Artifact Under Review
- Instance reviewed: [MIL-012]
- Checklist used: [QC-MIL-001], and [QC-LANG-001] (language and domain)
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in for S01 reads the language and knows the domain)
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | A concrete deliverable is defined for every gate | Pass | A concrete Deliverable section names the output evaluated at the gate. |
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | The Go / No-Go table has numbered criteria, each with an observable Go and No-Go. |
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Dependencies table names the milestone or documents it needs. |
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Traceability table maps to Business Case objectives and the user story. |
| 5 | Milestone owner and approving reviewer are identified | Pass | Ownership table names S01 as owner and approving reviewer. |
| 6 | Milestone has a defined target date consistent with project constraints | Pass | Target Date lies inside the 2026-10-14 to 2026-10-21 window of the Business Case. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Metadata of MIL-012 has `Language | en` and `Domain | it`; neither is a placeholder. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code and `it` is a value of the registry's domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | Prose and table cells are English; Malay and Danish words and file names appear only as quoted data. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | The registry gives `IT Executive English` for this type; the text is written for that reader. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The PO terms of DICT-001 (flash card, word list, words to learn, study session) are used and no synonym replaces them. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists beside the document (checked in `docs/`). |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no change of language or domain since an earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer is the stand-in for S01, the Product Owner, who reads English and knows the IT domain; no second language reviewer is needed (review-checklist-process step 2). Open to challenge by S01 in the end-of-run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | CSV, MVVM, UI, PO and similar abbreviations are not all spelled out at first use; Optional, deferred. |
## Overall Verdict
Go — every Mandatory criterion passes; the failed Optional criteria are deferred with an action item. Reviewed by AI as stand-in for S01; not independent of the author.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Criterion LANG 10 (Optional) failed: Abbreviations are spelled out on first use, in the stated language; fix or accept the deferral | S01 | 2026-10-21 |
---
[MIL-012]: ../../../docs/milestones/mil-012-release-0-2-0.md
[QC-MIL-001]: ../../../framework/qc/artifacts/qc-milestones-gateways.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[0264b60]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/0264b6084f26bac5af716ea71596ce3be961fec8
+64
View File
@@ -0,0 +1,64 @@
# RC-071: Review of PY-MIL-012
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-071 |
| CrossReference | [PY-MIL-012], [QC-PY-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [7c1f1b6] |
---
## Artifact Under Review
- Instance reviewed: [PY-MIL-012]
- Checklist used: [QC-PY-001]
- Scope: full review
- Language and domain: n/a (technical type)
- Language reviewer: none
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Packages, modules, functions, variables, classes and constants follow PEP 8 casing (`snake_case`, `PascalCase`, `UPPER_SNAKE`) | Pass | The change is one assignment and a test module; names follow PEP 8. |
| 2 | Names state purpose in the domain's language; no unexplained abbreviations, no single-letter names outside tiny scopes | Pass | `test_version_of_the_package_equals_pyproject_version` and similar names state the behaviour. |
| 3 | Code is produced by the project's formatter and passes its linter with no unexplained suppressions | Pass | `ruff check` and `ruff format --check` pass with no suppressions. |
| 4 | Every function and method signature is type-annotated, including `-> None` | Pass | Test functions are annotated `-> None`; `mypy --strict` passes on 49 source files. |
| 5 | No bare `except:`, no swallowed exceptions; specific exceptions are raised and the cause is kept (`raise ... from`) | Pass | No exception handling in the change. |
| 6 | No mutable default arguments and no shadowed builtins | Pass | No mutable defaults. |
| 7 | Files, locks and connections are managed with context managers | Pass | `pyproject.toml` is read with `tomllib` through a `with open` context. |
| 8 | Public modules, classes and functions have docstrings that say what, not how | Pass | The module docstring keeps `@file` and `@brief`; `doxygen Doxyfile` ends with 0 warnings. |
| 9 | Logging uses `logging`, not `print`; no secrets or personal data in log output | Pass | No `print`, no logging in the change. |
| 10 | Classes and operations trace to the Design Class Diagram they implement; deviations are recorded | Pass | No class or operation changed; the version string is not part of the design. |
| 11 | Tests exist for new behaviour, are named for the behaviour, and do not depend on order or the network | Pass | 3 tests compare `__version__`, `pyproject.toml` and the `Doxyfile` `PROJECT_NUMBER` and the `MAJOR.MINOR.PATCH` form; 3 consecutive full runs (261 tests) green. |
| 12 | Type checker runs in strict mode without errors; `Any` is justified in a comment | Pass | `mypy --strict` reports no issue. |
| 13 | Dependencies are declared and pinned in the project's dependency file, none unused | Pass | `dependencies` stays empty; `tomllib` is standard library. |
| 14 | Each piece of knowledge (a business rule, constant, format, validation or query) is defined in one place; code is merged only where it expresses the same knowledge, not where it merely looks alike | Pass | The version is stated once per file type; the test makes the three places agree. |
| 15 | Imports point inward: business-rule modules import no framework, database, UI or delivery-mechanism code, and there are no import cycles | Pass | `lint-imports` reports `Layers point inward` kept. |
| 16 | SOLID holds: a class or module has one reason to change; new behaviour is added by extension, not by editing a type test in several places; subclasses honour the contract of their base; protocols are narrow; high-level code depends on protocols or abstract types and receives its implementations | Pass | One test module with one reason to change. |
| 17 | Source is laid out in the layers and folders of the clean architecture folder structure (`domain`, `application`, `infrastructure`, `presentation` packages under `src/`, and `unit`, `integration` and `e2e` under `tests/`), in `snake_case`, and imports between the layers point inward | Pass | The test sits in `tests/unit`. |
| 18 | File and folder names are English, contain no space and no character outside letters, digits, `-`, `_` and `.`, and follow the casing of the language for files | Pass | File names follow the rule. |
## Overall Verdict
Go — every Mandatory criterion passes. Reviewed by AI as stand-in for S01; not independent of the author.
Milestone MIL-012 tasks 2, 3, 4 and 8 (this change set): 1 the three version places say 0.2.0 and a test fails if they differ; 2 CHANGELOG has `[0.2.0]` and `[0.1.0]` is unchanged; 3 the upload limit probe ran before the build: a draft release with a 1 MB random file was refused with `413 Request Entity Too Large`, so the largest accepted size is below 1 MB; the draft release and its tag were deleted afterwards (the tag list and the release list were checked); 8 README, CHANGELOG and the Install page of the wiki in three languages link v0.2.0 and say that the executable is not attached; `check-readme.sh` exit 0. The tag, the build and the release are criteria 4 to 7 and are recorded in a separate review record. Go.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| none | - | - |
---
[PY-MIL-012]: ../../../src/flash_card/__init__.py
[QC-PY-001]: ../../../framework/qc/code/qc-programming-python.md
[7c1f1b6]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/7c1f1b6423a876d25afafd24f7f206d16ac6d669
+54
View File
@@ -0,0 +1,54 @@
# RC-072: Review of the release v0.2.0
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-072 |
| CrossReference | [MIL-012] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [5345fd7] |
---
## Artifact Under Review
- Instance reviewed: [MIL-012] (the milestone's Go / No-Go criteria, checked against the release v0.2.0)
- Checklist used: none exists for a release; the nine criteria of MIL-012 are the checklist
- Scope: full review
- Language and domain: n/a (record of results)
- Language reviewer: none
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The three version places say `0.2.0` and a test fails when they differ | Pass | `pyproject.toml`, `flash_card.__version__` and `Doxyfile` say 0.2.0; `tests/unit/test_version.py` (3 tests) |
| 2 | `CHANGELOG.md` has a `[0.2.0]` entry (menu bar, progress per word list, UTF-8 message) and `[0.1.0]` is unchanged | Pass | Read in the pull request #94 |
| 3 | The upload limit of the git host is probed before the build with a draft release that is deleted afterwards, and the result is recorded | Pass | A draft release with a 1 MB random file was refused with `413 Request Entity Too Large`; the draft and its tag were deleted (release and tag lists checked) |
| 4 | The executable is built with `--clean` from the commit to be tagged and passes the smoke test of MIL-009 | Fail | Built with `--clean` from `d7ca24d` (25.8 MB). The first smoke run passed three cases (level screen window, embedded list, progress file with 999 cards at level 100); the list override case failed once because the simulated mouse click did not register, and in 3 of 8 reruns the same click was lost. The cause was not found: it may be the click automation (timing of the pointer and the focus) or a defect of the program. The checks were stopped at the Product Owner's request because they take over the desktop, and are to be repeated in a container or on an isolated desktop (MIL-013) |
| 5 | The tag `v0.2.0` is an annotated tag on that commit; `v0.1.0` is not moved | Fail | The tag points to `d7ca24d` and `v0.1.0` is unchanged (`2c580cc`), but the tag is lightweight: the push of my annotated tag failed on a connection error, and the release creation through the API then created a lightweight tag. Replacing it needs a force update of a tag, which is outside what an autonomous run may do without the Product Owner |
| 6 | The release `v0.2.0` is published with notes (new, unsigned, `data` folder rule, how to build) | Pass | Release page returns HTTP 200; notes say what is new, that the file is unsigned, the `data` folder and how to build |
| 7 | When the probe did not allow it: the notes say so and the issue "attach the files" stays open | Pass | The notes state that the executable is not attached and why; issue "Create the release and attach the files" stays open |
| 8 | README, CHANGELOG and the Install page of the wiki in three languages link `v0.2.0`; `check-readme.sh` exit 0 | Pass | Merged in #94; wiki republished |
| 9 | `pytest`, `ruff`, `mypy --strict`, `lint-imports` and `doxygen` are clean; BC-001, US-001 and PP-001 reviewed `Go` | Pass | 261 passed; RC-067 to RC-069 |
## Overall Verdict
Go-with-conditions — the version, the CHANGELOG, the tag (lightweight) and the release page are in place, and the executable is correctly stated as not attached. Criteria 4 and 5 fail or are incomplete: the smoke test of the executable is not complete, and the tag is not annotated. Reviewed by AI as stand-in for S01; not independent of the author.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Decide whether the lightweight tag `v0.2.0` may be replaced by an annotated tag on the same commit (a force update of the tag on the host); `v0.1.0` stays | S01 | 2026-10-18 |
| Repeat the smoke test of the executable on an isolated desktop or in a container and find the cause of the lost click (criterion 4), then close the issue "Build and smoke-test the executable" | S01 | 2026-10-21 |
| Attach `flash-card.exe` and its checksum when the git host's upload limit is raised (issue "Create the release and attach the files") | S01 | 2026-10-21 |
---
[MIL-012]: ../milestones/mil-012-release-0-2-0.md
[5345fd7]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/5345fd77d404b7a8b7c3722fa5ada2bf14f234a7
@@ -0,0 +1,70 @@
# RC-073: Review of BC-001
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-073 |
| CrossReference | [BC-001], [QC-BC-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [f86bc91] |
---
## Artifact Under Review
- Instance reviewed: [BC-001]
- Checklist used: [QC-BC-001], and [QC-LANG-001] (language and domain)
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in for S01 reads the language and knows the domain)
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | ROI/Cost-Benefit analysis is quantitative, or where qualitative, is explicitly justified | Pass | The Cost-Benefit table is qualitative and says why: no revenue is expected, so a quantitative return does not apply. |
| 2 | Risks are identified with documented impact and mitigation | Pass | The Risks table has 5 risks, each with an impact and a mitigation. |
| 3 | Success criteria are measurable, stating explicit targets rather than vague aspirations | Pass | The Success Criteria table has 8 rows with numeric targets and a measure each (for example 0 third-party packages; 5 commands or fewer). |
| 4 | Scope explicitly separates In Scope vs Out of Scope | Pass | Scope has `### In Scope` and `### Out of Scope`; the container and sandbox checks are In Scope; macOS and other virtual machines are Out of Scope. |
| 5 | Stakeholders are cross-referenced to Stakeholder Analysis IDs rather than re-described inline | Pass | The Stakeholders table cites S01, S02 and S03 and does not re-describe their roles. |
| 6 | Methodology and quality-standard foundation are stated explicitly (e.g. ISO/IEC 25010, Larman) | Pass | Methodological and Standards Foundation names the framework, Larman, ISO/IEC 25010:2023 and PEP 8. |
| 7 | Assumptions and constraints are explicit and clearly distinguished from one another | Pass | Assumptions and Constraints are separate sections. |
| 8 | Document supports executive decision-making with a clear, unambiguous recommendation | Pass | Recommendation reads `Proceed` with a one-sentence rationale. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Metadata of BC-001 has `Language | en` and `Domain | it`; neither is a placeholder. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code and `it` is a value of the registry's domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | Prose and table cells are English; Malay and Danish words and file names appear only as quoted data. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | The registry gives `IT Executive English` for this type; the text is written for that reader. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The PO terms of DICT-001 (flash card, word list, words to learn, study session) are used and no synonym replaces them. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists beside the document (checked in `docs/`). |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no change of language or domain since an earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer is the stand-in for S01, the Product Owner, who reads English and knows the IT domain; no second language reviewer is needed (review-checklist-process step 2). Open to challenge by S01 in the end-of-run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | CSV, MVVM, UI, PO and similar abbreviations are not all spelled out at first use; Optional, deferred. |
## Overall Verdict
Go — every Mandatory criterion passes; the failed Optional criteria are deferred with an action item. Reviewed by AI as stand-in for S01; not independent of the author.
Full review (not a delta) after the change for MIL-013 (container and sandbox checks).
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Criterion LANG 10 (Optional) failed: Abbreviations are spelled out on first use, in the stated language; fix or accept the deferral | S01 | 2026-10-21 |
---
[BC-001]: ../../../docs/business-case.md
[QC-BC-001]: ../../../framework/qc/artifacts/qc-business-case.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[f86bc91]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/f86bc9136e7719fbcd049a4f803959019b7d2df3
@@ -0,0 +1,54 @@
# RC-074: Review of PP-001
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-074 |
| CrossReference | [PP-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [f86bc91] |
---
## Artifact Under Review
- Instance reviewed: [PP-001]
- Checklist used: none exists for this type, and [QC-LANG-001] (language and domain)
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in for S01 reads the language and knows the domain)
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Metadata of PP-001 has `Language | en` and `Domain | it`; neither is a placeholder. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code and `it` is a value of the registry's domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | Prose and table cells are English; Malay and Danish words and file names appear only as quoted data. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | The registry gives `IT Executive English` for this type; the text is written for that reader. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The PO terms of DICT-001 (flash card, word list, words to learn, study session) are used and no synonym replaces them. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists beside the document (checked in `docs/`). |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no change of language or domain since an earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer is the stand-in for S01, the Product Owner, who reads English and knows the IT domain; no second language reviewer is needed (review-checklist-process step 2). Open to challenge by S01 in the end-of-run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | CSV, MVVM, UI, PO and similar abbreviations are not all spelled out at first use; Optional, deferred. |
## Overall Verdict
Go — no checklist exists for the Project Plan type; the plan now schedules MIL-013 on 2026-10-19 inside the Business Case constraint (delivery by 2026-10-21) and the language checklist passes. Accepted as the Product Owner's stand-in, after the Product Owner accepted the MIL-013 plan in chat. Reviewed by AI as stand-in for S01; not independent of the author.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Criterion LANG 10 (Optional) failed: Abbreviations are spelled out on first use, in the stated language; fix or accept the deferral | S01 | 2026-10-21 |
---
[PP-001]: ../../../docs/project-plan.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[f86bc91]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/f86bc9136e7719fbcd049a4f803959019b7d2df3
+55
View File
@@ -0,0 +1,55 @@
# RC-075: Review of ADR-0005
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-075 |
| CrossReference | [ADR-0005], [QC-ADR-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [f86bc91] |
---
## Artifact Under Review
- Instance reviewed: [ADR-0005]
- Checklist used: [QC-ADR-001]
- Scope: full review
- Language and domain: n/a (technical type)
- Language reviewer: none
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The ID (`ADR-NNNN`, 4-digit) matches the filename number and is unique and sequential | Pass | ID `ADR-0005` matches the file name number. |
| 2 | Context states the problem, the forces (cost, risk, constraints) and the options evaluated | Pass | Context states the problem (the host desktop is taken over) and four options. |
| 3 | At least two options were considered, or the absence of alternatives is justified | Pass | Four options were considered. |
| 4 | Decision is stated in one or two unhedged sentences and matches one of the evaluated options | Pass | Decision is stated plainly and is option 2. |
| 5 | Consequences list both Positive and Negative outcomes | Pass | Consequences have Positive and Negative lists. |
| 6 | Quality-attribute impacts (performance, security, portability, etc.) are named where the decision affects them | Pass | Portability, repeatability, image size and the weaker fallback are named. |
| 7 | Affected Artifacts are listed as links, and each is also in CrossReference | Pass | Affected Artifacts BC-001 and ADR-0004 are listed and in CrossReference. |
| 8 | Status changes are recorded as new Version History rows with a Change summary and Commit link; retained rows are never rewritten | Pass | First version; no status change yet. |
| 9 | A superseded or deprecated ADR names its successor, and the successor links back | N-A | Not superseded or deprecated. |
| 10 | Written in business or technical language of the domain, with no unexplained abbreviations | Pass | Written in plain technical English; product names are as the vendors write them. |
| 11 | Status is one of `Proposed`, `Accepted`, `Rejected`, `Deprecated` or `Superseded by ADR-NNNN`, and every Version History row uses only these | Pass | Status `Proposed` before this review; uses an allowed value. |
## Overall Verdict
Go — every Mandatory criterion passes. Reviewed by AI as stand-in for S01; not independent of the author.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| none | - | - |
---
[ADR-0005]: ../../../docs/adr/adr-0005-container-and-sandbox-checks.md
[QC-ADR-001]: ../../../framework/qc/artifacts/qc-adr.md
[f86bc91]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/f86bc9136e7719fbcd049a4f803959019b7d2df3
+66
View File
@@ -0,0 +1,66 @@
# RC-076: Review of MIL-013
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-076 |
| CrossReference | [MIL-013], [QC-MIL-001], [QC-LANG-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [f86bc91] |
---
## Artifact Under Review
- Instance reviewed: [MIL-013]
- Checklist used: [QC-MIL-001], and [QC-LANG-001] (language and domain)
- Scope: full review
- Language and domain: en / it
- Language reviewer: none (the stand-in for S01 reads the language and knows the domain)
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | A concrete deliverable is defined for every gate | Pass | A concrete Deliverable section names the output evaluated at the gate. |
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | The Go / No-Go table has numbered criteria, each with an observable Go and No-Go. |
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Dependencies table names the milestone or documents it needs. |
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Traceability table maps to Business Case objectives and the user story. |
| 5 | Milestone owner and approving reviewer are identified | Pass | Ownership table names S01 as owner and approving reviewer. |
| 6 | Milestone has a defined target date consistent with project constraints | Pass | Target Date lies inside the 2026-10-14 to 2026-10-21 window of the Business Case. |
## Language and Domain Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Metadata of MIL-013 has `Language | en` and `Domain | it`; neither is a placeholder. |
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | `en` is a BCP 47 code and `it` is a value of the registry's domain list. |
| 3 | The content (prose and table cells) is written in the stated language | Pass | Prose and table cells are English; Malay and Danish words and file names appear only as quoted data. |
| 4 | The register matches the one the registry gives for the artifact type | Pass | The registry gives `IT Executive English` for this type; the text is written for that reader. |
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | The PO terms of DICT-001 (flash card, word list, words to learn, study session) are used and no synonym replaces them. |
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. |
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No translated twin exists beside the document (checked in `docs/`). |
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no change of language or domain since an earlier accepted version. |
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The reviewer is the stand-in for S01, the Product Owner, who reads English and knows the IT domain; no second language reviewer is needed (review-checklist-process step 2). Open to challenge by S01 in the end-of-run summary. |
| 10 | Abbreviations are spelled out on first use, in the stated language | Fail | CSV, MVVM, UI, PO and similar abbreviations are not all spelled out at first use; Optional, deferred. |
## Overall Verdict
Go — every Mandatory criterion passes; the failed Optional criteria are deferred with an action item. Reviewed by AI as stand-in for S01; not independent of the author.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Criterion LANG 10 (Optional) failed: Abbreviations are spelled out on first use, in the stated language; fix or accept the deferral | S01 | 2026-10-21 |
---
[MIL-013]: ../../../docs/milestones/mil-013-container-checks.md
[QC-MIL-001]: ../../../framework/qc/artifacts/qc-milestones-gateways.md
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
[f86bc91]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/f86bc9136e7719fbcd049a4f803959019b7d2df3
+64
View File
@@ -0,0 +1,64 @@
# RC-077: Review of PY-MIL-013
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-077 |
| CrossReference | [PY-MIL-013], [QC-PY-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [f8ccfca] |
---
## Artifact Under Review
- Instance reviewed: [PY-MIL-013]
- Checklist used: [QC-PY-001]
- Scope: full review
- Language and domain: n/a (technical type)
- Language reviewer: none
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Packages, modules, functions, variables, classes and constants follow PEP 8 casing (`snake_case`, `PascalCase`, `UPPER_SNAKE`) | Pass | PEP 8 casing holds in `smoke_driver.py`, `capture_screenshots.py` and the new tests; ruff rule set N passes. |
| 2 | Names state purpose in the domain's language; no unexplained abbreviations, no single-letter names outside tiny scopes | Pass | Names state purpose (`known_button_point`, `parse_geometry`, `platform_kind`, `window_box`, `progress_ok`). |
| 3 | Code is produced by the project's formatter and passes its linter with no unexplained suppressions | Pass | `ruff check` and `ruff format --check` pass on 83 files; the one `type: ignore` for `os.killpg` names the errors it silences. |
| 4 | Every function and method signature is type-annotated, including `-> None` | Pass | Every signature is annotated; `mypy --strict` passes on 49 source files and on the four tool scripts. |
| 5 | No bare `except:`, no swallowed exceptions; specific exceptions are raised and the cause is kept (`raise ... from`) | Pass | Process start and stop failures are turned into a failed run with its reason, not swallowed; no bare `except`. |
| 6 | No mutable default arguments and no shadowed builtins | Pass | No mutable defaults, no builtin shadowed. |
| 7 | Files, locks and connections are managed with context managers | Pass | Temporary folders are context-managed or removed in `finally`; processes are stopped as a group. |
| 8 | Public modules, classes and functions have docstrings that say what, not how | Pass | Public modules, functions and constants have Doxygen docstrings; `doxygen Doxyfile` covers `src` and ends with 0 warnings. |
| 9 | Logging uses `logging`, not `print`; no secrets or personal data in log output | Pass | No `print` in `src`; the tools write results with `sys.stdout.write` as JSON lines. |
| 10 | Classes and operations trace to the Design Class Diagram they implement; deviations are recorded | Pass | No program class changed; the tools are packaging and check support outside the design classes (ADR-0005). |
| 11 | Tests exist for new behaviour, are named for the behaviour, and do not depend on order or the network | Pass | 272 tests; the pure parts of the smoke driver and the capture tool are unit tested with fakes (no xdotool, no display); the whole suite passed twice in the Debian container including the real-window e2e tests. |
| 12 | Type checker runs in strict mode without errors; `Any` is justified in a comment | Pass | `mypy --strict` reports no issue; no `Any`. |
| 13 | Dependencies are declared and pinned in the project's dependency file, none unused | Pass | `dependencies` stays empty; the container image installs the extras `dev`, `speech`, `tools` and `build`. |
| 14 | Each piece of knowledge (a business rule, constant, format, validation or query) is defined in one place; code is merged only where it expresses the same knowledge, not where it merely looks alike | Pass | The click point, the geometry parsing and the success rule are one function each in `smoke_driver.py`. |
| 15 | Imports point inward: business-rule modules import no framework, database, UI or delivery-mechanism code, and there are no import cycles | Pass | `lint-imports` reports `Layers point inward` kept; the tools import only the composition root. |
| 16 | SOLID holds: a class or module has one reason to change; new behaviour is added by extension, not by editing a type test in several places; subclasses honour the contract of their base; protocols are narrow; high-level code depends on protocols or abstract types and receives its implementations | Pass | Pure functions with injected `run`, `start` and `sleep`; no function mixes the platform choice with drawing. |
| 17 | Source is laid out in the layers and folders of the clean architecture folder structure (`domain`, `application`, `infrastructure`, `presentation` packages under `src/`, and `unit`, `integration` and `e2e` under `tests/`), in `snake_case`, and imports between the layers point inward | Pass | `tools/docker/` holds the container scripts and the driver; the layers and the test folders are unchanged. |
| 18 | File and folder names are English, contain no space and no character outside letters, digits, `-`, `_` and `.`, and follow the casing of the language for files | Pass | File and folder names follow the rule. |
## Overall Verdict
Go — every Mandatory criterion passes. Reviewed by AI as stand-in for S01; not independent of the author.
Reviewed in the Debian container (python:3.13-slim-bookworm, Python 3.13.16).
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| none | - | - |
---
[PY-MIL-013]: ../../../tools
[QC-PY-001]: ../../../framework/qc/code/qc-programming-python.md
[f8ccfca]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/f8ccfca02ef3a518eae472e3acdcd2aef03b5950
+61
View File
@@ -0,0 +1,61 @@
# RC-078: Review of SH-MIL-013
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-078 |
| CrossReference | [SH-MIL-013], [QC-SH-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [f8ccfca] |
---
## Artifact Under Review
- Instance reviewed: [SH-MIL-013]
- Checklist used: [QC-SH-001]
- Scope: full review
- Language and domain: n/a (technical type)
- Language reviewer: none
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Starts with `#!/usr/bin/env bash` and `set -euo pipefail` (or a comment explains the exception) | Pass | Every executable script starts with `#!/usr/bin/env bash` and `set -euo pipefail`; `start-desktop.sh` is sourced, says so in its header and sets no shell options in the caller. |
| 2 | Every expansion is quoted; lists are arrays; tests use `[[ ]]` and `$(...)` | Pass | Expansions are quoted, tests use `[[ ]]`, command substitutions use `$(...)`; shellcheck reports nothing. |
| 3 | Names follow the conventions: `kebab-case.sh` files, `snake_case` functions and variables, `UPPER_SNAKE` constants and environment variables | Pass | File names are kebab-case; variables are snake_case, environment variables UPPER_SNAKE. |
| 4 | Passes `shellcheck` and `bash -n` with no unexplained `disable` comments | Pass | `shellcheck -x` and `bash -n` pass on all six scripts with no `disable` comment. |
| 5 | Errors go to standard error with an `error:` message and a non-zero exit code; bad or missing arguments print a usage line | Pass | Errors go to standard error with `error:`, a usage line is printed, and bad arguments exit with 2 (`selftest.sh` checks it). |
| 6 | Temporary files use `mktemp` with a `trap ... EXIT` cleanup; no fixed `/tmp` names | Pass | `start-desktop.sh` uses `mktemp -d` with a `trap ... EXIT`; no fixed `/tmp` names remain. |
| 7 | No secret is written in the script, echoed, or put on a command line; secrets come from the environment or a gitignored file | Pass | No secret is used or written. |
| 8 | A script that changes state outside its own directory defaults to a dry run or needs an explicit flag, and says so in its header | Pass | `in-container.sh` is the only script that deletes a folder; its header says so and it refuses the repository and `/` as work folder. |
| 9 | A header comment states purpose, usage, options, environment variables and exit codes | Pass | Each header gives purpose, usage, environment, tools and exit codes. |
| 10 | The script implements a task or design it cites; deviations are recorded | Pass | The scripts implement tasks 3, 4 and 6 of MIL-013 and ADR-0005; the fallback from GNOME Shell to mutter is recorded in the output. |
| 11 | Behaviour is tested for success, failure and any disabled or bypass path | Pass | `selftest.sh` tests the refusals and `bash -n`; the success paths are the container runs of `run-checks.sh`, `screenshots.sh` and `smoke-binary.sh` (recorded in RC-079). |
| 12 | Formatted with `shfmt` (or the project's formatter) | Fail | `shfmt` was not run; Optional, deferred. |
| 13 | Safe to re-run: a second run does not duplicate or corrupt what the first did | Pass | The second container run gave the same result as the first (272 passed, 5 of 5 smoke runs). |
| 14 | Bash version and external tools it needs are stated; GNU-only options are named | Pass | Bash and the external tools are listed under `Needs`; GNU `tar --exclude` is named by the tool list. |
| 15 | A command sequence, constant, path or message used more than once is defined once (a function, a variable or a sourced helper); a helper is shared between scripts only where it expresses the same knowledge | Pass | The desktop start is defined once in `start-desktop.sh` and sourced by the three scripts. |
## Overall Verdict
Go — every Mandatory criterion passes; the failed Optional criteria are deferred with an action item. Reviewed by AI as stand-in for S01; not independent of the author.
Container run of the self test: 11 cases ok.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Criterion 12 (Optional) failed: Formatted with `shfmt` (or the project's formatter); fix or accept the deferral | S01 | 2026-10-21 |
---
[SH-MIL-013]: ../../../tools/docker
[QC-SH-001]: ../../../framework/qc/code/qc-programming-shell.md
[f8ccfca]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/f8ccfca02ef3a518eae472e3acdcd2aef03b5950
@@ -0,0 +1,54 @@
# RC-079: Review of the container checks
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-079 |
| CrossReference | [MIL-013] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [2f192b6] |
---
## Artifact Under Review
- Instance reviewed: [MIL-013] (the milestone's Go / No-Go criteria, checked against the container and sandbox checks)
- Checklist used: none exists for this result; the ten criteria of MIL-013 are the checklist
- Scope: full review
- Language and domain: n/a (record of results)
- Language reviewer: none
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | `docker build` of the Debian image succeeds | Pass | Image `flash-card-debian` built from `docker/debian.Dockerfile` (base `python:3.13-slim-bookworm`, Python 3.13.16); size 1697 MB; `binutils` was missing at first and was added after the first smoke build failed |
| 2 | Linters and the whole test suite run on the virtual desktop and end with exit code 0, e2e tests not skipped | Pass | `run-checks.sh` twice: ruff, ruff format, mypy (49 files), lint-imports (1 kept) and 272 tests passed in 3.5 s; 33 s per run |
| 3 | The full GNOME session is tried and the result recorded; fallback to mutter stated | Pass | `gnome-shell --x11` starts and then fails with `Gio.IOErrorEnum: Could not connect` in `LoginManagerSystemd` (no login manager in a container); the checks ran on GNOME's window manager mutter 43.8, which the script prints (`desktop: mutter on :99`) |
| 4 | Nothing opens or moves on the host desktop during the runs | Pass | All runs of this record were `docker run` commands with no display; note: earlier unit runs of the test suite on the host by a helper agent opened Tk windows briefly before the Product Owner's instruction; from then on the suite ran only in the container |
| 5 | The screenshot script writes the four PNG files from the Debian image | Pass | `screenshot-level.png`, `-front.png`, `-back.png`, `-menu.png` (20 to 23 KB each) written to the mounted folder and read by eye: the level screen, the card with the menu bar (File, About) are right |
| 6 | The Linux binary is built and passes the smoke test 5 consecutive runs, and the source program too | Pass | `smoke-binary.sh 5` twice: the PyInstaller binary 5 of 5 (0.64 s per run) and `python -m flash_card` 5 of 5 (0.38 s); each run: window found, click at the known button (650, 659), progress file has header plus 2 cards |
| 7 | The Windows executable passes the smoke test inside Windows Sandbox, 5 consecutive runs | Fail | Not run. `tools/sandbox/` (`flash-card.wsb`, `smoke.ps1`, `run.ps1`) is written, the PowerShell parses without errors and the configuration is well-formed XML, but starting Windows Sandbox opens a window on the host, and the Product Owner asked that no app runs on the development machine while working. The run waits for the Product Owner's go |
| 8 | The lost-click symptom of RC-072 is investigated and the finding recorded | Pass | 10 of 10 presses of the known button registered in the container (binary and source). The symptom was seen only with the simulated Windows mouse (about 3 of 8 reruns) and is most likely a timing problem of that click automation (cursor move, focus, button down and up) and not a program defect; this is a finding for Linux only and it is not proven for Windows until criterion 7 is run |
| 9 | README and the wiki Install page in three languages describe the commands and the limits; `check-readme.sh` exit 0 | Pass | Sections added; `check-readme.sh` exit 0; macOS stated as not covered, the Debian check stated as not a Windows check, the sandbox requirements stated |
| 10 | BC-001, PP-001 and ADR-0005 are reviewed Go; code review has no failed Mandatory criterion | Pass | RC-073 to RC-076; RC-077 (Python) and RC-078 (shell) are Go |
## Overall Verdict
Go-with-conditions — everything that can run without the host desktop runs and passes: the Debian checks (272 tests, linters), the screenshots, and the smoke test of the Linux binary and the source program. Criterion 7 (the Windows executable in Windows Sandbox) is not run and keeps the issue "Run and record the checks" open. Reviewed by AI as stand-in for S01; not independent of the author.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Run `powershell -File tools\sandbox\run.ps1 -Runs 5` after `python tools/build_executable.py` at a time that suits the Product Owner (Windows Sandbox shows its own window), and record the result in a new review record | S01 | 2026-10-21 |
| Decide whether the GNOME Shell start in the container is worth a login-manager stub (it is not needed for the checks) | S01 | 2026-10-21 |
---
[MIL-013]: ../milestones/mil-013-container-checks.md
[2f192b6]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/2f192b6936a92f85c6c200de3cac3d6cf3572903
+47
View File
@@ -0,0 +1,47 @@
# RC-080: Windows Sandbox run of the executable
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-080 |
| CrossReference | [MIL-013], [RC-079] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [6e3fcf8] |
---
## Artifact Under Review
- Instance reviewed: [MIL-013], criterion 7 (the Windows executable in Windows Sandbox), which [RC-079] left open
- Checklist used: none exists; criterion 7 of MIL-013 and the open condition of RC-072 (smoke test of the executable)
- Scope: delta re-review of criterion 7 of MIL-013 after the Product Owner started the run
- Language and domain: n/a (record of results)
- Language reviewer: none
- Mode: autonomous, not independent (reviewer is `AI as stand-in for S01`)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 7 | The Windows executable passes the smoke test inside Windows Sandbox (window titled Flashy, embedded list, list override, known button writes the progress file), 5 consecutive sandbox runs, with the results read from the mapped output folder | Pass | `tools/sandbox/run.ps1 -Runs 5` on Windows 11 Pro; the sandbox ran `Microsoft Windows 11 Enterprise`; `dist/flash-card.exe` (25.8 MB, built from the head of `main` before the container changes) mapped read-only; **5 of 5 runs passed**: window found, click made by the sandbox's own mouse at the known button, progress file with a header and 2 cards (3 rows), 4.5 to 5.2 s per run including the copy and the start; a screenshot of the sandbox desktop shows the card with the menu bar and both button images; the sandbox shut itself down and no sandbox process was left |
| RC-072 #4 | The executable passes the smoke test of MIL-009 | Pass | The list-override case (`ms-da.csv` next to the program, 3 words, one known word, 2 left) passed in all 5 runs; with the earlier 3 of 8 lost clicks on the host, the finding is that they came from the host click automation, not from the program |
## Overall Verdict
Go — criterion 7 of MIL-013 and the open condition of RC-072 on the smoke test of the executable are met. The issue "Run and record the checks" can be closed. The tag of v0.2.0 is still lightweight (RC-072 criterion 5) and the executable is still not attached to a release (upload limit of the host). Reviewed by AI as stand-in for S01; not independent of the author.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Decide whether the lightweight tag `v0.2.0` is replaced by an annotated tag (force update of the tag on the host) | S01 | 2026-10-21 |
| Raise the upload limit of the git host so that `flash-card.exe` and its checksum can be attached to a release | S01 | 2026-10-21 |
---
[MIL-013]: ../milestones/mil-013-container-checks.md
[RC-079]: ./rc-079-container-checks.md
[6e3fcf8]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/6e3fcf8aa3d66b9fa84339e1dce90d5f53cbed67
+217 -113
View File
@@ -1,113 +1,217 @@
# Traceability Matrix: Flash Card
## Metadata
| Key | Value |
| --- | --- |
| ID | TM-001 |
| CrossReference | [BC-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [c3fbcbc] |
---
## Purpose
Tracks backward/forward links between artifact instances so that the Business Case's
cross-artifact traceability success criterion is measurable. A row is added or
updated whenever an artifact instance is created or reviewed.
## Traceability Table
| Artifact Instance | Type | Language | Domain | Upstream (Backward Link) | Downstream (Forward Link) | Last Reviewed (RC-ID) |
| --- | --- | --- | --- | --- | --- | --- |
| BC-001 | Business Case | en | it | - | SA-001, PP-001 | [RC-001] |
| SA-001 | Stakeholder Analysis | en | it | BC-001 | PP-001, DICT-001 | [RC-002] |
| PP-001 | Project Plan | en | it | BC-001, SA-001 | MIL-001 to MIL-007 | [RC-003] |
| UCD-001 | Use Case Diagram | en | it | SA-001, BC-001 | US-001, UC-001 | [RC-004] |
| US-001 | User Story | en | it | UCD-001, BC-001 | MIL-002 to MIL-006 | [RC-005] |
| UC-001 | Use Case | en | it | UCD-001, US-001 | DM-001, SSD-001 | [RC-006] |
| DM-001 | Domain Model | en | it | UC-001 | SSD-001, DICT-001, DCD-001 | [RC-007] |
| SSD-001 | System Sequence Diagram | en | it | UC-001, DM-001 | DCD-001 | [RC-008] |
| OC-001 | Operation Contract | - | - | SSD-001, DM-001 | SD-001 | [RC-009] |
| SD-001 | Sequence Diagram | - | - | OC-001 | DCD-001 | [RC-010] |
| DCD-001 | Design Class Diagram | - | - | DM-001, SD-001, DICT-001 | src/flash_card | [RC-011] |
| DICT-001 | Domain Dictionary | en | it | BC-001, SA-001, DM-001 | DCD-001 | [RC-012] |
| ADR-0001 | Architecture Decision Record | - | - | BC-001 | MIL-001, MIL-003, MIL-006 | [RC-013] |
| ADR-0002 | Architecture Decision Record | - | - | BC-001 | DCD-001 | [RC-014] |
| ADR-0003 | Architecture Decision Record | - | - | BC-001 | - | [RC-015] |
| MIL-001 | Milestone / Gateway | en | it | BC-001, PP-001 | tasks of MIL-001 | [RC-016] |
| MIL-002 | Milestone / Gateway | en | it | BC-001, PP-001 | tasks of MIL-002 | [RC-017] |
| MIL-003 | Milestone / Gateway | en | it | BC-001, PP-001 | tasks of MIL-003 | [RC-018] |
| MIL-004 | Milestone / Gateway | en | it | BC-001, PP-001 | tasks of MIL-004 | [RC-019] |
| MIL-005 | Milestone / Gateway | en | it | BC-001, PP-001 | tasks of MIL-005 | [RC-020] |
| MIL-006 | Milestone / Gateway | en | it | BC-001, PP-001 | tasks of MIL-006 | [RC-021] |
| MIL-007 | Milestone / Gateway | en | it | BC-001, PP-001 | tasks of MIL-007 | [RC-022] |
| PY-MIL-001 | Python Source Code | - | - | DCD-001, ADR-0002 | - | [RC-023] |
| PY-MIL-002 | Python Source Code | - | - | DCD-001, ADR-0002 | - | [RC-024] |
| PY-MIL-003 | Python Source Code | - | - | DCD-001, ADR-0002 | - | [RC-025] |
| PY-MIL-004 | Python Source Code | - | - | DCD-001, ADR-0002 | - | [RC-026] |
## Coverage Notes
- `-` in Upstream means foundational; in Downstream it means nothing is built on it yet; in Last Reviewed it means no `RC-*` exists yet. Every row has a review record from the baseline review (autonomous mode, AI as stand-in for S01).
- Types not created for this project, and why: ADR-0003.
- Source code (`PY`) is added as `src/` is reviewed, one row per milestone.
---
[BC-001]: ../business-case.md
[SA-001]: ../stakeholder-analysis.md
[PP-001]: ../project-plan.md
[UCD-001]: ../use-case-diagram.md
[US-001]: ../user-stories.md
[UC-001]: ../uc-001/uc.md
[DM-001]: ../domain-model.md
[SSD-001]: ../uc-001/ssd.md
[OC-001]: ../uc-001/oc.md
[SD-001]: ../uc-001/sd.md
[DCD-001]: ../dcd.md
[DICT-001]: ../dictionary.md
[ADR-0001]: ../adr/adr-0001-standard-library-and-optional-speech.md
[ADR-0002]: ../adr/adr-0002-clean-architecture-and-mvvm.md
[ADR-0003]: ../adr/adr-0003-skipped-artifact-types.md
[MIL-001]: ../milestones/mil-001-foundation.md
[MIL-002]: ../milestones/mil-002-step1-user-interface.md
[MIL-003]: ../milestones/mil-003-step2-new-flash-cards.md
[MIL-004]: ../milestones/mil-004-step3-flip-cards.md
[MIL-005]: ../milestones/mil-005-step4-save-progress.md
[MIL-006]: ../milestones/mil-006-malay-speech.md
[MIL-007]: ../milestones/mil-007-documentation-and-publication.md
[PY-MIL-001]: ../../src/flash_card
[RC-001]: ./reviews/rc-001-business-case.md
[RC-002]: ./reviews/rc-002-stakeholder-analysis.md
[RC-003]: ./reviews/rc-003-project-plan.md
[RC-004]: ./reviews/rc-004-use-case-diagram.md
[RC-005]: ./reviews/rc-005-user-stories.md
[RC-006]: ./reviews/rc-006-use-case.md
[RC-007]: ./reviews/rc-007-domain-model.md
[RC-008]: ./reviews/rc-008-system-sequence-diagram.md
[RC-009]: ./reviews/rc-009-operation-contracts.md
[RC-010]: ./reviews/rc-010-sequence-diagrams.md
[RC-011]: ./reviews/rc-011-design-class-diagram.md
[RC-012]: ./reviews/rc-012-domain-dictionary.md
[RC-013]: ./reviews/rc-013-adr-0001.md
[RC-014]: ./reviews/rc-014-adr-0002.md
[RC-015]: ./reviews/rc-015-adr-0003.md
[RC-016]: ./reviews/rc-016-mil-001.md
[RC-017]: ./reviews/rc-017-mil-002.md
[RC-018]: ./reviews/rc-018-mil-003.md
[RC-019]: ./reviews/rc-019-mil-004.md
[RC-020]: ./reviews/rc-020-mil-005.md
[RC-021]: ./reviews/rc-021-mil-006.md
[RC-022]: ./reviews/rc-022-mil-007.md
[RC-023]: ./reviews/rc-023-py-mil-001.md
[c3fbcbc]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/c3fbcbcfaf799e0ae34aed7e14d3bc8a62f03db3
[RC-024]: ./reviews/rc-024-py-mil-002.md
[PY-MIL-002]: ../../src/flash_card
[RC-025]: ./reviews/rc-025-py-mil-003.md
[PY-MIL-003]: ../../src/flash_card
[RC-026]: ./reviews/rc-026-py-mil-004.md
[PY-MIL-004]: ../../src/flash_card
# Traceability Matrix: Flash Card
## Metadata
| Key | Value |
| --- | --- |
| ID | TM-001 |
| CrossReference | [BC-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Deprecated | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [c3fbcbc] |
| 2026-10-14 | Deprecated | Jens Tirsvad Nielsen | AI as stand-in for S01 | Added MIL-008 and the review records of the level choice (no checklist exists for this type) | [0b983b7] |
| 2026-10-15 | Deprecated | Jens Tirsvad Nielsen | AI as stand-in for S01 | Added the rows and review records of the executable request (no checklist exists for this type) | [768ca34] |
| 2026-10-15 | Deprecated | Jens Tirsvad Nielsen | AI as stand-in for S01 | Added the rows and review records of the executable request (no checklist exists for this type) | [061b4f4] |
| 2026-10-15 | Deprecated | Jens Tirsvad Nielsen | AI as stand-in for S01 | Added the rows and review records of the executable request (no checklist exists for this type) | [9c8e294] |
| 2026-10-15 | Deprecated | Jens Tirsvad Nielsen | AI as stand-in for S01 | Added the rows and review records of the executable request (no checklist exists for this type) | [2211d0f] |
| 2026-10-15 | Deprecated | Jens Tirsvad Nielsen | AI as stand-in for S01 | Added the rows and review records of the executable request (no checklist exists for this type) | [0264b60] |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Added the rows and review records of the executable request (no checklist exists for this type) | [f86bc91] |
---
## Purpose
Tracks backward/forward links between artifact instances so that the Business Case's
cross-artifact traceability success criterion is measurable. A row is added or
updated whenever an artifact instance is created or reviewed.
## Traceability Table
| Artifact Instance | Type | Language | Domain | Upstream (Backward Link) | Downstream (Forward Link) | Last Reviewed (RC-ID) |
| --- | --- | --- | --- | --- | --- | --- |
| BC-001 | Business Case | en | it | - | SA-001, PP-001 | [RC-073] |
| SA-001 | Stakeholder Analysis | en | it | BC-001 | PP-001, DICT-001 | [RC-002] |
| PP-001 | Project Plan | en | it | BC-001, SA-001 | MIL-001 to MIL-008 | [RC-074] |
| UCD-001 | Use Case Diagram | en | it | SA-001, BC-001 | US-001, UC-001 | [RC-004] |
| US-001 | User Story | en | it | UCD-001, BC-001 | MIL-002 to MIL-006, MIL-008 | [RC-068] |
| UC-001 | Use Case | en | it | UCD-001, US-001 | DM-001, SSD-001 | [RC-058] |
| DM-001 | Domain Model | en | it | UC-001 | SSD-001, DICT-001, DCD-001 | [RC-034] |
| SSD-001 | System Sequence Diagram | en | it | UC-001, DM-001 | DCD-001 | [RC-059] |
| OC-001 | Operation Contract | - | - | SSD-001, DM-001 | SD-001 | [RC-060] |
| SD-001 | Sequence Diagram | - | - | OC-001 | DCD-001 | [RC-061] |
| DCD-001 | Design Class Diagram | - | - | DM-001, SD-001, DICT-001 | src/flash_card | [RC-062] |
| DICT-001 | Domain Dictionary | en | it | BC-001, SA-001, DM-001 | DCD-001 | [RC-063] |
| ADR-0001 | Architecture Decision Record | - | - | BC-001 | MIL-001, MIL-003, MIL-006 | [RC-013] |
| ADR-0002 | Architecture Decision Record | - | - | BC-001 | DCD-001 | [RC-014] |
| ADR-0003 | Architecture Decision Record | - | - | BC-001 | - | [RC-015] |
| MIL-001 | Milestone / Gateway | en | it | BC-001, PP-001 | tasks of MIL-001 | [RC-016] |
| MIL-002 | Milestone / Gateway | en | it | BC-001, PP-001 | tasks of MIL-002 | [RC-017] |
| MIL-003 | Milestone / Gateway | en | it | BC-001, PP-001 | tasks of MIL-003 | [RC-018] |
| MIL-004 | Milestone / Gateway | en | it | BC-001, PP-001 | tasks of MIL-004 | [RC-019] |
| MIL-005 | Milestone / Gateway | en | it | BC-001, PP-001 | tasks of MIL-005 | [RC-020] |
| MIL-006 | Milestone / Gateway | en | it | BC-001, PP-001 | tasks of MIL-006 | [RC-021] |
| MIL-007 | Milestone / Gateway | en | it | BC-001, PP-001 | tasks of MIL-007 | [RC-022] |
| MIL-008 | Milestone / Gateway | en | it | BC-001, PP-001 | tasks of MIL-008 | [RC-040] |
| MIL-009 | Milestone / Gateway | en | it | BC-001 | - | [RC-050] |
| ADR-0004 | Architecture Decision Record | - | - | BC-001 | - | [RC-046] |
| MIL-010 | Milestone / Gateway | en | it | BC-001 | - | [RC-054], [RC-055] |
| MIL-011 | Milestone / Gateway | en | it | BC-001 | - | [RC-065] |
| MIL-012 | Milestone / Gateway | en | it | BC-001 | - | [RC-070], [RC-072] |
| MIL-013 | Milestone / Gateway | en | it | BC-001 | - | [RC-076], [RC-079], [RC-080] |
| ADR-0005 | Architecture Decision Record | - | - | BC-001 | - | [RC-075] |
| PY-MIL-001 | Python Source Code | - | - | DCD-001, ADR-0002 | - | [RC-023] |
| PY-MIL-002 | Python Source Code | - | - | DCD-001, ADR-0002 | - | [RC-024] |
| PY-MIL-003 | Python Source Code | - | - | DCD-001, ADR-0002 | - | [RC-025] |
| PY-MIL-004 | Python Source Code | - | - | DCD-001, ADR-0002 | - | [RC-026] |
| PY-MIL-005 | Python Source Code | - | - | DCD-001, ADR-0002 | - | [RC-027] |
| PY-MIL-006 | Python Source Code | - | - | DCD-001, ADR-0002 | - | [RC-028] |
| PY-MIL-007 | Python Source Code | - | - | DCD-001, ADR-0002 | - | [RC-029] |
| PY-MIL-008 | Python Source Code | - | - | DCD-001, ADR-0002 | - | [RC-041] |
| PY-MIL-009 | Python Source Code | - | - | DCD-001, ADR-0002 | - | [RC-048] |
| PY-MIL-011 | Python Source Code | - | - | DCD-001, ADR-0002 | - | [RC-066] |
| PY-FIX-001 | Python Source Code | - | - | PY-MIL-008 | - | [RC-049] |
| PY-MIL-012 | Python Source Code | - | - | MIL-012 | - | [RC-071] |
| PY-MIL-013 | Python Source Code | - | - | MIL-013 | - | [RC-077] |
| SH-MIL-013 | Shell Script | - | - | MIL-013 | - | [RC-078] |
## Coverage Notes
- `-` in Upstream means foundational; in Downstream it means nothing is built on it yet; in Last Reviewed it means no `RC-*` exists yet. Every row has a review record from the baseline review (autonomous mode, AI as stand-in for S01).
- Types not created for this project, and why: ADR-0003.
- Source code (`PY`) is added as `src/` is reviewed, one row per milestone.
---
[BC-001]: ../business-case.md
[SA-001]: ../stakeholder-analysis.md
[PP-001]: ../project-plan.md
[UCD-001]: ../use-case-diagram.md
[US-001]: ../user-stories.md
[UC-001]: ../uc-001/uc.md
[DM-001]: ../domain-model.md
[SSD-001]: ../uc-001/ssd.md
[OC-001]: ../uc-001/oc.md
[SD-001]: ../uc-001/sd.md
[DCD-001]: ../dcd.md
[DICT-001]: ../dictionary.md
[ADR-0001]: ../adr/adr-0001-standard-library-and-optional-speech.md
[ADR-0002]: ../adr/adr-0002-clean-architecture-and-mvvm.md
[ADR-0003]: ../adr/adr-0003-skipped-artifact-types.md
[MIL-001]: ../milestones/mil-001-foundation.md
[MIL-002]: ../milestones/mil-002-step1-user-interface.md
[MIL-003]: ../milestones/mil-003-step2-new-flash-cards.md
[MIL-004]: ../milestones/mil-004-step3-flip-cards.md
[MIL-005]: ../milestones/mil-005-step4-save-progress.md
[MIL-006]: ../milestones/mil-006-malay-speech.md
[MIL-007]: ../milestones/mil-007-documentation-and-publication.md
[PY-MIL-001]: ../../src/flash_card
[RC-001]: ./reviews/rc-001-business-case.md
[RC-002]: ./reviews/rc-002-stakeholder-analysis.md
[RC-003]: ./reviews/rc-003-project-plan.md
[RC-004]: ./reviews/rc-004-use-case-diagram.md
[RC-005]: ./reviews/rc-005-user-stories.md
[RC-006]: ./reviews/rc-006-use-case.md
[RC-007]: ./reviews/rc-007-domain-model.md
[RC-008]: ./reviews/rc-008-system-sequence-diagram.md
[RC-009]: ./reviews/rc-009-operation-contracts.md
[RC-010]: ./reviews/rc-010-sequence-diagrams.md
[RC-011]: ./reviews/rc-011-design-class-diagram.md
[RC-012]: ./reviews/rc-012-domain-dictionary.md
[RC-013]: ./reviews/rc-013-adr-0001.md
[RC-014]: ./reviews/rc-014-adr-0002.md
[RC-015]: ./reviews/rc-015-adr-0003.md
[RC-016]: ./reviews/rc-016-mil-001.md
[RC-017]: ./reviews/rc-017-mil-002.md
[RC-018]: ./reviews/rc-018-mil-003.md
[RC-019]: ./reviews/rc-019-mil-004.md
[RC-020]: ./reviews/rc-020-mil-005.md
[RC-021]: ./reviews/rc-021-mil-006.md
[RC-022]: ./reviews/rc-022-mil-007.md
[RC-023]: ./reviews/rc-023-py-mil-001.md
[c3fbcbc]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/c3fbcbcfaf799e0ae34aed7e14d3bc8a62f03db3
[RC-024]: ./reviews/rc-024-py-mil-002.md
[PY-MIL-002]: ../../src/flash_card
[RC-025]: ./reviews/rc-025-py-mil-003.md
[PY-MIL-003]: ../../src/flash_card
[RC-026]: ./reviews/rc-026-py-mil-004.md
[PY-MIL-004]: ../../src/flash_card
[RC-027]: ./reviews/rc-027-py-mil-005.md
[PY-MIL-005]: ../../src/flash_card
[RC-028]: ./reviews/rc-028-py-mil-006.md
[PY-MIL-006]: ../../src/flash_card
[RC-029]: ./reviews/rc-029-py-mil-007.md
[PY-MIL-007]: ../../src/flash_card
[RC-030]: ./reviews/rc-030-business-case-level.md
[RC-031]: ./reviews/rc-031-user-stories-level.md
[RC-032]: ./reviews/rc-032-project-plan-level.md
[RC-033]: ./reviews/rc-033-use-case-level.md
[RC-034]: ./reviews/rc-034-domain-model-level.md
[RC-035]: ./reviews/rc-035-domain-dictionary-level.md
[RC-036]: ./reviews/rc-036-system-sequence-diagram-level.md
[RC-037]: ./reviews/rc-037-operation-contracts-level.md
[RC-038]: ./reviews/rc-038-sequence-diagrams-level.md
[RC-039]: ./reviews/rc-039-design-class-diagram-level.md
[RC-040]: ./reviews/rc-040-mil-008.md
[MIL-008]: ../milestones/mil-008-choose-level.md
[0b983b7]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/0b983b7fdadf6958717c1d0227d0f2ebe037f7b1
[RC-041]: ./reviews/rc-041-py-mil-008.md
[PY-MIL-008]: ../../src/flash_card
[RC-042]: ./reviews/rc-042-business-case-exe.md
[RC-043]: ./reviews/rc-043-user-stories-exe.md
[RC-044]: ./reviews/rc-044-project-plan-exe.md
[RC-045]: ./reviews/rc-045-design-class-diagram-exe.md
[RC-046]: ./reviews/rc-046-adr-0004.md
[RC-047]: ./reviews/rc-047-mil-009.md
[MIL-009]: ../milestones/mil-009-executable.md
[ADR-0004]: ../adr/adr-0004-pyinstaller-executable.md
[768ca34]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/768ca344c95d4f21e565e37ac96661c2f8dc8f54
[RC-048]: ./reviews/rc-048-py-mil-009.md
[PY-MIL-009]: ../../src/flash_card
[RC-049]: ./reviews/rc-049-py-fix-001.md
[PY-FIX-001]: ../../tests/unit/test_app.py
[RC-050]: ./reviews/rc-050-mil-009-task9.md
[061b4f4]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/061b4f48b5d49e6800656c95d79df707e07ec0f3
[RC-051]: ./reviews/rc-051-business-case-release.md
[RC-052]: ./reviews/rc-052-user-stories-release.md
[RC-053]: ./reviews/rc-053-project-plan-release.md
[RC-054]: ./reviews/rc-054-mil-010.md
[MIL-010]: ../milestones/mil-010-release.md
[9c8e294]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/9c8e2940217e615f82eda2d48aca9b2fd58f3687
[RC-055]: ./reviews/rc-055-release-v0-1-0.md
[RC-056]: ./reviews/rc-056-business-case-menu.md
[RC-057]: ./reviews/rc-057-user-stories-menu.md
[RC-058]: ./reviews/rc-058-use-case-menu.md
[RC-059]: ./reviews/rc-059-system-sequence-diagram-menu.md
[RC-060]: ./reviews/rc-060-operation-contracts-menu.md
[RC-061]: ./reviews/rc-061-sequence-diagrams-menu.md
[RC-062]: ./reviews/rc-062-design-class-diagram-menu.md
[RC-063]: ./reviews/rc-063-domain-dictionary-menu.md
[RC-064]: ./reviews/rc-064-project-plan-menu.md
[RC-065]: ./reviews/rc-065-mil-011.md
[MIL-011]: ../milestones/mil-011-menu-bar.md
[2211d0f]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/2211d0f4cbd8182314d18cbdefd939ae50c39e6d
[RC-066]: ./reviews/rc-066-py-mil-011.md
[PY-MIL-011]: ../../src/flash_card
[RC-067]: ./reviews/rc-067-business-case-r020.md
[RC-068]: ./reviews/rc-068-user-stories-r020.md
[RC-069]: ./reviews/rc-069-project-plan-r020.md
[RC-070]: ./reviews/rc-070-mil-012.md
[MIL-012]: ../milestones/mil-012-release-0-2-0.md
[0264b60]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/0264b6084f26bac5af716ea71596ce3be961fec8
[RC-071]: ./reviews/rc-071-py-mil-012.md
[PY-MIL-012]: ../../src/flash_card/__init__.py
[RC-072]: ./reviews/rc-072-release-v0-2-0.md
[RC-073]: ./reviews/rc-073-business-case-containers.md
[RC-074]: ./reviews/rc-074-project-plan-containers.md
[RC-075]: ./reviews/rc-075-adr-0005.md
[RC-076]: ./reviews/rc-076-mil-013.md
[MIL-013]: ../milestones/mil-013-container-checks.md
[ADR-0005]: ../adr/adr-0005-container-and-sandbox-checks.md
[f86bc91]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/f86bc9136e7719fbcd049a4f803959019b7d2df3
[RC-077]: ./reviews/rc-077-py-mil-013.md
[RC-078]: ./reviews/rc-078-sh-mil-013.md
[PY-MIL-013]: ../../tools
[SH-MIL-013]: ../../tools/docker
[RC-079]: ./reviews/rc-079-container-checks.md
[RC-080]: ./reviews/rc-080-sandbox-run.md
+241 -99
View File
@@ -1,99 +1,241 @@
# Operation Contracts: Study Flash Cards
## Metadata
| Key | Value |
| --- | --- |
| ID | OC-001 |
| CrossReference | [SSD-001], [DM-001], [DICT-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [c3fbcbc] |
---
The turn-over of the card after 3000 ms is started by the system's own timer, not by a message from the Learner, so it has no contract; it is realized in [SD-001].
## Contract: startStudySession
| Item | Value |
| --- | --- |
| Operation | `startStudySession(): CardDto \| None` |
| Traces to | `startStudySession` in [SSD-001] |
| Domain Model concepts | Study Session, Words To Learn, Word List, Flash Card ([DM-001]); IT terms `StudySession`, `Deck`, `Vocabulary`, `Card` ([DICT-001]) |
**Preconditions**
- A `Vocabulary` exists in the word list file.
**Postconditions**
- A `StudySession` instance was created.
- A `Deck` instance was created and associated with the `StudySession`.
- The `Deck` holds the cards of the progress file when it exists, otherwise a copy of the cards of the `Vocabulary`.
- When the `Deck` is not empty, `StudySession.current_card` was set to a card of the `Deck` and a `CardDto` of it is returned; otherwise `current_card` is `None` and `None` is returned.
**Exceptions**
| Condition (failing precondition) | Outcome |
| --- | --- |
| The word list file does not exist | `VocabularyNotFoundError` is raised; no session is created |
| The word list or progress file has no header of two cells, or a row with other than two cells | `VocabularyFormatError` is raised; no session is created and no file is changed |
## Contract: markKnown
| Item | Value |
| --- | --- |
| Operation | `markKnown(): None` |
| Traces to | `markKnown` in [SSD-001] |
| Domain Model concepts | Study Session, Words To Learn, Flash Card ([DM-001]); IT terms `StudySession`, `Deck`, `Card` ([DICT-001]) |
**Preconditions**
- A `StudySession` exists and its `current_card` is not `None`.
**Postconditions**
- The `Card` of `current_card` was removed from the `Deck` (the association was destroyed).
- The `Deck` was stored in the progress file.
- `StudySession.current_card` was set to `None`.
**Exceptions**
| Condition (failing precondition) | Outcome |
| --- | --- |
| `current_card` is `None` (no card is shown) | Nothing is changed and nothing is stored |
## Contract: markUnknown
| Item | Value |
| --- | --- |
| Operation | `markUnknown(): CardDto \| None` |
| Traces to | `markUnknown` in [SSD-001] |
| Domain Model concepts | Study Session, Words To Learn, Flash Card ([DM-001]); IT terms `StudySession`, `Deck`, `Card` ([DICT-001]) |
**Preconditions**
- A `StudySession` exists.
**Postconditions**
- `StudySession.current_card` was set to a card of the `Deck` that differs from the previous `current_card` when the `Deck` holds two or more cards, and a `CardDto` of it is returned.
- When the `Deck` is empty, `current_card` is `None` and `None` is returned.
- The `Deck` and the progress file are unchanged.
- The Malay word of the new `current_card` was passed to the `SpeechPort`.
**Exceptions**
| Condition (failing precondition) | Outcome |
| --- | --- |
| The `Deck` is empty | `None` is returned; nothing is spoken |
---
[SSD-001]: ./ssd.md
[DM-001]: ../domain-model.md
[DICT-001]: ../dictionary.md
[SD-001]: ./sd.md
[c3fbcbc]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/c3fbcbcfaf799e0ae34aed7e14d3bc8a62f03db3
# Operation Contracts: Study Flash Cards
## Metadata
| Key | Value |
| --- | --- |
| ID | OC-001 |
| CrossReference | [SSD-001], [DM-001], [DICT-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Deprecated | Jens Tirsvad Nielsen | AI as stand-in for S01 | Added chooseLevel; startStudySession returns the levels | [0b983b7] |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Added the menu contracts | [2211d0f] |
---
The turn-over of the card after 3000 ms is started by the system's own timer, not by a message from the Learner, so it has no contract; it is realized in [SD-001].
## Contract: startStudySession
| Item | Value |
| --- | --- |
| Operation | `startStudySession(): tuple[Level, ...]` |
| Traces to | `startStudySession` in [SSD-001] |
| Domain Model concepts | Level ([DM-001]); IT term `Level` ([DICT-001]) |
**Preconditions**
- The program was started without a level.
**Postconditions**
- The levels 100 words, 1000 words and all words are returned, in that order.
- No `StudySession` or `Deck` was created and no file was read.
**Exceptions**
| Condition (failing precondition) | Outcome |
| --- | --- |
| The program was started with a level | The operation is not sent; `chooseLevel` is the first operation |
## Contract: chooseLevel
| Item | Value |
| --- | --- |
| Operation | `chooseLevel(level: Level): CardDto \| None` |
| Traces to | `chooseLevel` in [SSD-001] |
| Domain Model concepts | Study Session, Words To Learn, Word List, Level, Flash Card ([DM-001]); IT terms `StudySession`, `Deck`, `Vocabulary`, `Level`, `Card` ([DICT-001]) |
**Preconditions**
- A `Vocabulary` exists in the word list file.
- `level` is one of the levels returned by `startStudySession`, or was given at start.
**Postconditions**
- A `StudySession` instance was created and associated with `level`.
- A `Deck` instance was created and associated with the `StudySession`.
- The `Deck` holds the cards of the progress file when it exists, otherwise a copy of the cards of the `Vocabulary`; cards outside the level are kept in it.
- The level's cards are the first `level.limit` cards of the `Vocabulary` (all of them when the limit is none or larger than the list).
- When the `Deck` holds a card of the level, `StudySession.current_card` was set to such a card and a `CardDto` of it is returned; otherwise `current_card` is `None` and `None` is returned.
- The Malay word of the card was passed to the `SpeechPort`.
**Exceptions**
| Condition (failing precondition) | Outcome |
| --- | --- |
| The word list file does not exist | `VocabularyNotFoundError` is raised; no session is created |
| The word list or progress file has no header of two cells, or a row with other than two cells | `VocabularyFormatError` is raised; no session is created and no file is changed |
| No card of the level is left in the `Deck` | `None` is returned; nothing is spoken |
## Contract: markKnown
| Item | Value |
| --- | --- |
| Operation | `markKnown(): None` |
| Traces to | `markKnown` in [SSD-001] |
| Domain Model concepts | Study Session, Words To Learn, Flash Card ([DM-001]); IT terms `StudySession`, `Deck`, `Card` ([DICT-001]) |
**Preconditions**
- A `StudySession` exists and its `current_card` is not `None`.
**Postconditions**
- The `Card` of `current_card` was removed from the `Deck` (the association was destroyed); cards outside the level are not touched.
- The whole `Deck` was stored in the progress file.
- `StudySession.current_card` was set to `None`.
**Exceptions**
| Condition (failing precondition) | Outcome |
| --- | --- |
| `current_card` is `None` (no card is shown) | Nothing is changed and nothing is stored |
## Contract: openWordList
| Item | Value |
| --- | --- |
| Operation | `openWordList(path: Path): tuple[Level, ...]` |
| Traces to | `openWordList` in [SSD-001] |
| Domain Model concepts | Word List, Study Session, Words To Learn ([DM-001]); IT terms `Vocabulary`, `StudySession`, `Deck` ([DICT-001]) |
**Preconditions**
- `path` names an existing file.
**Postconditions**
- The `Vocabulary` of `path` is the word list in use and its progress file (`words_to_learn.csv` for `ms-da.csv`, else `words_to_learn_<name>.csv` in the data folder) is the progress in use.
- Any earlier `StudySession` was dropped and the levels are returned; no card is shown until a level is chosen.
**Exceptions**
| Condition (failing precondition) | Outcome |
| --- | --- |
| The file does not exist or is not a word list (no header of two language codes, a row that is not two cells, or no card) | `VocabularyNotFoundError` or `VocabularyFormatError` is raised; the earlier word list and session stay in use and no file is changed |
## Contract: changeLevel
| Item | Value |
| --- | --- |
| Operation | `changeLevel(): tuple[Level, ...]` |
| Traces to | `changeLevel` in [SSD-001] |
| Domain Model concepts | Level, Study Session ([DM-001]); IT terms `Level`, `StudySession` ([DICT-001]) |
**Preconditions**
- A word list is in use.
**Postconditions**
- The pending flip timer was cancelled, the `StudySession` was dropped and the levels are returned; the progress file was not changed.
**Exceptions**
| Condition (failing precondition) | Outcome |
| --- | --- |
| None | – |
## Contract: resetWordList
| Item | Value |
| --- | --- |
| Operation | `resetWordList(): tuple[Level, ...]` |
| Traces to | `resetWordList` in [SSD-001] |
| Domain Model concepts | Words To Learn, Word List ([DM-001]); IT terms `Deck`, `Vocabulary` ([DICT-001]) |
**Preconditions**
- A word list is in use and the Learner confirmed.
**Postconditions**
- The progress file of the word list in use does not exist; the word list file and the progress files of other word lists are unchanged.
- The `StudySession` was dropped and the levels are returned; the next session starts from a `Deck` of the whole `Vocabulary`.
**Exceptions**
| Condition (failing precondition) | Outcome |
| --- | --- |
| The progress file does not exist | Nothing is deleted and no error is raised |
| The progress file cannot be deleted (`OSError`) | The error is logged and shown to the Learner; the earlier session stays |
## Contract: showContact
| Item | Value |
| --- | --- |
| Operation | `showContact(): tuple[str, str, str]` |
| Traces to | `showContact` in [SSD-001] |
| Domain Model concepts | none (author information, outside the domain) |
**Preconditions**
- None.
**Postconditions**
- The name, the title and the link of the author are returned and the link was opened in the web browser.
**Exceptions**
| Condition (failing precondition) | Outcome |
| --- | --- |
| No web browser can be started | The failure is logged; nothing else changes |
## Contract: exit
| Item | Value |
| --- | --- |
| Operation | `exit(): None` |
| Traces to | `exit` in [SSD-001] |
| Domain Model concepts | Study Session ([DM-001]); IT term `StudySession` ([DICT-001]) |
**Preconditions**
- None.
**Postconditions**
- The pending flip timer was cancelled, the window was closed and the program ended with exit code 0; the progress file is as it was after the last `markKnown`.
**Exceptions**
| Condition (failing precondition) | Outcome |
| --- | --- |
| None | – |
## Contract: markUnknown
| Item | Value |
| --- | --- |
| Operation | `markUnknown(): CardDto \| None` |
| Traces to | `markUnknown` in [SSD-001] |
| Domain Model concepts | Study Session, Words To Learn, Flash Card ([DM-001]); IT terms `StudySession`, `Deck`, `Card` ([DICT-001]) |
**Preconditions**
- A `StudySession` exists.
**Postconditions**
- `StudySession.current_card` was set to a card of the level that differs from the previous `current_card` when the level holds two or more cards still to learn, and a `CardDto` of it is returned.
- When no card of the level is left, `current_card` is `None` and `None` is returned.
- The `Deck` and the progress file are unchanged.
- The Malay word of the new `current_card` was passed to the `SpeechPort`.
**Exceptions**
| Condition (failing precondition) | Outcome |
| --- | --- |
| No card of the level is left | `None` is returned; nothing is spoken |
---
[SSD-001]: ./ssd.md
[DM-001]: ../domain-model.md
[DICT-001]: ../dictionary.md
[SD-001]: ./sd.md
[0b983b7]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/0b983b7fdadf6958717c1d0227d0f2ebe037f7b1
[2211d0f]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/2211d0f4cbd8182314d18cbdefd939ae50c39e6d
+299 -171
View File
@@ -1,171 +1,299 @@
# Sequence Diagrams: Study Flash Cards
## Metadata
| Key | Value |
| --- | --- |
| ID | SD-001 |
| CrossReference | [OC-001], [DCD-001], [DICT-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [c3fbcbc] |
---
## Sequence: startStudySession
**Realizes:** `startStudySession` in [OC-001]
### Diagram
```plantuml
@startuml
participant "main : app" as M
participant ":CsvVocabularyRepository" as VR
participant ":CsvProgressRepository" as PR
participant ":StudySession" as S
participant ":Deck" as D
participant ":SpeechPort" as SP
M -> PR : load()
PR --> M : deck | None
alt deck is None
M -> VR : load()
VR --> M : vocabulary
create D
M -> D : from_vocabulary(vocabulary)
D --> M : deck
end
create S
M -> S : create(deck, progress, speech, choose)
M -> S : next_card()
activate S
opt deck is not empty
S -> D : draw(choose, exclude)
D --> S : card
S -> SP : speak(card.front, front_code)
end
S --> M : CardDto | None
deactivate S
@enduml
```
### Pattern Annotations
| Pattern (GRASP / GoF) | Applied to | Rationale |
| --- | --- | --- |
| Creator | `app.main` creates `StudySession` | It holds the adapters the session needs |
| Information Expert | `Deck` draws and removes its own cards | It owns the list of cards |
| Null Object | `NullSpeech` as `SpeechPort` | The session never tests for speech |
### Postcondition Coverage
| Postcondition (from contract) | Satisfied by message |
| --- | --- |
| A `StudySession` instance was created | `create(deck, progress, speech, choose)` |
| A `Deck` was created from the progress file or a copy of the `Vocabulary` | `PR.load()`, `alt` fragment, `from_vocabulary` |
| `current_card` set and a `CardDto` returned, or `None` | `next_card()` with the `opt` fragment |
### Responsibility Check
The session coordinates, the deck holds the cards, the repositories hold the file format; no object receives all messages.
## Sequence: markKnown
**Realizes:** `markKnown` in [OC-001]
### Diagram
```plantuml
@startuml
participant ":FlashCardView" as V
participant ":FlashCardViewModel" as VM
participant ":StudySession" as S
participant ":Deck" as D
participant ":CsvProgressRepository" as PR
V -> VM : is_known()
activate VM
VM -> S : mark_known()
activate S
opt current_card is not None
S -> D : remove(card)
S -> PR : save(deck)
end
deactivate S
VM -> S : next_card()
S --> VM : CardDto | None
VM --> V : side, language name, text
deactivate VM
@enduml
```
### Pattern Annotations
| Pattern (GRASP / GoF) | Applied to | Rationale |
| --- | --- | --- |
| MVVM | `FlashCardView`, `FlashCardViewModel` | The view raises the event and shows the result; the rule is behind the view model |
| Repository | `CsvProgressRepository` | The session stores the deck through a port |
### Postcondition Coverage
| Postcondition (from contract) | Satisfied by message |
| --- | --- |
| The card was removed from the `Deck` | `remove(card)` |
| The `Deck` was stored | `save(deck)` |
| `current_card` was set to `None` | `mark_known()` ends with no current card; `next_card()` then draws the next |
### Responsibility Check
The view model only sequences two session calls and maps the result for the view.
## Sequence: markUnknown
**Realizes:** `markUnknown` in [OC-001]
### Diagram
```plantuml
@startuml
participant ":FlashCardView" as V
participant ":FlashCardViewModel" as VM
participant ":StudySession" as S
participant ":Deck" as D
participant ":SpeechPort" as SP
V -> VM : next_card()
VM -> S : next_card()
activate S
opt deck is not empty
S -> D : draw(choose, exclude=current)
D --> S : card
S -> SP : speak(card.front, front_code)
end
S --> VM : CardDto | None
deactivate S
VM --> V : side, language name, text
@enduml
```
### Pattern Annotations
| Pattern (GRASP / GoF) | Applied to | Rationale |
| --- | --- | --- |
| Information Expert | `Deck.draw` | The deck knows its cards |
### Postcondition Coverage
| Postcondition (from contract) | Satisfied by message |
| --- | --- |
| A different card was chosen when two or more exist | `draw(choose, exclude=current)` |
| Deck and file unchanged | no `remove` or `save` message |
| The Malay word was passed to the `SpeechPort` | `speak(card.front, front_code)` |
### Responsibility Check
Same as `markKnown`; the session is the only object that speaks and draws.
---
[OC-001]: ./oc.md
[DCD-001]: ../dcd.md
[DICT-001]: ../dictionary.md
[c3fbcbc]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/c3fbcbcfaf799e0ae34aed7e14d3bc8a62f03db3
# Sequence Diagrams: Study Flash Cards
## Metadata
| Key | Value |
| --- | --- |
| ID | SD-001 |
| CrossReference | [OC-001], [DCD-001], [DICT-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Deprecated | Jens Tirsvad Nielsen | AI as stand-in for S01 | Added the sequences startStudySession (levels) and chooseLevel (level filter) | [0b983b7] |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Added the sequences openWordList and resetWordList | [2211d0f] |
---
## Sequence: startStudySession
**Realizes:** `startStudySession` in [OC-001]
### Diagram
```plantuml
@startuml
participant ":LevelView" as V
participant ":LevelViewModel" as VM
V -> VM : choices
VM --> V : tuple[Level, ...]
@enduml
```
### Pattern Annotations
| Pattern (GRASP / GoF) | Applied to | Rationale |
| --- | --- | --- |
| MVVM | `LevelView`, `LevelViewModel` | The view shows the choices; the labels and the order are in the view model |
### Postcondition Coverage
| Postcondition (from contract) | Satisfied by message |
| --- | --- |
| The three levels are returned in order | `choices` |
| No session or deck is created and no file is read | no other message is sent |
### Responsibility Check
The view model owns the choices; the view only draws buttons and forwards the click.
## Sequence: chooseLevel
**Realizes:** `chooseLevel` in [OC-001]
### Diagram
```plantuml
@startuml
participant "main : app" as M
participant ":CsvVocabularyRepository" as VR
participant ":CsvProgressRepository" as PR
participant "level : Level" as L
participant ":StudySession" as S
participant ":Deck" as D
participant ":SpeechPort" as SP
M -> VR : load()
VR --> M : vocabulary
M -> PR : load()
PR --> M : deck | None
alt deck is None
create D
M -> D : from_vocabulary(vocabulary)
D --> M : deck
end
M -> L : first(vocabulary.cards)
L --> M : level_cards
create S
M -> S : create(deck, progress, speech, choose, level_cards)
M -> S : next_card()
activate S
S -> D : within(level_cards)
D --> S : candidates
opt candidates is not empty
S -> D : draw(choose, exclude, among=candidates)
D --> S : card
S -> SP : speak(card.front, front_code)
end
S --> M : CardDto | None
deactivate S
@enduml
```
### Pattern Annotations
| Pattern (GRASP / GoF) | Applied to | Rationale |
| --- | --- | --- |
| Creator | `app.main` creates `StudySession` | It holds the adapters the session needs |
| Information Expert | `Level.first`, `Deck.within`, `Deck.draw` | The level knows its limit, the deck knows its cards |
| Null Object | `NullSpeech` as `SpeechPort` | The session never tests for speech |
### Postcondition Coverage
| Postcondition (from contract) | Satisfied by message |
| --- | --- |
| A `StudySession` was created and associated with the level | `create(deck, progress, speech, choose, level_cards)` |
| A `Deck` was created from the progress file or a copy of the `Vocabulary`, cards outside the level kept | `PR.load()`, `alt` fragment, `from_vocabulary` |
| The level's cards are the first N cards of the `Vocabulary` | `first(vocabulary.cards)` |
| `current_card` set and a `CardDto` returned, or `None`; the word was passed to the `SpeechPort` | `next_card()` with `within`, the `opt` fragment and `speak` |
### Responsibility Check
The composition root only wires; the level selects, the deck holds, the session coordinates; no object receives all messages.
## Sequence: openWordList
**Realizes:** `openWordList` in [OC-001]
### Diagram
```plantuml
@startuml
participant ":MenuView" as V
participant ":Application" as A
participant ":CsvVocabularyRepository" as VR
V -> A : open_word_list(path)
activate A
create VR
A -> VR : create(path)
A -> VR : load()
alt file is a word list
VR --> A : vocabulary
A -> A : drop session, use progress file of path
A --> V : levels
else file is refused
VR --> A : VocabularyError
A --> V : message, earlier list stays
end
deactivate A
@enduml
```
### Pattern Annotations
| Pattern (GRASP / GoF) | Applied to | Rationale |
| --- | --- | --- |
| Controller | `Application` | Receives the menu command and coordinates the repositories and the session |
| Repository | `CsvVocabularyRepository` | The file format stays in the adapter |
### Postcondition Coverage
| Postcondition (from contract) | Satisfied by message |
| --- | --- |
| The vocabulary and the progress file of `path` are in use | `load()`, `use progress file of path` |
| The earlier session was dropped and the levels are returned | `drop session`, `levels` |
| A refused file leaves everything as it was | the `else` branch |
### Responsibility Check
The view forwards the command; the application validates through the repository before it replaces anything.
## Sequence: resetWordList
**Realizes:** `resetWordList` in [OC-001]
### Diagram
```plantuml
@startuml
participant ":MenuView" as V
participant ":Application" as A
participant ":CsvProgressRepository" as PR
V -> A : reset_word_list()
activate A
A -> PR : reset()
PR --> A : done
A -> A : drop session
A --> V : levels
deactivate A
@enduml
```
### Pattern Annotations
| Pattern (GRASP / GoF) | Applied to | Rationale |
| --- | --- | --- |
| Controller | `Application` | Sequences the reset and the return to the level screen |
| Repository | `CsvProgressRepository` | Knows where the progress file is |
### Postcondition Coverage
| Postcondition (from contract) | Satisfied by message |
| --- | --- |
| The progress file of the word list in use does not exist | `reset()` |
| The session was dropped and the levels are returned | `drop session`, `levels` |
### Responsibility Check
The confirmation is asked by the view before `reset_word_list` is called; the repository deletes only its own file.
## Sequence: markKnown
**Realizes:** `markKnown` in [OC-001]
### Diagram
```plantuml
@startuml
participant ":FlashCardView" as V
participant ":FlashCardViewModel" as VM
participant ":StudySession" as S
participant ":Deck" as D
participant ":CsvProgressRepository" as PR
V -> VM : is_known()
activate VM
VM -> S : mark_known()
activate S
opt current_card is not None
S -> D : remove(card)
S -> PR : save(deck)
end
deactivate S
VM -> S : next_card()
S --> VM : CardDto | None
VM --> V : side, language name, text
deactivate VM
@enduml
```
### Pattern Annotations
| Pattern (GRASP / GoF) | Applied to | Rationale |
| --- | --- | --- |
| MVVM | `FlashCardView`, `FlashCardViewModel` | The view raises the event and shows the result; the rule is behind the view model |
| Repository | `CsvProgressRepository` | The session stores the deck through a port |
### Postcondition Coverage
| Postcondition (from contract) | Satisfied by message |
| --- | --- |
| The card was removed from the `Deck` | `remove(card)` |
| The `Deck` was stored | `save(deck)` |
| `current_card` was set to `None` | `mark_known()` ends with no current card; `next_card()` then draws the next |
### Responsibility Check
The view model only sequences two session calls and maps the result for the view.
## Sequence: markUnknown
**Realizes:** `markUnknown` in [OC-001]
### Diagram
```plantuml
@startuml
participant ":FlashCardView" as V
participant ":FlashCardViewModel" as VM
participant ":StudySession" as S
participant ":Deck" as D
participant ":SpeechPort" as SP
V -> VM : next_card()
VM -> S : next_card()
activate S
S -> D : within(level_cards)
D --> S : candidates
opt candidates is not empty
S -> D : draw(choose, exclude=current, among=candidates)
D --> S : card
S -> SP : speak(card.front, front_code)
end
S --> VM : CardDto | None
deactivate S
VM --> V : side, language name, text
@enduml
```
### Pattern Annotations
| Pattern (GRASP / GoF) | Applied to | Rationale |
| --- | --- | --- |
| Information Expert | `Deck.draw` | The deck knows its cards |
### Postcondition Coverage
| Postcondition (from contract) | Satisfied by message |
| --- | --- |
| A different card of the level was chosen when two or more exist | `within(level_cards)`, `draw(choose, exclude=current, among=candidates)` |
| Deck and file unchanged | no `remove` or `save` message |
| The Malay word was passed to the `SpeechPort` | `speak(card.front, front_code)` |
### Responsibility Check
Same as `markKnown`; the session is the only object that speaks and draws.
---
[OC-001]: ./oc.md
[DCD-001]: ../dcd.md
[DICT-001]: ../dictionary.md
[0b983b7]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/0b983b7fdadf6958717c1d0227d0f2ebe037f7b1
[2211d0f]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/2211d0f4cbd8182314d18cbdefd939ae50c39e6d
+82 -63
View File
@@ -1,63 +1,82 @@
# System Sequence Diagram: Study Flash Cards
## Metadata
| Key | Value |
| --- | --- |
| ID | SSD-001 |
| CrossReference | [UC-001], [DM-001], [OC-001] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [c3fbcbc] |
---
## Source Use Case
Study Flash Cards ([UC-001]) — scenario: main success scenario, with the unknown button as one repetition.
## Diagram
```plantuml
@startuml
actor Learner as L
participant ":System" as S
L -> S : startStudySession()
S --> L : card (word, language name)
... 3000 ms pass, the system turns the card over ...
S --> L : card (translation, language name)
L -> S : markKnown()
S --> L : next card (word, language name)
L -> S : markUnknown()
S --> L : next card (word, language name)
@enduml
```
## System Operations
| Step | Message | Parameters | Return | Use case step |
| --- | --- | --- | --- | --- |
| 1 | startStudySession | none | card to show, or "nothing left to learn" | 1, 2, 3 |
| 2 | (timer) turn the card over | none | the same card, translation side | 4 |
| 3 | markKnown | none | next card, or "nothing left to learn" | 5, 6, 7 |
| 4 | markUnknown | none | next card | 5a, 7 |
The turn-over in step 2 is started by the system's own timer, not by a message from the Learner; it is shown as a return without a call, which is the one deviation from "every return answers a message".
## Alternate Flows
The extensions 2a, 3a, 5b and 7a of [UC-001] add no system operation of their own (they are errors, speech and timer handling inside the three operations above); their behaviour is in [OC-001] as exceptions. They are out of scope of this diagram, which shows the main success scenario with `markUnknown` as the one alternate answer.
## Lifecycle Notes
The system instance lives for one run of the program. The words to learn are created when the session starts and saved after each `markKnown`.
---
[UC-001]: ./uc.md
[DM-001]: ../domain-model.md
[OC-001]: ./oc.md
[c3fbcbc]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/c3fbcbcfaf799e0ae34aed7e14d3bc8a62f03db3
# System Sequence Diagram: Study Flash Cards
## Metadata
| Key | Value |
| --- | --- |
| ID | SSD-001 |
| CrossReference | [UC-001], [DM-001], [OC-001] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Deprecated | Jens Tirsvad Nielsen | AI as stand-in for S01 | Added chooseLevel; startStudySession returns the levels | [0b983b7] |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Added the menu operations | [2211d0f] |
---
## Source Use Case
Study Flash Cards ([UC-001]) — scenario: main success scenario, with the unknown button as one repetition.
## Diagram
```plantuml
@startuml
actor Learner as L
participant ":System" as S
L -> S : startStudySession()
S --> L : levels (100 words, 1000 words, all words)
L -> S : chooseLevel(level)
S --> L : card (word, language name)
... 3000 ms pass, the system turns the card over ...
S --> L : card (translation, language name)
L -> S : markKnown()
S --> L : next card (word, language name)
L -> S : markUnknown()
S --> L : next card (word, language name)
L -> S : openWordList(path)
S --> L : levels, or the reason the file is refused
L -> S : changeLevel()
S --> L : levels
L -> S : resetWordList()
S --> L : levels
L -> S : showContact()
S --> L : name, title, link opened
L -> S : exit()
@enduml
```
## System Operations
| Step | Message | Parameters | Return | Use case step |
| --- | --- | --- | --- | --- |
| 1 | startStudySession | none | the levels to choose from | 1, 2 |
| 2 | chooseLevel | level | card to show, or "nothing left to learn" | 3, 4, 5 |
| 3 | (timer) turn the card over | none | the same card, translation side | 6 |
| 4 | markKnown | none | next card, or "nothing left to learn" | 7, 8, 9 |
| 5 | markUnknown | none | next card, or "nothing left to learn" | 7a, 9 |
| 6 | openWordList | path of a CSV file | the levels, or the reason the file is refused | *a.1 |
| 7 | changeLevel | none | the levels | *a.2 |
| 8 | resetWordList | none (the Learner confirmed) | the levels | *a.3 |
| 9 | showContact | none | the author's name and title; the link is opened | *a.4 |
| 10 | exit | none | none; the program ends | *a.5 |
The turn-over in step 3 is started by the system's own timer, not by a message from the Learner; it is shown as a return without a call, which is the one deviation from "every return answers a message". When the level is given at start (extension 3a of [UC-001]) the Learner's first message is `chooseLevel` and `startStudySession` is not sent.
## Alternate Flows
The extensions 3a, 4a, 5a, 7b and 9a of [UC-001] add no system operation of their own (they are errors, speech, timer and level handling inside the operations above); their behaviour is in [OC-001] as exceptions. They are out of scope of this diagram, which shows the main success scenario with `markUnknown` as the one alternate answer.
## Lifecycle Notes
The system instance lives for one run of the program. The words to learn are created when the level is chosen and saved after each `markKnown`.
---
[UC-001]: ./uc.md
[DM-001]: ../domain-model.md
[OC-001]: ./oc.md
[0b983b7]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/0b983b7fdadf6958717c1d0227d0f2ebe037f7b1
[2211d0f]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/2211d0f4cbd8182314d18cbdefd939ae50c39e6d
+94 -78
View File
@@ -1,78 +1,94 @@
# UC-001: Study Flash Cards
## Metadata
| Key | Value |
| --- | --- |
| ID | UC-001 |
| CrossReference | [UCD-001], [US-001], [SA-001], [DM-001], [SSD-001] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [c3fbcbc] |
---
**Format:** Fully Dressed
## Fully Dressed
- **Scope:** Flash Card program
- **Level:** user-goal
- **Primary Actor:** Learner
- **Stakeholders and Interests:**
- S01 — learns the Malay words and wants only unknown words to come up
- S02 — wants to see the assignment's behaviour step by step
- **Preconditions:**
- A word list exists.
- A display is available.
- **Postconditions (success guarantee):**
- The words the Learner marked as known are no longer in the words to learn.
- The words to learn are kept, so that the next session starts from them.
### Main Success Scenario
1. The Learner starts the program.
2. The system loads the words to learn: from the kept progress when it exists, otherwise from the word list.
3. The system shows a random card with the word in Malay.
4. After three seconds the system turns the card over and shows the translation in Danish.
5. The Learner states that the word is known.
6. The system removes the word from the words to learn and keeps the words to learn.
7. The system shows a new random card, and the Learner repeats from step 4 until no word is left.
### Extensions (Alternative / Exception Flows)
- 3a. Spoken words are available on the Learner's machine:
1. The system speaks the Malay word. If speaking fails, the system logs it and goes on.
- 5a. The Learner states that the word is not known:
1. The system keeps the word in the words to learn and shows a new random card; the Learner goes on at step 4.
- 5b. The Learner answers before three seconds have passed:
1. The system cancels the turn-over of the card being shown and starts a new one for the next card.
- 7a. No word is left:
1. The system tells the Learner that there is nothing left to learn, and further answers change nothing.
- 2a. The kept progress or the word list is unreadable:
1. The system reports the problem to the Learner and ends; it does not overwrite the kept progress.
### Special Requirements / Business Rules
| Step | Rule |
| --- | --- |
| 3, 7 | The next card is chosen at random from the words to learn |
| 4 | The turn-over comes three seconds after the card appears |
| 6 | A word is identified by its Malay and Danish text; the first equal word is removed |
| 2 | The word list names its two languages and holds one word and one translation per card |
### Open Issues
- Starting again (resetting the kept progress) is not offered in the program; deleting the kept progress does it.
---
[UCD-001]: ../use-case-diagram.md
[US-001]: ../user-stories.md
[SA-001]: ../stakeholder-analysis.md
[DM-001]: ../domain-model.md
[SSD-001]: ./ssd.md
[c3fbcbc]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/c3fbcbcfaf799e0ae34aed7e14d3bc8a62f03db3
# UC-001: Study Flash Cards
## Metadata
| Key | Value |
| --- | --- |
| ID | UC-001 |
| CrossReference | [UCD-001], [US-001], [SA-001], [DM-001], [SSD-001] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Deprecated | Jens Tirsvad Nielsen | AI as stand-in for S01 | Added the choice of level (US-001.06) | [0b983b7] |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Added the menu commands as an extension (US-001.09 to US-001.12) | [2211d0f] |
---
**Format:** Fully Dressed
## Fully Dressed
- **Scope:** Flash Card program
- **Level:** user-goal
- **Primary Actor:** Learner
- **Stakeholders and Interests:**
- S01 — learns the Malay words and wants only unknown words to come up
- S02 — wants to see the assignment's behaviour step by step
- **Preconditions:**
- A word list exists.
- A display is available.
- **Postconditions (success guarantee):**
- The words the Learner marked as known are no longer in the words to learn.
- The words to learn are kept, so that the next session starts from them.
### Main Success Scenario
1. The Learner starts the program.
2. The system offers the levels: 100 words, 1000 words and all words.
3. The Learner chooses a level.
4. The system loads the words to learn: from the kept progress when it exists, otherwise from the word list.
5. The system shows a random card, with the word in Malay, from the first words of the word list that fit the level and are still to learn.
6. After three seconds the system turns the card over and shows the translation in Danish.
7. The Learner states that the word is known.
8. The system removes the word from the words to learn and keeps the words to learn.
9. The system shows a new random card of the level, and the Learner repeats from step 6 until no word is left at the level.
### Extensions (Alternative / Exception Flows)
- 3a. The Learner has given the level when starting the program:
1. The system skips steps 2 and 3 and goes on at step 4.
- 5a. Spoken words are available on the Learner's machine:
1. The system speaks the Malay word. If speaking fails, the system logs it and goes on.
- 7a. The Learner states that the word is not known:
1. The system keeps the word in the words to learn and shows a new random card of the level; the Learner goes on at step 6.
- 7b. The Learner answers before three seconds have passed:
1. The system cancels the turn-over of the card being shown and starts a new one for the next card.
- 9a. No word is left at the level:
1. The system tells the Learner that there is nothing left to learn at this level, and further answers change nothing.
- 4a. The kept progress or the word list is unreadable:
1. The system reports the problem to the Learner and ends; it does not overwrite the kept progress.
- *a. At any time the Learner uses a menu command:
1. Open a word list: the system asks for a file and checks it; when it is a word list, the system replaces the word list in use and goes on at step 2; when it is not, the system tells the Learner why and keeps the word list in use. When the Learner cancels nothing changes.
2. Change level: the system goes on at step 2 with the word list in use; the kept progress stays.
3. Reset word list: the system asks the Learner to confirm; on yes it removes the kept progress of the word list in use and goes on at step 2, so all its words are to learn again; on no nothing changes.
4. Contact: the system shows the author's name and title and opens the author's LinkedIn page in the web browser.
5. Exit: the system ends the program.
### Special Requirements / Business Rules
| Step | Rule |
| --- | --- |
| 2, 3 | A level is a number of words (100 or 1000) or all words |
| 5 | The word list is ordered from the most to the least frequent word; a level of N words is its first N words; a list shorter than N is used whole |
| 5, 9 | The next card is chosen at random from the words of the level that are still to learn |
| 6 | The turn-over comes three seconds after the card appears |
| 8 | A word is identified by its Malay and Danish text; the first equal word is removed; known words stay known at every level and words outside the level are kept |
| 4 | The word list names its two languages and holds one word and one translation per card |
| *a | The kept progress of each word list is separate; resetting one word list never changes another word list or the word list itself |
### Open Issues
- Starting again (resetting the kept progress) is not offered in the program; deleting the kept progress does it.
- Going back to the level choice without restarting the program is not offered.
---
[UCD-001]: ../use-case-diagram.md
[US-001]: ../user-stories.md
[SA-001]: ../stakeholder-analysis.md
[DM-001]: ../domain-model.md
[SSD-001]: ./ssd.md
[0b983b7]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/0b983b7fdadf6958717c1d0227d0f2ebe037f7b1
[2211d0f]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/2211d0f4cbd8182314d18cbdefd939ae50c39e6d
+49 -1
View File
@@ -1,8 +1,32 @@
# Wireframe: Study Flash Cards
_Revision 2026-10-14: the level screen (screen 1) was added for US-001.06. It was drawn by the AI from the use case because the Product Owner gave no wireframe for it; S01 may change it._
The Product Owner gave this screen in the first prompt (the course's target screenshot). The presentation layer implements it and does not redesign it. Source use case: [UC-001](./uc.md).
## Screen
## Screen 1: Choose your level
```text
+----------------------------------------------------------+ background #B1DDC6
| padding 50 px |
| |
| Choose your level (Arial 40 italic) |
| |
| [ 100 words ] |
| [ 1000 words ] |
| [ All words ] |
| |
+----------------------------------------------------------+
```
| Element | Position | Details |
| --- | --- | --- |
| Window | whole | Same title, padding and background as the card screen |
| Title | row 0 | "Choose your level", Arial 40 italic |
| Level buttons | rows 1 to 3, one column | Labels "100 words", "1000 words", "All words"; Arial 24 bold; white background, equal width |
| After a choice | whole | The screen is replaced by screen 2 on the same window |
## Screen 2: The card
```text
+----------------------------------------------------------+ background #B1DDC6
@@ -36,3 +60,27 @@ The Product Owner gave this screen in the first prompt (the course's target scre
| Front (first 3000 ms) | `card_front.png` | Malay | the Malay word | black |
| Back (after 3000 ms) | `card_back.png` | Danish | the Danish translation | white |
| Finished | `card_front.png` | (empty) | "Nothing left to learn" | black |
## Menu bar and dialogs (all screens)
```text
+----------------------------------------------------------+
| File About | classic menu bar of the window
+----------------------------------------------------------+
File About
+------------------------+ +-----------------------------------------------+
| Open... | | Contact > |
| Change level... | | +-----------------------------------------+|
| Reset word list... | | | Jens Tirsvad Nielsen, Software engineer ||
| ---------------------- | | | (LinkedIn) ||
| Exit | | +-----------------------------------------+|
+------------------------+ +-----------------------------------------------+
```
| Element | Behaviour |
| --- | --- |
| File, Open... | Standard file dialog for `*.csv` (all files allowed), starting in the data folder; a refused file shows an error message with the reason |
| File, Change level... | Replaces the screen by Screen 1 |
| File, Reset word list... | Question "Start `<name>` from the beginning? All words will be to learn again." with Yes and No; Yes replaces the screen by Screen 1 |
| File, Exit | Closes the window |
| About, Contact, the author entry | Opens https://www.linkedin.com/in/tirsvad74 in the web browser |
+211 -105
View File
@@ -1,105 +1,211 @@
# User Stories: Flash Card
## Metadata
| Key | Value |
| --- | --- |
| ID | US-001 |
| CrossReference | [UCD-001], [BC-001], [UC-001], [MIL-002], [MIL-003], [MIL-004], [MIL-005], [MIL-006] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [c3fbcbc] |
---
## Purpose and Scope
These stories cover the epic "Study Flash Cards": the four steps of the course assignment (the window, new cards, flipping the cards, saving progress) and the spoken Malay word. Each story is delivered by one milestone. The wireframe the stories follow is in `docs/uc-001/wireframe.md`.
## Story List
### US-001.01 — See a flash card
**As a** Learner, **I want** a window that shows one flash card with the language name, a word and two buttons (known and unknown), **so that** I can see what I am asked to learn.
**Acceptance Criteria**
- Given the program is started, when the window opens, then it shows a card with the language name above a word, a button for "I do not know it" under the left side and a button for "I know it" under the right side.
- Given the window is open, when I look at the card, then the language name is in italics and the word is in bold, both centred on the card.
| Traces to | Size | INVEST exceptions |
| --- | --- | --- |
| [MIL-002], [UC-001] | fits one iteration | none |
### US-001.02 — Get a new card
**As a** Learner, **I want** a new random word every time I press a button, **so that** I do not meet the words in a fixed order.
**Acceptance Criteria**
- Given a card is shown, when I press the known button or the unknown button, then a different random word from the word list is shown.
- Given the word list has one word, when I press a button, then that word is shown again and the program does not fail.
| Traces to | Size | INVEST exceptions |
| --- | --- | --- |
| [MIL-003], [UC-001] | fits one iteration | none |
### US-001.03 — See the translation
**As a** Learner, **I want** the card to turn over after three seconds and show the translation, **so that** I can check my answer without asking for it.
**Acceptance Criteria**
- Given a new card is shown, when 3000 ms have passed, then the card shows the back image, the language name of the translation, the translation, and the text is white.
- Given a card was shown less than 3000 ms ago, when I press a button, then the earlier timer is cancelled and only the new card is flipped after its own 3000 ms.
| Traces to | Size | INVEST exceptions |
| --- | --- | --- |
| [MIL-004], [UC-001] | fits one iteration | none |
### US-001.04 — Keep my progress
**As a** Learner, **I want** the words I know to stop coming up, and the words still to learn to be kept when I close the program, **so that** I am only tested on what I do not know.
**Acceptance Criteria**
- Given a card is shown, when I press the known button, then that word is removed from the words to learn and the remaining words are saved in `words_to_learn.csv`.
- Given `words_to_learn.csv` exists, when the program starts, then the cards come from that file.
- Given `words_to_learn.csv` does not exist, when the program starts, then the cards come from the word list `ms-da.csv`.
- Given all words are known, when the last known button is pressed, then the program shows a message that there is nothing left to learn and does not fail.
| Traces to | Size | INVEST exceptions |
| --- | --- | --- |
| [MIL-005], [UC-001] | fits one iteration | none |
### US-001.05 — Hear the Malay word
**As a** Learner, **I want** to hear the Malay word when its card is shown, **so that** I learn how it is pronounced.
**Acceptance Criteria**
- Given the speech extra is installed and a network is available, when a card shows a Malay word, then the word is spoken in Malay.
- Given the speech extra is not installed or no network is available, when a card is shown, then the program works as without speech and does not show an error to the Learner.
| Traces to | Size | INVEST exceptions |
| --- | --- | --- |
| [MIL-006], [UC-001] | fits one iteration | none |
## INVEST Check
All five stories are Independent in delivery order (each builds on the one before but can be accepted alone), Negotiable in wording, Valuable to the Learner, Estimable, Small (one milestone each) and Testable (every criterion is Given/When/Then). Exception: US-001.02 to US-001.05 depend on the window of US-001.01, which is stated in their milestones' Dependencies.
---
[UCD-001]: ./use-case-diagram.md
[BC-001]: ./business-case.md
[UC-001]: ./uc-001/uc.md
[MIL-002]: ./milestones/mil-002-step1-user-interface.md
[MIL-003]: ./milestones/mil-003-step2-new-flash-cards.md
[MIL-004]: ./milestones/mil-004-step3-flip-cards.md
[MIL-005]: ./milestones/mil-005-step4-save-progress.md
[MIL-006]: ./milestones/mil-006-malay-speech.md
[c3fbcbc]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/c3fbcbcfaf799e0ae34aed7e14d3bc8a62f03db3
# User Stories: Flash Card
## Metadata
| Key | Value |
| --- | --- |
| ID | US-001 |
| CrossReference | [UCD-001], [BC-001], [UC-001], [MIL-002], [MIL-003], [MIL-004], [MIL-005], [MIL-006], [MIL-008], [MIL-009], [MIL-010], [MIL-011] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-15 | Deprecated | Jens Tirsvad Nielsen | AI as stand-in for S01 | Added US-001.09 to US-001.12 (menu bar) | [2211d0f] |
| 2026-10-15 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | US-001.08 names the latest release instead of v0.1.0 | [0264b60] |
---
## Purpose and Scope
These stories cover the epic "Study Flash Cards": the four steps of the course assignment (the window, new cards, flipping the cards, saving progress), the spoken Malay word the choice of level the start without an installed Python the download of the executable from a release and the menu bar. Each story is delivered by one milestone. The wireframe the stories follow is in `docs/uc-001/wireframe.md`.
## Story List
### US-001.01 — See a flash card
**As a** Learner, **I want** a window that shows one flash card with the language name, a word and two buttons (known and unknown), **so that** I can see what I am asked to learn.
**Acceptance Criteria**
- Given the program is started, when the window opens, then it shows a card with the language name above a word, a button for "I do not know it" under the left side and a button for "I know it" under the right side.
- Given the window is open, when I look at the card, then the language name is in italics and the word is in bold, both centred on the card.
| Traces to | Size | INVEST exceptions |
| --- | --- | --- |
| [MIL-002], [UC-001] | fits one iteration | none |
### US-001.02 — Get a new card
**As a** Learner, **I want** a new random word every time I press a button, **so that** I do not meet the words in a fixed order.
**Acceptance Criteria**
- Given a card is shown, when I press the known button or the unknown button, then a different random word from the word list is shown.
- Given the word list has one word, when I press a button, then that word is shown again and the program does not fail.
| Traces to | Size | INVEST exceptions |
| --- | --- | --- |
| [MIL-003], [UC-001] | fits one iteration | none |
### US-001.03 — See the translation
**As a** Learner, **I want** the card to turn over after three seconds and show the translation, **so that** I can check my answer without asking for it.
**Acceptance Criteria**
- Given a new card is shown, when 3000 ms have passed, then the card shows the back image, the language name of the translation, the translation, and the text is white.
- Given a card was shown less than 3000 ms ago, when I press a button, then the earlier timer is cancelled and only the new card is flipped after its own 3000 ms.
| Traces to | Size | INVEST exceptions |
| --- | --- | --- |
| [MIL-004], [UC-001] | fits one iteration | none |
### US-001.04 — Keep my progress
**As a** Learner, **I want** the words I know to stop coming up, and the words still to learn to be kept when I close the program, **so that** I am only tested on what I do not know.
**Acceptance Criteria**
- Given a card is shown, when I press the known button, then that word is removed from the words to learn and the remaining words are saved in `words_to_learn.csv`.
- Given `words_to_learn.csv` exists, when the program starts, then the cards come from that file.
- Given `words_to_learn.csv` does not exist, when the program starts, then the cards come from the word list `ms-da.csv`.
- Given all words are known, when the last known button is pressed, then the program shows a message that there is nothing left to learn and does not fail.
| Traces to | Size | INVEST exceptions |
| --- | --- | --- |
| [MIL-005], [UC-001] | fits one iteration | none |
### US-001.05 — Hear the Malay word
**As a** Learner, **I want** to hear the Malay word when its card is shown, **so that** I learn how it is pronounced.
**Acceptance Criteria**
- Given the speech extra is installed and a network is available, when a card shows a Malay word, then the word is spoken in Malay.
- Given the speech extra is not installed or no network is available, when a card is shown, then the program works as without speech and does not show an error to the Learner.
| Traces to | Size | INVEST exceptions |
| --- | --- | --- |
| [MIL-006], [UC-001] | fits one iteration | none |
### US-001.06 — Choose my level
**As a** Learner, **I want** to choose a level of 100 words, 1000 words or all words before I start, **so that** I begin with the most frequent words and widen the list when I am ready.
**Acceptance Criteria**
- Given the program is started, when the window opens, then I see the choices 100 words, 1000 words and All words, and no card yet.
- Given I choose a level of N words, when the first card is shown, then every card comes from the first N words of the word list, which is ordered from the most to the least frequent word.
- Given I choose 1000 words or All words and the word list has fewer words than that, when the cards are drawn, then all words of the word list are used.
- Given I have marked words as known at one level, when I choose another level, then the known words stay known and only the words of the chosen level that I do not know yet come up.
- Given every word of the chosen level is known, when the level is chosen, then the program tells me that there is nothing left to learn at this level.
| Traces to | Size | INVEST exceptions |
| --- | --- | --- |
| [MIL-008], [UC-001] | fits one iteration | none |
### US-001.07 — Start without Python
**As a** Learner, **I want** to start the program by opening one executable file, **so that** I can learn without installing Python or a virtual environment.
**Acceptance Criteria**
- Given the executable was built, when I open it on a Windows computer without Python, then the level screen appears and no console window opens.
- Given I mark a word as known in the executable, when I open it again, then the known word does not come up (my progress is kept in `data/words_to_learn.csv` next to the executable).
- Given a `data/ms-da.csv` exists next to the executable, when the program starts, then that word list is used; otherwise the word list inside the executable is used.
- Given the speech extra was included in the build and a network is available, when a card is shown, then the Malay word is spoken; without a network the program works silently.
| Traces to | Size | INVEST exceptions |
| --- | --- | --- |
| [MIL-009], [UC-001] | fits one iteration | none |
### US-001.08 — Download the executable
**As a** Learner, **I want** to download the executable from a release page of the repository, **so that** I can use the program without building it.
**Acceptance Criteria**
- Given a release exists (for example `v0.2.0`), when I open the releases page of the repository, then I find release notes and, when the git host accepts the upload, `flash-card.exe` and a checksum file attached to it.
- Given I downloaded `flash-card.exe`, when I compute its SHA-256 hash, then it equals the value in the checksum file and in the release notes.
- Given I read the release notes, when I look for what the file is, then they say that it is an unsigned Windows build, what the `data` folder next to it holds, and how to build it myself.
| Traces to | Size | INVEST exceptions |
| --- | --- | --- |
| [MIL-010], [UC-001] | fits one iteration | none |
### US-001.09 — Open another word list
**As a** Learner, **I want** to open another word list from a CSV file with the File menu, **so that** I can learn another language pair than the one delivered.
**Acceptance Criteria**
- Given the program is running, when I choose File, Open, then a file dialog lets me pick a CSV file that starts in the data folder.
- Given I picked a valid word list, when the dialog closes, then I choose a level and the cards come from that list, and my progress in it is kept apart from the progress in other lists.
- Given I picked a file that is not a word list (no header of two language codes, or a row that is not two cells), when the dialog closes, then a message names the problem and the earlier word list stays in use.
- Given I cancel the dialog, when it closes, then nothing changes.
| Traces to | Size | INVEST exceptions |
| --- | --- | --- |
| [MIL-011], [UC-001] | fits one iteration | none |
### US-001.10 — Change the level while learning
**As a** Learner, **I want** to change the level from the File menu, **so that** I do not have to restart the program to make the word list easier or harder.
**Acceptance Criteria**
- Given a card is shown, when I choose File, Change level, then I see the level choices again.
- Given I choose a level, when the cards continue, then they come from that level and the words I know stay known.
| Traces to | Size | INVEST exceptions |
| --- | --- | --- |
| [MIL-011], [UC-001] | fits one iteration | none |
### US-001.11 — Learn a word list from the start again
**As a** Learner, **I want** to reset the current word list from the File menu, **so that** all its words are to learn again.
**Acceptance Criteria**
- Given a word list is open, when I choose File, Reset word list, then I am asked to confirm and the message names the word list.
- Given I confirm, when the reset is done, then the progress of that word list is gone, all its words are to learn again and the level choice is shown; the progress of other word lists and the word list file itself are not changed.
- Given I do not confirm, when the question closes, then nothing changes.
| Traces to | Size | INVEST exceptions |
| --- | --- | --- |
| [MIL-011], [UC-001] | fits one iteration | none |
### US-001.12 — Find the author and leave the program
**As a** Learner, **I want** an About menu with the author's contact and a File, Exit command, **so that** I can reach the author and close the program in the usual way.
**Acceptance Criteria**
- Given the program is running, when I choose About, Contact, then I see an entry with the author's name and title (Jens Tirsvad Nielsen, Software engineer) and, when I choose it, the author's LinkedIn page opens in my web browser.
- Given the program is running, when I choose File, Exit, then the window closes and the program ends.
| Traces to | Size | INVEST exceptions |
| --- | --- | --- |
| [MIL-011], [UC-001] | fits one iteration | none |
## INVEST Check
All twelve stories are Independent in delivery order (each builds on the one before but can be accepted alone), Negotiable in wording, Valuable to the Learner, Estimable, Small (one milestone each) and Testable (every criterion is Given/When/Then). Exception: US-001.02 to US-001.12 depend on the window of US-001.01, which is stated in their milestones' Dependencies.
---
[UCD-001]: ./use-case-diagram.md
[BC-001]: ./business-case.md
[UC-001]: ./uc-001/uc.md
[MIL-002]: ./milestones/mil-002-step1-user-interface.md
[MIL-003]: ./milestones/mil-003-step2-new-flash-cards.md
[MIL-004]: ./milestones/mil-004-step3-flip-cards.md
[MIL-005]: ./milestones/mil-005-step4-save-progress.md
[MIL-006]: ./milestones/mil-006-malay-speech.md
[MIL-008]: ./milestones/mil-008-choose-level.md
[MIL-009]: ./milestones/mil-009-executable.md
[MIL-010]: ./milestones/mil-010-release.md
[MIL-011]: ./milestones/mil-011-menu-bar.md
[2211d0f]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/2211d0f4cbd8182314d18cbdefd939ae50c39e6d
[0264b60]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/commit/0264b6084f26bac5af716ea71596ce3be961fec8
+41
View File
@@ -0,0 +1,41 @@
# Arkitektur
🌐 [English](Architecture) · **Dansk** · [Bahasa Malaysia](Architecture-ms)
Programmet er bygget i fire lag under `src/flash_card/`. Importer peger indad; `lint-imports` kontrollerer det.
| Lag | Indeholder | Må importere |
| --- | --- | --- |
| `domain` | `Card`, `LanguagePair`, `Level`, `Vocabulary`, `Deck`, fejlene og repository-grænsefladerne | ingenting |
| `application` | `StudySession`, `open_study_session`, `CardDto` og `SpeechPort` | `domain` |
| `infrastructure` | CSV-repositories og tale-adaptere | `application`, `domain` |
| `presentation` | `FlashCardView`, `FlashCardViewModel` (MVVM) og kompositionsroden `app.py` | alle lag |
Alle konstanter står i `src/flash_card/constants.py`.
## Hvor er hvert opgavetrin?
| Opgave | Kode |
| --- | --- |
| Trin 1: vindue, lærred, billede, tekster, knapper | `FlashCardView.__init__` i `presentation/features/flash_card/flash_card_view.py`; billederne laves af `tools/generate_images.py` |
| Trin 2: læs CSV, tilfældigt ord ved hvert tryk | `CsvVocabularyRepository` og `read_word_list` (erstatter `pandas`), `Deck.draw`, `StudySession.next_card`, `FlashCardView.next_card` |
| Trin 3: vend efter 3 sekunder | `FlashCardView.flip_card`, `FlashCardView.flip_timer` (`after`, `after_cancel`), `FlashCardViewModel.flip_card` |
| Trin 4: kendte ord, `words_to_learn.csv` | `FlashCardView.is_known`, `StudySession.mark_known`, `CsvProgressRepository`, `open_study_session` |
| Ekstra: niveauvalg | `Level`, `Deck.within`, `StudySession.next_card`, `open_study_session`, `LevelView`, `LevelViewModel`, `Application.start` i `presentation/app.py` |
| Ekstra: tale | `SpeechPort`, `GttsSpeech`, `NullSpeech`, `build_speech` i `presentation/app.py` |
## Hvorfor en lagdelt løsning til en lille opgave?
Reglerne (hvilket kort der kommer næste gang, hvad et kendt ord gør) testes uden vindue og uden filsystem. Vinduet, CSV-filerne og taletjenesten kan udskiftes uden at røre reglerne. Se ADR-0001 og ADR-0002 i `docs/adr/`.
## Test
| Mappe | Hvad den tester |
| --- | --- |
| `tests/unit/` | Hvert lag for sig, med falske objekter til portene |
| `tests/integration/` | Den rigtige ordliste og fremgangsfilen i en midlertidig mappe |
| `tests/e2e/` | Det rigtige Tkinter-vindue (springes over uden skærm) |
## Projektdokumenter
Business case, plan, design og gennemgangsrapporter ligger i `docs/`. Arbejdet blev udført i syv milepæle, én pull request hver: se `docs/milestones/`.
+41
View File
@@ -0,0 +1,41 @@
# Seni bina
🌐 [English](Architecture) · [Dansk](Architecture-da) · **Bahasa Malaysia**
Program dibina dalam empat lapisan di bawah `src/flash_card/`. Import menuju ke dalam; `lint-imports` memeriksanya.
| Lapisan | Mengandungi | Boleh mengimport |
| --- | --- | --- |
| `domain` | `Card`, `LanguagePair`, `Level`, `Vocabulary`, `Deck`, ralat dan antara muka repositori | tiada |
| `application` | `StudySession`, `open_study_session`, `CardDto` dan `SpeechPort` | `domain` |
| `infrastructure` | Repositori CSV dan penyesuai suara | `application`, `domain` |
| `presentation` | `FlashCardView`, `FlashCardViewModel` (MVVM) dan akar komposisi `app.py` | semua lapisan |
Semua pemalar terdapat dalam `src/flash_card/constants.py`.
## Di manakah setiap langkah tugasan?
| Tugasan | Kod |
| --- | --- |
| Langkah 1: tetingkap, kanvas, imej, teks, butang | `FlashCardView.__init__` dalam `presentation/features/flash_card/flash_card_view.py`; imej dibuat oleh `tools/generate_images.py` |
| Langkah 2: baca CSV, perkataan rawak setiap tekanan | `CsvVocabularyRepository` dan `read_word_list` (menggantikan `pandas`), `Deck.draw`, `StudySession.next_card`, `FlashCardView.next_card` |
| Langkah 3: terbalik selepas 3 saat | `FlashCardView.flip_card`, `FlashCardView.flip_timer` (`after`, `after_cancel`), `FlashCardViewModel.flip_card` |
| Langkah 4: perkataan diketahui, `words_to_learn.csv` | `FlashCardView.is_known`, `StudySession.mark_known`, `CsvProgressRepository`, `open_study_session` |
| Tambahan: pilihan tahap | `Level`, `Deck.within`, `StudySession.next_card`, `open_study_session`, `LevelView`, `LevelViewModel`, `Application.start` dalam `presentation/app.py` |
| Tambahan: suara | `SpeechPort`, `GttsSpeech`, `NullSpeech`, `build_speech` dalam `presentation/app.py` |
## Mengapa program berlapis untuk tugasan kecil?
Peraturan (kad mana yang seterusnya, apa yang berlaku apabila perkataan diketahui) diuji tanpa tetingkap atau sistem fail. Tetingkap, fail CSV dan perkhidmatan suara boleh diganti tanpa menyentuh peraturan. Lihat ADR-0001 dan ADR-0002 dalam `docs/adr/`.
## Ujian
| Folder | Apa yang diuji |
| --- | --- |
| `tests/unit/` | Setiap lapisan sendiri, dengan objek palsu untuk port |
| `tests/integration/` | Senarai perkataan sebenar dan fail kemajuan dalam folder sementara |
| `tests/e2e/` | Tetingkap Tkinter sebenar (dilangkau tanpa paparan) |
## Dokumen projek
Kes perniagaan, pelan, reka bentuk dan rekod semakan terdapat dalam `docs/`. Kerja dilakukan dalam tujuh pencapaian, satu pull request setiap satu: lihat `docs/milestones/`.
+41
View File
@@ -0,0 +1,41 @@
# Architecture
🌐 **English** · [Dansk](Architecture-da) · [Bahasa Malaysia](Architecture-ms)
The program is built in four layers under `src/flash_card/`. Imports point inward; `lint-imports` checks this.
| Layer | Holds | May import |
| --- | --- | --- |
| `domain` | `Card`, `LanguagePair`, `Level`, `Vocabulary`, `Deck`, the errors and the repository interfaces | nothing |
| `application` | `StudySession`, `open_study_session`, `CardDto` and `SpeechPort` | `domain` |
| `infrastructure` | The CSV repositories and the speech adapters | `application`, `domain` |
| `presentation` | `FlashCardView`, `FlashCardViewModel` (MVVM) and the composition root `app.py` | all layers |
All constants are in `src/flash_card/constants.py`.
## Where is each assignment step?
| Assignment | Code |
| --- | --- |
| Step 1: window, canvas, image, texts, buttons | `FlashCardView.__init__` in `presentation/features/flash_card/flash_card_view.py`; images made by `tools/generate_images.py` |
| Step 2: read the CSV, random word on each press | `CsvVocabularyRepository` and `read_word_list` (replace `pandas`), `Deck.draw`, `StudySession.next_card`, `FlashCardView.next_card` |
| Step 3: flip after 3 seconds | `FlashCardView.flip_card`, `FlashCardView.flip_timer` (`after`, `after_cancel`), `FlashCardViewModel.flip_card` |
| Step 4: known words, `words_to_learn.csv` | `FlashCardView.is_known`, `StudySession.mark_known`, `CsvProgressRepository`, `open_study_session` |
| Extra: level choice | `Level`, `Deck.within`, `StudySession.next_card`, `open_study_session`, `LevelView`, `LevelViewModel`, `Application.start` in `presentation/app.py` |
| Extra: speech | `SpeechPort`, `GttsSpeech`, `NullSpeech`, `build_speech` in `presentation/app.py` |
## Why a layered program for a small assignment?
The rules (which card comes next, what a known word does) are tested without a window or a file system. The window, the CSV files and the speech service can be replaced without touching the rules. See ADR-0001 and ADR-0002 in `docs/adr/`.
## Tests
| Folder | What it tests |
| --- | --- |
| `tests/unit/` | Each layer alone, with fakes for the ports |
| `tests/integration/` | The real word list and the progress file in a temporary folder |
| `tests/e2e/` | The real Tkinter window (skipped when no display exists) |
## Project documents
The business case, plan, design and review records are in `docs/`. The work was done in seven milestones, one pull request each: see `docs/milestones/`.
+32
View File
@@ -0,0 +1,32 @@
# Flash Card
🌐 [English](Home) · **Dansk** · [Bahasa Malaysia](Home-ms)
Et flashkortprogram til at lære de mest almindelige malajiske ord med danske oversættelser. Det er løsningen på dag 31 i Udemys kursus *100 Days of Code: The Complete Python Pro Bootcamp*.
![Niveauskærmen: vælg 100 ord, 1000 ord eller alle ord](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/raw/branch/main/docs/images/screenshot-level.png)
![Forsiden af et kort: det malajiske ord](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/raw/branch/main/docs/images/screenshot-front.png)
![Bagsiden af kortet efter tre sekunder: den danske oversættelse](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/raw/branch/main/docs/images/screenshot-back.png)
| Side | Læs den, når du vil |
| --- | --- |
| [Installation](Install-da) | Oprette `.venv`, installere programmet og køre testene |
| [Brug](Usage-da) | Øve kortene, forstå fremgangsfilen og bruge indstillingerne |
| [Arkitektur](Architecture-da) | Se lagene og finde koden til hvert opgavetrin |
## De fire opgavetrin
| Trin | Hvad programmet gør | Milepæl |
| --- | --- | --- |
| 1. Brugerflade | Et vindue med et kort og to knapper | MIL-002 |
| 2. Nye flashkort | Et tilfældigt ord fra ordlisten ved hvert tryk på en knap | MIL-003 |
| 3. Vend kortene | Efter 3 sekunder viser kortet den danske oversættelse | MIL-004 |
| 4. Gem din fremgang | Kendte ord fjernes, og resten gemmes i `words_to_learn.csv` | MIL-005 |
| Ekstra | Det malajiske ord bliver udtalt (valgfrit) | MIL-006 |
| Ekstra | Du vælger først et niveau: de første 100 ord, de første 1000 ord eller alle ord | MIL-008 |
## Til kursister
Opgavens funktionsnavne er bevaret: `next_card`, `flip_card`, `is_known` og attributterne `flip_timer` og `current_card`. Data læses med standardbibliotekets `csv`-modul i stedet for `pandas`, så kerneprogrammet ikke har nogen afhængigheder ved kørsel.
Repository: <https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card>
+32
View File
@@ -0,0 +1,32 @@
# Flash Card
🌐 [English](Home) · [Dansk](Home-da) · **Bahasa Malaysia**
Program kad imbas untuk mempelajari perkataan Melayu yang paling kerap digunakan beserta terjemahan Denmark. Ia ialah penyelesaian hari ke-31 kursus Udemy *100 Days of Code: The Complete Python Pro Bootcamp*.
![Skrin tahap: pilih 100 perkataan, 1000 perkataan atau semua perkataan](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/raw/branch/main/docs/images/screenshot-level.png)
![Bahagian depan kad: perkataan Melayu](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/raw/branch/main/docs/images/screenshot-front.png)
![Bahagian belakang kad selepas tiga saat: terjemahan Denmark](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/raw/branch/main/docs/images/screenshot-back.png)
| Halaman | Baca apabila anda mahu |
| --- | --- |
| [Pemasangan](Install-ms) | Mencipta `.venv`, memasang program dan menjalankan ujian |
| [Penggunaan](Usage-ms) | Berlatih dengan kad, memahami fail kemajuan dan menggunakan pilihan |
| [Seni bina](Architecture-ms) | Melihat lapisan dan mencari kod bagi setiap langkah tugasan |
## Empat langkah tugasan
| Langkah | Apa yang program lakukan | Pencapaian |
| --- | --- | --- |
| 1. Antara muka pengguna | Tetingkap dengan satu kad dan dua butang | MIL-002 |
| 2. Kad imbas baharu | Satu perkataan rawak daripada senarai perkataan setiap kali butang ditekan | MIL-003 |
| 3. Terbalikkan kad | Selepas 3 saat kad menunjukkan terjemahan Denmark | MIL-004 |
| 4. Simpan kemajuan anda | Perkataan yang diketahui dibuang dan selebihnya disimpan dalam `words_to_learn.csv` | MIL-005 |
| Tambahan | Perkataan Melayu disebut (pilihan) | MIL-006 |
| Tambahan | Anda memilih tahap dahulu: 100 perkataan pertama, 1000 perkataan pertama atau semua perkataan | MIL-008 |
## Untuk peserta kursus
Nama fungsi tugasan dikekalkan: `next_card`, `flip_card`, `is_known`, serta atribut `flip_timer` dan `current_card`. Data dibaca dengan modul `csv` pustaka standard dan bukan `pandas`, jadi program teras tidak mempunyai kebergantungan semasa larian.
Repositori: <https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card>
+32
View File
@@ -0,0 +1,32 @@
# Flash Card
🌐 **English** · [Dansk](Home-da) · [Bahasa Malaysia](Home-ms)
A flash card program for learning the most frequent Malay words with their Danish translations. It is the solution of day 31 of Udemy's *100 Days of Code: The Complete Python Pro Bootcamp*.
![The level screen: choose 100 words, 1000 words or all words](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/raw/branch/main/docs/images/screenshot-level.png)
![The front of a card: the Malay word](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/raw/branch/main/docs/images/screenshot-front.png)
![The back of the card after three seconds: the Danish translation](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/raw/branch/main/docs/images/screenshot-back.png)
| Page | Read it when you want to |
| --- | --- |
| [Install](Install) | Create the `.venv`, install the program and run the tests |
| [Usage](Usage) | Study the cards, understand the progress file, use the options |
| [Architecture](Architecture) | See the layers and find the code of each assignment step |
## The four assignment steps
| Step | What the program does | Milestone |
| --- | --- | --- |
| 1. User interface | A window with a card and two buttons | MIL-002 |
| 2. New flash cards | A random word from the word list on every button press | MIL-003 |
| 3. Flip the cards | After 3 seconds the card shows the Danish translation | MIL-004 |
| 4. Save your progress | Known words are removed and the rest is saved in `words_to_learn.csv` | MIL-005 |
| Extra | The Malay word is spoken (optional) | MIL-006 |
| Extra | You choose a level first: the first 100 words, the first 1000 words or all words | MIL-008 |
## For course participants
The function names of the assignment are kept: `next_card`, `flip_card`, `is_known`, and the attributes `flip_timer` and `current_card`. The data is read with the standard library `csv` module instead of `pandas`, so the core program has no runtime dependency.
Repository: <https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card>
+103
View File
@@ -0,0 +1,103 @@
# Installation
🌐 [English](Install) · **Dansk** · [Bahasa Malaysia](Install-ms)
## Krav
- Python 3.13 eller nyere med Tkinter (på Debian eller Ubuntu: `sudo apt install python3-tk`).
- `git`.
- Valgfrit: en internetforbindelse og tilvalget `speech`, hvis du vil høre det malajiske ord.
## Hent koden
```bash
git clone https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card.git
cd 031-flash-card
```
## Opret og brug et lokalt virtuelt miljø
Windows (PowerShell):
```powershell
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
```
Linux og macOS:
```bash
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
```
- `.[dev]` tilføjer `pytest`, `ruff`, `mypy` og `import-linter`. Brug `.`, hvis du kun vil køre programmet.
- Hvis PowerShell nægter at køre `Activate.ps1`, så kør `Set-ExecutionPolicy -Scope CurrentUser RemoteSigned` én gang.
- Forlad miljøet med `deactivate`; slet mappen `.venv` for at starte forfra.
## Udtalt malajisk ord (valgfrit)
```bash
python -m pip install -e ".[speech]"
```
Det installerer `gTTS` og `playsound==1.2.2`. Uden tilvalget virker programmet uden lyd.
## Kør og test
```bash
python -m flash_card
python -m pytest
```
Vinduestesten i `tests/e2e/` springes over, når der ikke er en skærm.
## Udgivelse og programfil (Windows)
Udgivelsessiderne for [v0.2.0](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/releases/tag/v0.2.0) og [v0.1.0](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/releases/tag/v0.1.0) har udgivelsesnoterne. Programfilen er endnu ikke vedhæftet, fordi serverens grænse for upload afviser en fil af denne størrelse (HTTP 413); byg den som beskrevet nedenfor. Filen er ikke signeret, så Windows kan vise en SmartScreen-advarsel.
## Byg en programfil (Windows)
```powershell
python -m pip install -e ".[build,speech]"
python tools/build_executable.py
```
Scriptet bruger PyInstaller og skriver `dist/flash-card.exe`: én fil uden konsolvindue, med billeder, ordliste og udtalen indeni. Dobbeltklik for at starte; Python er ikke nødvendigt for at køre den.
- Din fremgang gemmes i en `data/`-mappe ved siden af programfilen (`data/words_to_learn.csv`).
- En `data/ms-da.csv` ved siden af programfilen erstatter ordlisten indeni.
- `python tools/build_executable.py --no-speech` udelader talepakkerne; `--clean` bygger forfra.
- Programfilen er ikke i repositoryet. Byg den på det system, hvor den skal køre; Windows kan vise en SmartScreen-advarsel, fordi filen ikke er signeret.
## Kontroller uden skrivebord (Docker)
Testene, linterne, skærmbillederne og en røgtest af en Linux-binær kører i en Debian-container på en virtuel skærm, så der ikke åbnes noget vindue på dit eget skrivebord.
```bash
docker build -f docker/debian.Dockerfile -t flash-card-debian .
# linters og hele testsuiten, også testene af det rigtige vindue
docker run --rm -v "$PWD:/repo:ro" flash-card-debian bash /repo/tools/docker/in-container.sh run-checks.sh
# skærmbilleder til ./build/container-out
docker run --rm -v "$PWD:/repo:ro" -v "$PWD/build/container-out:/out" flash-card-debian bash /repo/tools/docker/in-container.sh screenshots.sh /out
# byg Linux-binæren og tryk på "kender" 5 gange (binær og kildekode)
docker run --rm -v "$PWD:/repo:ro" flash-card-debian bash /repo/tools/docker/in-container.sh smoke-binary.sh 5
```
I Windows PowerShell skriver du `${PWD}` i stedet for `$PWD`. Repositoryet monteres skrivebeskyttet og kopieres inde i containeren.
- Skrivebordet er Xvfb med GNOMEs vindueshåndtering (mutter). GNOME Shell prøves først og starter ikke i en container (den kræver en login-manager), så scripts falder tilbage til mutter og skriver hvilken der kørte.
- Windows-programfilen kontrolleres i **Windows Sandbox** (Windows 11 Pro, funktionen aktiveret): `powershell -File tools\sandbox\run.ps1 -Runs 5` efter `python tools/build_executable.py`. Sandboxen viser sit eget vindue, mens den kører; klikket sker inde i sandboxen.
- Ikke dækket: macOS (kan ikke køres i Docker på Windows eller Linux, og Apples licens tillader det kun på Apple-hardware), og selve Windows i Debian-containeren.
## Dokumentation af kildekoden
```bash
doxygen Doxyfile
```
HTML-filerne skrives til `docs/doxygen/html/index.html`.
+103
View File
@@ -0,0 +1,103 @@
# Pemasangan
🌐 [English](Install) · [Dansk](Install-da) · **Bahasa Malaysia**
## Keperluan
- Python 3.13 atau lebih baharu dengan Tkinter (pada Debian atau Ubuntu: `sudo apt install python3-tk`).
- `git`.
- Pilihan: sambungan internet dan tambahan `speech` jika anda mahu mendengar perkataan Melayu.
## Dapatkan kod
```bash
git clone https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card.git
cd 031-flash-card
```
## Cipta dan gunakan persekitaran maya setempat
Windows (PowerShell):
```powershell
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
```
Linux dan macOS:
```bash
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
```
- `.[dev]` menambah `pytest`, `ruff`, `mypy` dan `import-linter`. Gunakan `.` jika anda hanya mahu menjalankan program.
- Jika PowerShell enggan menjalankan `Activate.ps1`, jalankan `Set-ExecutionPolicy -Scope CurrentUser RemoteSigned` sekali.
- Keluar daripada persekitaran dengan `deactivate`; padam folder `.venv` untuk bermula semula.
## Perkataan Melayu bersuara (pilihan)
```bash
python -m pip install -e ".[speech]"
```
Ini memasang `gTTS` dan `playsound==1.2.2`. Tanpa tambahan ini program berfungsi tanpa bunyi.
## Jalankan dan uji
```bash
python -m flash_card
python -m pytest
```
Ujian tetingkap dalam `tests/e2e/` dilangkau apabila tiada paparan.
## Keluaran dan fail boleh laku (Windows)
Halaman keluaran [v0.2.0](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/releases/tag/v0.2.0) dan [v0.1.0](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/releases/tag/v0.1.0) mempunyai nota keluaran. Fail boleh laku belum dilampirkan di sana kerana had muat naik pelayan menolak fail sebesar ini (HTTP 413); bina seperti yang diterangkan di bawah. Fail tidak ditandatangani, jadi Windows mungkin menunjukkan amaran SmartScreen.
## Bina fail boleh laku (Windows)
```powershell
python -m pip install -e ".[build,speech]"
python tools/build_executable.py
```
Skrip menggunakan PyInstaller dan menulis `dist/flash-card.exe`: satu fail tanpa tetingkap konsol, dengan imej, senarai perkataan dan suara di dalamnya. Klik dua kali untuk memulakan; Python tidak diperlukan untuk menjalankannya.
- Kemajuan anda disimpan dalam folder `data/` di sebelah fail boleh laku (`data/words_to_learn.csv`).
- `data/ms-da.csv` di sebelah fail boleh laku menggantikan senarai perkataan di dalamnya.
- `python tools/build_executable.py --no-speech` meninggalkan pakej suara; `--clean` membina semula dari awal.
- Fail boleh laku tidak disimpan dalam repositori. Bina di sistem tempat ia akan dijalankan; Windows mungkin menunjukkan amaran SmartScreen kerana fail tidak ditandatangani.
## Semakan tanpa desktop (Docker)
Ujian, linter, tangkapan skrin dan ujian asap bagi binari Linux dijalankan dalam kontena Debian pada skrin maya, jadi tiada tetingkap dibuka pada desktop anda sendiri.
```bash
docker build -f docker/debian.Dockerfile -t flash-card-debian .
# linter dan seluruh suite ujian, termasuk ujian tetingkap sebenar
docker run --rm -v "$PWD:/repo:ro" flash-card-debian bash /repo/tools/docker/in-container.sh run-checks.sh
# tangkapan skrin ke ./build/container-out
docker run --rm -v "$PWD:/repo:ro" -v "$PWD/build/container-out:/out" flash-card-debian bash /repo/tools/docker/in-container.sh screenshots.sh /out
# bina binari Linux dan tekan butang "tahu" 5 kali (binari dan kod sumber)
docker run --rm -v "$PWD:/repo:ro" flash-card-debian bash /repo/tools/docker/in-container.sh smoke-binary.sh 5
```
Dalam Windows PowerShell tulis `${PWD}` untuk `$PWD`. Repositori dipasang baca sahaja dan disalin di dalam kontena.
- Desktop ialah Xvfb dengan pengurus tetingkap GNOME (mutter). GNOME Shell dicuba dahulu dan tidak bermula dalam kontena (ia memerlukan pengurus log masuk), jadi skrip beralih kepada mutter dan mencetak yang mana dijalankan.
- Fail boleh laku Windows disemak dalam **Windows Sandbox** (Windows 11 Pro, ciri diaktifkan): `powershell -File tools\sandbox\run.ps1 -Runs 5` selepas `python tools/build_executable.py`. Sandbox menunjukkan tetingkapnya sendiri semasa berjalan; klik dibuat di dalam sandbox.
- Tidak dilindungi: macOS (tidak boleh dijalankan dalam Docker pada Windows atau Linux dan lesen Apple hanya membenarkannya pada perkakasan Apple), dan Windows sebenar dalam kontena Debian.
## Dokumentasi kod sumber
```bash
doxygen Doxyfile
```
HTML ditulis ke `docs/doxygen/html/index.html`.
+103
View File
@@ -0,0 +1,103 @@
# Install
🌐 **English** · [Dansk](Install-da) · [Bahasa Malaysia](Install-ms)
## Requirements
- Python 3.13 or later with Tkinter (on Debian or Ubuntu: `sudo apt install python3-tk`).
- `git`.
- Optional: an internet connection and the `speech` extra to hear the Malay word.
## Get the code
```bash
git clone https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card.git
cd 031-flash-card
```
## Create and use a local virtual environment
Windows (PowerShell):
```powershell
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
```
Linux and macOS:
```bash
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
```
- `.[dev]` adds `pytest`, `ruff`, `mypy` and `import-linter`. Use `.` if you only want to run the program.
- If PowerShell refuses to run `Activate.ps1`, run `Set-ExecutionPolicy -Scope CurrentUser RemoteSigned` once.
- Leave the environment with `deactivate`; delete the `.venv` folder to start over.
## Spoken Malay word (optional)
```bash
python -m pip install -e ".[speech]"
```
This installs `gTTS` and `playsound==1.2.2`. Without it the program works silently.
## Run and test
```bash
python -m flash_card
python -m pytest
```
The window test in `tests/e2e/` is skipped when no display is available.
## Release and executable (Windows)
The release pages of [v0.2.0](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/releases/tag/v0.2.0) and [v0.1.0](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/releases/tag/v0.1.0) have the release notes. The executable is not attached there yet, because the server's upload limit rejects a file of this size (HTTP 413); build it as described below. The file is not signed, so Windows may show a SmartScreen warning.
## Build an executable (Windows)
```powershell
python -m pip install -e ".[build,speech]"
python tools/build_executable.py
```
The script uses PyInstaller and writes `dist/flash-card.exe`: one file, no console window, with the images, the word list and the spoken word inside. Double-click it to start; Python is not needed to run it.
- Your progress is kept in a `data/` folder next to the executable (`data/words_to_learn.csv`).
- A `data/ms-da.csv` next to the executable replaces the word list inside it.
- `python tools/build_executable.py --no-speech` leaves the speech packages out; `--clean` rebuilds from scratch.
- The executable is not committed to the repository. Build it on the system you want to run it on; Windows may show a SmartScreen warning because the file is not signed.
## Checks without a desktop (Docker)
The tests, the linters, the screenshots and a smoke test of a Linux binary run in a Debian container on a virtual screen, so no window opens on your own desktop.
```bash
docker build -f docker/debian.Dockerfile -t flash-card-debian .
# linters and the whole test suite, including the real window tests
docker run --rm -v "$PWD:/repo:ro" flash-card-debian bash /repo/tools/docker/in-container.sh run-checks.sh
# screenshots into ./build/container-out
docker run --rm -v "$PWD:/repo:ro" -v "$PWD/build/container-out:/out" flash-card-debian bash /repo/tools/docker/in-container.sh screenshots.sh /out
# build the Linux binary and press the known button 5 times (binary and source)
docker run --rm -v "$PWD:/repo:ro" flash-card-debian bash /repo/tools/docker/in-container.sh smoke-binary.sh 5
```
On Windows PowerShell write `${PWD}` for `$PWD`. The repository is mounted read-only and copied inside the container.
- The desktop is Xvfb with GNOME's window manager (mutter). GNOME Shell is tried first and does not start in a container (it needs a login manager), so the scripts fall back to mutter and print which one ran.
- The Windows executable is checked in **Windows Sandbox** (Windows 11 Pro, feature enabled): `powershell -File tools\sandbox\run.ps1 -Runs 5` after `python tools/build_executable.py`. The sandbox shows its own window while it runs; the click is made inside the sandbox.
- Not covered: macOS (it cannot be run in Docker on Windows or Linux and Apple's licence allows it only on Apple hardware), and Windows itself in the Debian container.
## Documentation of the source code
```bash
doxygen Doxyfile
```
The HTML is written to `docs/doxygen/html/index.html`.
+67
View File
@@ -0,0 +1,67 @@
# Brug
🌐 [English](Usage) · **Dansk** · [Bahasa Malaysia](Usage-ms)
## Øv kortene
1. Start programmet med `python -m flash_card`.
2. Vælg et niveau: **100 words**, **1000 words** eller **All words**. Ordlisten er sorteret fra det hyppigste til det sjældneste ord, så niveau 100 er de 100 hyppigste ord.
3. Et kort viser et malajisk ord. Prøv at huske den danske oversættelse.
4. Efter tre sekunder vender kortet og viser oversættelsen.
5. Tryk på det grønne flueben, hvis du kendte ordet, eller på det røde kryds, hvis du ikke gjorde.
6. Et nyt tilfældigt ord fra niveauet vises. Gentag.
Et ord, du har markeret som kendt, fjernes og kommer ikke igen. Når der ikke er flere ord på niveauet, står der "Nothing left to learn" på kortet; start programmet igen og vælg et højere niveau.
## Menulinjen
![Vinduet med menulinjen](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/raw/branch/main/docs/images/screenshot-menu.png)
| Menu | Kommando | Hvad den gør |
| --- | --- | --- |
| File | Open... | Åbner en anden ordliste fra en CSV-fil (overskrift med to sprogkoder, fx `en;da`). Fremgang gemmes adskilt for hver liste |
| File | Change level... | Viser niveauvalget igen uden genstart; kendte ord forbliver kendte |
| File | Reset word list... | Fjerner efter en bekræftelse fremgangen for den åbne liste, så alle dens ord skal læres igen; listefilen ændres ikke |
| File | Exit | Lukker programmet |
| About | Contact | Forfatteren, Jens Tirsvad Nielsen, softwareudvikler; åbner LinkedIn-siden i din browser |
Fremgangen for den medfølgende `ms-da.csv` er `data/words_to_learn.csv`; en anden liste får `data/words_to_learn_<navn>.csv`. Den åbnede liste huskes ikke efter en genstart.
## Din fremgang
- Første gang du trykker på det grønne flueben, skriver programmet `data/words_to_learn.csv` med de ord, du endnu ikke kan.
- Næste start bruger den fil. Findes den ikke, bruger programmet hele ordlisten `data/ms-da.csv`.
- For at starte forfra skal du slette `data/words_to_learn.csv`.
- Det røde kryds ændrer aldrig filen.
- Kendte ord forbliver kendte på alle niveauer. Niveauet begrænser kun, hvilke af de ord, du endnu ikke kender, der kommer frem, og filen beholder altid alle ord, du ikke kender, også dem uden for niveauet.
- Denne liste har 1000 ord, så "1000 words" og "All words" giver de samme kort.
## Filformat
Begge filer er UTF-8-tekst med ét kort pr. linje og cellerne adskilt af semikolon. Første linje har de to sprogkoder.
```text
ms;da
aku;mig
yang;hvilke
```
## Indstillinger
| Indstilling | Betydning |
| --- | --- |
| `--data-dir <mappe>` | Mappen med `ms-da.csv` og `words_to_learn.csv` (standard: `data/` i repositoryet) |
| `--level {100,1000,all}` | Start på det niveau og spring niveauskærmen over |
| `--no-speech` | Udtal ikke det malajiske ord, selv om tilvalget til tale er installeret |
## Brug et andet sprogpar
Læg en fil med samme format i datamappen og kald den `ms-da.csv`, eller ret `VOCABULARY_FILE_NAME` og `LANGUAGE_NAMES` i `src/flash_card/constants.py`. Kodene i overskriften vises som sprognavne fra `LANGUAGE_NAMES`; ukendte koder vises med store bogstaver.
## Fejlfinding
| Problem | Hvad du skal gøre |
| --- | --- |
| `No module named tkinter` | Installer Tkinter (`python3-tk` på Debian og Ubuntu) |
| Ingen lyd | Installer tilvalget `speech` og tjek netværket; programmet logger en advarsel, når udtalen mislykkes |
| Programmet stopper med en meddelelse om filen | CSV-filen er forkert opbygget; meddelelsen nævner filen og linjen. Filen bliver ikke overskrevet |
+67
View File
@@ -0,0 +1,67 @@
# Penggunaan
🌐 [English](Usage) · [Dansk](Usage-da) · **Bahasa Malaysia**
## Berlatih dengan kad
1. Mulakan program dengan `python -m flash_card`.
2. Pilih tahap: **100 words**, **1000 words** atau **All words**. Senarai perkataan disusun daripada perkataan paling kerap kepada paling jarang, jadi tahap 100 ialah 100 perkataan paling kerap.
3. Kad menunjukkan satu perkataan Melayu. Cuba ingat terjemahan Denmarknya.
4. Selepas tiga saat kad terbalik dan menunjukkan terjemahan.
5. Tekan tanda semak hijau jika anda tahu perkataan itu, atau pangkah merah jika tidak.
6. Satu perkataan rawak baharu daripada tahap itu muncul. Ulang.
Perkataan yang anda tandakan sebagai diketahui dibuang dan tidak muncul lagi. Apabila tiada perkataan lagi pada tahap itu, kad menunjukkan "Nothing left to learn"; mulakan program semula dan pilih tahap yang lebih tinggi.
## Bar menu
![Tetingkap dengan bar menu](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/raw/branch/main/docs/images/screenshot-menu.png)
| Menu | Perintah | Apa yang dilakukan |
| --- | --- | --- |
| File | Open... | Membuka senarai perkataan lain daripada fail CSV (baris pertama dengan dua kod bahasa, contohnya `en;da`). Kemajuan disimpan berasingan bagi setiap senarai |
| File | Change level... | Menunjukkan pilihan tahap semula tanpa memulakan semula; perkataan yang diketahui kekal diketahui |
| File | Reset word list... | Selepas pengesahan membuang kemajuan senarai yang dibuka, supaya semua perkataannya perlu dipelajari semula; fail senarai tidak diubah |
| File | Exit | Menutup program |
| About | Contact | Pengarang, Jens Tirsvad Nielsen, jurutera perisian; membuka halaman LinkedIn dalam pelayar anda |
Kemajuan bagi `ms-da.csv` yang disertakan ialah `data/words_to_learn.csv`; senarai lain mendapat `data/words_to_learn_<nama>.csv`. Senarai yang dibuka tidak diingati selepas dimulakan semula.
## Kemajuan anda
- Kali pertama anda menekan tanda semak hijau, program menulis `data/words_to_learn.csv` dengan perkataan yang anda belum tahu.
- Permulaan seterusnya menggunakan fail itu. Jika ia tiada, program menggunakan senarai penuh `data/ms-da.csv`.
- Untuk bermula semula, padam `data/words_to_learn.csv`.
- Pangkah merah tidak pernah mengubah fail.
- Perkataan yang diketahui kekal diketahui pada semua tahap. Tahap hanya mengehadkan perkataan yang belum anda ketahui yang muncul, dan fail sentiasa menyimpan semua perkataan yang anda belum tahu, termasuk yang di luar tahap.
- Senarai ini mempunyai 1000 perkataan, jadi "1000 words" dan "All words" memberikan kad yang sama.
## Format fail
Kedua-dua fail ialah teks UTF-8 dengan satu kad setiap baris dan sel dipisahkan oleh koma bertitik. Baris pertama mengandungi dua kod bahasa.
```text
ms;da
aku;mig
yang;hvilke
```
## Pilihan
| Pilihan | Maksud |
| --- | --- |
| `--data-dir <folder>` | Folder yang mengandungi `ms-da.csv` dan `words_to_learn.csv` (lalai: `data/` dalam repositori) |
| `--level {100,1000,all}` | Mulakan pada tahap itu dan langkau skrin tahap |
| `--no-speech` | Jangan sebut perkataan Melayu, walaupun tambahan suara dipasang |
## Gunakan pasangan bahasa lain
Letakkan fail dengan format yang sama dalam folder data dan namakannya `ms-da.csv`, atau ubah `VOCABULARY_FILE_NAME` dan `LANGUAGE_NAMES` dalam `src/flash_card/constants.py`. Kod pada baris pertama dipaparkan sebagai nama bahasa daripada `LANGUAGE_NAMES`; kod yang tidak dikenali dipaparkan dengan huruf besar.
## Penyelesaian masalah
| Masalah | Apa yang perlu dilakukan |
| --- | --- |
| `No module named tkinter` | Pasang Tkinter (`python3-tk` pada Debian dan Ubuntu) |
| Tiada bunyi | Pasang tambahan `speech` dan periksa rangkaian; program mencatat amaran apabila penyebutan gagal |
| Program berhenti dengan mesej tentang fail | Fail CSV tidak betul; mesej menyebut fail dan barisnya. Fail tidak ditulis ganti |
+67
View File
@@ -0,0 +1,67 @@
# Usage
🌐 **English** · [Dansk](Usage-da) · [Bahasa Malaysia](Usage-ms)
## Study the cards
1. Start the program with `python -m flash_card`.
2. Choose a level: **100 words**, **1000 words** or **All words**. The word list is ordered from the most to the least frequent word, so level 100 is the 100 most frequent words.
3. A card shows a Malay word. Try to remember its Danish translation.
4. After three seconds the card turns over and shows the translation.
5. Press the green tick when you knew the word, or the red cross when you did not.
6. A new random word of the level appears. Repeat.
A word you marked as known is removed and does not come up again. When no word of the level is left, the card says "Nothing left to learn"; restart the program and choose a higher level.
## The menu bar
![The window with the menu bar](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/031-flash-card/raw/branch/main/docs/images/screenshot-menu.png)
| Menu | Command | What it does |
| --- | --- | --- |
| File | Open... | Opens another word list from a CSV file (header with two language codes, for example `en;da`). Progress is kept apart for each list |
| File | Change level... | Shows the level choice again without a restart; known words stay known |
| File | Reset word list... | After a confirmation removes the progress of the open list, so all its words are to learn again; the list file is not changed |
| File | Exit | Closes the program |
| About | Contact | The author, Jens Tirsvad Nielsen, Software engineer; opens the LinkedIn page in your browser |
The progress of the delivered `ms-da.csv` is `data/words_to_learn.csv`; another list gets `data/words_to_learn_<name>.csv`. The opened list is not remembered after a restart.
## Your progress
- The first time you press the green tick, the program writes `data/words_to_learn.csv` with the words you do not know yet.
- The next start uses that file. If it does not exist, the program uses the full word list `data/ms-da.csv`.
- To start again, delete `data/words_to_learn.csv`.
- The red cross never changes the file.
- Known words stay known at every level. The level only limits which of the words you do not know yet come up, and the file always keeps every word you do not know, also those outside the level.
- This list has 1000 words, so "1000 words" and "All words" give the same cards.
## File format
Both files are UTF-8 text with one card per line and the cells separated by a semicolon. The first line holds the two language codes.
```text
ms;da
aku;mig
yang;hvilke
```
## Options
| Option | Meaning |
| --- | --- |
| `--data-dir <folder>` | Folder that holds `ms-da.csv` and `words_to_learn.csv` (default: `data/` of the repository) |
| `--level {100,1000,all}` | Start at that level and skip the level screen |
| `--no-speech` | Do not speak the Malay word, even when the speech extra is installed |
## Use another language pair
Put a file with the same format in the data folder and name it `ms-da.csv`, or change `VOCABULARY_FILE_NAME` and `LANGUAGE_NAMES` in `src/flash_card/constants.py`. The header codes are shown as language names from `LANGUAGE_NAMES`; unknown codes are shown in upper case.
## Troubleshooting
| Problem | What to do |
| --- | --- |
| `No module named tkinter` | Install Tkinter (`python3-tk` on Debian and Ubuntu) |
| No sound | Install the `speech` extra and check the network; the program logs a warning when speaking fails |
| The program stops with a message about the file | The CSV file is malformed; the message names the file and the line. The file is not overwritten |
+12
View File
@@ -0,0 +1,12 @@
**Flash Card**
- [Home](Home)
- [Install](Install)
- [Usage](Usage)
- [Architecture](Architecture)
**Languages**
- English: [Home](Home) · [Install](Install) · [Usage](Usage) · [Architecture](Architecture)
- Dansk: [Hjem](Home-da) · [Installation](Install-da) · [Brug](Usage-da) · [Arkitektur](Architecture-da)
- Bahasa Malaysia: [Utama](Home-ms) · [Pemasangan](Install-ms) · [Penggunaan](Usage-ms) · [Seni bina](Architecture-ms)
+9 -2
View File
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "flash-card"
version = "0.1.0"
version = "0.2.0"
description = "Flash card program for learning Malay words with Danish translations (Udemy 100 Days of Code, day 31)"
readme = "README.md"
requires-python = ">=3.13"
@@ -24,6 +24,10 @@ dependencies = []
[project.optional-dependencies]
# Spoken Malay word (text to speech). Optional; the program works without it.
speech = ["gTTS>=2.5", "playsound==1.2.2"]
# Only for tools/capture_screenshots.py; not needed to run the program.
tools = ["pillow>=10"]
# Only for tools/build_executable.py; not needed to run the program.
build = ["pyinstaller>=6"]
dev = ["pytest>=8", "ruff>=0.6", "mypy>=1.11", "import-linter>=2.0"]
[project.scripts]
@@ -33,7 +37,7 @@ flash-card = "flash_card.presentation.app:run"
where = ["src"]
[tool.setuptools.package-data]
flash_card = ["presentation/assets/*.png"]
flash_card = ["presentation/assets/*.png", "presentation/assets/*.ico"]
[tool.pytest.ini_options]
testpaths = ["tests"]
@@ -45,6 +49,9 @@ line-length = 88
target-version = "py313"
src = ["src", "tests"]
[tool.ruff.format]
line-ending = "lf"
[tool.ruff.lint]
select = ["E", "F", "I", "UP", "B", "SIM", "N", "D"]
ignore = ["D203", "D213"]

Some files were not shown because too many files have changed in this diff Show More