You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This commit was created on GitHub.com and signed with GitHub’s verified signature.
Changed
Index-time embedding now batches chunks through try_embed_batch (#38). The store build
path used to embed one chunk per call — one HTTP request per chunk on the Ollama backend, so a
repo with tens of thousands of chunks cost tens of thousands of sequential round-trips. Chunks
are now embedded in bounded batches of EMBED_BATCH_SIZE (64, pinned in src/config.rs), so
indexing issues ceil(chunks / 64) requests instead of one per chunk (measured on a 300-file /
600-chunk synthetic repo against a 10 ms-latency stub: 601 → 11 requests, ~10.2 s → ~0.2 s).
The fail-loud policy (#30) holds at batch granularity: a failed or count-mismatched batch aborts
the index naming the batch's file span, and nothing is persisted — never empty or misaligned
vectors. The hash embedder is untouched (its default batch impl maps the same pure per-text
embed over each batch), so all goldens and conformance.json are byte-identical.
Fixed
The chunkers survive pathologically nested input — iterative tree walks, no SIGSEGV (#49).
A property-suite CI run died with SIGSEGV before proptest could persist the failing seed. Two
crash classes were reproduced deterministically and fixed. (1) The code and markdown chunkers'
per-node recursive AST walks (collect_chunks, visit_pre, the heading/inline walks)
overflowed the thread stack on deeply nested input — measured crash at depth ~219 on a 256 KiB
stack and ~875–1748 (grammar-dependent) at the 2 MiB Rust test-thread default, while tree-sitter
itself parses the same input fine at depth 500k. All walks are now iterative TreeCursor
loops with identical pre-order emission, so chunk output is byte-identical for every input.
(2) tree-sitter-md's external scanner serializes its open-block stack into tree-sitter's fixed
1024-byte buffer without a bounds check: ~255 simultaneously open blocks (e.g. one line of
255 > characters) is an assert-abort in debug and a buffer overrun (SIGSEGV) in release,
independent of stack size and uncatchable from Rust. chunk_markdown now computes a conservative
per-line upper bound on open-block depth before parsing and degrades estimated-deeper-than-192
input to the existing deterministic whole-doc fallback chunk — fail-safe, never crash. A
deterministic regression suite (tests/deep_nesting.rs) chunks nesting just under and far past
the old thresholds on a 256 KiB thread, and each chunker property case now runs on a 16 MiB
thread so any future crash becomes a persistable proptest counterexample instead of a process
kill. All goldens and conformance.json are byte-identical.
cce search --workspace --package "" now errors loudly instead of silently returning no
results (#45). An empty-but-present --package value ("", ",", whitespace — e.g. an unset
shell variable in --package "$PKG") used to parse to an empty scope, federate over zero members,
and print nothing, bypassing the #26 unknown-token error. parse_scope now lives in cce::federation and rejects a scope with no usable token with an actionable message
(--package requires at least one member or package name (e.g. --package app,billing)); the MCP context_searchpackage argument goes through the same parser, so {"package": ""} gets the
same friendly guidance instead of silent no-results. Valid scopes are byte-identical.
Added
Binary-level error-path tests: corrupt store, malformed manifest, garbage remote listing,
dashboard CLI (#37). Four real-world corruption scenarios are now pinned by driving the real cce binary: a truncated-JSON or binary-junk store makes search/stats exit non-zero with the
friendly could not load store … message (never a panic); a syntactically broken .cce/workspace.yml surfaces invalid workspace.yml: … from search --workspace and stats --workspace; non-artifact entries in a sync remote's ref listing are skipped gracefully
by SyncRemote::list (unit-level — no CLI command reaches the listing parser today); and cce dashboard --port 0 --no-open (plus the --workspace variant) binds an ephemeral loopback
port, prints the URL, and answers /api/health with 200 + valid JSON. Test-only — no behavior
change.
Tests for src/main.rs and a byte-pinned search --json golden (#32). The CLI entry point
(~1,300 lines) previously had zero tests. It now has a unit suite pinning current behavior of the
pure helpers — parse_scope comma/whitespace/empty-segment edges, resolve_read_store / resolve_metrics_path / metrics_beside_store precedence (explicit --metrics wins, else beside
the resolved --store, else <root>/.cce/metrics.jsonl) — plus byte-pinned goldens for the
script-facing results_json / fed_results_json shapes (field order, 6-decimal string scores
incl. round-half-away-from-zero, query_id: null when metrics are off, trailing newline), and a
binary-level tests/cli.rs test pinning the parsed --json field set. Test-only — no behavior
change; all existing goldens and conformance.json unchanged.
Automated, tag-driven releases. Pushing a vX.Y.Z tag now re-runs every CI gate on the tagged
commit, verifies the tag matches Cargo.toml and that this file has a matching section, builds
release binaries for macOS (arm64/x86_64) and Linux (x86_64/arm64), and publishes a GitHub Release
with this file's section as the notes plus a SHA256SUMS. Process documented in RELEASING.md;
README gains a prebuilt-binary install path. (Repo infrastructure — the cce binary is unchanged.)
Property-based tests for the chunkers and the pinned token rule (#33). A new proptest suite
(tests/property_chunkers.rs) generates adversarial-but-legal source for all six language packs
(unicode identifiers, CRLF line endings, trailing whitespace, missing final newline, empty and
comment-only files, deeply nested definitions, raw printable-unicode garbage) and markdown
(ATX/setext headings, preambles, fenced code blocks containing # lines, varied split budgets),
and asserts the chunkers' documented invariants on every input: in-bounds ordered line ranges,
content as an exact byte slice of the input, pre-order nested-or-disjoint emission, determinism, chunk_id recomputable from the persisted fields, the pinned max(1, floor(bytes/4)) token rule,
and markdown section ordering/coverage. Test-only: goldens, conformance.json, and the cce
binary are unchanged.
Documentation
v2.6 documentation sweep (#34). Re-ran the gapless-docs discipline (#11, last executed at
v2.5.5) over the v2.6.0–v2.6.7 surface. The knowledge track (cce knowledge index, the cce.knowledge/v1 contract, the context_searchsource: code|knowledge|both blend, provenance +
staleness weighting, the knowledge.* config keys) now appears in docs/knowledge.md (M4 section), docs/mcp.md (the source schema property), the README, and the getting-started/how-to/
how-it-works/architecture cross-references; the v2.6.3 gitignore-aware walker (committed .gitignore only — builder independence) is documented in the README, guides, architecture, and
sync's rationale; docs/sync.md states that push always rebuilds from source (v2.6.2); docs/workspace.md + docs/architecture.md carry the v2.6.4 --package semantics (name or package: field, loud error with the available list) and the v2.6.7 MCP caching instead of the
stale "reloaded per query" claim. Stale pins fixed: cce 2.5.5 / --tag v2.3.0/v2.4.0 examples,
the retired built_at CI comment, the --top-k default (10, not 5), and the 416/500 test counts
(now 540); the Cargo.toml description extends through v2.6 (metadata only). Docs-only — no engine
change; conformance.json and all goldens are byte-identical.