aws-samples / aws-samples/sample-collaborative-ai-dlc

Recompose can relaunch from an earlier stage excluded by the original projection

Open
#439 0 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
JavaScript
Stars
75
Forks
23
Avg merge
3d 17h
Merged PRs (30d)
24

Description

## Summary

`POST /projects/{projectId}/intents/{intentId}/recompose` freezes history only for stages that already have execution rows. A stage excluded from the original projection has no row, so an earlier stage can be changed from `SKIP` to `EXECUTE` and the run relaunches from that stage.

This was identified while reviewing #435. The frontend now clamps locked values before submitting, but the invariant remains unenforced by the backend and can still be bypassed by a direct API call or another client.

## Reproduction

1. Define an `ideation` stage before the current execution boundary and exclude it from the original `feature` projection.
2. Seed a parked run with `analyze: SUCCEEDED` and `optional: WAITING_FOR_HUMAN`. There is no execution row for `ideation`.
3. Submit a recompose grid containing:

```json
{
"ideation": "EXECUTE",
"analyze": "EXECUTE",
"optional": "EXECUTE",
"build": "SKIP"
}
```

A diagnostic backend test expecting `409` receives `202`, and the run is eligible to relaunch from `ideation`.

## Expected behavior

The server rejects the request with `409` because `ideation` is before the run progress boundary. Reshaping historical stages should require rewind.

## Actual behavior

The request is accepted with `202`. Frozen-state validation iterates only over `records.stages`, so the excluded stage is invisible to the check.

The in-flight composer has the same gap: its `frozenGrid` is also derived solely from execution rows. It may therefore produce a proposal that is valid according to composer validation but violates the intended progress boundary.

## Acceptance criteria

- Derive the canonical frozen boundary server-side from the compiled workflow/current plan and run progress, including stages with no execution row.
- Reject recomposed grids that add or alter stages before that boundary.
- Pass the same canonical frozen grid/boundary to in-flight composer validation.
- Add backend tests covering an earlier, originally excluded stage with no execution row for both `/recompose` and in-flight compose.
- Keep frontend locking as a UX guard, not as the enforcement boundary.

Contributor guide

Open the contributing guide

Research direction

Start with the backend handler and validation for POST /projects/{projectId}/intents/{intentId}/recompose, then trace how records.stages and the in-flight composer derive frozenGrid. Use the compiled workflow/current plan and run progress to define the shared boundary, and add backend coverage for an excluded earlier stage with no execution row in both paths. Done means both requests reject the invalid grid with 409 while valid recompositions continue to work.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
api, backend, testing
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.