Skip to content

Migration Doctor

wolfxl.doctor gives a conservative migration verdict for a Python project and an optional workbook corpus. It is intentionally diagnostic-only: it does not modify source, load a workbook into Excel, install an import shim implicitly, or claim that a missing observation is support.

wolfxl.doctor is the public Python namespace. The wolfxl-doctor console script and python -m wolfxl.doctor expose the same canonical JSON contract.

One verdict, three evidence sources

from wolfxl.doctor import create_verdict

verdict = create_verdict(
    "application-src",
    workbooks=["fixtures/monthly-review.xlsx"],
)

print(verdict.to_dict())

create_verdict(...) combines:

  1. Static AST evidence. The scanner follows import openpyxl, aliases, from openpyxl... import ..., and attribute/call chains without importing or executing customer source. A static call resolves only when it has an unambiguous canonical compatibility entry. getattr, wildcard imports, dynamic imports, namespace-dictionary lookup, syntax failures, and unrecognised calls remain assessment: "unknown".
  2. Workbook-corpus evidence. Each supplied workbook is inspected through the existing wolfxl.compatibility.scan_workbook_compatibility inventory. Its findings[].status and not_assessed values are retained unchanged; Doctor does not translate them into a second status vocabulary.
  3. Optional runtime evidence. A RuntimeProbe may be used during a customer test run with the existing opt-in compatibility shim. Probe records are observations only. In particular, an API that was not seen statically or at runtime is never converted into runtime support.

Compatibility entries in the verdict are projections of docs/migration/_compat_spec.py. Their IDs, canonical API labels, WolfXL counterparts, gap_id, and status come from that source. The current parity ratchet is included as ratchet_supported when it covers the same API. The only compatibility statuses emitted by an entry are the specification's "supported", "partial", "not_yet", and "out_of_scope".

Operational output

Every successful verdict also adds three deterministic, additive fields without changing the source, workbook, runtime, or Fit fields:

  • coverage counts observed canonical operations as supported, partial, unsupported, or unknown. ratio is the exact supported/total fraction (including 0/0 when no operation was observed), never a rounded floating-point value. coverage.entries links each canonical entry to its relative source locations when static evidence exists.
  • workbook_risk_summary aggregates corpus-member counts, retained inventory statuses, retained not_assessed boundaries, and a conservative risk level.
  • remediation_plan contains stable action IDs, categories, severities, descriptions, evidence locations, canonical entry IDs, and canonical gap IDs. It is ordered by severity, category, and ID. Partial, unsupported, and unknown observations each receive an action; source and workbook locations are attached whenever the observation supplies one.

Locations retain only relative source paths and line numbers or workbook ordinals and feature labels. The operational fields do not include source text, call arguments, cell values, workbook paths, or OOXML part names.

Runtime probe

The probe is deliberately opt-in so routine diagnosis has no process-global import effects:

from wolfxl.doctor import RuntimeProbe, create_verdict, load_catalog

catalog = load_catalog()
with RuntimeProbe(catalog) as probe:
    probe.install_compatibility_shim()
    # Run customer-owned compatibility tests here.
    # Adapters with explicit shim hooks may report a known API:
    probe.record_api("openpyxl.Workbook")

verdict = create_verdict("application-src", runtime_probe=probe, catalog=catalog)

install_compatibility_shim() delegates to the existing wolfxl.openpyxl_compat.install_as_openpyxl() implementation. The probe does not remove the shim on exit because it did not own the caller's process state. record_api() accepts API names only; it does not accept or retain call arguments, cell values, workbook paths, or other customer data.

Canonical JSON CLI

Invoke the installed console script directly:

wolfxl-doctor application-src \
  --workbook fixtures/monthly-review.xlsx \
  --workbook fixtures/forecast.xlsx

The command writes exactly one canonical JSON document to standard output. It uses relative source display paths, corpus ordinals rather than workbook paths, and strips source text, call values, workbook cell values, inventory summaries, and OOXML part names. Invalid requests likewise return a generic JSON error without echoing a supplied path.

Exit aggregation is stable:

Code Meaning
0 All observed compatibility entries are canonical supported, the parity ratchet has no reported contradiction, and no unresolved or unassessed boundary remains.
2 At least one observed canonical entry requires remediation, the parity ratchet reports it unsupported, or the current inventory requires workbook review.
3 No canonical entry was observed, or a dynamic/static unknown or retained not_assessed boundary remains.

Code 2 takes precedence over code 3: the JSON document still contains every unresolved and unassessed boundary, while automation receives the actionable remediation result.

Boundaries

A supported canonical entry means only that the existing specification says that entry is supported. It is not a claim that the customer's application, inputs, workbook, formulas, rendering, or unsupported dynamic dispatch were validated. Use the resulting unknown and not_assessed evidence to decide what customer-owned tests or bounded before/after proofs are still required.