[rebase w2] src/rune/token_optimizer.py::TokenOptimizer.TokenOptimizer.get_dynamic_cache #779

Closed
opened 2026-09-29 08:07:30 +01:00 by conductor · 3 comments
Owner

Identity (from the Wave 0 inventory — machine-generated)

  • File: src/rune/token_optimizer.py
  • Unit: TokenOptimizer.TokenOptimizer.get_dynamic_cache
  • Signature: def TokenOptimizer.TokenOptimizer.get_dynamic_cache(self, context: str) -> str (async: False)
  • Line range: 172–194
  • Decorators: none
  • Internal call edges (callers/callees inside the repo, from inventory):
    • self._compress_context (line 178)
    • self.estimate_tokens (line 182)
    • CacheEntry (line 183)
    • self._mark_dirty (line 191)
    • self._save_if_dirty (line 192)

Current behaviour

One honest paragraph from READING THE CODE at the line range above — what it
actually does, not what the docstring promises. Write this at disposition
time; the factory does not fabricate it.

The three questions — each answered WITH EVIDENCE

  1. IMPROVE? Can the unit be improved within its scope? Evidence or "no — because …".
    (Bounded to unit scope; larger findings spawn NEW issues, never expand this one.)
  2. FIX? Is it broken, buggy, or failing its expected outcome? Evidence: a failing
    test, a reproduced fault, or a code-level defect citation. A "no" needs evidence too.
  3. MISSING CONNECTORS? Are there expected outcomes this unit should connect to but
    doesn't (unwired events, dead parameters, promised-but-absent calls)? Evidence required.

A silent skip on any question is a factory bug — answer all three.

Language verdict (per tranche R1 §6 rubric — evidence beats instinct)

Choose exactly one, with the evidence line:

  • KEEP-PYTHON — one sentence of justification.
  • RECODE- — rubric scores (all 7 dimensions) + benchmark-gate plan: the compiled
    replacement must beat the Python original on the MEASURED hot path, or the recode is
    rejected and recorded. No win, no recode.
  • MERGE-into: — name the target and why.
  • DEPRECATE — name the caller that no longer needs it.

Go is NOT pre-decided. Python is not pre-decided. The rubric decides.

Constraint context

  • henxels structural contract: this unit's module ≤ 1,200 lines (or on the debt table's
    exception list — check before adding lines).
  • Spine: any module-surface change requires store/spine/current.json regen with the code
    change (test_manifest_maps_every_module is the arbiter for new top-level modules).
  • Debt table: docs/structural-contract.md.

Pipeline plan

  1. Branch issue-<N> from current master (existing issue-N convention).
  2. Scaffolding activation for any construction (construction_mode/decision per unit change).
  3. Research rounds are MANDATORY for any RECODE verdict (research-stage-headless; ≥2
    live-verified external sources per claim; per-source lessons; kill test per candidate).
  4. Implementation behind the interop contract (R1 §5): compiled units are standalone
    binaries — argv in, JSON on stdout, non-zero exit on failure, --version mandatory;
    Python wraps in a thin adapter; store stays the shared truth.
  5. Local gates: pytest + ruff + spine-store regen (if surface changed) + henxels.
  6. PR → pipeline-gate + ci + required checks → merge-robot → auto-version.

Verification

  • The specific test proving this unit's change: (write at disposition).
  • The keep-green set it must not break: full suite must stay green; named
    keep-green tests for this unit's callers.

Provenance

  • Tranche: tranche R1 language rebase (2026-09-29), ~/.config/opencode/tranches/2026-09-29-language-rebase-tranche-R1.md
  • Wave: 2 (leaf utilities & canaries)
  • Inventory: docs/rebase-inventory.json (regenerate with scripts/rebase_inventory.py — never hand-edit)
  • Factory: scripts/rebase_issue_factory.py
## Identity (from the Wave 0 inventory — machine-generated) - **File**: `src/rune/token_optimizer.py` - **Unit**: `TokenOptimizer.TokenOptimizer.get_dynamic_cache` - **Signature**: `def TokenOptimizer.TokenOptimizer.get_dynamic_cache(self, context: str) -> str` (async: False) - **Line range**: 172–194 - **Decorators**: none - **Internal call edges** (callers/callees inside the repo, from inventory): - `self._compress_context` (line 178) - `self.estimate_tokens` (line 182) - `CacheEntry` (line 183) - `self._mark_dirty` (line 191) - `self._save_if_dirty` (line 192) ## Current behaviour One honest paragraph from READING THE CODE at the line range above — what it actually does, not what the docstring promises. Write this at disposition time; the factory does not fabricate it. ## The three questions — each answered WITH EVIDENCE 1. **IMPROVE?** Can the unit be improved within its scope? Evidence or "no — because …". (Bounded to unit scope; larger findings spawn NEW issues, never expand this one.) 2. **FIX?** Is it broken, buggy, or failing its expected outcome? Evidence: a failing test, a reproduced fault, or a code-level defect citation. A "no" needs evidence too. 3. **MISSING CONNECTORS?** Are there expected outcomes this unit should connect to but doesn't (unwired events, dead parameters, promised-but-absent calls)? Evidence required. A silent skip on any question is a factory bug — answer all three. ## Language verdict (per tranche R1 §6 rubric — evidence beats instinct) Choose exactly one, with the evidence line: - **KEEP-PYTHON** — one sentence of justification. - **RECODE-<lang>** — rubric scores (all 7 dimensions) + benchmark-gate plan: the compiled replacement must beat the Python original on the MEASURED hot path, or the recode is rejected and recorded. No win, no recode. - **MERGE-into:<module>** — name the target and why. - **DEPRECATE** — name the caller that no longer needs it. Go is NOT pre-decided. Python is not pre-decided. The rubric decides. ## Constraint context - henxels structural contract: this unit's module ≤ 1,200 lines (or on the debt table's exception list — check before adding lines). - Spine: any module-surface change requires `store/spine/current.json` regen with the code change (`test_manifest_maps_every_module` is the arbiter for new top-level modules). - Debt table: docs/structural-contract.md. ## Pipeline plan 1. Branch `issue-<N>` from current master (existing issue-N convention). 2. Scaffolding activation for any construction (construction_mode/decision per unit change). 3. Research rounds are MANDATORY for any RECODE verdict (research-stage-headless; ≥2 live-verified external sources per claim; per-source lessons; kill test per candidate). 4. Implementation behind the interop contract (R1 §5): compiled units are standalone binaries — argv in, JSON on stdout, non-zero exit on failure, `--version` mandatory; Python wraps in a thin adapter; store stays the shared truth. 5. Local gates: pytest + ruff + spine-store regen (if surface changed) + henxels. 6. PR → pipeline-gate + ci + required checks → merge-robot → auto-version. ## Verification - The specific test proving this unit's change: (write at disposition). - The keep-green set it must not break: full suite must stay green; named keep-green tests for this unit's callers. ## Provenance - Tranche: tranche R1 language rebase (2026-09-29), ~/.config/opencode/tranches/2026-09-29-language-rebase-tranche-R1.md - Wave: 2 (leaf utilities & canaries) - Inventory: docs/rebase-inventory.json (regenerate with scripts/rebase_inventory.py — never hand-edit) - Factory: scripts/rebase_issue_factory.py

⚠️ Priority gate: this issue has no priority. Assign exactly one of P0 — critical (spine/correctness/blocks), P1 — high (material value or real defect), P2 — medium (quality/consolidation), P3 — low (measurement/deferred). An issue without a priority is not filed.

⚠️ **Priority gate:** this issue has no priority. Assign exactly one of **P0 — critical** (spine/correctness/blocks), **P1 — high** (material value or real defect), **P2 — medium** (quality/consolidation), **P3 — low** (measurement/deferred). An issue without a priority is not filed.
gitea-actions Bot added the bugcustodiangrowthidentityinfrastructurememory labels 2026-09-29 08:22:03 +01:00
Author
Owner

Disposition — get_dynamic_cache (178–200)

Current behaviour (from code read): compresses the caller's context via _compress_context, keys the entry by hashlib.md5(context.encode()).hexdigest()[:16] (keyed on the FULL context, not the compressed form — so identical contexts dedupe), estimates tokens on the compressed content, stores the entry, marks dirty, saves, returns the compressed text. Note: unlike get_static_cache, this path does not distinguish hit from miss — it always overwrites the entry for that key and always counts neither hit nor miss.

  1. IMPROVE? Bounded observation: the cache grows unboundedly with distinct contexts (no eviction, no size cap) — persisted across restarts since #770's fix made entries loadable. For a per-session dynamic cache this is acceptable (entries are small, keys dedupe), but a size cap is the named improvement if this surface ever sees long-running multi-context use. Out of this unit's scope to fix unilaterally; recording honestly.
  2. FIX? No — behaviour matches the docstring (compress + cache + return compressed); md5 is used as a dedupe key, not a security primitive, so md5 is the right algorithm choice here.
  3. MISSING CONNECTORS? No — called from optimize_prompt's context branch; the entry it stores is consumed by get_cache_stats reporting.

Language verdict (rebase R1 §6 rubric): KEEP-PYTHON. The wave's heaviest work in this module is 2 re.sub per turn (rubric :280) — no hot loop exists here; every candidate compiled crossing costs ~658 µs (14,000× the cost of the work it would replace), and this unit is already on the CPython 3.11+ PEP 659 shape the rubric awards (rubric :282). No benchmark gate is owed: no measured hot path exists to beat. Zero RECODE.

## Disposition — `get_dynamic_cache` (178–200) **Current behaviour (from code read):** compresses the caller's context via `_compress_context`, keys the entry by `hashlib.md5(context.encode()).hexdigest()[:16]` (keyed on the FULL context, not the compressed form — so identical contexts dedupe), estimates tokens on the compressed content, stores the entry, marks dirty, saves, returns the compressed text. Note: unlike `get_static_cache`, this path does not distinguish hit from miss — it always overwrites the entry for that key and always counts neither hit nor miss. 1. **IMPROVE?** Bounded observation: the cache grows unboundedly with distinct contexts (no eviction, no size cap) — persisted across restarts since #770's fix made entries loadable. For a per-session dynamic cache this is acceptable (entries are small, keys dedupe), but a size cap is the named improvement if this surface ever sees long-running multi-context use. Out of this unit's scope to fix unilaterally; recording honestly. 2. **FIX?** No — behaviour matches the docstring (compress + cache + return compressed); md5 is used as a dedupe key, not a security primitive, so md5 is the right algorithm choice here. 3. **MISSING CONNECTORS?** No — called from `optimize_prompt`'s context branch; the entry it stores is consumed by `get_cache_stats` reporting. **Language verdict (rebase R1 §6 rubric): KEEP-PYTHON.** The wave's heaviest work in this module is 2 `re.sub` per turn (rubric `:280`) — no hot loop exists here; every candidate compiled crossing costs ~658 µs (14,000× the cost of the work it would replace), and this unit is already on the CPython 3.11+ PEP 659 shape the rubric awards (rubric `:282`). No benchmark gate is owed: no measured hot path exists to beat. Zero RECODE.
Author
Owner

Folded into epic #2303 — per-file epic for src/rune/token_optimizer.py (w2). Absorbed child; closing as absorbed (content preserved, reversible by reopen).

Folded into epic #2303 — per-file epic for `src/rune/token_optimizer.py` (w2). Absorbed child; closing as absorbed (content preserved, reversible by reopen).
Sign in to join this conversation.
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: conductor/rune#779