Skip to content

feat(driver): serve compact rule metadata in the lint result - #436

Merged
Teakowa merged 7 commits into
mainfrom
wright-431-lint-rule-metadata
Sep 29, 2026
Merged

Teakowa merged 7 commits into
mainfrom
wright-431-lint-rule-metadata

Conversation

@e54-bot

@e54-bot e54-bot commented Sep 29, 2026

Copy link
Copy Markdown
Collaborator

Summary

Implements option C from #431: lint no longer inlines the full lintRules response.

  • wright lint --format json and the agent {"op":"lint"} result now carry rules as a compact [{"id", "effectiveSeverity"}] list — enough to interpret a finding's code and severity. Summary, rationale, documentation, known limits, evidence, and tags are served once by lintRules, which remains the authoritative full-metadata surface.
  • wright-agent/v1 schema: LintResult.rules items move from LintRule to a new LintRuleSummary definition; LintRulesResult keeps LintRule.
  • docs/cli/machine-contract.md gains the wright-result/v1 evolution policy the issue asked for (same additive-only rule as wright-agent/v1), with this reduction recorded as the approved exception ahead of the 1.0 freeze (Roadmap to v1.0: stable Workshop tooling platform #134).
  • docs/cli/lint.md, docs/cli/commands.md, docs/agent-contract.md, and SPEC-99 updated to match the shipped shape.

Measurement (issue fixture overpy-pixelart.ws, zero findings)

Field Before After
result.rules 7455 B (78%) 368 B
envelope total 9586 B 1912 B

Contract note

This is the owner-approved exception named by #431: a field reduction inside wright-result/v1 and the lint agent operation, deliberately made before the envelope freezes at 1.0 rather than via a wright-result/v2.

Test plan

  • cargo fmt --all -- --check, git diff --check
  • cargo clippy --workspace --all-targets --all-features -- -D warnings
  • cargo test --workspace --all-targets --all-features — all green, including agent_v1_schema_covers_every_advertised_request_and_response (schema-validates live lint/lintRules results)
  • wright lint --format json on tests/fixtures/workshop/real-world/overpy-pixelart.ws — rules block 7455→368 B, findings unchanged
  • New assertions pin the boundary: lint rules carry no prose fields; lintRules still serves summary et al.; --disable-rule still reported via config

Closes #431

Generated with Devin

wright lint and the agent lint operation inlined the full lintRules response — roughly 7.5 KB of static rule prose on every call, 78% of a clean result — while lintRules already serves the same metadata on demand. The lint result now keeps only each rule's id and effectiveSeverity, enough to interpret a finding's code and severity; summary, rationale, documentation, known limits, evidence, and tags stay exclusive to lintRules.

This is a recorded exception to wright-result/v1, decided ahead of the 1.0 freeze; machine-contract.md now documents the envelope's evolution policy alongside the wright-agent/v1 rule.

Closes #431

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Assert compact lint rules carry exactly id and effectiveSeverity, and look up lintRules metadata by id instead of array position.

Refs #431
@e54-bot

e54-bot commented Sep 29, 2026

Copy link
Copy Markdown
Collaborator Author

Heads-up on #431 so review measures this PR against the right contract.

Closes #431 stays valid once Q2 and Q3 are answered.

@e54-bot

e54-bot commented Sep 29, 2026

Copy link
Copy Markdown
Collaborator Author

Update: the owner has settled both open points on #431. Q2: recorded pre-1.0 exception, and Q3: add the wright-result/v1 evolution policy. So the docs/cli/machine-contract.md and docs/agent-contract.md hunks, and the PR description's exception wording, are now backed by an owner decision. #431 is fully decided and Closes #431 is valid.

@Teakowa Teakowa left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR implements the superseded draft text of #431's option C, not the approved decision. Requesting changes.

lint result must drop rules entirely

#431's approved body (ready-for-implementation, recorded 2026-09-29) decides: "the lint result stops carrying the rules array … This removes a duplicate and replaces nothing" — config.rules[id] already carries enabled and effective severity for every registered rule, which is all a caller needs to interpret a finding, and lintRules remains the authoritative full-metadata surface. The acceptance criteria require rules to be absent on both paths, tests asserting its absence, and LintResult to neither declare nor require rules.

This PR instead ships the earlier draft's option C ("lint keeps per-rule id and effective severity"), reducing each entry to {id, effectiveSeverity} via a new LintRuleSummary. The member is still emitted unconditionally on both paths:

  • crates/wright-driver/src/service.rs: {"op":"lint"} still returns "rules": compact_lint_rules(...)
  • crates/wright-driver/src/session/semantic.rs: CLI LintResult still carries rules
  • schemas/wright-agent-v1.schema.json: LintResult still requires and declares rules (re-typed to LintRuleSummary)
  • The new assertions in crates/wright-cli/tests/cli.rs and crates/wright-driver/tests/service.rs assert rules is present with exactly two keys — the opposite of the required absence assertion; the PR measurement itself reports result.rules = 368 B
  • docs/cli/lint.md's envelope example and the machine-contract.md exception record describe the compact member rather than its removal

Required correction: remove the rules member on both paths; delete compact_lint_rules, the LintResult.rules field, and the LintRuleSummary schema def; rewrite the new assertions to assert rules absent and config complete per the AC (no hard-coded byte counts); update lint.md, machine-contract.md, commands.md, SPEC-99, and the agent-contract.md operation table to describe the removal. The lint_rule_flags_control_findings change to read config is correct and stays.

agent-contract.md versioning does not record the exception

#431 requires recording the approved pre-1.0 exception "in both docs/cli/machine-contract.md and the versioning section of docs/agent-contract.md, with its rationale and a link to this issue". The PR only adds a pointer to machine-contract.md (agent-contract.md ~L129) — no exception entry, no rationale, no #431 link. The lint operation change is itself a wright-agent/v1 exception and needs the record in that section.

Verified clean: lintRules payload untouched on both paths; config completeness demonstrated by the updated assertion; the text-mode renderer reads only findings; no other command's result changed; the new wright-result/v1 evolution policy matches wright-agent/v1 in substance.

The agent lint result now carries the same program summary as CompilerSession::lint, and compact_lint_rules skips malformed entries instead of emitting null id/effectiveSeverity fields. Schema, contract docs, and the service test updated to match.

Refs #431

@Teakowa Teakowa left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow-up review of b3251bce.

Correction first: my previous review's central finding was based on #431's 09:49 body, which the correction thread establishes was an unapproved recording. The final record — the issue's current Decision section and the "Final record of option C" comment — approves the compact [{id, effectiveSeverity}] shape this PR ships. Both earlier findings are withdrawn: the shape is correct, and the corrected AC only requires agent-contract.md versioning to link to the policy, which it does.

Two new findings in the new commit:

{"op":"lint"} gains an out-of-scope program member

b3251bce adds program to the agent lint response (service.rs), to LintResult.required + properties in schemas/wright-agent-v1.schema.json, to the agent-contract.md operation table, and to the ToolRequest::Lint doc. Before this commit the agent lint result never carried program (the CLI envelope did — the asymmetry is pre-existing).

#431's non-goals explicitly list "Changing lintRules, config, findings, skipped, input_identity, or program", and the approved pre-1.0 exception covers only the rules reduction. This is a second contract change riding in the same PR without an owner decision. Either revert the program hunks, or have the owner amend the issue to cover it.

AC2 test gap: no coverage for a --rule-loaded rule in rules

The corrected AC requires: "Every registered rule, including a local YAML rule loaded with --rule, appears in rules. Covered by a test." The suite covers only the six built-ins — cli.rs iterates the default set and service.rs finds min-wait-loop; no test passes --rule, and no local-rule fixture exists. Add one minimal YAML rule fixture plus an assertion that it appears in result.rules with the {id, effectiveSeverity} shape.

Verified on this pass: exact-key-set assertions exist on both paths (AC1); lintRules full metadata is covered by the unchanged path plus LintRule's required schema fields (AC3); the compact_lint_rules hardening drops malformed entries instead of emitting nulls — fine; lint.md, commands.md, machine-contract.md, and SPEC-99 match the approved reduced shape.

Pin the compacting projection against non-array input and non-object or non-string entries so malformed analyzer output can never produce schema-invalid lint rules.

Refs #431
The agent contract's versioning policy now names the same pre-freeze exception as machine-contract.md, SPEC-99 REQ-006 no longer points at the compacted lint rules entries for rule documentation, and lint.md lists the skipped member and the findings operation by their contract names.

Refs #431
@Teakowa

Teakowa commented Sep 29, 2026

Copy link
Copy Markdown
Contributor

Reviewed 60e438a8 and 003a1517 — both clean. The new compact_lint_rules edge-case tests and the agent-contract.md exception record (rationale + #431/#134 links) look good; the skipped/findings doc fixes in lint.md are correct.

Note: the two findings from my last review are still open — they were posted after these commits were likely in flight:

  1. program is still added to {"op":"lint"} (service.rs + schema required/properties), which is outside Reduce the lint result's inlined rule metadata to id and effective severity #431's approved scope — the issue lists program under non-goals. Revert, or get the owner to amend the issue.
  2. AC2's test gap stands: no test loads a local YAML rule via --rule and asserts it appears in result.rules.

Adding program to the lint operation exceeded issue scope: #431 lists program under non-goals. Revert the field, its schema entry, doc wording, and test assertion.

Refs #431
AC2 of #431: every registered rule, including a local YAML rule loaded with --rule, must appear in result.rules with the compact id/effectiveSeverity shape.

Refs #431

@Teakowa Teakowa left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@Teakowa
Teakowa merged commit db42356 into main Sep 29, 2026
22 checks passed
@Teakowa
Teakowa deleted the wright-431-lint-rule-metadata branch September 29, 2026 13:40
e54-bot pushed a commit that referenced this pull request Sep 29, 2026
Resolve the lint-result overlap with #436: keep the compact per-rule id/effective-severity payload and apply finding selection on top, on both the CLI lint result and the agent lint operation.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Development

Successfully merging this pull request may close these issues.

Reduce the lint result's inlined rule metadata to id and effective severity

2 participants