Skip to content

Releases: cdnwetzel/pxx

pxx 2.5.4

Choose a tag to compare

@github-actions github-actions released this 20 Aug 00:40
456af35

Added

  • pxx doctor flags self-review — the reviewer defaults to the author model.
    Settings.effective_review_model falls back to the coder model when no [roles.review]
    overlay is set, so the shipped default puts the same model that wrote the diff in front
    of it as the judge — while pxx loop --review runs BLOCKING by default. A model cannot
    independently review its own output: it carries the blind spot that produced the defect,
    so the gate reports a pass it was never able to withhold, and that pass is then recorded
    as evidence. This is the vacuous-gate failure mode, and it is worse than having no gate.
    The new review:independence check reports three states: a distinct reviewer model passes;
    the same model on the same endpoint warns as SELF-review; the same model on a different
    endpoint still warns, because separate hardware is not separate judgement — identical
    weights carry identical blind spots. Warning-grade, never a hard failure: a single-model box
    is a legitimate if weaker posture, and doctor reserves hard failures for the runtime itself.
    The check compares settings.model — what Session actually constructs — rather than the
    author lane, which resolves in config but is not yet wired to the runtime; reading it
    would report an independence the loop does not have. Negative control per repo practice,
    stated as the mutation matrix actually measured rather than as a summary: against a mutant
    that always returns ok with a plausible pass detail, the three negative-path tests
    fail
    — including the one asserting the check is registered in run_doctor, since a check
    nobody calls is the vacuous case for the check itself — while the distinct-reviewer test
    survives, because it is the positive control, not a negative one. The inverse mutant
    (always warn) is caught by exactly that distinct-reviewer test and by nothing else. So the
    four tests pin the check in both directions, with no single test doing both jobs. (A weaker
    always-ok mutant carrying a placeholder detail string fails all four, which is why the
    first pass of this note over-claimed a 4-of-4 kill; CodeRabbit caught it on review.)
    Verified on hardware both ways — a clean HOME with no config fires
    the warning out of the box; a configured two-box coder/judge split passes.
    Docs: docs/CONFIG.md §[roles.review] gains an Independence note.
    Known limit: doctor reports this, the loop does not — a run that never invokes
    pxx doctor still gets a blocking gate it cannot fail. Making BLOCKING mode itself
    refuse, or require an explicit allow_self_review opt-in, is carded and not in this release.

pxx 2.5.3

Choose a tag to compare

@github-actions github-actions released this 18 Aug 04:35
b39f997

Changed

  • Greenfield gate soundness locked with a regression guard. A clone-from-docs probe
    raised a concern that the regression-relative test gate might vacuously pass broken
    greenfield code (a node appeared to reach COMPLETED on a module with a SyntaxError).
    A deterministic reproduce disproves it: run_loop on a suite that fails from round 1
    terminates LOOP_DETECTED / a non-success code, never COMPLETED
    (tests/test_loop.py::test_greenfield_failing_baseline_never_completes) — the apparent
    pass was a confound (lost per-round log + a sandbox whose state did not match the recorded
    outcome), the same failure mode as the earlier "planner fails greenfield" report. The gate
    is sound; a regression guard now locks that in and the roadmap claim is withdrawn. No
    behaviour change — a test + doc correction that hold the gate to its negative-control
    discipline (reproduce cleanly before carding a gap).

pxx 2.5.2

Choose a tag to compare

@github-actions github-actions released this 18 Aug 04:16
5703fbe

Added

  • Goal planner runs on the roles.plan lane. pxx goal's read-only planner now
    resolves Settings.effective_role("plan") (via a testable _planner_settings helper),
    so a reasoning/planning model can decompose the goal into the task DAG while the coder
    builds it — the second consumer of the 2.5 role-lane map, matching a separate PLAN role
    (reasoning brain ≠ builder). Falls back to the coder model when [roles.plan] is unset
    (byte-identical to before). Surfaced by the clone-from-docs probe. NOTE (honesty): the
    probe's initial "planner fails greenfield with OUT_OF_SCOPE" report was a harness
    artifact
    — a uv run --directory invocation ran the planner in the wrong repository; a
    clean reproduce shows pxx goal works greenfield end-to-end. So this is an architectural
    enhancement (reasoning-planner support), not a bug-fix. +2 tests.

pxx 2.5.1

Choose a tag to compare

@github-actions github-actions released this 17 Aug 20:45
bce3134

Fixed

  • Embedding-space versioning for observation memory (fail-closed on embedder swap).
    Stored vectors carried no record of which embedder produced them, so changing the memory
    embedder (or the roles.embed model) silently made search() compute cosine across
    incomparable spaces — confident garbage with no error, and worst in observation memory,
    which accumulates for months and is never reindexed. The store now stamps its
    embedding-space identity in a meta table, and set_embedder fails closed with
    EmbeddingSpaceError when a different identity is attached over existing vectors —
    targeting the dangerous same-dimension / different-model case (a plain dimension
    mismatch already threw). Recovery: MemoryStore.reset_embedding_space() clears the
    vectors + stamp and detaches the embedder (re-add observations to re-embed under the new
    embedder — it does not auto-reindex), or repoint to the original embedder. Empty stores
    adopt a new embedder freely; pre-versioning
    stores with vectors assume the current embedder (logged warning, not a hard fail).
    Embedders now expose an identity (HashEmbedderhash:dim=N, OllamaEmbedder
    ollama:<model>). This is the retrieval analogue of the content-truthfulness gate —
    refusing to answer from a corrupt index is refusing to fabricate, not judging. +10 tests
    including a same-dim/different-model negative control. Prerequisite for the forthcoming
    repo code index; flagged by PSAIOS in coordination.

pxx 2.5.0

Choose a tag to compare

@github-actions github-actions released this 17 Aug 20:38
0937c13

Added

  • Generalised per-role model lanes — [roles.<name>]. The reviewer overlay
    ([roles.review], shipped 2.2.0) is widened to a closed, validated role-lane
    map
    : author, reviewer, plan, fast, verify, embed. Each lane names a
    (provider, model, base_url, api_key) quadruple resolved late against the coder
    model, so different roles can run on different families/endpoints — the driver
    is family independence on the judgment axis (the reviewer/verifier should not
    share the author's lineage). Settings.effective_role(name) is the one resolver
    role consumers call. New per-lane env parity PXX_<ROLE>_{MODEL,PROVIDER,BASE_URL, API_KEY} (reviewer keeps PXX_REVIEW_*). review is a back-compat alias for
    reviewer; review_model / [roles.review] / PXX_REVIEW_* / --review-* are
    unchanged and the reviewer path is byte-identical (proven by the existing review
    suite staying green). An unconfigured box is byte-identical to before — every
    unset lane resolves to the coder model. The closed set is fail-closed on an
    unknown role; opening it later is non-breaking, narrowing is not.
  • Egress guard covers every lane. Role routing is a data-egress surface for all
    lanes (the diff for the reviewer, source chunks for embed, the prompt for any
    lane), so the entire [roles] table is honoured only from user config, env, or
    CLI — a repo-local pxx.toml can redirect no lane (ignored with a warning).
    Every lane inherits the reviewer's exfil protection by construction. pxx owns
    role→model name; endpoint/node placement stays a pluggable adapter (never
    a second placement authority) — advancing the ROADMAP "model-backed boundary
    roles" item. embed is reserved for the forthcoming repo code index.

Fixed

  • User-config symlink trust check now uses the repo root, not just cwd. The
    symlink-into-project guard (which downgrades a ~/.config/pxx/config.toml
    symlinked to repo-editable content to untrusted) compared the target against
    cwd. From a nested working directory, a symlink targeting a repo file that
    is an ancestor of cwd escaped the check and was trusted — letting a repo file
    smuggle allow_ungated_shell / memory_capture_successes / hooks / role-lane
    routing past the A0b gate. Containment is now checked against the repository root
    (_repo_boundary, nearest .git ancestor), closing the bypass; regression test
    added. Found pre-flight by CodeRabbit while reviewing the role-lane map (whose
    new lanes widened this guard's responsibility).

pxx 2.4.4

Choose a tag to compare

@github-actions github-actions released this 17 Aug 03:29
270a009

Changed

  • Review prompt: severity discipline to stop small reviewers over-flagging. The review gate's
    system prompt (pxx/prompts/review.md) told the model to APPROVE only with "no high or medium
    findings" but never that style, comments, renames, test-only edits, import order, and refactors
    that keep tests green are not defects
    — so smaller judges rated acceptable-change nitpicks as
    medium and voted REVISE. Added an explicit rule reserving high/medium for real correctness
    or safety defects; minor/stylistic observations are low at most and never a reason to REVISE.
    Measured on the calibration corpus at temperature:0: qwen2.5-coder:32b false-positive rate
    0.429 → 0.143 (now passes calibration ok) and qwen2.5:14b-instruct 0.429 → 0.286,
    with recall unchanged at 0.857 (precision up, no loss of critical-bug detection). This makes
    a fast, GPU-resident local model a viable blocking reviewer. NOTE: the calibration corpus is
    small (14 cases) — treat the magnitude as indicative pending held-out validation on real diffs.

pxx 2.4.3

Choose a tag to compare

@github-actions github-actions released this 17 Aug 02:17
9eabc7a

Fixed

  • Reviewer/judge now decodes greedily (temperature: 0) — the review gate is reproducible.
    The model-backed reviewer's request omitted temperature, so against an Ollama endpoint the
    server default (0.8) made the judge nondeterministic: the same diff produced different
    verdicts run-to-run, and pxx calibrate swung across its MIN_AGREEMENT / MIN_RECALL
    thresholds — so a calibrated reviewer couldn't be trusted to stay calibrated, and a single
    calibration near a threshold was a coin-flip. pxx/review.py now sends temperature: 0, pinning
    the judge to greedy decoding. Surfaced by a reachable → unparseable → calibrate → replace
    reviewer diagnostic that exposed the swing. Test asserts the reviewer payload carries
    temperature == 0.

pxx 2.4.2

Choose a tag to compare

@github-actions github-actions released this 14 Aug 11:56
fa767bd

Added

  • Content-truthfulness gate (advisory) — a new axis, separate from permission. Scope /
    R-014 governs what the agent may touch; it does not catch a model that stays fully
    in-scope and still reports something false about the code (quoting a comment that isn't
    there, presenting invented code as real). The objective gates (lint/tests/diff-cap) catch
    broken edits, not confident-but-wrong claims. This ships the first increment: deterministic
    quote-grounding
    (pxx/truthfulness.py). Every non-trivial code span the model quotes in its
    final narration must appear in content it actually read or wrote — the union of read
    tool-results and edit-tool args accumulated across the run. Grounding is checked
    per-source (a quote must sit inside a single source, so it can't be assembled from two
    unrelated reads) and only edit-tool args count as "written" (a non-edit tool arg is
    model-supplied, not read content, so it can't launder a fabricated quote). Fenced blocks are
    checked line-by-line (a model that quotes a function but elides its docstring is being
    terse, not fabricating; a single invented line is what flags), tolerating spaced info strings
    and CRLF; inline spans are checked only when they look like code (whitespace-normalized, no
    model, fully deterministic).
  • Wired into the native loop's COMPLETED path as an advisory, non-blocking, fail-safe check:
    an ungrounded quote emits a metadata-only content_truthfulness event (count + a kind
    breakdown, never the quoted code — the audit stream carries no file contents) plus a
    warning log, but never changes a run's outcome — the try/except swallows any checker
    error so an advisory can't break a run. Advisory-first is deliberate: the false-positive rate
    is measured on real runs (like the reviewer's calibration) before the gate is ever
    promotable to a heal trigger. Prove-before-you-call-it.
  • Negative control (shipped in the tests): a fabricated quote MUST flag and a real quote
    MUST pass — a check that cannot go red is not a check. content_truthfulness registered in
    the EVENT_KINDS allowlist.

pxx 2.4.1

Choose a tag to compare

@github-actions github-actions released this 12 Aug 00:01
28155ab

Added

  • --review-model / --review-base-url run flags — the per-role reviewer/judge
    overlay ([roles.review] / PXX_REVIEW_*, shipped 2.2.0) is now settable per-run on
    the command line, no config file needed. Available on every command that runs the
    reviewer: the run/loop commands (alongside --model/--base-url) and the reviewer
    commands pxx review / pxx calibrate
    . The flags layer as the highest-precedence
    [roles.review] source (user TOML → env → flags, per field), so pxx loop --review --model <coder> --base-url <coder-url> --review-model <judge> --review-base-url <judge-url> runs the coder and the judge on different endpoints in one invocation.
    Absent the flags a run is byte-identical to before. Tests: CLI→overlay mapping (run +
    review + calibrate), flag-over-env precedence (model and base_url), and no-flags no-op.

The Kimi K3 Swarm audit — an independent architecture + quality audit
(2.8T-parameter frontier model, high-effort) of the repo at v2.3.7 — landed as
three waves: validated bug/security fixes, then the loop-closing feature, then
the learning-loop completion. Every item rode the normal gate (verified in a real
venv → PR → CI + CodeRabbit). Notably, the Wave 1 memory-capture fix was authored
by pxx fixing its own bug on local hardware (receipt R-034).

Added

  • memory_retrieval_limit setting + stable settings overlay (Wave 2 — closes
    the improvement loop): the improve/ plane (candidates, promotion guards,
    shadow/canary, autopromote) never changed a production run. memory_retrieval_limit
    is now a real Settings field (default 8 == the historical _SEARCH_HITS, so
    an unconfigured box is byte-identical; strict positive-int TOML parse) consumed
    by memory injection. apply_stable_overlay() applies the STABLE channel's
    settings-class candidate at session start — re-validated (content-hash tamper
    check), budgets tighten-only against the current budgets, CLI-pinned keys
    always win, fail-closed but never bricking (a broken/tampered/absent artifact →
    base settings + a warning). This unblocks live (model-scored) eval arms.
  • Opt-in success-exemplar capture memory_capture_successes (Wave 3, default
    off, byte-identical when off): a COMPLETED run writes exactly one compact
    session_outcome exemplar of bounded shape metadata only (files-changed /
    tool-call counts — the raw task prompt is not persisted, since this durable row
    later becomes prompt context), contamination_risk below auto-quarantine,
    provenance from the completed-run ladder, deduped so identical verified shapes
    grow seen_count — the recurrence signal the graduation ladder consumes.
    Enabling it turns on persistent memory writes, so the key is honoured only from
    a trusted source (user config / PXX_MEMORY_CAPTURE_SUCCESSES / CLI — never a
    repo-local pxx.toml, A0b). Preserves the Phase 20.5 "no silent
    success-to-knowledge" default. Also: MemoryStore dedup now upgrades an
    observation's provenance label (not only its numeric confidence) when a
    stronger-evidence recurrence arrives.

Fixed

  • Memory capture read the wrong event key (Wave 1, R-034): the tool_result
    branch read result/output, but the tool bus emits result_preview — so
    every real tool-result observation was silently dropped. Now reads
    result_preview first (legacy keys kept as fallbacks); failed tool calls
    (error=True) are captured at low confidence so they stay distinguishable.
  • Unbounded git worktree add (Wave 1): improve/channels.py and
    improve/scheduler.py ran worktree add with no timeout= — the two sites the
    2.3.6/R-030 git-bounding missed. Both now timeout=30 and degrade to the copy
    fallback on TimeoutExpired (R-030's boundary amended to name the gap).

Security

  • Fail-closed secrets gate on auto-commit (Wave 1): commit_session_work now
    scans the staged delta (governance.scan_staged, already fail-closed) before an
    auto-commit; any finding or an unrunnable scan → no commit, work left staged.
  • The PR-time governance scan is now armed (Wave 1): same-repo PRs/pushes run
    pxx check --all-files --require-denylist (fork PRs stay unarmed with a loud
    warning), closing the 1.3.x silent-green hole where an empty denylist passed
    silently. Arming immediately surfaced — and this release fixes — fleet host
    names leaked into the public receipts corpus; docs/RECEIPTS.md now describes
    hardware by capability, not by hostname/IP.

pxx 2.4.0

Choose a tag to compare

@github-actions github-actions released this 06 Aug 23:06
108a498

The Kimi K3 Swarm audit — an independent architecture + quality audit
(2.8T-parameter frontier model, high-effort) of the repo at v2.3.7 — landed as
three waves: validated bug/security fixes, then the loop-closing feature, then
the learning-loop completion. Every item rode the normal gate (verified in a real
venv → PR → CI + CodeRabbit). Notably, the Wave 1 memory-capture fix was authored
by pxx fixing its own bug on local hardware (receipt R-034).

Added

  • memory_retrieval_limit setting + stable settings overlay (Wave 2 — closes
    the improvement loop): the improve/ plane (candidates, promotion guards,
    shadow/canary, autopromote) never changed a production run. memory_retrieval_limit
    is now a real Settings field (default 8 == the historical _SEARCH_HITS, so
    an unconfigured box is byte-identical; strict positive-int TOML parse) consumed
    by memory injection. apply_stable_overlay() applies the STABLE channel's
    settings-class candidate at session start — re-validated (content-hash tamper
    check), budgets tighten-only against the current budgets, CLI-pinned keys
    always win, fail-closed but never bricking (a broken/tampered/absent artifact →
    base settings + a warning). This unblocks live (model-scored) eval arms.
  • Opt-in success-exemplar capture memory_capture_successes (Wave 3, default
    off, byte-identical when off): a COMPLETED run writes exactly one compact
    session_outcome exemplar of bounded shape metadata only (files-changed /
    tool-call counts — the raw task prompt is not persisted, since this durable row
    later becomes prompt context), contamination_risk below auto-quarantine,
    provenance from the completed-run ladder, deduped so identical verified shapes
    grow seen_count — the recurrence signal the graduation ladder consumes.
    Enabling it turns on persistent memory writes, so the key is honoured only from
    a trusted source (user config / PXX_MEMORY_CAPTURE_SUCCESSES / CLI — never a
    repo-local pxx.toml, A0b). Preserves the Phase 20.5 "no silent
    success-to-knowledge" default. Also: MemoryStore dedup now upgrades an
    observation's provenance label (not only its numeric confidence) when a
    stronger-evidence recurrence arrives.

Fixed

  • Memory capture read the wrong event key (Wave 1, R-034): the tool_result
    branch read result/output, but the tool bus emits result_preview — so
    every real tool-result observation was silently dropped. Now reads
    result_preview first (legacy keys kept as fallbacks); failed tool calls
    (error=True) are captured at low confidence so they stay distinguishable.
  • Unbounded git worktree add (Wave 1): improve/channels.py and
    improve/scheduler.py ran worktree add with no timeout= — the two sites the
    2.3.6/R-030 git-bounding missed. Both now timeout=30 and degrade to the copy
    fallback on TimeoutExpired (R-030's boundary amended to name the gap).

Security

  • Fail-closed secrets gate on auto-commit (Wave 1): commit_session_work now
    scans the staged delta (governance.scan_staged, already fail-closed) before an
    auto-commit; any finding or an unrunnable scan → no commit, work left staged.
  • The PR-time governance scan is now armed (Wave 1): same-repo PRs/pushes run
    pxx check --all-files --require-denylist (fork PRs stay unarmed with a loud
    warning), closing the 1.3.x silent-green hole where an empty denylist passed
    silently. Arming immediately surfaced — and this release fixes — fleet host
    names leaked into the public receipts corpus; docs/RECEIPTS.md now describes
    hardware by capability, not by hostname/IP.