@cavelang/core 0.28.1 → 0.29.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/Authors.md +5 -0
- package/README.md +17 -5
- package/dist/src/claim.d.ts.map +1 -1
- package/dist/src/claim.js +22 -15
- package/dist/src/claim.js.map +1 -1
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/source-span.d.ts +30 -0
- package/dist/src/source-span.d.ts.map +1 -0
- package/dist/src/source-span.js +68 -0
- package/dist/src/source-span.js.map +1 -0
- package/dist/src/time.d.ts +14 -0
- package/dist/src/time.d.ts.map +1 -1
- package/dist/src/time.js +47 -10
- package/dist/src/time.js.map +1 -1
- package/dist/src/uncertainty.d.ts +13 -0
- package/dist/src/uncertainty.d.ts.map +1 -1
- package/dist/src/uncertainty.js +24 -4
- package/dist/src/uncertainty.js.map +1 -1
- package/dist/src/uuidv7.d.ts +6 -0
- package/dist/src/uuidv7.d.ts.map +1 -1
- package/dist/src/uuidv7.js +16 -0
- package/dist/src/uuidv7.js.map +1 -1
- package/dist/src/value.d.ts +2 -1
- package/dist/src/value.d.ts.map +1 -1
- package/dist/src/value.js +4 -3
- package/dist/src/value.js.map +1 -1
- package/dist/src/verb.d.ts +8 -3
- package/dist/src/verb.d.ts.map +1 -1
- package/dist/src/verb.js +14 -6
- package/dist/src/verb.js.map +1 -1
- package/package.json +14 -3
- package/src/claim.ts +20 -15
- package/src/index.ts +2 -0
- package/src/source-span.ts +98 -0
- package/src/time.ts +50 -11
- package/src/uncertainty.ts +35 -4
- package/src/uuidv7.ts +16 -0
- package/src/value.ts +4 -4
- package/src/verb.ts +16 -6
package/dist/src/value.js
CHANGED
|
@@ -19,16 +19,17 @@
|
|
|
19
19
|
* with their kind already known; use {@link ofText} / {@link ofCode}.
|
|
20
20
|
*/
|
|
21
21
|
import * as Multiplier from "./multiplier.js";
|
|
22
|
+
import { parsePeriod } from "./time.js";
|
|
22
23
|
const numberRe = /^(-?\d+(?:\.\d+)?)([A-Za-z%]*)$/;
|
|
23
24
|
const unitRe = /^[A-Za-z%$][A-Za-z0-9%$]*(?:\/[A-Za-z0-9%$]+)*$/;
|
|
24
|
-
const dateRe = /^\d{4}-(?:H[1-2]|Q[1-4]|W\d{1,2}|\d{2})(?:-\d{2})?$/;
|
|
25
25
|
/** @returns `true` if `s` is a valid unit expression (`USD/yr`, `ms`, `%`). */
|
|
26
26
|
export const isUnit = (s) => unitRe.test(s);
|
|
27
27
|
/**
|
|
28
28
|
* @returns `true` if `s` is date-like (spec §16 `date_like`): `2026-H2`,
|
|
29
|
-
* `2026-Q1`, `2026-04`, `2026-04-10`.
|
|
29
|
+
* `2026-Q1`, `2026-04`, `2026-04-10`. Calendar validity is shared with
|
|
30
|
+
* {@link parsePeriod}; a bare year parses as a number instead.
|
|
30
31
|
*/
|
|
31
|
-
export const isDateLike = (s) =>
|
|
32
|
+
export const isDateLike = (s) => s.includes('-') && parsePeriod(s) !== undefined;
|
|
32
33
|
/**
|
|
33
34
|
* Parses `body` as number [multiplier] [unit] where the unit is either glued
|
|
34
35
|
* (`30ms`, `94.5%`) or space-separated (`20B USD/yr`, `20 conn`).
|
package/dist/src/value.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"value.js","sourceRoot":"","sources":["../../src/value.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,UAAU,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"value.js","sourceRoot":"","sources":["../../src/value.ts"],"names":[],"mappings":"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"}
|
package/dist/src/verb.d.ts
CHANGED
|
@@ -18,12 +18,16 @@ export declare const causation: readonly ["CAUSE", "FIX", "BECOMES"];
|
|
|
18
18
|
/** Dependency and production (spec §5.2). */
|
|
19
19
|
export declare const dependency: readonly ["NEEDS", "USES", "YIELDS", "ENABLES", "BLOCKS"];
|
|
20
20
|
/** Structure and ordering (spec §5.2). */
|
|
21
|
-
export declare const structure: readonly ["CONTAINS", "PRECEDES", "
|
|
21
|
+
export declare const structure: readonly ["CONTAINS", "PRECEDES", "VS"];
|
|
22
|
+
/** Canonical verbs for qualifier comparisons (spec §8.2). */
|
|
23
|
+
export declare const comparison: readonly ["EXCEEDS", "IS-BELOW", "IS-AT-LEAST", "IS-AT-MOST", "EQUALS", "DIFFERS-FROM"];
|
|
22
24
|
/** Qualifier verbs — appear indented under another claim (spec §5.2, §8.2). */
|
|
23
25
|
export declare const qualifiers: readonly ["WHEN", "UNLESS", "VIA", "BECAUSE"];
|
|
24
26
|
export type Qualifier = (typeof qualifiers)[number];
|
|
25
27
|
/** The inverse-declaration verb (spec §5.5). */
|
|
26
28
|
export declare const REVERSE = "REVERSE";
|
|
29
|
+
/** The verb-lifecycle declaration (spec §5.8). */
|
|
30
|
+
export declare const RENAMED_TO = "RENAMED-TO";
|
|
27
31
|
/** The shape-expectation meta-verb (spec §20.1). */
|
|
28
32
|
export declare const EXPECTS = "EXPECTS";
|
|
29
33
|
/** The standard inverse names (spec §5.5's declaration block). */
|
|
@@ -32,7 +36,8 @@ export declare const standardInverses: readonly ["PART-OF", "CAUSED-BY", "FOLLOW
|
|
|
32
36
|
export declare const standard: readonly Verb[];
|
|
33
37
|
/**
|
|
34
38
|
* @returns `true` if `s` has the lexical shape of a verb — an uppercase atom:
|
|
35
|
-
* uppercase letters
|
|
39
|
+
* an uppercase letter followed by uppercase letters or `-` (spec §16
|
|
40
|
+
* `uppercase_atom`, which permits a trailing hyphen).
|
|
36
41
|
*/
|
|
37
42
|
export declare const isVerbToken: (s: string) => boolean;
|
|
38
43
|
/** @returns `true` if `v` is one of the standard relational verbs. */
|
|
@@ -41,7 +46,7 @@ export declare const isStandard: (v: string) => boolean;
|
|
|
41
46
|
export declare const isQualifier: (v: string) => v is Qualifier;
|
|
42
47
|
/**
|
|
43
48
|
* @returns `true` if `v` belongs to the known standard vocabulary —
|
|
44
|
-
* standard verbs, `HAS`, `REVERSE`, `EXPECTS`, and the standard §5.5
|
|
49
|
+
* standard verbs, `HAS`, `REVERSE`, `RENAMED-TO`, `EXPECTS`, and the standard §5.5
|
|
45
50
|
* inverse names.
|
|
46
51
|
* Used by the parser's indentation tiebreak: `USES JWT` is a continuation
|
|
47
52
|
* (JWT is not a known verb) while `API NEEDS auth` is a full triple.
|
package/dist/src/verb.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verb.d.ts","sourceRoot":"","sources":["../../src/verb.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,MAAM,IAAI,GAAG,MAAM,CAAA;AAEzB,MAAM,MAAM,CAAC,GAAG,IAAI,CAAA;AAEpB,mCAAmC;AACnC,eAAO,MAAM,SAAS,wBAAyB,CAAA;AAE/C,yCAAyC;AACzC,eAAO,MAAM,QAAQ,uDAAwD,CAAA;AAE7E,wCAAwC;AACxC,eAAO,MAAM,SAAS,sCAAuC,CAAA;AAE7D,6CAA6C;AAC7C,eAAO,MAAM,UAAU,2DAA4D,CAAA;AAEnF,0CAA0C;AAC1C,eAAO,MAAM,SAAS,
|
|
1
|
+
{"version":3,"file":"verb.d.ts","sourceRoot":"","sources":["../../src/verb.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,MAAM,IAAI,GAAG,MAAM,CAAA;AAEzB,MAAM,MAAM,CAAC,GAAG,IAAI,CAAA;AAEpB,mCAAmC;AACnC,eAAO,MAAM,SAAS,wBAAyB,CAAA;AAE/C,yCAAyC;AACzC,eAAO,MAAM,QAAQ,uDAAwD,CAAA;AAE7E,wCAAwC;AACxC,eAAO,MAAM,SAAS,sCAAuC,CAAA;AAE7D,6CAA6C;AAC7C,eAAO,MAAM,UAAU,2DAA4D,CAAA;AAEnF,0CAA0C;AAC1C,eAAO,MAAM,SAAS,yCAA0C,CAAA;AAEhE,6DAA6D;AAC7D,eAAO,MAAM,UAAU,yFAEb,CAAA;AAEV,+EAA+E;AAC/E,eAAO,MAAM,UAAU,+CAAgD,CAAA;AAEvE,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAA;AAEnD,gDAAgD;AAChD,eAAO,MAAM,OAAO,YAAY,CAAA;AAEhC,kDAAkD;AAClD,eAAO,MAAM,UAAU,eAAe,CAAA;AAEtC,oDAAoD;AACpD,eAAO,MAAM,OAAO,YAAY,CAAA;AAEhC,kEAAkE;AAClE,eAAO,MAAM,gBAAgB,iHAGnB,CAAA;AAEV,2DAA2D;AAC3D,eAAO,MAAM,QAAQ,EAAE,SAAS,IAAI,EAMnC,CAAA;AAMD;;;;GAIG;AACH,eAAO,MAAM,WAAW,GAAI,GAAG,MAAM,KAAG,OACd,CAAA;AAE1B,sEAAsE;AACtE,eAAO,MAAM,UAAU,GAAI,GAAG,MAAM,KAAG,OACnB,CAAA;AAEpB,uFAAuF;AACvF,eAAO,MAAM,WAAW,GAAI,GAAG,MAAM,KAAG,CAAC,IAAI,SACxB,CAAA;AAErB;;;;;;GAMG;AACH,eAAO,MAAM,OAAO,GAAI,GAAG,MAAM,KAAG,OACnB,CAAA"}
|
package/dist/src/verb.js
CHANGED
|
@@ -16,11 +16,17 @@ export const causation = ['CAUSE', 'FIX', 'BECOMES'];
|
|
|
16
16
|
/** Dependency and production (spec §5.2). */
|
|
17
17
|
export const dependency = ['NEEDS', 'USES', 'YIELDS', 'ENABLES', 'BLOCKS'];
|
|
18
18
|
/** Structure and ordering (spec §5.2). */
|
|
19
|
-
export const structure = ['CONTAINS', 'PRECEDES', '
|
|
19
|
+
export const structure = ['CONTAINS', 'PRECEDES', 'VS'];
|
|
20
|
+
/** Canonical verbs for qualifier comparisons (spec §8.2). */
|
|
21
|
+
export const comparison = [
|
|
22
|
+
'EXCEEDS', 'IS-BELOW', 'IS-AT-LEAST', 'IS-AT-MOST', 'EQUALS', 'DIFFERS-FROM'
|
|
23
|
+
];
|
|
20
24
|
/** Qualifier verbs — appear indented under another claim (spec §5.2, §8.2). */
|
|
21
25
|
export const qualifiers = ['WHEN', 'UNLESS', 'VIA', 'BECAUSE'];
|
|
22
26
|
/** The inverse-declaration verb (spec §5.5). */
|
|
23
27
|
export const REVERSE = 'REVERSE';
|
|
28
|
+
/** The verb-lifecycle declaration (spec §5.8). */
|
|
29
|
+
export const RENAMED_TO = 'RENAMED-TO';
|
|
24
30
|
/** The shape-expectation meta-verb (spec §20.1). */
|
|
25
31
|
export const EXPECTS = 'EXPECTS';
|
|
26
32
|
/** The standard inverse names (spec §5.5's declaration block). */
|
|
@@ -33,23 +39,25 @@ export const standard = [
|
|
|
33
39
|
...identity,
|
|
34
40
|
...causation,
|
|
35
41
|
...dependency,
|
|
36
|
-
...structure
|
|
42
|
+
...structure,
|
|
43
|
+
...comparison
|
|
37
44
|
];
|
|
38
45
|
const standardSet = new Set(standard);
|
|
39
46
|
const qualifierSet = new Set(qualifiers);
|
|
40
|
-
const knownSet = new Set([...standard, 'HAS', REVERSE, EXPECTS, ...standardInverses]);
|
|
47
|
+
const knownSet = new Set([...standard, 'HAS', REVERSE, RENAMED_TO, EXPECTS, ...standardInverses]);
|
|
41
48
|
/**
|
|
42
49
|
* @returns `true` if `s` has the lexical shape of a verb — an uppercase atom:
|
|
43
|
-
* uppercase letters
|
|
50
|
+
* an uppercase letter followed by uppercase letters or `-` (spec §16
|
|
51
|
+
* `uppercase_atom`, which permits a trailing hyphen).
|
|
44
52
|
*/
|
|
45
|
-
export const isVerbToken = (s) => /^[A-Z]
|
|
53
|
+
export const isVerbToken = (s) => /^[A-Z][A-Z-]*$/.test(s);
|
|
46
54
|
/** @returns `true` if `v` is one of the standard relational verbs. */
|
|
47
55
|
export const isStandard = (v) => standardSet.has(v);
|
|
48
56
|
/** @returns `true` if `v` is a qualifier verb (`WHEN`, `UNLESS`, `VIA`, `BECAUSE`). */
|
|
49
57
|
export const isQualifier = (v) => qualifierSet.has(v);
|
|
50
58
|
/**
|
|
51
59
|
* @returns `true` if `v` belongs to the known standard vocabulary —
|
|
52
|
-
* standard verbs, `HAS`, `REVERSE`, `EXPECTS`, and the standard §5.5
|
|
60
|
+
* standard verbs, `HAS`, `REVERSE`, `RENAMED-TO`, `EXPECTS`, and the standard §5.5
|
|
53
61
|
* inverse names.
|
|
54
62
|
* Used by the parser's indentation tiebreak: `USES JWT` is a continuation
|
|
55
63
|
* (JWT is not a known verb) while `API NEEDS auth` is a full triple.
|
package/dist/src/verb.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verb.js","sourceRoot":"","sources":["../../src/verb.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,mCAAmC;AACnC,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,IAAI,EAAE,KAAK,CAAU,CAAA;AAE/C,yCAAyC;AACzC,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAU,CAAA;AAE7E,wCAAwC;AACxC,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,CAAU,CAAA;AAE7D,6CAA6C;AAC7C,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAU,CAAA;AAEnF,0CAA0C;AAC1C,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,
|
|
1
|
+
{"version":3,"file":"verb.js","sourceRoot":"","sources":["../../src/verb.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,mCAAmC;AACnC,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,IAAI,EAAE,KAAK,CAAU,CAAA;AAE/C,yCAAyC;AACzC,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAU,CAAA;AAE7E,wCAAwC;AACxC,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,CAAU,CAAA;AAE7D,6CAA6C;AAC7C,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAU,CAAA;AAEnF,0CAA0C;AAC1C,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,UAAU,EAAE,UAAU,EAAE,IAAI,CAAU,CAAA;AAEhE,6DAA6D;AAC7D,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,SAAS,EAAE,UAAU,EAAE,aAAa,EAAE,YAAY,EAAE,QAAQ,EAAE,cAAc;CACpE,CAAA;AAEV,+EAA+E;AAC/E,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,CAAU,CAAA;AAIvE,gDAAgD;AAChD,MAAM,CAAC,MAAM,OAAO,GAAG,SAAS,CAAA;AAEhC,kDAAkD;AAClD,MAAM,CAAC,MAAM,UAAU,GAAG,YAAY,CAAA;AAEtC,oDAAoD;AACpD,MAAM,CAAC,MAAM,OAAO,GAAG,SAAS,CAAA;AAEhC,kEAAkE;AAClE,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS;IAC5C,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa;CAC9C,CAAA;AAEV,2DAA2D;AAC3D,MAAM,CAAC,MAAM,QAAQ,GAAoB;IACvC,GAAG,QAAQ;IACX,GAAG,SAAS;IACZ,GAAG,UAAU;IACb,GAAG,SAAS;IACZ,GAAG,UAAU;CACd,CAAA;AAED,MAAM,WAAW,GAAG,IAAI,GAAG,CAAS,QAAQ,CAAC,CAAA;AAC7C,MAAM,YAAY,GAAG,IAAI,GAAG,CAAS,UAAU,CAAC,CAAA;AAChD,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAS,CAAC,GAAG,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,gBAAgB,CAAC,CAAC,CAAA;AAEzG;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAS,EAAW,EAAE,CAChD,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AAE1B,sEAAsE;AACtE,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAS,EAAW,EAAE,CAC/C,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;AAEpB,uFAAuF;AACvF,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAS,EAAkB,EAAE,CACvD,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;AAErB;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,CAAS,EAAW,EAAE,CAC5C,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cavelang/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.29.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "CAVE domain model — claims, values, units, uncertainty, claim keys, UUIDv7 transactions.",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"cave",
|
|
8
|
+
"knowledge-graph",
|
|
9
|
+
"knowledge-representation",
|
|
10
|
+
"typescript"
|
|
11
|
+
],
|
|
12
|
+
"homepage": "https://github.com/mirek/cave#readme",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/mirek/cave/issues"
|
|
15
|
+
},
|
|
6
16
|
"license": "CC0-1.0",
|
|
7
17
|
"author": "Mirek Rusin (https://github.com/mirek)",
|
|
8
18
|
"repository": {
|
|
@@ -26,14 +36,15 @@
|
|
|
26
36
|
"src",
|
|
27
37
|
"!src/**/*.test.ts",
|
|
28
38
|
"README.md",
|
|
29
|
-
"License.md"
|
|
39
|
+
"License.md",
|
|
40
|
+
"Authors.md"
|
|
30
41
|
],
|
|
31
42
|
"publishConfig": {
|
|
32
43
|
"access": "public"
|
|
33
44
|
},
|
|
34
45
|
"scripts": {
|
|
35
46
|
"build": "tsc -b",
|
|
36
|
-
"test": "node --disable-warning=ExperimentalWarning --test
|
|
47
|
+
"test": "node --disable-warning=ExperimentalWarning --test \"test/*.test.ts\"",
|
|
37
48
|
"typecheck": "tsc -b"
|
|
38
49
|
}
|
|
39
50
|
}
|
package/src/claim.ts
CHANGED
|
@@ -15,6 +15,7 @@ import * as Value from './value.ts'
|
|
|
15
15
|
import * as Tag from './tag.ts'
|
|
16
16
|
import * as Context from './context.ts'
|
|
17
17
|
import * as Confidence from './confidence.ts'
|
|
18
|
+
import * as Uncertainty from './uncertainty.ts'
|
|
18
19
|
|
|
19
20
|
/** Subject or object term (spec §16: atom, literal or code literal). */
|
|
20
21
|
export type TermKind = 'entity' | 'text' | 'code'
|
|
@@ -106,20 +107,24 @@ export type Init = {
|
|
|
106
107
|
}
|
|
107
108
|
|
|
108
109
|
/** @returns claim with defaults applied (spec §6: all suffixes optional). */
|
|
109
|
-
export const of = (init: Init): Claim =>
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
110
|
+
export const of = (init: Init): Claim => {
|
|
111
|
+
if (init.delta !== undefined) Uncertainty.validateDelta(init.delta.num)
|
|
112
|
+
if (init.sigmaLevel !== undefined) Uncertainty.validateSigmaLevel(init.sigmaLevel)
|
|
113
|
+
return {
|
|
114
|
+
subject: init.subject,
|
|
115
|
+
verb: init.verb,
|
|
116
|
+
negated: init.negated ?? false,
|
|
117
|
+
payload: init.payload,
|
|
118
|
+
contexts: Context.dedupe(init.contexts ?? []),
|
|
119
|
+
tags: init.tags ?? [],
|
|
120
|
+
conf: init.conf ?? Confidence.defaultConfidence,
|
|
121
|
+
importance: init.importance ?? false,
|
|
122
|
+
...init.delta !== undefined ? { delta: init.delta } : {},
|
|
123
|
+
...init.sigmaLevel !== undefined ? { sigmaLevel: init.sigmaLevel } : {},
|
|
124
|
+
...init.comment !== undefined ? { comment: init.comment } : {},
|
|
125
|
+
raw: init.raw ?? ''
|
|
126
|
+
}
|
|
127
|
+
}
|
|
123
128
|
|
|
124
129
|
/** @returns relational claim payload. */
|
|
125
130
|
export const relation = (object: Term): Payload =>
|
|
@@ -145,4 +150,4 @@ export const none: Payload =
|
|
|
145
150
|
export const sigmaOf = (claim: Claim): undefined | number =>
|
|
146
151
|
claim.delta?.num === undefined ?
|
|
147
152
|
undefined :
|
|
148
|
-
claim.delta.num
|
|
153
|
+
Uncertainty.sigma(claim.delta.num, claim.sigmaLevel)
|
package/src/index.ts
CHANGED
|
@@ -16,6 +16,7 @@ export * as Context from './context.ts'
|
|
|
16
16
|
export * as Entity from './entity.ts'
|
|
17
17
|
export * as Key from './key.ts'
|
|
18
18
|
export * as Multiplier from './multiplier.ts'
|
|
19
|
+
export * as SourceSpan from './source-span.ts'
|
|
19
20
|
export * as Tag from './tag.ts'
|
|
20
21
|
export * as Time from './time.ts'
|
|
21
22
|
export * as Uncertainty from './uncertainty.ts'
|
|
@@ -23,3 +24,4 @@ export * as Uuidv7 from './uuidv7.ts'
|
|
|
23
24
|
export * as Value from './value.ts'
|
|
24
25
|
export * as Verb from './verb.ts'
|
|
25
26
|
export * as Version from './version.ts'
|
|
27
|
+
export type { LineSpan, Reference as SourceReference } from './source-span.ts'
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/** Stable source-line provenance carried by `src:` contexts (spec §9.8). */
|
|
2
|
+
|
|
3
|
+
import type { Context } from './context.ts'
|
|
4
|
+
|
|
5
|
+
export type LineSpan = {
|
|
6
|
+
/** One-based first source line. */
|
|
7
|
+
readonly startLine: number
|
|
8
|
+
/** One-based inclusive last source line. */
|
|
9
|
+
readonly endLine: number
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type Reference = {
|
|
13
|
+
/** Canonical stored context, without the leading `@`. */
|
|
14
|
+
readonly context: Context
|
|
15
|
+
/** Decoded underlying source identity, without the line fragment. */
|
|
16
|
+
readonly source: string
|
|
17
|
+
readonly span?: LineSpan
|
|
18
|
+
/** Human-facing source plus line fragment. */
|
|
19
|
+
readonly location: string
|
|
20
|
+
/** Navigable location when the source is an HTTP(S) URL. */
|
|
21
|
+
readonly href?: string
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const lineFragment = (span: LineSpan): string =>
|
|
25
|
+
span.startLine === span.endLine ? `L${span.startLine}` : `L${span.startLine}-L${span.endLine}`
|
|
26
|
+
|
|
27
|
+
const validSpan = (span: LineSpan): boolean =>
|
|
28
|
+
Number.isInteger(span.startLine) && Number.isInteger(span.endLine) &&
|
|
29
|
+
span.startLine >= 1 && span.endLine >= span.startLine
|
|
30
|
+
|
|
31
|
+
/** Percent-escape a source while keeping readable path and URL separators. */
|
|
32
|
+
export const escape = (source: string): string =>
|
|
33
|
+
encodeURIComponent(source)
|
|
34
|
+
.replace(/[!'()*]/g, char => `%${char.charCodeAt(0).toString(16).toUpperCase()}`)
|
|
35
|
+
.replaceAll('%2F', '/')
|
|
36
|
+
.replaceAll('%3A', ':')
|
|
37
|
+
|
|
38
|
+
/** Reverse {@link escape}; malformed percent encodings are rejected. */
|
|
39
|
+
export const unescape = (source: string): undefined | string => {
|
|
40
|
+
try {
|
|
41
|
+
return decodeURIComponent(source)
|
|
42
|
+
} catch {
|
|
43
|
+
return undefined
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Build a canonical `src:` context from a source and optional line span. */
|
|
48
|
+
export const context = (source: string, span?: LineSpan): Context => {
|
|
49
|
+
if (source === '') {
|
|
50
|
+
throw new Error('source must not be empty')
|
|
51
|
+
}
|
|
52
|
+
if (span !== undefined && !validSpan(span)) {
|
|
53
|
+
throw new Error(`invalid source line span ${JSON.stringify(span)}`)
|
|
54
|
+
}
|
|
55
|
+
return `src:${escape(source)}${span === undefined ? '' : `#${lineFragment(span)}`}`
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Parse one canonical source context, preserving an unspanned source too. */
|
|
59
|
+
export const parse = (value: Context): undefined | Reference => {
|
|
60
|
+
if (!value.startsWith('src:')) {
|
|
61
|
+
return undefined
|
|
62
|
+
}
|
|
63
|
+
const payload = value.slice(4)
|
|
64
|
+
const hashAt = payload.indexOf('#')
|
|
65
|
+
const encodedSource = hashAt === -1 ? payload : payload.slice(0, hashAt)
|
|
66
|
+
const fragment = hashAt === -1 ? undefined : payload.slice(hashAt + 1)
|
|
67
|
+
const match = fragment === undefined ? undefined : /^L([1-9]\d*)(?:-L([1-9]\d*))?$/.exec(fragment)
|
|
68
|
+
if (encodedSource === '' || (fragment !== undefined && match === null)) {
|
|
69
|
+
return undefined
|
|
70
|
+
}
|
|
71
|
+
const source = unescape(encodedSource)
|
|
72
|
+
if (source === undefined || escape(source) !== encodedSource) {
|
|
73
|
+
return undefined
|
|
74
|
+
}
|
|
75
|
+
const start = match == null ? undefined : Number(match[1])
|
|
76
|
+
const end = start === undefined || match == null ? undefined : Number(match[2] ?? match[1])
|
|
77
|
+
const span = start === undefined ? undefined : { startLine: start, endLine: end! }
|
|
78
|
+
if (span !== undefined && !validSpan(span)) {
|
|
79
|
+
return undefined
|
|
80
|
+
}
|
|
81
|
+
const location = `${source}${span === undefined ? '' : `#${lineFragment(span)}`}`
|
|
82
|
+
const href = /^https?:\/\//i.test(source) && !source.includes('#') ?
|
|
83
|
+
`${encodeURI(source)}${span === undefined ? '' : `#${lineFragment(span)}`}` : undefined
|
|
84
|
+
return {
|
|
85
|
+
context: value,
|
|
86
|
+
source,
|
|
87
|
+
...span === undefined ? {} : { span },
|
|
88
|
+
location,
|
|
89
|
+
...href === undefined ? {} : { href }
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** Parse every valid `src:` context, in authored order. */
|
|
94
|
+
export const ofContexts = (contexts: readonly Context[]): Reference[] =>
|
|
95
|
+
contexts.flatMap(value => {
|
|
96
|
+
const reference = parse(value)
|
|
97
|
+
return reference === undefined ? [] : [reference]
|
|
98
|
+
})
|
package/src/time.ts
CHANGED
|
@@ -24,6 +24,9 @@ export type Period = {
|
|
|
24
24
|
|
|
25
25
|
export type t = Period
|
|
26
26
|
|
|
27
|
+
/** A query boundary as a UTC half-open interval. */
|
|
28
|
+
export type Boundary = Period
|
|
29
|
+
|
|
27
30
|
/** How a context reads as time: a point period, or a `..` range. */
|
|
28
31
|
export type TimeContext =
|
|
29
32
|
| { readonly kind: 'point', readonly period: Period }
|
|
@@ -31,8 +34,14 @@ export type TimeContext =
|
|
|
31
34
|
|
|
32
35
|
const dayMs = 86_400_000
|
|
33
36
|
|
|
34
|
-
const utcDay = (year: number, month: number, day: number): number =>
|
|
35
|
-
Date.UTC
|
|
37
|
+
const utcDay = (year: number, month: number, day: number): number => {
|
|
38
|
+
// Date.UTC treats years 0..99 as 1900..1999. Setting the full year on an
|
|
39
|
+
// existing date preserves the four-digit year written in the CAVE value.
|
|
40
|
+
const date = new Date(0)
|
|
41
|
+
date.setUTCHours(0, 0, 0, 0)
|
|
42
|
+
date.setUTCFullYear(year, month - 1, day)
|
|
43
|
+
return date.getTime()
|
|
44
|
+
}
|
|
36
45
|
|
|
37
46
|
/** Monday starting ISO week `week` of `year` (ISO 8601: week 1 contains Jan 4). */
|
|
38
47
|
const isoWeekStart = (year: number, week: number): number => {
|
|
@@ -70,6 +79,10 @@ export const parsePeriod = (text: string): undefined | Period => {
|
|
|
70
79
|
return undefined
|
|
71
80
|
}
|
|
72
81
|
const start = isoWeekStart(year, w)
|
|
82
|
+
// Only years whose next ISO week-year starts after week 53 have one.
|
|
83
|
+
if (start >= isoWeekStart(year + 1, 1)) {
|
|
84
|
+
return undefined
|
|
85
|
+
}
|
|
73
86
|
return { start, end: start + 7 * dayMs }
|
|
74
87
|
}
|
|
75
88
|
if (month !== undefined) {
|
|
@@ -154,6 +167,40 @@ export const ofContext = (context: string): undefined | TimeContext => {
|
|
|
154
167
|
return period === undefined ? undefined : { kind: 'point', period }
|
|
155
168
|
}
|
|
156
169
|
|
|
170
|
+
const timestampRe = /^(\d{4}-\d{2}-\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.(\d+))?([zZ]|[+-]\d{2}:\d{2})?$/
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Parses an ISO timestamp into a UTC instant. An omitted offset means UTC,
|
|
174
|
+
* never the host's local timezone; explicit `Z` and numeric offsets retain
|
|
175
|
+
* their usual ISO meaning. Date and clock fields are validated before the
|
|
176
|
+
* platform parser can normalize them.
|
|
177
|
+
*/
|
|
178
|
+
export const parseTimestamp = (text: string): undefined | number => {
|
|
179
|
+
const match = timestampRe.exec(text)
|
|
180
|
+
if (match === null) return undefined
|
|
181
|
+
const [, date, hour, minute, second, , zone] = match
|
|
182
|
+
if (parsePeriod(date!) === undefined || Number(hour) > 23 || Number(minute) > 59 || Number(second) > 59) {
|
|
183
|
+
return undefined
|
|
184
|
+
}
|
|
185
|
+
if (zone !== undefined && zone !== 'Z' && zone !== 'z') {
|
|
186
|
+
const [offsetHour, offsetMinute] = zone.slice(1).split(':').map(Number)
|
|
187
|
+
if (offsetHour! > 23 || offsetMinute! > 59) return undefined
|
|
188
|
+
}
|
|
189
|
+
const parsed = Date.parse(zone === undefined ? `${text}Z` : text)
|
|
190
|
+
return Number.isNaN(parsed) ? undefined : parsed
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Parses the shared query-time boundary: a date-like period keeps its whole
|
|
195
|
+
* UTC interval, while a timestamp covers one second from its exact instant.
|
|
196
|
+
*/
|
|
197
|
+
export const parseBoundary = (text: string): undefined | Boundary => {
|
|
198
|
+
const period = parsePeriod(text)
|
|
199
|
+
if (period !== undefined) return period
|
|
200
|
+
const start = parseTimestamp(text)
|
|
201
|
+
return start === undefined ? undefined : { start, end: start + 1_000 }
|
|
202
|
+
}
|
|
203
|
+
|
|
157
204
|
/**
|
|
158
205
|
* Parses a query anchor into an instant (ms since epoch): a date-like
|
|
159
206
|
* period reads as its *start* instant (`2026` is 2026-01-01T00:00:00Z —
|
|
@@ -161,15 +208,7 @@ export const ofContext = (context: string): undefined | TimeContext => {
|
|
|
161
208
|
* exactly. @returns `undefined` when `text` is neither.
|
|
162
209
|
*/
|
|
163
210
|
export const parseInstant = (text: string): undefined | number => {
|
|
164
|
-
|
|
165
|
-
if (period !== undefined) {
|
|
166
|
-
return period.start
|
|
167
|
-
}
|
|
168
|
-
if (!text.includes('T')) {
|
|
169
|
-
return undefined
|
|
170
|
-
}
|
|
171
|
-
const parsed = Date.parse(text)
|
|
172
|
-
return Number.isNaN(parsed) ? undefined : parsed
|
|
211
|
+
return parseBoundary(text)?.start
|
|
173
212
|
}
|
|
174
213
|
|
|
175
214
|
/** @returns whether a time context covers the instant (spec §32.4). */
|
package/src/uncertainty.ts
CHANGED
|
@@ -16,12 +16,43 @@
|
|
|
16
16
|
/** Default σ level when `(Nσ)` is omitted (spec §7.2). */
|
|
17
17
|
export const defaultSigmaLevel = 2
|
|
18
18
|
|
|
19
|
+
export type Field = 'uncertainty delta' | 'sigma level' | 'sigma'
|
|
20
|
+
|
|
21
|
+
/** Typed failure for uncertainty values that cannot define a finite distribution. */
|
|
22
|
+
export class InvalidUncertaintyError extends RangeError {
|
|
23
|
+
readonly field: Field
|
|
24
|
+
readonly value: unknown
|
|
25
|
+
|
|
26
|
+
constructor(field: Field, value: unknown) {
|
|
27
|
+
super(`Expected positive finite ${field}, got ${String(value)}.`)
|
|
28
|
+
this.name = 'InvalidUncertaintyError'
|
|
29
|
+
this.field = field
|
|
30
|
+
this.value = value
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const positiveFinite = (field: Field, value: unknown): number => {
|
|
35
|
+
if (typeof value !== 'number' || !Number.isFinite(value) || !(value > 0)) {
|
|
36
|
+
throw new InvalidUncertaintyError(field, value)
|
|
37
|
+
}
|
|
38
|
+
return value
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Validates a `+/-` interval half-width. */
|
|
42
|
+
export const validateDelta = (value: unknown): number =>
|
|
43
|
+
positiveFinite('uncertainty delta', value)
|
|
44
|
+
|
|
45
|
+
/** Validates the `N` in an `(Nσ)` override. */
|
|
46
|
+
export const validateSigmaLevel = (value: unknown): number =>
|
|
47
|
+
positiveFinite('sigma level', value)
|
|
48
|
+
|
|
49
|
+
/** Validates a directly supplied standard deviation. */
|
|
50
|
+
export const validateSigma = (value: unknown): number =>
|
|
51
|
+
positiveFinite('sigma', value)
|
|
52
|
+
|
|
19
53
|
/** @returns σ from an interval `delta` given at `level`σ: σ = Δ / k. */
|
|
20
54
|
export const sigma = (delta: number, level: number = defaultSigmaLevel): number => {
|
|
21
|
-
|
|
22
|
-
throw new Error(`Expected positive sigma level, got ${level}.`)
|
|
23
|
-
}
|
|
24
|
-
return delta / level
|
|
55
|
+
return validateSigma(validateDelta(delta) / validateSigmaLevel(level))
|
|
25
56
|
}
|
|
26
57
|
|
|
27
58
|
/** @returns symmetric `[low, high]` interval around `mean`. */
|
package/src/uuidv7.ts
CHANGED
|
@@ -104,3 +104,19 @@ export const observe = (id: string): void => {
|
|
|
104
104
|
lastSeq = seq
|
|
105
105
|
}
|
|
106
106
|
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Runs synchronous speculative work without retaining UUID generator state.
|
|
110
|
+
* Database dry-runs use this alongside transaction rollback so explicit-id
|
|
111
|
+
* observations and locally minted rows are both absent after the preview.
|
|
112
|
+
*/
|
|
113
|
+
export const withStatePreserved = <T>(body: () => T): T => {
|
|
114
|
+
const savedMs = lastMs
|
|
115
|
+
const savedSeq = lastSeq
|
|
116
|
+
try {
|
|
117
|
+
return body()
|
|
118
|
+
} finally {
|
|
119
|
+
lastMs = savedMs
|
|
120
|
+
lastSeq = savedSeq
|
|
121
|
+
}
|
|
122
|
+
}
|
package/src/value.ts
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
22
|
import * as Multiplier from './multiplier.ts'
|
|
23
|
+
import { parsePeriod } from './time.ts'
|
|
23
24
|
|
|
24
25
|
/** How the value text was classified. */
|
|
25
26
|
export type Kind =
|
|
@@ -54,18 +55,17 @@ export type t = Value
|
|
|
54
55
|
|
|
55
56
|
const numberRe = /^(-?\d+(?:\.\d+)?)([A-Za-z%]*)$/
|
|
56
57
|
const unitRe = /^[A-Za-z%$][A-Za-z0-9%$]*(?:\/[A-Za-z0-9%$]+)*$/
|
|
57
|
-
const dateRe = /^\d{4}-(?:H[1-2]|Q[1-4]|W\d{1,2}|\d{2})(?:-\d{2})?$/
|
|
58
|
-
|
|
59
58
|
/** @returns `true` if `s` is a valid unit expression (`USD/yr`, `ms`, `%`). */
|
|
60
59
|
export const isUnit = (s: string): boolean =>
|
|
61
60
|
unitRe.test(s)
|
|
62
61
|
|
|
63
62
|
/**
|
|
64
63
|
* @returns `true` if `s` is date-like (spec §16 `date_like`): `2026-H2`,
|
|
65
|
-
* `2026-Q1`, `2026-04`, `2026-04-10`.
|
|
64
|
+
* `2026-Q1`, `2026-04`, `2026-04-10`. Calendar validity is shared with
|
|
65
|
+
* {@link parsePeriod}; a bare year parses as a number instead.
|
|
66
66
|
*/
|
|
67
67
|
export const isDateLike = (s: string): boolean =>
|
|
68
|
-
|
|
68
|
+
s.includes('-') && parsePeriod(s) !== undefined
|
|
69
69
|
|
|
70
70
|
type Numeric = { num: number, unit?: string }
|
|
71
71
|
|
package/src/verb.ts
CHANGED
|
@@ -25,7 +25,12 @@ export const causation = ['CAUSE', 'FIX', 'BECOMES'] as const
|
|
|
25
25
|
export const dependency = ['NEEDS', 'USES', 'YIELDS', 'ENABLES', 'BLOCKS'] as const
|
|
26
26
|
|
|
27
27
|
/** Structure and ordering (spec §5.2). */
|
|
28
|
-
export const structure = ['CONTAINS', 'PRECEDES', '
|
|
28
|
+
export const structure = ['CONTAINS', 'PRECEDES', 'VS'] as const
|
|
29
|
+
|
|
30
|
+
/** Canonical verbs for qualifier comparisons (spec §8.2). */
|
|
31
|
+
export const comparison = [
|
|
32
|
+
'EXCEEDS', 'IS-BELOW', 'IS-AT-LEAST', 'IS-AT-MOST', 'EQUALS', 'DIFFERS-FROM'
|
|
33
|
+
] as const
|
|
29
34
|
|
|
30
35
|
/** Qualifier verbs — appear indented under another claim (spec §5.2, §8.2). */
|
|
31
36
|
export const qualifiers = ['WHEN', 'UNLESS', 'VIA', 'BECAUSE'] as const
|
|
@@ -35,6 +40,9 @@ export type Qualifier = (typeof qualifiers)[number]
|
|
|
35
40
|
/** The inverse-declaration verb (spec §5.5). */
|
|
36
41
|
export const REVERSE = 'REVERSE'
|
|
37
42
|
|
|
43
|
+
/** The verb-lifecycle declaration (spec §5.8). */
|
|
44
|
+
export const RENAMED_TO = 'RENAMED-TO'
|
|
45
|
+
|
|
38
46
|
/** The shape-expectation meta-verb (spec §20.1). */
|
|
39
47
|
export const EXPECTS = 'EXPECTS'
|
|
40
48
|
|
|
@@ -49,19 +57,21 @@ export const standard: readonly Verb[] = [
|
|
|
49
57
|
...identity,
|
|
50
58
|
...causation,
|
|
51
59
|
...dependency,
|
|
52
|
-
...structure
|
|
60
|
+
...structure,
|
|
61
|
+
...comparison
|
|
53
62
|
]
|
|
54
63
|
|
|
55
64
|
const standardSet = new Set<string>(standard)
|
|
56
65
|
const qualifierSet = new Set<string>(qualifiers)
|
|
57
|
-
const knownSet = new Set<string>([...standard, 'HAS', REVERSE, EXPECTS, ...standardInverses])
|
|
66
|
+
const knownSet = new Set<string>([...standard, 'HAS', REVERSE, RENAMED_TO, EXPECTS, ...standardInverses])
|
|
58
67
|
|
|
59
68
|
/**
|
|
60
69
|
* @returns `true` if `s` has the lexical shape of a verb — an uppercase atom:
|
|
61
|
-
* uppercase letters
|
|
70
|
+
* an uppercase letter followed by uppercase letters or `-` (spec §16
|
|
71
|
+
* `uppercase_atom`, which permits a trailing hyphen).
|
|
62
72
|
*/
|
|
63
73
|
export const isVerbToken = (s: string): boolean =>
|
|
64
|
-
/^[A-Z]
|
|
74
|
+
/^[A-Z][A-Z-]*$/.test(s)
|
|
65
75
|
|
|
66
76
|
/** @returns `true` if `v` is one of the standard relational verbs. */
|
|
67
77
|
export const isStandard = (v: string): boolean =>
|
|
@@ -73,7 +83,7 @@ export const isQualifier = (v: string): v is Qualifier =>
|
|
|
73
83
|
|
|
74
84
|
/**
|
|
75
85
|
* @returns `true` if `v` belongs to the known standard vocabulary —
|
|
76
|
-
* standard verbs, `HAS`, `REVERSE`, `EXPECTS`, and the standard §5.5
|
|
86
|
+
* standard verbs, `HAS`, `REVERSE`, `RENAMED-TO`, `EXPECTS`, and the standard §5.5
|
|
77
87
|
* inverse names.
|
|
78
88
|
* Used by the parser's indentation tiebreak: `USES JWT` is a continuation
|
|
79
89
|
* (JWT is not a known verb) while `API NEEDS auth` is a full triple.
|