Release runway — maraxen/jaxlint first public cut#
task_id: jaxlint-release-readiness-2026-05-06
Status: Pre-publish. Synthesized from a parallel critique/defense audit (see .praxia/audits.jsonl rows audit-release-readiness-critique-2026-05-06 and audit-release-readiness-defense-2026-05-06).
Synthesis verdict: GATE-with-runway — proceed along this runway, not directly to pypi upload. The defense’s own minimum checklist concedes most GATE blockers; the disagreement is sequencing, not direction.
Why a runway, not a “ship now”#
Claim |
Defense |
Critique |
Synthesis |
|---|---|---|---|
MIT + src layout + hatchling + 143/1 passing + 79.7% coverage |
strength |
acknowledged |
engineering is alpha-ready |
Missing |
“post-ship polish” |
“PyPI metadata gap” |
fix before first upload (cheap; defines the project page) |
|
not raised |
authenticity / supply-chain risk |
fix — pick “single author” or “contributors” and be consistent |
No |
not raised |
required signals for first OSS release |
add — minimal versions, link |
PR CI doesn’t run full suite + coverage gate |
acceptable trade-off |
correctness risk for first external user |
tighten — full suite on PR (cost is small; current PRs are fast) |
|
“subprocess artifact, integration tests pass” |
“no end-to-end stdio smoke” |
add one stdio smoke test spawning |
RTD + |
“chicken-and-egg, resolves on push” |
“README’s first link is broken at publish time” |
stand up GitHub + RTD before PyPI upload so first-impression links work |
No release workflow, no tags, no |
not raised |
supply-chain |
add |
Version |
“honest signaling” |
“semver/lifecycle mismatch — 0.4.x reads as ruff-style stable-ish” |
either reset to |
OpenCode staging |
“real users get value today” |
“theoretical until exercised through MCP Inspector” |
stage post-publish and treat as 0.5 milestone evidence |
GATE wins where the two disagree (workspace audit-synthesis convention). The defense is right that the engineering is ready; the critique is right that the release is not.
Phased runway#
Each phase has a gate (single objective question). Don’t advance until the gate clears.
Phase R1 — Identity & metadata (≤ 1 day)#
Gate: Does the PyPI page render correctly with valid metadata, and does the LICENSE match reality?
Decide: single-author “Marielle
” or “jaxlint contributors” with at least one external acknowledgement. Updatepyproject.tomlauthorsandLICENSEcopyright line consistently.Add
[project.urls]topyproject.toml:Homepage = "https://github.com/maraxen/jaxlint"Documentation = "https://jaxlint.readthedocs.io/"Repository = "https://github.com/maraxen/jaxlint"Issues = "https://github.com/maraxen/jaxlint/issues"Changelog = "https://jaxlint.readthedocs.io/en/latest/changelog.html"
Add classifiers:
Programming Language :: Python :: 3.11,:: 3.12,Typing :: Typed(thesrc/jaxlint/py.typedmarker is already present).Decide version semantics:
Option A — reset to
0.1.0(matchesAlpha). Re-tag changelog history as0.1.0with a “previously developed under 0.x.y” note.Option B — graduate to
Development Status :: 4 - Betaand keep0.4.x.The runway assumes Option A unless the maintainer explicitly chooses B.
Refresh
docs/lsp.md(“as of 0.4.0”), README CLI list (addversion), and README MCP paragraph (addjaxlint_rules/jaxlint_version). README’s--formatline stays as-is; optionally mentiongithub-annotationsalias.
Phase R2 — Governance & community files (≤ 1 day)#
Gate: Does GitHub’s “community standards” checklist show green for a first-time visitor?
Top-level
CONTRIBUTING.md(one screen; can simply summarize and linkdocs/contributing.md).SECURITY.md(single contact + supported-versions table — even if it’s only0.1.x).CODE_OF_CONDUCT.md(Contributor Covenant 2.1 verbatim is fine)..github/ISSUE_TEMPLATE/bug_report.mdandfeature_request.md(minimal frontmatter)..github/PULL_REQUEST_TEMPLATE.md(link contributing, DoD checklist).
Phase R3 — CI tightening (≤ 1 day)#
Gate: Can a first external PR break a unit / integration / cache test without CI catching it?
.github/workflows/ci.yml: runuv run pytest -q --cov=jaxlint --cov-report=term-missingon every PR (drop themain-only guard) on the existing 3.11/3.12 matrix. Coverage runtime is currently ~7s with full extras — cost is negligible.Keep the merge-blocking
jax-hlojob as-is.Add a
releasejob stub (no-op until R5) so the matrix is visible.
Phase R4 — LSP smoke & build verification (≤ 1 day)#
Gate: Have we exercised the actual published artifacts end-to-end?
One subprocess stdio smoke test for the LSP: spawn
jaxlint-lsp, sendinitialize+initialized+textDocument/didOpen, assert atextDocument/publishDiagnosticsarrives for a JL-violating snippet. Mark@pytest.mark.lspso it joins the existing PR job.Add a build-and-install smoke (local script or CI job):
python -m build→twine check dist/*→ install the wheel into a fresh venv →jaxlint --version,jaxlint-lsp --help,jaxlint-mcp --helpall exit 0. Document the command sequence indocs/contributing.mdunder a “release verification” subsection.
Phase R5 — Public surfaces stand up (≤ 1 day)#
Gate: Do every link in the README and roadmap resolve to HTTP 200?
Create
github.com/maraxen/jaxlint, pushmain, enable Issues + Discussions (optional but cheap).Import the repo in Read the Docs; verify the project slug is
jaxlint(matches the README link); trigger a build.Once both return 200, shrink
linkcheck_ignoreindocs/conf.pyand update the Canonical hosted URLs table indocs/roadmap.md(HTTP 200, today’s date, drop the404rationale).
Phase R6 — Release workflow & first publish (≤ 1 day)#
Gate: Can we ship subsequent versions reproducibly from a tag without anyone touching an API token?
Configure PyPI Trusted Publishing for the repo (PyPI side: pending publisher; GitHub side: environment).
Add
.github/workflows/release.yml:Trigger: annotated tag matching
v*.Steps: checkout → setup uv →
python -m build→twine check dist/*→ publish via Trusted Publishing → attach sdist+wheel to a GitHub Release whose body is the matchingdocs/changelog.mdsection.
Cut
v0.1.0a1(pre-release alpha) orv0.1.0when stable, orv0.4.2under Option B. Confirm the wheel + sdist on PyPI install cleanly in a fresh venv.
Phase R7 — OpenCode staging (post-publish, ≤ 1 day)#
Gate: Have we observed a real MCP host calling jaxlint_check on a real path with structured output, and a real editor with the OpenCode lsp.jaxlint block reporting diagnostics?
Follows the staging plan from the orchestrator’s prior recon (docs/lsp.md, README MCP section, OpenCode config schema).
pip install jaxlint[lsp,mcp]from PyPI in a clean venv.Clone a small JAX-ish sample repo; drop in a minimal
jaxlint.toml.CLI baseline:
jaxlint check .— capture diagnostics output for comparison.MCP Inspector pass: run
jaxlint-mcp; confirm tool list (jaxlint_check,jaxlint_capabilities,jaxlint_rules,jaxlint_version); calljaxlint_checkwithstructured=trueon the same paths; diff the diagnostics against step 3.OpenCode MCP block: add
mcp.jaxlint(local stdio) to OpenCode config; invoke from an agent prompt; confirm parity with step 4.OpenCode LSP block: add
lsp.jaxlintwithextensions: [".py"]; open a.pyfile with a known JL violation; confirm diagnostics track edits. SetJAXLINT_LSP_DEBOUNCE_MS=0while debugging.Conflict check: if pyright also attaches to
.py, narrow extensions or disable one server so behavior is predictable.Capture a transcript / screenshot and attach to the next release notes (or a
docs/staging-opencode.mdnote) — converts the OpenCode claim from theoretical to evidenced.
Definition of Done (overall)#
The runway is complete when:
PyPI page for
jaxlintshows Homepage / Docs / Repo / Issues / Changelog.pip install jaxlintin a clean venv exposesjaxlint,jaxlint-lsp,jaxlint-mcpand the right--version.github.com/maraxen/jaxlintandjaxlint.readthedocs.ioboth return 200.Every PR runs the full pytest + coverage gate on 3.11/3.12, plus
jax-hlo.An LSP stdio smoke test asserts
publishDiagnosticsround-trip from a spawnedjaxlint-lsp.release.ymlpublishes fromv*tags via Trusted Publishing.Version classifier matches version: either
Alpha+0.1.x, orBeta+0.4.x— not the current contradiction.An OpenCode session has actually exercised both
lsp.jaxlintandmcp.jaxlint.
Roadmap deltas#
Move these into docs/roadmap.md as a new “Release runway” sprint section:
ID |
Deliverable |
Phase |
|---|---|---|
RR1 |
|
R1 |
RR2 |
Version semantics decision (reset 0.1.0 or graduate Beta); doc/README/lsp version refresh |
R1 |
RR3 |
|
R2 |
RR4 |
Full pytest + coverage gate on every PR |
R3 |
RR5 |
LSP stdio subprocess smoke test ( |
R4 |
RR6 |
|
R4 |
RR7 |
GitHub repo public, RTD project built once; |
R5 |
RR8 |
|
R6 |
RR9 |
OpenCode staging transcript (MCP Inspector + LSP) attached to the release notes |
R7 |
Existing Polish horizon items remain post-RR9 work.