Skip to content

P1: Run truthful opt-in Ruff lint and format checks #258

Description

@tomdps

Parent

Tracking parent #211; epic #243. This is one vertical delivery slice. Do not close or bypass the parent tracker from this child.

Goal

Add real, read-only, opt-in Ruff lint/format validation over the exact after-state without relabeling source hygiene or degrading users who did not enable Ruff.

Dependency contract

Required behavior

  1. Keep python.source-hygiene as Opcore policy. Add separate python.ruff-lint and python.ruff-format definitions with defaultScopes:[]; execute only when explicitly requested or enabled via .opcore/config defaults. Unrequested=not_applicable, policy disabled=disabled, and neither probes/invokes/degrades enforced coverage.
  2. Resolve the P0 — Resolve Python projects, interpreters, environments, and tools canonically #246 Ruff tool/config per project and reuse P0 — Harden Python type checking and configuration semantics #245 exact after-state workspace/evidence. Run ruff check --output-format=json with fixes off and cache redirected/disabled; run ruff format --check in bounded batches, refining exit-1 batches per file to produce exact format findings without prose parsing.
  3. Valid lint empty/finding JSON and format clean/drift map passed/findings; selected config errors map invalid_config only with proof; missing/unsupported protocol/bounds, timeout, signal/spawn/overflow/malformed/unknown output/exit all remain exact non-pass.
  4. Preserve ruff.toml/.ruff.toml/[tool.ruff], nested/extend, select/ignore/per-file-ignore/exclude, formatter quote/indent/line-ending/exclude, and target version through overlays. Never invoke fix/write/format mutation mode.
  5. Status reports missing Ruff as enforced degradation only when a real Ruff check is enabled; metrics python.ruff_lint_findings/python.ruff_format_findings derive only from actual Ruff receipts; ASP executes only selected IDs.

Acceptance criteria

  • Absent/explicit/default/disabled activation proves zero process when not applicable/disabled; config precedence/nesting/extend and source/config add/change/delete overlays match real Ruff.
  • Clean, lint JSON finding, format drift, both, missing, invalid config, internal exit, timeout/signal/malformed/truncated/unsupported protocol all have exact receipts.
  • Real pre-provisioned Ruff and packed public opcore prove no fix/source/config/lock/environment/cache mutation, after-state parity, cleanup, and optional status/metrics truth.

Observable outcomes

  • Clean success carries positive execution/provenance evidence; zero diagnostics alone is never proof.
  • Findings and every unavailable/invalid/timeout/crash/resource/stale/unsupported state are machine-readable and fail or degrade exactly as the capability contract says.
  • No implicit fallback, partial result, or skipped execution is reported as a pass.
  • Target source, configuration, lockfiles, environments, and caches remain unchanged except where this issue explicitly owns a validation-gated atomic edit; every temporary resource/process is cleaned.

Non-goals

  • replacing source hygiene
  • applying fixes/format
  • installing Ruff
  • pytest
  • semantic service
  • readiness receipts

Verification

Run focused behavior first, then the configured repository proof only after the acceptance matrix works:

  • npm run build
  • node --test tests/validation-python.test.mjs tests/opcore-metrics.test.mjs tests/opcore-facade.test.mjs
  • npm run lint
  • Attach exact real-tool/artifact versions, argv/config/cwd/source, normalized result examples, before/after cleanliness evidence, and packed-install proof where the slice changes public package behavior.

Execution rule

Implement only after a just-in-time review against current dev. Keep exactly one implementation run active. PR base is dev; require green checks, clean scoped diff, merged PR, closed child, parent checklist update, focused reproductions, and opcore-ci proof before starting the next child. Do not claim Python readiness/parity, ASP authority, old-tool replacement, security/SAST, all-stack support, automatic fixes, or a blended score.

Just-in-time implementation contract (2026-07-18)

Baseline reviewed at origin/dev 2d4e920e0b08a989953486b261327ed7496c328b after merged #256/#257; #245 is closed. This child is now the sole allowed implementation slice. #259 must not start until this child passes its full completion gate.

Current dev truth

  • @the-open-engine/opcore-validation-python resolves Ruff executable/config provenance into each canonical PythonProjectContext, but exports no python.ruff-lint or python.ruff-format definitions and executes no Ruff validation.
  • createPythonValidationAdapterStatus currently reports every unavailable context tool through generic toolchain inventory, so repo status can degrade on Ruff even though no Ruff check was activated. Activation-aware status is part of this slice.
  • PythonValidationCapabilityRun and its schema/validators/fixtures are currently types-only (capability:"types", checkId:"python.types", mypy/Pyright tool name). Ruff execution evidence must extend the shared portable receipt contract rather than invent package-private or prose-only proof.
  • The accepted canonical context, import/source closure, exact after-state workspace, bounded process runner, and ASP/result aggregation seams already exist. Reuse them; do not create a second discovery, materialization, subprocess, or receipt path.

Required implementation and acceptance

  1. Add stable PYTHON_RUFF_LINT_CHECK_ID = "python.ruff-lint" and PYTHON_RUFF_FORMAT_CHECK_ID = "python.ruff-format" exports and definitions owned by validation-python. Both have defaultScopes: []; python.source-hygiene remains unchanged and must never be presented as Ruff.
  2. Preserve the existing validation-policy selection model: explicit request or .opcore/config validation.checks.defaults activates a Ruff check; checks.disabled wins. An unrequested check is not_applicable, a disabled check is disabled, and neither state runs Ruff nor degrades enforced coverage.
  3. Make Python adapter/status/scan/init/metrics reporting activation-aware. Ruff availability may remain canonical context inventory, but missing Ruff is a degradation only when at least one Ruff check is active. Inventory or config discovery alone is not execution evidence.
  4. Execute the P0 — Resolve Python projects, interpreters, environments, and tools canonically #246-selected Ruff executable/config in a P0 — Harden Python type checking and configuration semantics #245-style exact after-state workspace built from the immutable Hypothetical (validate pre-write) evaluation must be comprehensive — graph-backed checks are silently skipped #197/fix(python): share import resolution between validation and graph #209 source and config/support-file universe. The lint argv uses ruff check --output-format=json with fixes disabled and cache disabled/redirected; format uses bounded ruff format --check with no writes to the real repo. Preserve canonical project cwd, config, interpreter/environment provenance, source closure, time/output limits, and cleanup.
  5. Normalize lint and format findings deterministically into Opcore diagnostics with check-specific codes, source-relative paths/ranges where Ruff supplies them, and Ruff name/version/argv/config/cwd provenance. A nonzero finding exit is findings; spawn/timeout/signal/malformed-output/internal/config failures are fail-closed and distinct. Never round malformed or missing output to zero findings.
  6. Extend PythonValidationCapabilityRun plus JSON schema, validators, fixtures, package exports, ASP mapping, aggregation, scan-preview, and contract tests for portable Ruff lint/format receipts. Receipts bind project key, context fingerprint, selected source/config paths, after-state manifest fingerprint, tool, termination/exit, duration, and diagnostic counts without absolute temp/materialization paths or source contents. Preserve existing types receipt compatibility.
  7. Prove explicit/default activation, disabled precedence, unrequested zero-invocation, missing-activated-tool degradation, clean/findings/config-failure/timeout/signal/malformed-output states, overlays that change source and Ruff config, mixed projects, spaces/symlinks/platform path normalization, output truncation, temp/process/cache cleanup, repeated-run isolation, ASP propagation, status/metrics semantics, and no source/config/lock/environment/cache mutation.
  8. Public/package behavior changes require source tests and packed-install execution with a real pinned Ruff artifact. Record exact Ruff version, generated argv, selected config/cwd/source closure, normalized examples, before/after repository hashes, process/temp/cache cleanliness, and final opcore-ci proof on the exact merged candidate. Restore protected native/package/release artifact churn before commit/handoff.

Required focused commands remain the child body commands. Also run any changed contract/schema/ASP/status/packlist suites needed by the implementation. PR base is dev; green checks, clean scoped diff, merged PR, closed child, parent matrix update, real-tool/packed reproductions, and accepted opcore-ci are mandatory before #259. No Python readiness/parity or other forbidden public claim is authorized.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions