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.
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.
Summary
Adopting rivet 0.16.0 in a downstream project (jess, the PulseEngine hardware-integration repo) flips a store that is
PASSon 0.15.0 toFAILwith 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:
All 21 errors are the same diagnostic:
Offending values across the 21 artifacts:
acceptedopenresolvedThe 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 migratestatus-remap (orvalidate --fixfor status) with a documented default mapping, so existing stores have a mechanical upgrade path rather than 21 manual edits.2.
acceptedwas the documented terminal staterivet's own release/lifecycle vocabulary (and the agent-facing guidance) describe the chain as
draft → proposed → approved → implemented → verified → accepted. The new enum dropsacceptedentirely in favor ofreleased / deprecated / rejected. Downstream artifacts that followed the documented lifecycle to its documented end state are now invalid. Either keepaccepted, or publish the rename (accepted → ?) so the docs/skills and the enum agree.3. One global document-lifecycle enum doesn't fit
ai-found-defectThe 8-value enum is a document/requirement lifecycle. A defect doesn't have a
draft → … → releasedlife — its natural vocabulary isopen / triaged / resolved / wontfix / duplicate. Forcingai-found-defectonto the document enum means a live unresolved defect has to be labeledproposed/draftand a fixed oneverified/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)
accepted,open,resolved, …) and ship a one-shot remap (rivet migrate --statusorvalidate --fix).accepted's fate explicitly and reconcile docs/agent-guidance with the enum.ai-found-defectcan keep anopen/triaged/resolvedlifecycle.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
acceptedto the canonical enum)Picking slice 2 per the triage recommendation: it clears the largest chunk (12 of the 21 errors), hits documented usage (
acceptedwas the published terminal state), and is a ~one-line schema change — highest value per line of diff.schemas/common.yamlcanonical status enum re-includesacceptedas a permitted terminal value alongsideverified/released/deprecated/rejected, with a one-line schema comment namingacceptedas the documented terminal state for design-decision / external-anchor / requirement-meta artifacts (the 12-error chunk).design-decisionwhosestatus: acceptedvalidates cleanly (0 errors) oncargo run -p rivet-cli -- validate.rivet schema info common(and/orrivet schema show common) printsacceptedin the allowed-values list so the diagnostic and the introspection surface agree.rivet validatePASS on the rivet repo itself;cargo test -p rivet-core -p rivet-cligreen;cargo fmt --check/clippy --all-targets -- -D warningsclean.Fixes: REQ-162+Refs: #352, #419, #522.rivet migratestatus-remap /validate --fix— distinct command + default-mapping policy:open → ?,resolved → ?); slice 3 (ai-found-defect'sopen/resolved— dedicated status enum vs. alifecycle:discriminator on common); therivet 0.16.0 upgradedocs page.Rationale for sequencing: slice 2 immediately un-breaks every store that followed the documented lifecycle (the jess store's 12
acceptederrors), 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.