Why the design is what it is. For what the commands do, read Reference; for a guided path through them, Getting started.
Why the file is the database#
A tracker that owns its own store forces a sync problem on everyone who also wants the data in git. Keeping the org file authoritative removes that problem: review happens in the diff, history comes from the log, and any editor that speaks orgmode is a client [1]. Each command pays a linear scan of the files it needs, which stays cheap until the issue count grows large enough to notice.
What the design costs#
There is no index, so a query is a parse. There is no transaction across two
projects, so a cross-project move writes the target first and leaves a
duplicate id, which check reports, rather than a hole if it fails. Two
writers are serialised by a lock rather than merged. Each is a deliberate
trade for the file staying readable by anything.
Why HTN, work stealing, and citation graphs all fit#
A markdown task list is a total order dressed as a document. Hierarchical task-network planning [3], [4] is how a plan becomes a network of actions; vissue does not search that network, it stores it. Least-commitment planning [2] is why the stored order is a partial order: the terminal UI cannot start before the overlay exists, but the catalog and an unrelated docs pass can run together. Work stealing [9] and rebuild DAGs [8] are why the query that matters is the set of open sources, not a serial schedule [7]. Claiming a source is the same interface as assigning a bug [11].
Citation graphs [12], [13], [14], [17] are the other declared-edge
discipline. OokCite is where that stack was searched, collected, and
run: identity and cite edges are truth; PageRank and text are ranking
features; a neighborhood query does not mint a new citation. related
is that split on issue headings. Extracted memory graphs [24], [25], [26] are
the refusal: they build a second store from prose. Hogan’s knowledge
graph [23] is the headings a human already wrote.
What ready is, exactly#
Let \(I\) be the issues in the corpus and \(B(i) \subseteq I\) the ids listed in
issue \(i\)’s :BLOCKED_BY:. Write \(\mathrm{open}(i)\) for the states an issue
can still be worked from or waited on, that is anything but DONE and
CANCELLED. Then
Three consequences are worth stating because they are choices, not accidents.
The intersection with \(I\) is deliberate: a blocker id that names nothing in
the corpus does not hold an issue back. A typo would otherwise park work
forever with no way to see why, so the dangling edge is reported by check
and ignored by ready.
STARTED is in the set. An issue someone is already on stays ready, because
the question ready answers is “may this be worked”, not “is this untouched”.
claims is what separates the two.
The set is computed over the whole corpus, not per project. A blocker in
another project blocks, so ready --project p can be smaller than the ready
set of \(p\) read alone.
Why the order is a partial order#
\(B\) induces a relation on \(I\): \(b \prec i\) when \(b \in B(i)\). vissue keeps its transitive closure irreflexive, which is to say the graph stays acyclic, and refuses an edge that would close a cycle.
The alternative is a total order, which is what a numbered list or a sprint
backlog is. A total order over-specifies: it asserts that the terminal UI
comes after the schema and that the docs pass comes after the catalog, when
only the first is true. The partial order says exactly what is known, and
ready is the antichain of currently-minimal open elements, which is the set
that can proceed in parallel.
Acyclicity is checked at two moments and they are not the same check.
update --block tests the prospective edge against the corpus read inside the
lock, so a cycle is refused before it is written. check and cycles test
the corpus as it stands, which is what catches an edge added by hand in an
editor, or two edges added at the same instant in different project files.
What each verb costs#
There is no index. The file is the store, so a query is a parse, and the honest table is:
Verb |
Cost |
|---|---|
|
Parse and rewrite one project file, under its lock |
|
Parse that project |
|
Parse every project: \(O(\lvert I \rvert)\) |
|
Parse every project, then \(O(\lv ert I \rvert + \lvert E \rvert)\) |
|
The above, plus a term index over the corpus |
|
Read one integer |
That last row is why the change stream exists. A poller that wants to know
whether anything moved should not pay for a corpus parse to find out nothing
did, so gen reads a counter and events reads only the tail of a log.
The costs are linear and the constant is a file read, which stays comfortable into the thousands of issues and would not stay comfortable into the millions. That is the trade the format buys: no daemon, no schema migration, and a backlog that diffs.
Why show does not print the body#
show returns metadata and file:line_start-line_end. An editor or an
reader opens that range when it wants the prose. Keeping prose out of the
command output is what stops a status check from turning into a wall of
text.
Concurrency#
Every read-modify-write cycle takes a process-local mutex and an
advisory lock on issues.org.lock, then writes through a temporary that
is flushed to the device, uniquely named, and renamed into place.
Concurrent creates from several processes therefore neither lose
headings nor collide on the temporary file, and a crash mid-write leaves
the previous file rather than a truncated one.
The lock covers one project file. Adding a blocker reads the whole
corpus for the acyclicity check inside that lock, so it sees every write
that has landed; two blockers added at the same moment in different
project files can still close a cycle between them. check and cycles
report one if it happens, and neither is expensive to run from CI.
How to audit a citation#
A paper earns a slot only if it maps onto a verb or property in this repository. The relation is one of four:
Relation |
Meaning |
|---|---|
implements |
The library runs this algorithm or formula. |
stores |
The file is the persistent form of this object’s output. The planner, not vissue, produces the object. |
analogizes |
Same interface, different domain. The mapping must name the issue property. |
refuses |
Cited so the opposite choice is checkable. |
A vibe match does not count. SPECTER does not justify BLOCKED_BY
because vissue does not embed papers. Zep does not justify related
because related does not extract a temporal knowledge graph. Both
still belong, under analogizes and refuses. The working bibliography
lives in the OokCite collection vissue-dag; every DOI below was
resolved there before it was pasted.
Claim in the tracker |
Site in the code |
Paper |
Relation |
|---|---|---|---|
The file is the store |
|
Schulte et al. [1] |
implements |
A plan splits into tagged children |
|
Erol et al. [3]; Nau et al. [4] |
stores |
Order is a partial order, not a list |
` :BLOCKED_BY:` |
Weld [2] |
stores |
The graph stays acyclic |
|
Kahn [5]; Tarjan [6] |
implements |
Several nodes can run at once |
|
Coffman and Graham [7]; Mokhov et al. [8] |
analogizes |
Two workers do not take the same node |
|
Blumofe and Leiserson [9]; Anvik et al. [11] |
analogizes |
Logbook order is happened-before |
|
Lamport [10] |
analogizes |
Edges are declared influence |
``
:BLOCKED_BY: |
Garfield [12]; Pinski and Narin [13] |
analogizes |
Neighborhood walks declared edges first |
|
Brin and Page [14]; Kleinberg [15]; Haveliwala [16]; Gleich [17] |
analogizes |
Cite-edge as a positive neighbor |
OokCite encoder research, not this binary |
Cohan et al. [18]; Ostendorff et al. [19]; Singh et al. [20]; Reimers and Gurevych [21] |
analogizes |
Leftover term overlap |
|
Sparck Jones [22] |
implements |
Issues are the entities |
headings with
|
Hogan et al. [23] |
analogizes |
Do not extract a second graph |
|
Rasmussen et al. [24]; Edge et al. [25]; Gutierrez et al. [26] |
refuses |
References#
Resolved and collected through OokCite into vissue-dag. Each entry has
a relation in the audit table above.
E. Schulte, D. Davison, T. Dye, and C. Dominik, “A Multi-Language Computing Environment for Literate Programming and Reproducible Research,” Journal of Statistical Software, 2012, doi: 10.18637/jss.v046.i03.
D. S. Weld, “An Introduction to Least Commitment Planning,” AI Magazine, 1994, doi: 10.1609/aimag.v15i4.1109.
K. Erol, J. Hendler, and D. S. Nau, “Complexity results for HTN planning,” Annals of Mathematics and Artificial Intelligence, 1996, doi: 10.1007/bf02136175.
D. S. Nau, T.-C. Au, O. Ilghami, U. Kuter, J. W. Murdock, D. Wu, and F. Yaman, “SHOP2: An HTN Planning System,” Journal of Artificial Intelligence Research, 2003, doi: 10.1613/jair.1141.
A. B. Kahn, “Topological sorting of large networks,” Communications of the ACM, 1962, doi: 10.1145/368996.369025.
R. Tarjan, “Depth-First Search and Linear Graph Algorithms,” SIAM Journal on Computing, 1972, doi: 10.1137/0201010.
E. G. Coffman and R. L. Graham, “Optimal scheduling for two-processor systems,” Acta Informatica, 1972, doi: 10.1007/bf00288685.
A. Mokhov, N. Mitchell, and S. Peyton Jones, “Build systems a la carte,” Proceedings of the ACM on Programming Languages, 2018, doi: 10.1145/3236774.
R. D. Blumofe and C. E. Leiserson, “Scheduling multithreaded computations by work stealing,” Journal of the ACM, 1999, doi: 10.1145/324133.324234.
L. Lamport, “Time, clocks, and the ordering of events in a distributed system,” Communications of the ACM, 1978, doi: 10.1145/359545.359563.
J. Anvik, L. Hiew, and G. C. Murphy, “Who should fix this bug?,” 2006, doi: 10.1145/1134285.1134336.
E. Garfield, “Citation Indexes for Science,” Science, 1955, doi: 10.1126/science.122.3159.108.
G. Pinski and F. Narin, “Citation influence for journal aggregates of scientific publications: Theory, with application to the literature of physics,” Information Processing & Management, 1976, doi: 10.1016/0306-4573(76)90048-0.
S. Brin and L. Page, “The anatomy of a large-scale hypertextual Web search engine,” Computer Networks and ISDN Systems, 1998, doi: 10.1016/s0169-7552(98)00110-x.
J. M. Kleinberg, “Authoritative sources in a hyperlinked environment,” Journal of the ACM, 1999, doi: 10.1145/324133.324140.
T. H. Haveliwala, “Topic-sensitive PageRank,” 2002, doi: 10.1145/511446.511513.
D. F. Gleich, “PageRank Beyond the Web,” SIAM Review, 2015, doi: 10.1137/140976649.
A. Cohan, S. Feldman, I. Beltagy, D. Downey, and D. Weld, “SPECTER: Document-level Representation Learning using Citation-informed Transformers,” 2020, doi: 10.18653/v1/2020.acl-main.207.
M. Ostendorff, N. Rethmeier, I. Augenstein, B. Gipp, and G. Rehm, “Neighborhood Contrastive Learning for Scientific Document Representations with Citation Embeddings,” 2022, doi: 10.48550/arXiv.2202.06671.
A. Singh, M. D’Arcy, A. Cohan, D. Downey, and S. Feldman, “SciRepEval: A Multi-Format Benchmark for Scientific Document Representations,” 2023, doi: 10.18653/v1/2023.emnlp-main.338.
N. Reimers and I. Gurevych, “Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks,” 2019, doi: 10.48550/arXiv.1908.10084.
K. S. Jones, “A statistical interpretation of term specificity and its application in retrieval,” Journal of Documentation, 1972, doi: 10.1108/eb026526.
A. Hogan et al., “Knowledge Graphs,” ACM Computing Surveys, 2022, doi: 10.1145/3447772.
P. Rasmussen, P. Paliychuk, T. Beauvais, J. Ryan, and D. Chalef, “Zep: A Temporal Knowledge Graph Architecture for Agent Memory,” 2025, doi: 10.48550/arXiv.2501.13956.
D. Edge et al., “From Local to Global: A Graph RAG Approach to Query-Focused Summarization,” 2024, doi: 10.48550/arXiv.2404.16130.
B. J. Gutierrez, Y. Shu, Y. Gu, M. Yasunaga, and Y. Su, “HippoRAG: Neurobiologically Inspired Long-Term Memory for Large Language Models,” 2024, doi: 10.48550/arXiv.2405.14831.
See also the Org mode manual, the Model Context Protocol, petgraph, and daggy.