docir — design documents Graph

Documents / Architecture / arch-3e305bc76ff0

Capture a decision (the write path)

How a decision is captured: validate, allocate an id, write the file, project the index.

arch-3e305bc76ff0architectureactive#cli#integrity
View as Markdown◉ View in graph

Backbone

decide → register vocabulary → author → validate → allocate id → persist file → project into index → embed (deferred)

Event timeline

# Event Actor Trigger Evidence
1 TagRegistered ACT-001/002 docir tag add <key> --description tag_service.py:43-52
2 DocumentRequested ACT-001/002 docir add --type … --title … --description … cli/app.py:152-181
3 StatusDefaulted system no --status given document_service.py:92
4 Tier0Validated system before any write validation.py:26-93
5 IdAllocated system from id_sequences counter id_generator.py:26-40
6 FileWritten system docs/<type>s/<id>-<slug>.md markdown_store.py:34-39
7 IndexProjected system same transaction: metadata + FTS + relations document_service.py:120-123
8 EmbeddingMarkedDirty system same transaction document_service.py:122
9 EmbeddingComputed ACT-004 inline, or debounced 2s in the daemon scheduler.py:27-44
10 DocumentUpdated ACT-001/002 docir update <id> … document_service.py:128-159
11 DocumentArchived ACT-001/002 docir archive <id> document_service.py:161-173
12 DocumentDeleted ACT-001/002 docir delete <id> [--force] document_service.py:190-206

Transaction boundary: events 6–8 commit atomically (one shared UnitOfWork, adr-d3e3616400bf). Event 9 is outside it and eventually consistent — the only deferred piece.

Ordering hazard: the file write (6) happens before the DB commit (7-8). A crash between them leaves a file on disk that the index does not know about. reindex repairs this, but nothing detects it automatically and no test covers it. → issue-61b66ed696de.

Hotspots

  • H1 — RESOLVED 2026-07-26. Id allocation read-then-wrote id_sequences with no serialization guarantee, so it was safe only because the daemon serializes requests (CONFIRMED: 6 concurrent --no-daemon adds all returned adr-0002). Allocation is now one atomic upsert, and docir init defaults to id_style: random, which uses no counter at all. → issue-389dc5dac58a.

H2

— RESOLVED 2026-07-26. reindex restored documents, tags, FTS and embeddings but not the id counter (CONFIRMED: fresh-clone → reindex → add re-minted a live id). It now restores it, and a create refuses to overwrite a file already holding the id. → issue-b7ddde3ce860. One residual: the restore misreads an all-digit random id as sequential → issue-f09fab3f5c36.

H3

--override permits an illegal status transition. Nothing records that an override occurred; the resulting document is indistinguishable from a legal one. → issue-0783d236d565.

H4

delete --force removes a document while other documents' files keep pointing at it. No compensating action. → issue-fd547a293d01 (CONFIRMED).

H5

archive does not check incoming references at all, though delete does. The asymmetry is undocumented; the archived doc silently vanishes from graph traversal.

H6

— On the archive/unarchive no-op path the view is built without computing staleness, so a stale document reports stale: false. → issue-7d4fdccf8343.

H7

— Tier 0 validates related only for edges supplied in this call. A document that already holds a dangling edge can be updated freely and the broken edge is rewritten to the canonical file. → issue-fd547a293d01 (CONFIRMED by probe).

H8

— Two concurrent updates to the same document silently last-write-wins; the stale-write guard is computed on every update but consulted only for --replace-body. → issue-be95d3e242a3.

H9

created/updated/verified are local dates with no timezone recorded. → issue-7e16dfe2521c (cosmetic).

H10

— No duplicate-content check on add. Two identical decisions can be created; only the opt-in Tier 2 lint --deep mentions it.

Off-system steps

  • Editing markdown by hand. The product's second thesis is "agents never edit markdown directly", but humans plainly do (the whole point of git-backed files, and reindex exists "after a hand-edit" — maintenance_service.py:3). A hand-edit that breaks frontmatter is silently skipped by scan() and surfaces only via check's malformed finding. The boundary between "canonical file you may edit" and "managed artifact you may not" is nowhere stated. → issue-6817ed1851e2.
  • Resolving a duplicate id. No tooling; the user must hand-edit files and reindex.

Rules

BR-001, BR-002, BR-003, BR-004, BR-005, BR-006, BR-007, BR-008, BR-009, BR-010, BR-011, BR-012, BR-013, BR-014, BR-015, BR-016, BR-017

Gaps

issue-b7ddde3ce860, issue-fd547a293d01, issue-389dc5dac58a, issue-61b66ed696de, issue-0783d236d565, issue-7d4fdccf8343, issue-6817ed1851e2, issue-be95d3e242a3, issue-7e16dfe2521c, issue-7a271eb0f21a

To amend: Re-verify: