opencodekit 0.21.10 → 0.22.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.
Files changed (156) hide show
  1. package/dist/index.js +1 -1
  2. package/dist/template/.opencode/AGENTS.md +116 -487
  3. package/dist/template/.opencode/README.md +1 -1
  4. package/dist/template/.opencode/agent/build.md +56 -396
  5. package/dist/template/.opencode/agent/explore.md +0 -1
  6. package/dist/template/.opencode/agent/review.md +0 -1
  7. package/dist/template/.opencode/agent/scout.md +0 -1
  8. package/dist/template/.opencode/agent/vision.md +0 -1
  9. package/dist/template/.opencode/command/clarify.md +48 -0
  10. package/dist/template/.opencode/command/commit.md +53 -0
  11. package/dist/template/.opencode/command/fix.md +56 -0
  12. package/dist/template/.opencode/command/improve-architecture.md +55 -0
  13. package/dist/template/.opencode/command/init.md +88 -68
  14. package/dist/template/.opencode/command/refactor.md +66 -0
  15. package/dist/template/.opencode/command/test.md +66 -0
  16. package/dist/template/.opencode/dcp.jsonc +13 -2
  17. package/dist/template/.opencode/memory/README.md +3 -5
  18. package/dist/template/.opencode/memory/_templates/adr.md +45 -0
  19. package/dist/template/.opencode/memory/project/gotchas.md +1 -1
  20. package/dist/template/.opencode/memory/session-context.md +1 -1
  21. package/dist/template/.opencode/plugin/README.md +1 -1
  22. package/dist/template/.opencode/plugin/guard.ts +62 -0
  23. package/dist/template/.opencode/plugin/{lib/memory-admin-tools.ts → memory/admin.ts} +4 -4
  24. package/dist/template/.opencode/plugin/{lib → memory}/capture.ts +1 -1
  25. package/dist/template/.opencode/plugin/{lib → memory}/compile.ts +2 -2
  26. package/dist/template/.opencode/plugin/{lib → memory}/context.ts +1 -1
  27. package/dist/template/.opencode/plugin/{lib → memory}/curator.ts +1 -1
  28. package/dist/template/.opencode/plugin/{lib → memory}/db/observations.ts +102 -3
  29. package/dist/template/.opencode/plugin/{lib → memory}/db/schema.ts +43 -1
  30. package/dist/template/.opencode/plugin/{lib → memory}/db/types.ts +22 -0
  31. package/dist/template/.opencode/plugin/{lib/memory-db.ts → memory/db.ts} +1 -1
  32. package/dist/template/.opencode/plugin/{lib → memory}/distill.ts +1 -1
  33. package/dist/template/.opencode/plugin/{lib/memory-helpers.ts → memory/helpers.ts} +5 -1
  34. package/dist/template/.opencode/plugin/{lib/memory-hooks.ts → memory/hooks.ts} +1 -1
  35. package/dist/template/.opencode/plugin/{lib → memory}/index-generator.ts +2 -2
  36. package/dist/template/.opencode/plugin/{lib → memory}/inject.ts +1 -1
  37. package/dist/template/.opencode/plugin/{lib → memory}/lint.ts +2 -2
  38. package/dist/template/.opencode/plugin/memory/tools.ts +322 -0
  39. package/dist/template/.opencode/plugin/{lib → memory}/validate.ts +2 -2
  40. package/dist/template/.opencode/plugin/memory.ts +7 -17
  41. package/dist/template/.opencode/plugin/srcwalk.ts +721 -0
  42. package/dist/template/.opencode/skill/agent-code-quality-gate/SKILL.md +98 -0
  43. package/dist/template/.opencode/skill/behavioral-kernel/SKILL.md +52 -0
  44. package/dist/template/.opencode/skill/browser-testing-with-devtools/SKILL.md +85 -0
  45. package/dist/template/.opencode/skill/code-cleanup/SKILL.md +114 -0
  46. package/dist/template/.opencode/skill/code-navigation/SKILL.md +142 -0
  47. package/dist/template/.opencode/skill/code-review-and-quality/SKILL.md +131 -0
  48. package/dist/template/.opencode/skill/debugging-and-error-recovery/SKILL.md +109 -0
  49. package/dist/template/.opencode/skill/deep-module-design/SKILL.md +207 -0
  50. package/dist/template/.opencode/skill/git-workflow-and-versioning/SKILL.md +77 -0
  51. package/dist/template/.opencode/skill/grill-me/SKILL.md +140 -0
  52. package/dist/template/.opencode/skill/memory-system/SKILL.md +9 -10
  53. package/dist/template/.opencode/skill/planning-and-task-breakdown/SKILL.md +116 -0
  54. package/dist/template/.opencode/skill/shipping-and-launch/SKILL.md +95 -0
  55. package/dist/template/.opencode/skill/source-driven-development/SKILL.md +103 -0
  56. package/dist/template/.opencode/skill/spec-driven-development/SKILL.md +121 -0
  57. package/dist/template/.opencode/skill/srcwalk/SKILL.md +161 -0
  58. package/dist/template/.opencode/skill/ubiquitous-language/SKILL.md +184 -0
  59. package/package.json +1 -1
  60. package/dist/template/.opencode/AGENT_ALIGNMENT.md +0 -564
  61. package/dist/template/.opencode/agent/painter.md +0 -83
  62. package/dist/template/.opencode/command/compound.md +0 -240
  63. package/dist/template/.opencode/command/curate.md +0 -299
  64. package/dist/template/.opencode/command/handoff.md +0 -149
  65. package/dist/template/.opencode/command/health.md +0 -356
  66. package/dist/template/.opencode/command/init-context.md +0 -297
  67. package/dist/template/.opencode/command/init-user.md +0 -125
  68. package/dist/template/.opencode/command/iterate.md +0 -200
  69. package/dist/template/.opencode/command/lfg.md +0 -173
  70. package/dist/template/.opencode/command/resume.md +0 -78
  71. package/dist/template/.opencode/command/status.md +0 -126
  72. package/dist/template/.opencode/command/ui-slop-check.md +0 -169
  73. package/dist/template/.opencode/plugin/lib/memory-tools.ts +0 -535
  74. package/dist/template/.opencode/skill/agent-evals/SKILL.md +0 -208
  75. package/dist/template/.opencode/skill/anti-ai-slop/SKILL.md +0 -76
  76. package/dist/template/.opencode/skill/augment-context-engine/SKILL.md +0 -122
  77. package/dist/template/.opencode/skill/augment-context-engine/mcp.json +0 -6
  78. package/dist/template/.opencode/skill/brand-asset-protocol/SKILL.md +0 -222
  79. package/dist/template/.opencode/skill/code-search-patterns/SKILL.md +0 -224
  80. package/dist/template/.opencode/skill/code-simplification/SKILL.md +0 -211
  81. package/dist/template/.opencode/skill/context-condensation/SKILL.md +0 -149
  82. package/dist/template/.opencode/skill/context-initialization/SKILL.md +0 -69
  83. package/dist/template/.opencode/skill/context-management/SKILL.md +0 -390
  84. package/dist/template/.opencode/skill/deep-research/SKILL.md +0 -384
  85. package/dist/template/.opencode/skill/design-direction-advisor/SKILL.md +0 -139
  86. package/dist/template/.opencode/skill/dispatching-parallel-agents/SKILL.md +0 -191
  87. package/dist/template/.opencode/skill/executing-plans/SKILL.md +0 -247
  88. package/dist/template/.opencode/skill/figma-go/SKILL.md +0 -65
  89. package/dist/template/.opencode/skill/finishing-a-development-branch/SKILL.md +0 -357
  90. package/dist/template/.opencode/skill/full-output-enforcement/SKILL.md +0 -62
  91. package/dist/template/.opencode/skill/gh-address-comments/SKILL.md +0 -29
  92. package/dist/template/.opencode/skill/gh-address-comments/scripts/fetch_comments.py +0 -237
  93. package/dist/template/.opencode/skill/gh-fix-ci/SKILL.md +0 -38
  94. package/dist/template/.opencode/skill/gh-fix-ci/scripts/inspect_pr_checks.py +0 -509
  95. package/dist/template/.opencode/skill/hi-fi-prototype-html/SKILL.md +0 -253
  96. package/dist/template/.opencode/skill/html-deck-export/SKILL.md +0 -189
  97. package/dist/template/.opencode/skill/index-knowledge/SKILL.md +0 -413
  98. package/dist/template/.opencode/skill/memory-grounding/SKILL.md +0 -68
  99. package/dist/template/.opencode/skill/playwriter/SKILL.md +0 -158
  100. package/dist/template/.opencode/skill/portless/SKILL.md +0 -109
  101. package/dist/template/.opencode/skill/prd/SKILL.md +0 -146
  102. package/dist/template/.opencode/skill/prd-task/SKILL.md +0 -182
  103. package/dist/template/.opencode/skill/prd-task/references/prd-schema.json +0 -124
  104. package/dist/template/.opencode/skill/prompt-leverage/SKILL.md +0 -90
  105. package/dist/template/.opencode/skill/prompt-leverage/references/framework.md +0 -91
  106. package/dist/template/.opencode/skill/prompt-leverage/scripts/augment_prompt.py +0 -157
  107. package/dist/template/.opencode/skill/receiving-code-review/SKILL.md +0 -263
  108. package/dist/template/.opencode/skill/reconcile/SKILL.md +0 -183
  109. package/dist/template/.opencode/skill/reflection-checkpoints/SKILL.md +0 -183
  110. package/dist/template/.opencode/skill/requesting-code-review/SKILL.md +0 -443
  111. package/dist/template/.opencode/skill/requesting-code-review/references/specialist-profiles.md +0 -108
  112. package/dist/template/.opencode/skill/requesting-code-review/review.md +0 -160
  113. package/dist/template/.opencode/skill/rtk-command-compression/SKILL.md +0 -134
  114. package/dist/template/.opencode/skill/screenshot/SKILL.md +0 -48
  115. package/dist/template/.opencode/skill/screenshot/scripts/ensure_macos_permissions.sh +0 -54
  116. package/dist/template/.opencode/skill/screenshot/scripts/macos_display_info.swift +0 -22
  117. package/dist/template/.opencode/skill/screenshot/scripts/macos_permissions.swift +0 -40
  118. package/dist/template/.opencode/skill/screenshot/scripts/macos_window_info.swift +0 -126
  119. package/dist/template/.opencode/skill/screenshot/scripts/take_screenshot.ps1 +0 -163
  120. package/dist/template/.opencode/skill/screenshot/scripts/take_screenshot.py +0 -585
  121. package/dist/template/.opencode/skill/security-threat-model/SKILL.md +0 -36
  122. package/dist/template/.opencode/skill/security-threat-model/references/prompt-template.md +0 -255
  123. package/dist/template/.opencode/skill/security-threat-model/references/security-controls-and-assets.md +0 -32
  124. package/dist/template/.opencode/skill/sharing-skills/SKILL.md +0 -214
  125. package/dist/template/.opencode/skill/skill-creator/SKILL.md +0 -181
  126. package/dist/template/.opencode/skill/skill-installer/SKILL.md +0 -58
  127. package/dist/template/.opencode/skill/skill-installer/scripts/github_utils.py +0 -21
  128. package/dist/template/.opencode/skill/skill-installer/scripts/install-skill-from-github.py +0 -313
  129. package/dist/template/.opencode/skill/skill-installer/scripts/list-skills.py +0 -106
  130. package/dist/template/.opencode/skill/swarm-coordination/SKILL.md +0 -244
  131. package/dist/template/.opencode/skill/swarm-coordination/references/architecture.md +0 -39
  132. package/dist/template/.opencode/skill/swarm-coordination/references/delegation-worker-protocol.md +0 -145
  133. package/dist/template/.opencode/skill/swarm-coordination/references/dependency-graph.md +0 -50
  134. package/dist/template/.opencode/skill/swarm-coordination/references/drift-check.md +0 -90
  135. package/dist/template/.opencode/skill/swarm-coordination/references/integration-beads.md +0 -20
  136. package/dist/template/.opencode/skill/swarm-coordination/references/launch-flow.md +0 -186
  137. package/dist/template/.opencode/skill/swarm-coordination/references/reconciler.md +0 -172
  138. package/dist/template/.opencode/skill/swarm-coordination/references/tier-enforcement.md +0 -78
  139. package/dist/template/.opencode/skill/swarm-coordination/references/tmux-integration.md +0 -134
  140. package/dist/template/.opencode/skill/systematic-debugging/SKILL.md +0 -402
  141. package/dist/template/.opencode/skill/terse-output-mode/SKILL.md +0 -95
  142. package/dist/template/.opencode/skill/think-in-code/SKILL.md +0 -136
  143. package/dist/template/.opencode/skill/ux-quality-gates/SKILL.md +0 -137
  144. package/dist/template/.opencode/skill/v1-run/SKILL.md +0 -175
  145. package/dist/template/.opencode/skill/v1-run/mcp.json +0 -6
  146. package/dist/template/.opencode/skill/verification-gates/SKILL.md +0 -63
  147. package/dist/template/.opencode/skill/visual-analysis/SKILL.md +0 -154
  148. package/dist/template/.opencode/skill/web-design-guidelines/SKILL.md +0 -46
  149. package/dist/template/.opencode/skill/workspace-setup/SKILL.md +0 -76
  150. package/dist/template/.opencode/skill/writing-plans/SKILL.md +0 -320
  151. /package/dist/template/.opencode/plugin/{lib → memory}/compact.ts +0 -0
  152. /package/dist/template/.opencode/plugin/{lib → memory}/db/graph.ts +0 -0
  153. /package/dist/template/.opencode/plugin/{lib → memory}/db/maintenance.ts +0 -0
  154. /package/dist/template/.opencode/plugin/{lib → memory}/db/pipeline.ts +0 -0
  155. /package/dist/template/.opencode/plugin/{lib → memory}/notify.ts +0 -0
  156. /package/dist/template/.opencode/plugin/{lib → memory}/operation-log.ts +0 -0
@@ -18,7 +18,7 @@ import {
18
18
  getMemoryDB,
19
19
  MEMORY_CONFIG,
20
20
  type TemporalMessageInput,
21
- } from "./memory-db.js";
21
+ } from "./db.js";
22
22
 
23
23
  // ============================================================================
24
24
  // Types
@@ -17,8 +17,8 @@
17
17
 
18
18
  import { upsertMemoryFile } from "./db/maintenance.js";
19
19
  import type { ObservationRow } from "./db/types.js";
20
- import { getMemoryDB } from "./memory-db.js";
21
- import { TYPE_ICONS, parseConcepts } from "./memory-helpers.js";
20
+ import { getMemoryDB } from "./db.js";
21
+ import { TYPE_ICONS, parseConcepts } from "./helpers.js";
22
22
  import { appendOperationLog } from "./operation-log.js";
23
23
 
24
24
  // ============================================================================
@@ -7,7 +7,7 @@
7
7
  * Protects the most recent N messages from compression.
8
8
  */
9
9
 
10
- import { estimateTokens, MEMORY_CONFIG } from "./memory-db.js";
10
+ import { estimateTokens, MEMORY_CONFIG } from "./db.js";
11
11
 
12
12
  // ============================================================================
13
13
  // Types
@@ -15,7 +15,7 @@ import {
15
15
  type ObservationInput,
16
16
  type ObservationType,
17
17
  storeObservation,
18
- } from "./memory-db.js";
18
+ } from "./db.js";
19
19
 
20
20
  // ============================================================================
21
21
  // Pattern Definitions
@@ -7,6 +7,7 @@
7
7
 
8
8
  import { getMemoryDB } from "./schema.js";
9
9
  import type {
10
+ FeedbackEvent,
10
11
  ObservationInput,
11
12
  ObservationRow,
12
13
  ObservationType,
@@ -19,8 +20,7 @@ import type {
19
20
 
20
21
  /**
21
22
  * Store a new observation in the database.
22
- */
23
- export function storeObservation(input: ObservationInput): number {
23
+ */ export function storeObservation(input: ObservationInput): number {
24
24
  const db = getMemoryDB();
25
25
  const now = new Date();
26
26
 
@@ -31,8 +31,10 @@ export function storeObservation(input: ObservationInput): number {
31
31
  type, title, subtitle, facts, narrative, raw_source, concepts,
32
32
  files_read, files_modified, confidence, bead_id,
33
33
  supersedes, markdown_file, source, wing, hall, room,
34
+ helpful_count, harmful_count, feedback_events, effective_score,
35
+ maturity, retrieval_count, last_retrieved,
34
36
  created_at, created_at_epoch
35
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
37
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
36
38
  `,
37
39
  )
38
40
  .run(
@@ -53,6 +55,13 @@ export function storeObservation(input: ObservationInput): number {
53
55
  input.wing ?? null,
54
56
  input.hall ?? null,
55
57
  input.room ?? null,
58
+ 0, // helpful_count
59
+ 0, // harmful_count
60
+ null, // feedback_events
61
+ 0.0, // effective_score
62
+ "candidate", // maturity
63
+ 0, // retrieval_count
64
+ null, // last_retrieved
56
65
  now.toISOString(),
57
66
  now.getTime(),
58
67
  );
@@ -302,3 +311,93 @@ export function getObservationStats(): Record<string, number> {
302
311
  }
303
312
  return stats;
304
313
  }
314
+
315
+ // ============================================================================
316
+ // Feedback & Tracking (aligned with pikit memory extension)
317
+ // ============================================================================
318
+
319
+ /**
320
+ * Record feedback (helpful/harmful) on an observation.
321
+ */
322
+ export function recordFeedback(
323
+ observationId: number,
324
+ feedbackType: "helpful" | "harmful",
325
+ reason?: string,
326
+ sessionId?: string,
327
+ ): {
328
+ success: boolean;
329
+ helpfulCount: number;
330
+ harmfulCount: number;
331
+ error?: string;
332
+ } {
333
+ const db = getMemoryDB();
334
+
335
+ const row = db
336
+ .query("SELECT * FROM observations WHERE id = ?")
337
+ .get(observationId) as ObservationRow | undefined;
338
+
339
+ if (!row) {
340
+ return {
341
+ success: false,
342
+ helpfulCount: 0,
343
+ harmfulCount: 0,
344
+ error: `Observation #${observationId} not found`,
345
+ };
346
+ }
347
+
348
+ // Parse existing feedback events
349
+ let events: FeedbackEvent[] = [];
350
+ try {
351
+ events = row.feedback_events ? JSON.parse(row.feedback_events) : [];
352
+ } catch {
353
+ events = [];
354
+ }
355
+
356
+ // Append new event
357
+ const newEvent: FeedbackEvent = {
358
+ type: feedbackType,
359
+ timestamp: Date.now(),
360
+ reason,
361
+ session_id: sessionId,
362
+ };
363
+ events.push(newEvent);
364
+
365
+ const helpfulCount =
366
+ feedbackType === "helpful" ? row.helpful_count + 1 : row.helpful_count;
367
+ const harmfulCount =
368
+ feedbackType === "harmful" ? row.harmful_count + 1 : row.harmful_count;
369
+
370
+ // Persist
371
+ db.run(
372
+ `UPDATE observations SET
373
+ helpful_count = ?,
374
+ harmful_count = ?,
375
+ feedback_events = ?,
376
+ updated_at = ?
377
+ WHERE id = ?`,
378
+ [
379
+ helpfulCount,
380
+ harmfulCount,
381
+ JSON.stringify(events),
382
+ new Date().toISOString(),
383
+ observationId,
384
+ ],
385
+ );
386
+
387
+ return { success: true, helpfulCount, harmfulCount };
388
+ }
389
+
390
+ /**
391
+ * Increment retrieval_count and update last_retrieved for given observation IDs.
392
+ */
393
+ export function markObservationsRetrieved(ids: number[]): void {
394
+ if (ids.length === 0) return;
395
+ const db = getMemoryDB();
396
+ const now = new Date().toISOString();
397
+ const stmt = db.query(
398
+ `UPDATE observations SET retrieval_count = retrieval_count + 1, last_retrieved = ? WHERE id = ?`,
399
+ );
400
+ for (const id of ids) {
401
+ stmt.run(now, id);
402
+ }
403
+ }
@@ -126,7 +126,7 @@ function logRecovery(message: string): void {
126
126
  // Schema v3 (v2 + navigation, entity graph, raw source, chunk type)
127
127
  // ============================================================================
128
128
 
129
- const SCHEMA_VERSION = 3;
129
+ const SCHEMA_VERSION = 4;
130
130
 
131
131
  const SCHEMA_SQL = `
132
132
  -- Schema versioning for migrations
@@ -158,6 +158,13 @@ CREATE TABLE IF NOT EXISTS observations (
158
158
  wing TEXT,
159
159
  hall TEXT CHECK(hall IS NULL OR hall IN ('facts','events','discoveries','preferences','advice')),
160
160
  room TEXT,
161
+ helpful_count INTEGER NOT NULL DEFAULT 0,
162
+ harmful_count INTEGER NOT NULL DEFAULT 0,
163
+ feedback_events TEXT,
164
+ effective_score REAL DEFAULT 0,
165
+ maturity TEXT DEFAULT 'active',
166
+ retrieval_count INTEGER DEFAULT 0,
167
+ last_retrieved TEXT,
161
168
  created_at TEXT NOT NULL,
162
169
  created_at_epoch INTEGER NOT NULL,
163
170
  updated_at TEXT,
@@ -610,6 +617,9 @@ function initializeSchema(db: Database): void {
610
617
  if (currentVersion < 3) {
611
618
  migrateV2ToV3(db);
612
619
  }
620
+ if (currentVersion < 4) {
621
+ migrateV3ToV4(db);
622
+ }
613
623
  }
614
624
 
615
625
  // Record schema version
@@ -685,3 +695,35 @@ function migrateV2ToV3(db: Database): void {
685
695
  }
686
696
  }
687
697
  }
698
+
699
+ // ============================================================================
700
+ // Schema v4: Pikit alignment — feedback, scoring, and tracking columns
701
+ // ============================================================================
702
+
703
+ const MIGRATION_V3_TO_V4 = `
704
+ ALTER TABLE observations ADD COLUMN helpful_count INTEGER NOT NULL DEFAULT 0;
705
+ ALTER TABLE observations ADD COLUMN harmful_count INTEGER NOT NULL DEFAULT 0;
706
+ ALTER TABLE observations ADD COLUMN feedback_events TEXT;
707
+ ALTER TABLE observations ADD COLUMN effective_score REAL DEFAULT 0;
708
+ ALTER TABLE observations ADD COLUMN maturity TEXT DEFAULT 'active';
709
+ ALTER TABLE observations ADD COLUMN retrieval_count INTEGER DEFAULT 0;
710
+ ALTER TABLE observations ADD COLUMN last_retrieved TEXT;
711
+ `;
712
+
713
+ /**
714
+ * Migrate from schema v3 to v4.
715
+ * Adds: helpful_count, harmful_count, feedback_events, effective_score,
716
+ * maturity, retrieval_count, last_retrieved.
717
+ */
718
+ function migrateV3ToV4(db: Database): void {
719
+ for (const stmt of MIGRATION_V3_TO_V4.split(";")) {
720
+ const trimmed = stmt.trim();
721
+ if (trimmed) {
722
+ try {
723
+ db.run(trimmed);
724
+ } catch {
725
+ // Statement may fail if already applied (e.g. column exists)
726
+ }
727
+ }
728
+ }
729
+ }
@@ -145,6 +145,13 @@ export interface ObservationRow {
145
145
  wing: string | null; // v3: navigation wing (project/person)
146
146
  hall: HallType | null; // v3: navigation hall (facts/events/...)
147
147
  room: string | null; // v3: navigation room (topic)
148
+ helpful_count: number;
149
+ harmful_count: number;
150
+ feedback_events: string | null; // JSON array of FeedbackEvent
151
+ effective_score: number | null;
152
+ maturity: string | null;
153
+ retrieval_count: number | null;
154
+ last_retrieved: string | null;
148
155
  created_at: string;
149
156
  created_at_epoch: number;
150
157
  updated_at: string | null;
@@ -282,3 +289,18 @@ export interface ArchiveOptions {
282
289
  /** Dry run — don't actually archive, just count */
283
290
  dryRun?: boolean;
284
291
  }
292
+
293
+ // ============================================================================
294
+ // Feedback & Scoring Types (aligned with pikit memory extension)
295
+ // ============================================================================
296
+
297
+ export type FeedbackType = "helpful" | "harmful";
298
+
299
+ export interface FeedbackEvent {
300
+ type: FeedbackType;
301
+ timestamp: number; // Date.now()
302
+ reason?: string;
303
+ session_id?: string;
304
+ }
305
+
306
+ export type MaturityState = "candidate" | "active" | "stale" | "deprecated";
@@ -2,7 +2,7 @@
2
2
  * Memory Database Module v3 — Barrel Export
3
3
  *
4
4
  * Re-exports all functions and types from sub-modules in ./db/.
5
- * This preserves backward compatibility for existing imports from "./lib/memory-db.js".
5
+ * This preserves backward compatibility for existing imports from "./db.js".
6
6
  *
7
7
  * Sub-module structure:
8
8
  * db/types.ts — Configuration, types, interfaces
@@ -16,7 +16,7 @@ import {
16
16
  markMessagesDistilled,
17
17
  storeDistillation,
18
18
  type TemporalMessageRow,
19
- } from "./memory-db.js";
19
+ } from "./db.js";
20
20
 
21
21
  // ============================================================================
22
22
  // TF-IDF Engine
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import { readFile } from "node:fs/promises";
9
- import type { ObservationType } from "./memory-db.js";
9
+ import type { ObservationType } from "./db.js";
10
10
 
11
11
  // ============================================================================
12
12
  // Constants
@@ -120,6 +120,8 @@ export function formatObservation(obs: {
120
120
  supersedes?: number | null;
121
121
  superseded_by?: number | null;
122
122
  source?: string | null;
123
+ helpful_count?: number | null;
124
+ harmful_count?: number | null;
123
125
  created_at?: string | null;
124
126
  }): string {
125
127
  const icon = TYPE_ICONS[obs.type] ?? "\uD83D\uDCCC";
@@ -135,6 +137,8 @@ export function formatObservation(obs: {
135
137
  if (obs.bead_id) lines.push(` Bead: ${obs.bead_id}`);
136
138
  if (obs.supersedes) lines.push(` Supersedes: #${obs.supersedes}`);
137
139
  if (obs.superseded_by) lines.push(` Superseded by: #${obs.superseded_by}`);
140
+ if ((obs.helpful_count ?? 0) > 0 || (obs.harmful_count ?? 0) > 0)
141
+ lines.push(` Feedback: ${obs.helpful_count ?? 0}\uD83D\uDC4D / ${obs.harmful_count ?? 0}\uD83D\uDC4E`);
138
142
  if (obs.narrative) lines.push(`\n${obs.narrative}`);
139
143
  if (obs.created_at) lines.push(`\n _Created: ${obs.created_at}_`);
140
144
  return lines.join("\n");
@@ -26,7 +26,7 @@ import {
26
26
  checkpointWAL,
27
27
  getDatabaseSizes,
28
28
  optimizeFTS5,
29
- } from "./memory-db.js";
29
+ } from "./db.js";
30
30
 
31
31
  interface HookDeps {
32
32
  showToast: (
@@ -10,8 +10,8 @@
10
10
 
11
11
  import { upsertMemoryFile } from "./db/maintenance.js";
12
12
  import type { ObservationRow } from "./db/types.js";
13
- import { getMemoryDB } from "./memory-db.js";
14
- import { TYPE_ICONS, parseConcepts } from "./memory-helpers.js";
13
+ import { getMemoryDB } from "./db.js";
14
+ import { TYPE_ICONS, parseConcepts } from "./helpers.js";
15
15
 
16
16
  // ============================================================================
17
17
  // Types
@@ -13,7 +13,7 @@ import {
13
13
  estimateTokens,
14
14
  getRelevantKnowledge,
15
15
  MEMORY_CONFIG,
16
- } from "./memory-db.js";
16
+ } from "./db.js";
17
17
 
18
18
  // ============================================================================
19
19
  // Query Term Extraction
@@ -9,8 +9,8 @@
9
9
  */
10
10
 
11
11
  import type { ObservationRow } from "./db/types.js";
12
- import { getMemoryDB } from "./memory-db.js";
13
- import { hasWord, parseConcepts } from "./memory-helpers.js";
12
+ import { getMemoryDB } from "./db.js";
13
+ import { hasWord, parseConcepts } from "./helpers.js";
14
14
 
15
15
  // ============================================================================
16
16
  // Types
@@ -0,0 +1,322 @@
1
+ /**
2
+ * Core Memory Tools
3
+ *
4
+ * Two tools aligned with pikit memory extension:
5
+ * - observation: create observations OR give feedback on existing ones
6
+ * - memory-search: search observations by text OR read memory files by path
7
+ */
8
+
9
+ import { tool, type ToolContext } from "@opencode-ai/plugin/tool";
10
+ import {
11
+ type ConfidenceLevel,
12
+ type ObservationSource,
13
+ type ObservationType,
14
+ type HallType,
15
+ VALID_HALLS,
16
+ } from "./db/types.js";
17
+ import {
18
+ autoDetectFiles,
19
+ parseCSV,
20
+ formatObservation,
21
+ TYPE_ICONS,
22
+ VALID_TYPES,
23
+ } from "./helpers.js";
24
+ import { validateObservation } from "./validate.js";
25
+ import {
26
+ storeObservation,
27
+ getObservationById,
28
+ searchObservationsFTS,
29
+ recordFeedback,
30
+ markObservationsRetrieved,
31
+ } from "./db/observations.js";
32
+ import { getMemoryFile } from "./db/maintenance.js";
33
+
34
+ // ============================================================================
35
+ // Error Handling Wrapper
36
+ // ============================================================================
37
+
38
+ function withDBErrorHandling<T extends Record<string, unknown>>(
39
+ handler: (args: T) => string | Promise<string>,
40
+ ): (args: T, context: ToolContext) => Promise<string> {
41
+ return async (args: T, _context: ToolContext) => {
42
+ try {
43
+ return await handler(args);
44
+ } catch (err) {
45
+ const msg = err instanceof Error ? err.message : String(err);
46
+ return `Error: ${msg}`;
47
+ }
48
+ };
49
+ }
50
+
51
+ // ============================================================================
52
+ // Tool Definitions
53
+ // ============================================================================
54
+
55
+ interface CoreToolDeps {
56
+ handoffDir: string;
57
+ }
58
+
59
+ export function createCoreTools(deps: CoreToolDeps) {
60
+ const { handoffDir } = deps;
61
+
62
+ return {
63
+ // --------------------------------------------------------------------
64
+ // observation: Create or give feedback
65
+ // --------------------------------------------------------------------
66
+ observation: tool({
67
+ description: `Create a durable observation for future retrieval, or mark an existing one as helpful/harmful.
68
+ Pass id+feedback for feedback mode; pass type+title for create mode.
69
+
70
+ Create mode captures decisions, bugs, features, patterns, discoveries, learnings, or warnings.
71
+ Feedback mode lets you rate past observations.
72
+
73
+ Create mode examples:
74
+ observation({ type: "decision", title: "Use JWT for auth", narrative: "Stateless across services.", confidence: "high" })
75
+ observation({ type: "bugfix", title: "Fix null pointer", files_modified: "src/auth.ts" })
76
+
77
+ Feedback mode examples:
78
+ observation({ id: 42, feedback: "helpful" })
79
+ observation({ id: 42, feedback: "harmful", reason: "Outdated information" })`,
80
+ args: {
81
+ // --- Create mode params ---
82
+ type: tool.schema
83
+ .string()
84
+ .optional()
85
+ .describe(
86
+ "Observation type for create mode: decision, bugfix, feature, pattern, discovery, learning, warning",
87
+ ),
88
+ title: tool.schema.string().optional().describe("Short title (create mode)"),
89
+ subtitle: tool.schema.string().optional().describe("Optional subtitle"),
90
+ facts: tool.schema
91
+ .string()
92
+ .optional()
93
+ .describe("Comma-separated key facts"),
94
+ narrative: tool.schema
95
+ .string()
96
+ .optional()
97
+ .describe("Detailed context"),
98
+ content: tool.schema
99
+ .string()
100
+ .optional()
101
+ .describe("Alias for narrative"),
102
+ concepts: tool.schema
103
+ .string()
104
+ .optional()
105
+ .describe("Comma-separated concepts"),
106
+ files_read: tool.schema
107
+ .string()
108
+ .optional()
109
+ .describe("Comma-separated files read"),
110
+ files_modified: tool.schema
111
+ .string()
112
+ .optional()
113
+ .describe("Comma-separated files modified"),
114
+ files: tool.schema
115
+ .string()
116
+ .optional()
117
+ .describe("Alias for files_modified"),
118
+ bead_id: tool.schema.string().optional().describe("Related bead ID"),
119
+ confidence: tool.schema
120
+ .string()
121
+ .optional()
122
+ .describe("high, medium, or low"),
123
+ supersedes: tool.schema
124
+ .string()
125
+ .optional()
126
+ .describe("Observation ID this supersedes"),
127
+ source: tool.schema
128
+ .string()
129
+ .optional()
130
+ .describe("manual, curator, or imported"),
131
+ hall: tool.schema
132
+ .string()
133
+ .optional()
134
+ .describe("Navigation hall: facts, events, discoveries, preferences, advice"),
135
+
136
+ // --- Feedback mode params ---
137
+ id: tool.schema
138
+ .number()
139
+ .optional()
140
+ .describe("Observation ID for feedback mode"),
141
+ feedback: tool.schema
142
+ .string()
143
+ .optional()
144
+ .describe('"helpful" or "harmful" (feedback mode)'),
145
+ reason: tool.schema
146
+ .string()
147
+ .optional()
148
+ .describe("Optional reason for feedback"),
149
+ },
150
+ execute: withDBErrorHandling(async (args) => {
151
+ // --- Feedback mode: observation #id marked helpful/harmful ---
152
+ if (args.id !== undefined && args.feedback !== undefined) {
153
+ const obsId = Number(args.id);
154
+ if (!Number.isInteger(obsId)) return "❌ id must be an integer.";
155
+ const fb = String(args.feedback);
156
+ if (fb !== "helpful" && fb !== "harmful") return '❌ feedback must be "helpful" or "harmful".';
157
+
158
+ const result = recordFeedback(obsId, fb, args.reason as string | undefined);
159
+ if (!result.success) return `❌ ${result.error ?? "Failed to record feedback."}`;
160
+
161
+ return [
162
+ `✅ Observation #${obsId} marked as ${fb}.`,
163
+ `- Feedback: ${result.helpfulCount} helpful / ${result.harmfulCount} harmful`,
164
+ ].join("\n");
165
+ }
166
+
167
+ // --- Create mode: store a new observation ---
168
+ if (!args.type || !args.title) {
169
+ return "❌ Provide type+title to create an observation, or id+feedback to give feedback.";
170
+ }
171
+
172
+ const obsType = args.type as ObservationType;
173
+ if (!VALID_TYPES.includes(obsType)) {
174
+ return `Error: Invalid type "${args.type}". Valid: ${VALID_TYPES.join(", ")}`;
175
+ }
176
+
177
+ const confidence = (args.confidence ?? "high") as ConfidenceLevel;
178
+ if (!["high", "medium", "low"].includes(confidence)) {
179
+ return `Error: Invalid confidence "${args.confidence}". Valid: high, medium, low`;
180
+ }
181
+
182
+ const narrative = args.narrative ?? args.content;
183
+ const facts = parseCSV(args.facts);
184
+ const concepts = parseCSV(args.concepts);
185
+ let filesRead = parseCSV(args.files_read);
186
+ const filesModified = parseCSV(args.files_modified ?? args.files);
187
+
188
+ // Auto-detect files from narrative if not explicitly provided
189
+ if (!filesRead && narrative) {
190
+ const detected = autoDetectFiles(narrative);
191
+ if (detected.length > 0) filesRead = detected;
192
+ }
193
+
194
+ let supersedes: number | undefined;
195
+ if (args.supersedes) {
196
+ const parsed = Number.parseInt(args.supersedes, 10);
197
+ if (!Number.isNaN(parsed)) supersedes = parsed;
198
+ }
199
+
200
+ const source = (args.source ?? "manual") as ObservationSource;
201
+ const hall = args.hall as HallType | undefined;
202
+
203
+ // Validation gate: check for duplicates, contradictions, low quality
204
+ const validation = validateObservation({
205
+ type: obsType,
206
+ title: args.title,
207
+ facts,
208
+ narrative,
209
+ concepts,
210
+ confidence,
211
+ });
212
+
213
+ if (validation.verdict === "reject") {
214
+ const reasons = validation.issues.map(i => i.message).join("; ");
215
+ const dupHint = validation.duplicateOf
216
+ ? ` Use \`observation({ supersedes: "${validation.duplicateOf}", ... })\` to update it.`
217
+ : "";
218
+ return `Rejected: ${reasons}.${dupHint}`;
219
+ }
220
+
221
+ const id = storeObservation({
222
+ type: obsType,
223
+ title: args.title,
224
+ subtitle: args.subtitle,
225
+ facts,
226
+ narrative,
227
+ concepts,
228
+ files_read: filesRead,
229
+ files_modified: filesModified,
230
+ confidence,
231
+ bead_id: args.bead_id,
232
+ supersedes,
233
+ source,
234
+ hall,
235
+ });
236
+
237
+ const warnings = validation.issues.length > 0
238
+ ? `\n⚠️ Warnings: ${validation.issues.map(i => i.message).join("; ")}`
239
+ : "";
240
+
241
+ return `${TYPE_ICONS[obsType] ?? "📌"} Observation #${id} stored [${obsType}] "${args.title}" (confidence: ${confidence}, source: ${source})${warnings}`;
242
+ }),
243
+ }),
244
+
245
+ // --------------------------------------------------------------------
246
+ // memory-search: Search or read memory
247
+ // --------------------------------------------------------------------
248
+ "memory-search": tool({
249
+ description: `Search observations by text query / #id references, or read a memory file by path.
250
+ Pass file=path to read a memory file; pass query=text to search observations.
251
+
252
+ Search modes:
253
+ - query only: Search observations using FTS5 (falls back to LIKE)
254
+ - query + type: Filter observations by type (decision, bugfix, etc.)
255
+ - file=path: Read a memory file (e.g. persona/default, scenes/<id>)
256
+ - #id refs: Lookup observations by ID number`,
257
+ args: {
258
+ query: tool.schema
259
+ .string()
260
+ .optional()
261
+ .describe("Search query or #id references"),
262
+ type: tool.schema
263
+ .string()
264
+ .optional()
265
+ .describe("Optional observation type filter"),
266
+ limit: tool.schema
267
+ .number()
268
+ .optional()
269
+ .describe("Maximum results, default 10"),
270
+ file: tool.schema
271
+ .string()
272
+ .optional()
273
+ .describe("Memory file path (e.g. persona/default, scenes/<id>)"),
274
+ },
275
+ execute: withDBErrorHandling(async (args) => {
276
+ const limit = Math.min(args.limit ?? 10, 50);
277
+
278
+ // --- File mode: read a memory file by path ---
279
+ if (args.file) {
280
+ const filePath = String(args.file);
281
+ const row = getMemoryFile(filePath);
282
+ if (!row) return `Memory file not found: ${filePath}`;
283
+ return row.content;
284
+ }
285
+
286
+ // --- ID refs mode: resolve #N references ---
287
+ if (args.query) {
288
+ const query = String(args.query);
289
+ const idRefs = [...query.matchAll(/#(\d+)/g)].map(m => parseInt(m[1], 10));
290
+ if (idRefs.length > 0) {
291
+ const rows = idRefs
292
+ .map(id => getObservationById(id))
293
+ .filter((r): r is NonNullable<typeof r> => r !== null);
294
+ if (rows.length === 0) return "No observations found for the requested IDs.";
295
+ return rows.map(r => formatObservation(r)).join("\n\n---\n\n");
296
+ }
297
+ }
298
+
299
+ // --- Search mode ---
300
+ const query = args.query ? String(args.query).trim() : "";
301
+ const scope = (args.type ?? "observations") as string;
302
+ const typeFilter = VALID_TYPES.includes(scope as ObservationType)
303
+ ? (scope as ObservationType)
304
+ : undefined;
305
+
306
+ let rows;
307
+ try {
308
+ rows = searchObservationsFTS(query, { type: typeFilter, limit });
309
+ } catch {
310
+ return "Search failed.";
311
+ }
312
+
313
+ if (rows.length === 0) return "No matching observations found.";
314
+
315
+ // Track retrieval
316
+ markObservationsRetrieved(rows.map(r => r.id));
317
+
318
+ return rows.map(r => formatObservation(r)).join("\n\n---\n\n");
319
+ }),
320
+ }),
321
+ };
322
+ }