Lint an app against the law
run_lintStep 2 of the lint, and the one that returns findings. Pass the activities and jurisdictions set_profile validated, and get lint-style findings: which obligations apply, with severity (warn/info), citation, as_of_date, staleness, and confidence. warn: a live obligation binds the profile (obligation), a posture finding needs attention (posture), or LexLint lacks current data for a declared jurisdiction (coverage). info: context rather than a live duty, and kind says which it is: an instrument LexLint cannot say is in force today (pending), a jurisdiction-wide statement of how the local law treats crawling as a whole, binding nobody on its own (posture), a note about what was not reported (coverage), a duty your customer, a public body or a financial institution, owes and meets through your software (customer_duty, with public_sector or regulated_sector declared; triage it in the product lane), or an instrument whose owed is not yours (obligation). LexLint never reports error: a lint cannot be sure something is prohibited, so it will not say so. Every instrument finding also carries certainty.resultset, which is the axis to present on and is NOT the same cut as kind: present is law as it stands today, including an instrument blocked by a court, whose enforcement is paused (a live risk held in abeyance, never hypothetical); forward is law that may be coming; historical is a spent instrument that is neither. NOTHING IN forward MAY GATE: it is informational, it must never reach an exit code, fail a build, or block a merge, and a bill in committee changing your build colour is a misuse of this tool. Within forward, certainty.rung orders by how much is PINNED to primary text and never by a probability, with rung 1 (enacted, commencement dated) predicting nothing at all; certainty.rung is null where the law library holds no stage to rank by, which is not the same as the lowest rung. If you suppress any part of forward from what you show a user, say so in your output: a run that drops rows and then reports "no basic issues found" is a silent pass. Each instrument finding also carries in_force, whose words is what to print wherever you say when a law binds. Obligations are matched from AI, scraping, privacy, cybersecurity, communications, content-moderation, product-liability, age-gating and reuse law; that is every topic the law library carries, so a declaration can raise findings from any of them and no topic is served by get_law alone any more. A finding whose instrument has a LexLint page carries note_url; show the citation as a link to it, and never construct that URL yourself. A jurisdiction LexLint has no current data for is a WARNING, never a silent pass, and the passing state is "no basic issues found", never "compliant". This is a lint for catching basic issues early, NOT legal advice and NOT a compliance certification. Costs three upstream requests for any number of declared jurisdictions: it reads the whole published law library and filters to your declaration in memory, rather than one request per jurisdiction. A trial key lints at most 10 distinct jurisdictions over its whole life; a declaration past that is refused before anything is spent. A repeat lint against a law library that has not moved since an earlier one can cost fewer, served from this key's own cache. This tool needs sign-in or an UnGovr Open Data key (metered per request; get one at https://ungovr.org/cli-login?client=lexlint).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| brief | No | Send true when you will show these findings to a person and have no LexLint procedure loaded. Each finding then comes back as one line to print: its summary and first duty clipped to 160 characters, with the citation, note_url, in_force, owed and kind; the full text of any law is one get_law call away. Leave it out when you write lexlint.yml: brief findings drop fields the manifest keeps. | |
| roles | No | Which role this software's maker holds under each regime, keyed by axis: ai_system (provider, deployer, importer, distributor, product_manufacturer, authorised_representative, the EU AI Act's operators) and personal_data (controller, processor, the GDPR's). {"ai_system": ["provider"], "personal_data": ["processor"]}; "none" alone when asked and none applies. Ask the developer; never infer it from the code. Omitted, an axis routes nothing and run_lint counts the duties a role would move in a coverage line. | |
| activities | Yes | What the app does, from the profile set_profile returned. Allowed: crawls_web, trains_models, generates_content, deploys_chatbot, automated_outreach, high_risk_decisions, processes_voice, processes_biometrics, publishes_adult_content, operates_social_platform, serves_minors, operates_app_store, ships_mobile_app, aggregates_content, distributes_software_product, handles_health_records, provides_financial_services, operates_essential_service, is_listed_company, provides_telecom_services, statutory_requests, records_calls, records_text_chat, tracks_devices, is_bank, is_lender, is_insurer, is_securities_firm, is_payment_provider, is_crypto_asset_provider, employment_decisions, credit_decisions, insurance_decisions, housing_decisions, education_decisions, health_care_decisions, public_services_decisions, justice_decisions | |
| jurisdictions | Yes | Jurisdiction slugs from the profile set_profile returned, lowercase, "/"-separated (e.g. "us", "us/ca", "eu", "kr"). A slug is the jurisdiction's UnGovr Atlas path: California is https://ungovr.org/us/ca and its Atlas ID is urn:ungovr:us/ca. Its ISO 3166 code, US-CA, is accepted too. A deeper or unresearched path resolves to the nearest jurisdiction with law, and the jurisdictions whose law is researched are listed at https://lexlint.io/law for the developer to check; name every jurisdiction the app operates in: one left off is unlinted, not passed. | |
| public_sector | No | Is this software run by a public body (body), sold to or run for public bodies (supplier), both, or neither (none)? Ask the developer every time the profile is declared; never infer it from the code. Omitted, duties binding only public bodies are reported as the caller's, and run_lint counts them in a coverage line. | |
| client_version | No | The LexLint plugin version you are running, from your SKILL.md, exactly as check_access takes it. Send it on every lint: a run that skips the preflight otherwise learns nothing about its own staleness. Omitted, update_available comes back null, which means LexLint learned nothing, never that you are current. | |
| regulated_sector | No | Whose duty a financial-law row is. Is this software run by a bank, insurer or other regulated financial entity (body), supplied to one (supplier), or neither (none)? {"financial": "supplier"}. Ask when provides_financial_services or a license class (is_bank, is_lender, is_insurer, is_securities_firm, is_payment_provider, is_crypto_asset_provider) is declared; never infer it. It routes and never matches, so a supplier still declares the classes of its customers. Omitted, the entity's duties are reported as the caller's, and run_lint counts them in a coverage line. |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| docs | Yes | Where the full documentation lives. | |
| lint | Yes | One-line verdict: counts by severity, then the verdict itself. The passing state is "no basic issues found", never "compliant". | |
| brief | No | Present, and true, when the call sent brief: each instrument finding is then one line, and fields it would otherwise carry (detail, why, matched_by, basis, lifecycle, the rest of requires) are not sent. Absent there means not sent, never empty. | |
| notice | Yes | The standing disclaimer. Not legal advice, not a certification, not authorization to access any system. | |
| replay | No | Quote this when you report a problem with a run, and LexLint can reproduce it exactly: the bundle, the law library build, the instant the run was judged at, and a digest of the declaration. Nothing about the run is stored to make it work. | |
| run_at | No | The instant this run was judged at, ISO 8601. Not the same question as corpus_built_at: a finding's kind, severity, staleness and certainty rung move with the clock as well as with the law library, so an instrument becomes a live obligation the moment its effective_date passes, against a law library that has not moved. Send it back on upload_lint_run's compact form, which rebuilds this run at this instant. | |
| findings | Yes | Every finding, one per instrument per jurisdiction. Group these into work items before showing them; eight jurisdictions produce a list nobody reads. | |
| activities | Yes | The declared activities this run was evaluated against, de-duplicated. | |
| model_notice | Yes | LexLint's advisory to the developer on models outside tested_model_families. Not a gate: the lint runs either way. | |
| jurisdictions | Yes | The declared jurisdiction slugs this run was evaluated against, normalized. | |
| client_version | Yes | The client_version this call sent back, normalized. Null when none was sent. | |
| latest_version | Yes | The newest published LexLint bundle, as the server knows it. | |
| update_command | Yes | The plugin update command, shown to the developer and not run by the assistant. Present only when update_available is true. | |
| corpus_built_at | Yes | When the bulk export this run read was built. Null on the per-slug request path, which reads no manifest and so has no build stamp: null means "not reported here", never "not built". | |
| update_available | Yes | Three-valued: true means a newer LexLint plugin is published. Null means LexLint learned nothing about your version, which is NOT the same as being current. | |
| lint_procedure_url | Yes | A link to show the developer: the written LexLint procedure for the lint loop. Set only for a caller that sent X-API-Key and no bundle version; null for a bundle session, which already holds it, and for a signed-in caller. | |
| freshness_window_days | No | The law library's re-read cadence in days, as the export publishes it. Not a staleness threshold: no finding is judged or marked against it. Null when the law library states none. | |
| lint_procedure_notice | Yes | Why lint_procedure_url is set and what that procedure holds, for the developer. Null with it. | |
| tested_model_families | Yes | Which model families LexLint's procedure is exercised against, as lowercase tokens. Nothing about your model is sent to LexLint. | |
| declaration_sensitivity | Yes | The finding ids that rest on exactly one declared activity, keyed by that activity in declared order: strike a value the developer doubts and these are the findings that go with it. Show it grouped by activity after the findings. A declared activity nothing rests on alone is absent, and {} means no finding rests on one value. Posture findings rest on crawls_web, which is what draws them; the untagged-activity coverage finding rests on the activity it names; other coverage findings rest on no single value. |