Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions src/router/workflow.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ async function runBoundedReviewLoop(draft, task, deps, opts = {}) {
phase: "reviewed",
...modelAttribution({
model: activeNemotronModel,
modelTier: escalation.escalate ? "REASONING" : task.nemotronTier,
modelTier: escalation.escalate ? "REASONING" : (task.nemotronTier || "SIMPLE"),
modelRole: "review",
}),
verdict,
Expand All @@ -182,7 +182,12 @@ async function runBoundedReviewLoop(draft, task, deps, opts = {}) {
if (verdict === "PASS") {
if (validate) {
emit({ phase: "validation-requested" });
const validationResult = await validate({ draft, task });
const rawValidation = await validate({ draft, task });
// Fail closed on malformed validator returns — treat as failed validation.
const validationResult =
rawValidation && typeof rawValidation === "object"
? rawValidation
: { passed: false, failureKind: "validator-malformed" };

if (!validationResult.passed) {
// Validation failed — budget check, then revise with failure context.
Expand Down Expand Up @@ -336,6 +341,8 @@ async function runComplexWorkflow(task, deps) {

// If either pre-review flagged issues, apply a targeted revision before the shared loop
// so findings are incorporated regardless of whether the standard review also returns REVISE.
// Note: this pre-revision does not consume the loop's revision budget — runBoundedReviewLoop
// starts revisionCount at 0, giving the loop its full maxRevisions budget after pre-reviews.
let resolvedDraft = draft;
if (archVerdict === "REVISE" || deepVerdict === "REVISE") {
emit({
Expand Down Expand Up @@ -417,6 +424,12 @@ async function runHighRiskWorkflow(task, deps) {
* @returns {Promise<{ output: string, verdict: 'PASS'|'REVISE', revisionCount: number }>}
*/
async function runWorkflow(task, deps) {
if (!deps || typeof deps.emit !== "function" || !deps.codingClient || !deps.nemotronClient) {
throw new Error(
"runWorkflow: deps must include codingClient, nemotronClient, and emit"
);
}

const workflow = task.workflow || "standard";

switch (workflow) {
Expand Down