fix(agent-pod): sync coordinator.js (slug repoId), tighten compaction, route judge to reasoning model

This commit is contained in:
Story Crater Bot
2026-08-19 10:41:33 -07:00
parent f6d25552f3
commit 00af9d8349
3 changed files with 43 additions and 9 deletions
+31 -7
View File
@@ -39,7 +39,6 @@ data:
// with fs.watch instead of polling.
const fs = require("node:fs");
const path = require("node:path");
const crypto = require("node:crypto");
const { spawn } = require("node:child_process");
const WORK_DIR = process.env.HUB_WORK_DIR || path.join(require("node:os").tmpdir(), "agent-harness-work");
@@ -523,6 +522,11 @@ data:
// running concurrently (see runCoordinator).
async function runRepoPipeline({ repoId, repo, baseBranch, tasks, branchName }, pipelineSession) {
const cwd = path.join(WORK_DIR, repoId);
// repoId is a slug derived from the repo URL now (see slugFor), not a
// fresh UUID -- reusable across separate `runCoordinator` invocations
// against the same repo, so a stale clone from a prior run has to be
// wiped before this one starts, not merged into.
fs.rmSync(cwd, { recursive: true, force: true });
fs.mkdirSync(cwd, { recursive: true });
const pool = {};
@@ -678,20 +682,40 @@ data:
// How many repos can be mid-flight at once. Each repo gets its own clone
// and its own 4-agent pool (planner/investigator/implementer/judge), so
// this is now the real concurrency knob -- tasks within one repo are
// already serialized against that repo's pool (see runPhase). Backends
// that queue rather than reject concurrent requests to one loaded model
// (e.g. Ollama) still process this many repos' worth of stages one at a
// time internally even if REPO_CONCURRENCY says otherwise; bump it once
// there's more than one model instance to actually parallelize against.
// already serialized against that repo's pool (see runPhase). The backend
// (homelab-ornith) actually runs 2 GPU replicas behind one Kubernetes
// Service, each with its own copy of the model loaded (see homelab's
// k8s/apps/llm-serving/ornith.yaml) -- so up to 2 concurrent LLM calls get
// real independent instances; a 3rd+ concurrent call queues inside
// whichever replica the Service's own load-balancing lands it on (each
// replica runs OLLAMA_NUM_PARALLEL=1). REPO_CONCURRENCY above 2 is still
// useful (more repos in flight overlaps git/file work, not just LLM calls)
// but past 2 simultaneous LLM calls, extra concurrency mostly means queueing
// rather than added throughput -- bump the backend's replica count to
// change that, not this constant.
const REPO_CONCURRENCY = Number(process.env.REPO_CONCURRENCY) || 3;
// repoId is the repo's own name, not a random id -- it's what every role
// session's --name is built from (see runOnPool: `${repoId}-${role}`), so
// agent-manager's own session list groups naturally by repo ("portfolio-
// planner", "portfolio-judge", "poiman-planner", ...) instead of by opaque
// UUID. Takes the last path segment of the URL, strips a trailing `.git`,
// and sanitizes anything that isn't safe in a tmux session name / directory
// name / git branch name. Two different repos that happen to share a
// basename (e.g. two orgs' "portfolio") would collide -- not handled, since
// nothing about this harness's usage has needed more than one org per run.
function slugFor(repoUrl) {
const last = repoUrl.replace(/\/+$/, "").split("/").pop() || repoUrl;
return last.replace(/\.git$/, "").replace(/[^a-zA-Z0-9._-]/g, "-");
}
// Top-level entry point: runs every repo in `repos` to completion, up to
// REPO_CONCURRENCY at a time. Returns a map of repoId -> final
// pipelineSession, one per repo, independent of how the others fared.
async function runCoordinator({ repos, base, tasks, branchName }) {
const sessions = {};
await runConcurrent(repos, REPO_CONCURRENCY, async (repoUrl) => {
const repoId = crypto.randomUUID();
const repoId = slugFor(repoUrl);
const pipelineSession = {
id: repoId,
repo: repoUrl,