darwin-agents 0.4.6 → 0.4.7

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 (233) hide show
  1. package/CHANGELOG.md +224 -0
  2. package/README.md +64 -1
  3. package/dist/examples/closed-loop-feedback.d.ts +100 -0
  4. package/dist/examples/closed-loop-feedback.d.ts.map +1 -0
  5. package/dist/examples/closed-loop-feedback.js +199 -0
  6. package/dist/examples/closed-loop-feedback.js.map +1 -0
  7. package/dist/examples/custom-agent.d.ts +10 -0
  8. package/dist/examples/custom-agent.d.ts.map +1 -0
  9. package/dist/examples/custom-agent.js +98 -0
  10. package/dist/examples/custom-agent.js.map +1 -0
  11. package/dist/examples/mcp-memory-bridge.d.ts +183 -0
  12. package/dist/examples/mcp-memory-bridge.d.ts.map +1 -0
  13. package/dist/examples/mcp-memory-bridge.js +542 -0
  14. package/dist/examples/mcp-memory-bridge.js.map +1 -0
  15. package/dist/examples/memory-darwin-integration.d.ts +63 -0
  16. package/dist/examples/memory-darwin-integration.d.ts.map +1 -0
  17. package/dist/examples/memory-darwin-integration.js +123 -0
  18. package/dist/examples/memory-darwin-integration.js.map +1 -0
  19. package/dist/examples/staleness-monitor.d.ts +45 -0
  20. package/dist/examples/staleness-monitor.d.ts.map +1 -0
  21. package/dist/examples/staleness-monitor.js +127 -0
  22. package/dist/examples/staleness-monitor.js.map +1 -0
  23. package/dist/src/agents/analyst.d.ts.map +1 -0
  24. package/dist/src/agents/analyst.js.map +1 -0
  25. package/dist/src/agents/blog-writer.d.ts.map +1 -0
  26. package/dist/src/agents/blog-writer.js.map +1 -0
  27. package/dist/src/agents/critic.d.ts.map +1 -0
  28. package/dist/src/agents/critic.js.map +1 -0
  29. package/dist/src/agents/index.d.ts.map +1 -0
  30. package/dist/src/agents/index.js.map +1 -0
  31. package/dist/src/agents/investigator-critic.d.ts.map +1 -0
  32. package/dist/src/agents/investigator-critic.js.map +1 -0
  33. package/dist/src/agents/investigator.d.ts.map +1 -0
  34. package/dist/src/agents/investigator.js.map +1 -0
  35. package/dist/src/agents/marketing.d.ts.map +1 -0
  36. package/dist/src/agents/marketing.js.map +1 -0
  37. package/dist/src/agents/researcher.d.ts.map +1 -0
  38. package/dist/src/agents/researcher.js.map +1 -0
  39. package/dist/src/agents/writer.d.ts.map +1 -0
  40. package/dist/src/agents/writer.js.map +1 -0
  41. package/dist/src/cli/create.d.ts.map +1 -0
  42. package/dist/src/cli/create.js.map +1 -0
  43. package/dist/src/cli/evolve.d.ts.map +1 -0
  44. package/dist/src/cli/evolve.js.map +1 -0
  45. package/dist/src/cli/index.d.ts.map +1 -0
  46. package/dist/src/cli/index.js.map +1 -0
  47. package/dist/src/cli/init.d.ts.map +1 -0
  48. package/dist/src/cli/init.js.map +1 -0
  49. package/dist/src/cli/run.d.ts.map +1 -0
  50. package/dist/src/cli/run.js.map +1 -0
  51. package/dist/src/cli/status.d.ts.map +1 -0
  52. package/dist/src/cli/status.js.map +1 -0
  53. package/dist/src/core/agent.d.ts.map +1 -0
  54. package/dist/src/core/agent.js.map +1 -0
  55. package/dist/src/core/runner.d.ts.map +1 -0
  56. package/dist/src/core/runner.js.map +1 -0
  57. package/dist/src/evolution/loop.d.ts.map +1 -0
  58. package/dist/src/evolution/loop.js.map +1 -0
  59. package/dist/src/evolution/multi-critic.d.ts.map +1 -0
  60. package/dist/src/evolution/multi-critic.js.map +1 -0
  61. package/dist/src/evolution/notifications.d.ts.map +1 -0
  62. package/dist/src/evolution/notifications.js.map +1 -0
  63. package/dist/src/evolution/optimizer.d.ts.map +1 -0
  64. package/dist/src/evolution/optimizer.js.map +1 -0
  65. package/dist/src/evolution/patterns.d.ts.map +1 -0
  66. package/dist/src/evolution/patterns.js.map +1 -0
  67. package/dist/src/evolution/safety.d.ts.map +1 -0
  68. package/dist/src/evolution/safety.js.map +1 -0
  69. package/dist/src/evolution/tracker.d.ts.map +1 -0
  70. package/dist/src/evolution/tracker.js.map +1 -0
  71. package/dist/src/index.d.ts.map +1 -0
  72. package/dist/src/index.js.map +1 -0
  73. package/dist/src/memory/index.d.ts.map +1 -0
  74. package/dist/src/memory/index.js.map +1 -0
  75. package/dist/src/memory/postgres-memory.d.ts.map +1 -0
  76. package/dist/src/memory/postgres-memory.js.map +1 -0
  77. package/dist/src/memory/sqlite-memory.d.ts.map +1 -0
  78. package/dist/src/memory/sqlite-memory.js.map +1 -0
  79. package/dist/src/providers/anthropic.d.ts.map +1 -0
  80. package/dist/src/providers/anthropic.js.map +1 -0
  81. package/dist/src/providers/claude-cli.d.ts.map +1 -0
  82. package/dist/src/providers/claude-cli.js.map +1 -0
  83. package/dist/src/providers/index.d.ts.map +1 -0
  84. package/dist/src/providers/index.js.map +1 -0
  85. package/dist/src/providers/ollama.d.ts.map +1 -0
  86. package/dist/src/providers/ollama.js.map +1 -0
  87. package/dist/src/providers/openai.d.ts.map +1 -0
  88. package/dist/src/providers/openai.js.map +1 -0
  89. package/dist/src/providers/types.d.ts.map +1 -0
  90. package/dist/src/providers/types.js.map +1 -0
  91. package/dist/src/types.d.ts.map +1 -0
  92. package/dist/src/types.js.map +1 -0
  93. package/package.json +19 -1
  94. package/dist/agents/analyst.d.ts.map +0 -1
  95. package/dist/agents/analyst.js.map +0 -1
  96. package/dist/agents/blog-writer.d.ts.map +0 -1
  97. package/dist/agents/blog-writer.js.map +0 -1
  98. package/dist/agents/critic.d.ts.map +0 -1
  99. package/dist/agents/critic.js.map +0 -1
  100. package/dist/agents/index.d.ts.map +0 -1
  101. package/dist/agents/index.js.map +0 -1
  102. package/dist/agents/investigator-critic.d.ts.map +0 -1
  103. package/dist/agents/investigator-critic.js.map +0 -1
  104. package/dist/agents/investigator.d.ts.map +0 -1
  105. package/dist/agents/investigator.js.map +0 -1
  106. package/dist/agents/marketing.d.ts.map +0 -1
  107. package/dist/agents/marketing.js.map +0 -1
  108. package/dist/agents/researcher.d.ts.map +0 -1
  109. package/dist/agents/researcher.js.map +0 -1
  110. package/dist/agents/writer.d.ts.map +0 -1
  111. package/dist/agents/writer.js.map +0 -1
  112. package/dist/cli/create.d.ts.map +0 -1
  113. package/dist/cli/create.js.map +0 -1
  114. package/dist/cli/evolve.d.ts.map +0 -1
  115. package/dist/cli/evolve.js.map +0 -1
  116. package/dist/cli/index.d.ts.map +0 -1
  117. package/dist/cli/index.js.map +0 -1
  118. package/dist/cli/init.d.ts.map +0 -1
  119. package/dist/cli/init.js.map +0 -1
  120. package/dist/cli/run.d.ts.map +0 -1
  121. package/dist/cli/run.js.map +0 -1
  122. package/dist/cli/status.d.ts.map +0 -1
  123. package/dist/cli/status.js.map +0 -1
  124. package/dist/core/agent.d.ts.map +0 -1
  125. package/dist/core/agent.js.map +0 -1
  126. package/dist/core/runner.d.ts.map +0 -1
  127. package/dist/core/runner.js.map +0 -1
  128. package/dist/evolution/loop.d.ts.map +0 -1
  129. package/dist/evolution/loop.js.map +0 -1
  130. package/dist/evolution/multi-critic.d.ts.map +0 -1
  131. package/dist/evolution/multi-critic.js.map +0 -1
  132. package/dist/evolution/notifications.d.ts.map +0 -1
  133. package/dist/evolution/notifications.js.map +0 -1
  134. package/dist/evolution/optimizer.d.ts.map +0 -1
  135. package/dist/evolution/optimizer.js.map +0 -1
  136. package/dist/evolution/patterns.d.ts.map +0 -1
  137. package/dist/evolution/patterns.js.map +0 -1
  138. package/dist/evolution/safety.d.ts.map +0 -1
  139. package/dist/evolution/safety.js.map +0 -1
  140. package/dist/evolution/tracker.d.ts.map +0 -1
  141. package/dist/evolution/tracker.js.map +0 -1
  142. package/dist/index.d.ts.map +0 -1
  143. package/dist/index.js.map +0 -1
  144. package/dist/memory/index.d.ts.map +0 -1
  145. package/dist/memory/index.js.map +0 -1
  146. package/dist/memory/postgres-memory.d.ts.map +0 -1
  147. package/dist/memory/postgres-memory.js.map +0 -1
  148. package/dist/memory/sqlite-memory.d.ts.map +0 -1
  149. package/dist/memory/sqlite-memory.js.map +0 -1
  150. package/dist/providers/anthropic.d.ts.map +0 -1
  151. package/dist/providers/anthropic.js.map +0 -1
  152. package/dist/providers/claude-cli.d.ts.map +0 -1
  153. package/dist/providers/claude-cli.js.map +0 -1
  154. package/dist/providers/index.d.ts.map +0 -1
  155. package/dist/providers/index.js.map +0 -1
  156. package/dist/providers/ollama.d.ts.map +0 -1
  157. package/dist/providers/ollama.js.map +0 -1
  158. package/dist/providers/openai.d.ts.map +0 -1
  159. package/dist/providers/openai.js.map +0 -1
  160. package/dist/providers/types.d.ts.map +0 -1
  161. package/dist/providers/types.js.map +0 -1
  162. package/dist/types.d.ts.map +0 -1
  163. package/dist/types.js.map +0 -1
  164. /package/dist/{agents → src/agents}/analyst.d.ts +0 -0
  165. /package/dist/{agents → src/agents}/analyst.js +0 -0
  166. /package/dist/{agents → src/agents}/blog-writer.d.ts +0 -0
  167. /package/dist/{agents → src/agents}/blog-writer.js +0 -0
  168. /package/dist/{agents → src/agents}/critic.d.ts +0 -0
  169. /package/dist/{agents → src/agents}/critic.js +0 -0
  170. /package/dist/{agents → src/agents}/index.d.ts +0 -0
  171. /package/dist/{agents → src/agents}/index.js +0 -0
  172. /package/dist/{agents → src/agents}/investigator-critic.d.ts +0 -0
  173. /package/dist/{agents → src/agents}/investigator-critic.js +0 -0
  174. /package/dist/{agents → src/agents}/investigator.d.ts +0 -0
  175. /package/dist/{agents → src/agents}/investigator.js +0 -0
  176. /package/dist/{agents → src/agents}/marketing.d.ts +0 -0
  177. /package/dist/{agents → src/agents}/marketing.js +0 -0
  178. /package/dist/{agents → src/agents}/researcher.d.ts +0 -0
  179. /package/dist/{agents → src/agents}/researcher.js +0 -0
  180. /package/dist/{agents → src/agents}/writer.d.ts +0 -0
  181. /package/dist/{agents → src/agents}/writer.js +0 -0
  182. /package/dist/{cli → src/cli}/create.d.ts +0 -0
  183. /package/dist/{cli → src/cli}/create.js +0 -0
  184. /package/dist/{cli → src/cli}/evolve.d.ts +0 -0
  185. /package/dist/{cli → src/cli}/evolve.js +0 -0
  186. /package/dist/{cli → src/cli}/index.d.ts +0 -0
  187. /package/dist/{cli → src/cli}/index.js +0 -0
  188. /package/dist/{cli → src/cli}/init.d.ts +0 -0
  189. /package/dist/{cli → src/cli}/init.js +0 -0
  190. /package/dist/{cli → src/cli}/run.d.ts +0 -0
  191. /package/dist/{cli → src/cli}/run.js +0 -0
  192. /package/dist/{cli → src/cli}/status.d.ts +0 -0
  193. /package/dist/{cli → src/cli}/status.js +0 -0
  194. /package/dist/{core → src/core}/agent.d.ts +0 -0
  195. /package/dist/{core → src/core}/agent.js +0 -0
  196. /package/dist/{core → src/core}/runner.d.ts +0 -0
  197. /package/dist/{core → src/core}/runner.js +0 -0
  198. /package/dist/{evolution → src/evolution}/loop.d.ts +0 -0
  199. /package/dist/{evolution → src/evolution}/loop.js +0 -0
  200. /package/dist/{evolution → src/evolution}/multi-critic.d.ts +0 -0
  201. /package/dist/{evolution → src/evolution}/multi-critic.js +0 -0
  202. /package/dist/{evolution → src/evolution}/notifications.d.ts +0 -0
  203. /package/dist/{evolution → src/evolution}/notifications.js +0 -0
  204. /package/dist/{evolution → src/evolution}/optimizer.d.ts +0 -0
  205. /package/dist/{evolution → src/evolution}/optimizer.js +0 -0
  206. /package/dist/{evolution → src/evolution}/patterns.d.ts +0 -0
  207. /package/dist/{evolution → src/evolution}/patterns.js +0 -0
  208. /package/dist/{evolution → src/evolution}/safety.d.ts +0 -0
  209. /package/dist/{evolution → src/evolution}/safety.js +0 -0
  210. /package/dist/{evolution → src/evolution}/tracker.d.ts +0 -0
  211. /package/dist/{evolution → src/evolution}/tracker.js +0 -0
  212. /package/dist/{index.d.ts → src/index.d.ts} +0 -0
  213. /package/dist/{index.js → src/index.js} +0 -0
  214. /package/dist/{memory → src/memory}/index.d.ts +0 -0
  215. /package/dist/{memory → src/memory}/index.js +0 -0
  216. /package/dist/{memory → src/memory}/postgres-memory.d.ts +0 -0
  217. /package/dist/{memory → src/memory}/postgres-memory.js +0 -0
  218. /package/dist/{memory → src/memory}/sqlite-memory.d.ts +0 -0
  219. /package/dist/{memory → src/memory}/sqlite-memory.js +0 -0
  220. /package/dist/{providers → src/providers}/anthropic.d.ts +0 -0
  221. /package/dist/{providers → src/providers}/anthropic.js +0 -0
  222. /package/dist/{providers → src/providers}/claude-cli.d.ts +0 -0
  223. /package/dist/{providers → src/providers}/claude-cli.js +0 -0
  224. /package/dist/{providers → src/providers}/index.d.ts +0 -0
  225. /package/dist/{providers → src/providers}/index.js +0 -0
  226. /package/dist/{providers → src/providers}/ollama.d.ts +0 -0
  227. /package/dist/{providers → src/providers}/ollama.js +0 -0
  228. /package/dist/{providers → src/providers}/openai.d.ts +0 -0
  229. /package/dist/{providers → src/providers}/openai.js +0 -0
  230. /package/dist/{providers → src/providers}/types.d.ts +0 -0
  231. /package/dist/{providers → src/providers}/types.js +0 -0
  232. /package/dist/{types.d.ts → src/types.d.ts} +0 -0
  233. /package/dist/{types.js → src/types.js} +0 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,224 @@
1
+ # Changelog
2
+
3
+ ## [0.4.7] — 2026-05-22
4
+
5
+ Generic MCP-Memory bridge — Darwin's closed loop now plugs into any
6
+ MCP-compliant memory server out of the box.
7
+
8
+ ### Added
9
+
10
+ - **`examples/mcp-memory-bridge.ts`** — pluggable JSON-RPC 2.0 client for
11
+ MCP-Memory servers. Two transports (`stdio` + `http`), default targets
12
+ `@studiomeyer/local-memory-mcp` for zero-config local memory. Override
13
+ `writeTool` / `readTool` and provide `mapWriteArgs` / `mapReadResult`
14
+ for Mem0 / Zep / Letta / Cognee / your own server. Exposed as the
15
+ `darwin-agents/memory/bridge` subpath export for clean consumer imports.
16
+ Companion entry point `darwin-agents/memory/closed-loop` maps to
17
+ `memory-darwin-integration.ts`.
18
+
19
+ Why raw JSON-RPC instead of `@modelcontextprotocol/sdk`? Darwin's
20
+ zero-hard-deps policy. The MCP wire for our case is three messages
21
+ (`initialize` + `tools/list` + `tools/call`), and we keep it that
22
+ way — no SDK dependency, no peer-dep update, fully testable.
23
+
24
+ Implements the `FeedbackStore` interface from `closed-loop-feedback.ts`
25
+ and extends it with `fetchRelevant(query, limit)` + `close()` via the
26
+ new `RetrievableFeedbackStore` interface. Backward-compatible: existing
27
+ `FeedbackStore` consumers keep working.
28
+
29
+ Hardening: per-RPC timeout (default 10s), bounded stdio respawn on
30
+ EPIPE/exit (default 1 attempt), SSE-tolerant HTTP body parser, defensive
31
+ result extraction for `content[].text` JSON envelopes and
32
+ `structuredContent` shortcuts.
33
+
34
+ Convenience factories: `localMemory(overrides)` for the default zero-
35
+ config wiring, `remoteMemory(url, overrides)` for any HTTP endpoint.
36
+
37
+ - **`examples/memory-darwin-integration.ts`** — closed-loop orchestration
38
+ in three lines: fetch lessons → render as context → run the agent →
39
+ persist critic findings. The next run sees the previous run's lessons.
40
+
41
+ Adds `runClosedLoopTurn()` (orchestration shape) and
42
+ `renderLessonContext()` (token-budgeted prompt rendering, default 1800
43
+ chars with elision fallback).
44
+
45
+ ### Hardening (Round-1 critic findings, fixed in-place before publish)
46
+
47
+ - F1 — removed inline-respawn path from `rpc()` that bypassed `ensureReady()`
48
+ and could double-spawn the stdio child.
49
+ - F2 — SSE parser now splits on event boundaries (`\n\n`) and joins multi-
50
+ line `data:` fields with `\n` per the EventSource spec §9.2.4. Returns
51
+ the most recent well-formed event so partial streams don't override the
52
+ final result.
53
+ - F3 — added `child.stdin.on('error', …)` to swallow EPIPE/ERR_STREAM_DESTROYED
54
+ emitted on the dying stdin between exit-event delivery, so the host
55
+ process doesn't crash on transient races.
56
+ - F4 — `initInFlight` is no longer auto-cleared in the catch handler.
57
+ Concurrent callers see the same failure once; the next call after the
58
+ failure starts a fresh attempt. Prevents the concurrent double-spawn
59
+ race on retry-after-init-failure.
60
+ - F5 — `close()` now nulls `initInFlight` so a caller awaiting a stale
61
+ init promise after close gets routed back through the `bridge is closed`
62
+ guard rather than racing the dead transport.
63
+ - F7 — HTTP responses without a `jsonrpc: "2.0"` envelope are logged via
64
+ the configured warn-logger and surface as `undefined` to the caller
65
+ (which then yields `[]` via the result mapper) rather than throwing
66
+ raw `SyntaxError` on malformed payloads.
67
+ - F9 — added `tsconfig.test.json` for opt-in test type-checking via
68
+ `npm run typecheck:tests`. Main build (`npm run build`) remains
69
+ src+examples only so pre-existing test-file type drift doesn't break
70
+ publish.
71
+
72
+ ### Robustness additions
73
+
74
+ - **HTTP retry policy** — `httpMaxRetries` config (default 2) with
75
+ exponential backoff for 5xx and transient network errors
76
+ (ECONNRESET/ETIMEDOUT/ENOTFOUND/EAI_AGAIN/AbortError). 4xx errors are
77
+ surfaced immediately. Matches the lesson from running an MCP server
78
+ behind Cloudflare/nginx where intermittent 502/503 are normal.
79
+ - **`fetchRelevant()` accepts an options bag** — call shape is
80
+ `bridge.fetchRelevant({ query, limit, tags })`. Legacy
81
+ `bridge.fetchRelevant('query', 5)` still works for backward-compat.
82
+ - **JSON-RPC id-mismatch** is logged but accepted (warn-not-throw) for
83
+ servers that re-key responses.
84
+
85
+ ### USP framing
86
+
87
+ - README "Memory Integration" section now spells out the differentiation
88
+ vs. Mem0/Zep/Letta/MemPalace/agentmemory/brainctl: pluggable backends
89
+ exist, closed-loop self-evolution exists, but Darwin v0.4.7 is the
90
+ first MIT-licensed, TypeScript-native, MCP-native combination. The
91
+ symmetric polarity rule (mistake/pattern, mediocre band skipped) is
92
+ the production-ready closed-loop pattern aligned with reflective
93
+ self-improvement work like GEPA (ICLR 2026 Oral).
94
+
95
+ - **+31 unit tests:**
96
+ - `tests/mcp-memory-bridge.test.ts` (24 tests) — default arg mappers,
97
+ structured-content extraction, http round-trip (initialize + tools/
98
+ call), tool-name + arg override (Mem0-style), Authorization header
99
+ propagation, JSON-RPC error surfacing, stdio round-trip against a
100
+ fake MCP child, child-crash-mid-session (F1/F3 regression), reject-
101
+ on-close-during-flight (F5 regression), 5xx retry + 4xx no-retry,
102
+ multi-event + multi-line SSE parsing (F2), non-JSON-RPC warn (F7),
103
+ single-flight initialize under concurrent calls (F4).
104
+ - `tests/memory-darwin-integration.test.ts` (7 tests) —
105
+ `renderLessonContext` boundary cases, three-turn closed-loop
106
+ behaviour (cold → warm → mediocre band), fetch-failure resilience,
107
+ custom `persistThresholds` honoured.
108
+
109
+ ### Notes
110
+
111
+ - No production code changed. Only `examples/` and `tests/` files are
112
+ added — `src/` and the existing CLI are untouched. Safe to upgrade.
113
+ - The bridge intentionally lives in `examples/` (not `src/`) so it stays
114
+ copy-paste-able and doesn't impose dependencies on the core package.
115
+
116
+ ## [0.4.6] — 2026-05-22
117
+
118
+ Three dedicated critic sets + two production patterns from real fleet usage.
119
+
120
+ ### Added
121
+
122
+ - **Three new built-in critic sets** in `src/evolution/multi-critic.ts`:
123
+ - `RESEARCH_PROMPTS` — for agents that synthesise external sources into
124
+ structured research reports. Scores source quality + multi-engine
125
+ coverage, analytical depth + synthesis, completeness + decision-value.
126
+ Use when your agent's output is a research brief, market analysis,
127
+ competitor scan, paper summary, or technology deep-dive.
128
+ - `CRITIC_AGENT_PROMPTS` — for agents whose job is critiquing other work
129
+ (devil's advocate, RFC-review, design-review). Scores fairness +
130
+ steelmanning, counter-argument depth + blind-spot detection, actionability
131
+ + clear verdict.
132
+ - `ANALYST_PROMPTS` — for agents that produce code/architecture analysis
133
+ (repository audits, refactoring proposals, tech-debt reports). Scores
134
+ technical accuracy with file:line references, pattern recognition,
135
+ recommendation quality with security + effort + risk estimates.
136
+
137
+ These three previously fell back to `INVESTIGATOR_PROMPTS` — which scored
138
+ them by the wrong criteria (e.g. code-analysis got dinged for "no URLs
139
+ cited" because it cited file paths instead). The anti-fallback regression
140
+ test in `tests/multi-critic.test.ts` locks the fix.
141
+
142
+ - **`examples/closed-loop-feedback.ts`** — backend-agnostic pattern for
143
+ piping Darwin multi-critic findings into your own memory store so the
144
+ next agent run sees them as context. Symmetric (writes both successes
145
+ and failures), matches the Hermes Agent v0.8.0 (NousResearch, MIT)
146
+ self-evolution pattern.
147
+
148
+ Decision logic (`shouldPersist`):
149
+ - `medianScore < 5` → polarity `mistake` (failure mode to watch)
150
+ - `medianScore >= 8` → polarity `pattern` (success pattern to reproduce)
151
+ - middle band → not persisted (mediocre runs are noise)
152
+
153
+ Plus guards for NaN/Infinity scores, all-critics-failed, and short
154
+ outputs (likely CLI failures). 38 unit tests in
155
+ `tests/closed-loop-feedback.test.ts`.
156
+
157
+ - **`examples/staleness-monitor.ts`** — detect agents that stopped firing
158
+ or were configured-but-never-fired. The latter is a silent failure mode
159
+ many production fleets hit: agent added to `AGENT_CRITIC_MAP`, wiring
160
+ missed on caller side, agent looks "configured" but produces zero data.
161
+
162
+ Four statuses: `active` / `stale` / `dead` / `never-tracked`. Pure
163
+ classifier + report builder + format helper, plus a `STALENESS_SQL`
164
+ constant ready for your `pg` Pool. 16 unit tests in
165
+ `tests/staleness-monitor.test.ts`.
166
+
167
+ ### Changed
168
+
169
+ - `getCriticPrompts('research' | 'researcher' | 'critic' | 'analyst')` now
170
+ returns dedicated sets instead of falling back to investigator. Adds
171
+ `researcher` as an alias of `research` for backwards compatibility.
172
+ - `AGENT_OUTPUT_LABELS` extended for the new agent types.
173
+ - README: new "Closed-Loop & Observability" section pointing to the two
174
+ example files.
175
+ - Examples README expanded with the two new pattern entries.
176
+
177
+ ### Tests
178
+
179
+ - 12 new tests in `multi-critic.test.ts` — critic-set coverage + 3
180
+ anti-fallback regression assertions (analyst, research, critic must NOT
181
+ use investigator's set).
182
+ - 38 new tests in `closed-loop-feedback.test.ts` — polarity logic, content
183
+ + tag + confidence builders, persist orchestration, store-failure
184
+ handling.
185
+ - 16 new tests in `staleness-monitor.test.ts` — classifier boundaries,
186
+ observed-vs-expected merging, format output.
187
+
188
+ Total: 66 new tests on top of the existing 140. All green, `tsc` clean.
189
+
190
+ ## [Unreleased] — Round-4 OSS-Sweep (2026-04-24)
191
+
192
+ Triple-agent review on the v0.4.5 OSS tree surfaced two defects that had
193
+ been documented-but-unshipped in earlier internal reviews.
194
+
195
+ ### Security
196
+
197
+ - **`spawn('claude')` no longer leaks user Anthropic API credentials to
198
+ the subprocess.** `ANTHROPIC_API_KEY` and `ANTHROPIC_AUTH_TOKEN` are now
199
+ stripped from the cleaned env before the Claude CLI is invoked, matching
200
+ the behaviour that `agent-fleet` shipped in Session 837. Without this
201
+ strip, any Darwin user with an API key in their shell was being billed
202
+ at full API rates for every experiment run instead of consuming their
203
+ paid Claude Pro / Max subscription. Opt back in with
204
+ `DARWIN_USE_API_KEY=1` for CI or server-side usage where a billed key is
205
+ the intended credential.
206
+
207
+ ### Added
208
+
209
+ - **Process-lifetime budget caps in `src/core/runner.ts`.** A runaway
210
+ A/B-critic-convergence loop could previously fire hundreds of paid
211
+ provider calls before anyone noticed. Two opt-out ceilings now short-
212
+ circuit the runner **before** the next LLM call:
213
+ - `DARWIN_MAX_RUNS_PER_PROCESS` (default `100`, `0` = disabled)
214
+ - `DARWIN_MAX_RUN_WALL_MS` (default `3_600_000` = 1 h, `0` = disabled)
215
+ Exceeding either throws a new `DarwinBudgetError` with the budget name.
216
+ Test helpers `setMaxRunsPerProcess` / `setMaxRunWallMs` /
217
+ `resetRunCounters` are exported from `src/core/runner` for wiring-tests.
218
+ - **3 new regression tests** (`tests/budget-caps.test.ts`): runs-cap trip,
219
+ 0 = disabled, wall-clock-cap trip. Total test count: 130 → 133 (all
220
+ green).
221
+
222
+ ## 1.0.0
223
+
224
+ Initial public release.
package/README.md CHANGED
@@ -131,9 +131,72 @@ Each agent ships with a dedicated **multi-critic set** that scores the output by
131
131
 
132
132
  Two production patterns Darwin users commonly need but had to build themselves:
133
133
 
134
- - [`examples/closed-loop-feedback.ts`](examples/closed-loop-feedback.ts) — pipe critic findings into your own memory store so the next run sees them. Symmetric (writes both successes and failures), backend-agnostic. Matches the Hermes Agent v0.8.0 self-evolution pattern.
134
+ - [`examples/closed-loop-feedback.ts`](examples/closed-loop-feedback.ts) — pipe critic findings into your own memory store so the next run sees them. Symmetric (writes both successes and failures), backend-agnostic. Aligned with reflective self-improvement patterns like [GEPA (ICLR 2026 Oral)](https://arxiv.org/abs/2507.19457) and NousResearch's `hermes-agent-self-evolution` loop.
135
135
  - [`examples/staleness-monitor.ts`](examples/staleness-monitor.ts) — detect agents that stopped firing, or were configured but never fired. Pure classifier + format helpers + ready-made SQL. Wire to your own cron + alert webhook.
136
136
 
137
+ ## Memory Integration (v0.4.7 — works with any MCP-compliant memory server)
138
+
139
+ Closes the loop in three lines. Defaults to zero-config local memory; one
140
+ config switch points at Mem0 / Zep / Letta / Cognee / a self-hosted MCP
141
+ server / your own.
142
+
143
+ ### Why this is different
144
+
145
+ Existing self-evolving agent frameworks pick one memory backend and stay
146
+ there. Existing MCP-memory servers (Mem0, Zep, Letta, MemPalace,
147
+ agentmemory, brainctl) optimize for storage, not for closed-loop critic
148
+ feedback. Darwin v0.4.7 is the first MIT-licensed, TypeScript-native,
149
+ MCP-native combination of **pluggable memory** + **symmetric self-evolution**
150
+ (score &lt; 5 → `mistake`, score ≥ 8 → `pattern`, mediocre middle band → not
151
+ persisted). No vendor lock-in, no cloud required by default, swap-able to
152
+ Mem0/Zep/Letta with two config lines.
153
+
154
+ ```typescript
155
+ import { localMemory, remoteMemory } from 'darwin-agents/memory/bridge';
156
+ import { runClosedLoopTurn } from 'darwin-agents/memory/closed-loop';
157
+
158
+ // Default: spawn @studiomeyer/local-memory-mcp via npx — zero cloud, zero keys
159
+ const memory = localMemory();
160
+
161
+ // Or any remote MCP-Memory server
162
+ // const memory = remoteMemory('https://your-mcp.example.com/mcp', { authHeader: `Bearer ${KEY}` });
163
+
164
+ // Or Mem0 with tool-name + arg aliasing
165
+ // const memory = remoteMemory('https://api.mem0.ai/mcp', {
166
+ // authHeader: `Bearer ${process.env.MEM0_KEY}`,
167
+ // writeTool: 'mem0_add',
168
+ // readTool: 'mem0_search',
169
+ // mapWriteArgs: (rec) => ({ messages: [{ role: 'user', content: rec.content }], metadata: { tags: rec.tags } }),
170
+ // });
171
+
172
+ const result = await runClosedLoopTurn(
173
+ { agentName: 'analyst', topic: 'Audit module X' },
174
+ { runner: yourAgentRunner, store: memory },
175
+ );
176
+ // Run 1 sees zero lessons. Run 2 sees Run 1's findings as context.
177
+ ```
178
+
179
+ ### Provider matrix
180
+
181
+ | Provider | `writeTool` | `readTool` | Notes |
182
+ |---|---|---|---|
183
+ | **`@studiomeyer/local-memory-mcp`** (default) | `memory_learn` | `memory_search` | zero-config, single SQLite file, no cloud |
184
+ | Any self-hosted MCP-Memory server | `memory_learn` | `memory_search` | same wire, remote endpoint |
185
+ | Mem0 MCP | `mem0_add` | `mem0_search` | needs `mapWriteArgs` for the `messages` shape |
186
+ | Zep MCP | `zep_add` | `zep_search` | optional `mapWriteArgs` for `group_id` |
187
+ | Letta MCP | `archival_insert` | `archival_search` | optional `mapReadResult` for their envelope |
188
+ | Cognee MCP | `cognee_add` | `cognee_search` | optional mappers |
189
+
190
+ Why an MCP-shaped bridge? Because the wire is the same — only tool names
191
+ and arg shapes vary. One bridge, one reconnect path, one timeout policy.
192
+ The pattern matches the [MCP Bridge proxy paper (arXiv 2504.08999)](https://arxiv.org/html/2504.08999v2)
193
+ but stays inside the Darwin process — no extra service to deploy.
194
+
195
+ See [`examples/memory-darwin-integration.ts`](examples/memory-darwin-integration.ts)
196
+ for the full closed-loop pattern: fetch relevant lessons → render them as
197
+ prompt context → run the agent → persist critic findings → next run sees
198
+ last run's lessons.
199
+
137
200
  ## How Evolution Works
138
201
 
139
202
  <!-- REAL_METRICS_START -->
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Example: Closed-Loop Feedback Persistence (Darwin → External Memory)
3
+ *
4
+ * After Darwin's multi-critic evaluates an agent run, this example shows
5
+ * how to persist critic findings as external lessons that the NEXT agent
6
+ * run can consult. We call the polarity rule "symmetric self-evolution"
7
+ * because it writes BOTH success patterns and failure modes — not only
8
+ * one side. This is structurally aligned with reflective self-improvement
9
+ * approaches like GEPA (Genetic-Pareto, ICLR 2026 Oral, arXiv 2507.19457)
10
+ * and the closed-loop pattern used by NousResearch's hermes-agent-self-
11
+ * evolution repo.
12
+ *
13
+ * Why a separate persistence layer?
14
+ * - darwin_db.darwin_experiments.feedback_report is great for analytics
15
+ * but it never reaches the agent's prompt on the next run
16
+ * - If your agents already read from a memory store (Mem0, Zep, Letta,
17
+ * Cognee, a Postgres table, or even a markdown directory), pipe the
18
+ * critic findings into THAT store so the next run sees them as context
19
+ *
20
+ * This example uses an in-memory store for demonstration. Replace with
21
+ * your real backend (database, vector store, file system, etc.).
22
+ *
23
+ * Run: npx tsx examples/closed-loop-feedback.ts
24
+ */
25
+ import type { MultiCriticResult } from '../src/evolution/multi-critic.js';
26
+ export type FeedbackPolarity = 'mistake' | 'pattern';
27
+ export interface FeedbackInput {
28
+ /** Darwin agent name (matches AGENT_CRITIC_MAP key). */
29
+ agentName: string;
30
+ /** The original task / prompt the agent ran. */
31
+ topic: string;
32
+ /** Length of the agent's output in characters. */
33
+ outputLength: number;
34
+ /** Median critic score (0-10). */
35
+ medianScore: number;
36
+ /** Combined report text from all critics. */
37
+ combinedReport: string;
38
+ /** Per-critic scores (NEGATIVE score = critic failed). */
39
+ criticScores: Array<{
40
+ critic: string;
41
+ score: number;
42
+ }>;
43
+ }
44
+ export interface FeedbackRecord {
45
+ polarity: FeedbackPolarity;
46
+ content: string;
47
+ tags: string[];
48
+ /** 0-1, higher = more confident this is a real signal. */
49
+ confidence: number;
50
+ }
51
+ /** Pluggable storage backend. Implement against your real store. */
52
+ export interface FeedbackStore {
53
+ save(record: FeedbackRecord): Promise<void>;
54
+ }
55
+ /** Below this score → persist as 'mistake'. */
56
+ export declare const DEFAULT_LOW_THRESHOLD = 5;
57
+ /** At/above this score → persist as 'pattern'. */
58
+ export declare const DEFAULT_HIGH_THRESHOLD = 8;
59
+ /** Skip persistence when output is below this length (likely CLI failure). */
60
+ export declare const DEFAULT_MIN_OUTPUT_CHARS = 200;
61
+ /**
62
+ * Decide whether to persist this run and which polarity.
63
+ * Mid-range scores (5..8) are intentionally NOT persisted — mediocre runs
64
+ * are noise. We want strong signal in both directions.
65
+ */
66
+ export declare function shouldPersist(input: FeedbackInput, options?: {
67
+ lowThreshold?: number;
68
+ highThreshold?: number;
69
+ minOutputChars?: number;
70
+ }): {
71
+ persist: boolean;
72
+ reason: string;
73
+ polarity?: FeedbackPolarity;
74
+ };
75
+ export declare function buildContent(input: FeedbackInput, polarity: FeedbackPolarity): string;
76
+ export declare function buildTags(input: FeedbackInput, polarity: FeedbackPolarity): string[];
77
+ export declare function computeConfidence(input: FeedbackInput, polarity: FeedbackPolarity): number;
78
+ /**
79
+ * Persist a Darwin critic result to your external memory store.
80
+ * Non-blocking — store errors are caught and surfaced as { persisted: false }.
81
+ */
82
+ export declare function persistFeedback(input: FeedbackInput, store: FeedbackStore, options?: {
83
+ lowThreshold?: number;
84
+ highThreshold?: number;
85
+ minOutputChars?: number;
86
+ }): Promise<{
87
+ persisted: boolean;
88
+ reason: string;
89
+ polarity?: FeedbackPolarity;
90
+ }>;
91
+ /**
92
+ * Bridge a Darwin MultiCriticResult into FeedbackInput shape.
93
+ * Pure helper — no I/O.
94
+ */
95
+ export declare function fromMultiCriticResult(result: MultiCriticResult, meta: {
96
+ agentName: string;
97
+ topic: string;
98
+ outputLength: number;
99
+ }): FeedbackInput;
100
+ //# sourceMappingURL=closed-loop-feedback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"closed-loop-feedback.d.ts","sourceRoot":"","sources":["../../examples/closed-loop-feedback.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAI1E,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,SAAS,CAAC;AAErD,MAAM,WAAW,aAAa;IAC5B,wDAAwD;IACxD,SAAS,EAAE,MAAM,CAAC;IAClB,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,kDAAkD;IAClD,YAAY,EAAE,MAAM,CAAC;IACrB,kCAAkC;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,6CAA6C;IAC7C,cAAc,EAAE,MAAM,CAAC;IACvB,0DAA0D;IAC1D,YAAY,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACxD;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,0DAA0D;IAC1D,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,oEAAoE;AACpE,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7C;AAID,+CAA+C;AAC/C,eAAO,MAAM,qBAAqB,IAAM,CAAC;AACzC,kDAAkD;AAClD,eAAO,MAAM,sBAAsB,IAAM,CAAC;AAC1C,8EAA8E;AAC9E,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAI5C;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,aAAa,EACpB,OAAO,GAAE;IACP,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;CACpB,GACL;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,gBAAgB,CAAA;CAAE,CAwBnE;AAID,wBAAgB,YAAY,CAAC,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,gBAAgB,GAAG,MAAM,CA6BrF;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,gBAAgB,GAAG,MAAM,EAAE,CAWpF;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,gBAAgB,GAAG,MAAM,CAO1F;AAID;;;GAGG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,aAAa,EACpB,KAAK,EAAE,aAAa,EACpB,OAAO,GAAE;IACP,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;CACpB,GACL,OAAO,CAAC;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,gBAAgB,CAAA;CAAE,CAAC,CAkB9E;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,iBAAiB,EACzB,IAAI,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAC/D,aAAa,CASf"}
@@ -0,0 +1,199 @@
1
+ /**
2
+ * Example: Closed-Loop Feedback Persistence (Darwin → External Memory)
3
+ *
4
+ * After Darwin's multi-critic evaluates an agent run, this example shows
5
+ * how to persist critic findings as external lessons that the NEXT agent
6
+ * run can consult. We call the polarity rule "symmetric self-evolution"
7
+ * because it writes BOTH success patterns and failure modes — not only
8
+ * one side. This is structurally aligned with reflective self-improvement
9
+ * approaches like GEPA (Genetic-Pareto, ICLR 2026 Oral, arXiv 2507.19457)
10
+ * and the closed-loop pattern used by NousResearch's hermes-agent-self-
11
+ * evolution repo.
12
+ *
13
+ * Why a separate persistence layer?
14
+ * - darwin_db.darwin_experiments.feedback_report is great for analytics
15
+ * but it never reaches the agent's prompt on the next run
16
+ * - If your agents already read from a memory store (Mem0, Zep, Letta,
17
+ * Cognee, a Postgres table, or even a markdown directory), pipe the
18
+ * critic findings into THAT store so the next run sees them as context
19
+ *
20
+ * This example uses an in-memory store for demonstration. Replace with
21
+ * your real backend (database, vector store, file system, etc.).
22
+ *
23
+ * Run: npx tsx examples/closed-loop-feedback.ts
24
+ */
25
+ // ─── Default thresholds ──────────────────────────────
26
+ /** Below this score → persist as 'mistake'. */
27
+ export const DEFAULT_LOW_THRESHOLD = 5.0;
28
+ /** At/above this score → persist as 'pattern'. */
29
+ export const DEFAULT_HIGH_THRESHOLD = 8.0;
30
+ /** Skip persistence when output is below this length (likely CLI failure). */
31
+ export const DEFAULT_MIN_OUTPUT_CHARS = 200;
32
+ // ─── Decision logic ───────────────────────────────────
33
+ /**
34
+ * Decide whether to persist this run and which polarity.
35
+ * Mid-range scores (5..8) are intentionally NOT persisted — mediocre runs
36
+ * are noise. We want strong signal in both directions.
37
+ */
38
+ export function shouldPersist(input, options = {}) {
39
+ const low = options.lowThreshold ?? DEFAULT_LOW_THRESHOLD;
40
+ const high = options.highThreshold ?? DEFAULT_HIGH_THRESHOLD;
41
+ const minOut = options.minOutputChars ?? DEFAULT_MIN_OUTPUT_CHARS;
42
+ if (!Number.isFinite(input.medianScore)) {
43
+ return { persist: false, reason: 'score-not-finite' };
44
+ }
45
+ if (input.medianScore <= 0) {
46
+ return { persist: false, reason: 'all-critics-failed' };
47
+ }
48
+ if (input.criticScores.filter((c) => c.score > 0).length === 0) {
49
+ return { persist: false, reason: 'no-valid-critic-scores' };
50
+ }
51
+ if (input.outputLength < minOut) {
52
+ return { persist: false, reason: 'output-too-short' };
53
+ }
54
+ if (input.medianScore < low) {
55
+ return { persist: true, reason: 'below-low-threshold', polarity: 'mistake' };
56
+ }
57
+ if (input.medianScore >= high) {
58
+ return { persist: true, reason: 'above-high-threshold', polarity: 'pattern' };
59
+ }
60
+ return { persist: false, reason: 'score-in-mediocre-band' };
61
+ }
62
+ // ─── Record builders ─────────────────────────────────
63
+ export function buildContent(input, polarity) {
64
+ const scores = input.criticScores
65
+ .map((c) => `${c.critic}: ${c.score > 0 ? c.score.toFixed(1) : 'FAILED'}/10`)
66
+ .join(', ');
67
+ const reportExcerpt = input.combinedReport.length > 1200
68
+ ? input.combinedReport.slice(0, 1197) + '...'
69
+ : input.combinedReport;
70
+ const topic = input.topic.length > 200
71
+ ? input.topic.slice(0, 197) + '...'
72
+ : input.topic;
73
+ const isMistake = polarity === 'mistake';
74
+ const headline = isMistake
75
+ ? `Darwin multi-critic flagged ${input.agentName} as low quality (${input.medianScore.toFixed(1)}/10) on task "${topic}".`
76
+ : `Darwin multi-critic scored ${input.agentName} as high quality (${input.medianScore.toFixed(1)}/10) on task "${topic}".`;
77
+ const tail = isMistake
78
+ ? `Recurring failure mode to watch out for in future ${input.agentName} runs.`
79
+ : `Recurring success pattern to reproduce in future ${input.agentName} runs.`;
80
+ return [
81
+ headline,
82
+ `Critic breakdown: ${scores}.`,
83
+ `Output length: ${input.outputLength} chars.`,
84
+ '',
85
+ 'Critic feedback excerpt:',
86
+ reportExcerpt,
87
+ '',
88
+ tail,
89
+ ].join('\n');
90
+ }
91
+ export function buildTags(input, polarity) {
92
+ const polarityTag = polarity === 'mistake' ? 'low-quality' : 'high-quality';
93
+ const tags = ['darwin-feedback', polarityTag, `agent:${input.agentName}`];
94
+ const valid = input.criticScores.filter((c) => c.score > 0);
95
+ if (valid.length > 0) {
96
+ const target = polarity === 'mistake'
97
+ ? valid.reduce((a, b) => (a.score <= b.score ? a : b))
98
+ : valid.reduce((a, b) => (a.score >= b.score ? a : b));
99
+ tags.push(`critic:${target.critic}`);
100
+ }
101
+ return tags;
102
+ }
103
+ export function computeConfidence(input, polarity) {
104
+ if (polarity === 'mistake') {
105
+ // Lower score → more confident this is a real issue. Clamp [0.5, 0.9].
106
+ return Math.max(0.5, Math.min(0.9, 1.0 - input.medianScore / 10));
107
+ }
108
+ // pattern: higher score → more confident this is reproducible. Clamp [0.5, 0.9].
109
+ return Math.max(0.5, Math.min(0.9, 0.5 + (input.medianScore - DEFAULT_HIGH_THRESHOLD) / 5));
110
+ }
111
+ // ─── Main entry point ─────────────────────────────────
112
+ /**
113
+ * Persist a Darwin critic result to your external memory store.
114
+ * Non-blocking — store errors are caught and surfaced as { persisted: false }.
115
+ */
116
+ export async function persistFeedback(input, store, options = {}) {
117
+ const decision = shouldPersist(input, options);
118
+ if (!decision.persist || !decision.polarity) {
119
+ return { persisted: false, reason: decision.reason };
120
+ }
121
+ try {
122
+ const record = {
123
+ polarity: decision.polarity,
124
+ content: buildContent(input, decision.polarity),
125
+ tags: buildTags(input, decision.polarity),
126
+ confidence: computeConfidence(input, decision.polarity),
127
+ };
128
+ await store.save(record);
129
+ return { persisted: true, reason: decision.reason, polarity: decision.polarity };
130
+ }
131
+ catch (err) {
132
+ console.warn(`[closed-loop] persist failed: ${err.message}`);
133
+ return { persisted: false, reason: 'store-error' };
134
+ }
135
+ }
136
+ /**
137
+ * Bridge a Darwin MultiCriticResult into FeedbackInput shape.
138
+ * Pure helper — no I/O.
139
+ */
140
+ export function fromMultiCriticResult(result, meta) {
141
+ return {
142
+ agentName: meta.agentName,
143
+ topic: meta.topic,
144
+ outputLength: meta.outputLength,
145
+ medianScore: result.medianScore,
146
+ combinedReport: result.combinedReport,
147
+ criticScores: result.critics.map((c) => ({ critic: c.critic, score: c.score })),
148
+ };
149
+ }
150
+ // ─── Demo: in-memory store ────────────────────────────
151
+ if (import.meta.url === `file://${process.argv[1]}`) {
152
+ const inMemoryStore = {
153
+ async save(record) {
154
+ console.log('[in-memory-store] saved:', {
155
+ polarity: record.polarity,
156
+ tags: record.tags,
157
+ confidence: record.confidence,
158
+ contentPreview: record.content.slice(0, 100) + '...',
159
+ });
160
+ },
161
+ };
162
+ // Demo 1: low-score → mistake
163
+ await persistFeedback({
164
+ agentName: 'analyst',
165
+ topic: 'Audit module X for tech debt',
166
+ outputLength: 5000,
167
+ medianScore: 3.5,
168
+ combinedReport: 'Analyst missed two security issues. Recommendations vague.',
169
+ criticScores: [
170
+ { critic: 'technical-accuracy', score: 3 },
171
+ { critic: 'pattern-recognition', score: 4 },
172
+ { critic: 'recommendation-quality', score: 3 },
173
+ ],
174
+ }, inMemoryStore);
175
+ // Demo 2: high-score → pattern
176
+ await persistFeedback({
177
+ agentName: 'analyst',
178
+ topic: 'Audit module Y for tech debt',
179
+ outputLength: 6500,
180
+ medianScore: 9.0,
181
+ combinedReport: 'Analyst surfaced 4 concrete issues, all with file:line refs and effort estimates.',
182
+ criticScores: [
183
+ { critic: 'technical-accuracy', score: 9 },
184
+ { critic: 'pattern-recognition', score: 9 },
185
+ { critic: 'recommendation-quality', score: 9 },
186
+ ],
187
+ }, inMemoryStore);
188
+ // Demo 3: mediocre-band → NOT persisted
189
+ const result3 = await persistFeedback({
190
+ agentName: 'analyst',
191
+ topic: 'Audit module Z',
192
+ outputLength: 5000,
193
+ medianScore: 6.5,
194
+ combinedReport: 'OK but unremarkable.',
195
+ criticScores: [{ critic: 'a', score: 6 }, { critic: 'b', score: 7 }, { critic: 'c', score: 6 }],
196
+ }, inMemoryStore);
197
+ console.log('[demo 3] skipped:', result3.reason);
198
+ }
199
+ //# sourceMappingURL=closed-loop-feedback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"closed-loop-feedback.js","sourceRoot":"","sources":["../../examples/closed-loop-feedback.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Example: Defining a Custom Darwin Agent
3
+ *
4
+ * This shows how to create a fully configured agent with evolution,
5
+ * custom metric weights, and MCP tool access.
6
+ *
7
+ * Run: npx tsx examples/custom-agent.ts
8
+ */
9
+ export {};
10
+ //# sourceMappingURL=custom-agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom-agent.d.ts","sourceRoot":"","sources":["../../examples/custom-agent.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}