chofex-cli 0.1.76 → 0.1.78

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.
Files changed (3) hide show
  1. package/README.md +15 -0
  2. package/dist/index.js +1050 -214
  3. package/package.json +2 -1
package/dist/index.js CHANGED
@@ -340,7 +340,7 @@ var require_errors = __commonJS((exports, module) => {
340
340
  toVercelCliError: () => toVercelCliError
341
341
  });
342
342
  module.exports = __toCommonJS(errors_exports);
343
- var import_promises2 = __require("node:fs/promises");
343
+ var import_promises3 = __require("node:fs/promises");
344
344
 
345
345
  class VercelCliError2 extends Error {
346
346
  constructor(options) {
@@ -378,7 +378,7 @@ var require_errors = __commonJS((exports, module) => {
378
378
  }
379
379
  async function assertValidCwd(cwd) {
380
380
  try {
381
- if (!(await (0, import_promises2.stat)(cwd)).isDirectory()) {
381
+ if (!(await (0, import_promises3.stat)(cwd)).isDirectory()) {
382
382
  throw new Error("not a directory");
383
383
  }
384
384
  } catch {
@@ -2435,12 +2435,12 @@ var require_fsutils = __commonJS((exports, module) => {
2435
2435
  statIfExists: () => statIfExists
2436
2436
  });
2437
2437
  module.exports = __toCommonJS(fsutils_exports);
2438
- var import_promises2 = __require("node:fs/promises");
2438
+ var import_promises3 = __require("node:fs/promises");
2439
2439
  var import_node_path = __toESM2(__require("node:path"));
2440
2440
  var import_errutils = require_errutils();
2441
2441
  async function getCanonicalPath(filePath) {
2442
2442
  try {
2443
- return await (0, import_promises2.realpath)(filePath);
2443
+ return await (0, import_promises3.realpath)(filePath);
2444
2444
  } catch {
2445
2445
  return filePath;
2446
2446
  }
@@ -2463,7 +2463,7 @@ var require_fsutils = __commonJS((exports, module) => {
2463
2463
  }
2464
2464
  async function statIfExists(filePath) {
2465
2465
  try {
2466
- return { stats: await (0, import_promises2.stat)(filePath) };
2466
+ return { stats: await (0, import_promises3.stat)(filePath) };
2467
2467
  } catch (error2) {
2468
2468
  if ((0, import_errutils.isMissingPathError)(error2)) {
2469
2469
  return { missing: true };
@@ -2519,7 +2519,7 @@ var require_safety = __commonJS((exports, module) => {
2519
2519
  getUnsafeStatsReason: () => getUnsafeStatsReason
2520
2520
  });
2521
2521
  module.exports = __toCommonJS(safety_exports);
2522
- var import_promises2 = __require("node:fs/promises");
2522
+ var import_promises3 = __require("node:fs/promises");
2523
2523
  var import_node_path = __toESM2(__require("node:path"));
2524
2524
  var import_errutils = require_errutils();
2525
2525
  var import_fsutils = require_fsutils();
@@ -2602,14 +2602,14 @@ var require_safety = __commonJS((exports, module) => {
2602
2602
  return reason ? `${filePath} is ${reason}` : null;
2603
2603
  }
2604
2604
  async function getUnsafeDirectoryReason(directory3) {
2605
- const stats = await (0, import_promises2.stat)(directory3);
2605
+ const stats = await (0, import_promises3.stat)(directory3);
2606
2606
  if (!stats.isDirectory()) {
2607
2607
  return "not a directory";
2608
2608
  }
2609
2609
  return getUnsafeStatsReason(stats);
2610
2610
  }
2611
2611
  async function getUnsafeFileReason(filePath) {
2612
- const stats = await (0, import_promises2.stat)(filePath);
2612
+ const stats = await (0, import_promises3.stat)(filePath);
2613
2613
  if (!stats.isFile()) {
2614
2614
  return "not a file";
2615
2615
  }
@@ -2666,7 +2666,7 @@ var require_lookup = __commonJS((exports, module) => {
2666
2666
  toVercelCliInvocation: () => toVercelCliInvocation
2667
2667
  });
2668
2668
  module.exports = __toCommonJS(lookup_exports);
2669
- var import_promises2 = __require("node:fs/promises");
2669
+ var import_promises3 = __require("node:fs/promises");
2670
2670
  var import_node_path = __toESM2(__require("node:path"));
2671
2671
  var import_envpath = require_envpath();
2672
2672
  var import_errutils = require_errutils();
@@ -2756,7 +2756,7 @@ var require_lookup = __commonJS((exports, module) => {
2756
2756
  }
2757
2757
  async function canAccessCommandCandidate(candidate, localBinSearch, diagnostics) {
2758
2758
  try {
2759
- await (0, import_promises2.access)(candidate, process.platform === "win32" ? import_promises2.constants.F_OK : import_promises2.constants.F_OK | import_promises2.constants.X_OK);
2759
+ await (0, import_promises3.access)(candidate, process.platform === "win32" ? import_promises3.constants.F_OK : import_promises3.constants.F_OK | import_promises3.constants.X_OK);
2760
2760
  return true;
2761
2761
  } catch (error2) {
2762
2762
  if (!(0, import_errutils.isMissingPathError)(error2)) {
@@ -2773,10 +2773,10 @@ var require_lookup = __commonJS((exports, module) => {
2773
2773
  recordSkippedLocalBin(diagnostics, candidate, "reason" in localBinCandidate ? localBinCandidate.reason : `local bin is not accessible: ${(0, import_errutils.getErrorMessage)(error2)}`);
2774
2774
  }
2775
2775
  async function resolveCommandCandidate(command, candidate, localBinSearch, diagnostics) {
2776
- if (!(await (0, import_promises2.stat)(candidate)).isFile()) {
2776
+ if (!(await (0, import_promises3.stat)(candidate)).isFile()) {
2777
2777
  return null;
2778
2778
  }
2779
- const realPath2 = await (0, import_promises2.realpath)(candidate);
2779
+ const realPath2 = await (0, import_promises3.realpath)(candidate);
2780
2780
  const localBinCandidate = await classifyPathLocalBinCandidate(candidate, localBinSearch.directories);
2781
2781
  if (!localBinCandidate) {
2782
2782
  return { realPath: realPath2, source: "path" };
@@ -2860,7 +2860,7 @@ var require_lookup = __commonJS((exports, module) => {
2860
2860
  async function getProjectRootMarker(directory3) {
2861
2861
  const gitPath = import_node_path.default.join(directory3, ".git");
2862
2862
  try {
2863
- await (0, import_promises2.stat)(gitPath);
2863
+ await (0, import_promises3.stat)(gitPath);
2864
2864
  return { path: gitPath };
2865
2865
  } catch {}
2866
2866
  return null;
@@ -2869,11 +2869,11 @@ var require_lookup = __commonJS((exports, module) => {
2869
2869
  const resolvedFilePath = import_node_path.default.resolve(filePath);
2870
2870
  let canonicalFilePath = resolvedFilePath;
2871
2871
  try {
2872
- canonicalFilePath = import_node_path.default.join(await (0, import_promises2.realpath)(import_node_path.default.dirname(resolvedFilePath)), import_node_path.default.basename(resolvedFilePath));
2872
+ canonicalFilePath = import_node_path.default.join(await (0, import_promises3.realpath)(import_node_path.default.dirname(resolvedFilePath)), import_node_path.default.basename(resolvedFilePath));
2873
2873
  } catch {}
2874
2874
  for (let localBinDirectory of localBinDirectories) {
2875
2875
  try {
2876
- localBinDirectory = await (0, import_promises2.realpath)(localBinDirectory);
2876
+ localBinDirectory = await (0, import_promises3.realpath)(localBinDirectory);
2877
2877
  } catch {}
2878
2878
  if (canonicalFilePath.startsWith(`${localBinDirectory}${import_node_path.default.sep}`)) {
2879
2879
  return localBinDirectory;
@@ -2885,7 +2885,7 @@ var require_lookup = __commonJS((exports, module) => {
2885
2885
  const candidateDirectory = import_node_path.default.resolve(import_node_path.default.dirname(filePath));
2886
2886
  const directories = [candidateDirectory];
2887
2887
  try {
2888
- const canonicalDirectory = await (0, import_promises2.realpath)(candidateDirectory);
2888
+ const canonicalDirectory = await (0, import_promises3.realpath)(candidateDirectory);
2889
2889
  if (!directories.includes(canonicalDirectory)) {
2890
2890
  directories.push(canonicalDirectory);
2891
2891
  }
@@ -2938,8 +2938,8 @@ var require_lookup = __commonJS((exports, module) => {
2938
2938
  }
2939
2939
  async function getLocalVercelPackage(nodeModulesDirectory) {
2940
2940
  const packageDirectory = import_node_path.default.join(nodeModulesDirectory, "vercel");
2941
- const realNodeModulesDirectory = await (0, import_promises2.realpath)(nodeModulesDirectory);
2942
- const realPackageDirectory = await (0, import_promises2.realpath)(packageDirectory);
2941
+ const realNodeModulesDirectory = await (0, import_promises3.realpath)(nodeModulesDirectory);
2942
+ const realPackageDirectory = await (0, import_promises3.realpath)(packageDirectory);
2943
2943
  if (!(0, import_fsutils.isSubpath)(realNodeModulesDirectory, realPackageDirectory)) {
2944
2944
  return {
2945
2945
  reason: "local vercel package resolves outside local node_modules"
@@ -2959,7 +2959,7 @@ var require_lookup = __commonJS((exports, module) => {
2959
2959
  }
2960
2960
  async function readLocalVercelPackageJson(realPackageDirectory) {
2961
2961
  const packageJsonPath = import_node_path.default.join(realPackageDirectory, "package.json");
2962
- const realPackageJsonPath = await (0, import_promises2.realpath)(packageJsonPath);
2962
+ const realPackageJsonPath = await (0, import_promises3.realpath)(packageJsonPath);
2963
2963
  if (!(0, import_fsutils.isSubpath)(realPackageDirectory, realPackageJsonPath)) {
2964
2964
  return { reason: "local vercel package.json resolves outside package" };
2965
2965
  }
@@ -2969,7 +2969,7 @@ var require_lookup = __commonJS((exports, module) => {
2969
2969
  reason: `local vercel package.json is unsafe: ${unsafePackageJsonReason}`
2970
2970
  };
2971
2971
  }
2972
- const packageJson = JSON.parse(await (0, import_promises2.readFile)(realPackageJsonPath, "utf8"));
2972
+ const packageJson = JSON.parse(await (0, import_promises3.readFile)(realPackageJsonPath, "utf8"));
2973
2973
  if (packageJson.name !== "vercel") {
2974
2974
  return {
2975
2975
  reason: 'local vercel package.json does not have name "vercel"'
@@ -2984,7 +2984,7 @@ var require_lookup = __commonJS((exports, module) => {
2984
2984
  return { reason: "local vercel package does not declare bin.vercel" };
2985
2985
  }
2986
2986
  const declaredBinPath = import_node_path.default.resolve(realPackageDirectory, binTarget);
2987
- const realDeclaredBinPath = await (0, import_promises2.realpath)(declaredBinPath);
2987
+ const realDeclaredBinPath = await (0, import_promises3.realpath)(declaredBinPath);
2988
2988
  if (!(0, import_fsutils.isSubpath)(realPackageDirectory, realDeclaredBinPath)) {
2989
2989
  return { reason: "local vercel package bin resolves outside package" };
2990
2990
  }
@@ -2996,7 +2996,7 @@ var require_lookup = __commonJS((exports, module) => {
2996
2996
  }
2997
2997
  if (process.platform !== "win32" && !(0, import_fsutils.isNodeScript)(realDeclaredBinPath)) {
2998
2998
  try {
2999
- await (0, import_promises2.access)(realDeclaredBinPath, import_promises2.constants.F_OK | import_promises2.constants.X_OK);
2999
+ await (0, import_promises3.access)(realDeclaredBinPath, import_promises3.constants.F_OK | import_promises3.constants.X_OK);
3000
3000
  } catch (error2) {
3001
3001
  return {
3002
3002
  reason: `local vercel package bin is not executable: ${(0, import_errutils.getErrorMessage)(error2)}`
@@ -3053,17 +3053,17 @@ var require_exec = __commonJS((exports, module) => {
3053
3053
  var import_node_path = __toESM2(__require("node:path"));
3054
3054
  var import_execa = __toESM2(require_execa());
3055
3055
  var import_envpath = require_envpath();
3056
- var import_errors6 = require_errors();
3056
+ var import_errors7 = require_errors();
3057
3057
  var import_lookup = require_lookup();
3058
3058
  async function execVercelCli2(args2, options = {}) {
3059
3059
  const cwd = import_node_path.default.resolve(options.cwd ?? process.cwd());
3060
- await (0, import_errors6.assertValidCwd)(cwd);
3060
+ await (0, import_errors7.assertValidCwd)(cwd);
3061
3061
  const env = mergeExecEnv(options.env);
3062
3062
  const pathValue = (0, import_envpath.getEnvPath)(env);
3063
3063
  try {
3064
3064
  return await execResolvedVercelCli(args2, options, cwd, env, pathValue);
3065
3065
  } catch (error2) {
3066
- if (error2 instanceof import_errors6.VercelCliError && error2.code === "VERCEL_CLI_NOT_FOUND") {
3066
+ if (error2 instanceof import_errors7.VercelCliError && error2.code === "VERCEL_CLI_NOT_FOUND") {
3067
3067
  (0, import_lookup.clearCachedCliInvocation)(cwd, pathValue);
3068
3068
  return await execResolvedVercelCli(args2, options, cwd, env, pathValue);
3069
3069
  }
@@ -3090,15 +3090,15 @@ var require_exec = __commonJS((exports, module) => {
3090
3090
  const { stdout, stderr } = await (0, import_execa.default)(invocation.command, [...invocation.commandArgs, ...args2], execaOptions);
3091
3091
  return { stdout, stderr, invocation };
3092
3092
  } catch (error2) {
3093
- throw (0, import_errors6.toVercelCliError)(invocation, error2);
3093
+ throw (0, import_errors7.toVercelCliError)(invocation, error2);
3094
3094
  }
3095
3095
  }
3096
3096
  async function resolveInvocationOrThrow(cwd, pathValue) {
3097
3097
  const resolution = await (0, import_lookup.resolveCachedCliInvocation)(cwd, pathValue);
3098
3098
  if (!resolution.found) {
3099
- throw new import_errors6.VercelCliError({
3099
+ throw new import_errors7.VercelCliError({
3100
3100
  code: "VERCEL_CLI_NOT_FOUND",
3101
- message: (0, import_errors6.getCliNotFoundMessage)(resolution.diagnostics)
3101
+ message: (0, import_errors7.getCliNotFoundMessage)(resolution.diagnostics)
3102
3102
  });
3103
3103
  }
3104
3104
  return (0, import_lookup.toVercelCliInvocation)(resolution);
@@ -3139,13 +3139,13 @@ var require_dist = __commonJS((exports, module) => {
3139
3139
  var __toCommonJS = (mod) => __copyProps(__defProp2({}, "__esModule", { value: true }), mod);
3140
3140
  var src_exports = {};
3141
3141
  __export2(src_exports, {
3142
- VercelCliError: () => import_errors6.VercelCliError,
3142
+ VercelCliError: () => import_errors7.VercelCliError,
3143
3143
  clearVercelCliLookupCache: () => import_lookup.clearVercelCliLookupCache,
3144
3144
  execVercelCli: () => import_exec.execVercelCli,
3145
3145
  findVercelCli: () => import_lookup.findVercelCli
3146
3146
  });
3147
3147
  module.exports = __toCommonJS(src_exports);
3148
- var import_errors6 = require_errors();
3148
+ var import_errors7 = require_errors();
3149
3149
  var import_exec = require_exec();
3150
3150
  var import_lookup = require_lookup();
3151
3151
  });
@@ -27642,6 +27642,9 @@ var require_throttleit = __commonJS((exports, module) => {
27642
27642
  }
27643
27643
  module.exports = throttle;
27644
27644
  });
27645
+
27646
+ // src/index.ts
27647
+ import { readFileSync } from "node:fs";
27645
27648
  // ../../node_modules/@effect/platform-node/dist/NodeRuntime.js
27646
27649
  var exports_NodeRuntime = {};
27647
27650
  __export(exports_NodeRuntime, {
@@ -58403,12 +58406,250 @@ var runWith2 = (command, config) => {
58403
58406
  yield* provideContext2(program, services);
58404
58407
  }, catchFilter2((error2) => isCliError(error2) && error2._tag === "ShowHelp" ? succeed2(error2) : fail2(error2), (error2) => andThen4(showHelp(command, error2, config.renderErrors !== false), fail6(error2))), catchFilter2((error2) => config.renderErrors !== false && isCliError(error2) && error2._tag === "UserError" ? succeed2(error2) : fail2(error2), (error2) => andThen4(showUserError(error2), fail6(error2))), catchFilter2((e) => isQuitError(e) ? succeed2(e) : fail2(e), (_) => interrupt2));
58405
58408
  };
58406
- // src/index.ts
58407
- import { readFileSync } from "node:fs";
58409
+ // ../../packages/challenges-contract/src/index.ts
58410
+ var blackBoxChallengeSlug = "black-box";
58411
+ var challengeCatalog = [
58412
+ {
58413
+ slug: blackBoxChallengeSlug,
58414
+ number: 1,
58415
+ code: "01",
58416
+ theme: "Black Box",
58417
+ title: "The Shipping Machine",
58418
+ summary: "Reverse-engineer an undocumented delivery-price service with a limited number of queries, then implement a compatible replacement.",
58419
+ coreSkill: "Reverse engineering & experimentation",
58420
+ format: "accuracy",
58421
+ formatLabel: "Accuracy score",
58422
+ opensAt: "2026-09-18T05:00:00.000Z",
58423
+ queryLimit: 25,
58424
+ evaluationLimit: 3,
58425
+ hiddenSampleSize: 1000,
58426
+ playable: true,
58427
+ solutionKind: "javascript_source"
58428
+ },
58429
+ {
58430
+ slug: "last-mile",
58431
+ number: 2,
58432
+ code: "02",
58433
+ theme: "Last Mile",
58434
+ title: "The Delivery Plan",
58435
+ summary: "Build a delivery plan under capacity, traffic, and deadline constraints. Better heuristics score higher.",
58436
+ coreSkill: "Optimization & heuristics",
58437
+ format: "optimization",
58438
+ formatLabel: "Optimization score",
58439
+ opensAt: "2026-09-25T05:00:00.000Z",
58440
+ queryLimit: 0,
58441
+ evaluationLimit: 3,
58442
+ hiddenSampleSize: 1,
58443
+ playable: false,
58444
+ solutionKind: "json_plan"
58445
+ },
58446
+ {
58447
+ slug: "make-it-fast",
58448
+ number: 3,
58449
+ code: "03",
58450
+ theme: "Make It Fast",
58451
+ title: "The Slow Service",
58452
+ summary: "Produce exactly the same result as a correct but inefficient implementation, ranked by runtime.",
58453
+ coreSkill: "Performance engineering",
58454
+ format: "runtime",
58455
+ formatLabel: "Runtime score",
58456
+ opensAt: "2026-10-02T05:00:00.000Z",
58457
+ queryLimit: 0,
58458
+ evaluationLimit: 3,
58459
+ hiddenSampleSize: 1,
58460
+ playable: false,
58461
+ solutionKind: "javascript_source"
58462
+ },
58463
+ {
58464
+ slug: "power-grid",
58465
+ number: 4,
58466
+ code: "04",
58467
+ theme: "Power Grid",
58468
+ title: "The Dispatch Desk",
58469
+ summary: "Keep a simplified energy grid stable while minimizing cost and blackouts under uncertainty.",
58470
+ coreSkill: "Simulation & decision making",
58471
+ format: "multi_objective",
58472
+ formatLabel: "Multi-objective score",
58473
+ opensAt: "2026-10-09T05:00:00.000Z",
58474
+ queryLimit: 0,
58475
+ evaluationLimit: 3,
58476
+ hiddenSampleSize: 1,
58477
+ playable: false,
58478
+ solutionKind: "javascript_source"
58479
+ },
58480
+ {
58481
+ slug: "agent-arena",
58482
+ number: 5,
58483
+ code: "05",
58484
+ theme: "Agent Arena",
58485
+ title: "The Tool-Using Agent",
58486
+ summary: "Configure an agent that balances accuracy, tool calls, model cost, and latency.",
58487
+ coreSkill: "AI engineering & system design",
58488
+ format: "multi_objective",
58489
+ formatLabel: "Accuracy + cost + latency",
58490
+ opensAt: "2026-10-13T05:00:00.000Z",
58491
+ queryLimit: 0,
58492
+ evaluationLimit: 3,
58493
+ hiddenSampleSize: 1,
58494
+ playable: false,
58495
+ solutionKind: "agent_config"
58496
+ }
58497
+ ];
58498
+ var playableChallenges = challengeCatalog.filter((challenge) => challenge.playable);
58499
+ var ChallengeSlugSchema = exports_Schema.Literals([
58500
+ "black-box",
58501
+ "last-mile",
58502
+ "make-it-fast",
58503
+ "power-grid",
58504
+ "agent-arena"
58505
+ ]);
58506
+ var ShipmentSchema = exports_Schema.Struct({
58507
+ distanceKm: exports_Schema.Number.pipe(exports_Schema.check(exports_Schema.isBetween({ minimum: 0.1, maximum: 2000 }))),
58508
+ weightKg: exports_Schema.Number.pipe(exports_Schema.check(exports_Schema.isBetween({ minimum: 0.1, maximum: 500 }))),
58509
+ hour: exports_Schema.Int.pipe(exports_Schema.check(exports_Schema.isBetween({ minimum: 0, maximum: 23 }))),
58510
+ fragile: exports_Schema.Boolean,
58511
+ express: exports_Schema.Boolean
58512
+ });
58513
+ var JavascriptSourceSolutionSchema = exports_Schema.Struct({
58514
+ kind: exports_Schema.Literal("javascript_source"),
58515
+ source: exports_Schema.String.pipe(exports_Schema.check(exports_Schema.isMinLength(1), exports_Schema.isMaxLength(32768)))
58516
+ });
58517
+ var ChallengeObservationSchema = exports_Schema.Struct({
58518
+ sequence: exports_Schema.Number,
58519
+ input: exports_Schema.Unknown,
58520
+ output: exports_Schema.Unknown,
58521
+ createdAt: exports_Schema.String
58522
+ });
58523
+ var ChallengeScoreSchema = exports_Schema.Struct({
58524
+ accuracy: exports_Schema.Number,
58525
+ exactCount: exports_Schema.Number,
58526
+ sampleSize: exports_Schema.Number,
58527
+ meanError: exports_Schema.Number,
58528
+ queriesUsed: exports_Schema.Number,
58529
+ runtimeMs: exports_Schema.Number
58530
+ });
58531
+ var ChallengeProgressStatus = exports_Schema.Literals([
58532
+ "not_started",
58533
+ "in_progress",
58534
+ "evaluated"
58535
+ ]);
58536
+ var ParticipantChallengeProgressSchema = exports_Schema.Struct({
58537
+ slug: ChallengeSlugSchema,
58538
+ title: exports_Schema.String,
58539
+ theme: exports_Schema.String,
58540
+ status: ChallengeProgressStatus,
58541
+ open: exports_Schema.Boolean,
58542
+ playable: exports_Schema.Boolean,
58543
+ queriesUsed: exports_Schema.Number,
58544
+ queriesLimit: exports_Schema.Number,
58545
+ evaluationsUsed: exports_Schema.Number,
58546
+ evaluationsLimit: exports_Schema.Number,
58547
+ bestAccuracy: exports_Schema.optional(exports_Schema.Number),
58548
+ bestExactCount: exports_Schema.optional(exports_Schema.Number),
58549
+ shareCode: exports_Schema.optional(exports_Schema.String),
58550
+ rank: exports_Schema.optional(exports_Schema.Number)
58551
+ });
58552
+ var ChallengeCatalogItemSchema = exports_Schema.Struct({
58553
+ slug: ChallengeSlugSchema,
58554
+ number: exports_Schema.Number,
58555
+ code: exports_Schema.String,
58556
+ theme: exports_Schema.String,
58557
+ title: exports_Schema.String,
58558
+ summary: exports_Schema.String,
58559
+ coreSkill: exports_Schema.String,
58560
+ format: exports_Schema.Literals([
58561
+ "accuracy",
58562
+ "optimization",
58563
+ "runtime",
58564
+ "multi_objective"
58565
+ ]),
58566
+ formatLabel: exports_Schema.String,
58567
+ opensAt: exports_Schema.String,
58568
+ queryLimit: exports_Schema.Number,
58569
+ evaluationLimit: exports_Schema.Number,
58570
+ playable: exports_Schema.Boolean,
58571
+ open: exports_Schema.Boolean,
58572
+ rankingPath: exports_Schema.String
58573
+ });
58574
+ var ChallengeEvaluationSummarySchema = exports_Schema.Struct({
58575
+ accuracy: exports_Schema.Number,
58576
+ exactCount: exports_Schema.Number,
58577
+ sampleSize: exports_Schema.Number,
58578
+ meanError: exports_Schema.Number,
58579
+ queriesUsed: exports_Schema.Number,
58580
+ runtimeMs: exports_Schema.Number,
58581
+ shareCode: exports_Schema.String,
58582
+ rank: exports_Schema.optional(exports_Schema.Number),
58583
+ percentile: exports_Schema.optional(exports_Schema.Number),
58584
+ createdAt: exports_Schema.String
58585
+ });
58586
+ var ChallengeAttemptViewSchema = exports_Schema.Struct({
58587
+ challenge: ChallengeCatalogItemSchema,
58588
+ progress: ParticipantChallengeProgressSchema,
58589
+ observations: exports_Schema.Array(ChallengeObservationSchema),
58590
+ latestEvaluation: exports_Schema.optional(ChallengeEvaluationSummarySchema),
58591
+ aiAllowed: exports_Schema.Literal(true),
58592
+ localTestHint: exports_Schema.String
58593
+ });
58594
+ var ChallengeQueryResultSchema = exports_Schema.Struct({
58595
+ observation: ChallengeObservationSchema,
58596
+ queriesUsed: exports_Schema.Number,
58597
+ queriesRemaining: exports_Schema.Number,
58598
+ queriesLimit: exports_Schema.Number
58599
+ });
58600
+ var ChallengeLocalTestResultSchema = exports_Schema.Struct({
58601
+ matchedObservations: exports_Schema.Number,
58602
+ observationCount: exports_Schema.Number,
58603
+ accuracy: exports_Schema.Number,
58604
+ meanError: exports_Schema.Number,
58605
+ mismatches: exports_Schema.Array(exports_Schema.Struct({
58606
+ sequence: exports_Schema.Number,
58607
+ expected: exports_Schema.Unknown,
58608
+ actual: exports_Schema.Unknown
58609
+ }))
58610
+ });
58611
+ var ChallengeEvaluationResultSchema = exports_Schema.Struct({
58612
+ accuracy: exports_Schema.Number,
58613
+ exactCount: exports_Schema.Number,
58614
+ sampleSize: exports_Schema.Number,
58615
+ meanError: exports_Schema.Number,
58616
+ queriesUsed: exports_Schema.Number,
58617
+ runtimeMs: exports_Schema.Number,
58618
+ shareCode: exports_Schema.String,
58619
+ rank: exports_Schema.optional(exports_Schema.Number),
58620
+ competitorCount: exports_Schema.optional(exports_Schema.Number),
58621
+ percentile: exports_Schema.optional(exports_Schema.Number),
58622
+ evaluationsUsed: exports_Schema.Number,
58623
+ evaluationsRemaining: exports_Schema.Number,
58624
+ evaluationsLimit: exports_Schema.Number,
58625
+ rankingPath: exports_Schema.String,
58626
+ shareText: exports_Schema.String
58627
+ });
58628
+ var ChallengeRankingEntrySchema = exports_Schema.Struct({
58629
+ rank: exports_Schema.Number,
58630
+ displayName: exports_Schema.String,
58631
+ shareCode: exports_Schema.String,
58632
+ accuracy: exports_Schema.Number,
58633
+ exactCount: exports_Schema.Number,
58634
+ sampleSize: exports_Schema.Number,
58635
+ meanError: exports_Schema.Number,
58636
+ queriesUsed: exports_Schema.Number,
58637
+ runtimeMs: exports_Schema.Number,
58638
+ evaluatedAt: exports_Schema.String
58639
+ });
58640
+ var ChallengeRankingSchema = exports_Schema.Struct({
58641
+ challenge: ChallengeCatalogItemSchema,
58642
+ entries: exports_Schema.Array(ChallengeRankingEntrySchema),
58643
+ competitorCount: exports_Schema.Number
58644
+ });
58645
+ var ChallengeCatalogSchema = exports_Schema.Struct({
58646
+ challenges: exports_Schema.Array(ChallengeCatalogItemSchema)
58647
+ });
58408
58648
 
58409
58649
  // ../../packages/registration-contract/src/index.ts
58410
58650
  var nonBlank = (maximum) => exports_Schema.Trim.pipe(exports_Schema.check(exports_Schema.isMinLength(1), exports_Schema.isMaxLength(maximum)));
58411
58651
  var optionalText = (maximum) => exports_Schema.optional(nonBlank(maximum));
58652
+ var nullableOptionalText = (maximum) => exports_Schema.optional(exports_Schema.NullOr(nonBlank(maximum)));
58412
58653
  var normalizedString = (normalize2) => exports_Schema.String.pipe(exports_Schema.decode({
58413
58654
  decode: exports_SchemaGetter.transform(normalize2),
58414
58655
  encode: exports_SchemaGetter.transform((value3) => value3)
@@ -58421,6 +58662,7 @@ var url = normalizedString((value3) => {
58421
58662
  }).pipe(exports_Schema.check(exports_Schema.isPattern(/^https?:\/\/[^\s]+$/i, {
58422
58663
  message: "Must be an http or https URL"
58423
58664
  }), exports_Schema.isMaxLength(2048)));
58665
+ var graduationYear = exports_Schema.Int.pipe(exports_Schema.check(exports_Schema.isBetween({ minimum: 1950, maximum: 2100 })));
58424
58666
  var RegistrationStatus = exports_Schema.Literals([
58425
58667
  "draft",
58426
58668
  "submitted",
@@ -58472,7 +58714,7 @@ var applicationInputFields = {
58472
58714
  organization: optionalText(200),
58473
58715
  role: optionalText(120),
58474
58716
  fieldOfStudy: optionalText(160),
58475
- graduationYear: exports_Schema.optional(exports_Schema.Int.pipe(exports_Schema.check(exports_Schema.isBetween({ minimum: 1950, maximum: 2100 })))),
58717
+ graduationYear: exports_Schema.optional(graduationYear),
58476
58718
  shippedProject: nonBlank(2000),
58477
58719
  hackathonProject: nonBlank(2000),
58478
58720
  bio: nonBlank(2000),
@@ -58487,6 +58729,35 @@ var applicationInputFields = {
58487
58729
  };
58488
58730
  var applicationInputFieldNames = Object.keys(applicationInputFields);
58489
58731
  var ApplicationInput = exports_Schema.Struct(applicationInputFields);
58732
+ var applicationDraftInputFields = {
58733
+ firstName: exports_Schema.optional(applicationInputFields.firstName),
58734
+ lastName: exports_Schema.optional(applicationInputFields.lastName),
58735
+ pronouns: nullableOptionalText(50),
58736
+ city: exports_Schema.optional(applicationInputFields.city),
58737
+ organization: nullableOptionalText(200),
58738
+ role: nullableOptionalText(120),
58739
+ fieldOfStudy: nullableOptionalText(160),
58740
+ graduationYear: exports_Schema.optional(exports_Schema.NullOr(graduationYear)),
58741
+ shippedProject: exports_Schema.optional(applicationInputFields.shippedProject),
58742
+ hackathonProject: exports_Schema.optional(applicationInputFields.hackathonProject),
58743
+ bio: exports_Schema.optional(applicationInputFields.bio),
58744
+ githubUrl: exports_Schema.optional(exports_Schema.NullOr(url)),
58745
+ linkedInUrl: exports_Schema.optional(exports_Schema.NullOr(url)),
58746
+ portfolioUrl: exports_Schema.optional(exports_Schema.NullOr(url)),
58747
+ teamPreference: exports_Schema.optional(applicationInputFields.teamPreference),
58748
+ teamName: nullableOptionalText(120),
58749
+ codeOfConductAccepted: exports_Schema.optional(exports_Schema.Boolean),
58750
+ privacyPolicyAccepted: exports_Schema.optional(exports_Schema.Boolean),
58751
+ mediaConsent: exports_Schema.optional(exports_Schema.Boolean)
58752
+ };
58753
+ var applicationDraftInputFieldNames = Object.keys(applicationDraftInputFields);
58754
+ var ApplicationDraftInput = exports_Schema.Struct(applicationDraftInputFields);
58755
+ var ApplicationPartId = exports_Schema.Literals([
58756
+ "identity",
58757
+ "experience",
58758
+ "team",
58759
+ "agreements"
58760
+ ]);
58490
58761
  var acceptedDetailsInputFields = {
58491
58762
  fullName: nonBlank(200),
58492
58763
  phone: nonBlank(32),
@@ -58577,15 +58848,33 @@ var RegistrationViewSchema = exports_Schema.Struct({
58577
58848
  pictureSource: exports_Schema.optional(PictureSource),
58578
58849
  pictureUrl: exports_Schema.optional(exports_Schema.String),
58579
58850
  rejectionReason: exports_Schema.optional(exports_Schema.String),
58580
- submittedAt: exports_Schema.String,
58851
+ codeOfConductAccepted: exports_Schema.Boolean,
58852
+ privacyPolicyAccepted: exports_Schema.Boolean,
58853
+ submittedAt: exports_Schema.optional(exports_Schema.String),
58581
58854
  acceptanceDetailsCompletedAt: exports_Schema.optional(exports_Schema.String),
58582
58855
  createdAt: exports_Schema.String,
58583
- updatedAt: exports_Schema.String
58856
+ updatedAt: exports_Schema.String,
58857
+ challenges: exports_Schema.Array(ParticipantChallengeProgressSchema)
58858
+ });
58859
+ var ApplicationPartSchema = exports_Schema.Struct({
58860
+ id: ApplicationPartId,
58861
+ title: exports_Schema.String,
58862
+ complete: exports_Schema.Boolean,
58863
+ missing: exports_Schema.Array(RequirementSchema)
58584
58864
  });
58585
58865
  var RegistrationRequirementsSchema = exports_Schema.Struct({
58586
- stage: exports_Schema.Literals(["review", "rejected", "accepted", "complete"]),
58866
+ stage: exports_Schema.Literals([
58867
+ "draft",
58868
+ "review",
58869
+ "rejected",
58870
+ "accepted",
58871
+ "complete"
58872
+ ]),
58587
58873
  canSubmitNewApplication: exports_Schema.Boolean,
58588
58874
  canSubmitAcceptedDetails: exports_Schema.Boolean,
58875
+ canSaveDraft: exports_Schema.Boolean,
58876
+ canSubmitApplication: exports_Schema.Boolean,
58877
+ parts: exports_Schema.Array(ApplicationPartSchema),
58589
58878
  missing: exports_Schema.Array(RequirementSchema),
58590
58879
  rejectionReason: exports_Schema.optional(exports_Schema.String)
58591
58880
  });
@@ -59061,7 +59350,8 @@ var sendRequest = (options, path4, init, token) => exports_Effect.tryPromise({
59061
59350
  try: () => {
59062
59351
  const headers = new Headers(init.headers);
59063
59352
  headers.set("accept", "application/json");
59064
- headers.set("authorization", `Bearer ${token}`);
59353
+ if (token)
59354
+ headers.set("authorization", `Bearer ${token}`);
59065
59355
  headers.set("x-request-id", crypto.randomUUID());
59066
59356
  if (init.body !== undefined) {
59067
59357
  headers.set("content-type", "application/json");
@@ -59074,14 +59364,7 @@ var sendRequest = (options, path4, init, token) => exports_Effect.tryPromise({
59074
59364
  },
59075
59365
  catch: (error2) => cliError("NETWORK_ERROR", `Could not reach the registration API: ${String(error2)}`, true)
59076
59366
  });
59077
- var request3 = exports_Effect.fn("apiRequest")(function* (options, path4, init, decodeResponse) {
59078
- const suppliedToken = options.token ?? process.env.CHOFEX_TOKEN;
59079
- let token = yield* resolveAccessToken(suppliedToken);
59080
- let response = yield* sendRequest(options, path4, init, token);
59081
- if (response.status === 401 && !suppliedToken) {
59082
- token = yield* resolveAccessToken(undefined, true);
59083
- response = yield* sendRequest(options, path4, init, token);
59084
- }
59367
+ var decodeHttpBody = exports_Effect.fn("decodeHttpBody")(function* (response, decodeResponse) {
59085
59368
  const body = yield* exports_Effect.tryPromise({
59086
59369
  try: () => response.json(),
59087
59370
  catch: () => cliError("INVALID_API_RESPONSE", `The API returned a non-JSON response (${response.status})`, response.status >= 500)
@@ -59095,25 +59378,564 @@ var request3 = exports_Effect.fn("apiRequest")(function* (options, path4, init,
59095
59378
  }
59096
59379
  return yield* decodeResponse(body).pipe(exports_Effect.mapError((error2) => cliError("INVALID_API_RESPONSE", "The API response did not match protocol version 1", false, { issues: String(error2) })));
59097
59380
  });
59381
+ var request3 = exports_Effect.fn("apiRequest")(function* (options, path4, init, decodeResponse) {
59382
+ const suppliedToken = options.token ?? process.env.CHOFEX_TOKEN;
59383
+ let token = yield* resolveAccessToken(suppliedToken);
59384
+ let response = yield* sendRequest(options, path4, init, token);
59385
+ if (response.status === 401 && !suppliedToken) {
59386
+ token = yield* resolveAccessToken(undefined, true);
59387
+ response = yield* sendRequest(options, path4, init, token);
59388
+ }
59389
+ return yield* decodeHttpBody(response, decodeResponse);
59390
+ });
59391
+ var publicRequest = exports_Effect.fn("publicApiRequest")(function* (options, path4, init, decodeResponse) {
59392
+ const response = yield* sendRequest(options, path4, init);
59393
+ return yield* decodeHttpBody(response, decodeResponse);
59394
+ });
59098
59395
  var decodeCreatedRegistration = exports_Schema.decodeUnknownEffect(ApiSuccessSchema(CreatedRegistrationSchema));
59099
59396
  var decodeBadgeResult = exports_Schema.decodeUnknownEffect(ApiSuccessSchema(BadgeResultSchema));
59100
59397
  var decodeCurrentUser = exports_Schema.decodeUnknownEffect(ApiSuccessSchema(CurrentUserSchema));
59101
59398
  var decodeRegistrationResult = exports_Schema.decodeUnknownEffect(ApiSuccessSchema(RegistrationResultSchema));
59102
59399
  var decodePictureUploadGrant = exports_Schema.decodeUnknownEffect(ApiSuccessSchema(PictureUploadGrantSchema));
59103
59400
  var decodePictureUpload = exports_Schema.decodeUnknownEffect(ApiSuccessSchema(PictureUploadSchema));
59104
- var register = (options, input) => request3(options, "/api/v1/registrations", {
59105
- method: "POST",
59106
- body: JSON.stringify(input)
59107
- }, decodeCreatedRegistration);
59401
+ var decodeChallengeCatalog = exports_Schema.decodeUnknownEffect(ApiSuccessSchema(ChallengeCatalogSchema));
59402
+ var decodeChallengeAttempt = exports_Schema.decodeUnknownEffect(ApiSuccessSchema(ChallengeAttemptViewSchema));
59403
+ var decodeChallengeQuery = exports_Schema.decodeUnknownEffect(ApiSuccessSchema(ChallengeQueryResultSchema));
59404
+ var decodeChallengeTest = exports_Schema.decodeUnknownEffect(ApiSuccessSchema(ChallengeLocalTestResultSchema));
59405
+ var decodeChallengeEvaluation = exports_Schema.decodeUnknownEffect(ApiSuccessSchema(ChallengeEvaluationResultSchema));
59406
+ var decodeChallengeRanking = exports_Schema.decodeUnknownEffect(ApiSuccessSchema(ChallengeRankingSchema));
59108
59407
  var getCurrentUser = (options) => request3(options, "/api/v1/me", { method: "GET" }, decodeCurrentUser);
59109
59408
  var getRegistration = (options) => request3(options, "/api/v1/registration", { method: "GET" }, decodeRegistrationResult);
59110
59409
  var getBadge = (options) => request3(options, "/api/v1/badge", { method: "GET" }, decodeBadgeResult);
59111
59410
  var confirmAttendance = (options, input) => request3(options, "/api/v1/registration/attendance", { method: "PUT", body: JSON.stringify(input) }, decodeRegistrationResult);
59112
59411
  var beginPictureUpload = (options, input) => request3(options, "/api/v1/profile-picture", { method: "POST", body: JSON.stringify(input) }, decodePictureUploadGrant);
59113
59412
  var completePictureUpload = (options, input) => request3(options, "/api/v1/profile-picture", { method: "PUT", body: JSON.stringify(input) }, decodePictureUpload);
59413
+ var saveRegistrationDraft = (options, input) => request3(options, "/api/v1/registration", {
59414
+ method: "PUT",
59415
+ body: JSON.stringify(input)
59416
+ }, decodeRegistrationResult);
59417
+ var submitRegistration = (options) => request3(options, "/api/v1/registration/submit", { method: "POST" }, decodeCreatedRegistration);
59418
+ var listChallenges = (options) => publicRequest(options, "/api/v1/challenges", { method: "GET" }, decodeChallengeCatalog);
59419
+ var getChallengeAttempt = (options, slug) => request3(options, `/api/v1/challenges/${slug}`, { method: "GET" }, decodeChallengeAttempt);
59420
+ var queryChallenge = (options, slug, input) => request3(options, `/api/v1/challenges/${slug}/query`, { method: "POST", body: JSON.stringify(input) }, decodeChallengeQuery);
59421
+ var testChallenge = (options, slug, input) => request3(options, `/api/v1/challenges/${slug}/test`, { method: "POST", body: JSON.stringify(input) }, decodeChallengeTest);
59422
+ var evaluateChallenge = (options, slug, input) => request3(options, `/api/v1/challenges/${slug}/evaluate`, { method: "POST", body: JSON.stringify(input) }, decodeChallengeEvaluation);
59423
+ var getChallengeRanking = (options, slug) => publicRequest(options, `/api/v1/challenges/${slug}/ranking`, { method: "GET" }, decodeChallengeRanking);
59424
+
59425
+ // src/challenge-input.ts
59426
+ import { readFile as readFile3 } from "node:fs/promises";
59427
+ var readStdin = async () => {
59428
+ const chunks = [];
59429
+ for await (const chunk of process.stdin) {
59430
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));
59431
+ }
59432
+ return Buffer.concat(chunks).toString("utf8");
59433
+ };
59434
+ var readTextFile = (path4) => exports_Effect.tryPromise({
59435
+ try: async () => {
59436
+ if (path4 === "-")
59437
+ return readStdin();
59438
+ return readFile3(path4, "utf8");
59439
+ },
59440
+ catch: (error2) => cliError("INVALID_INPUT_FILE", `Could not read ${path4}: ${String(error2)}`)
59441
+ });
59442
+ var javascriptSourceFromPath = (path4) => {
59443
+ if (!path4) {
59444
+ return exports_Effect.fail(cliError("SOURCE_REQUIRED", "Pass --source <file.js> with function calculateShipping(input)"));
59445
+ }
59446
+ return readTextFile(path4).pipe(exports_Effect.map((source) => ({ kind: "javascript_source", source })));
59447
+ };
59448
+ var requiredNumber = (message) => exports_Prompt.text({
59449
+ message,
59450
+ validate: (value3) => {
59451
+ if (value3.trim() === "" || Number.isNaN(Number(value3))) {
59452
+ return exports_Effect.fail("Must be a number");
59453
+ }
59454
+ return exports_Effect.succeed(value3);
59455
+ }
59456
+ });
59457
+ var interactiveShipment = () => exports_Prompt.run(exports_Prompt.all({
59458
+ distanceKm: requiredNumber("Distance (km)"),
59459
+ weightKg: requiredNumber("Weight (kg)"),
59460
+ hour: requiredNumber("Hour (0-23)"),
59461
+ fragile: exports_Prompt.confirm({ message: "Fragile?" }),
59462
+ express: exports_Prompt.confirm({ message: "Express?" })
59463
+ })).pipe(exports_Effect.map((input) => ({
59464
+ distanceKm: Number(input.distanceKm),
59465
+ weightKg: Number(input.weightKg),
59466
+ hour: Number(input.hour),
59467
+ fragile: input.fragile,
59468
+ express: input.express
59469
+ })), exports_Effect.flatMap((input) => exports_Schema.decodeUnknownEffect(ShipmentSchema)(input).pipe(exports_Effect.mapError((error2) => cliError("VALIDATION_ERROR", error2.message)))), exports_Effect.mapError((error2) => {
59470
+ if (error2 instanceof CliError2)
59471
+ return error2;
59472
+ return cliError("PROMPT_CANCELLED", "Interactive input was cancelled");
59473
+ }));
59474
+ var shipmentInput = (path4, flags) => {
59475
+ if (path4) {
59476
+ return readTextFile(path4).pipe(exports_Effect.flatMap((contents) => exports_Effect.try({
59477
+ try: () => JSON.parse(contents),
59478
+ catch: (error2) => cliError("INVALID_INPUT_FILE", `Could not parse JSON shipment: ${String(error2)}`)
59479
+ })), exports_Effect.flatMap((input) => exports_Schema.decodeUnknownEffect(ShipmentSchema)(input).pipe(exports_Effect.mapError((error2) => cliError("VALIDATION_ERROR", error2.message)))));
59480
+ }
59481
+ const hasFlags = flags.distanceKm !== undefined && flags.weightKg !== undefined && flags.hour !== undefined && flags.fragile !== undefined && flags.express !== undefined;
59482
+ if (hasFlags) {
59483
+ return exports_Schema.decodeUnknownEffect(ShipmentSchema)({
59484
+ distanceKm: flags.distanceKm,
59485
+ weightKg: flags.weightKg,
59486
+ hour: flags.hour,
59487
+ fragile: flags.fragile,
59488
+ express: flags.express
59489
+ }).pipe(exports_Effect.mapError((error2) => cliError("VALIDATION_ERROR", error2.message)));
59490
+ }
59491
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
59492
+ return exports_Effect.fail(cliError("INPUT_REQUIRED", "Provide --input shipment.json or --distance, --weight, --hour, --fragile, and --express"));
59493
+ }
59494
+ return interactiveShipment();
59495
+ };
59496
+ var defaultChallengeSlug = "black-box";
59497
+
59498
+ // src/challenge-output.ts
59499
+ var remainingBar = (used, limit) => {
59500
+ if (limit <= 0)
59501
+ return "";
59502
+ const width = 20;
59503
+ const remaining = Math.max(0, limit - used);
59504
+ const filled = Math.round(remaining / limit * width);
59505
+ return `${"█".repeat(filled)}${"░".repeat(width - filled)}`;
59506
+ };
59507
+ var percent = (value3) => `${(value3 * 100).toFixed(2)}%`;
59508
+ var challengeListText = (catalog) => {
59509
+ const lines2 = ["Hack the Andes challenges", ""];
59510
+ for (const challenge of catalog.challenges) {
59511
+ let state = "open";
59512
+ if (!challenge.open)
59513
+ state = `opens ${challenge.opensAt.slice(0, 10)}`;
59514
+ const playable = challenge.playable ? "" : " (coming later)";
59515
+ lines2.push(`${challenge.code} ${challenge.theme} — ${challenge.title}${playable}`);
59516
+ lines2.push(` ${challenge.coreSkill} · ${challenge.formatLabel} · ${state}`);
59517
+ lines2.push(` Ranking: ${challenge.rankingPath}`);
59518
+ lines2.push("");
59519
+ }
59520
+ lines2.push("Play the open challenge: chofex challenge query");
59521
+ return lines2.join(`
59522
+ `);
59523
+ };
59524
+ var challengeShowText = (attempt) => {
59525
+ const { challenge, progress } = attempt;
59526
+ const queryBar = remainingBar(progress.queriesUsed, progress.queriesLimit);
59527
+ const evalBar = remainingBar(progress.evaluationsUsed, progress.evaluationsLimit);
59528
+ const lines2 = [
59529
+ `${challenge.theme} #${challenge.code}`,
59530
+ challenge.title,
59531
+ challenge.summary,
59532
+ "",
59533
+ "AI is allowed. Use ChatGPT, Claude, Codex, Cursor, or any tool you want.",
59534
+ "The hidden rules are personalized to you, so leaked solutions will not match.",
59535
+ "",
59536
+ "Queries remaining",
59537
+ queryBar,
59538
+ `${progress.queriesLimit - progress.queriesUsed} / ${progress.queriesLimit}`,
59539
+ "",
59540
+ "Official evaluations remaining",
59541
+ evalBar,
59542
+ `${progress.evaluationsLimit - progress.evaluationsUsed} / ${progress.evaluationsLimit}`
59543
+ ];
59544
+ if (progress.bestAccuracy !== undefined) {
59545
+ lines2.push("", `Best accuracy ${percent(progress.bestAccuracy)}`);
59546
+ if (progress.rank !== undefined)
59547
+ lines2.push(`Rank #${progress.rank}`);
59548
+ if (progress.shareCode)
59549
+ lines2.push(`Share code #${progress.shareCode}`);
59550
+ }
59551
+ lines2.push("", "Next:", " chofex challenge query", " chofex challenge notebook", " chofex challenge test --source ./shipping.js", " chofex challenge evaluate --source ./shipping.js");
59552
+ return lines2.join(`
59553
+ `);
59554
+ };
59555
+ var challengeQueryText = (result3) => {
59556
+ const remaining = remainingBar(result3.queriesUsed, result3.queriesLimit);
59557
+ return [
59558
+ `Output ${JSON.stringify(result3.observation.output)}`,
59559
+ "",
59560
+ "Queries remaining",
59561
+ remaining,
59562
+ `${result3.queriesRemaining} / ${result3.queriesLimit}`
59563
+ ].join(`
59564
+ `);
59565
+ };
59566
+ var shipmentCells = (observation) => {
59567
+ const input = observation.input;
59568
+ if (typeof input !== "object" || input === null) {
59569
+ return {
59570
+ distance: "",
59571
+ weight: "",
59572
+ hour: "",
59573
+ fragile: "",
59574
+ express: ""
59575
+ };
59576
+ }
59577
+ const record2 = input;
59578
+ return {
59579
+ distance: String(record2.distanceKm ?? ""),
59580
+ weight: String(record2.weightKg ?? ""),
59581
+ hour: String(record2.hour ?? ""),
59582
+ fragile: String(record2.fragile ?? ""),
59583
+ express: String(record2.express ?? "")
59584
+ };
59585
+ };
59586
+ var notebookTableText = (observations) => {
59587
+ if (observations.length === 0) {
59588
+ return "No observations yet. Run `chofex challenge query`.";
59589
+ }
59590
+ const header = "#\tDistance\tWeight\tHour\tFragile\tExpress\tOutput";
59591
+ const rows = observations.map((observation) => {
59592
+ const cells = shipmentCells(observation);
59593
+ return [
59594
+ observation.sequence,
59595
+ cells.distance,
59596
+ cells.weight,
59597
+ cells.hour,
59598
+ cells.fragile,
59599
+ cells.express,
59600
+ JSON.stringify(observation.output)
59601
+ ].join("\t");
59602
+ });
59603
+ return [header, ...rows].join(`
59604
+ `);
59605
+ };
59606
+ var notebookCsvText = (observations) => {
59607
+ const header = "sequence,distanceKm,weightKg,hour,fragile,express,output";
59608
+ const rows = observations.map((observation) => {
59609
+ const cells = shipmentCells(observation);
59610
+ return [
59611
+ observation.sequence,
59612
+ cells.distance,
59613
+ cells.weight,
59614
+ cells.hour,
59615
+ cells.fragile,
59616
+ cells.express,
59617
+ JSON.stringify(observation.output)
59618
+ ].join(",");
59619
+ });
59620
+ return [header, ...rows].join(`
59621
+ `);
59622
+ };
59623
+ var challengeTestText = (result3) => {
59624
+ const lines2 = [
59625
+ "LOCAL TESTS (your notebook only)",
59626
+ `Accuracy ${percent(result3.accuracy)}`,
59627
+ `Exact predictions ${result3.matchedObservations} / ${result3.observationCount}`,
59628
+ `Mean error ${result3.meanError.toFixed(2)}`
59629
+ ];
59630
+ if (result3.mismatches.length > 0) {
59631
+ lines2.push("", "Mismatches:");
59632
+ for (const mismatch of result3.mismatches) {
59633
+ lines2.push(` #${mismatch.sequence} expected ${JSON.stringify(mismatch.expected)} got ${JSON.stringify(mismatch.actual)}`);
59634
+ }
59635
+ }
59636
+ return lines2.join(`
59637
+ `);
59638
+ };
59639
+ var challengeEvaluateText = (result3) => {
59640
+ const lines2 = [
59641
+ "BLACK BOX REPLICATION",
59642
+ `Accuracy ${percent(result3.accuracy)}`,
59643
+ `Exact predictions ${result3.exactCount} / ${result3.sampleSize}`,
59644
+ `Mean error ${result3.meanError.toFixed(2)}`,
59645
+ `Oracle queries used ${result3.queriesUsed}`
59646
+ ];
59647
+ if (result3.rank !== undefined)
59648
+ lines2.push(`Rank #${result3.rank}`);
59649
+ lines2.push(`Official evaluations remaining ${result3.evaluationsRemaining} / ${result3.evaluationsLimit}`, "", result3.shareText);
59650
+ return lines2.join(`
59651
+ `);
59652
+ };
59653
+ var challengeRankingText = (ranking) => {
59654
+ const lines2 = [
59655
+ `${ranking.challenge.theme} — ${ranking.challenge.title}`,
59656
+ `${ranking.competitorCount} official evaluations`,
59657
+ ""
59658
+ ];
59659
+ if (ranking.entries.length === 0) {
59660
+ lines2.push("No official evaluations yet.");
59661
+ return lines2.join(`
59662
+ `);
59663
+ }
59664
+ lines2.push("Rank Accuracy Exact Queries Name");
59665
+ for (const entry of ranking.entries.slice(0, 20)) {
59666
+ const rank = String(entry.rank).padStart(4, " ");
59667
+ const accuracy = percent(entry.accuracy).padStart(8, " ");
59668
+ const exact = `${entry.exactCount}/${entry.sampleSize}`.padStart(11, " ");
59669
+ const queries = String(entry.queriesUsed).padStart(7, " ");
59670
+ lines2.push(`${rank} ${accuracy} ${exact} ${queries} ${entry.displayName} #${entry.shareCode}`);
59671
+ }
59672
+ return lines2.join(`
59673
+ `);
59674
+ };
59675
+ var draftSavedText = (result3) => ["Application draft saved.", registrationPartsText(result3)].join(`
59676
+ `);
59677
+ var registrationPartsText = (result3) => {
59678
+ const parts = result3.requirements.parts ?? [];
59679
+ if (parts.length === 0)
59680
+ return "";
59681
+ const lines2 = ["", "Application parts:"];
59682
+ for (const part of parts) {
59683
+ const mark = part.complete ? "✓" : "○";
59684
+ let detail = "";
59685
+ if (!part.complete && part.missing[0]) {
59686
+ detail = ` — ${part.missing[0].reason}`;
59687
+ }
59688
+ lines2.push(` ${mark} ${part.title}${detail}`);
59689
+ }
59690
+ if (result3.requirements.canSubmitApplication) {
59691
+ lines2.push("", "Ready to submit: chofex register --submit");
59692
+ } else if (result3.requirements.stage === "draft") {
59693
+ lines2.push("", "Continue later with `chofex register`. Progress is saved.");
59694
+ }
59695
+ return lines2.join(`
59696
+ `);
59697
+ };
59698
+
59699
+ // src/cli-root.ts
59700
+ var root = exports_Command.make("chofex").pipe(exports_Command.withSharedFlags({
59701
+ apiUrl: exports_Flag.string("api-url").pipe(exports_Flag.withDefault(config.apiUrl), exports_Flag.withDescription("Registration API base URL")),
59702
+ output: exports_Flag.choice("output", ["human", "json"]).pipe(exports_Flag.withDefault("human"), exports_Flag.withDescription("Output format")),
59703
+ token: exports_Flag.string("token").pipe(exports_Flag.optional, exports_Flag.withDescription("Clerk OAuth token (prefer CHOFEX_TOKEN to avoid shell history)"))
59704
+ }), exports_Command.withDescription("Register for and manage your Chofex hackathon application"));
59705
+
59706
+ // src/output.ts
59707
+ var printJson = (value3) => exports_Effect.sync(() => {
59708
+ process.stdout.write(`${JSON.stringify(value3)}
59709
+ `);
59710
+ });
59711
+ var humanErrorDetails = (details) => {
59712
+ if (details === undefined)
59713
+ return "";
59714
+ if (typeof details === "object" && details !== null && "issues" in details) {
59715
+ const issues = details.issues;
59716
+ if (Array.isArray(issues)) {
59717
+ const decoded = exports_Schema.decodeUnknownResult(exports_Schema.Array(RequirementSchema))(issues);
59718
+ if (exports_Result.isSuccess(decoded) && decoded.success.length > 0) {
59719
+ const lines2 = decoded.success.map((issue) => ` - ${issue.field}: ${issue.reason}`);
59720
+ return `
59721
+ Details:
59722
+ ${lines2.join(`
59723
+ `)}`;
59724
+ }
59725
+ }
59726
+ if (typeof issues === "string")
59727
+ return `
59728
+ Details:
59729
+ ${issues}`;
59730
+ }
59731
+ if (typeof details === "string")
59732
+ return `
59733
+ Details:
59734
+ ${details}`;
59735
+ return `
59736
+ Details:
59737
+ ${JSON.stringify(details, null, 2)}`;
59738
+ };
59739
+ var execute = (mode, operation, human, humanError) => operation.pipe(exports_Effect.flatMap((response) => {
59740
+ if (mode === "json")
59741
+ return printJson(response);
59742
+ return exports_Console.log(human(response.data));
59743
+ }), exports_Effect.catch((error2) => {
59744
+ process.exitCode = exitCodeFor(error2);
59745
+ if (mode === "json") {
59746
+ return printJson({
59747
+ version: 1,
59748
+ ok: false,
59749
+ requestId: error2.requestId,
59750
+ error: {
59751
+ code: error2.code,
59752
+ message: error2.message,
59753
+ retryable: error2.retryable,
59754
+ details: error2.details
59755
+ }
59756
+ });
59757
+ }
59758
+ const customMessage = humanError?.(error2);
59759
+ if (customMessage !== undefined) {
59760
+ return exports_Console.error(`${customMessage}
59761
+ Request ID: ${error2.requestId}`);
59762
+ }
59763
+ const details = humanErrorDetails(error2.details);
59764
+ return exports_Console.error(`Error [${error2.code}]: ${error2.message}${details}
59765
+ Request ID: ${error2.requestId}`);
59766
+ }));
59767
+ var registrationLookupErrorText = (error2) => {
59768
+ if (error2.code !== "REGISTRATION_NOT_FOUND")
59769
+ return;
59770
+ return `No registration found.
59771
+ Next command: chofex register`;
59772
+ };
59773
+ var requirementsText = (result3) => {
59774
+ const { registration, requirements } = result3;
59775
+ if (registration.status === "withdrawn") {
59776
+ return "Application withdrawn. You may submit a new application.";
59777
+ }
59778
+ if (requirements.stage === "complete")
59779
+ return "Attendance details: complete";
59780
+ if (requirements.stage === "draft") {
59781
+ return `Application draft in progress.${registrationPartsText(result3)}`;
59782
+ }
59783
+ if (requirements.stage === "review")
59784
+ return "No action needed while your application is reviewed.";
59785
+ let feedback = "";
59786
+ const rejectionReason = requirements.rejectionReason ?? registration.rejectionReason;
59787
+ if (rejectionReason) {
59788
+ feedback = `
59789
+ Review feedback: ${rejectionReason}`;
59790
+ }
59791
+ let nextCommand = "";
59792
+ if (requirements.stage === "accepted") {
59793
+ nextCommand = `
59794
+ Next command: chofex confirm`;
59795
+ }
59796
+ let missing2 = "";
59797
+ if (requirements.missing.length > 0) {
59798
+ const items = requirements.missing.map((item) => ` - ${item.field}: ${item.reason}`).join(`
59799
+ `);
59800
+ missing2 = `
59801
+ Still required:
59802
+ ${items}`;
59803
+ }
59804
+ return `Next stage: ${requirements.stage}${feedback}${missing2}${nextCommand}`;
59805
+ };
59806
+ var registrationText = (result3) => [
59807
+ `Registration: ${result3.registration.id}`,
59808
+ `Participant: ${result3.registration.firstName} ${result3.registration.lastName}`,
59809
+ `Status: ${result3.registration.status}`,
59810
+ requirementsText(result3)
59811
+ ].join(`
59812
+ `);
59813
+ var createdText = (result3) => {
59814
+ if (result3.registration.status !== "submitted") {
59815
+ return ["Application draft saved.", registrationText(result3)].join(`
59816
+ `);
59817
+ }
59818
+ return ["Application submitted successfully.", registrationText(result3)].join(`
59819
+ `);
59820
+ };
59821
+ var requirementsOnlyText = (result3) => requirementsText(result3);
59822
+ var badgeText = (result3) => {
59823
+ if (result3.url)
59824
+ return result3.url;
59825
+ return "You don't have a badge yet.";
59826
+ };
59827
+
59828
+ // src/challenge-commands.ts
59829
+ var optionalString = (name, description) => exports_Flag.string(name).pipe(exports_Flag.optional, exports_Flag.withDescription(description));
59830
+ var challengeFlag = exports_Flag.string("challenge").pipe(exports_Flag.withDefault(defaultChallengeSlug), exports_Flag.withDescription("Challenge slug (default: black-box)"));
59831
+ var sourceFlag = optionalString("source", "JavaScript file exporting function calculateShipping(input)");
59832
+ var inputFlag = optionalString("input", "JSON file, or - for stdin");
59833
+ var formatFlag = exports_Flag.choice("format", ["table", "json", "csv"]).pipe(exports_Flag.withDefault("table"), exports_Flag.withDescription("Notebook format"));
59834
+ var numberFromOption = (value3) => {
59835
+ if (exports_Option.isNone(value3))
59836
+ return;
59837
+ return Number(value3.value);
59838
+ };
59839
+ var booleanFromOption = (value3) => {
59840
+ if (exports_Option.isNone(value3))
59841
+ return;
59842
+ if (value3.value === "true")
59843
+ return true;
59844
+ if (value3.value === "false")
59845
+ return false;
59846
+ };
59847
+ var listCommand = exports_Command.make("list", {}, exports_Effect.fn("challengeListCommand")(function* () {
59848
+ const options = yield* root;
59849
+ yield* execute(options.output, listChallenges({ apiUrl: options.apiUrl }), challengeListText);
59850
+ })).pipe(exports_Command.withDescription("List mini technical challenges"));
59851
+ var showCommand = exports_Command.make("show", { challenge: challengeFlag }, exports_Effect.fn("challengeShowCommand")(function* ({ challenge }) {
59852
+ const options = yield* root;
59853
+ const token = exports_Option.getOrUndefined(options.token);
59854
+ yield* execute(options.output, getChallengeAttempt({ apiUrl: options.apiUrl, token }, challenge), challengeShowText);
59855
+ })).pipe(exports_Command.withDescription("Show your Black Box status and remaining budget"));
59856
+ var queryCommand = exports_Command.make("query", {
59857
+ challenge: challengeFlag,
59858
+ input: inputFlag,
59859
+ distance: optionalString("distance", "Shipment distance in km"),
59860
+ weight: optionalString("weight", "Shipment weight in kg"),
59861
+ hour: optionalString("hour", "Hour of day, 0-23"),
59862
+ fragile: exports_Flag.choice("fragile", ["true", "false"]).pipe(exports_Flag.optional, exports_Flag.withDescription("Fragile surcharge flag")),
59863
+ express: exports_Flag.choice("express", ["true", "false"]).pipe(exports_Flag.optional, exports_Flag.withDescription("Express surcharge flag"))
59864
+ }, exports_Effect.fn("challengeQueryCommand")(function* ({
59865
+ challenge,
59866
+ input,
59867
+ distance: distance3,
59868
+ weight,
59869
+ hour,
59870
+ fragile,
59871
+ express
59872
+ }) {
59873
+ const options = yield* root;
59874
+ const token = exports_Option.getOrUndefined(options.token);
59875
+ const operation = exports_Effect.gen(function* () {
59876
+ const shipment = yield* shipmentInput(exports_Option.getOrUndefined(input), {
59877
+ distanceKm: numberFromOption(distance3),
59878
+ weightKg: numberFromOption(weight),
59879
+ hour: numberFromOption(hour),
59880
+ fragile: booleanFromOption(fragile),
59881
+ express: booleanFromOption(express)
59882
+ });
59883
+ return yield* queryChallenge({ apiUrl: options.apiUrl, token }, challenge, shipment);
59884
+ });
59885
+ yield* execute(options.output, operation, challengeQueryText);
59886
+ })).pipe(exports_Command.withDescription("Query the undocumented Black Box (uses one request)"), exports_Command.withExamples([
59887
+ {
59888
+ command: "chofex challenge query --distance 10 --weight 3 --hour 14 --fragile false --express false",
59889
+ description: "Spend one oracle query"
59890
+ }
59891
+ ]));
59892
+ var notebookCommand = exports_Command.make("notebook", { challenge: challengeFlag, format: formatFlag }, exports_Effect.fn("challengeNotebookCommand")(function* ({ challenge, format: format6 }) {
59893
+ const options = yield* root;
59894
+ const token = exports_Option.getOrUndefined(options.token);
59895
+ const operation = getChallengeAttempt({ apiUrl: options.apiUrl, token }, challenge);
59896
+ yield* execute(options.output, operation, (attempt) => {
59897
+ if (format6 === "csv")
59898
+ return notebookCsvText(attempt.observations);
59899
+ if (format6 === "json") {
59900
+ return JSON.stringify(attempt.observations, null, 2);
59901
+ }
59902
+ return notebookTableText(attempt.observations);
59903
+ });
59904
+ })).pipe(exports_Command.withDescription("Export Black Box observations as a table, JSON, or CSV"));
59905
+ var testCommand = exports_Command.make("test", { challenge: challengeFlag, source: sourceFlag }, exports_Effect.fn("challengeTestCommand")(function* ({ challenge, source }) {
59906
+ const options = yield* root;
59907
+ const token = exports_Option.getOrUndefined(options.token);
59908
+ const operation = exports_Effect.gen(function* () {
59909
+ const solution = yield* javascriptSourceFromPath(exports_Option.getOrUndefined(source));
59910
+ return yield* testChallenge({ apiUrl: options.apiUrl, token }, challenge, solution);
59911
+ });
59912
+ yield* execute(options.output, operation, challengeTestText);
59913
+ })).pipe(exports_Command.withDescription("Test a replacement against your notebook without consuming an official evaluation"));
59914
+ var evaluateCommand = exports_Command.make("evaluate", { challenge: challengeFlag, source: sourceFlag }, exports_Effect.fn("challengeEvaluateCommand")(function* ({ challenge, source }) {
59915
+ const options = yield* root;
59916
+ const token = exports_Option.getOrUndefined(options.token);
59917
+ const operation = exports_Effect.gen(function* () {
59918
+ const solution = yield* javascriptSourceFromPath(exports_Option.getOrUndefined(source));
59919
+ return yield* evaluateChallenge({ apiUrl: options.apiUrl, token }, challenge, solution);
59920
+ });
59921
+ yield* execute(options.output, operation, challengeEvaluateText);
59922
+ })).pipe(exports_Command.withDescription("Run an official hidden-set evaluation (limited attempts)"));
59923
+ var rankingCommand = exports_Command.make("ranking", { challenge: challengeFlag }, exports_Effect.fn("challengeRankingCommand")(function* ({ challenge }) {
59924
+ const options = yield* root;
59925
+ yield* execute(options.output, getChallengeRanking({ apiUrl: options.apiUrl }, challenge), challengeRankingText);
59926
+ })).pipe(exports_Command.withDescription("Show the public read-only challenge ranking"));
59927
+ var challengeCommand = exports_Command.make("challenge").pipe(exports_Command.withDescription("Play mini technical challenges and inspect public rankings"), exports_Command.withSubcommands([
59928
+ listCommand,
59929
+ showCommand,
59930
+ queryCommand,
59931
+ notebookCommand,
59932
+ testCommand,
59933
+ evaluateCommand,
59934
+ rankingCommand
59935
+ ]));
59114
59936
 
59115
59937
  // src/input.ts
59116
- import { readFile as readFile3 } from "node:fs/promises";
59938
+ import { readFile as readFile4 } from "node:fs/promises";
59117
59939
 
59118
59940
  // src/profile-username-prompt.ts
59119
59941
  var ansi = {
@@ -59321,11 +60143,11 @@ var applicationDefaultsFromRegistration = (registration) => ({
59321
60143
  portfolioUrl: registration.portfolioUrl,
59322
60144
  teamPreference: registration.teamPreference,
59323
60145
  teamName: registration.teamName,
59324
- codeOfConductAccepted: true,
59325
- privacyPolicyAccepted: true,
60146
+ codeOfConductAccepted: registration.codeOfConductAccepted ? true : undefined,
60147
+ privacyPolicyAccepted: registration.privacyPolicyAccepted ? true : undefined,
59326
60148
  mediaConsent: registration.mediaConsent
59327
60149
  });
59328
- var readStdin = async () => {
60150
+ var readStdin2 = async () => {
59329
60151
  const chunks = [];
59330
60152
  for await (const chunk of process.stdin) {
59331
60153
  chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));
@@ -59336,9 +60158,9 @@ var readJsonInput = (path4) => exports_Effect.tryPromise({
59336
60158
  try: async () => {
59337
60159
  let contents;
59338
60160
  if (path4 === "-") {
59339
- contents = await readStdin();
60161
+ contents = await readStdin2();
59340
60162
  } else {
59341
- contents = await readFile3(path4, "utf8");
60163
+ contents = await readFile4(path4, "utf8");
59342
60164
  }
59343
60165
  return JSON.parse(contents);
59344
60166
  },
@@ -59355,7 +60177,7 @@ var validateSemantics = (input, requirements) => {
59355
60177
  issues: requirements
59356
60178
  }));
59357
60179
  };
59358
- var applicationDetailsPrompts = (defaults2) => exports_Prompt.all({
60180
+ var identityPrompts = (defaults2) => exports_Prompt.all({
59359
60181
  firstName: requiredText("First name", applicationInputFields.firstName, defaults2.firstName),
59360
60182
  lastName: requiredText("Last name", applicationInputFields.lastName, defaults2.lastName),
59361
60183
  pronouns: optionalText2("Pronouns (optional)", applicationInputFields.pronouns, defaults2.pronouns),
@@ -59371,7 +60193,9 @@ var applicationDetailsPrompts = (defaults2) => exports_Prompt.all({
59371
60193
  return exports_Effect.succeed(value3);
59372
60194
  return validatePromptValue(applicationInputFields.graduationYear, Number(value3)).pipe(exports_Effect.as(value3));
59373
60195
  }
59374
- }),
60196
+ })
60197
+ });
60198
+ var experiencePrompts = (defaults2) => exports_Prompt.all({
59375
60199
  shippedProject: requiredText("What have you shipped?", applicationInputFields.shippedProject, defaults2.shippedProject),
59376
60200
  hackathonProject: requiredText("What do you want to ship at the hackathon?", applicationInputFields.hackathonProject, defaults2.hackathonProject),
59377
60201
  bio: requiredText("Short bio", applicationInputFields.bio, defaults2.bio),
@@ -59421,8 +60245,47 @@ var requiredAgreement = exports_Effect.fn("requiredAgreement")(function* (name,
59421
60245
  return true;
59422
60246
  return yield* cliError("REGISTRATION_CANCELLED", "Registration cancelled. Your answers were not submitted.");
59423
60247
  });
60248
+ var normalizeDraftFields = (input) => {
60249
+ const normalized = Object.fromEntries(Object.entries(input).filter(([, value3]) => value3 !== undefined).map(([key, value3]) => [key, value3 === "" ? null : value3]));
60250
+ if (typeof input.graduationYear === "string" && input.graduationYear !== "") {
60251
+ normalized.graduationYear = Number(input.graduationYear);
60252
+ }
60253
+ return normalized;
60254
+ };
60255
+ var collectIdentityPart = (defaults2) => exports_Prompt.run(identityPrompts(defaults2)).pipe(exports_Effect.map(normalizeDraftFields), exports_Effect.mapError(() => cliError("PROMPT_CANCELLED", "Interactive input was cancelled")));
60256
+ var collectExperiencePart = (defaults2) => exports_Prompt.run(experiencePrompts(defaults2)).pipe(exports_Effect.map(normalizeDraftFields), exports_Effect.mapError(() => cliError("PROMPT_CANCELLED", "Interactive input was cancelled")));
60257
+ var collectTeamPart = (defaults2) => exports_Effect.gen(function* () {
60258
+ const teamPreference = yield* exports_Prompt.run(teamPreferencePrompt(defaults2.teamPreference));
60259
+ let teamName = null;
60260
+ if (teamPreference === "have_team") {
60261
+ teamName = yield* exports_Prompt.run(requiredText("Team name", applicationInputFields.teamName, defaults2.teamName));
60262
+ }
60263
+ return { teamPreference, teamName };
60264
+ }).pipe(exports_Effect.mapError((error2) => {
60265
+ if (error2 instanceof CliError2)
60266
+ return error2;
60267
+ return cliError("PROMPT_CANCELLED", "Interactive input was cancelled");
60268
+ }));
60269
+ var collectAgreementsPart = (publicBaseUrl, defaults2) => exports_Effect.gen(function* () {
60270
+ const codeOfConductAccepted = yield* requiredAgreement("Terms and Code of Conduct", publicDocumentUrl(publicBaseUrl, "/terms"), defaults2.codeOfConductAccepted);
60271
+ const privacyPolicyAccepted = yield* requiredAgreement("Privacy Policy", publicDocumentUrl(publicBaseUrl, "/privacy"), defaults2.privacyPolicyAccepted);
60272
+ const mediaConsent = yield* exports_Prompt.run(exports_Prompt.confirm({
60273
+ message: "Do you consent to appearing in event media? (optional)",
60274
+ initial: defaults2.mediaConsent ?? false
60275
+ }));
60276
+ return {
60277
+ codeOfConductAccepted,
60278
+ privacyPolicyAccepted,
60279
+ mediaConsent
60280
+ };
60281
+ }).pipe(exports_Effect.mapError((error2) => {
60282
+ if (error2 instanceof CliError2)
60283
+ return error2;
60284
+ return cliError("PROMPT_CANCELLED", "Interactive input was cancelled");
60285
+ }));
59424
60286
  var interactiveApplication = (publicBaseUrl, defaults2) => exports_Effect.gen(function* () {
59425
- const details = yield* exports_Prompt.run(applicationDetailsPrompts(defaults2));
60287
+ const identity3 = yield* exports_Prompt.run(identityPrompts(defaults2));
60288
+ const experience = yield* exports_Prompt.run(experiencePrompts(defaults2));
59426
60289
  const teamPreference = yield* exports_Prompt.run(teamPreferencePrompt(defaults2.teamPreference));
59427
60290
  let teamName;
59428
60291
  if (teamPreference === "have_team") {
@@ -59435,7 +60298,8 @@ var interactiveApplication = (publicBaseUrl, defaults2) => exports_Effect.gen(fu
59435
60298
  initial: defaults2.mediaConsent ?? false
59436
60299
  }));
59437
60300
  return {
59438
- ...details,
60301
+ ...identity3,
60302
+ ...experience,
59439
60303
  teamPreference,
59440
60304
  teamName,
59441
60305
  codeOfConductAccepted,
@@ -59522,6 +60386,12 @@ var inputOrInteractive = (path4, interactive) => {
59522
60386
  }));
59523
60387
  };
59524
60388
  var applicationInput = (path4, publicBaseUrl, defaults2 = {}) => inputOrInteractive(path4, interactiveApplication(publicBaseUrl, defaults2)).pipe(exports_Effect.flatMap((input) => decode2(ApplicationInput, input, applicationInputFieldNames)), exports_Effect.flatMap((input) => validateSemantics(input, applicationSemanticRequirements(input))));
60389
+ var applicationDraftInput = (path4) => {
60390
+ if (!path4) {
60391
+ return exports_Effect.fail(cliError("INPUT_REQUIRED", "Non-interactive use requires --input <file>, or --input - for stdin"));
60392
+ }
60393
+ return readJsonInput(path4).pipe(exports_Effect.flatMap((input) => decode2(ApplicationDraftInput, input, applicationDraftInputFieldNames)));
60394
+ };
59525
60395
  var acceptedDetailsInput = (path4, participationMode, pictures = {}) => inputOrInteractive(path4, interactiveAcceptedDetails(participationMode, pictures)).pipe(exports_Effect.flatMap((input) => decode2(AcceptedDetailsInput, input, acceptedDetailsInputFieldNames)), exports_Effect.flatMap((input) => validateSemantics(input, acceptedDetailsSemanticRequirements(input, participationMode))));
59526
60396
  var picturePathInput = (suppliedPath) => {
59527
60397
  if (suppliedPath)
@@ -59532,121 +60402,8 @@ var picturePathInput = (suppliedPath) => {
59532
60402
  return exports_Prompt.run(requiredText("Path to a JPEG, PNG, or WebP picture (5 MB maximum)", exports_Schema.String.pipe(exports_Schema.check(exports_Schema.isMinLength(1))))).pipe(exports_Effect.mapError(() => cliError("PROMPT_CANCELLED", "Interactive input was cancelled")));
59533
60403
  };
59534
60404
 
59535
- // src/output.ts
59536
- var printJson = (value3) => exports_Effect.sync(() => {
59537
- process.stdout.write(`${JSON.stringify(value3)}
59538
- `);
59539
- });
59540
- var humanErrorDetails = (details) => {
59541
- if (details === undefined)
59542
- return "";
59543
- if (typeof details === "object" && details !== null && "issues" in details) {
59544
- const issues = details.issues;
59545
- if (Array.isArray(issues)) {
59546
- const decoded = exports_Schema.decodeUnknownResult(exports_Schema.Array(RequirementSchema))(issues);
59547
- if (exports_Result.isSuccess(decoded) && decoded.success.length > 0) {
59548
- const lines2 = decoded.success.map((issue) => ` - ${issue.field}: ${issue.reason}`);
59549
- return `
59550
- Details:
59551
- ${lines2.join(`
59552
- `)}`;
59553
- }
59554
- }
59555
- if (typeof issues === "string")
59556
- return `
59557
- Details:
59558
- ${issues}`;
59559
- }
59560
- if (typeof details === "string")
59561
- return `
59562
- Details:
59563
- ${details}`;
59564
- return `
59565
- Details:
59566
- ${JSON.stringify(details, null, 2)}`;
59567
- };
59568
- var execute = (mode, operation, human, humanError) => operation.pipe(exports_Effect.flatMap((response) => {
59569
- if (mode === "json")
59570
- return printJson(response);
59571
- return exports_Console.log(human(response.data));
59572
- }), exports_Effect.catch((error2) => {
59573
- process.exitCode = exitCodeFor(error2);
59574
- if (mode === "json") {
59575
- return printJson({
59576
- version: 1,
59577
- ok: false,
59578
- requestId: error2.requestId,
59579
- error: {
59580
- code: error2.code,
59581
- message: error2.message,
59582
- retryable: error2.retryable,
59583
- details: error2.details
59584
- }
59585
- });
59586
- }
59587
- const customMessage = humanError?.(error2);
59588
- if (customMessage !== undefined) {
59589
- return exports_Console.error(`${customMessage}
59590
- Request ID: ${error2.requestId}`);
59591
- }
59592
- const details = humanErrorDetails(error2.details);
59593
- return exports_Console.error(`Error [${error2.code}]: ${error2.message}${details}
59594
- Request ID: ${error2.requestId}`);
59595
- }));
59596
- var registrationLookupErrorText = (error2) => {
59597
- if (error2.code !== "REGISTRATION_NOT_FOUND")
59598
- return;
59599
- return `No registration found.
59600
- Next command: chofex register`;
59601
- };
59602
- var requirementsText = (result3) => {
59603
- const { registration, requirements } = result3;
59604
- if (registration.status === "withdrawn") {
59605
- return "Application withdrawn. You may submit a new application.";
59606
- }
59607
- if (requirements.stage === "complete")
59608
- return "Attendance details: complete";
59609
- if (requirements.stage === "review")
59610
- return "No action needed while your application is reviewed.";
59611
- let feedback = "";
59612
- const rejectionReason = requirements.rejectionReason ?? registration.rejectionReason;
59613
- if (rejectionReason) {
59614
- feedback = `
59615
- Review feedback: ${rejectionReason}`;
59616
- }
59617
- let nextCommand = "";
59618
- if (requirements.stage === "accepted") {
59619
- nextCommand = `
59620
- Next command: chofex confirm`;
59621
- }
59622
- let missing2 = "";
59623
- if (requirements.missing.length > 0) {
59624
- const items = requirements.missing.map((item) => ` - ${item.field}: ${item.reason}`).join(`
59625
- `);
59626
- missing2 = `
59627
- Still required:
59628
- ${items}`;
59629
- }
59630
- return `Next stage: ${requirements.stage}${feedback}${missing2}${nextCommand}`;
59631
- };
59632
- var registrationText = (result3) => [
59633
- `Registration: ${result3.registration.id}`,
59634
- `Participant: ${result3.registration.firstName} ${result3.registration.lastName}`,
59635
- `Status: ${result3.registration.status}`,
59636
- requirementsText(result3)
59637
- ].join(`
59638
- `);
59639
- var createdText = (result3) => ["Application submitted successfully.", registrationText(result3)].join(`
59640
- `);
59641
- var requirementsOnlyText = (result3) => requirementsText(result3);
59642
- var badgeText = (result3) => {
59643
- if (result3.url)
59644
- return result3.url;
59645
- return "You don't have a badge yet.";
59646
- };
59647
-
59648
60405
  // src/picture-upload.ts
59649
- import { readFile as readFile4, stat as stat3 } from "node:fs/promises";
60406
+ import { readFile as readFile5, stat as stat3 } from "node:fs/promises";
59650
60407
  import { homedir } from "node:os";
59651
60408
 
59652
60409
  // ../../node_modules/is-node-process/lib/index.mjs
@@ -61270,7 +62027,7 @@ var readPicture = (inputPath) => exports_Effect.tryPromise({
61270
62027
  if (metadata.size < 1 || metadata.size > maximumPictureBytes) {
61271
62028
  throw new Error("Picture must be between 1 byte and 5 MB");
61272
62029
  }
61273
- const contents = await readFile4(path4);
62030
+ const contents = await readFile5(path4);
61274
62031
  const contentType = detectPictureContentType(contents);
61275
62032
  if (!contentType)
61276
62033
  throw new Error("Picture must be JPEG, PNG, or WebP");
@@ -61309,59 +62066,137 @@ var uploadPicture = exports_Effect.fn("uploadPicture")(function* (options, path4
61309
62066
  });
61310
62067
 
61311
62068
  // src/commands.ts
61312
- var inputFlag = exports_Flag.string("input").pipe(exports_Flag.optional, exports_Flag.withDescription("Read JSON from a file, or use - for stdin"));
62069
+ var inputFlag2 = exports_Flag.string("input").pipe(exports_Flag.optional, exports_Flag.withDescription("Read JSON from a file, or use - for stdin"));
61313
62070
  var stageFlag = exports_Flag.choice("stage", ["application", "acceptance"]).pipe(exports_Flag.withDefault("application"));
61314
- var root = exports_Command.make("chofex").pipe(exports_Command.withSharedFlags({
61315
- apiUrl: exports_Flag.string("api-url").pipe(exports_Flag.withDefault(config.apiUrl), exports_Flag.withDescription("Registration API base URL")),
61316
- output: exports_Flag.choice("output", ["human", "json"]).pipe(exports_Flag.withDefault("human"), exports_Flag.withDescription("Output format")),
61317
- token: exports_Flag.string("token").pipe(exports_Flag.optional, exports_Flag.withDescription("Clerk OAuth token (prefer CHOFEX_TOKEN to avoid shell history)"))
61318
- }), exports_Command.withDescription("Register for and manage your Chofex hackathon application"));
61319
- var registerCommand = exports_Command.make("register", { input: inputFlag }, exports_Effect.fn("registerCommand")(function* ({ input }) {
62071
+ var submitFlag = exports_Flag.boolean("submit").pipe(exports_Flag.withDefault(false), exports_Flag.withDescription("Submit the saved application draft"));
62072
+ var currentRegistration = (client) => getRegistration(client).pipe(exports_Effect.map(exports_Option.some), exports_Effect.catch((error2) => {
62073
+ if (error2.code === "REGISTRATION_NOT_FOUND") {
62074
+ return exports_Effect.succeed(exports_Option.none());
62075
+ }
62076
+ return exports_Effect.fail(error2);
62077
+ }));
62078
+ var rejectIfApplicationLocked = exports_Effect.fn("rejectIfApplicationLocked")(function* (current) {
62079
+ if (exports_Option.isNone(current))
62080
+ return;
62081
+ const { registration, requirements } = current.value.data;
62082
+ const { status } = registration;
62083
+ const registrationAlreadyExists = status === "submitted" || status === "under_review" || status === "waitlisted" || status === "accepted";
62084
+ if (!registrationAlreadyExists)
62085
+ return;
62086
+ let message = "Already registered. Wait for approval.";
62087
+ if (status === "accepted") {
62088
+ message = "Already accepted. Your registration is complete.";
62089
+ if (requirements.stage === "accepted") {
62090
+ message = "Already accepted. Run `chofex confirm` to complete your registration.";
62091
+ }
62092
+ }
62093
+ return yield* cliError("ACTIVE_APPLICATION_EXISTS", message, false, {
62094
+ currentStatus: status
62095
+ });
62096
+ });
62097
+ var registerCommand = exports_Command.make("register", { input: inputFlag2, submit: submitFlag }, exports_Effect.fn("registerCommand")(function* ({ input, submit }) {
61320
62098
  const options = yield* root;
61321
62099
  const operation = exports_Effect.gen(function* () {
61322
62100
  const token = exports_Option.getOrUndefined(options.token);
61323
62101
  const client = { apiUrl: options.apiUrl, token };
61324
- const current = yield* getRegistration(client).pipe(exports_Effect.map(exports_Option.some), exports_Effect.catch((error2) => {
61325
- if (error2.code === "REGISTRATION_NOT_FOUND") {
61326
- return exports_Effect.succeed(exports_Option.none());
61327
- }
61328
- return exports_Effect.fail(error2);
61329
- }));
61330
- if (exports_Option.isSome(current)) {
61331
- const { registration, requirements } = current.value.data;
61332
- const { status } = registration;
61333
- const registrationAlreadyExists = status === "submitted" || status === "under_review" || status === "waitlisted" || status === "accepted";
61334
- if (registrationAlreadyExists) {
61335
- let message = "Already registered. Wait for approval.";
61336
- if (status === "accepted") {
61337
- message = "Already accepted. Your registration is complete.";
61338
- if (requirements.stage === "accepted") {
61339
- message = "Already accepted. Run `chofex confirm` to complete your registration.";
61340
- }
61341
- }
61342
- return yield* cliError("ACTIVE_APPLICATION_EXISTS", message, false, {
61343
- currentStatus: status
61344
- });
62102
+ const current = yield* currentRegistration(client);
62103
+ yield* rejectIfApplicationLocked(current);
62104
+ if (exports_Option.isSome(input) || submit) {
62105
+ if (exports_Option.isSome(input)) {
62106
+ const body = yield* applicationDraftInput(input.value);
62107
+ const saved = yield* saveRegistrationDraft(client, body);
62108
+ if (submit)
62109
+ return yield* submitRegistration(client);
62110
+ return saved;
61345
62111
  }
62112
+ return yield* submitRegistration(client);
61346
62113
  }
61347
- let applicationDefaults;
61348
- if (exports_Option.isSome(current) && current.value.data.registration.status === "rejected") {
61349
- applicationDefaults = applicationDefaultsFromRegistration(current.value.data.registration);
62114
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
62115
+ return yield* cliError("INPUT_REQUIRED", "Non-interactive use requires --input <file>, or --input - for stdin");
61350
62116
  }
61351
- const body = yield* applicationInput(exports_Option.getOrUndefined(input), config.publicSiteUrl, applicationDefaults);
61352
- return yield* register(client, body);
62117
+ return yield* interactiveRegister(client, current);
62118
+ });
62119
+ yield* execute(options.output, operation, (result3) => {
62120
+ if (result3.registration.status === "submitted")
62121
+ return createdText(result3);
62122
+ return draftSavedText(result3);
61353
62123
  });
61354
- yield* execute(options.output, operation, createdText);
61355
- })).pipe(exports_Command.withDescription("Submit an application, or apply again after a rejection"), exports_Command.withExamples([
62124
+ })).pipe(exports_Command.withDescription("Save an application draft in parts, then submit it for review"), exports_Command.withExamples([
61356
62125
  {
61357
62126
  command: "chofex register",
61358
- description: "Complete the application interactively"
62127
+ description: "Fill or resume application parts interactively"
61359
62128
  },
61360
62129
  {
61361
62130
  command: "chofex --output json register --input application.json",
61362
- description: "Submit an application from an agent or script"
62131
+ description: "Save a draft from JSON without submitting it"
62132
+ },
62133
+ {
62134
+ command: "chofex register --submit",
62135
+ description: "Submit a completed draft"
61363
62136
  }
61364
62137
  ]));
62138
+ var interactiveRegister = (client, initial) => exports_Effect.gen(function* () {
62139
+ let latest = exports_Option.isSome(initial) ? initial.value.data : undefined;
62140
+ while (true) {
62141
+ if (latest) {
62142
+ yield* exports_Console.log(registrationPartsText(latest));
62143
+ } else {
62144
+ yield* exports_Console.log("No draft yet. Choose a part to start. Progress is saved on the server.");
62145
+ }
62146
+ let defaults2 = {};
62147
+ if (latest) {
62148
+ defaults2 = applicationDefaultsFromRegistration(latest.registration);
62149
+ }
62150
+ const choice4 = yield* exports_Prompt.run(exports_Prompt.select({
62151
+ message: "What would you like to do?",
62152
+ choices: [
62153
+ { title: "Edit identity", value: "identity" },
62154
+ { title: "Edit experience", value: "experience" },
62155
+ { title: "Edit team", value: "team" },
62156
+ {
62157
+ title: "Black Box challenge status",
62158
+ value: "challenges"
62159
+ },
62160
+ { title: "Review agreements", value: "agreements" },
62161
+ { title: "Submit application", value: "submit" },
62162
+ { title: "Save and exit", value: "exit" }
62163
+ ]
62164
+ })).pipe(exports_Effect.mapError(() => cliError("PROMPT_CANCELLED", "Interactive input was cancelled")));
62165
+ if (choice4 === "exit") {
62166
+ if (!latest) {
62167
+ latest = (yield* saveRegistrationDraft(client, {})).data;
62168
+ }
62169
+ return {
62170
+ version: 1,
62171
+ ok: true,
62172
+ requestId: crypto.randomUUID(),
62173
+ data: latest
62174
+ };
62175
+ }
62176
+ if (choice4 === "submit") {
62177
+ return yield* submitRegistration(client);
62178
+ }
62179
+ if (choice4 === "challenges") {
62180
+ const attempt = yield* getChallengeAttempt(client, "black-box");
62181
+ yield* exports_Console.log(`
62182
+ ${challengeShowText(attempt.data)}
62183
+ `);
62184
+ latest = (yield* getRegistration(client)).data;
62185
+ continue;
62186
+ }
62187
+ let partBody = {};
62188
+ if (choice4 === "identity") {
62189
+ partBody = yield* collectIdentityPart(defaults2);
62190
+ } else if (choice4 === "experience") {
62191
+ partBody = yield* collectExperiencePart(defaults2);
62192
+ } else if (choice4 === "team") {
62193
+ partBody = yield* collectTeamPart(defaults2);
62194
+ } else {
62195
+ partBody = yield* collectAgreementsPart(config.publicSiteUrl, defaults2);
62196
+ }
62197
+ latest = (yield* saveRegistrationDraft(client, partBody)).data;
62198
+ }
62199
+ });
61365
62200
  var statusCommand = exports_Command.make("status", {}, exports_Effect.fn("statusCommand")(function* () {
61366
62201
  const options = yield* root;
61367
62202
  const operation = exports_Effect.gen(function* () {
@@ -61385,7 +62220,7 @@ var badgeCommand = exports_Command.make("badge", {}, exports_Effect.fn("badgeCom
61385
62220
  yield* execute(options.output, operation, badgeText);
61386
62221
  })).pipe(exports_Command.withDescription("Show your generated participant badge"));
61387
62222
  var confirmCommand = exports_Command.make("confirm", {
61388
- input: inputFlag,
62223
+ input: inputFlag2,
61389
62224
  picture: exports_Flag.string("picture").pipe(exports_Flag.optional, exports_Flag.withDescription("Path to a JPEG, PNG, or WebP picture (5 MB max)"))
61390
62225
  }, exports_Effect.fn("confirmCommand")(function* ({ input, picture }) {
61391
62226
  const options = yield* root;
@@ -61475,7 +62310,7 @@ var inputValidation = (stage, path4) => {
61475
62310
  }
61476
62311
  return acceptedDetailsInput(path4, "in_person").pipe(exports_Effect.asVoid);
61477
62312
  };
61478
- var validateCommand = exports_Command.make("validate", { input: inputFlag, stage: stageFlag }, exports_Effect.fn("validateCommand")(function* ({ input, stage }) {
62313
+ var validateCommand = exports_Command.make("validate", { input: inputFlag2, stage: stageFlag }, exports_Effect.fn("validateCommand")(function* ({ input, stage }) {
61479
62314
  const options = yield* root;
61480
62315
  const operation = inputValidation(stage, exports_Option.getOrUndefined(input)).pipe(exports_Effect.map(() => ({
61481
62316
  version: 1,
@@ -61547,7 +62382,8 @@ var command = root.pipe(exports_Command.withSubcommands([
61547
62382
  requirementsCommand,
61548
62383
  badgeCommand,
61549
62384
  confirmCommand,
61550
- schemaCommand
62385
+ schemaCommand,
62386
+ challengeCommand
61551
62387
  ]));
61552
62388
 
61553
62389
  // src/index.ts