universal-physics-tensor 11.0.0 → 12.0.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/README.md +36 -34
- package/data/applied-cases.json +1892 -0
- package/data/applied-cases.schema.json +194 -0
- package/data/atlas/atlas.json +21 -21
- package/data/atlas/atlas.jsonld +1 -1
- package/data/atlas/diffusion.json +5 -5
- package/data/atlas/oscillators.json +7 -7
- package/data/atlas/waves.json +11 -11
- package/data/bridge-catalog.json +20 -4
- package/data/units.json +6 -25
- package/dist/atlas/benchmark/stats.d.ts.map +1 -1
- package/dist/atlas/benchmark/stats.js +6 -20
- package/dist/atlas/benchmark/stats.js.map +1 -1
- package/dist/atlas/physjs-entries.generated.d.ts +13 -4
- package/dist/atlas/physjs-entries.generated.d.ts.map +1 -1
- package/dist/atlas/physjs-entries.generated.js +15 -4
- package/dist/atlas/physjs-entries.generated.js.map +1 -1
- package/dist/atlas/physjs-reviewed.js +2 -2
- package/dist/atlas/physjs-reviewed.js.map +1 -1
- package/dist/cases/catalog-checks.d.ts +10 -0
- package/dist/cases/catalog-checks.d.ts.map +1 -0
- package/dist/cases/catalog-checks.js +241 -0
- package/dist/cases/catalog-checks.js.map +1 -0
- package/dist/cases/catalog.d.ts +83 -0
- package/dist/cases/catalog.d.ts.map +1 -0
- package/dist/cases/catalog.js +118 -0
- package/dist/cases/catalog.js.map +1 -0
- package/dist/cases/engine.d.ts +13 -0
- package/dist/cases/engine.d.ts.map +1 -0
- package/dist/cases/engine.js +179 -0
- package/dist/cases/engine.js.map +1 -0
- package/dist/cases/index.d.ts.map +1 -1
- package/dist/cases/index.js +5 -7
- package/dist/cases/index.js.map +1 -1
- package/dist/cases/methods.d.ts +215 -0
- package/dist/cases/methods.d.ts.map +1 -0
- package/dist/cases/methods.js +743 -0
- package/dist/cases/methods.js.map +1 -0
- package/dist/cases/types.d.ts +12 -0
- package/dist/cases/types.d.ts.map +1 -1
- package/dist/cases/types.js.map +1 -1
- package/dist/cli/args.d.ts +2 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/command.d.ts +3 -0
- package/dist/cli/command.d.ts.map +1 -1
- package/dist/cli/command.js.map +1 -1
- package/dist/cli/commands/_discovery-opts.d.ts +1 -0
- package/dist/cli/commands/_discovery-opts.d.ts.map +1 -1
- package/dist/cli/commands/_discovery-opts.js +1 -0
- package/dist/cli/commands/_discovery-opts.js.map +1 -1
- package/dist/cli/commands/discover.d.ts.map +1 -1
- package/dist/cli/commands/discover.js +116 -71
- package/dist/cli/commands/discover.js.map +1 -1
- package/dist/cli/commands/evaluate.js +2 -2
- package/dist/cli/commands/evaluate.js.map +1 -1
- package/dist/cli/commands/explain.d.ts.map +1 -1
- package/dist/cli/commands/explain.js +22 -2
- package/dist/cli/commands/explain.js.map +1 -1
- package/dist/cli/commands/ground.d.ts.map +1 -1
- package/dist/cli/commands/ground.js +6 -1
- package/dist/cli/commands/ground.js.map +1 -1
- package/dist/cli/commands/map.d.ts.map +1 -1
- package/dist/cli/commands/map.js +9 -6
- package/dist/cli/commands/map.js.map +1 -1
- package/dist/cli/determination.d.ts +1 -0
- package/dist/cli/determination.d.ts.map +1 -1
- package/dist/cli/determination.js.map +1 -1
- package/dist/cli/flag-help.d.ts +1 -0
- package/dist/cli/flag-help.d.ts.map +1 -1
- package/dist/cli/flag-help.js +1 -0
- package/dist/cli/flag-help.js.map +1 -1
- package/dist/cli/graphs.d.ts +2 -0
- package/dist/cli/graphs.d.ts.map +1 -1
- package/dist/cli/graphs.js +1 -0
- package/dist/cli/graphs.js.map +1 -1
- package/dist/cli/main.d.ts +1 -0
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +1 -0
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/output.d.ts +8 -0
- package/dist/cli/output.d.ts.map +1 -1
- package/dist/cli/output.js +8 -0
- package/dist/cli/output.js.map +1 -1
- package/dist/cli/statuses.d.ts.map +1 -1
- package/dist/cli/statuses.js +12 -2
- package/dist/cli/statuses.js.map +1 -1
- package/dist/cli/version.d.ts +1 -0
- package/dist/cli/version.d.ts.map +1 -1
- package/dist/cli/version.js +1 -0
- package/dist/cli/version.js.map +1 -1
- package/dist/cli-api.d.ts +2 -0
- package/dist/cli-api.d.ts.map +1 -1
- package/dist/cli-api.js +2 -0
- package/dist/cli-api.js.map +1 -1
- package/dist/composition/canonical-graph.d.ts +2 -2
- package/dist/composition/canonical-graph.js +2 -2
- package/dist/composition/canonical-graph.js.map +1 -1
- package/dist/composition/consequence.d.ts +15 -5
- package/dist/composition/consequence.d.ts.map +1 -1
- package/dist/composition/consequence.js +6 -4
- package/dist/composition/consequence.js.map +1 -1
- package/dist/composition/discovery.d.ts +78 -14
- package/dist/composition/discovery.d.ts.map +1 -1
- package/dist/composition/discovery.js +73 -23
- package/dist/composition/discovery.js.map +1 -1
- package/dist/composition/expr-eval.d.ts +1 -1
- package/dist/composition/expr-eval.d.ts.map +1 -1
- package/dist/composition/expr-eval.js +4 -4
- package/dist/composition/expr-eval.js.map +1 -1
- package/dist/composition/expr-simplify.d.ts +10 -14
- package/dist/composition/expr-simplify.d.ts.map +1 -1
- package/dist/composition/expr-simplify.js +49 -52
- package/dist/composition/expr-simplify.js.map +1 -1
- package/dist/composition/grounding.d.ts.map +1 -1
- package/dist/composition/grounding.js +19 -7
- package/dist/composition/grounding.js.map +1 -1
- package/dist/composition/mathts-quiet.d.ts +4 -6
- package/dist/composition/mathts-quiet.d.ts.map +1 -1
- package/dist/composition/mathts-quiet.js +4 -14
- package/dist/composition/mathts-quiet.js.map +1 -1
- package/dist/composition/own-equation-magnitude.d.ts +95 -0
- package/dist/composition/own-equation-magnitude.d.ts.map +1 -0
- package/dist/composition/own-equation-magnitude.js +270 -0
- package/dist/composition/own-equation-magnitude.js.map +1 -0
- package/dist/composition/probe/backend-protocol.d.ts +3 -0
- package/dist/composition/probe/backend-protocol.d.ts.map +1 -1
- package/dist/composition/probe/backend-protocol.js.map +1 -1
- package/dist/composition/probe/candidate-store.d.ts +1 -0
- package/dist/composition/probe/candidate-store.d.ts.map +1 -1
- package/dist/composition/probe/candidate-store.js +1 -0
- package/dist/composition/probe/candidate-store.js.map +1 -1
- package/dist/composition/probe/corpus.d.ts +4 -2
- package/dist/composition/probe/corpus.d.ts.map +1 -1
- package/dist/composition/probe/corpus.js +3 -3
- package/dist/composition/probe/corpus.js.map +1 -1
- package/dist/composition/probe/dataset.d.ts +1 -0
- package/dist/composition/probe/dataset.d.ts.map +1 -1
- package/dist/composition/probe/dataset.js.map +1 -1
- package/dist/composition/probe/experiment-design.d.ts +2 -0
- package/dist/composition/probe/experiment-design.d.ts.map +1 -1
- package/dist/composition/probe/experiment-design.js.map +1 -1
- package/dist/composition/probe/falsify.d.ts +2 -0
- package/dist/composition/probe/falsify.d.ts.map +1 -1
- package/dist/composition/probe/falsify.js.map +1 -1
- package/dist/composition/probe/fit.d.ts +1 -0
- package/dist/composition/probe/fit.d.ts.map +1 -1
- package/dist/composition/probe/fit.js.map +1 -1
- package/dist/composition/probe/generator.d.ts +3 -0
- package/dist/composition/probe/generator.d.ts.map +1 -1
- package/dist/composition/probe/generator.js +5 -6
- package/dist/composition/probe/generator.js.map +1 -1
- package/dist/composition/probe/limits.d.ts +1 -0
- package/dist/composition/probe/limits.d.ts.map +1 -1
- package/dist/composition/probe/limits.js.map +1 -1
- package/dist/composition/probe/pipeline.d.ts +5 -0
- package/dist/composition/probe/pipeline.d.ts.map +1 -1
- package/dist/composition/probe/pipeline.js +64 -21
- package/dist/composition/probe/pipeline.js.map +1 -1
- package/dist/composition/probe/power-law.d.ts.map +1 -1
- package/dist/composition/probe/power-law.js +3 -7
- package/dist/composition/probe/power-law.js.map +1 -1
- package/dist/composition/probe/problem.d.ts +1 -0
- package/dist/composition/probe/problem.d.ts.map +1 -1
- package/dist/composition/probe/problem.js.map +1 -1
- package/dist/composition/probe/residual.d.ts +1 -0
- package/dist/composition/probe/residual.d.ts.map +1 -1
- package/dist/composition/probe/residual.js +1 -0
- package/dist/composition/probe/residual.js.map +1 -1
- package/dist/composition/probe/run-manifest.d.ts +1 -0
- package/dist/composition/probe/run-manifest.d.ts.map +1 -1
- package/dist/composition/probe/run-manifest.js.map +1 -1
- package/dist/composition/probe/scalar-search.d.ts +50 -0
- package/dist/composition/probe/scalar-search.d.ts.map +1 -0
- package/dist/composition/probe/scalar-search.js +169 -0
- package/dist/composition/probe/scalar-search.js.map +1 -0
- package/dist/composition/probe/scoring.d.ts +1 -0
- package/dist/composition/probe/scoring.d.ts.map +1 -1
- package/dist/composition/probe/scoring.js.map +1 -1
- package/dist/composition/probe/study.d.ts +2 -2
- package/dist/composition/probe/study.d.ts.map +1 -1
- package/dist/composition/probe/study.js +6 -10
- package/dist/composition/probe/study.js.map +1 -1
- package/dist/composition/probe/t-tail.d.ts +3 -4
- package/dist/composition/probe/t-tail.d.ts.map +1 -1
- package/dist/composition/probe/t-tail.js +7 -10
- package/dist/composition/probe/t-tail.js.map +1 -1
- package/dist/composition/proposed-bridges.d.ts +11 -2
- package/dist/composition/proposed-bridges.d.ts.map +1 -1
- package/dist/composition/proposed-bridges.js +7 -5
- package/dist/composition/proposed-bridges.js.map +1 -1
- package/dist/composition/rational-exponent.d.ts +2 -2
- package/dist/composition/rational-exponent.d.ts.map +1 -1
- package/dist/composition/rational-exponent.js +4 -4
- package/dist/composition/rational-exponent.js.map +1 -1
- package/dist/composition/representative-values.d.ts.map +1 -1
- package/dist/composition/representative-values.js +6 -0
- package/dist/composition/representative-values.js.map +1 -1
- package/dist/composition/retrodiction.d.ts +15 -0
- package/dist/composition/retrodiction.d.ts.map +1 -1
- package/dist/composition/retrodiction.js +10 -3
- package/dist/composition/retrodiction.js.map +1 -1
- package/dist/composition/user-equation.d.ts +1 -0
- package/dist/composition/user-equation.d.ts.map +1 -1
- package/dist/composition/user-equation.js +1 -0
- package/dist/composition/user-equation.js.map +1 -1
- package/dist/core/constants.d.ts +12 -11
- package/dist/core/constants.d.ts.map +1 -1
- package/dist/core/constants.js +24 -21
- package/dist/core/constants.js.map +1 -1
- package/dist/diff/bridge-ast-gradient.d.ts +27 -23
- package/dist/diff/bridge-ast-gradient.d.ts.map +1 -1
- package/dist/diff/bridge-ast-gradient.js +75 -173
- package/dist/diff/bridge-ast-gradient.js.map +1 -1
- package/dist/dimensional/ast-types.d.ts +15 -0
- package/dist/dimensional/ast-types.d.ts.map +1 -1
- package/dist/dimensional/ast-types.js.map +1 -1
- package/dist/dimensional/curvature-composite.d.ts +1 -1
- package/dist/dimensional/curvature-composite.js.map +1 -1
- package/dist/dimensional/exact-scale.d.ts +41 -11
- package/dist/dimensional/exact-scale.d.ts.map +1 -1
- package/dist/dimensional/exact-scale.js +115 -123
- package/dist/dimensional/exact-scale.js.map +1 -1
- package/dist/dimensional/mathts-unit-delegation.d.ts +29 -0
- package/dist/dimensional/mathts-unit-delegation.d.ts.map +1 -0
- package/dist/dimensional/mathts-unit-delegation.js +187 -0
- package/dist/dimensional/mathts-unit-delegation.js.map +1 -0
- package/dist/dimensional/mathts-unit-wrapper.d.ts +33 -0
- package/dist/dimensional/mathts-unit-wrapper.d.ts.map +1 -0
- package/dist/dimensional/mathts-unit-wrapper.js +190 -0
- package/dist/dimensional/mathts-unit-wrapper.js.map +1 -0
- package/dist/dimensional/scalar-lowering.d.ts +21 -0
- package/dist/dimensional/scalar-lowering.d.ts.map +1 -0
- package/dist/dimensional/scalar-lowering.js +45 -0
- package/dist/dimensional/scalar-lowering.js.map +1 -0
- package/dist/dimensional/unit-data.d.ts +5 -1
- package/dist/dimensional/unit-data.d.ts.map +1 -1
- package/dist/dimensional/unit-data.js +28 -4
- package/dist/dimensional/unit-data.js.map +1 -1
- package/dist/dimensional/units.d.ts +2 -0
- package/dist/dimensional/units.d.ts.map +1 -1
- package/dist/dimensional/units.js +59 -3
- package/dist/dimensional/units.js.map +1 -1
- package/dist/dimensional/validator.d.ts +2 -0
- package/dist/dimensional/validator.d.ts.map +1 -1
- package/dist/dimensional/validator.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/numerical/connection-lowering-helpers.d.ts +3 -1
- package/dist/numerical/connection-lowering-helpers.d.ts.map +1 -1
- package/dist/numerical/connection-lowering-helpers.js +11 -15
- package/dist/numerical/connection-lowering-helpers.js.map +1 -1
- package/dist/numerical/pderiv.d.ts.map +1 -1
- package/dist/numerical/pderiv.js +2 -6
- package/dist/numerical/pderiv.js.map +1 -1
- package/dist/numerical/quadrature.js +3 -3
- package/dist/numerical/quadrature.js.map +1 -1
- package/dist/numerical/statistics.js +1 -1
- package/dist/numerical/statistics.js.map +1 -1
- package/dist/numerical/strides.d.ts +3 -2
- package/dist/numerical/strides.d.ts.map +1 -1
- package/dist/numerical/strides.js +3 -10
- package/dist/numerical/strides.js.map +1 -1
- package/package.json +9 -12
- package/dist/cases/brownian-sphere.d.ts +0 -68
- package/dist/cases/brownian-sphere.d.ts.map +0 -1
- package/dist/cases/brownian-sphere.js +0 -355
- package/dist/cases/brownian-sphere.js.map +0 -1
- package/dist/cases/damped-resonator.d.ts +0 -23
- package/dist/cases/damped-resonator.d.ts.map +0 -1
- package/dist/cases/damped-resonator.js +0 -221
- package/dist/cases/damped-resonator.js.map +0 -1
- package/dist/cases/kepler-rv.d.ts +0 -13
- package/dist/cases/kepler-rv.d.ts.map +0 -1
- package/dist/cases/kepler-rv.js +0 -173
- package/dist/cases/kepler-rv.js.map +0 -1
- package/dist/cases/lumped-cooling.d.ts +0 -51
- package/dist/cases/lumped-cooling.d.ts.map +0 -1
- package/dist/cases/lumped-cooling.js +0 -259
- package/dist/cases/lumped-cooling.js.map +0 -1
- package/dist/cases/resistor-noise.d.ts +0 -14
- package/dist/cases/resistor-noise.d.ts.map +0 -1
- package/dist/cases/resistor-noise.js +0 -215
- package/dist/cases/resistor-noise.js.map +0 -1
- package/dist/cases/skin-depth.d.ts +0 -17
- package/dist/cases/skin-depth.d.ts.map +0 -1
- package/dist/cases/skin-depth.js +0 -170
- package/dist/cases/skin-depth.js.map +0 -1
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Symbolic simplification of a scalar `ExprNode`
|
|
3
|
-
*
|
|
2
|
+
* Symbolic simplification of a scalar `ExprNode` through MathTS, a supplement
|
|
3
|
+
* to symbolic composition.
|
|
4
4
|
*
|
|
5
5
|
* Composing two bridges' symbolic forms leaves an UNSIMPLIFIED AST — CT-1 is
|
|
6
6
|
* `k_B·(ℏc³/8πG·mass·k_B)·ln2`, with `k_B` uncancelled. This folds it to the
|
|
7
7
|
* canonical `ℏc³·ln2/(8πG·mass)` using `@danielsimonjr/mathts-functions`'
|
|
8
|
-
* `simplify
|
|
8
|
+
* `simplify`, a required dependency.
|
|
9
9
|
*
|
|
10
10
|
* Pipeline (Adam+Eve-vetted — docs/planning/v0.12.0-Symbolic-Simplification-
|
|
11
11
|
* Design.md): GENSYM every non-exponent leaf to a mathjs-safe identifier
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* 3. numeric — `evalExpr` agrees over ≥2 finite synthesized probes at
|
|
20
20
|
* rel tol 1e-9 (Adam CRITICAL-2 / EVE-C).
|
|
21
21
|
* A representable result that DISAGREES dimensionally/numerically THROWS (a
|
|
22
|
-
* bug to surface); anything we cannot represent
|
|
22
|
+
* bug to surface); anything we cannot represent or verify degrades to a
|
|
23
23
|
* graceful no-op (return the original, `simplified:false`).
|
|
24
24
|
*
|
|
25
25
|
* INTERNAL — surfaced via `upt symbolic --simplify`.
|
|
@@ -34,7 +34,8 @@ import { forEachScalarLeaf, isDecimalLiteral } from '../dimensional/ast-leaves.j
|
|
|
34
34
|
import { isRegisteredConstant } from '../dimensional/symbolic-constants.js';
|
|
35
35
|
import { makeObservable } from './compose-symbolic.js';
|
|
36
36
|
import { renderScalarLeaf } from './mathts-scalar-symbols.js';
|
|
37
|
-
import {
|
|
37
|
+
import { parse as mathtsParse, simplify as mathtsSimplify } from '@danielsimonjr/mathts-functions';
|
|
38
|
+
import { quietlySync } from './mathts-quiet.js';
|
|
38
39
|
/** A simplification completed but produced a dimensionally/numerically wrong
|
|
39
40
|
* result (a real bug — not a graceful no-op). @internal */
|
|
40
41
|
class SimplificationError extends Error {
|
|
@@ -48,37 +49,29 @@ class SimplificationError extends Error {
|
|
|
48
49
|
class Unsupported extends Error {
|
|
49
50
|
}
|
|
50
51
|
// ---------------------------------------------------------------------------
|
|
51
|
-
//
|
|
52
|
-
// formula-registry.ts).
|
|
52
|
+
// The MathTS simplifier: a static import, bound once after a smoke test.
|
|
53
53
|
// ---------------------------------------------------------------------------
|
|
54
54
|
let cached;
|
|
55
|
-
/**
|
|
56
|
-
*
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
// the smoke below is that first use. Later calls run with the console
|
|
63
|
-
// untouched.
|
|
64
|
-
return await quietly(async () => {
|
|
65
|
-
const mod = (await import('@danielsimonjr/mathts-functions'));
|
|
66
|
-
if (typeof mod.parse !== 'function' || typeof mod.simplify !== 'function') {
|
|
67
|
-
return null;
|
|
68
|
-
}
|
|
69
|
-
// Smoke: g0 must cancel out of (g0)*((g1)/(g0)) → only g1 remains.
|
|
70
|
-
const s = mod.simplify(mod.parse('(g0)*((g1)/(g0))'));
|
|
71
|
-
const names = new Set();
|
|
72
|
-
collectMathSymbols(s, names);
|
|
73
|
-
return names.size === 1 && names.has('g1') ? mod : null;
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
catch {
|
|
77
|
-
return null;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
55
|
+
/**
|
|
56
|
+
* `parse` and `simplify`, bound once after a smoke test that `simplify`
|
|
57
|
+
* CANCELS (`(g0)*((g1)/(g0))` must come back as `g1` alone). The smoke is the
|
|
58
|
+
* first use, so it runs inside the one console window (`mathts-quiet.ts`).
|
|
59
|
+
* MathTS is a required dependency, so a failed smoke is a defect of that
|
|
60
|
+
* dependency and throws; it is not read as an absent simplifier.
|
|
61
|
+
*/
|
|
80
62
|
function loadSimplifier() {
|
|
81
|
-
cached
|
|
63
|
+
if (cached !== undefined)
|
|
64
|
+
return cached;
|
|
65
|
+
const mod = {
|
|
66
|
+
parse: (text) => mathtsParse(text),
|
|
67
|
+
simplify: (node) => mathtsSimplify(node),
|
|
68
|
+
};
|
|
69
|
+
const names = new Set();
|
|
70
|
+
quietlySync(() => collectMathSymbols(mod.simplify(mod.parse('(g0)*((g1)/(g0))')), names));
|
|
71
|
+
if (names.size !== 1 || !names.has('g1')) {
|
|
72
|
+
throw new Error(`expr-simplify: MathTS simplify did not cancel g0 in the smoke test (left ${[...names].join(', ')})`);
|
|
73
|
+
}
|
|
74
|
+
cached = mod;
|
|
82
75
|
return cached;
|
|
83
76
|
}
|
|
84
77
|
function collectMathSymbols(n, out) {
|
|
@@ -113,6 +106,13 @@ export function renderGensym(expr, gensymOf, meta) {
|
|
|
113
106
|
}
|
|
114
107
|
if (expr.args.length === 0)
|
|
115
108
|
throw new Unsupported();
|
|
109
|
+
if (expr.args.length === 1) {
|
|
110
|
+
const arg = renderGensym(expr.args[0], gensymOf, meta);
|
|
111
|
+
if (expr.op === '-')
|
|
112
|
+
return `(-(${arg}))`;
|
|
113
|
+
if (expr.op === '+')
|
|
114
|
+
return `(${arg})`;
|
|
115
|
+
}
|
|
116
116
|
const parts = expr.args.map((a) => `(${renderGensym(a, gensymOf, meta)})`);
|
|
117
117
|
return `(${parts.join(expr.op)})`;
|
|
118
118
|
}
|
|
@@ -160,10 +160,12 @@ function walkBack(node, meta) {
|
|
|
160
160
|
args: [walkBack(args[0], meta), lit(exp.value)],
|
|
161
161
|
};
|
|
162
162
|
}
|
|
163
|
-
if (
|
|
163
|
+
if (op === '-' && args.length === 1) {
|
|
164
164
|
// unary minus → (-1) * arg
|
|
165
165
|
return { kind: 'op', op: '*', args: [lit(-1), walkBack(args[0], meta)] };
|
|
166
166
|
}
|
|
167
|
+
if (op === '+' && args.length === 1)
|
|
168
|
+
return walkBack(args[0], meta); // unary plus is the argument
|
|
167
169
|
if (op === '+' || op === '-' || op === '*' || op === '/') {
|
|
168
170
|
if (args.length < 2)
|
|
169
171
|
throw new Unsupported();
|
|
@@ -215,46 +217,41 @@ function numericAgreement(original, candidate) {
|
|
|
215
217
|
return finiteProbes >= 2 ? 'agree' : 'insufficient';
|
|
216
218
|
}
|
|
217
219
|
/**
|
|
218
|
-
* Whether the
|
|
219
|
-
* smoke test.
|
|
220
|
-
*
|
|
221
|
-
*
|
|
222
|
-
* and when it is present but could not reduce the expression, so a caller that
|
|
223
|
-
* must report WHY nothing happened (the atlas witness runner's `peer-absent`
|
|
224
|
-
* versus `not-simplified`) needs this separate signal. Shares the same cached
|
|
225
|
-
* detection, so it costs nothing after the first call.
|
|
220
|
+
* Whether the MathTS simplifier is usable. MathTS is a required dependency, so
|
|
221
|
+
* the answer is true; a simplifier that fails its smoke test throws instead.
|
|
222
|
+
* The atlas witness runner reads it to choose between the simplifier and its
|
|
223
|
+
* `peer-absent` path, which a caller still reaches by passing `null`.
|
|
226
224
|
*
|
|
227
225
|
* @internal
|
|
228
226
|
*/
|
|
229
227
|
export async function isSimplifierAvailable() {
|
|
230
|
-
|
|
228
|
+
loadSimplifier();
|
|
229
|
+
return true;
|
|
231
230
|
}
|
|
232
231
|
/**
|
|
233
232
|
* Simplify a scalar `ExprNode` via MathTS, guarded. Returns the original
|
|
234
|
-
* unchanged (`simplified:false`) when the
|
|
235
|
-
*
|
|
233
|
+
* unchanged (`simplified:false`) when the result cannot be represented or
|
|
234
|
+
* verified; THROWS {@link SimplificationError} only when a
|
|
236
235
|
* representable result disagrees dimensionally/numerically. See module docs.
|
|
237
236
|
*
|
|
238
237
|
* @internal
|
|
239
238
|
*/
|
|
240
239
|
export async function simplifyExpr(expr) {
|
|
241
|
-
const mod =
|
|
242
|
-
if (!mod)
|
|
243
|
-
return { expr, simplified: false };
|
|
240
|
+
const mod = loadSimplifier();
|
|
244
241
|
const gensymOf = new Map();
|
|
245
242
|
const meta = new Map();
|
|
246
243
|
let candidate;
|
|
247
244
|
try {
|
|
248
245
|
const str = renderGensym(expr, gensymOf, meta);
|
|
249
|
-
//
|
|
246
|
+
// MathTS can THROW on some forms (e.g. a known mathts `simplify` BigInt
|
|
250
247
|
// bug on nested `a/(b/c²)`); that, like an unsupported node, is a graceful
|
|
251
|
-
// no-op, not an error. The console is not touched here: the
|
|
252
|
-
//
|
|
248
|
+
// no-op, not an error. The console is not touched here: the first use
|
|
249
|
+
// already ran inside `loadSimplifier`'s window.
|
|
253
250
|
const simplifiedNode = mod.simplify(mod.parse(str));
|
|
254
251
|
candidate = walkBack(simplifiedNode, meta);
|
|
255
252
|
}
|
|
256
253
|
catch {
|
|
257
|
-
return { expr, simplified: false }; // unsupported / unrepresentable /
|
|
254
|
+
return { expr, simplified: false }; // unsupported / unrepresentable / MathTS threw
|
|
258
255
|
}
|
|
259
256
|
// Guard 1 — dimensional. Inability to validate ⇒ no-op; a CHANGED dimension
|
|
260
257
|
// is a representable disagreement ⇒ throw.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expr-simplify.js","sourceRoot":"","sources":["../../src/composition/expr-simplify.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Symbolic simplification of a scalar `ExprNode` via MathTS (v0.12 — optional\n * supplement to symbolic composition).\n *\n * Composing two bridges' symbolic forms leaves an UNSIMPLIFIED AST — CT-1 is\n * `k_B·(ℏc³/8πG·mass·k_B)·ln2`, with `k_B` uncancelled. This folds it to the\n * canonical `ℏc³·ln2/(8πG·mass)` using `@danielsimonjr/mathts-functions`'\n * `simplify` (the same OPTIONAL peer the Path-A formula parser loads).\n *\n * Pipeline (Adam+Eve-vetted — docs/planning/v0.12.0-Symbolic-Simplification-\n * Design.md): GENSYM every non-exponent leaf to a mathjs-safe identifier\n * (shared by name, so repeated leaves cancel), render FULLY-PARENTHESIZED\n * (EVE-A — no precedence ambiguity), `parse`+`simplify`, walk the result back\n * (un-gensym, INTEGER-exponent-strict — EVE/Adam HIGH-1). Three guards make a\n * black-box CAS safe to trust:\n * 1. dimensional — `validate(simplified)` dim `equals` the original's;\n * 2. structural — non-numeric symbols of the result ⊆ those of the original\n * (no leaf invented — Adam HIGH-2 / EVE-B);\n * 3. numeric — `evalExpr` agrees over ≥2 finite synthesized probes at\n * rel tol 1e-9 (Adam CRITICAL-2 / EVE-C).\n * A representable result that DISAGREES dimensionally/numerically THROWS (a\n * bug to surface); anything we cannot represent / verify / load degrades to a\n * graceful no-op (return the original, `simplified:false`).\n *\n * INTERNAL — surfaced via `upt symbolic --simplify`.\n *\n * @module composition/expr-simplify\n */\n\nimport type { ExprNode } from '../dimensional/validator.js';\nimport { validate } from '../dimensional/validator.js';\nimport { equals } from '../dimensional/algebra.js';\nimport type { Dimension } from '../dimensional/types.js';\nimport { DIMENSIONLESS } from '../dimensional/types.js';\nimport { evalExpr } from './expr-eval.js';\nimport { forEachScalarLeaf, isDecimalLiteral } from '../dimensional/ast-leaves.js';\nimport { isRegisteredConstant } from '../dimensional/symbolic-constants.js';\nimport type { Observable } from './compose-symbolic.js';\nimport { makeObservable } from './compose-symbolic.js';\nimport { renderScalarLeaf } from './mathts-scalar-symbols.js';\nimport { quietly } from './mathts-quiet.js';\n\n/** A simplification completed but produced a dimensionally/numerically wrong\n * result (a real bug — not a graceful no-op). @internal */\nclass SimplificationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'SimplificationError';\n }\n}\n\n/** The bits of a MathTS (mathjs-style) AST node the walk-back reads — pinned\n * + runtime-verified (Adam CRITICAL-1). */\ninterface MathNode {\n readonly type?: string;\n readonly op?: string;\n readonly name?: string;\n readonly value?: unknown;\n readonly args?: MathNode[];\n readonly content?: MathNode;\n toString(): string;\n}\ninterface MathtsSimplifyModule {\n parse(expr: string): MathNode;\n simplify(node: MathNode): MathNode;\n}\n\n/** Thrown internally when a node cannot be rendered/walked — caught and turned\n * into a graceful no-op (never escapes the module). */\nclass Unsupported extends Error {}\n\n// ---------------------------------------------------------------------------\n// Optional-peer load — cache + quietly + simplify-smoke (mirrors\n// formula-registry.ts).\n// ---------------------------------------------------------------------------\n\nlet cached: Promise<MathtsSimplifyModule | null> | undefined;\n\n/** Load + smoke-test the peer. A peer with `parse` but a missing/broken\n * `simplify` (it must actually CANCEL) is rejected → null (graceful no-op). */\nasync function detect(): Promise<MathtsSimplifyModule | null> {\n try {\n // Import AND smoke-test inside the ONE suppression window this module\n // opens (`mathts-quiet.ts` states the invariant): the WASM-fallback\n // chatter fires lazily on first parse/simplify, not only at import, and\n // the smoke below is that first use. Later calls run with the console\n // untouched.\n return await quietly(async () => {\n const mod = (await import(\n '@danielsimonjr/mathts-functions'\n )) as unknown as MathtsSimplifyModule;\n if (typeof mod.parse !== 'function' || typeof mod.simplify !== 'function') {\n return null;\n }\n // Smoke: g0 must cancel out of (g0)*((g1)/(g0)) → only g1 remains.\n const s = mod.simplify(mod.parse('(g0)*((g1)/(g0))'));\n const names = new Set<string>();\n collectMathSymbols(s, names);\n return names.size === 1 && names.has('g1') ? mod : null;\n });\n } catch {\n return null;\n }\n}\n\nfunction loadSimplifier(): Promise<MathtsSimplifyModule | null> {\n cached ??= detect();\n return cached;\n}\n\nfunction collectMathSymbols(n: MathNode, out: Set<string>): void {\n if (n.type === 'SymbolNode' && n.name) out.add(n.name);\n if (n.content) collectMathSymbols(n.content, out);\n for (const a of n.args ?? []) collectMathSymbols(a, out);\n}\n\n// ---------------------------------------------------------------------------\n// ExprNode → gensym string (fully parenthesized) and back.\n// ---------------------------------------------------------------------------\n\n/** The leaf a gensym stands for: its name and dimension. @internal */\nexport interface LeafMeta {\n readonly name: string;\n readonly dim: Dimension;\n}\n\nconst isLiteral = isDecimalLiteral;\n\n/**\n * Render a scalar ExprNode to a mathjs-safe, fully-parenthesized string,\n * gensym'ing each non-literal leaf by NAME (so repeats share an identifier\n * and can cancel). Throws on a non-scalar arm and on a non-literal exponent;\n * `algebraic-equivalence.ts` renders both sides of a quotient through one\n * gensym table with it.\n *\n * @internal\n */\nexport function renderGensym(\n expr: ExprNode,\n gensymOf: Map<string, string>,\n meta: Map<string, LeafMeta>,\n): string {\n switch (expr.kind) {\n case 'symbol':\n return renderScalarLeaf(expr, gensymOf, meta);\n case 'op': {\n if (expr.op === '^') {\n const exp = expr.args[1];\n if (!exp || exp.kind !== 'symbol' || !isLiteral(exp.name)) {\n throw new Unsupported();\n }\n return `(${renderGensym(expr.args[0], gensymOf, meta)})^${Number(exp.name)}`;\n }\n if (expr.args.length === 0) throw new Unsupported();\n const parts = expr.args.map((a) => `(${renderGensym(a, gensymOf, meta)})`);\n return `(${parts.join(expr.op)})`;\n }\n default:\n throw new Unsupported(); // integral / derivative / tensor arms\n }\n}\n\nconst lit = (v: number): ExprNode => ({ kind: 'symbol', name: String(v), dim: DIMENSIONLESS });\n\n/** Walk a simplified MathTS node back to an ExprNode, un-gensym'ing leaves and\n * rejecting anything outside UPT's integer-exponent scalar model (→ throws\n * `Unsupported`, a graceful no-op). */\nfunction walkBack(node: MathNode, meta: Map<string, LeafMeta>): ExprNode {\n switch (node.type) {\n case 'ConstantNode': {\n if (typeof node.value !== 'number' || !Number.isFinite(node.value)) {\n throw new Unsupported();\n }\n return lit(node.value);\n }\n case 'SymbolNode': {\n const m = node.name !== undefined ? meta.get(node.name) : undefined;\n if (!m) throw new Unsupported(); // a symbol we did not issue\n return { kind: 'symbol', name: m.name, dim: m.dim };\n }\n case 'ParenthesisNode':\n if (!node.content) throw new Unsupported();\n return walkBack(node.content, meta);\n case 'OperatorNode': {\n const op = node.op;\n const args = node.args ?? [];\n if (op === '^') {\n if (args.length !== 2) throw new Unsupported();\n const exp = args[1];\n if (\n exp.type !== 'ConstantNode' ||\n typeof exp.value !== 'number' ||\n !Number.isInteger(exp.value)\n ) {\n throw new Unsupported(); // non-integer exponent — not in ℤ⁷ model\n }\n return {\n kind: 'op',\n op: '^',\n args: [walkBack(args[0], meta), lit(exp.value)],\n };\n }\n if ((op === '+' || op === '-') && args.length === 1) {\n // unary minus → (-1) * arg\n return { kind: 'op', op: '*', args: [lit(-1), walkBack(args[0], meta)] };\n }\n if (op === '+' || op === '-' || op === '*' || op === '/') {\n if (args.length < 2) throw new Unsupported();\n return { kind: 'op', op, args: args.map((a) => walkBack(a, meta)) };\n }\n throw new Unsupported();\n }\n default:\n throw new Unsupported(); // FunctionNode (sqrt/cbrt/…) etc.\n }\n}\n\n// ---------------------------------------------------------------------------\n// Guards.\n// ---------------------------------------------------------------------------\n\nfunction symbolNames(expr: ExprNode, out: string[] = []): string[] {\n forEachScalarLeaf(expr, (leaf) => out.push(leaf.name), { integral: 'over+integrand', derivative: true });\n return out;\n}\n\nconst nonNumericSymbols = (expr: ExprNode): string[] =>\n symbolNames(expr).filter((n) => !isLiteral(n));\n\nconst PROBE_VALUES = [2.3, 3.7, 5.1, 7.9, 11.3, 13.1, 17.9, 19.3];\nconst PROBE_MULTIPLIERS = [1, 1.7, 0.41, 2.9];\n\n/** Numeric agreement of `original` and `candidate` over synthesized probes.\n * Free (non-constant) leaves get distinct, mutually-incommensurate values to\n * avoid accidental cancellation. <2 finite probes ⇒ 'insufficient' (cannot\n * verify — EVE-C). */\nfunction numericAgreement(\n original: ExprNode,\n candidate: ExprNode,\n): 'agree' | 'disagree' | 'insufficient' {\n const leaves = [...new Set(nonNumericSymbols(original))].filter(\n (n) => !isRegisteredConstant(n),\n );\n let finiteProbes = 0;\n for (const mult of PROBE_MULTIPLIERS) {\n const values: Record<string, number> = {};\n leaves.forEach((leaf, i) => {\n values[leaf] = PROBE_VALUES[i % PROBE_VALUES.length] * mult;\n });\n let a: number;\n let b: number;\n try {\n a = evalExpr(original, values);\n b = evalExpr(candidate, values);\n } catch {\n continue; // a probe drove evalExpr non-finite — skip it\n }\n if (!Number.isFinite(a) || !Number.isFinite(b)) continue;\n finiteProbes++;\n if (Math.abs(a - b) / Math.abs(b || 1) > 1e-9) return 'disagree';\n }\n return finiteProbes >= 2 ? 'agree' : 'insufficient';\n}\n\n// ---------------------------------------------------------------------------\n// Public entry points.\n// ---------------------------------------------------------------------------\n\n/** The result of attempting to simplify an expression. */\ninterface SimplifyResult {\n readonly expr: ExprNode;\n /** True iff MathTS was present AND produced a guard-passing, distinct form. */\n readonly simplified: boolean;\n}\n\n/**\n * Whether the optional MathTS simplifier peer is installed AND passes its\n * smoke test.\n *\n * {@link simplifyExpr} returns `simplified: false` both when the peer is absent\n * and when it is present but could not reduce the expression, so a caller that\n * must report WHY nothing happened (the atlas witness runner's `peer-absent`\n * versus `not-simplified`) needs this separate signal. Shares the same cached\n * detection, so it costs nothing after the first call.\n *\n * @internal\n */\nexport async function isSimplifierAvailable(): Promise<boolean> {\n return (await loadSimplifier()) !== null;\n}\n\n/**\n * Simplify a scalar `ExprNode` via MathTS, guarded. Returns the original\n * unchanged (`simplified:false`) when the peer is absent or the result cannot\n * be represented/verified; THROWS {@link SimplificationError} only when a\n * representable result disagrees dimensionally/numerically. See module docs.\n *\n * @internal\n */\nexport async function simplifyExpr(expr: ExprNode): Promise<SimplifyResult> {\n const mod = await loadSimplifier();\n if (!mod) return { expr, simplified: false };\n\n const gensymOf = new Map<string, string>();\n const meta = new Map<string, LeafMeta>();\n let candidate: ExprNode;\n try {\n const str = renderGensym(expr, gensymOf, meta);\n // The peer can THROW on some forms (e.g. a known mathts `simplify` BigInt\n // bug on nested `a/(b/c²)`); that, like an unsupported node, is a graceful\n // no-op, not an error. The console is not touched here: the peer's first\n // use already ran inside `detect`'s load window.\n const simplifiedNode = mod.simplify(mod.parse(str));\n candidate = walkBack(simplifiedNode, meta);\n } catch {\n return { expr, simplified: false }; // unsupported / unrepresentable / peer threw\n }\n\n // Guard 1 — dimensional. Inability to validate ⇒ no-op; a CHANGED dimension\n // is a representable disagreement ⇒ throw.\n const origDim = validate(expr).inferredDimension;\n // A literal ZERO carries every dimension: `x − x` with `x` a length is a zero\n // LENGTH, but the CAS hands back a bare dimensionless `0`. Re-stamp it with\n // the original dimension, or this guard would reject every exact\n // cancellation of a dimensioned expression as a \"changed dimension\".\n if (\n origDim !== null &&\n candidate.kind === 'symbol' &&\n candidate.name.trim() !== '' &&\n Number(candidate.name) === 0\n ) {\n candidate = { kind: 'symbol', name: '0', dim: origDim };\n }\n const newResult = validate(candidate);\n if (origDim === null || !newResult.ok || newResult.inferredDimension === null) {\n return { expr, simplified: false };\n }\n if (!equals(origDim, newResult.inferredDimension)) {\n throw new SimplificationError(\n `simplifyExpr: the simplified form changed dimension — a CAS or ` +\n `walk-back error.`,\n );\n }\n\n // Guard 2 — structural subset (no non-numeric leaf invented).\n const origSyms = new Set(nonNumericSymbols(expr));\n for (const s of nonNumericSymbols(candidate)) {\n if (!origSyms.has(s)) return { expr, simplified: false }; // suspicious ⇒ no-op\n }\n\n // Guard 3 — numeric agreement.\n const verdict = numericAgreement(expr, candidate);\n if (verdict === 'disagree') {\n throw new SimplificationError(\n `simplifyExpr: the simplified form disagrees numerically with the ` +\n `original — a CAS or walk-back error.`,\n );\n }\n if (verdict === 'insufficient') return { expr, simplified: false };\n\n // Identical-structure ⇒ nothing gained; report not simplified.\n const changed = symbolNames(candidate).length !== symbolNames(expr).length;\n return { expr: candidate, simplified: changed };\n}\n\n/**\n * Simplify a composed {@link Observable}: returns a freshly-RECONSTRUCTED\n * Observable (new strict `evaluate` closure over the simplified `expr` +\n * recomputed `leaves`) when simplification succeeds, else the original\n * unchanged. See module docs.\n *\n * @internal\n */\nexport async function simplifyObservable(obs: Observable): Promise<Observable> {\n const { expr, simplified } = await simplifyExpr(obs.expr);\n if (!simplified) return obs;\n return makeObservable(obs.name, obs.symbol, obs.dim, expr);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"expr-simplify.js","sourceRoot":"","sources":["../../src/composition/expr-simplify.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Symbolic simplification of a scalar `ExprNode` through MathTS, a supplement\n * to symbolic composition.\n *\n * Composing two bridges' symbolic forms leaves an UNSIMPLIFIED AST — CT-1 is\n * `k_B·(ℏc³/8πG·mass·k_B)·ln2`, with `k_B` uncancelled. This folds it to the\n * canonical `ℏc³·ln2/(8πG·mass)` using `@danielsimonjr/mathts-functions`'\n * `simplify`, a required dependency.\n *\n * Pipeline (Adam+Eve-vetted — docs/planning/v0.12.0-Symbolic-Simplification-\n * Design.md): GENSYM every non-exponent leaf to a mathjs-safe identifier\n * (shared by name, so repeated leaves cancel), render FULLY-PARENTHESIZED\n * (EVE-A — no precedence ambiguity), `parse`+`simplify`, walk the result back\n * (un-gensym, INTEGER-exponent-strict — EVE/Adam HIGH-1). Three guards make a\n * black-box CAS safe to trust:\n * 1. dimensional — `validate(simplified)` dim `equals` the original's;\n * 2. structural — non-numeric symbols of the result ⊆ those of the original\n * (no leaf invented — Adam HIGH-2 / EVE-B);\n * 3. numeric — `evalExpr` agrees over ≥2 finite synthesized probes at\n * rel tol 1e-9 (Adam CRITICAL-2 / EVE-C).\n * A representable result that DISAGREES dimensionally/numerically THROWS (a\n * bug to surface); anything we cannot represent or verify degrades to a\n * graceful no-op (return the original, `simplified:false`).\n *\n * INTERNAL — surfaced via `upt symbolic --simplify`.\n *\n * @module composition/expr-simplify\n */\n\nimport type { ExprNode } from '../dimensional/validator.js';\nimport { validate } from '../dimensional/validator.js';\nimport { equals } from '../dimensional/algebra.js';\nimport type { Dimension } from '../dimensional/types.js';\nimport { DIMENSIONLESS } from '../dimensional/types.js';\nimport { evalExpr } from './expr-eval.js';\nimport { forEachScalarLeaf, isDecimalLiteral } from '../dimensional/ast-leaves.js';\nimport { isRegisteredConstant } from '../dimensional/symbolic-constants.js';\nimport type { Observable } from './compose-symbolic.js';\nimport { makeObservable } from './compose-symbolic.js';\nimport { renderScalarLeaf } from './mathts-scalar-symbols.js';\nimport { parse as mathtsParse, simplify as mathtsSimplify } from '@danielsimonjr/mathts-functions';\nimport { quietlySync } from './mathts-quiet.js';\n\n/** A simplification completed but produced a dimensionally/numerically wrong\n * result (a real bug — not a graceful no-op). @internal */\nclass SimplificationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'SimplificationError';\n }\n}\n\n/** The bits of a MathTS (mathjs-style) AST node the walk-back reads — pinned\n * + runtime-verified (Adam CRITICAL-1). */\ninterface MathNode {\n readonly type?: string;\n readonly op?: string;\n readonly name?: string;\n readonly value?: unknown;\n readonly args?: MathNode[];\n readonly content?: MathNode;\n toString(): string;\n}\ninterface MathtsSimplifyModule {\n parse(expr: string): MathNode;\n simplify(node: MathNode): MathNode;\n}\n\n/** Thrown internally when a node cannot be rendered/walked — caught and turned\n * into a graceful no-op (never escapes the module). */\nclass Unsupported extends Error {}\n\n// ---------------------------------------------------------------------------\n// The MathTS simplifier: a static import, bound once after a smoke test.\n// ---------------------------------------------------------------------------\n\nlet cached: MathtsSimplifyModule | undefined;\n\n/**\n * `parse` and `simplify`, bound once after a smoke test that `simplify`\n * CANCELS (`(g0)*((g1)/(g0))` must come back as `g1` alone). The smoke is the\n * first use, so it runs inside the one console window (`mathts-quiet.ts`).\n * MathTS is a required dependency, so a failed smoke is a defect of that\n * dependency and throws; it is not read as an absent simplifier.\n */\nfunction loadSimplifier(): MathtsSimplifyModule {\n if (cached !== undefined) return cached;\n const mod: MathtsSimplifyModule = {\n parse: (text) => mathtsParse(text) as unknown as MathNode,\n simplify: (node) => mathtsSimplify(node as never) as unknown as MathNode,\n };\n const names = new Set<string>();\n quietlySync(() => collectMathSymbols(mod.simplify(mod.parse('(g0)*((g1)/(g0))')), names));\n if (names.size !== 1 || !names.has('g1')) {\n throw new Error(`expr-simplify: MathTS simplify did not cancel g0 in the smoke test (left ${[...names].join(', ')})`);\n }\n cached = mod;\n return cached;\n}\n\nfunction collectMathSymbols(n: MathNode, out: Set<string>): void {\n if (n.type === 'SymbolNode' && n.name) out.add(n.name);\n if (n.content) collectMathSymbols(n.content, out);\n for (const a of n.args ?? []) collectMathSymbols(a, out);\n}\n\n// ---------------------------------------------------------------------------\n// ExprNode → gensym string (fully parenthesized) and back.\n// ---------------------------------------------------------------------------\n\n/** The leaf a gensym stands for: its name and dimension. @internal */\nexport interface LeafMeta {\n readonly name: string;\n readonly dim: Dimension;\n}\n\nconst isLiteral = isDecimalLiteral;\n\n/**\n * Render a scalar ExprNode to a mathjs-safe, fully-parenthesized string,\n * gensym'ing each non-literal leaf by NAME (so repeats share an identifier\n * and can cancel). Throws on a non-scalar arm and on a non-literal exponent;\n * `algebraic-equivalence.ts` renders both sides of a quotient through one\n * gensym table with it.\n *\n * @internal\n */\nexport function renderGensym(\n expr: ExprNode,\n gensymOf: Map<string, string>,\n meta: Map<string, LeafMeta>,\n): string {\n switch (expr.kind) {\n case 'symbol':\n return renderScalarLeaf(expr, gensymOf, meta);\n case 'op': {\n if (expr.op === '^') {\n const exp = expr.args[1];\n if (!exp || exp.kind !== 'symbol' || !isLiteral(exp.name)) {\n throw new Unsupported();\n }\n return `(${renderGensym(expr.args[0], gensymOf, meta)})^${Number(exp.name)}`;\n }\n if (expr.args.length === 0) throw new Unsupported();\n if (expr.args.length === 1) {\n const arg = renderGensym(expr.args[0]!, gensymOf, meta);\n if (expr.op === '-') return `(-(${arg}))`;\n if (expr.op === '+') return `(${arg})`;\n }\n const parts = expr.args.map((a) => `(${renderGensym(a, gensymOf, meta)})`);\n return `(${parts.join(expr.op)})`;\n }\n default:\n throw new Unsupported(); // integral / derivative / tensor arms\n }\n}\n\nconst lit = (v: number): ExprNode => ({ kind: 'symbol', name: String(v), dim: DIMENSIONLESS });\n\n/** Walk a simplified MathTS node back to an ExprNode, un-gensym'ing leaves and\n * rejecting anything outside UPT's integer-exponent scalar model (→ throws\n * `Unsupported`, a graceful no-op). */\nfunction walkBack(node: MathNode, meta: Map<string, LeafMeta>): ExprNode {\n switch (node.type) {\n case 'ConstantNode': {\n if (typeof node.value !== 'number' || !Number.isFinite(node.value)) {\n throw new Unsupported();\n }\n return lit(node.value);\n }\n case 'SymbolNode': {\n const m = node.name !== undefined ? meta.get(node.name) : undefined;\n if (!m) throw new Unsupported(); // a symbol we did not issue\n return { kind: 'symbol', name: m.name, dim: m.dim };\n }\n case 'ParenthesisNode':\n if (!node.content) throw new Unsupported();\n return walkBack(node.content, meta);\n case 'OperatorNode': {\n const op = node.op;\n const args = node.args ?? [];\n if (op === '^') {\n if (args.length !== 2) throw new Unsupported();\n const exp = args[1];\n if (\n exp.type !== 'ConstantNode' ||\n typeof exp.value !== 'number' ||\n !Number.isInteger(exp.value)\n ) {\n throw new Unsupported(); // non-integer exponent — not in ℤ⁷ model\n }\n return {\n kind: 'op',\n op: '^',\n args: [walkBack(args[0], meta), lit(exp.value)],\n };\n }\n if (op === '-' && args.length === 1) {\n // unary minus → (-1) * arg\n return { kind: 'op', op: '*', args: [lit(-1), walkBack(args[0], meta)] };\n }\n if (op === '+' && args.length === 1) return walkBack(args[0], meta); // unary plus is the argument\n if (op === '+' || op === '-' || op === '*' || op === '/') {\n if (args.length < 2) throw new Unsupported();\n return { kind: 'op', op, args: args.map((a) => walkBack(a, meta)) };\n }\n throw new Unsupported();\n }\n default:\n throw new Unsupported(); // FunctionNode (sqrt/cbrt/…) etc.\n }\n}\n\n// ---------------------------------------------------------------------------\n// Guards.\n// ---------------------------------------------------------------------------\n\nfunction symbolNames(expr: ExprNode, out: string[] = []): string[] {\n forEachScalarLeaf(expr, (leaf) => out.push(leaf.name), { integral: 'over+integrand', derivative: true });\n return out;\n}\n\nconst nonNumericSymbols = (expr: ExprNode): string[] =>\n symbolNames(expr).filter((n) => !isLiteral(n));\n\nconst PROBE_VALUES = [2.3, 3.7, 5.1, 7.9, 11.3, 13.1, 17.9, 19.3];\nconst PROBE_MULTIPLIERS = [1, 1.7, 0.41, 2.9];\n\n/** Numeric agreement of `original` and `candidate` over synthesized probes.\n * Free (non-constant) leaves get distinct, mutually-incommensurate values to\n * avoid accidental cancellation. <2 finite probes ⇒ 'insufficient' (cannot\n * verify — EVE-C). */\nfunction numericAgreement(\n original: ExprNode,\n candidate: ExprNode,\n): 'agree' | 'disagree' | 'insufficient' {\n const leaves = [...new Set(nonNumericSymbols(original))].filter(\n (n) => !isRegisteredConstant(n),\n );\n let finiteProbes = 0;\n for (const mult of PROBE_MULTIPLIERS) {\n const values: Record<string, number> = {};\n leaves.forEach((leaf, i) => {\n values[leaf] = PROBE_VALUES[i % PROBE_VALUES.length] * mult;\n });\n let a: number;\n let b: number;\n try {\n a = evalExpr(original, values);\n b = evalExpr(candidate, values);\n } catch {\n continue; // a probe drove evalExpr non-finite — skip it\n }\n if (!Number.isFinite(a) || !Number.isFinite(b)) continue;\n finiteProbes++;\n if (Math.abs(a - b) / Math.abs(b || 1) > 1e-9) return 'disagree';\n }\n return finiteProbes >= 2 ? 'agree' : 'insufficient';\n}\n\n// ---------------------------------------------------------------------------\n// Public entry points.\n// ---------------------------------------------------------------------------\n\n/** The result of attempting to simplify an expression. */\ninterface SimplifyResult {\n readonly expr: ExprNode;\n /** True iff MathTS was present AND produced a guard-passing, distinct form. */\n readonly simplified: boolean;\n}\n\n/**\n * Whether the MathTS simplifier is usable. MathTS is a required dependency, so\n * the answer is true; a simplifier that fails its smoke test throws instead.\n * The atlas witness runner reads it to choose between the simplifier and its\n * `peer-absent` path, which a caller still reaches by passing `null`.\n *\n * @internal\n */\nexport async function isSimplifierAvailable(): Promise<boolean> {\n loadSimplifier();\n return true;\n}\n\n/**\n * Simplify a scalar `ExprNode` via MathTS, guarded. Returns the original\n * unchanged (`simplified:false`) when the result cannot be represented or\n * verified; THROWS {@link SimplificationError} only when a\n * representable result disagrees dimensionally/numerically. See module docs.\n *\n * @internal\n */\nexport async function simplifyExpr(expr: ExprNode): Promise<SimplifyResult> {\n const mod = loadSimplifier();\n\n const gensymOf = new Map<string, string>();\n const meta = new Map<string, LeafMeta>();\n let candidate: ExprNode;\n try {\n const str = renderGensym(expr, gensymOf, meta);\n // MathTS can THROW on some forms (e.g. a known mathts `simplify` BigInt\n // bug on nested `a/(b/c²)`); that, like an unsupported node, is a graceful\n // no-op, not an error. The console is not touched here: the first use\n // already ran inside `loadSimplifier`'s window.\n const simplifiedNode = mod.simplify(mod.parse(str));\n candidate = walkBack(simplifiedNode, meta);\n } catch {\n return { expr, simplified: false }; // unsupported / unrepresentable / MathTS threw\n }\n\n // Guard 1 — dimensional. Inability to validate ⇒ no-op; a CHANGED dimension\n // is a representable disagreement ⇒ throw.\n const origDim = validate(expr).inferredDimension;\n // A literal ZERO carries every dimension: `x − x` with `x` a length is a zero\n // LENGTH, but the CAS hands back a bare dimensionless `0`. Re-stamp it with\n // the original dimension, or this guard would reject every exact\n // cancellation of a dimensioned expression as a \"changed dimension\".\n if (\n origDim !== null &&\n candidate.kind === 'symbol' &&\n candidate.name.trim() !== '' &&\n Number(candidate.name) === 0\n ) {\n candidate = { kind: 'symbol', name: '0', dim: origDim };\n }\n const newResult = validate(candidate);\n if (origDim === null || !newResult.ok || newResult.inferredDimension === null) {\n return { expr, simplified: false };\n }\n if (!equals(origDim, newResult.inferredDimension)) {\n throw new SimplificationError(\n `simplifyExpr: the simplified form changed dimension — a CAS or ` +\n `walk-back error.`,\n );\n }\n\n // Guard 2 — structural subset (no non-numeric leaf invented).\n const origSyms = new Set(nonNumericSymbols(expr));\n for (const s of nonNumericSymbols(candidate)) {\n if (!origSyms.has(s)) return { expr, simplified: false }; // suspicious ⇒ no-op\n }\n\n // Guard 3 — numeric agreement.\n const verdict = numericAgreement(expr, candidate);\n if (verdict === 'disagree') {\n throw new SimplificationError(\n `simplifyExpr: the simplified form disagrees numerically with the ` +\n `original — a CAS or walk-back error.`,\n );\n }\n if (verdict === 'insufficient') return { expr, simplified: false };\n\n // Identical-structure ⇒ nothing gained; report not simplified.\n const changed = symbolNames(candidate).length !== symbolNames(expr).length;\n return { expr: candidate, simplified: changed };\n}\n\n/**\n * Simplify a composed {@link Observable}: returns a freshly-RECONSTRUCTED\n * Observable (new strict `evaluate` closure over the simplified `expr` +\n * recomputed `leaves`) when simplification succeeds, else the original\n * unchanged. See module docs.\n *\n * @internal\n */\nexport async function simplifyObservable(obs: Observable): Promise<Observable> {\n const { expr, simplified } = await simplifyExpr(obs.expr);\n if (!simplified) return obs;\n return makeObservable(obs.name, obs.symbol, obs.dim, expr);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grounding.d.ts","sourceRoot":"","sources":["../../src/composition/grounding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"grounding.d.ts","sourceRoot":"","sources":["../../src/composition/grounding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEtD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,0EAA0E;AAC1E,MAAM,WAAW,kBAAkB;IACjC,mEAAmE;IACnE,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,oFAAoF;IACpF,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,eAAe,EAAE,KAAK,CAAC;IAChC;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,UAAU,EAAE,KAAK,CAAC;CAC5B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC/B,CAAC,EAAE,eAAe,EAClB,WAAW,CAAC,EAAE,iBAAiB,GAC9B,kBAAkB,CAiDpB;AAED,oGAAoG;AACpG,MAAM,MAAM,oBAAoB,GAAG,WAAW,GAAG,MAAM,GAAG,aAAa,CAAC;AAExE;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,6EAA6E;IAC7E,QAAQ,CAAC,SAAS,EAAE;QAAE,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IACrF,wGAAwG;IACxG,QAAQ,CAAC,IAAI,EAAE,WAAW,GAAG,gBAAgB,CAAC;IAC9C;;;;;OAKG;IACH,QAAQ,CAAC,UAAU,EAAE;QACnB,QAAQ,CAAC,QAAQ,EAAE,SAAS,oBAAoB,EAAE,CAAC;QACnD,QAAQ,CAAC,SAAS,EAAE,SAAS,oBAAoB,EAAE,CAAC;KACrD,CAAC;IACF,QAAQ,CAAC,eAAe,EAAE,KAAK,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,KAAK,CAAC;IAC3B,gGAAgG;IAChG,QAAQ,CAAC,KAAK,EAAE;QACd,6DAA6D;QAC7D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QACzB,yFAAyF;QACzF,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;QACzC,kFAAkF;QAClF,QAAQ,CAAC,SAAS,EAAE,SAAS;YAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;SAAE,EAAE,CAAC;QAChG,6DAA6D;QAC7D,QAAQ,CAAC,oBAAoB,EAAE,OAAO,CAAC;KACxC,CAAC;IACF,+DAA+D;IAC/D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,eAAe,EAAE,WAAW,CAAC,EAAE,iBAAiB,GAAG,kBAAkB,CAgCzG"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { hasMagnitudeEvidence } from './discovery.js';
|
|
1
2
|
/**
|
|
2
3
|
* Derive the grounding ledger from a candidate's existing falsifier results.
|
|
3
4
|
* `consequence` is the optional consequence-annotation signal (from
|
|
@@ -18,15 +19,23 @@ export function describeGrounding(c, consequence) {
|
|
|
18
19
|
if (c.numericallyConsistent)
|
|
19
20
|
passed.push('numerical-consistency');
|
|
20
21
|
// Magnitude gate: ran only when both endpoints had a representative value.
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
-
|
|
22
|
+
// A clash is the gate FIRING: its failure is the magnitude-clash verdict, not a
|
|
23
|
+
// grounding line (as for numerical consistency above), so it is neither passed
|
|
24
|
+
// nor a gap. An anchor-invariant ratio is fixed by the graph at every anchor, so
|
|
25
|
+
// its agreement is an identity, not a survived test (persona finding L3).
|
|
26
|
+
if (c.verdict === 'magnitude-clash') {
|
|
27
|
+
// the verdict states it
|
|
28
|
+
}
|
|
29
|
+
else if (c.magnitudeChecked && c.magnitudeAnchorInvariant === true) {
|
|
24
30
|
gaps.push('magnitude (anchor-invariant: the graph fixes this ratio at every anchor, so the match is an identity, not evidence)');
|
|
25
31
|
}
|
|
26
32
|
else if (c.magnitudeChecked) {
|
|
27
33
|
const parts = [];
|
|
28
34
|
if (c.ordersApart != null)
|
|
29
35
|
parts.push(`${c.ordersApart.toFixed(1)} orders`);
|
|
36
|
+
// A magnitude from the quantity's own equation is not anchor-derived: say which, and where from.
|
|
37
|
+
if ((c.magnitudeDerived ?? []).length > 0)
|
|
38
|
+
parts.push(`${c.magnitudeDerived.join(', ')} from its own equation`);
|
|
30
39
|
if (c.magnitudeUsedAnchor)
|
|
31
40
|
parts.push('anchor-derived');
|
|
32
41
|
passed.push(parts.length ? `magnitude (${parts.join(', ')})` : 'magnitude');
|
|
@@ -62,10 +71,13 @@ export function describeGrounding(c, consequence) {
|
|
|
62
71
|
export function describeReadiness(c, consequence) {
|
|
63
72
|
const survived = [];
|
|
64
73
|
const abstained = [];
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
74
|
+
// A magnitude clash is the falsifier firing: it neither survived nor abstained.
|
|
75
|
+
if (c.verdict !== 'magnitude-clash') {
|
|
76
|
+
if (hasMagnitudeEvidence(c))
|
|
77
|
+
survived.push('magnitude');
|
|
78
|
+
else
|
|
79
|
+
abstained.push('magnitude');
|
|
80
|
+
}
|
|
69
81
|
if (c.axisChecked && c.axisClashes.length === 0)
|
|
70
82
|
survived.push('axis');
|
|
71
83
|
else if (!c.axisChecked)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grounding.js","sourceRoot":"","sources":["../../src/composition/grounding.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * PI-instrument Phase 1 — the epistemic-grounding ledger. A pure, derived view\n * over a `VettedCandidate`'s already-computed falsifier results: which gates RAN\n * a real comparison and the candidate SURVIVED (`passed`), which could not test\n * it or produced an unadjudicated result (`gaps`), and the honest ceiling — no\n * mechanism test (axis-compatibility is a proxy, not a mechanism test) and no\n * data confrontation. Annotation-only: it changes no verdict, score, or count.\n *\n * The ledger's job is to expose WEAKNESS so a PI knows how much weight a verdict\n * bears. A gate lands in `passed` ONLY if it ran a real comparison and the\n * candidate survived; anything untestable (an abstained gate) or unadjudicated\n * (a novel machine-derived consequence) is a `gap`, never a strength. There is\n * deliberately NO single \"tier\": magnitude (numeric) and axis (regime) are\n * orthogonal evidence and must not collapse into one rank a PI could misread as\n * credibility.\n *\n * @module composition/grounding\n */\nimport type { VettedCandidate } from './discovery.js';\nimport type { ConsequenceSignal } from './consequence.js';\n\n/** The epistemic-grounding ledger for one discovery candidate. @public */\nexport interface CandidateGrounding {\n /** Gates that ran a real comparison AND the candidate survived. */\n readonly passed: readonly string[];\n /** Gates that could NOT test the candidate, or produced an unadjudicated result. */\n readonly gaps: readonly string[];\n /**\n * Honest ceiling — no mechanism test has run. This is PERMANENT for a\n * dimensional discovery candidate, not a placeholder: axis-compatibility is a\n * regime PROXY, and `entailed` (the strongest available signal — the\n * consequence re-derives a known canonical law) is a structural-consequence\n * check, not a mechanism test. A dedicated mechanism-proxy gate was assessed\n * 2026-07-04 and found NOT buildable without fabricating coupling physics the\n * catalog does not have (Phase 2 grounding; see the PI-instrument Phase 2\n * not-build note). Real mechanism lives in the ESTABLISHED-bridge world\n * (`upt confront`), not in candidate space. The field stays for honesty (the\n * ceiling is never a silent omission) and for the constructive path: growing\n * the canonical registry so `entailed` stops abstaining.\n */\n readonly mechanismTested: false;\n /**\n * Honest ceiling — this candidate is not confronted with real data. This is\n * PERMANENT for a dimensional discovery candidate, not a placeholder: a\n * cross-cluster dimensional identification is a coincidence review surface\n * (0/8 ever adjudicated genuine) with no implied observable to measure. Data\n * confrontation lives in the ESTABLISHED-bridge world (`upt confront`), which\n * the evidence-spine work grows. The scientific loop is closed not by\n * confronting candidates but by the FIREWALL: a candidate must graduate to an\n * established bridge (human review + citation) before it can be data-tested.\n * A propose→confront loop over candidates was assessed 2026-07-04 (PI-instrument\n * Phase 3) and found to have no confrontable target — the honest boundary is\n * that candidates are unconfrontable until promoted. The field stays for\n * honesty and flips only for a candidate that is `entailed` into (or graduates\n * to) a data-confronted relation.\n */\n readonly dataTested: false;\n}\n\n/**\n * Derive the grounding ledger from a candidate's existing falsifier results.\n * `consequence` is the optional consequence-annotation signal (from\n * `annotateConsequences`); omit it when the consequence layer did not run.\n *\n * Designed for `promising` candidates (the ones a PI reviews), but honest for\n * any candidate: it never reports a gate as `passed` unless it actually ran and\n * the candidate survived it.\n *\n * @public\n */\nexport function describeGrounding(\n c: VettedCandidate,\n consequence?: ConsequenceSignal,\n): CandidateGrounding {\n const passed: string[] = [];\n const gaps: string[] = [];\n\n // Numerical-consistency: the retrodiction filter always runs. It is `passed`\n // only when the candidate is actually consistent (a contradictory candidate's\n // failure is its verdict, not a grounding line — this view is for survivors).\n if (c.numericallyConsistent) passed.push('numerical-consistency');\n\n // Magnitude gate: ran only when both endpoints had a representative value.\n // An anchor-invariant ratio is fixed by the graph at every anchor, so its\n // agreement is an identity, not a survived test (persona finding L3).\n if (c.magnitudeChecked && c.magnitudeAnchorInvariant === true) {\n gaps.push(\n 'magnitude (anchor-invariant: the graph fixes this ratio at every anchor, so the match is an identity, not evidence)',\n );\n } else if (c.magnitudeChecked) {\n const parts: string[] = [];\n if (c.ordersApart != null) parts.push(`${c.ordersApart.toFixed(1)} orders`);\n if (c.magnitudeUsedAnchor) parts.push('anchor-derived');\n passed.push(parts.length ? `magnitude (${parts.join(', ')})` : 'magnitude');\n } else {\n gaps.push('magnitude (no representative value)');\n }\n\n // Axis-compatibility: honestly PARTIAL — \"≥1 regime axis resolved and agreed\",\n // never \"fully axis-checked\". Cleared only when an axis was resolved AND none\n // clashed. (A clash is the axis-clash verdict, not a survivor's grounding.)\n if (c.axisChecked && c.axisClashes.length === 0) {\n passed.push('axis-compatible (≥1 regime axis)');\n } else if (!c.axisChecked) {\n gaps.push('axis (regime attributes unresolved)');\n }\n\n // Consequence: ONLY `entailed` clears (the consequence re-derives a known\n // canonical law — a real check against standard physics). `novel-consequence`\n // is an UNADJUDICATED machine-surfaced relation — a weakness to investigate,\n // not a passed test. `inconclusive` means the consequence layer could not test.\n if (consequence === 'entailed') passed.push('consequence: entailed');\n else if (consequence === 'novel-consequence') gaps.push('consequence: novel (unadjudicated)');\n else if (consequence === 'inconclusive') gaps.push('consequence: inconclusive');\n\n return { passed, gaps, mechanismTested: false, dataTested: false };\n}\n\n/** An independent falsifier: a gate that can reject an identification the anchored graph cannot. */\nexport type IndependentFalsifier = 'magnitude' | 'axis' | 'consequence';\n\n/**\n * How far one candidate is from being a testable claim, dimension by dimension.\n * Deliberately NOT a score: the dimensions are orthogonal and are never summed.\n * @internal\n */\nexport interface CandidateReadiness {\n /** Connectivity. It makes a candidate worth a look; it is never evidence. */\n readonly structure: { readonly mergesComponents: boolean; readonly unlocks: number };\n /** `same-kind`: the names share a kind token. `dimension-only`: nothing but the dimension is shared. */\n readonly kind: 'same-kind' | 'dimension-only';\n /**\n * Independent falsifiers that ran and the candidate survived, and those that\n * abstained. An abstention is a missing test, never a pass. Numerical\n * consistency is not listed: it runs from a single anchor and cannot reach\n * the quantities an identification unlocks.\n */\n readonly falsifiers: {\n readonly survived: readonly IndependentFalsifier[];\n readonly abstained: readonly IndependentFalsifier[];\n };\n readonly mechanismTested: false;\n readonly dataTested: false;\n /** What would make the identification testable, each item derived from why a gate abstained. */\n readonly needs: {\n /** The premise every literal identification a≡b rests on. */\n readonly premise: string;\n /** Endpoints that need a representative magnitude for the magnitude falsifier to run. */\n readonly magnitudeFor: readonly string[];\n /** Axes and endpoints that need a stated regime for the axis falsifier to run. */\n readonly regimeFor: readonly { readonly axis: string; readonly endpoints: readonly string[] }[];\n /** The consequence check could not re-derive a known law. */\n readonly derivableConsequence: boolean;\n };\n /** The independent observation that would test the premise. */\n readonly observation: string;\n}\n\n/**\n * Derive a candidate's readiness from its falsifier fields.\n * @internal\n */\nexport function describeReadiness(c: VettedCandidate, consequence?: ConsequenceSignal): CandidateReadiness {\n const survived: IndependentFalsifier[] = [];\n const abstained: IndependentFalsifier[] = [];\n if (c.magnitudeChecked && c.magnitudeAnchorInvariant !== true) survived.push('magnitude');\n else abstained.push('magnitude');\n if (c.axisChecked && c.axisClashes.length === 0) survived.push('axis');\n else if (!c.axisChecked) abstained.push('axis');\n if (consequence === 'entailed') survived.push('consequence');\n else abstained.push('consequence');\n const kind = c.sameKind ? 'same-kind' : 'dimension-only';\n return {\n structure: { mergesComponents: c.mergesComponents, unlocks: c.unlocksFromAnchor.length },\n kind,\n falsifiers: { survived, abstained },\n mechanismTested: false,\n dataTested: false,\n needs: {\n premise:\n kind === 'same-kind'\n ? `${c.a} and ${c.b} are the same physical quantity, not two quantities of one kind`\n : `${c.a} and ${c.b} are the same physical quantity, not only both ${c.dim}`,\n magnitudeFor: c.magnitudeChecked ? [] : [...(c.magnitudeMissing ?? [])],\n regimeFor: c.axisChecked ? [] : (c.axisUnstated ?? []).map((u) => ({ axis: u.axis, endpoints: [...u.endpoints] })),\n derivableConsequence: consequence !== 'entailed',\n },\n observation:\n `measure ${c.a} and ${c.b} in one system that defines both: the identification predicts equal values ` +\n 'within uncertainty. If no system defines both, it has no observable content yet.',\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"grounding.js","sourceRoot":"","sources":["../../src/composition/grounding.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * PI-instrument Phase 1 — the epistemic-grounding ledger. A pure, derived view\n * over a `VettedCandidate`'s already-computed falsifier results: which gates RAN\n * a real comparison and the candidate SURVIVED (`passed`), which could not test\n * it or produced an unadjudicated result (`gaps`), and the honest ceiling — no\n * mechanism test (axis-compatibility is a proxy, not a mechanism test) and no\n * data confrontation. Annotation-only: it changes no verdict, score, or count.\n *\n * The ledger's job is to expose WEAKNESS so a PI knows how much weight a verdict\n * bears. A gate lands in `passed` ONLY if it ran a real comparison and the\n * candidate survived; anything untestable (an abstained gate) or unadjudicated\n * (a novel machine-derived consequence) is a `gap`, never a strength. There is\n * deliberately NO single \"tier\": magnitude (numeric) and axis (regime) are\n * orthogonal evidence and must not collapse into one rank a PI could misread as\n * credibility.\n *\n * @module composition/grounding\n */\nimport type { VettedCandidate } from './discovery.js';\nimport { hasMagnitudeEvidence } from './discovery.js';\nimport type { ConsequenceSignal } from './consequence.js';\n\n/** The epistemic-grounding ledger for one discovery candidate. @public */\nexport interface CandidateGrounding {\n /** Gates that ran a real comparison AND the candidate survived. */\n readonly passed: readonly string[];\n /** Gates that could NOT test the candidate, or produced an unadjudicated result. */\n readonly gaps: readonly string[];\n /**\n * Honest ceiling — no mechanism test has run. This is PERMANENT for a\n * dimensional discovery candidate, not a placeholder: axis-compatibility is a\n * regime PROXY, and `entailed` (the strongest available signal — the\n * consequence re-derives a known canonical law) is a structural-consequence\n * check, not a mechanism test. A dedicated mechanism-proxy gate was assessed\n * 2026-07-04 and found NOT buildable without fabricating coupling physics the\n * catalog does not have (Phase 2 grounding; see the PI-instrument Phase 2\n * not-build note). Real mechanism lives in the ESTABLISHED-bridge world\n * (`upt confront`), not in candidate space. The field stays for honesty (the\n * ceiling is never a silent omission) and for the constructive path: growing\n * the canonical registry so `entailed` stops abstaining.\n */\n readonly mechanismTested: false;\n /**\n * Honest ceiling — this candidate is not confronted with real data. This is\n * PERMANENT for a dimensional discovery candidate, not a placeholder: a\n * cross-cluster dimensional identification is a coincidence review surface\n * (0/8 ever adjudicated genuine) with no implied observable to measure. Data\n * confrontation lives in the ESTABLISHED-bridge world (`upt confront`), which\n * the evidence-spine work grows. The scientific loop is closed not by\n * confronting candidates but by the FIREWALL: a candidate must graduate to an\n * established bridge (human review + citation) before it can be data-tested.\n * A propose→confront loop over candidates was assessed 2026-07-04 (PI-instrument\n * Phase 3) and found to have no confrontable target — the honest boundary is\n * that candidates are unconfrontable until promoted. The field stays for\n * honesty and flips only for a candidate that is `entailed` into (or graduates\n * to) a data-confronted relation.\n */\n readonly dataTested: false;\n}\n\n/**\n * Derive the grounding ledger from a candidate's existing falsifier results.\n * `consequence` is the optional consequence-annotation signal (from\n * `annotateConsequences`); omit it when the consequence layer did not run.\n *\n * Designed for `promising` candidates (the ones a PI reviews), but honest for\n * any candidate: it never reports a gate as `passed` unless it actually ran and\n * the candidate survived it.\n *\n * @public\n */\nexport function describeGrounding(\n c: VettedCandidate,\n consequence?: ConsequenceSignal,\n): CandidateGrounding {\n const passed: string[] = [];\n const gaps: string[] = [];\n\n // Numerical-consistency: the retrodiction filter always runs. It is `passed`\n // only when the candidate is actually consistent (a contradictory candidate's\n // failure is its verdict, not a grounding line — this view is for survivors).\n if (c.numericallyConsistent) passed.push('numerical-consistency');\n\n // Magnitude gate: ran only when both endpoints had a representative value.\n // A clash is the gate FIRING: its failure is the magnitude-clash verdict, not a\n // grounding line (as for numerical consistency above), so it is neither passed\n // nor a gap. An anchor-invariant ratio is fixed by the graph at every anchor, so\n // its agreement is an identity, not a survived test (persona finding L3).\n if (c.verdict === 'magnitude-clash') {\n // the verdict states it\n } else if (c.magnitudeChecked && c.magnitudeAnchorInvariant === true) {\n gaps.push(\n 'magnitude (anchor-invariant: the graph fixes this ratio at every anchor, so the match is an identity, not evidence)',\n );\n } else if (c.magnitudeChecked) {\n const parts: string[] = [];\n if (c.ordersApart != null) parts.push(`${c.ordersApart.toFixed(1)} orders`);\n // A magnitude from the quantity's own equation is not anchor-derived: say which, and where from.\n if ((c.magnitudeDerived ?? []).length > 0) parts.push(`${c.magnitudeDerived!.join(', ')} from its own equation`);\n if (c.magnitudeUsedAnchor) parts.push('anchor-derived');\n passed.push(parts.length ? `magnitude (${parts.join(', ')})` : 'magnitude');\n } else {\n gaps.push('magnitude (no representative value)');\n }\n\n // Axis-compatibility: honestly PARTIAL — \"≥1 regime axis resolved and agreed\",\n // never \"fully axis-checked\". Cleared only when an axis was resolved AND none\n // clashed. (A clash is the axis-clash verdict, not a survivor's grounding.)\n if (c.axisChecked && c.axisClashes.length === 0) {\n passed.push('axis-compatible (≥1 regime axis)');\n } else if (!c.axisChecked) {\n gaps.push('axis (regime attributes unresolved)');\n }\n\n // Consequence: ONLY `entailed` clears (the consequence re-derives a known\n // canonical law — a real check against standard physics). `novel-consequence`\n // is an UNADJUDICATED machine-surfaced relation — a weakness to investigate,\n // not a passed test. `inconclusive` means the consequence layer could not test.\n if (consequence === 'entailed') passed.push('consequence: entailed');\n else if (consequence === 'novel-consequence') gaps.push('consequence: novel (unadjudicated)');\n else if (consequence === 'inconclusive') gaps.push('consequence: inconclusive');\n\n return { passed, gaps, mechanismTested: false, dataTested: false };\n}\n\n/** An independent falsifier: a gate that can reject an identification the anchored graph cannot. */\nexport type IndependentFalsifier = 'magnitude' | 'axis' | 'consequence';\n\n/**\n * How far one candidate is from being a testable claim, dimension by dimension.\n * Deliberately NOT a score: the dimensions are orthogonal and are never summed.\n * @internal\n */\nexport interface CandidateReadiness {\n /** Connectivity. It makes a candidate worth a look; it is never evidence. */\n readonly structure: { readonly mergesComponents: boolean; readonly unlocks: number };\n /** `same-kind`: the names share a kind token. `dimension-only`: nothing but the dimension is shared. */\n readonly kind: 'same-kind' | 'dimension-only';\n /**\n * Independent falsifiers that ran and the candidate survived, and those that\n * abstained. An abstention is a missing test, never a pass. Numerical\n * consistency is not listed: it runs from a single anchor and cannot reach\n * the quantities an identification unlocks.\n */\n readonly falsifiers: {\n readonly survived: readonly IndependentFalsifier[];\n readonly abstained: readonly IndependentFalsifier[];\n };\n readonly mechanismTested: false;\n readonly dataTested: false;\n /** What would make the identification testable, each item derived from why a gate abstained. */\n readonly needs: {\n /** The premise every literal identification a≡b rests on. */\n readonly premise: string;\n /** Endpoints that need a representative magnitude for the magnitude falsifier to run. */\n readonly magnitudeFor: readonly string[];\n /** Axes and endpoints that need a stated regime for the axis falsifier to run. */\n readonly regimeFor: readonly { readonly axis: string; readonly endpoints: readonly string[] }[];\n /** The consequence check could not re-derive a known law. */\n readonly derivableConsequence: boolean;\n };\n /** The independent observation that would test the premise. */\n readonly observation: string;\n}\n\n/**\n * Derive a candidate's readiness from its falsifier fields.\n * @internal\n */\nexport function describeReadiness(c: VettedCandidate, consequence?: ConsequenceSignal): CandidateReadiness {\n const survived: IndependentFalsifier[] = [];\n const abstained: IndependentFalsifier[] = [];\n // A magnitude clash is the falsifier firing: it neither survived nor abstained.\n if (c.verdict !== 'magnitude-clash') {\n if (hasMagnitudeEvidence(c)) survived.push('magnitude');\n else abstained.push('magnitude');\n }\n if (c.axisChecked && c.axisClashes.length === 0) survived.push('axis');\n else if (!c.axisChecked) abstained.push('axis');\n if (consequence === 'entailed') survived.push('consequence');\n else abstained.push('consequence');\n const kind = c.sameKind ? 'same-kind' : 'dimension-only';\n return {\n structure: { mergesComponents: c.mergesComponents, unlocks: c.unlocksFromAnchor.length },\n kind,\n falsifiers: { survived, abstained },\n mechanismTested: false,\n dataTested: false,\n needs: {\n premise:\n kind === 'same-kind'\n ? `${c.a} and ${c.b} are the same physical quantity, not two quantities of one kind`\n : `${c.a} and ${c.b} are the same physical quantity, not only both ${c.dim}`,\n magnitudeFor: c.magnitudeChecked ? [] : [...(c.magnitudeMissing ?? [])],\n regimeFor: c.axisChecked ? [] : (c.axisUnstated ?? []).map((u) => ({ axis: u.axis, endpoints: [...u.endpoints] })),\n derivableConsequence: consequence !== 'entailed',\n },\n observation:\n `measure ${c.a} and ${c.b} in one system that defines both: the identification predicts equal values ` +\n 'within uncertainty. If no system defines both, it has no observable content yet.',\n };\n}\n"]}
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Load the MathTS
|
|
2
|
+
* Load the MathTS dependency without its console chatter reaching stderr.
|
|
3
3
|
*
|
|
4
4
|
* MathTS writes with `console.warn`/`console.error` directly (its `warnOnce`,
|
|
5
5
|
* the factorisation fallbacks, the WASM-integrity notice) and offers no option
|
|
6
6
|
* to route or silence them: `ImportOptions.silent` is for importing user
|
|
7
7
|
* functions, not for logging. The only way to keep that text out of a CLI's
|
|
8
8
|
* stderr is to replace the three process-global sinks for the duration of the
|
|
9
|
-
* call, which is what the
|
|
9
|
+
* call, which is what the helper here does, and nothing else in `src/` may
|
|
10
10
|
* do.
|
|
11
11
|
*
|
|
12
12
|
* THE INVARIANT: the replacement is process-global, so a concurrent caller in
|
|
13
13
|
* the same process (a worker pool thread, a vitest worker sharing a process)
|
|
14
14
|
* loses its console for the window. The window is therefore confined to the
|
|
15
|
-
*
|
|
15
|
+
* dependency's ONE-TIME load and first-use smoke in `expr-simplify.ts`,
|
|
16
16
|
* `mathts-scalar-symbols.ts` and `algebraic-equivalence.ts`: each caches the
|
|
17
17
|
* loaded function, so the sinks are replaced once per process, and never
|
|
18
18
|
* around a per-call parse or simplify.
|
|
19
|
-
*
|
|
19
|
+
* The helper restores the sinks in `finally`, so a throw inside the window
|
|
20
20
|
* cannot leave them replaced. `tests/composition/mathts-quiet.test.ts` scans
|
|
21
21
|
* `src/` for any other reassignment and traps the sinks during a call.
|
|
22
22
|
*
|
|
@@ -24,6 +24,4 @@
|
|
|
24
24
|
*/
|
|
25
25
|
/** Run `fn` with the console sinks replaced, restoring them in `finally`. @internal */
|
|
26
26
|
export declare function quietlySync<T>(fn: () => T): T;
|
|
27
|
-
/** The asynchronous form of {@link quietlySync}: the window spans the awaited promise. @internal */
|
|
28
|
-
export declare function quietly<T>(fn: () => Promise<T>): Promise<T>;
|
|
29
27
|
//# sourceMappingURL=mathts-quiet.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mathts-quiet.d.ts","sourceRoot":"","sources":["../../src/composition/mathts-quiet.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAsBH,uFAAuF;AACvF,wBAAgB,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAO7C
|
|
1
|
+
{"version":3,"file":"mathts-quiet.d.ts","sourceRoot":"","sources":["../../src/composition/mathts-quiet.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAsBH,uFAAuF;AACvF,wBAAgB,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAO7C"}
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Load the MathTS
|
|
2
|
+
* Load the MathTS dependency without its console chatter reaching stderr.
|
|
3
3
|
*
|
|
4
4
|
* MathTS writes with `console.warn`/`console.error` directly (its `warnOnce`,
|
|
5
5
|
* the factorisation fallbacks, the WASM-integrity notice) and offers no option
|
|
6
6
|
* to route or silence them: `ImportOptions.silent` is for importing user
|
|
7
7
|
* functions, not for logging. The only way to keep that text out of a CLI's
|
|
8
8
|
* stderr is to replace the three process-global sinks for the duration of the
|
|
9
|
-
* call, which is what the
|
|
9
|
+
* call, which is what the helper here does, and nothing else in `src/` may
|
|
10
10
|
* do.
|
|
11
11
|
*
|
|
12
12
|
* THE INVARIANT: the replacement is process-global, so a concurrent caller in
|
|
13
13
|
* the same process (a worker pool thread, a vitest worker sharing a process)
|
|
14
14
|
* loses its console for the window. The window is therefore confined to the
|
|
15
|
-
*
|
|
15
|
+
* dependency's ONE-TIME load and first-use smoke in `expr-simplify.ts`,
|
|
16
16
|
* `mathts-scalar-symbols.ts` and `algebraic-equivalence.ts`: each caches the
|
|
17
17
|
* loaded function, so the sinks are replaced once per process, and never
|
|
18
18
|
* around a per-call parse or simplify.
|
|
19
|
-
*
|
|
19
|
+
* The helper restores the sinks in `finally`, so a throw inside the window
|
|
20
20
|
* cannot leave them replaced. `tests/composition/mathts-quiet.test.ts` scans
|
|
21
21
|
* `src/` for any other reassignment and traps the sinks during a call.
|
|
22
22
|
*
|
|
@@ -44,14 +44,4 @@ export function quietlySync(fn) {
|
|
|
44
44
|
restore(saved);
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
|
-
/** The asynchronous form of {@link quietlySync}: the window spans the awaited promise. @internal */
|
|
48
|
-
export async function quietly(fn) {
|
|
49
|
-
const saved = silence();
|
|
50
|
-
try {
|
|
51
|
-
return await fn();
|
|
52
|
-
}
|
|
53
|
-
finally {
|
|
54
|
-
restore(saved);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
47
|
//# sourceMappingURL=mathts-quiet.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mathts-quiet.js","sourceRoot":"","sources":["../../src/composition/mathts-quiet.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAQH,SAAS,OAAO;IACd,MAAM,KAAK,GAAU,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IAC/F,OAAO,CAAC,IAAI,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;IACxB,OAAO,CAAC,KAAK,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;IACxB,OAAO,CAAC,MAA6B,CAAC,KAAK,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC;IAC1D,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,OAAO,CAAC,KAAY;IAC3B,OAAO,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;IAC1B,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IAC3B,OAAO,CAAC,MAA6B,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;AAC7D,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,WAAW,CAAI,EAAW;IACxC,MAAM,KAAK,GAAG,OAAO,EAAE,CAAC;IACxB,IAAI,CAAC;QACH,OAAO,EAAE,EAAE,CAAC;IACd,CAAC;YAAS,CAAC;QACT,OAAO,CAAC,KAAK,CAAC,CAAC;IACjB,CAAC;AACH,CAAC
|
|
1
|
+
{"version":3,"file":"mathts-quiet.js","sourceRoot":"","sources":["../../src/composition/mathts-quiet.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAQH,SAAS,OAAO;IACd,MAAM,KAAK,GAAU,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IAC/F,OAAO,CAAC,IAAI,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;IACxB,OAAO,CAAC,KAAK,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;IACxB,OAAO,CAAC,MAA6B,CAAC,KAAK,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC;IAC1D,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,OAAO,CAAC,KAAY;IAC3B,OAAO,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;IAC1B,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IAC3B,OAAO,CAAC,MAA6B,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;AAC7D,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,WAAW,CAAI,EAAW;IACxC,MAAM,KAAK,GAAG,OAAO,EAAE,CAAC;IACxB,IAAI,CAAC;QACH,OAAO,EAAE,EAAE,CAAC;IACd,CAAC;YAAS,CAAC;QACT,OAAO,CAAC,KAAK,CAAC,CAAC;IACjB,CAAC;AACH,CAAC","sourcesContent":["/**\n * Load the MathTS dependency without its console chatter reaching stderr.\n *\n * MathTS writes with `console.warn`/`console.error` directly (its `warnOnce`,\n * the factorisation fallbacks, the WASM-integrity notice) and offers no option\n * to route or silence them: `ImportOptions.silent` is for importing user\n * functions, not for logging. The only way to keep that text out of a CLI's\n * stderr is to replace the three process-global sinks for the duration of the\n * call, which is what the helper here does, and nothing else in `src/` may\n * do.\n *\n * THE INVARIANT: the replacement is process-global, so a concurrent caller in\n * the same process (a worker pool thread, a vitest worker sharing a process)\n * loses its console for the window. The window is therefore confined to the\n * dependency's ONE-TIME load and first-use smoke in `expr-simplify.ts`,\n * `mathts-scalar-symbols.ts` and `algebraic-equivalence.ts`: each caches the\n * loaded function, so the sinks are replaced once per process, and never\n * around a per-call parse or simplify.\n * The helper restores the sinks in `finally`, so a throw inside the window\n * cannot leave them replaced. `tests/composition/mathts-quiet.test.ts` scans\n * `src/` for any other reassignment and traps the sinks during a call.\n *\n * @module composition/mathts-quiet\n */\n\ntype Sinks = {\n readonly warn: typeof console.warn;\n readonly error: typeof console.error;\n readonly write: typeof process.stderr.write;\n};\n\nfunction silence(): Sinks {\n const saved: Sinks = { warn: console.warn, error: console.error, write: process.stderr.write };\n console.warn = () => {};\n console.error = () => {};\n (process.stderr as { write: unknown }).write = () => true;\n return saved;\n}\n\nfunction restore(saved: Sinks): void {\n console.warn = saved.warn;\n console.error = saved.error;\n (process.stderr as { write: unknown }).write = saved.write;\n}\n\n/** Run `fn` with the console sinks replaced, restoring them in `finally`. @internal */\nexport function quietlySync<T>(fn: () => T): T {\n const saved = silence();\n try {\n return fn();\n } finally {\n restore(saved);\n }\n}\n"]}
|