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 approved → implemented 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
- 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).
- Have
rivet validate flag out-of-vocabulary status values the same way it flags phase (belt-and-suspenders for hand-edited YAML).
- 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.
Summary
rivet modify <ID> --set-status <X>accepts any string as a lifecycle status, with no validation against the type's allowed status set — andrivet validatedoes not catch the invalid value either. This is inconsistent with how other enum fields (e.g.phase) are handled: an out-of-rangephaseis flagged at validate time, butstatusis not, at any point.Found while transitioning shipped artifacts from
approved→implementedin 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
Contrast — the same validator does enforce the
phaseenum:So
phase(an enum field) is validated against its allowed set, butstatus(the lifecycle enum) is not — neither atmodify --set-statustime nor atvalidatetime.Impact
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-corruptstatusundermines coverage/lifecycle reporting (e.g. "what's implemented?") without any signal.Secondary: valid status values aren't discoverable
There's no introspection path that enumerates the allowed
statusvalues for a type:rivet schema show featurelists fields, link fields,phaseallowed-values, and a one-line example (status: approved) — but no enumerated status lifecycle.rivet docstopic covers the status lifecycle (status,lifecycle,statereturn nothing relevant).I only confirmed
implementedwas valid by trying it (which, per the bug above, would have "succeeded" even if it weren't).Suggested fix
--set-statusagainst the type's allowed status set atmodifytime; reject with the allowed list on mismatch (mirror the helpfulphasemessage).rivet validateflag out-of-vocabularystatusvalues the same way it flagsphase(belt-and-suspenders for hand-edited YAML).rivet schema show <type>so the lifecycle is discoverable.What I used / what helped
rivet modify <ID> --set-status implemented(correct command, works) to transition 26 shipped artifacts;rivet validateto confirm (PASS).schema showdoesn't enumerate it, and the natural probe (modify --set-status) gives false confidence by accepting anything.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.