a73x

1f2c1661

Add design debt documentation for timestamp-wins resolution

a73x   2026-03-21 11:50

Closes issue 75f871c4.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

diff --git a/docs/design-debt.md b/docs/design-debt.md
new file mode 100644
index 0000000..d6b6993
--- /dev/null
+++ b/docs/design-debt.md
@@ -0,0 +1,44 @@
# Design Debt

## Timestamp-wins conflict resolution

**Location:** `src/state.rs` -- `IssueState::from_ref` and `PatchState::from_ref`

### Current approach

When replaying the event DAG to materialize issue/patch state, concurrent
status-changing events (e.g. a close and a reopen that share the same parent
commit) are resolved by comparing ISO-8601 timestamps. The event with the
later (lexicographically greater) timestamp wins.

### Why it is acceptable for now

- **Single-writer typical.** In practice most issues and patches have one
  active writer at a time; true concurrent status changes are rare.
- **Simple.** No additional data structures (vector clocks, CRDTs) or
  consensus protocols are needed.
- **No DAG complexity.** Avoids the need for a full three-way merge or
  topological ordering of concurrent branches in the event chain.

### Known risks

- **Clock skew.** Two machines with drifting clocks can produce an ordering
  that does not match wall-clock reality.
- **Forgeable timestamps.** A malicious or buggy writer can backdate or
  future-date an event to force a desired outcome.
- **Non-determinism across replays.** If two events have identical timestamps,
  the result depends on DAG walk order, which may vary.

### Alternatives to evaluate later

| Alternative | Trade-off |
|---|---|
| **Commit-hash tiebreaker** | Use the lexicographic commit OID as a secondary sort key when timestamps are equal. Deterministic but still timestamp-primary. |
| **Vector clocks** | Each writer maintains a logical clock. Correct ordering regardless of wall clock, but adds per-event overhead and requires writer identity tracking. |
| **Radicle-style CRDT COBs** | Model issues/patches as Conflict-free Replicated Data Types (Collaborative Objects). Robust multi-writer semantics but significantly more complex to implement. |

### When to revisit

Before multi-writer sync becomes a common workflow -- specifically, before
supporting `git-collab push/pull` across multiple independent clones that
routinely race on status changes.