feat(workflow-executor): add HTTP server and WorkflowRunner scaffold#1500
Merged
matthv merged 14 commits intofeat/prd-214-setup-workflow-executor-packagefrom Mar 20, 2026
Conversation
Scra3
reviewed
Mar 19, 2026
|
|
||
| private async handleGetRun(ctx: Koa.Context): Promise<void> { | ||
| const { runId } = ctx.params; | ||
| const runStore = this.options.runStoreFactory.getRunStore(runId); |
Scra3
reviewed
Mar 19, 2026
Adds ExecutorHttpServer (Koa) with two routes: - GET /runs/:runId — reads records + steps from RunStore - POST /runs/:runId/trigger — delegates to WorkflowRunner.triggerPoll() WorkflowRunner is a concrete class (stub) aligned with spec section 4.1. Polling and execution dispatch will be implemented in a follow-up PR. fixes PRD-222 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
88ef7d5 to
12bc2be
Compare
Scra3
reviewed
Mar 19, 2026
| import type { RunStore } from '../ports/run-store'; | ||
|
|
||
| export interface RunStoreFactory { | ||
| getRunStore(runId: string): RunStore | null; |
- Rename getRunStore → buildRunStore (Scra3) - Rename workflow-runner.ts → runner.ts (Scra3) - Fix stop() race condition: move this.server = null inside close callback (Macroscope) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Coverage Impact Unable to calculate total coverage change because base branch coverage was not found. Modified Files with Diff Coverage (6) 🤖 Increase coverage with AI coding...🚦 See full report on Qlty Cloud » 🛟 Help
|
Member
Author
|
Addressed all review feedback:
|
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Scra3
reviewed
Mar 19, 2026
| import type { RunStore } from '../ports/run-store'; | ||
|
|
||
| export interface RunStoreFactory { | ||
| buildRunStore(runId: string): RunStore | null; |
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Guard against double start() in Runner (Macroscope)
- Handle listen() error in start() via server.on('error', reject) (Macroscope)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Return 400 when runId is missing on both GET /runs/:runId and POST /runs/:runId/trigger. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Factory always builds a RunStore for the given runId. runId validation (400) is handled before calling buildRunStore. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Member
Author
|
Final summary of all fixes applied: Renames:
Bug fixes:
Validation:
Interface change:
Docs:
|
RunStoreFactory is not HTTP-specific — it's also used by the Runner. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tests start/stop lifecycle, HTTP server wiring, double-start guard, restart after stop, and triggerPoll stub. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… types
- Add Koa error middleware to ExecutorHttpServer (returns structured JSON on errors)
- Use server.once('error') instead of .on() to avoid stale listener after start
- Fix stop(): only null this.server on successful close, not on error
- Fix Runner.start(): use !== undefined check for httpPort (avoids falsy 0 bug)
- Fix Runner.start(): assign this.httpServer only after server.start() resolves
- Make ConditionStepExecutionData.executionResult optional (matches runtime behavior)
- Add GET /runs/:runId error path test (500 + structured body)
- Assert buildRunStore called with correct runId in GET test
- Assert response.body.error in trigger error test
- Strengthen Runner constructor assertion to verify full config object
- Remove module-level shared mock state in executor-http-server tests
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…onResult as required Out of scope for this PR — will be addressed separately. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tly to RunStore methods RunStoreFactory was a superfluous abstraction (YAGNI) — its only role was to scope a RunStore to a runId, but all callers already know their runId. Adding runId directly to RunStore.getStepExecutions/saveStepExecution removes one level of indirection, one file, and simplifies RunnerConfig. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Scra3
approved these changes
Mar 19, 2026
613ec1b
into
feat/prd-214-setup-workflow-executor-package
30 checks passed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
ExecutorHttpServer(Koa) with two routes:GET /runs/:runId— reads records + steps fromRunStoreFactoryPOST /runs/:runId/trigger— delegates toWorkflowRunner.triggerPoll()WorkflowRunnerclass (stub) as the main entry point, aligned with spec section 4.1. Starts HTTP server onstart()ifhttpPortis configuredRunStoreFactoryinterface to resolverunId → RunStoreTest plan
fixes PRD-222
🤖 Generated with Claude Code
Note
Add Koa HTTP server and
WorkflowRunnerscaffold to workflow-executorExecutorHttpServer, a Koa-based HTTP server withGET /runs/:runId(returns step executions or 404) andPOST /runs/:runId/trigger(invokesWorkflowRunner.triggerPoll).WorkflowRunner, which manages the HTTP server lifecycle viastart()/stop();triggerPollis currently a no-op stub.RunStoreFactoryinterface for looking up aRunStoreby run ID.handleTriggerdoes not catch errors fromtriggerPoll, so failures propagate as unhandled 500s via Koa's default error handler.Changes since #1500 opened
RunStoreFactory.getRunStoremethod tobuildRunStoreand updated all call sites inExecutorHttpServer.handleGetRunhandler and test files to use the new method name [a78e559]workflow-runner.tstorunner.tsand updated import paths from'../workflow-runner'and'../../src/workflow-runner'to'../runner'and'../../src/runner'respectively acrossExecutorHttpServer, the package index exports, and test files [a78e559]ExecutorHttpServer.stopmethod to defer settingthis.servertonulluntil inside the HTTP server close callback, ensuring the server reference remains non-null during the asynchronous shutdown process [a78e559]WorkflowRunnerclass toRunnerandWorkflowRunnerConfiginterface toRunnerConfigthroughout theworkflow-executorpackage [0d6abe8]ExecutorHttpServer.startmethod to reject the promise when the underlying HTTP server emits an error event during startup, and added guard logic toRunner.startmethod to prevent creating multipleExecutorHttpServerinstances whenhttpPortis configured [a7f17f2]RunStoreFactory.buildRunStorereturn type and corresponding null-check logic inExecutorHttpServer.handleGetRun[afd0743]RunStoreFactorycontract [afd0743]run-store-factory.tsmodule fromsrc/http/tosrc/directory and updated all import paths [40d44d1]Runnerclass HTTP server lifecycle management [42c459d]Runner.triggerPollmethod [42c459d]RunStoretype in therun-store-factorymodule [d2d4ff5]ExecutorHttpServerand removed explicit parameter validation from route handlers [2ed53b6]Runner.startto support HTTP server initialization on port 0 and fixedExecutorHttpServer.stopto preserve server instance on close failure [2ed53b6]executionResultoptional inConditionStepExecutionDatainterface [2ed53b6]executionResultproperty required inConditionStepExecutionDatainterface [fe50017]RunnerConfiginterface structure by replacing nestedportsobject with top-levelagentPortandworkflowPortproperties [19926eb]RunStoreinterface methods to acceptrunIdas a parameter [b6383ef]RunStoreFactoryinterface and its exports [b6383ef]ExecutorHttpServerto acceptRunStoreinstead ofRunStoreFactory[b6383ef]RunnerConfigto acceptRunStoreinstead ofRunStoreFactory[b6383ef]runIdtoRunStoremethods [b6383ef]RunStoreAPI signatures [b6383ef]📊 Macroscope summarized 12bc2be. 5 files reviewed, 2 issues evaluated, 0 issues filtered, 1 comment posted
🗂️ Filtered Issues