hippo-memory 1.14.0 → 1.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/README.md +862 -861
  2. package/dist/audit.d.ts +1 -1
  3. package/dist/audit.d.ts.map +1 -1
  4. package/dist/audit.js.map +1 -1
  5. package/dist/cli.d.ts.map +1 -1
  6. package/dist/cli.js +1594 -229
  7. package/dist/cli.js.map +1 -1
  8. package/dist/customer-notes.d.ts +95 -0
  9. package/dist/customer-notes.d.ts.map +1 -0
  10. package/dist/customer-notes.js +296 -0
  11. package/dist/customer-notes.js.map +1 -0
  12. package/dist/db.d.ts.map +1 -1
  13. package/dist/db.js +1286 -472
  14. package/dist/db.js.map +1 -1
  15. package/dist/decisions.d.ts +91 -0
  16. package/dist/decisions.d.ts.map +1 -0
  17. package/dist/decisions.js +278 -0
  18. package/dist/decisions.js.map +1 -0
  19. package/dist/graph-extract.d.ts +39 -0
  20. package/dist/graph-extract.d.ts.map +1 -0
  21. package/dist/graph-extract.js +141 -0
  22. package/dist/graph-extract.js.map +1 -0
  23. package/dist/graph-recall.d.ts +41 -0
  24. package/dist/graph-recall.d.ts.map +1 -0
  25. package/dist/graph-recall.js +246 -0
  26. package/dist/graph-recall.js.map +1 -0
  27. package/dist/graph.d.ts +137 -0
  28. package/dist/graph.d.ts.map +1 -0
  29. package/dist/graph.js +433 -0
  30. package/dist/graph.js.map +1 -0
  31. package/dist/incidents.d.ts +100 -0
  32. package/dist/incidents.d.ts.map +1 -0
  33. package/dist/incidents.js +322 -0
  34. package/dist/incidents.js.map +1 -0
  35. package/dist/index.d.ts +1 -0
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +1 -0
  38. package/dist/index.js.map +1 -1
  39. package/dist/memory.d.ts +6 -0
  40. package/dist/memory.d.ts.map +1 -1
  41. package/dist/memory.js +6 -0
  42. package/dist/memory.js.map +1 -1
  43. package/dist/policies.d.ts +149 -0
  44. package/dist/policies.d.ts.map +1 -0
  45. package/dist/policies.js +380 -0
  46. package/dist/policies.js.map +1 -0
  47. package/dist/processes.d.ts +104 -0
  48. package/dist/processes.d.ts.map +1 -0
  49. package/dist/processes.js +330 -0
  50. package/dist/processes.js.map +1 -0
  51. package/dist/project-briefs.d.ts +126 -0
  52. package/dist/project-briefs.d.ts.map +1 -0
  53. package/dist/project-briefs.js +453 -0
  54. package/dist/project-briefs.js.map +1 -0
  55. package/dist/search.d.ts +7 -0
  56. package/dist/search.d.ts.map +1 -1
  57. package/dist/search.js.map +1 -1
  58. package/dist/server.d.ts.map +1 -1
  59. package/dist/server.js +1181 -8
  60. package/dist/server.js.map +1 -1
  61. package/dist/skills.d.ts +98 -0
  62. package/dist/skills.d.ts.map +1 -0
  63. package/dist/skills.js +339 -0
  64. package/dist/skills.js.map +1 -0
  65. package/dist/src/audit.js.map +1 -1
  66. package/dist/src/cli.js +1594 -229
  67. package/dist/src/cli.js.map +1 -1
  68. package/dist/src/customer-notes.js +296 -0
  69. package/dist/src/customer-notes.js.map +1 -0
  70. package/dist/src/db.js +1286 -472
  71. package/dist/src/db.js.map +1 -1
  72. package/dist/src/decisions.js +278 -0
  73. package/dist/src/decisions.js.map +1 -0
  74. package/dist/src/graph-extract.js +141 -0
  75. package/dist/src/graph-extract.js.map +1 -0
  76. package/dist/src/graph-recall.js +246 -0
  77. package/dist/src/graph-recall.js.map +1 -0
  78. package/dist/src/graph.js +433 -0
  79. package/dist/src/graph.js.map +1 -0
  80. package/dist/src/incidents.js +322 -0
  81. package/dist/src/incidents.js.map +1 -0
  82. package/dist/src/index.js +1 -0
  83. package/dist/src/index.js.map +1 -1
  84. package/dist/src/memory.js +6 -0
  85. package/dist/src/memory.js.map +1 -1
  86. package/dist/src/policies.js +380 -0
  87. package/dist/src/policies.js.map +1 -0
  88. package/dist/src/processes.js +330 -0
  89. package/dist/src/processes.js.map +1 -0
  90. package/dist/src/project-briefs.js +453 -0
  91. package/dist/src/project-briefs.js.map +1 -0
  92. package/dist/src/search.js.map +1 -1
  93. package/dist/src/server.js +1181 -8
  94. package/dist/src/server.js.map +1 -1
  95. package/dist/src/skills.js +339 -0
  96. package/dist/src/skills.js.map +1 -0
  97. package/dist/src/version.js +1 -1
  98. package/dist/src/version.js.map +1 -1
  99. package/dist/version.d.ts +1 -1
  100. package/dist/version.d.ts.map +1 -1
  101. package/dist/version.js +1 -1
  102. package/dist/version.js.map +1 -1
  103. package/extensions/openclaw-plugin/openclaw.plugin.json +46 -46
  104. package/extensions/openclaw-plugin/package.json +14 -14
  105. package/openclaw.plugin.json +45 -45
  106. package/package.json +75 -75
@@ -0,0 +1,380 @@
1
+ /**
2
+ * E2 policy first-class object (docs/plans/2026-05-30-e2-policy-object.md).
3
+ *
4
+ * The "bi-temporal-first" object type: a named rule/statement that is in force
5
+ * over an EFFECTIVE-TIME range and evolves via supersession. Two time axes:
6
+ *
7
+ * - Valid time (effective time): when the policy is in force in the real world,
8
+ * as first-class columns `valid_from` (required; defaults to creation time)
9
+ * and `valid_to` (nullable = open-ended). This is the queryable axis: see
10
+ * `loadPoliciesAsOf` (the active policies in force at a given valid-time).
11
+ * - Transaction time (system time): when the row was recorded / retired, via
12
+ * `created_at` + the supersede chain's `superseded_at`. Present, but
13
+ * time-travel ("what did we BELIEVE was in force at past system time T") is
14
+ * deferred to a future version.
15
+ *
16
+ * The delta lifecycle reuses the process/decision supersede machinery verbatim
17
+ * (superseded_by self-FK + CAS + INSERT-preflight + server-derived version +
18
+ * change_summary + supersede tenant-match trigger). It DROPS process's `steps`
19
+ * (a policy has `policy_text`) and ADDS `valid_from`/`valid_to`.
20
+ *
21
+ * The `policies` table is the source of truth (survives memory decay); the
22
+ * memory mirror is for recall only. memory_id is NULLABLE with ON DELETE SET
23
+ * NULL so forget/consolidate/archive gracefully orphans the policy row.
24
+ *
25
+ * Lifecycle: active -> superseded (a newer version replaces it) or active ->
26
+ * closed (retired with no successor). Superseding leaves the predecessor's
27
+ * valid-time range intact (it WAS effective then); only the status flips.
28
+ *
29
+ * Date handling: every date input (savePolicy's valid_from/valid_to,
30
+ * loadPoliciesAsOf's asOfDate) is normalized to canonical ISO-8601 datetime
31
+ * (`toISOString`) at the store boundary BEFORE any persist or compare, so the
32
+ * fixed-width values sort lexically and the half-open [valid_from, valid_to)
33
+ * comparison is correct (plan-eng-critic round-1 CRIT fix: a date-only asOf vs a
34
+ * datetime valid_from otherwise made a same-day policy invisible).
35
+ *
36
+ * Dual-write atomicity: `savePolicy` writes the memory + policies row (and, on
37
+ * supersede, the predecessor's UPDATE) inside writeEntry's SAVEPOINT.
38
+ */
39
+ import { openHippoDb, closeHippoDb } from './db.js';
40
+ import { writeEntry, assertTenantId } from './store.js';
41
+ import { createMemory, Layer, POLICY_HALF_LIFE_DAYS } from './memory.js';
42
+ import { appendAuditEvent } from './audit.js';
43
+ export const VALID_POLICY_STATES = new Set([
44
+ 'active',
45
+ 'superseded',
46
+ 'closed',
47
+ ]);
48
+ // ---------------------------------------------------------------------------
49
+ // Date normalization + validation (the bi-temporal correctness core)
50
+ // ---------------------------------------------------------------------------
51
+ /**
52
+ * Parse + canonicalize a date input to ISO-8601 datetime (`toISOString`). Throws
53
+ * on an unparseable value. Whatever `new Date()` accepts is re-emitted in the
54
+ * single fixed-width canonical form, so date-only and datetime inputs collapse to
55
+ * comparable values and lexical ordering is sound. (Overflow inputs like
56
+ * '2026-02-30' roll forward per JS Date semantics rather than throwing; the
57
+ * stored value is still canonical.)
58
+ */
59
+ export function normalizePolicyDate(input, label = 'date') {
60
+ const d = new Date(input);
61
+ if (Number.isNaN(d.getTime())) {
62
+ throw new Error(`policy: invalid ${label} "${input}" (expected an ISO-8601 date or datetime)`);
63
+ }
64
+ return d.toISOString();
65
+ }
66
+ /**
67
+ * Normalize valid_from (defaulting to `nowIso` when undefined) + valid_to (null
68
+ * when undefined), then enforce valid_to > valid_from. Returns the canonical pair.
69
+ */
70
+ export function validatePolicyDates(validFromRaw, validToRaw, nowIso) {
71
+ const validFrom = validFromRaw !== undefined ? normalizePolicyDate(validFromRaw, 'valid_from') : nowIso;
72
+ const validTo = validToRaw !== undefined && validToRaw !== null
73
+ ? normalizePolicyDate(validToRaw, 'valid_to')
74
+ : null;
75
+ if (validTo !== null && validTo <= validFrom) {
76
+ throw new Error(`policy: valid_to (${validTo}) must be strictly after valid_from (${validFrom})`);
77
+ }
78
+ return { validFrom, validTo };
79
+ }
80
+ function rowToPolicy(row) {
81
+ return {
82
+ id: row.id,
83
+ memoryId: row.memory_id,
84
+ tenantId: row.tenant_id,
85
+ policyName: row.policy_name,
86
+ policyText: row.policy_text,
87
+ validFrom: row.valid_from,
88
+ validTo: row.valid_to,
89
+ version: row.version,
90
+ status: row.status,
91
+ supersededBy: row.superseded_by,
92
+ supersededAt: row.superseded_at,
93
+ changeSummary: row.change_summary,
94
+ closedAt: row.closed_at,
95
+ createdAt: row.created_at,
96
+ };
97
+ }
98
+ const POLICY_COLS = `
99
+ id, memory_id, tenant_id, policy_name, policy_text, valid_from, valid_to,
100
+ version, status, superseded_by, superseded_at, change_summary, closed_at, created_at
101
+ `;
102
+ /** Recall-surface content for the memory mirror: name + rule + effective range. */
103
+ function buildPolicyContent(policyName, policyText, validFrom, validTo) {
104
+ const range = validTo ? `${validFrom} to ${validTo}` : `${validFrom} onward`;
105
+ return `${policyName}\n\n${policyText}\n\nEffective: ${range}`;
106
+ }
107
+ // ---------------------------------------------------------------------------
108
+ // Public API
109
+ // ---------------------------------------------------------------------------
110
+ /**
111
+ * Create a policy (or a new version that supersedes an existing one). Writes the
112
+ * memory mirror + the policies row atomically inside writeEntry's SAVEPOINT.
113
+ * valid_from defaults to now; valid_to must be > valid_from (validatePolicyDates).
114
+ * When supersedesPolicyId is given, the referenced ACTIVE row is preflighted
115
+ * (status + version) BEFORE the INSERT, then CAS-UPDATEd -> superseded in the same
116
+ * SAVEPOINT; the new version = predecessor.version + 1 (server-derived).
117
+ */
118
+ export function savePolicy(hippoRoot, tenantId, opts, actor = 'cli') {
119
+ assertTenantId('savePolicy', tenantId);
120
+ if (!opts.policyName || opts.policyName.trim().length === 0) {
121
+ throw new Error('savePolicy: policyName is required');
122
+ }
123
+ if (!opts.policyText || opts.policyText.trim().length === 0) {
124
+ throw new Error('savePolicy: policyText is required');
125
+ }
126
+ const now = new Date().toISOString();
127
+ // valid_from defaults to the precise creation instant (the honest effective
128
+ // time). The same-day date-only as-of workflow is handled on the READ side
129
+ // (a date-only asOf resolves to end-of-day in loadPoliciesAsOf), NOT by
130
+ // backdating the stored valid_from - backdating to midnight would make an
131
+ // earlier-same-day as-of wrongly report the policy already in force and would
132
+ // hide a superseded predecessor for that earlier time (codex review
133
+ // 2026-05-30 round 2). An explicit --from is honored as-is.
134
+ const { validFrom, validTo } = validatePolicyDates(opts.validFrom, opts.validTo, now);
135
+ const isSupersede = opts.supersedesPolicyId !== undefined;
136
+ const changeSummary = isSupersede ? (opts.changeSummary ?? null) : null;
137
+ const content = buildPolicyContent(opts.policyName, opts.policyText, validFrom, validTo);
138
+ const tags = ['policy', ...(opts.extraTags ?? [])];
139
+ const mem = createMemory(content, {
140
+ tags,
141
+ layer: Layer.Semantic,
142
+ confidence: 'verified',
143
+ source: 'policy',
144
+ tenantId,
145
+ });
146
+ mem.half_life_days = POLICY_HALF_LIFE_DAYS;
147
+ let savedRow;
148
+ writeEntry(hippoRoot, mem, {
149
+ actor,
150
+ afterWrite: (db, memoryId) => {
151
+ // Preflight the supersede target BEFORE inserting the new row (so the new
152
+ // autoincrement id can never be its own supersede target); read the
153
+ // predecessor version in the same SELECT for server-derived versioning.
154
+ // Mirrors saveProcess / saveDecision (codex P1 2026-05-28).
155
+ let version = 1;
156
+ if (opts.supersedesPolicyId !== undefined) {
157
+ const pred = db.prepare(`SELECT status, version FROM policies WHERE id = ? AND tenant_id = ?`).get(opts.supersedesPolicyId, tenantId);
158
+ if (!pred) {
159
+ throw new Error(`savePolicy: policy ${opts.supersedesPolicyId} to supersede not found for tenant ${tenantId}`);
160
+ }
161
+ if (pred.status !== 'active') {
162
+ throw new Error(`savePolicy: policy ${opts.supersedesPolicyId} is not active (status='${pred.status}'); only active policies can be superseded.`);
163
+ }
164
+ version = pred.version + 1;
165
+ }
166
+ const result = db.prepare(`
167
+ INSERT INTO policies(
168
+ memory_id, tenant_id, policy_name, policy_text, valid_from, valid_to,
169
+ version, status, superseded_by, superseded_at, change_summary, closed_at, created_at
170
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, 'active', NULL, NULL, ?, NULL, ?)
171
+ `).run(memoryId, tenantId, opts.policyName, opts.policyText, validFrom, validTo, version, changeSummary, now);
172
+ const policyId = Number(result.lastInsertRowid ?? 0);
173
+ if (opts.supersedesPolicyId !== undefined) {
174
+ const sup = db.prepare(`
175
+ UPDATE policies
176
+ SET status = 'superseded', superseded_by = ?, superseded_at = ?
177
+ WHERE id = ? AND tenant_id = ? AND status = 'active' AND id != ?
178
+ `).run(policyId, now, opts.supersedesPolicyId, tenantId, policyId);
179
+ if (sup.changes === 0) {
180
+ throw new Error(`savePolicy: policy ${opts.supersedesPolicyId} could not be superseded (no longer active or self-reference).`);
181
+ }
182
+ appendAuditEvent(db, {
183
+ tenantId,
184
+ actor,
185
+ op: 'policy_supersede',
186
+ targetId: String(opts.supersedesPolicyId),
187
+ metadata: {
188
+ policy_id: opts.supersedesPolicyId,
189
+ superseded_by: policyId,
190
+ new_version: version,
191
+ },
192
+ });
193
+ }
194
+ const row = db.prepare(`SELECT ${POLICY_COLS} FROM policies WHERE id = ?`)
195
+ .get(policyId);
196
+ if (!row)
197
+ throw new Error('savePolicy: failed to reload saved policy row');
198
+ savedRow = row;
199
+ // GDPR-light metadata: ids + flags only, no policy text.
200
+ appendAuditEvent(db, {
201
+ tenantId,
202
+ actor,
203
+ op: 'policy_create',
204
+ targetId: String(policyId),
205
+ metadata: {
206
+ policy_id: policyId,
207
+ version,
208
+ open_ended: validTo === null,
209
+ },
210
+ });
211
+ },
212
+ });
213
+ if (!savedRow) {
214
+ throw new Error('savePolicy: afterWrite did not populate the row');
215
+ }
216
+ return rowToPolicy(savedRow);
217
+ }
218
+ /**
219
+ * Close (retire) an active policy with no successor. CAS guard WHERE
220
+ * status='active'; 0 changes distinguishes not-found from not-active. A
221
+ * superseded row is terminal and cannot be closed.
222
+ */
223
+ export function closePolicy(hippoRoot, tenantId, id, actor = 'cli') {
224
+ assertTenantId('closePolicy', tenantId);
225
+ const now = new Date().toISOString();
226
+ const db = openHippoDb(hippoRoot);
227
+ try {
228
+ db.exec('BEGIN IMMEDIATE');
229
+ try {
230
+ const updateResult = db.prepare(`
231
+ UPDATE policies
232
+ SET status = 'closed', closed_at = ?
233
+ WHERE id = ? AND tenant_id = ? AND status = 'active'
234
+ `).run(now, id, tenantId);
235
+ if (updateResult.changes === 0) {
236
+ const existing = db.prepare(`SELECT status FROM policies WHERE id = ? AND tenant_id = ?`).get(id, tenantId);
237
+ if (!existing) {
238
+ throw new Error(`closePolicy: policy ${id} not found for tenant ${tenantId}`);
239
+ }
240
+ throw new Error(`closePolicy: policy ${id} is not active (status='${existing.status}'); only active policies can be closed.`);
241
+ }
242
+ const row = db.prepare(`SELECT ${POLICY_COLS} FROM policies WHERE id = ? AND tenant_id = ?`)
243
+ .get(id, tenantId);
244
+ if (!row)
245
+ throw new Error(`closePolicy: policy ${id} not found after UPDATE`);
246
+ appendAuditEvent(db, {
247
+ tenantId,
248
+ actor,
249
+ op: 'policy_close',
250
+ targetId: String(id),
251
+ metadata: { policy_id: id },
252
+ });
253
+ db.exec('COMMIT');
254
+ return rowToPolicy(row);
255
+ }
256
+ catch (e) {
257
+ try {
258
+ db.exec('ROLLBACK');
259
+ }
260
+ catch {
261
+ // Ignore rollback failures — the throw below is what matters.
262
+ }
263
+ throw e;
264
+ }
265
+ }
266
+ finally {
267
+ closeHippoDb(db);
268
+ }
269
+ }
270
+ export function loadPolicyById(hippoRoot, tenantId, id) {
271
+ assertTenantId('loadPolicyById', tenantId);
272
+ const db = openHippoDb(hippoRoot);
273
+ try {
274
+ const row = db.prepare(`SELECT ${POLICY_COLS} FROM policies WHERE id = ? AND tenant_id = ?`)
275
+ .get(id, tenantId);
276
+ return row ? rowToPolicy(row) : null;
277
+ }
278
+ finally {
279
+ closeHippoDb(db);
280
+ }
281
+ }
282
+ export function loadPolicies(hippoRoot, tenantId, opts = {}) {
283
+ assertTenantId('loadPolicies', tenantId);
284
+ const limit = opts.limit ?? 100;
285
+ const db = openHippoDb(hippoRoot);
286
+ try {
287
+ let rows;
288
+ if (opts.status) {
289
+ if (!VALID_POLICY_STATES.has(opts.status)) {
290
+ throw new Error(`loadPolicies: status must be one of ${Array.from(VALID_POLICY_STATES).join('|')}; got ${opts.status}`);
291
+ }
292
+ rows = db.prepare(`
293
+ SELECT ${POLICY_COLS} FROM policies
294
+ WHERE tenant_id = ? AND status = ?
295
+ ORDER BY created_at DESC, id DESC
296
+ LIMIT ?
297
+ `).all(tenantId, opts.status, limit);
298
+ }
299
+ else {
300
+ rows = db.prepare(`
301
+ SELECT ${POLICY_COLS} FROM policies
302
+ WHERE tenant_id = ?
303
+ ORDER BY created_at DESC, id DESC
304
+ LIMIT ?
305
+ `).all(tenantId, limit);
306
+ }
307
+ return rows.map(rowToPolicy);
308
+ }
309
+ finally {
310
+ closeHippoDb(db);
311
+ }
312
+ }
313
+ export function loadActivePolicies(hippoRoot, tenantId, opts = {}) {
314
+ return loadPolicies(hippoRoot, tenantId, { status: 'active', limit: opts.limit });
315
+ }
316
+ /**
317
+ * The bi-temporal as-of query: the policies in force at `asOfDate` (a valid-time)
318
+ * per current knowledge. Half-open interval [valid_from, valid_to): a row covers
319
+ * T when valid_from <= asOf AND (valid_to IS NULL OR asOf < valid_to). asOfDate is
320
+ * normalized to canonical datetime first so the lexical comparison is sound.
321
+ *
322
+ * A row is returned when it covers T AND it is the live answer for T:
323
+ * - `active` rows that cover T, OR
324
+ * - `superseded` rows that cover T BUT whose successor was not yet effective at T
325
+ * (successor.valid_from > asOf) - i.e. an earlier version that was genuinely in
326
+ * force then. This is the core valid-time correctness: a Jan-Jun policy
327
+ * superseded in May is still the answer for `asof March`. (codex review
328
+ * 2026-05-30, P2 #2: filtering on status='active' alone dropped historically-
329
+ * valid superseded versions, conflating transaction-time with valid-time. The
330
+ * successor-aware filter mirrors the existing recall-history.ts asOf pattern.)
331
+ *
332
+ * `closed` rows are EXCLUDED: closing is a deliberate transaction-time retirement,
333
+ * and resurrecting closed policies for a historical valid-time is full
334
+ * transaction-time-travel (deferred). Returns an ARRAY (overlapping same-name
335
+ * ranges are allowed in v1). Optionally filtered to one policy_name.
336
+ *
337
+ * Date-only `asOfDate` (e.g. "2026-05-30", no time component) resolves to the END
338
+ * of that UTC day (23:59:59.999Z), so "as of [day D]" includes a policy that
339
+ * became effective at any instant during D - this is the read-side fix for the
340
+ * common create-then-asof-today workflow, keeping the stored valid_from honest
341
+ * (codex review 2026-05-30). A full datetime asOf is used as the precise instant.
342
+ */
343
+ export function loadPoliciesAsOf(hippoRoot, tenantId, asOfDate, opts = {}) {
344
+ assertTenantId('loadPoliciesAsOf', tenantId);
345
+ // A bare date means "as of (the whole of) that day" -> end-of-day instant; a
346
+ // datetime is used precisely. normalizePolicyDate validates/canonicalizes both.
347
+ const asOf = /^\d{4}-\d{2}-\d{2}$/.test(asOfDate.trim())
348
+ ? normalizePolicyDate(`${asOfDate.trim()}T23:59:59.999Z`, 'asOfDate')
349
+ : normalizePolicyDate(asOfDate, 'asOfDate');
350
+ const limit = opts.limit ?? 100;
351
+ const db = openHippoDb(hippoRoot);
352
+ try {
353
+ // LEFT JOIN the successor so a superseded row is kept only while its
354
+ // successor is not yet effective at asOf. p.status != 'closed' drops retired
355
+ // rows; the OR keeps active heads + still-in-force superseded versions.
356
+ const nameClause = opts.name !== undefined ? 'AND p.policy_name = ?' : '';
357
+ const params = [tenantId, asOf, asOf, asOf];
358
+ if (opts.name !== undefined)
359
+ params.push(opts.name);
360
+ params.push(limit);
361
+ const rows = db.prepare(`
362
+ SELECT p.id, p.memory_id, p.tenant_id, p.policy_name, p.policy_text,
363
+ p.valid_from, p.valid_to, p.version, p.status, p.superseded_by,
364
+ p.superseded_at, p.change_summary, p.closed_at, p.created_at
365
+ FROM policies p
366
+ LEFT JOIN policies s ON s.id = p.superseded_by
367
+ WHERE p.tenant_id = ? AND p.status != 'closed'
368
+ AND p.valid_from <= ? AND (p.valid_to IS NULL OR ? < p.valid_to)
369
+ AND (p.status = 'active' OR (s.id IS NOT NULL AND s.valid_from > ?))
370
+ ${nameClause}
371
+ ORDER BY p.valid_from DESC, p.id DESC
372
+ LIMIT ?
373
+ `).all(...params);
374
+ return rows.map(rowToPolicy);
375
+ }
376
+ finally {
377
+ closeHippoDb(db);
378
+ }
379
+ }
380
+ //# sourceMappingURL=policies.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policies.js","sourceRoot":"","sources":["../../src/policies.ts"],"names":[],"mappings":"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"}