wyrm-mcp 7.2.0 → 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 (156) hide show
  1. package/LICENSE +26 -667
  2. package/NOTICE +14 -33
  3. package/dist/activation.d.ts.map +1 -1
  4. package/dist/activation.js +1 -44
  5. package/dist/activation.js.map +1 -1
  6. package/dist/agent-daemon.js +4 -281
  7. package/dist/agent-loop.js +7 -332
  8. package/dist/analytics.js +13 -236
  9. package/dist/attribution.js +1 -49
  10. package/dist/audit.js +2 -457
  11. package/dist/auto-capture.js +3 -138
  12. package/dist/auto-orchestrator.js +1 -325
  13. package/dist/autoconfig.js +39 -840
  14. package/dist/buddy-runner.js +1 -109
  15. package/dist/buddy.js +14 -564
  16. package/dist/build-flags.js +1 -17
  17. package/dist/capabilities.js +3 -183
  18. package/dist/capture.js +1 -56
  19. package/dist/causality.js +6 -107
  20. package/dist/cli.js +20 -281
  21. package/dist/cloud/cli.js +5 -541
  22. package/dist/cloud/client.js +1 -221
  23. package/dist/cloud/crypto.js +1 -85
  24. package/dist/cloud/machine-id.js +2 -113
  25. package/dist/cloud/recovery.js +1 -60
  26. package/dist/cloud/sync-engine.js +7 -543
  27. package/dist/cloud-backup.js +5 -579
  28. package/dist/cloud-profile.js +1 -138
  29. package/dist/cloud-sync-entrypoint.js +1 -47
  30. package/dist/cloud-sync.js +2 -309
  31. package/dist/constellation.js +12 -168
  32. package/dist/context-build-budgeted.js +4 -144
  33. package/dist/context-ranking.js +1 -69
  34. package/dist/crypto.js +1 -179
  35. package/dist/daemon-write-endpoint.js +1 -290
  36. package/dist/daemon-writer.js +2 -406
  37. package/dist/database.js +43 -1110
  38. package/dist/deprecations.js +2 -162
  39. package/dist/design.js +13 -141
  40. package/dist/event-replication.js +1 -112
  41. package/dist/events-sse.js +7 -43
  42. package/dist/events.js +6 -238
  43. package/dist/failure-patterns.js +42 -659
  44. package/dist/federation.js +12 -236
  45. package/dist/goals.js +13 -101
  46. package/dist/golden.js +3 -355
  47. package/dist/handlers/agent.js +4 -165
  48. package/dist/handlers/alias-adapters.js +1 -129
  49. package/dist/handlers/aliases.js +1 -171
  50. package/dist/handlers/audit.js +1 -87
  51. package/dist/handlers/boundary.js +1 -221
  52. package/dist/handlers/capture.js +73 -1109
  53. package/dist/handlers/causality.js +7 -114
  54. package/dist/handlers/cloud.js +85 -382
  55. package/dist/handlers/companion.js +28 -459
  56. package/dist/handlers/datalake.js +7 -187
  57. package/dist/handlers/dispatch-context.js +0 -22
  58. package/dist/handlers/entity.js +25 -256
  59. package/dist/handlers/events.js +16 -335
  60. package/dist/handlers/failure.js +13 -340
  61. package/dist/handlers/goals.js +4 -296
  62. package/dist/handlers/intelligence.js +126 -674
  63. package/dist/handlers/invoicing.js +1 -70
  64. package/dist/handlers/mcpclient.js +6 -137
  65. package/dist/handlers/orchestration.js +40 -125
  66. package/dist/handlers/output-schemas.js +1 -24
  67. package/dist/handlers/presence.js +3 -99
  68. package/dist/handlers/project.js +28 -182
  69. package/dist/handlers/prompts.js +6 -157
  70. package/dist/handlers/quest.js +4 -224
  71. package/dist/handlers/recall.js +11 -218
  72. package/dist/handlers/registry.js +1 -167
  73. package/dist/handlers/resources.js +1 -288
  74. package/dist/handlers/review.js +11 -74
  75. package/dist/handlers/run.js +17 -487
  76. package/dist/handlers/search.js +15 -326
  77. package/dist/handlers/session.js +28 -615
  78. package/dist/handlers/share.js +8 -184
  79. package/dist/handlers/shims.js +1 -464
  80. package/dist/handlers/skill.js +67 -449
  81. package/dist/handlers/survivors.js +1 -120
  82. package/dist/handlers/symbols.js +8 -109
  83. package/dist/handlers/syncops.js +4 -302
  84. package/dist/handlers/types.js +1 -27
  85. package/dist/harvest.js +5 -191
  86. package/dist/hours.js +7 -156
  87. package/dist/http-auth.js +3 -321
  88. package/dist/http-fast.js +21 -1137
  89. package/dist/icons.js +1 -47
  90. package/dist/index.js +2 -924
  91. package/dist/indexer.js +4 -145
  92. package/dist/intelligence.js +31 -261
  93. package/dist/internal-dispatch.js +3 -212
  94. package/dist/keyset.js +1 -110
  95. package/dist/knowledge-graph.js +12 -176
  96. package/dist/license.d.ts +11 -0
  97. package/dist/license.d.ts.map +1 -1
  98. package/dist/license.js +2 -414
  99. package/dist/license.js.map +1 -1
  100. package/dist/logger.js +2 -199
  101. package/dist/maintenance.js +2 -148
  102. package/dist/mcp-client.js +6 -262
  103. package/dist/memory-artifacts.js +30 -449
  104. package/dist/migrate-prompt.js +2 -124
  105. package/dist/migrations.js +40 -655
  106. package/dist/performance.js +1 -228
  107. package/dist/presence.js +11 -140
  108. package/dist/priority-embed.js +5 -164
  109. package/dist/providers/embedding-provider.js +1 -196
  110. package/dist/readonly-gate.js +1 -29
  111. package/dist/rehydration.js +9 -157
  112. package/dist/reindex.js +1 -88
  113. package/dist/render-target.js +21 -514
  114. package/dist/render.js +4 -280
  115. package/dist/repl-guard.js +1 -173
  116. package/dist/replication-daemon-entrypoint.js +1 -31
  117. package/dist/replication-daemon.js +2 -262
  118. package/dist/resilience.js +1 -591
  119. package/dist/reverse-bridge.js +5 -360
  120. package/dist/security.js +1 -244
  121. package/dist/session-seen.js +3 -51
  122. package/dist/setup.js +1 -260
  123. package/dist/skill-author.js +5 -168
  124. package/dist/spec-kit.js +1 -191
  125. package/dist/sqlite-busy.js +1 -154
  126. package/dist/statusline.js +11 -315
  127. package/dist/sub-agent.js +13 -262
  128. package/dist/summarizer.js +13 -139
  129. package/dist/symbols.js +7 -283
  130. package/dist/sync.js +5 -359
  131. package/dist/tasks-dispatch.js +1 -84
  132. package/dist/tasks.js +1 -282
  133. package/dist/token-budget.js +1 -143
  134. package/dist/tool-analytics.js +7 -129
  135. package/dist/tool-annotations.js +1 -365
  136. package/dist/tool-manifest-v2.json +1 -1
  137. package/dist/tool-manifest.json +1 -1
  138. package/dist/tool-profiles.js +1 -75
  139. package/dist/trace-harvest.js +6 -244
  140. package/dist/types.js +1 -30
  141. package/dist/ui-dashboard.js +41 -50
  142. package/dist/ulid.js +1 -81
  143. package/dist/validate.js +1 -129
  144. package/dist/vault.js +1 -534
  145. package/dist/vectors.js +3 -184
  146. package/dist/version-check.js +4 -136
  147. package/dist/visibility.js +19 -155
  148. package/dist/wyrm-cli.js +98 -2451
  149. package/dist/wyrm-cli.js.map +1 -1
  150. package/dist/wyrm-guard.js +14 -424
  151. package/dist/wyrm-loop.js +3 -150
  152. package/dist/wyrm-manifest.json +1 -1
  153. package/dist/wyrm-statusline-daemon.js +1 -11
  154. package/dist/wyrm-statusline.js +4 -56
  155. package/dist/wyrm-ui.js +9 -77
  156. package/package.json +4 -2
@@ -1,290 +1 @@
1
- /**
2
- * Daemon-as-writer endpoint logic (v7 F2, T012) — the `POST /write` op surface.
3
- *
4
- * When a client process runs with WYRM_DAEMON_WRITES=1 (src/daemon-writer.ts),
5
- * its CANONICAL WRITES are routed over loopback HTTP to the running daemon
6
- * (http-fast), which executes them here against ITS database connection —
7
- * funneling a fleet's writes through one process instead of N contending ones.
8
- * Reads always stay local to the client.
9
- *
10
- * Extracted from http-fast.ts in the readonly-gate.ts style: DB-parameterized
11
- * and side-effect-free at module load, so the op surface is unit-testable
12
- * without booting the HTTP server.
13
- *
14
- * Article VII — minimal request surface, validated at the boundary:
15
- * - ONE endpoint, a CLOSED op allowlist (DAEMON_WRITE_OPS). Unknown ops are
16
- * rejected; there is deliberately no generic "run this SQL/method" escape.
17
- * - Each op calls the SAME domain method the client's direct path would call
18
- * (db.insertData / failures.record / truths.set / artifacts.add /
19
- * db.addQuest), so row shapes are identical in both modes.
20
- * - `project_id` is a plain integer id: client and daemon share the same
21
- * database file, so ids are stable across the loopback hop. Project-path
22
- * resolution (a read) happens client-side.
23
- * - Enum-ish fields (scope/severity/kind/...) are NOT re-validated here beyond
24
- * type checks: the domain methods + the schema CHECK constraints are the
25
- * single source of truth for value validation in BOTH modes — re-implementing
26
- * the lists here would let the two paths drift. A CHECK/FK violation comes
27
- * back to the client as the rejected `{e}` shape (see handleDaemonWrite's
28
- * error mapping), never a generic 500 the client would have to treat as
29
- * commit-state-unknown.
30
- *
31
- * Attribution (v7 F2 review fix): the caller's FULL envelope rides in the
32
- * request body as `actor: {agent_id, run_id}` — the `Wyrm-Actor` header
33
- * grammar (`agent_id[;run_id]`) cannot express a run-only envelope, so a
34
- * header-only hop silently dropped run attribution and let the DAEMON's own
35
- * env (http-fast's env-level resolution) stamp the caller's row — flipping
36
- * the T014 quarantine tier (a run-quarantined failure could land
37
- * project-wide, or an unattributed write could be quarantined to an
38
- * unrelated run). When the body carries `actor`, it is AUTHORITATIVE: the
39
- * write runs inside that exact envelope ('param' level), and both-null is an
40
- * EXPLICIT legacy envelope (columns stay NULL) — the daemon's env can never
41
- * bleed in. Bodies without `actor` (pre-fix clients) keep the ambient
42
- * header/env semantics.
43
- *
44
- * Idempotency (v7 F2 review fix): the client mints a ULID `write_id` per
45
- * logical write. Committed write_ids are remembered in an in-memory ledger
46
- * with TIME-BASED retention (DEDUP_TTL_MS — sized to the realistic caller
47
- * retry horizon: the instructed retry round-trips through an LLM agent whose
48
- * next turn is seconds to minutes away, NOT a protocol-bounded window); a
49
- * duplicate write_id inside the horizon REPLAYS the committed result instead
50
- * of re-executing — so the client's timeout re-send / instructed retry cannot
51
- * land a second row (the at-least-once duplicate the adversarial review
52
- * confirmed). The count cap (DEDUP_CAP) is a memory backstop only — under a
53
- * sustained fleet burst it, not time, may evict first. Documented residual
54
- * at-least-once windows: a daemon RESTART loses the ledger, and a retry
55
- * arriving past the retention horizon (TTL or backstop eviction) re-executes
56
- * — a VISIBLE fresh execution, never a silent stale replay.
57
- *
58
- * Privacy: ops write through the normal domain methods, so the Live Memory
59
- * surface is unchanged — failure events stay reference-only (is_shared=0).
60
- *
61
- * @copyright 2026 Ghost Protocol (Pvt) Ltd.
62
- * @license AGPL-3.0-or-later — dual-licensed; commercial terms: ghosts.lk@proton.me. See LICENSE.
63
- */
64
- import { isSqliteConstraintError } from './sqlite-busy.js';
65
- import { LEGACY_ENVELOPE, runWithActor, sanitizeActorId, } from './handlers/boundary.js';
66
- /**
67
- * The closed op allowlist — the four canonical write paths of spec FR-1
68
- * (data-lake insert, failure_record, truth_set, capture), where `capture`
69
- * decomposes into the three writes wyrm_capture can perform (quest_add /
70
- * truth_set / artifact_add). Anything else stays on the client's direct path.
71
- */
72
- export const DAEMON_WRITE_OPS = [
73
- 'data_insert',
74
- 'failure_record',
75
- 'truth_set',
76
- 'artifact_add',
77
- 'quest_add',
78
- ];
79
- export function isDaemonWriteOp(value) {
80
- return typeof value === 'string' && DAEMON_WRITE_OPS.includes(value);
81
- }
82
- /** Boundary check: a finite positive integer id (project ids are rowids). */
83
- function asProjectId(value) {
84
- return typeof value === 'number' && Number.isInteger(value) && value > 0 ? value : null;
85
- }
86
- function asString(value) {
87
- return typeof value === 'string' && value.length > 0 ? value : null;
88
- }
89
- // ── idempotency ledger (v7 F2 review fix) ───────────────────────────────────
90
- // write_id → the committed result, replayed on duplicate delivery. Retention
91
- // is TIME-based: the caller-level instructed retry round-trips through an LLM
92
- // agent (seconds to minutes — retry_after_ms is advice, not a bound), so a
93
- // count-FIFO sized to "seconds-scale" gets evicted from under a live retry by
94
- // any >cap fleet burst in that gap — re-executing a committed write_id, a
95
- // duplicate with no daemon crash. Entries live DEDUP_TTL_MS; expired entries
96
- // are swept on insert (insertion order is commit order, so they cluster at
97
- // the front). DEDUP_CAP remains only as a memory backstop ({ulid, small row}
98
- // entries are tiny). Only SUCCESSFUL (committed) results are remembered — a
99
- // rejected/thrown write left nothing behind, so re-executing it is correct.
100
- export const DEDUP_TTL_MS = 10 * 60_000;
101
- const DEDUP_CAP = 4096;
102
- const committedWrites = new Map();
103
- /** Test hook: clear the idempotency ledger between cases. */
104
- export function _resetDaemonWriteDedupForTests() {
105
- committedWrites.clear();
106
- }
107
- /** Test hook: age every ledger entry by `ms` (drives TTL eviction without a clock). */
108
- export function _ageDaemonWriteDedupForTests(ms) {
109
- for (const entry of committedWrites.values())
110
- entry.committedAt -= ms;
111
- }
112
- function rememberCommitted(writeId, result) {
113
- const now = Date.now();
114
- // Age sweep first: retention is the TTL; the count cap below is only the
115
- // memory backstop. committedAt is non-decreasing in insertion order, so the
116
- // sweep stops at the first fresh entry.
117
- for (const [id, entry] of committedWrites) {
118
- if (now - entry.committedAt < DEDUP_TTL_MS)
119
- break;
120
- committedWrites.delete(id);
121
- }
122
- if (!committedWrites.has(writeId) && committedWrites.size >= DEDUP_CAP) {
123
- const oldest = committedWrites.keys().next().value;
124
- if (oldest !== undefined)
125
- committedWrites.delete(oldest);
126
- }
127
- committedWrites.set(writeId, { result, committedAt: now });
128
- }
129
- /** Boundary check for the client-minted idempotency key (a 26-char ULID; the
130
- * bound mirrors sanitizeActorId's 64-char ceiling). Absent/invalid → no dedup
131
- * (the pre-fix client shape). */
132
- function asWriteId(value) {
133
- return typeof value === 'string' && value.length > 0 && value.length <= 64 ? value : null;
134
- }
135
- /**
136
- * Execute one allowlisted write op. Returns the written row on success or a
137
- * compact `{ e }` error (the house wire format for http-fast routes).
138
- *
139
- * Error mapping by what the throw PROVES about the commit:
140
- * - SQLITE_CONSTRAINT family (CHECK/FK/UNIQUE/NOT NULL) → the rejected `{e}`
141
- * shape carrying the real constraint message. Every op is a single
142
- * statement or one IMMEDIATE transaction, so a constraint throw proves the
143
- * rollback — the client safely fails direct and the local path surfaces
144
- * the same deterministic error to the caller. Without this, a generic 500
145
- * reads as commit-state-unknown and the same inputs re-violate forever.
146
- * - Everything else (SQLITE_BUSY → http-fast's structured 503; SQLITE_FULL,
147
- * a post-commit throw, ...) propagates — the dispatcher catch owns
148
- * transport mapping, and a non-constraint throw does NOT prove no commit,
149
- * so it must never claim the rejected shape.
150
- */
151
- export function handleDaemonWrite(deps, args) {
152
- const op = args.op;
153
- if (!isDaemonWriteOp(op))
154
- return { e: 'unknown op' };
155
- const input = (args.input ?? {});
156
- const projectId = asProjectId(args.project_id);
157
- // Idempotent replay: this write_id already committed — the response was
158
- // lost in flight. Hand back the SAME row; never execute twice. No age check
159
- // on read: an old committed result is still the truth (the TTL governs
160
- // memory retention, not correctness).
161
- const writeId = asWriteId(args.write_id);
162
- if (writeId !== null) {
163
- const replay = committedWrites.get(writeId);
164
- if (replay !== undefined)
165
- return replay.result;
166
- }
167
- // Body-supplied attribution is authoritative for the forwarded write (see
168
- // the module header): sanitize at the boundary, run the op inside that
169
- // exact envelope. Both-null → the EXPLICIT legacy envelope (NULL columns) —
170
- // never the daemon's own env. No `actor` field at all → pre-fix client:
171
- // keep the ambient (header/env) semantics unchanged.
172
- let result;
173
- try {
174
- const actorRaw = args.actor;
175
- if (actorRaw !== undefined && actorRaw !== null && typeof actorRaw === 'object') {
176
- const a = actorRaw;
177
- const agent = sanitizeActorId(a.agent_id);
178
- const run = sanitizeActorId(a.run_id);
179
- const envelope = agent === null && run === null
180
- ? LEGACY_ENVELOPE
181
- : { agent_id: agent, run_id: run, source: 'param' };
182
- result = runWithActor(envelope, () => executeDaemonOp(deps, op, projectId, args.project_id, input));
183
- }
184
- else {
185
- result = executeDaemonOp(deps, op, projectId, args.project_id, input);
186
- }
187
- }
188
- catch (err) {
189
- // Deterministic domain rejection — provably rolled back (see the function
190
- // doc). Carry the real message so the caller's direct-path retry of the
191
- // same inputs reproduces a NAMED error, not a mystery 500.
192
- if (isSqliteConstraintError(err)) {
193
- return { e: err instanceof Error ? err.message : String(err) };
194
- }
195
- // BUSY (the structured 503 contract) and anything that might have
196
- // committed stay on the throw path — never claim "no commit" for them.
197
- throw err;
198
- }
199
- // Remember only COMMITTED outcomes (post-commit by construction: the domain
200
- // method returned synchronously above).
201
- if (writeId !== null && 'ok' in result && result.ok === true) {
202
- rememberCommitted(writeId, result);
203
- }
204
- return result;
205
- }
206
- function executeDaemonOp(deps, op, projectId, rawProjectId, input) {
207
- switch (op) {
208
- case 'data_insert': {
209
- if (projectId === null)
210
- return { e: 'project_id required' };
211
- const category = asString(input.category);
212
- const key = asString(input.key);
213
- const value = asString(input.value);
214
- if (!category || !key || !value)
215
- return { e: 'category, key, value required' };
216
- // value arrives client-prepared (sanitized + maybeEncrypt'ed): the
217
- // encryption key stays in the CLIENT process (Article VII — the daemon
218
- // never needs WYRM_ENCRYPTION_KEY to serve writes).
219
- const row = deps.db.insertData(projectId, category, key, value, input.metadata);
220
- return { ok: true, op, row };
221
- }
222
- case 'failure_record': {
223
- // project_id may be null here: global (cross-project) failures are legal.
224
- if (rawProjectId != null && projectId === null)
225
- return { e: 'project_id must be an integer' };
226
- const target = asString(input.target);
227
- const description = asString(input.description);
228
- const scope = asString(input.scope);
229
- if (!scope || !target || !description)
230
- return { e: 'scope, target, description required' };
231
- const row = deps.failures.record({
232
- project_id: projectId,
233
- scope: scope,
234
- target,
235
- description,
236
- why_failed: typeof input.why_failed === 'string' ? input.why_failed : undefined,
237
- severity: typeof input.severity === 'string' ? input.severity : undefined,
238
- });
239
- return { ok: true, op, row };
240
- }
241
- case 'truth_set': {
242
- if (projectId === null)
243
- return { e: 'project_id required' };
244
- const category = asString(input.category);
245
- const key = asString(input.key);
246
- const value = asString(input.value);
247
- if (!category || !key || !value)
248
- return { e: 'category, key, value required' };
249
- const row = deps.truths.set(projectId, {
250
- category, key, value,
251
- rationale: typeof input.rationale === 'string' ? input.rationale : undefined,
252
- source: typeof input.source === 'string' ? input.source : undefined,
253
- confidence: typeof input.confidence === 'number' ? input.confidence : undefined,
254
- ttl_days: typeof input.ttl_days === 'number' ? input.ttl_days : undefined,
255
- });
256
- return { ok: true, op, row };
257
- }
258
- case 'artifact_add': {
259
- if (projectId === null)
260
- return { e: 'project_id required' };
261
- const kind = asString(input.kind);
262
- const problem = asString(input.problem);
263
- if (!kind || !problem)
264
- return { e: 'kind, problem required' };
265
- const row = deps.artifacts.add(projectId, {
266
- kind, problem,
267
- constraints: typeof input.constraints === 'string' ? input.constraints : undefined,
268
- validatedFix: typeof input.validatedFix === 'string' ? input.validatedFix : undefined,
269
- whyItWorked: typeof input.whyItWorked === 'string' ? input.whyItWorked : undefined,
270
- outcome: typeof input.outcome === 'string' ? input.outcome : undefined,
271
- sourceSessionId: typeof input.sourceSessionId === 'number' ? input.sourceSessionId : undefined,
272
- tags: Array.isArray(input.tags) ? input.tags.filter((t) => typeof t === 'string') : undefined,
273
- confidence: typeof input.confidence === 'number' ? input.confidence : undefined,
274
- createdBy: typeof input.createdBy === 'string' ? input.createdBy : undefined,
275
- needsReview: typeof input.needsReview === 'number' ? input.needsReview : undefined,
276
- });
277
- return { ok: true, op, row };
278
- }
279
- case 'quest_add': {
280
- if (projectId === null)
281
- return { e: 'project_id required' };
282
- const title = asString(input.title);
283
- if (!title)
284
- return { e: 'title required' };
285
- const row = deps.db.addQuest(projectId, title, typeof input.description === 'string' ? input.description : undefined, (typeof input.priority === 'string' ? input.priority : 'medium'), typeof input.tags === 'string' ? input.tags : undefined);
286
- return { ok: true, op, row };
287
- }
288
- }
289
- }
290
- //# sourceMappingURL=daemon-write-endpoint.js.map
1
+ import{isSqliteConstraintError as _}from"./sqlite-busy.js";import{LEGACY_ENVELOPE as g,runWithActor as k,sanitizeActorId as y}from"./handlers/boundary.js";const w=["data_insert","failure_record","truth_set","artifact_add","quest_add"];function h(t){return typeof t=="string"&&w.includes(t)}function b(t){return typeof t=="number"&&Number.isInteger(t)&&t>0?t:null}function d(t){return typeof t=="string"&&t.length>0?t:null}const D=10*6e4,q=4096,f=new Map;function S(){f.clear()}function P(t){for(const i of f.values())i.committedAt-=t}function x(t,i){const s=Date.now();for(const[a,e]of f){if(s-e.committedAt<D)break;f.delete(a)}if(!f.has(t)&&f.size>=q){const a=f.keys().next().value;a!==void 0&&f.delete(a)}f.set(t,{result:i,committedAt:s})}function W(t){return typeof t=="string"&&t.length>0&&t.length<=64?t:null}function F(t,i){const s=i.op;if(!h(s))return{e:"unknown op"};const a=i.input??{},e=b(i.project_id),o=W(i.write_id);if(o!==null){const r=f.get(o);if(r!==void 0)return r.result}let n;try{const r=i.actor;if(r!=null&&typeof r=="object"){const c=r,u=y(c.agent_id),l=y(c.run_id);n=k(u===null&&l===null?g:{agent_id:u,run_id:l,source:"param"},()=>m(t,s,e,i.project_id,a))}else n=m(t,s,e,i.project_id,a)}catch(r){if(_(r))return{e:r instanceof Error?r.message:String(r)};throw r}return o!==null&&"ok"in n&&n.ok===!0&&x(o,n),n}function m(t,i,s,a,e){switch(i){case"data_insert":{if(s===null)return{e:"project_id required"};const o=d(e.category),n=d(e.key),r=d(e.value);if(!o||!n||!r)return{e:"category, key, value required"};const c=t.db.insertData(s,o,n,r,e.metadata);return{ok:!0,op:i,row:c}}case"failure_record":{if(a!=null&&s===null)return{e:"project_id must be an integer"};const o=d(e.target),n=d(e.description),r=d(e.scope);if(!r||!o||!n)return{e:"scope, target, description required"};const c=t.failures.record({project_id:s,scope:r,target:o,description:n,why_failed:typeof e.why_failed=="string"?e.why_failed:void 0,severity:typeof e.severity=="string"?e.severity:void 0});return{ok:!0,op:i,row:c}}case"truth_set":{if(s===null)return{e:"project_id required"};const o=d(e.category),n=d(e.key),r=d(e.value);if(!o||!n||!r)return{e:"category, key, value required"};const c=t.truths.set(s,{category:o,key:n,value:r,rationale:typeof e.rationale=="string"?e.rationale:void 0,source:typeof e.source=="string"?e.source:void 0,confidence:typeof e.confidence=="number"?e.confidence:void 0,ttl_days:typeof e.ttl_days=="number"?e.ttl_days:void 0});return{ok:!0,op:i,row:c}}case"artifact_add":{if(s===null)return{e:"project_id required"};const o=d(e.kind),n=d(e.problem);if(!o||!n)return{e:"kind, problem required"};const r=t.artifacts.add(s,{kind:o,problem:n,constraints:typeof e.constraints=="string"?e.constraints:void 0,validatedFix:typeof e.validatedFix=="string"?e.validatedFix:void 0,whyItWorked:typeof e.whyItWorked=="string"?e.whyItWorked:void 0,outcome:typeof e.outcome=="string"?e.outcome:void 0,sourceSessionId:typeof e.sourceSessionId=="number"?e.sourceSessionId:void 0,tags:Array.isArray(e.tags)?e.tags.filter(c=>typeof c=="string"):void 0,confidence:typeof e.confidence=="number"?e.confidence:void 0,createdBy:typeof e.createdBy=="string"?e.createdBy:void 0,needsReview:typeof e.needsReview=="number"?e.needsReview:void 0});return{ok:!0,op:i,row:r}}case"quest_add":{if(s===null)return{e:"project_id required"};const o=d(e.title);if(!o)return{e:"title required"};const n=t.db.addQuest(s,o,typeof e.description=="string"?e.description:void 0,typeof e.priority=="string"?e.priority:"medium",typeof e.tags=="string"?e.tags:void 0);return{ok:!0,op:i,row:n}}}}export{w as DAEMON_WRITE_OPS,D as DEDUP_TTL_MS,P as _ageDaemonWriteDedupForTests,S as _resetDaemonWriteDedupForTests,F as handleDaemonWrite,h as isDaemonWriteOp};