spec-kitty / spec-kitty/spec-kitty
orchestrator-api transitions never reach the tracked kitty-specs/<slug>/status.json that `spec-kitty review` reads
- Dominant language
- Python
- Stars
- 1.6k
- Forks
- 165
- Avg merge
- 13h 53m
- Merged PRs (30d)
- 336
Description
`spec-kitty orchestrator-api transition` and `spec-kitty review` read and write **different** stores, so a mission whose WPs are genuinely `done` can permanently fail its own review gate.
## Reproduction
Project `spec-kitty-saas` (`sync.enabled: true`), mission `next-family-1-team-workspace-01M2EKAK`, CLI as installed at `~/.local/bin/spec-kitty`, contract version `1.3.0`.
Walk all five WPs `planned → claimed → in_progress → for_review → in_review → approved → done` via `orchestrator-api transition`. Every transition returns `"success": true`. Then:
```
$ spec-kitty orchestrator-api mission-state --mission next-family-1-team-workspace-01M2EKAK
['done', 'done', 'done', 'done', 'done']
$ python3 -c "import json;d=json.load(open('kitty-specs/next-family-1-team-workspace-01M2EKAK/status.json'));print({k:v['lane'] for k,v in d['work_packages'].items()})"
{'WP01': 'planned', 'WP02': 'planned', 'WP03': 'planned', 'WP04': 'planned', 'WP05': 'planned'}
$ spec-kitty review --mission next-family-1-team-workspace-01M2EKAK
✗ WP lane check: 5 WP(s) not in done
WP01: planned ... (all five)
Verdict: fail
```
`spec-kitty materialize` writes `.kittify/derived//status.json` (which correctly shows `done: 5`) — but that path is **gitignored** (`.gitignore:81: .kittify/derived/`). The tracked `kitty-specs//status.json` and `kitty-specs//status.events.jsonl` are never updated; the event log still has its original 16 creation-time events and an unchanged mtime.
## Impact
- `spec-kitty review` cannot pass for any mission driven through `orchestrator-api`, regardless of actual state.
- The committed mission record — the artifact that survives in git and that humans read — permanently misreports every WP as `planned`.
- The only way to make `review` agree is to hand-edit a generated, tracked file, which fabricates a record. I declined to do that; this mission's WPs are all merged and its record still reads `planned`.
## Notes
- Not specific to `--force`: the earlier non-forced `planned → claimed → in_progress` transitions also returned success and also left the tracked file untouched.
- `materialize --mission ` reports `OK ... status.json, board-summary.json, progress.json, lifecycle.json` and writes only under `.kittify/derived/`, so its success line is easy to mistake for having updated the committed record.
- This CLI build has no `move-task` command (`No such command 'move-task'. Did you mean 'validate-tasks'?`), so `orchestrator-api transition` is the only available lane-transition path.
## Suggested fix
Either have `transition`/`materialize` write the tracked `kitty-specs//status.json` + `status.events.jsonl`, or have `spec-kitty review` read the same store `orchestrator-api mission-state` reads. Today they disagree silently and only `review` is wired into the gate.
Contributor guide
Research direction
Start with the orchestrator-api transition, mission-state, materialize, and review entry points, then trace which stores each command reads and writes. Verify the behavior against kitty-specs//status.json and status.events.jsonl; done means transitions and review use a consistent store and the tracked mission record reflects the final lanes.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend-api-design, cli
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100