@orkestrel/reason 0.0.5 → 0.0.6

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.
@@ -770,6 +770,303 @@ function isDefinition(value) {
770
770
  return isQuantitativeDefinition(value) || isLogicalDefinition(value) || isSymbolicDefinition(value) || isInferentialDefinition(value);
771
771
  }
772
772
  /**
773
+ * Determine whether a value is a result-side {@link Fact}.
774
+ *
775
+ * @remarks
776
+ * Unlike the exact input guard {@link isFact}, this guard accepts unknown
777
+ * members, class instances, and every JavaScript `number` confidence.
778
+ *
779
+ * @param value - The value to test
780
+ * @returns `true` when every published fact member is valid for a result
781
+ *
782
+ * @example
783
+ * ```ts
784
+ * import { isResultFact } from '@src/core'
785
+ *
786
+ * isResultFact({ id: 'f1', predicate: 'bird', terms: ['tweety'], note: 'derived' }) // true
787
+ * isResultFact({ id: 'f1', predicate: 'bird' }) // false
788
+ * ```
789
+ */
790
+ function isResultFact(value) {
791
+ return (0, _orkestrel_contract.whereOf)(_orkestrel_contract.isObject, (result) => {
792
+ if ((0, _orkestrel_contract.isArray)(result)) return false;
793
+ const confidence = Reflect.get(result, "confidence");
794
+ return (0, _orkestrel_contract.isString)(Reflect.get(result, "id")) && (0, _orkestrel_contract.isString)(Reflect.get(result, "predicate")) && (0, _orkestrel_contract.isArray)(Reflect.get(result, "terms")) && (confidence === void 0 || (0, _orkestrel_contract.isNumber)(confidence));
795
+ })(value);
796
+ }
797
+ /**
798
+ * Determine whether a value is a {@link CheckResult}.
799
+ *
800
+ * @param value - The value to test
801
+ * @returns `true` when every published check-result member is valid
802
+ *
803
+ * @example
804
+ * ```ts
805
+ * import { isCheckResult } from '@src/core'
806
+ *
807
+ * isCheckResult({ field: 'age', met: true, actual: 30 }) // true
808
+ * isCheckResult({ field: 'age', met: 'yes', actual: 30 }) // false
809
+ * ```
810
+ */
811
+ function isCheckResult(value) {
812
+ return (0, _orkestrel_contract.whereOf)(_orkestrel_contract.isObject, (result) => {
813
+ if ((0, _orkestrel_contract.isArray)(result)) return false;
814
+ const error = Reflect.get(result, "error");
815
+ return isFieldPath(Reflect.get(result, "field")) && (0, _orkestrel_contract.isBoolean)(Reflect.get(result, "met")) && Reflect.has(result, "actual") && (error === void 0 || (0, _orkestrel_contract.isString)(error));
816
+ })(value);
817
+ }
818
+ /**
819
+ * Determine whether a value is a {@link FactorResult}.
820
+ *
821
+ * @param value - The value to test
822
+ * @returns `true` when every published factor-result member is valid
823
+ *
824
+ * @example
825
+ * ```ts
826
+ * import { isFactorResult } from '@src/core'
827
+ *
828
+ * isFactorResult({ id: 'age', applied: true, value: 5 }) // true
829
+ * isFactorResult({ id: 'age', applied: true, value: '5' }) // false
830
+ * ```
831
+ */
832
+ function isFactorResult(value) {
833
+ return (0, _orkestrel_contract.whereOf)(_orkestrel_contract.isObject, (result) => {
834
+ if ((0, _orkestrel_contract.isArray)(result)) return false;
835
+ const raw = Reflect.get(result, "raw");
836
+ const checks = Reflect.get(result, "checks");
837
+ return (0, _orkestrel_contract.isString)(Reflect.get(result, "id")) && (0, _orkestrel_contract.isBoolean)(Reflect.get(result, "applied")) && (0, _orkestrel_contract.isNumber)(Reflect.get(result, "value")) && (raw === void 0 || (0, _orkestrel_contract.isNumber)(raw)) && (checks === void 0 || (0, _orkestrel_contract.arrayOf)(isCheckResult)(checks));
838
+ })(value);
839
+ }
840
+ /**
841
+ * Determine whether a value is a {@link GroupResult}.
842
+ *
843
+ * @param value - The value to test
844
+ * @returns `true` when every published group-result member is valid
845
+ *
846
+ * @example
847
+ * ```ts
848
+ * import { isGroupResult } from '@src/core'
849
+ *
850
+ * isGroupResult({ id: 'risk', applied: true, value: 5, factors: [] }) // true
851
+ * isGroupResult({ id: 'risk', applied: true, value: 5 }) // false
852
+ * ```
853
+ */
854
+ function isGroupResult(value) {
855
+ return (0, _orkestrel_contract.whereOf)(_orkestrel_contract.isObject, (result) => {
856
+ return !(0, _orkestrel_contract.isArray)(result) && (0, _orkestrel_contract.isString)(Reflect.get(result, "id")) && (0, _orkestrel_contract.isBoolean)(Reflect.get(result, "applied")) && (0, _orkestrel_contract.isNumber)(Reflect.get(result, "value")) && (0, _orkestrel_contract.arrayOf)(isFactorResult)(Reflect.get(result, "factors"));
857
+ })(value);
858
+ }
859
+ /**
860
+ * Determine whether a value is a {@link RuleResult}.
861
+ *
862
+ * @param value - The value to test
863
+ * @returns `true` when every published rule-result member is valid
864
+ *
865
+ * @example
866
+ * ```ts
867
+ * import { isRuleResult } from '@src/core'
868
+ *
869
+ * isRuleResult({ id: 'adult', applied: true, premises: [true], conclusion: true }) // true
870
+ * isRuleResult({ id: 'adult', applied: true, premises: [1], conclusion: true }) // false
871
+ * ```
872
+ */
873
+ function isRuleResult(value) {
874
+ return (0, _orkestrel_contract.whereOf)(_orkestrel_contract.isObject, (result) => {
875
+ return !(0, _orkestrel_contract.isArray)(result) && (0, _orkestrel_contract.isString)(Reflect.get(result, "id")) && (0, _orkestrel_contract.isBoolean)(Reflect.get(result, "applied")) && (0, _orkestrel_contract.arrayOf)(_orkestrel_contract.isBoolean)(Reflect.get(result, "premises")) && (0, _orkestrel_contract.isBoolean)(Reflect.get(result, "conclusion"));
876
+ })(value);
877
+ }
878
+ /**
879
+ * Determine whether a value is a depth-bounded, acyclic {@link ProofNode} tree.
880
+ *
881
+ * @remarks
882
+ * Traversal is iterative and reuses `GUARD_DEPTH_LIMIT`. Active ancestors refuse cycles, and a
883
+ * settled-depth record prevents repeated validation of shared subtrees while keeping the bound
884
+ * exact: a node revisited no deeper than its validated depth is skipped, and one reached deeper
885
+ * is walked again. The traversal accepts an acyclic graph only when every reachable node is
886
+ * valid and every root-to-node path contains at most `GUARD_DEPTH_LIMIT` nodes; shared aliases
887
+ * and sibling order do not affect the verdict.
888
+ *
889
+ * @param value - The value to test
890
+ * @returns `true` when every proof node is valid within the runtime guard bound
891
+ *
892
+ * @example
893
+ * ```ts
894
+ * import { isProofNode } from '@src/core'
895
+ *
896
+ * isProofNode({ fact: 'bird', depth: 0, children: [{ fact: 'feathers', depth: 1 }] }) // true
897
+ * isProofNode({ fact: 'bird', children: [] }) // false
898
+ * ```
899
+ */
900
+ function isProofNode(value) {
901
+ return (0, _orkestrel_contract.holds)(() => {
902
+ if (!(0, _orkestrel_contract.isObject)(value) || (0, _orkestrel_contract.isArray)(value)) return false;
903
+ const active = /* @__PURE__ */ new WeakSet();
904
+ const settled = /* @__PURE__ */ new WeakMap();
905
+ const worklist = [[
906
+ value,
907
+ 1,
908
+ false
909
+ ]];
910
+ while (worklist.length > 0) {
911
+ const frame = worklist.pop();
912
+ if (frame === void 0) continue;
913
+ const node = frame[0];
914
+ const depth = frame[1];
915
+ if (frame[2]) {
916
+ active.delete(node);
917
+ const known = settled.get(node);
918
+ settled.set(node, known === void 0 || depth > known ? depth : known);
919
+ continue;
920
+ }
921
+ if (depth > _orkestrel_contract.GUARD_DEPTH_LIMIT || active.has(node)) return false;
922
+ const known = settled.get(node);
923
+ if (known !== void 0 && depth <= known) continue;
924
+ active.add(node);
925
+ worklist.push([
926
+ node,
927
+ depth,
928
+ true
929
+ ]);
930
+ const inference = Reflect.get(node, "inference");
931
+ const children = Reflect.get(node, "children");
932
+ if (!(0, _orkestrel_contract.isString)(Reflect.get(node, "fact")) || !(0, _orkestrel_contract.isNumber)(Reflect.get(node, "depth")) || inference !== void 0 && !(0, _orkestrel_contract.isString)(inference)) return false;
933
+ if (children === void 0) continue;
934
+ if (!(0, _orkestrel_contract.isArray)(children)) return false;
935
+ const entries = (0, _orkestrel_contract.readArrayEntries)(children);
936
+ if (!entries.success || !entries.value.dense) return false;
937
+ for (let index = entries.value.entries.length - 1; index >= 0; index -= 1) {
938
+ const child = entries.value.entries[index];
939
+ if (!(0, _orkestrel_contract.isObject)(child) || (0, _orkestrel_contract.isArray)(child)) return false;
940
+ worklist.push([
941
+ child,
942
+ depth + 1,
943
+ false
944
+ ]);
945
+ }
946
+ }
947
+ return true;
948
+ });
949
+ }
950
+ /**
951
+ * Determine whether a value is a {@link QuantitativeResult}.
952
+ *
953
+ * @param value - The value to test
954
+ * @returns `true` when every published quantitative-result member is valid
955
+ *
956
+ * @example
957
+ * ```ts
958
+ * import { isQuantitativeResult } from '@src/core'
959
+ *
960
+ * isQuantitativeResult({ reasoning: 'quantitative', value: 0, groups: [], count: 0, success: true, trace: [], errors: [] }) // true
961
+ * isQuantitativeResult({ reasoning: 'quantitative' }) // false
962
+ * ```
963
+ */
964
+ function isQuantitativeResult(value) {
965
+ return (0, _orkestrel_contract.whereOf)(_orkestrel_contract.isObject, (result) => {
966
+ return !(0, _orkestrel_contract.isArray)(result) && Reflect.get(result, "reasoning") === "quantitative" && (0, _orkestrel_contract.isNumber)(Reflect.get(result, "value")) && (0, _orkestrel_contract.arrayOf)(isGroupResult)(Reflect.get(result, "groups")) && (0, _orkestrel_contract.isNumber)(Reflect.get(result, "count")) && (0, _orkestrel_contract.isBoolean)(Reflect.get(result, "success")) && (0, _orkestrel_contract.arrayOf)(_orkestrel_contract.isString)(Reflect.get(result, "trace")) && (0, _orkestrel_contract.arrayOf)(_orkestrel_contract.isString)(Reflect.get(result, "errors"));
967
+ })(value);
968
+ }
969
+ /**
970
+ * Determine whether a value is a {@link LogicalResult}.
971
+ *
972
+ * @param value - The value to test
973
+ * @returns `true` when every published logical-result member is valid
974
+ *
975
+ * @example
976
+ * ```ts
977
+ * import { isLogicalResult } from '@src/core'
978
+ *
979
+ * isLogicalResult({ reasoning: 'logical', conclusion: false, rules: [], count: 0, success: true, trace: [], errors: [] }) // true
980
+ * isLogicalResult({ reasoning: 'logical', rules: [] }) // false
981
+ * ```
982
+ */
983
+ function isLogicalResult(value) {
984
+ return (0, _orkestrel_contract.whereOf)(_orkestrel_contract.isObject, (result) => {
985
+ return !(0, _orkestrel_contract.isArray)(result) && Reflect.get(result, "reasoning") === "logical" && (0, _orkestrel_contract.isBoolean)(Reflect.get(result, "conclusion")) && (0, _orkestrel_contract.arrayOf)(isRuleResult)(Reflect.get(result, "rules")) && (0, _orkestrel_contract.isNumber)(Reflect.get(result, "count")) && (0, _orkestrel_contract.isBoolean)(Reflect.get(result, "success")) && (0, _orkestrel_contract.arrayOf)(_orkestrel_contract.isString)(Reflect.get(result, "trace")) && (0, _orkestrel_contract.arrayOf)(_orkestrel_contract.isString)(Reflect.get(result, "errors"));
986
+ })(value);
987
+ }
988
+ /**
989
+ * Determine whether a value is a {@link SymbolicResult}.
990
+ *
991
+ * @remarks
992
+ * `solutions` is checked across its OWN string-named members, enumerable or
993
+ * not. Inherited members are deliberately unread: they belong to the
994
+ * accepted-prototype property, not to the record this guard certifies.
995
+ *
996
+ * @param value - The value to test
997
+ * @returns `true` when every published symbolic-result member is valid
998
+ *
999
+ * @example
1000
+ * ```ts
1001
+ * import { isSymbolicResult } from '@src/core'
1002
+ *
1003
+ * isSymbolicResult({ reasoning: 'symbolic', solutions: { x: 4 }, success: true, trace: [], errors: [] }) // true
1004
+ * isSymbolicResult({ reasoning: 'symbolic', solutions: { x: '4' }, success: true, trace: [], errors: [] }) // false
1005
+ * ```
1006
+ */
1007
+ function isSymbolicResult(value) {
1008
+ return (0, _orkestrel_contract.whereOf)(_orkestrel_contract.isObject, (result) => {
1009
+ return !(0, _orkestrel_contract.isArray)(result) && Reflect.get(result, "reasoning") === "symbolic" && (0, _orkestrel_contract.whereOf)(_orkestrel_contract.isObject, (solutions) => !(0, _orkestrel_contract.isArray)(solutions) && Object.getOwnPropertyNames(solutions).every((key) => (0, _orkestrel_contract.isNumber)(Reflect.get(solutions, key))))(Reflect.get(result, "solutions")) && (0, _orkestrel_contract.isBoolean)(Reflect.get(result, "success")) && (0, _orkestrel_contract.arrayOf)(_orkestrel_contract.isString)(Reflect.get(result, "trace")) && (0, _orkestrel_contract.arrayOf)(_orkestrel_contract.isString)(Reflect.get(result, "errors"));
1010
+ })(value);
1011
+ }
1012
+ /**
1013
+ * Determine whether a value is an {@link InferentialResult}.
1014
+ *
1015
+ * @param value - The value to test
1016
+ * @returns `true` when every published inferential-result member is valid
1017
+ *
1018
+ * @example
1019
+ * ```ts
1020
+ * import { isInferentialResult } from '@src/core'
1021
+ *
1022
+ * isInferentialResult({ reasoning: 'inferential', derived: [], success: true, trace: [], errors: [] }) // true
1023
+ * isInferentialResult({ reasoning: 'inferential', derived: [null], success: true, trace: [], errors: [] }) // false
1024
+ * ```
1025
+ */
1026
+ function isInferentialResult(value) {
1027
+ return (0, _orkestrel_contract.whereOf)(_orkestrel_contract.isObject, (result) => {
1028
+ if ((0, _orkestrel_contract.isArray)(result)) return false;
1029
+ const proof = Reflect.get(result, "proof");
1030
+ return Reflect.get(result, "reasoning") === "inferential" && (0, _orkestrel_contract.arrayOf)(isResultFact)(Reflect.get(result, "derived")) && (proof === void 0 || isProofNode(proof)) && (0, _orkestrel_contract.isBoolean)(Reflect.get(result, "success")) && (0, _orkestrel_contract.arrayOf)(_orkestrel_contract.isString)(Reflect.get(result, "trace")) && (0, _orkestrel_contract.arrayOf)(_orkestrel_contract.isString)(Reflect.get(result, "errors"));
1031
+ })(value);
1032
+ }
1033
+ /**
1034
+ * Determine whether a value is any {@link ReasonResult} arm.
1035
+ *
1036
+ * @param value - The value to test
1037
+ * @returns `true` when one complete reasoning-result guard accepts the value
1038
+ *
1039
+ * @example
1040
+ * ```ts
1041
+ * import { isReasonResult } from '@src/core'
1042
+ *
1043
+ * isReasonResult({ reasoning: 'symbolic', solutions: {}, success: true, trace: [], errors: [] }) // true
1044
+ * isReasonResult({ reasoning: 'unknown' }) // false
1045
+ * ```
1046
+ */
1047
+ function isReasonResult(value) {
1048
+ return isQuantitativeResult(value) || isLogicalResult(value) || isSymbolicResult(value) || isInferentialResult(value);
1049
+ }
1050
+ /**
1051
+ * Determine whether a value is a {@link ReasonValidationResult}.
1052
+ *
1053
+ * @param value - The value to test
1054
+ * @returns `true` when every published validation-result member is valid
1055
+ *
1056
+ * @example
1057
+ * ```ts
1058
+ * import { isReasonValidationResult } from '@src/core'
1059
+ *
1060
+ * isReasonValidationResult({ valid: true, errors: [], warnings: [] }) // true
1061
+ * isReasonValidationResult({ valid: true, errors: [] }) // false
1062
+ * ```
1063
+ */
1064
+ function isReasonValidationResult(value) {
1065
+ return (0, _orkestrel_contract.whereOf)(_orkestrel_contract.isObject, (result) => {
1066
+ return !(0, _orkestrel_contract.isArray)(result) && (0, _orkestrel_contract.isBoolean)(Reflect.get(result, "valid")) && (0, _orkestrel_contract.arrayOf)(_orkestrel_contract.isString)(Reflect.get(result, "errors")) && (0, _orkestrel_contract.arrayOf)(_orkestrel_contract.isString)(Reflect.get(result, "warnings"));
1067
+ })(value);
1068
+ }
1069
+ /**
773
1070
  * Determine whether a value is a `DefinitionBuilder` ENTITY — the brand-guarded
774
1071
  * stateful workspace, not the plain {@link Definition} data union.
775
1072
  *
@@ -1798,13 +2095,15 @@ function matchFacts(pattern, candidate) {
1798
2095
  for (let index = 0; index < pattern.terms.length; index++) {
1799
2096
  const patternTerm = pattern.terms[index];
1800
2097
  const factTerm = candidate.terms[index];
1801
- if (typeof patternTerm === "string" && patternTerm.startsWith("?")) if (patternTerm in bindings) {
1802
- if (bindings[patternTerm] !== factTerm) return void 0;
1803
- } else bindings[patternTerm] = factTerm;
1804
- else if (typeof factTerm === "string" && factTerm.startsWith("?")) if (factTerm in bindings) {
1805
- if (bindings[factTerm] !== patternTerm) return void 0;
1806
- } else bindings[factTerm] = patternTerm;
1807
- else if (patternTerm !== factTerm) return;
2098
+ if (typeof patternTerm === "string" && patternTerm.startsWith("?")) {
2099
+ if (patternTerm in bindings) {
2100
+ if (bindings[patternTerm] !== factTerm) return void 0;
2101
+ } else bindings[patternTerm] = factTerm;
2102
+ } else if (typeof factTerm === "string" && factTerm.startsWith("?")) {
2103
+ if (factTerm in bindings) {
2104
+ if (bindings[factTerm] !== patternTerm) return void 0;
2105
+ } else bindings[factTerm] = patternTerm;
2106
+ } else if (patternTerm !== factTerm) return;
1808
2107
  }
1809
2108
  return bindings;
1810
2109
  }
@@ -5315,7 +5614,6 @@ var DefinitionBuilder = class {
5315
5614
  case "inferential":
5316
5615
  this.facts.collection = definition.facts;
5317
5616
  this.inferences.collection = definition.inferences;
5318
- break;
5319
5617
  }
5320
5618
  this.#envelope = this.#strip(definition);
5321
5619
  }
@@ -5981,6 +6279,7 @@ exports.isAggregation = isAggregation;
5981
6279
  exports.isBounds = isBounds;
5982
6280
  exports.isChainingStrategy = isChainingStrategy;
5983
6281
  exports.isCheck = isCheck;
6282
+ exports.isCheckResult = isCheckResult;
5984
6283
  exports.isComparison = isComparison;
5985
6284
  exports.isDefinition = isDefinition;
5986
6285
  exports.isDefinitionBuilder = isDefinitionBuilder;
@@ -5990,22 +6289,33 @@ exports.isFact = isFact;
5990
6289
  exports.isFactor = isFactor;
5991
6290
  exports.isFactorGroup = isFactorGroup;
5992
6291
  exports.isFactorRange = isFactorRange;
6292
+ exports.isFactorResult = isFactorResult;
5993
6293
  exports.isFieldPath = isFieldPath;
6294
+ exports.isGroupResult = isGroupResult;
5994
6295
  exports.isInference = isInference;
5995
6296
  exports.isInferentialDefinition = isInferentialDefinition;
6297
+ exports.isInferentialResult = isInferentialResult;
5996
6298
  exports.isLogicalDefinition = isLogicalDefinition;
5997
6299
  exports.isLogicalOperator = isLogicalOperator;
6300
+ exports.isLogicalResult = isLogicalResult;
5998
6301
  exports.isMathOperation = isMathOperation;
5999
6302
  exports.isNumberRecord = isNumberRecord;
6303
+ exports.isProofNode = isProofNode;
6000
6304
  exports.isQuantitativeDefinition = isQuantitativeDefinition;
6305
+ exports.isQuantitativeResult = isQuantitativeResult;
6001
6306
  exports.isReasonError = isReasonError;
6307
+ exports.isReasonResult = isReasonResult;
6308
+ exports.isReasonValidationResult = isReasonValidationResult;
6002
6309
  exports.isReasoning = isReasoning;
6310
+ exports.isResultFact = isResultFact;
6003
6311
  exports.isRule = isRule;
6312
+ exports.isRuleResult = isRuleResult;
6004
6313
  exports.isSource = isSource;
6005
6314
  exports.isSubject = isSubject;
6006
6315
  exports.isSubjectBuilder = isSubjectBuilder;
6007
6316
  exports.isSymbolicDefinition = isSymbolicDefinition;
6008
6317
  exports.isSymbolicExpression = isSymbolicExpression;
6318
+ exports.isSymbolicResult = isSymbolicResult;
6009
6319
  exports.isTransform = isTransform;
6010
6320
  exports.logicalDefinition = logicalDefinition;
6011
6321
  exports.lookupFactor = lookupFactor;