21 Failure gallery
Quarto-Needs ships a gallery of deliberately failing projects under examples/broken/. Each directory is a real, self-contained project whose defect teaches one specific failure mode: what the engine says, how loudly it says it, and what the reader should do about it.
Nothing in the gallery is imported by, rendered into, or otherwise shared with the self-hosted case study; a broken fixture can never contaminate the canonical model.
Every expectation below is executable: the teaching-fixture regressions run the engine against each project and fail if a diagnostic ever drifts from this page. To explore by hand, run the same command the tests use:
quarto-needs --root examples/broken/missing-evidence check21.1 The fixtures
| Fixture | The mistake | What the engine does | Finding |
|---|---|---|---|
missing-evidence/ |
A passed test has no evidence behind it. | Warning on the test; the project still scans and renders. | REQ012 |
invalid-relations/ |
A relation targets an undeclared object and an identifier is declared twice. | Two errors; the snapshot is refused — nothing renders. |
REQ005, REQ004
|
probable-relation-typo/ |
A relation name is probably mistyped: verifed-by is one deletion away from verified-by. |
Warning names the nearby catalog relation, but the authored key stays an ordinary attribute and no edge is invented. | QND005 |
relation-typo/ |
linked-to looks relation-like but is not a catalog relation and is outside the conservative one-edit typo radius. |
No QND005: the custom attribute survives unchanged and creates no graph edge. This is the boundary that keeps arbitrary project metadata valid. |
— |
orphan-requirements/ |
Well-formed requirements connected to nothing. | Info findings naming both objects; scanning succeeds. | REQ014 |
overdue-decision/ |
An accepted decision’s revisit-after date has passed. |
Warning on the decision, naming the overdue review. | DEC006 |
expired-evidence/ |
Evidence carrying an expires date in the past. |
Warning on the evidence object; freshness is re-checked, never assumed. | REQ015 |
stale-evidence/ |
Evidence attested against an earlier semantic graph: the payload is intact, the provider agrees and nothing expired. |
evidence check refuses it — expiry is a date, staleness is a binding. |
EVD203 |
localization-drift/ |
The pt-BR sibling quietly changes a requirement’s status. | The semantic-parity check refuses the pair by name before publication. | — |
migration-loss/ |
A Sphinx-Needs export with an unmapped type and an unmapped link field. | The import plan records the loss as review items — planned, never guessed. |
TYPE_UNMAPPED, LINK_FIELD_UNMAPPED
|
interchange-loss/ |
Treating the ReqIF/JSON-LD export as a lossless round trip. | The project scans clean, and both projections document inside the export exactly which authored details stay behind. | PROJECTION-NOTE |
editor-refactor/ |
Renaming REQ-2 onto the existing REQ-1 in an unsaved buffer. |
The LSP rename refuses with the engine’s canonical diagnostic instead of writing a duplicate; a rename onto a free identifier still edits every reference. | — |
21.2 The one dynamic member
suspect-after-change has no checked-in directory on purpose: its point is two states of a project across a Git history, not a single snapshot. A requirement’s verified-by edge can stay structurally valid while the requirement behind it changes meaning, and only comparing two engineering states catches that. The gallery README carries a copy-paste reproduction recipe; the short version is two commits and one command:
quarto-needs --root . suspect --git HEAD~1..HEAD21.3 Severity, not just failure
The gallery’s real lesson is the gradient. A structural error (REQ004, REQ005) refuses the snapshot outright. A warning (REQ012, REQ015, DEC006, QND005) surfaces the problem but still publishes. An info finding (REQ014) stays visible without claiming the project is broken.
The two relation-looking fixtures deliberately pin the boundary of inference. probable-relation-typo/ is one edit from a real catalog relation, so the engine warns while preserving the original attribute and refusing to invent an edge. relation-typo/ is outside that narrow radius, so it stays silent custom metadata. Catching likely mistakes without treating arbitrary attributes as schema is the point of the pair.