NeoGraph 0.16.0
A C++20 Graph Agent Engine Library — LangGraph for C++
Loading...
Searching...
No Matches
evidence_ledger.h
Go to the documentation of this file.
1
10#pragma once
11
12#include <neograph/api.h>
13#include <neograph/json.h>
14
15#include <cstdint>
16#include <optional>
17#include <string>
18#include <string_view>
19#include <memory>
20#include <limits>
21#include <vector>
22#include <utility>
23
24namespace neograph::research {
25
26enum class ResearchTaskKind : std::uint8_t {
27 PrimaryExtraction,
28 IndependentReview,
29 Reproduction,
30 Rebuttal,
31 Reconciliation,
32};
33
34NEOGRAPH_API std::string_view to_string(ResearchTaskKind kind) noexcept;
35NEOGRAPH_API ResearchTaskKind research_task_kind_from_string(std::string_view value);
36
37enum class ResearchTaskState : std::uint8_t {
38 Ready,
39 Leased,
40 Published,
42};
43
44NEOGRAPH_API std::string_view to_string(ResearchTaskState state) noexcept;
45NEOGRAPH_API ResearchTaskState research_task_state_from_string(std::string_view value);
46
47enum class EvidencePolarity : std::uint8_t {
48 Supports,
49 Contradicts,
50 Inconclusive,
51 NoSupport,
52};
53
54NEOGRAPH_API std::string_view to_string(EvidencePolarity polarity) noexcept;
55NEOGRAPH_API EvidencePolarity evidence_polarity_from_string(std::string_view value);
56
57enum class SourceLifecycle : std::uint8_t {
58 Unclaimed,
59 Claimed,
60 Extracted,
61 Reviewed,
62 Corroborated,
63 Contradicted,
64 Inconclusive,
65};
66
67NEOGRAPH_API std::string_view to_string(SourceLifecycle state) noexcept;
68
69enum class ClaimResolutionKind : std::uint8_t {
70 Unresolved,
71 Corroborated,
72 Contradicted,
73 Inconclusive,
74 ReconciliationRequired,
75 HumanDecisionRequired,
76};
77
78NEOGRAPH_API std::string_view to_string(ClaimResolutionKind kind) noexcept;
79
80enum class EvidencePublishResult : std::uint8_t {
81 Published,
82 Duplicate,
83};
84
89struct NEOGRAPH_API SourceIdentity {
90 std::uint32_t schema_version = 1;
91 std::string source_id;
92 std::string canonical_locator;
93 std::string version;
94 std::string content_hash;
95 std::vector<std::string> aliases;
96 json metadata = json::object();
97
98 bool operator==(const SourceIdentity&) const = default;
99};
100
107struct NEOGRAPH_API ResearchTaskSpec {
108 std::uint32_t schema_version = 1;
109 std::string task_id;
110 std::string objective_id;
111 std::string source_id;
112 std::string claim_id;
113 std::string owner_scope;
114 std::string scope;
115 ResearchTaskKind kind = ResearchTaskKind::PrimaryExtraction;
116 std::string replication_of_task_id;
117 bool intentional_replication = false;
118 std::uint64_t lease_duration_ms = 60'000;
119 json requirements = json::object();
120
121 bool operator==(const ResearchTaskSpec&) const = default;
122};
123
125struct NEOGRAPH_API ResearchTask {
126 ResearchTaskSpec spec;
127 ResearchTaskState state = ResearchTaskState::Ready;
128 std::uint64_t generation = 0;
129 std::string lease_id;
130 std::string leased_by;
131 std::uint64_t lease_expires_at_unix_ms = 0;
133 std::string board_id;
134 std::string published_artifact_id;
135
136 bool operator==(const ResearchTask&) const = default;
137};
138
140struct NEOGRAPH_API ResearchLeaseRequest {
141 std::string task_id;
142 std::string lease_id;
143 std::string worker_id;
144 std::string owner_scope;
145 std::uint64_t now_unix_ms = 0;
150 std::string board_id;
151 std::uint32_t board_max_active_leases = 0;
152 std::uint64_t board_max_cost_microunits = std::numeric_limits<std::uint64_t>::max();
153 std::uint64_t cost_microunits = 0;
154
155 bool operator==(const ResearchLeaseRequest&) const = default;
156};
157
159struct NEOGRAPH_API ResearchTaskLease {
160 std::string task_id;
161 std::string lease_id;
162 std::string worker_id;
163 std::string owner_scope;
164 std::uint64_t generation = 0;
165 std::uint64_t expires_at_unix_ms = 0;
166 std::string board_id;
167
168 bool operator==(const ResearchTaskLease&) const = default;
169};
170
171
178struct NEOGRAPH_API EvidenceArtifact {
179 std::uint32_t schema_version = 1;
180 std::string artifact_id;
181 std::string task_id;
182 std::string source_id;
183 std::string claim_id;
184 std::string owner_scope;
185 std::string source_version;
186 std::string source_content_hash;
187 EvidencePolarity polarity = EvidencePolarity::Inconclusive;
188 std::string evidence_locator;
189 std::string observation;
190 std::string searched_scope;
191 json conditions = json::object();
192 json applicability = json::object();
193 json uncertainty = json::object();
194 std::vector<std::string> limitations;
195 std::vector<std::string> contradictions;
196 std::string recommended_next_task;
197 double confidence = 0.0;
198 std::string worker_id;
199 std::string model_id;
200 std::string tool_id;
201 std::string program_version_id;
202 std::string program_run_id;
203 std::string a2a_message_id;
204 json provenance = json::object();
205
206 bool operator==(const EvidenceArtifact&) const = default;
207};
208
210struct NEOGRAPH_API ClaimResolution {
211 std::string claim_id;
212 ClaimResolutionKind kind = ClaimResolutionKind::Unresolved;
213 std::vector<std::string> supporting_artifact_ids;
214 std::vector<std::string> contradicting_artifact_ids;
215 std::vector<std::string> inconclusive_artifact_ids;
216 std::optional<ResearchTaskKind> recommended_next_task;
217
218 bool operator==(const ClaimResolution&) const = default;
219};
220
227class NEOGRAPH_API EvidenceLedger {
228public:
229 virtual ~EvidenceLedger() = default;
230
231 virtual void register_source(SourceIdentity source) = 0;
232 [[nodiscard]] virtual std::optional<SourceIdentity>
233 source(std::string_view source_id) const = 0;
234
235 virtual void create_task(ResearchTaskSpec task) = 0;
236 [[nodiscard]] virtual std::optional<ResearchTask>
237 task(std::string_view owner_scope, std::string_view task_id) const = 0;
238
240 [[nodiscard]] virtual std::vector<ResearchTask>
241 tasks(std::string_view owner_scope, bool include_terminal) const = 0;
247 [[nodiscard]] virtual std::optional<ResearchTaskLease>
249
251 [[nodiscard]] virtual bool renew_lease(const ResearchTaskLease& lease,
252 std::uint64_t now_unix_ms) = 0;
253
255 [[nodiscard]] virtual std::vector<std::string>
256 expire_leases(std::string_view owner_scope, std::uint64_t now_unix_ms) = 0;
257
263 [[nodiscard]] virtual EvidencePublishResult
265 std::uint64_t now_unix_ms) = 0;
266
267 [[nodiscard]] virtual std::vector<EvidenceArtifact>
268 artifacts_for_claim(std::string_view owner_scope, std::string_view claim_id) const = 0;
269 [[nodiscard]] virtual SourceLifecycle source_lifecycle(std::string_view owner_scope,
270 std::string_view source_id,
271 std::uint64_t now_unix_ms) const = 0;
272 [[nodiscard]] virtual ClaimResolution
273 resolve_claim(std::string_view owner_scope, std::string_view claim_id) const = 0;
274};
275
281struct NEOGRAPH_API ResearchTaskBoardBudget {
282 std::uint32_t max_active_leases = 1;
283 std::uint64_t max_cost_microunits = std::numeric_limits<std::uint64_t>::max();
284};
285
295class NEOGRAPH_API ResearchTaskBoard final {
296public:
297 explicit ResearchTaskBoard(EvidenceLedger& ledger) noexcept : ledger_(ledger) {}
298
299 ResearchTaskBoard(const ResearchTaskBoard&) = delete;
300 ResearchTaskBoard& operator=(const ResearchTaskBoard&) = delete;
301
302 void submit(ResearchTaskSpec task) { ledger_.create_task(std::move(task)); }
303
304 [[nodiscard]] std::optional<ResearchTaskLease> acquire_next(
305 std::string_view owner_scope, std::string_view worker_id,
306 std::string_view board_id, std::uint64_t now_unix_ms,
307 ResearchTaskBoardBudget budget = {}) const;
308
309 [[nodiscard]] EvidencePublishResult publish(
310 const ResearchTaskLease& lease, EvidenceArtifact artifact,
311 std::uint64_t now_unix_ms) const {
312 return ledger_.publish(lease, std::move(artifact), now_unix_ms);
313 }
314
315 [[nodiscard]] std::vector<ResearchTask>
316 snapshot(std::string_view owner_scope) const {
317 return ledger_.tasks(owner_scope, true);
318 }
319
320private:
321 EvidenceLedger& ledger_;
322};
323
324} // namespace neograph::research
@ Cancelled
"cancelled" — cancelled via session/cancel.
NEOGRAPH_API export/import macro for shared-library builds.
virtual std::optional< ResearchTaskLease > acquire_lease(ResearchLeaseRequest request)=0
Atomically claims a ready/expired task.
virtual bool renew_lease(const ResearchTaskLease &lease, std::uint64_t now_unix_ms)=0
Extends only the exact live lease generation.
virtual std::vector< std::string > expire_leases(std::string_view owner_scope, std::uint64_t now_unix_ms)=0
Makes this owner's expired leases ready for reassignment.
virtual std::vector< ResearchTask > tasks(std::string_view owner_scope, bool include_terminal) const =0
Returns owner-scoped task snapshots in deterministic task-id order.
virtual EvidencePublishResult publish(const ResearchTaskLease &lease, EvidenceArtifact artifact, std::uint64_t now_unix_ms)=0
Atomically commits evidence and terminally publishes the claimed task.
Deterministic scheduler layered on EvidenceLedger.
Thin C++ RAII wrapper around yyjson with nlohmann-compatible API.
Deterministic planner result derived from committed evidence only.
Caller-supplied idempotency identity for one work claim.
std::string board_id
Optional durable board budget.
Owner-scoped scheduling budget for a durable research board.
Immutable proof that a worker owns the current task generation.
Durable snapshot of one task's current lease or terminal state.
std::string board_id
Board identity that owns the active or last published reservation.
Immutable version-specific source identity.