@mrrlin-dev/mcp 0.4.120 → 0.4.122

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 +60 -13
  2. package/package.json +1 -1
package/dist/bin.cjs CHANGED
@@ -39070,7 +39070,25 @@ var mrrlinProjectRenameSchema = external_exports.object({
39070
39070
  intentJudgeEnabled: external_exports.boolean().optional(),
39071
39071
  clientName: external_exports.string().trim().max(80).nullable().optional(),
39072
39072
  scopeDescription: external_exports.string().trim().max(240).nullable().optional(),
39073
- codeHost: mrrlinProjectCodeHostSchema.nullable().optional()
39073
+ codeHost: mrrlinProjectCodeHostSchema.nullable().optional(),
39074
+ // local-git-delivery: compare-and-set for codeHost. When true, codeHost is written only while the
39075
+ // stored value is still null, in one conditional UPDATE, so a background writer (the bridge applying
39076
+ // an answered code-host question) can never overwrite a host the operator chose meanwhile.
39077
+ codeHostOnlyIfUnset: external_exports.boolean().optional()
39078
+ }).superRefine((value, ctx) => {
39079
+ if (!value.codeHostOnlyIfUnset)
39080
+ return;
39081
+ const others = ["displayName", "intentJudgeEnabled", "clientName", "scopeDescription"].filter((key) => value[key] !== void 0);
39082
+ if (others.length > 0) {
39083
+ ctx.addIssue({
39084
+ code: external_exports.ZodIssueCode.custom,
39085
+ path: ["codeHostOnlyIfUnset"],
39086
+ message: `codeHostOnlyIfUnset updates codeHost alone; also sent: ${others.join(", ")}`
39087
+ });
39088
+ }
39089
+ if (value.codeHost === void 0 || value.codeHost === null) {
39090
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["codeHost"], message: "codeHostOnlyIfUnset requires a non-null codeHost" });
39091
+ }
39074
39092
  });
39075
39093
  var ONBOARDING_KICKOFF_TRANSITIONS = [
39076
39094
  { from: null, to: "pending" },
@@ -62102,7 +62120,7 @@ Do NOT derail the current task - if the operator has an in-flight question, answ
62102
62120
  }
62103
62121
 
62104
62122
  // src/_generated/version.ts
62105
- var PKG_VERSION = "0.4.120";
62123
+ var PKG_VERSION = "0.4.122";
62106
62124
 
62107
62125
  // src/receipt-signing.ts
62108
62126
  var import_node_crypto13 = __toESM(require("node:crypto"), 1);
@@ -66102,7 +66120,27 @@ function completionTurnMinBudgetMs() {
66102
66120
  function isCompletionTurnDisabled() {
66103
66121
  return (process.env.MRRLIN_COMPLETION_TURN_DISABLED ?? "").trim() === "1";
66104
66122
  }
66105
- function buildCompletionTurnPrompt(taskId, currentStatus) {
66123
+ function buildCompletionTurnPrompt(taskId, currentStatus, options = {}) {
66124
+ if (options.localGit) {
66125
+ return [
66126
+ `Your work turn ended but task ${taskId} is still in status "${currentStatus}".`,
66127
+ "",
66128
+ "This project's code lives only on the operator's computer; the bridge verifies and closes the task.",
66129
+ "",
66130
+ "If the work IS genuinely complete:",
66131
+ "1. Make sure every change is committed on the current run branch (never push, never touch the default branch).",
66132
+ "2. Update the task notes with a markdown summary of what you accomplished.",
66133
+ "3. Call update_task with status=awaiting_verification (NOT closed_done) \u2014 the bridge then runs the",
66134
+ " build and tests itself and closes the task on a signed receipt.",
66135
+ "",
66136
+ "If the work is NOT complete \u2014 be honest, do not close incomplete work:",
66137
+ "1. If you are blocked and need an operator decision, call update_task with status=handoff_needed and",
66138
+ " explain what remains in the notes.",
66139
+ "2. Append a handoff_judgement artifact explaining what the operator needs to do.",
66140
+ "",
66141
+ "You must pick one of these paths \u2014 do not leave the task in_progress."
66142
+ ].join("\n");
66143
+ }
66106
66144
  return [
66107
66145
  `Your work turn ended but task ${taskId} is still in status "${currentStatus}".`,
66108
66146
  "",
@@ -66320,8 +66358,9 @@ var LOCAL_GIT_EXECUTOR_INSTRUCTIONS = [
66320
66358
  "This project's code lives only in a git repository on the operator's own computer; it has no",
66321
66359
  "remote. Your worktree is on the run branch. Commit your work on THIS branch. Never run `git push`,",
66322
66360
  "never add a remote, never open a pull request, and never switch to or merge into the default branch.",
66323
- "When your turn ends, the bridge itself commits anything left uncommitted, runs the project's build",
66324
- "and tests, and records the result \u2014 you do not need to report a link."
66361
+ "When the work is done, set the task to status awaiting_verification (never closed_done): the bridge",
66362
+ "then commits anything left uncommitted, runs the project's build and tests itself, and closes the",
66363
+ "task on a signed receipt \u2014 you do not need to report a link."
66325
66364
  ].join("\n");
66326
66365
  var EXECUTOR_LOCAL_GIT_BASE_INSTRUCTIONS = `${EXECUTOR_BASE_INSTRUCTIONS}
66327
66366
  ${LOCAL_GIT_EXECUTOR_INSTRUCTIONS}`;
@@ -66343,6 +66382,7 @@ function artifactKindForEvent(event) {
66343
66382
  }
66344
66383
  var COMPLETED_TASK_STATUSES = /* @__PURE__ */ new Set(["closed_done"]);
66345
66384
  var CODE_PR_READY_TASK_STATUSES = /* @__PURE__ */ new Set(["closed_done", "awaiting_verification"]);
66385
+ var LOCAL_GIT_READY_TASK_STATUSES = /* @__PURE__ */ new Set(["awaiting_verification"]);
66346
66386
  var COMPLETION_EVIDENCE_KINDS = /* @__PURE__ */ new Set([
66347
66387
  "checkpoint",
66348
66388
  "test_result",
@@ -66476,15 +66516,16 @@ async function gatherContext(client, projectSlug, task, openRunId, rawProjectInp
66476
66516
  autonomyEvents
66477
66517
  };
66478
66518
  }
66479
- async function assertRunCompletionReady(deps, projectSlug, taskId, runId, allowedStatuses) {
66519
+ async function assertRunCompletionReady(deps, projectSlug, taskId, runId, allowedStatuses, options = {}) {
66480
66520
  const task = await deps.client.getTask(projectSlug, taskId);
66481
66521
  if (!allowedStatuses.has(task.status)) {
66482
66522
  return {
66483
66523
  ok: false,
66484
- reason: `Codex turn completed but task ${task.id} remained in status ${task.status}.`,
66524
+ reason: `Agent turn completed but task ${task.id} remained in status ${task.status}.`,
66485
66525
  task
66486
66526
  };
66487
66527
  }
66528
+ if (options.bridgeVerifiesDelivery) return { ok: true, task };
66488
66529
  const runs = await deps.client.listExecutionRuns(projectSlug, { taskId });
66489
66530
  const runIds = new Set(runs.map((run3) => run3.id));
66490
66531
  runIds.add(runId);
@@ -66497,7 +66538,7 @@ async function assertRunCompletionReady(deps, projectSlug, taskId, runId, allowe
66497
66538
  if (!hasEvidence) {
66498
66539
  return {
66499
66540
  ok: false,
66500
- reason: `Codex turn completed and task ${task.id} closed, but task lineage for run ${runId} has no durable completion evidence artifact.`,
66541
+ reason: `Agent turn completed and task ${task.id} closed, but task lineage for run ${runId} has no durable completion evidence artifact.`,
66501
66542
  task
66502
66543
  };
66503
66544
  }
@@ -67243,8 +67284,10 @@ Continue executing task ${task.id}. Make the next concrete increment of progress
67243
67284
  );
67244
67285
  return;
67245
67286
  }
67246
- const prReadyStatuses = useExecutor ? CODE_PR_READY_TASK_STATUSES : COMPLETED_TASK_STATUSES;
67247
- let readiness = await assertRunCompletionReady(deps, projectSlug, task.id, runId, prReadyStatuses);
67287
+ const prReadyStatuses = useExecutor ? localGitMode ? LOCAL_GIT_READY_TASK_STATUSES : CODE_PR_READY_TASK_STATUSES : COMPLETED_TASK_STATUSES;
67288
+ let readiness = await assertRunCompletionReady(deps, projectSlug, task.id, runId, prReadyStatuses, {
67289
+ bridgeVerifiesDelivery: useExecutor && localGitMode === true
67290
+ });
67248
67291
  if (!readiness.ok) {
67249
67292
  const completionBudget = Math.min(completionTurnBudgetMs(), remainingTurnBudgetMs());
67250
67293
  if (isCompletionTurnDisabled() || completionBudget < completionTurnMinBudgetMs()) {
@@ -67260,7 +67303,9 @@ Continue executing task ${task.id}. Make the next concrete increment of progress
67260
67303
  previousStatus: readiness.task.status
67261
67304
  })
67262
67305
  );
67263
- const completionPrompt = buildCompletionTurnPrompt(task.id, readiness.task.status);
67306
+ const completionPrompt = buildCompletionTurnPrompt(task.id, readiness.task.status, {
67307
+ localGit: useExecutor && localGitMode === true
67308
+ });
67264
67309
  const completionOutcome = recordTurn2(
67265
67310
  await driveTurn(
67266
67311
  deps,
@@ -67280,7 +67325,9 @@ Continue executing task ${task.id}. Make the next concrete increment of progress
67280
67325
  await failRun(deps, projectSlug, readiness.task, runId, leaseId, completionOutcome.error);
67281
67326
  return;
67282
67327
  }
67283
- readiness = await assertRunCompletionReady(deps, projectSlug, task.id, runId, prReadyStatuses);
67328
+ readiness = await assertRunCompletionReady(deps, projectSlug, task.id, runId, prReadyStatuses, {
67329
+ bridgeVerifiesDelivery: useExecutor && localGitMode === true
67330
+ });
67284
67331
  if (!readiness.ok) {
67285
67332
  await failRun(deps, projectSlug, readiness.task, runId, leaseId, readiness.reason);
67286
67333
  return;
@@ -75129,7 +75176,7 @@ function buildThreadStartParams(msg, config2, desiredModel) {
75129
75176
  "- Reply in the operator's language for the whole turn (questions, task scopes, summaries).",
75130
75177
  "- Keep chat short and human. No code blocks, DDL, terminal output, local filesystem paths, internal job/inbox UUIDs or alert markers in chat \u2014 put long content into a wiki page and link it.",
75131
75178
  "- Spec pages in folder Specs must contain `## Acceptance criteria` followed by `- [ ]` items.",
75132
- "- AGNOSTIC DELIVERY MANDATE: Mrrlin is an Agnostic Delivery Platform decoupled from mandatory GitHub. Delivery is routed strictly by artifact kind: (1) document -> wiki; (2) page -> publish (web pages, landing pages, interactive HTML previews); (3) file_set -> artifacts (file uploads, bundles, build zips); (4) message -> send (outbound webhooks, Slack, notifications); (5) code_change -> repo_host (GitHub; with no GitHub, a local git repo on the operator's computer: register_local_checkout without repo, init_local_repo only after an explicit yes, record their push choice with set_project_code_host). NEVER stall or refuse non-code tasks by demanding a Git repository. Non-code tasks deliver directly via page (Publish) or document (Wiki).",
75179
+ "- AGNOSTIC DELIVERY MANDATE: Mrrlin is an Agnostic Delivery Platform decoupled from mandatory GitHub. Delivery is routed strictly by artifact kind: (1) document -> wiki; (2) page -> publish (web pages, landing pages, interactive HTML previews); (3) file_set -> artifacts (file uploads, bundles, build zips); (4) message -> send (outbound webhooks, Slack, notifications); (5) code_change -> repo_host (GitHub, or with none a local repo: register_local_checkout without repo; init_local_repo only after a yes; push choice via set_project_code_host; NEVER edit or commit project code yourself, only a code run does). NEVER stall or refuse non-code tasks by demanding a Git repository. Non-code tasks deliver directly via page (Publish) or document (Wiki).",
75133
75180
  "- 3-TIER COMMERCIAL SCOPE GOVERNANCE: Treat tasks by domain governance tier. (1) Tier 1 Core Tech Delivery (backend, frontend, SRE, databases): decompose autonomously into repository code changes (when a repo is bound) or code artifacts. (2) Tier 2 Planning & Content (landing pages, SEO, marketing): create actionable drafts; when details such as a phone number, brand name or copy are missing, do not loop on questions \u2014 create the task, record `## Placeholders: [NEED_INPUT: <item>]` in the Wiki spec, and set `autonomyLevel: 'human_review'`. (3) Tier 3 Guardrailed Advisory (high risk: privacy/GDPR, security/SOC 2, billing, production database migrations, infrastructure): always set `autonomyLevel: 'human_review'`, put the domain's standard safety controls into the spec, and state that irreversible actions need human sign-off.",
75134
75181
  "- INBOX QUESTION RETIREMENT MANDATE \u2014 Retiring answered questions: Before creating a task/plan, retire only pending Inbox questions the operator actually answered. Call `decide_inbox_item(itemId: <exact id>, decidedBy: 'director', verdict: 'acknowledged', answer: <actual answer>)`. Use `verdict: 'rejected', reason: ...` only if moot. Never close an unrelated item.",
75135
75182
  "- CHAT CLARIFICATIONS ARE IN CHAT ONLY: During synchronous interactive Director chat, ask clarifying questions directly in your chat response. DO NOT call `create_inbox_item(kind: 'question')` for routine conversational clarifications in Turn 1 \u2014 Inbox questions are reserved for autonomous background workers or asynchronous gate pauses that occur while the operator is away.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrrlin-dev/mcp",
3
- "version": "0.4.120",
3
+ "version": "0.4.122",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "mrrlin-mcp": "dist/bin.cjs"