specs/015-gerrit-style-patchsets/data-model.md
Ref: Size: 3.7 KiB
# Data Model: Patch Revisions
## Entities
### Revision
A numbered snapshot of the branch state at a point in time.
| Field | Type | Description |
|-------|------|-------------|
| number | u32 | 1-indexed, derived from topological DAG order during materialization |
| commit | String | Branch tip commit OID at time of recording |
| tree | String | Tree OID of the commit (for fast interdiff without re-walking history) |
| body | Option\<String\> | Optional author note (e.g., "addressed review feedback") |
| timestamp | String | ISO 8601 timestamp of the PatchRevision event |
**Identity**: Revision number is derived, not stored. The commit OID is the true identifier.
**Uniqueness**: Within a patch, no two revisions share the same commit OID (dedup during materialization).
**Lifecycle**: Append-only. Revisions are never deleted or modified.
### PatchState (modified)
Existing entity, gains a `revisions` field.
| New Field | Type | Description |
|-----------|------|-------------|
| revisions | Vec\<Revision\> | Ordered list of all revisions, oldest first |
**Derivation**: Revision 1 comes from `PatchCreate` event (if `commit`/`tree` fields present). Subsequent revisions come from `PatchRevision` events in topological order. Duplicates (same commit OID) are skipped.
### InlineComment (modified)
Existing entity, gains a `revision` field.
| New Field | Type | Description |
|-----------|------|-------------|
| revision | Option\<u32\> | Revision number this comment was made on. None for legacy comments. |
### Review (modified)
Existing entity, gains a `revision` field.
| New Field | Type | Description |
|-----------|------|-------------|
| revision | Option\<u32\> | Revision number this review was made on. None for legacy reviews. |
## Event Schema Changes
### New: `patch.revision`
```rust
Action::PatchRevision {
commit: String, // branch tip commit OID
tree: String, // tree OID of the commit
body: Option<String>, // optional revision note
}
```
Serialized as:
```json
{
"type": "patch.revision",
"commit": "abc123...",
"tree": "def456...",
"body": "addressed review feedback"
}
```
### Modified: `patch.create`
Add optional fields (backward-compatible via `skip_serializing_if`):
```rust
Action::PatchCreate {
title: String,
body: String,
base_ref: String,
branch: String,
fixes: Option<String>,
commit: Option<String>, // NEW: branch tip at creation
tree: Option<String>, // NEW: tree OID at creation
}
```
### Modified: `patch.inline_comment`
Add optional field:
```rust
Action::PatchInlineComment {
file: String,
line: u32,
body: String,
revision: Option<u32>, // NEW: revision number at time of commenting
}
```
### Modified: `patch.review`
Add optional field:
```rust
Action::PatchReview {
verdict: ReviewVerdict,
body: String,
revision: Option<u32>, // NEW: revision number at time of review
}
```
## State Transitions
Revisions are append-only. The materialization flow:
```
PatchCreate (with commit/tree) → revision 1
PatchRevision (commit A) → revision 2
PatchRevision (commit A) → SKIPPED (dedup: same commit OID)
PatchRevision (commit B) → revision 3
```
## Relationships
```
Patch 1──* Revision (a patch has zero or more revisions)
Revision 1──* InlineComment (a revision has zero or more inline comments)
Revision 1──* Review (a revision has zero or more reviews)
Patch 1──* Comment (thread comments belong to the patch, not a revision)
```
## Config Model
### Merge Policy (in `refs/collab/config`)
| Key | Type | Default | Description |
|-----|------|---------|-------------|
| merge.require_approval_on_latest | bool | false | When true, patch merge requires approval on the latest revision |