Uncertainty policy · fail-closed
JNSP — saying "I don't know" is a valid signal
Saying "I don't know how" is a valid signal, not a failure. SDD Mode always prefers an honest JNSP answer to a confident but invented one — and it tools this preference end to end: verdicts, pre-commit hook, exit codes.
Why inventing costs more than doubting
An AI agent is trained to produce a plausible answer — including when it lacks the information to decide. This default confidence has a hidden cost: what is invented today reappears tomorrow as drift, as a production bug or as a regulatory violation. The JNSP policy (Je Ne Sais Pas — "I don't know") reverses the slope: when the agent cannot decide, it says so, structures what it is missing, and hands the decision back to the human. It is the natural extension of Human Authorship: when in doubt about the intent, the agent ASKS — it does not invent.
The situations that mandate a JNSP verdict
The agent MUST emit a JNSP verdict (UNKNOWN for English-language outputs) in the following cases:
| Situation | Verdict | Skill / Command |
|---|---|---|
| Intent not formulated by an identifiable human | JNSP | human-authorship-check |
| Acceptance criterion not unambiguously testable | JNSP | ears-validator, /sdd spec |
| Tier 1 governance not decidable | UNKNOWN = VETO (fail-closed) | regulatory-veto |
| SQS partially unscorable | ?/5 → Gate UNKNOWN | sqs-scoring, /sdd gate |
Missing @spec annotations during a drift-check | UNKNOWN (≠ OK) | drift-detection, traceability |
| Context file not fully readable | JNSP | context-budget, /sdd resume |
The common pattern: no absence of information ever scores "OK". A Gate that cannot be computed comes out UNKNOWN, not open; code without @spec annotations comes out UNKNOWN, not "no drift".
The form in code: TODO-JNSP
When uncertainty arises mid-implementation, it materialises as a marker in the diff:
// TODO-JNSP: <precise question for the human>
The pre-commit hook (.aiad/hooks/pre-commit.sh) blocks any diff containing an unresolved TODO-JNSP:. The git commit --no-verify bypass exists but is discouraged: it amounts to committing a question without an answer.
This mechanism guarantees that areas of uncertainty do not silently sediment into the code: either the human answers and the marker disappears, or the commit waits.
The form in a text answer
A JNSP is not a shrug — it is a structured three-line answer that makes the question actionable:
JNSP — <short title>
What is known: <verified facts, files read>
What is missing: <information needed to decide>
Question for the human: <actionable rephrasing, finite choice if possible>
The discipline of form matters: "what is known" proves the agent did the research work; "what is missing" circumscribes the uncertainty; the final question, as a finite choice where possible, minimises the human decision effort.
CLI exit codes: 2 is not an error
The policy goes all the way up to the npx aiad-sdd CLI and CI pipelines:
| Code | Semantics |
|---|---|
0 | Success / PASS verdict |
1 | Failure, error or FAIL verdict |
2 | JNSP verdict — human decision required (not an error) |
Distinguishing code 2 from code 1 is essential: a FAIL has a known correction; a JNSP is an open question that must be escalated to the human. Downgrading a JNSP into a FAIL "to keep things moving" is explicitly forbidden — as is downgrading it into a PASS.
Fail-closed: protection against self-clearance
The uncertainty policy is above all a protection against silent self-clearance: an agent that, facing a check it cannot perform, would conclude "nothing to report". In SDD Mode, doubt is fail-closed: an undecidable Tier 1 governance check equals VETO; an incomplete traceability matrix equals GAP and blocks the CI (--fail-on-gap treats UNKNOWN as a failure). We prefer a false positive that demands human clarification to a silent false negative — that is the price, deliberately accepted, of a verifiable chain of trust.