Catch an orphaned requirement in 5 minutes

Disclosure: I build Reqlan. This is a walkthrough of what it does today on a tiny repo, including the bit that surprised me while writing it.

You write a requirement, agree it matters, and then nothing in the code ever points at it. Nobody deleted it. It just never got wired up. That is an orphaned requirement, and in a repo where an agent writes most of the code it is easy to end up with several.

Here's how I find one with Reqlan on a two-idea repo. Every command below was run on reqlan CLI 0.10.0 and the output is pasted as it came out.

1. The tiny repo

repo/
  .reqlan/          # created by `reqlan init .`
  spec.rq
  src/cart.ts
  src/cart.test.ts
  package.json      # vitest + typescript, so the test runs (`npx vitest run`)

spec.rq holds two named ideas:

cart_total {
    The cart total is the sum of line prices times quantities.
    implemented in ["./src/cart.ts"]
    proven by ["./src/cart.test.ts"]
    @status in-progress
}

free_shipping {
    Orders over 50 pounds ship free.
    @status in-progress
}

The code and the test pin themselves back to cart_total with an rq: comment:

// src/cart.ts
// rq:["../spec.rq".cart_total]
export function cartTotal(lines: { price: number; qty: number }[]): number {
  return lines.reduce((sum, l) => sum + l.price * l.qty, 0);
}

src/cart.test.ts carries the same pin (and imports test/expect from vitest). Nothing anywhere mentions free_shipping.

2. Run the check, and notice what it doesn't say

$ reqlan check
No issues.

This is the seam I want to be upfront about. reqlan check looks for references that don't resolve: pins to ideas that don't exist, and file refs to files that aren't there. An idea with nothing pointing at it isn't a broken reference, so check is happy. On 0.10.0 it doesn't report orphans on its own.

3. Ask the graph about the idea

$ reqlan analyse -i free_shipping
## Graph (center spec.rq#free_shipping, depth 2)

### Nodes
### free_shipping (spec.rq:8)
Orders over 50 pounds ship free.
Status: in-progress

### Edges
(none)

Edges: (none) is the orphan. No implementation, no proven by, no rq: pin. Compare it with reqlan analyse -i cart_total, which lists edges to src/cart.ts and src/cart.test.ts.

4. Wire it up, and get it slightly wrong

I add the shipping code with a pin and, being me, make a typo in the name:

// src/shipping.ts
// rq:["../spec.rq".free_shiping]
export function shippingCost(total: number): number {
  return total > 50 ? 0 : 4.99;
}
$ reqlan check
## Issues (1)

../spec.rq.free_shiping
- src/shipping.ts:1 [comment_link]

It exits 1, so this fails in CI. This is the part check is built for: the pin names an idea that doesn't exist.

5. Fix the name and look again

$ reqlan check
No issues.

$ reqlan analyse -i free_shipping
...
### Edges
spec.rq#free_shipping -[comment_link]-> src/shipping.ts

The idea has an edge now, so it isn't orphaned. It still has no proven by, which is the next thing I'd add.

6. Bonus: the test file goes missing

If I move src/cart.test.ts out of the repo, the proven by edge on cart_total no longer resolves:

$ reqlan check
## Issues (2)

./src/cart.test.ts
- spec.rq:4 cart_total [file_reference]
- spec.rq:4 cart_total [file_reference]

(Yes, it lists the same line twice. I've noted that as something for us to tidy up.)

What it won't do

  • It checks named bindings, not meaning. If shippingCost ships free at 40 pounds, the pin still resolves and check still passes.
  • It won't catch a pinned test that asserts 1 == 1. For test quality, use mutation testing alongside it.
  • It flags a missing test file, not a deleted test case inside a file that still exists. I tried proven by ["./src/a.test.ts:does not exist case"] against a file without that case, and check still said No issues.
  • The CLI resolves a symbol ref like ["./src/cart.ts".cartTotal], but the VS Code extension (1.16.0 and 1.19.0) flags it as unresolved, so this repo uses a whole-file ref.
  • Finding orphans is a query today (analyse -i, or reqlan click <idea>, which shows backlinks (0)), not a check failure.

Takeaway

Name the idea, pin the code to the name, and the graph tells you two different things: reqlan check catches pins and test files that point at nothing, and reqlan analyse -i shows ideas that nothing points at. Five minutes, two commands.

Docs: https://reqlan.com. (Unrelated to SPARQL, which also uses .rq.)

Reproduce it: ./replay.sh in this folder runs every step and prints the output above (saved in output.txt).

Uploaded Image Uploaded Image Uploaded Image

Comments