wyrm-mcp 7.2.1 → 7.2.2

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 (150) hide show
  1. package/LICENSE +26 -667
  2. package/NOTICE +14 -33
  3. package/dist/activation.js +1 -60
  4. package/dist/agent-daemon.js +4 -281
  5. package/dist/agent-loop.js +7 -332
  6. package/dist/analytics.js +13 -236
  7. package/dist/attribution.js +1 -49
  8. package/dist/audit.js +2 -457
  9. package/dist/auto-capture.js +3 -138
  10. package/dist/auto-orchestrator.js +1 -325
  11. package/dist/autoconfig.js +39 -840
  12. package/dist/buddy-runner.js +1 -109
  13. package/dist/buddy.js +14 -564
  14. package/dist/build-flags.js +1 -17
  15. package/dist/capabilities.js +3 -183
  16. package/dist/capture.js +1 -56
  17. package/dist/causality.js +6 -107
  18. package/dist/cli.js +20 -281
  19. package/dist/cloud/cli.js +5 -541
  20. package/dist/cloud/client.js +1 -221
  21. package/dist/cloud/crypto.js +1 -85
  22. package/dist/cloud/machine-id.js +2 -113
  23. package/dist/cloud/recovery.js +1 -60
  24. package/dist/cloud/sync-engine.js +7 -543
  25. package/dist/cloud-backup.js +5 -579
  26. package/dist/cloud-profile.js +1 -138
  27. package/dist/cloud-sync-entrypoint.js +1 -47
  28. package/dist/cloud-sync.js +2 -309
  29. package/dist/constellation.js +12 -168
  30. package/dist/context-build-budgeted.js +4 -144
  31. package/dist/context-ranking.js +1 -69
  32. package/dist/crypto.js +1 -179
  33. package/dist/daemon-write-endpoint.js +1 -290
  34. package/dist/daemon-writer.js +2 -406
  35. package/dist/database.js +43 -1110
  36. package/dist/deprecations.js +2 -162
  37. package/dist/design.js +13 -141
  38. package/dist/event-replication.js +1 -112
  39. package/dist/events-sse.js +7 -43
  40. package/dist/events.js +6 -238
  41. package/dist/failure-patterns.js +42 -659
  42. package/dist/federation.js +12 -236
  43. package/dist/goals.js +13 -101
  44. package/dist/golden.js +3 -355
  45. package/dist/handlers/agent.js +4 -165
  46. package/dist/handlers/alias-adapters.js +1 -129
  47. package/dist/handlers/aliases.js +1 -171
  48. package/dist/handlers/audit.js +1 -87
  49. package/dist/handlers/boundary.js +1 -221
  50. package/dist/handlers/capture.js +73 -1109
  51. package/dist/handlers/causality.js +7 -114
  52. package/dist/handlers/cloud.js +85 -382
  53. package/dist/handlers/companion.js +28 -459
  54. package/dist/handlers/datalake.js +7 -187
  55. package/dist/handlers/dispatch-context.js +0 -22
  56. package/dist/handlers/entity.js +25 -256
  57. package/dist/handlers/events.js +16 -335
  58. package/dist/handlers/failure.js +13 -340
  59. package/dist/handlers/goals.js +4 -296
  60. package/dist/handlers/intelligence.js +126 -674
  61. package/dist/handlers/invoicing.js +1 -70
  62. package/dist/handlers/mcpclient.js +6 -137
  63. package/dist/handlers/orchestration.js +40 -125
  64. package/dist/handlers/output-schemas.js +1 -24
  65. package/dist/handlers/presence.js +3 -99
  66. package/dist/handlers/project.js +28 -182
  67. package/dist/handlers/prompts.js +6 -157
  68. package/dist/handlers/quest.js +4 -224
  69. package/dist/handlers/recall.js +11 -218
  70. package/dist/handlers/registry.js +1 -167
  71. package/dist/handlers/resources.js +1 -288
  72. package/dist/handlers/review.js +11 -74
  73. package/dist/handlers/run.js +17 -487
  74. package/dist/handlers/search.js +15 -326
  75. package/dist/handlers/session.js +28 -615
  76. package/dist/handlers/share.js +8 -184
  77. package/dist/handlers/shims.js +1 -464
  78. package/dist/handlers/skill.js +67 -449
  79. package/dist/handlers/survivors.js +1 -120
  80. package/dist/handlers/symbols.js +8 -109
  81. package/dist/handlers/syncops.js +4 -302
  82. package/dist/handlers/types.js +1 -27
  83. package/dist/harvest.js +5 -191
  84. package/dist/hours.js +7 -156
  85. package/dist/http-auth.js +3 -321
  86. package/dist/http-fast.js +21 -1137
  87. package/dist/icons.js +1 -47
  88. package/dist/index.js +2 -924
  89. package/dist/indexer.js +4 -145
  90. package/dist/intelligence.js +31 -261
  91. package/dist/internal-dispatch.js +3 -212
  92. package/dist/keyset.js +1 -110
  93. package/dist/knowledge-graph.js +12 -176
  94. package/dist/license.js +2 -441
  95. package/dist/logger.js +2 -199
  96. package/dist/maintenance.js +2 -148
  97. package/dist/mcp-client.js +6 -262
  98. package/dist/memory-artifacts.js +30 -449
  99. package/dist/migrate-prompt.js +2 -124
  100. package/dist/migrations.js +40 -655
  101. package/dist/performance.js +1 -228
  102. package/dist/presence.js +11 -140
  103. package/dist/priority-embed.js +5 -164
  104. package/dist/providers/embedding-provider.js +1 -196
  105. package/dist/readonly-gate.js +1 -29
  106. package/dist/rehydration.js +9 -157
  107. package/dist/reindex.js +1 -88
  108. package/dist/render-target.js +21 -514
  109. package/dist/render.js +4 -280
  110. package/dist/repl-guard.js +1 -173
  111. package/dist/replication-daemon-entrypoint.js +1 -31
  112. package/dist/replication-daemon.js +2 -262
  113. package/dist/resilience.js +1 -591
  114. package/dist/reverse-bridge.js +5 -360
  115. package/dist/security.js +1 -244
  116. package/dist/session-seen.js +3 -51
  117. package/dist/setup.js +1 -260
  118. package/dist/skill-author.js +5 -168
  119. package/dist/spec-kit.js +1 -191
  120. package/dist/sqlite-busy.js +1 -154
  121. package/dist/statusline.js +11 -315
  122. package/dist/sub-agent.js +13 -262
  123. package/dist/summarizer.js +13 -139
  124. package/dist/symbols.js +7 -283
  125. package/dist/sync.js +5 -359
  126. package/dist/tasks-dispatch.js +1 -84
  127. package/dist/tasks.js +1 -282
  128. package/dist/token-budget.js +1 -143
  129. package/dist/tool-analytics.js +7 -129
  130. package/dist/tool-annotations.js +1 -365
  131. package/dist/tool-manifest-v2.json +1 -1
  132. package/dist/tool-manifest.json +1 -1
  133. package/dist/tool-profiles.js +1 -75
  134. package/dist/trace-harvest.js +6 -244
  135. package/dist/types.js +1 -30
  136. package/dist/ui-dashboard.js +41 -50
  137. package/dist/ulid.js +1 -81
  138. package/dist/validate.js +1 -129
  139. package/dist/vault.js +1 -534
  140. package/dist/vectors.js +3 -184
  141. package/dist/version-check.js +4 -136
  142. package/dist/visibility.js +19 -155
  143. package/dist/wyrm-cli.js +98 -2464
  144. package/dist/wyrm-guard.js +14 -424
  145. package/dist/wyrm-loop.js +3 -150
  146. package/dist/wyrm-manifest.json +1 -1
  147. package/dist/wyrm-statusline-daemon.js +1 -11
  148. package/dist/wyrm-statusline.js +4 -56
  149. package/dist/wyrm-ui.js +9 -77
  150. package/package.json +4 -2
@@ -1,25 +1,4 @@
1
- /**
2
- * Capabilities self-description.
3
- *
4
- * Returns a structured pitch the AI can read at session start so it knows
5
- * exactly what Wyrm offers beyond "store and recall". The categories are
6
- * grouped by *what the operator gets*, not by table or module — the AI
7
- * should be able to read this once and immediately reach for the right
8
- * tool without re-discovering the surface.
9
- *
10
- * Also used as the body of the `wyrm_capabilities` MCP tool, the
11
- * `wyrm_inject_prompt` block, and the postinstall pitch.
12
- *
13
- * @copyright 2026 Ghost Protocol (Pvt) Ltd.
14
- * @license AGPL-3.0-or-later — dual-licensed; commercial terms: ghosts.lk@proton.me. See LICENSE.
15
- */
16
- import { homedir } from 'os';
17
- import { join, dirname } from 'path';
18
- import { readFileSync, existsSync } from 'fs';
19
- import { fileURLToPath } from 'url';
20
- const __filename = fileURLToPath(import.meta.url);
21
- const __dirname = dirname(__filename);
22
- const PITCH = `Wyrm is not "AI memory" in the file-write sense. It's a layered intelligence
1
+ import{homedir as n}from"os";import{join as o,dirname as l}from"path";import{readFileSync as c,existsSync as m}from"fs";import{fileURLToPath as y}from"url";const h=y(import.meta.url),a=l(h),d=`Wyrm is not "AI memory" in the file-write sense. It's a layered intelligence
23
2
  substrate that solves the four specific problems AI assistants share:
24
3
 
25
4
  1. Amnesia. Sessions inherit prior state via lossless rehydration.
@@ -32,164 +11,5 @@ substrate that solves the four specific problems AI assistants share:
32
11
  Every Wyrm session is local-first SQLite with FTS5 + hybrid semantic search.
33
12
  Encryption is operator-controlled. Federation is opt-in per row. The audit
34
13
  log is hash-chained and Ed25519-signable for SOC2/HIPAA scenarios. None of
35
- this requires you to leave your laptop.`;
36
- const FEATURES = [
37
- {
38
- name: 'Counter-pattern memory',
39
- what: 'Records failed approaches with (scope, target, description) and blocks the same suggestion next time.',
40
- why: 'Other memory tools learn only from success. Wyrm refuses to repeat mistakes — saves the most expensive class of tokens (the regenerated wrong answer).',
41
- tools: ['wyrm_failure_record', 'wyrm_failure_check', 'wyrm_failure_list', 'wyrm_failure_resolve'],
42
- },
43
- {
44
- name: 'Ground truths (versioned, cascade-aware)',
45
- what: 'Validated project facts (architecture, constraints, decisions) — each truth carries a version, last-verified timestamp, and outbound decision links.',
46
- why: 'Truths are injected first into every wyrm_context_build call so the AI never works from contradicted assumptions. When a truth changes, dependent decisions auto-invalidate.',
47
- tools: ['wyrm_truth_set', 'wyrm_truth_get', 'wyrm_decided_because', 'wyrm_decision_upstream', 'wyrm_decision_downstream', 'wyrm_decision_invalidate'],
48
- },
49
- {
50
- name: 'Reasoning scaffolds',
51
- what: 'Saved step-by-step checklists for problem types ("debug a slow query", "ship a migration") that surface automatically when a task description matches.',
52
- why: 'Replaces ad-hoc rediscovery of process knowledge with structured prompts. Cheaper than re-explaining the playbook every session.',
53
- tools: ['wyrm_scaffold_save', 'wyrm_scaffold_get'],
54
- },
55
- {
56
- name: 'Lossless session rehydration',
57
- what: 'wyrm_session_rehydrate produces a complete briefing markdown a fresh AI ingests to inherit prior state — decisions, open quests, failures, recent commits, files touched.',
58
- why: 'Cross-session continuity without re-exploration. The single biggest token-saver in the toolkit.',
59
- tools: ['wyrm_session_rehydrate', 'wyrm_session_prime', 'wyrm_session_start', 'wyrm_session_update'],
60
- },
61
- {
62
- name: 'Distillation queue',
63
- what: 'Candidate memory artifacts extracted from sessions land in a review queue; the operator approves or rejects each.',
64
- why: 'Bayesian confidence updates after each review — Wyrm gets sharper with use without auto-trusting noise.',
65
- tools: ['wyrm_distill', 'wyrm_review', 'wyrm_remember', 'wyrm_recall', 'wyrm_feedback'],
66
- },
67
- {
68
- name: 'Knowledge graph',
69
- what: 'Named entities + typed directional relationships, neighborhood traversal, shortest-path queries.',
70
- why: 'When the AI asks "how does X relate to Y?", Wyrm answers in O(log n) instead of grepping the corpus.',
71
- tools: ['wyrm_entity_add', 'wyrm_entity_link', 'wyrm_entity_search', 'wyrm_entity_graph', 'wyrm_entity_path', 'wyrm_entity_merge'],
72
- },
73
- {
74
- name: 'Cross-repo symbol index',
75
- what: 'Workspace-wide function/class/type index across TS/JS/Python/Rust/Go/PHP/Ruby with caller resolution.',
76
- why: 'Symbol lookups don\'t require re-grepping every project. "Who calls handleAuth?" answers immediately.',
77
- tools: ['wyrm_symbol_index', 'wyrm_symbol_search', 'wyrm_symbol_callers', 'wyrm_symbol_stats'],
78
- },
79
- {
80
- name: 'OODA agent loop (autonomous goals)',
81
- what: 'wyrm_goal_set persists an objective with success criteria. The wyrm-loop daemon runs Observe→Orient→Decide→Act every interval, dispatching whitelisted tools. Replayable, capped, auditable.',
82
- why: 'Lets you hand the AI a multi-step objective and walk away. No data-exfil tools accessible from inside the loop.',
83
- tools: ['wyrm_goal_set', 'wyrm_goal_list', 'wyrm_goal_pause', 'wyrm_goal_resume', 'wyrm_goal_complete', 'wyrm_goal_abandon', 'wyrm_goal_iterations', 'wyrm_act', 'wyrm_agent_init', 'wyrm_agent_status', 'wyrm_agent_stop', 'wyrm_agent_restart'],
84
- },
85
- {
86
- name: 'Outbound MCP client',
87
- what: 'Wyrm calls other MCP servers (GitHub, Slack, Linear, …) over stdio. The agent loop dispatches them like internal tools.',
88
- why: 'Composability: Wyrm becomes the orchestration layer over your entire MCP stack instead of a sibling.',
89
- tools: ['wyrm_mcp_register', 'wyrm_mcp_list', 'wyrm_mcp_disable', 'wyrm_mcp_tools', 'wyrm_call_external'],
90
- },
91
- {
92
- name: 'Hybrid semantic search',
93
- what: 'wyrm_search fuses FTS5 keyword candidates with vector candidates (Ollama nomic-embed-text by default; OpenAI optional) via Reciprocal Rank Fusion.',
94
- why: 'Catches both "exact term" and "semantically similar" hits in one call. Silently falls back to FTS5-only if Ollama isn\'t running.',
95
- tools: ['wyrm_search', 'wyrm_vector_setup'],
96
- },
97
- {
98
- name: 'Multi-agent presence + work-stealing',
99
- what: 'Claude, Copilot, Cursor, and Codex announce themselves via TTL heartbeats. Quests can be claimed exclusively.',
100
- why: 'No two agents step on the same quest. The work-stealing semantics scale to teams.',
101
- tools: ['wyrm_presence_announce', 'wyrm_presence_list', 'wyrm_presence_release', 'wyrm_quest_claim', 'wyrm_quest_release'],
102
- },
103
- {
104
- name: 'Federated team sync',
105
- what: 'Per-row is_shared flag, /sync/push endpoint, conflict-as-quest semantics. PII never leaves the box unless explicitly shared.',
106
- why: 'Team memory without a SaaS. No silent overwrites — every conflict becomes a quest the operator resolves.',
107
- tools: ['wyrm_share', 'wyrm_unshare', 'wyrm_sync', 'wyrm_sync_export', 'wyrm_sync_import', 'wyrm_sync_conflicts', 'wyrm_sync_resolve'],
108
- },
109
- {
110
- name: 'Compliance audit trail',
111
- what: 'Hash-chained audit log with optional Ed25519 signatures. wyrm_audit_export produces tamper-evident bundles.',
112
- why: 'SOC2/HIPAA reviewers get a real artifact. The hash chain detects any tampering after the fact.',
113
- tools: ['wyrm_audit_log', 'wyrm_audit_export', 'wyrm_audit_verify'],
114
- },
115
- {
116
- name: 'Hour ledger + invoice generation',
117
- what: 'Derives billable hours from session content and emits markdown invoices.',
118
- why: 'For solo operators and small teams: Wyrm is also the time tracker. No second tool to keep in sync.',
119
- tools: ['wyrm_hours_report', 'wyrm_invoice_generate', 'wyrm_cost_report'],
120
- },
121
- {
122
- name: 'Self-improvement analytics',
123
- what: 'Per-tool error rate, p50/p95 latency, cost-per-tool. Wyrm watches Wyrm.',
124
- why: 'Lets you spot which tools are hot, which are slow, which fail — input for both ops tuning and product decisions.',
125
- tools: ['wyrm_analytics_dashboard', 'wyrm_tool_analytics', 'wyrm_usage', 'wyrm_stats'],
126
- },
127
- ];
128
- function readPackageVersion() {
129
- try {
130
- // Resolve relative to this file. After tsc compile, this lives at
131
- // dist/capabilities.js, so package.json is one dir up.
132
- const candidates = [
133
- join(__dirname, '..', 'package.json'),
134
- join(__dirname, '..', '..', 'package.json'),
135
- ];
136
- for (const p of candidates) {
137
- if (existsSync(p)) {
138
- return JSON.parse(readFileSync(p, 'utf-8')).version ?? 'unknown';
139
- }
140
- }
141
- }
142
- catch {
143
- // fall through
144
- }
145
- return 'unknown';
146
- }
147
- export function getCapabilities(db, toolCount, probe) {
148
- void db; // reserved — future versions may surface runtime DB stats here
149
- const dbPath = process.env.WYRM_DB_PATH ?? join(homedir(), '.wyrm', 'wyrm.db');
150
- const agentState = probe.isAgentRunning();
151
- return {
152
- product: 'Wyrm',
153
- version: readPackageVersion(),
154
- pitch: PITCH,
155
- install: {
156
- dbPath,
157
- nodeVersion: process.version,
158
- platform: `${process.platform}-${process.arch}`,
159
- },
160
- runtime: {
161
- vectorProvider: probe.detectVectorProvider(),
162
- encryption: probe.hasEncryption(),
163
- federation: probe.isFederationEnabled(),
164
- agentLoop: agentState === null ? 'unknown' : agentState ? 'running' : 'stopped',
165
- },
166
- features: FEATURES,
167
- toolCount,
168
- };
169
- }
170
- /**
171
- * Render the capability report as a markdown briefing the AI can drop into a
172
- * session-prime answer or a user-facing reply. Keeps the structure stable so
173
- * the model can predict where to look.
174
- */
175
- export function renderCapabilityBriefing(report) {
176
- const lines = [];
177
- lines.push(`# 󱅝 ${report.product} ${report.version} — Capability Briefing`);
178
- lines.push('');
179
- lines.push(report.pitch);
180
- lines.push('');
181
- lines.push(`**Runtime:** ${report.toolCount} MCP tools · ${report.runtime.vectorProvider} embeddings · ${report.runtime.encryption ? 'encryption ON' : 'encryption off'} · agent ${report.runtime.agentLoop}`);
182
- lines.push(`**Install:** ${report.install.platform} · Node ${report.install.nodeVersion} · DB ${report.install.dbPath}`);
183
- lines.push('');
184
- lines.push('## What Wyrm gives you beyond "AI memory"');
185
- lines.push('');
186
- for (const f of report.features) {
187
- lines.push(`### ${f.name}`);
188
- lines.push(`- **What:** ${f.what}`);
189
- lines.push(`- **Why:** ${f.why}`);
190
- lines.push(`- **Tools:** \`${f.tools.join('`, `')}\``);
191
- lines.push('');
192
- }
193
- return lines.join('\n');
194
- }
195
- //# sourceMappingURL=capabilities.js.map
14
+ this requires you to leave your laptop.`,w=[{name:"Counter-pattern memory",what:"Records failed approaches with (scope, target, description) and blocks the same suggestion next time.",why:"Other memory tools learn only from success. Wyrm refuses to repeat mistakes \u2014 saves the most expensive class of tokens (the regenerated wrong answer).",tools:["wyrm_failure_record","wyrm_failure_check","wyrm_failure_list","wyrm_failure_resolve"]},{name:"Ground truths (versioned, cascade-aware)",what:"Validated project facts (architecture, constraints, decisions) \u2014 each truth carries a version, last-verified timestamp, and outbound decision links.",why:"Truths are injected first into every wyrm_context_build call so the AI never works from contradicted assumptions. When a truth changes, dependent decisions auto-invalidate.",tools:["wyrm_truth_set","wyrm_truth_get","wyrm_decided_because","wyrm_decision_upstream","wyrm_decision_downstream","wyrm_decision_invalidate"]},{name:"Reasoning scaffolds",what:'Saved step-by-step checklists for problem types ("debug a slow query", "ship a migration") that surface automatically when a task description matches.',why:"Replaces ad-hoc rediscovery of process knowledge with structured prompts. Cheaper than re-explaining the playbook every session.",tools:["wyrm_scaffold_save","wyrm_scaffold_get"]},{name:"Lossless session rehydration",what:"wyrm_session_rehydrate produces a complete briefing markdown a fresh AI ingests to inherit prior state \u2014 decisions, open quests, failures, recent commits, files touched.",why:"Cross-session continuity without re-exploration. The single biggest token-saver in the toolkit.",tools:["wyrm_session_rehydrate","wyrm_session_prime","wyrm_session_start","wyrm_session_update"]},{name:"Distillation queue",what:"Candidate memory artifacts extracted from sessions land in a review queue; the operator approves or rejects each.",why:"Bayesian confidence updates after each review \u2014 Wyrm gets sharper with use without auto-trusting noise.",tools:["wyrm_distill","wyrm_review","wyrm_remember","wyrm_recall","wyrm_feedback"]},{name:"Knowledge graph",what:"Named entities + typed directional relationships, neighborhood traversal, shortest-path queries.",why:'When the AI asks "how does X relate to Y?", Wyrm answers in O(log n) instead of grepping the corpus.',tools:["wyrm_entity_add","wyrm_entity_link","wyrm_entity_search","wyrm_entity_graph","wyrm_entity_path","wyrm_entity_merge"]},{name:"Cross-repo symbol index",what:"Workspace-wide function/class/type index across TS/JS/Python/Rust/Go/PHP/Ruby with caller resolution.",why:`Symbol lookups don't require re-grepping every project. "Who calls handleAuth?" answers immediately.`,tools:["wyrm_symbol_index","wyrm_symbol_search","wyrm_symbol_callers","wyrm_symbol_stats"]},{name:"OODA agent loop (autonomous goals)",what:"wyrm_goal_set persists an objective with success criteria. The wyrm-loop daemon runs Observe\u2192Orient\u2192Decide\u2192Act every interval, dispatching whitelisted tools. Replayable, capped, auditable.",why:"Lets you hand the AI a multi-step objective and walk away. No data-exfil tools accessible from inside the loop.",tools:["wyrm_goal_set","wyrm_goal_list","wyrm_goal_pause","wyrm_goal_resume","wyrm_goal_complete","wyrm_goal_abandon","wyrm_goal_iterations","wyrm_act","wyrm_agent_init","wyrm_agent_status","wyrm_agent_stop","wyrm_agent_restart"]},{name:"Outbound MCP client",what:"Wyrm calls other MCP servers (GitHub, Slack, Linear, \u2026) over stdio. The agent loop dispatches them like internal tools.",why:"Composability: Wyrm becomes the orchestration layer over your entire MCP stack instead of a sibling.",tools:["wyrm_mcp_register","wyrm_mcp_list","wyrm_mcp_disable","wyrm_mcp_tools","wyrm_call_external"]},{name:"Hybrid semantic search",what:"wyrm_search fuses FTS5 keyword candidates with vector candidates (Ollama nomic-embed-text by default; OpenAI optional) via Reciprocal Rank Fusion.",why:`Catches both "exact term" and "semantically similar" hits in one call. Silently falls back to FTS5-only if Ollama isn't running.`,tools:["wyrm_search","wyrm_vector_setup"]},{name:"Multi-agent presence + work-stealing",what:"Claude, Copilot, Cursor, and Codex announce themselves via TTL heartbeats. Quests can be claimed exclusively.",why:"No two agents step on the same quest. The work-stealing semantics scale to teams.",tools:["wyrm_presence_announce","wyrm_presence_list","wyrm_presence_release","wyrm_quest_claim","wyrm_quest_release"]},{name:"Federated team sync",what:"Per-row is_shared flag, /sync/push endpoint, conflict-as-quest semantics. PII never leaves the box unless explicitly shared.",why:"Team memory without a SaaS. No silent overwrites \u2014 every conflict becomes a quest the operator resolves.",tools:["wyrm_share","wyrm_unshare","wyrm_sync","wyrm_sync_export","wyrm_sync_import","wyrm_sync_conflicts","wyrm_sync_resolve"]},{name:"Compliance audit trail",what:"Hash-chained audit log with optional Ed25519 signatures. wyrm_audit_export produces tamper-evident bundles.",why:"SOC2/HIPAA reviewers get a real artifact. The hash chain detects any tampering after the fact.",tools:["wyrm_audit_log","wyrm_audit_export","wyrm_audit_verify"]},{name:"Hour ledger + invoice generation",what:"Derives billable hours from session content and emits markdown invoices.",why:"For solo operators and small teams: Wyrm is also the time tracker. No second tool to keep in sync.",tools:["wyrm_hours_report","wyrm_invoice_generate","wyrm_cost_report"]},{name:"Self-improvement analytics",what:"Per-tool error rate, p50/p95 latency, cost-per-tool. Wyrm watches Wyrm.",why:"Lets you spot which tools are hot, which are slow, which fail \u2014 input for both ops tuning and product decisions.",tools:["wyrm_analytics_dashboard","wyrm_tool_analytics","wyrm_usage","wyrm_stats"]}];function u(){try{const t=[o(a,"..","package.json"),o(a,"..","..","package.json")];for(const e of t)if(m(e))return JSON.parse(c(e,"utf-8")).version??"unknown"}catch{}return"unknown"}function v(t,e,s){const i=process.env.WYRM_DB_PATH??o(n(),".wyrm","wyrm.db"),r=s.isAgentRunning();return{product:"Wyrm",version:u(),pitch:d,install:{dbPath:i,nodeVersion:process.version,platform:`${process.platform}-${process.arch}`},runtime:{vectorProvider:s.detectVectorProvider(),encryption:s.hasEncryption(),federation:s.isFederationEnabled(),agentLoop:r===null?"unknown":r?"running":"stopped"},features:w,toolCount:e}}function b(t){const e=[];e.push(`# \u{F115D} ${t.product} ${t.version} \u2014 Capability Briefing`),e.push(""),e.push(t.pitch),e.push(""),e.push(`**Runtime:** ${t.toolCount} MCP tools \xB7 ${t.runtime.vectorProvider} embeddings \xB7 ${t.runtime.encryption?"encryption ON":"encryption off"} \xB7 agent ${t.runtime.agentLoop}`),e.push(`**Install:** ${t.install.platform} \xB7 Node ${t.install.nodeVersion} \xB7 DB ${t.install.dbPath}`),e.push(""),e.push('## What Wyrm gives you beyond "AI memory"'),e.push("");for(const s of t.features)e.push(`### ${s.name}`),e.push(`- **What:** ${s.what}`),e.push(`- **Why:** ${s.why}`),e.push(`- **Tools:** \`${s.tools.join("`, `")}\``),e.push("");return e.join(`
15
+ `)}export{v as getCapabilities,b as renderCapabilityBriefing};
package/dist/capture.js CHANGED
@@ -1,56 +1 @@
1
- /**
2
- * Wyrm Capture Helpers — Classification logic for unified auto-capture.
3
- *
4
- * @copyright 2026 Ghost Protocol (Pvt) Ltd.
5
- * @license AGPL-3.0-or-later — dual-licensed; commercial terms: ghosts.lk@proton.me. See LICENSE.
6
- */
7
- /**
8
- * Classify a piece of content into quest/truth/memory using heuristic patterns.
9
- * Patterns are applied in priority order; first match wins.
10
- */
11
- export function classifyCapture(content) {
12
- // Pattern 1: quest — action-oriented task starters
13
- if (/^(TODO|TASK|QUEST|implement|build|fix|add|create|refactor|migrate|update|remove)\b/i.test(content)) {
14
- return {
15
- type: 'quest',
16
- subtype: 'quest',
17
- confidence: 85,
18
- reasoning: 'Starts with action/task keyword -- classified as a quest',
19
- };
20
- }
21
- // Pattern 2: truth — architectural decisions / constraints
22
- if (/\b(always|never|must not|we use|we decided|architecture decision|constraint:|rule:|standard:)\b/i.test(content)) {
23
- return {
24
- type: 'truth',
25
- subtype: 'decision',
26
- confidence: 80,
27
- reasoning: 'Contains ground-truth / decision marker -- classified as truth',
28
- };
29
- }
30
- // Pattern 3: lesson — retrospective / root-cause learning
31
- if (/\b(learned|lesson|anti-pattern|mistake|bug was|root cause|turned out|retrospective)\b/i.test(content)) {
32
- return {
33
- type: 'memory',
34
- subtype: 'lesson',
35
- confidence: 80,
36
- reasoning: 'Contains lesson / retrospective marker -- classified as lesson',
37
- };
38
- }
39
- // Pattern 4: heuristic — guidelines / conditional rules
40
- if (/\b(when.*use|if.*then|prefer.*over|avoid|guideline|best practice)\b/i.test(content)) {
41
- return {
42
- type: 'memory',
43
- subtype: 'heuristic',
44
- confidence: 75,
45
- reasoning: 'Contains guideline / heuristic marker -- classified as heuristic',
46
- };
47
- }
48
- // Pattern 5: pattern — default fallback
49
- return {
50
- type: 'memory',
51
- subtype: 'pattern',
52
- confidence: 60,
53
- reasoning: 'No specific marker detected -- stored as general pattern',
54
- };
55
- }
56
- //# sourceMappingURL=capture.js.map
1
+ function t(e){return/^(TODO|TASK|QUEST|implement|build|fix|add|create|refactor|migrate|update|remove)\b/i.test(e)?{type:"quest",subtype:"quest",confidence:85,reasoning:"Starts with action/task keyword -- classified as a quest"}:/\b(always|never|must not|we use|we decided|architecture decision|constraint:|rule:|standard:)\b/i.test(e)?{type:"truth",subtype:"decision",confidence:80,reasoning:"Contains ground-truth / decision marker -- classified as truth"}:/\b(learned|lesson|anti-pattern|mistake|bug was|root cause|turned out|retrospective)\b/i.test(e)?{type:"memory",subtype:"lesson",confidence:80,reasoning:"Contains lesson / retrospective marker -- classified as lesson"}:/\b(when.*use|if.*then|prefer.*over|avoid|guideline|best practice)\b/i.test(e)?{type:"memory",subtype:"heuristic",confidence:75,reasoning:"Contains guideline / heuristic marker -- classified as heuristic"}:{type:"memory",subtype:"pattern",confidence:60,reasoning:"No specific marker detected -- stored as general pattern"}}export{t as classifyCapture};
package/dist/causality.js CHANGED
@@ -1,124 +1,23 @@
1
- /**
2
- * Causality — decision chains + downstream invalidation.
3
- *
4
- * "We chose Postgres because Y" → "Y turned out to be wrong" → flag every
5
- * downstream decision built on Y for re-evaluation.
6
- *
7
- * Edges link a `(kind, id)` pair to another `(kind, id)` pair with a
8
- * relation (`because_of`, `supersedes`, `refutes`, `verifies`). When a
9
- * ground truth flips to stale or gets superseded, the invalidation
10
- * cascade walks the edge graph and flags downstream decisions.
11
- *
12
- * @copyright 2026 Ghost Protocol (Pvt) Ltd.
13
- * @license AGPL-3.0-or-later — dual-licensed; commercial terms: ghosts.lk@proton.me. See LICENSE.
14
- */
15
- import { emitEvent } from './events.js';
16
- import { getActor } from './handlers/boundary.js';
17
- export class Causality {
18
- db;
19
- constructor(db) {
20
- this.db = db;
21
- }
22
- /** Record that `from` was decided BECAUSE OF `to` (or other relation). */
23
- link(input) {
24
- // v7 F2 (T009): stamp the writing actor (NULL outside a fleet context).
25
- const ambient = getActor();
26
- const info = this.db.prepare(`
1
+ import{emitEvent as l}from"./events.js";import{getActor as f}from"./handlers/boundary.js";class g{db;constructor(e){this.db=e}link(e){const d=f(),s=this.db.prepare(`
27
2
  INSERT INTO decision_edges
28
3
  (project_id, from_kind, from_id, to_kind, to_id, relation, rationale, confidence, agent_id, run_id)
29
4
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
30
- `).run(input.project_id, input.from_kind, input.from_id, input.to_kind, input.to_id, input.relation ?? 'because_of', input.rationale ?? null, input.confidence ?? 1.0, ambient.agent_id, ambient.run_id);
31
- const edge = this.get(info.lastInsertRowid);
32
- emitEvent(this.db, {
33
- projectId: input.project_id, kind: 'decision', refTable: 'decision_edges', refId: edge.id,
34
- isShared: !!edge.is_shared,
35
- });
36
- return edge;
37
- }
38
- get(id) {
39
- return this.db.prepare('SELECT * FROM decision_edges WHERE id = ?').get(id) ?? null;
40
- }
41
- /** All decisions that depend on the given source (outgoing edges from source). */
42
- downstreamOf(kind, id) {
43
- return this.db.prepare(`
5
+ `).run(e.project_id,e.from_kind,e.from_id,e.to_kind,e.to_id,e.relation??"because_of",e.rationale??null,e.confidence??1,d.agent_id,d.run_id),i=this.get(s.lastInsertRowid);return l(this.db,{projectId:e.project_id,kind:"decision",refTable:"decision_edges",refId:i.id,isShared:!!i.is_shared}),i}get(e){return this.db.prepare("SELECT * FROM decision_edges WHERE id = ?").get(e)??null}downstreamOf(e,d){return this.db.prepare(`
44
6
  SELECT * FROM decision_edges
45
7
  WHERE to_kind = ? AND to_id = ? AND invalidated_at IS NULL
46
8
  ORDER BY created_at DESC
47
- `).all(kind, id);
48
- }
49
- /** All sources that the given decision was based on (incoming edges to decision). */
50
- upstreamOf(kind, id) {
51
- return this.db.prepare(`
9
+ `).all(e,d)}upstreamOf(e,d){return this.db.prepare(`
52
10
  SELECT * FROM decision_edges
53
11
  WHERE from_kind = ? AND from_id = ? AND invalidated_at IS NULL
54
12
  ORDER BY created_at DESC
55
- `).all(kind, id);
56
- }
57
- /** Walk downstream from a source, depth-first, marking dependent decisions.
58
- * Returns the set of (kind, id) pairs affected. Idempotent — already-
59
- * invalidated edges are skipped. */
60
- invalidateDownstream(kind, id, reason) {
61
- const affected = [];
62
- const seen = new Set();
63
- const queue = [{ kind, id }];
64
- const markEdge = this.db.prepare(`
13
+ `).all(e,d)}invalidateDownstream(e,d,s){const i=[],r=new Set,t=[{kind:e,id:d}],c=this.db.prepare(`
65
14
  UPDATE decision_edges
66
15
  SET invalidated_at = datetime('now'),
67
16
  rationale = COALESCE(?, rationale)
68
17
  WHERE id = ?
69
- `);
70
- while (queue.length > 0) {
71
- const node = queue.shift();
72
- const key = `${node.kind}:${node.id}`;
73
- if (seen.has(key))
74
- continue;
75
- seen.add(key);
76
- const edges = this.downstreamOf(node.kind, node.id);
77
- for (const edge of edges) {
78
- markEdge.run(reason ?? null, edge.id);
79
- affected.push({
80
- kind: edge.from_kind,
81
- id: edge.from_id,
82
- edge_id: edge.id,
83
- rationale: edge.rationale,
84
- });
85
- queue.push({ kind: edge.from_kind, id: edge.from_id });
86
- }
87
- }
88
- return { invalidated: affected.length, affected };
89
- }
90
- /** Path query: list edges forming the decision chain from `from` back to `to`,
91
- * walking upstream up to maxDepth. Returns empty if no path. */
92
- pathTo(from, to, maxDepth = 6) {
93
- const visited = new Set();
94
- const stack = [
95
- { node: from, path: [] },
96
- ];
97
- while (stack.length > 0) {
98
- const { node, path } = stack.pop();
99
- const key = `${node.kind}:${node.id}`;
100
- if (visited.has(key) || path.length > maxDepth)
101
- continue;
102
- visited.add(key);
103
- if (node.kind === to.kind && node.id === to.id)
104
- return path;
105
- for (const edge of this.upstreamOf(node.kind, node.id)) {
106
- stack.push({
107
- node: { kind: edge.to_kind, id: edge.to_id },
108
- path: [...path, edge],
109
- });
110
- }
111
- }
112
- return [];
113
- }
114
- /** List all currently-invalidated edges that touch a project. */
115
- invalidatedInProject(projectId, limit = 50) {
116
- return this.db.prepare(`
18
+ `);for(;t.length>0;){const n=t.shift(),a=`${n.kind}:${n.id}`;if(r.has(a))continue;r.add(a);const _=this.downstreamOf(n.kind,n.id);for(const o of _)c.run(s??null,o.id),i.push({kind:o.from_kind,id:o.from_id,edge_id:o.id,rationale:o.rationale}),t.push({kind:o.from_kind,id:o.from_id})}return{invalidated:i.length,affected:i}}pathTo(e,d,s=6){const i=new Set,r=[{node:e,path:[]}];for(;r.length>0;){const{node:t,path:c}=r.pop(),n=`${t.kind}:${t.id}`;if(!(i.has(n)||c.length>s)){if(i.add(n),t.kind===d.kind&&t.id===d.id)return c;for(const a of this.upstreamOf(t.kind,t.id))r.push({node:{kind:a.to_kind,id:a.to_id},path:[...c,a]})}}return[]}invalidatedInProject(e,d=50){return this.db.prepare(`
117
19
  SELECT * FROM decision_edges
118
20
  WHERE project_id = ? AND invalidated_at IS NOT NULL
119
21
  ORDER BY invalidated_at DESC
120
22
  LIMIT ?
121
- `).all(projectId, limit);
122
- }
123
- }
124
- //# sourceMappingURL=causality.js.map
23
+ `).all(e,d)}}export{g as Causality};