@opus-magnum/rubedo 1.0.0 → 1.0.2

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 ADDED
@@ -0,0 +1,13 @@
1
+ # @opus-magnum/rubedo
2
+
3
+ **RUBEDO v1** — детерминированный движок структурного фингерпринтинга (canonical JSON + SHA-256), выделенный из sealed-ядра Opus Magnum.
4
+
5
+ ## Гарантии v1
6
+ - Независимость от порядка ключей в объектах (canonicalizeJson → stableStringify)
7
+ - Независимость от порядка элементов synopsis (сортировка по `id`)
8
+ - Детерминированный `fingerprint` (SHA-256) и `artifact_id` (`RUBEDO::v1::<prefix>`)
9
+ - Контракт-инварианты через `contract-test`
10
+
11
+ ## Установка
12
+ ```bash
13
+ npm i @opus-magnum/rubedo
package/dist/index.d.ts CHANGED
@@ -1,3 +1 @@
1
- export { RubedoForge } from "./v1/RubedoForge";
2
- export { stableStringify, canonicalizeJson, type Json } from "./v1/canonical-json";
3
- export { RUBEDO_CONTRACT_V1 } from "./v1/contract";
1
+ export * from "./v1/index.js";
package/dist/index.js CHANGED
@@ -1,3 +1 @@
1
- export { RubedoForge } from "./v1/RubedoForge";
2
- export { stableStringify, canonicalizeJson } from "./v1/canonical-json";
3
- export { RUBEDO_CONTRACT_V1 } from "./v1/contract";
1
+ export * from "./v1/index.js";
@@ -1,4 +1,4 @@
1
- import type { IRubedoForge, RubedoArtifact, RubedoInput } from "../../../interfaces/RUBEDO/v1/IRubedoForge";
1
+ import type { IRubedoForge, RubedoArtifact, RubedoForgeInput } from "./types.js";
2
2
  export declare class RubedoForge implements IRubedoForge {
3
- forge(input: RubedoInput): RubedoArtifact;
3
+ forge(input: RubedoForgeInput): RubedoArtifact;
4
4
  }
@@ -1,5 +1,5 @@
1
1
  import crypto from "node:crypto";
2
- import { stableStringify } from "./canonical-json";
2
+ import { stableStringify } from "./canonical-json.js";
3
3
  function sha256Hex(s) {
4
4
  return crypto.createHash("sha256").update(s, "utf-8").digest("hex");
5
5
  }
@@ -2,23 +2,23 @@ import { RUBEDO_CONTRACT_V1 } from "./contract.js";
2
2
  import { RubedoForge } from "./RubedoForge.js";
3
3
  function assertEq(a, b, msg) {
4
4
  if (a !== b)
5
- throw new Error(msg + `: ${String(a)} !== ${String(b)}`);
5
+ throw new Error(`${msg}: ${String(a)} !== ${String(b)}`);
6
6
  }
7
7
  console.log(`[RUBEDO_CONTRACT] version=${RUBEDO_CONTRACT_V1.version}`);
8
- const f = new RubedoForge();
9
- const fpOf = (synopsis) => f.forge({ synopsis }).fingerprint;
10
- // Key order independence (value object different key order must be same fingerprint)
8
+ const forge = new RubedoForge();
9
+ const fpOf = (synopsis) => forge.forge({ synopsis }).fingerprint;
10
+ // key order independence (value object must be stable-stringified)
11
11
  const s1 = [{ id: "key:a", kind: "KEY", value: { a: 1, b: 2, c: { y: 9, z: 0 } } }];
12
12
  const s2 = [{ id: "key:a", kind: "KEY", value: { b: 2, a: 1, c: { z: 0, y: 9 } } }];
13
13
  assertEq(fpOf(s1), fpOf(s2), "KEY_ORDER_INDEPENDENCE");
14
- // Synopsis order independence
14
+ // synopsis order independence (forge must sort synopsis)
15
15
  const t1 = [
16
16
  { id: "k:1", kind: "KEY", value: 1 },
17
- { id: "k:2", kind: "KEY", value: 2 }
17
+ { id: "k:2", kind: "KEY", value: 2 },
18
18
  ];
19
19
  const t2 = [
20
20
  { id: "k:2", kind: "KEY", value: 2 },
21
- { id: "k:1", kind: "KEY", value: 1 }
21
+ { id: "k:1", kind: "KEY", value: 1 },
22
22
  ];
23
23
  assertEq(fpOf(t1), fpOf(t2), "SYNOPSIS_ORDER_INDEPENDENCE");
24
24
  console.log("[PASS] RUBEDO package contract invariants satisfied");
@@ -0,0 +1,3 @@
1
+ export { RubedoForge } from "./RubedoForge.js";
2
+ export { RUBEDO_CONTRACT_V1 } from "./contract.js";
3
+ export * from "./types.js";
@@ -0,0 +1,3 @@
1
+ export { RubedoForge } from "./RubedoForge.js";
2
+ export { RUBEDO_CONTRACT_V1 } from "./contract.js";
3
+ export * from "./types.js";
@@ -0,0 +1,27 @@
1
+ /**
2
+ * RUBEDO v1 — package public contract types (self-contained)
3
+ */
4
+ export type RubedoValue = null | boolean | number | string | RubedoValue[] | {
5
+ [key: string]: RubedoValue;
6
+ };
7
+ export type RubedoSynopsisItem = {
8
+ id: string;
9
+ kind: string;
10
+ value: RubedoValue;
11
+ };
12
+ export type RubedoForgeInput = {
13
+ synopsis: RubedoSynopsisItem[];
14
+ };
15
+ export interface RubedoArtifact {
16
+ artifact_id: string;
17
+ fingerprint: string;
18
+ payload: {
19
+ synopsis: RubedoSynopsisItem[];
20
+ };
21
+ stats: {
22
+ count: number;
23
+ };
24
+ }
25
+ export interface IRubedoForge {
26
+ forge(input: RubedoForgeInput): RubedoArtifact;
27
+ }
@@ -0,0 +1,4 @@
1
+ /**
2
+ * RUBEDO v1 — package public contract types (self-contained)
3
+ */
4
+ export {};
package/package.json CHANGED
@@ -1,21 +1,43 @@
1
1
  {
2
2
  "name": "@opus-magnum/rubedo",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
+ "description": "RUBEDO v1 — deterministic structural fingerprint engine (sealed core of Opus Magnum)",
5
+ "keywords": [
6
+ "rubedo",
7
+ "fingerprint",
8
+ "hash",
9
+ "deterministic",
10
+ "canonical-json",
11
+ "sha256"
12
+ ],
13
+ "license": "MIT",
4
14
  "type": "module",
5
15
  "main": "dist/index.js",
6
16
  "types": "dist/index.d.ts",
17
+ "files": [
18
+ "dist",
19
+ "src",
20
+ "README.md"
21
+ ],
7
22
  "exports": {
8
23
  ".": {
9
24
  "types": "./dist/index.d.ts",
10
25
  "default": "./dist/index.js"
26
+ },
27
+ "./v1": {
28
+ "types": "./dist/v1/index.d.ts",
29
+ "default": "./dist/v1/index.js"
11
30
  }
12
31
  },
32
+ "publishConfig": {
33
+ "access": "public"
34
+ },
13
35
  "scripts": {
14
36
  "build": "npx tsc -p tsconfig.build.json",
15
37
  "test:contract": "npm run -s build >/dev/null && node dist/v1/contract-test.js"
16
38
  },
17
39
  "devDependencies": {
18
- "typescript": "^5.9.3",
19
- "@types/node": "^22.19.3"
40
+ "@types/node": "^22.19.3",
41
+ "typescript": "^5.9.3"
20
42
  }
21
43
  }
package/src/index.ts CHANGED
@@ -1,3 +1 @@
1
- export { RubedoForge } from "./v1/RubedoForge";
2
- export { stableStringify, canonicalizeJson, type Json } from "./v1/canonical-json";
3
- export { RUBEDO_CONTRACT_V1 } from "./v1/contract";
1
+ export * from "./v1/index.js";
@@ -1,6 +1,6 @@
1
1
  import crypto from "node:crypto";
2
- import type { IRubedoForge, RubedoArtifact, RubedoInput } from "../../../interfaces/RUBEDO/v1/IRubedoForge";
3
- import { stableStringify } from "./canonical-json";
2
+ import type { IRubedoForge, RubedoArtifact, RubedoForgeInput, RubedoSynopsisItem } from "./types.js";
3
+ import { stableStringify } from "./canonical-json.js";
4
4
 
5
5
  function sha256Hex(s: string): string {
6
6
  return crypto.createHash("sha256").update(s, "utf-8").digest("hex");
@@ -8,7 +8,7 @@ function sha256Hex(s: string): string {
8
8
 
9
9
  export class RubedoForge implements IRubedoForge {
10
10
 
11
- forge(input: RubedoInput): RubedoArtifact {
11
+ forge(input: RubedoForgeInput): RubedoArtifact {
12
12
  const synopsis = [...input.synopsis].slice().sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
13
13
  const payload = { synopsis };
14
14
 
@@ -1,28 +1,29 @@
1
1
  import { RUBEDO_CONTRACT_V1 } from "./contract.js";
2
2
  import { RubedoForge } from "./RubedoForge.js";
3
+ import type { RubedoSynopsisItem } from "./types.js";
3
4
 
4
- function assertEq(a: any, b: any, msg: string) {
5
- if (a !== b) throw new Error(msg + `: ${String(a)} !== ${String(b)}`);
5
+ function assertEq(a: string, b: string, msg: string) {
6
+ if (a !== b) throw new Error(`${msg}: ${String(a)} !== ${String(b)}`);
6
7
  }
7
8
 
8
9
  console.log(`[RUBEDO_CONTRACT] version=${RUBEDO_CONTRACT_V1.version}`);
9
10
 
10
- const f = new RubedoForge();
11
- const fpOf = (synopsis: any[]) => f.forge({ synopsis }).fingerprint;
11
+ const forge = new RubedoForge();
12
+ const fpOf = (synopsis: RubedoSynopsisItem[]) => forge.forge({ synopsis }).fingerprint;
12
13
 
13
- // Key order independence (value object different key order must be same fingerprint)
14
- const s1 = [{ id: "key:a", kind: "KEY", value: { a: 1, b: 2, c: { y: 9, z: 0 } } }];
15
- const s2 = [{ id: "key:a", kind: "KEY", value: { b: 2, a: 1, c: { z: 0, y: 9 } } }];
14
+ // key order independence (value object must be stable-stringified)
15
+ const s1: RubedoSynopsisItem[] = [{ id: "key:a", kind: "KEY", value: { a: 1, b: 2, c: { y: 9, z: 0 } } }];
16
+ const s2: RubedoSynopsisItem[] = [{ id: "key:a", kind: "KEY", value: { b: 2, a: 1, c: { z: 0, y: 9 } } }];
16
17
  assertEq(fpOf(s1), fpOf(s2), "KEY_ORDER_INDEPENDENCE");
17
18
 
18
- // Synopsis order independence
19
- const t1 = [
19
+ // synopsis order independence (forge must sort synopsis)
20
+ const t1: RubedoSynopsisItem[] = [
20
21
  { id: "k:1", kind: "KEY", value: 1 },
21
- { id: "k:2", kind: "KEY", value: 2 }
22
+ { id: "k:2", kind: "KEY", value: 2 },
22
23
  ];
23
- const t2 = [
24
+ const t2: RubedoSynopsisItem[] = [
24
25
  { id: "k:2", kind: "KEY", value: 2 },
25
- { id: "k:1", kind: "KEY", value: 1 }
26
+ { id: "k:1", kind: "KEY", value: 1 },
26
27
  ];
27
28
  assertEq(fpOf(t1), fpOf(t2), "SYNOPSIS_ORDER_INDEPENDENCE");
28
29
 
@@ -0,0 +1,3 @@
1
+ export { RubedoForge } from "./RubedoForge.js";
2
+ export { RUBEDO_CONTRACT_V1 } from "./contract.js";
3
+ export * from "./types.js";
@@ -0,0 +1,36 @@
1
+ /**
2
+ * RUBEDO v1 — package public contract types (self-contained)
3
+ */
4
+
5
+ export type RubedoValue =
6
+ | null
7
+ | boolean
8
+ | number
9
+ | string
10
+ | RubedoValue[]
11
+ | { [key: string]: RubedoValue };
12
+
13
+ export type RubedoSynopsisItem = {
14
+ id: string;
15
+ kind: string;
16
+ value: RubedoValue;
17
+ };
18
+
19
+ export type RubedoForgeInput = {
20
+ synopsis: RubedoSynopsisItem[];
21
+ };
22
+
23
+ export interface RubedoArtifact {
24
+ artifact_id: string;
25
+ fingerprint: string;
26
+ payload: {
27
+ synopsis: RubedoSynopsisItem[];
28
+ };
29
+ stats: {
30
+ count: number;
31
+ };
32
+ }
33
+
34
+ export interface IRubedoForge {
35
+ forge(input: RubedoForgeInput): RubedoArtifact;
36
+ }
@@ -1,13 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "ES2022",
5
- "moduleResolution": "Bundler",
6
- "declaration": true,
7
- "outDir": "dist",
8
- "rootDir": "src",
9
- "strict": true,
10
- "skipLibCheck": true
11
- },
12
- "include": ["src/**/*"]
13
- }