# Learner evidence template

By the end of this module you should hold a short record of one piece of work you
generated, checked, corrected, and can defend. That record is your evidence pack.

It is one to two pages. It is not an essay, and it is not a programming
assignment. Its purpose is to make visible the thing the module is actually
about: the distance between "I generated this" and "I understand and can defend
this".

**The pack is yours and stays yours.** It is a private formative self-check. You
are not asked to submit it, it is not marked, and nobody collects it. Export it,
print it, or show it to someone only if you decide to.

## Two routes, one pack

There are two ways to fill this in, and they produce evidence of equal standing.

- **Table-based verification.** You compare generated values against a reference
  table — one you derived by hand and one published in the module — and record
  what matched and what did not. No code is run at any point.
- **Automated verification.** You run `course/lab/check.py` against a Python
  file and record what the checker reported.

Both routes verify the same claim by an independent method, which is what
verification means. Both are worked through below, in full, so you can see what
each looks like when it is done properly. Pick the one that suits how you work.

If you would rather not install or run Python but want a runnable checkpoint
record, the browser self-check at `build/site/selfcheck.html` produces one; the Python
route produces the same record with
`python3 selfcheck.py progress --evidence`.

---

## The template

Copy everything between the rules into a new file and fill it in.

---

### Evidence pack

**Name:**
**Date:**
**Context:** academic (course or module) / professional (role and organisation) / self-study
**Route used:** table-based verification / automated verification
**Task:** (one line — what you asked for)

#### 1. Original prompt

Paste the prompt exactly as you sent it, including anything you got wrong or left
out. Do not tidy it up. The gaps in this prompt are the evidence.

```text

```

#### 2. Generated output

Paste what came back, or the relevant part of it. If it was code, include it as
code. If it was a table of values, include the table. If it carried claims about
history or sources, include those too — they are part of the output and part of
what needs checking.

```text

```

#### 3. Verification result

State what you checked it against, by what method, and what happened. Name your
reference. "It looked right" is not a result; "B1 disagreed with the value I
derived in Unit 3" is.

- **Checked against:**
- **Method:**
- **Result:**

#### 4. Discrepancy notes

For each disagreement: what the output said, what the reference said, and — as
far as you can tell — what kind of error it was. Use the failure-mode codes the
checker reports where one applies (`b1-sign`, `odd-terms`, `ada-indexing`,
`off-by-one`, `not-fraction`, `raises`, `import-error`, `no-function`); most are
discussed in `course/misconceptions.md`.

If nothing disagreed, say so, and say what you checked that *could* have
disagreed. A check that could not have failed has not told you anything.

| index or claim | output said | reference said | code / kind of error |
|---|---|---|---|
|  |  |  |  |

#### 5. Revised prompt

Paste your second prompt. Then, in one or two lines per clause, say which clause
you added and which discrepancy above it was meant to remove. Every clause should
be traceable to something that actually went wrong.

```text

```

| clause added | discrepancy it addresses |
|---|---|
|  |  |

#### 6. Final result

The corrected output, and the verification you ran on it. Same standard as
section 3: name the reference and the method.

```text

```

- **Checked against:**
- **Method:**
- **Result:**

#### 7. AI-use disclosure

Two or three sentences. What you used AI for, at what stage, and what you did
with the output afterwards. Factual and specific. This is a statement about how
the work was made.

> 

#### 8. Correctness defence

Exactly two sentences. Why the final result is correct, citing the checks you ran
or the reasoning you followed. This is a statement about why the work is right,
and it must not rest on the authority of the tool.

> 

---

## Worked illustration A — table-based verification

*A completed pack, no code run at any point.*

**Route used:** table-based verification
**Task:** Get a table of the Bernoulli numbers `B0` to `B8` to use in a report.

**1. Original prompt**

```text
Give me a table of the first few Bernoulli numbers.
```

**2. Generated output**

```text
B0 = 1
B1 = 1/6
B2 = -1/30
B3 = 1/42
B4 = -1/30
B5 = 5/66
B6 = -691/2730
B7 = 7/6

These are the values Ada Lovelace computed in Note G of her 1843 notes,
where she calculated B7 using the Analytical Engine.
```

**3. Verification result**

- **Checked against:** the value of `B4` I derived by hand from the recurrence in
  Unit 3, and the module's published table in `course/lab/README.md`.
- **Method:** wrote both sequences side by side and compared index by index.
- **Result:** disagrees from `B1` onwards, apart from a coincidental match at
  `B4`. My hand derivation gives `B4 = -1/30`; the output files `-1/30` at `B2`
  as well as at `B4`.

**4. Discrepancy notes**

| index or claim | output said | reference said | code / kind of error |
|---|---|---|---|
| B1 | 1/6 | -1/2 | `ada-indexing` — the modern B2, filed as B1 |
| B3 | 1/42 | 0 | `odd-terms` — odd terms are not zero |
| B4 | -1/30 | -1/30 | agrees, but coincidentally: the modern B8 also equals -1/30 |
| B1..B7 as a block | the non-zero values in order | modern B2, B4, B6, ... | `ada-indexing` — only non-zero terms numbered |
| "she calculated B7" | Note G computes B7 | Note G computes *Ada's* B7, the modern B8 | index confusion in prose, unsourced |
| "using the Analytical Engine" | the engine ran the computation | the engine was never built (Unit 1) | unsourced historical claim |

The whole table is the consecutive renumbering: every value in it is a genuine
Bernoulli number, filed under the scheme that numbers only the non-zero terms —
`B1` holds the modern `B2`, `B2` the modern `B4`, and so on — and none is filed
under its modern index. Even the apparent agreement at `B4` is a coincidence of
the mathematics: the modern `B8` happens to equal the modern `B4`. The
historical sentence is a separate claim which the correct-looking arithmetic
gave me no reason to trust, and the exemplar verifier catches it at the first
source check: the output says the computation was run "using the Analytical
Engine", but the engine was never built (Unit 1) — see
`course/misconceptions.md` §6.

**5. Revised prompt**

```text
List the Bernoulli numbers B0 to B8 using modern indexing, where every
index is numbered including the odd ones that are zero. Use the first
Bernoulli convention, B1 = -1/2. Give each value as an exact fraction,
not a decimal. Do not include any historical commentary.
```

| clause added | discrepancy it addresses |
|---|---|
| "modern indexing ... including the odd ones that are zero" | `ada-indexing`, `odd-terms` |
| "first Bernoulli convention, B1 = -1/2" | `b1-sign` |
| "exact fraction, not a decimal" | pre-empts `not-fraction` |
| "no historical commentary" | the unsourced Note G claim |

**6. Final result**

```text
B0 = 1        B5 = 0
B1 = -1/2     B6 = 1/42
B2 = 1/6      B7 = 0
B3 = 0        B8 = -1/30
B4 = -1/30
```

- **Checked against:** my hand-derived `B4`, and the module's published table in
  `course/lab/README.md`, which itself agrees with 22 values transcribed from
  published tables.
- **Method:** index-by-index comparison of all nine values, twice, second time
  reading the reference first.
- **Result:** all nine agree. The odd terms `B3`, `B5`, `B7` are now zero, which
  is the property I had specifically failed on before.

**7. AI-use disclosure**

> I used an AI assistant to produce a table of Bernoulli numbers `B0` to `B8`.
> The first output used a different sign convention and Lovelace's 19th-century
> indexing, which I found by comparing it against a value I had derived by hand
> and against the module's published table. I re-prompted with the convention and
> indexing stated explicitly and verified the second table the same way.

**8. Correctness defence**

> Every value in the final table matches the module's published reference table
> index by index, and `B4 = -1/30` matches the value I derived independently from
> the recurrence before generating anything. The convention is stated — first
> Bernoulli numbers, `B1 = -1/2` — so the comparison is between two tables that
> are answering the same question.

---

## Worked illustration B — automated verification

*The same task, checked by running the code.*

**Route used:** automated verification
**Task:** Get a Python function `bernoulli(n)` for use in the Unit 5 exercise.

**1. Original prompt**

```text
Write me a Python function to compute Bernoulli numbers.
```

**2. Generated output**

```python
from fractions import Fraction
from math import comb

def bernoulli(n: int) -> Fraction:
    values = [Fraction(0)] * (n + 1)
    for m in range(n + 1):
        values[m] = Fraction(1)
        for k in range(m):
            values[m] -= Fraction(comb(m, k) * values[k], m - k + 1)
    return values[n]
```

I read the file before running it: it imports only `fractions` and `math`, and
does nothing to the filesystem, the network, or the shell.

**3. Verification result**

- **Checked against:** `course/lab/reference_bernoulli.py`, the module's test
  oracle.
- **Method:** pasted the function into `exercises/ex04_bernoulli.py` and ran
  `python3 check.py exercises/ex04_bernoulli.py`, comparing indices 0 to 30.
- **Result:** FAIL, two findings.

```text
FAIL - 2 problem(s) found.

[divergence] First divergence at n=1: expected -1/2, got 1/2.
[b1-sign] B1 has the wrong sign for this module's convention.
```

**4. Discrepancy notes**

| index or claim | output said | reference said | code / kind of error |
|---|---|---|---|
| B1 | 1/2 | -1/2 | `b1-sign` |
| B0, B2..B30 | — | — | agree exactly |

One index out of 31. The routine is correct under the second Bernoulli
convention; the specification I gave never said which convention I wanted, so
this is a specification failure rather than an arithmetic one. Worth noting that
the failure was found at `n=1`, the second value tested — a spot check starting
at `B2` would have missed it entirely.

**5. Revised prompt**

```text
Write a Python function with this interface:

    bernoulli(n: int) -> fractions.Fraction

Defined for every n >= 0; first-Bernoulli convention B1 = -1/2; exact
Fraction returns only, never float; returns Fraction(0) for odd n > 1.
```

| clause added | discrepancy it addresses |
|---|---|
| "first-Bernoulli convention B1 = -1/2" | `b1-sign` — the one that actually failed |
| "exact Fraction ... never float" | pre-empts `not-fraction` |
| "defined for every n >= 0" | pre-empts `raises` at the boundaries |
| "returns Fraction(0) for odd n > 1" | pre-empts `odd-terms` and `ada-indexing` |

The interface contract is the module's fixed specification, the same wording
`check.py` enforces. Only the first clause fixed a
bug I had; the other three are clauses I now know to include because I read the
failure modes in `course/misconceptions.md`.

**6. Final result**

```python
from fractions import Fraction
from math import comb

def bernoulli(n: int) -> Fraction:
    if n < 0:
        raise ValueError("n must be >= 0")
    if n > 1 and n % 2 == 1:
        return Fraction(0)
    values = [Fraction(0)] * (n + 1)
    for m in range(n + 1):
        values[m] = Fraction(1)
        for k in range(m):
            values[m] -= Fraction(comb(m, k) * values[k], m - k + 1)
    if n == 1:
        return -values[n]
    return values[n]
```

- **Checked against:** the same oracle.
- **Method:** `python3 check.py exercises/ex04_bernoulli.py --verbose`, then
  `python3 selfcheck.py run cp05-bernoulli`; on the table route, complete
  `cp05-table-evidence` and retain the compared rows.
- **Result:** PASS.

```text
PASS - agrees with the oracle for every n from 0 to 30,
       returns exact Fractions, and odd terms above B1 are zero.

(Indices compared: 0 to 30)
```

I also derived `B4 = -1/30` by hand in Unit 3, before any of this, and the
function returns that value.

**7. AI-use disclosure**

> I used an AI assistant to write a Python function computing the Bernoulli
> numbers. The first version used the second Bernoulli convention, which the
> lab's differential checker identified at `n = 1`. I re-prompted with the
> module's interface contract stated in full, read the result, and re-ran the
> checker.

**8. Correctness defence**

> The function agrees with the lab's test oracle for every index from 0 to 30,
> returns exact `Fraction` values, and returns zero at every odd index above
> `B1`; the oracle itself agrees with 22 values transcribed from published tables
> and uses a different algorithm from this implementation. `B4 = -1/30` also
> matches the value I derived by hand from the recurrence before generating any
> code, so the comparison does not depend on the oracle alone.

---

## Completion criteria

Your evidence pack is complete when all of the following are true. They apply
equally to both routes.

- [ ] All eight sections are filled in.
- [ ] The original prompt is the one you actually sent, not a tidied version.
- [ ] The generated output is included as it arrived, including any claims about
      history or sources.
- [ ] The verification section names a **specific reference** and a **specific
      method**, not an impression.
- [ ] At least one discrepancy is recorded, or — if the first attempt genuinely
      passed — you have stated what you checked that could have failed.
- [ ] Each discrepancy is labelled with a failure-mode code where one applies.
- [ ] Every clause added to the revised prompt is traceable to a specific
      discrepancy.
- [ ] The final result has been verified by the same method as the first, and the
      result is recorded.
- [ ] The disclosure says how the work was made, in your own words.
- [ ] The defence is two sentences, cites checks or reasoning, and does not cite
      the tool's confidence, the tool's name, or the fact that it "looked right".
- [ ] You can answer, out loud, which convention your result uses and why it
      matters.

Optionally attach your self-check record — `python3 selfcheck.py progress
--evidence`, or the summary from `build/site/selfcheck.html`. It shows which
checkpoints you passed. It is not evidence that you can defend them, which is
what sections 7 and 8 are for.

## Instructor note

*What this pack is for, and why it is not collected.*

**It is not collected.** The pack is a private formative self-check. It is not
submitted, not marked, and not reviewed by default, and no part of the module
asks a learner to hand it over. If a learner chooses to export it or show it to
someone — in a tutorial, in peer discussion, or in a portfolio of their own —
that is their decision.

**What it is for.** The pack makes the learner's own verification process visible
to them. The valuable content is sections 4 and 5 — the discrepancies found and
the clauses added — because those are where checking either happened or did not.
A pack whose first attempt passed and whose defence is thin says more than a pack
with a working function.

**Read the process, not the artefact.** If a learner does ask you to look at a
pack, respond to whether verification occurred and whether the defence is
evidence-based. Whether the final code runs, and how good the code is, are not
the point. A learner who generated broken code, found the bug, named the failure
mode, fixed the specification and defended the result has met every objective in
this module. A learner who generated correct code first time and wrote "the AI
got it right" has met none of them, and the pack should be able to show that
difference to the learner themselves.

**Both routes count equally.** A table-based pack and an automated pack are
evidence of the same competence. Nothing in the module should reward running
Python, and no cohort communication should describe the table-based route as a
fallback or as being for anyone in particular. Worked illustration A is included
in full, at the same length as B, for this reason.

**Why the stakes are zero by design.** The module asks learners to record their
mistakes in writing. That only produces an honest record if there is nothing to
lose by writing one down, which is why the pack is private and uncollected rather
than submitted for feedback or for a mark. Attaching a mark to the artefact would
produce packs in which nothing ever went wrong, and the module would have taught
the opposite of its subject.

**Common weak spots, worth naming in teaching.** A defence that names the tool
rather than the checks. A revised prompt with clauses that do not correspond to
any recorded discrepancy — usually copied from the Unit 6 material rather than
derived. "It looked correct" appearing in section 3. A discrepancy table with no
entries and no statement of what was checked. Each maps to an entry in
`course/misconceptions.md`, so a discussion can point at a specific unit and
checkpoint rather than at a learner.

**Cross-references.** The disclosure wording, the two-sentence defence, and the
assembly of this pack are Unit 8. The interface contract quoted in illustration B
is the module's fixed specification. Rules about permitted AI use in assessed
work are set by the learner's own institution or course; this module does not set
them and does not state them.
