Start here: this week

Final assignment tutorial

Everything about the final assignment, in order: what it is, every command, how the cap01 notebook connects to it, how you hand it in, and how you read your score. The guide says what each piece is for. This page says what to type.

The final assignment is your research assistant. It is graded on a private question set and earns the certificate. It is separate from the Gecko capstone, the store project you present on Friday 2 October, which lives in its own repository. Nothing on this page is about that one.

The whole path

bootcamp final is the new name for bootcamp capstone. Both work, with the same options.

1. What you are building

The one-liner Your own research assistant, in your own public GitHub repository, that answers from six documents and names the one it used.
The goal It answers developer questions from data/corpus/ with a checked citation, and it refuses any question those documents do not support, and any order hidden inside a document.

2. Where everything lives

Three places. The repository is yours; the tests and the grader are the course's.

Place What it holds Who changes it What you run there
The course folder (dev3pack-cohort-2026-09) The lessons, the session notebooks, the cap01 notebook, and the grader The course uv run bootcamp check ..., uv run bootcamp submit ..., and uv run bootcamp final new once
Your repository (my-final-assignment, yours) Your agent (agent.py), the contract tests, docs/, your README, CI You, and only you uv run pytest, uv run bootcamp final grade, uv run bootcamp final submit
The submissions repository (dev3pack-submissions) What you hand in, and the score that comes back The course's bots Nothing. You read it.

How your repository reaches the course's grader. bootcamp final new pins the course package in pyproject.toml to the exact course commit your course folder holds, and uv sync records it in uv.lock. uv run bootcamp final grade and submit are that package's commands, running on your agent. So the test is always the course's, and the code under test is always yours.

Updating the course is your call. Nothing changes behind your back. When you want a newer course:

uv lock --upgrade-package dev3pack-bootcamp-ai-engineering
uv sync
git add uv.lock && git commit -m "Update the course package" && git push

3. The pieces, and which one judges your agent

Only one of them judges your agent: the private grader.

Piece What it is Where it lives What it proves When it counts
Your agent The class YourAgent. It takes one question and returns a ResearchAnswer: answer, citations, confidence, needs_human_review. agent.py, in your repository Nothing on its own. The grader judges it. Every grader run, and the private set
Your repository Your agent, contract tests, docs/, a README, and CI github.com/<you>/my-final-assignment That you can ship and explain a system. It is your showcase. When you submit, and after the course
The cap01 notebook Five checks, cap01-e1 to cap01-e5 The course folder: units/en/unit2/capstone/notebook.ipynb e1 to e4: the course's reference pipeline meets the contract. e5: you ranked what your agent does badly. Marks on the leaderboard, like a session's
The practice grader 10 practice questions, 5 of them critical, judged gate by gate The course package. You run it in your repository: uv run bootcamp final grade. How your agent does on each gate Never. It is for you.
The private grader and the certificate The same grader on a private set of 15 questions, 6 of them critical: same shape, unseen questions The course app. The answer keys never leave it. That your agent works on questions it was never tuned on At the end. It needs a score of at least 30% and every critical question.

There is no defence for the final assignment. Session 15 is where you present the Gecko capstone; the final assignment is judged only by the private set.

The numbers, exactly.

Practice set Private set
Questions 10 15
Critical 5 6
The starter agent, which only refuses 3/10 (30%), critical gate failed 4/15 (27%), both gates failed
The least a pass can be 6/15 (40%), because all 6 critical questions must pass

A pass needs a score of at least 30% and every critical question. On the private set the second gate is the one that decides: any pass is at least 40%.

4. Create your repository

In your course folder:

git pull
uv sync
uv run bootcamp final new ../my-final-assignment
cd ../my-final-assignment

If you use the projects or agents extras, name them as in today's class, for example uv sync --extra projects --extra agents. A bare uv sync removes extras you did not name.

What final new does:

It prints the next commands.

5. Sync once, commit uv.lock, and publish

In my-final-assignment:

uv sync
git add uv.lock
git commit -m "Lock the course package"

Do this now, not later. uv sync creates uv.lock, and final new did not commit it, because it did not exist yet. submit reads uv.lock to record which course commit your agent ran on, and it refuses a repository with anything uncommitted. Skip this and, on the day you submit, you get:

your repository has changes that are not committed:
    ?? uv.lock

The fix is the same whenever it happens: git add uv.lock, commit, push.

Publish it. You need the GitHub CLI, signed in with gh auth login (as in handing work in):

gh repo create my-final-assignment --public --source . --push

This creates the public repository, sets it as origin, and pushes both commits. Public matters: your submission links to your code.

Without gh, in your browser:

  1. Open github.com/new.

  2. Name it my-final-assignment. Choose Public. Add no README, no licence and no .gitignore: your repository already has them.

  3. Click Create repository. Then, in your terminal:

    git remote add origin https://github.com/<you>/my-final-assignment.git
    git push -u origin main
    

Never drag the folder into GitHub's upload page. That route ignores .gitignore, so it can upload your .env.

Open the Actions tab on GitHub. CI runs the tests and the practice grader on every push, on the fake model, with no key.

Point your assistant at AGENTS.md

Your repository has an AGENTS.md at its root: what the repository is, what your assistant may and may not do in it, and the commands. Most assistants read it by themselves; Claude Code reads the CLAUDE.md beside it, whose first line imports it. Give your assistant the rules has the table for every assistant, and the first prompt to paste.

Made your repository before 30 September? It has no AGENTS.md yet. Copy the two files from the course folder:

cp ../dev3pack-cohort-2026-09/capstone-template/AGENTS.md ../dev3pack-cohort-2026-09/capstone-template/CLAUDE.md .
git add AGENTS.md CLAUDE.md && git commit -m "Tell my assistant the rules" && git push

(Use your own course folder's name if it is not dev3pack-cohort-2026-09.)

6. Practise: the tests and the practice grader

In my-final-assignment:

uv run pytest
uv run bootcamp final grade

Useful options:

Command What it does
uv run bootcamp final grade --random 5 --seed 7 A sample of 5 questions, the same 5 each time
uv run bootcamp final grade --name "Your Name" Puts your name in the report
uv run bootcamp final trace "your question" One question through your agent, with every step it took

Give your agent a real model. A real score needs one:

cp .env.example .env
Variable What to put there
BOOTCAMP_PROVIDER anthropic, openai or ollama. Empty means the fake model.
BOOTCAMP_MODEL The model name your provider uses
ANTHROPIC_API_KEY Your key, when the provider is anthropic
OPENAI_API_KEY Your key, when the provider is openai
OPENAI_BASE_URL Only for an OpenAI-compatible service such as OpenRouter

ollama needs no key. It uses http://localhost:11434/v1 unless you set OLLAMA_BASE_URL. See a local model. .env is gitignored: never commit it and never paste it into a chat.

Run uv run bootcamp final grade again; the first line names the model it used. A real model can score differently on two runs of the same code, so write down which model produced each number.

7. What each session adds

bootcamp check chNN runs in the course folder. pytest and the grader run in your repository. The contract tests pass as shipped, because your agent starts as the course's pipeline: their job is to stay green while you change it.

Session What you learn What you add to your repository The one command, there
1 to 5 Already in your agent: AGENTS.md rules, one model adapter with a timeout, the ResearchAnswer shape with a strict parser, read-only tools with caps, a loop with four exits Nothing. Your agent already uses all five. uv run pytest
6 Load the documents strictly; retrieve by shared words; see how that fails Your first entry in docs/ISSUES.md: one retrieval failure you saw uv run pytest -k refusal
7 Measure retrieval and answers; attack your own evaluator A "Before" section in docs/EVAL_REPORT.md: practice score, model, one weakness of the evaluator uv run bootcamp final grade
8 One task as a chain, a loop and a graph, and what each costs A first draft of docs/adr/0001-run-shape.md; call counts in docs/EVAL_REPORT.md uv run bootcamp final grade
9 Trace every step; put each failure in a named bucket Failures by bucket in docs/EVAL_REPORT.md; rank 1 in docs/ISSUES.md with the trace line that decided it uv run bootcamp final trace "..."
10 A skill another assistant can load; a decision record that says what reverses it docs/SKILL.md with a before and after pair of runs; finish the ADR with the measurement that would reverse it uv run bootcamp final grade
11 What a session remembers, its cap, and what you refuse to store docs/RETENTION.md, including the line that names what you refuse to store; a test for your cap uv run pytest -k memory
12 Host, client and server; every tool marked read or write In docs/SKILL.md, every tool your agent can reach, marked read or write. Only readers stay wired. uv run pytest -k tools
13 Build the part of a server that says no A "Sources" line in README.md; an injection test in tests/ uv run pytest -k injection
14 Run it as a service; a smoke test that can say "bad"; a rollback sentence The timeout fix (remove its xfail); a regression test for rank 1 of docs/ISSUES.md; an "After" section in docs/EVAL_REPORT.md; the rollback sentence in README.md uv run bootcamp final grade

The loop, every time you change something:

uv run pytest
uv run bootcamp final grade
git add -A
git commit -m "what you changed"
git push

Read git status before git add -A. It should never list .env.

8. The cap01 notebook, and how it connects to your repository

The notebook is not in your repository. It is in the course folder, and it runs and is handed in from there, like a session notebook:

# in the course folder
git pull
uv run jupyter lab units/en/unit2/capstone/notebook.ipynb
uv run bootcamp check cap01
uv run bootcamp submit cap01 --github <you> --push

What its five checks judge:

Check What it runs on What it tells you
cap01-e1 to cap01-e4 The course's reference pipeline, on a scripted fake model. Not your agent. That the contract (a cited answer, a refusal before any model call, a readable trace) can be met. They pass before you write anything.
cap01-e5 Your ranked issue list That you ranked what your agent does badly: at least three rows, each with a real sentence for the issue and its impact

The connection is cap01-e5. Your issue list lives in docs/ISSUES.md, in your repository. Copy its top three rows into the notebook's issues cell, as rank, issue and impact, then run the check and hand the notebook in. When your ranking changes, update both.

So bootcamp check cap01 printing 4/5 as shipped is expected, and a green notebook means the contract can be met. Your agent is judged by the private grader, which runs on what your repository hands in.

9. Hand in the final assignment

The final questions are open. In my-final-assignment, finish the loop first: git status says "nothing to commit, working tree clean", and your last commit is pushed. Then:

export DEV3PACK_API_BASE=https://app.geckovision.tech
uv run bootcamp final submit --github <you> --dry-run
uv run bootcamp final submit --github <you>

<you> is your GitHub login, the one in your profile URL.

Before anything runs, it checks your repository: a commit, nothing uncommitted (uv.lock included), an origin on GitHub that is yours, and your last commit pushed. The submission links to that commit, so the code on GitHub has to be the code that answers.

Then three steps:

  1. 1/3 the practice set, locally: your practice score and the model it ran on. Nothing leaves your machine. Read this line. If it says WARNING: this run uses the fake model, your agent will score 4/15 (27%) on the final set and fail both gates. Stop, set up .env (section 6), and run it again.
  2. 2/3 the final questions: they come from the course app, with no answer keys. Your agent answers each one. A question that crashes or takes more than 120 seconds becomes a flagged refusal, and the run goes on.
  3. 3/3 the bundle: it writes answers.json and submission.json, then opens a pull request to Gecko-Academy/dev3pack-submissions, under submissions/<you>/final/.

--dry-run does every check and both runs, writes the bundle to a temporary folder, prints both files, and opens no pull request. It still asks your model every final question, so it costs what a real run costs.

Option What it does
--timeout 120 Seconds per question before it becomes a flagged refusal (default 120)
--budget 1800 Seconds for the whole run (default 1800)
--agent agent.py Which file and class to run, as FILE[:CLASS] (default agent.py)
--into DIR Where to write the bundle (default ~/.bootcamp/final)
--api URL The course app's address, instead of DEV3PACK_API_BASE

No gh? The command says so, keeps the bundle, and prints the steps to open the pull request in your browser.

You can submit again. Each new submission replaces the one before: your latest submission counts, not your best.

10. Read your score

submit does not print your final score: the answer keys never leave the course app, so nothing on your machine can compute it.

  1. The pull request's check reads your bundle.
  2. When it passes, the submissions repository merges the pull request.
  3. A workflow sends your answers to the course app and commits what comes back.

Your score is at:

https://github.com/Gecko-Academy/dev3pack-submissions/blob/main/finals/<you>/result.json
Field What it tells you
score Questions passed, and the percentage
gates The two gates: a score of at least 30%, and every critical question passed
passed true only when both gates pass
certificate_eligible Whether this result qualifies for the certificate
results A verdict per question. It does not repeat your answers.

A new submission overwrites the file. If your pull request shows Merged and the file is not there, tell the instructor; submitting again will not make it appear sooner.

The certificate is issued by the course, signed, and separately from this file. The final assignment page shows how anyone can verify one.

11. Reading the grader

Each question passes only when every gate on it passes. The last column of the grader's output lists the gates that failed. Reading the grader — opens with week 2, in the guide, has every gate, its usual cause, and the session that teaches the fix.

The verdict: PASSED needs a score of at least 30% and every critical question. 5 of the 10 practice questions are critical: the 3 refusals, the adversarial one, and one grounded one. 6 of the 15 private questions are critical. A practice report is never credential evidence; only the private set certifies.

12. Your README, for the showcase

The README final new wrote tells you how to start. When your agent runs, replace it with yours, in the order a reviewer reads it:

Section What goes in it
The problem Who has it, in two sentences
Demo One supported answer and one refusal, pasted exactly as final trace printed them
Architecture The shape of one run; link docs/adr/0001-run-shape.md
Measured results Your score, the model, and the exact command that produced it. Before and after.
The honest limitation Rank 1 of docs/ISSUES.md, and your next step
How to run it One line a stranger can copy

Never in it: an API key, your .env, anything from the private question set, or another student's code without a "Credits" line naming it.

13. Rules

Input The six documents in data/corpus/, never written to by anything you build. One question at a time. One model behind the LLMClient seam.
Output A ResearchAnswer with the same four fields on every path. Every citation is a document retrieval returned for that question. A refusal sets needs_human_review and cites nothing.
Budget One model call per question, one corrective retry, then a refusal. Tools only read. No new dependency, no database, no network in the answer path.
Failures it must handle A question the documents cannot answer. A citation retrieval never returned. An order hidden in a document. A model that never answers.

No solutions are published for the final assignment, and the private set stays private: a system tuned on the cases it is graded on measures its own homework.

Resources

You need Where
What each piece is for, and what counts the capstone guide
The rules for your assistant your repository's AGENTS.md, and give your assistant the rules
Every gate the grader checks reading the grader — opens with week 2
A free local model for your .env a local model, before you need one
Handing in, and a pull request with no checks handing work in
Your score finals/<you>/result.json in dev3pack-submissions
A question about the course the course MCP, https://mcp.geckovision.tech/course/mcp (connect any assistant)
The capstone, which is separate the Gecko capstone tutorial

Troubleshooting

Every refusal below is a message the command prints; each one means nothing was handed in. After any fix that changes a file, commit and push before you submit again: submit hands in the code that is on GitHub.

Creating the repository

You see Do this
... is inside the course clone. Your final assignment is its own repository Use a folder beside the course folder: uv run bootcamp final new ../my-final-assignment
... already exists and is not empty; nothing was overwritten Pick a new folder name, or delete the old folder yourself if you meant to start again
no capstone-template/ and data/corpus/ here Run it from your course folder, after git pull
this checkout is not a clone of ... Run it from your clone of the cohort repository, not a copy of its files
The files are written, but git could not commit them Usually git does not know your name yet. Run git config --global user.name "Your Name" and git config --global user.email "you@example.com", then the commit command it printed
invalid choice: 'final' This course or repository pins a version from before final existed. Use bootcamp capstone ..., the same command under its older name, or update the course (section 2).

Grading and the model

You see Do this
Unknown BOOTCAMP_PROVIDER ... fake, ollama, anthropic or openai in .env
score: 3/10 (30%) with critical safety gate failed You are on the fake model. Section 6, "Give your agent a real model".
... Run this inside your final assignment repository, or pass --agent FILE[:CLASS]. cd my-final-assignment first

Submitting

You see Do this
The pull request says "This branch has conflicts" and has no checks Your fork is behind, usually on a second submission. Press Sync fork on your fork's GitHub page, close the pull request, and run submit again
your repository has changes that are not committed: then ?? uv.lock git add uv.lock, commit, push
your repository has changes that are not committed: with other files Read git status, commit what belongs in your repository, push
`origin` is a course repository Your origin is under Gecko-Academy. Hand in from your own repository: section 4.
your repository has no `origin` on GitHub yet Section 5
`origin` is ..., which is not a GitHub repository git remote set-url origin https://github.com/<you>/my-final-assignment.git, then git push -u origin main
your last commit (...) is not on GitHub yet git push. If you pushed from another machine, git fetch first.
this is not a final assignment repository with a commit in it Run it inside the folder final new made
could not read which course commit this repository runs on uv lock, commit uv.lock, push
uv.lock pins the course at ..., but ... is installed. uv sync, then submit again
no API address. Pass --api <address>, or set DEV3PACK_API_BASE. export DEV3PACK_API_BASE=https://app.geckovision.tech in the same terminal
the API address must start with https:// Check the address you exported, character by character
The final questions are not open yet. / not published yet. Nothing is wrong. Run it again later.
--github ... is not a GitHub username Your login from your profile URL, not your display name
some answers are larger than the app accepts Your agent wrote an answer that is too long. Shorten it in your agent.
gh is installed but not signed in. Run: gh auth login gh auth login, then submit again

Stuck on something not here? Ask the course from your assistant. See search the course from your assistant.

Already started the research assistant somewhere else? A repository made with bootcamp capstone new is the same thing under the older name: keep it, and every section here applies. A clone of the Capstone Project repository is the Gecko capstone's home, not the final assignment's: create your final assignment with section 4 and copy your agent.py, tests/ and docs/ across.