@rallycry/conveyor-agent 10.10.0 → 10.11.1

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.
@@ -1901,6 +1901,7 @@ async function restoreOnBoot(bundle, cwd) {
1901
1901
  import { z } from "zod";
1902
1902
  import { z as z2 } from "zod";
1903
1903
  import { z as z3 } from "zod";
1904
+ import { z as z4 } from "zod";
1904
1905
  var DEFAULT_SONNET_MODEL = "claude-sonnet-5";
1905
1906
  var FABLE_MODEL = "claude-fable-5";
1906
1907
  var TUI_KINDS = ["claude-code", "opencode"];
@@ -2795,6 +2796,105 @@ var CreateProjectSuggestionRequestSchema = z3.object({
2795
2796
  tagNames: z3.array(z3.string()).optional(),
2796
2797
  requestingUserId: z3.string().optional()
2797
2798
  });
2799
+ var ProjectTagContextPathSchema = z4.object({
2800
+ type: z4.enum(["rule", "doc", "file", "folder"]),
2801
+ path: z4.string().min(1).max(500),
2802
+ label: z4.string().max(100).optional()
2803
+ });
2804
+ var hexColor = z4.string().regex(/^#[0-9a-fA-F]{6}$/, "Expected #RRGGBB hex color");
2805
+ var CreateProjectTagRequestSchema = z4.object({
2806
+ projectId: z4.string(),
2807
+ name: z4.string().min(1).max(50),
2808
+ color: hexColor.optional(),
2809
+ description: z4.string().max(500).optional(),
2810
+ contextPaths: z4.array(ProjectTagContextPathSchema).max(20).optional(),
2811
+ requestingUserId: z4.string().optional()
2812
+ });
2813
+ var UpdateProjectTagRequestSchema = z4.object({
2814
+ projectId: z4.string(),
2815
+ tagId: z4.string(),
2816
+ name: z4.string().min(1).max(50).optional(),
2817
+ color: hexColor.optional(),
2818
+ description: z4.string().max(500).optional(),
2819
+ /** Full replacement of the tag's context links when provided. */
2820
+ contextPaths: z4.array(ProjectTagContextPathSchema).max(20).optional(),
2821
+ requestingUserId: z4.string().optional()
2822
+ });
2823
+ var PostToProjectChatRequestSchema = z4.object({
2824
+ projectId: z4.string(),
2825
+ content: z4.string().min(1).max(2e4),
2826
+ requestingUserId: z4.string().optional()
2827
+ });
2828
+ var StartTagAuditRequestSchema = z4.object({
2829
+ projectId: z4.string(),
2830
+ requestingUserId: z4.string().optional()
2831
+ });
2832
+ var StartTaskAuditRequestSchema = z4.object({
2833
+ projectId: z4.string(),
2834
+ taskIds: z4.array(z4.string()).min(1).max(20),
2835
+ requestingUserId: z4.string().optional()
2836
+ });
2837
+ var GetActiveAuditSessionsRequestSchema = z4.object({
2838
+ projectId: z4.string()
2839
+ });
2840
+ var ReportTaskAuditResultRequestSchema = z4.object({
2841
+ projectId: z4.string(),
2842
+ taskId: z4.string(),
2843
+ summary: z4.string(),
2844
+ turnGrades: z4.array(
2845
+ z4.object({
2846
+ turnIndex: z4.number(),
2847
+ phase: z4.enum(["planning", "building", "human"]),
2848
+ grade: z4.enum(["correct", "neutral", "blunder"]),
2849
+ reasoning: z4.string(),
2850
+ eventType: z4.string(),
2851
+ eventSummary: z4.string()
2852
+ })
2853
+ ),
2854
+ planningAccuracy: z4.number().nullable(),
2855
+ buildingAccuracy: z4.number().nullable(),
2856
+ humanAccuracy: z4.number().nullable(),
2857
+ planningCorrect: z4.number(),
2858
+ planningNeutral: z4.number(),
2859
+ planningBlunder: z4.number(),
2860
+ buildingCorrect: z4.number(),
2861
+ buildingNeutral: z4.number(),
2862
+ buildingBlunder: z4.number(),
2863
+ humanCorrect: z4.number(),
2864
+ humanNeutral: z4.number(),
2865
+ humanBlunder: z4.number(),
2866
+ humanEvaluations: z4.array(
2867
+ z4.object({
2868
+ messageIndex: z4.number(),
2869
+ rating: z4.union([z4.literal(-1), z4.literal(0), z4.literal(1)]),
2870
+ reasoning: z4.string()
2871
+ })
2872
+ ).optional(),
2873
+ suggestionIds: z4.array(z4.string()),
2874
+ auditCostUsd: z4.number().nullable(),
2875
+ model: z4.string().nullable(),
2876
+ /** When set, the audit is marked failed with this message instead. */
2877
+ error: z4.string().optional()
2878
+ });
2879
+ var GetTaskAuditsRequestSchema = z4.object({
2880
+ projectId: z4.string(),
2881
+ limit: z4.number().int().positive().max(200).optional().default(50)
2882
+ });
2883
+ var GetTaskAuditRequestSchema = z4.object({
2884
+ projectId: z4.string(),
2885
+ auditId: z4.string()
2886
+ });
2887
+ var GetTaskAuditAggregatesRequestSchema = z4.object({
2888
+ projectId: z4.string()
2889
+ });
2890
+ var DeleteTaskAuditRequestSchema = z4.object({
2891
+ projectId: z4.string(),
2892
+ auditId: z4.string(),
2893
+ requestingUserId: z4.string().optional()
2894
+ });
2895
+ var MarkInitialPromptSubmittedRequestSchema = z4.object({
2896
+ sessionId: z4.string()
2897
+ });
2798
2898
  var AGENT_STATUS_REASON_USER_QUESTION = "user_question";
2799
2899
  var TASK_CHAT_HISTORY_LIMIT = 20;
2800
2900
  var PM_CHAT_HISTORY_LIMIT = 40;
@@ -3922,7 +4022,7 @@ var PtyOutputCoalescer = class {
3922
4022
 
3923
4023
  // src/harness/pty/tool-server.ts
3924
4024
  import { createServer as createServer2 } from "http";
3925
- import { z as z4 } from "zod";
4025
+ import { z as z5 } from "zod";
3926
4026
  import { writeFile as writeFile3 } from "fs/promises";
3927
4027
  import { join as join2 } from "path";
3928
4028
  import { randomBytes } from "crypto";
@@ -3979,7 +4079,7 @@ var PtyToolServer = class {
3979
4079
  const mcp = new McpServer({ name: this.name, version: "1.0.0" });
3980
4080
  const register = mcp.registerTool.bind(mcp);
3981
4081
  for (const tool2 of this.tools) {
3982
- const inputSchema = tool2.strict ? z4.strictObject(tool2.schema) : tool2.schema;
4082
+ const inputSchema = tool2.strict ? z5.strictObject(tool2.schema) : tool2.schema;
3983
4083
  register(
3984
4084
  tool2.name,
3985
4085
  {
@@ -5320,9 +5420,52 @@ var PtySession = class {
5320
5420
  }
5321
5421
  };
5322
5422
 
5423
+ // src/harness/pty/config-home-health.ts
5424
+ import { mkdir as mkdir4 } from "fs/promises";
5425
+ import { homedir as homedir3 } from "os";
5426
+ import { join as join5 } from "path";
5427
+ var MOUNT_DISCONNECT_CODES = /* @__PURE__ */ new Set(["ENOTCONN", "EIO", "ESTALE", "ENXIO"]);
5428
+ var MOUNT_DISCONNECT_MESSAGES = [
5429
+ "socket is not connected",
5430
+ "transport endpoint is not connected"
5431
+ ];
5432
+ function isMountDisconnectError(err) {
5433
+ if (typeof err !== "object" || err === null) return false;
5434
+ const code = err.code;
5435
+ if (typeof code === "string" && MOUNT_DISCONNECT_CODES.has(code)) return true;
5436
+ const message = err.message;
5437
+ if (typeof message !== "string") return false;
5438
+ const lower = message.toLowerCase();
5439
+ return MOUNT_DISCONNECT_MESSAGES.some((needle) => lower.includes(needle));
5440
+ }
5441
+ function podLocalConfigHome() {
5442
+ return join5(homedir3(), ".claude-local");
5443
+ }
5444
+ async function ensureUsableClaudeConfigHome(cwd, log) {
5445
+ const configHome = claudeConfigHome();
5446
+ try {
5447
+ await mkdir4(join5(configHome, "projects", projectSlug(cwd)), { recursive: true });
5448
+ return { configHome, fellBack: false };
5449
+ } catch (err) {
5450
+ if (!isMountDisconnectError(err)) throw err;
5451
+ const fallback = podLocalConfigHome();
5452
+ log?.warn(
5453
+ "shared ~/.claude mount is unreachable; falling back to a pod-local config home. Session history will not persist across pods until the mount recovers.",
5454
+ {
5455
+ code: err.code ?? null,
5456
+ from: configHome,
5457
+ to: fallback
5458
+ }
5459
+ );
5460
+ process.env.CLAUDE_CONFIG_DIR = fallback;
5461
+ await mkdir4(join5(fallback, "projects", projectSlug(cwd)), { recursive: true });
5462
+ return { configHome: fallback, fellBack: true };
5463
+ }
5464
+ }
5465
+
5323
5466
  // src/harness/pty/index.ts
5324
5467
  var ENDED_GRACE_MS = 4e3;
5325
- var PtyHarness = class {
5468
+ var PtyHarness = class _PtyHarness {
5326
5469
  /**
5327
5470
  * `bridge` relays raw terminal I/O to/from the S2 server (and on to the S5
5328
5471
  * terminal). It is undefined for SDK-only callers and PTY runs that never
@@ -5334,6 +5477,7 @@ var PtyHarness = class {
5334
5477
  }
5335
5478
  bridge;
5336
5479
  adapter;
5480
+ static log = createServiceLogger("pty-harness");
5337
5481
  /** Fingerprint of the spawn-time options a reused process cannot change. */
5338
5482
  fingerprintOf(options) {
5339
5483
  return this.adapter.spawnFingerprint({
@@ -5376,6 +5520,9 @@ var PtyHarness = class {
5376
5520
  await stale.teardown();
5377
5521
  }
5378
5522
  session = new PtySession(opts.prompt, opts.options, want, this.bridge, this.adapter);
5523
+ if (this.adapter.capabilities.structuredEvents) {
5524
+ await ensureUsableClaudeConfigHome(opts.options.cwd, _PtyHarness.log);
5525
+ }
5379
5526
  await this.adapter.prepareEnvironment({ cwd: opts.options.cwd });
5380
5527
  session.onExit(() => this.handleSessionExit(session));
5381
5528
  await session.start();
@@ -6915,7 +7062,7 @@ async function buildInitialPrompt(mode, context, isAuto, agentMode) {
6915
7062
  }
6916
7063
 
6917
7064
  // src/tools/task-context-tools.ts
6918
- import { z as z5 } from "zod";
7065
+ import { z as z6 } from "zod";
6919
7066
 
6920
7067
  // src/tools/helpers.ts
6921
7068
  function textResult(text) {
@@ -6949,8 +7096,8 @@ function buildReadTaskChatTool(connection) {
6949
7096
  "read_task_chat",
6950
7097
  "Read recent human/user chat messages for a task. Omit task_id for the current task; pass a child ID for a child's chat. For agent logs use get_execution_logs.",
6951
7098
  {
6952
- limit: z5.number().optional().describe("Number of recent messages to fetch (default 20)"),
6953
- task_id: z5.string().optional().describe("Child task ID to read chat from. Omit to read the current task's chat.")
7099
+ limit: z6.number().optional().describe("Number of recent messages to fetch (default 20)"),
7100
+ task_id: z6.string().optional().describe("Child task ID to read chat from. Omit to read the current task's chat.")
6954
7101
  },
6955
7102
  async ({ limit, task_id }) => {
6956
7103
  try {
@@ -6994,7 +7141,7 @@ function buildGetTaskTool(connection) {
6994
7141
  "get_task",
6995
7142
  "Look up any task by slug or ID. Returns JSON with id, slug, title, description, plan, status, branch, githubPRNumber, githubPRUrl, storyPoints. For children use list_subtasks.",
6996
7143
  {
6997
- slug_or_id: z5.string().describe("The task slug (e.g. 'my-task') or CUID")
7144
+ slug_or_id: z6.string().describe("The task slug (e.g. 'my-task') or CUID")
6998
7145
  },
6999
7146
  async ({ slug_or_id }) => {
7000
7147
  try {
@@ -7017,9 +7164,9 @@ function buildGetExecutionLogsTool(connection) {
7017
7164
  "get_execution_logs",
7018
7165
  "Read CLI execution logs \u2014 agent reasoning, tool calls, and setup/dev-server output. Filter via source='agent' or 'application'. For human chat use read_task_chat.",
7019
7166
  {
7020
- task_id: z5.string().optional().describe("Task ID or slug. Omit to read logs from the current task."),
7021
- source: z5.enum(["agent", "application"]).optional().describe("Filter by log source. Omit for all logs."),
7022
- limit: z5.number().optional().describe("Max number of log entries to return (default 50, max 500).")
7167
+ task_id: z6.string().optional().describe("Task ID or slug. Omit to read logs from the current task."),
7168
+ source: z6.enum(["agent", "application"]).optional().describe("Filter by log source. Omit for all logs."),
7169
+ limit: z6.number().optional().describe("Max number of log entries to return (default 50, max 500).")
7023
7170
  },
7024
7171
  async ({ task_id, source, limit }) => {
7025
7172
  try {
@@ -7079,7 +7226,7 @@ function buildGetAttachmentTool(connection) {
7079
7226
  return defineTool(
7080
7227
  "get_attachment",
7081
7228
  "Fetch one task file's content plus metadata by file ID. Call list_task_files first to discover IDs and check sizes \u2014 large binaries may be truncated by the service's size limit.",
7082
- { fileId: z5.string().describe("The file ID to retrieve") },
7229
+ { fileId: z6.string().describe("The file ID to retrieve") },
7083
7230
  async ({ fileId }) => {
7084
7231
  try {
7085
7232
  const file = await connection.call("getTaskFile", {
@@ -7117,7 +7264,7 @@ function buildTaskContextTools(connection) {
7117
7264
  }
7118
7265
 
7119
7266
  // src/tools/dependency-suggestion-tools.ts
7120
- import { z as z6 } from "zod";
7267
+ import { z as z7 } from "zod";
7121
7268
  function buildGetDependenciesTool(connection) {
7122
7269
  return defineTool(
7123
7270
  "get_dependencies",
@@ -7143,10 +7290,10 @@ function buildGetSuggestionsTool(connection) {
7143
7290
  "get_suggestions",
7144
7291
  "List project suggestions sorted by vote score. Filter by status or cap with limit (default 20). Suggestions are project-level ideas, not tasks \u2014 use get_task for tasks.",
7145
7292
  {
7146
- status: z6.string().optional().describe(
7293
+ status: z7.string().optional().describe(
7147
7294
  "Filter by status: Planning, Open, InProgress, ReviewPR, ReviewDev, ReviewLive, Complete, Cancelled"
7148
7295
  ),
7149
- limit: z6.number().int().min(1).max(100).optional().describe("Max results (default 20)")
7296
+ limit: z7.number().int().min(1).max(100).optional().describe("Max results (default 20)")
7150
7297
  },
7151
7298
  async ({ status, limit }) => {
7152
7299
  try {
@@ -7170,14 +7317,14 @@ function buildGetSuggestionsTool(connection) {
7170
7317
  }
7171
7318
 
7172
7319
  // src/tools/mutation-tools.ts
7173
- import { z as z7 } from "zod";
7320
+ import { z as z8 } from "zod";
7174
7321
  function buildPostToChatTool(connection) {
7175
7322
  return defineTool(
7176
7323
  "post_to_chat",
7177
7324
  "Post a message to the task chat for the team to see. Your turn output is NOT shown in chat, so this is the only way the team sees your status, summaries, and questions. Omit task_id to post to the current task's chat; pass a child's ID to message its chat.",
7178
7325
  {
7179
- message: z7.string().describe("The message to post to the team"),
7180
- task_id: z7.string().optional().describe("Child task ID to post to. Omit to post to the current task's chat.")
7326
+ message: z8.string().describe("The message to post to the team"),
7327
+ task_id: z8.string().optional().describe("Child task ID to post to. Omit to post to the current task's chat.")
7181
7328
  },
7182
7329
  async ({ message, task_id }) => {
7183
7330
  try {
@@ -7215,8 +7362,8 @@ function buildForceUpdateTaskStatusTool(connection) {
7215
7362
  "force_update_task_status",
7216
7363
  "EMERGENCY ONLY: force-override a task's Kanban status. Use when an automatic transition failed and the task is wedged. Normal flow transitions status automatically.",
7217
7364
  {
7218
- status: z7.enum(["InProgress", "ReviewPR", "ReviewDev", "Complete"]).describe("The new status for the task"),
7219
- task_id: z7.string().optional().describe("Child task ID to update. Omit to update the current task.")
7365
+ status: z8.enum(["InProgress", "ReviewPR", "ReviewDev", "Complete"]).describe("The new status for the task"),
7366
+ task_id: z8.string().optional().describe("Child task ID to update. Omit to update the current task.")
7220
7367
  },
7221
7368
  async ({ status, task_id }) => {
7222
7369
  try {
@@ -7247,18 +7394,18 @@ function buildCreatePullRequestTool(connection, config) {
7247
7394
  "create_pull_request",
7248
7395
  "Create a GitHub PR for this task. Auto-stages, commits (commitMessage or title default), pushes to origin, then opens the PR. Always use this instead of gh CLI or raw git.",
7249
7396
  {
7250
- title: z7.string().describe("The PR title"),
7251
- body: z7.string().describe("The PR description/body in markdown"),
7252
- branch: z7.string().optional().describe(
7397
+ title: z8.string().describe("The PR title"),
7398
+ body: z8.string().describe("The PR description/body in markdown"),
7399
+ branch: z8.string().optional().describe(
7253
7400
  "The head branch name for the PR. If the task doesn't have a branch set, this will be used. Defaults to the task's existing branch."
7254
7401
  ),
7255
- baseBranch: z7.string().optional().describe(
7402
+ baseBranch: z8.string().optional().describe(
7256
7403
  "The base branch to target for the PR (e.g. 'main', 'develop'). Defaults to the project's configured dev branch."
7257
7404
  ),
7258
- commitMessage: z7.string().optional().describe(
7405
+ commitMessage: z8.string().optional().describe(
7259
7406
  "Commit message for staging uncommitted changes. If not provided, a default message based on the PR title will be used."
7260
7407
  ),
7261
- skipVerify: z7.boolean().optional().describe(
7408
+ skipVerify: z8.boolean().optional().describe(
7262
7409
  "Controls the local pre-push quality gate (lint/typecheck/test). Defaults to true (--no-verify): the push skips the local gate because you should run gates yourself before opening the PR and CI re-runs them on the resulting PR. Running the full gate synchronously during the push would block the agent's event loop long enough to drop the Conveyor socket connection. Pass false to force the local pre-push hook to run."
7263
7410
  )
7264
7411
  },
@@ -7340,7 +7487,7 @@ function buildAddDependencyTool(connection) {
7340
7487
  "add_dependency",
7341
7488
  "Add a blocking dependency \u2014 this task cannot start until the named task is merged to dev. For post-task follow-ups use create_follow_up_task instead.",
7342
7489
  {
7343
- depends_on_slug_or_id: z7.string().describe("Slug or ID of the task this task depends on")
7490
+ depends_on_slug_or_id: z8.string().describe("Slug or ID of the task this task depends on")
7344
7491
  },
7345
7492
  async ({ depends_on_slug_or_id }) => {
7346
7493
  try {
@@ -7362,7 +7509,7 @@ function buildRemoveDependencyTool(connection) {
7362
7509
  "remove_dependency",
7363
7510
  "Remove a previously added dependency from this task. When to use: the dependency was added in error or is no longer relevant. Returns: confirmation string.",
7364
7511
  {
7365
- depends_on_slug_or_id: z7.string().describe("Slug or ID of the task to remove as dependency")
7512
+ depends_on_slug_or_id: z8.string().describe("Slug or ID of the task to remove as dependency")
7366
7513
  },
7367
7514
  async ({ depends_on_slug_or_id }) => {
7368
7515
  try {
@@ -7384,10 +7531,10 @@ function buildCreateFollowUpTaskTool(connection) {
7384
7531
  "create_follow_up_task",
7385
7532
  "Create a follow-up task that depends on the current task. Use for out-of-scope work or cleanup that should land after this task merges. For blockers use add_dependency.",
7386
7533
  {
7387
- title: z7.string().describe("Follow-up task title"),
7388
- description: z7.string().optional().describe("Brief description of the follow-up work"),
7389
- plan: z7.string().optional().describe("Implementation plan if known"),
7390
- story_point_value: z7.number().optional().describe("Story point estimate (1=Common, 2=Magic, 3=Rare, 5=Unique)")
7534
+ title: z8.string().describe("Follow-up task title"),
7535
+ description: z8.string().optional().describe("Brief description of the follow-up work"),
7536
+ plan: z8.string().optional().describe("Implementation plan if known"),
7537
+ story_point_value: z8.number().optional().describe("Story point estimate (1=Common, 2=Magic, 3=Rare, 5=Unique)")
7391
7538
  },
7392
7539
  async ({ title, description, plan, story_point_value }) => {
7393
7540
  try {
@@ -7414,11 +7561,11 @@ function buildCreateSuggestionTool(connection) {
7414
7561
  "create_suggestion",
7415
7562
  "Suggest a feature, improvement, rule, or idea for the project. Duplicates are deduped and your upvote is recorded. For actionable work on this task open a follow-up task.",
7416
7563
  {
7417
- title: z7.string().describe("Short title for the suggestion"),
7418
- description: z7.string().optional().describe(
7564
+ title: z8.string().describe("Short title for the suggestion"),
7565
+ description: z8.string().optional().describe(
7419
7566
  "1-2 sentence description of what should change and why. Keep concise and project-focused."
7420
7567
  ),
7421
- tag_names: z7.array(z7.string()).optional().describe("Tag names to categorize the suggestion")
7568
+ tag_names: z8.array(z8.string()).optional().describe("Tag names to categorize the suggestion")
7422
7569
  },
7423
7570
  async ({ title, description, tag_names }) => {
7424
7571
  try {
@@ -7447,8 +7594,8 @@ function buildVoteSuggestionTool(connection) {
7447
7594
  "vote_suggestion",
7448
7595
  "Vote +1 or -1 on a project suggestion. Use to express support or disagreement with a specific suggestion returned by get_suggestions.",
7449
7596
  {
7450
- suggestion_id: z7.string().describe("The suggestion ID to vote on"),
7451
- value: z7.number().refine((v) => v === 1 || v === -1, { message: "Value must be 1 or -1" }).describe("+1 to upvote, -1 to downvote")
7597
+ suggestion_id: z8.string().describe("The suggestion ID to vote on"),
7598
+ value: z8.number().refine((v) => v === 1 || v === -1, { message: "Value must be 1 or -1" }).describe("+1 to upvote, -1 to downvote")
7452
7599
  },
7453
7600
  async ({ suggestion_id, value }) => {
7454
7601
  try {
@@ -7480,8 +7627,8 @@ function buildMutationTools(connection, config) {
7480
7627
 
7481
7628
  // src/tools/attachment-tools.ts
7482
7629
  import { readFile as readFile3, stat as stat4 } from "fs/promises";
7483
- import { basename, extname, isAbsolute, join as join5 } from "path";
7484
- import { z as z8 } from "zod";
7630
+ import { basename, extname, isAbsolute, join as join6 } from "path";
7631
+ import { z as z9 } from "zod";
7485
7632
  var IMAGE_MIME_BY_EXT = {
7486
7633
  ".png": "image/png",
7487
7634
  ".jpg": "image/jpeg",
@@ -7494,12 +7641,12 @@ function buildUploadAttachmentTool(connection, config) {
7494
7641
  "upload_attachment",
7495
7642
  "Upload an image file (e.g. a Playwright screenshot) as a task attachment AND post it to the task chat in one step \u2014 no follow-up post_to_chat call needed. Supports png/jpg/gif/webp.",
7496
7643
  {
7497
- path: z8.string().describe("Path to the image file \u2014 absolute, or relative to the workspace root"),
7498
- title: z8.string().optional().describe("Short caption posted with the image (defaults to the file name)")
7644
+ path: z9.string().describe("Path to the image file \u2014 absolute, or relative to the workspace root"),
7645
+ title: z9.string().optional().describe("Short caption posted with the image (defaults to the file name)")
7499
7646
  },
7500
7647
  async ({ path: path4, title }) => {
7501
7648
  try {
7502
- const filePath = isAbsolute(path4) ? path4 : join5(config.workspaceDir, path4);
7649
+ const filePath = isAbsolute(path4) ? path4 : join6(config.workspaceDir, path4);
7503
7650
  const mimeType = IMAGE_MIME_BY_EXT[extname(filePath).toLowerCase()];
7504
7651
  if (!mimeType) {
7505
7652
  return textResult(
@@ -7551,7 +7698,7 @@ function buildUploadAttachmentTool(connection, config) {
7551
7698
  }
7552
7699
 
7553
7700
  // src/tools/checklist-tools.ts
7554
- import { z as z9 } from "zod";
7701
+ import { z as z10 } from "zod";
7555
7702
  function buildListManualTestsTool(connection) {
7556
7703
  return defineTool(
7557
7704
  "list_manual_tests",
@@ -7603,8 +7750,8 @@ function buildQueryManualTestsTool(connection) {
7603
7750
  "query_manual_tests",
7604
7751
  "Query manual tests across many tasks in this project, grouped by task. Filter by card status (ReviewDev, ReviewLive, Complete, ...) and/or test status (open | approved | rejected). Use to answer 'show all OPEN manual tests in ReviewDev' or 'show all REJECTED manual tests with the failing reason'. With no filters it defaults to the needs-attention view: open+rejected tests on ReviewDev/ReviewLive cards.",
7605
7752
  {
7606
- cardStatuses: z9.array(z9.string()).optional().describe('Filter tasks by card status, e.g. ["ReviewDev", "ReviewLive"]'),
7607
- testStatuses: z9.array(z9.enum(["open", "approved", "rejected"])).optional().describe("Filter tests by status: open | approved | rejected")
7753
+ cardStatuses: z10.array(z10.string()).optional().describe('Filter tasks by card status, e.g. ["ReviewDev", "ReviewLive"]'),
7754
+ testStatuses: z10.array(z10.enum(["open", "approved", "rejected"])).optional().describe("Filter tests by status: open | approved | rejected")
7608
7755
  },
7609
7756
  async ({ cardStatuses, testStatuses }) => {
7610
7757
  try {
@@ -7628,7 +7775,7 @@ function buildSetManualTestsTool(connection) {
7628
7775
  "set_manual_tests",
7629
7776
  "Add manual test steps to the task checklist. Existing items with the same title are automatically skipped (deduplication). Use to record specific manual verification steps that reviewers should follow when testing this PR.",
7630
7777
  {
7631
- items: z9.array(z9.object({ title: z9.string().min(1).describe("A concise, actionable test step") })).min(1).describe("List of manual test steps to add")
7778
+ items: z10.array(z10.object({ title: z10.string().min(1).describe("A concise, actionable test step") })).min(1).describe("List of manual test steps to add")
7632
7779
  },
7633
7780
  async ({ items }) => {
7634
7781
  try {
@@ -7651,8 +7798,8 @@ function buildEditManualTestTool(connection) {
7651
7798
  "edit_manual_test",
7652
7799
  "Rename an existing manual test step. Identify the test by its current title (case-insensitive); pass the new title to replace it. Use to correct or refine a recorded manual verification step.",
7653
7800
  {
7654
- title: z9.string().min(1).describe("The current title of the manual test to edit"),
7655
- newTitle: z9.string().min(1).describe("The new title for the manual test")
7801
+ title: z10.string().min(1).describe("The current title of the manual test to edit"),
7802
+ newTitle: z10.string().min(1).describe("The new title for the manual test")
7656
7803
  },
7657
7804
  async ({ title, newTitle }) => {
7658
7805
  try {
@@ -7674,7 +7821,7 @@ function buildRemoveManualTestTool(connection) {
7674
7821
  "remove_manual_test",
7675
7822
  "Remove an existing manual test step from the task checklist. Identify the test by its title (case-insensitive). Use to delete a stale or incorrect manual verification step.",
7676
7823
  {
7677
- title: z9.string().min(1).describe("The title of the manual test to remove")
7824
+ title: z10.string().min(1).describe("The title of the manual test to remove")
7678
7825
  },
7679
7826
  async ({ title }) => {
7680
7827
  try {
@@ -7695,7 +7842,7 @@ function buildApproveManualTestTool(connection) {
7695
7842
  "approve_manual_test",
7696
7843
  "Sign off on (approve) a manual test step on behalf of your authenticated user. Identify the test by its title (case-insensitive). Use after you have verified the step passes.",
7697
7844
  {
7698
- title: z9.string().min(1).describe("The title of the manual test to approve")
7845
+ title: z10.string().min(1).describe("The title of the manual test to approve")
7699
7846
  },
7700
7847
  async ({ title }) => {
7701
7848
  try {
@@ -7716,8 +7863,8 @@ function buildRejectManualTestTool(connection) {
7716
7863
  "reject_manual_test",
7717
7864
  "Flag an issue with (reject) a manual test step on behalf of your authenticated user, recording the reason. Identify the test by its title (case-insensitive). Use when the step fails verification.",
7718
7865
  {
7719
- title: z9.string().min(1).describe("The title of the manual test to reject"),
7720
- reason: z9.string().min(1).max(2e3).describe("Why the test failed \u2014 what went wrong, shown to the team")
7866
+ title: z10.string().min(1).describe("The title of the manual test to reject"),
7867
+ reason: z10.string().min(1).max(2e3).describe("Why the test failed \u2014 what went wrong, shown to the team")
7721
7868
  },
7722
7869
  async ({ title, reason }) => {
7723
7870
  try {
@@ -7754,7 +7901,7 @@ function buildCommonTools(connection, config) {
7754
7901
  }
7755
7902
 
7756
7903
  // src/tools/pm-tools.ts
7757
- import { z as z10 } from "zod";
7904
+ import { z as z11 } from "zod";
7758
7905
  var SP_DESCRIPTION = "Story point value (1=Common, 2=Magic, 3=Rare, 5=Unique)";
7759
7906
  var FOLLOW_PARENT_STATUS_DESCRIPTION = "Child mirrors the parent task's status automatically \u2014 for subtasks that ship on the parent's branch/PR with no build or PR of their own. Manual status writes on a follower stick only until the parent's next transition.";
7760
7907
  var DEPENDS_ON_DESCRIPTION = "Sibling subtask ids or slugs this subtask blocks on (it won't start until they merge to dev). Set explicit dependency metadata here instead of describing order in the plan text \u2014 the pack runner schedules children off these edges. Omit / leave empty for independent children so they run in parallel.";
@@ -7763,8 +7910,8 @@ function buildUpdateTaskTool(connection) {
7763
7910
  "update_task_plan",
7764
7911
  "Save the plan and/or description to the current task. In auto/building mode, save the plan BEFORE writing code and keep it current as the approach evolves \u2014 post it, then build; never pause the build waiting for approval. For children use update_subtask; for title/tags/PR use update_task_properties.",
7765
7912
  {
7766
- plan: z10.string().optional().describe("The task plan in markdown"),
7767
- description: z10.string().optional().describe("Updated task description")
7913
+ plan: z11.string().optional().describe("The task plan in markdown"),
7914
+ description: z11.string().optional().describe("Updated task description")
7768
7915
  },
7769
7916
  async ({ plan, description }) => {
7770
7917
  try {
@@ -7785,13 +7932,13 @@ function buildCreateSubtaskTool(connection) {
7785
7932
  "create_subtask",
7786
7933
  "Create a subtask under the current parent task. Use when breaking a complex parent into smaller pieces during planning. For post-task follow-ups use create_follow_up_task.",
7787
7934
  {
7788
- title: z10.string().describe("Subtask title"),
7789
- description: z10.string().optional().describe("Brief description"),
7790
- plan: z10.string().optional().describe("Implementation plan in markdown"),
7791
- ordinal: z10.number().optional().describe("Step/order number (0-based)"),
7792
- storyPointValue: z10.number().optional().describe(SP_DESCRIPTION),
7793
- followParentStatus: z10.boolean().optional().describe(FOLLOW_PARENT_STATUS_DESCRIPTION),
7794
- dependsOn: z10.array(z10.string()).optional().describe(DEPENDS_ON_DESCRIPTION)
7935
+ title: z11.string().describe("Subtask title"),
7936
+ description: z11.string().optional().describe("Brief description"),
7937
+ plan: z11.string().optional().describe("Implementation plan in markdown"),
7938
+ ordinal: z11.number().optional().describe("Step/order number (0-based)"),
7939
+ storyPointValue: z11.number().optional().describe(SP_DESCRIPTION),
7940
+ followParentStatus: z11.boolean().optional().describe(FOLLOW_PARENT_STATUS_DESCRIPTION),
7941
+ dependsOn: z11.array(z11.string()).optional().describe(DEPENDS_ON_DESCRIPTION)
7795
7942
  },
7796
7943
  async ({
7797
7944
  title,
@@ -7827,20 +7974,20 @@ function buildUpdateSubtaskTool(connection) {
7827
7974
  "update_subtask",
7828
7975
  "Update an existing subtask's fields (title, description, plan, ordinal, storyPointValue, dependsOn) \u2014 and the sanctioned path to make a child buildable: promote it to status Open, assign its agent (agentIdOrName), and set story points. Setting story points does NOT auto-promote; set status explicitly. For the current task use update_task_plan.",
7829
7976
  {
7830
- subtaskId: z10.string().describe("The subtask ID to update"),
7831
- title: z10.string().optional(),
7832
- description: z10.string().optional(),
7833
- plan: z10.string().optional(),
7834
- status: z10.enum(["Planning", "Open"]).optional().describe(
7977
+ subtaskId: z11.string().describe("The subtask ID to update"),
7978
+ title: z11.string().optional(),
7979
+ description: z11.string().optional(),
7980
+ plan: z11.string().optional(),
7981
+ status: z11.enum(["Planning", "Open"]).optional().describe(
7835
7982
  'Move the child between "Planning" and "Open". "Open" marks it ready to execute \u2014 required before start_child_cloud_build. Execution statuses transition automatically.'
7836
7983
  ),
7837
- agentIdOrName: z10.string().optional().describe(
7984
+ agentIdOrName: z11.string().optional().describe(
7838
7985
  "Assign a project agent to the child (agent id or exact name from the Project Agents list). Required before start_child_cloud_build."
7839
7986
  ),
7840
- ordinal: z10.number().optional(),
7841
- storyPointValue: z10.number().optional().describe(SP_DESCRIPTION),
7842
- followParentStatus: z10.boolean().optional().describe(FOLLOW_PARENT_STATUS_DESCRIPTION),
7843
- dependsOn: z10.array(z10.string()).optional().describe(
7987
+ ordinal: z11.number().optional(),
7988
+ storyPointValue: z11.number().optional().describe(SP_DESCRIPTION),
7989
+ followParentStatus: z11.boolean().optional().describe(FOLLOW_PARENT_STATUS_DESCRIPTION),
7990
+ dependsOn: z11.array(z11.string()).optional().describe(
7844
7991
  `${DEPENDS_ON_DESCRIPTION} Replaces the full dependency set \u2014 pass [] to clear all, omit to leave unchanged.`
7845
7992
  )
7846
7993
  },
@@ -7879,7 +8026,7 @@ function buildDeleteSubtaskTool(connection) {
7879
8026
  return defineTool(
7880
8027
  "delete_subtask",
7881
8028
  "Delete a subtask by id. When to use: a subtask was created in error or is no longer needed. Returns: confirmation string.",
7882
- { subtaskId: z10.string().describe("The subtask ID to delete") },
8029
+ { subtaskId: z11.string().describe("The subtask ID to delete") },
7883
8030
  async ({ subtaskId }) => {
7884
8031
  try {
7885
8032
  await connection.call("deleteSubtask", {
@@ -7898,7 +8045,7 @@ function buildListSubtasksTool(connection) {
7898
8045
  "list_subtasks",
7899
8046
  "List all subtasks under the current parent task. Default compact view returns per child: status, agent, story points, PR number/state, dependencies, and holdsBuildSlot \u2014 plus packSlots (in-flight environments vs the PACK_CHILD_LIMIT cap, and which children hold the slots). Use to coordinate child work; pass verbose:true only when you need full description/plan text (large). For non-child tasks use get_task.",
7900
8047
  {
7901
- verbose: z10.boolean().optional().describe(
8048
+ verbose: z11.boolean().optional().describe(
7902
8049
  "Return full task rows including description and plan text (large \u2014 can exceed tool result limits on big packs). Default: compact orchestration view."
7903
8050
  )
7904
8051
  },
@@ -7922,7 +8069,7 @@ function buildPackTools(connection) {
7922
8069
  "start_child_cloud_build",
7923
8070
  "Start a cloud build (codespace) for a child task. Preconditions: child status is `Open`, story points set, and an agent assigned \u2014 satisfy all three with update_subtask (status/agentIdOrName/storyPointValue) first; none happen automatically. A PACK_CHILD_LIMIT error is backpressure, not failure: check list_subtasks packSlots for which children hold the in-flight slots, merge/stop one, then retry.",
7924
8071
  {
7925
- childTaskId: z10.string().describe("The child task ID to start a cloud build for")
8072
+ childTaskId: z11.string().describe("The child task ID to start a cloud build for")
7926
8073
  },
7927
8074
  async ({ childTaskId }) => {
7928
8075
  try {
@@ -7942,7 +8089,7 @@ function buildPackTools(connection) {
7942
8089
  "stop_child_build",
7943
8090
  "Send a graceful stop signal to a running child build's agent. Not a force-kill \u2014 the agent may take a moment to wind down. Stopping a child eventually frees its PACK_CHILD_LIMIT build slot (see list_subtasks packSlots).",
7944
8091
  {
7945
- childTaskId: z10.string().describe("The child task ID whose build should be stopped")
8092
+ childTaskId: z11.string().describe("The child task ID whose build should be stopped")
7946
8093
  },
7947
8094
  async ({ childTaskId }) => {
7948
8095
  try {
@@ -7962,7 +8109,7 @@ function buildPackTools(connection) {
7962
8109
  "approve_and_merge_pr",
7963
8110
  "Approve and merge a child task's PR. Preconditions: child in ReviewPR. Returns { merged }: true = merged (status\u2192ReviewDev); false = automerge queued, wait for ReviewDev.",
7964
8111
  {
7965
- childTaskId: z10.string().describe("The child task ID whose PR should be approved and merged")
8112
+ childTaskId: z11.string().describe("The child task ID whose PR should be approved and merged")
7966
8113
  },
7967
8114
  async ({ childTaskId }) => {
7968
8115
  try {
@@ -8000,7 +8147,7 @@ function buildPmTools(connection, options) {
8000
8147
  }
8001
8148
 
8002
8149
  // src/tools/discovery-tools.ts
8003
- import { z as z11 } from "zod";
8150
+ import { z as z12 } from "zod";
8004
8151
  var SP_DESCRIPTION2 = "Story point value (1=Common, 2=Magic, 3=Rare, 5=Unique). The key is 'storyPointValue' \u2014 not 'storyPoints'.";
8005
8152
  var VALID_PROPERTY_KEYS = "title, storyPointValue, tagNames, githubPRUrl, githubBranch";
8006
8153
  function buildDiscoveryTools(connection) {
@@ -8009,11 +8156,11 @@ function buildDiscoveryTools(connection) {
8009
8156
  "update_task_properties",
8010
8157
  "Set one or more task properties in a single call. Valid keys: title, storyPointValue, tagNames, githubPRUrl, githubBranch. All are optional \u2014 include only the ones you want to update (at least one). Unknown keys are rejected.",
8011
8158
  {
8012
- title: z11.string().optional().describe("The new task title"),
8013
- storyPointValue: z11.number().optional().describe(SP_DESCRIPTION2),
8014
- tagNames: z11.array(z11.string()).optional().describe("Array of tag names to assign"),
8015
- githubPRUrl: z11.string().url().optional().describe("GitHub pull request URL to link to this task"),
8016
- githubBranch: z11.string().optional().describe("Set the GitHub branch name for this task (e.g. 'conveyor/my-feature-abc123')")
8159
+ title: z12.string().optional().describe("The new task title"),
8160
+ storyPointValue: z12.number().optional().describe(SP_DESCRIPTION2),
8161
+ tagNames: z12.array(z12.string()).optional().describe("Array of tag names to assign"),
8162
+ githubPRUrl: z12.string().url().optional().describe("GitHub pull request URL to link to this task"),
8163
+ githubBranch: z12.string().optional().describe("Set the GitHub branch name for this task (e.g. 'conveyor/my-feature-abc123')")
8017
8164
  },
8018
8165
  async ({ title, storyPointValue, tagNames, githubPRUrl, githubBranch }) => {
8019
8166
  try {
@@ -8054,7 +8201,7 @@ function buildDiscoveryTools(connection) {
8054
8201
  }
8055
8202
 
8056
8203
  // src/tools/code-review-tools.ts
8057
- import { z as z12 } from "zod";
8204
+ import { z as z13 } from "zod";
8058
8205
  async function endReviewSession(connection, reason) {
8059
8206
  await connection.call("endReviewSession", {
8060
8207
  sessionId: connection.sessionId,
@@ -8067,7 +8214,7 @@ function buildCodeReviewTools(connection) {
8067
8214
  "approve_code_review",
8068
8215
  "Approve the code review and exit. Use when the diff passes all review criteria. Takes only a summary \u2014 for changes, use request_code_changes with a structured issues[] list.",
8069
8216
  {
8070
- summary: z12.string().describe("Brief summary of what was reviewed and why it looks good")
8217
+ summary: z13.string().describe("Brief summary of what was reviewed and why it looks good")
8071
8218
  },
8072
8219
  async ({ summary }) => {
8073
8220
  const content = `**Code Review: Approved** :white_check_mark:
@@ -8091,15 +8238,15 @@ ${summary}`;
8091
8238
  "request_code_changes",
8092
8239
  "Request changes during code review and exit. Use when substantive issues must be fixed before merge. Each issue: { file, line?, severity: critical|major|minor, description }.",
8093
8240
  {
8094
- issues: z12.array(
8095
- z12.object({
8096
- file: z12.string().describe("File path where the issue was found"),
8097
- line: z12.number().optional().describe("Line number (if applicable)"),
8098
- severity: z12.enum(["critical", "major", "minor"]).describe("Issue severity"),
8099
- description: z12.string().describe("What is wrong and how to fix it")
8241
+ issues: z13.array(
8242
+ z13.object({
8243
+ file: z13.string().describe("File path where the issue was found"),
8244
+ line: z13.number().optional().describe("Line number (if applicable)"),
8245
+ severity: z13.enum(["critical", "major", "minor"]).describe("Issue severity"),
8246
+ description: z13.string().describe("What is wrong and how to fix it")
8100
8247
  })
8101
8248
  ).describe("List of issues found during review"),
8102
- summary: z12.string().describe("Brief overall summary of the review findings")
8249
+ summary: z13.string().describe("Brief overall summary of the review findings")
8103
8250
  },
8104
8251
  async ({ issues, summary }) => {
8105
8252
  const issueLines = issues.map((issue) => {
@@ -8212,7 +8359,7 @@ function createConveyorMcpServer(harness, connection, config, context, agentMode
8212
8359
 
8213
8360
  // src/harness/pty/adapters/types.ts
8214
8361
  import { accessSync, constants, statSync } from "fs";
8215
- import { join as join6 } from "path";
8362
+ import { join as join7 } from "path";
8216
8363
  var TuiUnavailableError = class extends Error {
8217
8364
  constructor(tui, message) {
8218
8365
  super(message);
@@ -8236,7 +8383,7 @@ function findOnPath(binary, env = process.env) {
8236
8383
  }
8237
8384
  for (const dir of (env.PATH ?? "").split(":")) {
8238
8385
  if (!dir) continue;
8239
- const candidate = join6(dir, binary);
8386
+ const candidate = join7(dir, binary);
8240
8387
  if (isExecutable(candidate)) return candidate;
8241
8388
  }
8242
8389
  return null;
@@ -9922,7 +10069,7 @@ var QueryBridge = class {
9922
10069
 
9923
10070
  // src/runner/session-runner-helpers.ts
9924
10071
  import { readFileSync as readFileSync2 } from "fs";
9925
- import { dirname as dirname2, join as join7 } from "path";
10072
+ import { dirname as dirname2, join as join8 } from "path";
9926
10073
  import { fileURLToPath as fileURLToPath2 } from "url";
9927
10074
  function mapChatHistory(messages) {
9928
10075
  if (!messages) return [];
@@ -9951,7 +10098,7 @@ function readAgentVersion() {
9951
10098
  const here = dirname2(fileURLToPath2(import.meta.url));
9952
10099
  for (const rel of ["../package.json", "../../package.json"]) {
9953
10100
  try {
9954
- const pkg = JSON.parse(readFileSync2(join7(here, rel), "utf-8"));
10101
+ const pkg = JSON.parse(readFileSync2(join8(here, rel), "utf-8"));
9955
10102
  if (pkg.version) return pkg.version;
9956
10103
  } catch {
9957
10104
  }
@@ -11424,12 +11571,12 @@ var SessionRunner = class _SessionRunner {
11424
11571
 
11425
11572
  // src/setup/config.ts
11426
11573
  import { readFile as readFile5 } from "fs/promises";
11427
- import { join as join8 } from "path";
11574
+ import { join as join9 } from "path";
11428
11575
  var DEVCONTAINER_PATH = ".devcontainer/conveyor/devcontainer.json";
11429
11576
  var DEVCONTAINER_PORT_DENY_LIST = /* @__PURE__ */ new Set([5432, 6379, 9200]);
11430
11577
  async function loadForwardPorts(workspaceDir) {
11431
11578
  try {
11432
- const raw = await readFile5(join8(workspaceDir, DEVCONTAINER_PATH), "utf-8");
11579
+ const raw = await readFile5(join9(workspaceDir, DEVCONTAINER_PATH), "utf-8");
11433
11580
  const parsed = JSON.parse(raw);
11434
11581
  const ports = (parsed.forwardPorts ?? []).filter(
11435
11582
  (p) => typeof p === "number" && !DEVCONTAINER_PORT_DENY_LIST.has(p)
@@ -11605,13 +11752,15 @@ export {
11605
11752
  TUI_KINDS,
11606
11753
  DEFAULT_LIFECYCLE_CONFIG,
11607
11754
  Lifecycle,
11755
+ defineTool,
11608
11756
  cleanTerminalOutput,
11609
11757
  loadPtySpawn,
11610
11758
  inheritedEnv,
11611
11759
  buildPromptBytes,
11612
11760
  ClaudeTuiAdapter,
11613
- PtyHarness,
11614
11761
  createServiceLogger,
11762
+ PtyHarness,
11763
+ textResult,
11615
11764
  GIT_TIMEOUT_MS,
11616
11765
  hasUncommittedChanges,
11617
11766
  getCurrentBranch,
@@ -11643,4 +11792,4 @@ export {
11643
11792
  runStartCommand,
11644
11793
  unshallowRepo
11645
11794
  };
11646
- //# sourceMappingURL=chunk-BN5TDTW7.js.map
11795
+ //# sourceMappingURL=chunk-N7CLCSZR.js.map