spec-kitty / spec-kitty/spec-kitty
Thread emitted event ids from the emit sites into the workflow rollback expectation capture
- Dominant language
- Python
- Stars
- 1.6k
- Forks
- 165
- Avg merge
- 13h 53m
- Merged PRs (30d)
- 336
Description
## Observed
spec-kitty #3960 migrated both lockless rollback truncates onto `specify_cli.status.rollback.rollback_events_log_tail` (lock-held, tail-verified). The verification compares the rollback-time tail against an **expectation capture**, and on the two workflow commit paths that capture runs at `commit_workflow_change` entry — *after* the emit's `feature_status_lock` has already been released. Rows appended by another writer in the emit→entry gap would be blessed into the expectation and cut at rollback. The coord fallback arm has no such window (its capture runs inside the L1 hold that spans emit, commit and rollback); the review-claim shell holds L1 across its whole sequence too, so the exposed paths are the implement-claim/resume flows that emit unlocked and then commit (`workflow_executor.implement_claim_transition` and its siblings).
The window is microseconds wide (capture runs in the same call stack, immediately after the emit returns) and is documented in `src/specify_cli/status/rollback.py`'s module docstring ("Residual window, stated plainly"). It is a tightening target, not a live defect.
## Expected / proposed fix
Thread the emitted events' ids from the emit call sites into `commit_workflow_change` (the emit functions return the `StatusEvent`/annotation objects; today the ids are re-read from the log instead), so the expectation record is authored by the writer itself rather than re-derived from the file. Candidate for the caller-migration follow-up mission already tracking the eight direct transactional callers.
## Severity
LOW (tightening; no observed loss). Depends-on: none.
## Provenance
Filed from the #3960 implementation self-review (sk-impl-spec-kitty-3960).
Contributor guide
Research direction
Start with the residual-window note in src/specify_cli/status/rollback.py, then trace workflow_executor.implement_claim_transition and its sibling commit paths. Follow the emit calls into commit_workflow_change and the eight direct transactional callers. Done means emitted StatusEvent or annotation ids are threaded into the expectation capture instead of being re-read from the log, while the existing lock-held paths remain unchanged.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100