Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ them (`v0.1.0` … `v1.19.0`); the 1.x ranges below are derived from that
history, not written from memory. Rust alpha and beta tags identify previews;
the stable 2.0 release has not been cut.

## 2.0.0-beta.76 — 2026-11-12

**Protected Codex 0.165.0**

- Update **`codex-current`** to protected Codex **0.165.0**, pinned to `360319d8dee62d87e2d59fc0c21805d79519cfed`. Fixes the blocked automatic update (#284).
- Port **`run_pre_compact_hooks`** to 0.165's environment hooks. Environment requirements hooks can stop compaction but cannot satisfy the trusted session-flags approval.
- Retain the exact 0.164.0 contract for saved Docker sessions and installer rollback. Build inputs stay Rust 1.99.1 and V8 152.2.0.

## 2.0.0-beta.75 — 2026-11-12

**LORE 0.62.26**
Expand Down
42 changes: 21 additions & 21 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion rust/doxa-claude/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "doxa-claude"
version = "2.0.0-beta.75"
version = "2.0.0-beta.76"
edition = "2021"
publish = false
license = "AGPL-3.0-only"
Expand Down
2 changes: 1 addition & 1 deletion rust/doxa-codegraph/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "doxa-codegraph"
version = "2.0.0-beta.75"
version = "2.0.0-beta.76"
edition = "2021"
publish = false
license = "AGPL-3.0-only"
Expand Down
2 changes: 1 addition & 1 deletion rust/doxa-daemon/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "doxa-daemon"
version = "2.0.0-beta.75"
version = "2.0.0-beta.76"
edition = "2021"
publish = false
license = "AGPL-3.0-only"
Expand Down
2 changes: 1 addition & 1 deletion rust/doxa-engines/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "doxa-engines"
version = "2.0.0-beta.75"
version = "2.0.0-beta.76"
edition = "2021"
publish = false
license = "AGPL-3.0-only"
Expand Down
6 changes: 3 additions & 3 deletions rust/doxa-engines/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Assistant text and reasoning are bounded and scrubbed as complete messages. The

## Compaction protection

Protected sessions require DOXA's private **Codex 0.164.0** app server with contract `doxa-precompact-fail-closed-v1`. Before thread startup, DOXA checks the build identity, trusted synchronous `PreCompact` hook hash, and disabled token-budget and asynchronous compaction flags. The protected payload also refuses speculative background compaction internally, regardless of client feature overrides. Stock or unsupported app servers fail before creating or resuming a protected thread.
Protected sessions require DOXA's private **Codex 0.165.0** app server with contract `doxa-precompact-fail-closed-v1`. Before thread startup, DOXA checks the build identity, trusted synchronous `PreCompact` hook hash, and disabled token-budget and asynchronous compaction flags. The protected payload also refuses speculative background compaction internally, regardless of client feature overrides. Stock or unsupported app servers fail before creating or resuming a protected thread.

The hook binds the actual provider thread and owned rollout, prepares a scrubbed snapshot, and waits for the native LORE reviewer. Manual `/compact` independently reviews the same bound source and rechecks its identity and digest before submission. Missing, failed, timed-out, changed, asynchronous, or duplicate review blocks replacement; a worker exit code without an exact receipt is insufficient. DOXA also waits for matching hook and compaction events after submission. It does not overwrite global Codex settings or trust unrelated user hooks.

Expand All @@ -34,7 +34,7 @@ On resume, current occupancy comes from the owned thread's latest bounded token

DOXA disables Codex's internal multi-agent spawning and verifies that policy before starting a protected thread. Fleet/session creation and peer messages go through DOXA so visible identities, review and account limits remain authoritative. Existing injected peer tools remain available.

The private provider makes the decision inside `run_pre_compact_hooks`, before compaction inference or history replacement. Exactly one required synchronous command must return explicit JSON approval. The provider identifies itself as `doxa_codex_rs/0.164.0` and does not impersonate stock Codex. [Earlier 0.156.1 authenticated default-window verification](../../docs/live-default-window-compaction-2026-09-30.md).
The private provider makes the decision inside `run_pre_compact_hooks`, before compaction inference or history replacement. Exactly one required synchronous command must return explicit JSON approval. The provider identifies itself as `doxa_codex_rs/0.165.0` and does not impersonate stock Codex. [Earlier 0.156.1 authenticated default-window verification](../../docs/live-default-window-compaction-2026-09-30.md).

## Install the protected provider

Expand All @@ -48,7 +48,7 @@ python3 scripts/install_codex_protected.py \
--launcher "$PWD/target/debug/doxa-codex-protected"
```

The installer pins source commit `6aaac694803004a63c6f393d153c96d22521a6b9` and a reviewed patch checksum. Each upstream/patch identity gets a separate retained source checkout. Cross-version publication checks the old receipt and helper bytes before selecting a new immutable artifact; rollback retains that prior provider. The patch normalizes local workspace package versions in the upstream lockfile; external sources and checksums stay fixed. A bounded initialize probe checks the compiled contract. Receipts bind the source, patch, dispatcher, server, and helper bytes. The code-mode helper's V8 inputs come from checksum-verified official artifacts. Changed fingerprints, corrupt installs, or partial receipts are refused; a fresh reviewed rebuild publishes a new immutable directory and atomically selects it for new launches. Existing processes keep their original files. An explicit `--codex-bin` takes precedence.
The installer pins source commit `360319d8dee62d87e2d59fc0c21805d79519cfed` and a reviewed patch checksum. Each upstream/patch identity gets a separate retained source checkout. Cross-version publication checks the old receipt and helper bytes before selecting a new immutable artifact; rollback retains that prior provider. The patch normalizes local workspace package versions in the upstream lockfile; external sources and checksums stay fixed. A bounded initialize probe checks the compiled contract. Receipts bind the source, patch, dispatcher, server, and helper bytes. The code-mode helper's V8 inputs come from checksum-verified official artifacts. Changed fingerprints, corrupt installs, or partial receipts are refused; a fresh reviewed rebuild publishes a new immutable directory and atomically selects it for new launches. Existing processes keep their original files. An explicit `--codex-bin` takes precedence.

Set `DOXA_CODEX_PROTECTED_CACHE` to choose the standard build cache, or pass `--cache` to the standalone builder. `DOXA_INSTALL_CODEX_PROTECTED=0` skips this optional provider. The official Codex CLI remains available for login and help; DOXA does not replace it.

Expand Down
4 changes: 2 additions & 2 deletions rust/doxa-engines/src/bin/doxa-codex-protected.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ use std::{
process::Command,
};

const SOURCE: &str = "6aaac694803004a63c6f393d153c96d22521a6b9";
const SOURCE: &str = "360319d8dee62d87e2d59fc0c21805d79519cfed";
const CONTRACT: &str = "doxa-precompact-fail-closed-v1";
const PATCH: &str = "f8759872787029e5bf7064fe5be7166c5367b1db09b4b60362ea625117658924";
const PATCH: &str = "128293eb2e10aebdff916ab1d8fbce30fa10eba2dfac01cc501f9c1591034484";
const MAX_BINARY: u64 = 1024 * 1024 * 1024;

#[derive(Deserialize)]
Expand Down
7 changes: 4 additions & 3 deletions rust/doxa-engines/src/codex_appserver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
//! Interactive requests require a host bridge; unknown requests are refused.
//!
//! The shapes below come from `codex app-server generate-ts --experimental`
//! (Codex 0.164.0). Stdio is newline-delimited JSON-RPC without LSP headers.
//! (Codex 0.164.0; the request shapes used here are unchanged in 0.165.0).
//! Stdio is newline-delimited JSON-RPC without LSP headers.
use std::io;
use std::os::unix::{process::CommandExt, net::UnixStream, io::AsRawFd};
use std::collections::VecDeque;
Expand Down Expand Up @@ -1264,9 +1265,9 @@ for line in sys.stdin:

#[test]
fn provider_version_uses_only_the_authoritative_product_prefix() {
let desktop = "Codex Desktop/0.164.0 (Ubuntu 26.4.0; x86_64) dumb (doxa; 2.0.0-alpha.37)";
let desktop = "Codex Desktop/0.165.0 (Ubuntu 26.4.0; x86_64) dumb (doxa; 2.0.0-alpha.37)";
assert_eq!(provider_version(desktop), Some(crate::codex_compact::SUPPORTED_VERSION));
assert_eq!(provider_version("codex_cli_rs/0.164.0"), Some(crate::codex_compact::SUPPORTED_VERSION));
assert_eq!(provider_version("codex_cli_rs/0.165.0"), Some(crate::codex_compact::SUPPORTED_VERSION));
let current = crate::codex_compact::SUPPORTED_VERSION;
for agent in [
format!("Codex Desktop/0.1.0 (doxa; {current})"),
Expand Down
8 changes: 4 additions & 4 deletions rust/doxa-engines/src/codex_compact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ use std::io::Write;
#[cfg(test)]
use std::os::unix::fs::PermissionsExt;

pub const SUPPORTED_VERSION: &str = "0.164.0";
pub const PROTECTED_AGENT_PREFIX: &str = "doxa_codex_rs/0.164.0 (doxa-precompact-fail-closed-v1; ";
pub const SUPPORTED_SOURCE: &str = "6aaac694803004a63c6f393d153c96d22521a6b9";
pub const SUPPORTED_PATCH: &str = "f8759872787029e5bf7064fe5be7166c5367b1db09b4b60362ea625117658924";
pub const SUPPORTED_VERSION: &str = "0.165.0";
pub const PROTECTED_AGENT_PREFIX: &str = "doxa_codex_rs/0.165.0 (doxa-precompact-fail-closed-v1; ";
pub const SUPPORTED_SOURCE: &str = "360319d8dee62d87e2d59fc0c21805d79519cfed";
pub const SUPPORTED_PATCH: &str = "128293eb2e10aebdff916ab1d8fbce30fa10eba2dfac01cc501f9c1591034484";

#[derive(serde::Deserialize)]
#[serde(deny_unknown_fields)]
Expand Down
2 changes: 1 addition & 1 deletion rust/doxa-engines/src/codex_interaction.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! Official Codex 0.164.0 server requests mapped to DOXA's input protocol.
//! Official Codex 0.165.0 server requests mapped to DOXA's input protocol.
//! Replies are single use and apply only to the currently displayed request.
use std::sync::{atomic::{AtomicU64, Ordering}, Mutex};
use serde_json::{json, Map, Value};
Expand Down
6 changes: 3 additions & 3 deletions rust/doxa-engines/tests/codex_launcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use serde_json::json;
use sha2::{Digest, Sha256};
use std::{fs, os::unix::fs::PermissionsExt, process::Command};
const PATCH: &str = "f8759872787029e5bf7064fe5be7166c5367b1db09b4b60362ea625117658924";
const PATCH: &str = "128293eb2e10aebdff916ab1d8fbce30fa10eba2dfac01cc501f9c1591034484";
fn fixture() -> tempfile::TempDir {
let dir = tempfile::tempdir().unwrap();
fs::set_permissions(dir.path(), fs::Permissions::from_mode(0o700)).unwrap();
Expand Down Expand Up @@ -38,8 +38,8 @@ fn fixture() -> tempfile::TempDir {
)
.unwrap();
fs::write(dir.path().join("receipt.json"),json!({"contract":"doxa-precompact-fail-closed-v1",
"source_commit":"6aaac694803004a63c6f393d153c96d22521a6b9","patch_sha256":PATCH,
"code_mode_host_source_commit":"6aaac694803004a63c6f393d153c96d22521a6b9",
"source_commit":"360319d8dee62d87e2d59fc0c21805d79519cfed","patch_sha256":PATCH,
"code_mode_host_source_commit":"360319d8dee62d87e2d59fc0c21805d79519cfed",
"code_mode_host_sha256":format!("{:x}",Sha256::digest(fs::read("/usr/bin/true").unwrap())),
"code_mode_host_dispatcher_sha256":format!("{:x}",Sha256::digest(fs::read(env!("CARGO_BIN_EXE_doxa-codex-protected")).unwrap())),
"binary_sha256":format!("{:x}",Sha256::digest(fs::read("/usr/bin/true").unwrap())),"official_cli":"/usr/bin/printf"}).to_string()).unwrap();
Expand Down
4 changes: 2 additions & 2 deletions rust/doxa-engines/tests/fixtures/codex_protected_fixture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def read():
def send(x): print(json.dumps(x),flush=True)
def notice(method,**params): send({'method':method,'params':dict(threadId='thread-actual',**params)})
init=read(); assert init['method']=='initialize'
agent='codex_cli_rs/0.164.0' if mode=='stock' else 'doxa_codex_rs/'+('0.1.0' if mode=='version' else '0.164.0')+' (doxa-precompact-fail-closed-v1; upstream fixture)'
agent='codex_cli_rs/0.165.0' if mode=='stock' else 'doxa_codex_rs/'+('0.1.0' if mode=='version' else '0.165.0')+' (doxa-precompact-fail-closed-v1; upstream fixture)'
send({'id':init['id'],'result':{'userAgent':agent}})
assert read()['method']=='initialized'
if mode in ('version','stock'):
Expand Down Expand Up @@ -150,7 +150,7 @@ else:
"#).unwrap();
fs::set_permissions(&executable, fs::Permissions::from_mode(0o700)).unwrap();
let gate_dir = dir.path().join("gate"); fs::create_dir(&gate_dir).unwrap(); fs::set_permissions(&gate_dir, fs::Permissions::from_mode(0o700)).unwrap();
let gate = CompactGate::prepare(&gate_dir, &std::env::current_exe().unwrap(), &dir.path().join("codex-home"), dir.path(), "doxa-fixture", "0.164.0").unwrap();
let gate = CompactGate::prepare(&gate_dir, &std::env::current_exe().unwrap(), &dir.path().join("codex-home"), dir.path(), "doxa-fixture", "0.165.0").unwrap();
let options = AppServerOptions { executable, cwd:dir.path().to_owned(), model:None, sandbox:SandboxMode::WorkspaceWrite, permission:CodexPermission::OnRequest, resume_thread:None, turn_timeout:Duration::from_secs(3) };
(dir, options, gate)
}
2 changes: 1 addition & 1 deletion rust/doxa-fleet/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "doxa-fleet"
version = "2.0.0-beta.75"
version = "2.0.0-beta.76"
edition = "2021"
publish = false
license = "AGPL-3.0-only"
Expand Down
2 changes: 1 addition & 1 deletion rust/doxa-hub/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "doxa-hub"
version = "2.0.0-beta.75"
version = "2.0.0-beta.76"
edition = "2021"
publish = false
license = "AGPL-3.0-only"
Expand Down
2 changes: 1 addition & 1 deletion rust/doxa-input/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "doxa-input"
version = "2.0.0-beta.75"
version = "2.0.0-beta.76"
edition = "2021"
publish = false
license = "AGPL-3.0-only"
Expand Down
2 changes: 1 addition & 1 deletion rust/doxa-isolation/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "doxa-isolation"
version = "2.0.0-beta.75"
version = "2.0.0-beta.76"
edition = "2021"
publish = false
license = "AGPL-3.0-only"
Expand Down
2 changes: 1 addition & 1 deletion rust/doxa-lore/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "doxa-lore"
version = "2.0.0-beta.75"
version = "2.0.0-beta.76"
edition = "2021"
publish = false
license = "AGPL-3.0-only"
Expand Down
Loading
Loading