behavior-contracts 0.1.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/LICENSE +21 -0
- package/README.md +58 -0
- package/dist/canonical.d.ts +46 -0
- package/dist/canonical.d.ts.map +1 -0
- package/dist/canonical.js +182 -0
- package/dist/canonical.js.map +1 -0
- package/dist/codec.d.ts +24 -0
- package/dist/codec.d.ts.map +1 -0
- package/dist/codec.js +65 -0
- package/dist/codec.js.map +1 -0
- package/dist/envelope.d.ts +34 -0
- package/dist/envelope.d.ts.map +1 -0
- package/dist/envelope.js +61 -0
- package/dist/envelope.js.map +1 -0
- package/dist/expr-eval.d.ts +28 -0
- package/dist/expr-eval.d.ts.map +1 -0
- package/dist/expr-eval.js +334 -0
- package/dist/expr-eval.js.map +1 -0
- package/dist/guard.d.ts +27 -0
- package/dist/guard.d.ts.map +1 -0
- package/dist/guard.js +43 -0
- package/dist/guard.js.map +1 -0
- package/dist/index.d.ts +43 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +46 -0
- package/dist/index.js.map +1 -0
- package/dist/plan.d.ts +82 -0
- package/dist/plan.d.ts.map +1 -0
- package/dist/plan.js +127 -0
- package/dist/plan.js.map +1 -0
- package/dist/template.d.ts +35 -0
- package/dist/template.d.ts.map +1 -0
- package/dist/template.js +66 -0
- package/dist/template.js.map +1 -0
- package/package.json +62 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 foo-ogawa
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# behavior-contracts
|
|
2
|
+
|
|
3
|
+
Language-agnostic runtime **core** for behavior contracts (the `dsl-contracts`
|
|
4
|
+
project). It is the TypeScript reference implementation of the shared, thin
|
|
5
|
+
DSL→Metadata→IR→Runtime primitives — the single source of truth that the
|
|
6
|
+
Python, Rust, and Go runtimes conform to via a shared 93-vector conformance
|
|
7
|
+
suite.
|
|
8
|
+
|
|
9
|
+
> This package publishes **only** the COMMON primitives judged portable in
|
|
10
|
+
> `runtime-boundary.md`. Backend execution, key resolution, retry tuning, and
|
|
11
|
+
> hydrate logic are consumer-specific and are intentionally **not** included.
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm i behavior-contracts
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Requires Node.js >= 22 (ESM only).
|
|
20
|
+
|
|
21
|
+
## Public primitives
|
|
22
|
+
|
|
23
|
+
| Export | Purpose |
|
|
24
|
+
|---|---|
|
|
25
|
+
| `validateEnvelope` | spec-version fail-closed validation (loud-rejects unknown versions) |
|
|
26
|
+
| `evaluateExpression` | evaluate the portable expression IR |
|
|
27
|
+
| `renderTemplate` | pure `{param}` string substitution |
|
|
28
|
+
| `runPlan` | execute the portable execution-plan IR |
|
|
29
|
+
| `canonicalValue` / `canonicalJson` | deterministic canonical serialization (sorted keys, compact JSON, `repr(float)`-parity decimals) |
|
|
30
|
+
|
|
31
|
+
## Usage
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
import { validateEnvelope, renderTemplate, canonicalJson } from "behavior-contracts";
|
|
35
|
+
|
|
36
|
+
validateEnvelope(envelope); // throws on unknown/incompatible spec version
|
|
37
|
+
|
|
38
|
+
renderTemplate("hello {name}", { name: "world" }); // "hello world"
|
|
39
|
+
|
|
40
|
+
canonicalJson({ b: 1, a: 2 }); // '{"a":2,"b":1}'
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Spec versions
|
|
44
|
+
|
|
45
|
+
This package tracks the IR/vector protocol versions independently from its
|
|
46
|
+
library (semver) version:
|
|
47
|
+
|
|
48
|
+
| Spec | Version |
|
|
49
|
+
|---|---|
|
|
50
|
+
| expression | 1 |
|
|
51
|
+
| template | 1 |
|
|
52
|
+
| plan | 1 |
|
|
53
|
+
| canonical | 1 |
|
|
54
|
+
| envelope | 1.1 |
|
|
55
|
+
|
|
56
|
+
## License
|
|
57
|
+
|
|
58
|
+
MIT — see [LICENSE](./LICENSE).
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* canonical.ts — canonical-serialization.md の参照実装(doc-grade, COMMON)。
|
|
3
|
+
*
|
|
4
|
+
* 提供する 3 プリミティブ:
|
|
5
|
+
* - pyFloatRepr(n) : CPython repr(float) 相当の正準10進(parity SSoT = Python)
|
|
6
|
+
* - canonicalValue(v) : key identity(トップレベルのみキーソート) — §2 serializeContractKey
|
|
7
|
+
* - canonicalJson(v) : fingerprint(全階層キーソート) — §3 canonicalJson
|
|
8
|
+
*
|
|
9
|
+
* 値モデルは expr-eval.ts と共有(bigint=int / number=float / string / bool / null / arr / obj)。
|
|
10
|
+
* 型付き値エンコード({int:"..."} / {float:n})は canonicalJson/canonicalValue が
|
|
11
|
+
* 「値」を直列化するときの中間表現ではなく、expr-eval.encodeValue(IR 層)が担う点に注意
|
|
12
|
+
* (canonical-serialization.md §4.3: IR 直列化と値直列化は別層)。ここでは runtime 値の直列化を扱う:
|
|
13
|
+
* - int(bigint) → 素の JSON 整数(範囲外も 10 進整数として素通し。DynamoDB N 値層)
|
|
14
|
+
* - float(number)→ pyFloatRepr(§4.1)。NaN/±Inf は Failure(§4.1-6)
|
|
15
|
+
*
|
|
16
|
+
* canonical-serialization.md §4.1 の CPython format_float_short('r') を移植する。
|
|
17
|
+
*/
|
|
18
|
+
import type { Value } from "./expr-eval.js";
|
|
19
|
+
export type CanonicalFailureCode = "NAN_OR_INF" | "INVALID_VALUE";
|
|
20
|
+
export declare class CanonicalFailure extends Error {
|
|
21
|
+
code: CanonicalFailureCode;
|
|
22
|
+
constructor(code: CanonicalFailureCode, message: string);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* pyFloatRepr — CPython の repr(float) / json.dumps(float) と byte 一致する 10 進表現。
|
|
26
|
+
*
|
|
27
|
+
* 規則(canonical-serialization.md §4.1 / CPython format_float_short('r')):
|
|
28
|
+
* 1. 最短往復 digits(JS の Number.prototype.toString(10) は shortest round-trip を出す)。
|
|
29
|
+
* 2. scientific 判定: decpt <= -4 || decpt > 16 のとき指数表記。
|
|
30
|
+
* 3. 指数は符号つき・最低 2 桁 zero-pad(e+05 / e-07)。
|
|
31
|
+
* 4. 整数値 float は `.0` を保つ(123 → "123.0")。
|
|
32
|
+
* 5. -0.0 は "-0.0"、+0.0 は "0.0"(signbit で復元)。
|
|
33
|
+
* 6. NaN / ±Inf は Failure。
|
|
34
|
+
*
|
|
35
|
+
* decpt は「10 進小数点の位置」= CPython の decpt。digits d1d2… に対し値 = 0.d1d2… × 10^decpt。
|
|
36
|
+
*/
|
|
37
|
+
export declare function pyFloatRepr(n: number): string;
|
|
38
|
+
/**
|
|
39
|
+
* canonicalValue — key identity 用の正準直列化。
|
|
40
|
+
* トップレベル object のキーのみ昇順ソートし、compact JSON を返す。
|
|
41
|
+
* ネスト値は挿入順のまま(canonical-serialization.md §2 の注: ネスト key identity は canonicalJson を使う)。
|
|
42
|
+
*/
|
|
43
|
+
export declare function canonicalValue(v: Value): string;
|
|
44
|
+
/** canonicalJson — fingerprint 用。全 object 階層のキーを昇順ソート(配列は順序保持)。 */
|
|
45
|
+
export declare function canonicalJson(v: Value): string;
|
|
46
|
+
//# sourceMappingURL=canonical.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canonical.d.ts","sourceRoot":"","sources":["../src/canonical.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAI5C,MAAM,MAAM,oBAAoB,GAC5B,YAAY,GACZ,eAAe,CAAC;AAEpB,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,IAAI,EAAE,oBAAoB,CAAC;gBACf,IAAI,EAAE,oBAAoB,EAAE,OAAO,EAAE,MAAM;CAKxD;AAOD;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAmB7C;AA+ED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,KAAK,GAAG,MAAM,CAO/C;AAGD,mEAAmE;AACnE,wBAAgB,aAAa,CAAC,CAAC,EAAE,KAAK,GAAG,MAAM,CAQ9C"}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { cmpCodePoints } from "./expr-eval.js";
|
|
2
|
+
export class CanonicalFailure extends Error {
|
|
3
|
+
code;
|
|
4
|
+
constructor(code, message) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.code = code;
|
|
7
|
+
this.name = "CanonicalFailure";
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
function fail(code, message) {
|
|
11
|
+
throw new CanonicalFailure(code, message);
|
|
12
|
+
}
|
|
13
|
+
// ── §4.1 float の正準10進(CPython repr(float))────────────────────────────────
|
|
14
|
+
/**
|
|
15
|
+
* pyFloatRepr — CPython の repr(float) / json.dumps(float) と byte 一致する 10 進表現。
|
|
16
|
+
*
|
|
17
|
+
* 規則(canonical-serialization.md §4.1 / CPython format_float_short('r')):
|
|
18
|
+
* 1. 最短往復 digits(JS の Number.prototype.toString(10) は shortest round-trip を出す)。
|
|
19
|
+
* 2. scientific 判定: decpt <= -4 || decpt > 16 のとき指数表記。
|
|
20
|
+
* 3. 指数は符号つき・最低 2 桁 zero-pad(e+05 / e-07)。
|
|
21
|
+
* 4. 整数値 float は `.0` を保つ(123 → "123.0")。
|
|
22
|
+
* 5. -0.0 は "-0.0"、+0.0 は "0.0"(signbit で復元)。
|
|
23
|
+
* 6. NaN / ±Inf は Failure。
|
|
24
|
+
*
|
|
25
|
+
* decpt は「10 進小数点の位置」= CPython の decpt。digits d1d2… に対し値 = 0.d1d2… × 10^decpt。
|
|
26
|
+
*/
|
|
27
|
+
export function pyFloatRepr(n) {
|
|
28
|
+
if (Number.isNaN(n) || !Number.isFinite(n))
|
|
29
|
+
fail("NAN_OR_INF", `non-finite float cannot be serialized: ${n}`);
|
|
30
|
+
// §4.1-5: 符号 0 の扱い。-0.0 を signbit で捕捉。
|
|
31
|
+
if (n === 0)
|
|
32
|
+
return Object.is(n, -0) ? "-0.0" : "0.0";
|
|
33
|
+
const neg = n < 0;
|
|
34
|
+
const abs = Math.abs(n);
|
|
35
|
+
// 最短往復の有効数字列と 10 進指数を得る(JS の toExponential は shortest を返さないので
|
|
36
|
+
// まず toString で shortest digits を確保し、そこから digits/decpt を導出する)。
|
|
37
|
+
const { digits, decpt } = shortestDigits(abs);
|
|
38
|
+
const body = decpt <= -4 || decpt > 16
|
|
39
|
+
? formatScientific(digits, decpt)
|
|
40
|
+
: formatFixed(digits, decpt);
|
|
41
|
+
return neg ? "-" + body : body;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* shortestDigits — 正の有限 float から shortest round-trip の
|
|
45
|
+
* digits(先頭ゼロ・末尾ゼロを除いた有効数字列)と decpt(10 進小数点位置)を得る。
|
|
46
|
+
* 値 = 0.<digits> × 10^decpt(CPython の David Gay mode 0 と同じ意味の decpt)。
|
|
47
|
+
*/
|
|
48
|
+
function shortestDigits(abs) {
|
|
49
|
+
// JS の Number#toString(10) は shortest round-trip を出す。
|
|
50
|
+
// これを指数表記に正規化して digits と 10 進指数 e(値 = d.ddd × 10^e)を取り出す。
|
|
51
|
+
const s = abs.toString(); // 例: "123", "1.5", "1e-7", "1.25e+30"
|
|
52
|
+
let mantissa;
|
|
53
|
+
let exp;
|
|
54
|
+
const eIdx = s.indexOf("e");
|
|
55
|
+
if (eIdx >= 0) {
|
|
56
|
+
mantissa = s.slice(0, eIdx);
|
|
57
|
+
exp = parseInt(s.slice(eIdx + 1), 10);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
mantissa = s;
|
|
61
|
+
exp = 0;
|
|
62
|
+
}
|
|
63
|
+
// mantissa を "整数部.小数部" に分解し、全 digits と小数点位置を求める。
|
|
64
|
+
const dot = mantissa.indexOf(".");
|
|
65
|
+
let intPart;
|
|
66
|
+
let fracPart;
|
|
67
|
+
if (dot >= 0) {
|
|
68
|
+
intPart = mantissa.slice(0, dot);
|
|
69
|
+
fracPart = mantissa.slice(dot + 1);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
intPart = mantissa;
|
|
73
|
+
fracPart = "";
|
|
74
|
+
}
|
|
75
|
+
// 全 digit 列(小数点を除去)と、その先頭からの小数点位置(整数部の桁数)。
|
|
76
|
+
let allDigits = intPart + fracPart;
|
|
77
|
+
// decpt(暫定) = 整数部桁数 + exp(値 = <allDigits を 0.d… とみなす> × 10^decpt)
|
|
78
|
+
let decpt = intPart.length + exp;
|
|
79
|
+
// 先頭ゼロを除去し decpt を調整("0025" → digits="25", 先頭 2 ゼロぶん decpt を減らす)。
|
|
80
|
+
let lead = 0;
|
|
81
|
+
while (lead < allDigits.length - 1 && allDigits[lead] === "0")
|
|
82
|
+
lead++;
|
|
83
|
+
if (lead > 0) {
|
|
84
|
+
allDigits = allDigits.slice(lead);
|
|
85
|
+
decpt -= lead;
|
|
86
|
+
}
|
|
87
|
+
// 末尾ゼロを除去(有効数字のみ残す)。
|
|
88
|
+
allDigits = allDigits.replace(/0+$/, "");
|
|
89
|
+
if (allDigits === "") {
|
|
90
|
+
// 値 0(呼び出し側で 0 は処理済みなので通常到達しない)。
|
|
91
|
+
return { digits: "0", decpt: 1 };
|
|
92
|
+
}
|
|
93
|
+
return { digits: allDigits, decpt };
|
|
94
|
+
}
|
|
95
|
+
/** 固定小数点表記。整数値 float は `.0` を付ける(§4.1-4)。 */
|
|
96
|
+
function formatFixed(digits, decpt) {
|
|
97
|
+
if (decpt <= 0) {
|
|
98
|
+
// 0.00ddd 形式。小数点直後に (-decpt) 個のゼロ。
|
|
99
|
+
return "0." + "0".repeat(-decpt) + digits;
|
|
100
|
+
}
|
|
101
|
+
if (decpt >= digits.length) {
|
|
102
|
+
// 整数値。末尾ゼロを補い `.0` を付ける。
|
|
103
|
+
return digits + "0".repeat(decpt - digits.length) + ".0";
|
|
104
|
+
}
|
|
105
|
+
// 小数点が digits の途中。
|
|
106
|
+
return digits.slice(0, decpt) + "." + digits.slice(decpt);
|
|
107
|
+
}
|
|
108
|
+
/** 指数表記。d.ddde±XX(指数は最低 2 桁 zero-pad)(§4.1-2/3)。 */
|
|
109
|
+
function formatScientific(digits, decpt) {
|
|
110
|
+
// CPython: 仮数は d1.d2d3…、指数 = decpt - 1。
|
|
111
|
+
const first = digits[0];
|
|
112
|
+
const rest = digits.slice(1);
|
|
113
|
+
const mant = rest.length > 0 ? `${first}.${rest}` : first;
|
|
114
|
+
const e = decpt - 1;
|
|
115
|
+
const sign = e < 0 ? "-" : "+";
|
|
116
|
+
const mag = Math.abs(e).toString().padStart(2, "0");
|
|
117
|
+
return `${mant}e${sign}${mag}`;
|
|
118
|
+
}
|
|
119
|
+
// ── §2 canonicalValue(serializeContractKey)— トップレベルのみキーソート ──────────
|
|
120
|
+
/**
|
|
121
|
+
* canonicalValue — key identity 用の正準直列化。
|
|
122
|
+
* トップレベル object のキーのみ昇順ソートし、compact JSON を返す。
|
|
123
|
+
* ネスト値は挿入順のまま(canonical-serialization.md §2 の注: ネスト key identity は canonicalJson を使う)。
|
|
124
|
+
*/
|
|
125
|
+
export function canonicalValue(v) {
|
|
126
|
+
if (isPlainObject(v)) {
|
|
127
|
+
const keys = Object.keys(v).sort(cmpCodePoints); // トップレベルのみソート(code-point 順)
|
|
128
|
+
const parts = keys.map((k) => `${jsonString(k)}:${encodeNested(v[k])}`);
|
|
129
|
+
return `{${parts.join(",")}}`;
|
|
130
|
+
}
|
|
131
|
+
return encodeNested(v);
|
|
132
|
+
}
|
|
133
|
+
// ── §3 canonicalJson — 全階層キーソート ────────────────────────────────────────
|
|
134
|
+
/** canonicalJson — fingerprint 用。全 object 階層のキーを昇順ソート(配列は順序保持)。 */
|
|
135
|
+
export function canonicalJson(v) {
|
|
136
|
+
if (isPlainObject(v)) {
|
|
137
|
+
const keys = Object.keys(v).sort(cmpCodePoints);
|
|
138
|
+
const parts = keys.map((k) => `${jsonString(k)}:${canonicalJson(v[k])}`);
|
|
139
|
+
return `{${parts.join(",")}}`;
|
|
140
|
+
}
|
|
141
|
+
if (Array.isArray(v))
|
|
142
|
+
return `[${v.map(canonicalJson).join(",")}]`;
|
|
143
|
+
return scalarJson(v);
|
|
144
|
+
}
|
|
145
|
+
// ── 内部: ネスト値の直列化(canonicalValue 用。ネスト object は挿入順)──────────────
|
|
146
|
+
function encodeNested(v) {
|
|
147
|
+
if (isPlainObject(v)) {
|
|
148
|
+
const parts = Object.keys(v).map((k) => `${jsonString(k)}:${encodeNested(v[k])}`);
|
|
149
|
+
return `{${parts.join(",")}}`;
|
|
150
|
+
}
|
|
151
|
+
if (Array.isArray(v))
|
|
152
|
+
return `[${v.map(encodeNested).join(",")}]`;
|
|
153
|
+
return scalarJson(v);
|
|
154
|
+
}
|
|
155
|
+
/** スカラ(int/float/string/bool/null)の JSON 直列化。float は pyFloatRepr。 */
|
|
156
|
+
function scalarJson(v) {
|
|
157
|
+
if (v === null)
|
|
158
|
+
return "null";
|
|
159
|
+
if (typeof v === "boolean")
|
|
160
|
+
return v ? "true" : "false";
|
|
161
|
+
if (typeof v === "string")
|
|
162
|
+
return jsonString(v);
|
|
163
|
+
if (typeof v === "bigint")
|
|
164
|
+
return v.toString(); // int: 素の 10 進整数(値層 JSON number)
|
|
165
|
+
if (typeof v === "number")
|
|
166
|
+
return pyFloatRepr(v); // float: CPython repr(§4.1)
|
|
167
|
+
fail("INVALID_VALUE", `cannot serialize value of unknown type`);
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* jsonString — 文字列を JSON 直列化(ensure_ascii=False 相当 = 非 ASCII 素通し)。
|
|
171
|
+
* JSON.stringify の既定と一致(BMP 外は surrogate pair のまま。§6 罠)。
|
|
172
|
+
*/
|
|
173
|
+
function jsonString(s) {
|
|
174
|
+
return JSON.stringify(s);
|
|
175
|
+
}
|
|
176
|
+
// キーソートは code-point 順が規範(canonical-serialization.md §2/§6。expr-eval の
|
|
177
|
+
// cmpCodePoints を再利用。JS の既定 Array#sort は UTF-16 code unit 順で astral-plane キーが
|
|
178
|
+
// 食い違うため使わない)。
|
|
179
|
+
function isPlainObject(v) {
|
|
180
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=canonical.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canonical.js","sourceRoot":"","sources":["../src/canonical.ts"],"names":[],"mappings":"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"}
|
package/dist/codec.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* codec.ts — conformance runner adapter の共通部(runtime-boundary.md §2.1 COMMON)。
|
|
3
|
+
*
|
|
4
|
+
* golden vector の型付き値エンコード(`{int:"..."}` / `{float:n}` / `{nan}` / `{inf}` / 素の
|
|
5
|
+
* JSON number 分類)と runtime {@link Value} との相互変換、および int/float を型で区別する
|
|
6
|
+
* 深い等価判定。全言語 runner が同じ判定規則で同じ pass/fail を出すための共有ロジック
|
|
7
|
+
* (conformance/PROTOCOL.md §4)。DSL 非依存。
|
|
8
|
+
*/
|
|
9
|
+
import type { Value } from "./expr-eval.js";
|
|
10
|
+
/**
|
|
11
|
+
* decodeValue — golden vector の JSON 値表現を runtime {@link Value} へ復元する。
|
|
12
|
+
* expression-ir.md §2.3 の逆写像:
|
|
13
|
+
* - 素の JSON number: 整数値 → int(bigint)、小数部あり → float(number)。
|
|
14
|
+
* - `{int:"..."}` → bigint(安全整数域外も表現可能)。
|
|
15
|
+
* - `{float:n}` → number(整数値 float を明示)。
|
|
16
|
+
* - `{nan}` / `{inf: ±1}` → NaN / ±Infinity(canonical の Failure テスト用)。
|
|
17
|
+
*/
|
|
18
|
+
export declare function decodeValue(x: unknown): Value;
|
|
19
|
+
/**
|
|
20
|
+
* deepEquals — int/float を型で区別する深い等価(PROTOCOL.md §4)。
|
|
21
|
+
* bigint(int) と number(float) は等しくない。NaN は NaN と等しいとみなす(Failure 判定用)。
|
|
22
|
+
*/
|
|
23
|
+
export declare function deepEquals(a: Value, b: Value): boolean;
|
|
24
|
+
//# sourceMappingURL=codec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codec.d.ts","sourceRoot":"","sources":["../src/codec.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAE5C;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,GAAG,KAAK,CAqB7C;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,GAAG,OAAO,CActD"}
|
package/dist/codec.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* decodeValue — golden vector の JSON 値表現を runtime {@link Value} へ復元する。
|
|
3
|
+
* expression-ir.md §2.3 の逆写像:
|
|
4
|
+
* - 素の JSON number: 整数値 → int(bigint)、小数部あり → float(number)。
|
|
5
|
+
* - `{int:"..."}` → bigint(安全整数域外も表現可能)。
|
|
6
|
+
* - `{float:n}` → number(整数値 float を明示)。
|
|
7
|
+
* - `{nan}` / `{inf: ±1}` → NaN / ±Infinity(canonical の Failure テスト用)。
|
|
8
|
+
*/
|
|
9
|
+
export function decodeValue(x) {
|
|
10
|
+
if (x === null)
|
|
11
|
+
return null;
|
|
12
|
+
if (typeof x === "boolean" || typeof x === "string")
|
|
13
|
+
return x;
|
|
14
|
+
if (typeof x === "number") {
|
|
15
|
+
return Number.isInteger(x) ? BigInt(x) : x;
|
|
16
|
+
}
|
|
17
|
+
if (Array.isArray(x))
|
|
18
|
+
return x.map(decodeValue);
|
|
19
|
+
if (typeof x === "object") {
|
|
20
|
+
const o = x;
|
|
21
|
+
const keys = Object.keys(o);
|
|
22
|
+
if (keys.length === 1) {
|
|
23
|
+
if (keys[0] === "int" && typeof o.int === "string")
|
|
24
|
+
return BigInt(o.int);
|
|
25
|
+
if (keys[0] === "float" && typeof o.float === "number")
|
|
26
|
+
return o.float;
|
|
27
|
+
if (keys[0] === "nan")
|
|
28
|
+
return NaN;
|
|
29
|
+
if (keys[0] === "inf")
|
|
30
|
+
return o.inf < 0 ? -Infinity : Infinity;
|
|
31
|
+
}
|
|
32
|
+
const out = {};
|
|
33
|
+
for (const k of keys)
|
|
34
|
+
out[k] = decodeValue(o[k]);
|
|
35
|
+
return out;
|
|
36
|
+
}
|
|
37
|
+
throw new Error(`cannot decode value: ${String(x)}`);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* deepEquals — int/float を型で区別する深い等価(PROTOCOL.md §4)。
|
|
41
|
+
* bigint(int) と number(float) は等しくない。NaN は NaN と等しいとみなす(Failure 判定用)。
|
|
42
|
+
*/
|
|
43
|
+
export function deepEquals(a, b) {
|
|
44
|
+
if (a === null || b === null)
|
|
45
|
+
return a === b;
|
|
46
|
+
if (typeof a !== typeof b)
|
|
47
|
+
return false;
|
|
48
|
+
if (typeof a === "bigint" || typeof a === "string" || typeof a === "boolean")
|
|
49
|
+
return a === b;
|
|
50
|
+
if (typeof a === "number")
|
|
51
|
+
return a === b || (Number.isNaN(a) && Number.isNaN(b));
|
|
52
|
+
if (Array.isArray(a)) {
|
|
53
|
+
if (!Array.isArray(b) || a.length !== b.length)
|
|
54
|
+
return false;
|
|
55
|
+
return a.every((v, i) => deepEquals(v, b[i]));
|
|
56
|
+
}
|
|
57
|
+
if (Array.isArray(b))
|
|
58
|
+
return false;
|
|
59
|
+
const ka = Object.keys(a).sort();
|
|
60
|
+
const kb = Object.keys(b).sort();
|
|
61
|
+
if (ka.length !== kb.length || ka.some((k, i) => k !== kb[i]))
|
|
62
|
+
return false;
|
|
63
|
+
return ka.every((k) => deepEquals(a[k], b[k]));
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=codec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codec.js","sourceRoot":"","sources":["../src/codec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* envelope.ts — validateEnvelope(spec-version fail-closed 検査)。
|
|
3
|
+
*
|
|
4
|
+
* runtime-boundary.md §2.1 の COMMON プリミティブ `validateEnvelope`。graphddb の
|
|
5
|
+
* `_validate_spec_version`(`runtime.py:66`)/ Rust `validate_spec_version` を
|
|
6
|
+
* DSL 非依存の形に一般化したもの。DynamoDB 概念はゼロ — `<major>.<minor>` の比較機構のみ。
|
|
7
|
+
*
|
|
8
|
+
* 互換規則(graphddb と同一・PROTOCOL.md §5 の fail-closed 規律):
|
|
9
|
+
* - version 文字列は `"<major>.<minor>"`(整数 2 つ)でなければならない。形式違反は fail-closed。
|
|
10
|
+
* - **major は supported major と一致**しなければならない(major bump = 破壊的変更)。
|
|
11
|
+
* - **minor は supported minor 以下**でなければならない(minor は additive)。
|
|
12
|
+
* - 未知(範囲外)version は黙って通さず loud reject する。
|
|
13
|
+
*
|
|
14
|
+
* `supported` は consumer が渡す(core は比較機構を提供するのみ。boundary §2.1)。
|
|
15
|
+
*/
|
|
16
|
+
export type EnvelopeFailureCode = "MISSING_VERSION" | "MALFORMED_VERSION" | "UNSUPPORTED_MAJOR" | "UNSUPPORTED_MINOR";
|
|
17
|
+
export declare class EnvelopeFailure extends Error {
|
|
18
|
+
code: EnvelopeFailureCode;
|
|
19
|
+
constructor(code: EnvelopeFailureCode, message: string);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* validateEnvelope — envelope の spec version を fail-closed で検査する。
|
|
23
|
+
*
|
|
24
|
+
* @param envelope `specVersion` を持つ任意の document(graphddb の manifest/operations 等)。
|
|
25
|
+
* @param supported この runtime が対応する版 `"<major>.<minor>"`(consumer が宣言)。
|
|
26
|
+
* @param opts.field version を読むフィールド名(既定 `"specVersion"`)。
|
|
27
|
+
* @param opts.label エラーメッセージ用ラベル(既定 `"envelope"`)。
|
|
28
|
+
* @throws {EnvelopeFailure} 形式違反・未対応 major/minor のとき。
|
|
29
|
+
*/
|
|
30
|
+
export declare function validateEnvelope(envelope: unknown, supported: string, opts?: {
|
|
31
|
+
field?: string;
|
|
32
|
+
label?: string;
|
|
33
|
+
}): void;
|
|
34
|
+
//# sourceMappingURL=envelope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envelope.d.ts","sourceRoot":"","sources":["../src/envelope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,MAAM,MAAM,mBAAmB,GAC3B,iBAAiB,GACjB,mBAAmB,GACnB,mBAAmB,GACnB,mBAAmB,CAAC;AAExB,qBAAa,eAAgB,SAAQ,KAAK;IACxC,IAAI,EAAE,mBAAmB,CAAC;gBACd,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM;CAKvD;AAiBD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,OAAO,EACjB,SAAS,EAAE,MAAM,EACjB,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAC5C,IAAI,CAsBN"}
|
package/dist/envelope.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* envelope.ts — validateEnvelope(spec-version fail-closed 検査)。
|
|
3
|
+
*
|
|
4
|
+
* runtime-boundary.md §2.1 の COMMON プリミティブ `validateEnvelope`。graphddb の
|
|
5
|
+
* `_validate_spec_version`(`runtime.py:66`)/ Rust `validate_spec_version` を
|
|
6
|
+
* DSL 非依存の形に一般化したもの。DynamoDB 概念はゼロ — `<major>.<minor>` の比較機構のみ。
|
|
7
|
+
*
|
|
8
|
+
* 互換規則(graphddb と同一・PROTOCOL.md §5 の fail-closed 規律):
|
|
9
|
+
* - version 文字列は `"<major>.<minor>"`(整数 2 つ)でなければならない。形式違反は fail-closed。
|
|
10
|
+
* - **major は supported major と一致**しなければならない(major bump = 破壊的変更)。
|
|
11
|
+
* - **minor は supported minor 以下**でなければならない(minor は additive)。
|
|
12
|
+
* - 未知(範囲外)version は黙って通さず loud reject する。
|
|
13
|
+
*
|
|
14
|
+
* `supported` は consumer が渡す(core は比較機構を提供するのみ。boundary §2.1)。
|
|
15
|
+
*/
|
|
16
|
+
export class EnvelopeFailure extends Error {
|
|
17
|
+
code;
|
|
18
|
+
constructor(code, message) {
|
|
19
|
+
super(message);
|
|
20
|
+
this.code = code;
|
|
21
|
+
this.name = "EnvelopeFailure";
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function fail(code, message) {
|
|
25
|
+
throw new EnvelopeFailure(code, message);
|
|
26
|
+
}
|
|
27
|
+
/** `"<major>.<minor>"` を { major, minor } に分解(形式違反は fail-closed)。 */
|
|
28
|
+
function parseVersion(version, label) {
|
|
29
|
+
const parts = version.split(".");
|
|
30
|
+
if (parts.length !== 2)
|
|
31
|
+
fail("MALFORMED_VERSION", `${label}: version '${version}' must be '<major>.<minor>'`);
|
|
32
|
+
const [majS, minS] = parts;
|
|
33
|
+
if (!/^\d+$/.test(majS) || !/^\d+$/.test(minS))
|
|
34
|
+
fail("MALFORMED_VERSION", `${label}: version '${version}' must be two integers '<major>.<minor>'`);
|
|
35
|
+
return { major: Number(majS), minor: Number(minS) };
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* validateEnvelope — envelope の spec version を fail-closed で検査する。
|
|
39
|
+
*
|
|
40
|
+
* @param envelope `specVersion` を持つ任意の document(graphddb の manifest/operations 等)。
|
|
41
|
+
* @param supported この runtime が対応する版 `"<major>.<minor>"`(consumer が宣言)。
|
|
42
|
+
* @param opts.field version を読むフィールド名(既定 `"specVersion"`)。
|
|
43
|
+
* @param opts.label エラーメッセージ用ラベル(既定 `"envelope"`)。
|
|
44
|
+
* @throws {EnvelopeFailure} 形式違反・未対応 major/minor のとき。
|
|
45
|
+
*/
|
|
46
|
+
export function validateEnvelope(envelope, supported, opts = {}) {
|
|
47
|
+
const field = opts.field ?? "specVersion";
|
|
48
|
+
const label = opts.label ?? "envelope";
|
|
49
|
+
if (typeof envelope !== "object" || envelope === null)
|
|
50
|
+
fail("MISSING_VERSION", `${label}: not an object`);
|
|
51
|
+
const raw = envelope[field];
|
|
52
|
+
if (typeof raw !== "string")
|
|
53
|
+
fail("MISSING_VERSION", `${label}: missing string '${field}'`);
|
|
54
|
+
const got = parseVersion(raw, label);
|
|
55
|
+
const want = parseVersion(supported, "supported");
|
|
56
|
+
if (got.major !== want.major)
|
|
57
|
+
fail("UNSUPPORTED_MAJOR", `${label}: version ${raw} has major ${got.major} but runtime supports major ${want.major}`);
|
|
58
|
+
if (got.minor > want.minor)
|
|
59
|
+
fail("UNSUPPORTED_MINOR", `${label}: version ${raw} has minor ${got.minor} > supported minor ${want.minor}`);
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=envelope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envelope.js","sourceRoot":"","sources":["../src/envelope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAQH,MAAM,OAAO,eAAgB,SAAQ,KAAK;IACxC,IAAI,CAAsB;IAC1B,YAAY,IAAyB,EAAE,OAAe;QACpD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED,SAAS,IAAI,CAAC,IAAyB,EAAE,OAAe;IACtD,MAAM,IAAI,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAC3C,CAAC;AAED,qEAAqE;AACrE,SAAS,YAAY,CAAC,OAAe,EAAE,KAAa;IAClD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QACpB,IAAI,CAAC,mBAAmB,EAAE,GAAG,KAAK,cAAc,OAAO,6BAA6B,CAAC,CAAC;IACxF,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,KAAK,CAAC;IAC3B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;QAC5C,IAAI,CAAC,mBAAmB,EAAE,GAAG,KAAK,cAAc,OAAO,0CAA0C,CAAC,CAAC;IACrG,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;AACtD,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,gBAAgB,CAC9B,QAAiB,EACjB,SAAiB,EACjB,OAA2C,EAAE;IAE7C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,aAAa,CAAC;IAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,UAAU,CAAC;IACvC,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,IAAI;QACnD,IAAI,CAAC,iBAAiB,EAAE,GAAG,KAAK,iBAAiB,CAAC,CAAC;IACrD,MAAM,GAAG,GAAI,QAAoC,CAAC,KAAK,CAAC,CAAC;IACzD,IAAI,OAAO,GAAG,KAAK,QAAQ;QACzB,IAAI,CAAC,iBAAiB,EAAE,GAAG,KAAK,qBAAqB,KAAK,GAAG,CAAC,CAAC;IAEjE,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACrC,MAAM,IAAI,GAAG,YAAY,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IAElD,IAAI,GAAG,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK;QAC1B,IAAI,CACF,mBAAmB,EACnB,GAAG,KAAK,aAAa,GAAG,cAAc,GAAG,CAAC,KAAK,+BAA+B,IAAI,CAAC,KAAK,EAAE,CAC3F,CAAC;IACJ,IAAI,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK;QACxB,IAAI,CACF,mBAAmB,EACnB,GAAG,KAAK,aAAa,GAAG,cAAc,GAAG,CAAC,KAAK,sBAAsB,IAAI,CAAC,KAAK,EAAE,CAClF,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* expr-eval.ts — expression-ir.md の参照評価器(規範実装)。
|
|
3
|
+
*
|
|
4
|
+
* 値モデル(../expression-ir.md §5):
|
|
5
|
+
* int = bigint(i64 checked) / float = number(IEEE754, NaN/Inf は Failure)
|
|
6
|
+
* / string / bool / null / arr / obj
|
|
7
|
+
*
|
|
8
|
+
* 規範ポイント(§6/§8 の罠に対応):
|
|
9
|
+
* - int 演算は checked i64(オーバーフロー = Failure)。TS では BigInt で実装
|
|
10
|
+
* - 評価結果が NaN / ±Infinity になった時点で Failure
|
|
11
|
+
* - mod は truncated division(符号は被除数。Python の % と異なる)
|
|
12
|
+
* - 文字列比較は code point 順(TS ネイティブ `<` の UTF-16 順ではない)
|
|
13
|
+
* - and / or / coalesce / cond は短絡評価(短絡側の Failure は発生しない)
|
|
14
|
+
* - 未知オペレータは fail-closed
|
|
15
|
+
*/
|
|
16
|
+
export type Value = bigint | number | string | boolean | null | Value[] | {
|
|
17
|
+
[k: string]: Value;
|
|
18
|
+
};
|
|
19
|
+
export type Scope = Record<string, Value>;
|
|
20
|
+
export type FailureCode = "INT_OVERFLOW" | "NAN_OR_INF" | "MOD_ZERO" | "PRECISION_LOSS" | "TYPE_MISMATCH" | "NULL_REF" | "MISSING_PROP" | "UNKNOWN_BINDING" | "UNKNOWN_OP" | "INVALID_NODE" | "INVALID_LITERAL";
|
|
21
|
+
export declare class ExprFailure extends Error {
|
|
22
|
+
code: FailureCode;
|
|
23
|
+
constructor(code: FailureCode, message: string);
|
|
24
|
+
}
|
|
25
|
+
export declare function cmpCodePoints(a: string, b: string): -1 | 0 | 1;
|
|
26
|
+
export declare function evaluate(node: unknown, scope?: Scope): Value;
|
|
27
|
+
export declare function encodeValue(v: Value): unknown;
|
|
28
|
+
//# sourceMappingURL=expr-eval.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expr-eval.d.ts","sourceRoot":"","sources":["../src/expr-eval.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,MAAM,MAAM,KAAK,GACb,MAAM,GACN,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,KAAK,EAAE,GACP;IAAE,CAAC,CAAC,EAAE,MAAM,GAAG,KAAK,CAAA;CAAE,CAAC;AAE3B,MAAM,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AAG1C,MAAM,MAAM,WAAW,GACnB,cAAc,GACd,YAAY,GACZ,UAAU,GACV,gBAAgB,GAChB,eAAe,GACf,UAAU,GACV,cAAc,GACd,iBAAiB,GACjB,YAAY,GACZ,cAAc,GACd,iBAAiB,CAAC;AAEtB,qBAAa,WAAY,SAAQ,KAAK;IACpC,IAAI,EAAE,WAAW,CAAC;gBACN,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM;CAK/C;AAgCD,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAa9D;AAsBD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,GAAE,KAAU,GAAG,KAAK,CAkLhE;AAoCD,wBAAgB,WAAW,CAAC,CAAC,EAAE,KAAK,GAAG,OAAO,CAa7C"}
|