Skip to content

modify --set-status accepts any string; status not enum-validated at modify or validate time (unlike phase) #354

@avrabe

Description

@avrabe

Summary

rivet modify <ID> --set-status <X> accepts any string as a lifecycle status, with no validation against the type's allowed status set — and rivet validate does not catch the invalid value either. This is inconsistent with how other enum fields (e.g. phase) are handled: an out-of-range phase is flagged at validate time, but status is not, at any point.

Found while transitioning shipped artifacts from approvedimplemented in a downstream project (witness). The transition itself worked fine; the gap surfaced when I deliberately probed for the allowed-status set.

Version

rivet 0.13.3 (b55a9c6f release/v0.14.0 2026-05-30)

Repro

$ rivet modify FEAT-024 --set-status bogus-xyz
modified FEAT-024                     # exit 0 — garbage accepted silently

$ rivet validate
...
Result: PASS (58 warnings)             # no diagnostic about the bogus status

Contrast — the same validator does enforce the phase enum:

$ rivet validate
  WARN: [FEAT-024] field 'phase' has value 'shipped', allowed: ["phase-1","phase-2","phase-3","future"]

So phase (an enum field) is validated against its allowed set, but status (the lifecycle enum) is not — neither at modify --set-status time nor at validate time.

Impact

  • A typo or wrong guess (implmented, done, shipped) is accepted and persists into the artifact YAML with zero feedback. For a traceability tool whose value is trustworthy lifecycle state, a silently-corrupt status undermines coverage/lifecycle reporting (e.g. "what's implemented?") without any signal.
  • It's most dangerous precisely because the valid set isn't discoverable (see below) — the natural way to find valid values is trial-and-error, and trial-and-error silently "succeeds" on invalid input.

Secondary: valid status values aren't discoverable

There's no introspection path that enumerates the allowed status values for a type:

  • rivet schema show feature lists fields, link fields, phase allowed-values, and a one-line example (status: approved) — but no enumerated status lifecycle.
  • No rivet docs topic covers the status lifecycle (status, lifecycle, state return nothing relevant).

I only confirmed implemented was valid by trying it (which, per the bug above, would have "succeeded" even if it weren't).

Suggested fix

  1. Validate --set-status against the type's allowed status set at modify time; reject with the allowed list on mismatch (mirror the helpful phase message).
  2. Have rivet validate flag out-of-vocabulary status values the same way it flags phase (belt-and-suspenders for hand-edited YAML).
  3. Surface the allowed status set in rivet schema show <type> so the lifecycle is discoverable.

What I used / what helped

  • Used: rivet modify <ID> --set-status implemented (correct command, works) to transition 26 shipped artifacts; rivet validate to confirm (PASS).
  • What was hard: discovering the valid status vocabulary — schema show doesn't enumerate it, and the natural probe (modify --set-status) gives false confidence by accepting anything.
  • What finally helped: knowing the value (implemented) out-of-band from the artifacts already using it. Nothing in the tooling validated or revealed it.

🤖 Filed via Claude Code while working on pulseengine/witness.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions