spec-kitty / spec-kitty/spec-kitty

move-task --agent does not persist to canonical runtime state, so accept's "missing agent" check is unclearable

Open
#3,029 1 comment 0 reactions 0 assignees View on GitHub
priority:P1 reliability usability workflow
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.