@theokit/sdk 4.49.0 → 4.50.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 4.50.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 7e6a0d4: Add `planReaping`: decide which session artifacts may be deleted — and never delete them. Tri-state (keep / reap / undetermined), a keep-last floor, and liveness that outranks age.
8
+
3
9
  ## 4.49.0
4
10
 
5
11
  ### Minor Changes
package/dist/index.cjs CHANGED
@@ -1571,6 +1571,60 @@ function loadProjectEnv(env = process.env, load = typeof process.loadEnvFile ===
1571
1571
  }
1572
1572
  }
1573
1573
 
1574
+ // src/reap-plan.ts
1575
+ var RetentionPolicyError = class extends chunkYULF6FPB_cjs.TheokitAgentError {
1576
+ name = "RetentionPolicyError";
1577
+ };
1578
+ function assertPolicy(retention) {
1579
+ const { maxAgeMs, keepLast } = retention;
1580
+ if (!Number.isFinite(maxAgeMs) || maxAgeMs < 0) {
1581
+ throw new RetentionPolicyError(
1582
+ `retention.maxAgeMs must be a non-negative number of milliseconds, got ${String(maxAgeMs)}`
1583
+ );
1584
+ }
1585
+ if (!Number.isInteger(keepLast) || keepLast < 0) {
1586
+ throw new RetentionPolicyError(
1587
+ `retention.keepLast must be a non-negative integer, got ${String(keepLast)}`
1588
+ );
1589
+ }
1590
+ }
1591
+ function classifyByOwnReason(input) {
1592
+ const keep = [];
1593
+ const atRisk = [];
1594
+ for (const artifact of input.artifacts) {
1595
+ if (artifact.live === "unknown") continue;
1596
+ if (artifact.live === true) {
1597
+ keep.push({ ...artifact, reason: "live" });
1598
+ continue;
1599
+ }
1600
+ if (input.nowMs - artifact.lastModifiedMs <= input.retention.maxAgeMs) {
1601
+ keep.push({ ...artifact, reason: "within-retention" });
1602
+ continue;
1603
+ }
1604
+ atRisk.push(artifact);
1605
+ }
1606
+ return { keep, atRisk };
1607
+ }
1608
+ function applyFloor(kept, atRisk, keepLast) {
1609
+ const shortfall = Math.max(0, keepLast - kept.length);
1610
+ const newestFirst = [...atRisk].sort((a, b) => b.lastModifiedMs - a.lastModifiedMs);
1611
+ const spared = new Set(newestFirst.slice(0, shortfall).map((a) => a.id));
1612
+ const rescued = [];
1613
+ const reap = [];
1614
+ for (const artifact of atRisk) {
1615
+ if (spared.has(artifact.id)) rescued.push({ ...artifact, reason: "keep-last" });
1616
+ else reap.push(artifact);
1617
+ }
1618
+ return { rescued, reap };
1619
+ }
1620
+ function planReaping(input) {
1621
+ assertPolicy(input.retention);
1622
+ const undetermined = input.artifacts.filter((a) => a.live === "unknown");
1623
+ const { keep, atRisk } = classifyByOwnReason(input);
1624
+ const { rescued, reap } = applyFloor(keep, atRisk, input.retention.keepLast);
1625
+ return { reap, keep: [...keep, ...rescued], undetermined };
1626
+ }
1627
+
1574
1628
  // src/schema-normalizer.ts
1575
1629
  function isJsonSchemaObject(s) {
1576
1630
  if (typeof s !== "object" || s === null) return false;
@@ -2370,6 +2424,7 @@ exports.PermissionEngine = PermissionEngine;
2370
2424
  exports.PermissionPlugin = PermissionPlugin;
2371
2425
  exports.Plugin = Plugin;
2372
2426
  exports.Provider = Provider;
2427
+ exports.RetentionPolicyError = RetentionPolicyError;
2373
2428
  exports.SOVEREIGN_ENV_KEYS = SOVEREIGN_ENV_KEYS;
2374
2429
  exports.Security = Security;
2375
2430
  exports.Skill = Skill;
@@ -2394,6 +2449,7 @@ exports.migrateSqliteToLance = migrateSqliteToLance2;
2394
2449
  exports.mkMemoryId = mkMemoryId;
2395
2450
  exports.normalizeSchema = normalizeSchema;
2396
2451
  exports.normalizeUsage = normalizeUsage;
2452
+ exports.planReaping = planReaping;
2397
2453
  exports.preflightCheck = preflightCheck;
2398
2454
  exports.recordWiring = recordWiring;
2399
2455
  exports.resolveTrustPosture = resolveTrustPosture;