[ADR-013/014] Note kind, storage, curation (cluster-04)#339
Conversation
Replace closed NoteKind enum with pack-owned String kinds, make salience/decay_factor genuinely nullable via V7 table rebuild, add NoteStatus::Deleted for soft-delete, tombstone merged entities instead of hard-deleting, and route update/delete/merge dispatch by public kind. 18 findings (6 CRIT, 10 MAJ, 2 MIN) across ADR-004, ADR-005, ADR-013, ADR-014, ADR-039. Schema changes: V5 (note status), V6 (entity tombstone columns), V7 (notes table rebuild for nullable metrics). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Codex adversarial reviewVerdict: REJECT Findings[Critical]
|
- types/lib.rs: export NoteKind + HandlerDef/Visibility (c03), keep NoteStatus (c04) - vocab.rs: add EntityKind enum (c04) alongside NoteKind (c03) - handlers.rs: merge import lists (LinkSpec from c03, ContentMergeStrategy/NotePatch from c04); drop orphaned dead-code block from c03 in handle_delete - stores/entity.rs: all SQL includes entity_type (c03) + merged_into/merge_event_id (c04) - migrations.rs: keep c03 V5-V9; renumber c04 V5→V10/V6→V11/V7→V12 with idempotency checks - curation.rs: SQL SELECTs include entity_type + merged_into/merge_event_id; drop misplaced c03 edge-rewire block (c04's dry_run-guarded version is authoritative) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…_edge arity NoteKind lives in khive-pack-kg/src/vocab.rs, not khive-types/src/note.rs. delete_edge requires a bool hard arg — pass p.hard.unwrap_or(false) in Edge branch. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…e cols) - Update DupPack test to use HANDLERS/handlers() (VerbDef→HandlerDef rename) - Fix create_entity test calls: add entity_type arg (7-arg signature from c03) - Fix link test call: add metadata arg (6-arg signature from c03) - Update edge rewire SQL to include updated_at/deleted_at/target_backend cols (V9 migration made updated_at NOT NULL) - Add #[allow(dead_code)] on EdgeRow structs (fields needed for column position) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add into_id == from_id guard on merge_entity and merge_note (data loss bug) - Add regression test merge_entity_self_merge_rejected - Update note-merge EdgeRow to include lifecycle cols from V9 migration - Update note-merge edge INSERT to include updated_at/deleted_at/target_backend Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…i-state patch - Contract tests: add `kind` field to delete calls (DeleteParams requires it) - Remove `kind_status` from public KG update (pack verbs handle lifecycle) - NoteStore::query_notes now returns Page<Note> with total count - salience/decay_factor use tri-state deserialization for null-clear semantics (closes #314) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- All contract/smoke test delete/update calls now pass required `kind` (Finding 1: smoke_test update/delete x5; contract_test soft-delete x1) - NotePatch.kind_status → pub(crate) with public NotePatch::new() constructor so external packs cannot set status directly (Finding 4) - kg handler uses NotePatch::new() instead of struct literal - cargo fmt applied (Finding 2) - Note: Option<Value> + f64_patch() is already correct tri-state serde (Finding 3: no change needed, absent→None, null→Some(Null), num→Some(Num)) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Option<Value> with serde's default Option impl treats JSON null as None, making it indistinguishable from an absent field. Replace with a proper tri_f64 deserializer on Option<Option<f64>> that correctly distinguishes: - field absent → None (preserve existing value) - field = null → Some(None) (clear the value) - field = number → Some(Some(v)) (set the value) This fixes the ADR-014 null-clear contract for salience and decay_factor through the MCP wire surface. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…n test Regression for round-3 codex finding: the previous Option<Value> representation of salience/decay_factor collapsed absent and JSON null into the same None, so JSON null could not distinguish "clear" from "preserve" through the MCP wire surface as ADR-014 requires. Asserts the wire deserializer maps: absent -> None null -> Some(None) (cleared) number -> Some(Some(v)) (set) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
6df5b0b
into
integration/v1-adr-alignment
Summary
Implements cluster from the v1 ADR alignment milestone. Closes #314.
Commits
Diff stat
Codex adversarial review
(no codex review run)
See full review in show artifacts:
/Users/lion/khive-work/shows/adr-001-015-alignment/impl-c04/codex_review.mdNo blocker/high findings.
Origin
Auto-generated by ADR-alignment overnight orchestration. Part of show
adr-001-015-alignment(one of 25 cluster PRs, merge sequence pertriage-plan/merge-sequence.md).🤖 Generated with Claude Code