git_internal/internal/object/mod.rs
1//! Object model definitions for Git blobs, trees, commits, tags, and
2//! supporting traits that let the pack/zlib layers create strongly typed
3//! values from raw bytes.
4//!
5//! AI objects are also defined here, as they are a fundamental part of
6//! the system and need to be accessible across multiple modules without
7//! circular dependencies.
8//!
9//! # AI Object End-to-End Flow
10//!
11//! ```text
12//! ① User input
13//! │
14//! ▼
15//! ② Intent (Draft → Active)
16//! │
17//! ├──▶ ContextPipeline ← seeded with IntentAnalysis frame
18//! │
19//! ▼
20//! ③ Plan (pipeline, fwindow, steps)
21//! │
22//! ├─ PlanStep₀ (inline)
23//! ├─ PlanStep₁ ──task──▶ sub-Task (recursive)
24//! └─ PlanStep₂ (inline)
25//! │
26//! ▼
27//! ④ Task (Draft → Running)
28//! │
29//! ▼
30//! ⑤ Run (Created → Patching → Validating → Completed/Failed)
31//! │
32//! ├──▶ Provenance (1:1, LLM config + token usage)
33//! ├──▶ ContextSnapshot (optional, static context at start)
34//! │
35//! │ ┌─── agent execution loop ───┐
36//! │ │ │
37//! │ │ ⑥ ToolInvocation (1:N) │ ← action log
38//! │ │ │ │
39//! │ │ ▼ │
40//! │ │ ⑦ PatchSet (Proposed) │ ← candidate diff
41//! │ │ │ │
42//! │ │ ▼ │
43//! │ │ ⑧ Evidence (1:N) │ ← test/lint/build
44//! │ │ │ │
45//! │ │ ├─ pass ──────────────┘
46//! │ │ └─ fail → new PatchSet (retry within Run)
47//! │ └─────────────────────────────┘
48//! │
49//! ▼
50//! ⑨ Decision (terminal verdict)
51//! │
52//! ├─ Commit → apply PatchSet, record result_commit
53//! ├─ Retry → create new Run ⑤ for same Task
54//! ├─ Abandon → mark Task as Failed
55//! ├─ Checkpoint → save state, resume later
56//! └─ Rollback → revert applied PatchSet
57//! │
58//! ▼
59//! ⑩ Intent (Completed) ← commit recorded
60//! ```
61//!
62//! ## Steps
63//!
64//! 1. **User input** — the user provides a natural-language request.
65//!
66//! 2. **[`Intent`](intent::Intent)** — captures the raw prompt and the
67//! AI's structured interpretation. Status transitions from `Draft`
68//! (prompt only) to `Active` (analysis complete). Supports
69//! conversational refinement via `parent` chain.
70//!
71//! 3. **[`Plan`](plan::Plan)** — a sequence of
72//! [`PlanStep`](plan::PlanStep)s derived from the Intent. References
73//! a [`ContextPipeline`](pipeline::ContextPipeline) and records the
74//! visible frame range (`fwindow`). Steps track consumed/produced
75//! frames by stable ID (`iframes`/`oframes`). A step may spawn a sub-Task for
76//! recursive decomposition. Plans form a revision chain via
77//! `previous`.
78//!
79//! 4. **[`Task`](task::Task)** — a unit of work with title, constraints,
80//! and acceptance criteria. May link back to its originating Intent.
81//! Accumulates Runs in `runs` (chronological execution history).
82//!
83//! 5. **[`Run`](run::Run)** — a single execution attempt of a Task.
84//! Records the baseline `commit`, the Plan version being executed
85//! (snapshot reference), and the host `environment`. A
86//! [`Provenance`](provenance::Provenance) (1:1) captures the LLM
87//! configuration and token usage.
88//!
89//! 6. **[`ToolInvocation`](tool::ToolInvocation)** — the finest-grained
90//! record: one per tool call (read file, run command, etc.). Forms
91//! a chronological action log for the Run. Tracks file I/O via
92//! `io_footprint`.
93//!
94//! 7. **[`PatchSet`](patchset::PatchSet)** — a candidate diff generated
95//! by the agent. Contains the diff `artifact`, file-level `touched`
96//! summary, and `rationale`. Starts as `Proposed`; transitions to
97//! `Applied` or `Rejected`. Ordering is by position in
98//! `Run.patchsets`.
99//!
100//! 8. **[`Evidence`](evidence::Evidence)** — output of a validation tool
101//! (test, lint, build) run against a PatchSet. One per tool
102//! invocation. Carries `exit_code`, `summary`, and
103//! `report_artifacts`. Feeds into the Decision.
104//!
105//! 9. **[`Decision`](decision::Decision)** — the terminal verdict of a
106//! Run. Selects a PatchSet to apply (`Commit`), retries the Task
107//! (`Retry`), gives up (`Abandon`), saves progress (`Checkpoint`),
108//! or reverts (`Rollback`). Records `rationale` and
109//! `result_commit_sha`.
110//!
111//! 10. **Intent completed** — the orchestrator records the final git
112//! commit in `Intent.commit` and transitions status to `Completed`.
113//!
114//! ## Object Relationship Summary
115//!
116//! | From | Field | To | Cardinality |
117//! |------|-------|----|-------------|
118//! | Intent | `parent` | Intent | 0..1 |
119//! | Intent | `plan` | Plan | 0..1 |
120//! | Plan | `previous` | Plan | 0..1 |
121//! | Plan | `pipeline` | ContextPipeline | 0..1 |
122//! | PlanStep | `task` | Task | 0..1 |
123//! | Task | `parent` | Task | 0..1 |
124//! | Task | `intent` | Intent | 0..1 |
125//! | Task | `runs` | Run | 0..N |
126//! | Task | `dependencies` | Task | 0..N |
127//! | Run | `task` | Task | 1 |
128//! | Run | `plan` | Plan | 0..1 |
129//! | Run | `snapshot` | ContextSnapshot | 0..1 |
130//! | Run | `patchsets` | PatchSet | 0..N |
131//! | PatchSet | `run` | Run | 1 |
132//! | Evidence | `run_id` | Run | 1 |
133//! | Evidence | `patchset_id` | PatchSet | 0..1 |
134//! | Decision | `run_id` | Run | 1 |
135//! | Decision | `chosen_patchset_id` | PatchSet | 0..1 |
136//! | Provenance | `run_id` | Run | 1 |
137//! | ToolInvocation | `run_id` | Run | 1 |
138//!
139pub mod blob;
140pub mod commit;
141pub mod context;
142pub mod decision;
143pub mod evidence;
144pub mod integrity;
145pub mod intent;
146pub mod note;
147pub mod patchset;
148pub mod pipeline;
149pub mod plan;
150pub mod provenance;
151pub mod run;
152pub mod signature;
153pub mod tag;
154pub mod task;
155pub mod tool;
156pub mod tree;
157pub mod types;
158pub mod utils;
159
160use std::{
161 fmt::Display,
162 io::{BufRead, Read},
163};
164
165use crate::{
166 errors::GitError,
167 hash::ObjectHash,
168 internal::{object::types::ObjectType, zlib::stream::inflate::ReadBoxed},
169};
170
171/// **The Object Trait**
172/// Defines the common interface for all Git object types, including blobs, trees, commits, and tags.
173pub trait ObjectTrait: Send + Sync + Display {
174 /// Creates a new object from a byte slice.
175 fn from_bytes(data: &[u8], hash: ObjectHash) -> Result<Self, GitError>
176 where
177 Self: Sized;
178
179 /// Generate a new Object from a `ReadBoxed<BufRead>`.
180 /// the input size,is only for new a vec with directive space allocation
181 /// the input data stream and output object should be plain base object .
182 fn from_buf_read<R: BufRead>(read: &mut ReadBoxed<R>, size: usize) -> Self
183 where
184 Self: Sized,
185 {
186 let mut content: Vec<u8> = Vec::with_capacity(size);
187 read.read_to_end(&mut content).unwrap();
188 let digest = read.hash.clone().finalize();
189 let hash = ObjectHash::from_bytes(&digest).unwrap();
190 Self::from_bytes(&content, hash).unwrap()
191 }
192
193 /// Returns the type of the object.
194 fn get_type(&self) -> ObjectType;
195
196 fn get_size(&self) -> usize;
197
198 fn to_data(&self) -> Result<Vec<u8>, GitError>;
199
200 /// Computes the object hash from serialized data.
201 ///
202 /// Default implementation serializes the object and computes the hash from that data.
203 /// Override only if you need custom hash computation or caching.
204 fn object_hash(&self) -> Result<ObjectHash, GitError> {
205 let data = self.to_data()?;
206 Ok(ObjectHash::from_type_and_data(self.get_type(), &data))
207 }
208}