feat(add): rivet add stamps AI provenance at creation (REQ-203, closes #476)#477
Merged
Conversation
…dd serializer (REQ-203) Closes #476. The AI-provenance system was wired to the editor, not to rivet's own mutation commands, so the sanctioned creation path produced UNSTAMPED artifacts: cmd_add built the Artifact with `provenance: None`, and the .claude/settings.json stamp hook only matches Edit/Write — a heredoc append or `rivet add` (both Bash calls) never fired it. For a tool whose pitch is AI-artifact auditability, AI-created artifacts silently missing provenance is a correctness gap. Compounding bug caught during implementation: `mutate::render_artifact_yaml` (the single serializer for the add path) did NOT emit the `provenance` block at all, so merely setting `artifact.provenance` would have been a silent no-op (the REQ-196/200 class of bug). Both halves are fixed: - `rivet add` gains `--created-by <human|ai|ai-assisted>` and `--model <M>`; `--created-by` falls back to the RIVET_PROVENANCE_CREATED_BY env var so CI/agent environments can set it once. Value validated up front. Absent => no provenance block (prior behavior preserved). - Extract `current_utc_timestamp()`, shared by cmd_stamp and cmd_add, so both emit identical ISO-8601 timestamps with no chrono dependency. - `render_artifact_yaml` now emits the `provenance:` block (field order matches yaml_edit::set_provenance). Tests (rivet-core): render_artifact_yaml_emits_provenance_when_present and render_artifact_yaml_omits_provenance_when_absent. Confirmed with: cargo test -p rivet-core --lib render_artifact_yaml_ (4 passed); end-to-end on a fresh `rivet init` project — `rivet add --created-by ai-assisted --model claude-opus-4-8` wrote the provenance block, plain add wrote none, RIVET_PROVENANCE_CREATED_BY=ai stamped from env, --created-by robot errored, rivet validate PASS; cargo fmt --all -- --check (exit 0); cargo clippy --all-targets -- -D warnings (exit 0, only pre-existing MSRV-config warning). Implements: REQ-203 Verifies: REQ-203 Refs: REQ-007
📐 Rivet artifact delta
Graphgraph LR
REQ_203["REQ-203"]:::added
classDef added fill:#d4edda,stroke:#28a745,color:#155724
classDef removed fill:#f8d7da,stroke:#dc3545,color:#721c24
classDef modified fill:#fff3cd,stroke:#ffc107,color:#856404
classDef overflow fill:#e2e3e5,stroke:#6c757d,color:#495057,stroke-dasharray: 3 3
Added
Posted by |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
⚠️ Performance Alert ⚠️
Possible performance regression was detected for benchmark 'Rivet Criterion Benchmarks'.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 1.20.
| Benchmark suite | Current: 545376b | Previous: 531f4f3 | Ratio |
|---|---|---|---|
store_insert/100 |
85014 ns/iter (± 288) |
67153 ns/iter (± 676) |
1.27 |
store_insert/1000 |
916162 ns/iter (± 6413) |
736228 ns/iter (± 4489) |
1.24 |
store_insert/10000 |
18030365 ns/iter (± 801889) |
11632774 ns/iter (± 386214) |
1.55 |
store_lookup/100 |
2120 ns/iter (± 9) |
1532 ns/iter (± 7) |
1.38 |
store_lookup/1000 |
27331 ns/iter (± 158) |
18605 ns/iter (± 186) |
1.47 |
store_lookup/10000 |
374782 ns/iter (± 2114) |
262385 ns/iter (± 1625) |
1.43 |
store_by_type/100 |
93 ns/iter (± 0) |
75 ns/iter (± 0) |
1.24 |
store_by_type/1000 |
93 ns/iter (± 1) |
75 ns/iter (± 0) |
1.24 |
store_by_type/10000 |
93 ns/iter (± 0) |
75 ns/iter (± 0) |
1.24 |
schema_load_and_merge |
1463144 ns/iter (± 27658) |
1108652 ns/iter (± 21999) |
1.32 |
link_graph_build/100 |
162384 ns/iter (± 1263) |
127912 ns/iter (± 1896) |
1.27 |
link_graph_build/1000 |
1931586 ns/iter (± 66341) |
1478194 ns/iter (± 19920) |
1.31 |
link_graph_build/10000 |
40494963 ns/iter (± 2876408) |
21634013 ns/iter (± 2533368) |
1.87 |
validate/100 |
463293 ns/iter (± 5203) |
338291 ns/iter (± 790) |
1.37 |
validate/1000 |
17661270 ns/iter (± 190084) |
13279552 ns/iter (± 215097) |
1.33 |
validate/10000 |
1472473051 ns/iter (± 26992588) |
1059688941 ns/iter (± 7886956) |
1.39 |
traceability_matrix/100 |
4292 ns/iter (± 56) |
3225 ns/iter (± 8) |
1.33 |
traceability_matrix/1000 |
59422 ns/iter (± 184) |
40497 ns/iter (± 495) |
1.47 |
traceability_matrix/10000 |
739753 ns/iter (± 2845) |
578239 ns/iter (± 3030) |
1.28 |
diff/100 |
59111 ns/iter (± 1328) |
48159 ns/iter (± 1810) |
1.23 |
diff/1000 |
698281 ns/iter (± 21674) |
514423 ns/iter (± 2954) |
1.36 |
diff/10000 |
7746274 ns/iter (± 271083) |
6054584 ns/iter (± 53019) |
1.28 |
query/100 |
1195 ns/iter (± 5) |
917 ns/iter (± 4) |
1.30 |
query/1000 |
16001 ns/iter (± 436) |
11897 ns/iter (± 156) |
1.34 |
query/10000 |
346197 ns/iter (± 2419) |
177307 ns/iter (± 1380) |
1.95 |
document_parse/10 |
23862 ns/iter (± 1059) |
17375 ns/iter (± 112) |
1.37 |
document_parse/100 |
174256 ns/iter (± 1613) |
125481 ns/iter (± 934) |
1.39 |
document_parse/1000 |
1588603 ns/iter (± 8581) |
1158417 ns/iter (± 14629) |
1.37 |
This comment was automatically generated by workflow using github-action-benchmark.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #476. From the hourly dogfooding loop — a friction I hit filing REQ-202, then traced to a correctness gap.
The gap
The AI-provenance system was wired to the editor, not to rivet's own mutation commands, so the sanctioned creation path produced unstamped artifacts:
Edit/Writetool onartifacts/**(fires the.claude/settings.jsonhook)cat >>/ heredoc append (aBashcall)rivet add(cmd_addbuilt theArtifactwithprovenance: None)For a tool whose pitch is AI-artifact auditability, AI-created artifacts silently missing provenance is a correctness gap — and the recommended tool was the one that dropped it.
Compounding bug caught while implementing
mutate::render_artifact_yaml— the single serializer for theaddpath — did not emit theprovenanceblock at all. So just settingartifact.provenance = Some(..)would have been a silent no-op (the exact REQ-196/REQ-200 class of bug). I verified against the written file, not the struct, and fixed both halves.Fix
rivet addgains--created-by <human|ai|ai-assisted>and--model <M>;--created-byfalls back to theRIVET_PROVENANCE_CREATED_BYenv var so CI/agent environments set it once. Value validated up front (before project load). Absent ⇒ no block (prior behavior preserved).current_utc_timestamp(), shared bycmd_stampandcmd_add, so both emit identical ISO-8601 timestamps (no chrono dep).render_artifact_yamlnow emits theprovenance:block (field order matchesyaml_edit::set_provenance).Verification
render_artifact_yaml_emits_provenance_when_present,render_artifact_yaml_omits_provenance_when_absent— both pass.rivet initproject:rivet add --created-by ai-assisted --model claude-opus-4-8wrote the block; plainrivet addwrote none;RIVET_PROVENANCE_CREATED_BY=ai rivet addstamped from env;--created-by roboterrored;rivet validatePASS.cargo fmt --all -- --checkexit 0 ·cargo clippy --all-targets -- -D warningsexit 0 (only the pre-existing MSRV-config warning).Implements + Verifies REQ-203.
🤖 Generated with Claude Code