Merge pull request 'MIL-001 Repository foundation' (#20) from mil-001-repository-foundation into main
Merge pull request MIL-001 Repository foundation (#20)
This commit was merged in pull request #20.
This commit is contained in:
@@ -0,0 +1,70 @@
|
|||||||
|
# Continuous integration for the NATO phonetic alphabet project.
|
||||||
|
#
|
||||||
|
# Purpose: run the pytest suite on Python 3.13 so a change is known to work
|
||||||
|
# before it is merged (BC-001 objective O3, success criterion 2).
|
||||||
|
# Triggers: a push to main or to a milestone branch, and every pull request
|
||||||
|
# that touches source, tests, project configuration or this file.
|
||||||
|
# Inputs: none.
|
||||||
|
# Secrets: none. The job reads the repository only.
|
||||||
|
# Changes: nothing outside the repository.
|
||||||
|
# Decision: MIL-001 task "Add the CI workflow".
|
||||||
|
# Host: Gitea Actions (act_runner); the same file runs on GitHub Actions.
|
||||||
|
# The runner must offer the label ubuntu-latest.
|
||||||
|
|
||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main, "mil-*"]
|
||||||
|
paths:
|
||||||
|
- "src/**"
|
||||||
|
- "tests/**"
|
||||||
|
- "pyproject.toml"
|
||||||
|
- ".gitea/workflows/ci.yml"
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- "src/**"
|
||||||
|
- "tests/**"
|
||||||
|
- "pyproject.toml"
|
||||||
|
- ".gitea/workflows/ci.yml"
|
||||||
|
|
||||||
|
# A newer run of the same branch makes the older one pointless.
|
||||||
|
concurrency:
|
||||||
|
group: ci-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
env:
|
||||||
|
PYTHON_VERSION: "3.13"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: Test on Python 3.13
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 10
|
||||||
|
steps:
|
||||||
|
- name: Check out the repository
|
||||||
|
uses: actions/checkout@v4.2.2
|
||||||
|
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v5.6.0
|
||||||
|
with:
|
||||||
|
python-version: ${{ env.PYTHON_VERSION }}
|
||||||
|
|
||||||
|
- name: Create the virtual environment and upgrade pip
|
||||||
|
run: |
|
||||||
|
python -m venv .venv
|
||||||
|
.venv/bin/python -m pip install --upgrade pip
|
||||||
|
|
||||||
|
- name: Install the project with its development tools
|
||||||
|
run: .venv/bin/python -m pip install -e ".[dev]"
|
||||||
|
|
||||||
|
- name: Check the code style
|
||||||
|
run: .venv/bin/python -m ruff check .
|
||||||
|
|
||||||
|
- name: Check the types
|
||||||
|
run: .venv/bin/python -m mypy
|
||||||
|
|
||||||
|
- name: Run the tests
|
||||||
|
run: .venv/bin/python -m pytest
|
||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
# Byte-compiled and cache files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
.pytest_cache/
|
||||||
|
.mypy_cache/
|
||||||
|
.ruff_cache/
|
||||||
|
.import_linter_cache/
|
||||||
|
|
||||||
|
# Virtual environments
|
||||||
|
.venv/
|
||||||
|
venv/
|
||||||
|
env/
|
||||||
|
|
||||||
|
# Packaging, build and Doxygen output
|
||||||
|
build/
|
||||||
|
dist/
|
||||||
|
*.egg-info/
|
||||||
|
.eggs/
|
||||||
|
|
||||||
|
# Coverage
|
||||||
|
.coverage
|
||||||
|
htmlcov/
|
||||||
|
|
||||||
|
# Secrets and local configuration (personal tokens, never committed)
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
!.env.example
|
||||||
|
|
||||||
|
# Editors and operating system
|
||||||
|
.idea/
|
||||||
|
.vscode/
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "framework"]
|
||||||
|
path = framework
|
||||||
|
url = ssh://git@git.tirsystem.com:10022/TirSystem/SQA-QC-Framework.git
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
# yamllint configuration for the repository's YAML files (tool: yamllint).
|
||||||
|
extends: default
|
||||||
|
rules:
|
||||||
|
line-length:
|
||||||
|
max: 100
|
||||||
|
truthy:
|
||||||
|
check-keys: false
|
||||||
|
document-start: disable
|
||||||
@@ -0,0 +1,374 @@
|
|||||||
|
# Doxyfile 1.15.0
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Project related configuration options
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
DOXYFILE_ENCODING = UTF-8
|
||||||
|
PROJECT_NAME = "NATO phonetic alphabet"
|
||||||
|
PROJECT_NUMBER =
|
||||||
|
PROJECT_BRIEF = "Spell a word with the NATO phonetic alphabet (100 Days of Code, day 30, exception handling)"
|
||||||
|
PROJECT_LOGO =
|
||||||
|
PROJECT_ICON =
|
||||||
|
OUTPUT_DIRECTORY = build
|
||||||
|
CREATE_SUBDIRS = NO
|
||||||
|
CREATE_SUBDIRS_LEVEL = 8
|
||||||
|
ALLOW_UNICODE_NAMES = NO
|
||||||
|
OUTPUT_LANGUAGE = English
|
||||||
|
BRIEF_MEMBER_DESC = YES
|
||||||
|
REPEAT_BRIEF = YES
|
||||||
|
ABBREVIATE_BRIEF = "The $name class" \
|
||||||
|
"The $name widget" \
|
||||||
|
"The $name file" \
|
||||||
|
is \
|
||||||
|
provides \
|
||||||
|
specifies \
|
||||||
|
contains \
|
||||||
|
represents \
|
||||||
|
a \
|
||||||
|
an \
|
||||||
|
the
|
||||||
|
ALWAYS_DETAILED_SEC = NO
|
||||||
|
INLINE_INHERITED_MEMB = NO
|
||||||
|
FULL_PATH_NAMES = YES
|
||||||
|
STRIP_FROM_PATH =
|
||||||
|
STRIP_FROM_INC_PATH =
|
||||||
|
SHORT_NAMES = YES
|
||||||
|
JAVADOC_AUTOBRIEF = NO
|
||||||
|
JAVADOC_BANNER = NO
|
||||||
|
QT_AUTOBRIEF = NO
|
||||||
|
MULTILINE_CPP_IS_BRIEF = NO
|
||||||
|
PYTHON_DOCSTRING = YES
|
||||||
|
INHERIT_DOCS = YES
|
||||||
|
SEPARATE_MEMBER_PAGES = NO
|
||||||
|
TAB_SIZE = 4
|
||||||
|
ALIASES =
|
||||||
|
OPTIMIZE_OUTPUT_FOR_C = NO
|
||||||
|
OPTIMIZE_OUTPUT_JAVA = YES
|
||||||
|
OPTIMIZE_FOR_FORTRAN = NO
|
||||||
|
OPTIMIZE_OUTPUT_VHDL = NO
|
||||||
|
OPTIMIZE_OUTPUT_SLICE = NO
|
||||||
|
EXTENSION_MAPPING =
|
||||||
|
MARKDOWN_SUPPORT = YES
|
||||||
|
MARKDOWN_STRICT = YES
|
||||||
|
TOC_INCLUDE_HEADINGS = 6
|
||||||
|
MARKDOWN_ID_STYLE = DOXYGEN
|
||||||
|
AUTOLINK_SUPPORT = YES
|
||||||
|
AUTOLINK_IGNORE_WORDS =
|
||||||
|
BUILTIN_STL_SUPPORT = NO
|
||||||
|
CPP_CLI_SUPPORT = NO
|
||||||
|
SIP_SUPPORT = NO
|
||||||
|
IDL_PROPERTY_SUPPORT = YES
|
||||||
|
DISTRIBUTE_GROUP_DOC = NO
|
||||||
|
GROUP_NESTED_COMPOUNDS = NO
|
||||||
|
SUBGROUPING = YES
|
||||||
|
INLINE_GROUPED_CLASSES = NO
|
||||||
|
INLINE_SIMPLE_STRUCTS = NO
|
||||||
|
TYPEDEF_HIDES_STRUCT = NO
|
||||||
|
LOOKUP_CACHE_SIZE = 0
|
||||||
|
NUM_PROC_THREADS = 1
|
||||||
|
TIMESTAMP = NO
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Build related configuration options
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
EXTRACT_ALL = NO
|
||||||
|
EXTRACT_PRIVATE = NO
|
||||||
|
EXTRACT_PRIV_VIRTUAL = NO
|
||||||
|
EXTRACT_PACKAGE = NO
|
||||||
|
EXTRACT_STATIC = NO
|
||||||
|
EXTRACT_LOCAL_CLASSES = YES
|
||||||
|
EXTRACT_LOCAL_METHODS = NO
|
||||||
|
EXTRACT_ANON_NSPACES = NO
|
||||||
|
RESOLVE_UNNAMED_PARAMS = YES
|
||||||
|
HIDE_UNDOC_MEMBERS = NO
|
||||||
|
HIDE_UNDOC_CLASSES = NO
|
||||||
|
HIDE_UNDOC_NAMESPACES = YES
|
||||||
|
HIDE_FRIEND_COMPOUNDS = NO
|
||||||
|
HIDE_IN_BODY_DOCS = NO
|
||||||
|
INTERNAL_DOCS = NO
|
||||||
|
CASE_SENSE_NAMES = SYSTEM
|
||||||
|
HIDE_SCOPE_NAMES = NO
|
||||||
|
HIDE_COMPOUND_REFERENCE= NO
|
||||||
|
SHOW_HEADERFILE = YES
|
||||||
|
SHOW_INCLUDE_FILES = YES
|
||||||
|
SHOW_GROUPED_MEMB_INC = NO
|
||||||
|
FORCE_LOCAL_INCLUDES = NO
|
||||||
|
INLINE_INFO = YES
|
||||||
|
SORT_MEMBER_DOCS = YES
|
||||||
|
SORT_BRIEF_DOCS = NO
|
||||||
|
SORT_MEMBERS_CTORS_1ST = NO
|
||||||
|
SORT_GROUP_NAMES = NO
|
||||||
|
SORT_BY_SCOPE_NAME = NO
|
||||||
|
STRICT_PROTO_MATCHING = NO
|
||||||
|
GENERATE_TODOLIST = YES
|
||||||
|
GENERATE_TESTLIST = YES
|
||||||
|
GENERATE_BUGLIST = YES
|
||||||
|
GENERATE_DEPRECATEDLIST= YES
|
||||||
|
ENABLED_SECTIONS =
|
||||||
|
MAX_INITIALIZER_LINES = 30
|
||||||
|
SHOW_USED_FILES = YES
|
||||||
|
SHOW_FILES = YES
|
||||||
|
SHOW_NAMESPACES = YES
|
||||||
|
FILE_VERSION_FILTER =
|
||||||
|
LAYOUT_FILE =
|
||||||
|
CITE_BIB_FILES =
|
||||||
|
EXTERNAL_TOOL_PATH =
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Configuration options related to warning and progress messages
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
QUIET = YES
|
||||||
|
WARNINGS = YES
|
||||||
|
WARN_IF_UNDOCUMENTED = YES
|
||||||
|
WARN_IF_DOC_ERROR = YES
|
||||||
|
WARN_IF_INCOMPLETE_DOC = YES
|
||||||
|
WARN_NO_PARAMDOC = NO
|
||||||
|
WARN_IF_UNDOC_ENUM_VAL = NO
|
||||||
|
WARN_LAYOUT_FILE = YES
|
||||||
|
WARN_AS_ERROR = FAIL_ON_WARNINGS
|
||||||
|
WARN_FORMAT = "$file:$line: $text"
|
||||||
|
WARN_LINE_FORMAT = "at line $line of file $file"
|
||||||
|
WARN_LOGFILE =
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Configuration options related to the input files
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
INPUT = src
|
||||||
|
INPUT_ENCODING = UTF-8
|
||||||
|
INPUT_FILE_ENCODING =
|
||||||
|
FILE_PATTERNS = *.py
|
||||||
|
RECURSIVE = YES
|
||||||
|
EXCLUDE =
|
||||||
|
EXCLUDE_SYMLINKS = NO
|
||||||
|
EXCLUDE_PATTERNS =
|
||||||
|
EXCLUDE_SYMBOLS =
|
||||||
|
EXAMPLE_PATH =
|
||||||
|
EXAMPLE_PATTERNS = *
|
||||||
|
EXAMPLE_RECURSIVE = NO
|
||||||
|
IMAGE_PATH =
|
||||||
|
INPUT_FILTER =
|
||||||
|
FILTER_PATTERNS =
|
||||||
|
FILTER_SOURCE_FILES = NO
|
||||||
|
FILTER_SOURCE_PATTERNS =
|
||||||
|
USE_MDFILE_AS_MAINPAGE =
|
||||||
|
IMPLICIT_DIR_DOCS = YES
|
||||||
|
FORTRAN_COMMENT_AFTER = 72
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Configuration options related to source browsing
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
SOURCE_BROWSER = NO
|
||||||
|
INLINE_SOURCES = NO
|
||||||
|
STRIP_CODE_COMMENTS = YES
|
||||||
|
REFERENCED_BY_RELATION = NO
|
||||||
|
REFERENCES_RELATION = NO
|
||||||
|
REFERENCES_LINK_SOURCE = YES
|
||||||
|
SOURCE_TOOLTIPS = YES
|
||||||
|
USE_HTAGS = NO
|
||||||
|
VERBATIM_HEADERS = YES
|
||||||
|
CLANG_ASSISTED_PARSING = NO
|
||||||
|
CLANG_ADD_INC_PATHS = YES
|
||||||
|
CLANG_OPTIONS =
|
||||||
|
CLANG_DATABASE_PATH =
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Configuration options related to the alphabetical class index
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
ALPHABETICAL_INDEX = YES
|
||||||
|
IGNORE_PREFIX =
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Configuration options related to the HTML output
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
GENERATE_HTML = YES
|
||||||
|
HTML_OUTPUT = html
|
||||||
|
HTML_FILE_EXTENSION = .html
|
||||||
|
HTML_HEADER =
|
||||||
|
HTML_FOOTER =
|
||||||
|
HTML_STYLESHEET =
|
||||||
|
HTML_EXTRA_STYLESHEET =
|
||||||
|
HTML_EXTRA_FILES =
|
||||||
|
HTML_COLORSTYLE = AUTO_LIGHT
|
||||||
|
HTML_COLORSTYLE_HUE = 220
|
||||||
|
HTML_COLORSTYLE_SAT = 100
|
||||||
|
HTML_COLORSTYLE_GAMMA = 80
|
||||||
|
HTML_DYNAMIC_MENUS = YES
|
||||||
|
HTML_DYNAMIC_SECTIONS = NO
|
||||||
|
HTML_CODE_FOLDING = YES
|
||||||
|
HTML_COPY_CLIPBOARD = YES
|
||||||
|
HTML_PROJECT_COOKIE =
|
||||||
|
HTML_INDEX_NUM_ENTRIES = 100
|
||||||
|
GENERATE_DOCSET = NO
|
||||||
|
DOCSET_FEEDNAME = "Doxygen generated docs"
|
||||||
|
DOCSET_FEEDURL =
|
||||||
|
DOCSET_BUNDLE_ID = org.doxygen.Project
|
||||||
|
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
|
||||||
|
DOCSET_PUBLISHER_NAME = Publisher
|
||||||
|
GENERATE_HTMLHELP = NO
|
||||||
|
CHM_FILE =
|
||||||
|
HHC_LOCATION =
|
||||||
|
GENERATE_CHI = NO
|
||||||
|
CHM_INDEX_ENCODING =
|
||||||
|
BINARY_TOC = NO
|
||||||
|
TOC_EXPAND = NO
|
||||||
|
SITEMAP_URL =
|
||||||
|
GENERATE_QHP = NO
|
||||||
|
QCH_FILE =
|
||||||
|
QHP_NAMESPACE = org.doxygen.Project
|
||||||
|
QHP_VIRTUAL_FOLDER = doc
|
||||||
|
QHP_CUST_FILTER_NAME =
|
||||||
|
QHP_CUST_FILTER_ATTRS =
|
||||||
|
QHP_SECT_FILTER_ATTRS =
|
||||||
|
QHG_LOCATION =
|
||||||
|
GENERATE_ECLIPSEHELP = NO
|
||||||
|
ECLIPSE_DOC_ID = org.doxygen.Project
|
||||||
|
DISABLE_INDEX = NO
|
||||||
|
GENERATE_TREEVIEW = YES
|
||||||
|
PAGE_OUTLINE_PANEL = YES
|
||||||
|
FULL_SIDEBAR = NO
|
||||||
|
ENUM_VALUES_PER_LINE = 4
|
||||||
|
SHOW_ENUM_VALUES = NO
|
||||||
|
TREEVIEW_WIDTH = 250
|
||||||
|
EXT_LINKS_IN_WINDOW = NO
|
||||||
|
OBFUSCATE_EMAILS = YES
|
||||||
|
HTML_FORMULA_FORMAT = png
|
||||||
|
FORMULA_FONTSIZE = 10
|
||||||
|
FORMULA_MACROFILE =
|
||||||
|
USE_MATHJAX = NO
|
||||||
|
MATHJAX_VERSION = MathJax_2
|
||||||
|
MATHJAX_FORMAT = HTML-CSS
|
||||||
|
MATHJAX_RELPATH =
|
||||||
|
MATHJAX_EXTENSIONS =
|
||||||
|
MATHJAX_CODEFILE =
|
||||||
|
SEARCHENGINE = YES
|
||||||
|
SERVER_BASED_SEARCH = NO
|
||||||
|
EXTERNAL_SEARCH = NO
|
||||||
|
SEARCHENGINE_URL =
|
||||||
|
SEARCHDATA_FILE = searchdata.xml
|
||||||
|
EXTERNAL_SEARCH_ID =
|
||||||
|
EXTRA_SEARCH_MAPPINGS =
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Configuration options related to the LaTeX output
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
GENERATE_LATEX = NO
|
||||||
|
LATEX_OUTPUT = latex
|
||||||
|
LATEX_CMD_NAME =
|
||||||
|
MAKEINDEX_CMD_NAME = makeindex
|
||||||
|
LATEX_MAKEINDEX_CMD = makeindex
|
||||||
|
COMPACT_LATEX = NO
|
||||||
|
PAPER_TYPE = a4
|
||||||
|
EXTRA_PACKAGES =
|
||||||
|
LATEX_HEADER =
|
||||||
|
LATEX_FOOTER =
|
||||||
|
LATEX_EXTRA_STYLESHEET =
|
||||||
|
LATEX_EXTRA_FILES =
|
||||||
|
PDF_HYPERLINKS = YES
|
||||||
|
USE_PDFLATEX = YES
|
||||||
|
LATEX_BATCHMODE = NO
|
||||||
|
LATEX_HIDE_INDICES = NO
|
||||||
|
LATEX_BIB_STYLE = plainnat
|
||||||
|
LATEX_EMOJI_DIRECTORY =
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Configuration options related to the RTF output
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
GENERATE_RTF = NO
|
||||||
|
RTF_OUTPUT = rtf
|
||||||
|
COMPACT_RTF = NO
|
||||||
|
RTF_HYPERLINKS = NO
|
||||||
|
RTF_STYLESHEET_FILE =
|
||||||
|
RTF_EXTENSIONS_FILE =
|
||||||
|
RTF_EXTRA_FILES =
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Configuration options related to the man page output
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
GENERATE_MAN = NO
|
||||||
|
MAN_OUTPUT = man
|
||||||
|
MAN_EXTENSION = .3
|
||||||
|
MAN_SUBDIR =
|
||||||
|
MAN_LINKS = NO
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Configuration options related to the XML output
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
GENERATE_XML = NO
|
||||||
|
XML_OUTPUT = xml
|
||||||
|
XML_PROGRAMLISTING = YES
|
||||||
|
XML_NS_MEMB_FILE_SCOPE = NO
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Configuration options related to the DOCBOOK output
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
GENERATE_DOCBOOK = NO
|
||||||
|
DOCBOOK_OUTPUT = docbook
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Configuration options for the AutoGen Definitions output
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
GENERATE_AUTOGEN_DEF = NO
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Configuration options related to Sqlite3 output
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
GENERATE_SQLITE3 = NO
|
||||||
|
SQLITE3_OUTPUT = sqlite3
|
||||||
|
SQLITE3_RECREATE_DB = YES
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Configuration options related to the Perl module output
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
GENERATE_PERLMOD = NO
|
||||||
|
PERLMOD_LATEX = NO
|
||||||
|
PERLMOD_PRETTY = YES
|
||||||
|
PERLMOD_MAKEVAR_PREFIX =
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Configuration options related to the preprocessor
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
ENABLE_PREPROCESSING = YES
|
||||||
|
MACRO_EXPANSION = NO
|
||||||
|
EXPAND_ONLY_PREDEF = NO
|
||||||
|
SEARCH_INCLUDES = YES
|
||||||
|
INCLUDE_PATH =
|
||||||
|
INCLUDE_FILE_PATTERNS =
|
||||||
|
PREDEFINED =
|
||||||
|
EXPAND_AS_DEFINED =
|
||||||
|
SKIP_FUNCTION_MACROS = YES
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Configuration options related to external references
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
TAGFILES =
|
||||||
|
GENERATE_TAGFILE =
|
||||||
|
ALLEXTERNALS = NO
|
||||||
|
EXTERNAL_GROUPS = YES
|
||||||
|
EXTERNAL_PAGES = YES
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Configuration options related to diagram generator tools
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
HIDE_UNDOC_RELATIONS = YES
|
||||||
|
HAVE_DOT = NO
|
||||||
|
DOT_NUM_THREADS = 0
|
||||||
|
DOT_COMMON_ATTR = "fontname=Helvetica,fontsize=10"
|
||||||
|
DOT_EDGE_ATTR = "labelfontname=Helvetica,labelfontsize=10"
|
||||||
|
DOT_NODE_ATTR = "shape=box,height=0.2,width=0.4"
|
||||||
|
DOT_FONTPATH =
|
||||||
|
CLASS_GRAPH = YES
|
||||||
|
COLLABORATION_GRAPH = YES
|
||||||
|
GROUP_GRAPHS = YES
|
||||||
|
UML_LOOK = NO
|
||||||
|
UML_LIMIT_NUM_FIELDS = 10
|
||||||
|
UML_MAX_EDGE_LABELS = 10
|
||||||
|
DOT_UML_DETAILS = NO
|
||||||
|
DOT_WRAP_THRESHOLD = 17
|
||||||
|
TEMPLATE_RELATIONS = NO
|
||||||
|
INCLUDE_GRAPH = YES
|
||||||
|
INCLUDED_BY_GRAPH = YES
|
||||||
|
CALL_GRAPH = NO
|
||||||
|
CALLER_GRAPH = NO
|
||||||
|
GRAPHICAL_HIERARCHY = YES
|
||||||
|
DIRECTORY_GRAPH = YES
|
||||||
|
DIR_GRAPH_MAX_DEPTH = 1
|
||||||
|
DOT_IMAGE_FORMAT = png
|
||||||
|
INTERACTIVE_SVG = NO
|
||||||
|
DOT_PATH =
|
||||||
|
DOTFILE_DIRS =
|
||||||
|
DIA_PATH =
|
||||||
|
DIAFILE_DIRS =
|
||||||
|
PLANTUML_JAR_PATH =
|
||||||
|
PLANTUML_CFG_FILE =
|
||||||
|
PLANTUML_INCLUDE_PATH =
|
||||||
|
PLANTUMLFILE_DIRS =
|
||||||
|
DOT_GRAPH_MAX_NODES = 50
|
||||||
|
MAX_DOT_GRAPH_DEPTH = 0
|
||||||
|
DOT_MULTI_TARGETS = NO
|
||||||
|
GENERATE_LEGEND = YES
|
||||||
|
DOT_CLEANUP = YES
|
||||||
|
MSCGEN_TOOL =
|
||||||
|
MSCFILE_DIRS =
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
# ADR-0001 Read the NATO data with the standard library csv module
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
| Key | Value |
|
||||||
|
| --- | --- |
|
||||||
|
| ID | ADR-0001 |
|
||||||
|
| CrossReference | [BC-001], [SA-001] |
|
||||||
|
|
||||||
|
## Version History
|
||||||
|
| Date | Status | Author | Reviewer | Change | Commit |
|
||||||
|
| --- | --- | --- | --- | --- | --- |
|
||||||
|
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version, reviewed in RC-006 | [f42e610] |
|
||||||
|
|
||||||
|
Allowed Status values: `Proposed`, `Accepted`, `Rejected`, `Deprecated`, `Superseded by ADR-NNNN`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
The lecture reads the NATO alphabet file into a Pandas DataFrame and builds the dictionary with `iterrows`. The file has 26 rows and two columns. S01 follows the lecture, but S03 wants a repository with no runtime dependencies, and [BC-001] objective O5 and constraint "no runtime dependencies unless needed" say the same.
|
||||||
|
|
||||||
|
Options evaluated:
|
||||||
|
|
||||||
|
1. Pandas, as in the lecture: matches the course, but adds a large runtime dependency for a 26-row table.
|
||||||
|
2. Polars: smaller than Pandas, still a runtime dependency that the task does not need.
|
||||||
|
3. The standard library `csv` module: no dependency, and the dictionary comprehension that the assignment teaches works unchanged on the rows of `csv.DictReader`.
|
||||||
|
|
||||||
|
## Decision
|
||||||
|
|
||||||
|
Read the NATO alphabet with the standard library `csv` module (`csv.DictReader`) and build the letter-to-code-word dictionary with a dictionary comprehension. The project declares no runtime dependencies.
|
||||||
|
|
||||||
|
## Consequences
|
||||||
|
|
||||||
|
**Positive:**
|
||||||
|
|
||||||
|
- No runtime dependency to install or keep secure; S03 sees an empty dependency list.
|
||||||
|
- Faster start and a smaller environment for S02.
|
||||||
|
- The comprehension taught in the lecture is still used.
|
||||||
|
|
||||||
|
**Negative:**
|
||||||
|
|
||||||
|
- The code differs from the lecture's Pandas code, so S02 comparing line by line sees a difference.
|
||||||
|
- A later day that needs Pandas has to add it explicitly.
|
||||||
|
|
||||||
|
## Affected Artifacts
|
||||||
|
|
||||||
|
- [BC-001] — meets objective O5 and the constraint on runtime dependencies.
|
||||||
|
- [SA-001] — resolves the conflict between S01 and S03 listed there.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[BC-001]: ../business-case.md
|
||||||
|
[SA-001]: ../stakeholder-analysis.md
|
||||||
|
[f42e610]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/030-nato-phonetic-alphabet/commit/f42e6109ac82937291e5c8207c0631f710b9da85
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
# ADR-0002 Skip the optional analysis artifacts
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
| Key | Value |
|
||||||
|
| --- | --- |
|
||||||
|
| ID | ADR-0002 |
|
||||||
|
| 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, reviewed in RC-007 | [f42e610] |
|
||||||
|
|
||||||
|
Allowed Status values: `Proposed`, `Accepted`, `Rejected`, `Deprecated`, `Superseded by ADR-NNNN`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
The journey of the framework offers analysis documents beyond the baseline: KPI definitions, a Business Model Canvas, a BPMN process model and a riskiest-assumption test. The project is a single-evening course exercise with six measurable success criteria already in [BC-001], no commercial model, no business process and no costly belief to test.
|
||||||
|
|
||||||
|
Options evaluated:
|
||||||
|
|
||||||
|
1. Write all four documents: complete, but each needs a review and adds no decision that the Business Case does not already hold.
|
||||||
|
2. Write only the KPI definitions: the success criteria would be restated in another file.
|
||||||
|
3. Skip all four and record the reason here.
|
||||||
|
|
||||||
|
## Decision
|
||||||
|
|
||||||
|
Skip the KPI definitions, the Business Model Canvas, the BPMN process model and the riskiest-assumption test. The Business Case's Success Criteria table carries the measures, and the baseline documents (Business Case, Stakeholder Analysis, Project Plan, milestones) are not skipped.
|
||||||
|
|
||||||
|
## Consequences
|
||||||
|
|
||||||
|
**Positive:**
|
||||||
|
|
||||||
|
- Less documentation to keep consistent for a small project.
|
||||||
|
- The success criteria are stated once, in one place.
|
||||||
|
|
||||||
|
**Negative:**
|
||||||
|
|
||||||
|
- A reader who expects a KPI document finds the measures in the Business Case instead.
|
||||||
|
- If the project grows (a package published, more users), the skipped documents must be written then.
|
||||||
|
|
||||||
|
## Affected Artifacts
|
||||||
|
|
||||||
|
- [BC-001] — its Success Criteria stay the only definition of the measures.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[BC-001]: ../business-case.md
|
||||||
|
[f42e610]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/030-nato-phonetic-alphabet/commit/f42e6109ac82937291e5c8207c0631f710b9da85
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
# 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 | 004 |
|
||||||
|
| RC | SQA Review Record | docs/sqa/reviews/rc-*.md | 001 |
|
||||||
|
| ADR | Architecture Decision Record | docs/adr/adr-NNNN-*.md | 0003 |
|
||||||
|
| 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 |
|
||||||
|
| SSD | System Sequence Diagram | docs/uc-*/ssd.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`) |
|
||||||
|
|
||||||
|
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.
|
||||||
@@ -0,0 +1,141 @@
|
|||||||
|
# Business Case
|
||||||
|
|
||||||
|
## 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, reviewed in RC-001 | [f42e610] |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Executive Summary
|
||||||
|
|
||||||
|
Day 30 of the Udemy course "100 Days of Code: The Complete Python Pro Bootcamp" extends the NATO phonetic alphabet console tool with exception handling: the user types a word and the program spells it out, and when the input holds a character that is not a letter the program catches the failed lookup, tells the user to enter letters only and asks again instead of crashing. This project delivers that assignment as a clean, tested, documented Python repository that other course participants and GitHub visitors can read, run and compare against their own solutions. It uses only the Python standard library at runtime.
|
||||||
|
|
||||||
|
## Methodological and Standards Foundation
|
||||||
|
|
||||||
|
- Methodology: the project follows the SQA and QC framework mounted at `framework/` (plan first, review every artifact against its QC checklist, one pull request per milestone).
|
||||||
|
- Quality model: ISO/IEC 25010:2023 characteristics tag every QC criterion; code is reviewed against `qc-programming-python.md`.
|
||||||
|
- Engineering practice: Clean Architecture layering at a size proportionate to the program, tests written with pytest, source documented with Doxygen comments.
|
||||||
|
|
||||||
|
## Problem Statement
|
||||||
|
|
||||||
|
- The course assignment ships as a loose `main.py` and a CSV file with no tests, no run instructions and no project structure, so a participant cannot easily share or compare a solution.
|
||||||
|
- Without exception handling the program crashes with a `KeyError` as soon as the user types a digit or a symbol.
|
||||||
|
- Public solutions to course assignments are often undocumented, depend on heavy libraries (the course uses Pandas for a 26-row table) and are not runnable without guesswork.
|
||||||
|
|
||||||
|
## Business Opportunity
|
||||||
|
|
||||||
|
A small, exemplary solution lets the Product Owner practise professional project hygiene (packaging, tests, CI, documentation, multilingual wiki) on a trivially small domain, and gives other learners and GitHub visitors a reference they can run in a minute.
|
||||||
|
|
||||||
|
## Objectives
|
||||||
|
|
||||||
|
1. O1: Deliver a console program that converts a word typed by the user into the list of NATO phonetic code words, built with list and dictionary comprehensions, that handles invalid input with `try`/`except` and asks again until the input is valid, keeping the assignment's function names (`generate_phonetic`).
|
||||||
|
2. O2: Make the repository runnable by following the README on Windows PowerShell, Debian Linux and macOS with a local `.venv`.
|
||||||
|
3. O3: Cover the behaviour with automated pytest tests that run in continuous integration.
|
||||||
|
4. O4: Document the source with Doxygen comments and a `Doxyfile`, and document the project in a README and a wiki in English, Danish and Bahasa Malaysia, with screenshots.
|
||||||
|
5. O5: Present the repository to GitHub viewers with a description and topics, and with no runtime dependencies.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
### In Scope
|
||||||
|
|
||||||
|
- Console program: reads a word, prints the NATO code words for its letters; catches the error and asks again when the input contains a character that is not a letter.
|
||||||
|
- NATO alphabet data file (comma-separated values, CSV, as supplied with the assignment) and a loader that uses the standard library.
|
||||||
|
- Project structure `src/`, `tests/`, `docs/`; `pyproject.toml`; `constants.py`; Python `.gitignore`; `Doxyfile`.
|
||||||
|
- pytest test suite; continuous integration (CI) workflow that runs the tests.
|
||||||
|
- README from the framework template; wiki pages in en, da and ms; screenshots for README and wiki.
|
||||||
|
- Repository description and topics on the git host.
|
||||||
|
|
||||||
|
### Out of Scope
|
||||||
|
|
||||||
|
- A graphical or web interface.
|
||||||
|
- Publishing a package to the Python Package Index (PyPI).
|
||||||
|
- Runtime dependencies such as Pandas.
|
||||||
|
- Non-Latin alphabets and digits (rejected with a message).
|
||||||
|
- Other course days.
|
||||||
|
|
||||||
|
## Expected Benefits
|
||||||
|
|
||||||
|
### Tangible Benefits
|
||||||
|
|
||||||
|
- A runnable, tested reference solution with a one-command test run.
|
||||||
|
- A reusable repository skeleton (pyproject, continuous integration, Doxygen, wiki) for later course days.
|
||||||
|
|
||||||
|
### Intangible Benefits
|
||||||
|
|
||||||
|
- Practice in professional project hygiene.
|
||||||
|
- A readable example for other learners, in three languages.
|
||||||
|
|
||||||
|
## Strategic Alignment
|
||||||
|
|
||||||
|
The project supports the Product Owner's personal goal of completing the 100 Days of Code bootcamp with portfolio-quality repositories, and the framework's goal of demonstrating the plan-first workflow on a small project.
|
||||||
|
|
||||||
|
## Success Criteria
|
||||||
|
|
||||||
|
| # | Criterion | Target | Measure |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| 1 | Program spells a word correctly | Every letter A-Z maps to its NATO code word; input is case-insensitive | pytest: all 26 letters and a mixed-case word pass |
|
||||||
|
| 1a | Invalid input is handled | A character that is not a letter never crashes the program; the user is told and asked again | pytest: a digit and a symbol are rejected and a later valid word is spelled |
|
||||||
|
| 2 | Tests pass | 100 % of tests pass on Python 3.13 locally and in CI | `python -m pytest` exit code 0; CI run green |
|
||||||
|
| 3 | No runtime dependencies | 0 runtime dependencies | `pyproject.toml` has an empty `dependencies` list |
|
||||||
|
| 4 | Setup works from the README | A fresh clone runs the program using only the README steps | Manual run of the README steps on Windows PowerShell |
|
||||||
|
| 5 | Documentation complete | README sections of the template, wiki in 3 languages, Doxygen builds without warnings | `check-readme.sh` exit 0; every wiki page exists in en, da and ms; `doxygen Doxyfile` reports 0 warnings |
|
||||||
|
| 6 | Repository presented | Description and at least 5 topics set | Repository page and API show both |
|
||||||
|
|
||||||
|
## Risks
|
||||||
|
|
||||||
|
| Risk | Impact | Mitigation |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| The git host token lacks scope for editing the repository or wiki | Description, topics or wiki cannot be published | Stop and report; keep the wiki content as files in the working tree and ask S01 for a token with the needed scope |
|
||||||
|
| The wiki is not enabled on the host | Wiki pages cannot be pushed | Enable it through the repository settings API; otherwise stop and report |
|
||||||
|
| Danish and Bahasa Malaysia translations contain errors | S02 or S03 read wrong text | Keep wiki sentences short and simple; S01 reviews the translations in the pull request |
|
||||||
|
| Starter code is copied verbatim | Originality concerns | The program is written fresh; only the supplied CSV data is reused, as the assignment intends |
|
||||||
|
| Secrets in `.env` leak into the repository | Credential exposure | `.env` is git-ignored, never imported by the program or tests, and never echoed |
|
||||||
|
|
||||||
|
## Assumptions
|
||||||
|
|
||||||
|
- The Product Owner is S01, who also develops and reviews; in autonomous mode the AI acts as S01's stand-in reviewer and the review records say so.
|
||||||
|
- Python 3.13 or newer is available on the machines of the readers.
|
||||||
|
- The git host (Gitea) offers repository, topic and wiki features through its application programming interface (API) and git remote.
|
||||||
|
- The CSV with 26 letter/code word rows supplied with the assignment is the data source.
|
||||||
|
|
||||||
|
## Constraints
|
||||||
|
|
||||||
|
- Python 3.13 or newer, a local `venv`, `pytest`, constants in `constants.py`, configuration in `pyproject.toml`.
|
||||||
|
- Folder structure `src/`, `tests/`, `docs/`.
|
||||||
|
- No runtime dependencies unless needed.
|
||||||
|
- Tokens are read from `.env` for personal use only; the project and its tests never import or test it.
|
||||||
|
- One pull request per milestone; no commit on `main`.
|
||||||
|
|
||||||
|
## Cost–Benefit Assessment
|
||||||
|
|
||||||
|
Qualitative, because the project is a personal learning exercise with no revenue; the effort is a few hours of S01's time and AI assistance.
|
||||||
|
|
||||||
|
| Costs | Benefits |
|
||||||
|
| --- | --- |
|
||||||
|
| A few hours of effort; hosting on an existing git host | A reusable reference repository, practice with the framework, a shareable example for S02 and S03 |
|
||||||
|
|
||||||
|
## Stakeholders
|
||||||
|
|
||||||
|
| Stakeholder ID (SA) | Interest in this project |
|
||||||
|
| --- | --- |
|
||||||
|
| S01 | Owns and builds the project; wants a clean, complete solution |
|
||||||
|
| S02 | Wants readable, runnable code with the assignment's function names and run instructions |
|
||||||
|
| S03 | Wants a clear description, topics and README, and no runtime dependencies |
|
||||||
|
|
||||||
|
## Recommendation
|
||||||
|
|
||||||
|
Proceed: the scope is small, the risks are low and every objective is verifiable.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[SA-001]: ./stakeholder-analysis.md
|
||||||
|
[f42e610]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/030-nato-phonetic-alphabet/commit/f42e6109ac82937291e5c8207c0631f710b9da85
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
# MIL-001 Repository foundation
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
| Key | Value |
|
||||||
|
| --- | --- |
|
||||||
|
| ID | MIL-001 |
|
||||||
|
| CrossReference | [BC-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, reviewed in RC-003 | [f42e610] |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
Decide whether the repository has the structure, configuration and automation that the converter can be built on: a Python 3.13 project with a local virtual environment, pytest, a Doxygen configuration, a CI workflow and a public presentation (description and topics).
|
||||||
|
|
||||||
|
## Deliverable
|
||||||
|
|
||||||
|
A repository containing `pyproject.toml`, a Python `.gitignore`, the `src/` package skeleton with `constants.py` and the NATO CSV data file, an empty but running `tests/` folder, a `Doxyfile`, a CI workflow, two ADRs, and a repository description and topics set on the git host.
|
||||||
|
|
||||||
|
## Go / No-Go Criteria
|
||||||
|
|
||||||
|
| # | Criterion (objectively checkable) | Go | No-Go |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| 1 | `pyproject.toml` declares `requires-python >=3.13`, an empty `dependencies` list and pytest as a development extra | Present | Missing or a runtime dependency is listed |
|
||||||
|
| 2 | `.gitignore` ignores `.venv/`, `__pycache__/`, `.env` and the Doxygen output | `git check-ignore` confirms each | Any entry missing |
|
||||||
|
| 3 | A fresh `.venv` installs the project with `python -m pip install -e ".[dev]"` and `python -m pytest` runs | Exit code 0 | Install or run fails |
|
||||||
|
| 4 | `doxygen Doxyfile` builds | Exit code 0 | Build fails |
|
||||||
|
| 5 | The CI workflow runs the same pytest command and passes the framework's workflow checklist | Review `Go` | Review `No-Go` |
|
||||||
|
| 6 | The repository description and at least 5 topics are set on the host | API returns both | Missing |
|
||||||
|
| 7 | `.env` is not tracked and no token appears in any tracked file | `git ls-files` and a search show none | Any hit |
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
| Depends on | Reason |
|
||||||
|
| --- | --- |
|
||||||
|
| None | First phase; follows the accepted Business Case, Stakeholder Analysis and Project Plan |
|
||||||
|
|
||||||
|
## Traceability
|
||||||
|
|
||||||
|
| Business Case objective / KPI / user story | Reference |
|
||||||
|
| --- | --- |
|
||||||
|
| O2, O3, O4, O5 | [BC-001] |
|
||||||
|
|
||||||
|
## Ownership
|
||||||
|
|
||||||
|
| Role | Stakeholder ID (SA) |
|
||||||
|
| --- | --- |
|
||||||
|
| Owner | S01 |
|
||||||
|
| Approving reviewer | S01 |
|
||||||
|
|
||||||
|
## Target Date
|
||||||
|
|
||||||
|
2026-10-14 — inside the plan's window (2026-10-14 to 2026-10-17).
|
||||||
|
|
||||||
|
## Tasks
|
||||||
|
|
||||||
|
| # | Task | Summary | Needs its own Use Case/User Story? | Reference |
|
||||||
|
| --- | --- | --- | --- | --- |
|
||||||
|
| 1 | Record architecture decisions | Write ADR-0001 (read the NATO data with the standard library `csv` module instead of Pandas, so the project has no runtime dependencies for S03) and ADR-0002 (KPI, BMC, BPMN and RA are skipped for a project of this size). | No | |
|
||||||
|
| 2 | Configure the Python project | Add `pyproject.toml` (Python 3.13 or newer, no runtime dependencies, pytest as a development extra, pytest and package settings) and a Python `.gitignore` that also ignores `.env`, `.venv` and Doxygen output. | No | |
|
||||||
|
| 3 | Create the package skeleton | Start from the code of `026-nato-alphabet` (same layers, tooling and CI) and create `src/nato_phonetic_alphabet/` with `constants.py` (data file name, prompt and message texts), the supplied `nato_phonetic_alphabet.csv` as package data, and an empty `tests/` package, so the converter has a place to land. | No | |
|
||||||
|
| 4 | Add the Doxyfile | Generate a `Doxyfile` that reads `src/`, writes to `build/doxygen/`, extracts Python docstrings and warns on undocumented members. | No | |
|
||||||
|
| 5 | Add the CI workflow | Add a Gitea Actions workflow that sets up Python 3.13, creates a venv, installs the project and runs `python -m pytest` on every push and pull request. | No | |
|
||||||
|
| 6 | Set repository description and topics | Use the Gitea API with the token from the git-ignored `.env` (never printed, imported or committed) to set a description and topics on `Tirsvad-Udemy-100-days-of-code/030-nato-phonetic-alphabet` so S03 sees what the repository is. | No | |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[BC-001]: ../business-case.md
|
||||||
|
[f42e610]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/030-nato-phonetic-alphabet/commit/f42e6109ac82937291e5c8207c0631f710b9da85
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
# Project Plan
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
| Key | Value |
|
||||||
|
| --- | --- |
|
||||||
|
| ID | PP-001 |
|
||||||
|
| CrossReference | [BC-001], [SA-001], [MIL-001], [MIL-002], [MIL-003] |
|
||||||
|
| 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, accepted as Product Owner stand-in (no QC checklist for PP yet); plan accepted by S01 in chat | [f42e610] |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
Schedule the three phases that deliver the Day 30 NATO alphabet assignment as a tested and documented repository: foundation, converter, documentation and publication. The plan runs against the Business Case's constraint of a small personal project with one pull request per milestone.
|
||||||
|
|
||||||
|
## Planning Assumptions
|
||||||
|
|
||||||
|
- The plan starts 2026-10-14 and ends by 2026-10-16.
|
||||||
|
- Each phase is one day of work and one pull request that closes its issues.
|
||||||
|
- S01 is owner and reviewer of every gateway; in autonomous mode the AI acts as S01's stand-in and every review record says so.
|
||||||
|
- The language of the planning documents is English (registry `Languages`); the wiki is written in English, Danish and Bahasa Malaysia.
|
||||||
|
- The git host is the Gitea instance at `git.tirsystem.com`; its token comes from the git-ignored `.env`.
|
||||||
|
|
||||||
|
## Gateway Schedule
|
||||||
|
|
||||||
|
| Gateway | Document | Window | Decision date | Owner | Stories | Main deliverable | Milestone |
|
||||||
|
| --- | --- | --- | --- | --- | --- | --- | --- |
|
||||||
|
| Repository foundation | [MIL-001] | 2026-10-14 to 2026-10-14 | 2026-10-14 | S01 | none | Project configuration, package skeleton, Doxyfile, CI workflow, ADRs, repository description and topics | |
|
||||||
|
| NATO converter | [MIL-002] | 2026-10-14 to 2026-10-15 | 2026-10-15 | S01 | US-001 | Working console program with pytest tests and Doxygen comments | |
|
||||||
|
| Documentation and publication | [MIL-003] | 2026-10-15 to 2026-10-16 | 2026-10-16 | S01 | none | README, screenshots, wiki in en, da and ms | |
|
||||||
|
|
||||||
|
```plantuml
|
||||||
|
@startgantt
|
||||||
|
Project starts 2026-10-14
|
||||||
|
[Repository foundation] starts 2026-10-14 and ends 2026-10-14
|
||||||
|
[MIL-001 Go/No-Go] happens 2026-10-14
|
||||||
|
[NATO converter] starts 2026-10-14 and ends 2026-10-15
|
||||||
|
[MIL-002 Go/No-Go] happens 2026-10-15
|
||||||
|
[Documentation and publication] starts 2026-10-15 and ends 2026-10-16
|
||||||
|
[MIL-003 Go/No-Go] happens 2026-10-16
|
||||||
|
@endgantt
|
||||||
|
```
|
||||||
|
|
||||||
|
## Scope Coverage
|
||||||
|
|
||||||
|
| Business Case scope item | Gateway |
|
||||||
|
| --- | --- |
|
||||||
|
| Console program and NATO data loader | [MIL-002] |
|
||||||
|
| Project structure, `pyproject.toml`, `constants.py`, `.gitignore`, `Doxyfile` | [MIL-001] |
|
||||||
|
| pytest test suite | [MIL-002] |
|
||||||
|
| CI workflow that runs the tests | [MIL-001] |
|
||||||
|
| README, wiki (en, da, ms) and screenshots | [MIL-003] |
|
||||||
|
| Repository description and topics | [MIL-001] |
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
```
|
||||||
|
MIL-001 → MIL-002 → MIL-003
|
||||||
|
```
|
||||||
|
|
||||||
|
A No-Go on a gateway holds the later ones until the cause is fixed and the gateway is reviewed again; later windows shift by the same days.
|
||||||
|
|
||||||
|
## Plan Risks
|
||||||
|
|
||||||
|
| Risk | Impact | Mitigation |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| The host token lacks scope for repository settings or wiki | MIL-001 or MIL-003 cannot finish | Stop and report (autonomous-mode stop rule); S01 supplies a token with the scope |
|
||||||
|
| The CI runner on the host is not available | CI workflow cannot be proven green | The workflow is verified by running the same commands locally; the gap is recorded in the review |
|
||||||
|
| Wiki translation takes longer than planned | MIL-003 slips | Wiki pages are short and share one structure |
|
||||||
|
|
||||||
|
## Open Issues
|
||||||
|
|
||||||
|
- "Python greater than 3.13" is read as 3.13 or newer (`requires-python = ">=3.13"`); S01 can tighten it.
|
||||||
|
- `.env` also holds a GitHub token and user; no GitHub mirror was requested, so they are not used.
|
||||||
|
- Screenshots are rendered from the real program output (a terminal-style image), because a desktop screenshot cannot be taken from an unattended run; S01 may replace them with native captures.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[BC-001]: ./business-case.md
|
||||||
|
[SA-001]: ./stakeholder-analysis.md
|
||||||
|
[MIL-001]: ./milestones/mil-001-repository-foundation.md
|
||||||
|
[MIL-002]: ./milestones/mil-002-nato-converter.md
|
||||||
|
[MIL-003]: ./milestones/mil-003-documentation-and-publication.md
|
||||||
|
[f42e610]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/030-nato-phonetic-alphabet/commit/f42e6109ac82937291e5c8207c0631f710b9da85
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
# SQA Review Record RC-001: BC-001
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
| Key | Value |
|
||||||
|
| --- | --- |
|
||||||
|
| ID | RC-001 |
|
||||||
|
| 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 | Review of BC-001 | [f42e610] |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Artifact Under Review
|
||||||
|
|
||||||
|
- Instance reviewed: [BC-001]
|
||||||
|
- Checklist used: [QC-BC-001] and [QC-LANG-001]
|
||||||
|
- Scope: full review
|
||||||
|
- Language and domain: en / it
|
||||||
|
- Language reviewer: none (the reviewer reads the language and knows the domain)
|
||||||
|
- Mode: autonomous, not independent (the 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 | Cost-Benefit is qualitative and the section states why (personal learning exercise, no revenue). |
|
||||||
|
| 2 | Risks are identified with documented impact and mitigation | Pass | Five risks, each with impact and mitigation. |
|
||||||
|
| 3 | Success criteria are measurable, stating explicit targets rather than vague aspirations | Pass | Seven success criteria (1 to 6 and 1a), each with a numeric or checkable target and a measure. |
|
||||||
|
| 4 | Scope explicitly separates In Scope vs Out of Scope | Pass | `### In Scope` and `### Out of Scope` are separate subsections. |
|
||||||
|
| 5 | Stakeholders are cross-referenced to Stakeholder Analysis IDs rather than re-described inline | Pass | The Stakeholders table cites S01, S02 and S03 from [SA-001]; roles are not re-described. |
|
||||||
|
| 6 | Methodology and quality-standard foundation are stated explicitly (e.g. ISO/IEC 25010, Larman) | Pass | The foundation section names the framework, ISO/IEC 25010:2023 and Clean Architecture. |
|
||||||
|
| 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 | The Recommendation is a single "Proceed" with a 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 | `Language | en` and `Domain | it` are in the Metadata table. |
|
||||||
|
| 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; `it` is in the registry's domain list. |
|
||||||
|
| 3 | The content (prose and table cells) is written in the stated language | Pass | All prose and table cells are English; the course title is quoted source text. Checked by the stand-in reviewer, who reads English. |
|
||||||
|
| 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 matches it. |
|
||||||
|
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | No dictionary (`DICT`) exists yet; the terms letter, code word and NATO alphabet are used consistently with no synonyms. Checked by the stand-in; open to challenge. |
|
||||||
|
| 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 of the file exists. |
|
||||||
|
| 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. |
|
||||||
|
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The domain is software and IT and the language English; the reviewer stood in for (S01) reads both. A person may challenge this in the run summary. |
|
||||||
|
| 10 | Abbreviations are spelled out on first use, in the stated language | Pass | Abbreviations are spelled out on first use or are identifiers (IDs, tool names). |
|
||||||
|
|
||||||
|
## Overall Verdict
|
||||||
|
|
||||||
|
Go — every Mandatory criterion of QC-BC-001 and of QC-LANG-001 passes. The review is a stand-in review by the author's AI and is not independent; it is open to challenge in the run summary.
|
||||||
|
|
||||||
|
## Action Items
|
||||||
|
|
||||||
|
| Action | Owner | Due |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| None | S01 | n/a |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[BC-001]: ../../business-case.md
|
||||||
|
[QC-BC-001]: ../../../framework/qc/artifacts/qc-business-case.md
|
||||||
|
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
|
||||||
|
[f42e610]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/030-nato-phonetic-alphabet/commit/f42e6109ac82937291e5c8207c0631f710b9da85
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
# SQA Review Record RC-002: SA-001
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
| Key | Value |
|
||||||
|
| --- | --- |
|
||||||
|
| ID | RC-002 |
|
||||||
|
| CrossReference | [SA-001], [QC-SA-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 | Review of SA-001 | [f42e610] |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Artifact Under Review
|
||||||
|
|
||||||
|
- Instance reviewed: [SA-001]
|
||||||
|
- Checklist used: [QC-SA-001] and [QC-LANG-001]
|
||||||
|
- Scope: full review
|
||||||
|
- Language and domain: en / it
|
||||||
|
- Language reviewer: none (the reviewer reads the language and knows the domain)
|
||||||
|
- Mode: autonomous, not independent (the reviewer is `AI as stand-in for S01`)
|
||||||
|
|
||||||
|
## Checklist Results
|
||||||
|
|
||||||
|
| # | Criterion | Status | Evidence/Notes |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| 1 | Power/Interest grid is filled for every stakeholder, with no gaps or unclassified entries | Pass | S01, S02 and S03 each have Power, Interest and Quadrant. |
|
||||||
|
| 2 | Each stakeholder is assigned a unique, stable ID (e.g. S01-S11 style) reusable for RACI assignments in other artifacts | Pass | Stable IDs S01 to S03, used by the other artifacts. |
|
||||||
|
| 3 | Roles and organizational context are defined with explicit Power and Interest levels, not just narrative description | Pass | Role and organization are stated with explicit HIGH/MEDIUM/LOW levels. |
|
||||||
|
| 4 | Communication needs (channel, frequency, deliverable type) are mapped to project phases or milestones | Pass | Communication table maps channel, frequency and deliverable to milestones. |
|
||||||
|
| 5 | Conflicting stakeholder interests are identified with documented mitigation or resolution strategies | Pass | Two conflicts, each with a mitigation. |
|
||||||
|
| 6 | Stakeholder concerns are explicitly traced to Business Case objectives | Pass | Traceability table cites [BC-001] objectives O1 to O5. |
|
||||||
|
| 7 | Primary concerns are expressed in both business language and a recognized quality-attribute mapping (e.g. FURPS+) | Pass | Each concern is mapped to a FURPS+ attribute. |
|
||||||
|
| 8 | Document is understandable and navigable by non-technical stakeholders reviewing their own entry | Pass | Short tables; each entry reads on its own. |
|
||||||
|
|
||||||
|
## 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 | `Language | en` and `Domain | it` are in the Metadata table. |
|
||||||
|
| 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; `it` is in the registry's domain list. |
|
||||||
|
| 3 | The content (prose and table cells) is written in the stated language | Pass | All prose and table cells are English; the course title is quoted source text. Checked by the stand-in reviewer, who reads English. |
|
||||||
|
| 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 matches it. |
|
||||||
|
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | No dictionary (`DICT`) exists yet; the terms letter, code word and NATO alphabet are used consistently with no synonyms. Checked by the stand-in; open to challenge. |
|
||||||
|
| 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 of the file exists. |
|
||||||
|
| 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. |
|
||||||
|
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The domain is software and IT and the language English; the reviewer stood in for (S01) reads both. A person may challenge this in the run summary. |
|
||||||
|
| 10 | Abbreviations are spelled out on first use, in the stated language | Pass | Abbreviations are spelled out on first use or are identifiers (IDs, tool names). |
|
||||||
|
|
||||||
|
## Overall Verdict
|
||||||
|
|
||||||
|
Go — every Mandatory criterion of QC-SA-001 and of QC-LANG-001 passes. The review is a stand-in review by the author's AI and is not independent; it is open to challenge in the run summary.
|
||||||
|
|
||||||
|
## Action Items
|
||||||
|
|
||||||
|
| Action | Owner | Due |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| None | S01 | n/a |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[SA-001]: ../../stakeholder-analysis.md
|
||||||
|
[QC-SA-001]: ../../../framework/qc/artifacts/qc-stakeholder-analysis.md
|
||||||
|
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
|
||||||
|
[f42e610]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/030-nato-phonetic-alphabet/commit/f42e6109ac82937291e5c8207c0631f710b9da85
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
# SQA Review Record RC-003: MIL-001
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
| Key | Value |
|
||||||
|
| --- | --- |
|
||||||
|
| ID | RC-003 |
|
||||||
|
| CrossReference | [MIL-001], [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 | Review of MIL-001 | [f42e610] |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Artifact Under Review
|
||||||
|
|
||||||
|
- Instance reviewed: [MIL-001]
|
||||||
|
- Checklist used: [QC-MIL-001] and [QC-LANG-001]
|
||||||
|
- Scope: full review
|
||||||
|
- Language and domain: en / it
|
||||||
|
- Language reviewer: none (the reviewer reads the language and knows the domain)
|
||||||
|
- Mode: autonomous, not independent (the reviewer is `AI as stand-in for S01`)
|
||||||
|
|
||||||
|
## Checklist Results
|
||||||
|
|
||||||
|
| # | Criterion | Status | Evidence/Notes |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| 1 | A concrete deliverable is defined for every gate | Pass | Deliverable section names concrete output: project configuration, skeleton, Doxyfile, CI workflow, ADRs, description and topics. |
|
||||||
|
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Go / No-Go table has objectively checkable rows (commands and counts). |
|
||||||
|
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Dependencies table is filled. |
|
||||||
|
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Traceability cites [BC-001] objectives. |
|
||||||
|
| 5 | Milestone owner and approving reviewer are identified | Pass | Owner and approving reviewer are S01. |
|
||||||
|
| 6 | Milestone has a defined target date consistent with project constraints | Pass | Target date lies inside the Project Plan window; the Business Case sets no calendar constraint. |
|
||||||
|
|
||||||
|
## 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 | `Language | en` and `Domain | it` are in the Metadata table. |
|
||||||
|
| 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; `it` is in the registry's domain list. |
|
||||||
|
| 3 | The content (prose and table cells) is written in the stated language | Pass | All prose and table cells are English; the course title is quoted source text. Checked by the stand-in reviewer, who reads English. |
|
||||||
|
| 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 matches it. |
|
||||||
|
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | No dictionary (`DICT`) exists yet; the terms letter, code word and NATO alphabet are used consistently with no synonyms. Checked by the stand-in; open to challenge. |
|
||||||
|
| 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 of the file exists. |
|
||||||
|
| 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. |
|
||||||
|
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | The domain is software and IT and the language English; the reviewer stood in for (S01) reads both. A person may challenge this in the run summary. |
|
||||||
|
| 10 | Abbreviations are spelled out on first use, in the stated language | Pass | Abbreviations are spelled out on first use or are identifiers (IDs, tool names). |
|
||||||
|
|
||||||
|
## Overall Verdict
|
||||||
|
|
||||||
|
Go — every Mandatory criterion of QC-MIL-001 and of QC-LANG-001 passes. The review is a stand-in review by the author's AI and is not independent; it is open to challenge in the run summary.
|
||||||
|
|
||||||
|
## Action Items
|
||||||
|
|
||||||
|
| Action | Owner | Due |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| None | S01 | n/a |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[MIL-001]: ../../milestones/mil-001-repository-foundation.md
|
||||||
|
[QC-MIL-001]: ../../../framework/qc/artifacts/qc-milestones-gateways.md
|
||||||
|
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
|
||||||
|
[f42e610]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/030-nato-phonetic-alphabet/commit/f42e6109ac82937291e5c8207c0631f710b9da85
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
# SQA Review Record RC-006: ADR-0001
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
| Key | Value |
|
||||||
|
| --- | --- |
|
||||||
|
| ID | RC-006 |
|
||||||
|
| CrossReference | [ADR-0001], [QC-ADR-001] |
|
||||||
|
|
||||||
|
## Version History
|
||||||
|
| Date | Status | Author | Reviewer | Change | Commit |
|
||||||
|
| --- | --- | --- | --- | --- | --- |
|
||||||
|
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Review of ADR-0001 | [f42e610] |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Artifact Under Review
|
||||||
|
|
||||||
|
- Instance reviewed: [ADR-0001]
|
||||||
|
- Checklist used: [QC-ADR-001]
|
||||||
|
- Scope: full review
|
||||||
|
- Language and domain: n/a (technical type)
|
||||||
|
- Language reviewer: none
|
||||||
|
- Mode: autonomous, not independent (the 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 | ADR-0001 matches `adr-0001-*.md` and follows the registry sequence. |
|
||||||
|
| 2 | Context states the problem, the forces (cost, risk, constraints) and the options evaluated | Pass | Context states the problem, forces and the options evaluated. |
|
||||||
|
| 3 | At least two options were considered, or the absence of alternatives is justified | Pass | Three options (ADR-0001) / three options (ADR-0002) are listed. |
|
||||||
|
| 4 | Decision is stated in one or two unhedged sentences and matches one of the evaluated options | Pass | The Decision is stated plainly and is one of the listed options. |
|
||||||
|
| 5 | Consequences list both Positive and Negative outcomes | Pass | Positive and Negative consequences are listed. |
|
||||||
|
| 6 | Quality-attribute impacts (performance, security, portability, etc.) are named where the decision affects them | Pass | Portability and security: no runtime dependency to install or patch. |
|
||||||
|
| 7 | Affected Artifacts are listed as links, and each is also in CrossReference | Pass | Affected Artifacts are links and each is 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 | One Version History row; no retained row was rewritten. |
|
||||||
|
| 9 | A superseded or deprecated ADR names its successor, and the successor links back | N-A | No ADR is superseded or deprecated. |
|
||||||
|
| 10 | Written in business or technical language of the domain, with no unexplained abbreviations | Pass | Plain technical language; abbreviations such as CSV are spelled out in the Business Case. |
|
||||||
|
| 11 | Status is one of `Proposed`, `Accepted`, `Rejected`, `Deprecated` or `Superseded by ADR-NNNN`, and every Version History row uses only these | Pass | The status is `Accepted`, an allowed value. |
|
||||||
|
|
||||||
|
## Overall Verdict
|
||||||
|
|
||||||
|
Go — every Mandatory criterion of QC-ADR-001 passes.
|
||||||
|
|
||||||
|
## Action Items
|
||||||
|
|
||||||
|
| Action | Owner | Due |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| None | S01 | n/a |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[ADR-0001]: ../../adr/adr-0001-read-nato-data-with-csv-module.md
|
||||||
|
[QC-ADR-001]: ../../../framework/qc/artifacts/qc-adr.md
|
||||||
|
[f42e610]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/030-nato-phonetic-alphabet/commit/f42e6109ac82937291e5c8207c0631f710b9da85
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
# SQA Review Record RC-007: ADR-0002
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
| Key | Value |
|
||||||
|
| --- | --- |
|
||||||
|
| ID | RC-007 |
|
||||||
|
| CrossReference | [ADR-0002], [QC-ADR-001] |
|
||||||
|
|
||||||
|
## Version History
|
||||||
|
| Date | Status | Author | Reviewer | Change | Commit |
|
||||||
|
| --- | --- | --- | --- | --- | --- |
|
||||||
|
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Review of ADR-0002 | [f42e610] |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Artifact Under Review
|
||||||
|
|
||||||
|
- Instance reviewed: [ADR-0002]
|
||||||
|
- Checklist used: [QC-ADR-001]
|
||||||
|
- Scope: full review
|
||||||
|
- Language and domain: n/a (technical type)
|
||||||
|
- Language reviewer: none
|
||||||
|
- Mode: autonomous, not independent (the 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 | ADR-0002 matches `adr-0002-*.md` and follows the registry sequence. |
|
||||||
|
| 2 | Context states the problem, the forces (cost, risk, constraints) and the options evaluated | Pass | Context states the problem, forces and the options evaluated. |
|
||||||
|
| 3 | At least two options were considered, or the absence of alternatives is justified | Pass | Three options (ADR-0001) / three options (ADR-0002) are listed. |
|
||||||
|
| 4 | Decision is stated in one or two unhedged sentences and matches one of the evaluated options | Pass | The Decision is stated plainly and is one of the listed options. |
|
||||||
|
| 5 | Consequences list both Positive and Negative outcomes | Pass | Positive and Negative consequences are listed. |
|
||||||
|
| 6 | Quality-attribute impacts (performance, security, portability, etc.) are named where the decision affects them | Pass | Maintainability: fewer documents to keep consistent. |
|
||||||
|
| 7 | Affected Artifacts are listed as links, and each is also in CrossReference | Pass | Affected Artifacts are links and each is 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 | One Version History row; no retained row was rewritten. |
|
||||||
|
| 9 | A superseded or deprecated ADR names its successor, and the successor links back | N-A | No ADR is superseded or deprecated. |
|
||||||
|
| 10 | Written in business or technical language of the domain, with no unexplained abbreviations | Pass | Plain technical language; abbreviations such as CSV are spelled out in the Business Case. |
|
||||||
|
| 11 | Status is one of `Proposed`, `Accepted`, `Rejected`, `Deprecated` or `Superseded by ADR-NNNN`, and every Version History row uses only these | Pass | The status is `Accepted`, an allowed value. |
|
||||||
|
|
||||||
|
## Overall Verdict
|
||||||
|
|
||||||
|
Go — every Mandatory criterion of QC-ADR-001 passes.
|
||||||
|
|
||||||
|
## Action Items
|
||||||
|
|
||||||
|
| Action | Owner | Due |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| None | S01 | n/a |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[ADR-0002]: ../../adr/adr-0002-skip-analysis-artifacts.md
|
||||||
|
[QC-ADR-001]: ../../../framework/qc/artifacts/qc-adr.md
|
||||||
|
[f42e610]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/030-nato-phonetic-alphabet/commit/f42e6109ac82937291e5c8207c0631f710b9da85
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
# SQA Review Record RC-008: WF-001
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
| Key | Value |
|
||||||
|
| --- | --- |
|
||||||
|
| ID | RC-008 |
|
||||||
|
| CrossReference | [WF-001], [QC-WF-001], [QC-YML-001] |
|
||||||
|
|
||||||
|
## Version History
|
||||||
|
| Date | Status | Author | Reviewer | Change | Commit |
|
||||||
|
| --- | --- | --- | --- | --- | --- |
|
||||||
|
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Review of WF-001 | [f42e610] |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Artifact Under Review
|
||||||
|
|
||||||
|
- Instance reviewed: [WF-001]
|
||||||
|
- Checklist used: [QC-WF-001] and [QC-YML-001]
|
||||||
|
- Scope: full review
|
||||||
|
- Language and domain: n/a (technical type)
|
||||||
|
- Language reviewer: none
|
||||||
|
- Mode: autonomous, not independent (the reviewer is `AI as stand-in for S01`)
|
||||||
|
|
||||||
|
## Checklist Results
|
||||||
|
|
||||||
|
| # | Criterion | Status | Evidence/Notes |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| 1 | The file meets the YAML checklist ([QC-YML-001]) | Pass | See the QC-YML-001 table below; every Mandatory row passes. |
|
||||||
|
| 2 | The file is in `.gitea/workflows/` or `.github/workflows/` with the extension `.yml` or `.yaml`, and the same workflow does not exist in both directories | Pass | `.gitea/workflows/ci.yml`; no workflow in `.github/workflows/`. |
|
||||||
|
| 3 | The file declares `name`, `on` and `jobs`; `on` lists explicit events and, where it matters, `branches` or `paths` | Pass | `name`, `on` (push with `branches` and `paths`, pull_request with `paths`) and `jobs` are declared. |
|
||||||
|
| 4 | A header comment states the purpose, the triggers, the inputs, the secrets it needs, what it changes outside the repository, and the decision or milestone it implements | Pass | The header states purpose, triggers, inputs, secrets, changes outside the repository and the decision. |
|
||||||
|
| 5 | Every job and step has a descriptive `name`, unique within its job | Pass | Every step has a unique descriptive `name`. |
|
||||||
|
| 6 | The file passes `actionlint` (or the project's workflow validation test) and the tool version is stated | Pass | actionlint 1.7.12 reports no finding; yamllint 1.38.0 as well. |
|
||||||
|
| 7 | Every job declares `permissions` explicitly with the least access that works (`contents: read` or none by default); write access only on the job that needs it | Pass | The job declares `permissions: contents: read`. |
|
||||||
|
| 8 | Every action used is pinned to a full commit SHA or an exact release tag, never to a branch; a moving major tag (`@v1`) is accepted only for an action published by the same organisation under a stated release policy | Pass | `actions/checkout@v4.2.2` and `actions/setup-python@v5.6.0` are exact release tags. |
|
||||||
|
| 9 | No secret is written in the file; a secret is read as `secrets.NAME`, passed to a step through `env:`, never placed on a command line or echoed | Pass | No secret is used or written. |
|
||||||
|
| 10 | Untrusted text (`inputs.*`, event fields such as a title, branch name or label, step outputs derived from them) is never interpolated into a `run:` script; it is passed through `env:` and used as a quoted variable | Pass | No event field is interpolated into a `run:` block; `github.ref` is used only in the concurrency group. |
|
||||||
|
| 11 | A trigger that gives a run secrets or a write token on code from a fork or an untrusted branch (`pull_request_target`, `workflow_run`) does not check out or execute that code | Pass | No `pull_request_target` or `workflow_run` trigger. |
|
||||||
|
| 12 | A workflow that changes state outside the repository (release, tag, publish, sync, deploy) is started by hand or by a protected branch, and a manual run defaults to a dry run with an explicit input to apply | N-A | The workflow changes nothing outside the repository. |
|
||||||
|
| 13 | The token the workflow uses has only the scope the job needs, and where the host's built-in token is enough it is used instead of a personal token | N-A | No token is used. |
|
||||||
|
| 14 | Every job sets `runs-on` to an explicit label and `timeout-minutes` | Pass | `runs-on: ubuntu-latest` and `timeout-minutes: 10`. |
|
||||||
|
| 15 | `concurrency` is set where two runs would conflict: a check cancels the older run (`cancel-in-progress: true`); a publishing job queues (`cancel-in-progress: false`) | Pass | `concurrency` with `cancel-in-progress: true` for a check. |
|
||||||
|
| 16 | Triggers are filtered (`branches`, `paths`, `types`) so the workflow runs only for the changes it concerns | Pass | Branch and path filters limit the runs to code and configuration changes. |
|
||||||
|
| 17 | Tools and dependencies are installed at pinned versions; a version is a workflow input with a default or a value in one place | Pass | Python version is the one value `PYTHON_VERSION`; development tools are pinned with `==` in `pyproject.toml`. |
|
||||||
|
| 18 | A dependency cache is used where the install is slow enough to matter | N-A | The install takes about 15 seconds; a cache would not matter. |
|
||||||
|
| 19 | A failing step names the tool, the file and the reason in its log (annotation or `::error::` line) | N-A | Each step is a single tool command whose own log names the file and reason. |
|
||||||
|
| 20 | A `run:` block is within the limit on embedded program text of criterion 7 of [QC-YML-001]; a longer script is a file (`tools/`, or a shared repository fetched at a pinned ref) that the step calls with one command, and the workflow passes its settings through `env:` | Pass | The longest `run:` block has two lines. |
|
||||||
|
| 21 | Logic used by more than one workflow or repository is a reusable workflow (`workflow_call`) or a composite action; each input has a `description`, a `type` and a `default` where one is sensible | N-A | One workflow; no logic is shared. |
|
||||||
|
| 22 | Every workflow feature used is verified on the instance that runs it, and the host and version are recorded; a feature the target hosts differ on is noted in the header | Pass | Verified on Gitea 1.27.3 (`/api/v1/version`): the pull_request run (run 1557) completed with state success on runner label ubuntu-latest. |
|
||||||
|
| 23 | A reusable workflow states, in its header, how a caller pins it and the script it fetches, so the workflow and its script are the same release | N-A | Not a reusable workflow. |
|
||||||
|
| 24 | A static test of the repository's workflows exists and runs on every pull request: valid YAML, required keys, explicit permissions and runner, no inline script above the limit | N-A | Optional; the workflow is linted by actionlint and yamllint in this review, no repeated static test exists for a single file. |
|
||||||
|
|
||||||
|
## Referenced Checklist Results (QC-YML-001)
|
||||||
|
|
||||||
|
| # | Criterion | Status | Evidence/Notes |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| 1 | The file parses with a safe YAML loader and has no duplicate keys in any mapping | Pass | Loaded with PyYAML `safe_load`; no duplicate keys (yamllint `key-duplicates`). |
|
||||||
|
| 2 | Indentation is 2 spaces everywhere, never tabs; lines end with LF; the file ends with one newline and has no trailing spaces | Pass | 2-space indentation, LF, final newline, no trailing spaces (yamllint default rules). |
|
||||||
|
| 3 | Passes `yamllint` (or the project's YAML linter) with its configuration committed next to the code and no unexplained `disable` comments | Pass | yamllint 1.38.0 with `.yamllint.yml` committed; no `disable` comments. |
|
||||||
|
| 4 | A scalar that YAML would coerce to another type is quoted: `yes`, `no`, `on`, `off`, `null`, `~`, numbers with a leading zero, versions such as `1.10`, and values that contain `: ` or ` #` | Pass | `"3.13"` is quoted; no coercible scalar remains. |
|
||||||
|
| 5 | Only safe, plain types are used: no language-specific tags (`!!python/object`, `!ruby/object`) and no `!include`-style extension unless the consuming tool documents it | Pass | No tags or extensions. |
|
||||||
|
| 6 | No secret is written in the file: no password, token, key or private connection string; a secret is referenced by name and supplied by the consuming tool | Pass | No secret. |
|
||||||
|
| 7 | Embedded program text (shell, Python, SQL, `jq`, and so on) in a value is at most five lines; a longer one is moved to a file of its own, in its own language, and the YAML calls it | Pass | Longest embedded script is two lines. |
|
||||||
|
| 8 | A block of keys or values repeated in the file or across files is defined once (an anchor, a template, an include or a reusable unit the consumer supports) | Pass | Nothing repeats beyond the three-line path list used by two triggers; the paths are a different trigger each, accepted because the host has no anchor support in `on:`. |
|
||||||
|
| 9 | Anchors, aliases and merge keys (`&`, `*`, `<<`) are used only where the consuming tool is known to support them | Pass | No anchors or aliases. |
|
||||||
|
| 10 | The file validates against the schema of the consuming tool where one exists, and the schema or tool version is stated | N-A | Optional: no schema file is available offline; actionlint validates the structure. |
|
||||||
|
| 11 | A header comment states what the file is for, which tool reads it, and where its decision or design is recorded | Pass | The header says what the file is for, which tool reads it and the decision. |
|
||||||
|
| 12 | Key names follow the convention of the consuming tool; one case style is used within the file (kebab-case or snake_case, never mixed) | Pass | kebab-case for keys such as `runs-on`, `timeout-minutes`; no mixed style. |
|
||||||
|
| 13 | Multi-line strings use a block scalar (`\|` or `>`) and state the chomping indicator (`\|-`, `\|+`) where the trailing newline matters | Pass | `run: |` is used for the two-line block with the default clip chomping, which suits a script. |
|
||||||
|
| 14 | The file name is lowercase kebab-case with one extension style (`.yml` or `.yaml`) used throughout the repository | Pass | `ci.yml`, lowercase, `.yml` throughout. |
|
||||||
|
| 15 | A change is exercised by a check that runs without the real target: a parse and schema test, or a dry run of the consuming tool | Pass | Exercised by actionlint, yamllint and a real run. |
|
||||||
|
|
||||||
|
## Overall Verdict
|
||||||
|
|
||||||
|
Go — every Mandatory criterion of QC-WF-001 and QC-YML-001 passes; the workflow ran green on Gitea 1.27.3. The `Doxyfile` output folder is `build/` (not `build/doxygen/` as the MIL-001 task summary says) because Doxygen creates only one directory level; the Go/No-Go criteria are not affected.
|
||||||
|
|
||||||
|
## Action Items
|
||||||
|
|
||||||
|
| Action | Owner | Due |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| None | S01 | n/a |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[WF-001]: ../../../.gitea/workflows/ci.yml
|
||||||
|
[QC-WF-001]: ../../../framework/qc/code/qc-workflow.md
|
||||||
|
[QC-YML-001]: ../../../framework/qc/code/qc-yaml.md
|
||||||
|
[f42e610]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/030-nato-phonetic-alphabet/commit/f42e6109ac82937291e5c8207c0631f710b9da85
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
# SQA Review Record RC-009: PY-001
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
| Key | Value |
|
||||||
|
| --- | --- |
|
||||||
|
| ID | RC-009 |
|
||||||
|
| CrossReference | [PY-001], [QC-PY-001] |
|
||||||
|
|
||||||
|
## Version History
|
||||||
|
| Date | Status | Author | Reviewer | Change | Commit |
|
||||||
|
| --- | --- | --- | --- | --- | --- |
|
||||||
|
| 2026-10-14 | Accepted | Jens Tirsvad Nielsen | AI as stand-in for S01 | Review of PY-001 | [f42e610] |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Artifact Under Review
|
||||||
|
|
||||||
|
- Instance reviewed: [PY-001]
|
||||||
|
- Checklist used: [QC-PY-001]
|
||||||
|
- Scope: full review
|
||||||
|
- Language and domain: n/a (technical type)
|
||||||
|
- Language reviewer: none
|
||||||
|
- Mode: autonomous, not independent (the 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 | snake_case modules, UPPER_SNAKE constants; 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: `DATA_FILE_NAME`, `LETTER_COLUMN`, `INVALID_INPUT_TEXT`. |
|
||||||
|
| 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; no suppressions. |
|
||||||
|
| 4 | Every function and method signature is type-annotated, including `-> None` | Pass | Test functions are annotated `-> None`; constants are annotated. |
|
||||||
|
| 5 | No bare `except:`, no swallowed exceptions; specific exceptions are raised and the cause is kept (`raise ... from`) | N-A | No exception handling exists in the skeleton. |
|
||||||
|
| 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 file handles are opened; `Traversable.read_text` closes its own. |
|
||||||
|
| 8 | Public modules, classes and functions have docstrings that say what, not how | Pass | The module and package have docstrings with `@brief`. |
|
||||||
|
| 9 | Logging uses `logging`, not `print`; no secrets or personal data in log output | N-A | No output is produced in the skeleton. |
|
||||||
|
| 10 | Classes and operations trace to the Design Class Diagram they implement; deviations are recorded | N-A | No design class diagram exists for this phase; the skeleton has no classes. |
|
||||||
|
| 11 | Tests exist for new behaviour, are named for the behaviour, and do not depend on order or the network | Pass | Two tests named for the behaviour test the data file. |
|
||||||
|
| 12 | Type checker runs in strict mode without errors; `Any` is justified in a comment | Pass | `mypy --strict` reports no issue in 3 files. |
|
||||||
|
| 13 | Dependencies are declared and pinned in the project's dependency file, none unused | Pass | Zero runtime dependencies; dev tools pinned exactly. |
|
||||||
|
| 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 | Each literal is defined once in `constants.py`; the test reads names, not copies. |
|
||||||
|
| 15 | Imports point inward: business-rule modules import no framework, database, UI or delivery-mechanism code, and there are no import cycles | Pass | The package imports nothing; no cycles. |
|
||||||
|
| 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 | A module with only constants has one reason to change. |
|
||||||
|
|
||||||
|
## Overall Verdict
|
||||||
|
|
||||||
|
Go — every Mandatory criterion of QC-PY-001 passes or is not applicable to the skeleton (constants and smoke tests).
|
||||||
|
|
||||||
|
## Action Items
|
||||||
|
|
||||||
|
| Action | Owner | Due |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| None | S01 | n/a |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[PY-001]: ../../../src/nato_phonetic_alphabet/constants.py
|
||||||
|
[QC-PY-001]: ../../../framework/qc/code/qc-programming-python.md
|
||||||
|
[f42e610]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/030-nato-phonetic-alphabet/commit/f42e6109ac82937291e5c8207c0631f710b9da85
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
# Stakeholder Analysis
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
| Key | Value |
|
||||||
|
| --- | --- |
|
||||||
|
| ID | SA-001 |
|
||||||
|
| CrossReference | [BC-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, reviewed in RC-002 | [f42e610] |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
Identify who has a stake in the NATO alphabet project, how much power and interest each has, and what each needs from the repository. The analysis uses the power/interest grid and maps concerns to FURPS+ (Functionality, Usability, Reliability, Performance, Supportability, plus constraints).
|
||||||
|
|
||||||
|
## Stakeholder Summary Table
|
||||||
|
|
||||||
|
| ID | Name | Role/Title | Organization | Power Level | Interest Level | Quadrant | Primary Concern (Business Language) |
|
||||||
|
| --- | --- | --- | --- | --- | --- | --- | --- |
|
||||||
|
| S01 | Jens Tirsvad Nielsen | Course participant, Product Owner, developer and reviewer | Tirsvad (personal) | HIGH | HIGH | Manage Closely | A correct, complete and well-structured solution that is easy to maintain |
|
||||||
|
| S02 | Udemy coursists | Fellow course participants who share and compare solutions | Udemy 100 Days of Code community | LOW | HIGH | Keep Informed | Readable, runnable code with the assignment's function names, and README instructions to run it |
|
||||||
|
| S03 | GitHub viewers | Visitors browsing the repository for ideas | Public | LOW | MEDIUM | Keep Informed | A clear repository description, topics and README, and no runtime dependencies |
|
||||||
|
|
||||||
|
## Power/Interest Classification Rationale
|
||||||
|
|
||||||
|
- **Manage Closely (S01):** decides scope, reviews and accepts every artifact, and is the only person who talks to the other stakeholders.
|
||||||
|
- **Keep Informed (S02, S03):** they cannot change the project but are its intended readers; their needs are met through the README, the wiki and the code itself. S02 has high interest because the repository is aimed at them; S03 is a passer-by with medium interest.
|
||||||
|
|
||||||
|
## Primary Concerns and FURPS+ Mapping
|
||||||
|
|
||||||
|
| ID | Concern | FURPS+ attribute |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| S01 | Program converts words correctly, handles invalid input without crashing, and the structure follows the framework | Functionality, Supportability |
|
||||||
|
| S01 | Tests and CI give confidence | Reliability |
|
||||||
|
| S02 | Code is readable and keeps the assignment's function names | Supportability |
|
||||||
|
| S02 | The README tells how to create the `.venv` and run program and tests | Usability |
|
||||||
|
| S03 | Description, topics and README explain the repository at a glance | Usability |
|
||||||
|
| S03 | No runtime dependencies to install | Plus: implementation constraint |
|
||||||
|
|
||||||
|
## Communication Requirements
|
||||||
|
|
||||||
|
| ID | Channel | Frequency | Deliverable | Phase / Milestone |
|
||||||
|
| --- | --- | --- | --- | --- |
|
||||||
|
| S01 | Chat and pull request review | Per milestone | Pull request with review record and run summary | Every milestone |
|
||||||
|
| S02 | README and wiki | When the documentation milestone ships | Run instructions, screenshots, wiki in en, da, ms | MIL-003 |
|
||||||
|
| S03 | Repository page (description, topics, README) | Once | Description, topics, README | MIL-001, MIL-003 |
|
||||||
|
|
||||||
|
## Conflicting Interests and Mitigations
|
||||||
|
|
||||||
|
| Conflict | Stakeholders | Mitigation |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| S01 follows the lecture, which uses Pandas; S03 wants no runtime dependencies | S01, S03 | Use the standard library `csv` module; the dictionary comprehension is unchanged. Recorded in an architecture decision record (ADR) |
|
||||||
|
| The assignment's function names vs. the project's naming conventions | S02, S01 | Keep the assignment's function names in the public API; internal helpers follow the conventions |
|
||||||
|
|
||||||
|
## Traceability Analysis
|
||||||
|
|
||||||
|
### Business Goal Alignment
|
||||||
|
|
||||||
|
| Stakeholder | Concern | Business Case objective |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| S01 | Correct program with project structure | [BC-001] O1, O2 |
|
||||||
|
| S01 | Tests and CI | [BC-001] O3 |
|
||||||
|
| S02 | Readable code, run instructions | [BC-001] O1, O2, O4 |
|
||||||
|
| S03 | Presentation and no dependencies | [BC-001] O4, O5 |
|
||||||
|
|
||||||
|
## Sign-Off
|
||||||
|
|
||||||
|
Reviewer: S01 (in autonomous mode the AI acts as S01's stand-in; the review record states this).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[BC-001]: ./business-case.md
|
||||||
|
[f42e610]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/030-nato-phonetic-alphabet/commit/f42e6109ac82937291e5c8207c0631f710b9da85
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
# Use Case Diagram
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
| Key | Value |
|
||||||
|
| --- | --- |
|
||||||
|
| ID | UCD-001 |
|
||||||
|
| CrossReference | [SA-001], [BC-001], [US-001], [UC-001] |
|
||||||
|
| Language | en |
|
||||||
|
| Domain | it |
|
||||||
|
|
||||||
|
## Version History
|
||||||
|
| Date | Status | Author | Reviewer | Change | Commit |
|
||||||
|
| --- | --- | --- | --- | --- | --- |
|
||||||
|
| 2026-10-14 | Proposed | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version, adapted from the 026 NATO alphabet project | pending |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Purpose and Scope
|
||||||
|
|
||||||
|
The boundary is the NATO alphabet console tool. One actor, the User, asks the tool to spell a word. Everything outside the console program (the course platform, the git host, the wiki) is outside the boundary.
|
||||||
|
|
||||||
|
## Diagram
|
||||||
|
|
||||||
|
```plantuml
|
||||||
|
@startuml
|
||||||
|
left to right direction
|
||||||
|
actor "User" <<Actor>> as U
|
||||||
|
rectangle "NATO alphabet tool" <<System>> {
|
||||||
|
usecase "Spell a Word" as UC1
|
||||||
|
}
|
||||||
|
U --> UC1
|
||||||
|
@enduml
|
||||||
|
```
|
||||||
|
|
||||||
|
## Actor Table
|
||||||
|
|
||||||
|
| Actor | Stereotype | Stakeholder ID (SA) | Goals (use cases) |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| User | `<<Actor>>` | S01, S02 | Spell a Word |
|
||||||
|
|
||||||
|
## Use Case Table
|
||||||
|
|
||||||
|
| Use Case | Actor(s) | Goal |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Spell a Word | User | Get the NATO code word of each letter of a word, so the word can be spelled out over the phone |
|
||||||
|
|
||||||
|
## Relationships
|
||||||
|
|
||||||
|
| From | Relationship (`<<include>>` / `<<extend>>`) | To | Justification |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| None | - | None | A single use case has no include or extend relationship |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[SA-001]: ./stakeholder-analysis.md
|
||||||
|
[BC-001]: ./business-case.md
|
||||||
|
[US-001]: ./user-stories.md
|
||||||
|
[UC-001]: ./uc-001/uc.md
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
# User Story
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
| Key | Value |
|
||||||
|
| --- | --- |
|
||||||
|
| ID | US-001 |
|
||||||
|
| CrossReference | [UCD-001], [BC-001], [MIL-002] |
|
||||||
|
| Language | en |
|
||||||
|
| Domain | it |
|
||||||
|
|
||||||
|
## Version History
|
||||||
|
| Date | Status | Author | Reviewer | Change | Commit |
|
||||||
|
| --- | --- | --- | --- | --- | --- |
|
||||||
|
| 2026-10-14 | Proposed | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version, adapted from the 026 NATO alphabet project | pending |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Purpose and Scope
|
||||||
|
|
||||||
|
The epic is [MIL-002] "NATO converter": the console behaviour that turns a typed word into NATO code words.
|
||||||
|
|
||||||
|
## Story List
|
||||||
|
|
||||||
|
### US-001.01 — Spell a word
|
||||||
|
|
||||||
|
**As a** User, **I want** to type a word and see the NATO code word of each of its letters, **so that** I can spell the word clearly over the phone.
|
||||||
|
|
||||||
|
**Acceptance Criteria**
|
||||||
|
|
||||||
|
- Given the program is running, when I enter `Hello`, then it lists `Hotel`, `Echo`, `Lima`, `Lima`, `Oscar` in that order.
|
||||||
|
- Given the program is running, when I enter the same word in lower case or upper case, then the result is the same.
|
||||||
|
- Given the program is running, when I enter a word with a character that is not a letter, then the program does not crash, tells me to enter only letters of the alphabet and asks for the word again.
|
||||||
|
- Given I entered an invalid word, when I then enter a valid word, then it lists the code words of that word.
|
||||||
|
|
||||||
|
| Traces to | Size | INVEST exceptions |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| [UC-001] | fits one iteration | none |
|
||||||
|
|
||||||
|
## INVEST Check
|
||||||
|
|
||||||
|
Independent (no other story is needed), Negotiable (wording of the messages is open), Valuable (it is the whole purpose of the tool), Estimable, Small (one console interaction) and Testable (each criterion is a pytest case). No exceptions.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[UCD-001]: ./use-case-diagram.md
|
||||||
|
[BC-001]: ./business-case.md
|
||||||
|
[MIL-002]: ./milestones/mil-002-nato-converter.md
|
||||||
|
[UC-001]: ./uc-001/uc.md
|
||||||
Submodule
+1
Submodule framework added at 5afc6e3b8e
@@ -0,0 +1,67 @@
|
|||||||
|
[build-system]
|
||||||
|
requires = ["setuptools>=77"]
|
||||||
|
build-backend = "setuptools.build_meta"
|
||||||
|
|
||||||
|
[project]
|
||||||
|
name = "nato-phonetic-alphabet"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "Console tool that spells a word with the NATO phonetic alphabet and handles invalid input with exceptions (100 Days of Code, day 30)."
|
||||||
|
readme = "README.md"
|
||||||
|
requires-python = ">=3.13"
|
||||||
|
license = "AGPL-3.0-or-later"
|
||||||
|
license-files = ["LICENSE"]
|
||||||
|
authors = [{ name = "Jens Tirsvad Nielsen" }]
|
||||||
|
keywords = ["nato", "phonetic-alphabet", "exception-handling", "100-days-of-code"]
|
||||||
|
dependencies = []
|
||||||
|
|
||||||
|
[project.optional-dependencies]
|
||||||
|
dev = [
|
||||||
|
"pytest==9.1.1",
|
||||||
|
"ruff==0.17.0",
|
||||||
|
"mypy==2.4.0",
|
||||||
|
"import-linter==2.15",
|
||||||
|
]
|
||||||
|
|
||||||
|
[project.scripts]
|
||||||
|
nato-phonetic-alphabet = "nato_phonetic_alphabet.main:main"
|
||||||
|
|
||||||
|
[tool.setuptools.packages.find]
|
||||||
|
where = ["src"]
|
||||||
|
|
||||||
|
[tool.setuptools.package-data]
|
||||||
|
nato_phonetic_alphabet = ["data/*.csv"]
|
||||||
|
|
||||||
|
[tool.pytest.ini_options]
|
||||||
|
testpaths = ["tests"]
|
||||||
|
pythonpath = ["src"]
|
||||||
|
|
||||||
|
[tool.ruff]
|
||||||
|
line-length = 88
|
||||||
|
src = ["src", "tests"]
|
||||||
|
extend-exclude = ["framework", ".agents", ".claude"]
|
||||||
|
|
||||||
|
[tool.ruff.lint]
|
||||||
|
select = ["E", "F", "I", "N", "UP", "B", "D"]
|
||||||
|
|
||||||
|
[tool.ruff.lint.pydocstyle]
|
||||||
|
convention = "pep257"
|
||||||
|
|
||||||
|
[tool.ruff.lint.per-file-ignores]
|
||||||
|
"tests/**" = ["D"]
|
||||||
|
|
||||||
|
[tool.mypy]
|
||||||
|
strict = true
|
||||||
|
files = ["src", "tests"]
|
||||||
|
mypy_path = "src"
|
||||||
|
|
||||||
|
[tool.importlinter]
|
||||||
|
root_package = "nato_phonetic_alphabet"
|
||||||
|
|
||||||
|
[[tool.importlinter.contracts]]
|
||||||
|
name = "Dependencies point inward"
|
||||||
|
type = "layers"
|
||||||
|
layers = [
|
||||||
|
"nato_phonetic_alphabet.adapters",
|
||||||
|
"nato_phonetic_alphabet.application",
|
||||||
|
"nato_phonetic_alphabet.domain",
|
||||||
|
]
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
"""@brief Console tool that spells a word with the NATO phonetic alphabet.
|
||||||
|
|
||||||
|
@mainpage NATO phonetic alphabet
|
||||||
|
|
||||||
|
The Day 30 assignment of "100 Days of Code: The Complete Python Pro Bootcamp".
|
||||||
|
The tool spells a typed word with the NATO phonetic alphabet and handles input
|
||||||
|
that holds a character that is not a letter with exception handling.
|
||||||
|
"""
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
"""@brief Constants of the NATO alphabet tool.
|
||||||
|
|
||||||
|
Every literal that the program, its messages or its data loading depend on is
|
||||||
|
defined here once.
|
||||||
|
"""
|
||||||
|
|
||||||
|
## @brief Name of the package that holds the data file.
|
||||||
|
DATA_PACKAGE: str = "nato_phonetic_alphabet"
|
||||||
|
|
||||||
|
## @brief Folder inside the package that holds the data file.
|
||||||
|
DATA_DIRECTORY: str = "data"
|
||||||
|
|
||||||
|
## @brief Name of the comma-separated values file with the NATO alphabet.
|
||||||
|
DATA_FILE_NAME: str = "nato_phonetic_alphabet.csv"
|
||||||
|
|
||||||
|
## @brief Header of the column with the letter in the data file.
|
||||||
|
LETTER_COLUMN: str = "letter"
|
||||||
|
|
||||||
|
## @brief Header of the column with the code word in the data file.
|
||||||
|
CODE_COLUMN: str = "code"
|
||||||
|
|
||||||
|
## @brief Text shown when the program asks for a word.
|
||||||
|
PROMPT_TEXT: str = "Enter a word: "
|
||||||
|
|
||||||
|
## @brief Text shown when the word holds a character that is not a letter.
|
||||||
|
INVALID_INPUT_TEXT: str = "Sorry, only the letters A to Z are allowed. Try again."
|
||||||
|
|
||||||
|
## @brief Text shown before the code words are printed.
|
||||||
|
RESULT_TEXT: str = "Phonetic code words:"
|
||||||
|
|
||||||
|
## @brief Text encoding of the data file.
|
||||||
|
DATA_ENCODING: str = "utf-8"
|
||||||
|
|
||||||
|
## @brief Exit status of a session that ended normally.
|
||||||
|
EXIT_OK: int = 0
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
letter,code
|
||||||
|
A,Alfa
|
||||||
|
B,Bravo
|
||||||
|
C,Charlie
|
||||||
|
D,Delta
|
||||||
|
E,Echo
|
||||||
|
F,Foxtrot
|
||||||
|
G,Golf
|
||||||
|
H,Hotel
|
||||||
|
I,India
|
||||||
|
J,Juliet
|
||||||
|
K,Kilo
|
||||||
|
L,Lima
|
||||||
|
M,Mike
|
||||||
|
N,November
|
||||||
|
O,Oscar
|
||||||
|
P,Papa
|
||||||
|
Q,Quebec
|
||||||
|
R,Romeo
|
||||||
|
S,Sierra
|
||||||
|
T,Tango
|
||||||
|
U,Uniform
|
||||||
|
V,Victor
|
||||||
|
W,Whiskey
|
||||||
|
X,X-ray
|
||||||
|
Y,Yankee
|
||||||
|
Z,Zulu
|
||||||
|
@@ -0,0 +1,29 @@
|
|||||||
|
"""Smoke tests of the package skeleton."""
|
||||||
|
|
||||||
|
from importlib import resources
|
||||||
|
|
||||||
|
from nato_phonetic_alphabet import constants
|
||||||
|
|
||||||
|
EXPECTED_ROW_COUNT = 26
|
||||||
|
|
||||||
|
|
||||||
|
def test_data_file_exists_in_package() -> None:
|
||||||
|
data_file = (
|
||||||
|
resources.files(constants.DATA_PACKAGE)
|
||||||
|
/ constants.DATA_DIRECTORY
|
||||||
|
/ constants.DATA_FILE_NAME
|
||||||
|
)
|
||||||
|
|
||||||
|
assert data_file.is_file()
|
||||||
|
|
||||||
|
|
||||||
|
def test_data_file_has_one_row_per_letter() -> None:
|
||||||
|
data_file = (
|
||||||
|
resources.files(constants.DATA_PACKAGE)
|
||||||
|
/ constants.DATA_DIRECTORY
|
||||||
|
/ constants.DATA_FILE_NAME
|
||||||
|
)
|
||||||
|
|
||||||
|
lines = data_file.read_text(encoding="utf-8").splitlines()
|
||||||
|
|
||||||
|
assert len(lines) - 1 == EXPECTED_ROW_COUNT
|
||||||
Reference in New Issue
Block a user