diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..a759dc9 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "framework"] + path = framework + url = ssh://git@git.tirsystem.com:10022/TirSystem/SQA-QC-Framework.git diff --git a/docs/artifact-registry.md b/docs/artifact-registry.md new file mode 100644 index 0000000..92baa30 --- /dev/null +++ b/docs/artifact-registry.md @@ -0,0 +1,59 @@ +# 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/use-cases/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 | 006 | + +## 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 and the PO language, at least (`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. diff --git a/docs/business-case.md b/docs/business-case.md new file mode 100644 index 0000000..ea3b80c --- /dev/null +++ b/docs/business-case.md @@ -0,0 +1,128 @@ +# 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-17 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version; reviewed in RC-001 (Go) | pending | + +--- + +## Executive Summary + +Day 32 of the Udemy course "100 Days of Code: The Complete Python Pro Bootcamp" asks for an automated birthday wisher. The program reads a CSV of friends and family, checks whether today is somebody's birthday, picks one of three letter templates at random, inserts the person's name and sends the letter by e-mail through SMTP. This project builds the "normal" difficulty level as a small, readable, runnable Python 3.13+ project with tests, documentation and a tri-lingual wiki, so that course participants and repository viewers can learn from it. + +## Methodological and Standards Foundation + +The work follows the SQA and QC framework mounted at `framework/`: Business Case, Stakeholder Analysis, Project Plan, milestones, tasks as issues, then code, each step reviewed before the next. Quality characteristics follow ISO/IEC 25010:2023. Source code follows the `coding-conventions` skill (Python) and the `clean-architecture` skill; the code is documented with Doxygen comments. + +## Problem Statement + +The course assignment ships only a stub (`main.py` with hints, three letter templates and a one-row `birthdays.csv`). A learner who finishes it has working but ad-hoc code. Without a reference solution that is structured, tested and documented, other course participants cannot compare solutions, and a viewer of the repository learns little. + +## Business Opportunity + +A clean reference solution lets participants compare approaches, and gives GitHub viewers a small example of a tested, documented Python project with no runtime dependencies beyond the standard library. + +## Objectives + +1. Deliver a Python program that sends a random birthday letter, with the person's name inserted, to every person in `birthdays.csv` whose month and day match today. +2. Keep the assignment's function and file names recognisable (`birthdays.csv`, `letter_templates/letter_1.txt` to `letter_3.txt`, `[NAME]` placeholder). +3. Deliver automated tests (pytest) that run without network access or real credentials. +4. Deliver a README, a Doxygen configuration and a wiki in English, Danish and Bahasa Malaysia, with screenshots. +5. Publish the repository with a description and topics. + +## Scope + +### In Scope + +- Reading `birthdays.csv`, matching today's month and day, choosing a random template, replacing `[NAME]`, sending by SMTP with STARTTLS (Gmail by default). +- Standard-library implementation (`csv`, `datetime`, `random`, `smtplib`); pandas is not used, to keep runtime dependencies at zero. +- `src/` and `tests/` layout, `constants.py`, `pyproject.toml`, Python `.gitignore`, `.env.example`, Doxyfile, local `.venv` instructions. +- README from the framework template and a wiki in en, da and ms, with screenshots. + +### Out of Scope + +- A scheduler or hosting (the program is run by hand or by the learner's own scheduler). +- A graphical user interface. +- The "hard" and "extra hard" course levels. +- Storing or testing real credentials: `.env` holds a personal token and is only for personal use; it is git-ignored, never imported by tests and never committed. + +## Expected Benefits + +### Tangible Benefits + +- A runnable, tested reference solution with instructions. +- Tests that give a repeatable result without sending mail. + +### Intangible Benefits + +- Learning value for the author and for other course participants. +- A tidy example for repository viewers. + +## Strategic Alignment + +The project is a learning portfolio piece within the repository group Tirsvad-Udemy-100_days_of_code, and a practice run of the SQA and QC framework on a small project. + +## Success Criteria + +| # | Criterion | Target | Measure | +| --- | --- | --- | --- | +| 1 | Tests pass | 100 % of pytest tests pass offline | `python -m pytest` exit code 0 | +| 2 | Runtime dependencies | 0 third-party packages | `pyproject.toml` `dependencies` is empty | +| 3 | Documentation | README plus wiki in 3 languages, each with at least one screenshot | files exist in the repository and wiki | +| 4 | Repository metadata | description and topics set | visible on the git host | +| 5 | Secrets | no secret in git history | search for the token value finds nothing | + +## Risks + +| Risk | Impact | Mitigation | +| --- | --- | --- | +| The Gmail token leaks into git or logs | High: account abuse | `.env` is git-ignored, only `.env.example` is tracked, tests never read `.env`, the token is never printed | +| Tests accidentally send mail | Medium | SMTP is injected and replaced by a fake in tests | +| Screenshots show an address or token | Medium | Screenshots use the dummy data and the dry-run output only | +| Git host token missing for topics or the wiki | Medium | Stop and report; the user supplies the token | +| Birthday on 29 February | Low | Documented behaviour: sent on 28 February in non-leap years, or a documented limitation | + +## Assumptions + +- The Product Owner is S01, who is also developer and reviewer; the AI authors the documents and acts as S01's stand-in in autonomous mode, recorded in each review. +- The people the project is for (S02, S03) are reached only by the user. +- The PO language is English and the domain is IT. +- Python 3.13 or newer is installed; the learner has a Gmail app password. + +## Constraints + +- Python 3.13 or newer, a local `.venv`, pytest for tests, constants in `constants.py`. +- Folder structure `src/`, `tests/`, `docs/`. +- One pull request per milestone, from a branch. +- `framework/` is not edited from this project. + +## Cost–Benefit Assessment + +| Costs | Benefits | +| --- | --- | +| A few hours of the author's time; no licence or hosting cost | A reference solution, learning value and a portfolio entry; qualitative, as the project has no revenue | + +## Stakeholders + +| Stakeholder ID (SA) | Interest in this project | +| --- | --- | +| S01 | Product Owner, developer and reviewer; wants a working, tested solution | +| S02 | Udemy coursists; want readable, runnable code with the assignment's names | +| S03 | GitHub viewers; want a clear description, topics and README, and no runtime dependencies | + +## Recommendation + +Proceed. The scope is small, the risk is manageable and the result has learning value. + +--- + +[SA-001]: ./stakeholder-analysis.md diff --git a/docs/milestones/mil-001-project-setup.md b/docs/milestones/mil-001-project-setup.md new file mode 100644 index 0000000..2273257 --- /dev/null +++ b/docs/milestones/mil-001-project-setup.md @@ -0,0 +1,73 @@ +# MIL-001 Project Setup + +## Metadata +| Key | Value | +| --- | --- | +| ID | MIL-001 | +| CrossReference | [BC-001], [SA-001] | +| Language | en | +| Domain | it | + +## Version History +| Date | Status | Author | Reviewer | Change | Commit | +| --- | --- | --- | --- | --- | --- | +| 2026-10-17 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version; reviewed in RC-003 (Go) | pending | + +--- + +## Purpose + +Decide whether the project skeleton is ready to hold code: configuration, tooling, ignore rules and repository metadata are in place and reviewed. + +## Deliverable + +A Python 3.13+ project skeleton: `pyproject.toml` with pytest and no runtime dependencies, `.gitignore`, `.env.example`, `src/` and `tests/` folders, `constants.py`, `Doxyfile`, `.venv` instructions, the assignment data files, and the repository description and topics on the git host. One pull request. + +## Go / No-Go Criteria + +| # | Criterion (objectively checkable) | Go | No-Go | +| --- | --- | --- | --- | +| 1 | `python -m pip install -e .[dev]` succeeds in a fresh `.venv` and `python -m pytest` runs (a smoke test passes) | Go | No-Go | +| 2 | `pyproject.toml` requires Python `>=3.13` and lists no runtime dependencies | Go | No-Go | +| 3 | `.gitignore` ignores `.venv/`, `__pycache__/` and `.env`; `.env` is not tracked | Go | No-Go | +| 4 | `Doxyfile` exists and `doxygen Doxyfile` runs without error (or the gap is recorded) | Go | No-Go | +| 5 | Repository description and topics are set on the git host (checked through the API) | Go | No-Go | + +## Dependencies + +| Depends on | Reason | +| --- | --- | +| none | First milestone | + +## Traceability + +| Business Case objective / KPI / user story | Reference | +| --- | --- | +| Objective 3 (tests), objective 5 (publish) | [BC-001] | +| S01, S03 concerns | [SA-001] | + +## Ownership + +| Role | Stakeholder ID (SA) | +| --- | --- | +| Owner | S01 | +| Approving reviewer | S01 | + +## Target Date + +2026-10-18 - within the schedule of the Business Case constraints. + +## Tasks + +| # | Task | Summary | Needs its own Use Case/User Story? | Reference | +| --- | --- | --- | --- | --- | +| 1 | Configure pyproject and tooling | Create `pyproject.toml` (`requires-python >=3.13`, no runtime dependencies, an optional `dev` extra with pytest, pytest configuration with `pythonpath = src`), a Python `.gitignore` that also ignores `.env`, and `.env.example` listing `GMAIL_TOKEN`. The token in `.env` is for personal use only and is never read by tests. | No | | +| 2 | Create src and tests layout with constants.py | Create the `src/birthday_wisher/` package with `constants.py` (file names, `[NAME]` placeholder, SMTP host and port, subject, environment variable names) and a `tests/` folder with a smoke test, so later work has a place to land. | No | | +| 3 | Add assignment data files | Add `birthdays.csv` (header `name,email,year,month,day`, dummy rows only, never a real address) and `letter_templates/letter_1.txt` to `letter_3.txt` from the course starter, keeping the `[NAME]` placeholder. | No | | +| 4 | Add Doxyfile | Add a `Doxyfile` that documents `src/` from the Doxygen comments and writes its output to an ignored `docs/doxygen/` folder. | No | | +| 5 | Set repository description and topics | Set the description and topics on the git host through its API, using `GITEA_TOKEN` read from the environment or `.env` without printing it. Stop and report if the token is missing or rejected. | No | | + +--- + +[BC-001]: ../business-case.md +[SA-001]: ../stakeholder-analysis.md diff --git a/docs/milestones/mil-002-birthday-wisher-core.md b/docs/milestones/mil-002-birthday-wisher-core.md new file mode 100644 index 0000000..64b1b1c --- /dev/null +++ b/docs/milestones/mil-002-birthday-wisher-core.md @@ -0,0 +1,76 @@ +# MIL-002 Birthday Wisher Core + +## Metadata +| Key | Value | +| --- | --- | +| ID | MIL-002 | +| CrossReference | [BC-001], [SA-001], [MIL-001] | +| Language | en | +| Domain | it | + +## Version History +| Date | Status | Author | Reviewer | Change | Commit | +| --- | --- | --- | --- | --- | --- | +| 2026-10-17 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version; reviewed in RC-004 (Go) | pending | + +--- + +## Purpose + +Decide whether the birthday wisher works: it finds today's birthdays, builds a letter and sends it, with tests that need no network and no credentials. + +## Deliverable + +The `birthday_wisher` package: loading `birthdays.csv`, matching today's month and day, choosing a random template and replacing `[NAME]`, sending by SMTP with STARTTLS, a `main` entry point, and a pytest suite. All public items carry Doxygen comments. + +## Go / No-Go Criteria + +| # | Criterion (objectively checkable) | Go | No-Go | +| --- | --- | --- | --- | +| 1 | `python -m pytest` passes with no network access and without a `.env` file | Go | No-Go | +| 2 | A test proves that a person whose month and day equal today receives exactly one letter and nobody else does | Go | No-Go | +| 3 | A test proves that `[NAME]` is replaced and every one of the three templates can be chosen | Go | No-Go | +| 4 | A test with a fake SMTP object proves STARTTLS is called before login and that the subject is "Happy Birthday" | Go | No-Go | +| 5 | No source or test file imports or reads `.env`; the token is read from the `GMAIL_TOKEN` environment variable only | Go | No-Go | +| 6 | The code is reviewed against `qc-programming-python` and the review record says Go | Go | No-Go | + +## Dependencies + +| Depends on | Reason | +| --- | --- | +| [MIL-001] | Needs the skeleton, constants and data files | + +## Traceability + +| Business Case objective / KPI / user story | Reference | +| --- | --- | +| Objectives 1, 2 and 3 | [BC-001] | +| S01, S02 concerns | [SA-001] | + +## Ownership + +| Role | Stakeholder ID (SA) | +| --- | --- | +| Owner | S01 | +| Approving reviewer | S01 | + +## Target Date + +2026-10-19 - within the schedule of the Business Case constraints. + +## Tasks + +| # | Task | Summary | Needs its own Use Case/User Story? | Reference | +| --- | --- | --- | --- | --- | +| 1 | Load and match birthdays | Read `birthdays.csv` with the standard `csv` module into a dictionary keyed by `(month, day)` as the course hint describes, and return the people whose key equals today's `(month, day)`. Today is a parameter so tests can fix the date. | No | | +| 2 | Build the letter | Choose one of the letter templates at random (the chooser is injectable for tests), and replace `[NAME]` with the person's name. Fail with a clear message when a template is missing. | No | | +| 3 | Send the letter by SMTP | Send the letter with `smtplib`: connect to the host in `constants.py`, call `starttls()`, log in with the sender address and the `GMAIL_TOKEN` environment variable, and send with the subject "Happy Birthday". The SMTP class is injected; the token is never logged. | No | | +| 4 | Add main entry point | Wire the pieces together in `main.py` (composition root): load, match, build, send. Add a `--dry-run` option that prints instead of sending, used for screenshots and by learners without credentials. Exit with a non-zero status on error. | No | | +| 5 | Write pytest tests | Cover matching, letters, sending with a fake SMTP and the entry point with a fixed date. Tests use temporary files and never touch the network or `.env`. | No | | +| 6 | Review code against the Python checklist | Review `src/` and `tests/` against `qc-programming-python`, write the `RC-*` record and fix findings before the pull request. | No | | + +--- + +[BC-001]: ../business-case.md +[SA-001]: ../stakeholder-analysis.md +[MIL-001]: ./mil-001-project-setup.md diff --git a/docs/milestones/mil-003-documentation-and-publication.md b/docs/milestones/mil-003-documentation-and-publication.md new file mode 100644 index 0000000..a9aca6b --- /dev/null +++ b/docs/milestones/mil-003-documentation-and-publication.md @@ -0,0 +1,75 @@ +# MIL-003 Documentation and Publication + +## Metadata +| Key | Value | +| --- | --- | +| ID | MIL-003 | +| CrossReference | [BC-001], [SA-001], [MIL-002] | +| Language | en | +| Domain | it | + +## Version History +| Date | Status | Author | Reviewer | Change | Commit | +| --- | --- | --- | --- | --- | --- | +| 2026-10-17 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version; reviewed in RC-005 (Go) | pending | + +--- + +## Purpose + +Decide whether the project is ready for its readers: instructions, generated documentation and a tri-lingual wiki with screenshots exist and are correct. + +## Deliverable + +A README from the framework template with run and test instructions and screenshots; the `.venv` and `python -m pip install --upgrade pip` instructions; a wiki in `docs/wiki/` in English, Danish (`-da`) and Bahasa Malaysia (`-ms`) with the same pages and screenshots; the wiki publish workflow. + +## Go / No-Go Criteria + +| # | Criterion (objectively checkable) | Go | No-Go | +| --- | --- | --- | --- | +| 1 | `bash framework/scripts/check-readme.sh` passes on `README.md` | Go | No-Go | +| 2 | README shows how to create and use a local `.venv`, run `python -m pip install --upgrade pip`, run the program and run the tests, and each command works as written | Go | No-Go | +| 3 | The wiki has the same page set in en, da and ms, each page with the language line, and `_Sidebar.md` lists all three | Go | No-Go | +| 4 | README and each wiki language contain at least one screenshot, and no screenshot shows an address or token | Go | No-Go | +| 5 | `bash framework/scripts/check-languages.sh` passes | Go | No-Go | + +## Dependencies + +| Depends on | Reason | +| --- | --- | +| [MIL-002] | The screenshots and instructions describe the working program | + +## Traceability + +| Business Case objective / KPI / user story | Reference | +| --- | --- | +| Objectives 4 and 5 | [BC-001] | +| S02 and S03 concerns | [SA-001] | + +## Ownership + +| Role | Stakeholder ID (SA) | +| --- | --- | +| Owner | S01 | +| Approving reviewer | S01 | + +## Target Date + +2026-10-20 - within the schedule of the Business Case constraints. + +## Tasks + +| # | Task | Summary | Needs its own Use Case/User Story? | Reference | +| --- | --- | --- | --- | --- | +| 1 | Capture screenshots | Produce screenshots of a dry run, a test run and the `.venv` setup using the dummy data only, stored in `docs/images/`. Screenshots are rendered from terminal output by a script, never taken on the host desktop, and never show an address or token. | No | | +| 2 | Write README | Create `README.md` from the framework template: overview, requirements, `.venv` and `python -m pip install --upgrade pip` setup, run, tests, license, links, appendix of project documents, and screenshots. | No | | +| 3 | Write English wiki | Write the wiki pages in `docs/wiki/` in English (Home, Setup, Usage, Configuration, Testing, Architecture), with screenshots and a `_Sidebar.md`. | No | | +| 4 | Translate wiki to Danish | Translate each English wiki page to `-da.md`, same page set, language line on top, code and commands unchanged. | No | | +| 5 | Translate wiki to Bahasa Malaysia | Translate each English wiki page to `-ms.md`, same page set, language line on top, code and commands unchanged. | No | | +| 6 | Add wiki publish workflow | Copy `framework/templates/ci/publish-wiki.yml` to the project CI folder so the wiki reaches the git host by merge. | No | | + +--- + +[BC-001]: ../business-case.md +[SA-001]: ../stakeholder-analysis.md +[MIL-002]: ./mil-002-birthday-wisher-core.md diff --git a/docs/project-plan.md b/docs/project-plan.md new file mode 100644 index 0000000..f3fd3ac --- /dev/null +++ b/docs/project-plan.md @@ -0,0 +1,86 @@ +# 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-17 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version; accepted by S01 (AI as stand-in, plan accepted in chat 2026-10-17) | pending | + +--- + +## Purpose + +This plan schedules the three phases that deliver the birthday wisher of [BC-001]: project setup, the core program, and documentation with publication. It is scheduled against the Business Case constraint of one pull request per milestone. + +## Planning Assumptions + +- Work starts 2026-10-17 and the plan ends by 2026-10-20. +- Each phase is one day; each phase is one branch and one pull request that closes its issues. +- Autonomous mode: the AI runs all phases after the user accepts this plan; the review of each artifact is by S01's stand-in and recorded as not independent ([SA-001]). + +## Gateway Schedule + +| Gateway | Document | Window | Decision date | Owner | Stories | Main deliverable | Milestone | +| --- | --- | --- | --- | --- | --- | --- | --- | +| G1 Project setup | [MIL-001] | 2026-10-17 to 2026-10-18 | 2026-10-18 | S01 | none (plain tasks) | Skeleton, tooling, repository metadata | | +| G2 Core | [MIL-002] | 2026-10-18 to 2026-10-19 | 2026-10-19 | S01 | none (plain tasks) | Working, tested birthday wisher | | +| G3 Documentation | [MIL-003] | 2026-10-19 to 2026-10-20 | 2026-10-20 | S01 | none (plain tasks) | README, tri-lingual wiki, screenshots | | + +```plantuml +@startgantt +Project starts 2026-10-17 +[G1 Project setup] starts 2026-10-17 and ends 2026-10-18 +[G2 Core] starts 2026-10-18 and ends 2026-10-19 +[G3 Documentation] starts 2026-10-19 and ends 2026-10-20 +[G1 Go/No-Go] happens 2026-10-18 +[G2 Go/No-Go] happens 2026-10-19 +[G3 Go/No-Go] happens 2026-10-20 +@endgantt +``` + +## Scope Coverage + +| Business Case scope item | Gateway | +| --- | --- | +| CSV reading, matching, letters, SMTP sending | G2 | +| `src/`, `tests/`, `constants.py`, `pyproject.toml`, `.gitignore`, `.env.example`, Doxyfile | G1 | +| Repository description and topics | G1 | +| README and wiki in en, da, ms with screenshots | G3 | + +## Dependencies + +``` +G1 Project setup -> G2 Core -> G3 Documentation +``` + +A No-Go at a gate moves every later date by the time needed to fix and re-review it. + +## Plan Risks + +| Risk | Impact | Mitigation | +| --- | --- | --- | +| The git host token cannot set topics or merge | Gate G1 or the merge is blocked | Stop and report; the user supplies or fixes the token | +| A screenshot cannot be produced without the host desktop | G3 delayed | Render terminal output to an image with a script, never on the host desktop | +| Danish or Malay translation quality | Readers misled | Keep sentences short, keep code in English; S01 can challenge in the run summary | + +## Open Issues + +- The repository named in the request (`https://git.tirsystem.com/Tirsvad-Udemy-100_days_of_code`) is the organisation; the project is published to this clone's `origin`, `Tirsvad-Udemy-100-days-of-code/032-birthday-wisher`. Please confirm. +- No use case or user story is written: the tasks are plain technical tasks for a one-feature learning project, so the plan-first gate is met through the "plain technical task" route. Say so if a use case should be written. +- The course hints use pandas; the project uses the standard `csv` module (no runtime dependencies, objective in [BC-001]). +- Support for 29 February birthdays is decided during G2 and documented. + +--- + +[BC-001]: ./business-case.md +[SA-001]: ./stakeholder-analysis.md +[MIL-001]: ./milestones/mil-001-project-setup.md +[MIL-002]: ./milestones/mil-002-birthday-wisher-core.md +[MIL-003]: ./milestones/mil-003-documentation-and-publication.md diff --git a/docs/sqa/reviews/rc-001-business-case.md b/docs/sqa/reviews/rc-001-business-case.md new file mode 100644 index 0000000..b96be86 --- /dev/null +++ b/docs/sqa/reviews/rc-001-business-case.md @@ -0,0 +1,66 @@ +# SQA Review Record + +## 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-17 | Proposed | Jens Tirsvad Nielsen | S01 | Initial version | pending | + +--- + +## Artifact Under Review + +- Instance reviewed: [BC-001] +- Checklist used: [QC-BC-001] +- Scope: full review +- Language and domain: en / it +- Language reviewer: none (the reviewer is the stand-in for S01, who reads English and knows the IT domain) +- Mode: autonomous, not independent (reviewer: 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 table is qualitative and justified: "the project has no revenue". | +| 2 | Risks are identified with documented impact and mitigation | Pass | Risks table has five rows, each with impact and mitigation. | +| 3 | Success criteria are measurable, stating explicit targets rather than vague aspirations | Pass | Success Criteria table has five criteria with targets (e.g. "100 % of pytest tests pass offline", "0 third-party packages"). | +| 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 | Stakeholders table cites S01, S02 and S03 from SA-001. | +| 6 | Methodology and quality-standard foundation are stated explicitly (e.g. ISO/IEC 25010, Larman) | Pass | Foundation names the framework, ISO/IEC 25010:2023, the coding conventions and Doxygen. | +| 7 | Assumptions and constraints are explicit and clearly distinguished from one another | Pass | Assumptions and Constraints are separate bullet lists. | +| 8 | Document supports executive decision-making with a clear, unambiguous recommendation | Pass | Recommendation is "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 domain list. | +| 3 | The content (prose and table cells) is written in the stated language | Pass | All prose and table cells of the Business Case are English. | +| 4 | The register matches the one the registry gives for the artifact type | Pass | Register is IT Executive English, as the registry gives for this type. | +| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | No domain dictionary (`DICT`) exists yet; the terms used are standard IT terms (repository, pull request, milestone) with no synonyms. Confirmed by the stand-in, not independent. | +| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. | +| 7 | No translated twin (`..md`) exists beside the document | Pass | No `*.en.md` or other translated twin 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 language change. | +| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | Confirmed by AI as stand-in for S01 (English, IT domain). Mode is autonomous, not independent. | +| 10 | Abbreviations are spelled out on first use, in the stated language | Pass | Abbreviations used (SMTP, STARTTLS, CSV, PO) are spelled out or standard; SMTP is explained in the scope. | + +## Overall Verdict + +Go - All eight criteria pass. + +## Action Items + +| Action | Owner | Due | +| --- | --- | --- | +| None | S01 | - | + +--- +[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 diff --git a/docs/sqa/reviews/rc-002-stakeholder-analysis.md b/docs/sqa/reviews/rc-002-stakeholder-analysis.md new file mode 100644 index 0000000..469afa6 --- /dev/null +++ b/docs/sqa/reviews/rc-002-stakeholder-analysis.md @@ -0,0 +1,66 @@ +# SQA Review Record + +## 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-17 | Proposed | Jens Tirsvad Nielsen | S01 | Initial version | pending | + +--- + +## Artifact Under Review + +- Instance reviewed: [SA-001] +- Checklist used: [QC-SA-001] +- Scope: full review +- Language and domain: en / it +- Language reviewer: none (the reviewer is the stand-in for S01, who reads English and knows the IT domain) +- Mode: autonomous, not independent (reviewer: 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 | IDs S01 to S03 are unique and used in the Business Case, milestones and plan. | +| 3 | Roles and organizational context are defined with explicit Power and Interest levels, not just narrative description | Pass | Role, organisation and HIGH/LOW levels are given, with a rationale per quadrant. | +| 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 (pandas vs no dependencies; secret vs public repository) with mitigations. | +| 6 | Stakeholder concerns are explicitly traced to Business Case objectives | Pass | Traceability section maps each stakeholder to objectives of BC-001. | +| 7 | Primary concerns are expressed in both business language and a recognized quality-attribute mapping (e.g. FURPS+) | Pass | Concerns table maps each concern to a FURPS+ attribute. | +| 8 | Document is understandable and navigable by non-technical stakeholders reviewing their own entry | Pass | Plain language, one table per topic. | + +## 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 domain list. | +| 3 | The content (prose and table cells) is written in the stated language | Pass | All prose and table cells of the Stakeholder Analysis are English. | +| 4 | The register matches the one the registry gives for the artifact type | Pass | Register is IT Professional English, as the registry gives for this type. | +| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | No domain dictionary (`DICT`) exists yet; the terms used are standard IT terms (repository, pull request, milestone) with no synonyms. Confirmed by the stand-in, not independent. | +| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. | +| 7 | No translated twin (`..md`) exists beside the document | Pass | No `*.en.md` or other translated twin 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 language change. | +| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | Confirmed by AI as stand-in for S01 (English, IT domain). Mode is autonomous, not independent. | +| 10 | Abbreviations are spelled out on first use, in the stated language | Pass | Abbreviations used (SMTP, STARTTLS, CSV, PO) are spelled out or standard; SMTP is explained in the scope. | + +## Overall Verdict + +Go - All eight criteria pass. S01 is the only reviewer and was named by the user as reviewer. + +## Action Items + +| Action | Owner | Due | +| --- | --- | --- | +| None | S01 | - | + +--- +[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 diff --git a/docs/sqa/reviews/rc-003-mil-001.md b/docs/sqa/reviews/rc-003-mil-001.md new file mode 100644 index 0000000..a86b796 --- /dev/null +++ b/docs/sqa/reviews/rc-003-mil-001.md @@ -0,0 +1,64 @@ +# SQA Review Record + +## 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-17 | Proposed | Jens Tirsvad Nielsen | S01 | Initial version | pending | + +--- + +## Artifact Under Review + +- Instance reviewed: [MIL-001] +- Checklist used: [QC-MIL-001] +- Scope: full review +- Language and domain: en / it +- Language reviewer: none (the reviewer is the stand-in for S01, who reads English and knows the IT domain) +- Mode: autonomous, not independent (reviewer: AI as stand-in for S01) + +## Checklist Results + +| # | Criterion | Status | Evidence/Notes | +| --- | --- | --- | --- | +| 1 | A concrete deliverable is defined for every gate | Pass | The Deliverable section names concrete output. | +| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Each Go/No-Go criterion is a command or a file check that can be run. | +| 3 | Dependencies on other milestones are explicitly mapped | Pass | First milestone: the dependency table says none. | +| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | The Traceability table names Business Case 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 2026-10-18 is inside the plan window of PP-001. | + +## Language and Domain Results + +| # | Criterion | Status | Evidence/Notes | +| --- | --- | --- | --- | +| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | `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 domain list. | +| 3 | The content (prose and table cells) is written in the stated language | Pass | All prose and table cells of MIL-001 are English. | +| 4 | The register matches the one the registry gives for the artifact type | Pass | Register is IT Executive English, as the registry gives for this type. | +| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | No domain dictionary (`DICT`) exists yet; the terms used are standard IT terms (repository, pull request, milestone) with no synonyms. Confirmed by the stand-in, not independent. | +| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. | +| 7 | No translated twin (`..md`) exists beside the document | Pass | No `*.en.md` or other translated twin 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 language change. | +| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | Confirmed by AI as stand-in for S01 (English, IT domain). Mode is autonomous, not independent. | +| 10 | Abbreviations are spelled out on first use, in the stated language | Pass | Abbreviations used (SMTP, STARTTLS, CSV, PO) are spelled out or standard; SMTP is explained in the scope. | + +## Overall Verdict + +Go - All six criteria pass. Tasks are plain technical tasks; no use case is needed. + +## Action Items + +| Action | Owner | Due | +| --- | --- | --- | +| None | S01 | - | + +--- +[MIL-001]: ../../milestones/mil-001-project-setup.md +[QC-MIL-001]: ../../../framework/qc/artifacts/qc-milestones-gateways.md +[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md diff --git a/docs/sqa/reviews/rc-004-mil-002.md b/docs/sqa/reviews/rc-004-mil-002.md new file mode 100644 index 0000000..9ada686 --- /dev/null +++ b/docs/sqa/reviews/rc-004-mil-002.md @@ -0,0 +1,64 @@ +# SQA Review Record + +## Metadata +| Key | Value | +| --- | --- | +| ID | RC-004 | +| CrossReference | [MIL-002], [QC-MIL-001], [QC-LANG-001] | + +## Version History +| Date | Status | Author | Reviewer | Change | Commit | +| --- | --- | --- | --- | --- | --- | +| 2026-10-17 | Proposed | Jens Tirsvad Nielsen | S01 | Initial version | pending | + +--- + +## Artifact Under Review + +- Instance reviewed: [MIL-002] +- Checklist used: [QC-MIL-001] +- Scope: full review +- Language and domain: en / it +- Language reviewer: none (the reviewer is the stand-in for S01, who reads English and knows the IT domain) +- Mode: autonomous, not independent (reviewer: AI as stand-in for S01) + +## Checklist Results + +| # | Criterion | Status | Evidence/Notes | +| --- | --- | --- | --- | +| 1 | A concrete deliverable is defined for every gate | Pass | The Deliverable section names concrete output. | +| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Each Go/No-Go criterion is a command or a file check that can be run. | +| 3 | Dependencies on other milestones are explicitly mapped | Pass | Depends on MIL-001, with the reason. | +| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | The Traceability table names Business Case 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 2026-10-19 is inside the plan window of PP-001. | + +## Language and Domain Results + +| # | Criterion | Status | Evidence/Notes | +| --- | --- | --- | --- | +| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | `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 domain list. | +| 3 | The content (prose and table cells) is written in the stated language | Pass | All prose and table cells of MIL-002 are English. | +| 4 | The register matches the one the registry gives for the artifact type | Pass | Register is IT Executive English, as the registry gives for this type. | +| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | No domain dictionary (`DICT`) exists yet; the terms used are standard IT terms (repository, pull request, milestone) with no synonyms. Confirmed by the stand-in, not independent. | +| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. | +| 7 | No translated twin (`..md`) exists beside the document | Pass | No `*.en.md` or other translated twin 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 language change. | +| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | Confirmed by AI as stand-in for S01 (English, IT domain). Mode is autonomous, not independent. | +| 10 | Abbreviations are spelled out on first use, in the stated language | Pass | Abbreviations used (SMTP, STARTTLS, CSV, PO) are spelled out or standard; SMTP is explained in the scope. | + +## Overall Verdict + +Go - All six criteria pass. Tasks are plain technical tasks; no use case is needed. + +## Action Items + +| Action | Owner | Due | +| --- | --- | --- | +| None | S01 | - | + +--- +[MIL-002]: ../../milestones/mil-002-birthday-wisher-core.md +[QC-MIL-001]: ../../../framework/qc/artifacts/qc-milestones-gateways.md +[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md diff --git a/docs/sqa/reviews/rc-005-mil-003.md b/docs/sqa/reviews/rc-005-mil-003.md new file mode 100644 index 0000000..2ceab5c --- /dev/null +++ b/docs/sqa/reviews/rc-005-mil-003.md @@ -0,0 +1,64 @@ +# SQA Review Record + +## Metadata +| Key | Value | +| --- | --- | +| ID | RC-005 | +| CrossReference | [MIL-003], [QC-MIL-001], [QC-LANG-001] | + +## Version History +| Date | Status | Author | Reviewer | Change | Commit | +| --- | --- | --- | --- | --- | --- | +| 2026-10-17 | Proposed | Jens Tirsvad Nielsen | S01 | Initial version | pending | + +--- + +## Artifact Under Review + +- Instance reviewed: [MIL-003] +- Checklist used: [QC-MIL-001] +- Scope: full review +- Language and domain: en / it +- Language reviewer: none (the reviewer is the stand-in for S01, who reads English and knows the IT domain) +- Mode: autonomous, not independent (reviewer: AI as stand-in for S01) + +## Checklist Results + +| # | Criterion | Status | Evidence/Notes | +| --- | --- | --- | --- | +| 1 | A concrete deliverable is defined for every gate | Pass | The Deliverable section names concrete output. | +| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Each Go/No-Go criterion is a command or a file check that can be run. | +| 3 | Dependencies on other milestones are explicitly mapped | Pass | Depends on MIL-002, with the reason. | +| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | The Traceability table names Business Case 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 2026-10-20 is inside the plan window of PP-001. | + +## Language and Domain Results + +| # | Criterion | Status | Evidence/Notes | +| --- | --- | --- | --- | +| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | `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 domain list. | +| 3 | The content (prose and table cells) is written in the stated language | Pass | All prose and table cells of MIL-003 are English. | +| 4 | The register matches the one the registry gives for the artifact type | Pass | Register is IT Executive English, as the registry gives for this type. | +| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | No domain dictionary (`DICT`) exists yet; the terms used are standard IT terms (repository, pull request, milestone) with no synonyms. Confirmed by the stand-in, not independent. | +| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Metadata keys, headings, IDs and statuses are English. | +| 7 | No translated twin (`..md`) exists beside the document | Pass | No `*.en.md` or other translated twin 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 language change. | +| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | Confirmed by AI as stand-in for S01 (English, IT domain). Mode is autonomous, not independent. | +| 10 | Abbreviations are spelled out on first use, in the stated language | Pass | Abbreviations used (SMTP, STARTTLS, CSV, PO) are spelled out or standard; SMTP is explained in the scope. | + +## Overall Verdict + +Go - All six criteria pass. Tasks are plain technical tasks; no use case is needed. + +## Action Items + +| Action | Owner | Due | +| --- | --- | --- | +| None | S01 | - | + +--- +[MIL-003]: ../../milestones/mil-003-documentation-and-publication.md +[QC-MIL-001]: ../../../framework/qc/artifacts/qc-milestones-gateways.md +[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md diff --git a/docs/stakeholder-analysis.md b/docs/stakeholder-analysis.md new file mode 100644 index 0000000..1724109 --- /dev/null +++ b/docs/stakeholder-analysis.md @@ -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-17 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version; reviewed in RC-002 (Go) | pending | + +--- + +## Purpose + +This analysis names the people the project serves and what each needs, so that scope and documentation choices can be traced to a person. It classifies each stakeholder by power and interest (Mendelow grid) and maps concerns to FURPS+. + +## 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 | HIGH | HIGH | Manage Closely | A working, tested solution to the assignment, built with the framework | +| S02 | Udemy coursists | Course participants who share and compare solutions | Udemy community | LOW | HIGH | Keep Informed | Readable, runnable code with the assignment's function names, and README instructions to run it | +| S03 | GitHub viewers | Visitors who browse the repository for ideas | Public | LOW | LOW | Monitor | A clear repository description, topics and README, and no runtime dependencies | + +## Power/Interest Classification Rationale + +- **Manage Closely (S01):** decides scope, reviews every step and accepts the result. +- **Keep Informed (S02):** cannot change the project but depends on the quality of the code and README. +- **Monitor (S03):** casual visitors; served by the repository front page. + +## Primary Concerns and FURPS+ Mapping + +| ID | Concern | FURPS+ attribute | +| --- | --- | --- | +| S01 | Birthday letters are sent correctly | Functionality | +| S01 | Tests run offline and are repeatable | Reliability | +| S01 | The token never leaks | Functionality (security) | +| S02 | Assignment names (`birthdays.csv`, `[NAME]`, letter templates) are kept | Usability | +| S02 | Code is easy to read and run | Usability, Supportability | +| S03 | Description, topics and README are clear | Usability | +| S03 | No runtime dependencies | Supportability (+ implementation constraint) | + +## Communication Requirements + +| ID | Channel | Frequency | Deliverable | Phase / Milestone | +| --- | --- | --- | --- | --- | +| S01 | Chat and pull request review | Each milestone | Pull request, review record, run summary | All milestones | +| S02 | README and wiki (en, da, ms) | At publication | Run instructions with screenshots | Documentation milestone | +| S03 | Repository description, topics and README | At publication | Front page | Documentation milestone | + +## Conflicting Interests and Mitigations + +| Conflict | Stakeholders | Mitigation | +| --- | --- | --- | +| The course hints use pandas, but S03 wants no runtime dependencies | S02, S03 | Use the standard `csv` module and keep the assignment's names; document the choice in the README | +| Real sending needs a secret, but the repository is public | S01, S03 | The token is read from the environment; only `.env.example` is tracked | + +## Traceability Analysis + +### Business Goal Alignment + +| Stakeholder | Concern | Business Case objective | +| --- | --- | --- | +| S01 | Correct sending, offline tests | [BC-001] objectives 1 and 3 | +| S02 | Assignment names, run instructions | [BC-001] objectives 2 and 4 | +| S03 | Description, topics, no dependencies | [BC-001] objectives 4 and 5 | + +## Sign-Off + +Reviewer: S01 (Product Owner). Review recorded in the `RC-*` for this instance. + +--- + +[BC-001]: ./business-case.md diff --git a/framework b/framework new file mode 160000 index 0000000..9ed600b --- /dev/null +++ b/framework @@ -0,0 +1 @@ +Subproject commit 9ed600b1949e734a5ea7d3fe73b54e86385a6019