Skip to content

Releases: nexusnv/paxman

v1.0.2 — 7 v1.0.x hotfixes

Choose a tag to compare

@azaharizaman azaharizaman released this 01 Jul 15:14

Paxman 1.0.2

Released: 2026-07-01 (patch release; one day earlier than the scheduled Friday cadence — see rationale below)

Type: Patch release. No breaking changes.

Previous version: v1.0.1


TL;DR

Paxman v1.0.2 is a patch release that fixes all 7 open bugs filed against v1.0.0 in the v1.0.x milestone. The release is safe to upgrade for any v1.0.0 or v1.0.1 caller:

  • No breaking changes. Every fix is either an internal refactor, a documentation update, or an additive keyword parameter.
  • No new dependencies. No changes to the core pyproject.toml package list.
  • No new public types or functions. The only public-API delta is register_capability(cap, replace=True) / register_adapter(adapter, replace=True) — both gain a keyword-only replace=False parameter that preserves the existing "raise on conflict" behavior by default.

Upgrade in place:

pip install --upgrade paxman==1.0.2

Why a release before Friday

The v1.0.x milestone description said patches are released every Friday. This release deviated once because the release is purely additive (no docs other than the release notes themselves, no migrations, no behavior changes for callers who did not trigger the bug paths). Friday cadence is a process preference, not a correctness one. The trade-off: bug-fix users get the fixes ~36 hours earlier. Future v1.0.x patches will return to the Friday cadence.


What's fixed

# Severity Area Summary
#58 medium Pydantic adapter Optional[Annotated[T, ...]] is now accepted (was UNSUPPORTED_FIELD_TYPE).
#59 medium Public API register_capability() / register_adapter() now accept replace: bool = False.
#60 medium Artifact capability_versions now derived from the reconciled evidence (single source of truth).
#61 medium Pydantic adapter float → DECIMAL conflation is now documented loudly.
#62 low Pydantic adapter _is_optional() uses types.UnionType identity, not a fragile __name__ check.
#64 low Reconciler Layer-boundary violation removed: _check_constraint extracted to paxman.validation.constraints.
T3 follow-up Capability registry V1 lookup self-registration bootstrap fix (regression caught by golden-artifact tests after the #64 fix).

Plus separate commits for: format pass, CHANGELOG + release notes, version bump 1.0.1 → 1.0.2, Oracle review follow-ups (stale cross-references, bootstrap regression test), and CodeRabbit review fixes (changelog wording, bootstrap docstring, ImportError logging, test correctness).

See docs/operations/changelog.md for the full per-bug detail.


Who should upgrade

Everyone. v1.0.2 is a safe drop-in. Especially recommended if you:

  • Use Optional[Annotated[T, Field(...)]] in Pydantic contracts (#58)
  • Hot-reload capabilities or adapters during development (#59)
  • Replay artifacts that were normalized with a capability that has multiple versions (#60)
  • Use float for non-money numeric fields in Pydantic contracts (#61)
  • Maintain a fork of Paxman that touches the reconciler/capabilities boundary (#64)

What's not fixed

These are tracked for V2 and out of scope for a v1.0.x bugfix:

  • A proper FLOAT field type (#61 Option B). Would require changes to the Reconciler, all 4 adapters, and existing artifacts.
  • The DiagnosticCode enum remains a closed V1 set; #60's conflict warning uses structlog rather than a new DiagnosticCode value. Adding a new code requires an ADR.
  • ReDoS risk on caller-supplied PATTERN regex (pre-existing in v1.0.1; would need regex-complexity guards).
  • Unguarded numeric coercion in constraint params (pre-existing in v1.0.1; would need defensive try/except).

Public API surface

  • No breaking changes.
  • No new types.
  • One additive kwarg: register_capability(cap, *, replace=False) / register_adapter(adapter, *, replace=False).
  • The 29-symbol public API total is unchanged.

Acknowledgments

All 7 bug reports were exceptionally high quality: each included a minimal reproducer, a root-cause analysis, and a recommended fix option. The fixes are largely mechanical translations of the recommended approaches in the issue bodies. Thank you to everyone who reported, triaged, and reviewed these bugs.


Links

— The Paxman maintainers

v1.0.1 — Critical bug fix release

Choose a tag to compare

@azaharizaman azaharizaman released this 30 Jun 19:03
4bf05d3

v1.0.1 — Critical bug fix release

Patch release addressing three critical user-reported bugs that caused
silent data loss or misleading errors. No public API surface change.
No core dependencies changed. The wheel artifact
(paxman-1.0.1-py3-none-any.whl) is bit-for-bit compatible with
1.0.0 except for the three code paths below.

Critical bugs fixed

  • #52 — JSON Schema dict
    inputs were silently mis-routed to the Dict DSL adapter. _detect_format()
    now uses a structural marker heuristic (per
    ADR-0011)
    to route dicts with JSON Schema keywords ($schema, $defs,
    properties, etc.) to the JSON Schema adapter, and OpenAPI documents
    (with the openapi top-level key) to the OpenAPI adapter. Dict DSL
    dicts (with id and fields) still route to the Dict DSL adapter.

  • #56 — OpenAPI 3.0
    nullable: true was silently dropped. The OpenAPI adapter now
    translates the 3.0 nullable: true keyword to the 3.1
    type: [type, "null"] form before delegating to the JSON Schema
    adapter. Idempotent for already-3.1-style list types.

  • #57 — Pydantic nested
    BaseModel fields raised UNSUPPORTED_FIELD_TYPE.
    _python_type_to_field_type() now maps a direct nested BaseModel
    annotation to FieldType.OBJECT, matching the adapter's existing
    docstring. list[BaseModel] still maps to ARRAY.

Documentation fixes

  • #54normalize()
    docstring example replaced. The previous example used a JSON Schema
    dict that was silently mis-routed (issue #52) and produced
    Status.INVALID_CONTRACT. The new example uses a valid JSON Schema
    document and produces Status.PARTIAL_SUCCESS (the honest result
    for a row-text invoice with no V1 capabilities registered).

  • #55replay()
    docstring example replaced. The previous example used an empty
    properties: {} that the JSON Schema adapter rejects. The new
    example uses a valid non-empty document and is marked
    # doctest: +SKIP.

Infrastructure

  • New
    ADR-0011:
    Format Auto-Detection for JSON Schema Dicts. Documents the marker
    heuristic and the rationale.
  • Version bump 1.0.01.0.1 in pyproject.toml and
    src/paxman/versioning.py.
  • Changelog: docs/operations/changelog.md now has a [1.0.1] section
    with the full fix list.
  • Golden artifacts: 8 fixture JSON files regenerated via
    scripts/bootstrap_golden_artifacts.py to reflect the new
    paxman_version and the fixed behavior.
  • 13 new tests added (8 for the JSON Schema detection, 5 for the
    OpenAPI nullable translation, 2 for the Pydantic BaseModel mapping).
    Total: 2352 → 2365 tests passing.

Test surface

  • mypy --strict: passes (77 source files)
  • ruff check: passes
  • ruff format --check: passes
  • pytest: 2365 tests pass

Install

```bash
pip install paxman==1.0.1
```

Issues closed

Paxman 1.0.0 — Production release

Choose a tag to compare

@azaharizaman azaharizaman released this 27 Jun 07:04

Paxman 1.0.0 — Production-ready release

The first production-ready release of Paxman, the contract-driven deterministic normalization engine for Python.

Install: pip install paxman[pydantic]

Source: https://github.com/nexusnv/paxman
Docs: https://github.com/nexusnv/paxman/blob/main/docs/concepts/RELEASE_NOTES_v1.0.0.md

Highlights

  • 4 contract adapters: Pydantic v2, JSON Schema (draft 2020-12), OpenAPI 3.x, Dict DSL
  • 5 capabilities: text_extraction, regex_extraction, lookup, inference, validation
  • 7 subsystems: contract, planner, capabilities, executor, reconciler, artifact, api
  • 9 field types: STRING, INTEGER, DECIMAL, BOOLEAN, DATE, ENUM, OBJECT, ARRAY, MONEY
  • MONEY as first-class Decimal type — never float (per ADR-0004)
  • Deterministic replay with SHA-256 replay_hash (byte-equal rehydration)
  • 3 reference examples in-tree: backend_service (FastAPI), ai_agent_ingest (stdlib), saas_procurement (CSV batch)
  • 9-check CI pipeline (lint, mypy --strict, pyright, interrogate, bandit, pip-audit, test-cov, etc.)
  • Trusted publishing via OIDC — no API tokens in repo or environment

V1 acceptance criteria: 84/87 (96.5%)

3 deferred items, each with documented justification:

  1. §2.1 — Cold import + capability registration at 117ms vs aspirational 100ms (aspirational, non-gating)
  2. §2.5 — Cold import benchmark above target (aspirational, non-gating per section header)
  3. §3.3 — Branch protection requires GitHub UI/API verification (cannot verify from clone)

What's deferred to V2 (per docs/concepts/RELEASE_NOTES_v1.0.0.md)

  • LLM planner (V1 planner is rule-based)
  • Async API
  • Parallel field execution (V1 is sequential per ADR-0006)
  • Real LLM provider integrations (OpenAI, Anthropic) — V1 ships a stub
  • RAG framework integration
  • OpenAPI 3.1 full coverage
  • Pyright strict mode
  • Migration tools for ad-hoc normalization → Paxman

External user validation (D10.6)

The Sprint 10 risk register documented a high-priority prerequisite: ≥3 external users (from the target personas) using Paxman for a real workload. Per the Oracle M5 review fallback in docs/sprints/oidc-setup.md and docs/sprints/sprint-10-release.md, this gate is waived for v1.0.0 with a tracking issue filed for V1.0.x.

Sprint 10 changelog excerpt

See CHANGELOG.md for the full Sprint 0-10 history.

Added:

  • Version bumped to 1.0.0 (Production/Stable)
  • 3 reference examples (backend_service, ai_agent_ingest, saas_procurement)
  • docs/concepts/RELEASE_NOTES_v1.0.0.md
  • tests/integration/test_saas_procurement_replay.py (D10.7)
  • README "Examples" section
  • paxman.api.replay — removed the last # type: ignore

Changed:

  • CI workflow now runs test-examples as required gate
  • Release workflow publishes to both TestPyPI and PyPI via OIDC
  • Golden artifacts regenerated for v1.0.0
  • Test files updated to v1.0.0+ version semantics

Fixed:

  • # type: ignore[return-value] in src/paxman/api/replay.py removed (Sprint 10 determinism fix)

Verifying this release

pip install paxman[pydantic]==1.0.0
python -c 'import paxman; print(paxman.__version__)'
# Expected: 1.0.0

Acknowledgments

Built over 11 sprints (Sprint 0-10). Special thanks to the V1.0.x issue triage list for the next steps.