Skip to content

Roadmap: what is done, what is next, and what is waiting on evidence #64

Description

@StefanKarpinski

The agreed sequencing, kept here so the order lives somewhere findable. One-line rationale each; details in the linked issues.

Current as of main at a595e04 (2026-09-12).

Where this stands

The resolver and its diagnostics are complete. What is left is not core work: it is a cache, two query forms, and the mechanics of shipping.

What is open, in full

Short enough now to list. Everything else is closed.

Umbrella #62 Pkg integration · #64 this roadmap
Explaining a success #52 holdbacks · #112 goals · #113 toolkit and --explain
Performance #55 persistence — modest, and evidence-gated
Blocked #63 multi-hop holdback stories, behind #52

The three explanation issues are one feature between them: pkg> why needs goals for presence answers and holdbacks for version answers, and the toolkit is how Pkg renders either in its own voice.

Done

Everything through #116. The load-bearing ones, newest first:

Next

The remaining feature work is one deliverable in three parts. pkg> why needs goals for presence answers and holdbacks for version answers, and the toolkit is how Pkg renders either in its own voice — so these are ordered by build cost, cheapest first, not by importance.

  1. Diagnostics should explain steering surprises: why a resolve was held back to an older julia (or package) version #52 — holdbacks. Why a package resolved below its best, and what to relax to move it. The cheapest of the three: the machinery is exactly what a conflict already uses, the proof checker verifies a holdback's lines with no changes, and the archived prototype supplies a scenario list. Closes the last asymmetry — a failed resolve gets a verified proof, a surprising success gets one character.
  2. Goals: resolve(…; with, without) — ask whether some solution has a property #112 — goals. resolve(…; with = X, without = X). More expensive than holdbacks because it is not just a query: a goal asks whether some solution has a property rather than about optimal ones, so reachability and redundancy are unsound for it. Carries theory (Proposition G, plus a counterexample in each direction) that should survive the port intact.
  3. Presentation toolkit: report() knobs, changes(), and --explain #113 — the presentation toolkit. report(io, d; knobs), changes(sol₁, sol₂), --explain, the guide section. Last because the structured surface is already public and documented, so Pkg can render its own reports today — and because every knob the prototype chose now aims at something that no longer exists. Best written against a real Pkg renderer.

Prior art for all three

archive/holdbacks-prototype is a pushed archive of a local branch that carried working prototypes of all three: holdbacks (c9e8b0c), goals (1539af3) and the toolkit plus --explain (3993297). Each is now captured as an issue with a build plan — #52, #112, #113 — and each issue names its own commit.

All three target src/Diagnose.jl and the Fact/UserCompat/Bound vocabulary that #105 replaced with clauses, and their tests assert wording that has since been retired: restricts for what is now leaves, and the symmetric "works with … only at" that directed verbs replaced. Read them for structure, theory and edge cases; re-derive every string.

They are not equally salvageable. Goals carries theory that should survive intact; holdbacks carries structure and a scenario list; the toolkit is mostly archaeology, since every knob it proposed aims at something main no longer has.

One thing found while capturing them: the prototype's upstream suggestions were never merged — but #114 has since shipped a better-founded version of the same idea, verified and narrowly scoped. What the prototype had that main still lacks is the knobs, not the feature.

Items 2 and 3 are what pkg> why needs. Presence answers come from goals, version answers from holdbacks; until both exist, why cannot be built on this.

Evidence-gated, not scheduled

Settled by measurement

Both of the measurements this section used to list have been taken, and they went opposite ways — which is the point of taking them.

Release

Worth stating plainly, because the mechanics have never been exercised: there are no tags, no GitHub releases, and Resolver is not registered in General. Project.toml says 0.2.0 and TagBot.yml is configured, but the path from here to an installable package has not been walked once.

Nothing in the code argues against releasing. CI is green across 1.9–1.13 plus nightly on four platforms, the suite includes registry-scale differential tests, and bin/resolve.jl has a production consumer in julia-downgrade-compat. The README's "experimental and research-stage" framing predates the diagnosis work and undersells what is here.

The one substantive question a release should settle is what is public. docs/src/api.md currently documents the diagnosis surface, the clause algebra and a block frankly labelled "Internals" (PkgInfo, prepare_pkg_info, exclusion_masks, find_reachable, …). Anything documented is something a user may reasonably pin to. Deciding which of those are 0.x-stable, and which should be marked as internal in a way that permits change, is cheaper before a release than after.

The Pkg test drive

Still not scheduled against a PR — but the calculus has changed. The unsatisfiable path is ready to review now: the API is stable, the reports are verified, the modelling conventions on #62 are settled.

JuliaLang/Pkg.jl#4738 targets the #30 API, three generations stale, and should be rewritten rather than rebased. KristofferC's feature-flag rollout — new resolver as default, old one retained — is unchanged and still right.

Principle behind the order

Structure before what is built on it; representation before persistence; performance and polish only where evidence points.

One addition, earned rather than assumed: where an issue's own text says "measure first", the measurement is the work item, and no successor is scheduled until the number exists. #60 and #91 were the test of it, and they went opposite ways — #60's penalty was real and got implemented, #91's payoff was exactly zero and got closed. Neither outcome was predictable from reading the issue, and #91's measurement in particular cost a script, because both rules turned out to be in the tree already.

#118 added a second lesson, cheaper than a measurement: check the premise before scheduling the gate. It was closed on 2026-09-15 without its measurement ever being run, because the mechanism it named was not the one at work — upstream fixes read PkgData.compat directly, so direction was never missing; what declines the registry-versus-registry case is a deliberate refusal to judge between two maintainers, which a direction bit does not resolve. The measurement would have counted the right rejections for the wrong reason.


🤖 Maintained with Claude Code.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions