Repository navigation
feat(telemetry): tunable chars-per-token divisor for composition estimate (default 3.5) - #23
Merged
Merged
Conversation
…mate (default 3.5) The /context /usage /compress composition estimate used a flat char/4 rule, which systematically UNDER-counts real Hermes requests (dominated by JSON/code- dense tool results that tokenize closer to ~3.5 chars/token). Measured against live data the delta-vs-measured ran -8% at 170k context and -15% at 280k. Switches the divisor to 3.5 (tightens the live band to ~+-5% / -3.2% at 280k) and makes it tunable via env HERMES_COMPOSITION_CHARS_PER_TOKEN, clamped to a 2.0-8.0 sane range so a typo cannot make the estimate absurd. Only affects the DISPLAYED composition estimate -- never billing, the provider prompt_tokens (Measured occupancy), or compression-pressure decisions (those keep the conservative /4 estimate_request_tokens_rough so Hermes still compresses before a provider rejects the payload). 3 new tests: default-3.5, env override (and 3.5>4.0 ordering), out-of-range fallback. User-facing "char/4" labels -> "char-based estimate" so wording survives future tuning. 13/13 pass, ruff clean.
🔎 Lint report:
|
Kyzcreig
added a commit
that referenced
this pull request
Jun 9, 2026
…24) PR #23 made the /context /usage /compress composition estimate use the tunable COMPOSITION_CHARS_PER_TOKEN (default 3.5), but the three shared rough estimators (estimate_tokens_rough / estimate_messages_tokens_rough / estimate_request_tokens_rough) still hardcoded char/4. Per Ace: use one variable, 3.5, for everything -- including compression-pressure / pre-flight 413 checks. Adds a single shared _ceil_chars_to_tokens(chars) helper and routes all four //4 sites + compose_request_breakdown._t() through it. char/3.5 estimates HIGHER than char/4, so compression and pre-flight oversize checks fire SOONER, never later -- strictly safer for context-overrun protection, and Ace already runs conservative compression params. Still only a char-based heuristic; the real provider prompt_tokens remains the source of truth for billing/occupancy. Tests updated to the 3.5 divisor (divisor-derived via math.ceil(n/3.5) rather than fresh magic numbers so they survive future tuning). 201 pass, ruff clean. Co-authored-by: Apollo <apollo@daemonarchy.local>
ang-fleet-workers Bot
added a commit
that referenced
this pull request
Sep 27, 2026
- kanban_db #23: the in-txn takeover audit fires only when the txn changed the target card's guarded columns (status/assignee/priority/session_id), not on any side write (reclaim_refused), so a refused mutation never records or re-homes. No longer reads conn.total_changes (fixes write_txn_busy_retry fakes, CI slice 13). - kanban_db #44: birth home re-resolved at the TOP of the write txn, before the duplicate / parent checks. - kanban_db #70: no own-claim exception by profile name; without a run id only a lapsed run (claim expired, no live owner) can be closed. - checkout_admission #52: read-check-replace under a per-consumer flock. - discord #30/#31: cancellation recorded before fut.done(); a cancelled disconnect waits for the in-flight flush and still runs every flush. - run.py #36: lock held until the worker write finishes on cancel; every write runs in FIFO order (no skipped-but-reported resets). - ci_overflow_integration #27: documented + tested that a secondary-limit 403 arrives as RateLimited(429) and fails closed. New tests, each red against the previous commit.
ang-fleet-workers Bot
added a commit
that referenced
this pull request
Sep 27, 2026
…iew send-back re-checked under the lock - #23 (PR951): the takeover/override event and comment are written in the guarded mutator's own write txn (only when it changed rows), so a failed audit rolls the mutation back; the chat subscription stays post-commit. - #44 (PR987): create_task re-resolves the parent home inside its write_txn. - #70 (PR1081): request_changes with a claimer and no expected_run_id refuses to close another holder's live review run (unexpired claim or live owner). Tests red on base: test_takeover_audit_is_in_the_mutators_txn, test_parent_rehomed_before_child_insert_is_the_childs_home, test_claimer_without_run_id_cannot_close_another_reviewers_live_run.
ang-fleet-workers Bot
added a commit
that referenced
this pull request
Sep 27, 2026
- kanban_db #23: the in-txn takeover audit fires only when the txn changed the target card's guarded columns (status/assignee/priority/session_id), not on any side write (reclaim_refused), so a refused mutation never records or re-homes. No longer reads conn.total_changes (fixes write_txn_busy_retry fakes, CI slice 13). - kanban_db #44: birth home re-resolved at the TOP of the write txn, before the duplicate / parent checks. - kanban_db #70: no own-claim exception by profile name; without a run id only a lapsed run (claim expired, no live owner) can be closed. - checkout_admission #52: read-check-replace under a per-consumer flock. - discord #30/#31: cancellation recorded before fut.done(); a cancelled disconnect waits for the in-flight flush and still runs every flush. - run.py #36: lock held until the worker write finishes on cancel; every write runs in FIFO order (no skipped-but-reported resets). - ci_overflow_integration #27: documented + tested that a secondary-limit 403 arrives as RateLimited(429) and fails closed. New tests, each red against the previous commit.
ang-fleet-workers Bot
added a commit
that referenced
this pull request
Sep 27, 2026
…iew send-back re-checked under the lock - #23 (PR951): the takeover/override event and comment are written in the guarded mutator's own write txn (only when it changed rows), so a failed audit rolls the mutation back; the chat subscription stays post-commit. - #44 (PR987): create_task re-resolves the parent home inside its write_txn. - #70 (PR1081): request_changes with a claimer and no expected_run_id refuses to close another holder's live review run (unexpired claim or live owner). Tests red on base: test_takeover_audit_is_in_the_mutators_txn, test_parent_rehomed_before_child_insert_is_the_childs_home, test_claimer_without_run_id_cannot_close_another_reviewers_live_run.
ang-fleet-workers Bot
added a commit
that referenced
this pull request
Sep 27, 2026
- kanban_db #23: the in-txn takeover audit fires only when the txn changed the target card's guarded columns (status/assignee/priority/session_id), not on any side write (reclaim_refused), so a refused mutation never records or re-homes. No longer reads conn.total_changes (fixes write_txn_busy_retry fakes, CI slice 13). - kanban_db #44: birth home re-resolved at the TOP of the write txn, before the duplicate / parent checks. - kanban_db #70: no own-claim exception by profile name; without a run id only a lapsed run (claim expired, no live owner) can be closed. - checkout_admission #52: read-check-replace under a per-consumer flock. - discord #30/#31: cancellation recorded before fut.done(); a cancelled disconnect waits for the in-flight flush and still runs every flush. - run.py #36: lock held until the worker write finishes on cancel; every write runs in FIFO order (no skipped-but-reported resets). - ci_overflow_integration #27: documented + tested that a secondary-limit 403 arrives as RateLimited(429) and fails closed. New tests, each red against the previous commit.
ang-fleet-workers Bot
added a commit
that referenced
this pull request
Sep 28, 2026
…iew send-back re-checked under the lock - #23 (PR951): the takeover/override event and comment are written in the guarded mutator's own write txn (only when it changed rows), so a failed audit rolls the mutation back; the chat subscription stays post-commit. - #44 (PR987): create_task re-resolves the parent home inside its write_txn. - #70 (PR1081): request_changes with a claimer and no expected_run_id refuses to close another holder's live review run (unexpired claim or live owner). Tests red on base: test_takeover_audit_is_in_the_mutators_txn, test_parent_rehomed_before_child_insert_is_the_childs_home, test_claimer_without_run_id_cannot_close_another_reviewers_live_run.
ang-fleet-workers Bot
added a commit
that referenced
this pull request
Sep 28, 2026
- kanban_db #23: the in-txn takeover audit fires only when the txn changed the target card's guarded columns (status/assignee/priority/session_id), not on any side write (reclaim_refused), so a refused mutation never records or re-homes. No longer reads conn.total_changes (fixes write_txn_busy_retry fakes, CI slice 13). - kanban_db #44: birth home re-resolved at the TOP of the write txn, before the duplicate / parent checks. - kanban_db #70: no own-claim exception by profile name; without a run id only a lapsed run (claim expired, no live owner) can be closed. - checkout_admission #52: read-check-replace under a per-consumer flock. - discord #30/#31: cancellation recorded before fut.done(); a cancelled disconnect waits for the in-flight flush and still runs every flush. - run.py #36: lock held until the worker write finishes on cancel; every write runs in FIFO order (no skipped-but-reported resets). - ci_overflow_integration #27: documented + tested that a secondary-limit 403 arrives as RateLimited(429) and fails closed. New tests, each red against the previous commit.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Makes the chars-per-token divisor used by the request-composition estimate (
/context,/usage,/compress) 3.5 by default (was a flat4), and tunable via envHERMES_COMPOSITION_CHARS_PER_TOKEN(clamped to a sane2.0–8.0range; malformed/out-of-range values fall back to the default).Why
The composition snapshot (PR #21) estimated each bucket at char/4. The classic ~4 chars/token rule is tuned for English prose, but real Hermes requests are dominated by JSON/code-dense tool results that tokenize closer to ~3.5 chars/token — so char/4 systematically under-counts, and the bias grows with the JSON-dense fraction. Measured against live data (this fleet's Discord channel):
Switching to 3.5 tightens the same turns to −1.2% / −3.2% / −3.2% — roughly ±5% across 170k–280k, vs the lopsided −15% before. (Validated 3.5-for-all-buckets against 9 live turns; it beats both flat /4 and a tool-only 3.5 split, and it's one knob instead of two.)
How
agent/model_metadata.py: new module constantCOMPOSITION_CHARS_PER_TOKEN(default3.5), read once at import fromHERMES_COMPOSITION_CHARS_PER_TOKENwith a2.0–8.0clamp and graceful fallback.compose_request_breakdown's internal_t()now ceiling-divides by it.prompt_tokens(the separate "Measured occupancy" line), or compression-pressure decisions — those keep the deliberately-conservative char/4estimate_request_tokens_roughso Hermes still compresses before a provider rejects an oversized payload.locales/en.yaml:/usagecomp_header"char/4 estimate" → "char-based estimate" so the wording survives future tuning.Verification
tests/test_request_composition.py13 passed; ruff clean. Live recompute of 3 real turns shows worst-case delta −15.3% → −3.2%. Companion home-plugin label change ("char/4" → "char-based estimate" in the/contextrenderer) deployed alongside.Companion
Builds directly on #21 (request composition snapshot). Independent, can land on its own.