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
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@ All notable changes to this project are documented here. The format follows [Kee

## [Unreleased]

### Added
- Added `denser minimize-context` and a versioned context-bundle manifest. The
selector greedily tests optional components, keeps behavior-changing or
uncertain components, requires a sensitive negative control, and repeats a
final audit against a caller-set full-input reduction target.
- Added bounded concurrent replay for the Codex CLI backend. Per-call metadata
remains thread-isolated and each CLI turn remains ephemeral and read-only.
- Added a two-task local-file Codex pilot. It removed an unrelated archived
handbook, retained the release and CI policies whose removal regressed, kept
all final cases at 3/3, and reduced provider-reported full input by 12.47%.

## [0.2.0-alpha.3] — 2026-08-18

### Changed
Expand Down
89 changes: 57 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,43 +20,55 @@

---

## Featured: measurable Codex input reduction for text-only tasks
## Featured: automatic context pruning in a normal Codex tool workflow

The first result that clears denser's end-to-end bar comes from capability
selection, not prose compression. For replay tasks that need no files, shell,
network, plugins, apps, skills, or memory, the Codex CLI adapter can use an
explicit `text-only` profile and omit those unused capabilities from the model
input. `standard` remains the default.
`denser minimize-context` takes a manifest of visible context components,
tries removing optional components one at a time, and keeps a removal only when
behavior remains identical and a known-bad control still fails. Errors,
improvements that change behavior, and insensitive tests all fail closed.

With Codex CLI 0.147.0, `gpt-5.6-sol`, and medium reasoning:
The first tool-using pilot used Codex CLI 0.147.0, `gpt-5.6-sol`, medium
reasoning, and the `standard` capability profile. Both tasks had to read a local
JSON file whose identifier and arbitrary policy code were absent from the
prompt, so the expected answers could not be recovered from a text-only input.

| Workload | Quality | Full input per call | Reduction |
| Workload | Complete context | Selected context |
|---|---:|---:|
| Local release-record decision | 3/3 | 3/3 |
| Local CI-record decision | 3/3 | 3/3 |

The selector removed a 17,236-byte archived handbook but rejected attempts to
remove the release or CI policy because each caused a covered regression. The
final three-trial audit completed with zero operational errors:

| Measurement | Complete context | Selected context | Reduction |
|---|---:|---:|---:|
| Release-operation decisions | 27/27 in each profile | 20,294.11 → 18,154.00 | 10.55% |
| Automation permission routing | 15/15 in each profile | 20,619.00 → 18,434.00 | 10.60% |

This clears the predeclared rule of at least two real scenarios with at least
10% provider-reported full-input reduction and no observed quality loss. The
final run made 84 authenticated calls in seeded randomized order, with three
trials per case, zero operational errors, and zero transport fallbacks. It is
not a general coding mode: tasks that need tools must use `standard`.

The first strict run caught one regression: without tools, one case asked for
more context instead of following its fixed output contract. The `text-only/v1`
wrapper now states that all required input is already present, and the complete
84-call audit was rerun rather than patching the single failure. This is the
kind of false confidence denser is designed to expose.

The earlier 10.3%-shorter instruction rewrite reduced full Codex input by only
about 0.25%. That negative result remains important: rewriting a small file is
not enough when the larger cost is unused runtime context.

See the [case study and reproduction
guide](docs/CODEX_TEXT_ONLY_CASE_STUDY.md), plus the complete per-call outputs,
token counts, source hashes, runtime settings, and limitations in the
| Provider-reported full input, 6 calls | 277,871 | 243,210 | **12.47%** |
| Visible bundle estimate | 4,626 | 303 | 93.45% |

Shell access, plugins, and skill search were not disabled. The benchmark's
standard profile did disable apps, memories, and multi-agent execution for
reproducibility, identically on both sides; the measured 12.47% delta comes
from the selected bundle, not from changing that runtime profile. This is one
synthetic two-task pilot, not proof that every repository can remove 12%.

See the [component-selection case study](docs/CODEX_CONTEXT_SELECTION_CASE_STUDY.md),
the [manifest and tool fixtures](examples/context_bundles/tool_workflows/), and
the [complete final audit](examples/context_bundles/tool_workflows/selection.codex-standard.3x.2026-08-18.json).

### Earlier result: text-only capability selection

For pre-bundled decisions that need no files or tools, the explicit
`text-only/v1` profile reduced full input by 10.55% and 10.60% across two
synthetic workloads, with 42/42 expected decisions per profile. That remains a
narrow capability-selection result, not the main product claim. A
10.3%-shorter instruction rewrite had reduced complete Codex input by only
about 0.25%, which is why denser now targets whole visible context bundles.

See the earlier [text-only case study](docs/CODEX_TEXT_ONLY_CASE_STUDY.md) and
[`paired three-trial audit`](examples/project_instructions/codex-text-only-profile-audit.paired-3x-final.2026-08-17.json).

### Public-project transfer check: Astral uv
### Earlier public-project transfer check: Astral uv

The same frozen profile was then tested against decision rules adapted from
public Astral uv agent prompts at commit
Expand Down Expand Up @@ -102,6 +114,11 @@ end-to-end input usage separately from asset-only length.
## What denser does

```bash
denser minimize-context context-bundle.json --suite replay.json \
--backend codex-cli --codex-capability-profile standard \
--selection-trials 1 --validation-trials 3 --parallelism 6 \
--out selected-context.md --json-out selection-evidence.json

denser audit AGENTS.md AGENTS.variant.md --type claude_md \
--suite replay.holdout.json \
--negative-control AGENTS.negative-control.md \
Expand All @@ -121,7 +138,15 @@ denser replay --type claude_md AGENTS.md --suite replay.json \
--backend codex-cli --codex-capability-profile text-only
```

`audit` is the primary interface. It runs paired baseline/variant replay,
`minimize-context` is the automatic selective-loading interface. A versioned
manifest names the visible context components, marks non-removable components,
and declares which required component to drop for the known-bad control. The
selector tests optional components largest first, retains every uncertain or
behavior-changing component, then repeats a final audit. It operates on
user-supplied visible text; it does not inspect hidden provider prefixes or
compact conversation history.

`audit` is the primary lower-level interface. It runs paired baseline/variant replay,
compares every covered case, checks whether a known-bad negative control causes
a regression, and reports both asset-only estimates and provider-reported full
input usage. Equal scores without a detected negative control are
Expand Down
18 changes: 18 additions & 0 deletions denser/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@
audit_context,
)
from denser.compress import CompressionResult, compress
from denser.context_selection import (
CONTEXT_BUNDLE_SCHEMA_VERSION,
CONTEXT_SELECTION_SCHEMA_VERSION,
ComponentAttempt,
ContextBundle,
ContextComponent,
ContextSelectionReport,
load_context_bundle,
minimize_context,
)
from denser.curve import DensityCurve, DensityPoint, curve
from denser.eval import (
CaseResult,
Expand Down Expand Up @@ -96,9 +106,15 @@
"CaseResult",
"ComparisonReport",
"CompressionResult",
"CONTEXT_BUNDLE_SCHEMA_VERSION",
"CONTEXT_SELECTION_SCHEMA_VERSION",
"ComponentAttempt",
"ContractCategory",
"ContractItem",
"ContractItemResult",
"ContextBundle",
"ContextComponent",
"ContextSelectionReport",
"ContextAuditReport",
"DensityCurve",
"DensityPoint",
Expand Down Expand Up @@ -147,9 +163,11 @@
"evaluate",
"inspect",
"load_golden_tasks",
"load_context_bundle",
"load_replay_suite",
"load_replay_tasks",
"optimize",
"minimize_context",
"replay",
"verify",
]
2 changes: 2 additions & 0 deletions denser/audit.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ def audit_context(
n_trials: int = 1,
seed: int = 0,
on_progress: Callable[[ReplayProgress], None] | None = None,
parallelism: int = 1,
) -> ContextAuditReport:
"""Audit a context variant and require a sensitive suite for a positive verdict.

Expand All @@ -232,6 +233,7 @@ def audit_context(
n_trials=n_trials,
seed=seed,
on_progress=on_progress,
parallelism=parallelism,
)
comparison = ReplayComparisonReport(
task_type=tt,
Expand Down
52 changes: 34 additions & 18 deletions denser/backends/codex_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import re
import shutil
import subprocess
import threading
import time
from dataclasses import dataclass
from pathlib import Path
Expand Down Expand Up @@ -269,7 +270,7 @@ def __init__(
self._disabled_features = _DISABLED_FEATURES_BY_PROFILE[capability_profile]
self._cli_version: str | None = None
self._cli_version_checked = False
self._last_call_metadata: CodexCliCallMetadata | None = None
self._call_state = threading.local()

@property
def name(self) -> str:
Expand All @@ -281,6 +282,11 @@ def supports_caching(self) -> bool:
"""Report that this adapter does not expose explicit prompt caching."""
return False

@property
def supports_concurrency(self) -> bool:
"""Report that per-call metadata is isolated for concurrent replays."""
return True

@property
def runtime_config(self) -> dict[str, object]:
"""Return the reproducibility settings safe to include in reports."""
Expand All @@ -306,9 +312,13 @@ def runtime_config(self) -> dict[str, object]:
@property
def last_call_metadata(self) -> dict[str, object] | None:
"""Return sanitized evidence for the most recent invocation."""
if self._last_call_metadata is None:
metadata = getattr(self._call_state, "last_call_metadata", None)
if not isinstance(metadata, CodexCliCallMetadata):
return None
return self._last_call_metadata.to_dict()
return metadata.to_dict()

def _set_last_call_metadata(self, metadata: CodexCliCallMetadata | None) -> None:
self._call_state.last_call_metadata = metadata

def _get_cli_version(self) -> str | None:
if self._cli_version_checked:
Expand Down Expand Up @@ -392,20 +402,24 @@ def _run(self, command: list[str], user: str) -> subprocess.CompletedProcess[str
)
except subprocess.TimeoutExpired as exc:
duration_ms = round((time.monotonic() - started) * 1000)
self._last_call_metadata = CodexCliCallMetadata(
status="timeout",
exit_code=None,
duration_ms=duration_ms,
self._set_last_call_metadata(
CodexCliCallMetadata(
status="timeout",
exit_code=None,
duration_ms=duration_ms,
)
)
raise BackendError(
f"Codex CLI timed out after {self._timeout_seconds:g} seconds"
) from exc
except OSError as exc:
duration_ms = round((time.monotonic() - started) * 1000)
self._last_call_metadata = CodexCliCallMetadata(
status="launch_error",
exit_code=None,
duration_ms=duration_ms,
self._set_last_call_metadata(
CodexCliCallMetadata(
status="launch_error",
exit_code=None,
duration_ms=duration_ms,
)
)
raise BackendError(f"Codex CLI could not be launched: {type(exc).__name__}") from exc

Expand All @@ -430,7 +444,7 @@ def complete(

command = self._build_command(system)
started = time.monotonic()
self._last_call_metadata = None
self._set_last_call_metadata(None)
completed = self._run(command, user)
duration_ms = round((time.monotonic() - started) * 1000)
parsed = _parse_events(completed.stdout, completed.stderr)
Expand All @@ -441,12 +455,14 @@ def complete(
and parsed.final_message is not None
else "failed"
)
self._last_call_metadata = CodexCliCallMetadata(
status=status,
exit_code=completed.returncode,
duration_ms=duration_ms,
usage=parsed.usage,
transport_fallback=parsed.transport_fallback,
self._set_last_call_metadata(
CodexCliCallMetadata(
status=status,
exit_code=completed.returncode,
duration_ms=duration_ms,
usage=parsed.usage,
transport_fallback=parsed.transport_fallback,
)
)
if status != "completed":
raise BackendError(
Expand Down
Loading