Lektorat Apply
Operationalises spec/project/lektorat/ for the nolte-shared plugin: the editorial layer that audits, patches, or revises already-existing human-readable Markdown prose against six named quality dimensions, with a per-language rule set and explicit operator dialogue at every mutating step.
This skill binds the spec's contract to an on-disk procedure. It does not redefine the rules; when this skill and the spec disagree, the spec wins and this skill needs the update.
German trigger phrases
This skill also triggers on equivalent German-language requests, including:
- "lektoriere die README"
- "prüfe diese Doku auf Lesbarkeit"
- "audit die Seite auf Audience-Fit"
- "revise diesen Eintrag mit Lektorat"
- "Rechtschreibung in den deutschen Docs prüfen"
User-language policy
Detect the user's language from their message and respond in it. The machine-readable JSON output uses English keys (per spec/project/lektorat/ §Outputs); the human-readable Markdown summary uses English section headings so downstream tooling can parse it reliably; prose around the report is localised.
The artefact being reviewed is not translated by this skill. Each file is reviewed against the rules of its own language (DE-rules on DE-text, EN-rules on EN-text); cross-language translation belongs to the spec skill or the spec/project/docs-multilingual-authoring/ spec.
Why this is a skill, not an agent
- Mid-flow user approval is load-bearing:
patch requires explicit per-finding approval before any write (one finding, one diff, one OK), and revise requires diff review on the full-artefact rewrite. Agents have no stable way to surface that dialogue back to the parent.
- Externally visible writes: outputs land under
.audits/lektorat/<YYYY-MM-DD-HHMM>/ and, in patch / revise, modify in-scope Markdown artefacts. The skill owns the persistent on-disk state.
- Orchestration role: this skill dispatches the
lektorat-scanner agent for the read-only D1–D6 detection (context-window protection, tool restriction) and stays in the main thread to render results, run operator dialogues, and write outputs.
- Counter-dimension considered and accepted: the
audit operation alone fits the agent shape cleanly (self-contained input, structured output, no interactivity). It still lives in this skill because patch and revise reuse the same detection inventory and consolidating the three operations behind one entry point keeps the operator's mental model coherent. The scan half is delegated to the agent; the orchestration half stays in the skill per the hybrid pattern from spec/claude/skill-vs-agent/.
Inputs
- Target set: one of (a) a single artefact path the user named, (b) a directory the user named (every in-scope file under it is reviewed), (c) the whole repository (default when the user gave no scope but invoked the skill). The set is filtered through §Scope and applicability in
spec/project/lektorat/ before any scan runs.
- Operation:
audit (default), patch, or revise. The operation name must match the spec's closed vocabulary exactly; synonyms like check or rewrite are rejected.
- Severity floor (optional, applies to all operations): defaults to
suggestion (report everything). The caller may narrow to warning or critical to de-noise gate-style runs.
- Audience-artefact path (optional, defaults to
AUDIENCES.md at the bounded-context root per audience-identification): the skill resolves the artefact through the priority chain in spec/project/lektorat/ §Audience binding; missing artefact stops the run with the message documented under §Hard rules.
Operations
1. audit (read-only)
Runs the spec's audit operation per §Operations §Operation A — audit. The operation completes without operator interaction and is suitable for CI / pre-commit / sprint-review / release-publish gates.
- Resolve scope — filter the user-supplied target set against
spec/project/lektorat/ §Scope and applicability. Reject any path under spec/, skills/, agents/, source code, generated configs, or binary artefacts with the single-sentence rejection message the spec mandates. Code fences, inline code, HTML comments, and YAML frontmatter are read-only context.
- Resolve languages — apply the file-to-language priority chain in §Language handling (path segment under
docs/<lang>/, suffix convention *.<lang>.md, repository default from spec/.spec-config.yml, interactive operator choice as last resort). Never auto-detect from text content. Record the resolved language per file; this drives whether EN-mechanics or DE-mechanics fire.
- Resolve audiences — read the audience artefact via the priority chain in §Audience binding. If missing at every declared location, stop with the single-sentence error message pointing at the
audience-identify skill; never invent audiences. Resolve each artefact's applicable audiences via frontmatter audience: → artefact-type defaults → whole audience set (priority order from the spec).
- Dispatch the read-only scanner — dispatch
lektorat-scanner (Agent) with the resolved (file, language, audiences, content_mode, audience-artefact) tuples and the severity floor. Wait for its structured findings inventory before proceeding. The spec leaves the dispatch shape open (one agent run per artefact vs. one batched run for the whole set); pick batched as the default and split per-file only when an artefact set spans more files than a single agent context can hold comfortably.
- Render the JSON report following the verbatim shape in
spec/project/lektorat/ §Outputs §Findings report (machine-readable). The top-level keys, in order, are operation, operation_version, repository, ran_at, language_summary, pipeline_metadata, inventory_findings, and findings — exactly these eight, no additions (a helpful-looking extra key like dimensions_evaluated is shape drift, not an improvement), and operation_version is the JSON string "1", never the integer 1. pipeline_metadata.<language> carries the resolved tool/version/configured_path per language; inventory_findings carries infrastructure-level scan conditions (closed kind enumeration). Keep id stable across runs (hash of file + dimension + line).
- Surface inventory conditions first — when
inventory_findings is non-empty, render it as the Markdown summary's first section under the heading Infrastructure conditions, before any severity-grouped editorial findings. They indicate parts of the scan that could not complete (Vale missing, DE pipeline missing, audience artefact missing, language ambiguous, content-mode missing). They carry no severity and are never auto-patchable. They also bound the report's claims: per spec/claude/claim-provenance/, "no findings" for a dimension is an established absence only where its pipeline ran, so a dimension covered by an inventory_finding is reported as unevaluated, naming the observation that would settle it, never as clean.
- Render the human-readable Markdown summary — severity-sorted (
critical first, then warning, then suggestion), within severity grouped by file then dimension, with each finding showing the offending sample (≤240 chars), the named rule or metric, the resolution hint, and the audience IDs it cites.
- Write the outputs under
.audits/lektorat/<YYYY-MM-DD-HHMM>/ (timestamp in UTC): findings.json, summary.md, and the caller-side configuration record run.json. Pipeline metadata lives in findings.json's pipeline_metadata, not in run.json.
- Confirm in the user's language with: the audit-trail folder path, the per-severity counts, the
inventory_findings count when non-zero, and a one-line next-step hint (patch for interactive fixes, revise for full-artefact rewrites, or no action when the run was a gate check).
The audit operation never writes outside .audits/lektorat/, never edits any in-scope artefact, and never dispatches any mutating tool. Deterministic re-run produces a byte-identical findings array (modulo ran_at) on an unchanged repository.
2. patch (one finding, one diff, one approval)
Runs the spec's patch operation per §Operations §Operation B — patch. Each approval cycle resolves at most one editorial finding (never an inventory_finding): run audit first (implicitly, if invoked standalone), block on any non-empty inventory_findings, then walk the findings in severity order and present each as a unified diff for an explicit approve / skip / skip-and-record decision, enforcing the pre-write refactor-safety checks and re-rendering the reports in the same run folder after every approved write. patch never combines multiple findings into one edit.
See references/operations.md §patch for the full seven-step sequence.
3. revise (full-artefact rewrite with diff review)
Runs the spec's revise operation per §Operations §Operation C — revise. Per single artefact: run audit first and cache the pre-revise count, compose one rewrite addressing every critical and warning finding under strict semantic preservation (no dropped sections/list items/table rows/code blocks, no invented facts), render the full-artefact unified diff, and wait for an explicit approve / reject / revise decision before any write. Re-run audit on the rewrite; if the total finding count rose, label the run a regression for the operator.
See references/operations.md §revise for the full eight-step sequence.
Output handling
All persistent outputs live under .audits/lektorat/<YYYY-MM-DD-HHMM>/ in the active repository (timestamp in UTC, minute-precision), one folder per run — never reuse an existing timestamped folder. The folder mirrors the audit-trail convention used by .audits/portfolio/, .audits/skill-review/, and similar layered audits; audit writes findings.json + summary.md + run.json, patch adds dismissals.json, and revise adds pre-revise.json + post-revise.json + rewrite.diff.
See references/operations.md §Output handling for the annotated folder-layout diagram.
Examples
- Read
examples/01-audit-bilingual-repo.md when running an audit across a repository with both DE and EN documentation trees.
- Read
examples/02-patch-readme-critical.md when running patch on a published top-level artefact (README) with a mix of critical and warning findings.
- Read
examples/03-revise-tutorial-page.md when running revise on a tutorial page whose readability metric crosses the corridor and whose voice flips active/passive.
Resumability
Per spec/claude/resumable-work/, this skill is resumable: true. State is persisted to .resume/lektorat-apply/<run-id>.yml after every successful user-approval gate and after each named phase boundary. On re-invocation, scan that directory for files with status: in_progress whose inputs: snapshot matches the current invocation; if one matches, prompt the operator with Resume run <run_id> from phase <phase> (last checkpoint <last_checkpoint_at>)? [resume / start-new / discard]. The state-file envelope (schema_version, run_id, inputs, phase, decisions[], status, ...) and the fail-closed semantics on schema or YAML errors are load-bearing in the spec; don't duplicate those rules here.
Hard rules
- The six quality dimensions (D1–D6), the three operations (
audit / patch / revise), the three severities (critical / warning / suggestion), the JSON output shape, the per-language readability corridors, the refactor-safety invariants, the audience-binding priority chain, and the language-resolution chain are defined in spec/project/lektorat/. This skill must not redefine, relax, or extend them; when this skill and the spec disagree, the spec wins.
- Never lektor a file under
spec/, skills/**/SKILL.md, skills/**/templates/**, skills/**/examples/**, or agents/*.md. Reject with a single-sentence message naming the responsible authoring flow (the spec skill for spec/, skill-management for skill artefacts, agent-management for agent artefacts).
- Never lektor source code, code comments, docstrings, generated configuration (
.github/*.yml, mkdocs.yml, Taskfile.yml, lockfiles), or binary artefacts. The scope is Markdown prose.
- Never write to any in-scope artefact during
audit. The operation is read-only and must run unattended.
- Never combine multiple findings into a single
patch edit; one finding, one diff, one approval.
- Never write the
revise rewrite to disk until the operator explicitly approves the diff. Never introduce new factual content not present in the original artefact during revise.
- Never invent audiences. When the audience artefact is missing at every location declared in
spec/project/lektorat/ §Audience binding, stop with the single-sentence error message pointing at the audience-identify skill.
- Never rewrite a non-English passage inside an English-resolved file (or vice versa). Such a passage is a
D3 (spelling) or D5 (register) finding and the resolution is flagged for the operator, not silently fixed.
- Never auto-detect a file's language from its text content for scope decisions. Use the path-segment / suffix / repository-default / interactive-choice chain in priority order.
- Never modify a Vale rule, a vocabulary entry, or any rule mechanic. Vale and
nolte/vale-style are owned by prose-style and vocab-drift-audit; this skill consumes their output and surfaces it as D3 / D4 findings.
- Always preserve refactor-safety invariants in every mutating operation: code blocks, inline code, HTML comments, YAML frontmatter (key set and key order), block-quoted citations, link
[text](target) pairs, heading IDs, embedded include directives, and the order and count of list items, table rows, and checklist entries.
- Always record the DE pipeline (tool name, version, configured path) in
findings.json's pipeline_metadata.de block per spec/project/lektorat/ §Outputs — not in run.json, which carries only caller-side configuration (severity floor, resolved target set, user-supplied options). The portfolio default is the LanguageTool HTTP API; a repository may override it but the chosen tool must be recorded in pipeline_metadata.de for the run to be reproducible.
- Always cite the spec section that motivates a finding in the finding's
rule field (for example lektorat §D1 Readability or lektorat §D5 Audience-fit); a finding without a spec citation is not a finding.
Gotchas
audit deterministic re-run depends on stable finding IDs. The id is the hash of file + dimension + line; if the implementation re-keys findings on every run, dismissals recorded under one ID won't match the next run's IDs and the spec's "dismissal does not re-surface" acceptance criterion fails. Use a stable hash, document its inputs in run.json, and never include ran_at or absolute paths in the hash.
- DE pipeline tool choice is resolved at spec level: the portfolio default is the LanguageTool HTTP API (
spec/project/lektorat/ §Open Questions §OQ-2, resolved). Use the Public endpoint (https://api.languagetool.org/v2) for open-source repositories or a self-hosted deployment of the same engine for repositories with sensitivity, throughput, or air-gap constraints — the HTTP-API contract is identical. A repository may override the default by pinning an alternative tool in its Lektorat-local configuration, but record whatever tool was actually used in findings.json's pipeline_metadata.de so the audit-trail is reproducible.
mkdocs-include-markdown-plugin directives look like prose but are not. Treat {% include … %} (or whatever syntax the plugin uses in the repository) as byte-identical context per §Refactor safety; the included source is reviewed when its own file is in scope, not through the consumer page. A naïve re-flow that paraphrases inside the include directive will silently break the include resolution at MkDocs build time.
content_mode: meta exempts D1 entirely. Navigational pages (Home, per-section index) have no readability corridor; producing a D1 finding for a meta page is a spec violation, not a smell-test catch. Read the page's frontmatter content_mode before running D1 evaluation; when absent, fall back to the spec's content_mode default per spec/project/mkdocs-structure/.
audit against the whole repository on a first run can produce hundreds of findings. The severity floor exists for a reason — gate-style runs (release-publish, sprint-review) should narrow to critical to keep the report actionable; the first end-to-end audit on a repo that never ran Lektorat before will surface a large suggestion backlog. Surface the per-severity counts up front in the operator-facing confirmation so the operator can decide whether to triage now or defer.
- GitHub Release-note bodies and Issue / PR bodies live outside the repository tree. The spec includes them as in-scope artefact types (per §Scope and applicability), but they are fetched via
gh api, not read from .. The audit-trail still writes to .audits/lektorat/<...>/ in the active repository; the source artefact's identifier in findings.json uses the gh URL shape (gh:nolte/<repo>/release/<tag> or gh:nolte/<repo>/issues/<n>) rather than a relative path so the link is unambiguous.
- The skill never bumps version, never opens a PR, and never commits. Mutating operations land on disk in the working tree; staging, committing, and PR-creation are the operator's call (via
git add / git commit and nolte-shared:pull-request-create). Surfacing those follow-ups in the operator-facing confirmation is helpful; performing them silently is forbidden.
Multi-model testing
Examples and operations in this skill are expected to work on Claude Sonnet (default), Haiku (cost-sensitive runs, smaller audit scopes), and Opus (high-stakes runs, large revise rewrites). The skill body has no model-specific assumptions beyond standard tool-call semantics; the dispatched lektorat-scanner agent pins its own model per its frontmatter.
1---2name: lektorat-apply3description: Reviews existing Markdown prose against six editorial dimensions (readability, comprehensibility, grammar, style, audience-fit, idiomatic naturalness) defined in `spec/project/lektorat/`. Three operations — `audit` (read-only report), `patch` (one finding, one diff, one approval), `revise` (full-artefact rewrite with diff review); dispatches `lektorat-scanner` for the detection phase. Invoke when the user asks to "lektoriere README.md", "audit docs for audience-fit", "revise this page with Lektorat", "prüfe auf Lesbarkeit", or equivalent EN/DE requests. Writes outputs to `.audits/lektorat/<YYYY-MM-DD-HHMM>/`. Don't use to author new prose (use `audience-doc-author`), curate Vale rules (use `prose-vale-curator`), lektor `spec/` files (out of scope), or edit code, configs, or LLM-instruction artefacts (SKILL.md, agents/*.md). Supports resume on re-invocation per `spec/claude/resumable-work/`.4---56# Lektorat Apply78Operationalises `spec/project/lektorat/` for the `nolte-shared` plugin: the editorial layer that audits, patches, or revises already-existing human-readable Markdown prose against six named quality dimensions, with a per-language rule set and explicit operator dialogue at every mutating step.910This skill binds the spec's contract to an on-disk procedure. It does not redefine the rules; when this skill and the spec disagree, the spec wins and this skill needs the update.1112## German trigger phrases1314This skill also triggers on equivalent German-language requests, including:1516- "lektoriere die README"17- "prüfe diese Doku auf Lesbarkeit"18- "audit die Seite auf Audience-Fit"19- "revise diesen Eintrag mit Lektorat"20- "Rechtschreibung in den deutschen Docs prüfen"2122## User-language policy2324Detect the user's language from their message and respond in it. The machine-readable JSON output uses English keys (per `spec/project/lektorat/` §Outputs); the human-readable Markdown summary uses English section headings so downstream tooling can parse it reliably; prose around the report is localised.2526The artefact being reviewed is **not** translated by this skill. Each file is reviewed against the rules of its own language (DE-rules on DE-text, EN-rules on EN-text); cross-language translation belongs to the `spec` skill or the `spec/project/docs-multilingual-authoring/` spec.2728## Why this is a skill, not an agent2930- **Mid-flow user approval is load-bearing**: `patch` requires explicit per-finding approval before any write (one finding, one diff, one OK), and `revise` requires diff review on the full-artefact rewrite. Agents have no stable way to surface that dialogue back to the parent.31- **Externally visible writes**: outputs land under `.audits/lektorat/<YYYY-MM-DD-HHMM>/` and, in `patch` / `revise`, modify in-scope Markdown artefacts. The skill owns the persistent on-disk state.32- **Orchestration role**: this skill dispatches the `lektorat-scanner` agent for the read-only D1–D6 detection (context-window protection, tool restriction) and stays in the main thread to render results, run operator dialogues, and write outputs.33- **Counter-dimension considered and accepted**: the `audit` operation alone fits the agent shape cleanly (self-contained input, structured output, no interactivity). It still lives in this skill because `patch` and `revise` reuse the same detection inventory and consolidating the three operations behind one entry point keeps the operator's mental model coherent. The scan half is delegated to the agent; the orchestration half stays in the skill per the hybrid pattern from `spec/claude/skill-vs-agent/`.3435## Inputs3637- **Target set**: one of (a) a single artefact path the user named, (b) a directory the user named (every in-scope file under it is reviewed), (c) the whole repository (default when the user gave no scope but invoked the skill). The set is filtered through §Scope and applicability in `spec/project/lektorat/` before any scan runs.38- **Operation**: `audit` (default), `patch`, or `revise`. The operation name must match the spec's closed vocabulary exactly; synonyms like `check` or `rewrite` are rejected.39- **Severity floor** (optional, applies to all operations): defaults to `suggestion` (report everything). The caller may narrow to `warning` or `critical` to de-noise gate-style runs.40- **Audience-artefact path** (optional, defaults to `AUDIENCES.md` at the bounded-context root per `audience-identification`): the skill resolves the artefact through the priority chain in `spec/project/lektorat/` §Audience binding; missing artefact stops the run with the message documented under §Hard rules.4142## Operations4344### 1. `audit` (read-only)4546Runs the spec's `audit` operation per §Operations §Operation A — `audit`. The operation completes without operator interaction and is suitable for CI / pre-commit / sprint-review / release-publish gates.47481. **Resolve scope** — filter the user-supplied target set against `spec/project/lektorat/` §Scope and applicability. Reject any path under `spec/`, `skills/`, `agents/`, source code, generated configs, or binary artefacts with the single-sentence rejection message the spec mandates. Code fences, inline code, HTML comments, and YAML frontmatter are read-only context.492. **Resolve languages** — apply the file-to-language priority chain in §Language handling (path segment under `docs/<lang>/`, suffix convention `*.<lang>.md`, repository default from `spec/.spec-config.yml`, interactive operator choice as last resort). Never auto-detect from text content. Record the resolved language per file; this drives whether EN-mechanics or DE-mechanics fire.503. **Resolve audiences** — read the audience artefact via the priority chain in §Audience binding. If missing at every declared location, **stop** with the single-sentence error message pointing at the `audience-identify` skill; never invent audiences. Resolve each artefact's applicable audiences via frontmatter `audience:` → artefact-type defaults → whole audience set (priority order from the spec).514. **Dispatch the read-only scanner** — dispatch `lektorat-scanner` (Agent) with the resolved (file, language, audiences, content_mode, audience-artefact) tuples and the severity floor. Wait for its structured findings inventory before proceeding. The spec leaves the dispatch shape open (one agent run per artefact vs. one batched run for the whole set); pick batched as the default and split per-file only when an artefact set spans more files than a single agent context can hold comfortably.525. **Render the JSON report** following the verbatim shape in `spec/project/lektorat/` §Outputs §Findings report (machine-readable). The top-level keys, in order, are `operation`, `operation_version`, `repository`, `ran_at`, `language_summary`, `pipeline_metadata`, `inventory_findings`, and `findings` — exactly these eight, no additions (a helpful-looking extra key like `dimensions_evaluated` is shape drift, not an improvement), and `operation_version` is the JSON **string** `"1"`, never the integer `1`. `pipeline_metadata.<language>` carries the resolved tool/version/configured_path per language; `inventory_findings` carries infrastructure-level scan conditions (closed `kind` enumeration). Keep `id` stable across runs (hash of file + dimension + line).536. **Surface inventory conditions first** — when `inventory_findings` is non-empty, render it as the Markdown summary's first section under the heading **Infrastructure conditions**, before any severity-grouped editorial findings. They indicate parts of the scan that could not complete (Vale missing, DE pipeline missing, audience artefact missing, language ambiguous, content-mode missing). They carry no severity and are never auto-patchable. They also bound the report's claims: per `spec/claude/claim-provenance/`, "no findings" for a dimension is an **established** absence only where its pipeline ran, so a dimension covered by an `inventory_finding` is reported as unevaluated, naming the observation that would settle it, never as clean.547. **Render the human-readable Markdown summary** — severity-sorted (`critical` first, then `warning`, then `suggestion`), within severity grouped by file then dimension, with each finding showing the offending sample (≤240 chars), the named rule or metric, the resolution hint, and the audience IDs it cites.558. **Write the outputs** under `.audits/lektorat/<YYYY-MM-DD-HHMM>/` (timestamp in UTC): `findings.json`, `summary.md`, and the caller-side configuration record `run.json`. Pipeline metadata lives in `findings.json`'s `pipeline_metadata`, not in `run.json`.569. **Confirm in the user's language** with: the audit-trail folder path, the per-severity counts, the `inventory_findings` count when non-zero, and a one-line next-step hint (`patch` for interactive fixes, `revise` for full-artefact rewrites, or no action when the run was a gate check).5758The `audit` operation never writes outside `.audits/lektorat/`, never edits any in-scope artefact, and never dispatches any mutating tool. Deterministic re-run produces a byte-identical `findings` array (modulo `ran_at`) on an unchanged repository.5960### 2. `patch` (one finding, one diff, one approval)6162Runs the spec's `patch` operation per §Operations §Operation B — `patch`. Each approval cycle resolves at most one editorial finding (never an `inventory_finding`): run `audit` first (implicitly, if invoked standalone), block on any non-empty `inventory_findings`, then walk the findings in severity order and present each as a unified diff for an explicit `approve` / `skip` / `skip-and-record` decision, enforcing the pre-write refactor-safety checks and re-rendering the reports in the same run folder after every approved write. `patch` never combines multiple findings into one edit.6364See `references/operations.md` §`patch` for the full seven-step sequence.6566### 3. `revise` (full-artefact rewrite with diff review)6768Runs the spec's `revise` operation per §Operations §Operation C — `revise`. Per single artefact: run `audit` first and cache the pre-`revise` count, compose one rewrite addressing every `critical` and `warning` finding under strict semantic preservation (no dropped sections/list items/table rows/code blocks, no invented facts), render the full-artefact unified diff, and wait for an explicit `approve` / `reject` / `revise` decision before any write. Re-run `audit` on the rewrite; if the total finding count rose, label the run a **regression** for the operator.6970See `references/operations.md` §`revise` for the full eight-step sequence.7172## Output handling7374All persistent outputs live under `.audits/lektorat/<YYYY-MM-DD-HHMM>/` in the active repository (timestamp in UTC, minute-precision), one folder per run — never reuse an existing timestamped folder. The folder mirrors the audit-trail convention used by `.audits/portfolio/`, `.audits/skill-review/`, and similar layered audits; `audit` writes `findings.json` + `summary.md` + `run.json`, `patch` adds `dismissals.json`, and `revise` adds `pre-revise.json` + `post-revise.json` + `rewrite.diff`.7576See `references/operations.md` §Output handling for the annotated folder-layout diagram.7778## Examples7980- Read `examples/01-audit-bilingual-repo.md` when running an `audit` across a repository with both DE and EN documentation trees.81- Read `examples/02-patch-readme-critical.md` when running `patch` on a published top-level artefact (README) with a mix of `critical` and `warning` findings.82- Read `examples/03-revise-tutorial-page.md` when running `revise` on a tutorial page whose readability metric crosses the corridor and whose voice flips active/passive.8384## Resumability8586Per `spec/claude/resumable-work/`, this skill is `resumable: true`. State is persisted to `.resume/lektorat-apply/<run-id>.yml` after every successful user-approval gate and after each named phase boundary. On re-invocation, scan that directory for files with `status: in_progress` whose `inputs:` snapshot matches the current invocation; if one matches, prompt the operator with `Resume run <run_id> from phase <phase> (last checkpoint <last_checkpoint_at>)? [resume / start-new / discard]`. The state-file envelope (`schema_version`, `run_id`, `inputs`, `phase`, `decisions[]`, `status`, ...) and the fail-closed semantics on schema or YAML errors are load-bearing in the spec; don't duplicate those rules here.8788## Hard rules8990- The six quality dimensions (D1–D6), the three operations (`audit` / `patch` / `revise`), the three severities (`critical` / `warning` / `suggestion`), the JSON output shape, the per-language readability corridors, the refactor-safety invariants, the audience-binding priority chain, and the language-resolution chain are defined in `spec/project/lektorat/`. This skill **must not** redefine, relax, or extend them; when this skill and the spec disagree, the spec wins.91- Never lektor a file under `spec/`, `skills/**/SKILL.md`, `skills/**/templates/**`, `skills/**/examples/**`, or `agents/*.md`. Reject with a single-sentence message naming the responsible authoring flow (the `spec` skill for `spec/`, `skill-management` for skill artefacts, `agent-management` for agent artefacts).92- Never lektor source code, code comments, docstrings, generated configuration (`.github/*.yml`, `mkdocs.yml`, `Taskfile.yml`, lockfiles), or binary artefacts. The scope is **Markdown prose**.93- Never write to any in-scope artefact during `audit`. The operation is read-only and must run unattended.94- Never combine multiple findings into a single `patch` edit; one finding, one diff, one approval.95- Never write the `revise` rewrite to disk until the operator explicitly approves the diff. Never introduce new factual content not present in the original artefact during `revise`.96- Never invent audiences. When the audience artefact is missing at every location declared in `spec/project/lektorat/` §Audience binding, stop with the single-sentence error message pointing at the `audience-identify` skill.97- Never rewrite a non-English passage inside an English-resolved file (or vice versa). Such a passage is a `D3` (spelling) or `D5` (register) finding and the resolution is flagged for the operator, not silently fixed.98- Never auto-detect a file's language from its text content for scope decisions. Use the path-segment / suffix / repository-default / interactive-choice chain in priority order.99- Never modify a Vale rule, a vocabulary entry, or any rule mechanic. Vale and `nolte/vale-style` are owned by `prose-style` and `vocab-drift-audit`; this skill consumes their output and surfaces it as `D3` / `D4` findings.100- Always preserve refactor-safety invariants in every mutating operation: code blocks, inline code, HTML comments, YAML frontmatter (key set and key order), block-quoted citations, link `[text](target)` pairs, heading IDs, embedded include directives, and the order and count of list items, table rows, and checklist entries.101- Always record the DE pipeline (tool name, version, configured path) in `findings.json`'s `pipeline_metadata.de` block per `spec/project/lektorat/` §Outputs — **not** in `run.json`, which carries only caller-side configuration (severity floor, resolved target set, user-supplied options). The portfolio default is the LanguageTool HTTP API; a repository may override it but the chosen tool **must** be recorded in `pipeline_metadata.de` for the run to be reproducible.102- Always cite the spec section that motivates a finding in the finding's `rule` field (for example `lektorat §D1 Readability` or `lektorat §D5 Audience-fit`); a finding without a spec citation is not a finding.103104## Gotchas105106- **`audit` deterministic re-run depends on stable finding IDs.** The `id` is the hash of file + dimension + line; if the implementation re-keys findings on every run, dismissals recorded under one ID won't match the next run's IDs and the spec's "dismissal does not re-surface" acceptance criterion fails. Use a stable hash, document its inputs in `run.json`, and never include `ran_at` or absolute paths in the hash.107- **DE pipeline tool choice is resolved at spec level: the portfolio default is the LanguageTool HTTP API** (`spec/project/lektorat/` §Open Questions §OQ-2, resolved). Use the Public endpoint (`https://api.languagetool.org/v2`) for open-source repositories or a self-hosted deployment of the same engine for repositories with sensitivity, throughput, or air-gap constraints — the HTTP-API contract is identical. A repository **may** override the default by pinning an alternative tool in its `Lektorat`-local configuration, but record whatever tool was actually used in `findings.json`'s `pipeline_metadata.de` so the audit-trail is reproducible.108- **`mkdocs-include-markdown-plugin` directives look like prose but are not.** Treat `{% include … %}` (or whatever syntax the plugin uses in the repository) as byte-identical context per §Refactor safety; the included source is reviewed when its own file is in scope, not through the consumer page. A naïve re-flow that paraphrases inside the include directive will silently break the include resolution at MkDocs build time.109- **`content_mode: meta` exempts D1 entirely.** Navigational pages (Home, per-section index) have no readability corridor; producing a D1 finding for a `meta` page is a spec violation, not a smell-test catch. Read the page's frontmatter `content_mode` before running D1 evaluation; when absent, fall back to the spec's `content_mode` default per `spec/project/mkdocs-structure/`.110- **`audit` against the whole repository on a first run can produce hundreds of findings.** The severity floor exists for a reason — gate-style runs (release-publish, sprint-review) should narrow to `critical` to keep the report actionable; the first end-to-end audit on a repo that never ran Lektorat before will surface a large `suggestion` backlog. Surface the per-severity counts up front in the operator-facing confirmation so the operator can decide whether to triage now or defer.111- **GitHub Release-note bodies and Issue / PR bodies live outside the repository tree.** The spec includes them as in-scope artefact types (per §Scope and applicability), but they are fetched via `gh api`, not read from `.`. The audit-trail still writes to `.audits/lektorat/<...>/` in the active repository; the source artefact's identifier in `findings.json` uses the `gh` URL shape (`gh:nolte/<repo>/release/<tag>` or `gh:nolte/<repo>/issues/<n>`) rather than a relative path so the link is unambiguous.112- **The skill never bumps version, never opens a PR, and never commits.** Mutating operations land on disk in the working tree; staging, committing, and PR-creation are the operator's call (via `git add` / `git commit` and `nolte-shared:pull-request-create`). Surfacing those follow-ups in the operator-facing confirmation is helpful; performing them silently is forbidden.113114## Multi-model testing115116Examples and operations in this skill are expected to work on Claude Sonnet (default), Haiku (cost-sensitive runs, smaller `audit` scopes), and Opus (high-stakes runs, large `revise` rewrites). The skill body has no model-specific assumptions beyond standard tool-call semantics; the dispatched `lektorat-scanner` agent pins its own model per its frontmatter.