agent-cache-optimizer 0.5.4 → 0.6.0

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.
@@ -0,0 +1,549 @@
1
+ # Cross-Agent Cache Sharing Implementation Plan
2
+
3
+ > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
4
+
5
+ **Goal:** Make shared stable system blocks appear before agent-specific stable blocks after OpenCode switches agents on the same provider/model.
6
+
7
+ **Architecture:** Keep the existing `provider__model__agent` DB for per-agent behavior, and add a `provider__model` family DB used only for cross-agent ranking. Classification remains content-agnostic; the new ranking phase partitions already-stable blocks into shared, scoped, and cold groups before appending dynamic blocks.
8
+
9
+ **Tech Stack:** TypeScript, OpenCode plugin hooks, Node fs/path APIs, Vitest.
10
+
11
+ ---
12
+
13
+ ## File Structure
14
+
15
+ - Modify `src/index.ts`: add family scope helpers, stable-block ranking, transform wiring, and diagnostics.
16
+ - Modify `src/__tests__/plugin.test.ts`: add cross-agent ordering and family DB persistence tests.
17
+ - Run existing tests through `npm test` and type checks through `npm run typecheck`.
18
+
19
+ The family DB should be persisted as another `stability-*.json` file using the existing DB helpers. Do not change prompt text. Do not migrate the warm-cache file format. Family warm membership should be derived from the family DB with `extractWarmHashes(familyDB)` so the existing global warm promotion does not count a family DB as a second agent scope. Family warm hashes are used for ranking only; they must not bypass volatile metadata classification.
20
+
21
+ ### Task 1: Add Failing Cross-Agent Ordering Test
22
+
23
+ **Files:**
24
+ - Modify: `src/__tests__/plugin.test.ts`
25
+
26
+ - [ ] **Step 1: Add a test showing shared blocks should outrank agent-specific blocks**
27
+
28
+ Append this test inside the existing `describe("CacheOptimizerPlugin provider/model scope", () => { ... })` block, after the warm-cache promotion test:
29
+
30
+ ```ts
31
+ it("orders family-stable shared blocks before agent-specific stable blocks after agent switches", async () => {
32
+ await withPlugin(async (hooks, cacheRoot) => {
33
+ const sharedTools = "Shared tool and project instructions stay identical across agents. ".repeat(30)
34
+ const buildPrompt = "You are the build agent with build-only instructions. ".repeat(30)
35
+ const reviewPrompt = "You are the review agent with review-only instructions. ".repeat(30)
36
+
37
+ await hooks["chat.params"](
38
+ { sessionID: "s-build", agent: "build", model: model("deepseek") },
39
+ {},
40
+ )
41
+ for (let i = 0; i < 3; i++) {
42
+ await hooks["experimental.chat.system.transform"](
43
+ { sessionID: "s-build", model: model("deepseek") },
44
+ { system: [`currentDate: 2026-06-25\nsession id: build-${i}`, buildPrompt, sharedTools] },
45
+ )
46
+ }
47
+
48
+ await hooks["chat.params"](
49
+ { sessionID: "s-review", agent: "review", model: model("deepseek") },
50
+ {},
51
+ )
52
+ for (let i = 0; i < 3; i++) {
53
+ await hooks["experimental.chat.system.transform"](
54
+ { sessionID: "s-review", model: model("deepseek") },
55
+ {
56
+ system: [
57
+ `currentDate: 2026-06-25\nsession id: review-${i}`,
58
+ reviewPrompt,
59
+ sharedTools,
60
+ ],
61
+ },
62
+ )
63
+ }
64
+
65
+ const output = {
66
+ system: ["currentDate: 2026-06-25\nsession id: review-final", reviewPrompt, sharedTools],
67
+ }
68
+ await hooks["experimental.chat.system.transform"](
69
+ { sessionID: "s-review", model: model("deepseek") },
70
+ output,
71
+ )
72
+
73
+ expect(output.system[0]).toBe(sharedTools)
74
+ expect(output.system[1]).toBe(reviewPrompt)
75
+ expect(output.system[2]).toContain("session id: review-final")
76
+
77
+ const raw = readFileSync(join(stateDir(cacheRoot), "events.jsonl"), "utf-8")
78
+ const events = raw
79
+ .trim()
80
+ .split("\n")
81
+ .map((line) => JSON.parse(line))
82
+ const transform = events.filter((event) => event.type === "transform").at(-1)
83
+
84
+ expect(transform.ranking).toMatchObject({
85
+ sharedStable: 1,
86
+ scopedStable: 1,
87
+ coldStable: 0,
88
+ })
89
+ expect(transform.ranking.sharedPrefixBytes).toBe(sharedTools.length)
90
+ })
91
+ })
92
+ ```
93
+
94
+ - [ ] **Step 2: Run the new test and verify it fails**
95
+
96
+ Run:
97
+
98
+ ```bash
99
+ npm test -- src/__tests__/plugin.test.ts -t "orders family-stable shared blocks"
100
+ ```
101
+
102
+ Expected: FAIL because current output keeps `reviewPrompt` before `sharedTools`, and the `ranking` diagnostic object does not exist.
103
+
104
+ ### Task 2: Add Failing Family DB Persistence Test
105
+
106
+ **Files:**
107
+ - Modify: `src/__tests__/plugin.test.ts`
108
+
109
+ - [ ] **Step 1: Add a test for writing both agent and family stability DBs**
110
+
111
+ Append this test near the existing scope tests:
112
+
113
+ ```ts
114
+ it("writes a provider-model family DB alongside agent-scoped DBs", async () => {
115
+ await withPlugin(async (hooks, cacheRoot) => {
116
+ const stable = "Stable shared prompt content for the model family. ".repeat(20)
117
+ const dynamic = "currentDate: 2026-06-25\nsession id: family-db"
118
+
119
+ await hooks["chat.params"](
120
+ { sessionID: "s-build-family", agent: "build", model: model("deepseek") },
121
+ {},
122
+ )
123
+ await hooks["experimental.chat.system.transform"](
124
+ { sessionID: "s-build-family", model: model("deepseek") },
125
+ { system: [dynamic, stable] },
126
+ )
127
+
128
+ const files = readdirSync(stateDir(cacheRoot))
129
+ .filter((file) => file.startsWith("stability-"))
130
+ .sort()
131
+
132
+ expect(files).toContain("stability-deepseek__deepseek-chat.json")
133
+ expect(files).toContain("stability-deepseek__deepseek-chat__build.json")
134
+ })
135
+ })
136
+ ```
137
+
138
+ - [ ] **Step 2: Run the family DB test and verify it fails**
139
+
140
+ Run:
141
+
142
+ ```bash
143
+ npm test -- src/__tests__/plugin.test.ts -t "writes a provider-model family DB"
144
+ ```
145
+
146
+ Expected: FAIL because only `stability-deepseek__deepseek-chat__build.json` is written for an agent session.
147
+
148
+ ### Task 3: Add Family Scope Context Helpers
149
+
150
+ **Files:**
151
+ - Modify: `src/index.ts`
152
+
153
+ - [ ] **Step 1: Replace string-only session scope tracking with scope contexts**
154
+
155
+ In `src/index.ts`, replace the current session-scope block with this implementation:
156
+
157
+ ```ts
158
+ // ── Session scope tracking ───────────────────────────────────────────
159
+
160
+ interface ScopeContext {
161
+ scope: string
162
+ familyScope: string
163
+ }
164
+
165
+ const sessionScopes = new Map<string, ScopeContext>()
166
+
167
+ function familyScope(model: ModelIdentity | undefined): string {
168
+ return modelScope(model)
169
+ }
170
+
171
+ function scopeContext(model: ModelIdentity | undefined, agent?: string): ScopeContext {
172
+ const scope = modelScope(model, agent)
173
+ const modelFamily = familyScope(model)
174
+ return {
175
+ scope,
176
+ familyScope: modelFamily === "default" ? scope : modelFamily,
177
+ }
178
+ }
179
+
180
+ function rememberSessionScope(
181
+ sessionID: string | undefined,
182
+ model: ModelIdentity | undefined,
183
+ agent?: string,
184
+ ): string {
185
+ const context = scopeContext(model, agent)
186
+ if (sessionID) sessionScopes.set(sessionID, context)
187
+ return context.scope
188
+ }
189
+
190
+ function scopeForSession(sessionID: string | undefined, model: ModelIdentity | undefined): string {
191
+ if (sessionID) {
192
+ const known = sessionScopes.get(sessionID)
193
+ if (known) return known.scope
194
+ }
195
+ return scopeContext(model).scope
196
+ }
197
+
198
+ function familyScopeForSession(
199
+ sessionID: string | undefined,
200
+ model: ModelIdentity | undefined,
201
+ ): string {
202
+ if (sessionID) {
203
+ const known = sessionScopes.get(sessionID)
204
+ if (known) return known.familyScope
205
+ }
206
+ return scopeContext(model).familyScope
207
+ }
208
+ ```
209
+
210
+ - [ ] **Step 2: Run existing scope tests**
211
+
212
+ Run:
213
+
214
+ ```bash
215
+ npm test -- src/__tests__/plugin.test.ts -t "scope"
216
+ ```
217
+
218
+ Expected: existing scope tests still PASS. The two new tests still FAIL.
219
+
220
+ ### Task 4: Add Stable Block Ranking Helpers
221
+
222
+ **Files:**
223
+ - Modify: `src/index.ts`
224
+
225
+ - [ ] **Step 1: Add `lookupContentScore` to the core imports**
226
+
227
+ Change the import from `./core` so it includes `lookupContentScore`:
228
+
229
+ ```ts
230
+ import {
231
+ emptyDB,
232
+ updateDB,
233
+ updateContentDB,
234
+ extractWarmHashes,
235
+ estimateSavings,
236
+ hashContent,
237
+ lookupContentScore,
238
+ } from "./core"
239
+ ```
240
+
241
+ - [ ] **Step 2: Add ranking types and helpers before the plugin definition**
242
+
243
+ Insert this block after `pruneStaleHashes`:
244
+
245
+ ```ts
246
+ // ── Cross-agent stable prefix ranking ────────────────────────────────
247
+
248
+ interface WarmHashMembership {
249
+ global: Set<string>
250
+ scoped: Set<string>
251
+ family: Set<string>
252
+ }
253
+
254
+ interface StableRanking {
255
+ sharedStable: string[]
256
+ scopedStable: string[]
257
+ coldStable: string[]
258
+ dynamic: string[]
259
+ }
260
+
261
+ function warmMembershipForScope(scope: string, familyDB: StabilityDB): WarmHashMembership {
262
+ const cache = loadWarmCache()
263
+ return {
264
+ global: cache.global,
265
+ scoped: cache.scopes.get(scope) ?? new Set(),
266
+ family: extractWarmHashes(familyDB),
267
+ }
268
+ }
269
+
270
+ function hasStableContentScore(db: StabilityDB, hash: string): boolean {
271
+ const score = lookupContentScore(db, hash)
272
+ return db.contentObservations >= 2 && score !== null && score >= 0.7
273
+ }
274
+
275
+ function classificationWarmHashes(membership: WarmHashMembership): Set<string> {
276
+ const hashes = new Set<string>(membership.global)
277
+ for (const hash of membership.scoped) hashes.add(hash)
278
+ return hashes
279
+ }
280
+
281
+ function rankStableBlocks(
282
+ stableBlocks: string[],
283
+ dynamicBlocks: string[],
284
+ scopeDB: StabilityDB,
285
+ familyDB: StabilityDB,
286
+ warmMembership: WarmHashMembership,
287
+ ): StableRanking {
288
+ const ranking: StableRanking = {
289
+ sharedStable: [],
290
+ scopedStable: [],
291
+ coldStable: [],
292
+ dynamic: dynamicBlocks,
293
+ }
294
+
295
+ for (const block of stableBlocks) {
296
+ const hash = hashContent(block)
297
+ if (
298
+ warmMembership.global.has(hash) ||
299
+ warmMembership.family.has(hash) ||
300
+ hasStableContentScore(familyDB, hash)
301
+ ) {
302
+ ranking.sharedStable.push(block)
303
+ continue
304
+ }
305
+
306
+ if (warmMembership.scoped.has(hash) || hasStableContentScore(scopeDB, hash)) {
307
+ ranking.scopedStable.push(block)
308
+ continue
309
+ }
310
+
311
+ ranking.coldStable.push(block)
312
+ }
313
+
314
+ return ranking
315
+ }
316
+ ```
317
+
318
+ - [ ] **Step 3: Run typecheck**
319
+
320
+ Run:
321
+
322
+ ```bash
323
+ npm run typecheck
324
+ ```
325
+
326
+ Expected: PASS after unused-import and type errors are resolved.
327
+
328
+ ### Task 5: Wire Family DB and Ranking Into Transform
329
+
330
+ **Files:**
331
+ - Modify: `src/index.ts`
332
+
333
+ - [ ] **Step 1: Load family DB and membership in the transform hook**
334
+
335
+ Inside `"experimental.chat.system.transform"`, replace:
336
+
337
+ ```ts
338
+ const db = loadDB(scope)
339
+
340
+ // Pass warm hashes to classifier for cache warming
341
+ const classified = classify(splitBlocks, db, {
342
+ splitThreshold: Number.MAX_SAFE_INTEGER,
343
+ warmHashes: warmHashesForScope(scope),
344
+ })
345
+
346
+ // Reorder: stable → unknown → dynamic
347
+ output.system = [...classified.stable, ...classified.unknown, ...classified.dynamic]
348
+ ```
349
+
350
+ with:
351
+
352
+ ```ts
353
+ const family = familyScopeForSession(input.sessionID, input.model)
354
+ const db = loadDB(scope)
355
+ const familyDB = family === scope ? db : loadDB(family)
356
+ const warmMembership = warmMembershipForScope(scope, familyDB)
357
+
358
+ const classified = classify(splitBlocks, db, {
359
+ splitThreshold: Number.MAX_SAFE_INTEGER,
360
+ warmHashes: classificationWarmHashes(warmMembership),
361
+ })
362
+
363
+ const ranked = rankStableBlocks(
364
+ classified.stable,
365
+ [...classified.unknown, ...classified.dynamic],
366
+ db,
367
+ familyDB,
368
+ warmMembership,
369
+ )
370
+
371
+ output.system = [
372
+ ...ranked.sharedStable,
373
+ ...ranked.scopedStable,
374
+ ...ranked.coldStable,
375
+ ...ranked.dynamic,
376
+ ]
377
+ ```
378
+
379
+ - [ ] **Step 2: Persist both DBs after reorder**
380
+
381
+ Replace:
382
+
383
+ ```ts
384
+ updateDB(db, output.system)
385
+ updateContentDB(db, output.system)
386
+ ```
387
+
388
+ with:
389
+
390
+ ```ts
391
+ updateDB(db, output.system)
392
+ updateContentDB(db, output.system)
393
+ if (family !== scope) {
394
+ updateDB(familyDB, output.system)
395
+ updateContentDB(familyDB, output.system)
396
+ }
397
+ ```
398
+
399
+ Replace:
400
+
401
+ ```ts
402
+ saveDB(scope, db)
403
+ ```
404
+
405
+ with:
406
+
407
+ ```ts
408
+ saveDB(scope, db)
409
+ if (family !== scope) saveDB(family, familyDB)
410
+ ```
411
+
412
+ - [ ] **Step 3: Keep warm-cache writes scoped to agent DBs**
413
+
414
+ Leave this block scoped-only:
415
+
416
+ ```ts
417
+ if (db.observations % 10 === 0) {
418
+ saveWarmCache(scope, db)
419
+ }
420
+ ```
421
+
422
+ Do not call `saveWarmCache(family, familyDB)`.
423
+
424
+ - [ ] **Step 4: Run the new family DB test**
425
+
426
+ Run:
427
+
428
+ ```bash
429
+ npm test -- src/__tests__/plugin.test.ts -t "writes a provider-model family DB"
430
+ ```
431
+
432
+ Expected: PASS.
433
+
434
+ ### Task 6: Add Ranking Diagnostics
435
+
436
+ **Files:**
437
+ - Modify: `src/index.ts`
438
+
439
+ - [ ] **Step 1: Track shared prefix bytes and ranking counts**
440
+
441
+ After savings are calculated, add:
442
+
443
+ ```ts
444
+ const sharedPrefixBytes = ranked.sharedStable.reduce((s, b) => s + b.length, 0)
445
+ ```
446
+
447
+ Change the diagnostic log call to include ranking counts:
448
+
449
+ ```ts
450
+ diag(
451
+ scope,
452
+ `S:${classified.stable.length} U:${classified.unknown.length} ` +
453
+ `D:${classified.dynamic.length} T:${output.system.length} ` +
454
+ `SH:${ranked.sharedStable.length} SC:${ranked.scopedStable.length} ` +
455
+ `CS:${ranked.coldStable.length} ` +
456
+ `obs:${db.observations} ` +
457
+ `stableKB:${(stableBytes / 1024).toFixed(1)} ` +
458
+ `sharedKB:${(sharedPrefixBytes / 1024).toFixed(1)} ` +
459
+ `saved:$${estCallSaving.toFixed(6)} ` +
460
+ `total:$${savings.estimatedSavingsUSD.toFixed(4)}`,
461
+ )
462
+ ```
463
+
464
+ Add this object to the `eventLog("transform", scope, { ... })` payload:
465
+
466
+ ```ts
467
+ family,
468
+ ranking: {
469
+ sharedStable: ranked.sharedStable.length,
470
+ scopedStable: ranked.scopedStable.length,
471
+ coldStable: ranked.coldStable.length,
472
+ dynamic: ranked.dynamic.length,
473
+ sharedPrefixBytes,
474
+ },
475
+ ```
476
+
477
+ - [ ] **Step 2: Run the cross-agent ordering test**
478
+
479
+ Run:
480
+
481
+ ```bash
482
+ npm test -- src/__tests__/plugin.test.ts -t "orders family-stable shared blocks"
483
+ ```
484
+
485
+ Expected: PASS.
486
+
487
+ ### Task 7: Full Verification and Commit
488
+
489
+ **Files:**
490
+ - Modify: `src/index.ts`
491
+ - Modify: `src/__tests__/plugin.test.ts`
492
+
493
+ - [ ] **Step 1: Run the focused plugin suite**
494
+
495
+ Run:
496
+
497
+ ```bash
498
+ npm test -- src/__tests__/plugin.test.ts
499
+ ```
500
+
501
+ Expected: PASS.
502
+
503
+ - [ ] **Step 2: Run all tests**
504
+
505
+ Run:
506
+
507
+ ```bash
508
+ npm test
509
+ ```
510
+
511
+ Expected: PASS.
512
+
513
+ - [ ] **Step 3: Run typecheck**
514
+
515
+ Run:
516
+
517
+ ```bash
518
+ npm run typecheck
519
+ ```
520
+
521
+ Expected: PASS.
522
+
523
+ - [ ] **Step 4: Inspect git diff**
524
+
525
+ Run:
526
+
527
+ ```bash
528
+ git diff -- src/index.ts src/__tests__/plugin.test.ts
529
+ ```
530
+
531
+ Expected: only family-scope ranking, diagnostics, and tests are changed.
532
+
533
+ - [ ] **Step 5: Commit implementation**
534
+
535
+ Run:
536
+
537
+ ```bash
538
+ git add src/index.ts src/__tests__/plugin.test.ts
539
+ git commit -m "feat: share stable cache prefix across agents"
540
+ ```
541
+
542
+ Expected: commit succeeds with the implementation changes only.
543
+
544
+ ## Self-Review
545
+
546
+ - Spec coverage: family scope, shared/scoped/cold ranking, diagnostics, fallback behavior, and tests are covered by Tasks 1-7.
547
+ - Placeholder scan: the plan contains no deferred implementation markers.
548
+ - Type consistency: `familyScope`, `familyScopeForSession`, `WarmHashMembership`, `StableRanking`, `rankStableBlocks`, and `sharedPrefixBytes` are consistently named across tasks.
549
+ - Scope check: the plan changes only OpenCode system prompt ordering and does not introduce conversation-log rewriting, prompt mutation, manual pinning, or DeepSeek-specific branches.
@@ -0,0 +1,102 @@
1
+ # Cross-Agent Cache Hit Design
2
+
3
+ Date: 2026-06-25
4
+
5
+ ## Goal
6
+
7
+ Improve DeepSeek prefix-cache hit rate when OpenCode switches between agents such
8
+ as `build`, `review`, and `plan`.
9
+
10
+ The plugin already moves stable system blocks before dynamic blocks. The missing
11
+ piece is that stable blocks are learned and ordered mostly inside
12
+ `provider__model__agent` scopes. After an agent switch, shared blocks can still
13
+ appear after an agent-specific prompt block, shortening the byte-identical prefix
14
+ that DeepSeek can reuse.
15
+
16
+ ## Constraints
17
+
18
+ - Keep the plugin content-agnostic: use hashes and structural metadata only.
19
+ - Do not edit prompt text. Only reorder system blocks.
20
+ - Preserve per-agent observability and stability databases.
21
+ - Keep behavior safe for non-DeepSeek providers that also use prefix caching.
22
+ - Avoid configuration requirements for the default path.
23
+
24
+ ## Design
25
+
26
+ Add a model-family learning layer alongside the existing per-agent scope.
27
+
28
+ Current scope:
29
+
30
+ ```text
31
+ provider__model__agent
32
+ ```
33
+
34
+ New family scope:
35
+
36
+ ```text
37
+ provider__model
38
+ ```
39
+
40
+ Each transform updates both databases. The agent scope keeps local behavior and
41
+ metrics. The family scope learns which block hashes are stable across multiple
42
+ agents using the same provider/model.
43
+
44
+ The reordered system prompt becomes:
45
+
46
+ ```text
47
+ sharedStable -> scopedStable -> coldStable -> dynamic
48
+ ```
49
+
50
+ `sharedStable` contains hashes that are stable in the family scope or promoted to
51
+ the global warm cache. These blocks form the cross-agent prefix and should appear
52
+ before agent-specific prompt blocks. `scopedStable` contains hashes stable only
53
+ for the current agent. `coldStable` contains blocks that cold-start heuristics
54
+ consider stable but the family learner has not confirmed yet.
55
+
56
+ ## Data Flow
57
+
58
+ 1. Resolve the current agent scope from OpenCode session events.
59
+ 2. Resolve the family scope from provider and model only.
60
+ 3. Split system blocks using the existing splitter.
61
+ 4. Load both stability DBs and warm-cache data.
62
+ 5. Classify each block using the existing classifier.
63
+ 6. Rank stable blocks by shared status first, then scoped status, then current
64
+ order as a deterministic fallback.
65
+ 7. Persist both DBs after reorder.
66
+ 8. Record diagnostics for shared-prefix size and hash counts.
67
+
68
+ ## Components
69
+
70
+ - `familyScope(model)`: returns `provider__model`.
71
+ - `rankStableBlocks(...)`: partitions classified stable blocks into shared,
72
+ scoped, and cold stable groups.
73
+ - Warm cache shape: keep existing v2 format but expose separate `global`,
74
+ `family`, and `scope` membership to ranking code instead of only returning a
75
+ merged set.
76
+ - Diagnostics: add `sharedStable`, `scopedStable`, `coldStable`, and
77
+ `sharedPrefixBytes` to structured transform events.
78
+
79
+ ## Error Handling
80
+
81
+ All new storage remains best-effort like the existing DBs. If the family DB or
82
+ warm cache cannot be read, the plugin falls back to the current per-agent
83
+ classification and reorder behavior. Failed family writes should log an error
84
+ event but must not block the chat request.
85
+
86
+ ## Testing
87
+
88
+ Add focused Vitest coverage:
89
+
90
+ - Two agents with the same provider/model and shared tool blocks should place
91
+ shared blocks before agent-specific stable blocks after family learning.
92
+ - Per-agent DB files should still be written.
93
+ - Metrics should still aggregate by `provider__model__agent`.
94
+ - Family DB read/write failures should not prevent transform output.
95
+ - Existing warm-cache promotion tests should continue to pass.
96
+
97
+ ## Non-Goals
98
+
99
+ - No conversation-log rewrite.
100
+ - No prompt text mutation or marker insertion.
101
+ - No manual pinning UI in this change.
102
+ - No provider-specific DeepSeek branching.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-cache-optimizer",
3
- "version": "0.5.4",
3
+ "version": "0.6.0",
4
4
  "description": "Content-agnostic KV cache optimizer for LLM CLI agents — boosts prompt cache hit rate by 40-88% through automatic stability tracking and block reordering",
5
5
  "keywords": [
6
6
  "kv-cache",