gsd-pi 2.75.0-dev.a44b82572 → 2.75.0-dev.e41b70b10

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 (111) hide show
  1. package/dist/resources/extensions/gsd/auto/phases.js +2 -0
  2. package/dist/resources/extensions/gsd/auto-dashboard.js +22 -1
  3. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +8 -2
  4. package/dist/resources/extensions/gsd/auto-dispatch.js +11 -11
  5. package/dist/resources/extensions/gsd/auto-model-selection.js +3 -1
  6. package/dist/resources/extensions/gsd/auto-prompts.js +19 -9
  7. package/dist/resources/extensions/gsd/auto-worktree.js +16 -1
  8. package/dist/resources/extensions/gsd/doctor-git-checks.js +22 -2
  9. package/dist/resources/extensions/gsd/pre-execution-checks.js +12 -8
  10. package/dist/resources/extensions/gsd/prompts/add-tests.md +1 -0
  11. package/dist/resources/extensions/gsd/prompts/execute-task.md +1 -1
  12. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -0
  13. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +14 -0
  14. package/dist/resources/extensions/search-the-web/command-search-provider.js +4 -1
  15. package/dist/resources/extensions/search-the-web/native-search.js +13 -2
  16. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  17. package/dist/web/standalone/.next/BUILD_ID +1 -1
  18. package/dist/web/standalone/.next/app-path-routes-manifest.json +15 -15
  19. package/dist/web/standalone/.next/build-manifest.json +2 -2
  20. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  21. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  22. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  23. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  24. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  25. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  26. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  27. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  28. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  29. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  30. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  31. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  32. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  33. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  34. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  35. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  36. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  37. package/dist/web/standalone/.next/server/app/index.html +1 -1
  38. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  39. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  40. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  41. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  42. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  43. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  44. package/dist/web/standalone/.next/server/app-paths-manifest.json +15 -15
  45. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  46. package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
  47. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  48. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  49. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  50. package/package.json +1 -1
  51. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  52. package/packages/mcp-server/dist/workflow-tools.js +102 -65
  53. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  54. package/packages/mcp-server/src/workflow-tools.test.ts +255 -0
  55. package/packages/mcp-server/src/workflow-tools.ts +108 -65
  56. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  57. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  58. package/packages/pi-ai/dist/index.d.ts +1 -0
  59. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  60. package/packages/pi-ai/dist/index.js +1 -0
  61. package/packages/pi-ai/dist/index.js.map +1 -1
  62. package/packages/pi-ai/dist/providers/api-family.d.ts +27 -0
  63. package/packages/pi-ai/dist/providers/api-family.d.ts.map +1 -0
  64. package/packages/pi-ai/dist/providers/api-family.js +47 -0
  65. package/packages/pi-ai/dist/providers/api-family.js.map +1 -0
  66. package/packages/pi-ai/dist/providers/api-family.test.d.ts +2 -0
  67. package/packages/pi-ai/dist/providers/api-family.test.d.ts.map +1 -0
  68. package/packages/pi-ai/dist/providers/api-family.test.js +101 -0
  69. package/packages/pi-ai/dist/providers/api-family.test.js.map +1 -0
  70. package/packages/pi-ai/src/index.ts +1 -0
  71. package/packages/pi-ai/src/providers/api-family.test.ts +129 -0
  72. package/packages/pi-ai/src/providers/api-family.ts +57 -0
  73. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  74. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +1 -0
  75. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  76. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  77. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +2 -1
  78. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  79. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  80. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
  81. package/packages/pi-coding-agent/dist/core/retry-handler.js +4 -1
  82. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
  83. package/packages/pi-coding-agent/src/core/extensions/runner.ts +4 -1
  84. package/packages/pi-coding-agent/src/core/extensions/types.ts +2 -2
  85. package/packages/pi-coding-agent/src/core/retry-handler.ts +4 -1
  86. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  87. package/src/resources/extensions/gsd/auto/loop-deps.ts +2 -10
  88. package/src/resources/extensions/gsd/auto/phases.ts +3 -0
  89. package/src/resources/extensions/gsd/auto-dashboard.ts +25 -1
  90. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +15 -2
  91. package/src/resources/extensions/gsd/auto-dispatch.ts +21 -7
  92. package/src/resources/extensions/gsd/auto-model-selection.ts +3 -1
  93. package/src/resources/extensions/gsd/auto-prompts.ts +33 -9
  94. package/src/resources/extensions/gsd/auto-worktree.ts +16 -1
  95. package/src/resources/extensions/gsd/doctor-git-checks.ts +23 -2
  96. package/src/resources/extensions/gsd/pre-execution-checks.ts +12 -8
  97. package/src/resources/extensions/gsd/prompts/add-tests.md +1 -0
  98. package/src/resources/extensions/gsd/prompts/execute-task.md +1 -1
  99. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -0
  100. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +49 -0
  101. package/src/resources/extensions/gsd/tests/integration/doctor-git-symlink-cwd.test.ts +79 -0
  102. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +66 -0
  103. package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +132 -8
  104. package/src/resources/extensions/gsd/tests/prompts-no-gitignored-test-refs.test.ts +56 -0
  105. package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +54 -0
  106. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +97 -0
  107. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +14 -0
  108. package/src/resources/extensions/search-the-web/command-search-provider.ts +4 -1
  109. package/src/resources/extensions/search-the-web/native-search.ts +13 -3
  110. /package/dist/web/standalone/.next/static/{iBwPQUj73sn8jxegTo320 → By_yegSJ-AA1OP0QjYbSl}/_buildManifest.js +0 -0
  111. /package/dist/web/standalone/.next/static/{iBwPQUj73sn8jxegTo320 → By_yegSJ-AA1OP0QjYbSl}/_ssgManifest.js +0 -0
@@ -445,38 +445,75 @@ const projectDirParam = z
445
445
  .string()
446
446
  .optional()
447
447
  .describe("Optional. Omit this field — the server defaults to its current working directory, which is already the correct project or worktree root.");
448
+ const nonEmptyString = (field) => z.string().trim().min(1, `${field} must be a non-empty string`);
449
+ // Optional non-empty string: accepts omitted/undefined but rejects "" or
450
+ // whitespace. Mirrors executor guards of the form
451
+ // `value !== undefined && !isNonEmptyString(value)` — e.g. plan-task's
452
+ // observabilityImpact. Do not preprocess "" to undefined; the executor
453
+ // treats them differently.
454
+ const optionalNonEmptyString = (field) => nonEmptyString(field).optional();
455
+ // Array of non-empty strings. Mirrors executor guards that call
456
+ // `validateStringArray` or `arr.some((item) => !isNonEmptyString(item))`.
457
+ const nonEmptyStringArray = (field) => z.array(nonEmptyString(`${field}[]`));
458
+ // Matches the executor's `isNonEmptyString` (trim + length>0) so Zod rejects
459
+ // empty/whitespace fields at parse time. Without this, MCP callers pass "" for
460
+ // the heavy planning fields, Zod accepts it, and the executor rejects one
461
+ // field per call — forcing the agent into a retry loop to discover every gap.
462
+ const planMilestoneSliceSchema = z.object({
463
+ sliceId: nonEmptyString("sliceId"),
464
+ title: nonEmptyString("title"),
465
+ risk: nonEmptyString("risk"),
466
+ depends: z.array(z.string()),
467
+ demo: nonEmptyString("demo"),
468
+ goal: nonEmptyString("goal"),
469
+ // ADR-011: heavy planning fields are optional for sketch slices; required for full slices.
470
+ successCriteria: z.string().optional(),
471
+ proofLevel: z.string().optional(),
472
+ integrationClosure: z.string().optional(),
473
+ observabilityImpact: z.string().optional(),
474
+ // ADR-011 sketch-then-refine fields.
475
+ isSketch: z.boolean().optional().describe("ADR-011: true marks this slice as a sketch awaiting refine-slice expansion"),
476
+ sketchScope: z.string().optional().describe("ADR-011: 2-3 sentence scope boundary, required when isSketch=true"),
477
+ }).superRefine((slice, ctx) => {
478
+ if (slice.isSketch === true) {
479
+ if (typeof slice.sketchScope !== "string" || slice.sketchScope.trim().length === 0) {
480
+ ctx.addIssue({
481
+ code: z.ZodIssueCode.custom,
482
+ path: ["sketchScope"],
483
+ message: "sketchScope must be a non-empty string when isSketch is true",
484
+ });
485
+ }
486
+ return;
487
+ }
488
+ const required = ["successCriteria", "proofLevel", "integrationClosure", "observabilityImpact"];
489
+ for (const field of required) {
490
+ const value = slice[field];
491
+ if (typeof value !== "string" || value.trim().length === 0) {
492
+ ctx.addIssue({
493
+ code: z.ZodIssueCode.custom,
494
+ path: [field],
495
+ message: `${field} must be a non-empty string`,
496
+ });
497
+ }
498
+ }
499
+ });
448
500
  const planMilestoneParams = {
449
501
  projectDir: projectDirParam,
450
- milestoneId: z.string().describe("Milestone ID (e.g. M001)"),
451
- title: z.string().describe("Milestone title"),
452
- vision: z.string().describe("Milestone vision"),
453
- slices: z.array(z.object({
454
- sliceId: z.string(),
455
- title: z.string(),
456
- risk: z.string(),
457
- depends: z.array(z.string()),
458
- demo: z.string(),
459
- goal: z.string(),
460
- // ADR-011: heavy planning fields are optional for sketch slices; required for full slices.
461
- successCriteria: z.string().optional(),
462
- proofLevel: z.string().optional(),
463
- integrationClosure: z.string().optional(),
464
- observabilityImpact: z.string().optional(),
465
- // ADR-011 sketch-then-refine fields.
466
- isSketch: z.boolean().optional().describe("ADR-011: true marks this slice as a sketch awaiting refine-slice expansion"),
467
- sketchScope: z.string().optional().describe("ADR-011: 2-3 sentence scope boundary, required when isSketch=true"),
468
- })).describe("Planned slices for the milestone"),
502
+ milestoneId: nonEmptyString("milestoneId").describe("Milestone ID (e.g. M001)"),
503
+ title: nonEmptyString("title").describe("Milestone title"),
504
+ vision: nonEmptyString("vision").describe("Milestone vision"),
505
+ slices: z.array(planMilestoneSliceSchema).describe("Planned slices for the milestone"),
469
506
  status: z.string().optional().describe("Milestone status"),
470
507
  dependsOn: z.array(z.string()).optional().describe("Milestone dependencies"),
471
508
  successCriteria: z.array(z.string()).optional().describe("Top-level success criteria bullets"),
472
509
  keyRisks: z.array(z.object({
473
- risk: z.string(),
474
- whyItMatters: z.string(),
510
+ risk: nonEmptyString("risk"),
511
+ whyItMatters: nonEmptyString("whyItMatters"),
475
512
  })).optional().describe("Structured risk entries"),
476
513
  proofStrategy: z.array(z.object({
477
- riskOrUnknown: z.string(),
478
- retireIn: z.string(),
479
- whatWillBeProven: z.string(),
514
+ riskOrUnknown: nonEmptyString("riskOrUnknown"),
515
+ retireIn: nonEmptyString("retireIn"),
516
+ whatWillBeProven: nonEmptyString("whatWillBeProven"),
480
517
  })).optional().describe("Structured proof strategy entries"),
481
518
  verificationContract: z.string().optional(),
482
519
  verificationIntegration: z.string().optional(),
@@ -489,19 +526,19 @@ const planMilestoneParams = {
489
526
  const planMilestoneSchema = z.object(planMilestoneParams);
490
527
  const planSliceParams = {
491
528
  projectDir: projectDirParam,
492
- milestoneId: z.string().describe("Milestone ID (e.g. M001)"),
493
- sliceId: z.string().describe("Slice ID (e.g. S01)"),
494
- goal: z.string().describe("Slice goal"),
529
+ milestoneId: nonEmptyString("milestoneId").describe("Milestone ID (e.g. M001)"),
530
+ sliceId: nonEmptyString("sliceId").describe("Slice ID (e.g. S01)"),
531
+ goal: nonEmptyString("goal").describe("Slice goal"),
495
532
  tasks: z.array(z.object({
496
- taskId: z.string(),
497
- title: z.string(),
498
- description: z.string(),
499
- estimate: z.string(),
500
- files: z.array(z.string()),
501
- verify: z.string(),
502
- inputs: z.array(z.string()),
503
- expectedOutput: z.array(z.string()),
504
- observabilityImpact: z.string().optional(),
533
+ taskId: nonEmptyString("taskId"),
534
+ title: nonEmptyString("title"),
535
+ description: nonEmptyString("description"),
536
+ estimate: nonEmptyString("estimate"),
537
+ files: nonEmptyStringArray("files"),
538
+ verify: nonEmptyString("verify"),
539
+ inputs: nonEmptyStringArray("inputs"),
540
+ expectedOutput: nonEmptyStringArray("expectedOutput"),
541
+ observabilityImpact: optionalNonEmptyString("observabilityImpact"),
505
542
  })).describe("Planned tasks for the slice"),
506
543
  successCriteria: z.string().optional(),
507
544
  proofLevel: z.string().optional(),
@@ -511,8 +548,8 @@ const planSliceParams = {
511
548
  const planSliceSchema = z.object(planSliceParams);
512
549
  const completeMilestoneParams = {
513
550
  projectDir: projectDirParam,
514
- milestoneId: z.string().describe("Milestone ID (e.g. M001)"),
515
- title: z.string().describe("Milestone title"),
551
+ milestoneId: nonEmptyString("milestoneId").describe("Milestone ID (e.g. M001)"),
552
+ title: nonEmptyString("title").describe("Milestone title"),
516
553
  oneLiner: z.string().describe("One-sentence summary of what the milestone achieved"),
517
554
  narrative: z.string().describe("Detailed narrative of what happened during the milestone"),
518
555
  verificationPassed: z.boolean().describe("Must be true after milestone verification succeeds"),
@@ -528,7 +565,7 @@ const completeMilestoneParams = {
528
565
  const completeMilestoneSchema = z.object(completeMilestoneParams);
529
566
  const validateMilestoneParams = {
530
567
  projectDir: projectDirParam,
531
- milestoneId: z.string().describe("Milestone ID (e.g. M001)"),
568
+ milestoneId: nonEmptyString("milestoneId").describe("Milestone ID (e.g. M001)"),
532
569
  verdict: z.enum(["pass", "needs-attention", "needs-remediation"]).describe("Validation verdict"),
533
570
  remediationRound: z.number().describe("Remediation round (0 for first validation)"),
534
571
  successCriteriaChecklist: z.string().describe("Markdown checklist of success criteria with evidence"),
@@ -541,18 +578,18 @@ const validateMilestoneParams = {
541
578
  };
542
579
  const validateMilestoneSchema = z.object(validateMilestoneParams);
543
580
  const roadmapSliceChangeSchema = z.object({
544
- sliceId: z.string(),
545
- title: z.string(),
581
+ sliceId: nonEmptyString("sliceId"),
582
+ title: nonEmptyString("title"),
546
583
  risk: z.string().optional(),
547
584
  depends: z.array(z.string()).optional(),
548
585
  demo: z.string().optional(),
549
586
  });
550
587
  const reassessRoadmapParams = {
551
588
  projectDir: projectDirParam,
552
- milestoneId: z.string().describe("Milestone ID (e.g. M001)"),
553
- completedSliceId: z.string().describe("Slice ID that just completed"),
554
- verdict: z.string().describe("Assessment verdict such as roadmap-confirmed or roadmap-adjusted"),
555
- assessment: z.string().describe("Assessment text explaining the roadmap decision"),
589
+ milestoneId: nonEmptyString("milestoneId").describe("Milestone ID (e.g. M001)"),
590
+ completedSliceId: nonEmptyString("completedSliceId").describe("Slice ID that just completed"),
591
+ verdict: nonEmptyString("verdict").describe("Assessment verdict such as roadmap-confirmed or roadmap-adjusted"),
592
+ assessment: nonEmptyString("assessment").describe("Assessment text explaining the roadmap decision"),
556
593
  sliceChanges: z.object({
557
594
  modified: z.array(roadmapSliceChangeSchema),
558
595
  added: z.array(roadmapSliceChangeSchema),
@@ -573,14 +610,14 @@ const saveGateResultParams = {
573
610
  const saveGateResultSchema = z.object(saveGateResultParams);
574
611
  const replanSliceParams = {
575
612
  projectDir: projectDirParam,
576
- milestoneId: z.string().describe("Milestone ID (e.g. M001)"),
577
- sliceId: z.string().describe("Slice ID (e.g. S01)"),
578
- blockerTaskId: z.string().describe("Task ID that discovered the blocker"),
579
- blockerDescription: z.string().describe("Description of the blocker"),
580
- whatChanged: z.string().describe("Summary of what changed in the plan"),
613
+ milestoneId: nonEmptyString("milestoneId").describe("Milestone ID (e.g. M001)"),
614
+ sliceId: nonEmptyString("sliceId").describe("Slice ID (e.g. S01)"),
615
+ blockerTaskId: nonEmptyString("blockerTaskId").describe("Task ID that discovered the blocker"),
616
+ blockerDescription: nonEmptyString("blockerDescription").describe("Description of the blocker"),
617
+ whatChanged: nonEmptyString("whatChanged").describe("Summary of what changed in the plan"),
581
618
  updatedTasks: z.array(z.object({
582
- taskId: z.string(),
583
- title: z.string(),
619
+ taskId: nonEmptyString("taskId"),
620
+ title: nonEmptyString("title"),
584
621
  description: z.string(),
585
622
  estimate: z.string(),
586
623
  files: z.array(z.string()),
@@ -594,8 +631,8 @@ const replanSliceParams = {
594
631
  const replanSliceSchema = z.object(replanSliceParams);
595
632
  const sliceCompleteParams = {
596
633
  projectDir: projectDirParam,
597
- sliceId: z.string().describe("Slice ID (e.g. S01)"),
598
- milestoneId: z.string().describe("Milestone ID (e.g. M001)"),
634
+ sliceId: nonEmptyString("sliceId").describe("Slice ID (e.g. S01)"),
635
+ milestoneId: nonEmptyString("milestoneId").describe("Milestone ID (e.g. M001)"),
599
636
  sliceTitle: z.string().describe("Title of the slice"),
600
637
  oneLiner: z.string().describe("One-line summary of what the slice accomplished"),
601
638
  narrative: z.string().describe("Detailed narrative of what happened across all tasks"),
@@ -684,17 +721,17 @@ const milestoneGenerateIdParams = {
684
721
  const milestoneGenerateIdSchema = z.object(milestoneGenerateIdParams);
685
722
  const planTaskParams = {
686
723
  projectDir: projectDirParam,
687
- milestoneId: z.string().describe("Milestone ID (e.g. M001)"),
688
- sliceId: z.string().describe("Slice ID (e.g. S01)"),
689
- taskId: z.string().describe("Task ID (e.g. T01)"),
690
- title: z.string().describe("Task title"),
691
- description: z.string().describe("Task description / steps block"),
692
- estimate: z.string().describe("Task estimate"),
724
+ milestoneId: nonEmptyString("milestoneId").describe("Milestone ID (e.g. M001)"),
725
+ sliceId: nonEmptyString("sliceId").describe("Slice ID (e.g. S01)"),
726
+ taskId: nonEmptyString("taskId").describe("Task ID (e.g. T01)"),
727
+ title: nonEmptyString("title").describe("Task title"),
728
+ description: nonEmptyString("description").describe("Task description / steps block"),
729
+ estimate: nonEmptyString("estimate").describe("Task estimate"),
693
730
  files: z.array(z.string()).describe("Files likely touched"),
694
- verify: z.string().describe("Verification command or block"),
731
+ verify: nonEmptyString("verify").describe("Verification command or block"),
695
732
  inputs: z.array(z.string()).describe("Input files or references"),
696
733
  expectedOutput: z.array(z.string()).describe("Expected output files or artifacts"),
697
- observabilityImpact: z.string().optional().describe("Task observability impact"),
734
+ observabilityImpact: optionalNonEmptyString("observabilityImpact").describe("Task observability impact"),
698
735
  };
699
736
  const planTaskSchema = z.object(planTaskParams);
700
737
  const skipSliceParams = {
@@ -706,9 +743,9 @@ const skipSliceParams = {
706
743
  const skipSliceSchema = z.object(skipSliceParams);
707
744
  const taskCompleteParams = {
708
745
  projectDir: projectDirParam,
709
- taskId: z.string().describe("Task ID (e.g. T01)"),
710
- sliceId: z.string().describe("Slice ID (e.g. S01)"),
711
- milestoneId: z.string().describe("Milestone ID (e.g. M001)"),
746
+ taskId: nonEmptyString("taskId").describe("Task ID (e.g. T01)"),
747
+ sliceId: nonEmptyString("sliceId").describe("Slice ID (e.g. S01)"),
748
+ milestoneId: nonEmptyString("milestoneId").describe("Milestone ID (e.g. M001)"),
712
749
  oneLiner: z.string().describe("One-line summary of what was accomplished"),
713
750
  narrative: z.string().describe("Detailed narrative of what happened during the task"),
714
751
  verification: z.string().describe("What was verified and how"),