{"record":{"id":"e1d8725797739686","repo":"stablyai/orca","slug":"package-json-must-declare-bin-orca","errorCode":null,"errorMessage":"package.json must declare bin.orca","messagePattern":"package\\.json must declare bin\\.orca","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"config/scripts/verify-cli-bin.mjs","lineNumber":32,"sourceCode":"  null,\n  2\n)}\\n`\n\n/**\n * Verifies the published CLI entrypoint and the module-type boundary for the\n * compiled output tree that the packaged CLI loads at runtime.\n */\nexport function verifyPackageCliBin({\n  projectDir = path.resolve(import.meta.dirname, '..', '..'),\n  fixExecutable = false,\n  fixPackageJson = false,\n  runHelp = false\n} = {}) {\n  const packageJsonPath = path.join(projectDir, 'package.json')\n  const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'))\n  const binTarget = packageJson.bin?.orca\n  if (typeof binTarget !== 'string' || binTarget.length === 0) {\n    throw new Error('package.json must declare bin.orca')\n  }\n\n  const binPath = path.resolve(projectDir, binTarget)\n  const stats = statSync(binPath)\n  if (!stats.isFile()) {\n    throw new Error(`bin.orca target is not a file: ${binTarget}`)\n  }\n  if (stats.size === 0) {\n    throw new Error(`bin.orca target is empty: ${binTarget}`)\n  }\n\n  const content = readFileSync(binPath, 'utf8')\n  if (!content.startsWith('#!/usr/bin/env node\\n')) {\n    throw new Error(`bin.orca target must start with a Node shebang: ${binTarget}`)\n  }\n\n  const outPackageJsonPath = path.join(projectDir, 'out', 'package.json')\n  if (fixPackageJson) {","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/config/scripts/verify-cli-bin.mjs#L14-L50","documentation":"verifyPackageCliBin reads projectDir/package.json and requires a non-empty string at bin.orca — the published CLI entrypoint. The package boundary check (CommonJS out/package.json downstream) and the executable-bit check both depend on resolving this bin target first, so a missing declaration aborts before any filesystem work. The message is fixed (no interpolation) because the defect is in the manifest, not a path.","triggerScenarios":"Called via verifyPackageCliBin() when packageJson.bin?.orca is undefined, not a string, or an empty string at line 31. Reproduced by a package.json lacking a `bin` field, having `bin: {}`, or `bin: { orca: '' }`.","commonSituations":"Refactoring package.json and dropping the bin field; renaming the CLI from `orca` to something else without updating the verifier; a publish/release pipeline running verify-cli-bin on a package that was never wired as a CLI.","solutions":["Add `\"bin\": { \"orca\": \"<path-to-compiled-entry>\" }` to package.json with the path resolved relative to projectDir.","Ensure the path points at the built/compiled entry, not the TypeScript source.","Re-run with no flags to confirm; the bin path must then exist, be non-empty, and carry the Node shebang."],"exampleFix":"// before\n{\n  \"name\": \"orca\",\n  \"bin\": {}\n}\n// after\n{\n  \"name\": \"orca\",\n  \"bin\": { \"orca\": \"out/cli/main.js\" }\n}","handlingStrategy":"validation","validationCode":"const pkg = JSON.parse(readFileSync('package.json', 'utf8'))\nif (typeof pkg.bin?.orca !== 'string' || pkg.bin.orca.length === 0) {\n  throw new Error('package.json must declare a non-empty bin.orca before verify-cli-bin')\n}","typeGuard":"function hasValidOrcaBin(pkg: unknown): pkg is { bin: { orca: string } } {\n  return (\n    typeof pkg === 'object' && pkg !== null &&\n    'bin' in pkg && typeof (pkg as any).bin === 'object' &&\n    typeof (pkg as any).bin?.orca === 'string' && (pkg as any).bin.orca.length > 0\n  )\n}","tryCatchPattern":null,"preventionTips":["Keep bin.orca pinned in package.json at all times; never drop it during a refactor.","Add a CI step that runs verify-cli-bin so a missing bin field fails the build early."],"tags":["cli","packaging","package-json","bin"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}