Skip to content

Diagnostics

The diagnostic is the product. While shapelint fix mechanically handles symbol renames, export conversions, and file moves, architectural shape corrections are actioned by the agent (or you). Each message is designed to be actioned in a single pass, without opening the config.

Anatomy of a finding

src/components/ui/Card.tsx:5:1  error  shapelint/ui-component  ARCH_NAME_MISMATCH

  Interface is named "Props" but this rule requires the literal name "IProps".

  $Name = Card

  expected   interface IProps {}
  actual     interface Props {}

  pattern
             interface IProps {}
             const $Name: React.FC<IProps> = () => {}
             export default $Name

  hint       Primitives are presentational, lift data access into a block.

Every finding carries:

  • Location: file:line:col, plus the rule name and a stable code.
  • Message: one sentence stating the exact defect.
  • Bindings: resolved placeholders ($Name = Card), so there's no ambiguity about what the hole matched.
  • expected / actual: the required shape versus what's there.
  • pattern: the rule's template, echoed inline. The fixer never has to open shapelint.config.ts.
  • hint: the rule's optional fix guidance.

Design choices that matter

  • Pairing over precision. When a props interface is named Props instead of IProps, Shapelint pairs the two and reports a rename, rather than emitting "IProps missing" and "Props unexpected". One actionable message beats two technically-correct ones.
  • Capped at 3 per file. A wall of a dozen findings makes a fixer thrash. Extra findings are summarized as (N more, hidden, rerun after fixing the above); they surface on the next run once the first batch is resolved.
  • Summary line. A run ends with a count: 5 errors in 2 files.

Diagnostic codes

CodeMeaning
ARCH_MISSING_DECLA declaration the pattern requires is absent from the file.
ARCH_NAME_MISMATCHA declaration has the wrong name, or violates placeholder casing.
ARCH_KIND_MISMATCHRight name, wrong kind (e.g. a function where a const is required).
ARCH_EXPORT_FORMThe declaration is exported in the wrong form.
ARCH_TYPE_MISMATCHA type annotation the pattern states doesn't match.
ARCH_NAME_AFFIX_MISMATCHA name is missing the literal prefix/suffix an affix hole requires (${Name}Controller).
ARCH_NAME_CORRELATION_MISMATCHTwo case spellings of one hole (filename / symbols) are different words.
ARCH_MISSING_DECORATORA class is missing a decorator the pattern names (or none carries the anchored decorator).
ARCH_MEMBER_PATTERNA member matched a methods selector but lacks a required decorator.
ARCH_MEMBER_DECORATOR_GROUPA member violates a methods oneOf (exactly one) / anyOf (at least one) group.
ARCH_CONSTRUCTOR_CONTRACTA class violates the inject constructor contract (required params or injected types).
ARCH_MEMBER_CORRELATIONAn optionalNames member is misnamed, or a pairWith counterpart is missing.
ARCH_DECORATOR_ARGA decorator argument violates its decoratorArgs convention or filename correlation.
ARCH_NAME_PLURALITYA ${Name:singular}/${Name:plural} hole has the wrong grammatical number (plural-aware correlation).
ARCH_BARREL_INCOMPLETEA barrel index doesn't re-export a sibling matching mustReexport.
ARCH_CARDINALITYA folder violates a contains cardinality (exactly-one / at-most-one / at-least-one).
ARCH_LAYER_VIOLATIONAn import crosses a boundary the config-level layers graph forbids.
ARCH_FILENAME_MISMATCHThe basename violates the rule's filename or config naming.files.
ARCH_FOLDERNAME_MISMATCHA folder name violates foldername or config naming.folders.
ARCH_DENIED_IMPORTAn import violates denyImports / allowImports.
ARCH_DISALLOWED_ELEMENTA banned JSX element/component was used.
ARCH_DISALLOWED_CALLA banned function call was used.
ARCH_BODY_ORDERA statement inside a body violates the rule's bodyOrder.
ARCH_BODY_INTRA_SPACINGStatements within the same bodyOrder group have unwanted blank lines between them.
ARCH_BODY_INTER_SPACINGStatements between distinct bodyOrder groups lack required blank line separation.
ARCH_MEMBER_ORDERA class member is out of the rule's memberOrder group order.
ARCH_EXTRA_EXPORTAn export the pattern didn't declare (closed export surface).
ARCH_MISSING_SIBLINGA requires sibling file is absent.
ARCH_MISPLACED_FILEA file matching a rule's belongsHere lives in the wrong place.
ARCH_UNMATCHED_FILENo rule claims this file and unmatched is not 'ignore'.
ARCH_SUPPRESS_NO_REASONA suppression comment is missing its mandatory -- reason.
ARCH_SEMANTICA semantic (AI) criterion failed. warn unless the rule sets blocking.

Codes are stable and greppable, safe to key CI logic or suppressions on.

Suppressions

Suppress a finding inline, with a mandatory reason (a reasonless suppression is itself an error, ARCH_SUPPRESS_NO_REASON):

tsx
// shapelint-disable-next-line ui-component -- legacy modal, tracked in TICKET-123
export const LegacyModal = () => null;

Forms: shapelint-disable-next-line, shapelint-disable-line, shapelint-disable-file. Name one or more rules after the directive, or omit to cover all rules.

Output for agents

--format agent emits the text form with color stripped, for piping into a model. --format json emits the same content structured. Today the CLI emits the human/agent text form (with color when the terminal supports it).

Released under the MIT License.