# Init Execute Async Resume Implementation Plan > **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. **Goal:** Make `/api/v1/init/tasks/{taskId}/execute` return immediately after accepting work, then run init steps in the background and resume from the first non-`SUCCESS` step on retry. **Architecture:** Keep the existing task table and step table as the source of truth. Split `InitService.executeTask` into an accept-and-dispatch path plus a background execution path, and use existing step statuses to determine where to resume. Add a lightweight in-process guard so one `taskId` cannot be started twice concurrently in the same application instance. **Tech Stack:** Spring Boot service/controller layer, Java concurrency utilities, MyBatis-style repositories already present in the module, JUnit 5 --- ### Task 1: Lock down current behavior with service tests **Files:** - Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/service/InitServiceTest.java` - Test: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/service/InitServiceTest.java` **Step 1: Write the failing tests** Add tests that assert: - `executeTask(taskId)` returns before a deliberately blocking executor finishes all steps - retry skips steps already marked `SUCCESS` and resumes from the first `FAILED` step - residual `RUNNING` steps are treated as the resume point on retry - duplicate execute calls for the same running task do not launch a second execution **Step 2: Run tests to verify they fail** Run: `mvn -q -Dtest=InitServiceTest#shouldAcceptTaskExecutionAsynchronously,InitServiceTest#shouldResumeFromFirstFailedStepOnRetry,InitServiceTest#shouldResumeFromResidualRunningStep,InitServiceTest#shouldNotDispatchDuplicateBackgroundExecutionForSameTask test` Expected: FAIL because execution is still synchronous and always starts from step 1. **Step 3: Write minimal test scaffolding** Extend the in-memory executor/repository helpers in the test file so they can: - block on a latch or sleep - count executed step codes - fail a chosen step once and succeed on retry Do not change production code in this step. **Step 4: Run tests to verify RED is stable** Run: `mvn -q -Dtest=InitServiceTest#shouldAcceptTaskExecutionAsynchronously,InitServiceTest#shouldResumeFromFirstFailedStepOnRetry,InitServiceTest#shouldResumeFromResidualRunningStep,InitServiceTest#shouldNotDispatchDuplicateBackgroundExecutionForSameTask test` Expected: FAIL with assertion mismatches that prove the new behavior is not implemented yet. **Step 5: Commit** Skip commit in the current dirty workspace per user instruction. ### Task 2: Introduce async dispatch in `InitService` **Files:** - Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/service/InitService.java` - Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/service/InitServiceTest.java` **Step 1: Implement minimal async acceptance path** Refactor `InitService` so `executeTask(taskId)`: - loads task and steps - returns a snapshot response quickly - submits real work to a background executor Use a small in-process dispatcher owned by `InitService`: - `ExecutorService` or equivalent - active-task map keyed by `taskId` **Step 2: Keep the real execution logic in a dedicated method** Create a private method such as `executeTaskInBackground(taskId)` that: - reloads task and steps from repository - updates statuses - runs steps serially - persists each step result immediately - updates final task status **Step 3: Run focused tests** Run: `mvn -q -Dtest=InitServiceTest#shouldAcceptTaskExecutionAsynchronously,InitServiceTest#shouldNotDispatchDuplicateBackgroundExecutionForSameTask test` Expected: PASS **Step 4: Refactor for readability** Extract helpers only if needed: - build response snapshot - mark task running - remove active-task entry in `finally` Do not add extra features. **Step 5: Commit** Skip commit in the current dirty workspace per user instruction. ### Task 3: Implement resume-from-first-non-success semantics **Files:** - Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/service/InitService.java` - Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/service/InitServiceTest.java` **Step 1: Implement step selection logic** Before running steps in the background: - convert residual `RUNNING` steps to `FAILED` - skip every step already marked `SUCCESS` - start execution at the first non-`SUCCESS` step Preserve current semantics after the resume point: - mark current step `RUNNING` - on success mark `SUCCESS` - on failure mark `FAILED` and stop **Step 2: Preserve response counters** Ensure `successSteps` in `InitTaskExecuteResponse` reflects the current number of successful steps, including successes from earlier runs. **Step 3: Run focused tests** Run: `mvn -q -Dtest=InitServiceTest#shouldResumeFromFirstFailedStepOnRetry,InitServiceTest#shouldResumeFromResidualRunningStep test` Expected: PASS **Step 4: Run the earlier async tests again** Run: `mvn -q -Dtest=InitServiceTest#shouldAcceptTaskExecutionAsynchronously,InitServiceTest#shouldNotDispatchDuplicateBackgroundExecutionForSameTask,InitServiceTest#shouldResumeFromFirstFailedStepOnRetry,InitServiceTest#shouldResumeFromResidualRunningStep test` Expected: PASS **Step 5: Commit** Skip commit in the current dirty workspace per user instruction. ### Task 4: Align controller and API-facing semantics **Files:** - Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/controller/InitInternalController.java` - Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/dto/InitTaskExecuteResponse.java` - Modify: `/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/service/InitServiceTest.java` **Step 1: Make the API comments and DTO semantics match async behavior** Update JavaDoc/comments so they describe: - execute endpoint only accepts and starts background work - polling should use existing detail/step/log APIs If needed, add a field only if tests prove it is necessary. Prefer reusing the current DTO unchanged. **Step 2: Run focused verification** Run: `mvn -q -Dtest=InitServiceTest test` Expected: PASS for all service tests, including the pre-existing create/query/execute cases. **Step 3: Review the controller surface** Check that: - route path stays unchanged - response wrapper stays unchanged - no new endpoint is introduced unnecessarily **Step 4: Commit** Skip commit in the current dirty workspace per user instruction. ### Task 5: Final verification **Files:** - Verify only **Step 1: Run init service tests** Run: `mvn -q -Dtest=InitServiceTest test` Expected: PASS **Step 2: Run init executor regression tests touched by earlier behavior changes** Run: `mvn -q -Dtest=ConfigurableInitStepExecutorTest#shouldInjectDatabaseCredentialsWhenExecutingStandardDbApplyCommand,ConfigurableInitStepExecutorTest#shouldExposeStandardInitScriptTemplates,ConfigurableInitStepExecutorTest#shouldStartStandardCmspCmtpWithConfiguredCommand test` Expected: PASS **Step 3: Run compile** Run: `mvn -q -DskipTests compile` Expected: PASS **Step 4: Review focused diff** Run: `git diff -- src/main/java/com/cisd/tms/modules/init/service/InitService.java src/main/java/com/cisd/tms/modules/init/controller/InitInternalController.java src/main/java/com/cisd/tms/modules/init/dto/InitTaskExecuteResponse.java src/test/java/com/cisd/tms/modules/init/service/InitServiceTest.java docs/plans/2026-03-10-init-execute-async-resume-design.md docs/plans/2026-03-10-init-execute-async-resume-plan.md` Expected: only async-dispatch, resume logic, and related documentation changes. **Step 5: Commit** Skip commit in the current dirty workspace per user instruction.