ruvnet / ruvnet/ruflo

ruflo-adr: the documented ADR_ROOT override makes every store fail (cwd:ROOT doubles as the db root), and import.mjs always exits 0 so it reports success

Open
#3,097 3 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
72.7k
Forks
8.6k
Avg merge
2d 23h
Merged PRs (30d)
83

Description

`scripts/import.mjs` documents an `ADR_ROOT` override:

```
// ADR_ROOT=/path/to/repo node scripts/import.mjs # override scan root (default: cwd)
```

and `skills/adr-index/SKILL.md:34` advertises the same: `` `ADR_ROOT=/path` — scan a different root (default: cwd) ``.

**Setting it to anything other than the repo root makes every store fail, and the importer still exits 0.**

## What happens

Scanning is scoped correctly — the right files are found and parsed. Then every write fails:

```
Total ADRs: **43** across 43 source dirs (root: /path/to/repo/docs/adr)
Records stored to `adr-patterns`: 0/43
Edges stored to `adr-edges`: 0/27
...
- Storage errors: 70
- ADR-001 ...: error: [ERROR] Failed to store: [ruflo-source-patch] REFUSING memory.db operation for /Users/
```

70 = 43 records + 27 edges. Not a partial failure — a total one.

## Cause

`import.mjs:74` passes `cwd: ROOT` to the memory subprocess, and `ROOT` is `ADR_ROOT || process.cwd()` (`:50`). The comment above it is explicit about why:

```js
// #2666 point 2: without `cwd: ROOT`, this subprocess inherits THIS
// process's own cwd, so `ADR_ROOT=/other/repo node import.mjs` run from
// anywhere else scans the right files but writes to the wrong
// `.swarm/memory.db` (the CLI resolves the db path relative to the
// subprocess's cwd, not ADR_ROOT). Every memory subprocess call in this
// plugin must pass `cwd: ROOT` so the scan root and the db root agree.
```

That reasoning is right for the case it was written for — `ADR_ROOT` pointing at **another repo root**. It silently breaks the other documented use, `ADR_ROOT` pointing at a **subdirectory of the current repo** (`./docs/adr`), which is the natural way to scope a scan. The subprocess then resolves its db path from `docs/adr`, walks out of the project, and the guard refuses the write.

`ROOT` is doing two jobs — *where ADRs are read from* and *where the database lives* — and they only coincide when `ADR_ROOT` happens to be a repo root.

## Reproduction

From a repo with ADRs in `docs/adr/`:

```sh
# works: scan root and db root coincide
node scripts/import.mjs # Records stored: 43/43

# fails: same files, every store refused
ADR_ROOT="$PWD/docs/adr" node scripts/import.mjs # Records stored: 0/43, Storage errors: 70
echo $? # 0
```

## The exit code is 0 either way

`import.mjs`'s only `process.exit` is `process.exit(0)` at `:171`, inside the `IMPORT_FORMAT=json` branch. The markdown branch falls off the end of the script, so the process always exits 0 — regardless of `errors.length`.

So the failing invocation above reports success to anything that gates on `$?`. In my case the importer was being run from a documented recipe that used `ADR_ROOT`; it had been believed to work for weeks because it exits 0 and prints a well-formed summary. The `0/43` is the only signal, and it is easy to miss in a report that otherwise looks healthy.

This is the same class as the title of #2660 — *"and both reported as success"* — surfacing again in a different path.

## Suggested directions

- **Separate the two roots.** Keep `cwd` for the memory subprocess anchored to the *project* root (walk up for `.swarm`/`package.json`/`.git` from `ROOT`, or take an explicit `--db-root`), and let `ADR_ROOT` mean only "where to scan". That preserves the #2666 fix while unbreaking subdirectory scoping.
- **Exit non-zero when `errors.length > 0`**, at minimum for a total failure. A `--strict` flag would do if a bare non-zero is considered breaking.
- **Or reject the input.** If `ADR_ROOT` is only ever meant to be a repo root, detect that it isn't one and fail fast with that message, rather than scanning happily and discarding every write.

Versions: `ruflo-adr` 0.4.1, node 22, macOS. Related: #2666 (introduced `cwd: ROOT`), #2660 (success-reporting), #3096 (orphan detector, filed alongside this).

Contributor guide

Open the contributing guide

Research direction

Start with scripts/import.mjs, especially the ROOT assignment, memory subprocess cwd, and exit handling; also read skills/adr-index/SKILL.md:34 and the related #2666 and #2660 context. Run both documented ADR_ROOT reproductions and verify that subdirectory scans store records in the project database while storage errors produce a non-zero exit status.

Written by the indexing model from the issue text.

Assessment

Tech stack
node.js, typescript
Domain
database, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.