@exaudeus/workrail 3.39.0 → 3.41.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 (97) hide show
  1. package/dist/cli/commands/init.js +0 -3
  2. package/dist/cli-worktrain.js +58 -26
  3. package/dist/cli.js +0 -18
  4. package/dist/config/app-config.d.ts +0 -16
  5. package/dist/config/app-config.js +0 -14
  6. package/dist/config/config-file.js +0 -3
  7. package/dist/console-ui/assets/index-CQt4UhPB.js +28 -0
  8. package/dist/console-ui/assets/index-DGj8EsFR.css +1 -0
  9. package/dist/console-ui/index.html +2 -2
  10. package/dist/coordinators/pr-review.d.ts +23 -1
  11. package/dist/coordinators/pr-review.js +224 -5
  12. package/dist/daemon/daemon-events.d.ts +9 -1
  13. package/dist/daemon/soul-template.d.ts +2 -2
  14. package/dist/daemon/soul-template.js +11 -1
  15. package/dist/daemon/workflow-runner.d.ts +17 -3
  16. package/dist/daemon/workflow-runner.js +401 -28
  17. package/dist/di/container.js +1 -25
  18. package/dist/di/tokens.d.ts +0 -3
  19. package/dist/di/tokens.js +0 -3
  20. package/dist/engine/engine-factory.js +0 -1
  21. package/dist/infrastructure/console-defaults.d.ts +1 -0
  22. package/dist/infrastructure/console-defaults.js +4 -0
  23. package/dist/infrastructure/session/index.d.ts +0 -1
  24. package/dist/infrastructure/session/index.js +1 -3
  25. package/dist/manifest.json +124 -124
  26. package/dist/mcp/handlers/session.d.ts +1 -0
  27. package/dist/mcp/handlers/session.js +61 -13
  28. package/dist/mcp/output-schemas.d.ts +10 -10
  29. package/dist/mcp/server.js +1 -18
  30. package/dist/mcp/tools.d.ts +12 -12
  31. package/dist/mcp/transports/http-entry.js +0 -2
  32. package/dist/mcp/transports/stdio-entry.js +1 -2
  33. package/dist/mcp/types.d.ts +0 -2
  34. package/dist/trigger/daemon-console.d.ts +2 -0
  35. package/dist/trigger/daemon-console.js +1 -1
  36. package/dist/trigger/trigger-listener.d.ts +2 -0
  37. package/dist/trigger/trigger-listener.js +3 -1
  38. package/dist/trigger/trigger-router.d.ts +4 -3
  39. package/dist/trigger/trigger-router.js +13 -5
  40. package/dist/trigger/trigger-store.js +17 -4
  41. package/dist/types/workflow-source.d.ts +0 -1
  42. package/dist/types/workflow-source.js +3 -6
  43. package/dist/types/workflow.d.ts +1 -1
  44. package/dist/types/workflow.js +1 -2
  45. package/dist/v2/durable-core/domain/artifact-contract-validator.js +66 -0
  46. package/dist/v2/durable-core/schemas/artifacts/coordinator-signal.d.ts +25 -0
  47. package/dist/v2/durable-core/schemas/artifacts/coordinator-signal.js +31 -0
  48. package/dist/v2/durable-core/schemas/artifacts/index.d.ts +3 -1
  49. package/dist/v2/durable-core/schemas/artifacts/index.js +14 -1
  50. package/dist/v2/durable-core/schemas/artifacts/review-verdict.d.ts +41 -0
  51. package/dist/v2/durable-core/schemas/artifacts/review-verdict.js +30 -0
  52. package/dist/v2/durable-core/schemas/export-bundle/index.d.ts +236 -236
  53. package/dist/v2/durable-core/schemas/session/events.d.ts +50 -50
  54. package/dist/v2/durable-core/schemas/session/gaps.d.ts +2 -2
  55. package/dist/v2/durable-core/schemas/session/manifest.d.ts +4 -4
  56. package/dist/v2/durable-core/schemas/session/outputs.d.ts +8 -8
  57. package/dist/v2/usecases/console-routes.d.ts +2 -1
  58. package/dist/v2/usecases/console-routes.js +207 -5
  59. package/dist/v2/usecases/console-service.js +14 -0
  60. package/dist/v2/usecases/console-types.d.ts +1 -0
  61. package/docs/authoring.md +16 -16
  62. package/docs/design/coordinator-artifact-protocol-design-candidates.md +155 -0
  63. package/docs/design/coordinator-artifact-protocol-design-review.md +103 -0
  64. package/docs/design/coordinator-artifact-protocol-implementation-plan.md +259 -0
  65. package/docs/design/coordinator-message-queue-drain-plan.md +241 -0
  66. package/docs/design/coordinator-message-queue-drain-review.md +120 -0
  67. package/docs/design/coordinator-message-queue-drain.md +289 -0
  68. package/docs/design/shaping-workflow-external-research.md +119 -0
  69. package/docs/discovery/late-bound-goals-impl-plan.md +147 -0
  70. package/docs/discovery/late-bound-goals-review.md +82 -0
  71. package/docs/discovery/late-bound-goals.md +118 -0
  72. package/docs/discovery/steer-endpoint-design-candidates.md +288 -0
  73. package/docs/discovery/steer-endpoint-design-review-findings.md +104 -0
  74. package/docs/discovery/steer-endpoint-implementation-plan.md +284 -0
  75. package/docs/ideas/backlog.md +447 -97
  76. package/docs/ideas/design-candidates-console-session-tree-impl.md +64 -0
  77. package/docs/ideas/design-candidates-session-tree-view.md +196 -0
  78. package/docs/ideas/design-review-findings-console-session-tree-impl.md +75 -0
  79. package/docs/ideas/design-review-findings-session-tree-view.md +88 -0
  80. package/docs/ideas/implementation_plan_session_tree_view.md +238 -0
  81. package/package.json +2 -1
  82. package/spec/authoring-spec.json +16 -16
  83. package/spec/shape.schema.json +178 -0
  84. package/spec/workflow-tags.json +232 -47
  85. package/workflows/coding-task-workflow-agentic.json +491 -480
  86. package/workflows/mr-review-workflow.agentic.v2.json +5 -1
  87. package/workflows/wr.shaping.json +182 -0
  88. package/dist/console-ui/assets/index-3oXZ_A9m.js +0 -28
  89. package/dist/console-ui/assets/index-8dh0Psu-.css +0 -1
  90. package/dist/infrastructure/session/DashboardHeartbeat.d.ts +0 -8
  91. package/dist/infrastructure/session/DashboardHeartbeat.js +0 -39
  92. package/dist/infrastructure/session/DashboardLockRelease.d.ts +0 -2
  93. package/dist/infrastructure/session/DashboardLockRelease.js +0 -29
  94. package/dist/infrastructure/session/HttpServer.d.ts +0 -60
  95. package/dist/infrastructure/session/HttpServer.js +0 -912
  96. package/workflows/coding-task-workflow-agentic.lean.v2.json +0 -648
  97. package/workflows/coding-task-workflow-agentic.v2.json +0 -324
@@ -54,9 +54,6 @@ const CONFIG_FILE_TEMPLATE = `{
54
54
 
55
55
  "CACHE_TTL": "300000",
56
56
  "WORKRAIL_WORKFLOWS_DIR": "",
57
- "WORKRAIL_DISABLE_UNIFIED_DASHBOARD": "0",
58
- "WORKRAIL_DISABLE_AUTO_OPEN": "0",
59
- "WORKRAIL_DASHBOARD_PORT": "3456",
60
57
 
61
58
  "WORKRAIL_ENABLE_SESSION_TOOLS": "true",
62
59
  "WORKRAIL_ENABLE_EXPERIMENTAL_WORKFLOWS": "false",
@@ -330,6 +330,7 @@ program
330
330
  triggerRouter: handle.router,
331
331
  serverVersion: pkg.version,
332
332
  workflowService,
333
+ steerRegistry: handle.steerRegistry,
333
334
  });
334
335
  let consoleHandle = null;
335
336
  if (consoleResult.kind === 'ok') {
@@ -810,27 +811,28 @@ runCommand
810
811
  })), allSucceeded: false };
811
812
  },
812
813
  getAgentResult: async (sessionHandle) => {
814
+ const emptyResult = { recapMarkdown: null, artifacts: [] };
813
815
  try {
814
816
  const sessionUrl = `http://127.0.0.1:${port}/api/v2/sessions/${encodeURIComponent(sessionHandle)}`;
815
817
  const sessionRes = await globalThis.fetch(sessionUrl, { signal: AbortSignal.timeout(30000) });
816
818
  if (!sessionRes.ok) {
817
819
  process.stderr.write(`[WARN coord:reason=http_error status=${sessionRes.status} handle=${sessionHandle.slice(0, 16)}] getAgentResult: session fetch returned HTTP ${sessionRes.status}\n`);
818
- return null;
820
+ return emptyResult;
819
821
  }
820
822
  const sessionBody = await sessionRes.json();
821
823
  if (sessionBody['success'] !== true) {
822
824
  process.stderr.write(`[WARN coord:reason=api_error handle=${sessionHandle.slice(0, 16)}] getAgentResult: session API returned success=false\n`);
823
- return null;
825
+ return emptyResult;
824
826
  }
825
827
  const data = sessionBody['data'];
826
828
  if (!data) {
827
829
  process.stderr.write(`[WARN coord:reason=no_data handle=${sessionHandle.slice(0, 16)}] getAgentResult: session response missing data field\n`);
828
- return null;
830
+ return emptyResult;
829
831
  }
830
832
  const runs = data['runs'];
831
833
  if (!Array.isArray(runs) || runs.length === 0) {
832
834
  process.stderr.write(`[WARN coord:reason=no_runs handle=${sessionHandle.slice(0, 16)}] getAgentResult: session has no runs\n`);
833
- return null;
835
+ return emptyResult;
834
836
  }
835
837
  const firstRun = runs[0];
836
838
  const tipNodeId = typeof firstRun['preferredTipNodeId'] === 'string'
@@ -838,34 +840,57 @@ runCommand
838
840
  : null;
839
841
  if (!tipNodeId) {
840
842
  process.stderr.write(`[WARN coord:reason=no_tip_node handle=${sessionHandle.slice(0, 16)}] getAgentResult: session run has no preferredTipNodeId\n`);
841
- return null;
843
+ return emptyResult;
842
844
  }
843
- const nodeUrl = `http://127.0.0.1:${port}/api/v2/sessions/${encodeURIComponent(sessionHandle)}/nodes/${encodeURIComponent(tipNodeId)}`;
844
- const nodeRes = await globalThis.fetch(nodeUrl, { signal: AbortSignal.timeout(30000) });
845
- if (!nodeRes.ok) {
846
- process.stderr.write(`[WARN coord:reason=node_http_error status=${nodeRes.status} handle=${sessionHandle.slice(0, 16)} node=${tipNodeId.slice(0, 16)}] getAgentResult: node fetch returned HTTP ${nodeRes.status}\n`);
847
- return null;
848
- }
849
- const nodeBody = await nodeRes.json();
850
- if (nodeBody['success'] !== true) {
851
- process.stderr.write(`[WARN coord:reason=node_api_error handle=${sessionHandle.slice(0, 16)} node=${tipNodeId.slice(0, 16)}] getAgentResult: node API returned success=false\n`);
852
- return null;
853
- }
854
- const nodeData = nodeBody['data'];
855
- if (!nodeData) {
856
- process.stderr.write(`[WARN coord:reason=no_node_data handle=${sessionHandle.slice(0, 16)} node=${tipNodeId.slice(0, 16)}] getAgentResult: node response missing data field\n`);
857
- return null;
858
- }
859
- const recap = typeof nodeData['recapMarkdown'] === 'string' ? nodeData['recapMarkdown'] : null;
860
- if (recap === null) {
861
- process.stderr.write(`[WARN coord:reason=no_recap handle=${sessionHandle.slice(0, 16)} node=${tipNodeId.slice(0, 16)}] getAgentResult: node has no recapMarkdown\n`);
845
+ const allNodes = Array.isArray(firstRun['nodes'])
846
+ ? firstRun['nodes']
847
+ : [];
848
+ const allNodeIds = allNodes
849
+ .map((n) => (typeof n['nodeId'] === 'string' ? n['nodeId'] : null))
850
+ .filter((id) => id !== null);
851
+ const nodeIdsToFetch = allNodeIds.length > 0
852
+ ? allNodeIds
853
+ : [tipNodeId];
854
+ const baseNodeUrl = `http://127.0.0.1:${port}/api/v2/sessions/${encodeURIComponent(sessionHandle)}/nodes/`;
855
+ let recap = null;
856
+ const collectedArtifacts = [];
857
+ for (const nodeId of nodeIdsToFetch) {
858
+ try {
859
+ const nodeRes = await globalThis.fetch(baseNodeUrl + encodeURIComponent(nodeId), { signal: AbortSignal.timeout(30000) });
860
+ if (!nodeRes.ok) {
861
+ process.stderr.write(`[WARN coord:reason=node_http_error status=${nodeRes.status} handle=${sessionHandle.slice(0, 16)} node=${nodeId.slice(0, 16)}] getAgentResult: node fetch returned HTTP ${nodeRes.status}\n`);
862
+ continue;
863
+ }
864
+ const nodeBody = await nodeRes.json();
865
+ if (nodeBody['success'] !== true) {
866
+ process.stderr.write(`[WARN coord:reason=node_api_error handle=${sessionHandle.slice(0, 16)} node=${nodeId.slice(0, 16)}] getAgentResult: node API returned success=false\n`);
867
+ continue;
868
+ }
869
+ const nodeData = nodeBody['data'];
870
+ if (!nodeData)
871
+ continue;
872
+ if (nodeId === tipNodeId) {
873
+ recap = typeof nodeData['recapMarkdown'] === 'string' ? nodeData['recapMarkdown'] : null;
874
+ if (recap === null) {
875
+ process.stderr.write(`[WARN coord:reason=no_recap handle=${sessionHandle.slice(0, 16)} node=${nodeId.slice(0, 16)}] getAgentResult: tip node has no recapMarkdown\n`);
876
+ }
877
+ }
878
+ const nodeArtifacts = nodeData['artifacts'];
879
+ if (Array.isArray(nodeArtifacts) && nodeArtifacts.length > 0) {
880
+ collectedArtifacts.push(...nodeArtifacts);
881
+ }
882
+ }
883
+ catch (nodeErr) {
884
+ const msg = nodeErr instanceof Error ? nodeErr.message : String(nodeErr);
885
+ process.stderr.write(`[WARN coord:reason=node_exception handle=${sessionHandle.slice(0, 16)} node=${nodeId.slice(0, 16)}] getAgentResult: ${msg}\n`);
886
+ }
862
887
  }
863
- return recap;
888
+ return { recapMarkdown: recap, artifacts: collectedArtifacts };
864
889
  }
865
890
  catch (e) {
866
891
  const msg = e instanceof Error ? e.message : String(e);
867
892
  process.stderr.write(`[WARN coord:reason=exception handle=${sessionHandle.slice(0, 16)}] getAgentResult: ${msg}\n`);
868
- return null;
893
+ return emptyResult;
869
894
  }
870
895
  },
871
896
  listOpenPRs: async (workspace) => {
@@ -897,6 +922,13 @@ runCommand
897
922
  writeFile: async (filePath, content) => {
898
923
  await fs_1.default.promises.writeFile(filePath, content, 'utf-8');
899
924
  },
925
+ readFile: (filePath) => fs_1.default.promises.readFile(filePath, 'utf-8'),
926
+ appendFile: (filePath, content) => fs_1.default.promises.appendFile(filePath, content, 'utf-8'),
927
+ mkdir: (dirPath, opts) => fs_1.default.promises.mkdir(dirPath, opts),
928
+ homedir: os_1.default.homedir,
929
+ joinPath: path_1.default.join,
930
+ nowIso: () => new Date().toISOString(),
931
+ generateId: () => (0, crypto_1.randomUUID)(),
900
932
  stderr: (line) => process.stderr.write(line + '\n'),
901
933
  now: () => Date.now(),
902
934
  port,
package/dist/cli.js CHANGED
@@ -166,24 +166,6 @@ program
166
166
  });
167
167
  (0, interpret_result_js_1.interpretCliResult)(result, terminator);
168
168
  });
169
- program
170
- .command('cleanup')
171
- .description('Clean up orphaned workrail processes and free up ports')
172
- .option('-f, --force', 'Force cleanup without confirmation')
173
- .action(async (options) => {
174
- if (!options.force) {
175
- console.error('⚠️ This will terminate all workrail dashboard processes');
176
- console.error(' Press Ctrl+C to cancel, or wait 3 seconds to continue...');
177
- await new Promise((resolve) => setTimeout(resolve, 3000));
178
- }
179
- await (0, container_js_1.initializeContainer)({ runtimeMode: { kind: 'cli' } });
180
- const terminator = container_js_1.container.resolve(tokens_js_1.DI.Runtime.ProcessTerminator);
181
- const httpServer = container_js_1.container.resolve(tokens_js_1.DI.Infra.HttpServer);
182
- const result = await (0, index_js_1.executeCleanupCommand)({
183
- fullCleanup: () => httpServer.fullCleanup(),
184
- });
185
- (0, interpret_result_js_1.interpretCliResult)(result, terminator);
186
- });
187
169
  program
188
170
  .command('daemon')
189
171
  .description('Start the autonomous WorkRail daemon (trigger webhook server on port 3200)')
@@ -5,17 +5,6 @@ import type { ValidatedAppConfig } from '../errors/app-error.js';
5
5
  export type CacheTtlMs = Brand<number, 'CacheTtlMs'>;
6
6
  export type ProjectPath = Brand<string, 'ProjectPath'>;
7
7
  export type WorkflowDir = Brand<string, 'WorkflowDir'>;
8
- export type DashboardPort = Brand<number, 'DashboardPort'>;
9
- export type DashboardMode = {
10
- readonly kind: 'unified';
11
- } | {
12
- readonly kind: 'legacy';
13
- };
14
- export type BrowserBehavior = {
15
- readonly kind: 'auto_open';
16
- } | {
17
- readonly kind: 'manual';
18
- };
19
8
  export interface AppConfig {
20
9
  readonly cache: {
21
10
  readonly ttlMs: CacheTtlMs;
@@ -24,11 +13,6 @@ export interface AppConfig {
24
13
  readonly projectPath: ProjectPath;
25
14
  readonly workflowDir: WorkflowDir;
26
15
  };
27
- readonly dashboard: {
28
- readonly mode: DashboardMode;
29
- readonly browserBehavior: BrowserBehavior;
30
- readonly port: DashboardPort;
31
- };
32
16
  }
33
17
  export type ValidatedConfig = ValidatedAppConfig<AppConfig>;
34
18
  export interface LoadConfigOptions {
@@ -16,13 +16,6 @@ const EnvSchema = zod_1.z.object({
16
16
  .max(86400000, 'CACHE_TTL cannot exceed 24 hours (86400000ms)')
17
17
  .default(300000)),
18
18
  WORKRAIL_WORKFLOWS_DIR: zod_1.z.string().optional(),
19
- WORKRAIL_DISABLE_UNIFIED_DASHBOARD: zod_1.z.enum(['0', '1']).default('0'),
20
- WORKRAIL_DISABLE_AUTO_OPEN: zod_1.z.enum(['0', '1']).default('0'),
21
- WORKRAIL_DASHBOARD_PORT: zod_1.z
22
- .string()
23
- .optional()
24
- .transform((v) => (v === undefined ? undefined : Number(v)))
25
- .pipe(zod_1.z.number().int().min(1024, 'Port must be >= 1024').max(65535, 'Port must be <= 65535').default(3456)),
26
19
  });
27
20
  function loadConfig(options) {
28
21
  const parsed = EnvSchema.safeParse(options.env);
@@ -35,19 +28,12 @@ function createValidatedConfig(value) {
35
28
  return value;
36
29
  }
37
30
  function buildConfig(env, projectPath) {
38
- const dashboardMode = env.WORKRAIL_DISABLE_UNIFIED_DASHBOARD === '1' ? { kind: 'legacy' } : { kind: 'unified' };
39
- const browserBehavior = env.WORKRAIL_DISABLE_AUTO_OPEN === '1' ? { kind: 'manual' } : { kind: 'auto_open' };
40
31
  return {
41
32
  cache: { ttlMs: env.CACHE_TTL },
42
33
  paths: {
43
34
  projectPath: projectPath,
44
35
  workflowDir: (env.WORKRAIL_WORKFLOWS_DIR ?? projectPath),
45
36
  },
46
- dashboard: {
47
- mode: dashboardMode,
48
- browserBehavior,
49
- port: env.WORKRAIL_DASHBOARD_PORT,
50
- },
51
37
  };
52
38
  }
53
39
  function toConfigIssues(error) {
@@ -44,9 +44,6 @@ const result_js_1 = require("../runtime/result.js");
44
44
  const ALLOWED_CONFIG_FILE_KEYS = new Set([
45
45
  'CACHE_TTL',
46
46
  'WORKRAIL_WORKFLOWS_DIR',
47
- 'WORKRAIL_DISABLE_UNIFIED_DASHBOARD',
48
- 'WORKRAIL_DISABLE_AUTO_OPEN',
49
- 'WORKRAIL_DASHBOARD_PORT',
50
47
  'WORKRAIL_DEV',
51
48
  'WORKRAIL_ENABLE_SESSION_TOOLS',
52
49
  'WORKRAIL_ENABLE_EXPERIMENTAL_WORKFLOWS',