For AI agents: the complete documentation index is available at https://docs.phax.run/llms.txt, the full documentation bundle is available at https://docs.phax.run/llms-full.txt, and this page is available as Markdown at https://docs.phax.run/releases/0-32-0.md.

phax 0.32.0

Changes since 0.31.0: v0.31.0...v0.32.0.

Highlights

  • Structured output — The provider may shape the answer; only phax's decoder accepts it.

Upgrading

  • Records and schema readers: hand-decision-answer is two formats. spec-hand-decision-answer and plan-hand-decision-answer are each the old variant with a $schema const. hand-decision-answer stays readable at 0.25.0, and phax no longer reads or asks for it.
  • Schema readers: plan-document no longer pairs sourceSpec and completesSpec in its schema. phax checks the pair.
  • Schema readers: every answer's $schema is a const of its 0.32.0 stamp. That covers spec and plan sidecars, the two hand-decision formats, first-reading, interactive-handoff, code-review and phax-plan-extraction. An older @lbdremy/phax-schemas cannot read them, and the package reads a const format only at its own stamps.
  • Schema readers: phax-plan is restamped 0.32.0, its decoding unchanged. An older @lbdremy/phax-schemas cannot read a 0.32.0 run plan.
  • Schema readers: the code-review answer and file are one shape, $schema in place of version.
  • Schema readers: new phax-plan-extraction format, the answer of the plan extraction.
  • Headless authoring answers carry $schema in place of version: 1.
  • Records and schema readers: compliance-review.json is stamped 0.32.0. $schema is a const, and two ledgers are required: unplannedChanges (phaseId, path, note) and unmetPromises (phaseId, promise, note), each possibly empty. A 0.32.0 file without either is refused.
  • Records and schema readers: older compliance reviews read without ledgers. A 0.17.0 or pre-schema review still reads, never with empty ledgers; @lbdremy/phax-schemas gives them Unknown ledgers.
  • Records readers: compliance-review.md is rendered by phax from the answer, with fixed sections (summary, one per phase, unplanned changes, unmet promises, attention points, pointers).
  • phax review-compliance no longer prints Verdict: unknown. A review refused twice fails with exit 1 and writes no file and no records entry; the corrective resume's transcript is compliance-review-retry.session.jsonl.
  • The compliance session is read-only and writes nothing under .phax-context/.
  • Run phax artifact migrate-documents once. It restamps every live spec and plan sidecar below its current shape, their bodies unchanged. Until then approve, reopen and decide refuse, naming the command.

See Structured answers and providers for what each provider now checks.

What's new

Structured output

The provider may shape the answer; only phax's decoder accepts it.

  • A compliance review whose answer is wrong gets one more chance in the same session, and when it still fails phax says why instead of showing an unknown verdict. phax review-compliance

    Now:

    $ phax review-compliance audio-export
    ⚠ compliance-review answer refused — perPhase: phase "phase-04" is not a phase of this run
      resuming the session once to ask for the whole answer again
    Verdict: conformant-with-deviations
    Compliance review: ~/.phax/runs/notebook.audio-export/compliance-review.md
    Recorded: notebook.audio-export/compliance-review (3fa91c0d)
    
    $ phax review-compliance audio-export
    ✗ Compliance review failed: compliance-review answer rejected twice — first answer: perPhase: phase "phase-02" is missing; retry: perPhase: phase "phase-02" is missing. To retry, run: phax review-compliance audio-export
    $? = 1
    Before
    $ phax review-compliance audio-export
    Verdict: unknown
    Compliance review: ~/.phax/runs/notebook.audio-export/compliance-review.md
  • The compliance review now lists the files changed beyond the plan and the promised tests that are missing, alongside its verdict. compliance-review.json

    Now:

    {
      "$schema": "https://docs.phax.run/schemas/compliance-review/0.32.0.json",
      "verdict": "conformant-with-deviations",
      "summary": "All four phases delivered; phase-02 skipped one promised test.",
      "perPhase": [ … ],
      "unplannedChanges": [
        { "phaseId": "phase-02", "path": "src/export/backoff.ts", "note": "Shared helper, justified in the handoff." }
      ],
      "unmetPromises": [
        { "phaseId": "phase-02", "promise": "integration test: export retries on 503", "note": "Not found in tests/integration." }
      ],
      "attentionPoints": [ "Confirm the retry backoff with the audio team." ],
      "pointers": []
    }
    Before
    {
      "$schema": "https://docs.phax.run/schemas/compliance-review/0.17.0.json",
      "verdict": "conformant-with-deviations",
      "summary": "All four phases delivered; phase-02 skipped one promised test.",
      "perPhase": [ … ],
      "attentionPoints": [ "Confirm the retry backoff with the audio team." ],
      "pointers": []
    }
  • The compliance review's Markdown is written by phax from the review itself, so it always matches the verdict and keeps the same sections from run to run. compliance-review.md

    Now:

    # Compliance review — notebook.audio-export
    
    Verdict: conformant-with-deviations
    
    All four phases delivered; phase-02 skipped one promised test.
    
    ## phase-02 — conformant-with-deviations
    
    - tests · deviation — The promised integration test for export retries is missing.
    
    ## Unplanned changes
    
    - phase-02 · src/export/backoff.ts — Shared helper, justified in the handoff.
    
    ## Unmet promises
    
    - phase-02 · integration test: export retries on 503 — Not found in tests/integration.
    
    ## Attention points
    
    - Confirm the retry backoff with the audio team.
    
    ## Pointers
    
    None.
    Before
    (free prose written by the review agent, in its own layout)
  • A headless code review whose answer is refused is asked once more in the same session instead of failing straight away. phax review-code --headless

    Now:

    $ phax review-code greet-cli --headless
    ⚠ code-review answer refused — findings[0].lens: "security" is not a lens (expected one of surface, acceptance, boundary, core, edge, tests, architecture, docs)
      resuming the session once to ask for the whole answer again
    Code review: 2 findings (1 bug, 1 concern)
    Findings: ~/.phax/runs/notebook.greet-cli/code-review.json
    Fix them in the session: phax review-code greet-cli
    Before
    $ phax review-code greet-cli --headless
    Code review failed: answer refused: findings[0].lens: "security" is not a lens (expected one of surface, acceptance, boundary, core, edge, tests, architecture, docs). To retry, run: phax review-code greet-cli --headless
    $? = 1
  • Headless authoring, decide and review sessions on Claude Code and Codex no longer stop on a wrongly shaped answer: the provider fixes the shape while it writes. phax artifact new spec --headless (on Claude Code or Codex)

    Now:

    $ phax artifact new spec audio-export --headless --brief brief.md
    Wrote docs/specs/2610271600-audio-export.md
    Before
    $ phax artifact new spec audio-export --headless --brief brief.md
    ⚠ spec document refused — requirements[2].pattern: "conditional" is not one of ubiquitous, event, state, unwanted, optional
      resuming the session once to ask for the whole document again
    Wrote docs/specs/2610271600-audio-export.md
  • The published plan schema now follows the strict rules Claude Code and Codex enforce: sourceSpec and completesSpec stay required and nullable, and phax checks that they go together instead of the schema. phax artifact schema plan

    Now:

    $ phax artifact schema plan
    {
      "$defs": { "NonEmptyString": { "type": "string", "pattern": "^[\\s\\S]+$" } },
      "required": [ "$schema", "kind", "sourceSpec", "completesSpec", "run", "preamble", "phases" ],
      "properties": {
        "$schema": { "const": "https://docs.phax.run/schemas/plan-document/0.32.0.json" },
        "sourceSpec": { "anyOf": [ { "$ref": "#/$defs/NonEmptyString" }, { "type": "null" } ] },
        "completesSpec": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ] },
        …
      }
    }
    Before
    $ phax artifact schema plan
    {
      "$defs": { "NonEmptyString": { "type": "string", "minLength": 1 } },
      "required": [ "$schema", "kind", "sourceSpec", "completesSpec", "run", "preamble", "phases" ],
      "properties": {
        "$schema": { "type": "string", "pattern": "^https:\\/\\/docs\\.phax\\.run\\/schemas\\/plan-document\\/…\\.json$" },
        "sourceSpec": { "anyOf": [ { "$ref": "#/$defs/NonEmptyString" }, { "type": "null" } ] },
        "completesSpec": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ] },
        …
      },
      "allOf": [ { "oneOf": [
        { "properties": { "sourceSpec": { "type": "string", "minLength": 1 }, "completesSpec": { "type": "boolean" } } },
        { "properties": { "sourceSpec": { "type": "null" }, "completesSpec": { "type": "null" } } }
      ] } ]
    }