@mrrlin-dev/mcp 0.3.57 → 0.3.59

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/bin.cjs +89 -22
  2. package/package.json +5 -5
package/dist/bin.cjs CHANGED
@@ -20665,10 +20665,7 @@ function normalizeUrl(value) {
20665
20665
  var RETIRED_API_BASE_URLS = {
20666
20666
  // Retired 2026-07-28 when staging moved to the mrrlin2 Vercel team; serves a decommissioned
20667
20667
  // Supabase project and now answers `GET /health` with 402 DEPLOYMENT_DISABLED. Added in 0.3.50.
20668
- "mrrlin-api-fnnzzz-fnnzzzs-projects.vercel.app": STAGING_API_BASE_URL,
20669
- // Retired 2026-08-11 when staging moved to the mrrlin3 Vercel team after mrrlin2 hit usage
20670
- // limits. Added in 0.3.57.
20671
- "mrrlin-api-mrrlin2.vercel.app": STAGING_API_BASE_URL
20668
+ "mrrlin-api-fnnzzz-fnnzzzs-projects.vercel.app": STAGING_API_BASE_URL
20672
20669
  };
20673
20670
  function isSameApiHost(a, b) {
20674
20671
  const origin = (value) => {
@@ -39460,7 +39457,7 @@ function startCodexProbe(deps = {}) {
39460
39457
  }
39461
39458
 
39462
39459
  // src/_generated/version.ts
39463
- var PKG_VERSION = "0.3.57";
39460
+ var PKG_VERSION = "0.3.59";
39464
39461
 
39465
39462
  // src/api-base-url-migrate.ts
39466
39463
  var import_node_fs2 = __toESM(require("node:fs"), 1);
@@ -40749,7 +40746,7 @@ function reviserIdentityInstructions(taskId, title) {
40749
40746
  function buildSpecGateDeps(args) {
40750
40747
  const { client, projectSlug, specPageId, cwd, codexExecutable, extraHeadCount = 0 } = args;
40751
40748
  const rounds = Number(process.env["MRRLIN_CONSENSUS_ROUNDS"] ?? 5);
40752
- const maxHeadCalls = rounds * (4 + extraHeadCount + 1);
40749
+ const maxHeadCalls = 2 * rounds * (4 + extraHeadCount + 1);
40753
40750
  const timeoutMs = Number(process.env["MRRLIN_CONSENSUS_HEAD_TIMEOUT_MS"] ?? 15e4);
40754
40751
  let intentPromise = null;
40755
40752
  function loadIntent() {
@@ -40913,7 +40910,7 @@ function buildCodeGateDeps(args) {
40913
40910
  const { client, projectSlug, baseRef, cwd, codexExecutable, extraHeads } = args;
40914
40911
  const rounds = Number(process.env["MRRLIN_CONSENSUS_ROUNDS"] ?? 5);
40915
40912
  const heads = ["code-reviewer", ...extraHeads ?? []];
40916
- const maxHeadCalls = rounds * (heads.length + 1);
40913
+ const maxHeadCalls = 2 * rounds * (heads.length + 1);
40917
40914
  const headTimeoutMs = Number(process.env["MRRLIN_CONSENSUS_HEAD_TIMEOUT_MS"] ?? 15e4);
40918
40915
  const reviserTimeoutMs = Number(process.env["MRRLIN_CODEGATE_REVISER_TIMEOUT_MS"] ?? 6e5);
40919
40916
  const gitArgs = { cwd, baseRef, run: defaultRunCmd };
@@ -41011,7 +41008,7 @@ async function buildDeliverableGateDeps(args) {
41011
41008
  }
41012
41009
  }
41013
41010
  const heads = resolveHeads(domain2);
41014
- const maxHeadCalls = rounds * (heads.length + 1);
41011
+ const maxHeadCalls = 2 * rounds * (heads.length + 1);
41015
41012
  const criteriaBlock = renderCriteriaBlock(criteria);
41016
41013
  return {
41017
41014
  heads,
@@ -43897,6 +43894,46 @@ function createBoundedSemaphore(slots) {
43897
43894
  };
43898
43895
  }
43899
43896
 
43897
+ // src/consensus/escalation.ts
43898
+ function diagnoseStall(history, configuredRounds) {
43899
+ const n = history.length;
43900
+ const nonRespPerRound = history.map((h) => h.headOutcomes.filter((o) => !o.responded).length);
43901
+ const infraRoundCount = nonRespPerRound.filter((c) => c >= 2).length;
43902
+ const infraQualifies = infraRoundCount > n / 2;
43903
+ if (infraQualifies) {
43904
+ const roundIndices = [];
43905
+ nonRespPerRound.forEach((c, i) => {
43906
+ if (c >= 2) roundIndices.push(i + 1);
43907
+ });
43908
+ const evidence2 = `INFRA basis: \u22652 non\u2011responding heads in ${infraRoundCount} of ${n} rounds (rounds ${roundIndices.join(",")})`;
43909
+ let grant = 3;
43910
+ const headroom = 2 * configuredRounds - n;
43911
+ grant = Math.max(1, Math.min(grant, headroom));
43912
+ return { diagnosis: "INFRA", grantedRounds: grant, evidence: evidence2 };
43913
+ }
43914
+ if (n >= 2) {
43915
+ const counts = history.map((h) => h.accepted.length);
43916
+ const last = counts[n - 1];
43917
+ const secondLast = counts[n - 2];
43918
+ const lastFall = last < secondLast;
43919
+ if (lastFall) {
43920
+ let falls = 1;
43921
+ if (n >= 3 && secondLast < counts[n - 3]) {
43922
+ falls++;
43923
+ }
43924
+ let grant = 2 + falls;
43925
+ if (grant > 5) grant = 5;
43926
+ const headroom = 2 * configuredRounds - n;
43927
+ grant = Math.max(1, Math.min(grant, headroom));
43928
+ const seqDesc = counts.map((c, i) => `round${i + 1}:${c}`).join(" \u2192 ");
43929
+ const evidence2 = `SUBSTANCE basis: accepted count fell (${seqDesc})`;
43930
+ return { diagnosis: "SUBSTANCE", grantedRounds: grant, evidence: evidence2 };
43931
+ }
43932
+ }
43933
+ const evidence = n === 0 ? "empty history" : `no infra or substance basis found in ${n} rounds`;
43934
+ return { diagnosis: "AMBIGUITY", grantedRounds: 0, evidence };
43935
+ }
43936
+
43900
43937
  // src/consensus/loop.ts
43901
43938
  async function runConsensus(input) {
43902
43939
  const sem = createBoundedSemaphore(input.concurrency ?? input.heads.length);
@@ -43904,9 +43941,12 @@ async function runConsensus(input) {
43904
43941
  let artifact = input.artifact;
43905
43942
  let calls = 0;
43906
43943
  const dismissedFwd = [];
43907
- for (let round = 1; round <= input.rounds; round++) {
43944
+ let effectiveRounds = input.rounds;
43945
+ let escalated = false;
43946
+ let decision;
43947
+ for (let round = 1; round <= effectiveRounds; round++) {
43908
43948
  if (calls + input.heads.length > input.maxHeadCalls) {
43909
- return { outcome: "CONSENSUS_BLOCKED", rounds: round - 1, finalArtifact: artifact, history };
43949
+ return { outcome: "CONSENSUS_BLOCKED", rounds: round - 1, finalArtifact: artifact, history, ...decision ? { escalation: decision } : {} };
43910
43950
  }
43911
43951
  const dismissedBlock = dismissedFwd.length ? `PREVIOUSLY DISMISSED (do not re-raise unless new information):
43912
43952
  ${dismissedFwd.slice(-20).join("\n")}` : "";
@@ -43930,12 +43970,19 @@ ${dismissedFwd.slice(-20).join("\n")}` : "";
43930
43970
  if (responding.length === 0) {
43931
43971
  return { outcome: "CONSENSUS_UNAVAILABLE", rounds: round, finalArtifact: artifact, history };
43932
43972
  }
43973
+ const headOutcomes = input.heads.map((persona) => ({
43974
+ persona,
43975
+ responded: false
43976
+ }));
43933
43977
  const issues = [];
43934
- const verdicts = [];
43935
43978
  for (const { idx, res } of responding) {
43936
43979
  const parsed = parseVerdict(res.text);
43937
- verdicts.push(parsed.verdict);
43938
43980
  parsed.issues.forEach((iss, n) => issues.push({ ...iss, id: `r${round}-h${idx}-${n}` }));
43981
+ const outcome = headOutcomes[idx];
43982
+ if (outcome) {
43983
+ outcome.responded = true;
43984
+ outcome.verdict = parsed.verdict;
43985
+ }
43939
43986
  if (parsed.verdict !== "APPROVE" && parsed.issues.length === 0 && parsed.parseFallbacks.length === 0) {
43940
43987
  issues.push({
43941
43988
  category: "ambiguity",
@@ -43947,7 +43994,7 @@ ${dismissedFwd.slice(-20).join("\n")}` : "";
43947
43994
  let adj;
43948
43995
  if (issues.length > 0) {
43949
43996
  if (calls + 1 > input.maxHeadCalls) {
43950
- return { outcome: "CONSENSUS_BLOCKED", rounds: round, finalArtifact: artifact, history };
43997
+ return { outcome: "CONSENSUS_BLOCKED", rounds: round, finalArtifact: artifact, history, ...decision ? { escalation: decision } : {} };
43951
43998
  }
43952
43999
  calls++;
43953
44000
  try {
@@ -43958,17 +44005,25 @@ ${dismissedFwd.slice(-20).join("\n")}` : "";
43958
44005
  } else {
43959
44006
  adj = { adjudicatedVerdict: "APPROVE", accepted: [], dismissed: [] };
43960
44007
  }
43961
- history.push({ round, verdicts, accepted: adj.accepted, dismissed: adj.dismissed });
44008
+ history.push({ round, accepted: adj.accepted, dismissed: adj.dismissed, headOutcomes });
43962
44009
  adj.dismissed.forEach((d) => dismissedFwd.push(`- ${d.id}: ${d.reason}`));
43963
44010
  if (adj.accepted.length === 0) {
43964
- return { outcome: "CONVERGED", rounds: round, finalArtifact: artifact, history };
44011
+ return { outcome: "CONVERGED", rounds: round, finalArtifact: artifact, history, ...decision ? { escalation: decision } : {} };
43965
44012
  }
43966
- if (round === input.rounds) {
43967
- return { outcome: "CONSENSUS_BLOCKED", rounds: round, finalArtifact: artifact, history };
44013
+ if (round === effectiveRounds) {
44014
+ if (!decision) {
44015
+ decision = diagnoseStall(history, input.rounds);
44016
+ }
44017
+ if (decision.grantedRounds > 0 && !escalated) {
44018
+ escalated = true;
44019
+ effectiveRounds = Math.min(effectiveRounds + decision.grantedRounds, input.rounds * 2);
44020
+ } else {
44021
+ return { outcome: "CONSENSUS_BLOCKED", rounds: round, finalArtifact: artifact, history, ...decision ? { escalation: decision } : {} };
44022
+ }
43968
44023
  }
43969
44024
  artifact = await input.revise(artifact, adj.accepted);
43970
44025
  }
43971
- return { outcome: "CONSENSUS_BLOCKED", rounds: input.rounds, finalArtifact: artifact, history };
44026
+ return { outcome: "CONSENSUS_BLOCKED", rounds: effectiveRounds, finalArtifact: artifact, history };
43972
44027
  }
43973
44028
 
43974
44029
  // src/consensus/deliverable-gate.ts
@@ -44018,7 +44073,12 @@ async function runDeliverableGate(_target, deps) {
44018
44073
  whyBlocking: `reviewer raised a ${issue2.category} issue`,
44019
44074
  category: issue2.category
44020
44075
  }));
44021
- return clarifications.length > 0 ? { outcome: "CONSENSUS_BLOCKED", rounds: result.rounds, clarifications } : { outcome: "CONSENSUS_BLOCKED", rounds: result.rounds };
44076
+ return {
44077
+ outcome: "CONSENSUS_BLOCKED",
44078
+ rounds: result.rounds,
44079
+ ...clarifications.length > 0 ? { clarifications } : {},
44080
+ ...result.escalation ? { escalation: result.escalation } : {}
44081
+ };
44022
44082
  }
44023
44083
  return { outcome: result.outcome, rounds: result.rounds };
44024
44084
  }
@@ -48907,8 +48967,8 @@ var DEFAULT_DIRECTOR_BRIDGE_ALLOWED_ORIGINS = [
48907
48967
  "http://[::1]:*",
48908
48968
  // Staging Vercel team migrated 2026-07-28 (see docs/reference/deployments.md). The prior
48909
48969
  // fnnzzz-fnnzzzs-projects web alias was dropped once no operator was left on an old build.
48910
- // mrrlin2 hit usage limits and was replaced by mrrlin3 on 2026-08-11.
48911
- "https://mrrlin-web-mrrlin2.vercel.app",
48970
+ // mrrlin2 hit usage limits and was replaced by mrrlin3 on 2026-08-11; the mrrlin2 web alias
48971
+ // was dropped the same day since no operator was left on that build either.
48912
48972
  "https://mrrlin-web-mrrlin3.vercel.app",
48913
48973
  "https://app.mrrlin.dev",
48914
48974
  "https://mrrlin-web.vercel.app"
@@ -55207,7 +55267,11 @@ async function runSpecGate(_target, deps, opts) {
55207
55267
  if (result.outcome === "CONSENSUS_BLOCKED") {
55208
55268
  const accepted = result.history.at(-1)?.accepted ?? [];
55209
55269
  const operatorClarifications = accepted.filter((issue2) => issue2.category === "ambiguity" || issue2.category === "scope").map((issue2) => mapAcceptedIssueToClarification(issue2));
55210
- return operatorClarifications.length > 0 ? { outcome: "CONSENSUS_BLOCKED", operatorClarifications } : { outcome: "CONSENSUS_BLOCKED" };
55270
+ return {
55271
+ outcome: "CONSENSUS_BLOCKED",
55272
+ ...operatorClarifications.length > 0 ? { operatorClarifications } : {},
55273
+ ...result.escalation ? { escalation: result.escalation } : {}
55274
+ };
55211
55275
  }
55212
55276
  return { outcome: result.outcome };
55213
55277
  }
@@ -55774,6 +55838,9 @@ async function handleConsensusBlocked(result, ctx, input, resolvedTaskId) {
55774
55838
  } else {
55775
55839
  error51 = "Consensus blocked: reviewers did not converge within budget.";
55776
55840
  }
55841
+ if (result.escalation) {
55842
+ error51 += ` (diagnosis: ${result.escalation.diagnosis})`;
55843
+ }
55777
55844
  return {
55778
55845
  kind: "failed",
55779
55846
  failureReason: "consensus_blocked",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrrlin-dev/mcp",
3
- "version": "0.3.57",
3
+ "version": "0.3.59",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "mrrlin-mcp": "dist/bin.cjs"
@@ -21,12 +21,12 @@
21
21
  "@types/ws": "^8.18.1",
22
22
  "esbuild": "^0.24.0",
23
23
  "tsx": "^4.22.3",
24
+ "@mrrlin/director-e2e": "0.0.0",
25
+ "@mrrlin/wiki": "0.0.0",
24
26
  "@mrrlin/schemas": "0.0.0",
25
- "@mrrlin/codex-client": "0.0.0",
26
27
  "@mrrlin/client": "0.0.0",
27
- "@mrrlin/director-e2e": "0.0.0",
28
- "@mrrlin/tsconfig": "0.0.0",
29
- "@mrrlin/wiki": "0.0.0"
28
+ "@mrrlin/codex-client": "0.0.0",
29
+ "@mrrlin/tsconfig": "0.0.0"
30
30
  },
31
31
  "dependencies": {
32
32
  "@iarna/toml": "^2.2.5",