|
| 1 | +# ADR-0030 — Research for a repository-level decision lives in a nested project |
| 2 | + |
| 3 | +- **Date:** 2026-09-21 |
| 4 | +- **Status:** accepted |
| 5 | +- **Area:** research protocol, project layout, provenance |
| 6 | +- **Depends on:** ADR-0003 (the corpus has one reader and one writer), ADR-0017 (the project is the cwd) |
| 7 | +- **Worked example:** `docs/decisions/2026-09-21-delivery-architecture/` |
| 8 | + |
| 9 | +## Context |
| 10 | + |
| 11 | +On 2026-09-21 this repository needed to decide how the kit should be delivered to a |
| 12 | +non-technical operator. That question has its own unknowns — what the dispatch API returns, |
| 13 | +how long an artifact survives, what a public run discloses — and none of them belong to the |
| 14 | +contract at `research/DISCOVERY.md`, which enumerates U-1..U-8 about transports and vendors. |
| 15 | + |
| 16 | +The kit offers one place to put a corpus. `readCorpus(root)` reads `research/` relative to |
| 17 | +one project root (ADR-0003), a project has exactly one discovery contract, and the project |
| 18 | +is the current working directory with no override (ADR-0017). Putting architecture |
| 19 | +unknowns into the repository's own contract would mean one corpus asserting two unrelated |
| 20 | +sets of claims, with `unknown-closure` and `subtopic-coverage` judging them together. |
| 21 | + |
| 22 | +So the research was collected into a temporary directory outside the repository. The |
| 23 | +findings were read, the note was written — and the temporary directory was then removed as |
| 24 | +routine cleanup, taking nine captures, the hash-chained ledger, and the provenance for |
| 25 | +every claim with it. What remained was a recommendation with nothing underneath it, in a |
| 26 | +repository whose entire premise is that a claim without provenance is not evidence. |
| 27 | + |
| 28 | +That was not carelessness about an available alternative. **It was the only shape the kit |
| 29 | +offered**, and the cleanup that destroyed the evidence was the ordinary treatment of a |
| 30 | +temporary directory. A protocol that makes the careful path unavailable will keep producing |
| 31 | +this outcome. |
| 32 | + |
| 33 | +## Decision |
| 34 | + |
| 35 | +**Research supporting a repository-level architectural decision lives in a self-contained |
| 36 | +project at `docs/decisions/<date>-<decision-name>/`.** |
| 37 | + |
| 38 | +It is an ordinary project in every respect the kit can see: scaffolded by |
| 39 | +`bin/new-project.mjs`, holding its own `AGENTS.md`, `START_HERE.md`, `research/DISCOVERY.md`, |
| 40 | +`research/MAP.md`, `research/plan.json`, `research/EVIDENCE.md`, `research/BRIEF.md` and |
| 41 | +`research/raw/`, and verified by `cd`-ing into it. The kit needs no change to support this, |
| 42 | +because the project is the working directory and always was. |
| 43 | + |
| 44 | +Two rules bind it: |
| 45 | + |
| 46 | +1. **The corpus is committed, ledger included.** `research/raw/.fetches.jsonl` travels with |
| 47 | + the decision. The nested `.gitignore` the scaffold writes already negates it explicitly, |
| 48 | + and its patterns are relative to the nested root, so the byproducts (`.usage.jsonl`, |
| 49 | + `.diagnostics.jsonl`, `.failures.jsonl`, `.fetches.lock`) are excluded there without the |
| 50 | + repository's own rules needing to know the path exists. |
| 51 | +2. **Temporary scratch projects may be used for experiments, but their findings cannot |
| 52 | + support a committed decision unless the complete evidence corpus and ledger are |
| 53 | + preserved.** A scratch project remains the right tool for testing whether a predicate is |
| 54 | + satisfiable, or what a transport does. It stops being the right tool the moment its |
| 55 | + output is cited. |
| 56 | + |
| 57 | +And one consequence that has already been violated once, so it is stated rather than |
| 58 | +implied: **verification runs with the nested directory as the current working directory.** |
| 59 | +The repository's own preflight judges the repository's corpus. Quoting it beside a nested |
| 60 | +project's claims asserts something it does not say. |
| 61 | + |
| 62 | +## Alternatives considered |
| 63 | + |
| 64 | +**A second repository per decision.** Clean separation, and each decision gets a real |
| 65 | +project. It scatters the reasoning away from the thing it reasons about, multiplies |
| 66 | +repositories without bound, and makes the evidence for a decision something you have to |
| 67 | +know to go looking for. Rejected on cost, not on correctness. |
| 68 | + |
| 69 | +**One contract, several topics.** The most general fix and the most invasive: it changes |
| 70 | +the protocol rather than a directory layout. `unknown-closure`, `subtopic-coverage` and the |
| 71 | +brief's shape all assume one topic per corpus, and each would need a topic dimension. |
| 72 | +Deferred rather than rejected — if decision projects become frequent enough that the |
| 73 | +duplication hurts, this is the thing to build. Nothing here forecloses it. |
| 74 | + |
| 75 | +**Leave it as it was, and be more careful.** The failure this ADR responds to was a |
| 76 | +`rm -rf` of a directory whose entire purpose was to be temporary. Asking for more care from |
| 77 | +the next person, who will also be looking at a temporary directory, is not a fix. |
| 78 | + |
| 79 | +## Consequences |
| 80 | + |
| 81 | +- `docs/decisions/<date>-<name>/` is a recognised location, and a reader who finds a |
| 82 | + `research/` tree there is looking at a decision project rather than a stray copy. |
| 83 | +- A decision can be re-verified years later: the captures are in the repository, the chain |
| 84 | + verifies, and every claim in the brief resolves to a page that was actually fetched. |
| 85 | +- The repository now contains more than one `research/` tree. Nothing in the kit is |
| 86 | + confused by this — every command resolves relative to its cwd — but a reader might be, |
| 87 | + which is what the nested `AGENTS.md` and `START_HERE.md` are for. |
| 88 | +- The nested project's `docs/ARCHITECTURE.md` is scaffolded and has no code to map. It is |
| 89 | + kept and says so, rather than being deleted and reported missing by `doctor` forever. |
| 90 | +- The convention is recorded in the repository's own `AGENTS.md` and in |
| 91 | + `research/DISCOVERY.md` under **Already decided**, so an agent meets it before it needs |
| 92 | + it rather than after. |
| 93 | + |
| 94 | +## What this ADR does not claim |
| 95 | + |
| 96 | +That nested projects are the right home for *all* research. They are for research whose |
| 97 | +subject is a decision about this repository. Research about what this kit should be able to |
| 98 | +do belongs in the repository's own contract, where it has always been. |
0 commit comments