# Changelog

All notable changes to Pixir are recorded here. Issue and PR references
(`#N`) point to the private development repository; this public mirror
carries curated history, so those references may not resolve here. Pixir is a developer preview;
the CLI/ACP runtime is the public surface, and there is no stable Elixir library
API yet. Versions follow [Semantic Versioning](https://semver.org/) with the
caveat that pre-1.0 minor versions may still change behavior.

## [Unreleased]

## [0.1.7]

### Added
- Delegate subagent children now carry durable `children[].index` task-position
  evidence across attached envelopes, async snapshots, tree projection, and retry
  lineage (#227). The delegate envelope `schema_version` is now `2` to signal the
  additive `children[].index` / `children_order` keys; the
  `pixir.delegate.envelope.v1` family name is unchanged (reserved for breaking
  shape changes).
- Delegate specs are validated fail-closed (#223): unknown top-level or
  `subagents` keys are rejected as structured `invalid_spec` with `field`,
  `json_pointer`, `path`, and `next_actions`, in dry-run and real runs alike,
  so a typo can no longer pass the rehearsal silently.
- New delegate spec provider knobs mirroring ACP `session/prompt` `_meta`
  (#223): `subagents.model` and `subagents.reasoning_effort`
  (`low|medium|high|xhigh`) thread to every child's provider calls with
  spec > config > default resolution; effective values are evidenced by child
  `provider_usage` events, not echoed in the envelope. The model-facing
  `spawn_agent` tool strips caller-authored `model`/`reasoning_effort` args:
  provider knobs are operator decisions, not a capability a spawning model
  grants its children.

### Fixed
- Delegate `--dry-run` now mirrors the runner's task normalization exactly:
  malformed or blank `tasks[]` entries are rejected as `invalid_spec` instead of
  silently planned, and a list-valued `tasks` field owns validation (even when
  empty) before any legacy `task` fallback, matching real-run branch precedence.
- The model-facing `spawn_agent` tool strips caller-authored `index` args so
  task-position evidence in durable `subagent_event` data cannot be forged.
- Workspace confinement no longer misreads leading POSIX environment
  assignments as path arguments (#188): `TMPDIR=/tmp mix test` and
  `PREFIX=/usr/local ./configure` pass, while literal outside paths,
  redirection targets, and non-leading `NAME=VALUE` arguments keep failing
  closed; the window resets after `;`, `&&`, `||`, and `|`. The residual
  runtime-expansion vector (`VAR=/outside cmd $VAR`) is documented in
  SECURITY.md: confinement is a defense-in-depth tripwire, not a sandbox.

## [0.1.6]

### Added
- Published the proc-pressure kernel-pressure evidence bundle (23 files,
  gate-hardened) at `docs/benchmarks/scale/`, and the matching /scale
  kernel-tax section: marginal threads/processes/RSS/kernel-CPU/involuntary
  context switches per additional worker under two labeled machine
  conditions, per-provider-call normalization from durable usage evidence,
  the spawn-tax microbench, and the completion audits with the negative
  result (199/205 loaded) published as the headline. The /scale hero line
  and the N=8 transport-table cause cell were corrected to claims the
  published bundles can back.

### Fixed
- `pixir delegate --help` (and the main help) now document `--timeout-ms` on
  the attached form; the flag was always accepted there but only listed under
  `delegate start`, so contract-of-record readers concluded it was invalid
  (#204).

### Added
- Subagents-strategy delegate result envelopes now give every non-completed
  child the same ready-made recovery commands the one-shot contract ships:
  conditional `children[].resume_command` and `children[].diagnose_command`,
  including children reported `running` at the collection horizon (their
  writer lease fails closed if anything is genuinely alive). Start/lifecycle
  snapshots stay terminal-only, and workflow-strategy children keep their
  step-based evidence without these commands. Without `--json`, per-child
  resume hints print on stderr, matching the one-shot mode contract (#204).

### Changed
- A `bash` call denied because the bounded write policy disables the shell now
  surfaces as `kind: "bash_disabled"` ("shell is disabled by the bounded write
  policy") instead of the misleading `write_policy_denied` ("write denied"),
  with shell-free `next_actions` (`use_native_read_tools`,
  `use_edit_or_write_within_allowed_globs`). The denial keeps exit code 3 but
  is no longer terminal for the child's Turn: the model can adapt with native
  tools instead of dying on a read-only command. Write-allowlist denials keep
  `write_policy_denied` and remain terminal (#218).

### Added
- Delegate spec transport knob: `subagents.transport` (or top-level
  `transport`) accepts `auto` | `websocket` | `http_sse`; invalid values fail
  `--dry-run` with a structured error and the effective value is surfaced as
  `limits.transport` (#205).
- Manager-level bounded auto-retry for read-only subagent children killed by
  mid-stream websocket drops or provider-declared-retryable server errors,
  with jittered re-queueing, an observable `retrying` lifecycle event, and a
  retry confession on delegate envelopes (`children[].retry_attempts`,
  `retry_max_attempts`, `current_attempt_index`, `retry_history`; present only
  when a retry happened) (#205).
- `usage_summary.model` is now populated on provider usage events, and
  subagent session ids are aliased in `pixir tree` projections (#216).
- Isolated subagent workspace snapshots accept extra exclusion directory names
  (directory basenames, byte-exact, matched at any depth) via
  `config :pixir, :subagents, snapshot_excluded_dir_names: [...]` or the
  `:excluded_dir_names` snapshot option; built-in defaults (`.git`, `.pixir`,
  `_build`, ...) always stay in effect, invalid names and a non-keyword
  `:subagents` application env fail closed with structured errors, and the
  effective list is confessed as `excluded_dir_names` in snapshot metadata and
  runtime failure envelopes (never on validation failures, where no effective
  policy ran) (#221).

## [0.1.5]

### Fixed
- Clean CLI exits now release Session writer leases across one-shot, `resume`,
  and attached delegate (parent and children); stale leases from crashed runs
  remain fail-closed behind `--force-release-writer-lease`. Headless
  orchestrators no longer need the force flag on the happy path.
- `Subagents.Manager` survives late timeouts or cancels racing an
  already-terminated child Session; the recorded timeout/cancel evidence is the
  honest record either way.

### Added
- `pixir-delegate` skill family for orchestrating agents
  (`.agents/skills/pixir-delegate*`): a host-neutral delegation judgment core,
  real blind-run demonstrations, deterministic `fanout.sh`/`steer.sh` scripts,
  and variants for Claude Code, Codex root agents, and Pixir-native
  orchestration. Discoverable by Claude Code via `.claude/skills/`.
- Site route `/scale` with measured scale evidence (up to 64 concurrent
  workers) and bounded public claims.
- Delegate CLI contract documentation for expensive orchestrators
  (`docs/examples/delegate-cli-live/README.md`): a per-subcommand exit-code table,
  the read/scope vs write-policy denial distinction (`outside_workspace` vs
  `write_policy_denied`), and honest caveats for `next_actions` and
  `observed_applied_writes`.
- `SECURITY.md` with private vulnerability reporting and a clear
  tripwire-not-a-sandbox disclaimer, and `CONTRIBUTING.md` describing the real
  workflow and invariants.
- Partial-write observability: bounded-write delegate envelopes now report
  `observed_applied_writes` from child Session Logs as an at-least lower bound,
  without changing existing `writes_applied_to` / `contract_status` fields.

### Changed
- Elixir requirement moved to `~> 1.20`; CI runs on Elixir 1.20.2 / OTP 29.
- Delegate error locations now carry machine-readable metadata (`json_pointer`,
  `path`, `step_index`) alongside the human-facing 1-based field label.

### Fixed
- `mix check` no longer hangs after the test phase. The test step nested a BEAM
  node under `cmd env MIX_ENV=test mix ...` that did not exit cleanly on teardown;
  it now shells out with `MIX_ENV` as an environment variable and returns cleanly.
- Bash tool workspace confinement now rejects path escapes beyond `..` — absolute
  out-of-workspace paths, `$HOME`/`~`, and symlink prefixes resolving outside the
  workspace — before crossing the host boundary, surfaced honestly as
  `outside_workspace` rather than a write-policy denial.

## [0.1.4] and earlier

See the release notes at
`docs/release-notes/open-beta-developer-preview.md` for the 0.1.0–0.1.4 developer
preview history (runtime truth and fanout honesty, ACP Registry readiness, and
runtime diagnostics).
