tokenfold 0.4.0__tar.gz → 0.4.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {tokenfold-0.4.0 → tokenfold-0.4.1}/Cargo.lock +10 -10
- {tokenfold-0.4.0 → tokenfold-0.4.1}/Cargo.toml +1 -1
- {tokenfold-0.4.0 → tokenfold-0.4.1}/PKG-INFO +36 -11
- {tokenfold-0.4.0 → tokenfold-0.4.1}/README.md +35 -10
- {tokenfold-0.4.0 → tokenfold-0.4.1}/crates/tokenfold-core/benches/THRESHOLDS.toml +1 -1
- {tokenfold-0.4.0 → tokenfold-0.4.1}/crates/tokenfold-core/benches/compression_bench.rs +2 -2
- {tokenfold-0.4.0 → tokenfold-0.4.1}/crates/tokenfold-core/src/budget.rs +16 -16
- {tokenfold-0.4.0 → tokenfold-0.4.1}/crates/tokenfold-core/src/errors.rs +6 -1
- {tokenfold-0.4.0 → tokenfold-0.4.1}/crates/tokenfold-core/src/filters.rs +8 -8
- {tokenfold-0.4.0 → tokenfold-0.4.1}/crates/tokenfold-core/src/modes.rs +17 -15
- tokenfold-0.4.1/crates/tokenfold-core/src/pipeline/mod.rs +1010 -0
- tokenfold-0.4.1/crates/tokenfold-core/src/pipeline/tests.rs +1287 -0
- {tokenfold-0.4.0 → tokenfold-0.4.1}/crates/tokenfold-core/src/report.rs +5 -5
- {tokenfold-0.4.0 → tokenfold-0.4.1}/crates/tokenfold-core/src/retrieval_store.rs +3 -3
- {tokenfold-0.4.0 → tokenfold-0.4.1}/crates/tokenfold-core/src/safety.rs +3 -1
- {tokenfold-0.4.0 → tokenfold-0.4.1}/crates/tokenfold-core/src/stats.rs +16 -15
- {tokenfold-0.4.0 → tokenfold-0.4.1}/crates/tokenfold-core/src/transforms/diff.rs +4 -6
- {tokenfold-0.4.0 → tokenfold-0.4.1}/crates/tokenfold-core/src/transforms/json_prune.rs +1 -2
- {tokenfold-0.4.0 → tokenfold-0.4.1}/crates/tokenfold-core/src/transforms/logs.rs +4 -4
- {tokenfold-0.4.0 → tokenfold-0.4.1}/crates/tokenfold-core/tests/golden.rs +3 -1
- {tokenfold-0.4.0 → tokenfold-0.4.1}/crates/tokenfold-core/tests/integration.rs +1 -1
- {tokenfold-0.4.0 → tokenfold-0.4.1}/crates/tokenfold-core/tests/property_tests.rs +1 -1
- {tokenfold-0.4.0 → tokenfold-0.4.1}/crates/tokenfold-py/Cargo.toml +1 -1
- {tokenfold-0.4.0 → tokenfold-0.4.1}/crates/tokenfold-py/src/lib.rs +255 -31
- tokenfold-0.4.0/crates/tokenfold-core/examples/quickstart.rs +0 -83
- tokenfold-0.4.0/crates/tokenfold-core/src/pipeline.rs +0 -2301
- {tokenfold-0.4.0 → tokenfold-0.4.1}/LICENSE +0 -0
- {tokenfold-0.4.0 → tokenfold-0.4.1}/crates/tokenfold-core/Cargo.toml +0 -0
- {tokenfold-0.4.0 → tokenfold-0.4.1}/crates/tokenfold-core/src/input.rs +0 -0
- {tokenfold-0.4.0 → tokenfold-0.4.1}/crates/tokenfold-core/src/lib.rs +0 -0
- {tokenfold-0.4.0 → tokenfold-0.4.1}/crates/tokenfold-core/src/status.rs +0 -0
- {tokenfold-0.4.0 → tokenfold-0.4.1}/crates/tokenfold-core/src/token_estimator.rs +0 -0
- {tokenfold-0.4.0 → tokenfold-0.4.1}/crates/tokenfold-core/src/transforms/json.rs +0 -0
- {tokenfold-0.4.0 → tokenfold-0.4.1}/crates/tokenfold-core/src/transforms/json_dict.rs +0 -0
- {tokenfold-0.4.0 → tokenfold-0.4.1}/crates/tokenfold-core/src/transforms/json_fold.rs +0 -0
- {tokenfold-0.4.0 → tokenfold-0.4.1}/crates/tokenfold-core/src/transforms/log_fold.rs +0 -0
- {tokenfold-0.4.0 → tokenfold-0.4.1}/crates/tokenfold-core/src/transforms/mod.rs +0 -0
- {tokenfold-0.4.0 → tokenfold-0.4.1}/crates/tokenfold-core/src/transforms/redaction.rs +0 -0
- {tokenfold-0.4.0 → tokenfold-0.4.1}/crates/tokenfold-core/src/transforms/schema.rs +0 -0
- {tokenfold-0.4.0 → tokenfold-0.4.1}/pyproject.toml +0 -0
|
@@ -1013,7 +1013,7 @@ dependencies = [
|
|
|
1013
1013
|
|
|
1014
1014
|
[[package]]
|
|
1015
1015
|
name = "tokenfold-adapters"
|
|
1016
|
-
version = "0.4.
|
|
1016
|
+
version = "0.4.1"
|
|
1017
1017
|
dependencies = [
|
|
1018
1018
|
"serde",
|
|
1019
1019
|
"serde_json",
|
|
@@ -1022,7 +1022,7 @@ dependencies = [
|
|
|
1022
1022
|
|
|
1023
1023
|
[[package]]
|
|
1024
1024
|
name = "tokenfold-admin"
|
|
1025
|
-
version = "0.4.
|
|
1025
|
+
version = "0.4.1"
|
|
1026
1026
|
dependencies = [
|
|
1027
1027
|
"ed25519-dalek",
|
|
1028
1028
|
"serde",
|
|
@@ -1032,7 +1032,7 @@ dependencies = [
|
|
|
1032
1032
|
|
|
1033
1033
|
[[package]]
|
|
1034
1034
|
name = "tokenfold-cli"
|
|
1035
|
-
version = "0.4.
|
|
1035
|
+
version = "0.4.1"
|
|
1036
1036
|
dependencies = [
|
|
1037
1037
|
"clap",
|
|
1038
1038
|
"serde",
|
|
@@ -1045,7 +1045,7 @@ dependencies = [
|
|
|
1045
1045
|
|
|
1046
1046
|
[[package]]
|
|
1047
1047
|
name = "tokenfold-core"
|
|
1048
|
-
version = "0.4.
|
|
1048
|
+
version = "0.4.1"
|
|
1049
1049
|
dependencies = [
|
|
1050
1050
|
"proptest",
|
|
1051
1051
|
"regex",
|
|
@@ -1059,25 +1059,25 @@ dependencies = [
|
|
|
1059
1059
|
|
|
1060
1060
|
[[package]]
|
|
1061
1061
|
name = "tokenfold-image"
|
|
1062
|
-
version = "0.4.
|
|
1062
|
+
version = "0.4.1"
|
|
1063
1063
|
|
|
1064
1064
|
[[package]]
|
|
1065
1065
|
name = "tokenfold-learn"
|
|
1066
|
-
version = "0.4.
|
|
1066
|
+
version = "0.4.1"
|
|
1067
1067
|
dependencies = [
|
|
1068
1068
|
"tokenfold-core",
|
|
1069
1069
|
]
|
|
1070
1070
|
|
|
1071
1071
|
[[package]]
|
|
1072
1072
|
name = "tokenfold-output"
|
|
1073
|
-
version = "0.4.
|
|
1073
|
+
version = "0.4.1"
|
|
1074
1074
|
dependencies = [
|
|
1075
1075
|
"tokenfold-core",
|
|
1076
1076
|
]
|
|
1077
1077
|
|
|
1078
1078
|
[[package]]
|
|
1079
1079
|
name = "tokenfold-proxy"
|
|
1080
|
-
version = "0.4.
|
|
1080
|
+
version = "0.4.1"
|
|
1081
1081
|
dependencies = [
|
|
1082
1082
|
"clap",
|
|
1083
1083
|
"serde",
|
|
@@ -1089,7 +1089,7 @@ dependencies = [
|
|
|
1089
1089
|
|
|
1090
1090
|
[[package]]
|
|
1091
1091
|
name = "tokenfold-py"
|
|
1092
|
-
version = "0.4.
|
|
1092
|
+
version = "0.4.1"
|
|
1093
1093
|
dependencies = [
|
|
1094
1094
|
"pyo3",
|
|
1095
1095
|
"serde_json",
|
|
@@ -1098,7 +1098,7 @@ dependencies = [
|
|
|
1098
1098
|
|
|
1099
1099
|
[[package]]
|
|
1100
1100
|
name = "tokenfold-rag"
|
|
1101
|
-
version = "0.4.
|
|
1101
|
+
version = "0.4.1"
|
|
1102
1102
|
|
|
1103
1103
|
[[package]]
|
|
1104
1104
|
name = "toml"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tokenfold
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.1
|
|
4
4
|
Classifier: Development Status :: 4 - Beta
|
|
5
5
|
Classifier: Intended Audience :: Developers
|
|
6
6
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
@@ -30,7 +30,7 @@ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
|
30
30
|
|
|
31
31
|
CLI · Python · TypeScript · Rust · proxy · MCP · local-first · provider-neutral
|
|
32
32
|
|
|
33
|
-
[](https://github.com/snchimata/tokenfold/actions/workflows/ci.yml) [](https://github.com/snchimata/tokenfold/actions/workflows/ci.yml) [](https://github.com/snchimata/tokenfold/releases/latest) [](https://pypi.org/project/tokenfold/) [](https://www.npmjs.com/package/tokenfold) [](https://docs.rs/crate/tokenfold-core/latest) [](LICENSE)
|
|
33
|
+
[](https://github.com/snchimata/tokenfold/actions/workflows/ci.yml) [](https://github.com/snchimata/tokenfold/actions/workflows/ci.yml) [](https://github.com/snchimata/tokenfold/releases/latest) [](https://pypi.org/project/tokenfold/) [](https://www.npmjs.com/package/tokenfold) [](https://docs.rs/crate/tokenfold-core/latest) [](https://github.com/snchimata/tokenfold/blob/main/LICENSE)
|
|
34
34
|
|
|
35
35
|
[Measured results](#measured-results) · [Platform](#one-platform-two-engines) · [Quick start](#quick-start) · [Lossy pruning](#recoverable-lossy-pruning) · [Select model](#tokenfold-select) · [Reproduce](#reproduce-the-results)
|
|
36
36
|
|
|
@@ -144,13 +144,18 @@ print(f"saved {result.report.saved_tokens} tokens ({result.saved_pct():.1f}%)")
|
|
|
144
144
|
`tokenfold doctor` verifies it. Trusted filters for Git, build, and test output
|
|
145
145
|
are available through `tokenfold filters list`.
|
|
146
146
|
|
|
147
|
-
Runnable examples:
|
|
147
|
+
Runnable examples, one per surface, all under [`examples/`](examples):
|
|
148
148
|
|
|
149
149
|
```bash
|
|
150
|
-
python examples/quickstart.py
|
|
151
|
-
|
|
150
|
+
python examples/quickstart.py # Python: compress messages, request bodies, JSON data
|
|
151
|
+
node examples/quickstart.mjs # TypeScript/Node: compress, inspect, read the receipt
|
|
152
|
+
cargo run -p tokenfold-core --example quickstart # Rust: the embedded core API
|
|
153
|
+
python examples/lossy_pruning.py # CLI: opt-in recoverable pruning, end to end
|
|
152
154
|
```
|
|
153
155
|
|
|
156
|
+
[`examples/quickstart.ipynb`](examples/quickstart.ipynb) is the notebook form of the
|
|
157
|
+
Python quickstart, one operation per cell.
|
|
158
|
+
|
|
154
159
|
## Recoverable lossy pruning
|
|
155
160
|
|
|
156
161
|
Lossless folding has a ceiling on heterogeneous arrays. `--lossy` ranks rows,
|
|
@@ -204,6 +209,27 @@ tokenfold compress examples/incident_feed.json --format json \
|
|
|
204
209
|
--lossy heuristic --lossy-ratio 0.35 --dry-run
|
|
205
210
|
```
|
|
206
211
|
|
|
212
|
+
The same flags, and the same fail-closed contract, from Python and TypeScript:
|
|
213
|
+
|
|
214
|
+
```python
|
|
215
|
+
from tokenfold import CompressionPolicy, InputFormat, LossyPath, compress, retrieve
|
|
216
|
+
|
|
217
|
+
policy = CompressionPolicy(lossy=LossyPath.HEURISTIC, lossy_ratio=0.35)
|
|
218
|
+
result = compress(feed_bytes, format=InputFormat.JSON, policy=policy)
|
|
219
|
+
original = retrieve(marker["$tf_ref"]["hash"]) # any dropped row, verbatim
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
```ts
|
|
223
|
+
import { compress, retrieve } from "tokenfold";
|
|
224
|
+
|
|
225
|
+
const { payload, report } = await compress(feed, {
|
|
226
|
+
format: "json",
|
|
227
|
+
lossy: "heuristic",
|
|
228
|
+
lossyRatio: 0.35,
|
|
229
|
+
});
|
|
230
|
+
const original = await retrieve(hash); // any dropped row, verbatim
|
|
231
|
+
```
|
|
232
|
+
|
|
207
233
|
<details>
|
|
208
234
|
<summary><strong>Current Phase 1 constraints</strong></summary>
|
|
209
235
|
|
|
@@ -212,9 +238,8 @@ already contain retrieval markers. A filesystem failure after partial writes
|
|
|
212
238
|
may also leave unreferenced entries until their configured TTL expires. Both
|
|
213
239
|
require location-based transactional materialization before promotion.
|
|
214
240
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
more rows if storage becomes unavailable.
|
|
241
|
+
Preview is a projection rather than a filesystem transaction, so a real run may
|
|
242
|
+
keep more rows if storage becomes unavailable.
|
|
218
243
|
|
|
219
244
|
</details>
|
|
220
245
|
|
|
@@ -308,8 +333,8 @@ cargo run --release --locked -p tokenfold-cli -- \
|
|
|
308
333
|
```
|
|
309
334
|
|
|
310
335
|
The small bundled API response reports 382 → 206 tokens, a **46.1% lossless
|
|
311
|
-
reduction**. Benchmark sources and thresholds live in [CHANGELOG.md](CHANGELOG.md)
|
|
312
|
-
and [`crates/tokenfold-core/benches/THRESHOLDS.toml`](crates/tokenfold-core/benches/THRESHOLDS.toml).
|
|
336
|
+
reduction**. Benchmark sources and thresholds live in [CHANGELOG.md](https://github.com/snchimata/tokenfold/blob/main/CHANGELOG.md)
|
|
337
|
+
and [`crates/tokenfold-core/benches/THRESHOLDS.toml`](https://github.com/snchimata/tokenfold/blob/main/crates/tokenfold-core/benches/THRESHOLDS.toml).
|
|
313
338
|
|
|
314
339
|
## Contributing
|
|
315
340
|
|
|
@@ -326,7 +351,7 @@ cd packages/tokenfold && npm ci && npm test
|
|
|
326
351
|
|
|
327
352
|
## License
|
|
328
353
|
|
|
329
|
-
[Apache-2.0](LICENSE)
|
|
354
|
+
[Apache-2.0](https://github.com/snchimata/tokenfold/blob/main/LICENSE)
|
|
330
355
|
|
|
331
356
|
---
|
|
332
357
|
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
CLI · Python · TypeScript · Rust · proxy · MCP · local-first · provider-neutral
|
|
10
10
|
|
|
11
|
-
[](https://github.com/snchimata/tokenfold/actions/workflows/ci.yml) [](https://github.com/snchimata/tokenfold/actions/workflows/ci.yml) [](https://github.com/snchimata/tokenfold/releases/latest) [](https://pypi.org/project/tokenfold/) [](https://www.npmjs.com/package/tokenfold) [](https://docs.rs/crate/tokenfold-core/latest) [](LICENSE)
|
|
11
|
+
[](https://github.com/snchimata/tokenfold/actions/workflows/ci.yml) [](https://github.com/snchimata/tokenfold/actions/workflows/ci.yml) [](https://github.com/snchimata/tokenfold/releases/latest) [](https://pypi.org/project/tokenfold/) [](https://www.npmjs.com/package/tokenfold) [](https://docs.rs/crate/tokenfold-core/latest) [](https://github.com/snchimata/tokenfold/blob/main/LICENSE)
|
|
12
12
|
|
|
13
13
|
[Measured results](#measured-results) · [Platform](#one-platform-two-engines) · [Quick start](#quick-start) · [Lossy pruning](#recoverable-lossy-pruning) · [Select model](#tokenfold-select) · [Reproduce](#reproduce-the-results)
|
|
14
14
|
|
|
@@ -122,13 +122,18 @@ print(f"saved {result.report.saved_tokens} tokens ({result.saved_pct():.1f}%)")
|
|
|
122
122
|
`tokenfold doctor` verifies it. Trusted filters for Git, build, and test output
|
|
123
123
|
are available through `tokenfold filters list`.
|
|
124
124
|
|
|
125
|
-
Runnable examples:
|
|
125
|
+
Runnable examples, one per surface, all under [`examples/`](examples):
|
|
126
126
|
|
|
127
127
|
```bash
|
|
128
|
-
python examples/quickstart.py
|
|
129
|
-
|
|
128
|
+
python examples/quickstart.py # Python: compress messages, request bodies, JSON data
|
|
129
|
+
node examples/quickstart.mjs # TypeScript/Node: compress, inspect, read the receipt
|
|
130
|
+
cargo run -p tokenfold-core --example quickstart # Rust: the embedded core API
|
|
131
|
+
python examples/lossy_pruning.py # CLI: opt-in recoverable pruning, end to end
|
|
130
132
|
```
|
|
131
133
|
|
|
134
|
+
[`examples/quickstart.ipynb`](examples/quickstart.ipynb) is the notebook form of the
|
|
135
|
+
Python quickstart, one operation per cell.
|
|
136
|
+
|
|
132
137
|
## Recoverable lossy pruning
|
|
133
138
|
|
|
134
139
|
Lossless folding has a ceiling on heterogeneous arrays. `--lossy` ranks rows,
|
|
@@ -182,6 +187,27 @@ tokenfold compress examples/incident_feed.json --format json \
|
|
|
182
187
|
--lossy heuristic --lossy-ratio 0.35 --dry-run
|
|
183
188
|
```
|
|
184
189
|
|
|
190
|
+
The same flags, and the same fail-closed contract, from Python and TypeScript:
|
|
191
|
+
|
|
192
|
+
```python
|
|
193
|
+
from tokenfold import CompressionPolicy, InputFormat, LossyPath, compress, retrieve
|
|
194
|
+
|
|
195
|
+
policy = CompressionPolicy(lossy=LossyPath.HEURISTIC, lossy_ratio=0.35)
|
|
196
|
+
result = compress(feed_bytes, format=InputFormat.JSON, policy=policy)
|
|
197
|
+
original = retrieve(marker["$tf_ref"]["hash"]) # any dropped row, verbatim
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
```ts
|
|
201
|
+
import { compress, retrieve } from "tokenfold";
|
|
202
|
+
|
|
203
|
+
const { payload, report } = await compress(feed, {
|
|
204
|
+
format: "json",
|
|
205
|
+
lossy: "heuristic",
|
|
206
|
+
lossyRatio: 0.35,
|
|
207
|
+
});
|
|
208
|
+
const original = await retrieve(hash); // any dropped row, verbatim
|
|
209
|
+
```
|
|
210
|
+
|
|
185
211
|
<details>
|
|
186
212
|
<summary><strong>Current Phase 1 constraints</strong></summary>
|
|
187
213
|
|
|
@@ -190,9 +216,8 @@ already contain retrieval markers. A filesystem failure after partial writes
|
|
|
190
216
|
may also leave unreferenced entries until their configured TTL expires. Both
|
|
191
217
|
require location-based transactional materialization before promotion.
|
|
192
218
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
more rows if storage becomes unavailable.
|
|
219
|
+
Preview is a projection rather than a filesystem transaction, so a real run may
|
|
220
|
+
keep more rows if storage becomes unavailable.
|
|
196
221
|
|
|
197
222
|
</details>
|
|
198
223
|
|
|
@@ -286,8 +311,8 @@ cargo run --release --locked -p tokenfold-cli -- \
|
|
|
286
311
|
```
|
|
287
312
|
|
|
288
313
|
The small bundled API response reports 382 → 206 tokens, a **46.1% lossless
|
|
289
|
-
reduction**. Benchmark sources and thresholds live in [CHANGELOG.md](CHANGELOG.md)
|
|
290
|
-
and [`crates/tokenfold-core/benches/THRESHOLDS.toml`](crates/tokenfold-core/benches/THRESHOLDS.toml).
|
|
314
|
+
reduction**. Benchmark sources and thresholds live in [CHANGELOG.md](https://github.com/snchimata/tokenfold/blob/main/CHANGELOG.md)
|
|
315
|
+
and [`crates/tokenfold-core/benches/THRESHOLDS.toml`](https://github.com/snchimata/tokenfold/blob/main/crates/tokenfold-core/benches/THRESHOLDS.toml).
|
|
291
316
|
|
|
292
317
|
## Contributing
|
|
293
318
|
|
|
@@ -304,7 +329,7 @@ cd packages/tokenfold && npm ci && npm test
|
|
|
304
329
|
|
|
305
330
|
## License
|
|
306
331
|
|
|
307
|
-
[Apache-2.0](LICENSE)
|
|
332
|
+
[Apache-2.0](https://github.com/snchimata/tokenfold/blob/main/LICENSE)
|
|
308
333
|
|
|
309
334
|
---
|
|
310
335
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# Measured 2026-07-11 on AMD Ryzen 7 9800X3D (8c/16t), 31GB RAM, Windows, rustc 1.97.0,
|
|
3
3
|
# `cargo bench -p tokenfold-core` release profile. See CHANGELOG.md for the full reproducibility
|
|
4
4
|
# record. Thresholds carry ~1.3-1.5x headroom over the measured baseline for runner variance;
|
|
5
|
-
# tighten once `bench-regression` has run on a dedicated CI runner
|
|
5
|
+
# tighten once `bench-regression` has run on a dedicated, fixed-spec CI runner.
|
|
6
6
|
#
|
|
7
7
|
# p95 latency — dominated by TiktokenEstimator::o200k_base() reloading BPE ranks on every
|
|
8
8
|
# `compress()` call (the public API doesn't cache the estimator across calls) plus tiktoken-rs's
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
//!
|
|
1
|
+
//! Benchmark suite for `compress`: a p95-latency and bytes-allocated regression gate.
|
|
2
2
|
//!
|
|
3
|
-
//! ponytail:
|
|
3
|
+
//! ponytail: the conventional picks here are `criterion` + `divan`. Both pull in real
|
|
4
4
|
//! dependency trees (criterion: plotting/serde chain; divan: its own harness+macros) for what
|
|
5
5
|
//! this project actually needs: a p95-latency and bytes-allocated regression gate against a
|
|
6
6
|
//! checked-in threshold file. `std::time::Instant` + a custom counting `GlobalAlloc` do the same
|
|
@@ -5,9 +5,9 @@ use crate::input::{CompressionInput, InputFormat};
|
|
|
5
5
|
use crate::token_estimator::TokenEstimator;
|
|
6
6
|
|
|
7
7
|
/// Placeholder floor for `retrieval_ttl_seconds` whenever `lossy` is set — see
|
|
8
|
-
/// `CompressionPolicyBuilder::build`'s lossy validation. The
|
|
9
|
-
///
|
|
10
|
-
///
|
|
8
|
+
/// `CompressionPolicyBuilder::build`'s lossy validation. The exact retention policy is still an
|
|
9
|
+
/// open owner decision, not yet confirmed; this value only needs to be "clearly more than
|
|
10
|
+
/// instant," not final.
|
|
11
11
|
const MIN_LOSSY_TTL_SECONDS: u64 = 86_400;
|
|
12
12
|
|
|
13
13
|
// NOT Eq: `lossy_ratio` holds an f64 (same precedent as `CompressionOutput`/`CompressionReport`).
|
|
@@ -29,30 +29,30 @@ pub struct CompressionPolicy {
|
|
|
29
29
|
/// entry doesn't enable it for the current mode. Still requires `experimental` for any
|
|
30
30
|
/// transform whose `ModeEntry.experimental == true` (see `modes::pipeline_for`).
|
|
31
31
|
pub enable: Vec<String>,
|
|
32
|
-
///
|
|
32
|
+
/// When true, and the full pre-transform input contains no secret-shaped content,
|
|
33
33
|
/// `pipeline::compress_with_estimator` persists it to the reversible evidence store
|
|
34
34
|
/// (`retrieval_backend`/`retrieval_store_path`) under its SHA-256 hash.
|
|
35
35
|
pub store_originals: bool,
|
|
36
|
-
///
|
|
36
|
+
/// The evidence-store namespace stored-original entries are keyed under (see
|
|
37
37
|
/// `retrieval_store::RetrievalStore::store`).
|
|
38
38
|
pub retrieval_namespace: String,
|
|
39
|
-
///
|
|
39
|
+
/// TTL passed to `RetrievalStore::store` for newly stored originals. `None` means
|
|
40
40
|
/// "use `retrieval_store::DEFAULT_TTL_SECONDS`" (this is a *default*, not "never expire" —
|
|
41
41
|
/// that per-entry meaning belongs to `RetrievalStore::store`'s own `ttl_seconds` parameter).
|
|
42
42
|
pub retrieval_ttl_seconds: Option<u64>,
|
|
43
|
-
///
|
|
43
|
+
/// Backend name passed to `RetrievalStore::open` ("memory" | "filesystem" |
|
|
44
44
|
/// "sqlite" — the latter fails clearly, handled as best-effort skip, see
|
|
45
45
|
/// `pipeline::maybe_store_originals`).
|
|
46
46
|
pub retrieval_backend: String,
|
|
47
|
-
///
|
|
47
|
+
/// Filesystem backend root override. `None` means
|
|
48
48
|
/// `retrieval_store::default_store_path()`.
|
|
49
49
|
pub retrieval_store_path: Option<PathBuf>,
|
|
50
|
-
/// Opt-in lossy JSON array-item selection
|
|
51
|
-
///
|
|
52
|
-
/// is set only by an explicit CLI flag, never derived from
|
|
53
|
-
/// deliberately NOT part of `modes.rs`/`ALL_ENTRIES`: it is a
|
|
54
|
-
/// category (data-lossy, not just structurally-lossy-but-reversible)
|
|
55
|
-
/// transform in this crate. See `pipeline::apply_lossy_reduction`.
|
|
50
|
+
/// Opt-in lossy JSON array-item selection: array items are dropped and replaced by a
|
|
51
|
+
/// recoverable `$tf_ref` marker. `None` (the default) means the lossless pipeline is
|
|
52
|
+
/// untouched — this field is set only by an explicit CLI flag, never derived from
|
|
53
|
+
/// `mode`/`experimental`, and is deliberately NOT part of `modes.rs`/`ALL_ENTRIES`: it is a
|
|
54
|
+
/// fundamentally different category (data-lossy, not just structurally-lossy-but-reversible)
|
|
55
|
+
/// from every other transform in this crate. See `pipeline::apply_lossy_reduction`.
|
|
56
56
|
pub lossy: Option<LossyPath>,
|
|
57
57
|
/// BEST-EFFORT selection hint, not an enforced budget: how aggressively to prune, as the
|
|
58
58
|
/// fraction (0.0..=1.0) of the prunable pool's own estimated token cost to keep when `lossy`
|
|
@@ -422,8 +422,8 @@ fn message_content_bytes(message: &serde_json::Value) -> Option<Vec<u8>> {
|
|
|
422
422
|
}
|
|
423
423
|
}
|
|
424
424
|
|
|
425
|
-
/// Keeps file names and hunk headers, matching the `diff_compaction`
|
|
426
|
-
///
|
|
425
|
+
/// Keeps file names and hunk headers, matching the `diff_compaction` contract of what must
|
|
426
|
+
/// survive compaction. Each kept line is its own segment.
|
|
427
427
|
fn extract_diff_protected(bytes: &[u8]) -> Vec<Vec<u8>> {
|
|
428
428
|
let text = String::from_utf8_lossy(bytes);
|
|
429
429
|
let mut segments = Vec::new();
|
|
@@ -17,7 +17,12 @@ pub enum TokenFoldError {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
impl TokenFoldError {
|
|
20
|
-
/// CLI exit code
|
|
20
|
+
/// Stable CLI exit code for this error: 2 invalid input, 3 safety/redaction violation,
|
|
21
|
+
/// 4 estimator failure, 5 bad configuration, 6 internal or I/O failure. Every successful
|
|
22
|
+
/// [`crate::Status`] outcome — including `UnreachableTarget`, which is a typed result and
|
|
23
|
+
/// not an error — exits 0. The proxy's HTTP status mapping and the Python binding's
|
|
24
|
+
/// exception hierarchy are derived from these same buckets, so the numbering is a public
|
|
25
|
+
/// contract; `exit_codes_match_error_taxonomy_table` below pins it.
|
|
21
26
|
pub fn exit_code(&self) -> i32 {
|
|
22
27
|
match self {
|
|
23
28
|
TokenFoldError::InvalidInput(_) => 2,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
//!
|
|
2
|
-
//!
|
|
1
|
+
//! Declarative command-output filter registry: the filter-pack schema, its stage-execution
|
|
2
|
+
//! engine, and the trust store that gates project- and user-authored packs.
|
|
3
3
|
//!
|
|
4
4
|
//! Filter packs are TOML documents describing an ordered list of pure text-transform "stages"
|
|
5
5
|
//! (`strip_ansi`, `replace`, `keep_lines`, `strip_lines`, `head`, `tail`, `max_lines`,
|
|
@@ -218,7 +218,7 @@ impl FixtureCheck {
|
|
|
218
218
|
}
|
|
219
219
|
|
|
220
220
|
// ---------------------------------------------------------------------------------------------
|
|
221
|
-
// Regex complexity guard (
|
|
221
|
+
// Regex complexity guard (defense-in-depth against hostile filter patterns; see module doc)
|
|
222
222
|
// ---------------------------------------------------------------------------------------------
|
|
223
223
|
|
|
224
224
|
fn check_pattern_safety(pattern: &str) -> Result<(), TokenFoldError> {
|
|
@@ -407,7 +407,7 @@ pub fn never_worse(raw: &[u8], filtered: &[u8]) -> NeverWorseOutcome {
|
|
|
407
407
|
}
|
|
408
408
|
|
|
409
409
|
// ---------------------------------------------------------------------------------------------
|
|
410
|
-
// Trust store
|
|
410
|
+
// Trust store
|
|
411
411
|
// ---------------------------------------------------------------------------------------------
|
|
412
412
|
|
|
413
413
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
|
@@ -541,7 +541,7 @@ pub struct FilterLookup<'a> {
|
|
|
541
541
|
pub project_filters_path: Option<&'a Path>,
|
|
542
542
|
pub user_filters_path: Option<&'a Path>,
|
|
543
543
|
pub trust_store_path: &'a Path,
|
|
544
|
-
/// `TOKENFOLD_TRUST_PROJECT_FILTERS=1
|
|
544
|
+
/// `TOKENFOLD_TRUST_PROJECT_FILTERS=1`: bypasses the trust-store check
|
|
545
545
|
/// for the *project* tier only (its literal name is the documented CI override, not a
|
|
546
546
|
/// generic "trust everything" switch) — user-tier filters always require an explicit
|
|
547
547
|
/// `filters trust` regardless of this flag.
|
|
@@ -642,10 +642,10 @@ pub fn parse_pack_file(path: &Path) -> Result<FilterPack, TokenFoldError> {
|
|
|
642
642
|
}
|
|
643
643
|
|
|
644
644
|
// ---------------------------------------------------------------------------------------------
|
|
645
|
-
// Built-ins (
|
|
645
|
+
// Built-ins (solo-dogfooding scope: git diff, git status, cargo build/test log framing)
|
|
646
646
|
// ---------------------------------------------------------------------------------------------
|
|
647
647
|
|
|
648
|
-
///
|
|
648
|
+
/// This project's first consumer is solo dogfooding (git diffs, build/test logs, agent
|
|
649
649
|
/// tool-call JSON) — these three built-ins deliberately cover only that, not a broad command
|
|
650
650
|
/// library. Encoded as Rust struct literals rather than parsed TOML strings: for packs this
|
|
651
651
|
/// small, embedding multi-line fixture text in Rust raw strings and building the structs
|
|
@@ -785,7 +785,7 @@ fn build_test_log_pack() -> FilterPack {
|
|
|
785
785
|
version: "1.0.0".to_string(),
|
|
786
786
|
},
|
|
787
787
|
filters: vec![Filter {
|
|
788
|
-
// Generic cargo build/test log filter (
|
|
788
|
+
// Generic cargo build/test log filter (dogfooding scope: this repo's own
|
|
789
789
|
// `cargo test`/`cargo build`); `match_command = ["cargo"]` fires on any cargo
|
|
790
790
|
// subcommand rather than one filter per subcommand, keeping this a single built-in.
|
|
791
791
|
id: "cargo-build-test-log".to_string(),
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
//! cannot be disabled (see `budget::CompressionPolicyBuilder::build`).
|
|
5
5
|
//!
|
|
6
6
|
//! `tests/fixtures/mode_matrix.toml` mirrors this table for cross-surface testing
|
|
7
|
-
//! (
|
|
7
|
+
//! (this table is authoritative; the fixture must be kept in sync with it).
|
|
8
8
|
|
|
9
9
|
use crate::budget::{CompressionMode, TaskScope};
|
|
10
10
|
use crate::input::InputFormat;
|
|
@@ -71,12 +71,12 @@ impl ModeEntry {
|
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
// Canonical ordered table — order here IS the pipeline execution order (
|
|
75
|
-
//
|
|
74
|
+
// Canonical ordered table — order here IS the pipeline execution order (lossless before lossy,
|
|
75
|
+
// higher-savings before lower-savings, within each mode).
|
|
76
76
|
//
|
|
77
|
-
// ponytail: `table_compaction` is intentionally omitted.
|
|
78
|
-
//
|
|
79
|
-
//
|
|
77
|
+
// ponytail: `table_compaction` is intentionally omitted. Tabular payloads aren't among this
|
|
78
|
+
// project's dominant input types, so a table transform stays out of scope until a real consumer
|
|
79
|
+
// asks for it.
|
|
80
80
|
pub static ALL_ENTRIES: &[ModeEntry] = &[
|
|
81
81
|
ModeEntry {
|
|
82
82
|
transform_id: TransformId::JsonMinify,
|
|
@@ -164,11 +164,11 @@ pub static ALL_ENTRIES: &[ModeEntry] = &[
|
|
|
164
164
|
ModeEntry {
|
|
165
165
|
transform_id: TransformId::LogCompaction,
|
|
166
166
|
version: "1.0.0",
|
|
167
|
-
// Promoted out of --experimental (
|
|
168
|
-
// full-lossy-promotion
|
|
167
|
+
// Promoted out of --experimental (Phase 5 fidelity gate, 2026-07-12): the
|
|
168
|
+
// full-lossy-promotion gate profile clears every draft fidelity threshold cleanly
|
|
169
169
|
// (quality_retention=1.0, contrastive_failure_rate=0.0, critical_token_survival_rate=1.0).
|
|
170
|
-
// conservative_enabled stays false —
|
|
171
|
-
//
|
|
170
|
+
// conservative_enabled stays false — Conservative never runs lossy-with-evidence
|
|
171
|
+
// transforms at all, same convention table_compaction documents.
|
|
172
172
|
conservative_enabled: false,
|
|
173
173
|
balanced_enabled: true,
|
|
174
174
|
aggressive_enabled: true,
|
|
@@ -182,12 +182,14 @@ pub static ALL_ENTRIES: &[ModeEntry] = &[
|
|
|
182
182
|
ModeEntry {
|
|
183
183
|
transform_id: TransformId::DiffCompaction,
|
|
184
184
|
version: "1.0.0",
|
|
185
|
-
// Stays --experimental (
|
|
185
|
+
// Stays --experimental (Phase 5 fidelity gate, 2026-07-12 re-investigation): the
|
|
186
186
|
// full-lossy-promotion gate's per_variant breakdown checked the default (body-preserving,
|
|
187
187
|
// task_scope != ChangeSummary) and header-only (TaskScope::ChangeSummary) forms
|
|
188
|
-
// separately, as
|
|
189
|
-
//
|
|
190
|
-
// 0.
|
|
188
|
+
// separately, as diff_compaction's two documented forms require, and BOTH miss the draft
|
|
189
|
+
// fidelity thresholds on their own — the bar is quality_retention >= 0.95,
|
|
190
|
+
// contrastive_failure_rate <= 0.005, critical_token_survival >= 0.99, and the default form
|
|
191
|
+
// measured quality_retention=0.36, contrastive_failure_rate=0.5, critical_token_survival=
|
|
192
|
+
// 0.5. Root cause: compact_diff has no fallback for non-diff-shaped input — it drops
|
|
191
193
|
// everything, critical tokens included, when no line matches a unified-diff prefix. See
|
|
192
194
|
// eval/tasks/FIXTURES.md's "Scorer status" section for the full measured breakdown.
|
|
193
195
|
conservative_enabled: false,
|
|
@@ -205,7 +207,7 @@ pub static ALL_ENTRIES: &[ModeEntry] = &[
|
|
|
205
207
|
],
|
|
206
208
|
},
|
|
207
209
|
// v0.2+ entries (table_compaction, prose_extraction, code_digest, conversation) added
|
|
208
|
-
// here after their fidelity approval /
|
|
210
|
+
// here after their fidelity approval / scope decisions land.
|
|
209
211
|
];
|
|
210
212
|
|
|
211
213
|
/// Returns the ordered, applicable transform list for a given (mode, task_scope, format).
|