opencode-autognosis 2.3.0 → 2.3.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.
@@ -13,9 +13,11 @@ export declare class CodeGraphDB {
13
13
  }): void;
14
14
  getJob(id: string): any;
15
15
  listJobs(type?: string, limit?: number): any;
16
- postToBlackboard(author: string, message: string, topic?: string, symbolId?: string): void;
16
+ postToBlackboard(author: string, message: string, topic?: string, symbolId?: string, isPinned?: boolean): void;
17
+ getGraffiti(symbolId: string, limit?: number): any;
18
+ archiveGraffiti(symbolId: string): void;
19
+ pinGraffiti(id: number, pinned?: boolean): void;
17
20
  readBlackboard(topic?: string, limit?: number): any;
18
- getGraffiti(symbolId: string): any;
19
21
  acquireLock(resourceId: string, agentName: string, ttlSeconds?: number): void;
20
22
  releaseLock(resourceId: string, agentName: string): void;
21
23
  isLocked(resourceId: string): {
package/dist/database.js CHANGED
@@ -146,8 +146,11 @@ export class CodeGraphDB {
146
146
  author TEXT,
147
147
  message TEXT,
148
148
  topic TEXT,
149
- symbol_id TEXT, -- Optional link to a code symbol
150
- embedding BLOB, -- For semantic search on the blackboard
149
+ symbol_id TEXT,
150
+ git_hash TEXT, -- Version of code when note was made
151
+ is_archived BOOLEAN DEFAULT 0,
152
+ is_pinned BOOLEAN DEFAULT 0,
153
+ embedding BLOB,
151
154
  timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
152
155
  );
153
156
 
@@ -231,19 +234,54 @@ export class CodeGraphDB {
231
234
  }
232
235
  return this.db.prepare("SELECT * FROM background_jobs ORDER BY created_at DESC LIMIT ?").all(limit);
233
236
  }
234
- postToBlackboard(author, message, topic = 'general', symbolId) {
237
+ postToBlackboard(author, message, topic = 'general', symbolId, isPinned = false) {
238
+ // Get current git hash for contextual verification
239
+ let currentHash = "unknown";
240
+ try {
241
+ const { execSync } = require("node:child_process");
242
+ currentHash = execSync("git rev-parse --short HEAD", { encoding: "utf-8" }).trim();
243
+ }
244
+ catch { }
235
245
  const insert = this.db.prepare(`
236
- INSERT INTO blackboard (author, message, topic, symbol_id)
237
- VALUES (?, ?, ?, ?)
246
+ INSERT INTO blackboard (author, message, topic, symbol_id, git_hash, is_pinned)
247
+ VALUES (?, ?, ?, ?, ?, ?)
238
248
  RETURNING id
239
249
  `);
240
- const res = insert.get(author, message, topic, symbolId || null);
241
- // Queue for embedding (blackboard search)
250
+ const res = insert.get(author, message, topic, symbolId || null, currentHash, isPinned ? 1 : 0);
242
251
  this.db.prepare(`
243
252
  INSERT INTO embedding_queue (chunk_id, text_to_embed)
244
253
  VALUES (?, ?)
245
254
  `).run(`blackboard-${res.id}`, `${topic.toUpperCase()}: ${message}`);
246
255
  }
256
+ getGraffiti(symbolId, limit = 3) {
257
+ // Automatically archive notes older than 7 days that aren't pinned
258
+ this.db.prepare(`
259
+ UPDATE blackboard
260
+ SET is_archived = 1
261
+ WHERE is_pinned = 0
262
+ AND timestamp < datetime('now', '-7 days')
263
+ `).run();
264
+ return this.db.prepare(`
265
+ SELECT author, message, timestamp, git_hash, is_pinned
266
+ FROM blackboard
267
+ WHERE symbol_id = ?
268
+ AND is_archived = 0
269
+ ORDER BY is_pinned DESC, timestamp DESC
270
+ LIMIT ?
271
+ `).all(symbolId, limit);
272
+ }
273
+ archiveGraffiti(symbolId) {
274
+ this.db.prepare(`
275
+ UPDATE blackboard
276
+ SET is_archived = 1
277
+ WHERE symbol_id = ? AND is_pinned = 0
278
+ `).run(symbolId);
279
+ }
280
+ pinGraffiti(id, pinned = true) {
281
+ this.db.prepare(`
282
+ UPDATE blackboard SET is_pinned = ? WHERE id = ?
283
+ `).run(pinned ? 1 : 0, id);
284
+ }
247
285
  readBlackboard(topic, limit = 10) {
248
286
  if (topic) {
249
287
  return this.db.prepare(`
@@ -254,14 +292,6 @@ export class CodeGraphDB {
254
292
  SELECT * FROM blackboard ORDER BY timestamp DESC LIMIT ?
255
293
  `).all(limit);
256
294
  }
257
- getGraffiti(symbolId) {
258
- return this.db.prepare(`
259
- SELECT author, message, timestamp
260
- FROM blackboard
261
- WHERE symbol_id = ?
262
- ORDER BY timestamp DESC
263
- `).all(symbolId);
264
- }
265
295
  acquireLock(resourceId, agentName, ttlSeconds = 300) {
266
296
  // Check if already locked by someone else
267
297
  const current = this.isLocked(resourceId);
@@ -127,7 +127,7 @@ export function unifiedTools() {
127
127
  }
128
128
  }),
129
129
  code_read: tool({
130
- description: "Precise reading of symbols or file slices. Follows current plan. Checks for locks and returns graffiti.",
130
+ description: "Precise reading of symbols or file slices. Follows current plan. Checks for locks and returns historical graffiti.",
131
131
  args: {
132
132
  symbol: tool.schema.string().optional().describe("Symbol to jump to"),
133
133
  file: tool.schema.string().optional().describe("File path to read"),
@@ -140,7 +140,22 @@ export function unifiedTools() {
140
140
  if (resourceId) {
141
141
  getDb().logAccess(resourceId, args.plan_id);
142
142
  const lock = getDb().isLocked(resourceId);
143
- const graffiti = getDb().getGraffiti(resourceId);
143
+ // Smart History Housekeeping
144
+ const graffiti = getDb().getGraffiti(resourceId, 3); // Limit to top 3 recent/pinned notes
145
+ // Contextual Verification: Get current hash
146
+ let currentHash = "";
147
+ try {
148
+ const { execSync } = await import("node:child_process");
149
+ currentHash = execSync("git rev-parse --short HEAD", { encoding: "utf-8" }).trim();
150
+ }
151
+ catch { }
152
+ const verifiedGraffiti = graffiti.map((g) => ({
153
+ author: g.author,
154
+ message: g.message,
155
+ timestamp: g.timestamp,
156
+ status: g.git_hash !== currentHash ? "LEGACY (Potentially Outdated)" : "CURRENT",
157
+ is_pinned: !!g.is_pinned
158
+ }));
144
159
  let result;
145
160
  if (args.symbol) {
146
161
  result = await internal.jump_to_symbol.execute({ symbol: args.symbol, plan_id: args.plan_id });
@@ -153,7 +168,7 @@ export function unifiedTools() {
153
168
  ...parsed,
154
169
  coordination: {
155
170
  lock_status: lock ? `LOCKED by ${lock.owner_agent}` : "FREE",
156
- graffiti: graffiti.length > 0 ? graffiti : undefined
171
+ historical_notes: verifiedGraffiti.length > 0 ? verifiedGraffiti : undefined
157
172
  }
158
173
  }, null, 2);
159
174
  }
@@ -180,22 +195,19 @@ export function unifiedTools() {
180
195
  return internal.brief_fix_loop.execute({ symbol: args.symbol, intent: args.intent });
181
196
  }
182
197
  case "patch": {
183
- // 1. Check for locks on all changed files
184
- const { stdout: diff } = await internal.runCmd("git diff");
185
198
  const { stdout: files } = await internal.runCmd("git diff --name-only");
186
199
  const changedFiles = files.split('\n').filter(Boolean);
187
200
  for (const file of changedFiles) {
188
201
  const lock = getDb().isLocked(file);
189
202
  if (lock && lock.owner_agent !== agentName) {
190
- return JSON.stringify({ status: "COLLISION_PREVENTED", message: `File ${file} is locked by ${lock.owner_agent}. Use 'code_status' to investigate.` });
203
+ return JSON.stringify({ status: "COLLISION_PREVENTED", message: `File ${file} is locked by ${lock.owner_agent}.` });
191
204
  }
192
205
  }
193
- // 2. Run Policy Engine
206
+ const { stdout: diff } = await internal.runCmd("git diff");
194
207
  const violations = policyEngine.checkDiff(diff);
195
208
  if (violations.some(v => v.severity === "error")) {
196
209
  return JSON.stringify({ status: "POLICY_VIOLATION", violations, message: "Patch rejected by policy engine." }, null, 2);
197
210
  }
198
- // 3. Prepare patch and record intent
199
211
  const res = await internal.prepare_patch.execute({ message: args.message, plan_id: args.plan_id });
200
212
  const json = JSON.parse(res);
201
213
  if (json.status === "SUCCESS") {
@@ -232,12 +244,13 @@ export function unifiedTools() {
232
244
  }
233
245
  }),
234
246
  code_status: tool({
235
- description: "Monitor system health, background jobs, Multi-Agent Blackboard, and Resource Locks.",
247
+ description: "Monitor system health, Multi-Agent Blackboard, and Resource Locks.",
236
248
  args: {
237
249
  mode: tool.schema.enum(["stats", "hot_files", "jobs", "plan", "doctor", "blackboard", "locks"]).optional().default("stats"),
238
- action: tool.schema.enum(["post", "read", "lock", "unlock"]).optional(),
250
+ action: tool.schema.enum(["post", "read", "lock", "unlock", "archive", "pin"]).optional(),
239
251
  topic: tool.schema.string().optional().default("general"),
240
- target: tool.schema.string().optional().describe("Resource ID (file/symbol) for locks or Symbol ID for graffiti"),
252
+ target: tool.schema.string().optional().describe("Resource ID (file/symbol) or Note ID"),
253
+ pinned: tool.schema.boolean().optional().default(false),
241
254
  message: tool.schema.string().optional(),
242
255
  job_id: tool.schema.string().optional(),
243
256
  plan_id: tool.schema.string().optional(),
@@ -258,9 +271,17 @@ export function unifiedTools() {
258
271
  }
259
272
  case "blackboard": {
260
273
  if (args.action === "post") {
261
- getDb().postToBlackboard(agentName, args.message, args.topic, args.target);
274
+ getDb().postToBlackboard(agentName, args.message, args.topic, args.target, args.pinned);
262
275
  return JSON.stringify({ status: "SUCCESS", message: "Posted to blackboard." });
263
276
  }
277
+ else if (args.action === "archive") {
278
+ getDb().archiveGraffiti(args.target);
279
+ return JSON.stringify({ status: "SUCCESS", message: `Archived notes for ${args.target}` });
280
+ }
281
+ else if (args.action === "pin") {
282
+ getDb().pinGraffiti(parseInt(args.target, 10), true);
283
+ return JSON.stringify({ status: "SUCCESS", message: `Pinned note ${args.target}` });
284
+ }
264
285
  return JSON.stringify({ status: "SUCCESS", entries: getDb().readBlackboard(args.topic) });
265
286
  }
266
287
  case "hot_files": return internal.journal_query_hot_files.execute({ path_prefix: args.path });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-autognosis",
3
- "version": "2.3.0",
3
+ "version": "2.3.1",
4
4
  "description": "Advanced RAG-powered codebase awareness for OpenCode agents. Features Chunk Cards synthesis, hierarchical reasoning, ActiveSet working memory, and performance optimization for enterprise-scale repositories.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",