@specforge/mcp 3.1.1 → 3.2.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.
- package/dist/autopilot/api/autopilot-api-client.d.ts.map +1 -1
- package/dist/autopilot/api/autopilot-api-client.js +0 -8
- package/dist/autopilot/api/autopilot-api-client.js.map +1 -1
- package/dist/autopilot/readiness/post-scoring.js +3 -1
- package/dist/autopilot/readiness/post-scoring.js.map +1 -1
- package/dist/cli/commands/docs/tool-examples.js +4 -3
- package/dist/cli/commands/docs/tool-examples.js.map +1 -1
- package/dist/cli/commands/docs/types.js +1 -1
- package/dist/cli/commands/docs/types.js.map +1 -1
- package/dist/lib/prompt-generator.js +1 -1
- package/dist/lib/prompt-generator.js.map +1 -1
- package/dist/tools/core/help.js +1 -1
- package/dist/tools/core/help.js.map +1 -1
- package/dist/tools/core/index.d.ts +0 -1
- package/dist/tools/core/index.d.ts.map +1 -1
- package/dist/tools/core/index.js +0 -1
- package/dist/tools/core/index.js.map +1 -1
- package/dist/tools/core/session.d.ts.map +1 -1
- package/dist/tools/core/session.js +6 -15
- package/dist/tools/core/session.js.map +1 -1
- package/dist/tools/core/ticket.js +1 -1
- package/dist/tools/core/ticket.js.map +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +167 -215
- package/dist/tools/index.js.map +1 -1
- package/dist/types/index.d.ts +82 -11
- package/dist/types/index.d.ts.map +1 -1
- package/dist/validation/index.d.ts.map +1 -1
- package/dist/validation/index.js +20 -56
- package/dist/validation/index.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/templates/skills/specforge-orchestrator.md +17 -15
- package/src/cli/templates/skills/specforge-worker.md +1 -9
package/dist/tools/index.js
CHANGED
|
@@ -82,8 +82,6 @@ const READ_TOOL_NAMES = new Set([
|
|
|
82
82
|
'search_tickets',
|
|
83
83
|
// Working context
|
|
84
84
|
'get_working_context',
|
|
85
|
-
// Job status
|
|
86
|
-
'get_job_status',
|
|
87
85
|
// Agent Teams (read operations)
|
|
88
86
|
'get_epic_dependency_graph',
|
|
89
87
|
'get_implementation_plan',
|
|
@@ -726,7 +724,7 @@ Examples:
|
|
|
726
724
|
// ========================================================================
|
|
727
725
|
{
|
|
728
726
|
name: 'start_work_session',
|
|
729
|
-
description: 'Start working on a ticket.
|
|
727
|
+
description: 'Start working on a ticket. Creates a WorkSession record and transitions ready -> active. Returns the workSessionId along with error with statusReason if ticket is pending (dependencies not met).',
|
|
730
728
|
inputSchema: {
|
|
731
729
|
type: 'object',
|
|
732
730
|
properties: {
|
|
@@ -740,10 +738,9 @@ Examples:
|
|
|
740
738
|
},
|
|
741
739
|
{
|
|
742
740
|
name: 'complete_work_session',
|
|
743
|
-
description: 'Mark a ticket as complete. Transitions active -> done.\n\n' +
|
|
741
|
+
description: 'Mark a ticket as complete and finalize the active WorkSession. Transitions active -> done. Session data (files, test results, time) is stored on the WorkSession record.\n\n' +
|
|
742
|
+
'All acceptance criteria must be validated and all implementation steps must be completed via action_work_session before calling this. The completion gate enforces this — shortcuts are not available.\n\n' +
|
|
744
743
|
'Automatically recalculates status for dependent tickets and returns cascade info.\n\n' +
|
|
745
|
-
'By default, checks if summary addresses acceptance criteria and returns warnings (not errors) for gaps.\n\n' +
|
|
746
|
-
'Use validated: true as a simple confirmation that the agent has verified all work meets criteria.\n\n' +
|
|
747
744
|
'Optional validation flags can be provided to report test results inline:\n' +
|
|
748
745
|
'- tests: Unit/integration test results\n' +
|
|
749
746
|
'- lint: Linting results\n' +
|
|
@@ -770,21 +767,18 @@ Examples:
|
|
|
770
767
|
items: { type: 'string' },
|
|
771
768
|
description: 'List of files created',
|
|
772
769
|
},
|
|
770
|
+
filesDeleted: {
|
|
771
|
+
type: 'array',
|
|
772
|
+
items: { type: 'string' },
|
|
773
|
+
description: 'List of files deleted',
|
|
774
|
+
},
|
|
773
775
|
actualHours: {
|
|
774
776
|
type: 'number',
|
|
775
777
|
description: 'Actual hours spent on the ticket',
|
|
776
778
|
},
|
|
777
|
-
validated: {
|
|
778
|
-
type: 'boolean',
|
|
779
|
-
description: 'Simple validation confirmation. When true, indicates:\n' +
|
|
780
|
-
'- Agent has verified work meets acceptance criteria\n' +
|
|
781
|
-
'- All necessary tests/validations were run and passed\n' +
|
|
782
|
-
'- No detailed breakdown needed\n' +
|
|
783
|
-
'Trust-based approach for streamlined completion.',
|
|
784
|
-
},
|
|
785
779
|
validation: {
|
|
786
780
|
type: 'object',
|
|
787
|
-
description: 'Detailed validation flags
|
|
781
|
+
description: 'Detailed validation flags for reporting test/lint/build results',
|
|
788
782
|
properties: {
|
|
789
783
|
tests: {
|
|
790
784
|
type: 'string',
|
|
@@ -812,61 +806,175 @@ Examples:
|
|
|
812
806
|
},
|
|
813
807
|
},
|
|
814
808
|
},
|
|
815
|
-
skipCriteriaCheck: {
|
|
816
|
-
type: 'boolean',
|
|
817
|
-
description: 'Skip acceptance criteria validation. Use for trivial changes or when criteria check is not needed. Default: false',
|
|
818
|
-
},
|
|
819
809
|
},
|
|
820
810
|
required: ['ticketId', 'summary'],
|
|
821
811
|
},
|
|
822
812
|
},
|
|
823
813
|
{
|
|
824
|
-
name: '
|
|
825
|
-
description: '
|
|
814
|
+
name: 'pause_work_session',
|
|
815
|
+
description: 'Pause work on a ticket, setting it back to ready status. Use this to temporarily pause work on a ticket without completing it.',
|
|
826
816
|
inputSchema: {
|
|
827
817
|
type: 'object',
|
|
828
818
|
properties: {
|
|
829
819
|
ticketId: {
|
|
830
820
|
type: 'string',
|
|
831
|
-
description: 'The ID of the ticket',
|
|
832
|
-
},
|
|
833
|
-
progress: {
|
|
834
|
-
type: 'number',
|
|
835
|
-
minimum: 0,
|
|
836
|
-
maximum: 100,
|
|
837
|
-
description: 'Progress percentage (0-100)',
|
|
838
|
-
},
|
|
839
|
-
message: {
|
|
840
|
-
type: 'string',
|
|
841
|
-
description: 'Progress message',
|
|
821
|
+
description: 'The ID of the ticket to pause',
|
|
842
822
|
},
|
|
843
823
|
},
|
|
844
|
-
required: ['ticketId'
|
|
824
|
+
required: ['ticketId'],
|
|
845
825
|
},
|
|
846
826
|
},
|
|
847
827
|
{
|
|
848
|
-
name: '
|
|
849
|
-
description: '
|
|
828
|
+
name: 'resume_work_session',
|
|
829
|
+
description: 'Resume work on a paused ticket, setting it to active status. Use this to continue work on a ticket that was previously paused.',
|
|
850
830
|
inputSchema: {
|
|
851
831
|
type: 'object',
|
|
852
832
|
properties: {
|
|
853
833
|
ticketId: {
|
|
854
834
|
type: 'string',
|
|
855
|
-
description: 'The ID of the ticket to
|
|
835
|
+
description: 'The ID of the ticket to resume',
|
|
856
836
|
},
|
|
857
837
|
},
|
|
858
838
|
required: ['ticketId'],
|
|
859
839
|
},
|
|
860
840
|
},
|
|
861
841
|
{
|
|
862
|
-
name: '
|
|
863
|
-
description:
|
|
842
|
+
name: 'action_work_session',
|
|
843
|
+
description: `Update checklist state during an active WorkSession. Combines step completion, AC validation, test result reporting, and file tracking into a single atomic operation. All state changes are recorded on the WorkSession and its related validation/completion records.
|
|
844
|
+
|
|
845
|
+
Use this instead of calling update_ticket for checklist changes. Provides:
|
|
846
|
+
- Step completion (individual or bulk via WorkSessionStepCompletion)
|
|
847
|
+
- Acceptance criteria validation (individual or bulk via WorkSessionACValidation)
|
|
848
|
+
- Test result reporting (merged by test type via WorkSessionTestResult)
|
|
849
|
+
- File tracking (created, modified, deleted on WorkSession)
|
|
850
|
+
- Blocker management (set/clear block reasons)
|
|
851
|
+
- Auto-calculated progress percentage
|
|
852
|
+
- Completion readiness hints
|
|
853
|
+
|
|
854
|
+
IMPORTANT: All acceptance criteria must be validated and all implementation steps must be completed via this tool before calling complete_work_session. The completion gate enforces this.`,
|
|
864
855
|
inputSchema: {
|
|
865
856
|
type: 'object',
|
|
866
857
|
properties: {
|
|
867
858
|
ticketId: {
|
|
868
859
|
type: 'string',
|
|
869
|
-
description: 'The ID of the ticket
|
|
860
|
+
description: 'The ID of the ticket being worked on (must be in active status)',
|
|
861
|
+
},
|
|
862
|
+
steps: {
|
|
863
|
+
type: 'array',
|
|
864
|
+
description: 'Individual step completion updates',
|
|
865
|
+
items: {
|
|
866
|
+
type: 'object',
|
|
867
|
+
properties: {
|
|
868
|
+
index: {
|
|
869
|
+
type: 'number',
|
|
870
|
+
description: 'Zero-based index of the step in the implementation.steps array',
|
|
871
|
+
},
|
|
872
|
+
completed: {
|
|
873
|
+
type: 'boolean',
|
|
874
|
+
description: 'Whether the step is completed',
|
|
875
|
+
},
|
|
876
|
+
notes: {
|
|
877
|
+
type: 'string',
|
|
878
|
+
description: 'Optional note about this step',
|
|
879
|
+
},
|
|
880
|
+
},
|
|
881
|
+
required: ['index', 'completed'],
|
|
882
|
+
},
|
|
883
|
+
},
|
|
884
|
+
allStepsDone: {
|
|
885
|
+
type: 'boolean',
|
|
886
|
+
description: 'Shortcut: mark all steps as completed',
|
|
887
|
+
},
|
|
888
|
+
acceptanceCriteria: {
|
|
889
|
+
type: 'array',
|
|
890
|
+
description: 'Individual AC validation updates',
|
|
891
|
+
items: {
|
|
892
|
+
type: 'object',
|
|
893
|
+
properties: {
|
|
894
|
+
index: {
|
|
895
|
+
type: 'number',
|
|
896
|
+
description: 'Zero-based index of the AC in the acceptanceCriteria array',
|
|
897
|
+
},
|
|
898
|
+
validated: {
|
|
899
|
+
type: 'boolean',
|
|
900
|
+
description: 'Whether the AC is validated',
|
|
901
|
+
},
|
|
902
|
+
notes: {
|
|
903
|
+
type: 'string',
|
|
904
|
+
description: 'Optional note about this AC',
|
|
905
|
+
},
|
|
906
|
+
},
|
|
907
|
+
required: ['index', 'validated'],
|
|
908
|
+
},
|
|
909
|
+
},
|
|
910
|
+
allACValidated: {
|
|
911
|
+
type: 'boolean',
|
|
912
|
+
description: 'Shortcut: mark all acceptance criteria as validated',
|
|
913
|
+
},
|
|
914
|
+
testResults: {
|
|
915
|
+
type: 'array',
|
|
916
|
+
description: 'Test result reports to append (merged by testType)',
|
|
917
|
+
items: {
|
|
918
|
+
type: 'object',
|
|
919
|
+
properties: {
|
|
920
|
+
testType: {
|
|
921
|
+
type: 'string',
|
|
922
|
+
description: 'Type of test (e.g., "unit", "integration", "e2e", "lint", "typeCheck")',
|
|
923
|
+
},
|
|
924
|
+
passed: {
|
|
925
|
+
type: 'number',
|
|
926
|
+
description: 'Number of tests that passed',
|
|
927
|
+
},
|
|
928
|
+
failed: {
|
|
929
|
+
type: 'number',
|
|
930
|
+
description: 'Number of tests that failed',
|
|
931
|
+
},
|
|
932
|
+
skipped: {
|
|
933
|
+
type: 'number',
|
|
934
|
+
description: 'Number of tests skipped',
|
|
935
|
+
},
|
|
936
|
+
command: {
|
|
937
|
+
type: 'string',
|
|
938
|
+
description: 'Command used to run the tests',
|
|
939
|
+
},
|
|
940
|
+
output: {
|
|
941
|
+
type: 'string',
|
|
942
|
+
description: 'Test output (truncated if needed)',
|
|
943
|
+
},
|
|
944
|
+
duration: {
|
|
945
|
+
type: 'number',
|
|
946
|
+
description: 'Duration in milliseconds',
|
|
947
|
+
},
|
|
948
|
+
},
|
|
949
|
+
required: ['testType', 'passed', 'failed'],
|
|
950
|
+
},
|
|
951
|
+
},
|
|
952
|
+
notes: {
|
|
953
|
+
type: 'string',
|
|
954
|
+
description: 'Additional notes to append to the ticket',
|
|
955
|
+
},
|
|
956
|
+
filesCreated: {
|
|
957
|
+
type: 'array',
|
|
958
|
+
items: { type: 'string' },
|
|
959
|
+
description: 'Files created during this session. Accumulated incrementally.',
|
|
960
|
+
},
|
|
961
|
+
filesModified: {
|
|
962
|
+
type: 'array',
|
|
963
|
+
items: { type: 'string' },
|
|
964
|
+
description: 'Files modified during this session. Accumulated incrementally.',
|
|
965
|
+
},
|
|
966
|
+
filesDeleted: {
|
|
967
|
+
type: 'array',
|
|
968
|
+
items: { type: 'string' },
|
|
969
|
+
description: 'Files deleted during this session. Accumulated incrementally.',
|
|
970
|
+
},
|
|
971
|
+
blockReason: {
|
|
972
|
+
type: 'string',
|
|
973
|
+
description: 'Set a blocker on this ticket. Requires a prior discovery via report_discovery.',
|
|
974
|
+
},
|
|
975
|
+
clearBlockReason: {
|
|
976
|
+
type: 'boolean',
|
|
977
|
+
description: 'Clear existing blocker and resume work.',
|
|
870
978
|
},
|
|
871
979
|
},
|
|
872
980
|
required: ['ticketId'],
|
|
@@ -883,7 +991,7 @@ Report types:
|
|
|
883
991
|
- 'implementation': Progress, velocity, completions (replaces get_implementation_summary)
|
|
884
992
|
- 'time': Estimated vs actual hours (replaces get_time_report)
|
|
885
993
|
- 'blockers': Blocked tickets with reasons (replaces get_blockers_report)
|
|
886
|
-
- 'work': Completed work summary (replaces get_work_summary)
|
|
994
|
+
- 'work': Completed work summary from WorkSession records (replaces get_work_summary)
|
|
887
995
|
|
|
888
996
|
Format options:
|
|
889
997
|
- 'json': Full structured data (default)
|
|
@@ -2043,119 +2151,6 @@ At least one scope filter (projectId, specificationId, or epicId) is required.`,
|
|
|
2043
2151
|
// ========================================================================
|
|
2044
2152
|
// Bulk Operations
|
|
2045
2153
|
// ========================================================================
|
|
2046
|
-
{
|
|
2047
|
-
name: 'bulk_create_tickets',
|
|
2048
|
-
description: 'Create multiple tickets in an epic with optional inline dependencies in a single atomic transaction. Reduces 15+ API calls to one.',
|
|
2049
|
-
inputSchema: {
|
|
2050
|
-
type: 'object',
|
|
2051
|
-
properties: {
|
|
2052
|
-
epicId: {
|
|
2053
|
-
type: 'string',
|
|
2054
|
-
description: 'The ID of the epic to create tickets in',
|
|
2055
|
-
},
|
|
2056
|
-
tickets: {
|
|
2057
|
-
type: 'array',
|
|
2058
|
-
description: 'Array of ticket definitions to create',
|
|
2059
|
-
items: {
|
|
2060
|
-
type: 'object',
|
|
2061
|
-
properties: {
|
|
2062
|
-
title: { type: 'string', description: 'Ticket title (required)' },
|
|
2063
|
-
description: { type: 'string', description: 'Ticket description' },
|
|
2064
|
-
estimatedHours: { type: 'number', description: 'Estimated hours' },
|
|
2065
|
-
complexity: {
|
|
2066
|
-
type: 'string',
|
|
2067
|
-
enum: ['small', 'medium', 'large', 'xlarge'],
|
|
2068
|
-
description: 'Complexity level',
|
|
2069
|
-
},
|
|
2070
|
-
priority: {
|
|
2071
|
-
type: 'string',
|
|
2072
|
-
enum: ['high', 'medium', 'low'],
|
|
2073
|
-
description: 'Priority level',
|
|
2074
|
-
},
|
|
2075
|
-
acceptanceCriteria: {
|
|
2076
|
-
type: 'array',
|
|
2077
|
-
items: { type: 'string' },
|
|
2078
|
-
description: 'Acceptance criteria',
|
|
2079
|
-
},
|
|
2080
|
-
implementation: {
|
|
2081
|
-
type: 'object',
|
|
2082
|
-
description: 'Implementation details (filesToCreate, filesToModify, steps, etc.)',
|
|
2083
|
-
},
|
|
2084
|
-
technicalDetails: {
|
|
2085
|
-
type: 'object',
|
|
2086
|
-
description: 'Technical details (files, stack, endpoints, etc.)',
|
|
2087
|
-
},
|
|
2088
|
-
tags: {
|
|
2089
|
-
type: 'array',
|
|
2090
|
-
items: { type: 'string' },
|
|
2091
|
-
description: 'Tags',
|
|
2092
|
-
},
|
|
2093
|
-
},
|
|
2094
|
-
required: ['title'],
|
|
2095
|
-
},
|
|
2096
|
-
},
|
|
2097
|
-
dependencies: {
|
|
2098
|
-
type: 'array',
|
|
2099
|
-
description: 'Optional inline dependencies using array indexes',
|
|
2100
|
-
items: {
|
|
2101
|
-
type: 'object',
|
|
2102
|
-
properties: {
|
|
2103
|
-
ticket: {
|
|
2104
|
-
type: 'number',
|
|
2105
|
-
description: 'Index of the ticket in the tickets array',
|
|
2106
|
-
},
|
|
2107
|
-
dependsOn: {
|
|
2108
|
-
oneOf: [
|
|
2109
|
-
{ type: 'number', description: 'Index of the ticket it depends on' },
|
|
2110
|
-
{
|
|
2111
|
-
type: 'array',
|
|
2112
|
-
items: { type: 'number' },
|
|
2113
|
-
description: 'Indexes of the tickets it depends on',
|
|
2114
|
-
},
|
|
2115
|
-
],
|
|
2116
|
-
description: 'Index(es) of the ticket(s) it depends on',
|
|
2117
|
-
},
|
|
2118
|
-
},
|
|
2119
|
-
required: ['ticket', 'dependsOn'],
|
|
2120
|
-
},
|
|
2121
|
-
},
|
|
2122
|
-
onError: {
|
|
2123
|
-
type: 'string',
|
|
2124
|
-
enum: ['rollback', 'continue'],
|
|
2125
|
-
description: "Error handling mode: 'rollback' stops and undoes all, 'continue' skips failures (default: 'continue')",
|
|
2126
|
-
},
|
|
2127
|
-
},
|
|
2128
|
-
required: ['epicId', 'tickets'],
|
|
2129
|
-
},
|
|
2130
|
-
},
|
|
2131
|
-
{
|
|
2132
|
-
name: 'get_job_status',
|
|
2133
|
-
description: 'Get the status of an asynchronous bulk operation job. For batches >= 20 items, bulk operations return a job ID for async processing.',
|
|
2134
|
-
inputSchema: {
|
|
2135
|
-
type: 'object',
|
|
2136
|
-
properties: {
|
|
2137
|
-
jobId: {
|
|
2138
|
-
type: 'string',
|
|
2139
|
-
description: 'The job ID returned from a bulk operation',
|
|
2140
|
-
},
|
|
2141
|
-
},
|
|
2142
|
-
required: ['jobId'],
|
|
2143
|
-
},
|
|
2144
|
-
},
|
|
2145
|
-
{
|
|
2146
|
-
name: 'cancel_job',
|
|
2147
|
-
description: 'Cancel a running async job. Only queued or processing jobs can be cancelled.',
|
|
2148
|
-
inputSchema: {
|
|
2149
|
-
type: 'object',
|
|
2150
|
-
properties: {
|
|
2151
|
-
jobId: {
|
|
2152
|
-
type: 'string',
|
|
2153
|
-
description: 'The job ID returned from a bulk operation',
|
|
2154
|
-
},
|
|
2155
|
-
},
|
|
2156
|
-
required: ['jobId'],
|
|
2157
|
-
},
|
|
2158
|
-
},
|
|
2159
2154
|
{
|
|
2160
2155
|
name: 'bulk_add_dependencies',
|
|
2161
2156
|
description: 'Add multiple dependencies between tickets in a single atomic transaction.',
|
|
@@ -3223,19 +3218,9 @@ export function createToolHandlers(apiClient) {
|
|
|
3223
3218
|
summary: args.summary,
|
|
3224
3219
|
filesModified: args.filesModified,
|
|
3225
3220
|
filesCreated: args.filesCreated,
|
|
3221
|
+
filesDeleted: args.filesDeleted,
|
|
3226
3222
|
actualHours: args.actualHours,
|
|
3227
|
-
|
|
3228
|
-
validation: args.validation, // MCI-064: validation flags
|
|
3229
|
-
skipCriteriaCheck: args.skipCriteriaCheck, // MCI-065: skip criteria check
|
|
3230
|
-
});
|
|
3231
|
-
},
|
|
3232
|
-
report_progress: async (_client, args) => {
|
|
3233
|
-
validateRequired(args, 'ticketId', 'progress');
|
|
3234
|
-
validateRange(args.progress, 'progress', 0, 100);
|
|
3235
|
-
return await apiClient.call('report_progress', {
|
|
3236
|
-
ticketId: args.ticketId,
|
|
3237
|
-
progress: args.progress,
|
|
3238
|
-
message: args.message,
|
|
3223
|
+
validation: args.validation,
|
|
3239
3224
|
});
|
|
3240
3225
|
},
|
|
3241
3226
|
pause_work_session: async (_client, args) => {
|
|
@@ -3250,6 +3235,23 @@ export function createToolHandlers(apiClient) {
|
|
|
3250
3235
|
ticketId: args.ticketId,
|
|
3251
3236
|
});
|
|
3252
3237
|
},
|
|
3238
|
+
action_work_session: async (_client, args) => {
|
|
3239
|
+
validateRequired(args, 'ticketId');
|
|
3240
|
+
return await apiClient.call('action_work_session', {
|
|
3241
|
+
ticketId: args.ticketId,
|
|
3242
|
+
steps: args.steps,
|
|
3243
|
+
allStepsDone: args.allStepsDone,
|
|
3244
|
+
acceptanceCriteria: args.acceptanceCriteria,
|
|
3245
|
+
allACValidated: args.allACValidated,
|
|
3246
|
+
testResults: args.testResults,
|
|
3247
|
+
notes: args.notes,
|
|
3248
|
+
filesCreated: args.filesCreated,
|
|
3249
|
+
filesModified: args.filesModified,
|
|
3250
|
+
filesDeleted: args.filesDeleted,
|
|
3251
|
+
blockReason: args.blockReason,
|
|
3252
|
+
clearBlockReason: args.clearBlockReason,
|
|
3253
|
+
});
|
|
3254
|
+
},
|
|
3253
3255
|
// ========================================================================
|
|
3254
3256
|
// Status & Analytics Tools
|
|
3255
3257
|
// ========================================================================
|
|
@@ -3630,56 +3632,6 @@ export function createToolHandlers(apiClient) {
|
|
|
3630
3632
|
// ========================================================================
|
|
3631
3633
|
// Bulk Operations
|
|
3632
3634
|
// ========================================================================
|
|
3633
|
-
bulk_create_tickets: async (_client, args) => {
|
|
3634
|
-
validateRequired(args, 'epicId', 'tickets');
|
|
3635
|
-
if (!Array.isArray(args.tickets) || args.tickets.length === 0) {
|
|
3636
|
-
throw new Error('tickets array is required and must not be empty');
|
|
3637
|
-
}
|
|
3638
|
-
// Validate each ticket has a title
|
|
3639
|
-
const tickets = args.tickets;
|
|
3640
|
-
for (let i = 0; i < tickets.length; i++) {
|
|
3641
|
-
if (!tickets[i].title || typeof tickets[i].title !== 'string') {
|
|
3642
|
-
throw new Error(`tickets[${i}].title is required and must be a string`);
|
|
3643
|
-
}
|
|
3644
|
-
}
|
|
3645
|
-
// Validate dependencies if provided
|
|
3646
|
-
if (args.dependencies && Array.isArray(args.dependencies)) {
|
|
3647
|
-
const deps = args.dependencies;
|
|
3648
|
-
for (let i = 0; i < deps.length; i++) {
|
|
3649
|
-
const dep = deps[i];
|
|
3650
|
-
if (typeof dep.ticket !== 'number' || dep.ticket < 0 || dep.ticket >= tickets.length) {
|
|
3651
|
-
throw new Error(`dependencies[${i}].ticket must be a valid index in tickets array (0-${tickets.length - 1})`);
|
|
3652
|
-
}
|
|
3653
|
-
const dependsOn = Array.isArray(dep.dependsOn) ? dep.dependsOn : [dep.dependsOn];
|
|
3654
|
-
for (const idx of dependsOn) {
|
|
3655
|
-
if (typeof idx !== 'number' || idx < 0 || idx >= tickets.length) {
|
|
3656
|
-
throw new Error(`dependencies[${i}].dependsOn contains invalid index ${idx} (must be 0-${tickets.length - 1})`);
|
|
3657
|
-
}
|
|
3658
|
-
if (idx === dep.ticket) {
|
|
3659
|
-
throw new Error(`dependencies[${i}]: ticket cannot depend on itself`);
|
|
3660
|
-
}
|
|
3661
|
-
}
|
|
3662
|
-
}
|
|
3663
|
-
}
|
|
3664
|
-
return await apiClient.call('bulk_create_tickets', {
|
|
3665
|
-
epicId: args.epicId,
|
|
3666
|
-
tickets: args.tickets,
|
|
3667
|
-
dependencies: args.dependencies,
|
|
3668
|
-
onError: args.onError,
|
|
3669
|
-
});
|
|
3670
|
-
},
|
|
3671
|
-
get_job_status: async (_client, args) => {
|
|
3672
|
-
validateRequired(args, 'jobId');
|
|
3673
|
-
return await apiClient.call('get_job_status', {
|
|
3674
|
-
jobId: args.jobId,
|
|
3675
|
-
});
|
|
3676
|
-
},
|
|
3677
|
-
cancel_job: async (_client, args) => {
|
|
3678
|
-
validateRequired(args, 'jobId');
|
|
3679
|
-
return await apiClient.call('cancel_job', {
|
|
3680
|
-
jobId: args.jobId,
|
|
3681
|
-
});
|
|
3682
|
-
},
|
|
3683
3635
|
bulk_add_dependencies: async (_client, args) => {
|
|
3684
3636
|
validateRequired(args, 'dependencies');
|
|
3685
3637
|
if (!Array.isArray(args.dependencies) || args.dependencies.length === 0) {
|