Agent PCIS 2500 / 3990
CIS 3990 · Fall 2026

Lab 1

Read-only Lab specification

Sign in to Agent P
Instructions

Lab specification

Lab 1 — Terminal, Git, and CI Bootstrap

Assigned: Tuesday, August 25 · Due: before Thursday, September 3

Prerequisites: None (this is the setup lab).

Prepares for: All subsequent labs and projects. The Claude Code configuration, Spacebar installation, and CI pipeline you create here are the foundation everything else builds on.

Estimated time: 105–150 minutes with agentic tools (setup: ~30 min; exploration: ~30 min; CI: ~30 min; client connect: ~20–30 min; reflection: ~15 min).

Grading: Pass/fail.


Overview

You will set up your development environment from scratch, get Spacebar running locally, configure Claude Code pointed at the course LiteLLM proxy, bootstrap a CI pipeline that runs on every push, and connect a real chat client to prove the server does what it claims. The goal is not just to check boxes — it is to have a working baseline that you fully understand and can explain.

By the end you will have: a running Spacebar server, a working Claude Code installation routed through the course proxy, an auto-generated CLAUDE.md, a CI workflow that lights up green on every push, and a channel with real messages posted through a connected client.

Repository platform

Staff provisions a private, per-group repository containing the pinned Spacebar checkout, hosted on Gitea and managed through Agent P, the course portal. Gitea is a Git host with a GitHub-like workflow: you will use branches, issues, Pull Requests, and repository checks in much the same way, but your course repository and links are on Gitea, reached through Agent P. Use the repository URL and pinned commit or tag Agent P gives you; do not clone an unpinned public upstream copy. If the staff instance exposes CI through a separate provider, use the checks page linked from the Gitea repository.

Before you can clone anything, you need an SSH key registered with Agent P — see "SSH Key Setup and Repository Access" below.


Lab System Prompt

Before starting, save [AGENTS.md](AGENTS.md) as your CLAUDE.md (or paste it as a system prompt). It configures the agent to produce structured, verifiable artifacts for every lab this semester, not just this one — you only need to set it up once.


Platform Setup: Get to an Ubuntu 22.04 Terminal

Everything in this course — every lab, every project, every command anyone will ever debug with you — assumes an Ubuntu 22.04 terminal. Neither macOS Terminal nor Windows PowerShell is that, directly, so step zero is getting a real Ubuntu 22.04 environment running and learning to open a terminal into it. Do the section for your host OS; skip the other one.

Once you're in — for the rest of this lab, and every lab this semester — run every command in your Ubuntu terminal, not in a native macOS or Windows shell.

macOS — OrbStack

  1. Install OrbStack:
   brew install --cask orbstack

(No Homebrew? Download the installer directly from [orbstack.dev](https://orbstack.dev) instead.) Launch OrbStack once from your Applications folder — first launch asks for a couple of macOS permissions (networking, in particular); allow them.

  1. Create an Ubuntu 22.04 machine from your Mac's Terminal app (this one command, only, runs outside Ubuntu — everything after it runs inside):
   orb create ubuntu:jammy spacebar-dev

(jammy is Ubuntu 22.04's release codename.)

  1. Open a shell inside it:
   orb -m spacebar-dev

You should see your prompt change to something like you@spacebar-dev. That's Ubuntu 22.04, not macOS — confirm with cat /etc/os-release.

OrbStack machines run systemd by default — no extra configuration needed for the systemctl commands used later in this lab (PostgreSQL, in Part A step 3).

  1. Install VS Code on macOS if you don't already have it — [code.visualstudio.com](https://code.visualstudio.com), or brew install --cask visual-studio-code.
  1. Install the Remote - SSH extension: click the Extensions icon in the left sidebar (four squares), search "Remote - SSH", click Install on the one published by Microsoft.
  1. Open the Command Palette (Cmd+Shift+P), type "Remote-SSH: Connect to Host", and select or type spacebar-dev@orb — OrbStack registers this hostname for you automatically once the machine exists. A new window opens; the first connection takes a minute while VS Code installs a small server component inside Ubuntu.
  1. Confirm you're actually editing files inside Ubuntu, not on macOS: the bottom-left corner of the window should show a green ><SSH: spacebar-dev indicator. Editing files from the macOS side and expecting Ubuntu-side tools (git, npm, Claude Code) to see the changes is a common source of confusion — this indicator is how you check you're not doing that.
  1. Once connected, File → Open Folder and point it at your home directory (~) — you'll clone spacebar into it in Part A, and can reopen the folder afterward to see it appear.
  1. Open a terminal for Claude Code: with this Remote-SSH window open, use Terminal → New Terminal (or ` Ctrl+ `). Because the window itself is the Remote-SSH session, this terminal opens inside Ubuntu automatically — it is not macOS Terminal in disguise. If you want to double check, run cat /etc/os-release in it; you should see the same Ubuntu 22.04 output as step 3. Use this integrated terminal for every command for the rest of this lab, including npm install, git, and — once you install it in Part B — claude` itself. You do not need a separate Terminal.app window at any point.

Windows 11 — WSL2

  1. Open PowerShell as Administrator (right-click the Start menu → "Terminal (Admin)" or search for PowerShell, right-click, "Run as administrator").
  1. Install WSL2 with Ubuntu 22.04 specifically.
   wsl --install -d Ubuntu-22.04

This enables the Windows features WSL2 needs and installs Ubuntu 22.04 in one step. Restart Windows if prompted.

  1. After restarting, launch "Ubuntu 22.04 LTS" from the Start menu. The first launch takes a minute to finish setting up and will ask you to create a Linux username and password — these are separate from your Windows login and only exist inside this Ubuntu environment.
  1. Enable systemd — required later in this lab for the systemctl commands that manage PostgreSQL, and generally expected by tooling that assumes a normal Linux init system. It is not on by default for a distro installed this way:
   sudo nano /etc/wsl.conf

Add these two lines to the file:

   [boot]
   systemd=true

Save and exit (Ctrl+O, Enter, then Ctrl+X in nano). Back in PowerShell (not inside Ubuntu), restart WSL for the change to take effect:

   wsl --shutdown

Reopen "Ubuntu 22.04 LTS" from the Start menu. Confirm systemd is actually running as PID 1:

   ps -p 1 -o comm=

This should print systemd. If it prints init instead, the wsl.conf change didn't take — double check the file contents and that you ran wsl --shutdown from PowerShell, not from inside Ubuntu.

  1. Install VS Code on Windows if you don't already have it — [code.visualstudio.com](https://code.visualstudio.com).
  1. Install the WSL extension: click the Extensions icon in the left sidebar (four squares), search "WSL", click Install on the one published by Microsoft.
  1. From inside your Ubuntu terminal, launch VS Code connected to this machine:
   cd ~
   code .

The first time, this installs a small VS Code server component inside Ubuntu and opens a new window — expected, and only happens once. (VS Code's Command Palette also has a "WSL: Connect to WSL" command if you'd rather start from the Windows side instead.)

  1. Confirm you're actually editing files inside the Linux filesystem, not on Windows: the bottom-left corner of the window should show a green ><WSL: Ubuntu-22.04 indicator.
  1. Open a terminal for Claude Code: with this WSL window open, use Terminal → New Terminal (or ` Ctrl+ `). Because the window itself is the WSL session, this terminal opens inside Ubuntu automatically — it is not PowerShell in disguise. If you want to double check, run ps -p 1 -o comm= in it; you should still see systemd, same as step 4. Use this integrated terminal for every command for the rest of this lab, including npm install, git, and — once you install it in Part B — claude` itself. You do not need to switch back to a separate PowerShell or Ubuntu console window.

SSH Key Setup and Repository Access

Everything below happens inside your Ubuntu terminal (from Platform Setup, above) and on Agent P, the course portal (URL posted on the course website). Do this once — the same key and repository access carry through the rest of the semester.

<div class="callout warn">
Agent P's Git host is only reachable from Penn's network. If you're off campus, connect to the Penn VPN (vpn.upenn.edu) before running any `git clone`, `git push`, or `git pull` — for this lab and every lab and project afterward. A clone or push that hangs or times out is usually this, not a broken key.
</div>

Before anything else, tell git who you are. A fresh Ubuntu install has no identity configured, and your very first git commit (Part C) will fail with Please tell me who you are without this — do it once, now, and it's set for every lab this semester:

git config --global user.name "Your Name"
git config --global user.email "you@seas.upenn.edu"

Use the same email Agent P has on file for you if you know it — it's how your commits get attributed to you for grading.

  1. Check whether you already have an SSH key:
   ls ~/.ssh/id_ed25519.pub

If that file exists, you can reuse it — skip to step 2. If you see "No such file or directory," generate one:

   ssh-keygen -t ed25519

Press Enter at every prompt to accept the defaults — this saves the key to ~/.ssh/id_ed25519 and ~/.ssh/id_ed25519.pub with no passphrase. Using the default filename is fine; a fresh Ubuntu 22.04 environment won't already have a conflicting key.

  1. Print your public key so you can copy it:
   cat ~/.ssh/id_ed25519.pub

Select and copy the entire line — it starts with ssh-ed25519 and ends with a comment.

If you already use SSH for something else (a personal GitHub account, another server) and have more than one key under ~/.ssh/, add this to ~/.ssh/config (create the file if it doesn't exist):

   Host ssh.git.agent-p.org
     User git
     Port 2224
     IdentityFile ~/.ssh/id_ed25519
     IdentitiesOnly yes

Without this, SSH may offer your other keys first, and Agent P's Git host will reject the connection with "Too many authentication failures" before it ever tries the right one. If you only have the one key this lab just created, you can skip this.

  1. Log into Agent P and go to Profile / Git access. Paste your public key into the field there and save it.
  1. Go to My Courses and scroll to the bottom of the page. You'll see a "Your Git repositories are ready" panel with a card for each provisioned repository, including one for Lab 1. Click Copy on the git clone command shown on that card — it will look like:
   git clone ssh://git@ssh.git.agent-p.org:2224/<your-course-and-section>/<your-repo-slug>.git

You'll come back to this same panel for every subsequent lab and project to find that assignment's clone command.

  1. Add spacebar to the end of the copied command so the checkout lands in a directory with that name — this is the destination directory Part A and the rest of this lab assume:
   git clone ssh://git@ssh.git.agent-p.org:2224/<your-course-and-section>/<your-repo-slug>.git spacebar

You'll run this for real in Part A, step 2.


Git, Just Enough for Today

You'll use six git ideas in this lab. If you already know git, skip this — Week 9 covers it in real depth. If this is new to you:

  • Repository (repo) — the project folder, plus its entire tracked history. spacebar/ becomes your repo the moment you clone it in Part A.
  • Commit — a saved snapshot of a set of changes, with a message describing what and why. git add <file> stages which changes go into the next commit; git commit -m "..." actually saves it.
  • Branch — a named line of development. You start on main; git checkout -b <name> creates a new branch and switches to it, so you can make changes without touching main until you're ready to.
  • Remote — a copy of the repo hosted somewhere else — for this course, on Agent P's Gitea instance. origin is the name git gives by default to the remote you cloned from.
  • Pushgit push origin <branch> sends your local commits to the remote. (You won't need git pull in this lab — nobody else is committing to your repo yet.)
  • Tag — a fixed pointer to one specific commit. This course uses tags to mark exactly which commit counts as "the submission" for a given lab — see "Submitting Your Lab" below.

Two habits worth starting now, both free: run git status before you commit, so nothing unexpected gets swept in, and git log --oneline afterward, so you can see what you actually recorded.


Taking and Saving Screenshots

Several deliverables in this lab ask for a screenshot. Screenshots are captured by your host OS (macOS or Windows), not from inside the Ubuntu terminal — then moved into your repo, which lives inside the Ubuntu filesystem. Save every screenshot into the lab1/ folder in your repo, alongside lab1/submission.md, using the exact filename given at each step.

macOS:

  1. Capture the active window: press Cmd+Shift+4, then press Space, then click the window you want to capture — this grabs the whole window without you having to drag a selection box. (To capture a region instead, press Cmd+Shift+4 and drag.) Either way, the screenshot saves as a .png to your Desktop by default.
  2. Get the file into your repo. Easiest: open your project in VS Code (already connected to your Ubuntu machine via Remote-SSH, per Platform Setup above), then drag the .png straight from Finder into the lab1/ folder in the VS Code Explorer sidebar.
  • Command-line alternative: OrbStack shares your Mac's files into Ubuntu automatically under /mnt/mac. From your Ubuntu terminal:
     mv /mnt/mac/Users/<your-mac-username>/Desktop/Screenshot*.png ~/spacebar/lab1/<name>.png

Windows:

  1. Capture a region: press Win+Shift+S, drag to select the terminal window, then release — this copies the screenshot to your clipboard. Open Paint (search "Paint" in the Start menu), press Ctrl+V to paste, then save as a .png.
  2. Get the file into your repo. Easiest: open your project in VS Code (already connected to your Ubuntu machine via the WSL extension, per Platform Setup above), then drag the .png straight from File Explorer into the lab1/ folder in the VS Code Explorer sidebar.
  • Command-line alternative: WSL2 shares your Windows drives into Ubuntu automatically under /mnt/c. From your Ubuntu terminal:
     mv "/mnt/c/Users/<your-windows-username>/Pictures/<file>.png" ~/spacebar/lab1/<name>.png

Confirm each screenshot actually landed in the right place before committing: ls lab1/.


Part A — Terminal and Project Setup

Goal: Confirm you can navigate the command line and get Spacebar running locally.

  1. Open a terminal (Ubuntu via Orb on Mac, or WSL2 on Windows).
  1. Clone your repository using the command you copied from Agent P above (see "SSH Key Setup and Repository Access"), with spacebar added as the destination directory:
   git clone ssh://git@ssh.git.agent-p.org:2224/<your-course-and-section>/<your-repo-slug>.git spacebar
   cd spacebar
   npm install

Verify the checkout before making changes. The commit or tag should match the staff-pinned value announced for your group:

   git rev-parse HEAD
   git status

Do not run npm audit fix in the pinned baseline. It can rewrite the lockfile and change the experiment everyone is meant to share; dependency auditing and remediation belong to the later supply-chain work.

  1. Install and start PostgreSQL — Spacebar will not boot without it.
   sudo apt update
   sudo apt install -y postgresql
   sudo systemctl start postgresql
   sudo systemctl enable postgresql   # optional: start automatically on every VM boot

On Windows WSL2, you can install it but you may need to start it each time you restart WSL:

Ubuntu's default PostgreSQL install creates a postgres role with no password and only local "peer" authentication — that won't work with the postgres://user:password@host:port/db connection string Spacebar expects. Give it a password and create the database:

   sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'postgres';"
   sudo -u postgres createdb spacebar

(A password of postgres is fine for a local throwaway dev database. Don't reuse it anywhere that matters!!!)

  1. npm start runs in the foreground and doesn't return your prompt — and you'll want the server running again later in this lab (Part F) and for most labs afterward. Rather than backgrounding it with & (which interleaves its log output with whatever else you're doing in the same terminal — workable, but annoying), open a second terminal tab or pane into the same Ubuntu environment and dedicate it to the running server. Call it your server tab — the instructions below refer back to it.

In your server tab:

   export DATABASE=postgres://postgres:postgres@localhost:5432/spacebar
   export CONFIG_PATH=./config.json
   npm run build
   npm run sync:db
   npm start

Leave this tab open and running. Do the rest of Part A in your original tab.

  1. Back in your original tab, confirm the server is live:
   curl http://localhost:3001/healthz

You should see a response like: OK. Screenshot this and save it as lab1/healthz.png — this is your evidence that the server runs.

  1. npm test starts its own server instance on port 3001 (hardcoded — see scripts/test.js) to run its smoke test. That collides with the one already running in your server tab, so stop it first: switch to your server tab and press Ctrl+C. Then, back in your original tab:
   npm test

npm test is a smoke test: it starts the server, waits for the word "listening" in stdout, and exits. A passing result confirms the server boots without crashing — not that the code is correct. You will add real tests later in the semester. Screenshot the passing output and save it as lab1/npm-test.png.

Once it passes, go back to your server tab and run npm start again (same command as step 4) — you'll want it running for the rest of this lab and most labs afterward. If you skip stopping it, you'll see EADDRINUSE: address already in use :::3001 here, and the smoke test fails.


Part B — Claude Code Installation and LiteLLM Configuration

Goal: Get Claude Code working through the course proxy.

  1. Install Claude Code globally:
   npm install -g @anthropic-ai/claude-code
  1. Configure Claude Code to use the course LiteLLM proxy. Edit (or create) ~/.claude/settings.json:
   {
     "model": "parcc/GLM-5.2",
     "env": {
       "ANTHROPIC_BASE_URL": "https://litellm.parcc.upenn.edu",
       "ANTHROPIC_API_KEY": "<your-course-api-key>",
       "MAX_THINKING_TOKENS": "0"
     }
   }

Replace <your-course-api-key> with the value posted on the course portal. The proxy routes your requests to the nvidia/GLM-5.2-NVFP4 model while enforcing per-student rate limits.

  1. Verify the installation:
   claude --version
   claude "What is 2 + 2?"

You should get a response routed through the proxy. Screenshot this output and save it as lab1/litellm-check.png — it is a required deliverable confirming your LiteLLM routing works.


Part C — Project Initialization with Claude Code

Goal: Use Claude Code to generate an initial CLAUDE.md and understand the project structure.

  1. In the VS Code integrated terminal (Platform Setup, step 9), cd into the root of your cloned Spacebar repository and start Claude Code:
   claude
  1. Inside the Claude Code session, run:
    /init

This scans the repository and generates a CLAUDE.md with a summary of the project structure, key files, and conventions. Review the generated file critically — it will be imperfect. Do not edit it yet: Lab 3 will have you verify and rewrite it properly.

Commit the auto-generated file to a branch called lab1/claude-init — your first real commit of the semester, so worth a git status glance first to confirm you're only about to commit CLAUDE.md:

    git checkout -b lab1/claude-init
    git status
    git add CLAUDE.md
    git commit -m "chore: auto-generated CLAUDE.md from /init"
  1. Ask Claude Code to produce a Mermaid diagram of the main modules:
"Generate a Mermaid diagram showing the top-level modules of this codebase, their responsibilities, and how they communicate with each other."

Copy (or use Claude code to write) the Mermaid source into docs/module-diagram.mmd in your repo. Render it using the Marp/Mermaid VS Code extension, screenshot the rendered diagram, and save the screenshot as lab1/module-diagram.png.


Part D — Understanding Discord Servers via the Agent

Goal: Use Claude Code to learn the domain model, and practice critical evaluation of what it tells you.

  1. Use Claude Code to get a thorough explanation of the Discord/guild domain model:
"Using this codebase as a reference, explain in detail how a Discord server (called a 'guild' in the API) works: the data model, the hierarchy of guilds → channels → messages → roles → permissions, how real-time events are dispatched to clients, and how the permission system determines what each user can see and do. Cite specific files and functions from this codebase where relevant."
  1. Read the response critically. Identify:
  • Two claims you can verify by looking directly at the source files. Verify them. Quote the relevant file path and line number.
  • Two claims you cannot easily verify (or that seem uncertain). Note why they are uncertain — for example: "The agent says X, but I couldn't find the relevant code in the file it cited."

Write this up as a short annotation — a few sentences per claim is enough.

Why this matters: This is the core skill of the course. An LLM produces confident, plausible output. Plausible ≠ correct. The discipline of checking specific claims against the actual source — rather than accepting the summary — is what separates an engineer from someone who delegates without understanding.


Part E — CI Bootstrap

Goal: Put a CI workflow in place on day one. This workflow will grow with the course — right now it just proves the code compiles and boots.

  1. Create .github/workflows/ci.yml with the following content:
name: CI
on: [push, pull_request]

jobs:
  build:
    runs-on: ubuntu-latest
    env:
      DATABASE: postgres://postgres:postgres@postgres:5432/spacebar
    services:
      postgres:
        image: postgres:16
        env:
          POSTGRES_USER: postgres
          POSTGRES_PASSWORD: postgres
          POSTGRES_DB: spacebar
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '22'
      - run: npm install
      - run: npm run build
      - run: npm test
  1. Commit this file on your lab branch and push it to the course Gitea repository. Confirm the green check in the repository's CI/checks view (or the linked staff-configured CI provider). If the repository protects main, do not bypass the protection; use the normal Pull Request workflow.
  1. Break one existing test intentionally (e.g., add throw new Error("intentional break") at the top of any test file). Push; screenshot the red X and save it as lab1/ci-fail.png. Then restore the file, push again, confirm the green check returns, and screenshot that as lab1/ci-pass.png.

The point: CI failing loudly on a broken push is the whole value. The pipeline exists to catch mistakes before they get to main.

    <div class="callout">
    This workflow only proves the server starts. That is intentional — the posture of <em>running something on every push</em> matters more than what it runs today. The pipeline grows with the course: conformance tests in P1, integration tests in Labs 8–10, and additional quality gates in later projects.
    </div>

Part F — Connect a Client and Post Messages

Goal: A success message from /healthz proves the process is alive. It doesn't prove the thing you built is actually a chat server. This part closes that gap — install a Discord-compatible client, connect it to your local instance, and use it the way an actual user would.

Check your server tab from Part A before continuing — if you closed it, restarted your Ubuntu environment, or it's otherwise not running, restart it now (same commands as Part A step 4) and reconfirm with curl http://localhost:3001/healthz. Fermi needs a live server to connect to.

  1. In a separate directory outside your `spacebar/` repo, install [Fermi](https://github.com/MathMan05/Fermi), a lightweight Spacebar-compatible web client:
    cd ~
    git clone https://github.com/MathMan05/Fermi.git
    cd Fermi
    npm install
    npm run build
    npm start

Fermi serves on http://localhost:8080 by default. Open that address in a browser.

    <div class="callout warn">
    Do not try to point the real Discord desktop or web app at Spacebar. Patching Discord's official client to talk to a third-party server is a violation of Discord's Terms of Service. Spacebar-compatible clients like Fermi are built for exactly this use case — use one of them.
    </div>
  1. On Fermi's login page, change the Instance from "Harmony" to "Other Instance" and enter your local server's address (http://localhost:3001).

Client/server compatibility across independent Spacebar-client projects shifts over time, so this step may not work on the first try — treat that as expected, not a sign you did something wrong earlier. If the client can't connect, ask Claude Code: "Fermi at localhost:8080 can't connect to my local Spacebar instance at http://localhost:3001. What request is it making, and what does the server's response look like? Check `src/api/middlewares/CORS.ts` and my `config.json` — is there a configuration mismatch?" Verify whatever the agent tells you against the actual request (the browser's dev-tools Network tab) and the actual source file, and write down what you changed, if anything, to get it working.

(spacebarchat/client, the official React client, is a heavier alternative if you want to try it instead — but it is a React Native / webpack project with a more involved build, and is not required.)

  1. Once connected: create a Guild ("server") from scratch, create a text channel inside it, and post at least three messages through the client's UI.

![Screenshot of the client](images/first-channel.png)

  1. Screenshot the channel with your messages visible and save it as lab1/client-channel.png.

Deliverables

Start from the [Lab 1 submission template](lab-01-submission.md) and copy it to lab1/submission.md in your repo — the same template can also be downloaded from the bottom of the Lab 1 assignment page on Agent P, if that's more convenient than pulling it from this repo. Save every screenshot into lab1/ alongside it, using the exact filenames below, and embed each one in submission.md with Markdown image syntax (![description](filename.png)) — see "Taking and Saving Screenshots" above for how to capture and move them. It should include:

  1. LiteLLM verification: lab1/litellm-check.png — output of claude "What is 2 + 2?" confirming the proxy routing works.
  2. Running server: lab1/healthz.png (curl http://localhost:3001/healthz returning OK) and lab1/npm-test.png (npm test passing).
  3. Module diagram: docs/module-diagram.mmd committed to your repo with the Mermaid source, plus lab1/module-diagram.png — a screenshot of the rendered diagram.
  4. Auto-generated CLAUDE.md: Committed to the lab1/claude-init branch (leave it there; Lab 3 writes its own reference version at lab3/CLAUDE.md rather than overwriting this one). Link to the branch.
  5. Guild explanation annotation: Two verified claims (file:line for each), two uncertain claims (explanation of why).
  6. CI evidence: Link to a repository with the CI workflow committed; lab1/ci-fail.png (red X on a broken push) and lab1/ci-pass.png (green after restore).
  7. One sentence: What does it mean that the CI check runs on every push, not just on main?
  8. Connected client: lab1/client-channel.png — a channel you created in Fermi (or another Spacebar-compatible client) with at least three posted messages visible. If you had to troubleshoot the connection, a short note on what was wrong and how you diagnosed it (agent-assisted or not).

Submitting Your Lab

A tag, not the current state of main, is what actually gets graded — see "Repository and artifact conventions" in [homeworks.md](../homeworks.md) for the full policy.

  1. Confirm lab1/submission.md is complete and every screenshot it links to actually exists in lab1/.
  1. Push your lab1/claude-init branch (from Part C) so the branch link in your submission resolves for grading:
   git push origin lab1/claude-init
  1. Commit and push your submission to main, then tag it:
   git add lab1/
   git commit -m "Submit Lab 1"
   git push origin main
   git tag lab1-submission
   git push origin lab1-submission

A lab with no tag by the deadline is treated as late or incomplete, even if the files exist somewhere in the repo's history.

  1. If you need to fix something before the deadline, commit the fix, push main, then move the tag rather than leaving two conflicting states:
   git tag -d lab1-submission && git push origin :refs/tags/lab1-submission
   git tag lab1-submission && git push origin lab1-submission

Remember the VPN requirement from "SSH Key Setup and Repository Access" above — every git push here needs the Penn VPN if you're off campus.


Grading

Pass/fail. Required to pass:

  • Claude Code routes through LiteLLM (screenshot required).
  • Module diagram is plausible Mermaid (renders without errors; nodes correspond to real src/ directories).
  • /init output is committed to a branch.
  • Guild explanation annotation is substantive — generic observations ("I couldn't verify everything") receive zero credit. Name specific files and lines.
  • CI/checks view shows both a red failure (on a broken push) and a green check (after restore).
  • A connected client shows a real channel with at least three messages (screenshot required). If the connection needed troubleshooting, the write-up names the specific fix, not just "eventually got it working."