Skip to content

P1: Make Python package-subtree moves atomic and import-aware #268

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

Extend semantic moves to complete Python package subtrees with deterministic expansion, explicit asset/metadata support, import proof, atomic apply, and full layout rollback.

Dependency contract

Required behavior

  1. Accept a package directory only when old/new are one unambiguous package move inside the same supported P0 — Resolve Python projects, interpreters, environments, and tools canonically #246 project/source-root. Send the folder pair to willRenameFiles, then enumerate one bounded immutable subtree and simulate returned edits before physical expansion.
  2. Expand deterministic per-file operations plus explicit directory create/remove expectations; preview every descendant old/new path, checksum, source type, version, encoding/newline, and supported metadata. Destination absent; source cannot contain target; no cycle/case/duplicate/concurrent descendant.
  3. Required supported cells are .py, .pyi, init.py, namespace modules, and UTF-8 markers such as py.typed. Binary/non-UTF-8 assets, empty directories, ACL/xattr-only metadata, symlinks/hardlinks/special/generated/cache/read-only descendants are explicit refusal unless deliberately implemented and verified; never silently omit.
  4. Use fix(python): share import resolution between validation and graph #209 to compare all affected absolute/relative/re-export import edges and require semantic service completeness for every importer/submodule; validate full moved subtree through B exact after-state and gates.
  5. Apply only reviewed plans via B. Rollback restores importers, complete subtree contents/metadata, source directory layout, destination absence, and no unexpected/temp residue; incomplete layout verification is rollback_failed.

Acceptance criteria

  • Regular/src/namespace/nested packages, init re-exports, .pyi/py.typed, internal/external absolute/relative imports, and same-name other project are covered.
  • Destination-inside-source/partial/case/concurrent descendant, symlink/generated/read-only/special/hardlink/empty/binary/Latin-1/cap/service-incomplete cells explicitly refuse.
  • Validation and injected beginning/middle/end commit failures prove byte/listing/mode parity after rollback; no omitted asset or physical-only path remains.
  • Packed preview/apply and refusal receipts bind directory manifests, import edges, hashes/metadata/cleanup. Parent P1 — Make Python rename and module moves semantic and atomic #249 closes only after A-D and local proof pass.

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

  • arbitrary/cross-project directory moves
  • package-manager/config/lock migration
  • unsupported binary/encoding metadata
  • dynamic strings
  • unrelated formatting
  • readiness wording

Verification

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

  • npm run build
  • node --test tests/edit-preview-apply.test.mjs tests/semantic-provider-integration.test.mjs tests/inspect-commands.test.mjs tests/contracts.test.mjs tests/opcore-facade.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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions