@mrrlin-dev/mcp 0.4.1 → 0.4.2
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.
- package/dist/bin.cjs +91 -10
- package/package.json +4 -4
package/dist/bin.cjs
CHANGED
|
@@ -38187,6 +38187,9 @@ var mrrlinInboxQuestionOptionsSchema = external_exports.array(mrrlinInboxQuestio
|
|
|
38187
38187
|
});
|
|
38188
38188
|
}
|
|
38189
38189
|
});
|
|
38190
|
+
var REVIEW_AGAIN_ANSWER = "Review the current spec again without changing it.";
|
|
38191
|
+
var EDIT_SPEC_ANSWER = "Hold the task until the spec is edited by hand.";
|
|
38192
|
+
var PROCEED_ANYWAY_ANSWER = "Proceed without agreement; record the unsettled points on the spec.";
|
|
38190
38193
|
var mrrlinInboxItemSchema = external_exports.object({
|
|
38191
38194
|
actionPayload: mrrlinInboxItemActionPayloadSchema.nullable(),
|
|
38192
38195
|
answer: external_exports.string().nullable(),
|
|
@@ -40187,7 +40190,7 @@ function startCodexProbe(deps = {}) {
|
|
|
40187
40190
|
}
|
|
40188
40191
|
|
|
40189
40192
|
// src/_generated/version.ts
|
|
40190
|
-
var PKG_VERSION = "0.4.
|
|
40193
|
+
var PKG_VERSION = "0.4.2";
|
|
40191
40194
|
|
|
40192
40195
|
// src/api-base-url-migrate.ts
|
|
40193
40196
|
var import_node_fs2 = __toESM(require("node:fs"), 1);
|
|
@@ -41312,7 +41315,7 @@ async function runConsensus(input) {
|
|
|
41312
41315
|
let decision;
|
|
41313
41316
|
for (let round = 1; round <= effectiveRounds; round++) {
|
|
41314
41317
|
if (calls + input.heads.length > input.maxHeadCalls) {
|
|
41315
|
-
return { outcome: "CONSENSUS_BLOCKED", rounds: round - 1, finalArtifact: artifact, history, ...decision ? { escalation: decision } : {} };
|
|
41318
|
+
return { outcome: "CONSENSUS_BLOCKED", rounds: round - 1, finalArtifact: artifact, history, unresolved: history[history.length - 1]?.accepted ?? [], ...decision ? { escalation: decision } : {} };
|
|
41316
41319
|
}
|
|
41317
41320
|
const dismissedBlock = dismissedFwd.length ? `PREVIOUSLY DISMISSED (do not re-raise unless new information):
|
|
41318
41321
|
${dismissedFwd.slice(-20).join("\n")}` : "";
|
|
@@ -41334,7 +41337,7 @@ ${dismissedFwd.slice(-20).join("\n")}` : "";
|
|
|
41334
41337
|
(r) => r.res.ok
|
|
41335
41338
|
);
|
|
41336
41339
|
if (responding.length === 0) {
|
|
41337
|
-
return { outcome: "CONSENSUS_UNAVAILABLE", rounds: round, finalArtifact: artifact, history };
|
|
41340
|
+
return { outcome: "CONSENSUS_UNAVAILABLE", rounds: round, finalArtifact: artifact, history, unresolved: [] };
|
|
41338
41341
|
}
|
|
41339
41342
|
const headOutcomes = input.heads.map((persona) => ({
|
|
41340
41343
|
persona,
|
|
@@ -41360,7 +41363,7 @@ ${dismissedFwd.slice(-20).join("\n")}` : "";
|
|
|
41360
41363
|
let adj;
|
|
41361
41364
|
if (issues.length > 0) {
|
|
41362
41365
|
if (calls + 1 > input.maxHeadCalls) {
|
|
41363
|
-
return { outcome: "CONSENSUS_BLOCKED", rounds: round, finalArtifact: artifact, history, ...decision ? { escalation: decision } : {} };
|
|
41366
|
+
return { outcome: "CONSENSUS_BLOCKED", rounds: round, finalArtifact: artifact, history, unresolved: history[history.length - 1]?.accepted ?? [], ...decision ? { escalation: decision } : {} };
|
|
41364
41367
|
}
|
|
41365
41368
|
calls++;
|
|
41366
41369
|
try {
|
|
@@ -41374,7 +41377,7 @@ ${dismissedFwd.slice(-20).join("\n")}` : "";
|
|
|
41374
41377
|
history.push({ round, accepted: adj.accepted, dismissed: adj.dismissed, headOutcomes });
|
|
41375
41378
|
adj.dismissed.forEach((d) => dismissedFwd.push(`- ${d.id}: ${d.reason}`));
|
|
41376
41379
|
if (adj.accepted.length === 0) {
|
|
41377
|
-
return { outcome: "CONVERGED", rounds: round, finalArtifact: artifact, history, ...decision ? { escalation: decision } : {} };
|
|
41380
|
+
return { outcome: "CONVERGED", rounds: round, finalArtifact: artifact, history, unresolved: [], ...decision ? { escalation: decision } : {} };
|
|
41378
41381
|
}
|
|
41379
41382
|
if (round === effectiveRounds) {
|
|
41380
41383
|
if (!decision) {
|
|
@@ -41384,12 +41387,12 @@ ${dismissedFwd.slice(-20).join("\n")}` : "";
|
|
|
41384
41387
|
escalated = true;
|
|
41385
41388
|
effectiveRounds = Math.min(effectiveRounds + decision.grantedRounds, input.rounds * 2);
|
|
41386
41389
|
} else {
|
|
41387
|
-
return { outcome: "CONSENSUS_BLOCKED", rounds: round, finalArtifact: artifact, history, ...decision ? { escalation: decision } : {} };
|
|
41390
|
+
return { outcome: "CONSENSUS_BLOCKED", rounds: round, finalArtifact: artifact, history, unresolved: history[history.length - 1]?.accepted ?? [], ...decision ? { escalation: decision } : {} };
|
|
41388
41391
|
}
|
|
41389
41392
|
}
|
|
41390
41393
|
artifact = await input.revise(artifact, adj.accepted);
|
|
41391
41394
|
}
|
|
41392
|
-
return { outcome: "CONSENSUS_BLOCKED", rounds: effectiveRounds, finalArtifact: artifact, history };
|
|
41395
|
+
return { outcome: "CONSENSUS_BLOCKED", rounds: effectiveRounds, finalArtifact: artifact, history, unresolved: history[history.length - 1]?.accepted ?? [] };
|
|
41393
41396
|
}
|
|
41394
41397
|
|
|
41395
41398
|
// src/consensus/spec-identity.ts
|
|
@@ -41688,7 +41691,8 @@ async function runSpecGate(_target, deps, opts) {
|
|
|
41688
41691
|
outcome: "CONSENSUS_BLOCKED",
|
|
41689
41692
|
...keptClarifications.length > 0 ? { operatorClarifications: keptClarifications } : {},
|
|
41690
41693
|
...droppedByCap.length > 0 ? { droppedByCap } : {},
|
|
41691
|
-
...result.escalation ? { escalation: result.escalation } : {}
|
|
41694
|
+
...result.escalation ? { escalation: result.escalation } : {},
|
|
41695
|
+
unresolved: result.unresolved
|
|
41692
41696
|
};
|
|
41693
41697
|
}
|
|
41694
41698
|
return { outcome: result.outcome };
|
|
@@ -57470,6 +57474,44 @@ function humanizeClarificationBody(clarification) {
|
|
|
57470
57474
|
const context = clarification.rawQuestion.replace(/\b(?:parseable|SPEC_IDENTITY_MISMATCH|machine-usable)\b/gi, "").replace(/\s+/g, " ").trim();
|
|
57471
57475
|
return context ? `${prefix} ${context}` : prefix;
|
|
57472
57476
|
}
|
|
57477
|
+
var BLOCK_DECISION_OPENER = "The reviewers could not agree on this spec";
|
|
57478
|
+
var BLOCK_BODY_TRAILER = " How should I proceed?";
|
|
57479
|
+
function renderUnresolvedPoints(unresolved) {
|
|
57480
|
+
return unresolved.map(
|
|
57481
|
+
(issue2) => issue2.text.replace(/\b(?:parseable|SPEC_IDENTITY_MISMATCH|machine-usable)\b/gi, "").replace(/\s+/g, " ").trim()
|
|
57482
|
+
).join("; ");
|
|
57483
|
+
}
|
|
57484
|
+
function renderBlockDecisionBody(taskRef, unresolved) {
|
|
57485
|
+
if (unresolved.length === 0) {
|
|
57486
|
+
return `${BLOCK_DECISION_OPENER} (task ${taskRef}), and their objections could not be read back.${BLOCK_BODY_TRAILER}`;
|
|
57487
|
+
}
|
|
57488
|
+
return `${BLOCK_DECISION_OPENER} (task ${taskRef}). Still unsettled: ${renderUnresolvedPoints(unresolved)}.${BLOCK_BODY_TRAILER}`;
|
|
57489
|
+
}
|
|
57490
|
+
function buildBlockDecisionOptions(diagnosis, reviewAgainAvailable) {
|
|
57491
|
+
const recommendReviewAgain = reviewAgainAvailable && (diagnosis === "INFRA" || diagnosis === "SUBSTANCE");
|
|
57492
|
+
const recommendEditSpec = !reviewAgainAvailable || diagnosis === "AMBIGUITY";
|
|
57493
|
+
const options = [];
|
|
57494
|
+
if (reviewAgainAvailable) {
|
|
57495
|
+
options.push({
|
|
57496
|
+
label: "Review again",
|
|
57497
|
+
description: "Send the current spec back for another review.",
|
|
57498
|
+
answer: REVIEW_AGAIN_ANSWER,
|
|
57499
|
+
...recommendReviewAgain ? { recommended: true } : {}
|
|
57500
|
+
});
|
|
57501
|
+
}
|
|
57502
|
+
options.push({
|
|
57503
|
+
label: "Edit spec",
|
|
57504
|
+
description: "Open the spec and change it by hand; the review restarts on save.",
|
|
57505
|
+
answer: EDIT_SPEC_ANSWER,
|
|
57506
|
+
...recommendEditSpec ? { recommended: true } : {}
|
|
57507
|
+
});
|
|
57508
|
+
options.push({
|
|
57509
|
+
label: "Proceed anyway",
|
|
57510
|
+
description: "Start the work with these points unsettled and recorded.",
|
|
57511
|
+
answer: PROCEED_ANYWAY_ANSWER
|
|
57512
|
+
});
|
|
57513
|
+
return options;
|
|
57514
|
+
}
|
|
57473
57515
|
var defaultNativeSpecGateBuilders = { buildSpecGateDeps, runSpecGate };
|
|
57474
57516
|
async function runNativeSpecGate(ctx, input, builders = defaultNativeSpecGateBuilders) {
|
|
57475
57517
|
const deps = builders.buildSpecGateDeps({
|
|
@@ -57516,6 +57558,7 @@ function stripHumanizeOpener(body) {
|
|
|
57516
57558
|
}
|
|
57517
57559
|
return body;
|
|
57518
57560
|
}
|
|
57561
|
+
var DID_NOT_CONVERGE_ERROR = "Consensus blocked: reviewers did not converge within budget.";
|
|
57519
57562
|
async function handleConsensusBlocked(result, ctx, input, resolvedTaskId) {
|
|
57520
57563
|
const operatorClarifications = result.operatorClarifications ?? [];
|
|
57521
57564
|
const diagnostics = result.diagnostics ?? [];
|
|
@@ -57523,9 +57566,10 @@ async function handleConsensusBlocked(result, ctx, input, resolvedTaskId) {
|
|
|
57523
57566
|
const taskId = page?.taskId ?? null;
|
|
57524
57567
|
if (!resolvedTaskId && taskId) resolvedTaskId = taskId;
|
|
57525
57568
|
const adjudicated = [];
|
|
57569
|
+
let taskInboxItems = [];
|
|
57526
57570
|
if (taskId) {
|
|
57527
57571
|
try {
|
|
57528
|
-
|
|
57572
|
+
taskInboxItems = await ctx.client.listInboxItems(input.projectSlug, { taskId });
|
|
57529
57573
|
for (const item of taskInboxItems) {
|
|
57530
57574
|
if (item.origin === "gate" && (item.status === "acknowledged" || item.status === "rejected")) {
|
|
57531
57575
|
adjudicated.push({ body: stripHumanizeOpener(item.body), answer: item.answer, status: item.status });
|
|
@@ -57594,6 +57638,35 @@ async function handleConsensusBlocked(result, ctx, input, resolvedTaskId) {
|
|
|
57594
57638
|
filedQuestionCount = toFile.length;
|
|
57595
57639
|
}
|
|
57596
57640
|
}
|
|
57641
|
+
if (filedQuestionCount === 0 && diagnostics.length === 0 && taskId && page) {
|
|
57642
|
+
const domain2 = await resolveSpecDomain(ctx.client, input.projectSlug, {
|
|
57643
|
+
id: page.id,
|
|
57644
|
+
taskId: page.taskId ?? null
|
|
57645
|
+
});
|
|
57646
|
+
const reviewHash = domainScopedReviewHash2(page.contentHash, domain2);
|
|
57647
|
+
const baseBlockItemId = `II-${taskId}-gateblock-${(0, import_node_crypto9.createHash)("sha256").update(reviewHash).digest("hex").slice(0, 10)}`;
|
|
57648
|
+
let taskRef = taskId;
|
|
57649
|
+
try {
|
|
57650
|
+
const t = await ctx.client.getTask(input.projectSlug, taskId);
|
|
57651
|
+
if (t?.title) taskRef = `${taskId} \u2014 ${t.title}`;
|
|
57652
|
+
} catch {
|
|
57653
|
+
}
|
|
57654
|
+
const reviewAgainAvailable = !taskInboxItems.some(
|
|
57655
|
+
(item) => item.id === baseBlockItemId && item.status !== "pending" && item.answer === REVIEW_AGAIN_ANSWER
|
|
57656
|
+
);
|
|
57657
|
+
const blockItemId = reviewAgainAvailable ? baseBlockItemId : `${baseBlockItemId}-2`;
|
|
57658
|
+
try {
|
|
57659
|
+
await ctx.client.createInboxItem(input.projectSlug, {
|
|
57660
|
+
id: blockItemId,
|
|
57661
|
+
kind: "question",
|
|
57662
|
+
taskId,
|
|
57663
|
+
body: renderBlockDecisionBody(taskRef, result.unresolved ?? []),
|
|
57664
|
+
origin: "gate_block",
|
|
57665
|
+
questionOptions: buildBlockDecisionOptions(result.escalation?.diagnosis, reviewAgainAvailable)
|
|
57666
|
+
});
|
|
57667
|
+
} catch {
|
|
57668
|
+
}
|
|
57669
|
+
}
|
|
57597
57670
|
if (operatorClarifications.length > 0) {
|
|
57598
57671
|
try {
|
|
57599
57672
|
if (page) {
|
|
@@ -57634,7 +57707,7 @@ async function handleConsensusBlocked(result, ctx, input, resolvedTaskId) {
|
|
|
57634
57707
|
} else if (operatorClarifications.length > 0) {
|
|
57635
57708
|
error51 = `Consensus blocked on ${operatorClarifications.length} clarification(s), but the spec page is not linked to a task or plan, so none could be filed as questions.`;
|
|
57636
57709
|
} else {
|
|
57637
|
-
error51 =
|
|
57710
|
+
error51 = DID_NOT_CONVERGE_ERROR;
|
|
57638
57711
|
}
|
|
57639
57712
|
if (result.escalation) {
|
|
57640
57713
|
error51 += ` (diagnosis: ${result.escalation.diagnosis})`;
|
|
@@ -57776,6 +57849,14 @@ function onComplete2(outcome, input) {
|
|
|
57776
57849
|
body: taskRef ? `Consensus blocked on ${taskRef} (Specs/${input.pageId}); filed ${n} clarifying question${n === 1 ? "" : "s"} \u2014 answer to unblock the run.` : `Consensus blocked on Specs/${input.pageId}; filed ${n} clarifying question${n === 1 ? "" : "s"} \u2014 answer to unblock the run.`
|
|
57777
57850
|
};
|
|
57778
57851
|
}
|
|
57852
|
+
if (outcome.kind === "failed" && outcome.error.startsWith(DID_NOT_CONVERGE_ERROR) && taskId) {
|
|
57853
|
+
return {
|
|
57854
|
+
kind: "info",
|
|
57855
|
+
suppressInbox: true,
|
|
57856
|
+
...taskId ? { taskId } : {},
|
|
57857
|
+
body: taskRef ? `Consensus blocked on ${taskRef} (Specs/${input.pageId}); the reviewers did not agree \u2014 answer the decision question to unblock the run.` : `Consensus blocked on Specs/${input.pageId}; the reviewers did not agree \u2014 answer the decision question to unblock the run.`
|
|
57858
|
+
};
|
|
57859
|
+
}
|
|
57779
57860
|
const handoffTaskRef = taskRef ? ` (${taskRef})` : "";
|
|
57780
57861
|
return {
|
|
57781
57862
|
kind: "handoff",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrrlin-dev/mcp",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"mrrlin-mcp": "dist/bin.cjs"
|
|
@@ -23,10 +23,10 @@
|
|
|
23
23
|
"tsx": "^4.22.3",
|
|
24
24
|
"@mrrlin/client": "0.0.0",
|
|
25
25
|
"@mrrlin/codex-client": "0.0.0",
|
|
26
|
-
"@mrrlin/director-e2e": "0.0.0",
|
|
27
|
-
"@mrrlin/schemas": "0.0.0",
|
|
28
26
|
"@mrrlin/tsconfig": "0.0.0",
|
|
29
|
-
"@mrrlin/wiki": "0.0.0"
|
|
27
|
+
"@mrrlin/wiki": "0.0.0",
|
|
28
|
+
"@mrrlin/schemas": "0.0.0",
|
|
29
|
+
"@mrrlin/director-e2e": "0.0.0"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@iarna/toml": "^2.2.5",
|