Skill: Review Chaining Engine
Purpose
This skill guides Copilot when reviewing or modifying the Chaining Engine of OpenAEV.
It covers the full feature: step lifecycle, condition evaluation, queue processing, state management,
timeout handling, scope resolution, and the AOP bridge to inject lifecycle.
When to use this skill
- Reviewing a PR that touches chaining code (API, service, model, scheduler)
- Adding a new Step action type (implementing
ActionStep)
- Adding a new Condition type (extending
ConditionType enum)
- Modifying the Global/Local State synchronization logic
- Adding or modifying queue processing (ready queue, update queue, delay queue)
- Modifying timeout or scope logic
- Adding new endpoints that need
@WorkflowUpdateEvent annotation
- Debugging step execution flow or queue processing
Review Checklist
1. Step Lifecycle Integrity
2. Workflow Lifecycle
3. Queue & Scheduling
4. State Management
5. Conditions
6. External Update Bridge (AOP)
7. Scope
8. API Layer
9. Error Handling
Step-by-step: Add a new Step action type
- Create the class — implement
ActionStep interface in io.openaev.api.chaining.
- Implement all methods —
create(), ready(), run(), update(), end().
- Register in factory — add to
StepService.factoryAction() switch/map.
- Add enum value — extend
StepActionClass with the new action class name.
- Add tests — unit test each lifecycle method; integration test the full flow.
Step-by-step: Add a new Condition type
- Add enum value — extend
ConditionType with the new type.
- Update evaluation — add logic in
ConditionUtils for the new type.
- Update factory (if special) — add a factory method in
ConditionFactory.
- Update mapper — extend
ConditionMapper if the new type has special serialization.
- Write tests — test condition evaluation in isolation and in a workflow context.
Step-by-step: Add a new API endpoint
- Add the method in the relevant
*Api.java file.
- Add
@AccessControl with appropriate Action and ResourceType.
- Add
@Transactional(rollbackFor = Exception.class) for writes.
- Create input/output DTOs in
io.openaev.api.chaining.dto.
- Add static mapper methods (not MapStruct annotations).
- Implement service logic in
io.openaev.service.chaining.
- Write integration test following existing patterns (
StepApiTest, ConditionApiTest, WorkflowApiTest).
Key Invariants (Never Break)
- ✅ Endpoint access is enforced via
@AccessControl (including EE validation where required)
- ✅ Conditions evaluated before step execution
- ✅ Global state updated before local state propagation
- ✅ Step status follows TEMPLATE → READY → RUN → END
- ✅ Workflow ended check before any step execution
- ✅ Queue interactions go only through
QueueChainingService
- ✅ Time delays use
StepDelayQueueService
- ✅ Static mapper methods for entity ↔ DTO conversions
- ✅
@WorkflowUpdateEvent on inject-mutating methods
- ✅ Timeout force-completes all active steps and clears delay queue
Test Fixtures & Composers
| Class |
Purpose |
WorkflowFixture |
Creates test workflow entities |
WorkflowComposer |
Builds complex workflow test scenarios |
ConditionComposer |
Builds condition trees for tests |
StepComposer |
Builds Step tests |
Key Test Classes
| Test |
Scope |
ChainingIntegrationTest |
End-to-end chaining flow |
StepServiceTest / StepServiceIntegrationTest |
Step lifecycle |
StepServiceScenarioIntegrationTest |
Scenario-based chaining |
ConditionServiceTest |
Condition CRUD and evaluation |
WorkflowServiceTest |
Workflow CRUD and configuration |
WorkflowStateServiceTest |
State sync and propagation |
StepEventServiceTest |
Queue event handling |
QueueChainingServiceTest |
Queue management |
ScopeServiceTest |
Scope resolution |
WorkflowEndServiceTest / WorkflowTimeoutIntegrationTest |
Timeout handling |
StepDelayQueueServiceTest / StepDelayQueueIntegrationTest |
Delay queue |
StepApiTest / ConditionApiTest / WorkflowApiTest |
API layer |
Useful Links
1---2name: review-chaining-engine3description: Skill: Review Chaining Engine4---5# Skill: Review Chaining Engine67## Purpose89This skill guides Copilot when reviewing or modifying the **Chaining Engine** of OpenAEV.10It covers the full feature: step lifecycle, condition evaluation, queue processing, state management,11timeout handling, scope resolution, and the AOP bridge to inject lifecycle.1213---1415## When to use this skill1617- Reviewing a PR that touches chaining code (API, service, model, scheduler)18- Adding a new **Step action type** (implementing `ActionStep`)19- Adding a new **Condition type** (extending `ConditionType` enum)20- Modifying the **Global/Local State** synchronization logic21- Adding or modifying **queue processing** (ready queue, update queue, delay queue)22- Modifying **timeout** or **scope** logic23- Adding new endpoints that need `@WorkflowUpdateEvent` annotation24- Debugging step execution flow or queue processing2526---2728## Review Checklist2930### 1. Step Lifecycle Integrity31- [ ] Status transitions follow: `TEMPLATE` → `READY` → `RUN` → `END`32- [ ] TEMPLATE steps are never executed directly — always cloned to READY33- [ ] Before execution, `workflowService.isWorkflowEnded()` is checked34- [ ] Active steps are identified by `StepStatus.READY` or `StepStatus.RUN`3536### 2. Workflow Lifecycle37- [ ] Workflow status transitions: `TEMPLATE` → `RUN` → `END`/`STOP`38- [ ] Timeout handling doesn't leave orphaned READY/RUN steps39- [ ] Duplication correctly copies templates and conditions4041### 3. Queue & Scheduling42- [ ] All queue publishing goes through `QueueChainingService`43- [ ] No direct RabbitMQ calls from services44- [ ] Time delays use `StepDelayQueueService`, never `Thread.sleep()`45- [ ] Quartz jobs handle concurrent execution correctly (`@DisallowConcurrentExecution`)4647### 4. State Management48- [ ] Global state updated via `WorkflowStateService.syncState()` BEFORE propagation49- [ ] Local state propagation uses `propagateToLocalStates()`50- [ ] State entries are properly serialized/deserialized (Gson)5152### 5. Conditions53- [ ] Conditions evaluated BEFORE step execution54- [ ] Tree structure maintained: root (AND/OR) + leaf conditions55- [ ] `DEPEND_ON` conditions use `ConditionFactory.dependOn()`56- [ ] `MAPPER` conditions properly resolve from LOCAL or GLOBAL pool57- [ ] Conditions linked to steps via `ConditionStep` entity5859### 6. External Update Bridge (AOP)60- [ ] Methods that mutate inject status are annotated with `@WorkflowUpdateEvent`61- [ ] SpEL expressions correctly extract inject/expectation IDs62- [ ] Exactly one of `injectId`, `injectIds`, or `expectationIds` is specified per annotation6364### 7. Scope65- [ ] Allowlist rules are applied first, then denylist exclusions66- [ ] Both individual assets and asset groups are handled67- [ ] IP address matching uses `IpAddressUtils`6869### 8. API Layer70- [ ] All endpoints have `@AccessControl` with correct `Action` and `ResourceType`71- [ ] DTOs are returned (never entities)72- [ ] Static mapper methods used (not MapStruct annotation processing)73- [ ] `@Transactional(rollbackFor = Exception.class)` on write operations74- [ ] Proper HTTP status codes (201 for creation, 204 for deletion)7576### 9. Error Handling77- [ ] `ChainingException` used for chaining-specific errors78- [ ] No swallowed exceptions in queue consumers (at minimum logged)7980---8182## Step-by-step: Add a new Step action type83841. **Create the class** — implement `ActionStep` interface in `io.openaev.api.chaining`.852. **Implement all methods** — `create()`, `ready()`, `run()`, `update()`, `end()`.863. **Register in factory** — add to `StepService.factoryAction()` switch/map.874. **Add enum value** — extend `StepActionClass` with the new action class name.885. **Add tests** — unit test each lifecycle method; integration test the full flow.8990---9192## Step-by-step: Add a new Condition type93941. **Add enum value** — extend `ConditionType` with the new type.952. **Update evaluation** — add logic in `ConditionUtils` for the new type.963. **Update factory (if special)** — add a factory method in `ConditionFactory`.974. **Update mapper** — extend `ConditionMapper` if the new type has special serialization.985. **Write tests** — test condition evaluation in isolation and in a workflow context.99100---101102## Step-by-step: Add a new API endpoint1031041. Add the method in the relevant `*Api.java` file.1052. Add `@AccessControl` with appropriate `Action` and `ResourceType`.1063. Add `@Transactional(rollbackFor = Exception.class)` for writes.1074. Create input/output DTOs in `io.openaev.api.chaining.dto`.1085. Add static mapper methods (not MapStruct annotations).1096. Implement service logic in `io.openaev.service.chaining`.1107. Write integration test following existing patterns (`StepApiTest`, `ConditionApiTest`, `WorkflowApiTest`).111112---113114## Key Invariants (Never Break)115116- ✅ Endpoint access is enforced via `@AccessControl` (including EE validation where required)117- ✅ Conditions evaluated before step execution118- ✅ Global state updated before local state propagation119- ✅ Step status follows TEMPLATE → READY → RUN → END120- ✅ Workflow ended check before any step execution121- ✅ Queue interactions go only through `QueueChainingService`122- ✅ Time delays use `StepDelayQueueService`123- ✅ Static mapper methods for entity ↔ DTO conversions124- ✅ `@WorkflowUpdateEvent` on inject-mutating methods125- ✅ Timeout force-completes all active steps and clears delay queue126127---128129## Test Fixtures & Composers130131| Class | Purpose |132|---------------------|----------------------------------------|133| `WorkflowFixture` | Creates test workflow entities |134| `WorkflowComposer` | Builds complex workflow test scenarios |135| `ConditionComposer` | Builds condition trees for tests |136| `StepComposer` | Builds Step tests |137138## Key Test Classes139140| Test | Scope |141|---|---|142| `ChainingIntegrationTest` | End-to-end chaining flow |143| `StepServiceTest` / `StepServiceIntegrationTest` | Step lifecycle |144| `StepServiceScenarioIntegrationTest` | Scenario-based chaining |145| `ConditionServiceTest` | Condition CRUD and evaluation |146| `WorkflowServiceTest` | Workflow CRUD and configuration |147| `WorkflowStateServiceTest` | State sync and propagation |148| `StepEventServiceTest` | Queue event handling |149| `QueueChainingServiceTest` | Queue management |150| `ScopeServiceTest` | Scope resolution |151| `WorkflowEndServiceTest` / `WorkflowTimeoutIntegrationTest` | Timeout handling |152| `StepDelayQueueServiceTest` / `StepDelayQueueIntegrationTest` | Delay queue |153| `StepApiTest` / `ConditionApiTest` / `WorkflowApiTest` | API layer |154155---156157## Useful Links158159- [Chaining PRs](https://github.com/OpenAEV-Platform/openaev/pulls?q=is%3Apr+chaining+draft%3Afalse)160- Instructions: [chaining-engine.instructions.md](../../instructions/chaining-engine.instructions.md)