Jadpo is experimental and not ready for production. These docs follow the compiler's main branch as of 30 Oct 2026. What's built · Install 0.1.0
jadpo
Reference: Project layout and modules

Project layout and modules

Declining a judgement call

On this page

Most rules report plain mistakes, and only a fix answers them. A few rules are judgement calls, where the code can be right as written: two helpers that match today but differ on purpose, or two constants that share a value by coincidence. These rules are declinable. You either fix the finding, or decline it on the declaration itself, with a reason.

Here a library function already caps an amount, and cap_total does the same. The decline line says why the second one is deliberate, so library.similar_exists doesn't report it:

example
type Stock = Int {    min: 0}library rounding {    /// The amount, capped at a thousand.    function capped(amount: Stock) -> Stock {        if (amount > Stock(1000)) {            return Stock(1000)        }        return amount    }}/// The basket total, capped for the till.decline library.similar_exists: "Caps the basket for the till, which changes on its own; rounding.capped caps one line"function cap_total(total: Stock) -> Stock {    if (total > Stock(1000)) {        return Stock(1000)    }    return total}

Writing a decline

A decline is a line of the form decline <rule>: "<reason>", directly above the declaration or member it covers, after its /// comments. So the order is /// comments, then decline lines, then the declaration.

The rule is written area.name with no spaces, and either part may be a reserved word. A decline with no declaration under it is syntax.expected_declaration, and one inside a body is syntax.expected_statement.

A decline covers its one rule on its one declaration: the innermost declaration or member around the finding's location. So a decline on a type covers a finding on the type, not one on its field.

The reason is required. A missing or blank one is decline.no_reason, and the finding stays declined meanwhile, so you see one error, not two.

An agent or a person may decline. Every declinable error's next: line ends with ", or write decline <rule>: "<why>" above it if this is deliberate".

Which rules can be declined

Rule Page Reports
library.similar_exists Project layout and modules A library function already does the same
constant.similar_exists Logic Another constant of the same type holds the same value
translation.field_unused Configuration and time No wording in a language uses one of a message's fields
package.standard_candidate Integrations A provider field looks like a standard type the package doesn't use
type.batch_order_updatable Jobs and events A batch walks a query ordered by a field an update can change
step.late_failure Jobs and events An action can fail for good after a changing call took effect
email.field_unused Built-in services An email's field is written by no template and no subject
email.health_problem Built-in services An email's template fails a check of the mail health score
rate_limits.counted_in_memory Built-in services A deployable built for Workers would count its rate limits in each instance's memory
type.standard_exists Standard library A type has a standard type's shape under another name
type.variant_retired Standard library Code writes a retired code
query.nearest_exact AI Nearest-neighbour order on a vector too long for an index reads every record

Each of these can be right as written. Two helpers can differ on purpose, two constants can share a value by coincidence (a VAT rate and a fee), a shape can match a standard type by chance, and code that reads old records names a withdrawn code on purpose.

Plain mistakes are never declinable. That includes retries of a call to an outside service that outlast a route's deadline (Integrations), which can't work as written. Naming any other rule in a decline, or a rule Jadpo doesn't have, is decline.not_declinable, which names the nearest declinable rule.

Declines that no longer apply

A decline whose rule no longer fires on its declaration is decline.unused, so declines don't outlive their reason. A second decline of the same rule on one declaration is unused too.

decline.unused is judged only once every other finding is answered: no syntax errors, and every other error is itself declinable or about a decline. That's because another error can stop a rule from firing.

A declined finding is still an error

In JSON, a declined diagnostic keeps "severity": "error" and gains "declinable". jadpo help --json gives each rule's declinable, and jadpo check --json and jadpo test --json have no warnings counts.

Listing and clearing declines

jadpo declines list shows every decline with its rule, place and reason. jadpo declines clear removes them, so each finding comes back to be fixed or declined again. Both take --rule <id>, a path and --json (Commands for records, findings and review).

text
$ jadpo declines listDeclines  constant.similar_exists  domains/sales/libraries/fees.jadpo:4    A courier's charge, not the fee  library.similar_exists   domains/sales/libraries/rounding.jadpo:12    Caps the basket for the till, which changes on its own✓ 2 declines  2 rules · 2 files$ jadpo declines clear --rule library.similar_exists✓ Removed 1 decline from 1 file→ jadpo check  shows each finding again, to fix or decline

When a reason doesn't fit beside its row, list puts every reason on the lines under its row, wrapped.

Use clear after a new standard type lands, after a compiler upgrade makes a rule smarter, and for a periodic sweep. It stops on syntax errors, as every command that writes source does; list lists whatever the state of the code.

In the editor, "Decline with a reason" on a declinable finding writes the line with an empty reason for you to fill in, and "Remove decline" on a decline line removes it. Both run the same code as the commands.

jadpo approval lists every decline a change adds or edits, so declining by reflex shows in review (Records and manifest).

Rules triggered by time passing

A rule triggered by time passing, such as a feature flag whose date has expired, is judged at today's date by check, so CI fails a new change. It is judged at the commit's date by jadpo build, so rebuilding a merged revision for a hotfix is never blocked by a date passing. It isn't declinable: extending the date is the reviewed choice.

Not built yet: jadpo approval, and the rule for an expired feature flag.

Markdown for agents: /docs/declining-a-judgement-call.md.Built from Jadpo main at a707efb.