あなたに何かを証明してもらう前に、私たちは自分たちを監査します。
2026年8月15日、私たちは教えているのと同じ試練をレッスンに課しました。git リポジトリ内のすべてのレッスンに対して、18回の独立した監査、修正、検証パスを実行し、実行可能なコードの主張はすべて目視ではなく実際に実行しました。以下がその結果です。
自社レッスンで発見した実際の欠陥
監査人が報告した通りに引用しています。あなたの作品を評価するカリキュラムは、自らの成績表を見せる用意がなければならないため、これらを公開しています。
Without quotes the computer reads Hello and world! as commands to look up, not text to show — and there is no such command, so it errors.
レッスンは誤ったエラーメカニズムを教えていました。壊れたコード print(Hello, world!) は名前検索に到達しません。Python は「!」で SyntaxError を出して停止します。私たち自身のアドバイス(「エラーメッセージを読む」)に従う学習者は、画面がレッスンと矛盾しているのを見ることになります。
✓ 真の仕組みを教えるために書き直し、python3で両方のバリアントを実行して検証しました。
# your code here
すべてのラボのスターターには、インデントされた「# your code here」マーカーが付いていました。まったくの初心者がそのインデントで入力すると、インデントが教えられる前にIndentationErrorが発生します。
✓ 9つのスターターすべてを修正し、スターター版と修正版を実行して、意図した失敗と成功を確認しました。
Name the two structural errors in how the rubric was applied.
タスクは2つのエラーを求めていましたが、レッスン自身の回答は3つを挙げています。
✓ タスクと回答を一貫して番号を付け直しました。
まだお客様の声はありませんし、作り上げるつもりもありません。私たちが持っているのは、まず私たち自身に適用された基準そのものです。独立した検証者、実行された証拠、そしてあなたが到着する前に公開したゲートです。最初のコホートが証明を提出したとき、ここには引用ではなく、彼らの台帳が置かれるでしょう。
全73件 — 公開され、隠されたものはありません。
上記の3つが見出しです。ここに、監査が私たち自身のレッスンで見つけたすべての欠陥があります。重大度でフィルタリングし、テキストを検索し、逐語的な引用と修正を読んでください。これは、すべてのコースがあなたに届く前にクリアする基準です。
CRITICALyour-first-program
“Without quotes the computer reads Hello and world! as commands to look up, not text to show — and there is no such command, so it errors.”
The debug fix teaches a name-lookup (NameError) story, but print(Hello, world!) is unparseable because of the !, so Python raises SyntaxError before any name lookup — directly contradicting what the learner sees on screen.
Rewrote the fix to the true mechanism: the ! makes the line unparseable so Python stops with a SyntaxError before running anything.
CRITICAL01-problem-frame
“{ lines: [6], label: 'Decision + deadline'”
The code-walkthrough highlights the wrong line for 5 of 6 steps (each offset +2), so "Decision + deadline" lights the constraint line, "Feared failure" an empty line, and "Reversibility" an HTML comment — teaching false label-to-content mappings.
Renumbered all six steps to the actual 1-based lines of FRAME_MEMO_TEMPLATE and re-verified each mapping.
CRITICAL08-testa-proof
“The Lesson 06 injected failure was stale prices. 10k sampled reads, 0 mismatches over 24h — this proves the injected failure does not occur. The module closes its own loop.”
False recap of the module's own content: L06's injected failure was the downstream cache eviction, not stale prices (a side example). The capstone claims to close a loop it never closes.
Rewrote PROOF_SECTION to prove the rollback decision (p99 < 350ms on v2.3.9 through the next peak), genuinely closing L06's downstream-cause failure.
CRITICAL14-package-evidence
“because the commit history makes it impossible to fake”
Taught three times, but git author/committer dates are arbitrarily settable and history is rewritable, so a local commit proves nothing about when a prediction was made — the exact skepticism the lesson claims git defeats.
Replaced with the honest push-to-remote version in all three locations (remote received timestamp / PR history), softening to "hard to dispute once pushed".
HIGHbuild-a-tiny-program
“Your program defines a function and CALLS it (Lesson 7)”
Functions are Lesson 8, not 7 (Lesson 7 is Loops); the checklist uses stale 8-lesson numbering from before Reading Input was inserted, contradicting the lesson's own diagram ("L8").
Changed "(Lesson 7)" to "(Lesson 8)".
HIGHbuild-a-tiny-program
“It uses an if INSIDE the loop to count only the passing scores (Lessons 4 & 6)”
if/elif/else is Lesson 5 and loops is Lesson 7; Lessons 4 and 6 are Reading Input and Lists, so a learner is sent to the wrong lessons, contradicting the capstone diagram.
Changed "(Lessons 4 & 6)" to "(Lessons 5 & 7)".
HIGHtypes-and-data
“'2' + '3' produces 5, not '23' — values are converted, not concatenated”
The verification item states something literally false in Python — '2' + '3' is '23', not 5 — and contradicts the lesson's own pretest reveal on its central concept.
Reworded to "total_quantity(['2','3']) returns 5 — elements are converted with int() before summing, never concatenated".
HIGH02-diagnostic-route
“description: 'B: compare newest index vs DB timestamp'”
The diagram attributes the timestamp-compare kill-test to Hypothesis B, but the lesson's own memo and Lesson 4 assign it to Hypothesis A (lag) — scrambling the running example in the lesson about mapping kill-tests to hypotheses.
Changed the node description to "A: compare newest index vs DB timestamp" (A is the surviving cause).
HIGH03-system-map
“[Client] --query-------- + (reads here)”
The exemplar text System Map misdraws the read path: the caret lands inside [Index Worker] not [Search Index], and the query connector dangles into empty space — contradicting the walkthrough and the verification item that a peer can trace one request end-to-end.
Redrew the read path so caret and connector both align under [Search Index] (column 89), preserving line count.
HIGH07-tradeoff-decision
“B: flag not wired for payments (the L06 failure)”
The memo exemplar attributes the unwired-payment-flag risk to L06's injected failure, but it is the L05 rejected-option reason; L06's injected failure is the downstream cache eviction — the section contradicts itself 8 lines later.
Changed to "B: flag not wired for payments (the L05 rejected-option risk)".
HIGH07-tradeoff-decision
“Risk if wrong: 256KB limit -> alert at 200KB”
Presented as gold-standard fact, but AWS raised the SQS maximum message payload from 256 KiB to 1 MiB on Aug 4, 2025 — a paid learner would repeat a stale "SQS has a 256KB limit" claim.
Replaced with "256KiB default msg-size cap (raisable to 1MiB) -> alert at 200KB", per the Aug 2025 AWS increase.
HIGH08-testa-proof
“Prove the caching decision. Watch the strongest available mode get selected, the L06 failure closed, and confidence calibrated to the evidence.”
The file promises every lesson grows the same memo; L05–L07 grow the ROLLBACK memo, but the L08 walkthrough proves the CACHING decision from side examples, so the "complete four-part artifact" spans two different scenarios.
Rewrote PROOF_SECTION and the walkthrough to the rollback decision, keeping caching numbers only in the compare block where they started.
HIGH08-testa-proof
“(Proves the L06 stale-price failure absent.)”
The same false L06 attribution is embedded in the memo text learners are told to copy, asserting L06's failure was stale prices when it was the downstream eviction.
Rewrote the memo contract check to the downstream-cause failure as part of the rollback rewrite.
HIGH10-review-rubric
“diluted into a 7.5 average that rounds up to 90”
False arithmetic in the answer-key fix text: a 7.5/10 average is 75/100, not 90. The fix endorses the 7.5-to-90 jump as mere rounding in a lesson about honest scoring.
Reworded the fix to flag the 7.5-to-90 jump as a third error (75/100, not rounding).
HIGH14-package-evidence
“{ lines: [6], label: 'The claim — a proof, not a topic'”
The entire hero walkthrough is off by one (authored 0-based, renderer 1-based): "The claim" highlights the date heading, and "The commit that makes it un-fakeable" never lights the git commit line its note describes.
Shifted every step +1 to [7], [8], [9], [10], [14,15,16] (the extra 16 covers the new git push line).
HIGH16-capstone-rehearsal
“lines: [12, 13, 14, 15, 16, 17, 18, 19], label: 'The honest gate, AND-ed'”
The note calls every_claim_names_proof the through-line, but the highlight covers only six criteria and excludes line 20 (every_claim_names_proof) — the visual contradicts its own caption in the capstone hero artifact.
Extended the highlight to [12..20] so every_claim_names_proof is lit.
HIGH16-capstone-rehearsal
“{ lines: [20], label: 'One REPAIR closes it'”
The final two steps are off by one (0-based authored): "One REPAIR closes it" highlights the criterion line instead of the gate comment (line 21), and "Commit the whole packet" lights git add but never the git commit line.
Changed [20] to [21] and [22,23] to [23,24].
SYSTEMICall 9 first-steps lab starters
“ # your code here”
The "# your code here" marker is indented two spaces at top level; a beginner who types code at that indent gets IndentationError — before indentation has been taught. Appears in all 9 starters.
Dedented the marker to column 0 via replace_all across all 9 occurrences.
MEDIUMbooleans-and-logic
“but it prints nothing — or errors — instead”
The debug symptom hedges that the code might print nothing, but if age = 18: ALWAYS raises SyntaxError — "prints nothing" is impossible and muddies the taught = vs == distinction.
Changed the symptom to state it gives a SyntaxError every time when Run is pressed.
MEDIUMbooleans-and-logic
“What do and / or / not each do to True/False values?”
The sprint-contract and teachback ask learners to explain and/or/not, but the lesson body only mentions them in a single compare-caption sentence — no concept, example, lab, or quiz coverage.
Added a tip callout teaching and/or/not with runnable examples (sign-in, weekend, not is_raining) plus a lab pointer.
MEDIUMbuild-a-tiny-program
“It loops over the list once, with an accumulator set up before the loop (Lessons 2 & 6)”
Under the shipped numbering Loops is Lesson 7 (Lesson 6 is Lists); the accumulator-before-loop pattern is Lessons 2 & 7.
Changed "(Lessons 2 & 6)" to "(Lessons 2 & 7)".
MEDIUMbuild-a-tiny-program
“It computes the average AFTER the loop and formats output with f-strings (Lessons 3 & 6)”
Computing after the loop is Lesson 7 material, not Lesson 6 (Lists); the "6" is stale pre-insertion numbering.
Changed "(Lessons 3 & 6)" to "(Lessons 3 & 7)".
MEDIUMinput-validation
“check: "rejected '25'"”
A degenerate validator that rejects EVERYTHING passes the automated check, because the harness output still contains the "rejected '25'" substring even when valid input 25 is also rejected.
Made the harness record accepted/rejected outcomes for [25, '25', -3, 200] and assert a computed "PASS: True" (25 accepted AND the rest rejected).
MEDIUMinput-validation
“hours: 1,”
The course row seeds hours: 1 while the file seeds nine lessons at 75 min each (~11.25 h), understating the course by an order of magnitude on the learner-facing card.
Set hours to 11 (9 x 75 min = 675 min = 11.25 h).
MEDIUMerror-handling
“check: 'error surfaced: cannot divide by zero'”
An implementation that ALWAYS raises and never divides passes the check — safe_divide(10, 2) never returns 5.0, yet the checkpoint substring still appears, so the happy path is unenforced.
Harness now computes ok = (safe_divide(10, 2) == 5.0) before the error case and asserts a combined "PASS: True".
MEDIUMtypes-and-data
“'2'+'3' must give 5, not '23'”
Same literal falsehood in the lab summary: '2'+'3' evaluates to '23', so the sentence asserts an untrue evaluation on the exact expression the lesson teaches.
Reworded to "the elements '2' and '3' must contribute 5 to the sum, not concatenate to '23'".
MEDIUMfiles-and-io
“raises → still closes”
The diagram routes a missing-file (FileNotFoundError from open) to a "Handle closed" node claiming close is "guaranteed on every path", but a failed open never acquires a handle, so nothing is closed.
Routed the missing-file branch to a new "noopen" outcome and scoped "Handle closed" to paths where open succeeded.
MEDIUM01-problem-frame
“Sections 2–5 are added in Lessons 2, 3, 4 and the capstone.”
The memo template promises five sections and implies a fifth lesson, but the module has exactly four lessons (Lesson 4 IS the capstone) and only four sections — Section 5 never arrives.
Rewrote the comment to "Sections 2–4 are added in Lessons 2, 3 and the capstone (Lesson 4)."
MEDIUM01-problem-frame
“the real decision through tradeoff; flawed”
The file's design statement promises delivery through tradeoff/debug/worked-example blocks, but zero such blocks exist in any of the four lessons even though the schema supports them.
Rewrote the header comment to describe the delivery mechanisms actually used (sprint-contract, compare, code-walkthrough).
MEDIUM02-diagnostic-route
“description: 'A lag · B silent-fail · C stale-cache · D mapping-drop'”
The "Rank hypotheses" node lists four hypotheses including "D mapping-drop", but the memo lists only A/B/C and the run order is A → B → C, so D silently vanishes.
Dropped "· D mapping-drop" so the diagram lists exactly the memo's three hypotheses.
MEDIUM05-tiny-artifact
“It is shrunk to the smallest form a reviewer can inspect in about two minutes, while still carrying the decision, the rejected option, and the proof.”
The correct quiz option is index 1 in ALL four module lessons and is always the longest, most nuanced option — a learner can pass every quiz without reading the lessons.
Shuffled the correct-answer positions across the four lessons and rebalanced option lengths.
MEDIUM06-failure-injection
“Because the purpose is to harden the decision: a realistic failure changes what you would watch and do, while a toy failure lets you feel thorough without improving anything.”
Same module-wide quiz telegraphing: correct answer again at index 1 and again the longest option.
Moved the key to a different index and trimmed the correct option to comparable length.
MEDIUM07-tradeoff-decision
“One option carries only upsides and the other only downsides, and a pro/con tally — not a binding constraint — does the deciding.”
Same module-wide quiz telegraphing: correct answer at index 1 and the longest option, third lesson in a row.
Shuffled key position and balanced option lengths.
MEDIUM08-testa-proof
“It is the strongest mode the situation actually allows (executable > contract > domain check > reviewer rubric), run for real and named so its strength is legible.”
Same module-wide quiz telegraphing: correct answer at index 1 and the longest option — 4 for 4 in this module.
Shuffled key position and balanced option lengths.
MEDIUM10-review-rubric
“Six dimensions score against evidence, but the lowest-capping one sets the ceiling.”
The subtitle says six dimensions but the diagram renders only five nodes — the TRANSFER dimension is missing, so the copy contradicts the visual.
Added a "transfer" node with a pass edge to score, matching the six-dimension rubric.
MEDIUM12-spacing-queue
“recall "shaky", confidence 2 → flagged for repair”
The tax-line card (confidence 2, shaky) is routed to repair, but the artifact's own Rule 3 only routes HIGH-confidence misses to repair and Rule 1 says a miss resets the card — the walkthrough amplifies the contradiction.
Changed the tax-line row to confidence 4 (a genuine confident-but-wrong case Rule 3 covers) and updated the walkthrough note.
MEDIUM12-spacing-queue
“Easy, well-timed effort beats hard, mistimed effort.”
Calling well-timed review "easy" inverts the desirable-difficulty framing the rest of the lesson teaches (retrieval at the point of forgetting is deliberately harder — that difficulty is the mechanism).
Reworded to "Fewer, well-timed, effortful reviews beat many mistimed easy ones."
MEDIUM13-transfer-challenge
“lines: [21, 22, 23, 24, 25, 26], label: 'Skeleton vs load, named'”
The final step claims to show "the two explicit sections" but stops at line 26, leaving line 27 (part of the Domain-load section) dimmed while highlighting blank line 24.
Changed to lines: [21,22,23,25,26,27] so the whole Domain-load section is lit and the blank line is skipped.
MEDIUM13-transfer-challenge
“add a 200ms cache to an AUTH endpoint”
The subtitle says "200ms cache" while the memo below it says "5s TTL"; a learner can read 200ms as a TTL, contradicting the artifact, and 200ms appears nowhere else.
Reworded the subtitle to "add a cache in front of a slow AUTH endpoint to cut load" — no TTL-contradicting number remains.
MEDIUM14-package-evidence
“A failure autopsy committed before the outcome is known is the single most credible artifact you can own”
Near-verbatim duplication: the walkthrough note and the immediately-following callout repeat the same "most credible artifact / timestamp before outcome / git proves order" sentences — copy-paste padding.
Cut the repeated sentences from the callout, leaving it only the net-new advice.
MEDIUM15-unlock-gate
“{ lines: [9, 10], label: 'Why 4/5 does not open it'”
The step highlights a blank line plus the comment but never lights line 11 "GATE: CLOSED" — the payoff line the note ("One required REPAIR closes it") is about.
Changed to lines: [10, 11] so GATE: CLOSED is lit.
MEDIUM15-unlock-gate
“The gate is most valuable exactly when it is most inconvenient.”
Adjacent-block duplication: the compare caption and the callout directly below repeat the same two sentences nearly verbatim.
Kept the sentences in the compare caption only; the callout now carries only its unique content.
MEDIUM16-capstone-rehearsal
“The reviewer objection answered, the cold-domain transfer, and the evidence ledger”
The note folds "Reviewer objection answered" into Module 4's contribution, but the context block and roll-call diagram assign make + defend to Module 2 — the objection-answered piece belongs to Module 2.
Tagged packet item 5 with (Module 2), added it to the m2 diagram node, and relabeled the step "Modules 2 & 4".
MEDIUM16-capstone-rehearsal
“Not six documents — one defensible argument.”
The packet artifact has seven numbered items plus the gate, but the concept block, sprint-contract, and diagram subtitle all say "six documents", omitting the Proof item the artifact and gate criterion require.
Added Proof to the enumerations and changed "not six documents" to "not seven documents".
MEDIUM16-capstone-rehearsal
“the template for every review, promotion, and design defense you will ever walk into”
Verbatim duplication: this exact clause appears in both the final walkthrough step note and the closing transfer block of the same lesson.
Kept it in the transfer block and rewrote the walkthrough note's last sentence.
LOWvariables-and-values
“substitutes 18”
The diagram edge label says print substitutes 18, but the diagram itself never states per_box = 6 or boxes = 3 — those appear only in the later compare block, so 18 dangles unexplained.
Add the values to the diagram (e.g. "substitutes 18 (6 * 3)") or reorder so the compare block precedes the diagram.
LOWreading-input
“it + text and a number before converting”
The compare caption is a near-verbatim copy of the walkthrough caption three blocks earlier, and this copy drops "tries to", leaving an ungrammatical fragment.
Rewrite the compare caption to say something new, or restore "it tries to +" to match the walkthrough.
LOWbooleans-and-logic
“(A single == would test "exactly 18"”
"A single ==" reads as a contradiction (== is the double-equals operator) in a lesson whose whole point is single-= vs double-==, muddling the meaning at the worst moment.
Change to "(== would test 'exactly 18'; >= is the right test for 'adult'.)".
LOWlists
“names[-1] — always the last item”
The diagram legend uses negative indexing before the lesson introduces it (first explained two blocks later), so a beginner hits unexplained syntax.
Reference already-taught syntax in the legend, or move the diagram after the compare block that introduces [-1].
LOWlists
“and ask whether something is in it”
The sprint-contract promises membership testing ("in"), but no lab step, verification item, or quiz ever exercises it — it appears only in prose.
Add a membership step to the lab/verification, or trim the promise from the sprint-contract.
LOWloops
“passes ends at 2”
The compare caption asserts "passes ends at 2" but the block never shows the scores data, so the claimed result is unverifiable from anything on screen.
Show the scores data in the compare lines, or drop the specific count.
LOWbuild-a-tiny-program
“Seven lessons ago you could not print a line.”
Off-by-one from the same stale 8-lesson numbering: this is Lesson 9 and printing was taught in Lesson 1 — eight lessons ago.
Change to "Eight lessons ago you could not print a line."
LOWinput-validation
“Accept ONLY an int in 0..120”
The taught isinstance(value, int) + range pattern accepts True/False because bool is a subclass of int, contradicting "ONLY an int"; the harness never tests a bool so it slips through.
Add a bool guard (not isinstance(value, bool)) or a footnote, and optionally add True to the harness inputs.
LOWinput-validation
“lessonSlug: 'input-validation',”
The --dry-run summary and file header comment describe only lesson 1 while the script now seeds 9 lessons — stale operator-facing output that misreports what --apply will do.
Report all nine lesson slugs/block counts in the dry-run JSON and update the header comment.
LOWfunctions-and-modules
“another module changes the global mid-run”
globals()["discount"] = 7 executes in the same module, not another module — harmless as a simulation but literally inaccurate.
Reword to "simulates another part of the app changing the global mid-run".
LOWcontrol-flow
“you end up processing every other item”
"Every other item" is only true when every item matches the removal condition; in the lesson's own harness data exactly one element is skipped, not alternating items.
Reword to "the loop skips the element right after each removal — consecutive matches slip through unprocessed."
LOWcontrol-flow
“ids = [o["id"] for o in active_orders(data)]”
The unmodified starter stub returns None, so the harness crashes with an unhandled TypeError instead of reaching the graceful "PASS: False" line every other module lab prints.
Guard the harness (result = active_orders(data) or []) or have the stub return orders so the harness reports PASS: False.
LOWtesting-and-debugging
“Each assertion has a clear message”
The verification item is contradicted by the lesson's own worked example: the test_safe_average suite uses bare asserts with no messages, modeling the opposite of the checklist demand.
Add messages to the walkthrough asserts, or soften the checklist item.
LOW04-retrieval-protocol
“This is the step the worked run scored 3/5”
The walkthrough narrates results of "the worked run" (3/5 score, missed Analytics edge) as if the learner has seen it, but no worked-example block exists in this or any prior lesson.
Add a worked-example block, or reword the notes to introduce it as a fresh illustration.
LOW06-failure-injection
“the real bug is still live in v2.3.9.”
The injected premise is a downstream cache eviction (not the release), so the bug is not "in v2.3.9" — it persists regardless of version, and the phrasing can read as contradicting line 5 of the same autopsy.
Reword to "the real (downstream) bug is still live even on v2.3.9."
LOW06-failure-injection
“lines: [5, 6], label: 'Inject the most realistic failure'”
Highlight convention drifts from Lesson 05: L05 steps include the section header line, but all four L06 steps highlight content only, leaving the "## Injected failure" headers un-highlighted.
Include the header lines: [4,5,6], [8,9,10], [12,13,14], [16,17,18].
LOW08-testa-proof
“lines: [12, 13], label: 'Calibrate confidence to the proof'”
Three highlight ranges under-cover: they omit lines 14, 18 and 22 even though the step notes explicitly reference that content.
Change the three steps to lines: [12,13,14], [16,17,18], and [20,21,22].
LOW08-testa-proof
“eyebrow: 'Module 2 · Lesson 8 · 25 min'”
Time contradiction: the eyebrow and est_minutes say 25 min but the capstone sprint-contract says 25–35 min.
Set eyebrow to 30 min and est_minutes: 30, or align the sprint-contract to 20–30 min.
LOW09-explain-back
“Each lesson is rebuilt as the full 15-block world-class sequence”
The maintainer header claims a 15-block sequence naming worked-example/code blocks and calibration/tradeoff blocks, but every lesson actually ships 16 blocks and none of those block types exist.
Rewrite the header to the actual 16-block sequence and delete the false block claims.
LOW09-explain-back
“The reordered move is your weakest part.”
The lesson's thesis is that the SKIPPED moves are weakest, but the caption can be read as "the move you promote to the front is your weakest part" — the opposite of what is taught.
Replace with "The move you skip or bury is your weakest part."
LOW09-explain-back
“language: 'bash',”
All four lessons tag Markdown artifact files (explain_back.md etc.) with language "bash", producing wrong syntax highlighting for quoted strings and numbers.
Use "markdown" (or "text"/"plaintext") as the language for these artifact blocks.
LOW10-review-rubric
“should CAP the artifact (around 78–82)”
When two dimensions fail (caps 82 and 78) the ceiling is the minimum, 78; "around 78–82" implies the cap is a range, softening the hard-cap rule.
Replace with "should CAP the artifact at 78 (the lower of the two failed caps)".
LOW11-repair-loop
“Lesson 3 · 25 min”
The eyebrow states 25 min but the sprint-contract says 25–35 min; the same mismatch exists in lessons 10 and 12.
Change the eyebrows for lessons 10–12 to 30 min (midpoint), or align est_minutes/eyebrow with the sprint-contract range.
LOW12-spacing-queue
“Name the three things it gets wrong.”
The debug task asks for exactly three flaws but the fix enumerates four, so a learner who names the missing-calibration flaw is marked against a key that counts it as a bonus.
Ask "Name the flaws (there are at least three)" or fold the calibration miss into the third numbered flaw.
LOW12-spacing-queue
“Expanding intervals: same-day → day 3 → day 7 → day 30. A miss resets the card.”
The taught schedule starts at "same-day" but the lesson's own spaced-review block ships ["1 day", "3 days", "7 days", "30 days"] — a first-interval mismatch in the lesson about interval discipline.
Aligned the artifact interval prose to the shipped schedule (day 1 → 3 → 7 → 30).
LOW14-package-evidence
“- failure: stale-revoked-session”
The ledger value column is ragged: claim/artifact/proof values start at column 13 but "- failure:" and "- status:" values start at column 12 in a monospace hero artifact.
Pad "- failure:" and "- status:" values to the same value column.
LOW15-unlock-gate
“I hit retrieval, the artifact, the explanation, and the transfer”
The pretest names "the explanation" as a gate criterion, but the hero artifact's five criteria are retrieval / artifact / proof / failure_case / transfer — "explanation" matches none.
Change "the explanation" to "the failure case" to match the artifact's criterion names.
LOW15-unlock-gate
“(concept / build / verification / oral-defense)”
The verification block names a four-route repair taxonomy the lesson never introduces — its artifact and prose only ever route one red to "verification".
Introduce the four repair routes in this lesson, or drop the parenthetical.