How sidecar orchestration works inside server.mjs

CodeOtter's backend is a single dependency-free Node.js file (server.mjs) that speaks raw HTTP to both hosted APIs and local sidecars. Local models are declared as rows in models.json and stored under PR_SCORER_DATA.

Nothing ever downloads automatically on startup—admins explicitly select which runtime and checkpoint to install from Admin → Local Models. Multi-file checkpoints declare a files array and a dir, and server.mjs verifies every shard with modelReady(m) before marking a model ready.

// Multi-file checkpoint readiness check in server.mjs
function modelReady(m) {
  if (Array.isArray(m.files) && m.dir) {
    return m.files.every((f) => fs.existsSync(path.join(PR_SCORER_DATA, m.dir, f)));
  }
  return fs.existsSync(path.join(PR_SCORER_DATA, m.file));
}

Chunking System One requests (maxQuestions: 8) and pairing CodeReviewer

During stress testing of the local ggmlc laya runtime, we discovered that sending more than 8 typed questions in a single POST /v1/systemone payload caused the local runtime to stall. CodeOtter automatically chunks questions into batches of maxQuestions (8) and trims diffs to contextChars so local reviews never hang.

Similarly, because the Python CodeReviewer model (runtimes/codereviewer/serve.py) produces specialized per-hunk review comments rather than numeric rubrics, CodeOtter pairs it with a System One model—refusing to run a scoreless review unless a System One engine is active.