spec-kitty / spec-kitty/spec-kitty
move-task --agent does not persist to canonical runtime state, so accept's "missing agent" check is unclearable
- Dominant language
- Python
- Stars
- 1.6k
- Forks
- 165
- Avg merge
- 13h 53m
- Merged PRs (30d)
- 336
Description
## What happens
`spec-kitty accept` blocks on:
```
- metadata
• WP02: missing agent in canonical runtime state
• WP04: missing agent in canonical runtime state
```
`spec-kitty agent tasks move-task` advertises a flag that looks like the remedy:
```
spec-kitty agent tasks move-task WP02 --to for_review --agent claude
│ --agent TEXT Agent name / agent profile actual
```
It does not populate the field the gate reads. Verified three ways on a real mission:
1. `move-task WP02 --to approved --agent claude --force` on an already-`approved` WP → *"Moved WP02 from approved to approved"*, no event appended, field unchanged.
2. A full round-trip — `--to for_review --agent claude` then `--to approved --agent claude` → both transitions succeeded, events appended, **`agent` still `None`**.
3. Inspecting `status.events.jsonl`: the event schema carries `actor`, `execution_mode`, `from_lane`, `to_lane`, `wp_id` — **there is no `agent` key at all**, so the value has nowhere to persist.
## Where the field does get set
In the same mission, `status.json` shows:
| WP | `agent` | how it was allocated |
|---|---|---|
| WP01, WP03, WP06 | `implement-command` | `spec-kitty implement` |
| WP05 | `claude` | `spec-kitty implement` |
| WP02, WP04 | `None` | reached `for_review` via `move-task --force` |
So `agent` appears to be stamped only by the lane-allocation path. Any WP that reaches `for_review` by another route never acquires one, and `--agent` cannot retrofit it.
## Why that route was taken at all
Because of Priivacy-ai/spec-kitty#2993: `spec-kitty implement` snapshots `kitty-specs/` onto the lane instead of branching from the mission base, so `move-task` refuses with *"kitty-specs/ changes are not allowed on lane branches"* and `--force` becomes the only way forward. The forced transition then skips whatever stamps `agent`, and the accept gate blocks on the result. **One defect manufactures the precondition for the next.**
## Expected
One of:
1. **Make `--agent` do what it says** — persist it into the event and into the materialized state, so a missing value is retrofittable without hand-editing a derived artifact.
2. **Drop the flag** if it is vestigial. A flag documented as *"Agent name / agent profile actual"* that silently no-ops is worse than no flag, because it costs an operator several attempts before they inspect the event schema.
3. **Demote the gate check to a warning** when the lane history shows a forced transition — the mission is not less complete because a workaround for another defect skipped a metadata stamp.
## Impact
Low severity, but it is an unclearable blocker: the only remedies available to an operator are hand-editing `status.json` (a derived artifact, so it will be overwritten by the next materialize) or `--allow-fail`, which downgrades every *other* acceptance check to get past one metadata field.
Contributor guide
Research direction
Start with the `spec-kitty agent tasks move-task --agent` entry point, the `status.events.jsonl` event schema, and the materialized `status.json` state consumed by `spec-kitty accept`. Trace where the agent value is expected to persist and how the missing-agent gate reads it. Done requires an agreed behavior among persisting the value, removing the flag, or changing the gate, with coverage for forced transitions.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- cli, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100