Skip to content
Cockpit0.29.0
A snapshot: read at commit 707a04c7ce8 on 2026-10-18T00:06:01Z by majordomus 0.29.0. Nothing on this page is read again. See it live

project.diagnostics-decide-the-exit@1

A return code is not the diagnostic channel

What it is

URI
majordomus://rule/project.diagnostics-decide-the-exit@1
Kind
rule
Identity
project.diagnostics-decide-the-exit@1
Path
.ai/repo/rules/project/a-return-code-is-not-the-diagnostic-channel.v1.md
Provenance
declared
Media type
text/markdown
As a capability
rule.project.diagnostics-decide-the-exit@1

Front matter

{
  "id": "project.diagnostics-decide-the-exit",
  "version": 1,
  "kind": "rule",
  "title": "A return code is not the diagnostic channel",
  "description": "A command that emits an error diagnostic does not exit zero; every derivation and every check runs so that an error in the layer stops it.",
  "statement": "Where the tool reports an error diagnostic about the layer, the process that ran it exits non-zero. A derivation or a check that reads the index runs under `--strict`, so that a document excluded from the index stops the run instead of being quietly absent from everything derived afterwards.",
  "status": "active",
  "class": "blocking",
  "depends_on": [],
  "tags": [
    "gates",
    "diagnostics"
  ],
  "x-majordomus": {
    "tests": [
      "test/cases/104_strict_derivation.sh"
    ]
  }
}

Content

---
id: project.diagnostics-decide-the-exit
version: 1
kind: rule
title: A return code is not the diagnostic channel
description: A command that emits an error diagnostic does not exit zero; every derivation and every check runs so that an error in the layer stops it.
statement: Where the tool reports an error diagnostic about the layer, the process that ran it exits non-zero. A derivation or a check that reads the index runs under `--strict`, so that a document excluded from the index stops the run instead of being quietly absent from everything derived afterwards.
status: active
class: blocking
depends_on: []
tags: [gates, diagnostics]

x-majordomus:
  tests: [test/cases/104_strict_derivation.sh]
---

# Rationale

On 2026-09-09 `scripts/derive` printed

    ERROR majordomus://adr/adr-0028 is claimed by <two files>; every claimant is excluded
          code=duplicate_identity

and exited 0. Two architecture decisions had been dropped from the index, every projection
was then written without them, and the return code said success. It was noticed only
because someone grepped the log on a hunch.

That is the worst shape a gate can have. A failure that announces itself and is then
overruled by the exit code is more dangerous than no check at all, because everything
downstream — a hook, a workflow, a person reading `echo $?` — is entitled to believe it.

The index is deliberately tolerant: a file it cannot place becomes a diagnostic and the
build continues, so that one broken document does not make the repository unreadable. That
tolerance is right for *reading* and wrong for *deriving*. What is written down as the state
of the repository must not be written from a state the tool has already said is incomplete.

# Required behaviour

Every invocation that derives committed artifacts, or checks them, passes `--strict`, so
that an error diagnostic in the layer ends the run with a non-zero exit and a message naming
the count. This covers `scripts/derive` and `scripts/derive-check` today.

A command that reads the layer to *answer a question* — `context`, `search`, the served
surfaces — stays tolerant, and reports the degraded state rather than refusing. The
distinction is whether the output becomes a committed fact about the repository.

# Failure behaviour

The run exits non-zero, naming how many error diagnostics were found and the command that
lists them. Nothing is written.

# Verification

Review, and `test/cases/104_strict_derivation.sh`: a duplicate identity is introduced, the
derivation refuses, and the same tree without the duplicate derives cleanly.