icoa-cli 2.15.2 → 2.15.4

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.
@@ -85,6 +85,8 @@ function printQuestion(q, answer) {
85
85
  const answered = Object.keys(state?.answers || {}).length;
86
86
  const help = getHelpState(state);
87
87
  const eliminated = help.eliminated[q.number] || [];
88
+ // Top hint
89
+ console.log(chalk.gray(' Type "back" to pause · Don\'t type "exit" (it quits CLI)'));
88
90
  // Progress bar
89
91
  printQuestionProgress(q.number, total, answered);
90
92
  // Easter egg
@@ -110,14 +112,15 @@ function printQuestion(q, answer) {
110
112
  }
111
113
  }
112
114
  console.log();
113
- // Navigation + help hint
115
+ // Bottom navigation
114
116
  const remaining = help.max - help.used;
115
117
  const helpHint = remaining > 0
116
118
  ? chalk.yellow('help') + chalk.gray(` (${remaining}/${help.max})`)
117
119
  : (help.max < 8 ? chalk.gray('help 0/5 — type ') + chalk.yellow('more help') : chalk.gray('help 0/8'));
118
- console.log(chalk.gray(' Type ') + chalk.white('A') + chalk.gray('/') + chalk.white('B') + chalk.gray('/') + chalk.white('C') + chalk.gray('/') + chalk.white('D') + chalk.gray(' to answer · ') + helpHint +
120
+ console.log(chalk.gray(' ') + chalk.white('A') + chalk.gray('/') + chalk.white('B') + chalk.gray('/') + chalk.white('C') + chalk.gray('/') + chalk.white('D') + chalk.gray(' to answer · ') + helpHint +
119
121
  (q.number > 1 ? chalk.gray(' · ') + chalk.white('prev') : '') +
120
- (q.number < total ? chalk.gray(' · ') + chalk.white('next') : ''));
122
+ (q.number < total ? chalk.gray(' · ') + chalk.white('next') : '') +
123
+ chalk.gray(' · ') + chalk.white('back'));
121
124
  }
122
125
  export function registerExamCommand(program) {
123
126
  const exam = program.command('exam').description('National selection exam');
@@ -128,7 +131,7 @@ export function registerExamCommand(program) {
128
131
  .action(() => {
129
132
  logCommand('exam nations');
130
133
  console.log();
131
- printHeader('ICOA Participating Countries');
134
+ printHeader('ICOA Participating Countries and Regions');
132
135
  console.log();
133
136
  const nations = [
134
137
  ['AU', 'Australia'], ['BR', 'Brazil'], ['CN', 'China'],
@@ -146,8 +149,8 @@ export function registerExamCommand(program) {
146
149
  console.log(row);
147
150
  }
148
151
  console.log();
149
- console.log(chalk.gray(' 40+ countries and regions accredited'));
150
- console.log(chalk.gray(' New country? Contact: accreditation@icoa2026.au'));
152
+ console.log(chalk.gray(' 40+ countries and regions represented'));
153
+ console.log(chalk.gray(' New member? Contact: accreditation@icoa2026.au'));
151
154
  console.log();
152
155
  console.log(chalk.white(' Check exams for your country:'));
153
156
  console.log(chalk.cyan(' exam list AU') + chalk.gray(' exam list PE') + chalk.gray(' exam list CN'));
@@ -212,7 +215,7 @@ export function registerExamCommand(program) {
212
215
  ];
213
216
  });
214
217
  const countries = [...new Set(exams.map((e) => e.country))];
215
- printHeader(country ? `Exams — ${country.toUpperCase()}` : `Available Exams (${countries.length} countries)`);
218
+ printHeader(country ? `Exams — ${country.toUpperCase()}` : `Available Exams (${countries.length} regions)`);
216
219
  printTable(['ID', 'Name', 'Country', 'Questions', 'Duration', 'Status'], rows);
217
220
  console.log();
218
221
  console.log(chalk.gray(' Start: exam start <id>'));
@@ -671,7 +674,7 @@ export function registerExamCommand(program) {
671
674
  console.log(chalk.red.bold(' ctf4ai') + chalk.gray(' Trick the AI — make it say "koala"'));
672
675
  console.log();
673
676
  console.log(chalk.gray(' For national selection exams:'));
674
- console.log(chalk.white(' nations') + chalk.gray(' View all country codes'));
677
+ console.log(chalk.white(' nations') + chalk.gray(' View all participating regions'));
675
678
  console.log(chalk.white(' exam AU') + chalk.gray(' Enter Australia selection exam'));
676
679
  console.log();
677
680
  }
package/dist/repl.js CHANGED
@@ -84,7 +84,7 @@ export async function startRepl(program, resumeMode) {
84
84
  console.log(chalk.red.bold(' CTF4AI') + chalk.gray(' [Day 2] Hack & evaluate AI — adversarial ML, red-teaming'));
85
85
  console.log();
86
86
  console.log(chalk.white(' Sydney, Australia') + chalk.gray(' · Jun 27 - Jul 2, 2026'));
87
- console.log(chalk.gray(' 40+ accredited nations and regions'));
87
+ console.log(chalk.gray(' 40+ countries and regions represented'));
88
88
  console.log();
89
89
  console.log(chalk.cyan(' ─────────────────────────────────────────────────'));
90
90
  console.log();
@@ -318,6 +318,16 @@ export async function startRepl(program, resumeMode) {
318
318
  logCommand(input);
319
319
  // Exit — record, reset terminal colors, and quit
320
320
  if (input === 'exit' || input === 'quit' || input === 'q') {
321
+ // During exam, warn and suggest back instead
322
+ if (getExamState()) {
323
+ console.log();
324
+ console.log(chalk.yellow(' ⚠ "exit" will close ICOA CLI entirely.'));
325
+ console.log(chalk.white(' To return to menu without quitting, type: ') + chalk.bold.cyan('back'));
326
+ console.log(chalk.gray(' Your exam progress is auto-saved.'));
327
+ console.log();
328
+ rl.prompt();
329
+ return;
330
+ }
321
331
  // stopLogSync();
322
332
  recordExit();
323
333
  console.log(chalk.gray(' Session saved. Use ') + chalk.white('icoa --resume') + chalk.gray(' to continue.'));
@@ -325,6 +335,21 @@ export async function startRepl(program, resumeMode) {
325
335
  realExit(0);
326
336
  return;
327
337
  }
338
+ // "back" — return to main menu (clear exam state for demo, keep for real)
339
+ if (input === 'back') {
340
+ const state = getExamState();
341
+ if (state) {
342
+ console.log();
343
+ console.log(chalk.gray(' Exam paused. Your progress is saved.'));
344
+ console.log(chalk.white(' Resume: exam q 1') + chalk.gray(' · ') + chalk.white('exam review') + chalk.gray(' · ') + chalk.white('exam submit'));
345
+ console.log();
346
+ }
347
+ else {
348
+ console.log(chalk.gray(' Already at main menu.'));
349
+ }
350
+ rl.prompt();
351
+ return;
352
+ }
328
353
  // Help — during exam, route to exam help; otherwise show REPL help
329
354
  if (input === 'help' || input === '?') {
330
355
  if (getExamState()) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "icoa-cli",
3
- "version": "2.15.2",
3
+ "version": "2.15.4",
4
4
  "description": "ICOA CLI — The world's first CLI-native CTF competition terminal",
5
5
  "type": "module",
6
6
  "bin": {