icoa-cli 2.19.26 → 2.19.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,10 +2,13 @@ import chalk from 'chalk';
2
2
  import { logCommand } from '../lib/logger.js';
3
3
  import { printError } from '../lib/ui.js';
4
4
  import { getConfig } from '../lib/config.js';
5
+ import { getRetryQueue } from '../lib/demo-stats.js';
5
6
  import { t } from '../lib/i18n.js';
6
7
  function printDemoReport(ctf4aiSolved, ctf4aiTokens) {
7
8
  const config = getConfig();
8
9
  const modelName = config.geminiModel || 'gemma-4-31b-it';
10
+ const retryQueue = getRetryQueue();
11
+ const hasWrongAnswers = !!(retryQueue && retryQueue.length > 0);
9
12
  console.log();
10
13
  console.log(chalk.cyan(' ═══════════════════════════════════════════════'));
11
14
  console.log(chalk.bold.white(` ${t('reportTitle')}`));
@@ -40,10 +43,25 @@ function printDemoReport(ctf4aiSolved, ctf4aiTokens) {
40
43
  console.log();
41
44
  console.log(chalk.cyan(' ─────────────────────────────────────────────'));
42
45
  console.log();
46
+ // Context framing (moved here from stage 1 end — user has now lived through
47
+ // all three stages, so the "theory vs real competition" callout lands with
48
+ // real meaning).
49
+ console.log(chalk.white(` ${t('theoryDone')}`));
50
+ console.log(chalk.white(` ${t('theoryDone2')}`));
51
+ console.log();
52
+ if (hasWrongAnswers) {
53
+ console.log(chalk.white(' 💪 Want to nail the ones you missed? Type: ') + chalk.bold.cyan('retry'));
54
+ console.log();
55
+ }
56
+ console.log(chalk.cyan(' ─────────────────────────────────────────────'));
43
57
  console.log(chalk.white(` ${t('reportReady')}`));
58
+ if (hasWrongAnswers) {
59
+ console.log(chalk.cyan(' retry') + chalk.gray(` retry the ${retryQueue.length} wrong question${retryQueue.length > 1 ? 's' : ''}`));
60
+ }
61
+ console.log(chalk.white(' back') + chalk.gray(` return to main menu`));
62
+ console.log(chalk.white(' demo') + chalk.gray(` ${t('reportDemo')}`));
44
63
  console.log(chalk.white(' nations') + chalk.gray(` ${t('reportNations')}`));
45
64
  console.log(chalk.white(' about') + chalk.gray(` ${t('reportAbout')}`));
46
- console.log(chalk.white(' demo') + chalk.gray(` ${t('reportDemo')}`));
47
65
  console.log();
48
66
  console.log(chalk.yellow(' ICOA 2026 · Sydney, Australia · Jun 27 - Jul 2'));
49
67
  console.log(chalk.cyan.underline(' https://icoa2026.au'));
@@ -837,6 +837,8 @@ export function registerExamCommand(program) {
837
837
  console.log(chalk.gray(' Sydney, Australia · Jun 27 - Jul 2, 2026'));
838
838
  console.log();
839
839
  console.log(chalk.cyan(' ═══════════════════════════════════════'));
840
+ // Paced reveal: give the user time to absorb each section.
841
+ await sleep(3000);
840
842
  // Per-category breakdown with ASCII progress bars
841
843
  const catEntries = Object.entries(categoryStats);
842
844
  if (catEntries.length > 0) {
@@ -870,6 +872,7 @@ export function registerExamCommand(program) {
870
872
  else {
871
873
  clearRetryQueue();
872
874
  }
875
+ await sleep(3000);
873
876
  // Show wrong answers with explanations
874
877
  if (wrongQuestions.length > 0) {
875
878
  console.log();
@@ -901,38 +904,17 @@ export function registerExamCommand(program) {
901
904
  console.log();
902
905
  console.log(chalk.green(` ${t('perfectScore')}`));
903
906
  }
904
- // Offer retry wrong only
905
- if (wrongQuestions.length > 0) {
906
- console.log();
907
- console.log(chalk.white(' 💪 Want to nail the ones you missed? Type: ') + chalk.bold.cyan('retry'));
908
- }
909
- console.log();
910
- // ─── What is CTF + Dual-track introduction ───
911
- console.log(chalk.white(` ${t('theoryDone')}`));
912
- console.log(chalk.white(` ${t('theoryDone2')}`));
913
- console.log();
914
- console.log(chalk.yellow(` ${t('didYouKnow')}`));
915
- console.log(chalk.gray(` ${t('ctfFlags1')}`));
916
- console.log(chalk.gray(` ${t('ctfFlags2')}`));
917
- console.log(chalk.green(' icoa{example_flag_here}'));
918
- console.log(chalk.gray(` ${t('ctfFlags3')}`));
907
+ // Stage 1 ends here. Retry hint, CTF intro, and dual-track overview
908
+ // are deferred to the final report printed after ctf4ai so the flow
909
+ // feels: theory → ai4ctf → ctf4ai → one combined report + retry/back.
910
+ // The retry queue was already persisted above, so the final report
911
+ // can surface it later via getRetryQueue().
912
+ await sleep(2000);
919
913
  console.log();
920
- console.log(chalk.white(` ${t('twoTracks')}`));
921
- console.log();
922
- console.log(chalk.green.bold(' AI4CTF') + chalk.white(` — ${t('ai4ctfDesc')}`));
914
+ console.log(chalk.cyan(' ─────────────────────────────────────────────'));
915
+ console.log(chalk.white(' Next: ') + chalk.bold.green('ai4ctf') + chalk.gray(` — ${t('ai4ctfDesc')}`));
923
916
  console.log(chalk.gray(` ${t('ai4ctfSub')}`));
924
- console.log();
925
- console.log(chalk.red.bold(' CTF4AI') + chalk.white(` — ${t('ctf4aiDesc')}`));
926
- console.log(chalk.gray(` ${t('ctf4aiSub')}`));
927
- console.log();
928
917
  console.log(chalk.cyan(' ─────────────────────────────────────────────'));
929
- console.log(chalk.white(` ${t('readyToTry')}`));
930
- console.log(chalk.green.bold(' ai4ctf') + chalk.gray(` ${t('ai4ctfDesc')}`));
931
- console.log(chalk.red.bold(' ctf4ai') + chalk.gray(` ${t('ctf4aiDesc')}`));
932
- console.log();
933
- console.log(chalk.gray(` ${t('forNational')}`));
934
- console.log(chalk.white(' nations') + chalk.gray(` ${t('viewRegions')}`));
935
- console.log(chalk.white(' exam AU') + chalk.gray(` ${t('enterExam')}`));
936
918
  console.log();
937
919
  }
938
920
  catch (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "icoa-cli",
3
- "version": "2.19.26",
3
+ "version": "2.19.28",
4
4
  "description": "ICOA CLI — The world's first CLI-native CTF competition terminal",
5
5
  "type": "module",
6
6
  "bin": {