Position was only in the bincode cache (serde field) — it would be lost on cache rebuild from capnp logs. Now persisted in the append-only log via ContentNode.position @19. Also fixes journal-tail sorting to extract dates from content headers, falling back to key-embedded dates.
89 lines
2.6 KiB
Cap'n Proto
89 lines
2.6 KiB
Cap'n Proto
@0xb78d9e3a1c4f6e2d;
|
|
|
|
# poc-memory: append-only memory store with graph structure
|
|
#
|
|
# Two append-only logs (nodes + relations) are the source of truth.
|
|
# A derived KV cache merges both, keeping latest version per UUID.
|
|
# Update = append new version with same UUID + incremented version.
|
|
# Delete = append with deleted=true. GC compacts monthly.
|
|
|
|
struct ContentNode {
|
|
uuid @0 :Data; # 16 bytes, random
|
|
version @1 :UInt32; # monotonic per UUID, latest wins
|
|
timestamp @2 :Float64; # unix epoch
|
|
nodeType @3 :NodeType;
|
|
provenance @4 :Provenance;
|
|
key @5 :Text; # "identity.md#boundaries" human-readable
|
|
content @6 :Text; # markdown blob
|
|
weight @7 :Float32;
|
|
category @8 :Category;
|
|
emotion @9 :Float32; # max intensity from tags, 0-10
|
|
deleted @10 :Bool; # soft delete
|
|
sourceRef @11 :Text; # link to raw experience: "transcript:SESSION_ID:BYTE_OFFSET"
|
|
|
|
# Migrated metadata from old system
|
|
created @12 :Text; # YYYY-MM-DD from old system
|
|
retrievals @13 :UInt32;
|
|
uses @14 :UInt32;
|
|
wrongs @15 :UInt32;
|
|
stateTag @16 :Text; # cognitive state (warm/open, bright/alert, etc.)
|
|
|
|
# Spaced repetition
|
|
lastReplayed @17 :Float64; # unix epoch
|
|
spacedRepetitionInterval @18 :UInt32; # days: 1, 3, 7, 14, 30
|
|
|
|
# Section ordering within a file
|
|
position @19 :UInt32; # 0 = file-level, 1+ = section index
|
|
}
|
|
|
|
enum NodeType {
|
|
episodicSession @0;
|
|
episodicDaily @1;
|
|
episodicWeekly @2;
|
|
semantic @3;
|
|
}
|
|
|
|
enum Provenance {
|
|
manual @0;
|
|
journal @1;
|
|
agent @2;
|
|
dream @3;
|
|
derived @4;
|
|
}
|
|
|
|
enum Category {
|
|
general @0;
|
|
core @1;
|
|
technical @2;
|
|
observation @3;
|
|
task @4;
|
|
}
|
|
|
|
struct Relation {
|
|
uuid @0 :Data; # 16 bytes, random
|
|
version @1 :UInt32;
|
|
timestamp @2 :Float64; # unix epoch
|
|
source @3 :Data; # content node UUID
|
|
target @4 :Data; # content node UUID
|
|
relType @5 :RelationType;
|
|
strength @6 :Float32; # manual=1.0, auto=0.1-0.7
|
|
provenance @7 :Provenance;
|
|
deleted @8 :Bool; # soft delete
|
|
sourceKey @9 :Text; # human-readable source key (for debugging)
|
|
targetKey @10 :Text; # human-readable target key (for debugging)
|
|
}
|
|
|
|
enum RelationType {
|
|
link @0; # bidirectional association (from links= or md links)
|
|
causal @1; # directed: source caused target
|
|
auto @2; # auto-discovered
|
|
}
|
|
|
|
# Wrapper for streaming multiple messages in one file
|
|
struct NodeLog {
|
|
nodes @0 :List(ContentNode);
|
|
}
|
|
|
|
struct RelationLog {
|
|
relations @0 :List(Relation);
|
|
}
|