opencodekit 0.21.10 → 0.23.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 (213) hide show
  1. package/README.md +1 -1
  2. package/dist/index.js +4 -25
  3. package/dist/template/.opencode/.template-manifest.json +115 -188
  4. package/dist/template/.opencode/AGENTS.md +127 -484
  5. package/dist/template/.opencode/README.md +2 -2
  6. package/dist/template/.opencode/agent/build.md +158 -356
  7. package/dist/template/.opencode/agent/explore.md +0 -1
  8. package/dist/template/.opencode/agent/plan.md +7 -16
  9. package/dist/template/.opencode/agent/review.md +0 -1
  10. package/dist/template/.opencode/agent/scout.md +2 -3
  11. package/dist/template/.opencode/agent/vision.md +0 -1
  12. package/dist/template/.opencode/artifacts/.active +1 -0
  13. package/dist/template/.opencode/artifacts/example/plan.md +12 -0
  14. package/dist/template/.opencode/artifacts/example/progress.md +4 -0
  15. package/dist/template/.opencode/artifacts/example/research.md +4 -0
  16. package/dist/template/.opencode/artifacts/example/spec.md +16 -0
  17. package/dist/template/.opencode/artifacts/todo.md +5 -0
  18. package/dist/template/.opencode/artifacts/verify.log +4 -0
  19. package/dist/template/.opencode/command/clarify.md +46 -0
  20. package/dist/template/.opencode/command/commit.md +53 -0
  21. package/dist/template/.opencode/command/create.md +29 -71
  22. package/dist/template/.opencode/command/design.md +1 -2
  23. package/dist/template/.opencode/command/explore.md +3 -4
  24. package/dist/template/.opencode/command/fix.md +55 -0
  25. package/dist/template/.opencode/command/improve-architecture.md +55 -0
  26. package/dist/template/.opencode/command/init.md +86 -69
  27. package/dist/template/.opencode/command/plan.md +30 -60
  28. package/dist/template/.opencode/command/pr.md +10 -28
  29. package/dist/template/.opencode/command/refactor.md +65 -0
  30. package/dist/template/.opencode/command/research.md +7 -29
  31. package/dist/template/.opencode/command/review-codebase.md +6 -13
  32. package/dist/template/.opencode/command/ship.md +136 -78
  33. package/dist/template/.opencode/command/test.md +66 -0
  34. package/dist/template/.opencode/command/ui-review.md +2 -4
  35. package/dist/template/.opencode/command/verify.md +15 -23
  36. package/dist/template/.opencode/dcp.jsonc +96 -85
  37. package/dist/template/.opencode/memory/README.md +4 -6
  38. package/dist/template/.opencode/memory/_templates/adr.md +45 -0
  39. package/dist/template/.opencode/memory/_templates/prd.md +1 -1
  40. package/dist/template/.opencode/memory/_templates/roadmap.md +1 -1
  41. package/dist/template/.opencode/memory/_templates/state.md +1 -1
  42. package/dist/template/.opencode/memory/project/gotchas.md +4 -4
  43. package/dist/template/.opencode/memory/project/project.md +2 -2
  44. package/dist/template/.opencode/memory/project/roadmap.md +1 -1
  45. package/dist/template/.opencode/memory/project/state.md +2 -2
  46. package/dist/template/.opencode/memory/project/tech-stack.md +2 -2
  47. package/dist/template/.opencode/memory/session-context.md +1 -1
  48. package/dist/template/.opencode/opencode.json +14 -152
  49. package/dist/template/.opencode/plugin/README.md +2 -2
  50. package/dist/template/.opencode/plugin/guard.ts +62 -0
  51. package/dist/template/.opencode/plugin/{lib/memory-admin-tools.ts → memory/admin.ts} +4 -4
  52. package/dist/template/.opencode/plugin/{lib → memory}/capture.ts +1 -1
  53. package/dist/template/.opencode/plugin/{lib → memory}/compile.ts +2 -2
  54. package/dist/template/.opencode/plugin/{lib → memory}/context.ts +1 -1
  55. package/dist/template/.opencode/plugin/{lib → memory}/curator.ts +1 -1
  56. package/dist/template/.opencode/plugin/{lib → memory}/db/observations.ts +102 -3
  57. package/dist/template/.opencode/plugin/{lib → memory}/db/schema.ts +43 -1
  58. package/dist/template/.opencode/plugin/{lib → memory}/db/types.ts +22 -0
  59. package/dist/template/.opencode/plugin/{lib/memory-db.ts → memory/db.ts} +1 -1
  60. package/dist/template/.opencode/plugin/{lib → memory}/distill.ts +1 -1
  61. package/dist/template/.opencode/plugin/{lib/memory-helpers.ts → memory/helpers.ts} +5 -1
  62. package/dist/template/.opencode/plugin/{lib/memory-hooks.ts → memory/hooks.ts} +1 -1
  63. package/dist/template/.opencode/plugin/{lib → memory}/index-generator.ts +2 -2
  64. package/dist/template/.opencode/plugin/{lib → memory}/inject.ts +1 -1
  65. package/dist/template/.opencode/plugin/{lib → memory}/lint.ts +2 -2
  66. package/dist/template/.opencode/plugin/memory/tools.ts +322 -0
  67. package/dist/template/.opencode/plugin/{lib → memory}/validate.ts +2 -2
  68. package/dist/template/.opencode/plugin/memory.ts +7 -17
  69. package/dist/template/.opencode/plugin/srcwalk.ts +721 -0
  70. package/dist/template/.opencode/skill/agent-code-quality-gate/SKILL.md +98 -0
  71. package/dist/template/.opencode/skill/behavioral-kernel/SKILL.md +52 -0
  72. package/dist/template/.opencode/skill/brainstorming/SKILL.md +1 -1
  73. package/dist/template/.opencode/skill/browser-testing-with-devtools/SKILL.md +85 -0
  74. package/dist/template/.opencode/skill/code-cleanup/SKILL.md +114 -0
  75. package/dist/template/.opencode/skill/code-navigation/SKILL.md +142 -0
  76. package/dist/template/.opencode/skill/code-review-and-quality/SKILL.md +131 -0
  77. package/dist/template/.opencode/skill/context-engineering/SKILL.md +1 -1
  78. package/dist/template/.opencode/skill/debugging-and-error-recovery/SKILL.md +109 -0
  79. package/dist/template/.opencode/skill/deep-module-design/SKILL.md +207 -0
  80. package/dist/template/.opencode/skill/development-lifecycle/SKILL.md +26 -45
  81. package/dist/template/.opencode/skill/gemini-large-context/SKILL.md +4 -4
  82. package/dist/template/.opencode/skill/git-workflow-and-versioning/SKILL.md +77 -0
  83. package/dist/template/.opencode/skill/grill-me/SKILL.md +140 -0
  84. package/dist/template/.opencode/skill/memory-system/SKILL.md +9 -10
  85. package/dist/template/.opencode/skill/opensrc/references/example-workflow.md +1 -1
  86. package/dist/template/.opencode/skill/planning-and-task-breakdown/SKILL.md +116 -0
  87. package/dist/template/.opencode/skill/shipping-and-launch/SKILL.md +95 -0
  88. package/dist/template/.opencode/skill/source-driven-development/SKILL.md +103 -0
  89. package/dist/template/.opencode/skill/spec-driven-development/SKILL.md +121 -0
  90. package/dist/template/.opencode/skill/srcwalk/SKILL.md +161 -0
  91. package/dist/template/.opencode/skill/subagent-driven-development/SKILL.md +1 -1
  92. package/dist/template/.opencode/skill/ubiquitous-language/SKILL.md +184 -0
  93. package/dist/template/.opencode/skill/using-git-worktrees/SKILL.md +6 -6
  94. package/dist/template/.opencode/skill/verification-before-completion/SKILL.md +6 -6
  95. package/dist/template/.opencode/skill/verification-before-completion/references/VERIFICATION_PROTOCOL.md +5 -5
  96. package/package.json +76 -76
  97. package/dist/template/.opencode/AGENT_ALIGNMENT.md +0 -564
  98. package/dist/template/.opencode/agent/painter.md +0 -83
  99. package/dist/template/.opencode/command/compound.md +0 -240
  100. package/dist/template/.opencode/command/curate.md +0 -299
  101. package/dist/template/.opencode/command/handoff.md +0 -149
  102. package/dist/template/.opencode/command/health.md +0 -356
  103. package/dist/template/.opencode/command/init-context.md +0 -297
  104. package/dist/template/.opencode/command/init-user.md +0 -125
  105. package/dist/template/.opencode/command/iterate.md +0 -200
  106. package/dist/template/.opencode/command/lfg.md +0 -173
  107. package/dist/template/.opencode/command/resume.md +0 -78
  108. package/dist/template/.opencode/command/status.md +0 -126
  109. package/dist/template/.opencode/command/ui-slop-check.md +0 -169
  110. package/dist/template/.opencode/plans/1768385996691-silent-wizard.md +0 -247
  111. package/dist/template/.opencode/plans/1770006237537-mighty-otter.md +0 -418
  112. package/dist/template/.opencode/plans/1770006913647-glowing-forest.md +0 -170
  113. package/dist/template/.opencode/plans/1770013678126-witty-planet.md +0 -278
  114. package/dist/template/.opencode/plans/1770112267595-shiny-rocket.md +0 -258
  115. package/dist/template/.opencode/plans/swarm-protocol.md +0 -123
  116. package/dist/template/.opencode/plugin/lib/memory-tools.ts +0 -535
  117. package/dist/template/.opencode/skill/agent-evals/SKILL.md +0 -208
  118. package/dist/template/.opencode/skill/anti-ai-slop/SKILL.md +0 -76
  119. package/dist/template/.opencode/skill/augment-context-engine/SKILL.md +0 -122
  120. package/dist/template/.opencode/skill/augment-context-engine/mcp.json +0 -6
  121. package/dist/template/.opencode/skill/beads/SKILL.md +0 -182
  122. package/dist/template/.opencode/skill/beads/references/BEST_PRACTICES.md +0 -27
  123. package/dist/template/.opencode/skill/beads/references/BOUNDARIES.md +0 -219
  124. package/dist/template/.opencode/skill/beads/references/DEPENDENCIES.md +0 -124
  125. package/dist/template/.opencode/skill/beads/references/EXAMPLES.md +0 -45
  126. package/dist/template/.opencode/skill/beads/references/FILE_CLAIMING.md +0 -101
  127. package/dist/template/.opencode/skill/beads/references/GIT_SYNC.md +0 -25
  128. package/dist/template/.opencode/skill/beads/references/HIERARCHY.md +0 -71
  129. package/dist/template/.opencode/skill/beads/references/MULTI_AGENT.md +0 -40
  130. package/dist/template/.opencode/skill/beads/references/RESUMABILITY.md +0 -177
  131. package/dist/template/.opencode/skill/beads/references/SESSION_PROTOCOL.md +0 -61
  132. package/dist/template/.opencode/skill/beads/references/TASK_CREATION.md +0 -38
  133. package/dist/template/.opencode/skill/beads/references/TROUBLESHOOTING.md +0 -38
  134. package/dist/template/.opencode/skill/beads/references/WORKFLOWS.md +0 -226
  135. package/dist/template/.opencode/skill/brand-asset-protocol/SKILL.md +0 -222
  136. package/dist/template/.opencode/skill/code-search-patterns/SKILL.md +0 -224
  137. package/dist/template/.opencode/skill/code-simplification/SKILL.md +0 -211
  138. package/dist/template/.opencode/skill/context-condensation/SKILL.md +0 -149
  139. package/dist/template/.opencode/skill/context-initialization/SKILL.md +0 -69
  140. package/dist/template/.opencode/skill/context-management/SKILL.md +0 -390
  141. package/dist/template/.opencode/skill/deep-research/SKILL.md +0 -384
  142. package/dist/template/.opencode/skill/design-direction-advisor/SKILL.md +0 -139
  143. package/dist/template/.opencode/skill/dispatching-parallel-agents/SKILL.md +0 -191
  144. package/dist/template/.opencode/skill/executing-plans/SKILL.md +0 -247
  145. package/dist/template/.opencode/skill/figma-go/SKILL.md +0 -65
  146. package/dist/template/.opencode/skill/finishing-a-development-branch/SKILL.md +0 -357
  147. package/dist/template/.opencode/skill/full-output-enforcement/SKILL.md +0 -62
  148. package/dist/template/.opencode/skill/gh-address-comments/SKILL.md +0 -29
  149. package/dist/template/.opencode/skill/gh-address-comments/scripts/fetch_comments.py +0 -237
  150. package/dist/template/.opencode/skill/gh-fix-ci/SKILL.md +0 -38
  151. package/dist/template/.opencode/skill/gh-fix-ci/scripts/inspect_pr_checks.py +0 -509
  152. package/dist/template/.opencode/skill/hi-fi-prototype-html/SKILL.md +0 -253
  153. package/dist/template/.opencode/skill/html-deck-export/SKILL.md +0 -189
  154. package/dist/template/.opencode/skill/index-knowledge/SKILL.md +0 -413
  155. package/dist/template/.opencode/skill/memory-grounding/SKILL.md +0 -68
  156. package/dist/template/.opencode/skill/playwriter/SKILL.md +0 -158
  157. package/dist/template/.opencode/skill/portless/SKILL.md +0 -109
  158. package/dist/template/.opencode/skill/prd/SKILL.md +0 -146
  159. package/dist/template/.opencode/skill/prd-task/SKILL.md +0 -182
  160. package/dist/template/.opencode/skill/prd-task/references/prd-schema.json +0 -124
  161. package/dist/template/.opencode/skill/prompt-leverage/SKILL.md +0 -90
  162. package/dist/template/.opencode/skill/prompt-leverage/references/framework.md +0 -91
  163. package/dist/template/.opencode/skill/prompt-leverage/scripts/augment_prompt.py +0 -157
  164. package/dist/template/.opencode/skill/receiving-code-review/SKILL.md +0 -263
  165. package/dist/template/.opencode/skill/reconcile/SKILL.md +0 -183
  166. package/dist/template/.opencode/skill/reflection-checkpoints/SKILL.md +0 -183
  167. package/dist/template/.opencode/skill/requesting-code-review/SKILL.md +0 -443
  168. package/dist/template/.opencode/skill/requesting-code-review/references/specialist-profiles.md +0 -108
  169. package/dist/template/.opencode/skill/requesting-code-review/review.md +0 -160
  170. package/dist/template/.opencode/skill/rtk-command-compression/SKILL.md +0 -134
  171. package/dist/template/.opencode/skill/screenshot/SKILL.md +0 -48
  172. package/dist/template/.opencode/skill/screenshot/scripts/ensure_macos_permissions.sh +0 -54
  173. package/dist/template/.opencode/skill/screenshot/scripts/macos_display_info.swift +0 -22
  174. package/dist/template/.opencode/skill/screenshot/scripts/macos_permissions.swift +0 -40
  175. package/dist/template/.opencode/skill/screenshot/scripts/macos_window_info.swift +0 -126
  176. package/dist/template/.opencode/skill/screenshot/scripts/take_screenshot.ps1 +0 -163
  177. package/dist/template/.opencode/skill/screenshot/scripts/take_screenshot.py +0 -585
  178. package/dist/template/.opencode/skill/security-threat-model/SKILL.md +0 -36
  179. package/dist/template/.opencode/skill/security-threat-model/references/prompt-template.md +0 -255
  180. package/dist/template/.opencode/skill/security-threat-model/references/security-controls-and-assets.md +0 -32
  181. package/dist/template/.opencode/skill/sharing-skills/SKILL.md +0 -214
  182. package/dist/template/.opencode/skill/skill-creator/SKILL.md +0 -181
  183. package/dist/template/.opencode/skill/skill-installer/SKILL.md +0 -58
  184. package/dist/template/.opencode/skill/skill-installer/scripts/github_utils.py +0 -21
  185. package/dist/template/.opencode/skill/skill-installer/scripts/install-skill-from-github.py +0 -313
  186. package/dist/template/.opencode/skill/skill-installer/scripts/list-skills.py +0 -106
  187. package/dist/template/.opencode/skill/swarm-coordination/SKILL.md +0 -244
  188. package/dist/template/.opencode/skill/swarm-coordination/references/architecture.md +0 -39
  189. package/dist/template/.opencode/skill/swarm-coordination/references/delegation-worker-protocol.md +0 -145
  190. package/dist/template/.opencode/skill/swarm-coordination/references/dependency-graph.md +0 -50
  191. package/dist/template/.opencode/skill/swarm-coordination/references/drift-check.md +0 -90
  192. package/dist/template/.opencode/skill/swarm-coordination/references/integration-beads.md +0 -20
  193. package/dist/template/.opencode/skill/swarm-coordination/references/launch-flow.md +0 -186
  194. package/dist/template/.opencode/skill/swarm-coordination/references/reconciler.md +0 -172
  195. package/dist/template/.opencode/skill/swarm-coordination/references/tier-enforcement.md +0 -78
  196. package/dist/template/.opencode/skill/swarm-coordination/references/tmux-integration.md +0 -134
  197. package/dist/template/.opencode/skill/systematic-debugging/SKILL.md +0 -402
  198. package/dist/template/.opencode/skill/terse-output-mode/SKILL.md +0 -95
  199. package/dist/template/.opencode/skill/think-in-code/SKILL.md +0 -136
  200. package/dist/template/.opencode/skill/ux-quality-gates/SKILL.md +0 -137
  201. package/dist/template/.opencode/skill/v1-run/SKILL.md +0 -175
  202. package/dist/template/.opencode/skill/v1-run/mcp.json +0 -6
  203. package/dist/template/.opencode/skill/verification-gates/SKILL.md +0 -63
  204. package/dist/template/.opencode/skill/visual-analysis/SKILL.md +0 -154
  205. package/dist/template/.opencode/skill/web-design-guidelines/SKILL.md +0 -46
  206. package/dist/template/.opencode/skill/workspace-setup/SKILL.md +0 -76
  207. package/dist/template/.opencode/skill/writing-plans/SKILL.md +0 -320
  208. /package/dist/template/.opencode/plugin/{lib → memory}/compact.ts +0 -0
  209. /package/dist/template/.opencode/plugin/{lib → memory}/db/graph.ts +0 -0
  210. /package/dist/template/.opencode/plugin/{lib → memory}/db/maintenance.ts +0 -0
  211. /package/dist/template/.opencode/plugin/{lib → memory}/db/pipeline.ts +0 -0
  212. /package/dist/template/.opencode/plugin/{lib → memory}/notify.ts +0 -0
  213. /package/dist/template/.opencode/plugin/{lib → memory}/operation-log.ts +0 -0
@@ -1,535 +0,0 @@
1
- /**
2
- * Memory Plugin — Core Tools
3
- *
4
- * observation, memory-search, memory-get, memory-read, memory-update, memory-timeline,
5
- * memory-graph-add, memory-graph-query, memory-graph-invalidate, memory-compact
6
- *
7
- * Uses factory pattern: createCoreTools(deps) returns tool definitions
8
- * that can be spread into plugin's tool:{} export.
9
- */
10
-
11
- import { readdir } from "node:fs/promises";
12
- import path from "node:path";
13
- import { tool } from "@opencode-ai/plugin/tool";
14
- import {
15
- addEntityTriple,
16
- type ConfidenceLevel,
17
- checkFTS5Available,
18
- getMemoryDB,
19
- getMemoryFile,
20
- getObservationsByIds,
21
- getTimelineAroundObservation,
22
- invalidateTriple,
23
- type ObservationSource,
24
- type ObservationType,
25
- queryEntity,
26
- searchDistillationsFTS,
27
- searchObservationsFTS,
28
- storeObservation,
29
- upsertMemoryFile,
30
- type HallType,
31
- VALID_HALLS,
32
- } from "./memory-db.js";
33
- import {
34
- autoDetectFiles,
35
- formatObservation,
36
- parseCSV,
37
- safeReadFile,
38
- TYPE_ICONS,
39
- VALID_TYPES,
40
- } from "./memory-helpers.js";
41
- import { validateObservation } from "./validate.js";
42
- import { compactObservations } from "./compact.js";
43
-
44
- /**
45
- * Wrap a memory tool execute function with DB error handling.
46
- * Returns a user-friendly error message instead of raw SQLite crashes.
47
- */
48
- function withDBErrorHandling<T extends Record<string, unknown>>(
49
- fn: (args: T) => Promise<string>,
50
- ): (args: T) => Promise<string> {
51
- return async (args: T) => {
52
- try {
53
- return await fn(args);
54
- } catch (err) {
55
- const message =
56
- err instanceof Error ? err.message : String(err);
57
- if (
58
- message.includes("database disk image is malformed") ||
59
- message.includes("SQLITE_CORRUPT") ||
60
- message.includes("integrity check failed")
61
- ) {
62
- return (
63
- `Error: Memory database is corrupted. ` +
64
- `Run \`memory-admin({ operation: "full" })\` to attempt repair, ` +
65
- `or delete .opencode/memory.db to start fresh. Details: ${message}`
66
- );
67
- }
68
- return `Error: Memory operation failed: ${message}`;
69
- }
70
- };
71
- }
72
-
73
- interface CoreToolDeps {
74
- handoffDir: string;
75
- }
76
-
77
- export function createCoreTools(deps: CoreToolDeps) {
78
- const { handoffDir } = deps;
79
-
80
- return {
81
- observation: tool({
82
- description: `Create a structured observation for future reference.\n\t\n\tPurpose:\n\t- Capture decisions, bugs, features, patterns, discoveries, learnings, or warnings\n\t- Auto-detects file references from content (file:line, \`path\`, src/, .opencode/)\n\t- Stores in SQLite with FTS5 index for fast search\n\t- Supports enhanced schema: facts, subtitle, files_read/files_modified\n\t\n\tConfidence guidance:\n\t- high: verified by tests, logs, or direct inspection (default)\n\t- medium: likely, but not fully verified\n\t- low: uncertain or speculative\n\t\n\tType-specific examples:\n\tdecision\n\tobservation({\n\t type: "decision",\n\t title: "Use JWT for auth",\n\t narrative: "Chose JWT for stateless auth across services.",\n\t facts: "stateless, scalable",\n\t concepts: "authentication, jwt",\n\t confidence: "high"\n\t})\n\t\n\tbugfix\n\tobservation({\n\t type: "bugfix",\n\t title: "Fix null pointer on login",\n\t narrative: "Guarded optional user in src/auth.ts:42 to prevent crash.",\n\t files_modified: "src/auth.ts",\n\t concepts: "auth, null-check",\n\t confidence: "high"\n\t})\n\t\n\tfeature\n\tobservation({\n\t type: "feature",\n\t title: "Add CLI --dry-run",\n\t narrative: "Introduce dry-run mode to show planned changes without writing.",\n\t files_modified: "src/commands/init.ts",\n\t concepts: "cli, ux",\n\t confidence: "medium"\n\t})\n\t\n\tpattern\n\tobservation({\n\t type: "pattern",\n\t title: "Use zod for input validation",\n\t narrative: "All command inputs validated with zod schemas before execute.",\n\t concepts: "validation, zod",\n\t confidence: "high"\n\t})\n\t\n\tdiscovery\n\tobservation({\n\t type: "discovery",\n\t title: "Build copies .opencode/ to dist/template/",\n\t narrative: "Found rsync step in build.ts that bundles .opencode/.",\n\t files_read: "build.ts",\n\t confidence: "high"\n\t})\n\t\n\tlearning\n\tobservation({\n\t type: "learning",\n\t title: "Bun test respects --watch",\n\t narrative: "Observed bun test --watch keeps runner active during edits.",\n\t confidence: "medium"\n\t})\n\t\n\twarning\n\tobservation({\n\t type: "warning",\n\t title: "Do not edit dist/ directly",\n\t narrative: "dist/ is built output and overwritten on build.",\n\t concepts: "build, generated",\n\t confidence: "high"\n\t})`,
83
- args: {
84
- type: tool.schema
85
- .string()
86
- .describe(
87
- "Observation type: decision, bugfix, feature, pattern, discovery, learning, warning",
88
- ),
89
- title: tool.schema.string().describe("Brief title"),
90
- subtitle: tool.schema.string().optional().describe("Optional subtitle"),
91
- facts: tool.schema
92
- .string()
93
- .optional()
94
- .describe("Comma-separated key facts"),
95
- narrative: tool.schema.string().optional().describe("Detailed content"),
96
- content: tool.schema
97
- .string()
98
- .optional()
99
- .describe("DEPRECATED: Use 'narrative'"),
100
- concepts: tool.schema
101
- .string()
102
- .optional()
103
- .describe("Comma-separated concept tags"),
104
- files_read: tool.schema
105
- .string()
106
- .optional()
107
- .describe("Comma-separated files read"),
108
- files_modified: tool.schema
109
- .string()
110
- .optional()
111
- .describe("Comma-separated files modified"),
112
- files: tool.schema
113
- .string()
114
- .optional()
115
- .describe("DEPRECATED: Use 'files_modified'"),
116
- bead_id: tool.schema.string().optional().describe("Related bead ID"),
117
- confidence: tool.schema
118
- .string()
119
- .optional()
120
- .describe("high, medium, low"),
121
- supersedes: tool.schema
122
- .string()
123
- .optional()
124
- .describe("ID this supersedes"),
125
- source: tool.schema
126
- .string()
127
- .optional()
128
- .describe("manual, curator, imported"),
129
- wing: tool.schema
130
- .string()
131
- .optional()
132
- .describe("Navigation wing (project or person name)"),
133
- hall: tool.schema
134
- .string()
135
- .optional()
136
- .describe("Navigation hall: facts, events, discoveries, preferences, advice"),
137
- room: tool.schema
138
- .string()
139
- .optional()
140
- .describe("Navigation room (topic name, e.g. auth-migration)"),
141
- raw_source: tool.schema
142
- .string()
143
- .optional()
144
- .describe("Verbatim source text to preserve losslessly alongside narrative"),
145
- },
146
- execute: withDBErrorHandling(async (args) => {
147
- const obsType = args.type as ObservationType;
148
- if (!VALID_TYPES.includes(obsType)) {
149
- return `Error: Invalid type "${args.type}". Valid: ${VALID_TYPES.join(", ")}`;
150
- }
151
-
152
- const confidence = (args.confidence ?? "high") as ConfidenceLevel;
153
- if (!["high", "medium", "low"].includes(confidence)) {
154
- return `Error: Invalid confidence "${args.confidence}". Valid: high, medium, low`;
155
- }
156
-
157
- const narrative = args.narrative ?? args.content;
158
- const filesModifiedRaw = args.files_modified ?? args.files;
159
- const facts = parseCSV(args.facts);
160
- const concepts = parseCSV(args.concepts);
161
- let filesRead = parseCSV(args.files_read);
162
- const filesModified = parseCSV(filesModifiedRaw);
163
-
164
- if (narrative) {
165
- const detected = autoDetectFiles(narrative);
166
- if (detected.length > 0) {
167
- const existing = new Set([
168
- ...(filesRead ?? []),
169
- ...(filesModified ?? []),
170
- ]);
171
- const newRefs = detected.filter((f) => !existing.has(f));
172
- if (newRefs.length > 0)
173
- filesRead = [...(filesRead ?? []), ...newRefs];
174
- }
175
- }
176
-
177
- let supersedes: number | undefined;
178
- if (args.supersedes) {
179
- const parsed = Number.parseInt(args.supersedes, 10);
180
- if (!Number.isNaN(parsed)) supersedes = parsed;
181
- }
182
-
183
- const source = (args.source ?? "manual") as ObservationSource;
184
- const hall = args.hall as HallType | undefined;
185
- if (hall && !VALID_HALLS.includes(hall)) {
186
- return `Error: Invalid hall "${args.hall}". Valid: ${VALID_HALLS.join(", ")}`;
187
- }
188
-
189
- // Validation gate: check for duplicates, contradictions, low quality
190
- const validation = validateObservation({
191
- type: obsType,
192
- title: args.title,
193
- subtitle: args.subtitle,
194
- facts,
195
- narrative,
196
- concepts,
197
- files_read: filesRead,
198
- files_modified: filesModified,
199
- confidence,
200
- bead_id: args.bead_id,
201
- supersedes,
202
- source,
203
- wing: args.wing,
204
- hall,
205
- room: args.room,
206
- });
207
-
208
- if (validation.verdict === "reject") {
209
- const reasons = validation.issues.map(i => i.message).join("; ");
210
- const dupHint = validation.duplicateOf
211
- ? ` Use \`observation({ supersedes: "${validation.duplicateOf}", ... })\` to update it.`
212
- : "";
213
- return `Rejected: ${reasons}.${dupHint}`;
214
- }
215
-
216
- const id = storeObservation({
217
- type: obsType,
218
- title: args.title,
219
- subtitle: args.subtitle,
220
- facts,
221
- narrative,
222
- raw_source: args.raw_source,
223
- concepts,
224
- files_read: filesRead,
225
- files_modified: filesModified,
226
- confidence,
227
- bead_id: args.bead_id,
228
- supersedes,
229
- source,
230
- wing: args.wing,
231
- hall,
232
- room: args.room,
233
- });
234
-
235
- const warnings = validation.issues.length > 0
236
- ? `\n⚠️ Warnings: ${validation.issues.map(i => i.message).join("; ")}`
237
- : "";
238
-
239
- return `${TYPE_ICONS[obsType] ?? "\uD83D\uDCCC"} Observation #${id} stored [${obsType}] "${args.title}" (confidence: ${confidence}, source: ${source})${warnings}`;
240
- }),
241
- }),
242
-
243
- "memory-search": tool({
244
- description: `Search memory across observations and markdown archives.\n\t\n\tPurpose:\n\t- Fast, ranked search across all observations in SQLite (when FTS5 is available)\n\t- Returns compact index (~50-100 tokens per result) for progressive disclosure\n\t- Use memory-get for full details after identifying relevant observations\n\t\n\tFTS5 availability:\n\t- Auto-detected at runtime; if unavailable, observation searches fall back to file scan\n\t\n\tSearch modes and hints:\n\t- "observations" (default): Best for decisions, bugs, learnings; uses FTS5 ranking when available\n\t- "handoffs": Use for past session handoffs and summaries\n\t- "research": Use for research notes and external findings\n\t- "templates": Use for memory templates and boilerplate references\n\t- "beads": Use for task artifacts in .beads/artifacts\n\t- "all": Use when you are unsure where info lives; searches SQLite + markdown + beads\n\t\n\tExample:\n\tmemory-search({ query: "authentication" })\n\tmemory-search({ query: "auth", type: "decision", limit: 5 })`,
245
- args: {
246
- query: tool.schema.string().describe("Search query"),
247
- type: tool.schema
248
- .string()
249
- .optional()
250
- .describe("Filter by type or scope"),
251
- limit: tool.schema
252
- .number()
253
- .optional()
254
- .describe("Max results (default: 10)"),
255
- },
256
- execute: withDBErrorHandling(async (args) => {
257
- const query = args.query.trim();
258
- if (!query) return "Error: Empty search query";
259
- const limit = args.limit ?? 10;
260
- const scope = args.type ?? "observations";
261
- const lines: string[] = [];
262
-
263
- if (
264
- scope === "observations" ||
265
- scope === "all" ||
266
- VALID_TYPES.includes(scope as ObservationType)
267
- ) {
268
- const typeFilter = VALID_TYPES.includes(scope as ObservationType)
269
- ? (scope as ObservationType)
270
- : undefined;
271
- if (checkFTS5Available()) {
272
- const results = searchObservationsFTS(query, {
273
- type: typeFilter,
274
- limit,
275
- });
276
- if (results.length > 0) {
277
- lines.push(`## Observations (${results.length} results)\n`);
278
- lines.push("| ID | Type | Title | Date |");
279
- lines.push("|---|---|---|---|");
280
- for (const r of results)
281
- lines.push(
282
- `| ${r.id} | ${r.type} | ${r.title} | ${r.created_at.slice(0, 10)} |`,
283
- );
284
- lines.push("");
285
- for (const r of results.slice(0, 3)) {
286
- if (r.snippet) lines.push(`**#${r.id}**: ${r.snippet}`);
287
- }
288
- lines.push(
289
- `\nUse \`memory-get({ ids: "${results
290
- .slice(0, 3)
291
- .map((r) => r.id)
292
- .join(",")}" })\` for full details.`,
293
- );
294
- } else {
295
- lines.push("No observation matches found.");
296
- }
297
- } else {
298
- lines.push("FTS5 not available. Use memory-admin to check status.");
299
- }
300
- }
301
-
302
- if (scope === "distillations" || scope === "all") {
303
- const distResults = searchDistillationsFTS(query, limit);
304
- if (distResults.length > 0) {
305
- lines.push(`\n## Distillations (${distResults.length} results)\n`);
306
- for (const d of distResults) {
307
- lines.push(
308
- `- **Session ${d.session_id.slice(0, 8)}** (${d.message_count} msgs): ${d.snippet}`,
309
- );
310
- }
311
- }
312
- }
313
-
314
- if (scope === "handoffs" || scope === "all") {
315
- try {
316
- const handoffFiles = await readdir(handoffDir);
317
- const matches: string[] = [];
318
- for (const f of handoffFiles.filter((n) => n.endsWith(".md"))) {
319
- const content = await safeReadFile(path.join(handoffDir, f));
320
- if (content.toLowerCase().includes(query.toLowerCase()))
321
- matches.push(f);
322
- }
323
- if (matches.length > 0) {
324
- lines.push(`\n## Handoffs (${matches.length} matches)\n`);
325
- for (const m of matches.slice(0, 5)) lines.push(`- ${m}`);
326
- }
327
- } catch {
328
- /* No handoffs directory */
329
- }
330
- }
331
-
332
- return lines.length > 0 ? lines.join("\n") : "No results found.";
333
- }),
334
- }),
335
-
336
- "memory-get": tool({
337
- description: `Get full observation details by ID.\n\t\n\tPurpose:\n\t- Progressive disclosure: fetch full details after identifying relevant observations via search\n\t- Get complete narrative, facts, and metadata\n\t- Supports multiple IDs for batch retrieval\n\t\n\tExample:\n\tmemory-get({ ids: "42" }) // Single observation\n\tmemory-get({ ids: "1,5,10" }) // Multiple observations`,
338
- args: {
339
- ids: tool.schema.string().describe("Comma-separated observation IDs"),
340
- },
341
- execute: withDBErrorHandling(async (args) => {
342
- const idList = args.ids
343
- .split(",")
344
- .map((s) => Number.parseInt(s.trim(), 10))
345
- .filter((n) => !Number.isNaN(n));
346
- if (idList.length === 0) return "Error: No valid IDs provided";
347
- const observations = getObservationsByIds(idList);
348
- if (observations.length === 0)
349
- return "No observations found for given IDs.";
350
- return observations
351
- .map((obs) => formatObservation(obs))
352
- .join("\n\n---\n\n");
353
- }),
354
- }),
355
-
356
- "memory-read": tool({
357
- description: `Read memory files for persistent cross-session context.\n\t\n\tPurpose:\n\t- Retrieve project state, learnings, and active tasks\n\t- Reads from SQLite database\n\t- Supports subdirectories: handoffs/, research/\n\t\n\tExample:\n\tmemory-read({ file: "handoffs/2024-01-20-phase-1" })\n\tmemory-read({ file: "research/2024-01-topic" })`,
358
- args: {
359
- file: tool.schema.string().optional().describe("Memory file path"),
360
- },
361
- execute: withDBErrorHandling(async (args) => {
362
- const filePath = (args.file ?? "").replace(/\.md$/, "");
363
- if (!filePath) return "Error: No file path provided";
364
- const row = getMemoryFile(filePath);
365
- return row ? row.content : `Memory file "${filePath}" not found.`;
366
- }),
367
- }),
368
-
369
- "memory-update": tool({
370
- description: `Update memory files with new learnings, progress, or context.\n\t\n\tPurpose:\n\t- Write or append to project memory in SQLite\n\t- Supports subdirectories (e.g., 'research/2024-01-topic')\n\t- Two modes: 'replace' (overwrite) or 'append' (add to end)\n\t\n\tExample:\n\tmemory-update({ file: "research/session-findings", content: "..." })\n\tmemory-update({ file: "handoffs/phase-2", content: "...", mode: "append" })`,
371
- args: {
372
- file: tool.schema.string().describe("Memory file to update"),
373
- content: tool.schema.string().describe("Content to write or append"),
374
- mode: tool.schema
375
- .string()
376
- .optional()
377
- .describe("replace (default) or append"),
378
- },
379
- execute: withDBErrorHandling(async (args) => {
380
- const filePath = args.file.replace(/\.md$/, "");
381
- const mode = (args.mode ?? "replace") as "replace" | "append";
382
- let finalContent = args.content;
383
- if (mode === "append") {
384
- finalContent = `\n---\n_Updated: ${new Date().toISOString()}_\n\n${args.content}`;
385
- }
386
- upsertMemoryFile(filePath, finalContent, mode);
387
- return `Memory file "${filePath}" updated (mode: ${mode}).`;
388
- }),
389
- }),
390
-
391
- "memory-timeline": tool({
392
- description: `Get chronological context around an observation.\n\t\n\tPurpose:\n\t- Progressive disclosure: see what was happening before/after a specific observation\n\t- Understand decision context over time\n\t- Navigate memory timeline\n\t\n\tExample:\n\tmemory-timeline({ anchor_id: 42, depth_before: 5, depth_after: 5 })`,
393
- args: {
394
- anchor_id: tool.schema.number().describe("ID of the observation"),
395
- depth_before: tool.schema
396
- .number()
397
- .optional()
398
- .describe("Earlier observations (default: 5)"),
399
- depth_after: tool.schema
400
- .number()
401
- .optional()
402
- .describe("Later observations (default: 5)"),
403
- },
404
- execute: withDBErrorHandling(async (args) => {
405
- const { anchor, before, after } = getTimelineAroundObservation(
406
- args.anchor_id,
407
- args.depth_before ?? 5,
408
- args.depth_after ?? 5,
409
- );
410
- if (!anchor) return `Observation #${args.anchor_id} not found.`;
411
- const lines: string[] = [];
412
- if (before.length > 0) {
413
- lines.push("### Earlier");
414
- for (const b of before)
415
- lines.push(
416
- ` ${b.id}: [${b.type}] ${b.title} (${b.created_at.slice(0, 10)})`,
417
- );
418
- }
419
- lines.push(
420
- `\n### ${TYPE_ICONS[anchor.type] ?? "\uD83D\uDCCC"} Current: #${anchor.id} [${anchor.type}] ${anchor.title}`,
421
- );
422
- if (anchor.narrative) lines.push(anchor.narrative.slice(0, 200));
423
- if (after.length > 0) {
424
- lines.push("\n### Later");
425
- for (const a of after)
426
- lines.push(
427
- ` ${a.id}: [${a.type}] ${a.title} (${a.created_at.slice(0, 10)})`,
428
- );
429
- }
430
- return lines.join("\n");
431
- }),
432
- }),
433
-
434
- "memory-graph-add": tool({
435
- description: `Add a triple to the entity knowledge graph.\n\nStores a subject-predicate-object relationship with optional temporal bounds and confidence.\nUse for structured facts like "project uses typescript" or "user prefers dark-mode".\n\nExample:\nmemory-graph-add({ subject: "project", predicate: "uses", object: "typescript" })\nmemory-graph-add({ subject: "auth", predicate: "depends-on", object: "jwt", confidence: 0.9, source_observation_id: 42 })`,
436
- args: {
437
- subject: tool.schema.string().describe("Entity subject"),
438
- predicate: tool.schema.string().describe("Relationship type (e.g. uses, depends-on, prefers)"),
439
- object: tool.schema.string().describe("Entity object"),
440
- valid_from: tool.schema.string().optional().describe("Start date (ISO, default: today)"),
441
- valid_to: tool.schema.string().optional().describe("End date (ISO, null = still active)"),
442
- confidence: tool.schema.number().optional().describe("Confidence 0.0-1.0 (default: 1.0)"),
443
- source_observation_id: tool.schema.number().optional().describe("Link to source observation"),
444
- },
445
- execute: withDBErrorHandling(async (args) => {
446
- if (!args.subject?.trim() || !args.predicate?.trim() || !args.object?.trim()) {
447
- return "Error: subject, predicate, and object are required.";
448
- }
449
- const id = addEntityTriple({
450
- subject: args.subject,
451
- predicate: args.predicate,
452
- object: args.object,
453
- valid_from: args.valid_from,
454
- valid_to: args.valid_to,
455
- confidence: args.confidence,
456
- source_observation_id: args.source_observation_id,
457
- });
458
- return `Triple #${id} added: ${args.subject} —[${args.predicate}]→ ${args.object}`;
459
- }),
460
- }),
461
-
462
- "memory-graph-query": tool({
463
- description: `Query the entity knowledge graph.\n\nFind relationships for an entity with optional time and direction filters.\nReturns triples where the entity appears as subject, object, or both.\n\nExample:\nmemory-graph-query({ entity: "typescript" })\nmemory-graph-query({ entity: "auth", direction: "out", active_only: true })\nmemory-graph-query({ entity: "project", as_of: "2025-06-01" })`,
464
- args: {
465
- entity: tool.schema.string().describe("Entity to query"),
466
- direction: tool.schema.string().optional().describe("out (subject), in (object), both (default)"),
467
- predicate: tool.schema.string().optional().describe("Filter by predicate"),
468
- as_of: tool.schema.string().optional().describe("ISO date for point-in-time query"),
469
- active_only: tool.schema.boolean().optional().describe("Only active triples (default: false)"),
470
- limit: tool.schema.number().optional().describe("Max results (default: 50)"),
471
- },
472
- execute: withDBErrorHandling(async (args) => {
473
- if (!args.entity?.trim()) return "Error: entity is required.";
474
- const results = queryEntity(args.entity, {
475
- direction: args.direction as "out" | "in" | "both" | undefined,
476
- predicate: args.predicate,
477
- as_of: args.as_of,
478
- activeOnly: args.active_only,
479
- limit: args.limit,
480
- });
481
- if (results.length === 0) return `No triples found for entity "${args.entity}".`;
482
- const lines: string[] = [
483
- `## Entity Graph: ${args.entity} (${results.length} triples)\n`,
484
- "| ID | Subject | Predicate | Object | Active | Confidence |",
485
- "|---|---|---|---|---|---|",
486
- ];
487
- for (const r of results) {
488
- lines.push(`| ${r.id} | ${r.subject} | ${r.predicate} | ${r.object} | ${r.is_active ? "\u2705" : "\u274C"} | ${(r.confidence * 100).toFixed(0)}% |`);
489
- }
490
- return lines.join("\n");
491
- }),
492
- }),
493
-
494
- "memory-graph-invalidate": tool({
495
- description: `Invalidate (close) entity triples in the knowledge graph.\n\nMarks active triples matching subject+predicate+object as no longer valid by setting valid_to.\nUse when a fact is no longer true (e.g. project stopped using a library).\n\nExample:\nmemory-graph-invalidate({ subject: "project", predicate: "uses", object: "moment.js" })`,
496
- args: {
497
- subject: tool.schema.string().describe("Entity subject"),
498
- predicate: tool.schema.string().describe("Relationship type"),
499
- object: tool.schema.string().describe("Entity object"),
500
- end_date: tool.schema.string().optional().describe("End date (ISO, default: today)"),
501
- },
502
- execute: withDBErrorHandling(async (args) => {
503
- if (!args.subject?.trim() || !args.predicate?.trim() || !args.object?.trim()) {
504
- return "Error: subject, predicate, and object are required.";
505
- }
506
- const count = invalidateTriple(args.subject, args.predicate, args.object, args.end_date);
507
- return count > 0
508
- ? `Invalidated ${count} triple(s): ${args.subject} —[${args.predicate}]→ ${args.object}`
509
- : `No active triples found matching ${args.subject} —[${args.predicate}]→ ${args.object}.`;
510
- }),
511
- }),
512
-
513
- "memory-compact": tool({
514
- description: `Compact observations into a dense, token-efficient format.\n\nUses AAAK-inspired pipe-separated compression achieving ~3-5x token reduction.\nUseful for injecting memory into prompts with minimal token cost.\n\nExample:\nmemory-compact({})\nmemory-compact({ limit: 20 })`,
515
- args: {
516
- limit: tool.schema.number().optional().describe("Max observations to compact (default: all)"),
517
- },
518
- execute: withDBErrorHandling(async (args) => {
519
- const db = getMemoryDB();
520
- const limitClause = args.limit ? `LIMIT ${Number(args.limit)}` : "";
521
- const observations = db.query(
522
- `SELECT id, type, title, narrative, concepts, wing, hall, room, confidence, created_at
523
- FROM observations
524
- WHERE superseded_by IS NULL
525
- ORDER BY created_at_epoch DESC ${limitClause}`
526
- ).all() as { id: number; type: string; title: string; narrative?: string | null; concepts?: string | null; wing?: string | null; hall?: string | null; room?: string | null; confidence?: string | null; created_at?: string | null }[];
527
- if (observations.length === 0) return "No observations to compact.";
528
- const result = compactObservations(observations);
529
- if (!result.compressed) return "No observations to compact.";
530
- const ratio = result.compression_ratio > 0 ? ` (${(result.compression_ratio * 100).toFixed(0)}% of original)` : "";
531
- return `## Compact Memory (${observations.length} observations, ~${result.token_estimate} tokens${ratio})\n\n${result.compressed}`;
532
- }),
533
- }),
534
- };
535
- }