- MCP create-backlog-item for natural language Plan/Epic/Task authoring - Worker non-code: optional worktree + per-harness allowlist + doc_review→published - Harness registry: harness_providers/role_harness_routes, WorkerAdapter (minimal|crewai|langgraph|remote-ag-ui), AG-UI POST /api/ag-ui, Settings → Harnesses with Test - Plans tree: backlog.listTree + createPlan/Epic/Task + Start→Convoy, web CRUD without CLI - Fleet: /fleet rollup across workspaces + SSE /api/fleet/events Decision: docs/decisions/2026-08-25-second-brain-os-pivot.md Convoy: .convoys/second-brain-os-v01 Co-authored-by: orchestrator
47 lines
1.4 KiB
TypeScript
47 lines
1.4 KiB
TypeScript
import { z } from "zod";
|
|
|
|
const envSchema = z.object({
|
|
DATABASE_URL: z.string().min(1),
|
|
REDIS_URL: z.string().min(1).optional(),
|
|
WORKER_DRY_RUN: z
|
|
.enum(["0", "1", "true", "false", ""])
|
|
.optional()
|
|
.transform((value) => value === "1" || value === "true"),
|
|
WORKER_BLPOP_TIMEOUT_S: z
|
|
.string()
|
|
.optional()
|
|
.transform((value) => {
|
|
const parsed = Number(value ?? "5");
|
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : 5;
|
|
}),
|
|
WORKER_MAX_TOOL_STEPS: z
|
|
.string()
|
|
.optional()
|
|
.transform((value) => {
|
|
const parsed = Number(value ?? "12");
|
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : 12;
|
|
}),
|
|
WORKER_CHECKPOINT_EVERY_N_STEPS: z
|
|
.string()
|
|
.optional()
|
|
.transform((value) => {
|
|
const parsed = Number(value ?? "1");
|
|
return Number.isFinite(parsed) && parsed > 0 ? Math.floor(parsed) : 1;
|
|
}),
|
|
WORKER_REPO_ROOT: z.string().optional(),
|
|
WORKER_WORKTREE_BASE: z
|
|
.string()
|
|
.optional()
|
|
.transform((value) => value?.trim() || "/tmp/echodo-worker-worktrees"),
|
|
});
|
|
|
|
export type WorkerEnv = z.infer<typeof envSchema>;
|
|
|
|
export function loadEnv(): WorkerEnv {
|
|
const parsed = envSchema.safeParse(process.env);
|
|
if (!parsed.success) {
|
|
console.error("[worker] Invalid environment:", parsed.error.flatten().fieldErrors);
|
|
process.exit(1);
|
|
}
|
|
return parsed.data;
|
|
}
|