opencode-dejavu 2.5.0 → 2.5.1

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.5.1 — 2026-08-26
4
+
5
+ ### Fixed
6
+ - Cross-project index + forensic log now key on the gate's OWN key (post fuzzy-consolidation), not the raw failure key. Before, a failure that fuzzy-merged into an existing gate indexed a key with no gate — orphaning the entry and silently starving that gate's cross-project escalation (the "INDEX ORPHANS" you'd see in doctor).
7
+
3
8
  ## 2.5.0 — 2026-08-24
4
9
 
5
10
  ### Changed (the three known gaps, closed)
package/index.ts CHANGED
@@ -275,7 +275,7 @@ export const Dejavu: Plugin = async ({ directory, client }) => {
275
275
 
276
276
  await stores.logAll({
277
277
  type: "detected",
278
- key,
278
+ key: result.gate.key,
279
279
  tool: input.tool,
280
280
  session,
281
281
  project: directory,
@@ -285,7 +285,7 @@ export const Dejavu: Plugin = async ({ directory, client }) => {
285
285
  })
286
286
 
287
287
  if (result.promoted) {
288
- await stores.logAll({ type: "promoted", key, tool: input.tool, session, project: directory })
288
+ await stores.logAll({ type: "promoted", key: result.gate.key, tool: input.tool, session, project: directory })
289
289
  await logClient(
290
290
  "info",
291
291
  `dejavu: gate promoted — "${result.gate.signature}" (${result.gate.count}x, ${result.gate.sessions.length} sessions)`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-dejavu",
3
- "version": "2.5.0",
3
+ "version": "2.5.1",
4
4
  "description": "Cross-session memory prosthesis for OpenCode: detects recurring tool-call failures and promotes them into enforced gates. Remind first, block on same-session repeat offense.",
5
5
  "type": "module",
6
6
  "main": "index.ts",
package/src/store.ts CHANGED
@@ -4,7 +4,7 @@ import { canBlock, canRemind, fuzzySimilar, FUZZY_MAX_LEN, isRepoLocal, scrubSec
4
4
  import { coerceGateShape, repairGate } from "./validate"
5
5
 
6
6
  /** Bumped on behavior changes; stamped into init log events so stale sessions are visible. */
7
- export const PLUGIN_VERSION = "2.5.0"
7
+ export const PLUGIN_VERSION = "2.5.1"
8
8
 
9
9
  export interface Gate {
10
10
  /** sha1 signature prefix — the pattern identity */
@@ -954,14 +954,17 @@ export class Stores {
954
954
  // ever sees its own store's directory, so alone it can never reach two
955
955
  // projects. A pattern seen in enough distinct project dirs is an
956
956
  // agent-level habit, not a repo quirk — move it to the global store.
957
+ // Keyed by the gate's OWN key (post fuzzy-consolidation), not the raw
958
+ // failure key — otherwise consolidated failures index a key that has no
959
+ // gate, orphaning the entry and starving the gate's escalation.
957
960
  // Lock order is always gates -> index and project -> global: no cycles.
958
961
  const moved = gate
959
962
  const indexProjects = await this.globalStore.runLockedIndex(async () => {
960
963
  const index = await this.globalStore.loadIndex(true)
961
- let entry = index.keys[input.key]
964
+ let entry = index.keys[moved.key]
962
965
  if (!entry) {
963
966
  entry = { projects: [], lastSeen: now }
964
- index.keys[input.key] = entry
967
+ index.keys[moved.key] = entry
965
968
  }
966
969
  if (input.projectDir !== "" && !entry.projects.includes(input.projectDir)) {
967
970
  entry.projects.push(input.projectDir)