oracular 0.13.0 → 0.14.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/dist/index.d.cts CHANGED
@@ -54,6 +54,13 @@ interface RevealOptions {
54
54
  z?: number;
55
55
  /** How long after `markRevealed` the intent stays revealed and `shouldReveal` is false. Default: the intent's `halfLife`. */
56
56
  cooldown?: number;
57
+ /**
58
+ * How long after the intent's outcome event `shouldReveal` stays false. Default: `cooldown`.
59
+ * 0 is allowed: the outcome then pauses nothing, while a reveal still starts its cooldown, for
60
+ * an intent whose outcome recurs within minutes, or a "stuck" intent whose help should be back
61
+ * at the next attempt.
62
+ */
63
+ outcomeCooldown?: number;
57
64
  /**
58
65
  * How `lower` is computed. `'normal'` (default): p − z·sd, clamped to [0, 1]. `'exact'`: the
59
66
  * Beta distribution's own quantile at the same one-sided level, Φ(−z), so `z` keeps its
@@ -307,8 +314,8 @@ interface Prediction {
307
314
  revealedAt: number | null;
308
315
  /**
309
316
  * When the current suppression ends: the later of the reveal cooldown (after `markRevealed`)
310
- * and the outcome cooldown (after the outcome event) still running at `at`, or null when
311
- * neither is. `shouldReveal` is false while this is non-null.
317
+ * and the outcome cooldown (`outcomeCooldown` after the outcome event) still running at `at`,
318
+ * or null when neither is. `shouldReveal` is false while this is non-null.
312
319
  */
313
320
  suppressedUntil: number | null;
314
321
  }
@@ -730,9 +737,10 @@ declare function episodeClosed(prev: EngineState, next: EngineState): boolean;
730
737
  * @param state - The current state. Not mutated.
731
738
  * @param intent - Name of an intent declared in the config.
732
739
  * @param at - The time to evaluate at, in the same unit as your durations.
733
- * @param opts - Overrides for `threshold`, `z`, `cooldown` and `bound`, resolved as call →
734
- * intent → engine → defaults. `z` and `bound` set `lower`; `cooldown` sets `revealed` and
735
- * `suppressedUntil`; `threshold` only matters to {@link shouldReveal}.
740
+ * @param opts - Overrides for `threshold`, `z`, `cooldown`, `outcomeCooldown` and `bound`,
741
+ * resolved as call → intent → engine → defaults. `z` and `bound` set `lower`; `cooldown` sets
742
+ * `revealed` and, with `outcomeCooldown` (default: `cooldown`), `suppressedUntil`;
743
+ * `threshold` only matters to {@link shouldReveal}.
736
744
  * @returns The prediction. `p`, `sd`, `lower` and `confidence` are in [0, 1]; `evidence` is
737
745
  * α + β.
738
746
  * @throws `RangeError` when `intent` is not declared in the config.
@@ -755,7 +763,8 @@ declare function predict(state: EngineState, intent: string, at: number, opts?:
755
763
  * @param intent - Name of an intent declared in the config.
756
764
  * @param at - The time to evaluate at.
757
765
  * @param opts - Overrides for `threshold` (default 0.5), `z` (default 1.28, a one-sided 90%
758
- * bound) and `cooldown` (default: the intent's `halfLife`).
766
+ * bound), `cooldown` (default: the intent's `halfLife`) and `outcomeCooldown` (default:
767
+ * `cooldown`; 0 lets the outcome pause nothing).
759
768
  * @returns True when the app should show, offer or reveal whatever this intent gates.
760
769
  * @throws `RangeError` when `intent` is not declared in the config.
761
770
  * @throws `TypeError` when `state` is not an engine state, `at` is not finite, or `opts` is
package/dist/index.d.ts CHANGED
@@ -54,6 +54,13 @@ interface RevealOptions {
54
54
  z?: number;
55
55
  /** How long after `markRevealed` the intent stays revealed and `shouldReveal` is false. Default: the intent's `halfLife`. */
56
56
  cooldown?: number;
57
+ /**
58
+ * How long after the intent's outcome event `shouldReveal` stays false. Default: `cooldown`.
59
+ * 0 is allowed: the outcome then pauses nothing, while a reveal still starts its cooldown, for
60
+ * an intent whose outcome recurs within minutes, or a "stuck" intent whose help should be back
61
+ * at the next attempt.
62
+ */
63
+ outcomeCooldown?: number;
57
64
  /**
58
65
  * How `lower` is computed. `'normal'` (default): p − z·sd, clamped to [0, 1]. `'exact'`: the
59
66
  * Beta distribution's own quantile at the same one-sided level, Φ(−z), so `z` keeps its
@@ -307,8 +314,8 @@ interface Prediction {
307
314
  revealedAt: number | null;
308
315
  /**
309
316
  * When the current suppression ends: the later of the reveal cooldown (after `markRevealed`)
310
- * and the outcome cooldown (after the outcome event) still running at `at`, or null when
311
- * neither is. `shouldReveal` is false while this is non-null.
317
+ * and the outcome cooldown (`outcomeCooldown` after the outcome event) still running at `at`,
318
+ * or null when neither is. `shouldReveal` is false while this is non-null.
312
319
  */
313
320
  suppressedUntil: number | null;
314
321
  }
@@ -730,9 +737,10 @@ declare function episodeClosed(prev: EngineState, next: EngineState): boolean;
730
737
  * @param state - The current state. Not mutated.
731
738
  * @param intent - Name of an intent declared in the config.
732
739
  * @param at - The time to evaluate at, in the same unit as your durations.
733
- * @param opts - Overrides for `threshold`, `z`, `cooldown` and `bound`, resolved as call →
734
- * intent → engine → defaults. `z` and `bound` set `lower`; `cooldown` sets `revealed` and
735
- * `suppressedUntil`; `threshold` only matters to {@link shouldReveal}.
740
+ * @param opts - Overrides for `threshold`, `z`, `cooldown`, `outcomeCooldown` and `bound`,
741
+ * resolved as call → intent → engine → defaults. `z` and `bound` set `lower`; `cooldown` sets
742
+ * `revealed` and, with `outcomeCooldown` (default: `cooldown`), `suppressedUntil`;
743
+ * `threshold` only matters to {@link shouldReveal}.
736
744
  * @returns The prediction. `p`, `sd`, `lower` and `confidence` are in [0, 1]; `evidence` is
737
745
  * α + β.
738
746
  * @throws `RangeError` when `intent` is not declared in the config.
@@ -755,7 +763,8 @@ declare function predict(state: EngineState, intent: string, at: number, opts?:
755
763
  * @param intent - Name of an intent declared in the config.
756
764
  * @param at - The time to evaluate at.
757
765
  * @param opts - Overrides for `threshold` (default 0.5), `z` (default 1.28, a one-sided 90%
758
- * bound) and `cooldown` (default: the intent's `halfLife`).
766
+ * bound), `cooldown` (default: the intent's `halfLife`) and `outcomeCooldown` (default:
767
+ * `cooldown`; 0 lets the outcome pause nothing).
759
768
  * @returns True when the app should show, offer or reveal whatever this intent gates.
760
769
  * @throws `RangeError` when `intent` is not declared in the config.
761
770
  * @throws `TypeError` when `state` is not an engine state, `at` is not finite, or `opts` is
package/dist/index.js CHANGED
@@ -287,7 +287,7 @@ var INTENT_KEYS = [
287
287
  "attribution",
288
288
  "reveal"
289
289
  ];
290
- var REVEAL_KEYS = ["threshold", "z", "cooldown", "bound"];
290
+ var REVEAL_KEYS = ["threshold", "z", "cooldown", "outcomeCooldown", "bound"];
291
291
  var LEARNING_KEYS = ["halfLife", "gain", "priorEpisodes", "lift"];
292
292
  var LIFT_TYPES = [
293
293
  "absolute-difference",
@@ -373,6 +373,9 @@ function normalizeRevealOptions(value, path, strict = true) {
373
373
  if (record2.cooldown !== void 0) {
374
374
  out.cooldown = expectNonNegative(record2.cooldown, `${path}.cooldown`);
375
375
  }
376
+ if (record2.outcomeCooldown !== void 0) {
377
+ out.outcomeCooldown = expectNonNegative(record2.outcomeCooldown, `${path}.outcomeCooldown`);
378
+ }
376
379
  if (record2.bound !== void 0) {
377
380
  if (record2.bound !== "normal" && record2.bound !== "exact") {
378
381
  typeError(`${path}.bound`, 'must be "normal" or "exact"');
@@ -511,10 +514,12 @@ function splitEvaluateOptions(value, path) {
511
514
  }
512
515
  function resolveReveal(config, intent, opts, normalized = false) {
513
516
  const o = opts === void 0 ? {} : normalized ? opts : normalizeRevealOptions(opts, "options", false);
517
+ const cooldown = o.cooldown ?? intent.reveal?.cooldown ?? config?.reveal?.cooldown ?? intent.halfLife;
514
518
  return {
515
519
  threshold: o.threshold ?? intent.reveal?.threshold ?? config?.reveal?.threshold ?? DEFAULT_THRESHOLD,
516
520
  z: o.z ?? intent.reveal?.z ?? config?.reveal?.z ?? DEFAULT_Z,
517
- cooldown: o.cooldown ?? intent.reveal?.cooldown ?? config?.reveal?.cooldown ?? intent.halfLife,
521
+ cooldown,
522
+ outcomeCooldown: o.outcomeCooldown ?? intent.reveal?.outcomeCooldown ?? config?.reveal?.outcomeCooldown ?? cooldown,
518
523
  bound: o.bound ?? intent.reveal?.bound ?? config?.reveal?.bound ?? "normal"
519
524
  };
520
525
  }
@@ -619,7 +624,7 @@ function buildPrediction(is, name, reveal, at) {
619
624
  const p = betaMean(is.alpha, is.beta);
620
625
  const sd = betaSd(is.alpha, is.beta);
621
626
  const revealEnd = cooldownEnd(is.lastRevealedAt, reveal.cooldown, at);
622
- const outcomeEnd = cooldownEnd(is.lastOutcomeAt, reveal.cooldown, at);
627
+ const outcomeEnd = cooldownEnd(is.lastOutcomeAt, reveal.outcomeCooldown, at);
623
628
  const suppressedUntil = revealEnd === null ? outcomeEnd : outcomeEnd === null ? revealEnd : Math.max(revealEnd, outcomeEnd);
624
629
  return {
625
630
  intent: name,