Skip to main content

agentstatedeveloper_core/
paths.rs

1//! ASG path convention for ASD data.
2//!
3//! All ASD state lives under `/asd/v1/` inside an ASG repository.
4
5pub const ASD_ROOT: &str = "/asd/v1";
6
7pub fn clean(p: &str) -> String {
8    p.trim_start_matches('/').replace("//", "/")
9}
10
11pub fn code_path(lang: &str, file: &str, symbol_fp: &str) -> String {
12    format!("{}/code/{}/{}/{}", ASD_ROOT, lang, clean(file), symbol_fp)
13}
14
15pub fn qname_index_path(qname: &str) -> String {
16    format!("{}/index/by-qname/{}", ASD_ROOT, qname)
17}
18
19pub fn callers_path(symbol_id: &str) -> String {
20    format!("{}/index/callers/{}", ASD_ROOT, symbol_id)
21}
22
23pub fn callees_path(symbol_id: &str) -> String {
24    format!("{}/index/callees/{}", ASD_ROOT, symbol_id)
25}
26
27pub fn effects_reverse_index_path(effect: &str, symbol_id: &str) -> String {
28    format!("{}/index/effects-rev/{}/{}", ASD_ROOT, effect, symbol_id)
29}
30
31// ---------------------------------------------------------------------------
32// Cross-service edge paths (t-002)
33//
34// Service endpoints (HTTP routes/clients, pub-sub emit/listen) are indexed by a
35// hash of their normalized *contract key* so endpoints from any repo that share
36// a contract collapse under one prefix — the cross-service analog of the
37// effects-rev reverse index. The contract hash (not the raw key) is used as a
38// path segment to keep keys path-safe (raw keys contain '/', ':', spaces).
39// ---------------------------------------------------------------------------
40
41/// All endpoints (local + imported) for one contract live under this prefix.
42pub fn endpoint_contract_prefix(contract_hash: &str) -> String {
43    format!("{}/index/endpoints/{}", ASD_ROOT, contract_hash)
44}
45
46/// A single endpoint record, namespaced by repo_id so same-contract endpoints
47/// from different repos never collide.
48pub fn endpoint_path(contract_hash: &str, repo_id: &str, symbol_id: &str) -> String {
49    format!(
50        "{}/index/endpoints/{}/{}/{}",
51        ASD_ROOT, contract_hash, repo_id, symbol_id
52    )
53}
54
55/// This repo's exported service manifest (the unit other repos import to match
56/// contracts cross-repo).
57pub fn service_manifest_path() -> String {
58    format!("{}/meta/service-manifest", ASD_ROOT)
59}
60
61/// Per-edge runtime-confidence sidecar (t-013), keyed by from→to symbol id.
62/// Kept separate from the hot-path callees/callers lists.
63pub fn edge_evidence_path(from_symbol_id: &str, to_symbol_id: &str) -> String {
64    format!(
65        "{}/index/edge-evidence/{}/{}",
66        ASD_ROOT, from_symbol_id, to_symbol_id
67    )
68}
69
70/// Prefix holding all outgoing edge-evidence records for `from_symbol_id`.
71pub fn edge_evidence_from_prefix(from_symbol_id: &str) -> String {
72    format!("{}/index/edge-evidence/{}", ASD_ROOT, from_symbol_id)
73}
74
75/// Root of the ledger tree: `<root>/<symbol_id>/<entry_id>`.
76pub fn ledger_root() -> String {
77    format!("{}/ledger", ASD_ROOT)
78}
79
80pub fn ledger_entry_path(symbol_id: &str, entry_id: &str) -> String {
81    format!("{}/ledger/{}/{}", ASD_ROOT, symbol_id, entry_id)
82}
83
84pub fn ledger_symbol_path(symbol_id: &str) -> String {
85    format!("{}/ledger/{}", ASD_ROOT, symbol_id)
86}
87
88pub fn effects_path(symbol_id: &str) -> String {
89    format!("{}/effects/{}", ASD_ROOT, symbol_id)
90}
91
92pub fn traces_path(symbol_id: &str, trace_id: &str) -> String {
93    format!("{}/traces/{}/{}", ASD_ROOT, symbol_id, trace_id)
94}
95
96pub fn file_meta_path(file: &str) -> String {
97    format!("{}/meta/files/{}", ASD_ROOT, clean(file))
98}
99
100pub fn schema_version_path() -> String {
101    format!("{}/meta/schema-version", ASD_ROOT)
102}
103
104pub fn rebind_path(from_symbol_id: &str) -> String {
105    format!("{}/rebinds/{}", ASD_ROOT, from_symbol_id)
106}
107
108/// Reverse index: maps entry_id → symbol_id for O(1) find_entry in ratify.
109/// Kept under a separate prefix (ledger-idx/) to avoid polluting tree walks
110/// over the main ledger/ subtree.
111pub fn ledger_index_root() -> String {
112    format!("{}/ledger-idx", ASD_ROOT)
113}
114
115pub fn ledger_entry_index_path(entry_id: &str) -> String {
116    format!("{}/ledger-idx/{}", ASD_ROOT, entry_id)
117}
118
119// ---------------------------------------------------------------------------
120// Scratchpad paths
121// ---------------------------------------------------------------------------
122
123/// Root prefix for all scratch entries. Flat layout (not symbol-nested)
124/// because scratch has multiple scoping dimensions (symbol, workflow, session).
125pub fn scratch_root() -> &'static str {
126    "/asd/v1/scratch"
127}
128
129/// Path for a single scratch entry.
130pub fn scratch_entry_path(scratch_id: &str) -> String {
131    format!("/asd/v1/scratch/{}", scratch_id)
132}
133
134// ---------------------------------------------------------------------------
135// Feedback paths
136// ---------------------------------------------------------------------------
137
138pub fn feedback_entry_path(symbol_id: &str, entry_id: &str) -> String {
139    format!("{}/feedback/{}/{}", ASD_ROOT, symbol_id, entry_id)
140}
141
142pub fn feedback_symbol_path(symbol_id: &str) -> String {
143    format!("{}/feedback/{}", ASD_ROOT, symbol_id)
144}