Lint engine for JobyKit-installed apps. Verifies wrapper-contract invariants by introspecting a manifest module and scanning the host's component source files.
Rules
:manifest_drift(error) — a manifest entry points at a function that is not actually a Phoenix function component. Caught first because every other check depends on the entry being live.:missing_data_component(error) — a registered wrapper does not carrydata-component="Module.function"in its source.:missing_rest_global(warning) — a registered wrapper does not declareattr :rest, :global, blocking pass-through of phx- and aria- attributes from callers.:unregistered_wrapper(warning) — a function carries adata-component="..."attribute but is not registered in the manifest, making it invisible to/design.jsonand to agents.:raw_html_primitive(warning) — a.heextemplate (or~Hblock in a.ex) contains a raw<button>,<input>,<textarea>, or<select>outside of a wrapper definition. The kit ships wrappers for all four; reaching past them drops the contract. Exempted per enclosingdef: a function whose body carriesdata-component=is a wrapper, and raw primitives inside it are its own body. Commented-out markup is ignored. Per-line opt-out via<%!-- jobykit:allow-raw-html --%>.:forked_wrapper(warning) — the app excludes a kit component fromimport JobyKit.CoreComponentsand substitutes its own, so upstream fixes to that component never reach it.:duplicated_class_string(warning) — the same longclass="..."string appears three or more times, which the kit's own guidance names as the signal that markup wants lifting into a wrapper.:unmarked_component(warning) — a public function component renders markup but carries nodata-componentat all, so:unregistered_wrapper(which keys off that attribute) cannot see it. The most common way to skip the contract entirely.:assign_new_default(error) —assign_new(assigns, :x, ...)on an attr declared with adefault:. The key is always present, so the fallback is dead code. This shipped once as the flash nil-id bug.
Each violation is a map with :rule, :severity, :message,
:file, :line, :module, :function. The engine is pure data —
formatting and exit codes live in Mix.Tasks.JobyKit.Lint.
Summary
Types
Functions
Run the lint engine. Returns a list of violations in deterministic order (drift first, then per-entry checks in manifest declaration order, then unregistered wrappers sorted by data-component string).
Options
:manifest— required. The host's manifest module (use JobyKit.Manifest).:paths— list of glob patterns to scan for the unregistered- wrapper rule. Defaults to["lib/**/*.ex"]. Patterns are resolved relative tocwd.