Skip to main content

wire/answer/
commits.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4// Copyright (c) 2026 2youg1 and the sprawling contributors
5
6//! What the city says about a commit it made: one, by oid, or a page of
7//! them, newest first.
8//!
9//! Its own file so that the two questions share one vocabulary in one
10//! place: a commit is the same eight facts whether it was looked up or
11//! listed, and a second shape for the list would be a second authority
12//! on what a commit is.
13
14use kernel::{Address, B3Hash, Effort, GitOid, RunId, Seq, SessionName, TimeMs, UsdMicros};
15use serde::{Deserialize, Serialize};
16
17/// Which run wrote one commit, in the words the commit's own git
18/// trailers use.
19///
20/// Four of the five trailers appear here; `Sprawling-City` does not,
21/// because whoever asked this question already holds the city. `seq` is
22/// what the trailers cannot carry: where in the one history the line
23/// announcing this commit sits, so a reader can go on from there.
24#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
25#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
26pub struct CommitAnswer {
27    pub oid: GitOid,
28    pub run: RunId,
29    /// `Sprawling-Actor`: the address the run worked at.
30    pub actor: Address,
31    /// `Sprawling-Model`. Empty when the record predates the city
32    /// writing the model down: an absent id beats an invented one.
33    pub model: String,
34    /// `Sprawling-Effort`. Absent leaves the choice to the provider,
35    /// which is not the same fact as `Effort::None`.
36    pub effort: Option<Effort>,
37    /// Where the line announcing this commit sits in the one history.
38    pub seq: Seq,
39    /// When that line was written: the record's own clock, so a list
40    /// of commits reads as a day rather than as a column of numbers.
41    pub at: TimeMs,
42    /// What a person called this line of work, read off the room the
43    /// actor worked in. Absent when the run worked at a building's own
44    /// address, which is a run nobody opened a session for.
45    pub session: Option<SessionName>,
46    /// This run first, then each run it replaced by succession, back to
47    /// the first. One entry for a run that replaced nobody.
48    pub lineage: Vec<RunId>,
49    /// What the run that wrote this commit has been billed, whole.
50    ///
51    /// The run's total rather than this commit's share: a commit is a
52    /// checkpoint and nothing prices a checkpoint, so dividing the run's spend
53    /// between its checkpoints would be a number nobody measured. Zero for
54    /// a run no priced call is attributed to.
55    pub spent: UsdMicros,
56    /// The commit the same run announced last before this one; `None`
57    /// for the run's first. The two bound what this commit is the
58    /// result of: `Query::Changes` from `previous.oid` to `oid` says
59    /// which files moved, and `Query::RunHistory` read back from `seq`
60    /// to `previous.seq` says which calls the run made meanwhile - as
61    /// candidates, since another run in the same building may have
62    /// written in that span too.
63    pub previous: Option<CommitAt>,
64    /// The commit object's own parents, in git's order: an empty list
65    /// is a root commit. `None` when the city has no repository beside
66    /// it, the repository does not hold this object, or it could not be
67    /// read - the other facts still stand without it.
68    pub parents: Option<Vec<GitOid>>,
69    /// The commit object's own message, trailers included, read when
70    /// the parents are and absent for the same reasons, or when it is
71    /// not UTF-8 (`crates/wire/spec/Answer/Commits.lean` §8-54).
72    pub message: Option<String>,
73    /// The BLAKE3 of the canonical bytes of the line that announced this
74    /// commit - the digest the next line of the chain carries as `prev`,
75    /// not this line's own `prev`. A person finds the line by it and
76    /// checks it was not altered. `None` only in a frame from a city
77    /// written before it was answered (`crates/wire/Spec.lean` §8-78).
78    #[serde(default)]
79    pub b3: Option<B3Hash>,
80}
81
82/// A commit, and where in the one history the line announcing it sits.
83#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
84#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
85pub struct CommitAt {
86    pub oid: GitOid,
87    pub seq: Seq,
88}
89
90/// One page of the commits a city made, newest first.
91///
92/// `building` and `before` are the question handed back: the wire
93/// carries no request id, so a page matches an answer to what it asked
94/// by content, the way `ChangesAnswer` carries `base` and `head`. `more`
95/// rather than a cursor: the next page begins before the last `seq`
96/// here, which the reader already holds.
97#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
98#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
99pub struct CommitsAnswer {
100    pub building: Option<Address>,
101    pub before: Option<Seq>,
102    pub commits: Vec<CommitAnswer>,
103    pub more: bool,
104}