dira decision memory for AI coding agents
$dira whyqst-0003
qst-0003Does bulk-importing an existing ADR corpus produce a useful ledger, or a second pile?answered 2026-07-29
qst-0003Does bulk-importing an existing ADR corpus produce a useful ledger, or a second pile?
qst-0003 ◆ answered 2026-07-29

Does bulk-importing an existing ADR corpus produce a useful ledger, or a second pile?

The pitch to any repo with history is "import what you already have." kazi has 77+ ADRs; that corpus is the first real test.

The risk is precise: ADRs record *the choice*, and usually record context, but they rarely record the **rejected alternatives with their why_nots** — which is the field `dira check` reads and the field that makes `dira why` worth reading (dec-0003 makes the same point about regex capture). An import that yields 77 entries with empty `alternatives` arrays produces a ledger that cannot enforce anything: the ADR pile, reindexed, with a nicer front end. That is a bad first impression at exactly the moment a user is deciding whether dira is real.

Three options:

1. **Index, don't import.** Treat existing ADRs as read-only referenced documents — `dira why` can cite and link them without claiming them as entries. Preserves honesty about what is enforceable. Weakest immediate payoff. 2. **Semantic import via the skill.** Let the live session read each ADR and extract alternatives where they exist, marking entries `staged` where they don't. Better fidelity, but 77 staged entries is a triage queue nobody will finish. 3. **Import only what is cited.** Import an ADR the first time something references it. Lazy, ordered by real relevance, no queue — but the corpus stays mostly dark, so it does not answer "what did we decide" retrospectively.

Leaning toward (1) plus (3): index everything for retrieval, promote to a real entry on first citation. Needs validating against the actual kazi corpus before committing.

Measured 2026-07-31 — the premise above is false, and the real blocker is elsewhere

Full method and controls in `docs/decisions-pending/qst-0003-experiment.md`. Measured over kazi's 80 ADRs (81 files, one is the index):

| | measured | |---|---| | ADRs carrying at least one rejected alternative **with a reason** | **63 / 80** | | alternatives extractable | **218** | | ...carrying a real `why_not`, after hand-check | **218 / 218** | | ...bare name, no reason | **0** | | `why_not` length, median | **23 words** | | ...carrying a `revisit_if` | **2 / 218** | | ADRs with no alternative at all | **17 / 80** |

This entry predicted "77 entries with empty `alternatives` arrays." That is simply not what the corpus contains. The triage objection to option (2) — a queue nobody finishes — is answered by the split: 63 import with real content and 17 have nothing to extract, and a 17-item queue is finishable.

**The blocker is the `option` label, not the `why_not`.** `dec-0014` makes matching lexical and in-binary, so the label is the only handle `dira check` has. Against four real relitigation attempts plus a negative control, the imported corpus cited correctly **2 of 4**, and loosening the threshold to catch the other two made it cite the *wrong* record for both and refuse the negative control seven ways. **21 of 218 labels carry two or fewer matchable words, and they are the load-bearing ones** — `Go`, `Rust`, `Redis`, `Git refs`, `MCP-only.`, `LLM-as-judge for completion.` The `why_not` under `Go` is three rich sentences; the handle is one word that is also an English verb.

**The evidence supports option (2), semantic import** — not the (1)+(3) leaning above, which was reasoned from the falsified premise. (2) is also the only option that reaches the two ADRs whose rejections sit in prose rather than under a heading: a regex importer gets 61, a semantic one gets 63.

**Two requirements no option above states**, both falling out of the citation test: the importer must **expand short option labels at extraction time**, which is free then and expensive afterwards — it is the difference between an entry that can refuse something and one that is merely readable; and it must **report `revisit_if` as absent** rather than let its absence be discovered when `check` first fires.

Why this stays open

**n=1, and the sample is not neutral.** kazi's ADRs were written by the same person building dira, using one heading string in 54 of 80 files. That is the best possible case for an importer and the worst possible evidence for "any repo with history." Measuring two or three unrelated public ADR corpora is the cheapest thing that would move this answer, and the import pitch should not ship before it.

Also unestablished: that a live session *extracts* as accurately as a regex did. What was measured is what the corpus contains, not whether a model reliably pulls it out — and a semantic importer that hallucinates a `why_not` is worse than no import at all.

Neutrality run, 2026-07-31 — the kazi finding does NOT generalise

Four unrelated public corpora, four organisations, four house styles. Report and SHAs in `docs/decisions-pending/qst-0003-neutrality.md`.

| | kazi | bbc/tams | Sylius | nulib/meadow | IRS direct-file | |---|---|---|---|---|---| | ADRs | 80 | 49 | 26 | **31** | 35 | | **>=1 reasoned rejected alternative** | 76% | **90%** | 65% | **0%** | **11%** | | alternatives extracted | 221 | 237 | 40 | **0** | 24 | | carrying `revisit_if` | 0.9% | **0%** | **0%** | - | **0%** | | option labels <=2 words | 6% | 1% | 0% | - | 8% |

**The launch-relevant row is `nulib/meadow`: 31 ADRs, textbook Nygard, zero recorded alternatives.** Verified independently — 32 files, exactly four headings each (Status, Decision, Context, Consequences), no options section anywhere. Importing that corpus produces *precisely* the second pile this question feared. Nygard is the original and most-copied ADR template, so this is a class of repository, not an outlier.

**The short-label requirement was wrong and is withdrawn.** kazi 6%, tams 1%, Sylius 0%, IRS 8% — kazi's `Go`/`Rust`/`Redis` terseness is house style, not a property of ADRs. Confirmed by citation rather than inferred: the same matcher at the same threshold cites 3 of 3 real conflicts on tams and Sylius with the negative control silent both times, against kazi's 2 of 4. Extraction-time label expansion is a **conditional repair for terse corpora**, detectable in one pass, not a universal spec item.

**Heading uniformity holds within a corpus and not across them**, which settles the build shape empirically: each corpus is internally consistent (tams 98% under one heading, meadow 100% Nygard) but the heading differs in every one, and two of five have no options heading at all. The direct evidence is the experiment itself — a kazi-shaped extractor needed a structural rewrite plus three bug fixes to survive four more corpora. **A regex importer is viable per corpus and not viable in general.**

The answer

**Option (2), semantic import — with a precondition no option here stated: a pre-import dry run.** Yield ranges from 218 enforceable `why_not`s to nothing, so the importer must say what it will produce *before* producing it: *"31 ADRs found, 0 record a rejected alternative - index them instead?"* That makes option (1) correct **for some corpora**, chosen by measurement rather than policy. The three options were never mutually exclusive; which applies is a property of the corpus and is cheaply measurable first.

`revisit_if` is confirmed universal and worse than kazi alone suggested: **0% across all four public corpora and 0.9% in kazi, over 301 alternatives.** The detector is proven able to fire. No import will produce it; it is a field only dira's own capture creates.

**Still open, and now the largest risk:** this measured what is *in* these corpora, not whether a live session extracts it faithfully. A semantic importer that hallucinates a `why_not` is worse than no import at all, and nothing here tests that.

Answered 2026-08-09 by `dec-0028`

Settled by the founder. See that entry for the reasoning and what it rejected.

Alternatives on record — 0

no alternatives recorded — nothing has been weighed against this question yet

Every decision in this repo is recorded like this one.

Keep your own →