agentopology 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/README.md +1 -1
  2. package/dist/analyzer/index.d.ts +1 -0
  3. package/dist/analyzer/index.d.ts.map +1 -1
  4. package/dist/analyzer/index.js +35 -0
  5. package/dist/analyzer/index.js.map +1 -1
  6. package/dist/bindings/claude-code.d.ts.map +1 -1
  7. package/dist/bindings/claude-code.js +283 -2
  8. package/dist/bindings/claude-code.js.map +1 -1
  9. package/dist/bindings/openclaw.d.ts.map +1 -1
  10. package/dist/bindings/openclaw.js +367 -5
  11. package/dist/bindings/openclaw.js.map +1 -1
  12. package/dist/cli/index.js +2 -2
  13. package/dist/cli/index.js.map +1 -1
  14. package/dist/docs/__tests__/docs.test.js +2 -1
  15. package/dist/docs/__tests__/docs.test.js.map +1 -1
  16. package/dist/docs/content.d.ts.map +1 -1
  17. package/dist/docs/content.js +730 -4
  18. package/dist/docs/content.js.map +1 -1
  19. package/dist/exporters/markdown.d.ts.map +1 -1
  20. package/dist/exporters/markdown.js +165 -0
  21. package/dist/exporters/markdown.js.map +1 -1
  22. package/dist/exporters/mermaid.d.ts.map +1 -1
  23. package/dist/exporters/mermaid.js +30 -0
  24. package/dist/exporters/mermaid.js.map +1 -1
  25. package/dist/import/__tests__/import.test.js +554 -0
  26. package/dist/import/__tests__/import.test.js.map +1 -1
  27. package/dist/import/claude-code.d.ts.map +1 -1
  28. package/dist/import/claude-code.js +2 -0
  29. package/dist/import/claude-code.js.map +1 -1
  30. package/dist/import/index.d.ts +1 -0
  31. package/dist/import/index.d.ts.map +1 -1
  32. package/dist/import/index.js +7 -1
  33. package/dist/import/index.js.map +1 -1
  34. package/dist/import/openclaw.d.ts +70 -0
  35. package/dist/import/openclaw.d.ts.map +1 -0
  36. package/dist/import/openclaw.js +1060 -0
  37. package/dist/import/openclaw.js.map +1 -0
  38. package/dist/import/serializer.d.ts.map +1 -1
  39. package/dist/import/serializer.js +171 -4
  40. package/dist/import/serializer.js.map +1 -1
  41. package/dist/parser/__tests__/parser.test.js +463 -0
  42. package/dist/parser/__tests__/parser.test.js.map +1 -1
  43. package/dist/parser/ast.d.ts +122 -0
  44. package/dist/parser/ast.d.ts.map +1 -1
  45. package/dist/parser/index.d.ts +14 -2
  46. package/dist/parser/index.d.ts.map +1 -1
  47. package/dist/parser/index.js +226 -5
  48. package/dist/parser/index.js.map +1 -1
  49. package/dist/parser/validator.d.ts +1 -1
  50. package/dist/parser/validator.d.ts.map +1 -1
  51. package/dist/parser/validator.js +214 -1
  52. package/dist/parser/validator.js.map +1 -1
  53. package/dist/visualizer/index.d.ts.map +1 -1
  54. package/dist/visualizer/index.js +104 -16
  55. package/dist/visualizer/index.js.map +1 -1
  56. package/examples/memory-system.at +162 -0
  57. package/examples/script-agent-pipeline.at +65 -0
  58. package/package.json +1 -1
  59. package/spec/grammar.md +345 -10
  60. package/spec/reserved-keywords.md +25 -1
  61. package/spec/validation.md +171 -2
  62. package/examples/simple-pipeline-topology.html +0 -5700
@@ -671,10 +671,10 @@ flow {
671
671
  // -------------------------------------------------------------------------
672
672
  memory: {
673
673
  name: "memory",
674
- description: "Memory block -- workspace, domains, references, metrics",
674
+ description: "Memory block -- workspace, domains, stores, retrieval strategies",
675
675
  content: () => `# memory
676
676
 
677
- The \`memory\` block declares the shared data layer for the topology. It defines where agents read and write data.
677
+ The \`memory\` block declares the shared data layer for the topology. It defines where agents read and write data, declares memory stores for persistent knowledge, and configures retrieval strategies for multi-source memory queries.
678
678
 
679
679
  ## Syntax
680
680
 
@@ -702,6 +702,42 @@ memory {
702
702
  path: "metrics/data.jsonl"
703
703
  mode: append-only
704
704
  }
705
+
706
+ store codebase-knowledge {
707
+ type: semantic
708
+ backend: lancedb
709
+ path: ".memory/semantic/"
710
+ scope: global
711
+ isolation: soft
712
+ embedding {
713
+ provider: ollama
714
+ model: "nomic-embed-text"
715
+ dimensions: 768
716
+ }
717
+ search {
718
+ strategy: hybrid
719
+ rerank: true
720
+ top-k: 10
721
+ }
722
+ lifecycle {
723
+ retention: 90d
724
+ decay-half-life: 30d
725
+ contradiction: overwrite
726
+ }
727
+ }
728
+
729
+ retrieval default {
730
+ sources: [codebase-knowledge]
731
+ budget: 4096
732
+ scoring {
733
+ recency-weight: 0.3
734
+ semantic-weight: 0.5
735
+ importance-weight: 0.2
736
+ }
737
+ paths: [semantic]
738
+ cache-hit-threshold: 0.92
739
+ cache-hit-action: short-circuit
740
+ }
705
741
  }
706
742
  \`\`\`
707
743
 
@@ -714,6 +750,8 @@ memory {
714
750
  | references | Reference documentation |
715
751
  | external-docs | External documentation |
716
752
  | metrics | Metrics output (supports append-only mode) |
753
+ | store \`<id>\` | Named memory store declaration (vector, graph, episodic backends) |
754
+ | retrieval \`<id>\` | Named retrieval strategy for multi-source memory queries |
717
755
 
718
756
  ### workspace Fields
719
757
 
@@ -742,6 +780,38 @@ memory {
742
780
  | path | string | Output file path |
743
781
  | mode | string | "append-only" for log-style output |
744
782
 
783
+ ## Memory Stores
784
+
785
+ The \`store <id> {}\` sub-block declares a named memory store within the memory block. Each store specifies a memory type, storage backend, embedding configuration, and lifecycle policies. See the **store** topic for full field reference.
786
+
787
+ Supported memory types: \`semantic\`, \`episodic\`, \`procedural\`, \`entity\`, \`graph\`, \`user\`, \`session\`, \`temporal\`.
788
+
789
+ Supported backends: \`lancedb\`, \`sqlite-vec\`, \`chroma\`, \`kuzu\`, \`falkordb\`, \`mongodb\`, \`pinecone\`, \`qdrant\`, \`pgvector\`, \`neo4j\`, \`sqlite\`.
790
+
791
+ Each store can contain sub-blocks: \`embedding {}\`, \`index {}\`, \`ingestion {}\`, \`search {}\`, \`lifecycle {}\`, \`backend-config {}\`.
792
+
793
+ ## Retrieval Strategies
794
+
795
+ The \`retrieval <id> {}\` sub-block declares a named retrieval strategy that queries one or more stores. It controls token budgets, scoring weights, retrieval paths, and cache-hit behavior. See the **retrieval** topic for full field reference.
796
+
797
+ Key fields: \`sources\` (store IDs to query), \`budget\` (token limit), \`scoring {}\` (weight configuration), \`paths\` (retrieval types), \`cache-hit-threshold\`, \`cache-hit-action\`.
798
+
799
+ ## Agent Memory References
800
+
801
+ Agents reference memory stores and retrieval strategies via two fields on the agent node:
802
+
803
+ | Field | Type | Description |
804
+ |-------|------|-------------|
805
+ | memory | name-list | Store IDs this agent can access |
806
+ | retrieval | identifier | Retrieval strategy ID for memory queries |
807
+
808
+ \`\`\`at
809
+ agent researcher {
810
+ memory: [codebase-knowledge, session-history]
811
+ retrieval: default
812
+ }
813
+ \`\`\`
814
+
745
815
  ## Validation Rules
746
816
 
747
817
  - **V11**: Agent \`reads\` and \`writes\` must be consistent with flow order
@@ -752,6 +822,662 @@ memory {
752
822
  - Memory paths are relative to the topology's root directory.
753
823
  - Agents declare which memory keys they access via \`reads\` and \`writes\` fields.
754
824
  - The workspace structure is informational -- it documents expected folders but does not create them.
825
+ - Store and retrieval blocks are parsed into typed AST nodes (\`StoreNode[]\` and \`RetrievalNode[]\`) at the top level of the AST.
826
+ - Local-first defaults: \`lancedb\` for semantic, \`kuzu\` for graph, \`sqlite\` for session/episodic.
827
+ `,
828
+ },
829
+ // -------------------------------------------------------------------------
830
+ // 9a. store
831
+ // -------------------------------------------------------------------------
832
+ store: {
833
+ name: "store",
834
+ description: "Memory store declaration -- vector, graph, and episodic backends",
835
+ content: () => `# store
836
+
837
+ The \`store\` block declares a named memory store within the \`memory {}\` block. Each store represents a persistent knowledge backend -- vector databases for semantic search, graph databases for entity relationships, or simple key-value stores for session state.
838
+
839
+ ## Syntax
840
+
841
+ \`\`\`at
842
+ store <id> {
843
+ type: <semantic | episodic | procedural | entity | graph | user | session | temporal>
844
+ description: "Human-readable purpose"
845
+ scope: <agent | user | session | org | global>
846
+ isolation: <strict | soft | none>
847
+
848
+ backend: <lancedb | sqlite-vec | chroma | kuzu | falkordb | mongodb | pinecone | qdrant | pgvector | neo4j | sqlite>
849
+ path: ".memory/<type>/"
850
+ connection: secret "STORE_URL"
851
+
852
+ embedding {
853
+ provider: <ollama | local | voyage | openai | gemini>
854
+ model: "nomic-embed-text"
855
+ dimensions: 768
856
+ endpoint: secret "EMBEDDING_URL"
857
+ }
858
+
859
+ index {
860
+ collection: "chunks"
861
+ metric: <cosine | euclidean | dot-product>
862
+ }
863
+
864
+ ingestion {
865
+ sources: ["docs/", "references/"]
866
+ chunking: <recursive | sentence | paragraph | fixed>
867
+ chunk-size: 512
868
+ overlap: 50
869
+ }
870
+
871
+ search {
872
+ strategy: <vector | keyword | hybrid | graph>
873
+ rerank: true
874
+ top-k: 10
875
+ }
876
+
877
+ lifecycle {
878
+ retention: 90d
879
+ decay-half-life: 30d
880
+ consolidation: 0.85
881
+ contradiction: <overwrite | preserve | bi-temporal>
882
+ audit-log: true
883
+ }
884
+
885
+ extraction: <llm | regex | hybrid>
886
+
887
+ backend-config {
888
+ # passthrough key-value pairs for backend-specific settings
889
+ }
890
+ }
891
+ \`\`\`
892
+
893
+ ## Top-Level Fields
894
+
895
+ | Field | Type | Required | Description |
896
+ |-------|------|----------|-------------|
897
+ | type | string | yes | Memory type: semantic, episodic, procedural, entity, graph, user, session, temporal |
898
+ | description | string | no | Human-readable description of this store's purpose |
899
+ | scope | string | yes | Access scope: agent, user, session, org, global |
900
+ | isolation | string | no | Isolation level: strict, soft, none |
901
+ | backend | string | yes | Storage backend identifier |
902
+ | path | string | no | File system path for local backends |
903
+ | connection | string | no | Connection string or \`secret "..."\` reference for remote backends |
904
+ | extraction | string | no | Entity/fact extraction method: llm, regex, hybrid |
905
+
906
+ ## Memory Types
907
+
908
+ | Type | Description |
909
+ |------|-------------|
910
+ | semantic | Long-term knowledge via vector embeddings (RAG) |
911
+ | episodic | Event and experience memories with temporal context |
912
+ | procedural | Learned procedures, workflows, and how-to knowledge |
913
+ | entity | Named entity facts and attributes |
914
+ | graph | Relationship graphs between entities |
915
+ | user | Per-user preferences and profile data |
916
+ | session | Short-lived conversational context |
917
+ | temporal | Time-series data with temporal ordering |
918
+
919
+ ## Supported Backends
920
+
921
+ | Backend | Type | Local | Description |
922
+ |---------|------|-------|-------------|
923
+ | lancedb | vector | yes | Embeddable columnar vector DB (Rust, zero-infra) |
924
+ | sqlite-vec | vector | yes | SQLite extension for vector search |
925
+ | chroma | vector | yes/no | Open-source embedding database |
926
+ | kuzu | graph | yes | Embeddable graph DB (columnar, fast multi-hop) |
927
+ | falkordb | graph | no | Redis-compatible graph database |
928
+ | mongodb | document | no | Document store with Atlas Vector Search |
929
+ | pinecone | vector | no | Managed vector database |
930
+ | qdrant | vector | no | Vector similarity search engine |
931
+ | pgvector | vector | no | PostgreSQL vector extension |
932
+ | neo4j | graph | no | Native graph database |
933
+ | sqlite | kv/relational | yes | Lightweight relational/key-value store |
934
+
935
+ ## Sub-Block: embedding {}
936
+
937
+ Configures the embedding model used to vectorize content for this store. Required when type is semantic, episodic, or procedural.
938
+
939
+ | Field | Type | Description |
940
+ |-------|------|-------------|
941
+ | provider | string | Embedding provider: ollama, local, voyage, openai, gemini |
942
+ | model | string | Model identifier (e.g. "nomic-embed-text", "text-embedding-3-small") |
943
+ | dimensions | number | Vector dimensions produced by the model |
944
+ | endpoint | string | Endpoint URL or \`secret "..."\` reference |
945
+
946
+ See the **embedding** topic for full details.
947
+
948
+ ## Sub-Block: index {}
949
+
950
+ Configures the index or collection within the backend.
951
+
952
+ | Field | Type | Description |
953
+ |-------|------|-------------|
954
+ | collection | string | Collection or table name within the backend |
955
+ | metric | string | Distance metric: cosine, euclidean, dot-product |
956
+
957
+ ## Sub-Block: ingestion {}
958
+
959
+ Configures how content is loaded into the store.
960
+
961
+ | Field | Type | Description |
962
+ |-------|------|-------------|
963
+ | sources | string-list | Source paths or globs to ingest from |
964
+ | chunking | string | Chunking strategy: recursive, sentence, paragraph, fixed |
965
+ | chunk-size | number | Target chunk size in tokens or characters |
966
+ | overlap | number | Overlap between chunks |
967
+
968
+ ## Sub-Block: search {}
969
+
970
+ Configures how the store is queried.
971
+
972
+ | Field | Type | Description |
973
+ |-------|------|-------------|
974
+ | strategy | string | Search strategy: vector, keyword, hybrid, graph |
975
+ | rerank | boolean | Whether to apply reranking to results |
976
+ | top-k | number | Number of top results to return |
977
+
978
+ ## Sub-Block: lifecycle {}
979
+
980
+ Configures memory retention, decay, and contradiction resolution. See the **lifecycle** topic for full details.
981
+
982
+ | Field | Type | Description |
983
+ |-------|------|-------------|
984
+ | retention | string | Retention period (e.g. "90d", "1y") |
985
+ | decay-half-life | string | Half-life for memory decay scoring (e.g. "30d") |
986
+ | consolidation | number | Consolidation threshold (0 to 1) |
987
+ | contradiction | string | Resolution strategy: overwrite, preserve, bi-temporal |
988
+ | audit-log | boolean | Whether to maintain an audit log |
989
+
990
+ ## Sub-Block: backend-config {}
991
+
992
+ Passthrough key-value pairs for backend-specific settings not covered by the universal schema. Follows the same pattern as \`extensions {}\` -- unknown keys are preserved as-is.
993
+
994
+ ## Connection with Secret Modifier
995
+
996
+ Remote backends use the \`secret\` modifier for connection strings:
997
+
998
+ \`\`\`at
999
+ store vectors {
1000
+ backend: pinecone
1001
+ connection: secret "PINECONE_URL"
1002
+ embedding {
1003
+ endpoint: secret "EMBEDDING_API_KEY"
1004
+ }
1005
+ }
1006
+ \`\`\`
1007
+
1008
+ ## Scope and Isolation
1009
+
1010
+ Every store declares a \`scope\` (who can access it) and optionally an \`isolation\` level (how strictly access is enforced):
1011
+
1012
+ - **scope: agent** -- private to a single agent
1013
+ - **scope: user** -- per-user data
1014
+ - **scope: session** -- per-session, ephemeral
1015
+ - **scope: org** -- shared across an organization
1016
+ - **scope: global** -- accessible by all agents in the topology
1017
+
1018
+ Isolation levels: \`strict\` (hard boundaries), \`soft\` (warnings on cross-scope access), \`none\` (no enforcement).
1019
+
1020
+ ## Example
1021
+
1022
+ \`\`\`at
1023
+ memory {
1024
+ store codebase {
1025
+ type: semantic
1026
+ description: "Indexed codebase for semantic search"
1027
+ scope: global
1028
+ isolation: soft
1029
+ backend: lancedb
1030
+ path: ".memory/codebase/"
1031
+ embedding {
1032
+ provider: ollama
1033
+ model: "nomic-embed-text"
1034
+ dimensions: 768
1035
+ }
1036
+ index {
1037
+ collection: "code-chunks"
1038
+ metric: cosine
1039
+ }
1040
+ ingestion {
1041
+ sources: ["src/", "docs/"]
1042
+ chunking: recursive
1043
+ chunk-size: 512
1044
+ overlap: 50
1045
+ }
1046
+ search {
1047
+ strategy: hybrid
1048
+ rerank: true
1049
+ top-k: 10
1050
+ }
1051
+ lifecycle {
1052
+ retention: 90d
1053
+ decay-half-life: 30d
1054
+ consolidation: 0.85
1055
+ contradiction: overwrite
1056
+ audit-log: true
1057
+ }
1058
+ }
1059
+ }
1060
+ \`\`\`
1061
+ `,
1062
+ },
1063
+ // -------------------------------------------------------------------------
1064
+ // 9b. retrieval
1065
+ // -------------------------------------------------------------------------
1066
+ retrieval: {
1067
+ name: "retrieval",
1068
+ description: "Retrieval strategy -- multi-source memory query planning",
1069
+ content: () => `# retrieval
1070
+
1071
+ The \`retrieval\` block declares a named retrieval strategy within the \`memory {}\` block. A retrieval strategy defines how an agent queries one or more memory stores -- controlling token budgets, scoring weights, retrieval paths, and cache-hit behavior.
1072
+
1073
+ ## Syntax
1074
+
1075
+ \`\`\`at
1076
+ retrieval <id> {
1077
+ sources: [store-id-1, store-id-2]
1078
+ budget: 4096
1079
+
1080
+ scoring {
1081
+ recency-weight: 0.3
1082
+ semantic-weight: 0.5
1083
+ importance-weight: 0.2
1084
+ }
1085
+
1086
+ paths: [semantic, episodic, procedural, graph, hybrid]
1087
+ rerank: true
1088
+ diversity: true
1089
+
1090
+ cache-hit-threshold: 0.92
1091
+ cache-hit-action: <short-circuit | augment | pass-through>
1092
+ }
1093
+ \`\`\`
1094
+
1095
+ ## Fields
1096
+
1097
+ | Field | Type | Required | Description |
1098
+ |-------|------|----------|-------------|
1099
+ | sources | name-list | no | Store IDs this retrieval draws from |
1100
+ | budget | number | no | Token budget for retrieved context |
1101
+ | scoring | sub-block | no | Scoring weight configuration |
1102
+ | paths | name-list | no | Retrieval path types to activate |
1103
+ | rerank | boolean | no | Whether to apply cross-source reranking |
1104
+ | diversity | boolean | no | Whether to enforce diversity across results |
1105
+ | cache-hit-threshold | number | no | Similarity threshold for cache-hit detection (0 to 1) |
1106
+ | cache-hit-action | string | no | Action on cache hit: short-circuit, augment, pass-through |
1107
+
1108
+ ## Sources
1109
+
1110
+ The \`sources\` field lists store IDs declared in the same \`memory {}\` block. The retrieval strategy queries all listed stores and merges results according to the scoring weights.
1111
+
1112
+ \`\`\`at
1113
+ retrieval multi-source {
1114
+ sources: [codebase, session-history, entity-graph]
1115
+ }
1116
+ \`\`\`
1117
+
1118
+ ## Budget
1119
+
1120
+ The \`budget\` field sets a token limit for the total retrieved context injected into the agent's prompt. This prevents context window overflow when querying multiple large stores.
1121
+
1122
+ \`\`\`at
1123
+ retrieval compact {
1124
+ budget: 2048
1125
+ }
1126
+ \`\`\`
1127
+
1128
+ ## Sub-Block: scoring {}
1129
+
1130
+ The \`scoring\` sub-block controls how results from multiple stores are ranked and merged. Weights should sum to 1.0.
1131
+
1132
+ | Field | Type | Description |
1133
+ |-------|------|-------------|
1134
+ | recency-weight | number | Weight for recency in scoring (0 to 1) |
1135
+ | semantic-weight | number | Weight for semantic similarity (0 to 1) |
1136
+ | importance-weight | number | Weight for importance/frequency (0 to 1) |
1137
+
1138
+ \`\`\`at
1139
+ scoring {
1140
+ recency-weight: 0.3
1141
+ semantic-weight: 0.5
1142
+ importance-weight: 0.2
1143
+ }
1144
+ \`\`\`
1145
+
1146
+ ## Paths
1147
+
1148
+ Retrieval paths define which types of memory retrieval are activated. Multiple paths can run in parallel and results are merged.
1149
+
1150
+ | Path | Description |
1151
+ |------|-------------|
1152
+ | semantic | Vector similarity search |
1153
+ | episodic | Temporal event retrieval |
1154
+ | procedural | Workflow/how-to retrieval |
1155
+ | graph | Graph traversal queries |
1156
+ | hybrid | Combined vector + keyword search |
1157
+
1158
+ ## Cache-Hit Threshold and Action
1159
+
1160
+ Memory-gated routing allows the retrieval strategy to short-circuit agent execution when a sufficiently similar memory already exists.
1161
+
1162
+ - **cache-hit-threshold**: A similarity score (0 to 1). If a retrieved memory exceeds this threshold, it is considered a cache hit.
1163
+ - **cache-hit-action**: What to do on a cache hit:
1164
+ - \`short-circuit\` -- return the cached result directly, skip agent execution
1165
+ - \`augment\` -- inject the cached result as additional context alongside the query
1166
+ - \`pass-through\` -- ignore the cache hit, proceed normally
1167
+
1168
+ \`\`\`at
1169
+ retrieval with-cache {
1170
+ cache-hit-threshold: 0.92
1171
+ cache-hit-action: short-circuit
1172
+ }
1173
+ \`\`\`
1174
+
1175
+ ## Agent Reference
1176
+
1177
+ Agents reference a retrieval strategy by ID:
1178
+
1179
+ \`\`\`at
1180
+ agent researcher {
1181
+ retrieval: default
1182
+ memory: [codebase, session-history]
1183
+ }
1184
+ \`\`\`
1185
+
1186
+ ## Validation Rules
1187
+
1188
+ - Retrieval \`sources\` must reference valid store IDs declared in the same \`memory {}\` block.
1189
+ - Agent \`retrieval\` field must reference a valid retrieval ID.
1190
+
1191
+ ## Example
1192
+
1193
+ \`\`\`at
1194
+ memory {
1195
+ store codebase {
1196
+ type: semantic
1197
+ backend: lancedb
1198
+ scope: global
1199
+ embedding {
1200
+ provider: ollama
1201
+ model: "nomic-embed-text"
1202
+ dimensions: 768
1203
+ }
1204
+ }
1205
+
1206
+ store conversations {
1207
+ type: episodic
1208
+ backend: sqlite
1209
+ scope: session
1210
+ }
1211
+
1212
+ retrieval balanced {
1213
+ sources: [codebase, conversations]
1214
+ budget: 4096
1215
+ scoring {
1216
+ recency-weight: 0.3
1217
+ semantic-weight: 0.5
1218
+ importance-weight: 0.2
1219
+ }
1220
+ paths: [semantic, episodic]
1221
+ rerank: true
1222
+ diversity: true
1223
+ cache-hit-threshold: 0.92
1224
+ cache-hit-action: augment
1225
+ }
1226
+ }
1227
+ \`\`\`
1228
+ `,
1229
+ },
1230
+ // -------------------------------------------------------------------------
1231
+ // 9c. lifecycle
1232
+ // -------------------------------------------------------------------------
1233
+ lifecycle: {
1234
+ name: "lifecycle",
1235
+ description: "Memory lifecycle management -- retention, decay, contradiction resolution",
1236
+ content: () => `# lifecycle
1237
+
1238
+ The \`lifecycle {}\` sub-block within a \`store\` declaration configures memory retention, decay, consolidation, and contradiction resolution policies.
1239
+
1240
+ ## Syntax
1241
+
1242
+ \`\`\`at
1243
+ lifecycle {
1244
+ retention: 90d
1245
+ decay-half-life: 30d
1246
+ consolidation: 0.85
1247
+ contradiction: <overwrite | preserve | bi-temporal>
1248
+ audit-log: true
1249
+ }
1250
+ \`\`\`
1251
+
1252
+ ## Fields
1253
+
1254
+ | Field | Type | Required | Description |
1255
+ |-------|------|----------|-------------|
1256
+ | retention | string | no | How long memories are kept (duration string) |
1257
+ | decay-half-life | string | no | Half-life for memory decay scoring |
1258
+ | consolidation | number | no | Threshold (0 to 1) for merging similar memories |
1259
+ | contradiction | string | no | Strategy for handling contradictory information |
1260
+ | audit-log | boolean | no | Whether to log all memory mutations |
1261
+
1262
+ ## Retention
1263
+
1264
+ The \`retention\` field accepts duration strings that specify how long memories are kept before expiration:
1265
+
1266
+ | Format | Example | Meaning |
1267
+ |--------|---------|---------|
1268
+ | Days | 90d | 90 days |
1269
+ | Weeks | 4w | 4 weeks |
1270
+ | Months | 6m | 6 months |
1271
+ | Years | 1y | 1 year |
1272
+ | Forever | forever | Never expires |
1273
+
1274
+ Expired memories are eligible for garbage collection by the binding runtime.
1275
+
1276
+ ## Decay Half-Life
1277
+
1278
+ The \`decay-half-life\` field controls how quickly memory relevance scores decay over time. A shorter half-life means older memories lose relevance faster.
1279
+
1280
+ \`\`\`at
1281
+ lifecycle {
1282
+ decay-half-life: 30d # relevance halves every 30 days
1283
+ }
1284
+ \`\`\`
1285
+
1286
+ This is used in scoring calculations -- retrieval strategies weight results by recency using the decay curve.
1287
+
1288
+ ## Consolidation Threshold
1289
+
1290
+ The \`consolidation\` field sets a similarity threshold (0 to 1) for merging similar memories. When two memories exceed this similarity, they are candidates for consolidation into a single, stronger memory.
1291
+
1292
+ \`\`\`at
1293
+ lifecycle {
1294
+ consolidation: 0.85 # merge memories that are 85%+ similar
1295
+ }
1296
+ \`\`\`
1297
+
1298
+ ## Contradiction Strategies
1299
+
1300
+ The \`contradiction\` field determines how the system handles new information that conflicts with existing memories:
1301
+
1302
+ | Strategy | Behavior |
1303
+ |----------|----------|
1304
+ | overwrite | Replace the old memory with the new one. Simplest approach -- last write wins. |
1305
+ | preserve | Keep both memories. The system maintains conflicting facts and lets the agent or user decide. |
1306
+ | bi-temporal | Track both the "valid time" (when the fact was true) and "transaction time" (when it was recorded). Enables point-in-time queries and full audit trails. |
1307
+
1308
+ \`\`\`at
1309
+ # Mem0-style: always overwrite
1310
+ lifecycle {
1311
+ contradiction: overwrite
1312
+ }
1313
+
1314
+ # Letta-style: preserve conflicting facts
1315
+ lifecycle {
1316
+ contradiction: preserve
1317
+ }
1318
+
1319
+ # Zep/Graphiti-style: full temporal tracking
1320
+ lifecycle {
1321
+ contradiction: bi-temporal
1322
+ }
1323
+ \`\`\`
1324
+
1325
+ ## Audit Logging
1326
+
1327
+ When \`audit-log: true\`, all memory mutations (creates, updates, deletes, consolidations) are logged for debugging and compliance.
1328
+
1329
+ \`\`\`at
1330
+ lifecycle {
1331
+ audit-log: true
1332
+ }
1333
+ \`\`\`
1334
+
1335
+ ## Example
1336
+
1337
+ \`\`\`at
1338
+ store project-knowledge {
1339
+ type: semantic
1340
+ backend: lancedb
1341
+ scope: global
1342
+ lifecycle {
1343
+ retention: 1y
1344
+ decay-half-life: 60d
1345
+ consolidation: 0.9
1346
+ contradiction: bi-temporal
1347
+ audit-log: true
1348
+ }
1349
+ }
1350
+ \`\`\`
1351
+ `,
1352
+ },
1353
+ // -------------------------------------------------------------------------
1354
+ // 9d. embedding
1355
+ // -------------------------------------------------------------------------
1356
+ embedding: {
1357
+ name: "embedding",
1358
+ description: "Embedding configuration -- providers, models, dimensions",
1359
+ content: () => `# embedding
1360
+
1361
+ The \`embedding {}\` sub-block within a \`store\` declaration configures the embedding model used to vectorize content. It specifies the provider, model, vector dimensions, and optional endpoint.
1362
+
1363
+ ## Syntax
1364
+
1365
+ \`\`\`at
1366
+ embedding {
1367
+ provider: <ollama | local | voyage | openai | gemini>
1368
+ model: "nomic-embed-text"
1369
+ dimensions: 768
1370
+ endpoint: secret "EMBEDDING_URL"
1371
+ }
1372
+ \`\`\`
1373
+
1374
+ ## Fields
1375
+
1376
+ | Field | Type | Required | Description |
1377
+ |-------|------|----------|-------------|
1378
+ | provider | string | no | Embedding provider |
1379
+ | model | string | no | Model identifier for embedding generation |
1380
+ | dimensions | number | no | Vector dimensions produced by the model |
1381
+ | endpoint | string | no | Endpoint URL or \`secret "..."\` reference |
1382
+
1383
+ ## Providers
1384
+
1385
+ | Provider | Type | Description |
1386
+ |----------|------|-------------|
1387
+ | ollama | local | Local inference via Ollama. Zero-cost, no data leaves the machine. |
1388
+ | local | local | Generic local embedding (e.g. ONNX runtime, sentence-transformers). |
1389
+ | voyage | cloud | Voyage AI embedding models. High quality for code and text. |
1390
+ | openai | cloud | OpenAI embedding models (text-embedding-3-small, text-embedding-3-large). |
1391
+ | gemini | cloud | Google Gemini embedding models. |
1392
+
1393
+ ## Model Selection
1394
+
1395
+ The \`model\` field accepts any model identifier supported by the chosen provider:
1396
+
1397
+ \`\`\`at
1398
+ # Local with Ollama
1399
+ embedding {
1400
+ provider: ollama
1401
+ model: "nomic-embed-text"
1402
+ dimensions: 768
1403
+ }
1404
+
1405
+ # OpenAI cloud
1406
+ embedding {
1407
+ provider: openai
1408
+ model: "text-embedding-3-small"
1409
+ dimensions: 1536
1410
+ }
1411
+
1412
+ # Voyage (optimized for code)
1413
+ embedding {
1414
+ provider: voyage
1415
+ model: "voyage-code-3"
1416
+ dimensions: 1024
1417
+ }
1418
+ \`\`\`
1419
+
1420
+ ## Dimensions
1421
+
1422
+ The \`dimensions\` field specifies the vector size produced by the embedding model. This must match the model's output dimensions:
1423
+
1424
+ | Model | Provider | Dimensions |
1425
+ |-------|----------|------------|
1426
+ | nomic-embed-text | ollama | 768 |
1427
+ | text-embedding-3-small | openai | 1536 |
1428
+ | text-embedding-3-large | openai | 3072 |
1429
+ | voyage-code-3 | voyage | 1024 |
1430
+
1431
+ ## Local vs Cloud Embedding
1432
+
1433
+ **Local embedding** (ollama, local) runs on the developer's machine:
1434
+ - Zero cost, no API keys needed
1435
+ - Data never leaves the machine
1436
+ - Suitable for development and sensitive codebases
1437
+ - Requires model download and local compute
1438
+
1439
+ **Cloud embedding** (voyage, openai, gemini) calls external APIs:
1440
+ - Higher quality models available
1441
+ - Requires API keys (use \`secret "..."\` modifier)
1442
+ - Per-token pricing
1443
+ - Suitable for production deployments
1444
+
1445
+ \`\`\`at
1446
+ # Local-first development setup
1447
+ embedding {
1448
+ provider: ollama
1449
+ model: "nomic-embed-text"
1450
+ dimensions: 768
1451
+ }
1452
+
1453
+ # Production cloud setup
1454
+ embedding {
1455
+ provider: openai
1456
+ model: "text-embedding-3-small"
1457
+ dimensions: 1536
1458
+ endpoint: secret "OPENAI_API_KEY"
1459
+ }
1460
+ \`\`\`
1461
+
1462
+ ## Example
1463
+
1464
+ \`\`\`at
1465
+ store documentation {
1466
+ type: semantic
1467
+ backend: lancedb
1468
+ scope: global
1469
+ path: ".memory/docs/"
1470
+ embedding {
1471
+ provider: ollama
1472
+ model: "nomic-embed-text"
1473
+ dimensions: 768
1474
+ }
1475
+ search {
1476
+ strategy: vector
1477
+ top-k: 5
1478
+ }
1479
+ }
1480
+ \`\`\`
755
1481
  `,
756
1482
  },
757
1483
  // -------------------------------------------------------------------------
@@ -2270,10 +2996,10 @@ import reviewer from ./review.at sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e
2270
2996
  // -------------------------------------------------------------------------
2271
2997
  validation: {
2272
2998
  name: "validation",
2273
- description: "All 29 validation rules with descriptions and fixes",
2999
+ description: "All validation rules with descriptions and fixes",
2274
3000
  content: () => `# validation
2275
3001
 
2276
- AgenTopology enforces 29 validation rules during parsing. Errors prevent compilation; warnings are informational.
3002
+ AgenTopology enforces 82 validation rules during parsing. Errors prevent compilation; warnings are informational.
2277
3003
 
2278
3004
  ## Rules
2279
3005