Skip to main content

git_internal/internal/object/
mod.rs

1//! Object model definitions for Git blobs, trees, commits, tags, and
2//! AI workflow objects.
3//!
4//! This module is the storage-layer contract for `git-internal`.
5//! Git-native objects (`Blob`, `Tree`, `Commit`, `Tag`) model repository
6//! content, while the AI objects model immutable workflow history that
7//! Libra orchestrates on top.
8//!
9//! # How Libra should use this module
10//!
11//! Libra should treat every AI object here as an immutable record:
12//!
13//! - construct the object in memory,
14//! - populate optional fields before persistence,
15//! - persist it once,
16//! - derive current state later from object history plus Libra
17//!   projections.
18//!
19//! Libra should not store scheduler state, selected heads, active UI
20//! focus, or query caches in these objects. Those belong to Libra's own
21//! runtime and index layer.
22//!
23//! AI workflow objects are split into three layers:
24//!
25//! - **Snapshot objects** in `git-internal` answer "what was the stored
26//!   fact at this revision?"
27//! - **Event objects** in `git-internal` answer "what happened later?"
28//! - **Libra projections** answer "what is the system's current view?"
29//!
30//! # Relationship Design Standard
31//!
32//! Relationship fields follow a simple storage rule:
33//!
34//! - Store the canonical ownership edge on the child object when the
35//!   relationship is a historical fact.
36//! - Low-frequency, strongly aggregated relationships that benefit
37//!   from fast parent-to-children traversal may additionally keep a
38//!   reverse convenience link.
39//! - High-frequency, high-cardinality, event-stream relationships
40//!   should remain single-directional to avoid turning parent objects
41//!   into rewrite hotspots.
42//!
43//! # Three-Layer Design
44//!
45//! ```text
46//! +------------------------------------------------------------------+
47//! | Libra projection / runtime                                       |
48//! |------------------------------------------------------------------|
49//! | thread heads / selected_plan_id / active_run / scheduler state   |
50//! | live context window / UI focus / query indexes                   |
51//! +--------------------------------+---------------------------------+
52//!                                  |
53//!                                  v
54//! +------------------------------------------------------------------+
55//! | git-internal event objects                                        |
56//! |------------------------------------------------------------------|
57//! | IntentEvent / TaskEvent / RunEvent / PlanStepEvent / RunUsage    |
58//! | ToolInvocation / Evidence / Decision / ContextFrame              |
59//! +--------------------------------+---------------------------------+
60//!                                  |
61//!                                  v
62//! +------------------------------------------------------------------+
63//! | git-internal snapshot objects                                     |
64//! |------------------------------------------------------------------|
65//! | Intent / Plan / Task / Run / PatchSet / ContextSnapshot          |
66//! | Provenance                                                       |
67//! +------------------------------------------------------------------+
68//! ```
69//!
70//! # Main Object Relationships
71//!
72//! ```text
73//! Snapshot layer
74//! ==============
75//!
76//! Intent --parents----------------------------> Intent
77//! Intent --analysis_context_frames-----------> ContextFrame
78//! Plan   --intent-----------------------------> Intent
79//! Plan   --context_frames---------------------> ContextFrame
80//! Plan   --parents----------------------------> Plan
81//! Task   --intent?----------------------------> Intent
82//! Task   --parent?----------------------------> Task
83//! Task   --origin_step_id?-------------------> PlanStep.step_id
84//! Run    --task-------------------------------> Task
85//! Run    --plan?------------------------------> Plan
86//! Run    --snapshot?--------------------------> ContextSnapshot
87//! PatchSet   --run----------------------------> Run
88//! Provenance --run_id-------------------------> Run
89//!
90//! Event layer
91//! ===========
92//!
93//! IntentEvent   --intent_id-------------------> Intent
94//! IntentEvent   --next_intent_id?-------------> Intent
95//! ContextFrame  --intent_id?------------------> Intent
96//! TaskEvent     --task_id---------------------> Task
97//! RunEvent      --run_id----------------------> Run
98//! RunUsage      --run_id----------------------> Run
99//! PlanStepEvent --plan_id + step_id + run_id-> Plan / Run / PlanStep
100//! ToolInvocation--run_id----------------------> Run
101//! Evidence      --run_id / patchset_id?-------> Run / PatchSet
102//! Decision      --run_id / chosen_patchset_id?> Run / PatchSet
103//! ContextFrame  --run_id? / plan_id? / step_id?> Run / Plan / PlanStep
104//! ```
105//!
106//! # Libra read / write pattern
107//!
108//! A typical Libra call flow looks like this:
109//!
110//! 1. write snapshot objects when a new immutable revision is defined
111//!    (`Intent`, `Plan`, `Task`, `Run`, `PatchSet`, `ContextSnapshot`,
112//!    `Provenance`);
113//! 2. append event objects as execution progresses
114//!    (`IntentEvent`, `TaskEvent`, `RunEvent`, `PlanStepEvent`,
115//!    `RunUsage`, `ToolInvocation`, `Evidence`, `Decision`,
116//!    `ContextFrame`);
117//! 3. rebuild current state in Libra from those immutable objects plus
118//!    its own `Thread`, `Scheduler`, `UI`, and `Query Index`
119//!    projections.
120//!
121//! ## Object Relationship Summary
122//!
123//! | From | Field | To | Cardinality |
124//! |------|-------|----|-------------|
125//! | Intent | `parents` | Intent | 0..N |
126//! | Intent | `analysis_context_frames` | ContextFrame | 0..N |
127//! | Plan | `intent` | Intent | 1 canonical |
128//! | Plan | `parents` | Plan | 0..N |
129//! | Plan | `context_frames` | ContextFrame | 0..N |
130//! | Task | `parent` | Task | 0..1 |
131//! | Task | `intent` | Intent | 0..1 |
132//! | Task | `origin_step_id` | PlanStep.step_id | 0..1 |
133//! | Task | `dependencies` | Task | 0..N |
134//! | Run | `task` | Task | 1 |
135//! | Run | `plan` | Plan | 0..1 |
136//! | Run | `snapshot` | ContextSnapshot | 0..1 |
137//! | PatchSet | `run` | Run | 1 |
138//! | Provenance | `run_id` | Run | 1 |
139//! | IntentEvent | `intent_id` | Intent | 1 |
140//! | IntentEvent | `next_intent_id` | Intent | 0..1 recommended follow-up |
141//! | ContextFrame | `intent_id` | Intent | 0..1 |
142//! | TaskEvent | `task_id` | Task | 1 |
143//! | RunEvent | `run_id` | Run | 1 |
144//! | RunUsage | `run_id` | Run | 1 |
145//! | PlanStepEvent | `plan_id` | Plan | 1 |
146//! | PlanStepEvent | `step_id` | PlanStep.step_id | 1 |
147//! | PlanStepEvent | `run_id` | Run | 1 |
148//! | ToolInvocation | `run_id` | Run | 1 |
149//! | Evidence | `run_id` | Run | 1 |
150//! | Evidence | `patchset_id` | PatchSet | 0..1 |
151//! | Decision | `run_id` | Run | 1 |
152//! | Decision | `chosen_patchset_id` | PatchSet | 0..1 |
153//! | ContextFrame | `run_id` | Run | 0..1 |
154//! | ContextFrame | `plan_id` | Plan | 0..1 |
155//! | ContextFrame | `step_id` | PlanStep.step_id | 0..1 |
156//!
157pub mod blob;
158pub mod commit;
159pub mod context;
160pub mod context_frame;
161pub mod decision;
162pub mod evidence;
163pub mod integrity;
164pub mod intent;
165pub mod intent_event;
166pub mod note;
167pub mod patchset;
168pub mod plan;
169pub mod plan_step_event;
170pub mod provenance;
171pub mod run;
172pub mod run_event;
173pub mod run_usage;
174pub mod signature;
175pub mod tag;
176pub mod task;
177pub mod task_event;
178pub mod tool;
179pub mod tree;
180pub mod types;
181pub mod utils;
182
183use std::{
184    fmt::Display,
185    io::{BufRead, Read},
186};
187
188use crate::{
189    errors::GitError,
190    hash::ObjectHash,
191    internal::{object::types::ObjectType, zlib::stream::inflate::ReadBoxed},
192};
193
194/// **The Object Trait**
195/// Defines the common interface for all Git object types, including blobs, trees, commits, and tags.
196pub trait ObjectTrait: Send + Sync + Display {
197    /// Creates a new object from a byte slice.
198    fn from_bytes(data: &[u8], hash: ObjectHash) -> Result<Self, GitError>
199    where
200        Self: Sized;
201
202    /// Generate a new Object from a `ReadBoxed<BufRead>`.
203    /// the input size,is only for new a vec with directive space allocation
204    /// the input data stream and output object should be plain base object .
205    fn from_buf_read<R: BufRead>(read: &mut ReadBoxed<R>, size: usize) -> Self
206    where
207        Self: Sized,
208    {
209        let mut content: Vec<u8> = Vec::with_capacity(size);
210        read.read_to_end(&mut content).unwrap();
211        let digest = read.hash.clone().finalize();
212        let hash = ObjectHash::from_bytes(&digest).unwrap();
213        Self::from_bytes(&content, hash).unwrap()
214    }
215
216    /// Returns the type of the object.
217    fn get_type(&self) -> ObjectType;
218
219    fn get_size(&self) -> usize;
220
221    fn to_data(&self) -> Result<Vec<u8>, GitError>;
222
223    fn object_hash(&self) -> Result<ObjectHash, GitError> {
224        let data = self.to_data()?;
225        Ok(ObjectHash::from_type_and_data(self.get_type(), &data))
226    }
227}