Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ trunk check enable {linter}
| Technology | Linters |
| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| All | [codespell], [cspell], [gitleaks], [git-diff-check], [ls-lint], [pre-commit-hooks], [trunk-toolbox], [vale] |
| AI agents | [lintlang] |
| Ansible | [ansible-lint] |
| Apex | [pmd] |
| Bash | [shellcheck], [shfmt] |
Expand Down Expand Up @@ -138,6 +139,7 @@ trunk check enable {linter}
[isort]: https://github.com/PyCQA/isort#readme
[ktlint]: https://github.com/pinterest/ktlint#readme
[kube-linter]: https://github.com/stackrox/kube-linter#readme
[lintlang]: https://github.com/hermes-labs-ai/lintlang
[ls-lint]: https://github.com/loeffel-io/ls-lint#readme
[markdownlint]: https://github.com/DavidAnson/markdownlint#readme
[markdownlint-cli2]: https://github.com/DavidAnson/markdownlint-cli2#readme
Expand Down
3 changes: 3 additions & 0 deletions linters/lintlang/lintlang.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { linterCheckTest } from "tests";

linterCheckTest({ linterName: "lintlang" });
27 changes: 27 additions & 0 deletions linters/lintlang/plugin.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
version: 0.1
tools:
definitions:
- name: lintlang
runtime: python
package: lintlang
shims: [lintlang]
known_good_version: 0.6.0
lint:
definitions:
- name: lintlang
description:
Static analysis for AI agent instructions, tool descriptions, and agent configuration
files: [markdown, yaml, json, python]
tools: [lintlang]
known_good_version: 0.6.0
suggest_if: never
commands:
- name: lint
output: sarif
run: lintlang scan --format sarif --fail-on fail ${target}
success_codes: [0, 1]
read_output_from: stdout
batch: true
version_command:
parse_regex: lintlang ${semver}
run: lintlang --version
16 changes: 16 additions & 0 deletions linters/lintlang/test_data/clean.in.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
system_prompt: |
You are a weather information assistant.
Stop and report the failure after one retry.
tools:
- name: get_current_weather
description: Retrieve current weather for one named location. Do not use this tool for forecasts.
parameters:
type: object
properties:
location:
type: string
description: City and country for the requested weather.
required: [location]
constraints:
max_iterations: 2
timeout_seconds: 30
10 changes: 10 additions & 0 deletions linters/lintlang/test_data/findings.in.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
system_prompt: |
You are a customer support agent. Help the user with their issues.
tools:
- name: process_ticket
description: ""
parameters:
type: object
properties:
ticket_id:
type: string
30 changes: 30 additions & 0 deletions linters/lintlang/test_data/lintlang_v0.6.0_clean.check.shot
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Testing linter lintlang test clean 1`] = `
{
"issues": [],
"lintActions": [
{
"command": "lint",
"fileGroupName": "yaml",
"linter": "lintlang",
"paths": [
"test_data/clean.in.yaml",
],
"verb": "TRUNK_VERB_CHECK",
},
{
"command": "lint",
"fileGroupName": "yaml",
"linter": "lintlang",
"paths": [
"test_data/clean.in.yaml",
],
"upstream": true,
"verb": "TRUNK_VERB_CHECK",
},
],
"taskFailures": [],
"unformattedFiles": [],
}
`;
64 changes: 64 additions & 0 deletions linters/lintlang/test_data/lintlang_v0.6.0_findings.check.shot
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Testing linter lintlang test findings 1`] = `
{
"issues": [
{
"code": "H1.1",
"column": "1",
"file": "test_data/findings.in.yaml",
"issueClass": "ISSUE_CLASS_NEW",
"level": "LEVEL_HIGH",
"line": "1",
"linter": "lintlang",
"message": "Tool 'process_ticket' has no description. Suggested action: Add a specific, disambiguating description that explains WHEN to use this tool, not just WHAT it does.",
"targetType": "yaml",
},
{
"code": "H2",
"column": "1",
"file": "test_data/findings.in.yaml",
"issueClass": "ISSUE_CLASS_NEW",
"level": "LEVEL_HIGH",
"line": "1",
"linter": "lintlang",
"message": "System prompt defines tools but contains no termination conditions, retry budgets, or progress checks. Suggested action: Add explicit constraints: 'You have a maximum of 5 tool calls per task. If no progress after 2 attempts, stop and report the issue.'",
"targetType": "yaml",
},
{
"code": "H3",
"column": "1",
"file": "test_data/findings.in.yaml",
"issueClass": "ISSUE_CLASS_NEW",
"level": "LEVEL_MEDIUM",
"line": "1",
"linter": "lintlang",
"message": "Parameter 'ticket_id' in tool 'process_ticket' has no description. Suggested action: Add a description explaining what this parameter means semantically, not just its type.",
"targetType": "yaml",
},
],
"lintActions": [
{
"command": "lint",
"fileGroupName": "yaml",
"linter": "lintlang",
"paths": [
"test_data/findings.in.yaml",
],
"verb": "TRUNK_VERB_CHECK",
},
{
"command": "lint",
"fileGroupName": "yaml",
"linter": "lintlang",
"paths": [
"test_data/findings.in.yaml",
],
"upstream": true,
"verb": "TRUNK_VERB_CHECK",
},
],
"taskFailures": [],
"unformattedFiles": [],
}
`;