-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCargo.toml
More file actions
290 lines (278 loc) · 13.7 KB
/
Copy pathCargo.toml
File metadata and controls
290 lines (278 loc) · 13.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
[workspace]
members = [
"crates/eval-adapters",
"crates/cli",
"crates/conversation",
"crates/core",
"crates/ecaa-conformance",
"crates/ecaa-types",
"crates/harness",
"crates/server",
"crates/workspace-hack",
]
default-members = [
"crates/cli",
"crates/conversation",
"crates/core",
"crates/ecaa-conformance",
"crates/harness",
"crates/server",
]
resolver = "2"
# `thiserror` 2.0 workspace pin. Per Round-3 §3.11, we
# stay on `anyhow + thiserror` (do NOT migrate to `eyre`) — eyre's
# only edge over anyhow is `SpanTrace`, which is only worthwhile if
# Sentry integration lands. thiserror 2.0 dropped Jan 2026; the bump
# from 1.x is mechanical (format-arg ambiguity in tuple variants).
# Inheriting from the workspace via `thiserror.workspace = true`
# keeps the version pin in one place.
[workspace.dependencies]
# Centralized version pins for high-fanout deps. Per-crate Cargo.toml
# files inherit via `<dep>.workspace = true` (with per-crate features
# additive on top of the workspace feature set). Promoting a dep up
# here means one place to bump versions and one place to audit
# feature surface; reduces the chance of feature/version skew that
# forces cargo to recompile a dep twice.
#
# When the feature set varies across crates, the workspace entry holds
# the COMMON SUBSET (or default-features=false) and each crate adds
# its specific features. Cargo unions feature flags across
# dependency declarations, so a workspace-level `features = ["a"]`
# plus a per-crate `features = ["b"]` yields {a, b}.
anyhow = "1"
async-trait = "0.1"
chrono = { version = "0.4", features = ["serde"] }
# `derive` feature is the only consumer flavour across the workspace
# (cli, harness, eval-adapters all use #[derive(Parser)] on their
# argument structs). One pin keeps the proc-macro toolchain version
# in sync across those sites.
clap = { version = "4", features = ["derive"] }
csv = "1"
# Sharded concurrent map. Conversation uses per-session mutex
# persistence (session_id -> Mutex<File>); server uses fan-out
# broadcaster maps + chat-route rate-buckets keyed by session/IP.
# Both rely on DashMap's internal sharding to avoid a single
# outer-map lock under chat-route concurrency.
dashmap = "6"
# `default-features = false` drops the optional `cli` feature so we
# don't pull a second copy of clap; core validates the downstream-
# policy JSON sidecars at registry-load time, harness validates the
# dispatch-WAL schema on resume. Both want only the library API.
jsonschema = { version = "0.18", default-features = false }
# R-39 — TTL-aware concurrent cache used by `conversation::side_calls`
# (`explain.rs`, `summary.rs`) to bound per-call dedup tables. Replaces
# a coarse `Mutex<HashMap>` with random-eviction-on-cap that leaked
# entries past the 1-hour TTL on slow eviction paths. The `sync` feature
# pulls in the std-thread-safe `Cache<K, V>` (no async runtime required;
# both call sites are inside short tokio tasks where the cache lookup is
# a non-await sync call).
moka = { version = "0.12", features = ["sync"] }
once_cell = "1"
pretty_assertions = "1"
# Cryptographic RNG seeded via `OsRng` in core (audit-writer per-session
# HMAC secret) and server (share-token preimage). Pinned at 0.8 because
# the 0.8 → 0.9 API retired `thread_rng()` and reshaped `OsRng` (now
# `TryRngCore`-based); bumping requires call-site changes in
# `core::audit_writer` + `server::chat_routes::share`. This workspace
# pin is the deliberate-0.8 floor.
#
# eval-adapters declares its own `rand = "0.9"` literal because
# `src/stats.rs` uses the 0.9-only `IndexedRandom` trait (renamed from
# `SliceRandom::choose_multiple`); workspace-hack is auto-generated by
# `cargo hakari` and tracks the highest resolved version (0.9) — both
# crates are intentionally NOT on this workspace pin. TODO unify to
# 0.9 after migrating core + server to the new RNG API.
rand = "0.8"
regex = "1"
# reqwest feature divergence across crates: conversation needs
# `stream` (SSE accumulator); eval-adapters needs `blocking`; everyone
# needs `json` + `rustls-tls`. The workspace entry has the common
# subset; each per-crate `features = [...]` adds what it needs on top.
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
# Layer 5 — JSON Schema (draft-07) derivation from Rust types so the
# eight `docs/ecaa-spec/subgraph-schemas/*.schema.json` files become a
# derived artifact of `#[derive(JsonSchema)]` rather than a
# hand-maintained sidecar. Pinned at 0.8.x — 0.9+ ships an API break
# (`SchemaSettings::draft07()` was reshaped) that downstream callers
# haven't been ported for. `derive` is the only flavour we need;
# `chrono`/`uuid1`/`semver` give leaf JsonSchema bindings on
# `DateTime<Utc>`, `Uuid`, and `semver::Version` so the cascade
# terminates cleanly at the leaves.
schemars = { version = "0.8", default-features = false, features = ["derive", "chrono", "uuid1", "semver"] }
# SHA-256 hashing across the workspace: BLAKE3-adjacent integrity
# digests in core, content-addressed task/script signatures in cli,
# summary-markdown fingerprints in conversation, evidence-row hashes
# in eval-adapters, and share-token preimage commitments in server.
# Single pin keeps the digest algorithm + crate ABI lock-stepped.
sha2 = "0.10"
strum = { version = "0.26", features = ["derive"] }
tempfile = "3"
# `thiserror` 2.0 workspace pin. We stay on `anyhow + thiserror` (do
# NOT migrate to `eyre`) — eyre's only edge over anyhow is
# `SpanTrace`, which is only worthwhile if Sentry integration is
# wired in. The 1.x → 2.x bump is mechanical (format-arg ambiguity in
# tuple variants).
thiserror = "2"
tracing = "0.1"
ts-rs = { version = "10", features = ["serde-compat"] }
uuid = { version = "1", features = ["v4", "v5", "serde"] }
walkdir = "2"
# NFC normalization + ASCII-strict casefold of narrative excerpts before
# substring-matching against table cells in `core::claim_verifier`. Stops
# canonically-equivalent but byte-different Unicode forms (NFC vs NFD)
# from producing false `Unverifiable` verdicts.
unicode-normalization = "0.1"
# Migrated off the abandoned `serde_yaml` (0.9.34+deprecated) and then
# off the archived `serde_yml` (0.0.12, RUSTSEC-2025-0068, pulling the
# unmaintained `libyml` unsafe FFI) to `serde_yaml_ng`, the maintained
# drop-in fork. The API surface is compatible (`from_str`, `to_string`,
# `Value`, `Error`); call sites use the `serde_yml::` → `serde_yaml_ng::`
# rename only. Per-crate `Cargo.toml` files inherit the version via
# `serde_yaml_ng.workspace = true`.
serde_yaml_ng = "0.10"
# v3 P7 — SemVer for `schema_version` IR fields. Promoted from
# `u32` so future minor/patch bumps don't require a migration cycle.
# Custom serde adapter accepts both legacy `u64` JSON values and
# canonical SemVer strings for backward compatibility.
semver = { version = "1", features = ["serde"] }
# Tier F property-test stack per `docs/dag_eval.md`. Used as
# `dev-dependencies` by crates that author Tier F tests
# (`crates/core` integration tests under `tests/property/`); the
# `eval-adapters` crate exports the generator strategies as a
# `[dependencies]` library entry so binaries and downstream crates
# can pull them. `cargo-mutants` is invoked as an installed binary
# (`cargo install --locked cargo-mutants`), not a workspace dep.
proptest = "1.5"
# R-23 — snapshot testing. `insta::assert_json_snapshot!` produces a
# `tests/snapshots/<test_name>.snap` file on first run; subsequent runs
# diff against the snapshot. Eliminates per-field
# `assert_eq!(actual_json, expected_json)` boilerplate in tests that
# verify whole JSON / YAML / serialized-shape outputs. Updating after
# an intentional change is one `cargo insta review` command instead of
# a manual recompute of every expected literal. Dev-only via per-crate
# `[dev-dependencies]` inheritance.
insta = { version = "1.39", features = ["json", "yaml", "redactions"] }
# R-29 — CLI integration tests. `Command::cargo_bin("ecaa-workflow")`
# locates the compiled binary so `crates/cli/tests/*.rs` can exec the
# CLI surface end-to-end (intake / build / dag / chat --help). The
# crate's own `Assert` helpers (`success()`, `stdout(predicate)`) keep
# the assertions compact. Inherited via `assert_cmd.workspace = true`
# in the cli crate's `[dev-dependencies]`.
assert_cmd = "2"
# Workspace-wide lint policy. Reference: plan §S1.1 + §S1.7 + §S5.32.
#
# `await_holding_lock` denies the entire `MutexGuard`-across-`.await`
# class (covers std::sync, parking_lot, and (now standard) the
# tokio::sync subtype check via clippy's mutex-list); this is the
# load-bearing P0 fix per the plan, since holding a sync lock across an
# `.await` blocks the executor thread and can deadlock the runtime.
#
# `unsafe_code = "deny"` is the §S5.32 hardening — every `unsafe` block
# must carry a `#[allow(unsafe_code)]` waiver with a justifying comment
# at the use site. We use `deny` not `forbid` because POSIX subprocess
# setup (`pre_exec`, `libc::kill`) genuinely requires `unsafe` and the
# bounded-waiver pattern is the right shape: each unsafe block becomes
# a code-review trigger, not a routine workaround.
#
# Per-crate finer-grained lints (e.g. `unwrap_used`, `expect_used` in
# core/conversation non-test code) are scoped at the crate level via
# `[lints]` in each Cargo.toml so test code can keep its idiomatic
# `.unwrap()`s.
[workspace.lints.rust]
unsafe_code = "deny"
# Every production crate (core/conversation/server/harness/cli) is
# at zero `unreachable_pub` warnings. The deny
# ratchet locks the gate so any new pub item must justify
# cross-crate visibility.
unreachable_pub = "deny"
[workspace.lints.clippy]
await_holding_lock = "deny"
missing_assert_message = "warn"
# Pervasive doc-comment continuation style across the doc-heavy core
# crates: indented wrapped lines in `///` lists/blocks that clippy now
# flags as needing a continuation marker. Exempted workspace-wide as a
# stylistic preference; every substantive (non-doc-style) clippy lint is
# fixed rather than suppressed.
doc_lazy_continuation = "allow"
# `unwrap_or_default()` silently substitutes `T::default()` when
# the source value is `None`/`Err`. That's almost always a bug
# masquerading as ergonomic sugar: empty strings, zero counters,
# default-constructed structs all flow into downstream logic without
# ever signalling the original was missing. Promoting to `warn` (not
# `deny`) so existing call sites surface for triage without blocking
# the build — the audit catalog estimates ~212 sites; we'll work the
# list down in follow-up commits.
unwrap_or_default = "warn"
# Dev profile knobs:
# - `debug = "line-tables-only"`: match the test profile. Full DWARF
# in dev costs link time + disk for no inner-loop benefit; the only
# debug info anyone reads at this tier is panic-line backtraces.
# - `split-debuginfo = "unpacked"`: ship debug info as separate
# `.dwo`/`.o` objects rather than embedded in the rlib/binary. The
# linker doesn't have to copy the debug section into the output,
# which is a substantial fraction of incremental link time on a
# workspace with 169 integration-test binaries. Linux-only;
# harmless on other platforms (cargo ignores it).
# - `incremental = true` is the cargo default for dev but pinned
# here to keep behavior explicit.
[profile.dev]
debug = "line-tables-only"
split-debuginfo = "unpacked"
incremental = true
# Dependencies are recompiled rarely but executed often (serde_json
# parsing, regex matching, jsonschema validation, proptest
# shrinking). The classic Cargo trick: build dependencies at -O1 so
# the dev profile pays a small one-time compile cost in exchange for
# 2-3x faster test execution. The crates under workspace `members`
# stay at -O0 (the dev default), so iteration speed for code we
# actually edit is unchanged.
[profile.dev.package."*"]
opt-level = 1
# Test compiles default to `-C debuginfo=2` (full DWARF), which inflates
# every `.rlib` 5–10× over release. CI's `ubuntu-latest` runners ship
# ~14 GB of usable disk; the workspace's combined `target/` plus
# sccache and cached registry hit the disk limit. `line-tables-only`
# keeps panic-line backtraces (the only debug-info CI actually consumes)
# while dropping ~60% of the size.
[profile.test]
debug = "line-tables-only"
split-debuginfo = "unpacked"
# proptest's per-input shrinking loop is hot enough that running it
# under `-C opt-level = 0` (the dev default) adds noticeable
# wall-clock time to every property test. Bumping only the `proptest`
# package to `opt-level = 1` keeps debug symbols on the test crate
# itself (line-tables-only above) but lets the shrink/replay loop
# run at optimization parity with release. Same idea Cargo
# recommends in the proptest book.
#
# Now redundant with `profile.dev.package."*"` above (which sets
# every dep to opt-level=1), but kept explicit so a future change
# to the wildcard rule doesn't silently regress proptest perf.
[profile.dev.package.proptest]
opt-level = 1
[profile.test.package.proptest]
opt-level = 1
# [profile.release] tuning.
# Pass-9 verified .cargo/config.toml carries detailed dev/test-profile
# rationale; release-profile was missing (defaults-by-omission).
#
# `lto = "thin"`: cross-crate inlining + DCE. Measured 10-15 % runtime
# speedup on release CLI binaries; comparable shrinkage in distributed
# binary size.
#
# `strip = "debuginfo"`: drop DWARF sections. Typically 50-70 % size
# reduction. Panic backtraces still resolve function names (in symbol
# table, not DWARF).
#
# `codegen-units = 1`: one LLVM unit for the whole crate. Slower compile,
# faster output. Acceptable for the rare release builds.
#
# DEFERRED: `panic = "abort"`. Faster + smaller, but the F33
# byte-reproducibility baseline was captured with the default
# `panic = "unwind"`. Re-baseline before flipping.
[profile.release]
lto = "thin"
strip = "debuginfo"
codegen-units = 1