Skip to content

P1: Preview Python semantic rename as checksummed WorkspaceEdit #265

Description

@tomdps

Parent

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

Goal

Return a deterministic, non-writing, hash-bound Python semantic rename preview from prepareRename/rename while making exact text visibly non-semantic and eliminating every hidden fallback.

Dependency contract

Required behavior

  1. Dispatch .py/.pyi through the injected P1 — Add truthful Python LSP semantic inspection and navigation #248 semantic client. Run prepareRename and rename in the same immutable input snapshot/epoch; a restart redoes both and requires identical prepared identity. Bind normalized symbol name/kind/definition range, prepare range/placeholder, target version/hash, P0 — Resolve Python projects, interpreters, environments, and tools canonically #246 context, and stable provider/config/interpreter provenance.
  2. Normalize exactly one LSP WorkspaceEdit shape (changes xor ordered documentChanges). Accept only canonical in-repo file URIs; negotiated position encoding; valid original-document ranges; matching document versions; deterministic non-overlapping edits. Refuse unsupported/malformed operations, schemes, authorities, encodings, aliases, traversal, CRLF splits, stale/null unsaved versions, overlaps, conflicts, and unreviewable annotations.
  3. Preview every range with old/new text, normalized range/offset/order/version/checksums and every file with workspace/overlay preimage, service/final checksum, BOM/line-ending/final-newline metadata. Simulate ordered operations, retain source-operation digest, collapse only final effect into deterministic validation overlays; null/empty rename is semantic_no_edit.
  4. Create edit-owned content identities: inputSnapshotId over canonical repo/context/sorted path-source-version-content checksums and overlays; baselineHash over the complete validation-visible universe; afterStateHash after edit; planHash over intent/symbol/operations/files/snapshot/provenance/exact requested validation set, excluding temp/session/time data. Derive planId and require repeated previews to match byte-for-byte.
  5. Add stable nested outcome/phase/refusal codes. Any ambiguous/degraded/unsupported/unavailable/invalid/timeout/crash/restart mismatch/cancel/protocol/snapshot/range/path state refuses before write; semantic failure never calls exact/search/patch/tree/lexical graph replacement.
  6. Make every edit intent/semantic flag explicit. Exact is semantic:false, preserves checksum/occurrence guards, and returns total matchCount even on success. Python move refuses semantic_move_unavailable until later children; Python rename apply refuses preview_required until B. Hidden warm ASP may preview only.

Acceptance criteria

  • Local/parameter/method/class/function/module alias/imported/re-exported symbols, duplicate scopes, inheritance/override/property, unique position, ambiguous/defaultBehavior, invalid new name, service failure/cancellation/restart, and no-edit results are covered.
  • changes/documentChanges/annotations/disk-null version/overlay versions, Unicode astral UTF-16, LF/CRLF/mixed/BOM/no-final-newline, multi-file, duplicate/overlap/out-of-range/conflicting insert/non-file/out-of-root operations produce exact previews/refusals.
  • Repeated preview is byte/hash identical and worktree unchanged; Python move/one-shot apply fail closed; exact 0/1/N/occurrence/stale/success matchCount is semantic:false.
  • Clean installed public opcore preview records tarball/service/context/snapshot/plan/ranges and absent-service typed refusal with no text fallback. No checked-in release receipt refresh.

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

  • apply/rollback
  • resource file operations
  • module/package moves
  • provider lifecycle implementation
  • type selection/import parsing
  • readiness wording
  • automatic codemod/tool install

Verification

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

  • npm run build
  • node --test tests/edit-python-rename-preview.test.mjs tests/contracts.test.mjs tests/edit-symbols.test.mjs tests/inspect-commands.test.mjs tests/asp-provider.test.mjs tests/opcore-facade.test.mjs tests/installed-bins.test.mjs
  • npm run lint
  • npm run pack:check
  • bash ./scripts/ci/run-local-ci-equivalent.sh
  • 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions