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:
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).
$ 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.