Chapter 14 Companion: Code, Explanations and Solutions
Responding to Change and Handing Over
OO Development and Agile Practices
1. Scope and execution
This file accompanies Chapter 14, Responding to Change and Handing Over. It contains the handover version of the visiting-researcher project (0.14.0): a requirements-to-evidence table with a test that keeps it true, a reproducible demonstration, a script that follows the handover in a fresh copy, the handover documents, a decision record about the flag, the prepared and tested removal of that flag, the AI activity files, model solutions, the experiments behind the chapter’s figures and teaching notes.
No production code changed. Every file under src/main is byte for byte as in the Chapter 13 version. What changed is tests, scripts, documents and the version.
Input version. The starting point is the Chapter 13 version, which is the Chapter 10 companion, the new and changed files of the Chapter 11 companion and the new and changed files of the Chapter 13 companion. To keep verified listings from being copied again, this file lists only the files that are new or changed. Every other file is exactly as in those companions.
1.1 Reconstruct the version
- Create the directory
after. Save every listing of the Chapter 10 companion, then the new and changed listings of the Chapter 11 companion, then those of the Chapter 13 companion, applying the hunks of the Chapter 13 companion withpatch -p1from insideafter. - Save every listing in Sections 3 and 4 of this file at its path. Where a path already exists (
README.md,scripts/pipeline.sh,scripts/simulate-release.sh), the listing here replaces it. Apply the hunk of Section 3.2 topom.xmlwithpatch -p1. - The files under
ai-activity/andrehearsal/are not compiled by Maven.
Use a full Java 17 JDK, including the jdk.jdeps module, and Maven 3.9.11. The pinned versions are unchanged (JUnit Jupiter 5.13.4, Mockito 5.20.0, Compiler Plugin 3.14.1, Surefire 3.5.4); only the project version becomes 0.14.0. Then, from inside after:
1.2 Expected output
mvn --batch-mode verify ends with Tests run: 235, Failures: 0, Errors: 0, Skipped: 0 and BUILD SUCCESS. The 235 are the 232 of Chapter 13 and the three of TraceabilityTest. scripts/pipeline.sh ends with PIPELINE PASSED, with 206, 26 and 3 invocations in stages 2, 3 and 4. scripts/demo.sh prints:
(Maven and the mocking library print WARNING lines on a recent JDK; they are not errors. The Maven warnings appear before the demonstration lines.) scripts/handover-check.sh ends with HANDOVER CHECK PASSED after twelve ok lines.
1.3 Run the traceability check alone
Expected: Tests run: 3, Failures: 0, Errors: 0, Skipped: 0.
2. Design map
2.1 What is new or changed
| Path | Status | Purpose |
|---|---|---|
src/test/java/edu/se506/lending/docs/TraceabilityTest.java | New | Fails the build if the requirements table names a test or class that is gone, or an acceptance example loses its row |
src/test/java/edu/se506/lending/integration/DemoRun.java | New | Starts the local directory stub and runs the system twice, for scripts/demo.sh |
scripts/demo.sh | New | Compiles and runs DemoRun; one command, no other setup |
scripts/handover-check.sh | New | Follows docs/HANDOVER.md in a fresh copy and compares the results |
scripts/pipeline.sh, scripts/simulate-release.sh | Changed | A clear message and a non-zero exit when Maven is missing |
docs/HANDOVER.md | New | The handover bundle |
docs/REQUIREMENTS-TO-EVIDENCE.md | New | Ten contract clauses and eighteen acceptance examples traced to a deciding class and a test, and five known gaps |
docs/KNOWN-ISSUES.md | New | Fourteen known issues, each with a decision |
docs/RELEASE-NOTES-0.14.0.md | New | What changed in this version |
docs/ADR-014-flag-handover.md | New | Decision: keep the flag, rehearse the removal |
rehearsal/remove-visitor-flag.patch | New | The prepared, tested removal of the visitor flag. Not applied |
ai-activity/README-draft.md, ai-activity/README-corrected.md | New | The AI-drafted README and the corrected one |
README.md, pom.xml | Changed | Handover pointer; version 0.14.0 |
2.2 Test counts by stage
| Stage | Chapter 13 | Chapter 14 |
|---|---|---|
| 2 Unit tests and architecture checks | 203 | 206 (adds TraceabilityTest, 3) |
| 3 Integration | 26 | 26 |
| 4 End-to-end | 3 | 3 |
| Total | 232 | 235 |
2.3 What TraceabilityTest checks, and what it does not
| Check | Method |
|---|---|
| Every test named in the Evidence column exists as a method | everyTestNamedInTheTableStillExists (also requires at least 29 named tests, so that a deleted row cannot hide) |
Every class named in the Decided by column exists under src/main | everyClassNamedAsDecidingStillExists |
AC1 to AC18 each have exactly one row, and every ac<N>_ test in VisitorAcceptanceTest appears in the table | everyAcceptanceExampleHasExactlyOneRowAndEveryAcceptanceTestIsInTheTable |
| That a named test is the right evidence for its requirement | Not checked. A reviewer decides |
3. New and changed listings: build, scripts, documents
3.1 after/README.md
3.2 after/pom.xml
Change the project version from 0.13.1 to 0.14.0 and nothing else. The hunk is an edit to the Chapter 13 POM:
3.3 after/scripts/pipeline.sh
3.4 after/scripts/simulate-release.sh
3.5 after/scripts/demo.sh
3.6 after/scripts/handover-check.sh
3.7 after/docs/HANDOVER.md
3.8 after/docs/REQUIREMENTS-TO-EVIDENCE.md
3.9 after/docs/KNOWN-ISSUES.md
3.10 after/docs/RELEASE-NOTES-0.14.0.md
3.11 after/docs/ADR-014-flag-handover.md
4. New listings: tests, the rehearsal and the AI activity files
4.1 after/src/test/java/edu/se506/lending/docs/TraceabilityTest.java
4.2 after/src/test/java/edu/se506/lending/integration/DemoRun.java
4.3 after/rehearsal/remove-visitor-flag.patch
This is a unified diff against the finished 0.14.0 version. Apply it from inside after with patch -p1 < rehearsal/remove-visitor-flag.patch. It is the rehearsal of ADR-014: it is stored and tested, not applied.
4.4 after/ai-activity/README-draft.md
4.5 after/ai-activity/README-corrected.md
5. Worked explanation and evidence
5.1 The change footprint
The figures of Section 14.1 come from comparing the Chapter 11 and the Chapter 13 versions with diff -rq, excluding build output, and counting lines.
| Group | Files | Lines |
|---|---|---|
| New production files | 9 | 399 (63 + 15 + 9 + 73 + 53 + 6 + 16 + 92 + 72) |
| Existing production files changed | 5 | 21 added, 3 removed |
| New test files | 10 | 992 |
| Existing test files changed | 3 | 10 added, 4 removed |
| New scripts, workflow and record | 4 | 213 |
| README and POM changed | 2 | 14 added, 8 removed |
The five existing production files are BorrowerCategory (+1 −1), DirectoryReservationService (+14), ReservationApplication (+3 −1), LegacyDirectoryAdapter (+1) and LegacyDirectoryClient (+2 −1). A changed line counts as one added and one removed.
5.2 Three experiments on the same change
Each was run in its own scratch copy.
| Experiment | Starting point | Edit | Result |
|---|---|---|---|
| E1 | Chapter 11 version (159 invocations) | Add VISITOR to the enum only | 45 of 159 fail (1 failure, 44 errors). 89 lines of output say Missing policy: VISITOR; the one failure is RepositoryBoundaryTest.coordinatorRequiresARepository, which expects a NullPointerException and gets an IllegalArgumentException |
| E2 | The same | The enum, VisitorReservationRules and the composition root | 5 of 159 fail, in the three files that build their own policy map: LegacyRegressionTest.chapter06, BehaviourStrategyTest.injectedPolicyChangesDecisionWithoutChangingCoordinator, and three tests in RepositoryBoundaryTest. With the four map entries added, all 159 pass |
| E3 | Chapter 13 version (232 invocations) | LegacyDirectoryAdapter maps kind V to BorrowerCategory.STAFF; nothing else | 4 of 232 fail: the three end-to-end journeys and DirectoryOutageIntegrationTest.aVisitorIsServedThroughTheRealDirectoryAndTheRealApprovalFile. All 203 unit invocations pass. With the flag off, visitor V1 is confirmed; V2 is rejected only because CAM2 is already taken, with Rejected: item unavailable., not because it is unapproved |
| B1 | Chapter 14 version (235 invocations) | Remove the visitor policy from ReservationApplication.create | 73 of 235 fail (3 failures, 70 errors) in 14 test classes; 146 lines of output say Missing policy: VISITOR (each failure is reported more than once). The classes: VisitorAcceptanceTest 19, DirectoryOutageIntegrationTest 10, LoanServiceTest 9, AvailabilityTest 8, ReserveEquipmentCommandTest 4, LegacyRegressionTest 4, DirectoryAdapterTest 4, ReservationConsoleTest 3, NotificationPublisherTest 3, NotificationMockitoTest 3, Chapter13JourneyE2ETest 3, RepositoryBoundaryTest 1, OverdueBridgeTest 1, AvailabilityTddTest 1 |
What E1 and E2 show is how far the fail-fast check reaches. Everything that is constructed through the composition root fails together when the policy is missing there, which is one fix; the tests that spell out their own map fail separately, which is four fixes. What E3 shows is that this suite has a gap, and that a smaller change can pass a whole stage and fail the next one. Notice what it does not show: that unit tests cannot see such a change. No unit test checks the adapter’s mapping of the visitor code, so nothing in the unit stage goes through it. A focused adapter test would catch the change, and Section 6.2 (B8) says what it should check. The experiment found the hole by trying a change that goes through it, and Chapter 13’s own tests do not close it: the exercise B8 asks the reader to.
5.3 Revised assumptions: notes for the table in Section 14.1
- Policy answers a count and duration question only. Held:
VisitorReservationRulesis 16 lines andBorrowingPolicywas not widened. The approval needs identity and time, which a policy does not have, so the request-specific decision is inVisitorGate. - Every category has a policy in one place. Held in production (one map in the composition root). Four test constructions also spelled out the map (Chapter 13 companion, Section 4.7).
- The directory is a synthetic in-process provider with no transport (Chapter 8). Chapter 8 already defined the provider’s
Failure, translated it to aDirectoryExceptionand told an outage from an absence. Chapter 13 added the real HTTP client and the cases a transport brings, including a timeout that covers the whole answer, the body included. The contract held and the behaviour behind it grew. - Retained reservations are the count. Open, SD-12, pinned by AC11.
- The report knows two kinds. Open, SD-11-1, shown by AC18.
- One attempt, no retry. Held for notices (Chapter 6) and extended to the directory.
5.4 The constructed review of the visitor change
This review is author-written and fictional, constructed for this chapter. No real peer review of the project has taken place. The point of the exercise is to check each comment against the code instead of accepting or rejecting it by tone.
| # | Comment | Check | Verdict |
|---|---|---|---|
| R1 | “DirectoryReservationService now branches on VISITOR. Will that grow?” | Read the class: one if on the category, delegating to the gate. | Valid. Recorded as KI-14 with its trigger (a second special category). No code change |
| R2 | “Where is the flag read in production? I cannot find a global.” | Search for lending.visitors: only Chapter13Demo reads it, and passes a boolean to VisitorGate. There is no static state. | No issue |
| R3 | “Is the old two-argument service constructor still safe for visitors?” | ac12_... builds a service with the two-argument constructor and asserts the disabled rejection. | Covered |
| R4 | “The README says 230 tests. I count 233 after this change.” | The count appeared in both README.md and HANDOVER.md. | Valid. A number stated in two places rots. The README now states no number, and scripts/handover-check.sh checks the numbers in HANDOVER.md |
R4 is the useful one: it led to a change in the version, and the change has a check.
5.5 The dry run, in order
The handover was followed in a fresh folder, as a reader would, before the fixes were made:
- Step “check the tools”:
mvn -versionwas not found on the machine’s path. The scripts printedmvn: command not found. Finding D1. Fix: the document starts with a tool check and says what to do; the scripts print a clear message and exit with status 2. - Step “build”: Maven 3.9.11 printed
WARNINGlines aboutsun.misc.Unsafeand the mocking library printed a dynamic-agent warning, on a recent JDK. The build ended withBUILD SUCCESS. Finding D2. Fix: the document lists them as things that are not errors. - Step “see it work”: there was no way to run the demonstration program without a directory service. Finding D3 (KI-1). Fix:
DemoRunandscripts/demo.sh. - The new clear message was then run on the machine’s real setup, with the Maven command given as a full path to a
.cmdfile. It rejected the valid path, becausecommand -vdoes not accept a file that is not marked executable in the shell. Finding D4. Fix: also accept a file that exists. The handover check found this, not a reader. - The project was copied into a folder whose name contains spaces and run again. Nothing broke.
5.6 The rehearsal of the flag removal
The rehearsal was produced by a script in a scratch copy of the 0.14.0 version, and then written out as rehearsal/remove-visitor-flag.patch. It was verified in three ways: the patch applies to a fresh copy and gives a tree identical to the scratch copy; the full build of that tree passed; and scripts/handover-check.sh passed in it.
| File | Change |
|---|---|
VisitorGate.java | Removes DISABLED, the enabled field and parameter and the disabled() factory; adds noApprovals() (a gate whose source never has a record) |
DirectoryReservationService.java | The two-argument constructor uses VisitorGate.noApprovals() |
Chapter13Demo.java | No lending.visitors property and no Visitors enabled line |
VisitorGateTest.java | Drops the flag argument; removes the two disabled tests; adds aGateWithNoRegisterApprovesNoVisitor |
VisitorAcceptanceTest.java | World has no flag; AC12 becomes “no register approves no visitor”; AC13 and AC16 are renamed |
Chapter13JourneyE2ETest.java | Removes the flag-off journey, so two journeys remain |
DirectoryOutageIntegrationTest.java | disabled() becomes noApprovals(); constructor calls lose the flag |
DemoRun.java | Runs once |
REQUIREMENTS-TO-EVIDENCE.md | C9, C10, AC12, AC13 and AC16 point at the new names |
HANDOVER.md, handover-check.sh | The expected counts: 233 in total, 205 in stage 2, 26 in stage 3, 2 in stage 4 |
Eleven files; 87 lines added and 131 removed. The prose of README.md, the rest of HANDOVER.md and ADR-013 is not edited by the patch, and it still says that the flag exists.
Two things worth noticing. TraceabilityTest is why the table edits are in the patch: without them, the build fails after the patch on the first stale test name, which is the check doing its job. And the specification changed, not just the code: AC12 as written (a disabled flag rejects explicitly) has no meaning without a flag.
5.7 The contribution example
The numbers are synthetic. P1: 38 commits (17 formatting only), 410 lines changed, 4 reviews given (1 requested changes). P2: 9 commits, 1,150 lines, 11 reviews (5 requested changes). P3: 24 commits (3 formatting only), 620 lines, 7 reviews (0 requested changes). The team total is 71 commits and 2,180 changed lines.
| Measure | Order | Share of the team total |
|---|---|---|
| Commits | P1, P3, P2 | P1 38 of 71 (more than half) |
| Lines changed | P2, P3, P1 | P1 410 of 2,180 (19%) |
| Reviews given | P2, P3, P1 | |
| Reviews that requested changes | P2, P1, P3 |
The four orders are three different orders. The sentences about what the people did (a pipeline, an adapter, a demonstration and documents, four pair sessions of which two were recorded) are also synthetic. They are included to show what a count leaves out. Nothing in this example justifies a ranking.
6. Suggested practical solution
6.1 the book’s project, steps B1–B4
B1. Predict and measure what breaks. A good answer predicts before running: removing the one map entry in the composition root breaks everything built through it, which is most of the suite (the experiment gave 73 of 235, in 14 classes), and every message names the missing policy. It says what the result shows: the design fails fast and precisely, and the cost is breadth. It says what the result does not show: that the code is correct. Restore the file and rerun.
B2. Triage. A good answer applies the three questions to each item and gives a reason, for example:
| Item | Decision | Reason |
|---|---|---|
| KI-2 (SD-11-1, visitor late-fine rate) | Defer | Needs the records office; any rate would be a guess |
| KI-7 (whole-file rejection of the register) | Accept | A silent skip could hide a lost approval or a duplicate; revisit with real use |
| KI-8 (one-second wait, not measured) | Accept | It is a setting; measure before changing |
| KI-12 (no Java 17 or hosted CI run) | Defer | Needs a JDK 17 and a hosted runner |
KI-14 (the VISITOR branch) | Accept | Fine for one category; refactor at the second |
A good new item comes from reading the project, not from the list: for example, that DemoRun fixes the clock, so the demonstration cannot show an approval that expires (a limitation of the demonstration, accepted), or that nothing checks the README’s description of the architecture packages.
B3. Follow the handover. A good answer lists each place the reader guessed. Likely ones: where the project directory is, how to set CHAPTER_MVN, what the warnings mean, and how long the build takes. It also notes what did not need a guess.
B4. Trace and break a row. A good answer opens the test for each of its three rows and says whether it checks the claim. Example: C5 (valid at request time, start inclusive and end exclusive) is checked by VisitorGateTest.theWindowIncludesItsStartAndExcludesItsEnd, which tests exactly the two edges and one instant before the start. After renaming a named test, TraceabilityTest fails with the row’s ID and the missing name. What it cannot catch: a row that names a different but existing test (Section 10.2, fault 6).
6.2 the book’s project, optional steps B5–B7
B5. Rehearse the removal. Apply the patch from inside a scratch copy of after: patch -p1 < rehearsal/remove-visitor-flag.patch. Run mvn --batch-mode verify (233 invocations) and bash scripts/handover-check.sh (passes). A good answer lists what still says the flag exists: README.md (the paragraph about the flag), docs/HANDOVER.md section 6 (the visitor flag), docs/ADR-013-visiting-researchers.md (the flag removal plan and the rollback), docs/KNOWN-ISSUES.md (KI-13) and docs/REQUIREMENTS-TO-EVIDENCE.md (the descriptions are updated; the contract text in Chapter 12 is not).
B6. AI activity. See Section 7.
B7. Read a synthetic contribution table. A good answer asks questions, for example “What are the seventeen formatting-only commits, and were they needed?” (read the commit list), “What did P2’s two review findings say?” (read the review comments), “Which of P3’s pair sessions were with P1, and what was produced?” (read the pull requests and the retrospective notes). It does not conclude that P1 contributed most because of 38 commits, and it does not conclude that P2 contributed least because of 9.
B8. Close the gap that E3 found. A good answer adds a unit test class for LegacyDirectoryAdapter that uses an in-memory client (no network) and checks at least: a row with kind V and status Y maps to BorrowerCategory.VISITOR (and not to staff or student); a row with kind V and status N gives an empty result; and an unknown kind code throws DirectoryException and is never defaulted. Then it applies the one-line change of Section 14.1 and shows that the unit stage now fails. A weak answer adds a test that passes against the changed adapter too, for example one that only checks that a visitor is found. The new unit tests also raise the stage-2 count, so scripts/handover-check.sh and docs/HANDOVER.md need their numbers updated, which is the handover check doing its job.
6.3 your team’s project, steps T1–T5
These are not model answers, because the code is your team’s. A good answer shows:
- T1: the four questions answered with real evidence: the list of files changed and what each does; the tests that broke when the change started, and what that says; two or three assumptions the change overturned, with the chapter or document where they were written; actual review comments with responses. It names at least one place where the design bent.
- T2: a known-issues list in which every item has a decision, a reason, and (for a deferred item) an owner and a trigger; no feature added; a freeze time.
- T3: the bundle (setup, usage example, limitations, test instructions, requirements-to-evidence table, demonstration outline); a dry run in a fresh copy; a record of what a person outside the team struggled with, and what was changed; at least one statement in the bundle that a script checks.
- T4: two decision records with a true status, one about the flag or the change (the conditions for removal checked one by one, and a decision) and one other; the old record untouched if the new one applies or supersedes it.
- T5: at most three retrospective actions with owners, each tied to evidence; an individual reflection of claims with links and honest limits; the checklist of Section 14.7 with each item marked complete or a gap.
A weak answer describes the code instead of the change, lists defects with no decision, writes documents nobody has followed, edits an accepted decision record, ranks people by commit counts or claims a run that did not happen.
7. AI activity solution
The example makes sixteen statements. Each was checked by running the command or reading the code and tests it depends on.
| # | Statement | Verdict | Evidence and correction |
|---|---|---|---|
| 1 | A Java 11 application | Contradicted | maven.compiler.release is 17, and javac --release 11 on the main sources fails at behaviour/LifecycleExamples.java: switch rules are not supported in -source 11. A Java 17 application |
| 2 | Supports students, staff and visiting researchers | Supported | BorrowerCategory, ADR-013 |
| 3 | Build: mvn package | Supported | Produces target/equipment-lending-0.14.0.jar (it also runs the tests unless they are skipped) |
| 4 | Run: java -jar target/equipment-lending.jar | Contradicted | java -jar target/equipment-lending.jar prints Error: Unable to access jarfile target/equipment-lending.jar (the file name includes the version). With the right name, java -jar target/equipment-lending-0.14.0.jar prints no main manifest attribute, in target\equipment-lending-0.14.0.jar. The POM has no main class. Run the program with java -cp target/classes edu.se506.lending.bootstrap.ReservationApplication, which prints a notice and Result: Confirmed: R1 for B1 on CAM1 [2026-10-20, 2026-10-22). |
| 5 | mvn verify runs all 230 tests | Contradicted | 233 |
| 6 | …which pass in under 30 seconds | Not established | A full mvn verify took about 21 seconds on the verification machine with the dependencies already cached. That is one run on one machine; do not promise a time |
| 7 | Visitors are enabled by default; -Dlending.visitors=false turns them off | Contradicted | The default is false: Boolean.parseBoolean(System.getProperty("lending.visitors", "false")). The first run of scripts/demo.sh prints Visitors enabled: false. Correct: disabled by default; =true enables |
| 8 | A visitor may reserve CAM1 or CAM2 for one to three days when a sponsor approval matches | Supported | C2, C3, C4 of the requirements table |
| 9 | Approvals are read from a CSV file | Contradicted | Tab-separated with a fixed header and eight columns (FileApprovalSource.HEADER) |
| 10 | The file is cached in memory for speed | Contradicted | theFileIsReadAfreshOnEveryCall: a changed register is seen at once |
| 11 | If the directory does not answer within one second, the system retries three times and then treats the borrower as a student | Contradicted (the one-second default is correct) | One attempt, no retry, no fallback: aServerErrorIsAnOutageNotANotFoundAndIsNotRetried asserts exactly one request; the request fails with Unavailable. A borrower is never given a category the provider did not state |
| 12 | scripts/pipeline.sh runs five stages… | Supported | Compile, unit tests and architecture checks, integration, end-to-end, package |
| 13 | …and deploys the application to the staging server | Contradicted | Stage 5 only packages. scripts/simulate-release.sh copies a jar into a local folder and is labelled a simulation. Nothing is deployed |
| 14 | Architecture rules are enforced by DependencyRulesTest | Partly supported | It checks the direction of dependencies between packages (and a separate test checks for cycles). It does not enforce every architecture rule |
| 15 | The system is production-ready and safe for concurrent use | Not established, and contradicted by the project’s own limits | KI-10 and KI-11: stand-in directory and register; concurrency not considered; an in-memory teaching system |
| 16 | Run bash scripts/demo.sh to see visitors rejected and then approved | Supported | The output of Section 1.2 |
Of sixteen statements, six are supported or partly supported as written, eight are contradicted and two are not established. (Counting statements, not sentences: statements 5 and 6 split one sentence.) The corrected README is ai-activity/README-corrected.md. Each command in it was run, and its claims were checked against the same evidence.
Notice which errors reading alone reveals and which only a run does. A reader who knows the project notices the default of the flag and the CSV. Nobody notices that java -jar fails without running it, because the sentence is exactly what a README usually says. And a draft in which half of the statements are contradicted reads as fluently as one that is right. Notice also that the draft says nothing about limitations, and that the corrected README adds them.
If a live assistant is used, keep its actual output, and check its README the same way. Do not use a generated README to approve generated code.
8. Intentionally flawed alternatives
These fragments are diagnostic alternatives, not files to compile. Each corresponds to a mistake in Section 14.9 of the chapter or to a fault in the experiments of Section 10.2.
8.1 A number stated in two places
One of them is stale the moment a test is added, and a reader cannot tell which. State a number once, and have a script check it.
8.2 A decision record edited after the fact
The reasons the team had at the time are gone. Write a new record that applies or supersedes the old one, and leave the old one readable.
8.3 A guess presented as a fix
It looks like a repair of SD-11-1. It is a new rule, it hides the question and it changes AC18. Defer it with the question and the owner.
8.4 A ranking by counts
Habits are not contributions, and the same team has three other orders by other counts (Section 5.7). Use a count to choose which piece of work to read.
8.5 A claim that did not happen
The workflow file has never run. Say workflow file written, not run and keep the local run as the evidence.
9. Review answers and transfer solution
9.1 Concept answers
1. The four questions. Which responsibilities were affected (file and line counts do not show importance); what broke when the change started (shows only what the tests cover); which assumptions turned out wrong (only those that were written down); what a reviewer said (only as good as the review).
2. A one-line change that fails four tests. The change is smaller than the requirement: it does not implement the flag, the register check or the failure behaviour. The unit tests cannot say so, because none of them goes through the directory adapter with a real visitor. The stage that crosses the real boundary does, which is the reason to have it.
3. Deferred and accepted. A deferred issue is waiting for a decision that is not ours, so it carries an owner and a trigger (SD-11-1, the late-fine rate). An accepted issue is a limit we decided to live with, so it carries a reason and a statement (the one-second wait, not measured; no retry).
4. A requirements-to-evidence check. It can confirm that a named test or class exists and that each acceptance example has exactly one row. It cannot confirm that the named test is the right evidence for the requirement. A reviewer does that.
9.2 Applied diagnosis answers
5. 40 commits against 8. Questions: Are most of the 40 formatting, generated or reverted? (read the commit list.) What are the eight? (read the diffs and the pull requests.) Who reviewed whom, and what did the reviews find? (read the review comments.) Was there pair work recorded as one author? (read the commit trailers and the retrospective.) Say nothing about contribution until the artefacts are read.
6. A colleague adds a test. Two things that could notice: scripts/handover-check.sh, which compares the pipeline’s stage counts with what the handover promises (cost: it runs the whole pipeline in a fresh copy, about a minute); and a reviewer reading the pull request who knows the number is stated in the handover (cost: attention, and it relies on memory). The script is cheaper to repeat.
9.3 Transfer solution
For the model-serving team:
| Item | Content |
|---|---|
| README for a stranger | What the service does; what it needs (language runtime, build tool, a model file or a synthetic stand-in); three commands with their expected output; where the decisions are |
| Tool check | The runtime and tool versions with the output they should print; what to do if a tool is missing; the warnings that are not errors |
| Demonstration | A fixed model identifier and fixed synthetic data, a fixed clock if time matters, and a script that runs the same requests with the gate off and on |
| Requirements to evidence | Each rule (only approved model versions are served to external callers) to the class that decides it and the test, plus a check that the names exist |
| Known issues | Including what was not evaluated about the model: accuracy, fairness, drift, behaviour on data unlike the synthetic data |
| Decision record | The flag that gates a model version: the conditions for removal, the owner, what rollback does not undo (responses already served) |
| Limits statement | No real model evaluated; synthetic identifiers; no load test; no hosted run if none was made |
9.4 Quiz and revision pointers
None. This chapter adds no assessed content beyond the descriptor’s final project, and it creates no new rubric.
10. Instructor notes
10.1 Suggested demonstration and review
Run scripts/handover-check.sh, then break one thing (add a trivial test, or edit a number in HANDOVER.md) and run it again. Rename one test named in the requirements table and run TraceabilityTest. Show experiment E3: a one-line change that passes the whole unit stage. Ask the class which stage should have caught it and why. Let students predict B1’s failure count before running it.
For your team’s project, the review is of the bundle and not of the code: ask for the dry-run record, the person outside the team who followed it, the triage decisions and the statement of what was not run. Ask each student for one artefact that shows what they did. A weak answer to “what was not run?” is “nothing”.
10.2 Do the checks detect faults?
TraceabilityTest. Six faults were applied one at a time to a copy of the project and the test was run each time.
| Fault | Result |
|---|---|
| A named test is renamed | Caught: two of the three methods fail |
| An acceptance example loses its row | Caught: two of the three methods fail (the row check, and the minimum of 29 named tests) |
A deciding class is renamed in the table (VisitorGuard) | Caught: the class check fails |
| An acceptance test is added that no row mentions | Caught: the row check fails |
| A row names an extra test that exists | Not caught; harmless |
| AC3 is pointed at the AC1 test, which exists | Not caught; a wrong mapping that only a reviewer finds |
scripts/handover-check.sh. Three faults, each run through the whole script: a test added (stage 2 shows 207 invocations: FAIL stage 2 ran 206 invocations, one problem); a word changed in the demonstration’s output (FAIL an outage is reported as unavailable, and the pipeline fails too, because the end-to-end journeys check the same line: three problems); and HANDOVER.md edited to promise 232 invocations (FAIL HANDOVER.md promises 235 invocations in total, one problem). All three were caught.
These are a few faults, chosen by the author, in two small checks. They say nothing about how these checks compare with others. They show that the checks notice the faults that make a document disagree with a run, and that they do not notice a document that is wrong in a way the script cannot see.
The results establish the selected behaviours on the supplied inputs. They do not establish that the handover is followable by a reader on another machine.
References
The online references of the student chapter (sources 1–9) were opened on 13 October 2026; see the chapter for the source context.
- Nygard, M., Documenting Architecture Decisions.
- Keep a Changelog 1.1.0.
- Schwaber, K. and Sutherland, J., The Scrum Guide.
- Retrospective Wiki: The Prime Directive.
- Fowler, M., Yagni.
- GitHub, Why are my contributions not showing up on my profile?.
- GitHub, Creating a commit with multiple authors.
- GitHub, About pull request reviews.
- Hodgson, P., Feature Toggles (aka Feature Flags).