Chapter 12 Companion: Code, Explanations and Solutions
Measuring Progress, Flow and Technical Health
OO Development and Agile Practices: Campus Equipment Lending
This companion supplies a small executable metrics exercise, worked calculations, the required repository-analysis method, a precise change specification and model answers. It follows the Week 11 syllabus. The application remains at Chapter 11; the Java calculator is a separate teaching tool, not a new lending feature or an analytics service.
The issue history is synthetic. The repository-lab template is blank by design: no real student repository has been inspected for this chapter, and no sample numbers are represented as real results. Complete that part with actual team evidence or an instructor-provided real export.
1. Files, toolchain and execution
The complete files appear under File: lab/... headings in the appendix. Create a directory named lab and copy each following fenced block into its named file. The TSV data uses actual tab characters and preserves empty fields, including trailing empty fields. Do not replace tabs with spaces or insert Markdown fences into the files.
| Tool or method | Pinned choice |
|---|---|
| Calculator | FlowMetrics v1.0, complete source in this file |
| Repository method | RM-12 v1.0, defined in Section 4 below |
| Java | Full JDK 17; locally checked with 17.0.20 |
| Build/test | Plain JDK compilation and explicit Java checks; no new dependencies |
| Optional Git provenance command | Git 2.51.1 syntax and locally inspected version |
| Running lending project | Chapter 11’s Java 17 / Maven 3.9.11 version, unchanged |
From lab:
These commands use a POSIX-style terminal, including Git Bash on Windows. In another terminal, create out using its normal directory command; the javac and java arguments remain the same. A JRE alone is insufficient. The assertions throw explicitly, so the -ea option is not required.
Expected checks: FlowMetricsChecks: 17 checks passed.
Expected report:
The --scope output samples every 24 hours from from through until when aligned. It is suitable for this midnight-UTC example. It is not a business-calendar or local-midnight plotting engine. Real PR data normally uses the summary without --scope because point estimates are unavailable or inappropriate.
2. Data contract and code explanation
Schema
Each TSV line has exactly six fields. There is no quoting or escaping syntax; use stable IDs without tabs or newlines. The file must have the exact header shown in the appendix.
| Field | Meaning | Missing value |
|---|---|---|
id | Unique work-item ID within this input | Invalid |
points | Nonnegative integer estimate held fixed in this example | Blank means unknown, not zero |
accepted | Timestamp admitted to tracked scope | Invalid |
started | Timestamp at the chosen start boundary | Blank means not started |
done | Timestamp at the chosen finish boundary | Blank means not completed |
removed | Explicit cancellation/removal timestamp | Blank means not removed |
Use ISO-8601 instants such as 2026-10-06T00:00:00Z, with a timezone offset if converting an original timestamp. Do not submit a bare local time. Preserve original timestamps and their timezone in the evidence record as well as any normalised UTC value.
Item rejects start-before-acceptance, completion without a start, completion before start, and contradictory done/removed states. read rejects duplicate IDs and the wrong number of fields. Unknown points produce NA for completed points if any completed item lacks an estimate; they do not prevent duration calculations. Scope-point output rejects missing estimates rather than inventing them.
The model permits a removed item to have been started; that item leaves WIP at removal but never counts as Done. It does not model reopening, multiple blocked intervals, changing estimates, parent/child aggregation or completed work later removed from the product. Use an event-history model for those cases rather than forcing them into these six columns. Input validity does not prove that the source population is complete or the timestamps reflect the claimed workflow.
Calculation responsibilities
completed selects Done instants in [from, until). summarize uses that cohort for count, points, lead and cycle statistics, and separately inspects all supplied rows for WIP at until. This deliberately permits carried-in work: an item can start before the window and finish within it.
inProgress treats an item as open once its Started event has occurred and until Done or Removed occurs. Events exactly at the snapshot instant are already applied. A completion at until is therefore excluded from that interval’s throughput and also excluded from WIP at that snapshot. There is no contradiction: one is a count over a half-open period, the other a state after boundary events.
days uses elapsed seconds and nanoseconds divided by 86,400 seconds. It does not call Duration.toDays, which would truncate partial days. This matters for real PR timestamps: a one-hour interval is approximately 0.041667 days, not zero. Output is rounded to two decimals for reading; calculations retain unrounded doubles.
An empty completion cohort yields zero completions and NA durations, because an average over no observations is not a measured zero-day average. Completed points for that empty cohort are zero as a sum. The median sorts completed cycle times and uses the middle value, or the average of the two central values for an even-sized cohort.
scopePoints and donePointsAt support this example’s fixed estimates and explicit removals. The first includes accepted items not removed as of the snapshot; the second includes completion events at or before it. They do not infer scope from Git commits.
Meaningful checks
The 17 checks protect independently useful properties: correct example totals and durations; scope addition/removal; completion-window boundaries; WIP at a completion instant; fractional elapsed days; empty-cohort handling; unknown estimates; and invalid event order. They are plain-Java teaching checks, not additions to the running application’s JUnit count.
For an optional fault experiment, use a separate copy. In completed, replace:
with:
Recompile and run FlowMetricsChecks. The check named Exclusive upper bound must fail: B at 6 October is incorrectly counted in the first window. Restore the expression and rerun. This experiment concerns a reporting interval, not a change to LoanPeriod or the overdue policy.
3. Worked calculations and interpretation
Finished cohort
| ID | Lead calculation | Lead days | Cycle calculation | Cycle days |
|---|---|---|---|---|
| A | 03 − 01 | 2 | 03 − 01 | 2 |
| B | 06 − 01 | 5 | 06 − 02 | 4 |
| C | 04 − 01 | 3 | 04 − 03 | 1 |
| D | 08 − 01 | 7 | 08 − 05 | 3 |
| G | 10 − 04 | 6 | 10 − 06 | 4 |
| Total | 23 | 14 |
Mean lead = 23 / 5 = 4.6 elapsed days. Mean cycle = 14 / 5 = 2.8 elapsed days. Sorted cycles are 1, 2, 3, 4, 4, so the median is three. Waiting before start totals nine days and averages 1.8, consistent with 4.6 − 2.8 for this same cohort.
B’s blocked interval [03,05) contributes two elapsed days within its four-day cycle. Subtracting those two days would make the cohort total 12 and mean 2.4, not two. Even 2.4 is not the defined cycle-time statistic and cannot be called coding time without further evidence.
Scope and completion reconciliation
Initial scope = 3 + 5 + 2 + 3 + 5 + 2 = 20 points. Added scope = G(3) + H(2) = 5. Removed scope = F(2). Final scope = 20 + 5 − 2 = 23. Completed points = A(3) + B(5) + C(2) + D(3) + G(3) = 16. Remaining = 23 − 16 = 7, exactly E(5) + H(2).
Throughput is five items in ten elapsed days, or 0.5 item per elapsed day as a rate over this interval. It is not 16 items and not six items. A and C finish in [01,06); B, D and G finish in [06,11). There is no double counting at the shared boundary.
At 11 October, E has age 11 − 07 = 4 days and H has age 11 − 08 = 3 days. Neither has a known completed cycle time. F was removed before starting, so it is neither WIP nor Done. A daily WIP count is a snapshot; it is not an average WIP over all instants.
Cautious interpretation example
“The synthetic iteration finished five items and 16 points. Scope grew by five points and later lost two, leaving seven points across two open items. The remaining-work rise on day 04 reflects a scope addition despite a completion. Completed cycle time averages 2.8 days, while the current open items have ages four and three days. B has a recorded two-day wait for clarification, but this small history cannot establish the causes of all delays. Before forecasting the approval change, inspect E’s unresolved issue and agree the approval data contract.”
This paragraph distinguishes facts, limitations and a next action. It does not claim real team performance or assign responsibility to a person.
4. RM-12 v1.0: required real repository lab
This is the pinned repository-metrics method for this chapter. It uses genuine issue/PR events and the same Java 17 calculator; no paid dashboard, API account or repository-analysis library is necessary. A hosting provider’s UI or an authorised export can supply the data. The source must be real even when an instructor prepares the export.
Route A: PR open-to-merge duration: minimum route
- Choose a source and rule. Record repository URL, target branch, fixed UTC interval, extraction timestamp and inclusion rule. For a small exercise, select the first five qualifying merged PRs ordered by merge time and then PR number within the interval; if fewer exist, use all and report the actual count. State whether bots, draft PRs and documentation changes are included before selection. This is a bounded duration sample, not repository throughput.
- Keep provenance. For each selected PR retain its URL/ID, original opened timestamp, merged timestamp and target branch. Inspect its event history. Exclude or separately document reopened PRs because the supplied one-interval model cannot express multiple open/closed episodes. Use actual precise timestamps; if the UI only gives relative dates, obtain an export with exact timestamps or report that precise calculation is blocked. Do not guess midnight.
- Map the data. Set
acceptedandstartedboth to the PR opened instant; setdoneto its actual merged instant. Leavepointsandremovedblank. Give it a stable ID such asPR-42. These boundaries intentionally make printed lead and cycle equal; report the result as PR open-to-merge duration, not issue lead time. Do not infer acceptance into a backlog from PR opening. - Calculate. Save the normalised six-column file as
repository.tsv. Run the calculator with the chosen interval and without--scope. Manually verify the longest selected duration using its two timestamps. Record count, median and mean for the sample, plus the observed range if helpful. - Interpret and review. State that coding may begin before a PR opens; draft/review waiting remains included; a merge need not be deployed or accepted by a user; the sample may differ from the full population. Ask a peer to trace one row back to the source, or label a solo provenance check accurately.
Example command shape, using your actual interval:
Those dates are the book example’s window, not a required window for a real repository. Replace them if they do not match your selection. If the input contains only merged sample PRs, do not interpret the displayed WIP as repository WIP: open PRs were not supplied.
Route B: complete-window throughput and open work
To report repository PR throughput, enumerate all qualifying merged PRs in the chosen branch and [from, until) interval. Check pagination and filters; record the number of results and any exclusions. Do not filter by opened date, because that would lose carried-in work. The completion count then measures merges of the stated PR unit, not finished user stories or deployments.
To report WIP at until, also include every qualifying PR opened at or before that instant that had neither merged nor closed at that instant. Historical snapshots require event history: a PR merged after until was still open at until. The calculator can retain the later Done event and correctly treat it as open at the snapshot. A PR closed without merging maps to removed, not done. Capture such rows where needed to reconstruct historical state. Record any reopened cases separately or use a richer event model.
Only a complete population supports full-window throughput/WIP claims. A small verified duration sample is sufficient for Route A and fulfils the required repository-duration exercise; do not mislabel it as Route B. Issue exports are an alternative when they include genuine Started/Done transition history and the same explicit completeness checks. In that route, define what “accepted” actually means before using it.
Optional Git cross-check
For a local repository, Git 2.51.1 can provide a compact provenance inventory without collecting names or emails:
%H is the commit hash and %cI the strict ISO committer timestamp. First-parent traversal changes the history being inspected. These records may help match a PR to a revision, but they do not supply PR-open times or prove deployment. The last 20 commits are not a complete interval export, and commit counts are not substituted for the required PR/issue measure.
Evidence template: fill with observed data
| Field | Your record |
|---|---|
| Repository and target branch | |
| Source interface/export and extraction timestamp | |
| Interval and timezone convention | |
| Unit; accepted/start/finish meanings | |
| Inclusion rule; excluded event histories | |
| Route A sample rule or Route B completeness evidence | |
| Raw IDs/URLs and exact timestamps | |
| Normalised file and command | |
| Number analysed; mean; median; longest manual check | |
| Throughput/WIP, only if supported by complete input | |
| One uncertainty; one defensible next question | |
| Reviewer and actual feedback, or solo review |
A zero-completion interval is a valid result; report it and retain NA durations. If the team has no usable history, use an instructor-provided real repository export or inspect a suitable public repository. Do not manufacture commits or PRs to claim historical evidence. Synthetic data may be used to practise the commands while arranging the real input, but the real-data lab remains unfinished until that input is examined.
5. CR-12: worked change specification for Chapter 13
Status: specified teaching change; implementation pending. It is not institutional policy and does not substitute for the team’s separately released assessment variant. These choices make the example concrete enough to implement and verify without reopening its basic scope in Chapter 13.
Behaviour and data decisions
| ID | Book contract |
|---|---|
| CR12-1 | Add a recognised VISITOR borrower category. Legacy directory code V maps to it. Existing S/T, inactive and unknown-code behaviour stays as documented; unknown codes never default to STUDENT. |
| CR12-2 | Visitors may request only CAM1 or CAM2, for one, two or three calendar days. Use the existing half-open loan period. Zero/negative duration and four or more days are rejected. |
| CR12-3 | Reuse the student count limit: fewer than three retained reservations for that borrower before adding one. This is the existing repository-count convention, not an active-loan count. |
| CR12-4 | A visitor needs one matching trusted approval record for the exact tuple (borrowerId, itemId, start, endExclusive). The record must have a nonblank sponsor ID and status APPROVED. Approval for another borrower, item or period is insufficient. |
| CR12-5 | Capture one request-time instant from an injected Clock. A record is valid when validFrom <= now < validUntil. Equality at expiry is invalid. The loan period need not lie inside the approval-validity window; that window governs when the reservation may be requested. |
| CR12-6 | A missing match, DENIED status or an out-of-window record is an expected rejection. It creates no reservation and sends no confirmation. |
| CR12-7 | An unreadable register, malformed row, duplicate request key, unknown status or invalid validity interval is an operational failure. It also creates no reservation and sends no confirmation, but is distinguishable from sponsor rejection. No fallback approval or empty-success response. |
| CR12-8 | Once approval and existing checks succeed, create the reservation and use existing confirmation behaviour. Retain the current rule that an expected notification failure leaves an already-created reservation in place. |
| CR12-9 | The initial release has one visitingResearchersEnabled flag, default false. Disabled visitor requests are explicitly rejected without reading the approval register. Student/staff requests use their existing path under either setting and never require sponsor approval. |
| CR12-10 | Approval is checked at reservation time only. Expiry or disabling the flag later does not cancel an existing reservation or block its normal checkout/return. Revocation after reservation is outside this exercise. |
The current direct category-taking entry point and the older overload that defaults to STUDENT are trusted teaching APIs, not authentication boundaries. Directory-backed requests obtain their category from the directory; arbitrary caller-supplied categories do not establish real-world identity. Do not claim this exercise prevents hostile impersonation. A production authorisation system would need separate requirements and evidence.
SD-12: count semantics: ReservationCoordinator calls its variable activeCount but counts all stored reservations. Returning a loan does not remove its reservation. Preserve this behaviour for the worked change and record the question: should a future authorised rule count active loans, future reservations, or all retained reservations? Renaming the local variable for clarity is possible as a separate structural edit; changing the count is a functional decision. SD-11’s due-today report behaviour also remains unresolved and unchanged.
Planned approval-register boundary
Choose a local UTF-8 TSV file with exactly eight columns:
Each column is separated by a tab; the example data below contains actual tabs. IDs cannot contain tabs or newlines. Dates are ISO local dates; validity timestamps are ISO instants. Status is exactly APPROVED or DENIED. Require start < endExclusive and validFrom < validUntil. Reject a malformed register as a whole, including an invalid unrelated row; do not silently skip bad records. Require unique request keys within one read. The file is treated as a trusted, sequential example, not an atomic concurrent approval database.
Synthetic valid example for the future implementation:
At request instant 2026-10-19T12:00:00Z, this approves V1’s two-day CAM1 request starting 20 October. At 2026-10-20T00:00:00Z, the same approval has expired. The row is a specification example, not input to FlowMetrics, and there is no approval parser implemented in Chapter 12.
A candidate application port can obtain the approval decision for a request; its file adapter performs actual I/O and validation. Keep deterministic membership/duration rules apart from source access and time. Do not force identity/approval information into BorrowingPolicy.mayRequest(count, days) through a global flag. Chapter 13 should decide the smallest interface shape that satisfies these examples and fits the existing orchestration.
Acceptance matrix
In visitor success/rejection rows assume a recognised active V1, flag enabled, fewer than three retained reservations, available equipment, valid identifiers and an ordinary working notification sender, except where the row changes one condition. Construct every example independently so one failure does not mask another.
| Example | Input difference | Expected observation |
|---|---|---|
| AC1 | CAM1, two days, matching approved record valid at request time | One new reservation; existing confirmation format; one notice |
| AC2 | CAM2, three days with its own matching record | Allowed; upper duration boundary preserved |
| AC3 | Four days, otherwise matching approval | Reject; no state or notice change |
| AC4 | Zero or negative days | Reject; no state or notice change |
| AC5 | Item MIC1 with matching approval | Reject because item is outside visitor allowlist |
| AC6 | Missing approval or DENIED record | Expected rejection; no state or notice change |
| AC7 | Approval belongs to V2, CAM2 or a different end date | Does not authorise the V1/CAM1/requested-period tuple |
| AC8 | now == validFrom | Valid if all other conditions hold |
| AC9 | now == validUntil, or before validFrom | Rejected as invalid at request time |
| AC10 | Unreadable file, malformed row or duplicate matching key | Distinct operational failure; no state or notice change |
| AC11 | Three retained reservations already exist | Reject count limit even if loans have been returned |
| AC12 | Visitor feature disabled | Explicit disabled result; approval source not called |
| AC13 | Existing student/staff request, either flag setting | Existing result and notification behaviour; approval source not called |
| AC14 | Visitor’s approved item overlaps an existing reservation | Existing availability rejection; no extra reservation or notice |
| AC15 | Valid visitor succeeds but expected notification failure occurs | Reservation retained; existing notification-failure outcome |
| AC16 | Visitor reservation created, then approval expires or flag turns off | Existing checkout/return flow remains available |
| AC17 | Unknown directory code or inactive visitor | Existing unknown/inactive semantics; never default to student |
| AC18 | Report generated after a visitor loan exists | Existing report mapping and SD-11 boundary retained |
These are planned examples, not claims that new tests have run. Existing policy tests, directory tests, command tests and the 159-test Chapter 11 suite remain relevant. Some test setups that enumerate every category will require explicit updates because adding an enum value changes their setup; document that necessary example change without weakening old assertions.
Ordered backlog and impact note
| ID | Ordered work | Dependency | Exit evidence |
|---|---|---|---|
| C12-1 | Preserve baseline and confirm CR12/SD12 examples | Chapter 11 source | Passing baseline result; retained revision/copy; reviewed contract |
| C12-2 | Add recognised visitor path, policies and explicit wiring | C12-1 | Valid visitor with controlled approval source; old categories still behave correctly |
| C12-3 | Implement and test actual approval-file adapter | C12-1 data contract; connect after C12-2 | Temporary-file success, malformed/missing/duplicate failures; no mock replacing the reader under test |
| C12-4 | Complete matching/time/failure and no-mutation protection | C12-2, C12-3 | AC boundary and operational-failure evidence |
| C12-5 | Introduce one flag and integrate CLI/demo | C12-2–4 | Both settings; old path; existing reservations usable after disable |
| C12-6 | Run full regression, real boundary checks and delivery workflow | C12-2–5 | Observed pipeline/local gate, repeatable demonstration and retrospective for Chapter 13 |
Status of C12-2–6 in this chapter: planned, not implemented. C12-1’s source preservation is supplied here; the learner records their actual baseline result and review. Do not assign owners, dates or points as if a real team had agreed them. Add those during the team planning activity, using its capacity and dependencies.
Impact rationale: category recognition reaches the directory and wiring; the coordinator enforces every-category policy availability; sponsor approval requires request identity/time that the existing count/duration interface lacks; the file reader needs integration checks; failures must be distinguished before a new reservation is added. The existing repository, loan lifecycle and report do not need a broad redesign for this narrow requirement. Concurrent approval updates and revocation remain outside scope.
Flag plan: default off; enable only for the controlled demonstration after both paths pass. Disabling prevents new visitor reservations, but does not erase existing data or roll back arbitrary side effects. Keep the pre-change revision for code comparison. Record a removal decision during Chapter 14 once the intended release path is accepted; do not let an unnamed temporary flag become permanent by default. No public production deployment is required.
6. Preserve the pre-change version
The supplied Chapter 11 code is the baseline; this chapter makes no edits to its production classes, tests or build file. Its last delivered full run passed 159 JUnit invocations. The metrics tool lives outside that Maven project and has its own checks; do not add its check count to the baseline’s count.
For your working project, first run its documented gate from its project root:
Retain the command, actual result, Java/Maven versions and any failure explanation. In a Git project inspect:
A commit ID is a sufficient source reference only when the intended baseline files are committed. If the working tree includes changes or untracked files, retain them in a separate complete source copy or make a deliberate scoped commit before recording the baseline. A tag alone does not capture uncommitted work. Avoid resetting the project or overwriting unrelated work to make this record look clean.
For learners assembling source from Markdown without Git, copy the complete Chapter 11 project directory as pre-change-ch12 before making Chapter 13 changes. Keep src, build configuration, resources and scripts. Generated target files are reproducible and need not be preserved as source. Keep a record of the copied file set and the successful command.
Suggested record:
7. Model answers and lab reasoning
Chapter 12.8: AI review
| Candidate claim | Judgement and correction |
|---|---|
| Six items / 18 points delivered | Contradicted: F is removed, not Done. Five items and 16 points completed. |
| Mean cycle is two after subtracting blocking | Contradicted: defined mean is 2.8. Subtracting B’s two days would give 2.4, and would change the measure. |
| Day 04 rise proves productivity declined | Not established: G adds three points while C completes two. The remaining line rises by one. |
| Day 08 fall proves five points delivered | Contradicted: D completes three; F removes two. |
| Legacy architecture caused waiting | Not established: one mapping clarification is recorded; broad causality needs more evidence. |
| Remaining work definitely finishes in 0.44 iterations | Unsupported forecast: the division is approximately right, but comparability, capacity and uncertainty are missing. |
| Rank members by commits | Reject the recommendation: commits do not measure individual value or identify the cause of delay. |
A corrected response can use the cautious interpretation in Section 3. A useful next step is to inspect E’s unresolved problem and settle the approval data contract. That is actionable without inventing a productivity diagnosis.
Chapter 12.11: concept questions
1. Lead versus cycle. Accepted-to-Done includes the pre-start queue; Started-to-Done does not. B has lead five and cycle four. Another team’s “lead time” might begin at a customer request rather than admission to scope, so the number cannot travel without its event definition and elapsed/business-time convention.
2. Falling burn-down. Removing F reduces remaining scope by two while delivering nothing. Re-estimation could also move a line under another data model. Keep a scope event record and distinguish the completed and scope lines in a burn-up.
3. Equal throughput. Two periods can each finish two items whose earlier start dates differ. A carried-in seven-day item and a newly completed one-day item can contribute equally to the period’s count. Recipients experience different waiting even when completion totals match.
4. Old versus new behaviour. The existing tests describe selected existing contracts. They do not contain sponsor-approval requirements and cannot establish those requirements by passing. Keep them, add new acceptance/unit/integration checks for CR-12, and examine any changes to test setups required by the new category.
Chapter 12.11: applied diagnosis
5. Biased cohort. Filtering on both start and finish being within the week excludes long-running carried-in work that finished this week. Define the completion cohort by the finish event and compute durations from actual start timestamps, even before the window. Report unfinished-item age separately. A start-cohort study is possible, but it answers another question and includes censored unfinished observations.
6. Global approval Boolean. Approval belongs to a specific borrower/item/period at a specific time. A static flag loses that identity and can leak across requests and tests. The current BorrowingPolicy contract deliberately handles count/duration only. Obtain a typed approval decision through an application boundary; validate its match and time using explicit inputs before reservation creation. Retain a pure count/duration policy. A global “approved” state is not an adequate record or security mechanism.
Chapter 12.11: ML serving transfer
Choose a unit such as one requested release of a named model version to a stated serving environment. Define Done as the approved version being demonstrably served at that boundary with required checks, not merely a successful build. Keep build, approval and activation timestamps separate. An unavailable approval registry must not be treated as permission to serve.
Plan a narrow valid activation path, mismatched/expired/denied approval outcomes if those concepts are required, and registry failure evidence. Test the genuine registry boundary separately from orchestration doubles. Preserve the old serving path and record how disabling the new release path affects already active versions. Model accuracy concerns predictive behaviour under an evaluation design; build success concerns construction checks; approval is a governance decision. None substitutes for the others.
Chapter 12.10: lab completion reasoning
the book’s project produces the calculations, corrected interpretation, CR-12 plan and baseline reference. your team’s project contributes real repository evidence and an impact note for its actual released change. Accept different task splits and interfaces when they preserve the observation boundaries and have defensible dependencies. Do not assess by number of commits, charts or AI prompts.
A good impact note identifies the concrete touchpoints, uncertainty and first experiment. A weak note merely lists class names or repeats “add tests.” A good repository result includes traceable timestamps and honest population scope; an attractive chart with guessed timestamps is not an acceptable replacement.
8. Verification record and limits
The supplied calculator was compiled at Java release 17 and its 17 checks passed. The exact synthetic report above was executed. A separate boundary-mutant copy was checked to confirm the exclusive-window assertion detects the deliberately inclusive upper bound; restoration returned the checks to green. The Markdown file listings were reconstructed and run before delivery.
An independent calculation also reconciled the eight source rows, five completions, 16 completed points, 23 final scope points, seven remaining points, the five-item duration means and the daily chart table. Chapter 11’s source was retained without modification. Its prior 159-test result is a baseline reference, not a newly implemented CR-12 result.
No student repository or actual PR history has been analysed in this authoring run. RM-12 supplies the procedure and blank evidence record for that required learner activity. No sponsor approval, stakeholder acceptance, hosted pipeline or peer review is claimed. CR-12’s adapter, tests and feature flag are specifications for Chapter 13. The calculator does not handle reopened histories, revised estimates or business calendars.
Sources and assigned reading are listed in the main chapter. All sample records, contracts, code and answers here are original teaching material.
Appendix: Complete isolated Java exercise
Keep these files outside the running lending application’s source roots. The two Java classes have no package declaration so the plain-JDK commands above work as written.