Found while completing the flow-model migration (ConductionNL/hydra#529).
The gap
hermiq contributes two node types to OpenRegister's flow engine. Their coverage is asymmetric:
| node type |
unit |
executed through the engine |
hermiq.agent-step |
✅ |
✅ openregister/tests/newman/openregister-flow-engine.postman_collection.json |
hermiq.workload-step |
✅ tests/Unit/Flow/HermiqWorkloadNodeTest.php |
❌ never |
Searched: no integration test, no e2e spec, not in the newman flow-engine collection. Its only non-source references are the ExApp README, a docker-compose file, a deploy script, StageDispatchService.php, and an openspec proposal.
So "hermiq contributes working nodes to OR's engine" is measured for agent-step and asserted for workload-step. Given that hydra's dispatch and applier flows both depend on it, that is the weaker half carrying the more consequential work.
Why it was skipped, and why this is not a simple copy of the agent-step case
agent-step is testable in the newman suite because it is an API call with a parseable answer. The suite authors a flow, runs it with sync: true, and asserts on the result.
workload-step is a different shape. Its contract from lib/Flow/HermiqWorkloadNode.php:
required : repo · ref · command (array)
optional : output (default "stage") · owner · credentialId · pushCredentialId
timeoutMs · toolRepo · toolRef · push · scope
It clones a repository and executes a command inside the ExApp sidecar. That needs a reachable repo, a running sidecar, and a credential path — real side effects rather than a request/response pair. That is presumably why it was left, and it is a legitimate reason, not an oversight.
What a first test could look like
The cheapest honest coverage is not a full stage run. Two smaller assertions each prove something that is currently unproven:
- The node resolves and is dispatched at all. A flow with a
hermiq.workload-step whose repo/ref point at something trivially reachable, asserting the run reaches that transition and produces an item under the configured output key (default stage). Even a failing workload proves the engine resolved the type, dispatched it, and routed the result — which is exactly what has never been demonstrated.
- The required-field guard fires.
validate() throws UnexpectedValueException on a missing repo, ref or command. A flow omitting one should fail the run rather than pass through silently. This needs no sidecar at all and is worth having on its own.
⚠️ Assert on itemsIn/itemsOut per transition, not on the run's status. A flow reporting completed with itemsOut: 0 everywhere is a pass-through, and that is precisely how the whole hydra pipeline looked healthy while nine of twelve flows had never run. The per-transition counts are the only thing that distinguishes work from a heartbeat.
⚠️ sync: true on the run endpoint is what makes any of this testable. Async needs a worker, and every dev stack has backgroundjobs_mode=cron with nothing calling cron.php, so queue-and-poll times out against a perfectly healthy engine.
Context
This is the last unproven piece of the hermiq→OpenRegister node contribution. The rest is now verified: both types are registered in FlowNodeRegistry, all 12 node types hydra's flows reference resolve against the 22 registered, and the engine demonstrably executes (openregister#... — Hydra lock reaper runs every 10 minutes and its per-transition log shows types resolving and items moving).
Found while completing the flow-model migration (ConductionNL/hydra#529).
The gap
hermiq contributes two node types to OpenRegister's flow engine. Their coverage is asymmetric:
hermiq.agent-stepopenregister/tests/newman/openregister-flow-engine.postman_collection.jsonhermiq.workload-steptests/Unit/Flow/HermiqWorkloadNodeTest.phpSearched: no integration test, no e2e spec, not in the newman flow-engine collection. Its only non-source references are the ExApp README, a docker-compose file, a deploy script,
StageDispatchService.php, and an openspec proposal.So "hermiq contributes working nodes to OR's engine" is measured for
agent-stepand asserted forworkload-step. Given that hydra's dispatch and applier flows both depend on it, that is the weaker half carrying the more consequential work.Why it was skipped, and why this is not a simple copy of the agent-step case
agent-stepis testable in the newman suite because it is an API call with a parseable answer. The suite authors a flow, runs it withsync: true, and asserts on the result.workload-stepis a different shape. Its contract fromlib/Flow/HermiqWorkloadNode.php:It clones a repository and executes a command inside the ExApp sidecar. That needs a reachable repo, a running sidecar, and a credential path — real side effects rather than a request/response pair. That is presumably why it was left, and it is a legitimate reason, not an oversight.
What a first test could look like
The cheapest honest coverage is not a full stage run. Two smaller assertions each prove something that is currently unproven:
hermiq.workload-stepwhoserepo/refpoint at something trivially reachable, asserting the run reaches that transition and produces an item under the configuredoutputkey (defaultstage). Even a failing workload proves the engine resolved the type, dispatched it, and routed the result — which is exactly what has never been demonstrated.validate()throwsUnexpectedValueExceptionon a missingrepo,reforcommand. A flow omitting one should fail the run rather than pass through silently. This needs no sidecar at all and is worth having on its own.itemsIn/itemsOutper transition, not on the run'sstatus. A flow reportingcompletedwithitemsOut: 0everywhere is a pass-through, and that is precisely how the whole hydra pipeline looked healthy while nine of twelve flows had never run. The per-transition counts are the only thing that distinguishes work from a heartbeat.sync: trueon the run endpoint is what makes any of this testable. Async needs a worker, and every dev stack hasbackgroundjobs_mode=cronwith nothing callingcron.php, so queue-and-poll times out against a perfectly healthy engine.Context
This is the last unproven piece of the hermiq→OpenRegister node contribution. The rest is now verified: both types are registered in
FlowNodeRegistry, all 12 node types hydra's flows reference resolve against the 22 registered, and the engine demonstrably executes (openregister#... —Hydra lock reaperruns every 10 minutes and its per-transition log shows types resolving and items moving).