1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
//! Local issue tracking system — GitHub-style issues stored as markdown files.
//!
//! Issues live in `.oxi/issues/` at the project root (discovered by walking
//! up from the current directory until `.oxi/` is found, mirroring
//! `Settings::find_project_settings`). Each issue is a single markdown file
//! with a YAML frontmatter block holding structured metadata, followed by a
//! free-form markdown body:
//!
//! ```markdown
//! ---
//! id: 12
//! title: "Fix login bug"
//! status: open
//! priority: high
//! labels: [bug, auth]
//! assignee: null
//! created_at: 2026-06-17T10:30:00Z
//! updated_at: 2026-06-17T14:20:00Z
//! closed_at: null
//! sessions: [abc123, def456]
//! assigned_to: null
//! github: null
//! ---
//!
//! Free-form markdown body...
//! ```
//!
//! # Design decisions
//!
//! - **Why not a `StateStore` port?** Issues are *documents* that humans open
//! in `$EDITOR`, commit to git, and diff. `StateStore` is an opaque KV/append
//! blob. Different workload, different storage shape. This mirrors how
//! `store/session.rs` and `store/settings.rs` coexist with the SDK ports.
//! - **Optimistic concurrency (content-hash CAS).** Mutations take an optional
//! `content_hash` captured at the last read. The write is rejected if the
//! on-disk content has changed since. This is the exact pattern used by the
//! `edit` tool (`oxi-agent/src/tools/edit.rs`), so external edits (e.g.
//! someone editing the file in vim) are detected without any locking.
//! - **Atomic writes** via temp+rename (same pattern as `store/session.rs`).
//! - **Assignment is process-liveness based, not time based.** An assigned
//! issue records the owning session id. Whether that session is still alive
//! is determined by an OS-held advisory lock on
//! `.oxi/issues/.alive/<session_id>` (see [`liveness`]). When the owning
//! process exits — including `kill -9`, crash, or terminal close — the OS
//! releases the lock and the assignment becomes stale and reclaimable.
// Re-export the public surface so callers can keep using
// `crate::store::issues::*` exactly as before the directory split.
pub use IssueError;
pub use IssueFilter;
pub use ;
pub use ;
pub use ;