@exaudeus/workrail 3.12.0 → 3.14.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.
Files changed (54) hide show
  1. package/dist/console/assets/{index-CRgjJiMS.js → index-EsSXrC_a.js} +11 -11
  2. package/dist/console/index.html +1 -1
  3. package/dist/di/container.js +8 -0
  4. package/dist/di/tokens.d.ts +1 -0
  5. package/dist/di/tokens.js +1 -0
  6. package/dist/infrastructure/session/HttpServer.js +2 -14
  7. package/dist/manifest.json +93 -53
  8. package/dist/mcp/boundary-coercion.d.ts +2 -0
  9. package/dist/mcp/boundary-coercion.js +73 -0
  10. package/dist/mcp/handler-factory.d.ts +1 -1
  11. package/dist/mcp/handler-factory.js +13 -6
  12. package/dist/mcp/handlers/v2-manage-workflow-source.d.ts +7 -0
  13. package/dist/mcp/handlers/v2-manage-workflow-source.js +50 -0
  14. package/dist/mcp/handlers/v2-workflow.d.ts +3 -0
  15. package/dist/mcp/handlers/v2-workflow.js +58 -0
  16. package/dist/mcp/output-schemas.d.ts +93 -0
  17. package/dist/mcp/output-schemas.js +8 -1
  18. package/dist/mcp/server.js +2 -0
  19. package/dist/mcp/tool-descriptions.js +20 -0
  20. package/dist/mcp/tools.js +6 -0
  21. package/dist/mcp/types/tool-description-types.d.ts +1 -1
  22. package/dist/mcp/types/tool-description-types.js +1 -0
  23. package/dist/mcp/types/workflow-tool-edition.d.ts +1 -1
  24. package/dist/mcp/types.d.ts +2 -0
  25. package/dist/mcp/v2/tool-registry.js +8 -0
  26. package/dist/mcp/v2/tools.d.ts +12 -0
  27. package/dist/mcp/v2/tools.js +7 -1
  28. package/dist/types/workflow-definition.d.ts +1 -0
  29. package/dist/v2/infra/in-memory/managed-source-store/index.d.ts +8 -0
  30. package/dist/v2/infra/in-memory/managed-source-store/index.js +33 -0
  31. package/dist/v2/infra/local/data-dir/index.d.ts +2 -0
  32. package/dist/v2/infra/local/data-dir/index.js +6 -0
  33. package/dist/v2/infra/local/managed-source-store/index.d.ts +15 -0
  34. package/dist/v2/infra/local/managed-source-store/index.js +164 -0
  35. package/dist/v2/ports/data-dir.port.d.ts +2 -0
  36. package/dist/v2/ports/managed-source-store.port.d.ts +25 -0
  37. package/dist/v2/ports/managed-source-store.port.js +2 -0
  38. package/package.json +2 -1
  39. package/spec/authoring-spec.json +9 -2
  40. package/spec/workflow.schema.json +418 -96
  41. package/workflows/adaptive-ticket-creation.json +276 -282
  42. package/workflows/document-creation-workflow.json +70 -191
  43. package/workflows/documentation-update-workflow.json +59 -309
  44. package/workflows/intelligent-test-case-generation.json +37 -212
  45. package/workflows/personal-learning-materials-creation-branched.json +1 -21
  46. package/workflows/presentation-creation.json +143 -308
  47. package/workflows/relocation-workflow-us.json +161 -535
  48. package/workflows/scoped-documentation-workflow.json +110 -181
  49. package/workflows/workflow-for-workflows.v2.json +72 -16
  50. package/workflows/CHANGELOG-bug-investigation.md +0 -298
  51. package/workflows/bug-investigation.agentic.json +0 -212
  52. package/workflows/bug-investigation.json +0 -112
  53. package/workflows/mr-review-workflow.agentic.json +0 -538
  54. package/workflows/mr-review-workflow.json +0 -277
@@ -3,9 +3,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.shouldShowStaleness = shouldShowStaleness;
7
+ exports.computeWorkflowStaleness = computeWorkflowStaleness;
6
8
  exports.handleV2ListWorkflows = handleV2ListWorkflows;
7
9
  exports.handleV2InspectWorkflow = handleV2InspectWorkflow;
8
10
  const path_1 = __importDefault(require("path"));
11
+ const fs_1 = __importDefault(require("fs"));
9
12
  const neverthrow_1 = require("neverthrow");
10
13
  const types_js_1 = require("../types.js");
11
14
  const error_mapper_js_1 = require("../error-mapper.js");
@@ -14,6 +17,51 @@ const output_schemas_js_1 = require("../output-schemas.js");
14
17
  const v1_to_v2_shim_js_1 = require("../../v2/read-only/v1-to-v2-shim.js");
15
18
  const hashing_js_1 = require("../../v2/durable-core/canonical/hashing.js");
16
19
  const TIMEOUT_MS = 30000;
20
+ function readCurrentSpecVersion() {
21
+ try {
22
+ const specPath = path_1.default.resolve(__dirname, '../../../spec/authoring-spec.json');
23
+ const raw = fs_1.default.readFileSync(specPath, 'utf-8');
24
+ const parsed = JSON.parse(raw);
25
+ if (typeof parsed === 'object' && parsed !== null && 'version' in parsed) {
26
+ const v = parsed['version'];
27
+ if (typeof v === 'number' && Number.isInteger(v) && v >= 1)
28
+ return v;
29
+ }
30
+ return null;
31
+ }
32
+ catch {
33
+ return null;
34
+ }
35
+ }
36
+ const CURRENT_SPEC_VERSION = readCurrentSpecVersion();
37
+ const DEV_STALENESS = process.env['WORKRAIL_DEV_STALENESS'] === '1';
38
+ function shouldShowStaleness(category, devMode = DEV_STALENESS) {
39
+ if (devMode)
40
+ return true;
41
+ return category === 'personal' || category === 'rooted_sharing' || category === 'external';
42
+ }
43
+ function computeWorkflowStaleness(stamp, currentVersion) {
44
+ if (currentVersion === null)
45
+ return undefined;
46
+ if (stamp === undefined) {
47
+ return {
48
+ level: 'possible',
49
+ reason: 'This workflow has not been validated against the authoring spec via workflow-for-workflows.',
50
+ };
51
+ }
52
+ if (stamp === currentVersion) {
53
+ return {
54
+ level: 'none',
55
+ reason: `Workflow validated against current authoring spec (v${currentVersion}).`,
56
+ specVersionAtLastReview: stamp,
57
+ };
58
+ }
59
+ return {
60
+ level: 'likely',
61
+ reason: `Authoring spec updated from v${stamp} to v${currentVersion} since this workflow was last reviewed.`,
62
+ specVersionAtLastReview: stamp,
63
+ };
64
+ }
17
65
  const with_timeout_js_1 = require("./shared/with-timeout.js");
18
66
  const request_workflow_reader_js_1 = require("./shared/request-workflow-reader.js");
19
67
  const remembered_roots_js_1 = require("./shared/remembered-roots.js");
@@ -142,6 +190,12 @@ async function handleV2InspectWorkflow(input, ctx) {
142
190
  ...(visibility ? { visibility } : {}),
143
191
  ...(stalePaths.length > 0 ? { staleRoots: [...stalePaths] } : {}),
144
192
  ...(references != null && references.length > 0 ? { references } : {}),
193
+ ...(() => {
194
+ const staleness = shouldShowStaleness(visibility?.category)
195
+ ? computeWorkflowStaleness(workflow.definition.validatedAgainstSpecVersion, CURRENT_SPEC_VERSION)
196
+ : undefined;
197
+ return staleness !== undefined ? { staleness } : {};
198
+ })(),
145
199
  });
146
200
  return (0, neverthrow_1.okAsync)((0, types_js_1.success)(payload));
147
201
  }));
@@ -199,6 +253,9 @@ async function buildV2WorkflowListItem(options) {
199
253
  };
200
254
  }
201
255
  }
256
+ const staleness = shouldShowStaleness(visibility?.category)
257
+ ? computeWorkflowStaleness(workflow.definition.validatedAgainstSpecVersion, CURRENT_SPEC_VERSION)
258
+ : undefined;
202
259
  return {
203
260
  workflowId: summary.id,
204
261
  name: summary.name,
@@ -207,6 +264,7 @@ async function buildV2WorkflowListItem(options) {
207
264
  workflowHash: hash,
208
265
  kind: 'workflow',
209
266
  visibility,
267
+ ...(staleness !== undefined ? { staleness } : {}),
210
268
  };
211
269
  }
212
270
  async function buildSourceCatalog(workflowReader, rememberedRootRecords) {
@@ -152,6 +152,20 @@ export declare const WorkflowGetSchemaOutputSchema: z.ZodObject<{
152
152
  stepStructure: Record<string, string>;
153
153
  };
154
154
  }>;
155
+ export declare const StalenessSummarySchema: z.ZodObject<{
156
+ level: z.ZodEnum<["none", "possible", "likely"]>;
157
+ reason: z.ZodString;
158
+ specVersionAtLastReview: z.ZodOptional<z.ZodNumber>;
159
+ }, "strip", z.ZodTypeAny, {
160
+ level: "none" | "possible" | "likely";
161
+ reason: string;
162
+ specVersionAtLastReview?: number | undefined;
163
+ }, {
164
+ level: "none" | "possible" | "likely";
165
+ reason: string;
166
+ specVersionAtLastReview?: number | undefined;
167
+ }>;
168
+ export type StalenessSummary = z.infer<typeof StalenessSummarySchema>;
155
169
  export declare const V2WorkflowListItemSchema: z.ZodObject<{
156
170
  workflowId: z.ZodString;
157
171
  name: z.ZodString;
@@ -235,6 +249,19 @@ export declare const V2WorkflowListItemSchema: z.ZodObject<{
235
249
  currentSource: "legacy_project";
236
250
  } | undefined;
237
251
  }>>;
252
+ staleness: z.ZodOptional<z.ZodObject<{
253
+ level: z.ZodEnum<["none", "possible", "likely"]>;
254
+ reason: z.ZodString;
255
+ specVersionAtLastReview: z.ZodOptional<z.ZodNumber>;
256
+ }, "strip", z.ZodTypeAny, {
257
+ level: "none" | "possible" | "likely";
258
+ reason: string;
259
+ specVersionAtLastReview?: number | undefined;
260
+ }, {
261
+ level: "none" | "possible" | "likely";
262
+ reason: string;
263
+ specVersionAtLastReview?: number | undefined;
264
+ }>>;
238
265
  }, "strip", z.ZodTypeAny, {
239
266
  kind: "workflow";
240
267
  name: string;
@@ -260,6 +287,11 @@ export declare const V2WorkflowListItemSchema: z.ZodObject<{
260
287
  currentSource: "legacy_project";
261
288
  } | undefined;
262
289
  } | undefined;
290
+ staleness?: {
291
+ level: "none" | "possible" | "likely";
292
+ reason: string;
293
+ specVersionAtLastReview?: number | undefined;
294
+ } | undefined;
263
295
  }, {
264
296
  kind: "workflow";
265
297
  name: string;
@@ -285,6 +317,11 @@ export declare const V2WorkflowListItemSchema: z.ZodObject<{
285
317
  currentSource: "legacy_project";
286
318
  } | undefined;
287
319
  } | undefined;
320
+ staleness?: {
321
+ level: "none" | "possible" | "likely";
322
+ reason: string;
323
+ specVersionAtLastReview?: number | undefined;
324
+ } | undefined;
288
325
  }>;
289
326
  export declare const V2WorkflowSourceCatalogEntrySchema: z.ZodObject<{
290
327
  sourceKey: z.ZodString;
@@ -461,6 +498,19 @@ export declare const V2WorkflowListOutputSchema: z.ZodObject<{
461
498
  currentSource: "legacy_project";
462
499
  } | undefined;
463
500
  }>>;
501
+ staleness: z.ZodOptional<z.ZodObject<{
502
+ level: z.ZodEnum<["none", "possible", "likely"]>;
503
+ reason: z.ZodString;
504
+ specVersionAtLastReview: z.ZodOptional<z.ZodNumber>;
505
+ }, "strip", z.ZodTypeAny, {
506
+ level: "none" | "possible" | "likely";
507
+ reason: string;
508
+ specVersionAtLastReview?: number | undefined;
509
+ }, {
510
+ level: "none" | "possible" | "likely";
511
+ reason: string;
512
+ specVersionAtLastReview?: number | undefined;
513
+ }>>;
464
514
  }, "strip", z.ZodTypeAny, {
465
515
  kind: "workflow";
466
516
  name: string;
@@ -486,6 +536,11 @@ export declare const V2WorkflowListOutputSchema: z.ZodObject<{
486
536
  currentSource: "legacy_project";
487
537
  } | undefined;
488
538
  } | undefined;
539
+ staleness?: {
540
+ level: "none" | "possible" | "likely";
541
+ reason: string;
542
+ specVersionAtLastReview?: number | undefined;
543
+ } | undefined;
489
544
  }, {
490
545
  kind: "workflow";
491
546
  name: string;
@@ -511,6 +566,11 @@ export declare const V2WorkflowListOutputSchema: z.ZodObject<{
511
566
  currentSource: "legacy_project";
512
567
  } | undefined;
513
568
  } | undefined;
569
+ staleness?: {
570
+ level: "none" | "possible" | "likely";
571
+ reason: string;
572
+ specVersionAtLastReview?: number | undefined;
573
+ } | undefined;
514
574
  }>, "many">;
515
575
  staleRoots: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
516
576
  sources: z.ZodOptional<z.ZodArray<z.ZodObject<{
@@ -630,6 +690,11 @@ export declare const V2WorkflowListOutputSchema: z.ZodObject<{
630
690
  currentSource: "legacy_project";
631
691
  } | undefined;
632
692
  } | undefined;
693
+ staleness?: {
694
+ level: "none" | "possible" | "likely";
695
+ reason: string;
696
+ specVersionAtLastReview?: number | undefined;
697
+ } | undefined;
633
698
  }[];
634
699
  sources?: {
635
700
  source: {
@@ -681,6 +746,11 @@ export declare const V2WorkflowListOutputSchema: z.ZodObject<{
681
746
  currentSource: "legacy_project";
682
747
  } | undefined;
683
748
  } | undefined;
749
+ staleness?: {
750
+ level: "none" | "possible" | "likely";
751
+ reason: string;
752
+ specVersionAtLastReview?: number | undefined;
753
+ } | undefined;
684
754
  }[];
685
755
  sources?: {
686
756
  source: {
@@ -811,6 +881,19 @@ export declare const V2WorkflowInspectOutputSchema: z.ZodObject<{
811
881
  authoritative: boolean;
812
882
  resolveFrom?: "workspace" | "package" | undefined;
813
883
  }>, "many">>;
884
+ staleness: z.ZodOptional<z.ZodObject<{
885
+ level: z.ZodEnum<["none", "possible", "likely"]>;
886
+ reason: z.ZodString;
887
+ specVersionAtLastReview: z.ZodOptional<z.ZodNumber>;
888
+ }, "strip", z.ZodTypeAny, {
889
+ level: "none" | "possible" | "likely";
890
+ reason: string;
891
+ specVersionAtLastReview?: number | undefined;
892
+ }, {
893
+ level: "none" | "possible" | "likely";
894
+ reason: string;
895
+ specVersionAtLastReview?: number | undefined;
896
+ }>>;
814
897
  }, "strip", z.ZodTypeAny, {
815
898
  workflowId: string;
816
899
  workflowHash: string;
@@ -842,6 +925,11 @@ export declare const V2WorkflowInspectOutputSchema: z.ZodObject<{
842
925
  currentSource: "legacy_project";
843
926
  } | undefined;
844
927
  } | undefined;
928
+ staleness?: {
929
+ level: "none" | "possible" | "likely";
930
+ reason: string;
931
+ specVersionAtLastReview?: number | undefined;
932
+ } | undefined;
845
933
  staleRoots?: string[] | undefined;
846
934
  }, {
847
935
  workflowId: string;
@@ -874,6 +962,11 @@ export declare const V2WorkflowInspectOutputSchema: z.ZodObject<{
874
962
  currentSource: "legacy_project";
875
963
  } | undefined;
876
964
  } | undefined;
965
+ staleness?: {
966
+ level: "none" | "possible" | "likely";
967
+ reason: string;
968
+ specVersionAtLastReview?: number | undefined;
969
+ } | undefined;
877
970
  staleRoots?: string[] | undefined;
878
971
  }>;
879
972
  export declare const V2PendingStepSchema: z.ZodObject<{
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.OpenDashboardOutputSchema = exports.ReadSessionSchemaOutputSchema = exports.ReadSessionOutputSchema = exports.UpdateSessionOutputSchema = exports.CreateSessionOutputSchema = exports.V2StartWorkflowOutputSchema = exports.V2CheckpointWorkflowOutputSchema = exports.V2ResumeSessionOutputSchema = exports.V2ContinueWorkflowOutputSchema = exports.V2StepContextSchema = exports.V2BindingDriftWarningSchema = exports.V2BlockerReportSchema = exports.V2ResumeNextCallSchema = exports.V2NextCallSchema = exports.V2NextIntentSchema = exports.V2PreferencesSchema = exports.V2PendingStepSchema = exports.V2WorkflowInspectOutputSchema = exports.V2WorkflowListOutputSchema = exports.V2WorkflowSourceCatalogEntrySchema = exports.V2WorkflowListItemSchema = exports.WorkflowGetSchemaOutputSchema = exports.WorkflowValidateJsonOutputSchema = exports.WorkflowNextOutputSchema = exports.WorkflowGetOutputSchema = exports.WorkflowListOutputSchema = exports.WorkflowSummarySchema = exports.JsonValueSchema = void 0;
3
+ exports.OpenDashboardOutputSchema = exports.ReadSessionSchemaOutputSchema = exports.ReadSessionOutputSchema = exports.UpdateSessionOutputSchema = exports.CreateSessionOutputSchema = exports.V2StartWorkflowOutputSchema = exports.V2CheckpointWorkflowOutputSchema = exports.V2ResumeSessionOutputSchema = exports.V2ContinueWorkflowOutputSchema = exports.V2StepContextSchema = exports.V2BindingDriftWarningSchema = exports.V2BlockerReportSchema = exports.V2ResumeNextCallSchema = exports.V2NextCallSchema = exports.V2NextIntentSchema = exports.V2PreferencesSchema = exports.V2PendingStepSchema = exports.V2WorkflowInspectOutputSchema = exports.V2WorkflowListOutputSchema = exports.V2WorkflowSourceCatalogEntrySchema = exports.V2WorkflowListItemSchema = exports.StalenessSummarySchema = exports.WorkflowGetSchemaOutputSchema = exports.WorkflowValidateJsonOutputSchema = exports.WorkflowNextOutputSchema = exports.WorkflowGetOutputSchema = exports.WorkflowListOutputSchema = exports.WorkflowSummarySchema = exports.JsonValueSchema = void 0;
4
4
  exports.toPendingStep = toPendingStep;
5
5
  const zod_1 = require("zod");
6
6
  const state_js_1 = require("../domain/execution/state.js");
@@ -48,6 +48,11 @@ exports.WorkflowGetSchemaOutputSchema = zod_1.z.object({
48
48
  stepStructure: zod_1.z.record(zod_1.z.string()),
49
49
  }),
50
50
  });
51
+ exports.StalenessSummarySchema = zod_1.z.object({
52
+ level: zod_1.z.enum(['none', 'possible', 'likely']),
53
+ reason: zod_1.z.string().min(1),
54
+ specVersionAtLastReview: zod_1.z.number().int().positive().optional(),
55
+ });
51
56
  exports.V2WorkflowListItemSchema = zod_1.z.object({
52
57
  workflowId: zod_1.z.string().min(1),
53
58
  name: zod_1.z.string().min(1),
@@ -73,6 +78,7 @@ exports.V2WorkflowListItemSchema = zod_1.z.object({
73
78
  summary: zod_1.z.string().min(1),
74
79
  }).optional(),
75
80
  }).optional(),
81
+ staleness: exports.StalenessSummarySchema.optional(),
76
82
  });
77
83
  exports.V2WorkflowSourceCatalogEntrySchema = zod_1.z.object({
78
84
  sourceKey: zod_1.z.string().min(1).describe('Stable identifier for this source. Format: "{kind}:{absolutePath}" for filesystem sources (e.g. "project:/path/to/workflows", "custom:/path/to/.workrail/workflows"), or "built_in" for bundled sources.'),
@@ -122,6 +128,7 @@ exports.V2WorkflowInspectOutputSchema = zod_1.z.object({
122
128
  authoritative: zod_1.z.boolean(),
123
129
  resolveFrom: zod_1.z.enum(['workspace', 'package']).optional(),
124
130
  })).optional(),
131
+ staleness: exports.StalenessSummarySchema.optional(),
125
132
  });
126
133
  exports.V2PendingStepSchema = zod_1.z.object({
127
134
  stepId: zod_1.z.string().min(1),
@@ -110,6 +110,7 @@ async function createToolContext() {
110
110
  console.error(`[V2Init] Token alias index load warning: ${aliasLoadResult.error.message}`);
111
111
  }
112
112
  const rememberedRootsStore = container_js_1.container.resolve(tokens_js_1.DI.V2.RememberedRootsStore);
113
+ const managedSourceStore = container_js_1.container.resolve(tokens_js_1.DI.V2.ManagedSourceStore);
113
114
  v2 = {
114
115
  gate,
115
116
  sessionStore,
@@ -122,6 +123,7 @@ async function createToolContext() {
122
123
  tokenCodecPorts,
123
124
  tokenAliasStore,
124
125
  rememberedRootsStore,
126
+ managedSourceStore,
125
127
  validationPipelineDeps,
126
128
  resolvedRootUris: [],
127
129
  workspaceResolver: new index_js_1.LocalWorkspaceAnchorV2(process.cwd()),
@@ -73,6 +73,16 @@ Remember: inspecting is read-only. Call start_workflow when ready to begin.`,
73
73
  continue_workflow: (0, workflow_protocol_contracts_js_1.renderProtocolDescription)(workflow_protocol_contracts_js_1.CONTINUE_WORKFLOW_PROTOCOL, 'standard'),
74
74
  checkpoint_workflow: (0, workflow_protocol_contracts_js_1.renderProtocolDescription)(workflow_protocol_contracts_js_1.CHECKPOINT_WORKFLOW_PROTOCOL, 'standard'),
75
75
  resume_session: (0, workflow_protocol_contracts_js_1.renderProtocolDescription)(workflow_protocol_contracts_js_1.RESUME_SESSION_PROTOCOL, 'standard'),
76
+ manage_workflow_source: `Attach or detach a workflow directory as a managed source.
77
+
78
+ Use this to explicitly add a directory containing workflow files so its workflows appear in list_workflows as managed entries.
79
+
80
+ Parameters:
81
+ - action: "attach" to add a directory, "detach" to remove it. Both are idempotent.
82
+ - path: absolute filesystem path to the workflow directory
83
+
84
+ Attach is idempotent: attaching an already-attached path is a no-op.
85
+ Detach is idempotent: detaching an absent path is a no-op.`,
76
86
  },
77
87
  authoritative: {
78
88
  discover_workflows: `Check for workflows that apply to the user's request. Workflows are the user's pre-defined instructions that you MUST follow when they exist.
@@ -150,5 +160,15 @@ This is read-only. Call start_workflow when ready to commit to following the wor
150
160
  continue_workflow: (0, workflow_protocol_contracts_js_1.renderProtocolDescription)(workflow_protocol_contracts_js_1.CONTINUE_WORKFLOW_PROTOCOL, 'authoritative'),
151
161
  checkpoint_workflow: (0, workflow_protocol_contracts_js_1.renderProtocolDescription)(workflow_protocol_contracts_js_1.CHECKPOINT_WORKFLOW_PROTOCOL, 'authoritative'),
152
162
  resume_session: (0, workflow_protocol_contracts_js_1.renderProtocolDescription)(workflow_protocol_contracts_js_1.RESUME_SESSION_PROTOCOL, 'authoritative'),
163
+ manage_workflow_source: `Attach or detach a workflow directory as a managed source.
164
+
165
+ When the user wants to register an external workflow directory, use attach. When they want to remove it, use detach. Both are idempotent.
166
+
167
+ Parameters:
168
+ - action: "attach" to add a directory, "detach" to remove it. Both are idempotent.
169
+ - path: absolute filesystem path to the workflow directory
170
+
171
+ Attach is idempotent: attaching an already-attached path is a no-op.
172
+ Detach is idempotent: detaching an absent path is a no-op.`,
153
173
  },
154
174
  };
package/dist/mcp/tools.js CHANGED
@@ -92,6 +92,11 @@ exports.WORKFLOW_TOOL_ANNOTATIONS = {
92
92
  destructiveHint: false,
93
93
  idempotentHint: true,
94
94
  },
95
+ manage_workflow_source: {
96
+ readOnlyHint: false,
97
+ destructiveHint: false,
98
+ idempotentHint: true,
99
+ },
95
100
  };
96
101
  exports.WORKFLOW_TOOL_TITLES = {
97
102
  discover_workflows: 'Discover Available Workflows',
@@ -105,6 +110,7 @@ exports.WORKFLOW_TOOL_TITLES = {
105
110
  continue_workflow: 'Continue Workflow (v2)',
106
111
  checkpoint_workflow: 'Checkpoint Workflow (v2)',
107
112
  resume_session: 'Resume Session (v2)',
113
+ manage_workflow_source: 'Manage Workflow Source (v2)',
108
114
  };
109
115
  exports.CreateSessionInput = zod_1.z.object({
110
116
  workflowId: zod_1.z
@@ -1,6 +1,6 @@
1
1
  export declare const DESCRIPTION_MODES: readonly ["standard", "authoritative"];
2
2
  export type DescriptionMode = typeof DESCRIPTION_MODES[number];
3
- export declare const WORKFLOW_TOOL_NAMES: readonly ["discover_workflows", "preview_workflow", "advance_workflow", "validate_workflow", "get_workflow_schema", "list_workflows", "inspect_workflow", "start_workflow", "continue_workflow", "checkpoint_workflow", "resume_session"];
3
+ export declare const WORKFLOW_TOOL_NAMES: readonly ["discover_workflows", "preview_workflow", "advance_workflow", "validate_workflow", "get_workflow_schema", "list_workflows", "inspect_workflow", "start_workflow", "continue_workflow", "checkpoint_workflow", "resume_session", "manage_workflow_source"];
4
4
  export type WorkflowToolName = typeof WORKFLOW_TOOL_NAMES[number];
5
5
  export type ToolDescriptionMap = Readonly<Record<WorkflowToolName, string>>;
6
6
  export type DescriptionsByMode = Readonly<Record<DescriptionMode, ToolDescriptionMap>>;
@@ -19,6 +19,7 @@ exports.WORKFLOW_TOOL_NAMES = [
19
19
  'continue_workflow',
20
20
  'checkpoint_workflow',
21
21
  'resume_session',
22
+ 'manage_workflow_source',
22
23
  ];
23
24
  function isDescriptionMode(value) {
24
25
  return exports.DESCRIPTION_MODES.includes(value);
@@ -2,7 +2,7 @@ import type { z } from 'zod';
2
2
  import type { ToolDefinition } from '../tool-factory.js';
3
3
  import type { ToolContext } from '../types.js';
4
4
  export type V1WorkflowToolName = 'discover_workflows' | 'preview_workflow' | 'advance_workflow' | 'validate_workflow' | 'get_workflow_schema';
5
- export type V2WorkflowToolName = 'list_workflows' | 'inspect_workflow' | 'start_workflow' | 'continue_workflow' | 'checkpoint_workflow' | 'resume_session';
5
+ export type V2WorkflowToolName = 'list_workflows' | 'inspect_workflow' | 'start_workflow' | 'continue_workflow' | 'checkpoint_workflow' | 'resume_session' | 'manage_workflow_source';
6
6
  export type McpCallToolResult = {
7
7
  readonly content: ReadonlyArray<{
8
8
  readonly type: 'text';
@@ -20,6 +20,7 @@ import type { ValidationPipelineDepsPhase1a } from '../application/services/work
20
20
  import type { TokenAliasStorePortV2 } from '../v2/ports/token-alias-store.port.js';
21
21
  import type { RandomEntropyPortV2 } from '../v2/ports/random-entropy.port.js';
22
22
  import type { RememberedRootsStorePortV2 } from '../v2/ports/remembered-roots-store.port.js';
23
+ import type { ManagedSourceStorePortV2 } from '../v2/ports/managed-source-store.port.js';
23
24
  export interface SessionHealthDetails {
24
25
  readonly health: SessionHealthV2;
25
26
  }
@@ -61,6 +62,7 @@ export interface V2Dependencies {
61
62
  readonly tokenCodecPorts: TokenCodecPorts;
62
63
  readonly tokenAliasStore: TokenAliasStorePortV2;
63
64
  readonly rememberedRootsStore?: RememberedRootsStorePortV2;
65
+ readonly managedSourceStore?: ManagedSourceStorePortV2;
64
66
  readonly entropy: RandomEntropyPortV2;
65
67
  readonly validationPipelineDeps: ValidationPipelineDepsPhase1a;
66
68
  readonly resolvedRootUris?: readonly string[];
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.buildV2ToolRegistry = buildV2ToolRegistry;
4
4
  const handler_factory_js_1 = require("../handler-factory.js");
5
5
  const tools_js_1 = require("./tools.js");
6
+ const v2_manage_workflow_source_js_1 = require("../handlers/v2-manage-workflow-source.js");
6
7
  const v2_execution_js_1 = require("../handlers/v2-execution.js");
7
8
  const v2_workflow_js_1 = require("../handlers/v2-workflow.js");
8
9
  const v2_checkpoint_js_1 = require("../handlers/v2-checkpoint.js");
@@ -46,6 +47,12 @@ function buildV2ToolRegistry(buildTool) {
46
47
  inputSchema: tools_js_1.V2ResumeSessionInput,
47
48
  annotations: tools_js_1.V2_TOOL_ANNOTATIONS.resume_session,
48
49
  }),
50
+ buildTool({
51
+ name: 'manage_workflow_source',
52
+ title: tools_js_1.V2_TOOL_TITLES.manage_workflow_source,
53
+ inputSchema: tools_js_1.V2ManageWorkflowSourceInput,
54
+ annotations: tools_js_1.V2_TOOL_ANNOTATIONS.manage_workflow_source,
55
+ }),
49
56
  ];
50
57
  const handlers = {
51
58
  list_workflows: (0, handler_factory_js_1.createHandler)(tools_js_1.V2ListWorkflowsInput, v2_workflow_js_1.handleV2ListWorkflows),
@@ -54,6 +61,7 @@ function buildV2ToolRegistry(buildTool) {
54
61
  continue_workflow: (0, handler_factory_js_1.createHandler)(tools_js_1.V2ContinueWorkflowInput, v2_execution_js_1.handleV2ContinueWorkflow, tools_js_1.V2ContinueWorkflowInputShape, workflow_protocol_contracts_js_1.CONTINUE_WORKFLOW_PROTOCOL.aliasMap),
55
62
  checkpoint_workflow: (0, handler_factory_js_1.createHandler)(tools_js_1.V2CheckpointWorkflowInput, v2_checkpoint_js_1.handleV2CheckpointWorkflow),
56
63
  resume_session: (0, handler_factory_js_1.createHandler)(tools_js_1.V2ResumeSessionInput, v2_resume_js_1.handleV2ResumeSession),
64
+ manage_workflow_source: (0, handler_factory_js_1.createHandler)(tools_js_1.V2ManageWorkflowSourceInput, v2_manage_workflow_source_js_1.handleV2ManageWorkflowSource),
57
65
  };
58
66
  return { tools, handlers };
59
67
  }
@@ -174,6 +174,17 @@ export declare const V2ResumeSessionInput: z.ZodObject<{
174
174
  sameWorkspaceOnly?: boolean | undefined;
175
175
  }>;
176
176
  export type V2ResumeSessionInput = z.infer<typeof V2ResumeSessionInput>;
177
+ export declare const V2ManageWorkflowSourceInput: z.ZodObject<{
178
+ action: z.ZodEnum<["attach", "detach"]>;
179
+ path: z.ZodEffects<z.ZodString, string, string>;
180
+ }, "strict", z.ZodTypeAny, {
181
+ path: string;
182
+ action: "attach" | "detach";
183
+ }, {
184
+ path: string;
185
+ action: "attach" | "detach";
186
+ }>;
187
+ export type V2ManageWorkflowSourceInput = z.infer<typeof V2ManageWorkflowSourceInput>;
177
188
  export declare const V2CheckpointWorkflowInput: z.ZodObject<{
178
189
  checkpointToken: z.ZodString;
179
190
  }, "strict", z.ZodTypeAny, {
@@ -189,5 +200,6 @@ export declare const V2_TOOL_TITLES: {
189
200
  readonly continue_workflow: "Continue Workflow (v2)";
190
201
  readonly checkpoint_workflow: "Checkpoint Workflow (v2)";
191
202
  readonly resume_session: "Resume Session (v2)";
203
+ readonly manage_workflow_source: "Manage Workflow Source (v2)";
192
204
  };
193
205
  export declare const V2_TOOL_ANNOTATIONS: Readonly<Record<keyof typeof V2_TOOL_TITLES, ToolAnnotations>>;
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.V2_TOOL_ANNOTATIONS = exports.V2_TOOL_TITLES = exports.V2CheckpointWorkflowInput = exports.V2ResumeSessionInput = exports.V2ContinueWorkflowInput = exports.V2ContinueWorkflowInputShape = exports.V2StartWorkflowInput = exports.V2InspectWorkflowInput = exports.V2ListWorkflowsInput = void 0;
6
+ exports.V2_TOOL_ANNOTATIONS = exports.V2_TOOL_TITLES = exports.V2CheckpointWorkflowInput = exports.V2ManageWorkflowSourceInput = exports.V2ResumeSessionInput = exports.V2ContinueWorkflowInput = exports.V2ContinueWorkflowInputShape = exports.V2StartWorkflowInput = exports.V2InspectWorkflowInput = exports.V2ListWorkflowsInput = void 0;
7
7
  const path_1 = __importDefault(require("path"));
8
8
  const zod_1 = require("zod");
9
9
  const workflow_protocol_contracts_js_1 = require("../workflow-protocol-contracts.js");
@@ -112,6 +112,10 @@ exports.V2ResumeSessionInput = zod_1.z.object({
112
112
  sameWorkspaceOnly: zod_1.z.boolean().optional().describe('If true, only sessions from the same repo/workspace are considered when repo_root_hash is available. ' +
113
113
  'Use this when the user clearly means "resume work from this repo only".'),
114
114
  }).strict();
115
+ exports.V2ManageWorkflowSourceInput = zod_1.z.object({
116
+ action: zod_1.z.enum(['attach', 'detach']).describe('The operation to perform. "attach" registers the directory as a managed workflow source; "detach" removes it. Both operations are idempotent.'),
117
+ path: zod_1.z.string().min(1).refine((p) => path_1.default.isAbsolute(p), 'path must be an absolute path').describe('Absolute filesystem path to the workflow directory to attach or detach. Must be an absolute path. The path is normalized (resolved) before storage.'),
118
+ }).strict();
115
119
  exports.V2CheckpointWorkflowInput = zod_1.z.object({
116
120
  checkpointToken: zod_1.z.string().min(1).describe('The checkpoint token from the most recent start_workflow or continue_workflow response. ' +
117
121
  'Creates a checkpoint on the current step without advancing. Idempotent — calling with the same token is safe.'),
@@ -123,6 +127,7 @@ exports.V2_TOOL_TITLES = {
123
127
  continue_workflow: 'Continue Workflow (v2)',
124
128
  checkpoint_workflow: 'Checkpoint Workflow (v2)',
125
129
  resume_session: 'Resume Session (v2)',
130
+ manage_workflow_source: 'Manage Workflow Source (v2)',
126
131
  };
127
132
  exports.V2_TOOL_ANNOTATIONS = {
128
133
  list_workflows: { readOnlyHint: true, destructiveHint: false, idempotentHint: true },
@@ -131,4 +136,5 @@ exports.V2_TOOL_ANNOTATIONS = {
131
136
  continue_workflow: { readOnlyHint: false, destructiveHint: false, idempotentHint: true },
132
137
  checkpoint_workflow: { readOnlyHint: false, destructiveHint: false, idempotentHint: true },
133
138
  resume_session: { readOnlyHint: true, destructiveHint: false, idempotentHint: true },
139
+ manage_workflow_source: { readOnlyHint: false, destructiveHint: false, idempotentHint: true },
134
140
  };
@@ -134,6 +134,7 @@ export interface WorkflowDefinition {
134
134
  readonly assessments?: readonly AssessmentDefinition[];
135
135
  readonly extensionPoints?: readonly ExtensionPoint[];
136
136
  readonly references?: readonly WorkflowReference[];
137
+ readonly validatedAgainstSpecVersion?: number;
137
138
  }
138
139
  export declare function isLoopStepDefinition(step: WorkflowStepDefinition | LoopStepDefinition): step is LoopStepDefinition;
139
140
  export declare function isWorkflowStepDefinition(step: WorkflowStepDefinition | LoopStepDefinition): step is WorkflowStepDefinition;
@@ -0,0 +1,8 @@
1
+ import type { ResultAsync } from 'neverthrow';
2
+ import type { ManagedSourceRecordV2, ManagedSourceStoreError, ManagedSourceStorePortV2 } from '../../../ports/managed-source-store.port.js';
3
+ export declare class InMemoryManagedSourceStoreV2 implements ManagedSourceStorePortV2 {
4
+ private readonly sources;
5
+ list(): ResultAsync<readonly ManagedSourceRecordV2[], ManagedSourceStoreError>;
6
+ attach(sourcePath: string): ResultAsync<void, ManagedSourceStoreError>;
7
+ detach(sourcePath: string): ResultAsync<void, ManagedSourceStoreError>;
8
+ }
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.InMemoryManagedSourceStoreV2 = void 0;
7
+ const path_1 = __importDefault(require("path"));
8
+ const neverthrow_1 = require("neverthrow");
9
+ class InMemoryManagedSourceStoreV2 {
10
+ constructor() {
11
+ this.sources = [];
12
+ }
13
+ list() {
14
+ return (0, neverthrow_1.okAsync)([...this.sources]);
15
+ }
16
+ attach(sourcePath) {
17
+ const normalizedPath = path_1.default.resolve(sourcePath);
18
+ const alreadyPresent = this.sources.some((s) => s.path === normalizedPath);
19
+ if (!alreadyPresent) {
20
+ this.sources.push({ path: normalizedPath, addedAtMs: Date.now() });
21
+ }
22
+ return (0, neverthrow_1.okAsync)(undefined);
23
+ }
24
+ detach(sourcePath) {
25
+ const normalizedPath = path_1.default.resolve(sourcePath);
26
+ const index = this.sources.findIndex((s) => s.path === normalizedPath);
27
+ if (index !== -1) {
28
+ this.sources.splice(index, 1);
29
+ }
30
+ return (0, neverthrow_1.okAsync)(undefined);
31
+ }
32
+ }
33
+ exports.InMemoryManagedSourceStoreV2 = InMemoryManagedSourceStoreV2;
@@ -19,4 +19,6 @@ export declare class LocalDataDirV2 implements DataDirPortV2 {
19
19
  sessionManifestPath(sessionId: SessionId): string;
20
20
  sessionLockPath(sessionId: SessionId): string;
21
21
  tokenIndexPath(): string;
22
+ managedSourcesPath(): string;
23
+ managedSourcesLockPath(): string;
22
24
  }
@@ -89,5 +89,11 @@ class LocalDataDirV2 {
89
89
  tokenIndexPath() {
90
90
  return path.join(this.keysDir(), 'token-index.jsonl');
91
91
  }
92
+ managedSourcesPath() {
93
+ return path.join(this.root(), 'managed-sources', 'managed-sources.json');
94
+ }
95
+ managedSourcesLockPath() {
96
+ return path.join(this.root(), 'managed-sources', 'managed-sources.lock');
97
+ }
92
98
  }
93
99
  exports.LocalDataDirV2 = LocalDataDirV2;
@@ -0,0 +1,15 @@
1
+ import type { ResultAsync } from 'neverthrow';
2
+ import type { DataDirPortV2 } from '../../../ports/data-dir.port.js';
3
+ import type { FileSystemPortV2 } from '../../../ports/fs.port.js';
4
+ import type { ManagedSourceRecordV2, ManagedSourceStoreError, ManagedSourceStorePortV2 } from '../../../ports/managed-source-store.port.js';
5
+ export declare class LocalManagedSourceStoreV2 implements ManagedSourceStorePortV2 {
6
+ private readonly dataDir;
7
+ private readonly fs;
8
+ constructor(dataDir: DataDirPortV2, fs: FileSystemPortV2);
9
+ list(): ResultAsync<readonly ManagedSourceRecordV2[], ManagedSourceStoreError>;
10
+ attach(sourcePath: string): ResultAsync<void, ManagedSourceStoreError>;
11
+ detach(sourcePath: string): ResultAsync<void, ManagedSourceStoreError>;
12
+ private readSources;
13
+ private persist;
14
+ private withLock;
15
+ }