fix: caller clock everywhere — value TTL, decay, qualitative decay, cache TTL
The principle: time is caller-provided (options.now / partialGraph.now); the wall clock is only the fallback for unpinned callers, never a hidden decision input. Remaining clock leaks: - getBlurredValue gained an optional now param threaded to _isValueExpired; ChainRule (2 sites), MultiHopRule (2 sites), RelationManager (3 sites) now pass the caller clock. Previously a pinned-clock caller's chain/ multi-hop value TTL used the WALL clock (wall in 2026, pinned T0 in 2001 -> values wrongly expired). - MultiHopRule's TTL gate used valueFilters.ttl || 24h instead of the valueManager's per-relation TTL (inconsistent with chain/comparator); now valueManager.getTTL is the authority, valueFilters.ttl the override. - QualitativeRelationalComparatorRule decay (_calculatePeriodsElapsed) and value timestamps used the wall clock, so qualitative possibility decay ignored the pinned clock; now threaded through _evaluateOperand. - ValueManager decay internals (getDecayedRelation, _calculateSeparated Decay, _calculateBlurredValue) accept a now param (background worker still passes none -> wall clock is correct there). - PartialGraphContext._addChallengeProof/_addRelation used Date.now() instead of the context's own this.now (the partial graph's time). - Arbiter gained an injectable clock (options.clock) driving unpinned cache-entry freshness in DecisionCache, RuleEvaluator, ChainRule, and RelationalComparatorRule; DecisionCache explicit clock still wins. - Collected-value timestamps in DirectRule and RelationalComparatorRule honor the caller clock. Pinned-clock chain probe: values fresh at T0, expired at T0+61s, with the wall clock in 2026. Rigor 251/251, full suite 853/791/0.
This commit is contained in:
@@ -244,7 +244,7 @@ export class QualitativeRelationalComparatorRule extends BaseRule {
|
||||
}
|
||||
|
||||
// Extract blurred values with qualitative decay and blur
|
||||
const blurredValues = this._extractBlurredValues(adjustedValues, operandConfig, scale);
|
||||
const blurredValues = this._extractBlurredValues(adjustedValues, operandConfig, scale, options);
|
||||
|
||||
if (operandMeta) {
|
||||
operandMeta.blurredValues = blurredValues;
|
||||
@@ -299,7 +299,7 @@ export class QualitativeRelationalComparatorRule extends BaseRule {
|
||||
values.push({
|
||||
value: qualitativeValue,
|
||||
possibility: qualitativeValue,
|
||||
timestamp: Date.now(),
|
||||
timestamp: options && options.now !== undefined && options.now !== null ? options.now : Date.now(),
|
||||
relation: 'rule_result',
|
||||
meta: { source: 'rule_possibility' }
|
||||
});
|
||||
@@ -351,7 +351,7 @@ export class QualitativeRelationalComparatorRule extends BaseRule {
|
||||
* Extract blurred values with qualitative decay and blur
|
||||
* @private
|
||||
*/
|
||||
_extractBlurredValues(values, operandConfig, scale) {
|
||||
_extractBlurredValues(values, operandConfig, scale, options = null) {
|
||||
const {
|
||||
decaySteps = 1,
|
||||
decayPeriod = 'HOUR',
|
||||
@@ -366,10 +366,11 @@ export class QualitativeRelationalComparatorRule extends BaseRule {
|
||||
for (const valueObj of values) {
|
||||
const pointValue = valueObj.value;
|
||||
const initialPossibility = valueObj.possibility;
|
||||
const timestamp = valueObj.timestamp || Date.now();
|
||||
const timestamp = valueObj.timestamp ||
|
||||
(options && options.now !== undefined && options.now !== null ? options.now : Date.now());
|
||||
|
||||
// Calculate periods elapsed
|
||||
const periodsElapsed = this._calculatePeriodsElapsed(timestamp, decayPeriod);
|
||||
const periodsElapsed = this._calculatePeriodsElapsed(timestamp, decayPeriod, options);
|
||||
|
||||
// Calculate decayed possibility
|
||||
const decayedPossibility = this._calculateDecayedPossibility(
|
||||
@@ -415,8 +416,8 @@ export class QualitativeRelationalComparatorRule extends BaseRule {
|
||||
* Calculate periods elapsed since timestamp
|
||||
* @private
|
||||
*/
|
||||
_calculatePeriodsElapsed(timestamp, decayPeriod) {
|
||||
const now = Date.now();
|
||||
_calculatePeriodsElapsed(timestamp, decayPeriod, options = null) {
|
||||
const now = options && options.now !== undefined && options.now !== null ? options.now : Date.now();
|
||||
const elapsed = now - timestamp;
|
||||
|
||||
const periodMs = {
|
||||
@@ -533,7 +534,8 @@ export class QualitativeRelationalComparatorRule extends BaseRule {
|
||||
step: index
|
||||
},
|
||||
metadata: {
|
||||
timestamp: bv.timestamp || Date.now(),
|
||||
timestamp: bv.timestamp ||
|
||||
(options && options.now !== undefined && options.now !== null ? options.now : Date.now()),
|
||||
reliability: 1.0,
|
||||
originalValue: bv.originalValue,
|
||||
originalPossibility: bv.originalPossibility,
|
||||
|
||||
Reference in New Issue
Block a user