The LIA project: one system, five milestones
420-302-VA · LIA PROJECT · FALL 2026

Stage 4 of 5 · Working · method is what gets graded

Method & repo

Every evaluation focus on the milestones page comes back to method, and method lives in two places: the agreements a pair writes down, and the repo that records everything else. This page is the operating manual for both, assembled from habits the course installed one week at a time, now running together.

Three agreements, in writing

In the repo's README, from Week 11 on, because pairs fail by silence, not by skill:

  1. Boards. Who carries which board between classes, and the handoff rule when plans change. A project whose hardware is "somewhere" is blocked by logistics, the one blocker no studio can fix.
  2. Split. How the work divides: by layer (one owns node and sensing, the other owns Pi and dashboard) or by feature (each owns rungs end to end). Both work; by layer needs the stubs from Week 12 so neither waits, by feature needs stricter contract discipline since both touch every layer. Choose one, write it down, renegotiate out loud if it stops fitting.
  3. Rhythm. A fixed sync: the ten-minute stand-up at each class's start, plus one mid-week check-in with a definite time. Done, next, blocked, one line each in the journal.

The repo's spine

One shared repository, the Week 1 promise at full scale: the project is replicable from the repo, meaning a stranger with the kit could rebuild it from what is committed. The documentation spine your project inherits and extends:

The project repository tree. At the root: README with the pair agreements, config underscore example dot py committed while config dot py is git ignored, node slash for the ESP32 code, pi slash for the broker side programs including app dot py, deploy slash holding the systemd unit files, and docs slash containing topics dot md, requirements dot md with the verification table, tuning dot md, journal dot md, and the deliverable documents. Annotations mark which week each habit came from. project-repo/ ├── README.md ├── config_example.py ├── node/ └── main.py · light_node.py … ├── pi/ └── monitor.py · app.py … ├── deploy/ └── bench-bridge.service └── docs/ └── topics.md · requirements.md · journal.md … pair agreements live hereWeek 11 committed; config.py withsecrets stays git-ignored, Week 9 unit files + install notes,Week 12 the documentation spine:contracts, table, journal, deliverables
The repo a marker can trust. Names may differ; the spine should not. docs/topics.md is the contract file every stub and every half-split reads, and the brief's deliverable documents live beside it in docs/.

The Git rhythm for two

The Week 1 collaboration stack, now load-bearing: a branch per person or per rung, small commits whose messages name causes and rungs, a pull-request review before merging to main, and the conflict ritual when it bites. One rule keeps main precious: main always walks, meaning anything merged has passed the end-to-end check, so main is always the branch a milestone could demo from. Tags mark the gates: d2-skeleton, d3-rung, d4, d5-final.

A git graph with a main line and two short lived branches. Partner A's branch, labelled rung, the settable threshold, leaves main, carries three commits, and returns through a box labelled PR, partner B reviews, end to end check. Partner B's branch, labelled rung, history sparkline, does the same further along. Tags d2 skeleton and d3 rung sit on main. A caption states main always walks: every merge has passed the end to end check. main A · rung: settable threshold PR · B reviews ·end-to-end check B · rung: history sparkline PR · A reviews ·end-to-end check d2-skeleton d3-rung main always walks: every merge has passed the end-to-end check, so any Monday can demo from main.
Short branches, reviewed merges, tagged gates. The reviewer runs the end-to-end check before approving, which is how regressions get caught at the PR instead of at the milestone. The conflict ritual is Week 1's, unchanged; the stand-up's who-owns-which-file line is its prevention.

The verification table

The A2 habit at project scale, living in docs/requirements.md: one row per requirement, filled left to right as the project climbs.

#Requirement (five qualities)How demonstratedDisturbance causedMilestoneStatus
R1Reading on the dashboard is at most 3 s older than the sensor's measurement in normal operationStopwatch: shade sensor, time the page's changeShading, by handD2green · Nov 23
R2When the reading crosses the threshold, the actuator engages within 5 sCause crossing, observe actuator and its log lineThreshold crossing, causedD3green · Nov 30
R3The threshold is settable from the dashboard and takes effect without restartsSet from a phone, re-run R2 at the new valueNew threshold mid-runD4open

The example rows are a shape, not your content; the brief says which deliverables must include the table. Its honesty rule: a row goes green only when the demonstration has actually been run, dated, and any green row can be re-demonstrated on request.

The weekly cycle

  1. Monday, class: stand-up, studio or milestone work, the milestone's demonstration, exit with next week's rung named.
  2. In the week: each partner works their branch; every session ends with a commit, a push, and the two-minute end-to-end check; the mid-week check-in happens at its fixed time.
  3. Before next Monday: PRs reviewed and merged, old rungs re-verified, the verification table and journal updated, main walking.

Checklist

Check yourself

Defend "main always walks" against a partner who finds PRs slow and wants to commit straight to main.
The rule's product is a guarantee: at any moment, main is a state the pair could demo from, which is exactly what a milestone is. Direct commits trade that for speed you mostly do not get back, because an unreviewed break on main blocks both partners until found (and it is found by the next person to pull, at the worst time), while the PR's cost is minutes of a reviewer running the end-to-end check. The compromise that keeps both honest: tiny rungs so branches live hours, not days, and review latency stays short. Slow PRs are a symptom of big rungs, and the fix is the rung size, not the safety rule.
Split by layer or by feature: which creates more pressure on docs/topics.md, and why does the other need stubs more?
By feature pressures the contract file more: both partners modify every layer, so the written contracts are the only thing preventing two divergent ideas of a topic or payload from both reaching main; the file must be updated in the same PR as any contract change. By layer needs stubs more: each partner's layers can only be exercised against the other's, so without mosquitto_pub and curl standing in, each is blocked whenever the other is mid-surgery. Both splits work precisely because the course provides the missing piece for each: a contract file for one, stubs for the other.
Why does the verification table demand a date on every green row, when the status column already says green?
Because green decays. A row verified on November 23 says nothing certain about the system on December 7 unless the demonstration was re-run, and the date is what makes the decay visible: an old date on a row the recent rungs could plausibly have broken is a re-verification prompt, and a cluster of fresh dates before a milestone is the rehearsal record. Undated green collapses "was true once" and "is true now" into one mark, and the difference between those two is precisely what a demo day exposes.