From 3e29ec5cf09ebbf1fb61eb6df2dee24542ffd1df Mon Sep 17 00:00:00 2001 From: Gwyneth Pena-Siguenza Date: Thu, 28 May 2026 09:31:58 -0400 Subject: [PATCH] Count example verify step in progress Update learner-facing progress to count the example verification as part of the 19 total checks while keeping export and token completion semantics tied to the 18 real challenges. Refresh the CTF test script and docs to match the new 1/19 and 19/19 progress behavior. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../skills/ctf-testing/test_ctf_challenges.sh | 14 +++++-- README.md | 5 ++- gcp/README.md | 2 +- verify/src/verify/commands.py | 38 ++++++++++++------- 4 files changed, 38 insertions(+), 21 deletions(-) diff --git a/.github/skills/ctf-testing/test_ctf_challenges.sh b/.github/skills/ctf-testing/test_ctf_challenges.sh index 9a43c52..25a29dc 100644 --- a/.github/skills/ctf-testing/test_ctf_challenges.sh +++ b/.github/skills/ctf-testing/test_ctf_challenges.sh @@ -147,7 +147,7 @@ if [[ -f "${REBOOT_MARKER}" ]]; then EXPECTED=$(cat "$PROGRESS_SNAPSHOT") ACTUAL=$(sort -u /var/ctf/completed_challenges 2>/dev/null | wc -l) if [ "$ACTUAL" -ge "$EXPECTED" ]; then - _pass "Progress persisted after reboot ($ACTUAL challenges)" + _pass "Progress persisted after reboot ($ACTUAL checks)" else _fail "Progress lost after reboot (expected ${EXPECTED}, got ${ACTUAL})" fi @@ -192,6 +192,12 @@ else exit 1 fi +if echo "${VERIFY_OUTPUT}" | grep -q "1/19"; then + _pass "verify progress counts the example check" +else + _fail "verify progress did not show 1/19 after the example check" +fi + if [[ -f /var/ctf/ctf_start_time ]]; then _pass "Timer starts after first numeric verify command" else @@ -580,10 +586,10 @@ fi _section "VERIFICATION TOKEN TEST" PROGRESS=$(verify progress 2>&1) -if echo "${PROGRESS}" | grep -q "18/18"; then - _pass "All 18 challenges completed" +if echo "${PROGRESS}" | grep -q "19/19"; then + _pass "All 19 progress checks completed" else - _fail "Not all challenges completed: ${PROGRESS}" + _fail "Not all progress checks completed: ${PROGRESS}" fi EXPORT_OUT=$(verify export testuser 2>&1) || true diff --git a/README.md b/README.md index 0084325..11d1008 100644 --- a/README.md +++ b/README.md @@ -59,8 +59,9 @@ Save the token it generates — you'll need it to verify your progress at [learn - `verify time` shows **wall clock elapsed time** (not active keyboard time). - The timer starts when you first submit a challenge with `verify `. -- The timer freezes on your first successful `verify export` after reaching 18/18. -- Run `verify 0 CTF{example}` early. The example challenge is part of verify progress tracking. +- Progress tracks 19 total checks: the example verification plus the 18 real challenges. +- After `verify 0 CTF{example}`, `verify progress` should show `1/19`. +- The timer freezes on your first successful `verify export` after you've solved all 18 real challenges. ### Troubleshooting Your Token diff --git a/gcp/README.md b/gcp/README.md index 318649b..6fb0b8b 100644 --- a/gcp/README.md +++ b/gcp/README.md @@ -53,7 +53,7 @@ ## Timer Behavior -`verify time` uses wall clock elapsed time. The timer starts on your first challenge submission and freezes on your first successful `verify export` after 18/18. +`verify time` uses wall clock elapsed time. The timer starts on your first challenge submission and freezes on your first successful `verify export` after you've solved all 18 real challenges. ## Cleaning Up diff --git a/verify/src/verify/commands.py b/verify/src/verify/commands.py index a25bc1a..a53b05f 100644 --- a/verify/src/verify/commands.py +++ b/verify/src/verify/commands.py @@ -68,15 +68,25 @@ ] -def completed_count() -> int: +EXAMPLE_CHALLENGE_NUMBER = 0 +MAX_CHALLENGE_NUMBER = len(CHALLENGE_NAMES) - 1 +REAL_CHALLENGE_COUNT = MAX_CHALLENGE_NUMBER +TOTAL_PROGRESS_CHECKS = len(CHALLENGE_NAMES) + + +def completed_progress_count() -> int: + return len(read_completed()) + + +def completed_challenge_count() -> int: completed = read_completed() - return max(len(completed - {0}), 0) + return max(len(completed - {EXAMPLE_CHALLENGE_NUMBER}), 0) def show_progress() -> None: - count = completed_count() - console.print(f"Flags Found: {count}/18") - if count == 18: + count = completed_progress_count() + console.print(f"Flags Found: {count}/{TOTAL_PROGRESS_CHECKS}") + if count == TOTAL_PROGRESS_CHECKS: console.print("Congratulations! You've completed all challenges!") @@ -98,7 +108,7 @@ def elapsed_seconds() -> int | None: def freeze_end_time_on_export() -> None: if END_TIME_FILE.exists(): return - if completed_count() >= 18: + if completed_challenge_count() >= REAL_CHALLENGE_COUNT: END_TIME_FILE.write_text(f"{int(time.time())}\n") END_TIME_FILE.chmod(0o666) @@ -114,8 +124,8 @@ def format_elapsed(seconds: int, *, include_seconds: bool) -> str: def check_flag(state: CtfState, challenge_num: str, submitted_flag: str) -> int: init_timer() - if not challenge_num.isdigit() or not 0 <= int(challenge_num) <= 18: - console.print("✗ Invalid challenge number. Use 0-18.") + if not challenge_num.isdigit() or not 0 <= int(challenge_num) <= MAX_CHALLENGE_NUMBER: + console.print(f"✗ Invalid challenge number. Use 0-{MAX_CHALLENGE_NUMBER}.") return 1 num = int(challenge_num) @@ -158,8 +168,8 @@ def show_list() -> int: def show_hint(num_text: str | None) -> int: - if num_text is None or not num_text.isdigit() or int(num_text) > 18: - console.print("Usage: verify hint [0-18]") + if num_text is None or not num_text.isdigit() or int(num_text) > MAX_CHALLENGE_NUMBER: + console.print(f"Usage: verify hint [0-{MAX_CHALLENGE_NUMBER}]") return 1 num = int(num_text) console.print("======================================") @@ -171,10 +181,10 @@ def show_hint(num_text: str | None) -> int: def export_certificate(state: CtfState, github_username: str | None) -> int: - count = completed_count() - if count < 18: - console.print("Complete all 18 challenges to earn your certificate!") - console.print(f"Current progress: {count}/18") + count = completed_challenge_count() + if count < REAL_CHALLENGE_COUNT: + console.print(f"Complete all {REAL_CHALLENGE_COUNT} challenges to earn your certificate!") + console.print(f"Current progress: {count}/{REAL_CHALLENGE_COUNT}") return 1 if not github_username: