Skip to content

0.16.0 canonical status enum is breaking: no migration, drops documented 'accepted', and doesn't fit ai-found-defect #522

@avrabe

Description

@avrabe

Summary

Adopting rivet 0.16.0 in a downstream project (jess, the PulseEngine hardware-integration repo) flips a store that is PASS on 0.15.0 to FAIL with 21 errors on 0.16.0 — all from the new canonical status enum (feat(schema): declare canonical status lifecycle in common.yaml, REQ-162 / #352 / PR #419).

The enum itself is a genuine improvement (#352 was a real gap — typo'd statuses used to pass silently). This issue is about three friction points in rolling it out, surfaced by actually upgrading a real store.

Reproduction

Same artifact store, two binaries:

# rivet 0.15.0 (930e531e)
$ rivet validate
Result: PASS (4 warnings)

# rivet 0.16.0 (23b24958), no artifact changes
$ rivet validate
Result: FAIL (21 errors, 4 warnings, 0 broken cross-refs)

All 21 errors are the same diagnostic:

ERROR: [<id>] status '<x>' is not an allowed value,
  allowed: ["draft","proposed","approved","implemented","verified","released","deprecated","rejected"]

Offending values across the 21 artifacts:

status count artifact types
accepted 12 design-decision, external-anchor, requirement (meta)
open 7 ai-found-defect
resolved 2 ai-found-defect

The three friction points

1. Breaking change with no migration path

A store that validated on the prior release now has 21 hard errors on a minor bump, and the only remedy offered is hand-editing each artifact. Consider a rivet migrate status-remap (or validate --fix for status) with a documented default mapping, so existing stores have a mechanical upgrade path rather than 21 manual edits.

2. accepted was the documented terminal state

rivet's own release/lifecycle vocabulary (and the agent-facing guidance) describe the chain as draft → proposed → approved → implemented → verified → accepted. The new enum drops accepted entirely in favor of released / deprecated / rejected. Downstream artifacts that followed the documented lifecycle to its documented end state are now invalid. Either keep accepted, or publish the rename (accepted → ?) so the docs/skills and the enum agree.

3. One global document-lifecycle enum doesn't fit ai-found-defect

The 8-value enum is a document/requirement lifecycle. A defect doesn't have a draft → … → released life — its natural vocabulary is open / triaged / resolved / wontfix / duplicate. Forcing ai-found-defect onto the document enum means a live unresolved defect has to be labeled proposed/draft and a fixed one verified/released, which loses the triage semantics. Consider per-schema status allowed-values (a defect lifecycle distinct from the document lifecycle), or a dedicated triage-status field for findings.

Suggested fix (smallest first)

  • Document the canonical mapping for the removed values (accepted, open, resolved, …) and ship a one-shot remap (rivet migrate --status or validate --fix).
  • Decide accepted's fate explicitly and reconcile docs/agent-guidance with the enum.
  • Allow schema-type-specific status enums so ai-found-defect can keep an open/triaged/resolved lifecycle.

Happy to test any of these against the jess store immediately — it's a compact, public reproduction (mixed design-decision / external-anchor / ai-found-defect artifacts) at https://github.com/pulseengine/jess. Thanks for the canonical-status work; this is purely about making the transition non-breaking for stores already in the wild.

Filed from the jess release-watch dogfooding loop (tracked as AFD-012).


Acceptance Criteria — first slice (slice 2: re-add accepted to the canonical enum)

Picking slice 2 per the triage recommendation: it clears the largest chunk (12 of the 21 errors), hits documented usage (accepted was the published terminal state), and is a ~one-line schema change — highest value per line of diff.

  • schemas/common.yaml canonical status enum re-includes accepted as a permitted terminal value alongside verified/released/deprecated/rejected, with a one-line schema comment naming accepted as the documented terminal state for design-decision / external-anchor / requirement-meta artifacts (the 12-error chunk).
  • Regression fixture: a project store with a design-decision whose status: accepted validates cleanly (0 errors) on cargo run -p rivet-cli -- validate.
  • rivet schema info common (and/or rivet schema show common) prints accepted in the allowed-values list so the diagnostic and the introspection surface agree.
  • rivet validate PASS on the rivet repo itself; cargo test -p rivet-core -p rivet-cli green; cargo fmt --check / clippy --all-targets -- -D warnings clean.
  • Commit trailer: Fixes: REQ-162 + Refs: #352, #419, #522.
  • Out of scope (file separately): slice 1 (rivet migrate status-remap / validate --fix — distinct command + default-mapping policy: open → ?, resolved → ?); slice 3 (ai-found-defect's open/resolved — dedicated status enum vs. a lifecycle: discriminator on common); the rivet 0.16.0 upgrade docs page.

Rationale for sequencing: slice 2 immediately un-breaks every store that followed the documented lifecycle (the jess store's 12 accepted errors), buying time to design slices 1 and 3 properly rather than under a breaking-change clock. jess stays on 0.15.0 until at least slice 2 ships.

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