Skip to content

The Graduation Gate and the Bug in the Original

Every visible target line in the original dashboard this course is re-platformed from, the chart's target marker, the report text's "Target: 80%", said 80%. Anyone reading that dashboard would reasonably conclude 80% automation was the bar to clear. But the actual graduation-readiness check buried in that program's code tested ai_current >= 70. Seventy, not eighty. The number printed everywhere a human would read it did not match the number the code actually enforced. That is the bug this lesson is about, and the fix.

The "graduation gate" is just this course's term for the check report.py runs against your twelve weeks of logged data to decide whether you've hit the program's targets. Lesson 9 named this lesson's job without doing it: read that gate correctly. Here it is, done properly, including the real inconsistency named above and how the fix landed.

What that inconsistency does to a reader who trusts the dashboard

Nobody reading only the visible target lines in the original program would have known the code would graduate them ten points earlier than the dashboard claimed. That's not a rounding error or a display quirk. It's two different numbers, one shown and one enforced, both claiming to be the same bar.

This is not a hypothetical concern raised for this lesson's sake. It is a real bug in a real prior repo I wrote and ran, billion_tracker.py from the business-transformation-tracker repo, found by rereading my own old code while building the version this course teaches. Lesson 4 already credited that repo's lineage for the five metrics; the graduation logic came from the same place, and it carried this inconsistency until I read the two halves of that program side by side.

The four requirements, and where they live in the code

report.py checks graduation against five constants, not a vibe:

python
GRADUATION_AUTOMATION_TARGET = 70.0
STRETCH_AUTOMATION_TARGET = 80.0
GRADUATION_RECURRING_TARGET = 50.0
GRADUATION_TIME_REDUCTION_TARGET = 50.0
GRADUATION_WEEKS = 12

Four of those five are the actual gate. Automation Index at or above 70%. Time reduction, time_saved_vs_baseline as a share of the Week 1 baseline, at or above 50%. Recurring-revenue percentage at or above 50%. Twelve weeks logged, meaning twelve consecutive rows in transformation-log.jsonl, not twelve weeks of calendar time with gaps in the middle. Clear all four and the script prints "All graduation requirements met." Miss any one and it prints exactly how many remain and, for the metrics that fall short, how far.

STRETCH_AUTOMATION_TARGET is the fifth constant, and it is not part of the gate. It is 80%, ten points above the 70% bar, and it exists to be checked against, reported on, and cleared as a stretch goal after graduation, not before it. That separation, one number that gates and a second number that doesn't, is not how the original program worked, which is exactly the bug named above.

The fix: name both numbers, pick one as the bar

The fix is not "make the dashboard say 70 too" or "make the code check 80." Either single-number fix erases the fact that 80% is a real, meaningful figure worth tracking, it was the original author's aspiration, just not the actual gate. Silently picking one and deleting the other would hide that a decision got made at all.

report.py instead names both numbers and separates their roles, with the reasoning written directly into a code comment rather than left for a reader to reconstruct:

What the comment in report.py actually says, in substance

70% is the graduation bar, the number the four-requirement check tests against. 80% is STRETCH_AUTOMATION_TARGET, reported separately, reached after graduation, never confused with the gate itself. The original program's dashboard showed 80% everywhere a target appeared while its code tested 70. This version does not carry that forward silently.

Read the report output at both ends of a run and the distinction is visible in the text itself, not just in a comment nobody but you will ever open.

Week 4: not graduated, and the report says exactly why

This course's own log has four real weeks in it, the same four from Lessons 5 through 8. Running report.py against that real log, not a hypothetical one, produces this:

Week 4 of 12 Started: 2026-08-17 Latest: 2026-08-17 Automation Index Week 1: 14.6% Week 4: 58.1% Change: +43.6% Graduation target (70%): 11.9% to go Time Liberation Score Hours saved per week vs Week 1: 12.0 Time reduction: 21.8% (target: 50%) Revenue Efficiency Multiple: 1.60x baseline Client Capacity Score: 1.71x baseline Recurring revenue: 25.0% (target: 50%) Graduation readiness [ ] Automation Index >= 70% [ ] Time reduction >= 50% [ ] Recurring revenue >= 50% [ ] 12 weeks logged 4 requirement(s) remaining.

Notice the label on the first line: "Graduation target (70%)," not 80. That label is the fix from the last section, made visible in the actual output a reader sees, not just documented in a comment. All four checkboxes are unchecked, honestly, because none of the four requirements are met yet at Week 4. Automation Index needs 11.9 more points. Time reduction sits at 21.8% against a 50% target, under half of what graduation requires. Recurring revenue sits at 25.0% against 50%. And only 4 of the required 12 weeks are logged, which alone would block graduation even if the other three numbers were already clear.

This is real output from this course's own tracked run, not a constructed example. It is not graduated, and it should not claim to be.

Week 12: what a cleared gate looks like, and why this course cannot show you its own

This course has not run twelve real weeks. Lesson 9 was explicit about that, and this lesson is not going to quietly imply otherwise by only showing passing output. What follows is a hypothetical Week 12, built to show the shape of a graduated report, clearly labeled as illustrative rather than this course's own data:

Week 12 of 12 Automation Index Week 1: 14.6% Week 12: 80.0% Change: +65.5% Stretch target (80%): reached Time Liberation Score Hours saved per week vs Week 1: 30.0 Time reduction: 54.5% (target: 50%) Revenue Efficiency Multiple: 3.96x baseline Client Capacity Score: 4.40x baseline Recurring revenue: 55.0% (target: 50%) Graduation readiness [x] Automation Index >= 70% [x] Time reduction >= 50% [x] Recurring revenue >= 50% [x] 12 weeks logged All graduation requirements met.

Line up the two labels against each other: Week 4's report shows "Graduation target (70%)," and this hypothetical Week 12 shows "Stretch target (80%): reached," a completely different label for a completely different number. That is the fix from the earlier section rendered as actual output, not just a promise about code you can't see. Automation Index in this hypothetical run happens to land exactly on the 80% stretch figure, which is a choice I made in constructing the example to show both labels in one page, not a claim that every graduating run lands there. The four-requirement gate only needs 70%, 50%, 50%, and 12 weeks logged; a run could graduate with Automation Index at 71% and never touch the stretch target at all.

One automation number, two separate roles

Why this bug mattered enough to fix rather than leave alone

A ten-point gap between a shown target and an enforced one is not cosmetic. It changes what a reader believes they've agreed to. Someone running the original program toward what they read as an 80% bar could have graduated at 70% without ever noticing the number that actually decided it, or, worse, could have kept pushing for two more months chasing a bar the code had already cleared for them. Neither outcome is what a graduation gate is supposed to produce. The point of naming a specific threshold at all is so a reader can trust the number they're reading is the number being enforced.

ConstantValueRole
GRADUATION_AUTOMATION_TARGET70.0Gates. Part of the four-requirement check.
STRETCH_AUTOMATION_TARGET80.0Does not gate. Reported separately, reached after graduation.
GRADUATION_TIME_REDUCTION_TARGET50.0Gates.
GRADUATION_RECURRING_TARGET50.0Gates.
GRADUATION_WEEKS12Gates. Consecutive logged weeks, not calendar weeks.

What to actually do with this at Week 12 of your own run

Reading your own report correctly is not "look at the top line and stop." It's a short, specific order, because reading it out of order is exactly how the original program's dashboard misled people:

Read the "Graduation readiness" block first, not the Automation Index line

The four checkboxes are the actual gate. A climbing Automation Index on its own, the way Lesson 5's four weeks climbed from 14.6% to 58.1%, tells you nothing about whether time reduction or recurring revenue are anywhere close, exactly the pattern Lesson 5 flagged when automation outran the other metrics.

Check "12 weeks logged" as its own hard requirement

It does not soften because the other three numbers look strong. A run at Week 8 with all three percentages already cleared still has four requirements remaining, not one, because the week count is separate from every numeric threshold.

Only then look at where Automation Index sits relative to 80%

If it has crossed 70% already, the gate on that metric is clear. 80% past that point is the stretch figure, something to keep reaching for, never something you were required to clear to graduate.

Quick check — In the original business-transformation-tracker program, every visible dashboard line showed an 80% automation target. What did the actual graduation-readiness check in the code test?
Continue to Lesson 11

The gate is defined. Lesson 11 turns twelve weeks of logged data, real or in progress, into something you can actually show someone.

Have a question about this lesson?

Reply here and it goes straight to Rod. Same as replying to one of his emails.