{"record":{"id":"2285a31008d68407","repo":"JuliusBrussee/caveman","slug":"usage-invokedcommand-audit-eval-import-evi","errorCode":null,"errorMessage":"usage: ${invokedCommand(\"audit\")} eval-import <evidence.jsonl> [--project <uuid>] [--dry-run]","messagePattern":"usage: (.+?) eval-import <evidence\\.jsonl> \\[--project <uuid>\\] \\[--dry-run\\]","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/index.ts","lineNumber":17143,"sourceCode":"    \"content-type\": \"application/octet-stream\",\n    \"x-cave-csrf\": \"cli\"\n  };\n  const fieldMap = flagFrom(argv, \"--field-map\", \"\");\n  if (fieldMap) headers[\"x-cave-field-map\"] = fieldMap;\n  const response = await fetch(`${cfg.baseURL}/api/v1/imports?format=${encodeURIComponent(format)}`, {\n    method: \"POST\",\n    headers,\n    body: data\n  });\n  print(await response.json());\n}\n\n// auditEvalImport turns newline-delimited, source-neutral eval records into one\n// bounded batch. Server stamps tenant scope, observed basis, and external-only\n// authority; CI cannot promote its own results into rollout authority.\nasync function auditEvalImport(argv: string[]) {\n  const file = positionalAfterOptions(argv.slice(1), new Set([\"--project\"]));\n  if (!file) throw new Error(`usage: ${invokedCommand(\"audit\")} eval-import <evidence.jsonl> [--project <uuid>] [--dry-run]`);\n  const data = await readFile(file);\n  if (data.byteLength > 4 * 1024 * 1024) throw new Error(\"eval evidence file exceeds 4 MiB batch limit\");\n\n  const items: Record<string, unknown>[] = [];\n  for (const [index, rawLine] of data.toString(\"utf8\").split(/\\r?\\n/).entries()) {\n    const line = rawLine.trim();\n    if (!line) continue;\n    let parsed: unknown;\n    try {\n      parsed = JSON.parse(line);\n    } catch {\n      throw new Error(`eval evidence line ${index + 1} is not valid JSON`);\n    }\n    if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n      throw new Error(`eval evidence line ${index + 1} must be a JSON object`);\n    }\n    items.push(parsed as Record<string, unknown>);\n    if (items.length > 1000) throw new Error(\"eval evidence batch exceeds 1000 records\");","sourceCodeStart":17125,"sourceCodeEnd":17161,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/5184b3d11ac6a1acb7d44b9bfaa31698157cff97/packages/cli/src/index.ts#L17125-L17161","documentation":"Usage guard for `caveman audit eval-import`: after skipping the `--project` option, the CLI requires one positional path to a newline-delimited evidence file. When only flags remain (no positional), this usage error throws before the file is opened. The command turns source-neutral eval records into one bounded batch stamped server-side with tenant scope and external-only authority.","triggerScenarios":"`caveman audit eval-import --project <uuid>` without a file; the evidence path passed through an unset variable; a filename starting with `--` being consumed as an option.","commonSituations":"CI steps templating the file path; artifacts with leading-dash filenames; argument-order churn between CLI versions.","solutions":["Supply the JSONL path: `caveman audit eval-import ./evidence.jsonl`","Prefix leading-dash filenames with `./` so they parse as positionals","Echo the full command in CI before execution to catch missing paths"],"exampleFix":"# before\ncaveman audit eval-import --dry-run\n# after\ncaveman audit eval-import --dry-run ./evidence.jsonl","handlingStrategy":"validation","validationCode":"const file = positionalAfterOptions(argv.slice(1), new Set(['--project']));\nif (!file) {\n  console.error('usage: caveman audit eval-import <evidence.jsonl> [--project <uuid>] [--dry-run]');\n  process.exit(2);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Fail CI when a required file argument resolves to an empty string","Pre-check `test -s \"$EVIDENCE\"` so missing and empty files surface early","Prefix leading-dash filenames with ./"],"tags":["cli","usage-error","eval","import"],"backgroundTag":"missing-cli-argument","analyzedSha":"5184b3d11ac6a1acb7d44b9bfaa31698157cff97","analyzedAt":"2026-08-18T03:14:35.516Z","contentChangedAt":"2026-08-18T03:14:35.516Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}