This is a ready-to-use record of an independent code review. It answers the question that homegrown analytics tools fail most often: who other than the author confirmed that the logic is correct, and against which exact version. Complete one per release of every tool that requires independent review. Replace every <<FILL: ...>> placeholder with your own specifics and route the completed record through your normal review and retention process. A filled specimen follows. This content is educational reference, not legal or regulatory advice; verify each cited regulation against the current source before you rely on it.
The independence rule, stated plainly
Self-review is not independent review. A record signed by the person who wrote the logic does not satisfy this control, no matter how carefully that person checked their own work. The reviewer must be a qualified person who did not author any part of the logic under review, and the record must say so explicitly.
Three variations that also fail the independence test, and are worth naming because each one appears in practice:
- The reviewer wrote the function under review and the author wrote the rest. Independence is judged per unit of logic, not per file.
- The reviewer’s only qualification is availability. A reviewer who cannot follow the calculation cannot confirm it, and the record should not claim otherwise.
- The review was a verbal walkthrough with no record of what was examined or what was found. An undocumented review is indistinguishable from no review.
Where the team is genuinely too small to supply an internal reviewer, draw the reviewer from another function or an approved external party and record the arrangement in section 2. A reviewer shortage is a resourcing problem, not a justification.
Record control header
| Field | Entry |
|---|---|
| Record title | Independent Code Review Record |
| Record number | <<FILL: CR-<tool ID>-nnn>> |
| Governing procedure | <<FILL: SOP-ID>> |
| Review date(s) | <<FILL>> |
| Review type | Initial release / Change <<FILL: change record>> / Periodic review verification / Retrospective (tool found in use) |
Section 1: What was reviewed
| Field | Entry |
|---|---|
| Tool ID | <<FILL>> |
| Tool name | <<FILL>> |
| Tool type | Script / Notebook / Dashboard / Query / Macro workbook / Pipeline job |
| Risk class | <<FILL: A / B / C>> |
| Repository or controlled location | <<FILL>> |
| Branch reviewed | <<FILL>> |
| Exact version reviewed | Commit identifier <<FILL: full or abbreviated commit hash>>, dated <<FILL>> |
| Merge or pull request reference | <<FILL: number and URL or system reference>> |
| Tag applied on approval | <<FILL: e.g. v1.0-validated>> |
| Files or artefacts in scope | <<FILL: list, including test code and the environment manifest>> |
| Files explicitly out of scope | <<FILL: list and reason>> |
| Specification reviewed against | <<FILL: document ID and version>> |
| Source method reviewed against | <<FILL: SOP, compendial procedure, or statistical reference, with version>> |
| Prior review superseded | <<FILL: record number, or "None, initial review">> |
| Lines or objects changed since the prior reviewed version | <<FILL: e.g. diff summary, or "full review, no prior version">> |
For low-code projects, name the artefact actually examined. A binary project file cannot be reviewed by diff, so state what the reviewer opened, in what tool, and how the comparison against the previous version was made.
Section 2: Reviewer identity, qualification, and independence
| Field | Entry |
|---|---|
| Reviewer name and role | <<FILL>> |
| Reviewer function or department | <<FILL>> |
| Relevant technical qualification | <<FILL: languages, platforms, and years of relevant practice>> |
| Relevant domain qualification | <<FILL: knowledge of the science, method, or process the tool implements>> |
| Training on the governing procedure | Complete on <<FILL: date>> |
| Second reviewer, where required | <<FILL: name, role, and what they specifically reviewed, or "Not required">> |
| Author of the logic under review | <<FILL: name and role>> |
| Independence statement | I confirm that I did not author any part of the logic under review, that I have no reporting or performance relationship that would compromise this review, and that I am competent to assess the calculation and its implementation. |
| Reviewer signature and date | <<FILL>> |
Where the reviewer is external or drawn from another function, record the arrangement and its approval: <<FILL>>
Section 3: Review checklist
Mark each item Pass, Fail, or N/A. Any Fail raises a finding in section 4. An N/A carries a reason.
3.1 Correctness of the calculation
| # | Item | Result | Evidence or comment |
|---|---|---|---|
| 3.1.1 | The calculation implemented matches the equation and method stated in the approved specification | <<FILL>> | <<FILL>> |
| 3.1.2 | The calculation matches the cited source method, SOP, or compendial procedure, including any conditions the source places on its use | <<FILL>> | <<FILL>> |
| 3.1.3 | Units are consistent throughout, and every conversion is explicit and correct | <<FILL>> | <<FILL>> |
| 3.1.4 | Aggregation is performed at the correct grain, with no unintended duplication or omission from joins, merges, or lookups | <<FILL>> | <<FILL>> |
| 3.1.5 | Filtering, exclusion, and grouping rules match the specification, including inclusivity at each boundary of a range | <<FILL>> | <<FILL>> |
| 3.1.6 | Statistical choices (degrees of freedom, one-sided versus two-sided, denominators, weighting) are correct for the stated method | <<FILL>> | <<FILL>> |
| 3.1.7 | Sorting is deterministic where order affects the result | <<FILL>> | <<FILL>> |
| 3.1.8 | Date, period, and time zone handling is correct and unambiguous | <<FILL>> | <<FILL>> |
3.2 Edge cases, missing data, and rounding
| # | Item | Result | Evidence or comment |
|---|---|---|---|
| 3.2.1 | Behaviour on empty input is defined and matches the specification | <<FILL>> | <<FILL>> |
| 3.2.2 | Behaviour with a single record, or with the stated minimum record count, is correct | <<FILL>> | <<FILL>> |
| 3.2.3 | Missing values are handled as specified, and never silently replaced with a default, a zero, or a forward fill | <<FILL>> | <<FILL>> |
| 3.2.4 | Out-of-range values are handled as specified | <<FILL>> | <<FILL>> |
| 3.2.5 | Duplicate records are detected and handled as specified | <<FILL>> | <<FILL>> |
| 3.2.6 | Rounding uses the rule stated in the specification and is applied only at final reporting, not to intermediate values | <<FILL>> | <<FILL>> |
| 3.2.7 | Reported precision matches the specification and the downstream system it must agree with | <<FILL>> | <<FILL>> |
| 3.2.8 | Division, logarithm, and other operations with undefined domains are guarded | <<FILL>> | <<FILL>> |
3.3 Hard-coded values
| # | Item | Result | Evidence or comment |
|---|---|---|---|
| 3.3.1 | No specification limit, acceptance criterion, or alert or action level is hard-coded where it should be a controlled parameter | <<FILL>> | <<FILL>> |
| 3.3.2 | No product, lot, study, site, or method identifier is hard-coded where the tool is intended to be general | <<FILL>> | <<FILL>> |
| 3.3.3 | No date, cut-off, or period boundary is hard-coded where it should be supplied or derived | <<FILL>> | <<FILL>> |
| 3.3.4 | No conversion factor or physical constant is hard-coded without a comment naming its source | <<FILL>> | <<FILL>> |
| 3.3.5 | No file path, server name, or connection string is hard-coded in a way that breaks portability between the test and production environments | <<FILL>> | <<FILL>> |
3.4 Silent failure paths
| # | Item | Result | Evidence or comment |
|---|---|---|---|
| 3.4.1 | No exception handler swallows an error and allows execution to continue with an incomplete or default dataset | <<FILL>> | <<FILL>> |
| 3.4.2 | Every failure path produces a visible message and a non-zero exit status or equivalent failure signal | <<FILL>> | <<FILL>> |
| 3.4.3 | No failure path writes an output that could be mistaken for a valid result | <<FILL>> | <<FILL>> |
| 3.4.4 | Warnings that indicate a data problem are surfaced rather than suppressed | <<FILL>> | <<FILL>> |
| 3.4.5 | A partially completed run cannot leave a partially written output in the destination | <<FILL>> | <<FILL>> |
3.5 Maintainability
| # | Item | Result | Evidence or comment |
|---|---|---|---|
| 3.5.1 | A qualified third person who has not seen the tool could read it and understand what it does | <<FILL>> | <<FILL>> |
| 3.5.2 | Functions and variables are named for what they represent, including units where relevant | <<FILL>> | <<FILL>> |
| 3.5.3 | The calculation section carries comments that reference the specification requirement IDs | <<FILL>> | <<FILL>> |
| 3.5.4 | Dead code, unused branches, and abandoned experiments have been removed | <<FILL>> | <<FILL>> |
| 3.5.5 | Automated tests, where present, are readable and their expected values are traceable to the specification rather than to previous tool output | <<FILL>> | <<FILL>> |
3.6 Repository hygiene and data protection
| # | Item | Result | Evidence or comment |
|---|---|---|---|
| 3.6.1 | No credentials, tokens, connection strings with secrets, or private keys appear in the code, the manifest, the notebook output, or the commit history | <<FILL>> | <<FILL>> |
| 3.6.2 | No GxP source data, patient data, or personal data is committed to the repository, including inside notebook output cells | <<FILL>> | <<FILL>> |
| 3.6.3 | The environment manifest pins exact versions and is stored with the code | <<FILL>> | <<FILL>> |
| 3.6.4 | The tool accesses the source system read-only and contains no write, update, or delete operation against it | <<FILL>> | <<FILL>> |
| 3.6.5 | The output provenance block is implemented and complete | <<FILL>> | <<FILL>> |
3.7 Notebook-specific items (complete where the tool is a notebook)
| # | Item | Result | Evidence or comment |
|---|---|---|---|
| 3.7.1 | The saved output was produced by the saved code: the notebook was restarted and run top to bottom, or executed non-interactively, and the reviewer confirmed this | <<FILL>> | <<FILL>> |
| 3.7.2 | Execution counts are sequential from the first cell, with no evidence of out-of-order execution | <<FILL>> | <<FILL>> |
| 3.7.3 | No state is carried in from a previous session or a manually executed cell | <<FILL>> | <<FILL>> |
| 3.7.4 | Output cells contain no GxP data that should not be committed | <<FILL>> | <<FILL>> |
3.8 Low-code-specific items (complete where the tool is a dashboard or visual data-preparation flow)
| # | Item | Result | Evidence or comment |
|---|---|---|---|
| 3.8.1 | Every calculated measure in the project appears in the specification, and every specified measure exists in the project, with no orphans in either direction | <<FILL>> | <<FILL>> |
| 3.8.2 | Every transformation step and calculated column is specified and its purpose is clear | <<FILL>> | <<FILL>> |
| 3.8.3 | Relationship cardinality and filter direction match the data model in the specification | <<FILL>> | <<FILL>> |
| 3.8.4 | Row-level security rules match the specification and their combined coverage is complete | <<FILL>> | <<FILL>> |
| 3.8.5 | No measure silently depends on the current filter or slicer state in a way the specification does not describe | <<FILL>> | <<FILL>> |
Section 4: Findings
Severity definitions:
| Severity | Definition | Required action |
|---|---|---|
| Critical | Could produce a wrong GxP result, or hide a failure, in normal use | Must be corrected and re-reviewed before release. Cannot be accepted with a rationale. |
| Major | Could produce a wrong result in a foreseeable but non-routine condition, or breaches a stated requirement without an immediate wrong-result path | Corrected and re-reviewed before release, or accepted only with a documented rationale approved by the tool owner and QA |
| Minor | Does not affect the result, but affects maintainability, clarity, traceability, or diagnostic output | Corrected before release, or scheduled with an owner and a due date |
| Observation | No defect. A suggestion or a note for the record | No action required |
| Finding ID | Checklist item | Severity | Description | Requirement or specification affected | Proposed resolution | Resolution implemented at commit | Re-reviewed | Reviewer initials and date |
|---|---|---|---|---|---|---|---|---|
<<FILL>> | <<FILL>> | <<FILL>> | <<FILL>> | <<FILL>> | <<FILL>> | <<FILL>> | Yes / No | <<FILL>> |
Findings accepted without correction:
| Finding ID | Severity | Rationale for acceptance | Owner approval | QA approval |
|---|---|---|---|---|
<<FILL>> | <<FILL>> | <<FILL>> | <<FILL>> | <<FILL>> |
Section 5: Impact on testing
| Question | Answer |
|---|---|
| Did any finding change the code? | Yes / No |
| If yes, which test cases must be executed or re-executed? | <<FILL: test case IDs>> |
| Did the review identify a scenario not covered by any existing test case? | Yes / No |
| If yes, which new test cases were added to the protocol? | <<FILL>> |
| Was the specification found to be wrong, ambiguous, or incomplete? | Yes / No |
| If yes, specification change reference | <<FILL>> |
Section 6: Reviewer conclusion
Select one.
| Conclusion | Meaning | Selected |
|---|---|---|
| Approved | The version identified in section 1 correctly implements the approved specification, subject to no open Critical or Major findings, and is suitable to proceed to testing or release | <<FILL>> |
| Approved with minor findings tracked | As above, with Minor findings recorded and scheduled | <<FILL>> |
| Not approved, rework required | One or more Critical or Major findings remain open. A new commit and a further review are required | <<FILL>> |
Reviewer statement:
<<FILL: two to four sentences stating what was examined, what was found, and the basis for the conclusion>>
| Role | Name | Signature | Date |
|---|---|---|---|
| Independent reviewer | <<FILL>> | ||
| Second reviewer (where required) | <<FILL>> | ||
| Author (acknowledging findings and resolutions) | <<FILL>> | ||
| Tool owner | <<FILL>> | ||
| Quality Assurance (where required by risk class) | <<FILL>> |
Filled specimen
Independent code review of tool ANL-0007, the class A stability regression script, at initial release. Names, identifiers, and dates are illustrative.
Section 1
| Field | Entry |
|---|---|
| Record number | CR-ANL-0007-001 |
| Review dates | 27 to 29 April 2026 |
| Review type | Initial release |
| Tool ID and name | ANL-0007, Stability slope and shelf-life bound |
| Tool type and risk class | Script, class A |
| Repository and branch | gxp-analytics/stability-slope, branch main via merge request 14 |
| Version first reviewed | Commit 7bd0e21, dated 24 April 2026 |
| Version approved after rework | Commit a3f19c4, dated 29 April 2026 |
| Tag applied on approval | v1.0-validated |
| Files in scope | slope.py, io_contract.py, provenance.py, tests/test_slope.py, requirements.txt |
| Files out of scope | README.md (documentation only, no logic) |
| Specification | SPEC-ANL-0007 v1.0 |
| Source method | <<FILL: internal stability data evaluation SOP-ID>> v4, written against the ICH stability guidance series |
| Prior review | None, initial review |
Section 2
Reviewer: M. Larsen, Process Statistician, Manufacturing Science. MSc in statistics, nine years applying regression and stability data evaluation in commercial biologics, routine Python user, trained on the governing SOP on 12 January 2026. Author of the logic under review: K. Osei, Stability Lead. The reviewer confirmed in writing that she authored no part of the code, has no reporting relationship to the author, and is competent to assess both the statistical method and its implementation. No second reviewer required; the risk classification specified a statistical reviewer, which this reviewer satisfies.
Section 3, results summary
Thirty-six applicable checklist items, being all of sections 3.1 to 3.6. Thirty-two Pass and four Fail, with the four Fails raising findings F-01 to F-04. The nine items in sections 3.7 and 3.8 were recorded N/A as a group with the reason stated once for each group: 3.7 because the tool is a script rather than a notebook, and 3.8 because it is neither a dashboard nor a visual data-preparation flow.
Selected evidence entries:
| Item | Result | Comment |
|---|---|---|
| 3.1.1 | Pass at a3f19c4 | Slope and intercept implemented exactly as CALC-01. Verified by recomputing the seven-point reference dataset by hand: slope -0.2440 per month, intercept 100.1527, matching the script to four decimal places. |
| 3.1.6 | Pass | The confidence bound uses the one-sided t quantile at 95% with n minus 2 degrees of freedom, 2.0150 for n equal to 7, matching CALC-03. |
| 3.2.6 | Pass at a3f19c4 | Rounding applied only at output. Confirmed by inspecting the write path: full-precision values are carried through to the formatter. |
| 3.6.1 | Pass | Full commit history scanned for credential patterns; database connection is built from a secrets lookup at run time. Nothing found. |
| 3.6.4 | Pass | The tool opens the reporting replica with a read-only account. No write, update, or delete statement present. |
Section 4, findings
| ID | Item | Severity | Description | Affected | Resolution | Fixed at | Re-reviewed |
|---|---|---|---|---|---|---|---|
| F-01 | 3.3.3 | Critical | The proposed shelf life was hard-coded as 24 months in the prediction and confidence bound functions. SPEC CALC-02 requires it to be supplied as a controlled parameter. A product with a 36-month proposed shelf life would have been silently evaluated at 24 months and the output would have looked entirely normal. | CALC-02, CALC-03, CALC-05 | Shelf life read from the controlled parameter file and echoed into the provenance block. Test case TC-06b added at T equal to 18 months to prove the supplied parameter is honoured, and TC-08 extended to confirm the extrapolation guard fires against the supplied value rather than a constant. | a3f19c4 | Yes, 29 Apr 2026 |
| F-02 | 3.4.1 | Major | The input read was wrapped in a broad exception handler that logged at debug level and continued with an empty dataset. The script then wrote no output but exited with status zero, so the scheduler would have reported the run as successful. Contrary to ERR-09 and ERR-12. | ERR-01, ERR-09, ERR-12 | Broad handler removed. Specific errors raised with the offending filename, and the process exits non-zero. TC-11 extended with an unreadable-input case that asserts the exit status. | a3f19c4 | Yes, 29 Apr 2026 |
| F-03 | 3.1.6 | Minor | A diagnostic helper printed a residual standard deviation computed with a denominator of n minus 1 rather than n minus 2. On the reference dataset it printed 0.036909 where the correct value is 0.040432. The controlled result did not use this helper, so no reported value was affected, but the log would have misled anyone investigating a discrepancy. | Diagnostic output only | Denominator corrected to n minus 2 so the log agrees with the value used in CALC-03. | a3f19c4 | Yes, 29 Apr 2026 |
| F-04 | 3.5.2 | Minor | The regression function had no docstring and used single-letter variable names with no units. A third person maintaining the tool would have to reconstruct the method from the code. | Maintainability | Docstring added naming the specification requirement IDs; variables renamed to include units, for example timepoint_months and potency_pct. | a3f19c4 | Yes, 29 Apr 2026 |
No findings were accepted without correction.
Section 5, impact on testing
Code changed, so TC-05, TC-06, TC-07, TC-08, and TC-11 required execution against a3f19c4 rather than 7bd0e21. Two new test cases were added to the protocol as a direct result of this review: TC-06b (prediction at a shelf life of 18 months, to prove the supplied parameter is honoured rather than a constant) and an extension of TC-11 asserting a non-zero exit status on unreadable input. The specification was found to be correct and unambiguous; no specification change was raised.
Section 6, conclusion
Approved with minor findings tracked, at commit a3f19c4.
Reviewer statement: I reviewed the five files listed in section 1 against SPEC-ANL-0007 v1.0 and the stability data evaluation SOP, and independently recomputed the slope, intercept, residual standard deviation, prediction at 24 months and the one-sided lower 95% bound on the seven-point reference dataset by hand and in a second statistical package. At commit 7bd0e21 I raised one Critical finding, one Major and two Minor. All four were corrected at commit a3f19c4, which I re-reviewed in full for the affected code paths and by diff for the remainder. At a3f19c4 the implementation matches the specification, fails visibly on the error conditions I could construct, and contains no hard-coded value that should be a controlled parameter. I did not author any part of this code.
| Role | Name | Signature | Date |
|---|---|---|---|
| Independent reviewer | M. Larsen | signed | 30 April 2026 |
| Author acknowledging findings | K. Osei | signed | 30 April 2026 |
| Tool owner | K. Osei | signed | 30 April 2026 |
| Quality Assurance | T. Marchetti | signed | 04 May 2026 |
The finding worth pausing on is F-01. The script produced correct numbers throughout development, because every dataset the author tried had a 24-month shelf life. The defect was invisible to testing until the reviewer read the code and compared it to the requirement. That is what an independent code review buys that testing does not.
Common inspection findings this record prevents
- The only person who confirmed the calculation is the person who wrote it.
- A review is claimed but no record exists showing what was examined or what was found.
- A review record exists but does not identify the version reviewed, so it cannot be tied to the version that ran.
- The reviewer is named but there is nothing on record showing they were qualified to assess the calculation.
- Findings were raised in a review but no record shows whether they were fixed, and the tool was released anyway.
- A hard-coded specification limit or date cut-off survived into production because nobody read the code.
- An exception handler suppressed a failure, so a scheduled run reported success while producing nothing, and the gap went unnoticed for weeks.
- A notebook’s saved output was never produced by its saved code, and no reviewer checked the execution order.
- Credentials or GxP data are present in the repository history.
- A dashboard has measures in the project that appear nowhere in the specification, so they were never reviewed or tested.
How to adapt this record
- If your version control platform records merge or pull request approvals, use that as the record and attach or reference this checklist, rather than duplicating the approval in two places. What matters is that the checklist content is evidenced and the approval is attributable and timestamped.
- Trim the checklist by risk class. Class C tools can reasonably use sections 3.1, 3.2, 3.3, and 3.4 only. Do not trim section 3.4, because silent failure is the defect that testing is least likely to catch.
- Define reviewer qualification criteria once in the governing SOP and reference them here, so that section 2 is a confirmation rather than an argument.
- Keep the severity definitions exactly as written or map them onto your existing defect severity scale, but preserve the rule that a Critical finding cannot be accepted with a rationale.
- Section 5 is the part teams skip and the part that pays. A review that changes the code and does not trigger re-testing has produced a record about a version that no longer exists.
- For low-code projects, decide in advance how a reviewer will compare versions when the project format is binary, and write that method into the governing SOP. Where the platform offers a text-diffable project format, require it for new content.
- Retain this record for the retention period of the records the tool supports, not the life of the tool. The tool may be retired long before the results it produced leave the retention window.