@rallycry/conveyor-agent 10.3.1 → 10.4.0

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.
@@ -2962,7 +2962,8 @@ function defineTool(name, description, schema, handler, options) {
2962
2962
  description,
2963
2963
  schema,
2964
2964
  handler,
2965
- annotations: options?.annotations
2965
+ annotations: options?.annotations,
2966
+ strict: options?.strict
2966
2967
  };
2967
2968
  }
2968
2969
 
@@ -3759,6 +3760,7 @@ var PtyOutputCoalescer = class {
3759
3760
 
3760
3761
  // src/harness/pty/tool-server.ts
3761
3762
  import { createServer as createServer2 } from "http";
3763
+ import { z as z3 } from "zod";
3762
3764
  import { writeFile as writeFile3 } from "fs/promises";
3763
3765
  import { join as join2 } from "path";
3764
3766
  import { randomBytes } from "crypto";
@@ -3813,9 +3815,14 @@ var PtyToolServer = class {
3813
3815
  /** Fresh McpServer with every tool registered — one per MCP session. */
3814
3816
  buildMcpServer() {
3815
3817
  const mcp = new McpServer({ name: this.name, version: "1.0.0" });
3816
- const register = mcp.tool.bind(mcp);
3818
+ const register = mcp.registerTool.bind(mcp);
3817
3819
  for (const tool2 of this.tools) {
3818
- register(tool2.name, tool2.description, tool2.schema, (args) => tool2.handler(args));
3820
+ const inputSchema = tool2.strict ? z3.strictObject(tool2.schema) : tool2.schema;
3821
+ register(
3822
+ tool2.name,
3823
+ { description: tool2.description, inputSchema },
3824
+ (args) => tool2.handler(args)
3825
+ );
3819
3826
  }
3820
3827
  return mcp;
3821
3828
  }
@@ -6078,7 +6085,9 @@ Environment (fully ready \u2014 do NOT verify or set up):`,
6078
6085
  `- All dependencies are installed, database is migrated, and the dev server is running.`,
6079
6086
  `- Git is configured. Commit and push directly to this branch.`,
6080
6087
  `- The shell cwd resets between Bash calls \u2014 always use absolute paths (or \`git -C\`, \`bun run --cwd\`); never spend a tool call on a bare \`cd\`.`,
6081
- `- When a build/lint/test run fails, capture its output to a file once and grep the file \u2014 never re-run the suite just to re-filter the same output. Don't poll background jobs with sleep/ps/tail loops.`,
6088
+ `- When a build/lint/test run fails, capture its output to a file once and grep the file \u2014 never re-run the suite just to re-filter the same output.`,
6089
+ `- Waiting on long-running commands: if a gate finishes in under ~2 minutes, run it in the foreground with a timeout. Anything longer: launch it with run_in_background and STOP \u2014 a completion notification arrives when it finishes. Never busy-wait with sleep/pgrep/tail loops (foreground shell commands are killed at ~2 minutes), and never re-run the suite to escape a wait that looks stalled.`,
6090
+ `- Deferred tools have no schema loaded until fetched \u2014 before first use, load it via ToolSearch (query "select:<ToolName>", e.g. "select:Monitor"); never guess a deferred tool's parameters.`,
6082
6091
  `- The \`gh\` CLI may not be installed \u2014 use the mcp__conveyor__* tools for PR and task state.`,
6083
6092
  `- Read a file before your first Write/Edit to it, and batch multiple changes to the same file into a single call instead of many sequential edits.`,
6084
6093
  `
@@ -6508,7 +6517,7 @@ async function buildInitialPrompt(mode, context, isAuto, agentMode) {
6508
6517
  }
6509
6518
 
6510
6519
  // src/tools/task-context-tools.ts
6511
- import { z as z3 } from "zod";
6520
+ import { z as z4 } from "zod";
6512
6521
 
6513
6522
  // src/tools/helpers.ts
6514
6523
  function textResult(text) {
@@ -6542,8 +6551,8 @@ function buildReadTaskChatTool(connection) {
6542
6551
  "read_task_chat",
6543
6552
  "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.",
6544
6553
  {
6545
- limit: z3.number().optional().describe("Number of recent messages to fetch (default 20)"),
6546
- task_id: z3.string().optional().describe("Child task ID to read chat from. Omit to read the current task's chat.")
6554
+ limit: z4.number().optional().describe("Number of recent messages to fetch (default 20)"),
6555
+ task_id: z4.string().optional().describe("Child task ID to read chat from. Omit to read the current task's chat.")
6547
6556
  },
6548
6557
  async ({ limit, task_id }) => {
6549
6558
  try {
@@ -6587,7 +6596,7 @@ function buildGetTaskTool(connection) {
6587
6596
  "get_task",
6588
6597
  "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.",
6589
6598
  {
6590
- slug_or_id: z3.string().describe("The task slug (e.g. 'my-task') or CUID")
6599
+ slug_or_id: z4.string().describe("The task slug (e.g. 'my-task') or CUID")
6591
6600
  },
6592
6601
  async ({ slug_or_id }) => {
6593
6602
  try {
@@ -6610,9 +6619,9 @@ function buildGetExecutionLogsTool(connection) {
6610
6619
  "get_execution_logs",
6611
6620
  "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.",
6612
6621
  {
6613
- task_id: z3.string().optional().describe("Task ID or slug. Omit to read logs from the current task."),
6614
- source: z3.enum(["agent", "application"]).optional().describe("Filter by log source. Omit for all logs."),
6615
- limit: z3.number().optional().describe("Max number of log entries to return (default 50, max 500).")
6622
+ task_id: z4.string().optional().describe("Task ID or slug. Omit to read logs from the current task."),
6623
+ source: z4.enum(["agent", "application"]).optional().describe("Filter by log source. Omit for all logs."),
6624
+ limit: z4.number().optional().describe("Max number of log entries to return (default 50, max 500).")
6616
6625
  },
6617
6626
  async ({ task_id, source, limit }) => {
6618
6627
  try {
@@ -6672,7 +6681,7 @@ function buildGetAttachmentTool(connection) {
6672
6681
  return defineTool(
6673
6682
  "get_attachment",
6674
6683
  "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.",
6675
- { fileId: z3.string().describe("The file ID to retrieve") },
6684
+ { fileId: z4.string().describe("The file ID to retrieve") },
6676
6685
  async ({ fileId }) => {
6677
6686
  try {
6678
6687
  const file = await connection.call("getTaskFile", {
@@ -6710,7 +6719,7 @@ function buildTaskContextTools(connection) {
6710
6719
  }
6711
6720
 
6712
6721
  // src/tools/dependency-suggestion-tools.ts
6713
- import { z as z4 } from "zod";
6722
+ import { z as z5 } from "zod";
6714
6723
  function buildGetDependenciesTool(connection) {
6715
6724
  return defineTool(
6716
6725
  "get_dependencies",
@@ -6736,10 +6745,10 @@ function buildGetSuggestionsTool(connection) {
6736
6745
  "get_suggestions",
6737
6746
  "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.",
6738
6747
  {
6739
- status: z4.string().optional().describe(
6748
+ status: z5.string().optional().describe(
6740
6749
  "Filter by status: Planning, Open, InProgress, ReviewPR, ReviewDev, ReviewLive, Complete, Cancelled"
6741
6750
  ),
6742
- limit: z4.number().int().min(1).max(100).optional().describe("Max results (default 20)")
6751
+ limit: z5.number().int().min(1).max(100).optional().describe("Max results (default 20)")
6743
6752
  },
6744
6753
  async ({ status, limit }) => {
6745
6754
  try {
@@ -6763,14 +6772,14 @@ function buildGetSuggestionsTool(connection) {
6763
6772
  }
6764
6773
 
6765
6774
  // src/tools/mutation-tools.ts
6766
- import { z as z5 } from "zod";
6775
+ import { z as z6 } from "zod";
6767
6776
  function buildPostToChatTool(connection) {
6768
6777
  return defineTool(
6769
6778
  "post_to_chat",
6770
6779
  "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.",
6771
6780
  {
6772
- message: z5.string().describe("The message to post to the team"),
6773
- task_id: z5.string().optional().describe("Child task ID to post to. Omit to post to the current task's chat.")
6781
+ message: z6.string().describe("The message to post to the team"),
6782
+ task_id: z6.string().optional().describe("Child task ID to post to. Omit to post to the current task's chat.")
6774
6783
  },
6775
6784
  async ({ message, task_id }) => {
6776
6785
  try {
@@ -6808,8 +6817,8 @@ function buildForceUpdateTaskStatusTool(connection) {
6808
6817
  "force_update_task_status",
6809
6818
  "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.",
6810
6819
  {
6811
- status: z5.enum(["InProgress", "ReviewPR", "ReviewDev", "Complete"]).describe("The new status for the task"),
6812
- task_id: z5.string().optional().describe("Child task ID to update. Omit to update the current task.")
6820
+ status: z6.enum(["InProgress", "ReviewPR", "ReviewDev", "Complete"]).describe("The new status for the task"),
6821
+ task_id: z6.string().optional().describe("Child task ID to update. Omit to update the current task.")
6813
6822
  },
6814
6823
  async ({ status, task_id }) => {
6815
6824
  try {
@@ -6840,18 +6849,18 @@ function buildCreatePullRequestTool(connection, config) {
6840
6849
  "create_pull_request",
6841
6850
  "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.",
6842
6851
  {
6843
- title: z5.string().describe("The PR title"),
6844
- body: z5.string().describe("The PR description/body in markdown"),
6845
- branch: z5.string().optional().describe(
6852
+ title: z6.string().describe("The PR title"),
6853
+ body: z6.string().describe("The PR description/body in markdown"),
6854
+ branch: z6.string().optional().describe(
6846
6855
  "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."
6847
6856
  ),
6848
- baseBranch: z5.string().optional().describe(
6857
+ baseBranch: z6.string().optional().describe(
6849
6858
  "The base branch to target for the PR (e.g. 'main', 'develop'). Defaults to the project's configured dev branch."
6850
6859
  ),
6851
- commitMessage: z5.string().optional().describe(
6860
+ commitMessage: z6.string().optional().describe(
6852
6861
  "Commit message for staging uncommitted changes. If not provided, a default message based on the PR title will be used."
6853
6862
  ),
6854
- skipVerify: z5.boolean().optional().describe(
6863
+ skipVerify: z6.boolean().optional().describe(
6855
6864
  "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."
6856
6865
  )
6857
6866
  },
@@ -6933,7 +6942,7 @@ function buildAddDependencyTool(connection) {
6933
6942
  "add_dependency",
6934
6943
  "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.",
6935
6944
  {
6936
- depends_on_slug_or_id: z5.string().describe("Slug or ID of the task this task depends on")
6945
+ depends_on_slug_or_id: z6.string().describe("Slug or ID of the task this task depends on")
6937
6946
  },
6938
6947
  async ({ depends_on_slug_or_id }) => {
6939
6948
  try {
@@ -6955,7 +6964,7 @@ function buildRemoveDependencyTool(connection) {
6955
6964
  "remove_dependency",
6956
6965
  "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.",
6957
6966
  {
6958
- depends_on_slug_or_id: z5.string().describe("Slug or ID of the task to remove as dependency")
6967
+ depends_on_slug_or_id: z6.string().describe("Slug or ID of the task to remove as dependency")
6959
6968
  },
6960
6969
  async ({ depends_on_slug_or_id }) => {
6961
6970
  try {
@@ -6977,10 +6986,10 @@ function buildCreateFollowUpTaskTool(connection) {
6977
6986
  "create_follow_up_task",
6978
6987
  "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.",
6979
6988
  {
6980
- title: z5.string().describe("Follow-up task title"),
6981
- description: z5.string().optional().describe("Brief description of the follow-up work"),
6982
- plan: z5.string().optional().describe("Implementation plan if known"),
6983
- story_point_value: z5.number().optional().describe("Story point estimate (1=Common, 2=Magic, 3=Rare, 5=Unique)")
6989
+ title: z6.string().describe("Follow-up task title"),
6990
+ description: z6.string().optional().describe("Brief description of the follow-up work"),
6991
+ plan: z6.string().optional().describe("Implementation plan if known"),
6992
+ story_point_value: z6.number().optional().describe("Story point estimate (1=Common, 2=Magic, 3=Rare, 5=Unique)")
6984
6993
  },
6985
6994
  async ({ title, description, plan, story_point_value }) => {
6986
6995
  try {
@@ -7007,11 +7016,11 @@ function buildCreateSuggestionTool(connection) {
7007
7016
  "create_suggestion",
7008
7017
  "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.",
7009
7018
  {
7010
- title: z5.string().describe("Short title for the suggestion"),
7011
- description: z5.string().optional().describe(
7019
+ title: z6.string().describe("Short title for the suggestion"),
7020
+ description: z6.string().optional().describe(
7012
7021
  "1-2 sentence description of what should change and why. Keep concise and project-focused."
7013
7022
  ),
7014
- tag_names: z5.array(z5.string()).optional().describe("Tag names to categorize the suggestion")
7023
+ tag_names: z6.array(z6.string()).optional().describe("Tag names to categorize the suggestion")
7015
7024
  },
7016
7025
  async ({ title, description, tag_names }) => {
7017
7026
  try {
@@ -7040,8 +7049,8 @@ function buildVoteSuggestionTool(connection) {
7040
7049
  "vote_suggestion",
7041
7050
  "Vote +1 or -1 on a project suggestion. Use to express support or disagreement with a specific suggestion returned by get_suggestions.",
7042
7051
  {
7043
- suggestion_id: z5.string().describe("The suggestion ID to vote on"),
7044
- value: z5.number().refine((v) => v === 1 || v === -1, { message: "Value must be 1 or -1" }).describe("+1 to upvote, -1 to downvote")
7052
+ suggestion_id: z6.string().describe("The suggestion ID to vote on"),
7053
+ value: z6.number().refine((v) => v === 1 || v === -1, { message: "Value must be 1 or -1" }).describe("+1 to upvote, -1 to downvote")
7045
7054
  },
7046
7055
  async ({ suggestion_id, value }) => {
7047
7056
  try {
@@ -7074,7 +7083,7 @@ function buildMutationTools(connection, config) {
7074
7083
  // src/tools/attachment-tools.ts
7075
7084
  import { readFile as readFile3, stat as stat5 } from "fs/promises";
7076
7085
  import { basename, extname, isAbsolute, join as join5 } from "path";
7077
- import { z as z6 } from "zod";
7086
+ import { z as z7 } from "zod";
7078
7087
  var IMAGE_MIME_BY_EXT = {
7079
7088
  ".png": "image/png",
7080
7089
  ".jpg": "image/jpeg",
@@ -7087,8 +7096,8 @@ function buildUploadAttachmentTool(connection, config) {
7087
7096
  "upload_attachment",
7088
7097
  "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.",
7089
7098
  {
7090
- path: z6.string().describe("Path to the image file \u2014 absolute, or relative to the workspace root"),
7091
- title: z6.string().optional().describe("Short caption posted with the image (defaults to the file name)")
7099
+ path: z7.string().describe("Path to the image file \u2014 absolute, or relative to the workspace root"),
7100
+ title: z7.string().optional().describe("Short caption posted with the image (defaults to the file name)")
7092
7101
  },
7093
7102
  async ({ path: path4, title }) => {
7094
7103
  try {
@@ -7144,7 +7153,7 @@ function buildUploadAttachmentTool(connection, config) {
7144
7153
  }
7145
7154
 
7146
7155
  // src/tools/checklist-tools.ts
7147
- import { z as z7 } from "zod";
7156
+ import { z as z8 } from "zod";
7148
7157
  function buildListManualTestsTool(connection) {
7149
7158
  return defineTool(
7150
7159
  "list_manual_tests",
@@ -7196,8 +7205,8 @@ function buildQueryManualTestsTool(connection) {
7196
7205
  "query_manual_tests",
7197
7206
  "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.",
7198
7207
  {
7199
- cardStatuses: z7.array(z7.string()).optional().describe('Filter tasks by card status, e.g. ["ReviewDev", "ReviewLive"]'),
7200
- testStatuses: z7.array(z7.enum(["open", "approved", "rejected"])).optional().describe("Filter tests by status: open | approved | rejected")
7208
+ cardStatuses: z8.array(z8.string()).optional().describe('Filter tasks by card status, e.g. ["ReviewDev", "ReviewLive"]'),
7209
+ testStatuses: z8.array(z8.enum(["open", "approved", "rejected"])).optional().describe("Filter tests by status: open | approved | rejected")
7201
7210
  },
7202
7211
  async ({ cardStatuses, testStatuses }) => {
7203
7212
  try {
@@ -7221,7 +7230,7 @@ function buildSetManualTestsTool(connection) {
7221
7230
  "set_manual_tests",
7222
7231
  "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.",
7223
7232
  {
7224
- items: z7.array(z7.object({ title: z7.string().min(1).describe("A concise, actionable test step") })).min(1).describe("List of manual test steps to add")
7233
+ items: z8.array(z8.object({ title: z8.string().min(1).describe("A concise, actionable test step") })).min(1).describe("List of manual test steps to add")
7225
7234
  },
7226
7235
  async ({ items }) => {
7227
7236
  try {
@@ -7244,8 +7253,8 @@ function buildEditManualTestTool(connection) {
7244
7253
  "edit_manual_test",
7245
7254
  "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.",
7246
7255
  {
7247
- title: z7.string().min(1).describe("The current title of the manual test to edit"),
7248
- newTitle: z7.string().min(1).describe("The new title for the manual test")
7256
+ title: z8.string().min(1).describe("The current title of the manual test to edit"),
7257
+ newTitle: z8.string().min(1).describe("The new title for the manual test")
7249
7258
  },
7250
7259
  async ({ title, newTitle }) => {
7251
7260
  try {
@@ -7267,7 +7276,7 @@ function buildRemoveManualTestTool(connection) {
7267
7276
  "remove_manual_test",
7268
7277
  "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.",
7269
7278
  {
7270
- title: z7.string().min(1).describe("The title of the manual test to remove")
7279
+ title: z8.string().min(1).describe("The title of the manual test to remove")
7271
7280
  },
7272
7281
  async ({ title }) => {
7273
7282
  try {
@@ -7288,7 +7297,7 @@ function buildApproveManualTestTool(connection) {
7288
7297
  "approve_manual_test",
7289
7298
  "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.",
7290
7299
  {
7291
- title: z7.string().min(1).describe("The title of the manual test to approve")
7300
+ title: z8.string().min(1).describe("The title of the manual test to approve")
7292
7301
  },
7293
7302
  async ({ title }) => {
7294
7303
  try {
@@ -7309,8 +7318,8 @@ function buildRejectManualTestTool(connection) {
7309
7318
  "reject_manual_test",
7310
7319
  "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.",
7311
7320
  {
7312
- title: z7.string().min(1).describe("The title of the manual test to reject"),
7313
- reason: z7.string().min(1).max(2e3).describe("Why the test failed \u2014 what went wrong, shown to the team")
7321
+ title: z8.string().min(1).describe("The title of the manual test to reject"),
7322
+ reason: z8.string().min(1).max(2e3).describe("Why the test failed \u2014 what went wrong, shown to the team")
7314
7323
  },
7315
7324
  async ({ title, reason }) => {
7316
7325
  try {
@@ -7347,7 +7356,7 @@ function buildCommonTools(connection, config) {
7347
7356
  }
7348
7357
 
7349
7358
  // src/tools/pm-tools.ts
7350
- import { z as z8 } from "zod";
7359
+ import { z as z9 } from "zod";
7351
7360
  var SP_DESCRIPTION = "Story point value (1=Common, 2=Magic, 3=Rare, 5=Unique)";
7352
7361
  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.";
7353
7362
  function buildUpdateTaskTool(connection) {
@@ -7355,8 +7364,8 @@ function buildUpdateTaskTool(connection) {
7355
7364
  "update_task_plan",
7356
7365
  "Save the finalized plan and/or description to the current task. Use in Plan mode after alignment. For children use update_subtask; for title/tags/PR use update_task_properties.",
7357
7366
  {
7358
- plan: z8.string().optional().describe("The task plan in markdown"),
7359
- description: z8.string().optional().describe("Updated task description")
7367
+ plan: z9.string().optional().describe("The task plan in markdown"),
7368
+ description: z9.string().optional().describe("Updated task description")
7360
7369
  },
7361
7370
  async ({ plan, description }) => {
7362
7371
  try {
@@ -7377,12 +7386,12 @@ function buildCreateSubtaskTool(connection) {
7377
7386
  "create_subtask",
7378
7387
  "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.",
7379
7388
  {
7380
- title: z8.string().describe("Subtask title"),
7381
- description: z8.string().optional().describe("Brief description"),
7382
- plan: z8.string().optional().describe("Implementation plan in markdown"),
7383
- ordinal: z8.number().optional().describe("Step/order number (0-based)"),
7384
- storyPointValue: z8.number().optional().describe(SP_DESCRIPTION),
7385
- followParentStatus: z8.boolean().optional().describe(FOLLOW_PARENT_STATUS_DESCRIPTION)
7389
+ title: z9.string().describe("Subtask title"),
7390
+ description: z9.string().optional().describe("Brief description"),
7391
+ plan: z9.string().optional().describe("Implementation plan in markdown"),
7392
+ ordinal: z9.number().optional().describe("Step/order number (0-based)"),
7393
+ storyPointValue: z9.number().optional().describe(SP_DESCRIPTION),
7394
+ followParentStatus: z9.boolean().optional().describe(FOLLOW_PARENT_STATUS_DESCRIPTION)
7386
7395
  },
7387
7396
  async ({ title, description, plan, ordinal, storyPointValue, followParentStatus }) => {
7388
7397
  try {
@@ -7409,13 +7418,13 @@ function buildUpdateSubtaskTool(connection) {
7409
7418
  "update_subtask",
7410
7419
  "Update an existing subtask's fields (title, description, plan, ordinal, storyPointValue). Use when refining a child's plan or reordering. For the current task use update_task_plan.",
7411
7420
  {
7412
- subtaskId: z8.string().describe("The subtask ID to update"),
7413
- title: z8.string().optional(),
7414
- description: z8.string().optional(),
7415
- plan: z8.string().optional(),
7416
- ordinal: z8.number().optional(),
7417
- storyPointValue: z8.number().optional().describe(SP_DESCRIPTION),
7418
- followParentStatus: z8.boolean().optional().describe(FOLLOW_PARENT_STATUS_DESCRIPTION)
7421
+ subtaskId: z9.string().describe("The subtask ID to update"),
7422
+ title: z9.string().optional(),
7423
+ description: z9.string().optional(),
7424
+ plan: z9.string().optional(),
7425
+ ordinal: z9.number().optional(),
7426
+ storyPointValue: z9.number().optional().describe(SP_DESCRIPTION),
7427
+ followParentStatus: z9.boolean().optional().describe(FOLLOW_PARENT_STATUS_DESCRIPTION)
7419
7428
  },
7420
7429
  async ({ subtaskId, title, description, plan, storyPointValue, followParentStatus }) => {
7421
7430
  try {
@@ -7439,7 +7448,7 @@ function buildDeleteSubtaskTool(connection) {
7439
7448
  return defineTool(
7440
7449
  "delete_subtask",
7441
7450
  "Delete a subtask by id. When to use: a subtask was created in error or is no longer needed. Returns: confirmation string.",
7442
- { subtaskId: z8.string().describe("The subtask ID to delete") },
7451
+ { subtaskId: z9.string().describe("The subtask ID to delete") },
7443
7452
  async ({ subtaskId }) => {
7444
7453
  try {
7445
7454
  await connection.call("deleteSubtask", {
@@ -7477,7 +7486,7 @@ function buildPackTools(connection) {
7477
7486
  "start_child_cloud_build",
7478
7487
  "Start a cloud build (codespace) for a child task. Preconditions: child is in Open status, has a story point value, and has an agent assigned.",
7479
7488
  {
7480
- childTaskId: z8.string().describe("The child task ID to start a cloud build for")
7489
+ childTaskId: z9.string().describe("The child task ID to start a cloud build for")
7481
7490
  },
7482
7491
  async ({ childTaskId }) => {
7483
7492
  try {
@@ -7497,7 +7506,7 @@ function buildPackTools(connection) {
7497
7506
  "stop_child_build",
7498
7507
  "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.",
7499
7508
  {
7500
- childTaskId: z8.string().describe("The child task ID whose build should be stopped")
7509
+ childTaskId: z9.string().describe("The child task ID whose build should be stopped")
7501
7510
  },
7502
7511
  async ({ childTaskId }) => {
7503
7512
  try {
@@ -7517,7 +7526,7 @@ function buildPackTools(connection) {
7517
7526
  "approve_and_merge_pr",
7518
7527
  "Approve and merge a child task's PR. Preconditions: child in ReviewPR. Returns { merged }: true = merged (status\u2192ReviewDev); false = automerge queued, wait for ReviewDev.",
7519
7528
  {
7520
- childTaskId: z8.string().describe("The child task ID whose PR should be approved and merged")
7529
+ childTaskId: z9.string().describe("The child task ID whose PR should be approved and merged")
7521
7530
  },
7522
7531
  async ({ childTaskId }) => {
7523
7532
  try {
@@ -7555,22 +7564,29 @@ function buildPmTools(connection, options) {
7555
7564
  }
7556
7565
 
7557
7566
  // src/tools/discovery-tools.ts
7558
- import { z as z9 } from "zod";
7559
- var SP_DESCRIPTION2 = "Story point value (1=Common, 2=Magic, 3=Rare, 5=Unique)";
7567
+ import { z as z10 } from "zod";
7568
+ var SP_DESCRIPTION2 = "Story point value (1=Common, 2=Magic, 3=Rare, 5=Unique). The key is 'storyPointValue' \u2014 not 'storyPoints'.";
7569
+ var VALID_PROPERTY_KEYS = "title, storyPointValue, tagNames, githubPRUrl, githubBranch";
7560
7570
  function buildDiscoveryTools(connection) {
7561
7571
  return [
7562
7572
  defineTool(
7563
7573
  "update_task_properties",
7564
- "Set one or more task properties in a single call. All fields are optional \u2014 only include the fields you want to update.",
7574
+ "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.",
7565
7575
  {
7566
- title: z9.string().optional().describe("The new task title"),
7567
- storyPointValue: z9.number().optional().describe(SP_DESCRIPTION2),
7568
- tagNames: z9.array(z9.string()).optional().describe("Array of tag names to assign"),
7569
- githubPRUrl: z9.string().url().optional().describe("GitHub pull request URL to link to this task"),
7570
- githubBranch: z9.string().optional().describe("Set the GitHub branch name for this task (e.g. 'conveyor/my-feature-abc123')")
7576
+ title: z10.string().optional().describe("The new task title"),
7577
+ storyPointValue: z10.number().optional().describe(SP_DESCRIPTION2),
7578
+ tagNames: z10.array(z10.string()).optional().describe("Array of tag names to assign"),
7579
+ githubPRUrl: z10.string().url().optional().describe("GitHub pull request URL to link to this task"),
7580
+ githubBranch: z10.string().optional().describe("Set the GitHub branch name for this task (e.g. 'conveyor/my-feature-abc123')")
7571
7581
  },
7572
7582
  async ({ title, storyPointValue, tagNames, githubPRUrl, githubBranch }) => {
7573
7583
  try {
7584
+ const nothingToUpdate = title === void 0 && storyPointValue === void 0 && tagNames === void 0 && githubPRUrl === void 0 && githubBranch === void 0;
7585
+ if (nothingToUpdate) {
7586
+ return textResult(
7587
+ `No task properties were updated: none of the recognized keys were provided. Valid keys: ${VALID_PROPERTY_KEYS}. (Story points are set via 'storyPointValue', not 'storyPoints'.)`
7588
+ );
7589
+ }
7574
7590
  await connection.call("updateTaskProperties", {
7575
7591
  sessionId: connection.sessionId,
7576
7592
  title,
@@ -7592,13 +7608,17 @@ function buildDiscoveryTools(connection) {
7592
7608
  `Failed to update task properties: ${error instanceof Error ? error.message : "Unknown error"}`
7593
7609
  );
7594
7610
  }
7595
- }
7611
+ },
7612
+ // Reject unknown keys (e.g. "storyPoints") at validation instead of
7613
+ // stripping them into a silent no-op — every field here is optional, so
7614
+ // a stripped typo would otherwise report success while updating nothing.
7615
+ { strict: true }
7596
7616
  )
7597
7617
  ];
7598
7618
  }
7599
7619
 
7600
7620
  // src/tools/code-review-tools.ts
7601
- import { z as z10 } from "zod";
7621
+ import { z as z11 } from "zod";
7602
7622
  async function endReviewSession(connection, reason) {
7603
7623
  await connection.call("endReviewSession", {
7604
7624
  sessionId: connection.sessionId,
@@ -7611,7 +7631,7 @@ function buildCodeReviewTools(connection) {
7611
7631
  "approve_code_review",
7612
7632
  "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.",
7613
7633
  {
7614
- summary: z10.string().describe("Brief summary of what was reviewed and why it looks good")
7634
+ summary: z11.string().describe("Brief summary of what was reviewed and why it looks good")
7615
7635
  },
7616
7636
  async ({ summary }) => {
7617
7637
  const content = `**Code Review: Approved** :white_check_mark:
@@ -7635,15 +7655,15 @@ ${summary}`;
7635
7655
  "request_code_changes",
7636
7656
  "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 }.",
7637
7657
  {
7638
- issues: z10.array(
7639
- z10.object({
7640
- file: z10.string().describe("File path where the issue was found"),
7641
- line: z10.number().optional().describe("Line number (if applicable)"),
7642
- severity: z10.enum(["critical", "major", "minor"]).describe("Issue severity"),
7643
- description: z10.string().describe("What is wrong and how to fix it")
7658
+ issues: z11.array(
7659
+ z11.object({
7660
+ file: z11.string().describe("File path where the issue was found"),
7661
+ line: z11.number().optional().describe("Line number (if applicable)"),
7662
+ severity: z11.enum(["critical", "major", "minor"]).describe("Issue severity"),
7663
+ description: z11.string().describe("What is wrong and how to fix it")
7644
7664
  })
7645
7665
  ).describe("List of issues found during review"),
7646
- summary: z10.string().describe("Brief overall summary of the review findings")
7666
+ summary: z11.string().describe("Brief overall summary of the review findings")
7647
7667
  },
7648
7668
  async ({ issues, summary }) => {
7649
7669
  const issueLines = issues.map((issue) => {
@@ -11026,4 +11046,4 @@ export {
11026
11046
  runStartCommand,
11027
11047
  unshallowRepo
11028
11048
  };
11029
- //# sourceMappingURL=chunk-HAH2S5AD.js.map
11049
+ //# sourceMappingURL=chunk-TZYEU4QE.js.map