wyrm-mcp 7.3.2 → 7.3.3

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 (184) hide show
  1. package/README.md +8 -14
  2. package/dist/activation.js +59 -1
  3. package/dist/agent-daemon.js +281 -4
  4. package/dist/agent-loop.js +332 -7
  5. package/dist/analytics.js +236 -13
  6. package/dist/attribution.js +49 -1
  7. package/dist/audit.js +457 -2
  8. package/dist/auto-capture.js +138 -3
  9. package/dist/auto-orchestrator.js +325 -1
  10. package/dist/autoconfig.d.ts +50 -0
  11. package/dist/autoconfig.d.ts.map +1 -1
  12. package/dist/autoconfig.js +1115 -39
  13. package/dist/autoconfig.js.map +1 -1
  14. package/dist/buddy-runner.js +109 -1
  15. package/dist/buddy.js +564 -14
  16. package/dist/build-flags.js +15 -1
  17. package/dist/capabilities.js +183 -3
  18. package/dist/capture.js +56 -1
  19. package/dist/causality.js +148 -8
  20. package/dist/cli.js +281 -20
  21. package/dist/cloud/cli.js +541 -5
  22. package/dist/cloud/client.js +221 -1
  23. package/dist/cloud/crypto.js +85 -1
  24. package/dist/cloud/machine-id.js +113 -2
  25. package/dist/cloud/recovery.js +60 -1
  26. package/dist/cloud/sync-engine.js +543 -7
  27. package/dist/cloud-backup.js +579 -5
  28. package/dist/cloud-profile.js +138 -1
  29. package/dist/cloud-sync-entrypoint.js +47 -1
  30. package/dist/cloud-sync.js +309 -2
  31. package/dist/connectors/bridge-source.d.ts +46 -0
  32. package/dist/connectors/bridge-source.d.ts.map +1 -0
  33. package/dist/connectors/bridge-source.js +77 -0
  34. package/dist/connectors/bridge-source.js.map +1 -0
  35. package/dist/connectors/index.d.ts +24 -0
  36. package/dist/connectors/index.d.ts.map +1 -0
  37. package/dist/connectors/index.js +69 -0
  38. package/dist/connectors/index.js.map +1 -0
  39. package/dist/connectors/ingest.d.ts +16 -0
  40. package/dist/connectors/ingest.d.ts.map +1 -0
  41. package/dist/connectors/ingest.js +116 -0
  42. package/dist/connectors/ingest.js.map +1 -0
  43. package/dist/connectors/types.d.ts +99 -0
  44. package/dist/connectors/types.d.ts.map +1 -0
  45. package/dist/connectors/types.js +17 -0
  46. package/dist/connectors/types.js.map +1 -0
  47. package/dist/constellation.js +168 -12
  48. package/dist/content-signature.js +45 -1
  49. package/dist/context-build-budgeted.js +144 -4
  50. package/dist/context-ranking.js +69 -1
  51. package/dist/crypto.js +179 -1
  52. package/dist/daemon-write-endpoint.js +290 -1
  53. package/dist/daemon-writer.js +406 -2
  54. package/dist/database.js +1278 -53
  55. package/dist/deprecations.js +162 -2
  56. package/dist/design.js +141 -13
  57. package/dist/event-replication.js +112 -1
  58. package/dist/events-sse.js +43 -7
  59. package/dist/events.js +238 -6
  60. package/dist/failure-patterns.d.ts +107 -0
  61. package/dist/failure-patterns.d.ts.map +1 -1
  62. package/dist/failure-patterns.js +924 -43
  63. package/dist/failure-patterns.js.map +1 -1
  64. package/dist/federation.js +236 -12
  65. package/dist/goals.js +101 -13
  66. package/dist/golden.js +355 -3
  67. package/dist/handlers/agent.js +165 -4
  68. package/dist/handlers/alias-adapters.js +129 -1
  69. package/dist/handlers/aliases.js +171 -1
  70. package/dist/handlers/audit.js +87 -1
  71. package/dist/handlers/boundary.js +221 -1
  72. package/dist/handlers/capture.js +1114 -73
  73. package/dist/handlers/causality.js +119 -9
  74. package/dist/handlers/cloud.js +382 -85
  75. package/dist/handlers/companion.js +459 -28
  76. package/dist/handlers/datalake.js +187 -7
  77. package/dist/handlers/dispatch-context.js +22 -0
  78. package/dist/handlers/entity.js +256 -25
  79. package/dist/handlers/events.js +335 -16
  80. package/dist/handlers/failure.d.ts.map +1 -1
  81. package/dist/handlers/failure.js +408 -13
  82. package/dist/handlers/failure.js.map +1 -1
  83. package/dist/handlers/goals.js +296 -4
  84. package/dist/handlers/intelligence.js +681 -126
  85. package/dist/handlers/invoicing.js +70 -1
  86. package/dist/handlers/mcpclient.js +137 -6
  87. package/dist/handlers/orchestration.js +125 -40
  88. package/dist/handlers/output-schemas.js +24 -1
  89. package/dist/handlers/presence.js +99 -3
  90. package/dist/handlers/project.js +182 -28
  91. package/dist/handlers/prompts.js +157 -6
  92. package/dist/handlers/quest.js +224 -4
  93. package/dist/handlers/recall.js +237 -13
  94. package/dist/handlers/registry.js +167 -1
  95. package/dist/handlers/resources.js +288 -1
  96. package/dist/handlers/review.js +74 -11
  97. package/dist/handlers/run.js +498 -16
  98. package/dist/handlers/search.js +338 -15
  99. package/dist/handlers/session.js +643 -31
  100. package/dist/handlers/share.js +184 -8
  101. package/dist/handlers/shims.js +464 -1
  102. package/dist/handlers/skill.js +449 -67
  103. package/dist/handlers/survivors.js +120 -1
  104. package/dist/handlers/symbols.js +109 -8
  105. package/dist/handlers/syncops.js +302 -4
  106. package/dist/handlers/types.js +27 -1
  107. package/dist/harvest.js +191 -5
  108. package/dist/hours.js +156 -7
  109. package/dist/http-auth.js +321 -3
  110. package/dist/http-fast.js +1302 -22
  111. package/dist/icons.js +47 -1
  112. package/dist/importers.js +268 -1
  113. package/dist/index.js +840 -2
  114. package/dist/indexer.js +145 -4
  115. package/dist/intelligence.js +261 -31
  116. package/dist/internal-dispatch.js +212 -3
  117. package/dist/keyset.js +110 -1
  118. package/dist/knowledge-graph.js +176 -12
  119. package/dist/license.js +441 -2
  120. package/dist/logger.js +199 -2
  121. package/dist/maintenance.js +148 -2
  122. package/dist/mcp-client.js +262 -6
  123. package/dist/memory-artifacts.js +596 -32
  124. package/dist/migrate-prompt.js +124 -2
  125. package/dist/migrations.d.ts.map +1 -1
  126. package/dist/migrations.js +799 -42
  127. package/dist/migrations.js.map +1 -1
  128. package/dist/performance.js +228 -1
  129. package/dist/presence.js +140 -11
  130. package/dist/priority-embed.js +164 -5
  131. package/dist/providers/embedding-provider.js +196 -1
  132. package/dist/readonly-gate.js +29 -1
  133. package/dist/receipt.js +43 -1
  134. package/dist/rehydration.js +157 -9
  135. package/dist/reindex.js +88 -1
  136. package/dist/render-target.js +544 -21
  137. package/dist/render.js +280 -4
  138. package/dist/repl-guard.js +173 -1
  139. package/dist/replication-daemon-entrypoint.js +31 -1
  140. package/dist/replication-daemon.js +262 -2
  141. package/dist/rerank.js +142 -1
  142. package/dist/resilience.js +591 -1
  143. package/dist/reverse-bridge.js +360 -5
  144. package/dist/security.js +244 -1
  145. package/dist/session-seen.js +51 -3
  146. package/dist/setup.js +260 -1
  147. package/dist/skill-author.js +168 -5
  148. package/dist/spec-kit.js +191 -1
  149. package/dist/sqlite-busy.js +154 -1
  150. package/dist/statusline.js +315 -11
  151. package/dist/sub-agent.js +262 -13
  152. package/dist/summarizer.js +139 -13
  153. package/dist/symbols.js +283 -7
  154. package/dist/sync.js +359 -5
  155. package/dist/tasks-dispatch.js +84 -1
  156. package/dist/tasks.js +282 -1
  157. package/dist/token-budget.js +143 -1
  158. package/dist/tool-analytics.js +129 -7
  159. package/dist/tool-annotations.js +365 -1
  160. package/dist/tool-manifest-v2.json +1 -1
  161. package/dist/tool-manifest.json +1 -1
  162. package/dist/tool-profiles.js +75 -1
  163. package/dist/trace-harvest.js +244 -6
  164. package/dist/types.js +30 -1
  165. package/dist/ui-dashboard.js +50 -41
  166. package/dist/ulid.js +81 -1
  167. package/dist/usage-tracker.js +66 -1
  168. package/dist/validate.js +129 -1
  169. package/dist/vault.js +534 -1
  170. package/dist/vector-init.js +67 -1
  171. package/dist/vectors.js +184 -3
  172. package/dist/version-check.js +136 -4
  173. package/dist/visibility.js +155 -19
  174. package/dist/wyrm-cli.js +2845 -101
  175. package/dist/wyrm-cli.js.map +1 -1
  176. package/dist/wyrm-guard.d.ts.map +1 -1
  177. package/dist/wyrm-guard.js +475 -14
  178. package/dist/wyrm-guard.js.map +1 -1
  179. package/dist/wyrm-loop.js +150 -3
  180. package/dist/wyrm-manifest.json +1 -1
  181. package/dist/wyrm-statusline-daemon.js +11 -1
  182. package/dist/wyrm-statusline.js +56 -4
  183. package/dist/wyrm-ui.js +77 -9
  184. package/package.json +1 -1
@@ -1,4 +1,25 @@
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
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 Proprietary — (c) 2026 Ghost Protocol (Pvt) Ltd. All rights reserved. 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
2
23
  substrate that solves the four specific problems AI assistants share:
3
24
 
4
25
  1. Amnesia. Sessions inherit prior state via lossless rehydration.
@@ -11,5 +32,164 @@ substrate that solves the four specific problems AI assistants share:
11
32
  Every Wyrm session is local-first SQLite with FTS5 + hybrid semantic search.
12
33
  Encryption is operator-controlled. Federation is opt-in per row. The audit
13
34
  log is hash-chained and Ed25519-signable for SOC2/HIPAA scenarios. None of
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};
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
package/dist/capture.js CHANGED
@@ -1 +1,56 @@
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};
1
+ /**
2
+ * Wyrm Capture Helpers — Classification logic for unified auto-capture.
3
+ *
4
+ * @copyright 2026 Ghost Protocol (Pvt) Ltd.
5
+ * @license Proprietary — (c) 2026 Ghost Protocol (Pvt) Ltd. All rights reserved. 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
package/dist/causality.js CHANGED
@@ -1,29 +1,169 @@
1
- import{emitEvent as f}from"./events.js";import{getActor as E}from"./handlers/boundary.js";function g(c){if(c.length===0)return"";const e=c.map(r=>`${r.to_kind} #${r.to_id} (${r.reason})`).join(", "),t=c.length===1;return`[STALE FOUNDATION] this decision rests on ${t?"a foundation that has":`${c.length} foundations that have`} since been ${t?c[0].reason:"invalidated"} -- ${e}. Re-evaluate before relying on it (wyrm_decision_invalidate to cascade, or re-decide).`}class p{db;constructor(e){this.db=e}link(e){const t=E(),r=this.db.prepare(`
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 Proprietary — (c) 2026 Ghost Protocol (Pvt) Ltd. All rights reserved. See LICENSE.
14
+ */
15
+ import { emitEvent } from './events.js';
16
+ import { getActor } from './handlers/boundary.js';
17
+ /**
18
+ * Warn-at-recall: render the read-time interrupt for a decision whose recalled
19
+ * foundations have gone stale. ASCII-only (render-contract glyph law). Empty
20
+ * string when nothing is stale, so callers can append unconditionally.
21
+ */
22
+ export function staleFoundationWarning(stale) {
23
+ if (stale.length === 0)
24
+ return '';
25
+ const items = stale.map((s) => `${s.to_kind} #${s.to_id} (${s.reason})`).join(', ');
26
+ const one = stale.length === 1;
27
+ return (`[STALE FOUNDATION] this decision rests on ${one ? 'a foundation that has' : `${stale.length} foundations that have`} ` +
28
+ `since been ${one ? stale[0].reason : 'invalidated'} -- ${items}. ` +
29
+ `Re-evaluate before relying on it (wyrm_decision_invalidate to cascade, or re-decide).`);
30
+ }
31
+ export class Causality {
32
+ db;
33
+ constructor(db) {
34
+ this.db = db;
35
+ }
36
+ /** Record that `from` was decided BECAUSE OF `to` (or other relation). */
37
+ link(input) {
38
+ // v7 F2 (T009): stamp the writing actor (NULL outside a fleet context).
39
+ const ambient = getActor();
40
+ const info = this.db.prepare(`
2
41
  INSERT INTO decision_edges
3
42
  (project_id, from_kind, from_id, to_kind, to_id, relation, rationale, confidence, agent_id, run_id)
4
43
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
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,t.agent_id,t.run_id),n=this.get(r.lastInsertRowid);return f(this.db,{projectId:e.project_id,kind:"decision",refTable:"decision_edges",refId:n.id,isShared:!!n.is_shared}),n}get(e){return this.db.prepare("SELECT * FROM decision_edges WHERE id = ?").get(e)??null}downstreamOf(e,t){return this.db.prepare(`
44
+ `).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);
45
+ const edge = this.get(info.lastInsertRowid);
46
+ emitEvent(this.db, {
47
+ projectId: input.project_id, kind: 'decision', refTable: 'decision_edges', refId: edge.id,
48
+ isShared: !!edge.is_shared,
49
+ });
50
+ return edge;
51
+ }
52
+ get(id) {
53
+ return this.db.prepare('SELECT * FROM decision_edges WHERE id = ?').get(id) ?? null;
54
+ }
55
+ /** All decisions that depend on the given source (outgoing edges from source). */
56
+ downstreamOf(kind, id) {
57
+ return this.db.prepare(`
6
58
  SELECT * FROM decision_edges
7
59
  WHERE to_kind = ? AND to_id = ? AND invalidated_at IS NULL
8
60
  ORDER BY created_at DESC
9
- `).all(e,t)}upstreamOf(e,t){return this.db.prepare(`
61
+ `).all(kind, id);
62
+ }
63
+ /** All sources that the given decision was based on (incoming edges to decision). */
64
+ upstreamOf(kind, id) {
65
+ return this.db.prepare(`
10
66
  SELECT * FROM decision_edges
11
67
  WHERE from_kind = ? AND from_id = ? AND invalidated_at IS NULL
12
68
  ORDER BY created_at DESC
13
- `).all(e,t)}staleFoundations(e,t){const r=this.db.prepare(`
69
+ `).all(kind, id);
70
+ }
71
+ /**
72
+ * Warn-at-recall engine: the decision's `because_of` foundations that have
73
+ * gone stale — a foundation truth that was SUPERSEDED (is_current=0) or
74
+ * REFUTED (a live `refutes` edge targets it). Read-only, deterministic, the
75
+ * basis of the read-time interrupt surfaced by wyrm_decision_upstream.
76
+ */
77
+ staleFoundations(kind, id) {
78
+ const foundations = this.db.prepare(`
14
79
  SELECT to_kind, to_id FROM decision_edges
15
80
  WHERE from_kind = ? AND from_id = ? AND relation = 'because_of' AND invalidated_at IS NULL
16
- `).all(e,t),n=this.db.prepare("SELECT is_current FROM ground_truths WHERE id = ?"),s=this.db.prepare(`
81
+ `).all(kind, id);
82
+ const truthCurrent = this.db.prepare(`SELECT is_current FROM ground_truths WHERE id = ?`);
83
+ const refutes = this.db.prepare(`
17
84
  SELECT 1 FROM decision_edges
18
85
  WHERE to_kind = ? AND to_id = ? AND relation = 'refutes' AND invalidated_at IS NULL LIMIT 1
19
- `),i=[];for(const o of r){let d=null;if(o.to_kind==="truth"){const a=n.get(o.to_id);a&&a.is_current===0&&(d="superseded")}!d&&s.get(o.to_kind,o.to_id)&&(d="refuted"),d&&i.push({to_kind:o.to_kind,to_id:o.to_id,reason:d})}return i}invalidateDownstream(e,t,r){const n=[],s=new Set,i=[{kind:e,id:t}],o=this.db.prepare(`
86
+ `);
87
+ const out = [];
88
+ for (const f of foundations) {
89
+ let reason = null;
90
+ if (f.to_kind === 'truth') {
91
+ const t = truthCurrent.get(f.to_id);
92
+ if (t && t.is_current === 0)
93
+ reason = 'superseded';
94
+ }
95
+ if (!reason && refutes.get(f.to_kind, f.to_id))
96
+ reason = 'refuted';
97
+ if (reason)
98
+ out.push({ to_kind: f.to_kind, to_id: f.to_id, reason });
99
+ }
100
+ return out;
101
+ }
102
+ /** Walk downstream from a source, depth-first, marking dependent decisions.
103
+ * Returns the set of (kind, id) pairs affected. Idempotent — already-
104
+ * invalidated edges are skipped. */
105
+ invalidateDownstream(kind, id, reason) {
106
+ const affected = [];
107
+ const seen = new Set();
108
+ const queue = [{ kind, id }];
109
+ const markEdge = this.db.prepare(`
20
110
  UPDATE decision_edges
21
111
  SET invalidated_at = datetime('now'),
22
112
  rationale = COALESCE(?, rationale)
23
113
  WHERE id = ?
24
- `);for(;i.length>0;){const d=i.shift(),a=`${d.kind}:${d.id}`;if(s.has(a))continue;s.add(a);const l=this.downstreamOf(d.kind,d.id);for(const _ of l)o.run(r??null,_.id),n.push({kind:_.from_kind,id:_.from_id,edge_id:_.id,rationale:_.rationale}),i.push({kind:_.from_kind,id:_.from_id})}return{invalidated:n.length,affected:n}}pathTo(e,t,r=6){const n=new Set,s=[{node:e,path:[]}];for(;s.length>0;){const{node:i,path:o}=s.pop(),d=`${i.kind}:${i.id}`;if(!(n.has(d)||o.length>r)){if(n.add(d),i.kind===t.kind&&i.id===t.id)return o;for(const a of this.upstreamOf(i.kind,i.id))s.push({node:{kind:a.to_kind,id:a.to_id},path:[...o,a]})}}return[]}invalidatedInProject(e,t=50){return this.db.prepare(`
114
+ `);
115
+ while (queue.length > 0) {
116
+ const node = queue.shift();
117
+ const key = `${node.kind}:${node.id}`;
118
+ if (seen.has(key))
119
+ continue;
120
+ seen.add(key);
121
+ const edges = this.downstreamOf(node.kind, node.id);
122
+ for (const edge of edges) {
123
+ markEdge.run(reason ?? null, edge.id);
124
+ affected.push({
125
+ kind: edge.from_kind,
126
+ id: edge.from_id,
127
+ edge_id: edge.id,
128
+ rationale: edge.rationale,
129
+ });
130
+ queue.push({ kind: edge.from_kind, id: edge.from_id });
131
+ }
132
+ }
133
+ return { invalidated: affected.length, affected };
134
+ }
135
+ /** Path query: list edges forming the decision chain from `from` back to `to`,
136
+ * walking upstream up to maxDepth. Returns empty if no path. */
137
+ pathTo(from, to, maxDepth = 6) {
138
+ const visited = new Set();
139
+ const stack = [
140
+ { node: from, path: [] },
141
+ ];
142
+ while (stack.length > 0) {
143
+ const { node, path } = stack.pop();
144
+ const key = `${node.kind}:${node.id}`;
145
+ if (visited.has(key) || path.length > maxDepth)
146
+ continue;
147
+ visited.add(key);
148
+ if (node.kind === to.kind && node.id === to.id)
149
+ return path;
150
+ for (const edge of this.upstreamOf(node.kind, node.id)) {
151
+ stack.push({
152
+ node: { kind: edge.to_kind, id: edge.to_id },
153
+ path: [...path, edge],
154
+ });
155
+ }
156
+ }
157
+ return [];
158
+ }
159
+ /** List all currently-invalidated edges that touch a project. */
160
+ invalidatedInProject(projectId, limit = 50) {
161
+ return this.db.prepare(`
25
162
  SELECT * FROM decision_edges
26
163
  WHERE project_id = ? AND invalidated_at IS NOT NULL
27
164
  ORDER BY invalidated_at DESC
28
165
  LIMIT ?
29
- `).all(e,t)}}export{p as Causality,g as staleFoundationWarning};
166
+ `).all(projectId, limit);
167
+ }
168
+ }
169
+ //# sourceMappingURL=causality.js.map