@mrrlin-dev/mcp 0.3.40 → 0.3.41

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 +72 -24
  2. package/package.json +3 -3
package/dist/bin.cjs CHANGED
@@ -38955,7 +38955,7 @@ function startCodexProbe(deps = {}) {
38955
38955
  }
38956
38956
 
38957
38957
  // src/_generated/version.ts
38958
- var PKG_VERSION = "0.3.40";
38958
+ var PKG_VERSION = "0.3.41";
38959
38959
 
38960
38960
  // src/api-base-url.ts
38961
38961
  var DEFAULT_API_BASE_URL = "http://127.0.0.1:8787";
@@ -53397,31 +53397,77 @@ async function resolveActiveRunHead(input, deps) {
53397
53397
 
53398
53398
  // src/async-tools/consensus.ts
53399
53399
  var import_node_crypto8 = require("node:crypto");
53400
- function buildGateQuestionOptions(category) {
53401
- if (category === "scope") {
53402
- return [
53403
- {
53404
- answer: "Use the narrower scope only. Update the spec to keep the original limited scope and do not add the broader interpretation unless explicitly required.",
53405
- description: "Do only the originally requested narrower scope and leave the broader bucket out unless explicitly required.",
53406
- label: "Narrower"
53407
- },
53408
- {
53409
- answer: "Use the broader scope. Update the spec to explicitly include the broader interpretation and any required acceptance criteria.",
53410
- description: "Treat the broader interpretation as in scope and spell out the extra acceptance criteria it adds.",
53411
- label: "Broader"
53412
- }
53413
- ];
53400
+ function normalizeClarificationQuestion(question) {
53401
+ return question.replace(/\s+/g, " ").trim().replace(/[?.!]+$/, "").trim();
53402
+ }
53403
+ function stripLeadingPromptPhrase(part) {
53404
+ return part.replace(
53405
+ /^(?:should|could|would|can|do|does|is|are)\s+(?:this|we|it|the spec|the plan|the task)\s+/i,
53406
+ ""
53407
+ ).trim();
53408
+ }
53409
+ function stripLeadVerb(part) {
53410
+ return part.replace(/^(?:cover|include|support|use|keep|allow|propose|add|handle)\s+/i, "").trim();
53411
+ }
53412
+ function isAbstractOnlyChoice(part) {
53413
+ const normalized = stripLeadVerb(stripLeadingPromptPhrase(part)).replace(/^(?:the|a|an)\s+/i, "").trim().toLowerCase();
53414
+ return /^(?:broader|narrower|safer(?: default)?|stronger(?: interpretation)?)$/.test(normalized);
53415
+ }
53416
+ function sentenceCase(text) {
53417
+ return text ? text.charAt(0).toUpperCase() + text.slice(1) : text;
53418
+ }
53419
+ function deriveGateChoice(question) {
53420
+ const normalized = normalizeClarificationQuestion(question);
53421
+ if (!normalized || normalized.length > 180 || /[;:]/.test(normalized)) return null;
53422
+ const matches = [...normalized.matchAll(/\sor\s/gi)];
53423
+ if (matches.length !== 1) return null;
53424
+ const match = matches[0];
53425
+ if (!match) return null;
53426
+ const splitAt = match.index ?? -1;
53427
+ if (splitAt <= 0) return null;
53428
+ let left = stripLeadingPromptPhrase(normalized.slice(0, splitAt).trim());
53429
+ let right = stripLeadingPromptPhrase(normalized.slice(splitAt + match[0].length).trim());
53430
+ if (!left || !right || /\sor\s/i.test(left) || /\sor\s/i.test(right)) return null;
53431
+ if (isAbstractOnlyChoice(left) || isAbstractOnlyChoice(right)) return null;
53432
+ if (/^only\s+/i.test(left) && /^also\s+/i.test(right)) {
53433
+ const leftScope = stripLeadVerb(left.replace(/^only\s+/i, "").trim());
53434
+ const rightScope = stripLeadVerb(right.replace(/^also\s+/i, "").trim());
53435
+ if (!leftScope || !rightScope) return null;
53436
+ return {
53437
+ leftLabel: `Only ${leftScope}`,
53438
+ leftDescription: `Keep the scope limited to ${leftScope} only.`,
53439
+ leftAnswer: `Keep the scope limited to ${leftScope} only. Update the spec so that limit is explicit.`,
53440
+ rightLabel: `${sentenceCase(leftScope)} + ${rightScope}`,
53441
+ rightDescription: `Expand the scope to cover ${leftScope} and ${rightScope}.`,
53442
+ rightAnswer: `Expand the scope to cover ${leftScope} and ${rightScope}. Update the spec so both are explicitly in scope.`
53443
+ };
53414
53444
  }
53445
+ left = sentenceCase(left);
53446
+ right = sentenceCase(right);
53447
+ if (!left || !right) return null;
53448
+ return {
53449
+ leftLabel: left,
53450
+ leftDescription: `Choose the first direction: ${left}.`,
53451
+ leftAnswer: `Choose ${left}. Update the spec so that direction is explicit.`,
53452
+ rightLabel: right,
53453
+ rightDescription: `Choose the second direction: ${right}.`,
53454
+ rightAnswer: `Choose ${right}. Update the spec so that direction is explicit.`
53455
+ };
53456
+ }
53457
+ function buildGateQuestionOptions(question, category) {
53458
+ if (category !== "scope" && category !== "ambiguity") return null;
53459
+ const derived = deriveGateChoice(question);
53460
+ if (!derived) return null;
53415
53461
  return [
53416
53462
  {
53417
- answer: "Use the safer/default interpretation. Update the spec to document that assumption explicitly.",
53418
- description: "Choose the lower-risk default interpretation and record it explicitly so implementation is unblocked.",
53419
- label: "Safer default"
53463
+ answer: derived.leftAnswer,
53464
+ description: derived.leftDescription,
53465
+ label: derived.leftLabel
53420
53466
  },
53421
53467
  {
53422
- answer: "Use the broader/stronger interpretation. Update the spec to make that interpretation explicit.",
53423
- description: "Commit to the stronger interpretation instead of a conservative default, and update the spec to match.",
53424
- label: "Stronger interpretation"
53468
+ answer: derived.rightAnswer,
53469
+ description: derived.rightDescription,
53470
+ label: derived.rightLabel
53425
53471
  }
53426
53472
  ];
53427
53473
  }
@@ -53509,13 +53555,14 @@ async function run(ctx, input) {
53509
53555
  const scopeId = taskId;
53510
53556
  const id = `II-${scopeId}-gate-${(0, import_node_crypto8.createHash)("sha256").update(clarification.question).digest("hex").slice(0, 10)}`;
53511
53557
  try {
53558
+ const questionOptions = buildGateQuestionOptions(clarification.question, clarification.category);
53512
53559
  await ctx.client.createInboxItem(input.projectSlug, {
53513
53560
  id,
53514
53561
  kind: "question",
53515
53562
  taskId: scopeId,
53516
53563
  body: clarification.question,
53517
53564
  origin: "gate",
53518
- questionOptions: buildGateQuestionOptions(clarification.category)
53565
+ ...questionOptions ? { questionOptions } : {}
53519
53566
  });
53520
53567
  } catch {
53521
53568
  }
@@ -53526,13 +53573,14 @@ async function run(ctx, input) {
53526
53573
  const scopeId = planId;
53527
53574
  const id = `II-${scopeId}-gate-${(0, import_node_crypto8.createHash)("sha256").update(clarification.question).digest("hex").slice(0, 10)}`;
53528
53575
  try {
53576
+ const questionOptions = buildGateQuestionOptions(clarification.question, clarification.category);
53529
53577
  await ctx.client.createInboxItem(input.projectSlug, {
53530
53578
  id,
53531
53579
  kind: "question",
53532
53580
  planId: scopeId,
53533
53581
  body: clarification.question,
53534
53582
  origin: "gate",
53535
- questionOptions: buildGateQuestionOptions(clarification.category)
53583
+ ...questionOptions ? { questionOptions } : {}
53536
53584
  });
53537
53585
  } catch {
53538
53586
  }
@@ -53605,7 +53653,7 @@ function onComplete2(outcome, input) {
53605
53653
  return {
53606
53654
  kind: "handoff",
53607
53655
  ...taskId ? { taskId } : {},
53608
- body: `Consensus could not complete for Specs/${input.pageId}${taskRef}: ${outcome.error} Needs operator attention.`
53656
+ body: `The spec review stopped for Specs/${input.pageId}${taskRef}. ${outcome.error} Review the item, consult the Director if needed, then continue in Codex or handle it manually.`
53609
53657
  };
53610
53658
  }
53611
53659
  var consensusDescriptor = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrrlin-dev/mcp",
3
- "version": "0.3.40",
3
+ "version": "0.3.41",
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/client": "0.0.0",
25
24
  "@mrrlin/director-e2e": "0.0.0",
26
25
  "@mrrlin/wiki": "0.0.0",
27
26
  "@mrrlin/schemas": "0.0.0",
28
27
  "@mrrlin/codex-client": "0.0.0",
29
- "@mrrlin/tsconfig": "0.0.0"
28
+ "@mrrlin/tsconfig": "0.0.0",
29
+ "@mrrlin/client": "0.0.0"
30
30
  },
31
31
  "dependencies": {
32
32
  "@iarna/toml": "^2.2.5",