Skip to main content

Module issues

Module issues 

Source
Expand description

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:

---
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. No wall-clock expiry, no heartbeats, no zombie assignments.
  • Per-file write serialization uses the agent’s file_mutation_queue for in-process concurrency. Cross-process races are bounded by the content-hash CAS: the loser gets a “retry” response, the same semantics as the edit tool.

Modules§

liveness
Process-liveness tracking via OS advisory locks.

Structs§

Assignment
Who currently owns the work on an issue.
FileIssueStore
File-backed issue store.
GithubRef
A reference to a synced GitHub issue. Populated only after Phase 6 sync.
Issue
An in-memory issue: metadata + markdown body + the file path it came from.
IssueFilter
Filter for list. All fields optional (None = no constraint).
IssueMeta
YAML frontmatter for an issue.
IssuePatch
A precise update payload for FileIssueStore::apply_patch.
IssueSummary
Summary view exposed for UI consumers (footer indicator, panel header). Cheap to construct — values come straight from the in-memory cache.

Enums§

IssueError
Errors returned by issue operations.
Priority
Issue priority. Ordered low → critical for sorting.
Status
Issue status.

Functions§

content_hash
Compute a content hash used for optimistic concurrency (same idea as the edit tool’s expected_hash). Uses the std default hasher for zero deps.
issue_filename
Filename for an issue: zero-padded 4-digit id + slugified title.
issues_dir
Walk up from start looking for a .oxi/ directory. Returns the path to <root>/.oxi/issues. If no .oxi/ exists, returns <start>/.oxi/issues (lazily created on first write).
parse_issue
Parse a markdown-with-frontmatter file into an Issue.
serialize_issue
Serialize an issue back to the markdown-with-frontmatter form.