Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
122 commits
Select commit Hold shift + click to select a range
5740e2f
Implement TokenJuice pipeline and policy primitives
senamakel Jul 5, 2026
e19ac4d
Add class-labeled savings records
senamakel Jul 5, 2026
f2fc10f
Add web extract truncate-store reducer
senamakel Jul 5, 2026
8b2d7c8
Add explicit code stub read intent
senamakel Jul 5, 2026
6319d31
Add richer bloat estimators
senamakel Jul 5, 2026
b52ec89
Add DiffNoise and log template reformat
senamakel Jul 5, 2026
3e17f2a
Add TextCrusher and BM25 relevance
senamakel Jul 5, 2026
fd2036e
Upgrade SmartCrusher JSON planning
senamakel Jul 5, 2026
49b3ed9
Protect custom tags in ML text compression
senamakel Jul 5, 2026
e46fac4
Add ranked search-read scoring helpers
senamakel Jul 5, 2026
e404b1f
Add deterministic subagent summaries
senamakel Jul 5, 2026
135d7eb
Merge origin/main into prompt slice
senamakel Jul 5, 2026
61ddb69
Add summary contract and cache hints
senamakel Jul 5, 2026
a66f165
Add context breakdown observability API
senamakel Jul 5, 2026
910ed89
Record recovery tool passthrough status
senamakel Jul 5, 2026
52e148c
Add shell policy route overrides
senamakel Jul 5, 2026
9eb4216
Cover cascading tool boundary alignment
senamakel Jul 5, 2026
632b799
Cover generated tool boundary histories
senamakel Jul 5, 2026
e8487ca
Require host resolution for Auto profile
senamakel Jul 5, 2026
7c749be
Document unresolved Auto profile behavior
senamakel Jul 5, 2026
44a149c
Update Auto profile integration notes
senamakel Jul 5, 2026
05ae1f4
Update recovery tool migration notes
senamakel Jul 5, 2026
1fa4305
Flatten stringified JSON cells
senamakel Jul 5, 2026
74e5706
Cover stringified JSON adapter compaction
senamakel Jul 5, 2026
6f0d4e9
Preserve JSON discriminator buckets
senamakel Jul 5, 2026
7d9b5a1
Anchor JSON duplicate clusters
senamakel Jul 5, 2026
bbb46d4
Serialize ML callback tests
senamakel Jul 5, 2026
d292c62
Add JSON spread anchors
senamakel Jul 5, 2026
c93043a
Anchor JSON numeric change points
senamakel Jul 5, 2026
0d93f63
Anchor JSON information-dense rows
senamakel Jul 5, 2026
45e66ba
Bias JSON anchors by query direction
senamakel Jul 5, 2026
ca62439
Adapt JSON spread anchors by saturation
senamakel Jul 5, 2026
e00e0ec
Anchor JSON near-duplicate clusters
senamakel Jul 5, 2026
72019fc
Detect JSON spread saturation knees
senamakel Jul 5, 2026
d143666
Classify DiffNoise omission reasons
senamakel Jul 5, 2026
cb7031e
Align DiffNoise bloat patterns
senamakel Jul 5, 2026
c02dc24
Require context in log templates
senamakel Jul 5, 2026
8e38a25
Report global search omissions
senamakel Jul 5, 2026
e322792
Use BM25 for search query ranking
senamakel Jul 5, 2026
5648222
Omit private declarations in public API stubs
senamakel Jul 5, 2026
eaba531
Expand heuristic code stub modes
senamakel Jul 5, 2026
953009c
Cover one megabyte web extraction recovery
senamakel Jul 5, 2026
6627239
Label savings record sources
senamakel Jul 6, 2026
064359b
Correct TokenJuice savings plan assumption
senamakel Jul 6, 2026
f73eeaf
Honor explicit vendor search scope
senamakel Jul 6, 2026
8cd15a8
Expand tool digest credential redaction
senamakel Jul 6, 2026
3217d72
Update footer cap audit status
senamakel Jul 6, 2026
ea3dbc3
Update stub read port status
senamakel Jul 6, 2026
9504f13
Refresh completed integration status notes
senamakel Jul 6, 2026
0334de5
Refresh reference status summary
senamakel Jul 6, 2026
fdc4e4b
Use bloat estimate for low-signal skips
senamakel Jul 6, 2026
bec10e9
Gate web extract footer through typed offload
senamakel Jul 6, 2026
934a411
Refresh web extract reference status
senamakel Jul 6, 2026
77fae55
Add typed transform pipeline runner
senamakel Jul 6, 2026
7ed76ab
Add conversation partial split helpers
senamakel Jul 6, 2026
7028dbf
Add last user exchange split helpers
senamakel Jul 6, 2026
807ef2d
Record web extract config integration status
senamakel Jul 6, 2026
4d1baf6
Add SmartCrusher shape bucket tables
senamakel Jul 6, 2026
fcac317
Record SmartCrusher bucket table status
senamakel Jul 6, 2026
72da4a9
Hoist SmartCrusher constant columns
senamakel Jul 6, 2026
70854bc
Record SmartCrusher constant column status
senamakel Jul 6, 2026
f4d1817
Expose SmartCrusher analysis estimates
senamakel Jul 6, 2026
e1c9c41
Record SmartCrusher analysis estimate status
senamakel Jul 6, 2026
7df38cd
Record SmartCrusher planner status
senamakel Jul 6, 2026
a7fd074
Add typed DiffNoise offload transform
senamakel Jul 6, 2026
91e227e
Record DiffNoise transform status
senamakel Jul 6, 2026
72122f0
Add typed log template transform
senamakel Jul 6, 2026
e73efa1
Record log template transform status
senamakel Jul 6, 2026
440c9df
Add typed TextCrusher offload transform
senamakel Jul 6, 2026
f74143b
Record TextCrusher transform status
senamakel Jul 6, 2026
8476a00
Add typed HTML offload transform
senamakel Jul 6, 2026
6ffc2bb
Record HTML extractor transform status
senamakel Jul 6, 2026
542cb70
Add typed search offload transform
senamakel Jul 6, 2026
8505f7d
Record search transform status
senamakel Jul 6, 2026
bee7608
Add typed signal log offload transform
senamakel Jul 6, 2026
fba1dec
Record signal log transform status
senamakel Jul 6, 2026
d742d52
Add typed SmartCrusher transforms
senamakel Jul 6, 2026
a03a2f6
Record SmartCrusher transform status
senamakel Jul 6, 2026
d58a9b9
Add typed code stub offload transform
senamakel Jul 6, 2026
fa105aa
Record code stub transform status
senamakel Jul 6, 2026
72ebca0
Wire typed transforms into router
senamakel Jul 6, 2026
b670577
Update typed router status docs
senamakel Jul 6, 2026
18ba2cd
Add live-zone cache contract
senamakel Jul 6, 2026
78d009c
Record live-zone cache contract status
senamakel Jul 6, 2026
32cf47d
Add rule verification diagnostics
senamakel Jul 6, 2026
4ef19a9
Record rule verifier status
senamakel Jul 6, 2026
ecefb8e
Add fixture verification diagnostics
senamakel Jul 6, 2026
26ae10c
Record fixture verifier status
senamakel Jul 6, 2026
ffe0c4f
Add fallback discovery diagnostics
senamakel Jul 6, 2026
1a29f42
Add reduce-json protocol surface
senamakel Jul 6, 2026
9aef058
Record savings accounting status
senamakel Jul 6, 2026
d7d1d22
Add GitHub Actions failure rule fixture
senamakel Jul 6, 2026
00329d9
Add safe inventory reducer fixture
senamakel Jul 6, 2026
af78a85
Document reduce-json protocol surface
senamakel Jul 6, 2026
3114c46
Add initial reducer CLI
senamakel Jul 6, 2026
7a116c7
Add reducer verify CLI
senamakel Jul 6, 2026
362e0c0
Add fallback discovery CLI
senamakel Jul 6, 2026
86f824a
Add command wrapper CLI
senamakel Jul 6, 2026
a998b8f
Add CCR retrieval CLI
senamakel Jul 6, 2026
3bedbdd
Add CCR store stats CLI
senamakel Jul 6, 2026
a5cd758
Add doctor CLI
senamakel Jul 6, 2026
29c21a3
Add Codex host installer CLI
senamakel Jul 6, 2026
d7fcfeb
Add compressor fixture coverage
senamakel Jul 6, 2026
ee726aa
Add web extract fixture coverage
senamakel Jul 6, 2026
706ecd3
Add hook-path compressor e2e coverage
senamakel Jul 6, 2026
10cc554
Add reduce-json CCR metadata refs
senamakel Jul 6, 2026
9a4e219
Record reduce-json stats metadata
senamakel Jul 6, 2026
57d0b7b
Add log template reconstruction fixture
senamakel Jul 6, 2026
be58693
Add SmartCrusher planner fixtures
senamakel Jul 6, 2026
ac5c044
Broaden SmartCrusher fixture coverage
senamakel Jul 6, 2026
e2329a7
Cover remaining SmartCrusher planner fixtures
senamakel Jul 6, 2026
12ebc97
Add DiffNoise policy fixtures
senamakel Jul 6, 2026
5234a8a
Add ML tag protection fixtures
senamakel Jul 6, 2026
960f3d9
Add search-read ranking fixtures
senamakel Jul 6, 2026
db2206e
Record search_read OpenHuman wiring status
senamakel Jul 6, 2026
130c9a7
Record subagent summary integration status
senamakel Jul 6, 2026
87babd3
Record summary cache integration status
senamakel Jul 6, 2026
caa0e7d
Record TokenJuice adapter fixture coverage
senamakel Jul 6, 2026
e7e9968
Record OpenHuman algorithm port statuses
senamakel Jul 6, 2026
0fadb01
Clean up OpenHuman plan status wording
senamakel Jul 6, 2026
07da950
Record recovery tool migration status
senamakel Jul 6, 2026
92fbb2e
Resolve main merge conflicts
senamakel Jul 6, 2026
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
9 changes: 9 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ repository = "https://github.com/tinyhumansai/tinyjuice"
readme = "README.md"
keywords = ["llm", "tokens", "compression", "openhuman", "context"]
categories = ["text-processing"]
autobins = false

[dependencies]
async-trait = "0.1"
Expand Down Expand Up @@ -49,6 +50,14 @@ tokio = { version = "1", features = ["macros", "rt", "test-util"] }
name = "compression"
harness = false

[[bin]]
name = "tinyjuice"
path = "src/main.rs"

[[bin]]
name = "tinyjuice-hooks"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep hook entrypoints on the tinyjuice binary

With this bin rename, cargo install tinyjuice now exposes the existing hook installer/entrypoints as tinyjuice-hooks, while the hook templates, defaults, and docs still configure agents to run commands such as tinyjuice codex-post-tool-use, tinyjuice claude-code-post-tool-use, and tinyjuice install claude-code. Those commands now hit the new reducer CLI in src/main.rs, so existing Codex/Claude hooks break after upgrade and fresh Claude installs fail unless users manually discover and override the renamed binary.

Useful? React with 👍 / 👎.

path = "src/bin/tinyjuice.rs"

[features]
default = ["tinyjuice-treesitter"]
tinyjuice-treesitter = [
Expand Down
301 changes: 298 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,146 @@ behind a retrieval token so it can be pulled back on demand. Hosts that want
the strict lossless-or-recoverable guarantee (e.g. coding agents on the
`light` profile) can require a recovery token for any lossy output.

## Highlights

- **Content-aware by default** - JSON, code, logs, search results, diffs, HTML,
and plain text take different paths instead of one generic truncation rule.
- **Recoverable lossy views** - the CCR cache stores exact originals and appends
a `tokenjuice_retrieve` footer whenever data is dropped.
- **Agent-profile policy** - hosts can run `full`, `light`, `off`, or runtime
`auto` profiles per agent instead of using one global behavior.
- **Command-aware reduction** - built-in rules compact common shell, git, cargo,
npm, docker, kubectl, database, cloud, lint, and test outputs.
- **OpenHuman-ready boundary** - the core crate avoids OpenHuman runtime
dependencies; adapters install configuration, ML callbacks, and savings
recorders from the host side.
- **No raw-content analytics requirement** - the dashboard consumes metadata,
token and byte counts, latency, status, and strategy labels, not prompt text.

TinyJuice is designed for the work agents actually do: reading too much,
searching broadly, running noisy commands, and needing a compact but reversible
view that keeps failures, anomalies, changed hunks, signatures, and matching
lines visible.

## How It Works

```text
tool output / file / web payload
|
v
ContentHint + structural detection
|
v
JSON | Code | Log | Search | Diff | HTML | PlainText
|
v
specialized compressor or command-rule reducer
|
v
pass-through if unsafe, too small, disabled, or not smaller
|
v
CCR offload + retrieval footer when the view is lossy
```

The router is intentionally fail-soft. If it cannot shrink safely, it returns
the original bytes unchanged.

## Compression Surfaces

- **JSON SmartCrusher** - renders repeated object arrays as compact tables,
flattens safe nested cells, and keeps query-relevant, query-direction,
anomaly, numeric change-point, information-dense, duplicate/near-duplicate
cluster, and saturation/knee-based spread-anchor rows when large arrays are
row-dropped.
- **Code compressor** - keeps imports, signatures, shallow structure, and
important markers while collapsing deep bodies.
- **Log compressor** - preserves failures, warnings, summaries, stack traces,
command-rule outputs, and reconstructible high-context template runs while
dropping passing noise.
- **Search compressor** - groups grep/ripgrep output by file, ranks matches
with shared BM25 query context, and keeps top hits with per-file and global
omitted-match tallies.
- **Diff compressor** - keeps patch structure and changed lines, collapses long
context, and marks omitted lockfile, generated-bundle, or configured noisy
hunks with explicit reasons.
- **HTML compressor** - extracts readable text from rendered markup.
- **Plain-text ML slot** - optional host-provided callback for learned text
compression; disabled by default.
- **Generic command fallback** - line-oriented head/tail reduction for command
output when no specialized rule wins.

TinyJuice does not publish compression percentage claims yet. Throughput
benchmarks exist for hot paths, but ratio and quality claims require benchmark
fixtures that prove retained facts, latency, reversibility, and regression
safety.

## Quick Start

Add TinyJuice to a Rust project once published:

```toml
[dependencies]
tinyjuice = "0.1"
```

Use the small public trait scaffold when you want a simple strategy boundary:

```rust
use tinyjuice::{CompressionConfig, CompressionInput, Compressor, PassthroughCompressor};

fn main() -> Result<(), tinyjuice::TinyJuiceError> {
let compressor = PassthroughCompressor;
let output = compressor.compress(
CompressionInput::new("Keep this text unchanged for now."),
&CompressionConfig::default(),
)?;

assert_eq!(output.report.strategy, "passthrough");
Ok(())
}
```

Use the content router for real tool-output compaction:

```rust
use tinyjuice::{CompressOptions, ContentHint, compress_content};

async fn compact_payload(big_payload: &str) {
let hint = ContentHint {
source_tool: Some("read_file".to_string()),
extension: Some("json".to_string()),
..Default::default()
};

let result = compress_content(big_payload, Some(hint), &CompressOptions::default()).await;
if result.applied {
println!("{} -> {} bytes", result.original_bytes, result.compacted_bytes);
}
}
```

OpenHuman-style tool output integration goes through:

```rust
use tinyjuice::{AgentTokenjuiceCompression, compact_tool_output_with_policy};

async fn compact_command_output(command_output: &str) {
let (_text, _stats) = compact_tool_output_with_policy(
"shell",
Some(&serde_json::json!({ "command": "cargo test" })),
command_output,
Some(101),
AgentTokenjuiceCompression::Full,
).await;
}
```

Host agent layers should resolve `AgentTokenjuiceCompression::Auto` to `Full`,
`Light`, or `Off` before calling TokenJuice. Passing unresolved `Auto` to the
tool-output adapter leaves the output unchanged and reports
`none/agent-profile-auto-unresolved`.

## Quick Setup

Install the CLI:
Expand All @@ -34,13 +174,137 @@ Install the CLI:
cargo install tinyjuice --locked
```

Run the minimal reducer CLI:

```sh
cargo run -- reduce --tool-name bash --command "git status" status.txt
cargo run -- reduce-json payload.json
cargo run -- verify --rules --fixtures
cargo run -- discover executions.ndjson
cargo run -- wrap -- cargo test
cargo run -- ls --store-dir .tokenjuice/ccr
cargo run -- cat --store-dir .tokenjuice/ccr <token>
cargo run -- stats --store-dir .tokenjuice/ccr
cargo run -- doctor --store-dir .tokenjuice/ccr
cargo run -- doctor codex
cargo run -- doctor hooks
cargo run -- install codex --local target/debug/tinyjuice
cargo run -- uninstall codex
```

Run hot-path benchmarks:

Run one hook installer:

| Logo | Client | Install |
| --- | --- | --- |
| <img width="48px" src="https://raw.githubusercontent.com/vincentkoc/tokenjuice/main/docs/client-openai.jpg" alt="Codex" /> | [Codex CLI](https://github.com/openai/codex) | `tinyjuice install codex` |
| <img width="48px" src="https://raw.githubusercontent.com/vincentkoc/tokenjuice/main/docs/client-claude.jpg" alt="Claude Code" /> | [Claude Code](https://docs.anthropic.com/en/docs/claude-code) | `tinyjuice install claude-code` |

## API Notes

`compress_content` and `route` return `CompressedOutput`. The `text` field is
the compatibility output ready to inline into model context. When CCR retained
an original, `body` contains the compacted body without the recovery footer and
`recovery_footer` contains the footer separately. Hosts that apply their own
post-compaction caps should truncate only `body` and then reattach
`recovery_footer` so recovery markers remain reachable.

`compress_content_with_store` and `route_with_store` accept an injectable
`CcrStore`. Their `_report` variants also return a redacted `PipelineReport`
with byte counts, a cheap bloat estimate, applied steps, skip reason, lossy
flag, and CCR token IDs. Existing `compress_content`, `route`, and `cache::*`
helpers still use the process-global `GlobalCcrStore` for compatibility. New
tests and host adapters can use `MemoryCcrStore` to assert CCR behavior without
touching the global cache.

The CLI `ls`, `cat`, and `stats` commands operate only on an explicit CCR disk
tier via `--store-dir`; they do not imply access to another process's in-memory
cache. `cat` supports `--lines START:END` and `--bytes START:END` ranges.
`stats` reports metadata-only counts and byte totals without reading token
content.

The CLI `doctor` command emits structured health JSON using `ok`, `warn`,
`broken`, and `disabled` statuses. It verifies built-in rule health by default,
can include fixture checks with `--fixtures [dir]`, and can inspect an explicit
CCR disk tier with `--store-dir`.
Host-aware doctor targets (`codex`, `openhuman`, and aggregate `hooks`) expose
expected commands, detected commands when present, and one repair command
without mutating user configuration.
The first host mutation path is `install codex` / `uninstall codex`, which
maintains only a TinyJuice-managed instruction block under the Codex config
root and preserves unrelated text.

`run_typed_pipeline` is the typed-transform entry point for new reducers. It
runs lossless `ReformatTransform`s before CCR-backed `OffloadTransform`s and
keeps the true original content available to offload transforms even after an
intermediate reformat.

Shell-producing hosts can use the `route*_shell_policy` variants or call
`apply_shell_compaction_policy` with `ShellCompactionPolicy` before compacting
command output. The default OpenHuman-facing path uses `AllowSafeInventory`:
exact file-content reads, unsafe inventory actions, and mixed shell sequences
stay raw, while repository inventory output can still be summarized.

Conversation-level helpers under `conversation::*` expose deterministic Hermes
primitives without host runtime dependencies: token-budget tail selection,
tool-call/result boundary alignment, latest user/assistant anchors, JSON
string-leaf shrinking, partial split/rejoin helpers for compacting a middle
window, last-N user exchange retention helpers, and old tool-result digesting
with sensitive metadata redaction.

`savings::configure_record_recorder` installs a metadata-only savings recorder
that receives class-labeled `SavingsRecord` values (`counted`, `measured`, or
`estimated`) with a source label (`live` or `fixture_benchmark`), content kind,
compressor, byte/token counts, lossy/CCR flags, and redacted rule or skip
labels. Fixture benchmark records are meant to be reported separately from live
runtime stats. The older four-argument
`configure_recorder` callback remains as a compatibility wrapper.

`ContextBreakdown` and `ContextBucket` provide host-facing context usage
metadata for UI bars and compression diagnostics. Buckets separate static
prefix costs such as system prompts and tool definitions from compressible
conversation or memory history, and measured provider prompt usage can override
rough local estimates without storing raw prompt text.

`live_zone::*` exposes provider-neutral cache/live-zone contracts for hosts
that need to preserve frozen prompt bytes exactly. Hosts provide byte ranges;
TinyJuice validates mutable-block replacements, preserves the frozen prefix,
and can detect volatile cache-hostile values such as UUIDs, timestamps, JWTs,
and hex hashes with redacted findings only.

`reduce_json_str` and `reduce_json_request` expose the library form of the
`reduce-json` protocol. They accept direct `ToolExecutionInput` JSON or an
`{ "input": ..., "options": ... }` envelope, reject malformed payloads with
structured errors, and return stable serde-compatible response fields. See
[docs/reduce-json-protocol.md](docs/reduce-json-protocol.md) for the current
request and response contract.

`verify_rules` checks the same builtin/user/project rule layers as the loader
without changing the lenient load contract. It reports parse errors, invalid
regex patterns, duplicate rule IDs, and shadowed lower-priority rules so CLI
or host diagnostics can fail loudly while runtime loading remains compatible.
`verify_rule_fixtures` runs recorded `*.fixture.json` examples through compiled
rules and reports pass counts, parse errors, and hash-only output mismatches.
`discover_fallback_outputs` groups command families that still fall through to
`generic/fallback` without including raw tool output in the report.

Already-extracted web pages can be passed through `reduce_web_extract` or
`reduce_web_extract_with_store`. The reducer removes inline base64 image blobs,
preserves ordinary markdown image URLs, and stores omitted middle content in CCR
before emitting a head/tail truncation footer. If CCR cannot retain the full
cleaned page, the reducer returns the cleaned page without lossy truncation.

Source-code file reads are exact by default. Hosts that intentionally want a
structural view can call `stub_code` with a `StubMode`; the returned
`CodeStubOutput` includes symbols, elided line ranges, and whether tree-sitter
or the heuristic fallback produced the stub. `PublicApi` stubs keep imports and
public signatures while replacing private declarations with elision metadata;
matched-symbol and line-range expansion also work through the heuristic
fallback.

Run the local analytics interface:

Use `tinyjuice update <host>` to refresh an installed hook and
`tinyjuice uninstall <host>` to remove it.

Expand All @@ -64,6 +328,28 @@ attribution for agent-created commits.
- **Privacy-aware by design** - analytics can use metadata, byte counts,
latency, status, and strategy labels without requiring raw prompt text.

```text
src/
cache/ CCR recovery stores and retrieval markers
compressor/ Compression trait and input/output types
compressors/ Content-aware compressor implementations
config/ Compression target and policy configuration
conversation/ Provider-neutral conversation compaction helpers
detect/ Content-kind hints and structural detection
observability.rs Non-sensitive context usage breakdowns
pipeline/ Typed transform/report primitives
policy/ Host compaction policy helpers
reduce/ Rule-engine reducers and command normalization
rules/ Built-in, user, and project command reduction rules
savings.rs Host-installed savings attribution hook
tool_integration.rs OpenHuman-style tool-output adapter
openhuman/ Placeholder OpenHuman integration boundary
error.rs Shared error type
interface/ Self-hostable analytics UI for compression run metadata
wiki/ Technical GitHub wiki source
docs/references/ Design references and candidate strategy specs
```

## What It Compresses

| Surface | What stays visible |
Expand Down Expand Up @@ -164,6 +450,15 @@ The technical docs live in the wiki:
- [Development](wiki/Development.md)
- [Security and Privacy](wiki/Security-and-Privacy.md)

TinyJuice is pre-1.0. The CLI, router, command-rule engine, CCR recovery store,
content detectors, native compressors, and OpenHuman-style adapter are in place;
public API names may still move as host integration hardens.
## Status

TinyJuice is pre-1.0. The router, command-rule engine, CCR recovery store,
content detectors, several native compressors, the OpenHuman-style tool adapter,
typed-pipeline primitives, injectable CCR store, report-producing router path,
savings metadata, deterministic conversation helpers, live-zone cache contracts,
and the analytics interface are implemented. Public API names may still move as OpenHuman
integration hardens.

The project boundary is deliberate: keep the core crate small, do not add
OpenHuman runtime dependencies without a feature or adapter boundary, and do not
claim compression percentages until benchmark fixtures exist.
Loading