Skip to content

Integrations

Braden Seaborn edited this page Aug 26, 2026 · 1 revision

Integrations

Every way to wire ste100/ste_lint.py into a workflow besides running it by hand: a pre-commit hook, GitHub Actions, GitLab CI, a VS Code task, HELVE-ADE, and the baseline workflow for adopting the linter on an existing repository without a wall of red. See Installation for getting the tool itself running first, and Agent Skill for driving it from Claude Code instead of a CI job.

pre-commit

This repository publishes two hook definitions in its own .pre-commit-hooks.yaml:

  • ste100-lint -- check only. Fails the commit on any error-tier finding.
  • ste100-lint-fix -- opt-in. Applies --fix's narrow, unambiguous T1 word substitutions and re-stages the result. It does not touch T2-T6, structural, or CSV findings, so ste100-lint still needs to run after it.

Both hooks declare language: python, types_or: [markdown, csv], and pass_filenames: true. language: python means pre-commit installs this repository as a Python package into its own isolated venv per hook and resolves entry: ste100 from that venv -- a developer does not need ste100 on PATH already; pre-commit's own install step provides it, driven by the ste100 console-script entry point declared in pyproject.toml. types_or: [markdown, csv] matches the file types ste_lint.py itself ever walks or lints.

In a consuming repository's .pre-commit-config.yaml:

repos:
  - repo: https://github.com/Firelight-Innovations/STE-Linter
    rev: v0.1.0  # pin to a real tag or commit SHA once one is cut
    hooks:
      - id: ste100-lint
        # Optionally scope to a subset of Markdown/CSV, e.g.:
        # files: ^docs/

      # Auto-fix unambiguous T1 substitutions before the check hook runs.
      # Opt-in only -- see the Agent Skill page for --fix's real, narrow scope.
      # - id: ste100-lint-fix

A full copy of this is in examples/config/pre-commit-config.sample.yaml.

GitHub Actions

A ready-made workflow is in examples/github-actions/ste100-lint.yml. Copy it to .github/workflows/ste100-lint.yml. The core step:

- name: Run linter (exit 1 on any ERROR-tier finding)
  run: ste100 .

Exit code 1 (error-tier findings present) fails the job, which is the lint gate you want; exit code 2 (tool failure -- bad config, missing file) also fails the job, and that failure mode is correct too -- a broken config should not silently pass CI as "no findings."

The sample workflow also uploads a JSON report as a build artifact regardless of the lint job's own outcome, useful for inspecting findings without re-running locally:

- name: Run linter (JSON report)
  if: always()
  run: ste100 --format json --stats . > ste100-report.json

- name: Upload lint report
  if: always()
  uses: actions/upload-artifact@v4
  with:
    name: ste100-report
    path: ste100-report.json

For adopting the linter on an existing repository without failing every PR at once, swap the core step for the --baseline form -- see "The baseline workflow" below.

GitLab CI

A ready-made job is in examples/gitlab-ci/ste100-lint.gitlab-ci.yml:

ste100-lint:
  image: python:3.12-slim
  stage: test
  script:
    - pip install ste100-linter
    - ste100 .
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

The same sample file also defines a second job that always runs and always keeps its JSON report as a downloadable artifact, independent of whether the lint job itself passes:

ste100-lint-report:
  image: python:3.12-slim
  stage: test
  script:
    - pip install ste100-linter
    - ste100 --format json --stats . > ste100-report.json
  artifacts:
    when: always
    paths:
      - ste100-report.json
  allow_failure: true

VS Code

examples/vscode/tasks.json defines two tasks -- "STE100: Lint workspace" and "STE100: Lint current file" -- that run ste100 and feed its text output through a problemMatcher straight into the Problems panel. Copy the file to .vscode/tasks.json (or merge its tasks array into an existing one), then run it from Ctrl+Shift+P -> Tasks: Run Task -> STE100: Lint workspace.

The matcher parses ste_lint.py's text output format directly:

file:line:col SEVERITY TEST RULE_ID -- message
    <excerpt>

with CSV findings inserting an optional [row_id:field] tag before the severity. The regex:

^(.*):(\d+):(\d+)(?:\s+\[[^\]]+\])?\s+(ERROR|WARNING|REVIEW)\s+(\S+)\s+(\S+)\s+--\s+(.*)$

Capture groups map to VS Code's problem fields: 1 file, 2 line, 3 column, 4 severity, 5 test family (unused by the matcher's pattern mapping but present in the line), 6 rule ID (used as the Problems panel's "code"), 7 message.

This regex is checked against both hand-picked cases and a live linter run in examples/vscode/test_problem_matcher.py -- re-run python examples/vscode/test_problem_matcher.py if src/ste100/report.py's output format ever changes -- a live run stands as the source of truth this matcher is verified against.

One warning stated plainly: VS Code's problemMatcher only recognizes error/warning/info severities from matched text. The sample tasks never pass --stats, so REVIEW-tier findings never reach the matcher and this does not come up in normal use. If you add --stats to a task's args yourself, REVIEW text will not match either of the matcher's recognized keywords (ERROR, WARNING), and VS Code's fallback behavior for an unrecognized severity string needs local verification before you depend on it.

If ste100 is not yet on PATH in your environment, change a task's "command" to "python" and prepend "-X", "utf8", "ste_lint.py" to its "args" array instead.

HELVE-ADE

ste100-linter also installs as a HELVE-ADE Tool -- an independent repo, carrying a helve-tool.toml manifest at its root, that HELVE-ADE runs as a child process speaking JSON-RPC 2.0 over newline-delimited stdio. This repository's helve-tool.toml declares a [core] section only (no UI surface):

[tool]
id      = "ste100"
version = "0.1.0"
name    = "STE100 Linter"
description = "ASD-STE100 Simplified Technical English linter for Markdown and CSV."

[core]
bin  = "bin/ste100-helve.cmd"
args = ["--helve-rpc"]

Install it from HELVE-ADE's Home screen via Install App, pointed at the root of a checkout of this repository -- no build step is required. The single method the Tool exposes under its own namespace, ste100/lint, mirrors ste100 --format json's {schema_version, summary, findings} shape; the finding schema needs no separate relearning.

Full protocol details -- the handshake, the params and result shapes for ste100/lint, error codes, and the limitations section (no UI surface yet, HELVE-ADE is Windows-only and pre-alpha, Tools run unsandboxed, [permissions] is reserved but not enforced) -- live in docs/helve.md in this repository, which stands as the source of truth for the integration; this page only summarizes it.

The baseline workflow: adopting the linter without a wall of red

Turning the linter on for a lint gate that already has hundreds of existing findings means every PR fails until every finding is fixed -- not a realistic bar for a repository's first pass under the gate. --baseline PATH solves this by filtering out any finding whose (file, rule, message) triple already existed when the baseline was captured. It keys off the message text (which includes the specific matched word or phrase, for example "Optional (hedge): 'many'"), not line and column, so the baseline survives unrelated edits elsewhere in the file that shift line numbers. A different occurrence of the same rule with a different matched word still counts as new.

This is the recommended way to introduce the linter into an existing repository's CI:

  1. Generate the baseline from the current state of the codebase. Use --format json --stats so the baseline captures every severity tier, including review -- findings not in the baseline file are never suppressed, so if you ever turn on --stats for day-to-day runs later, you want review-tier findings already accounted for.

    ste100 --format json --stats . > .ste100-baseline.json
  2. Commit .ste100-baseline.json.

  3. Run day-to-day (locally, in pre-commit, in CI) with the baseline applied:

    ste100 --baseline .ste100-baseline.json .

    Every finding present when the baseline was captured is suppressed. A new file, a new sentence, or a new violation in existing prose still fails the run -- the gate applies to everything written from this point on, without blocking on the backlog.

  4. Chip away at the baselined findings over time. Fix prose and re-generate the baseline (step 1) to shrink it, or cut entries from the JSON file directly for findings you have addressed.

This workflow applies the same way whether the baseline is consumed from the plain CLI, from the GitHub Actions or GitLab CI samples above (swap their ste100 . step for ste100 --baseline .ste100-baseline.json .), or from a pre-commit hook (add args: [--baseline, .ste100-baseline.json] to the ste100-lint hook entry).

Clone this wiki locally