@kumbatio/energy-system 0.6.0 → 1.0.1

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.
@@ -1,4 +1,4 @@
1
- import { createEnergyState, isEnergyLevel, isEnergySource } from './levels.js';
1
+ import { parseExternalEnergyState } from './levels.js';
2
2
  /*
3
3
  * `null` means "nothing usable is stored", which the engine treats as a fresh
4
4
  * install. Corrupt or schema-violating data reaches the same conclusion, but it
@@ -16,26 +16,17 @@ function parsePersistedState(source, raw) {
16
16
  console.error(`[energy-system] Discarding unparseable persisted energy state (${source})`, err);
17
17
  return null;
18
18
  }
19
- if (typeof parsed !== 'object' || parsed === null || !('level' in parsed)) {
20
- console.error(`[energy-system] Discarding persisted energy state with unexpected shape (${source})`);
21
- return null;
22
- }
23
- const obj = parsed;
24
- if (!isEnergyLevel(obj['level']) ||
25
- !isEnergySource(obj['source']) ||
26
- typeof obj['timestamp'] !== 'number' ||
27
- typeof obj['revision'] !== 'number' ||
28
- typeof obj['origin'] !== 'string') {
29
- console.error(`[energy-system] Discarding malformed persisted energy state (${source})`);
30
- return null;
31
- }
32
19
  try {
33
- return createEnergyState(obj['level'], obj['source'], obj['timestamp'], obj['revision'], obj['origin']);
20
+ // Shape, key set and field invariants are all one boundary rule, enforced
21
+ // to the letter of spec/energy-state.schema.json — including its
22
+ // `additionalProperties: false`. Storage written by a newer or foreign
23
+ // producer is rejected, not quietly trimmed to fit.
24
+ return parseExternalEnergyState(parsed);
34
25
  }
35
26
  catch (err) {
36
- // Field-level invariants (negative timestamp, non-integer revision, blank
37
- // origin) are enforced by createEnergyState, not by the checks above.
38
- console.error(`[energy-system] Discarding invalid persisted energy state (${source})`, err);
27
+ // Distinct from the unparseable case above: the bytes were JSON, the
28
+ // content was not an EnergyState. The thrown error carries which rule broke.
29
+ console.error(`[energy-system] Discarding malformed persisted energy state (${source})`, err);
39
30
  return null;
40
31
  }
41
32
  }
@@ -90,18 +81,20 @@ export function localStoragePersistence(key = 'energy-state') {
90
81
  * Useful for tests, SSR, or ephemeral sessions.
91
82
  */
92
83
  export function memoryPersistence(initial) {
93
- let stored = initial === undefined
94
- ? null
95
- : createEnergyState(initial.level, initial.source, initial.timestamp, initial.revision, initial.origin);
84
+ let stored = initial === undefined ? null : parseExternalEnergyState(initial);
96
85
  const listeners = new Set();
97
86
  return {
98
87
  async load() {
99
88
  return stored;
100
89
  },
101
90
  async save(state) {
102
- stored = createEnergyState(state.level, state.source, state.timestamp, state.revision, state.origin);
91
+ // Re-parsed rather than stored by reference: this adapter is the one
92
+ // observers read back from, so what it hands out must satisfy the
93
+ // interchange contract exactly, whoever called save().
94
+ const next = parseExternalEnergyState(state);
95
+ stored = next;
103
96
  for (const listener of listeners) {
104
- listener(stored);
97
+ listener(next);
105
98
  }
106
99
  },
107
100
  observe(onState) {
@@ -1 +1 @@
1
- {"version":3,"file":"persistence.js","sourceRoot":"","sources":["../src/persistence.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"persistence.js","sourceRoot":"","sources":["../src/persistence.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import type { EnergyState } from './types.js';
2
+ /**
3
+ * Should `candidate` replace `current`?
4
+ *
5
+ * The comparison walks four keys in order, stopping at the first that differs:
6
+ *
7
+ * 1. **`timestamp`** — later wins. The ordinary case, and the only one most
8
+ * states ever reach.
9
+ * 2. **`revision`** — higher wins. Two writes inside one clock tick are not
10
+ * simultaneous; the producer numbers them so they still order.
11
+ * 3. **`source`** — `manual` > `scheduled` > `inferred`. See `sourcePriority`.
12
+ * 4. **`origin`** — higher string wins. Not meaningful, and deliberately so:
13
+ * when two producers write the same instant, the same revision, and the same
14
+ * kind of source, there is no principled winner, and an arbitrary rule every
15
+ * context computes identically beats a coin flip each context tosses
16
+ * separately. Convergence is the property that matters.
17
+ *
18
+ * A final `level` comparison exists below the four keys as a backstop for
19
+ * producers that reuse one identity for different state, which is a contract
20
+ * violation but should still converge rather than oscillate.
21
+ *
22
+ * Equal on every key means equal: `false`, so an identical state never counts
23
+ * as a change and never fires a notification.
24
+ */
25
+ export declare function isPreferredEnergyState(candidate: EnergyState, current: EnergyState): boolean;
26
+ //# sourceMappingURL=reconcile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconcile.d.ts","sourceRoot":"","sources":["../src/reconcile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAgB,WAAW,EAAE,MAAM,YAAY,CAAA;AAqC3D;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAsB5F"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * State reconciliation — how two `EnergyState` values that describe the same
3
+ * user are ordered when they meet.
4
+ *
5
+ * They meet constantly: a second browser tab writes the shared store, a desktop
6
+ * window and its detached child both hold an engine, a sync layer hands back
7
+ * what another device recorded. Every one of those paths needs the same answer
8
+ * to "which of these two is the current state?", and the answer has to be
9
+ * *deterministic* — not "last write wins by arrival order", which converges on
10
+ * different values depending on network timing.
11
+ *
12
+ * This is the rule, extracted from the engine so it can be read, tested, and
13
+ * ported on its own. It is the single hardest thing to reimplement correctly in
14
+ * another language, and the conformance vectors exercise it directly.
15
+ */
16
+ /**
17
+ * How much authority each source carries when everything else ties.
18
+ *
19
+ * A level the user set by hand outranks one a schedule applied, which outranks
20
+ * one inferred from behaviour. This is the library's central stance in numeric
21
+ * form: the dial is the trust anchor, and nothing the system worked out on its
22
+ * own may quietly overwrite what the person said about themselves.
23
+ */
24
+ function sourcePriority(source) {
25
+ switch (source) {
26
+ case 'manual':
27
+ return 3;
28
+ case 'scheduled':
29
+ return 2;
30
+ case 'inferred':
31
+ return 1;
32
+ }
33
+ }
34
+ /**
35
+ * Should `candidate` replace `current`?
36
+ *
37
+ * The comparison walks four keys in order, stopping at the first that differs:
38
+ *
39
+ * 1. **`timestamp`** — later wins. The ordinary case, and the only one most
40
+ * states ever reach.
41
+ * 2. **`revision`** — higher wins. Two writes inside one clock tick are not
42
+ * simultaneous; the producer numbers them so they still order.
43
+ * 3. **`source`** — `manual` > `scheduled` > `inferred`. See `sourcePriority`.
44
+ * 4. **`origin`** — higher string wins. Not meaningful, and deliberately so:
45
+ * when two producers write the same instant, the same revision, and the same
46
+ * kind of source, there is no principled winner, and an arbitrary rule every
47
+ * context computes identically beats a coin flip each context tosses
48
+ * separately. Convergence is the property that matters.
49
+ *
50
+ * A final `level` comparison exists below the four keys as a backstop for
51
+ * producers that reuse one identity for different state, which is a contract
52
+ * violation but should still converge rather than oscillate.
53
+ *
54
+ * Equal on every key means equal: `false`, so an identical state never counts
55
+ * as a change and never fires a notification.
56
+ */
57
+ export function isPreferredEnergyState(candidate, current) {
58
+ if (candidate.timestamp !== current.timestamp) {
59
+ return candidate.timestamp > current.timestamp;
60
+ }
61
+ if (candidate.revision !== current.revision) {
62
+ return candidate.revision > current.revision;
63
+ }
64
+ if (candidate.source !== current.source) {
65
+ return sourcePriority(candidate.source) > sourcePriority(current.source);
66
+ }
67
+ if (candidate.origin !== current.origin) {
68
+ return candidate.origin > current.origin;
69
+ }
70
+ if (candidate.level !== current.level) {
71
+ return candidate.level > current.level;
72
+ }
73
+ return false;
74
+ }
75
+ //# sourceMappingURL=reconcile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconcile.js","sourceRoot":"","sources":["../src/reconcile.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;GAcG;AAEH;;;;;;;GAOG;AACH,SAAS,cAAc,CAAC,MAAoB;IAC1C,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,QAAQ;YACX,OAAO,CAAC,CAAA;QACV,KAAK,WAAW;YACd,OAAO,CAAC,CAAA;QACV,KAAK,UAAU;YACb,OAAO,CAAC,CAAA;IACZ,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,sBAAsB,CAAC,SAAsB,EAAE,OAAoB;IACjF,IAAI,SAAS,CAAC,SAAS,KAAK,OAAO,CAAC,SAAS,EAAE,CAAC;QAC9C,OAAO,SAAS,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAA;IAChD,CAAC;IAED,IAAI,SAAS,CAAC,QAAQ,KAAK,OAAO,CAAC,QAAQ,EAAE,CAAC;QAC5C,OAAO,SAAS,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAA;IAC9C,CAAC;IAED,IAAI,SAAS,CAAC,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC;QACxC,OAAO,cAAc,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;IAC1E,CAAC;IAED,IAAI,SAAS,CAAC,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC;QACxC,OAAO,SAAS,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAA;IAC1C,CAAC;IAED,IAAI,SAAS,CAAC,KAAK,KAAK,OAAO,CAAC,KAAK,EAAE,CAAC;QACtC,OAAO,SAAS,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAA;IACxC,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kumbatio/energy-system",
3
- "version": "0.6.0",
3
+ "version": "1.0.1",
4
4
  "private": false,
5
5
  "description": "Framework-agnostic TypeScript library for energy-aware application behavior.",
6
6
  "license": "MIT",
@@ -8,6 +8,10 @@
8
8
  "dist",
9
9
  "src/energy.css",
10
10
  "api-surface.json",
11
+ "conformance.json",
12
+ "spec",
13
+ "SPEC.md",
14
+ "CHANGELOG.md",
11
15
  "README.md"
12
16
  ],
13
17
  "type": "module",
@@ -35,27 +39,31 @@
35
39
  },
36
40
  "./css": "./src/energy.css",
37
41
  "./api-surface.json": "./api-surface.json",
38
- "./package.json": "./package.json"
42
+ "./package.json": "./package.json",
43
+ "./conformance.json": "./conformance.json",
44
+ "./spec/energy-state.schema.json": "./spec/energy-state.schema.json",
45
+ "./spec/conformance.schema.json": "./spec/conformance.schema.json"
39
46
  },
40
47
  "publishConfig": {
41
48
  "access": "public"
42
49
  },
43
50
  "devDependencies": {
44
- "@happy-dom/global-registrator": "^20.11.1",
45
- "@types/node": "^26.1.2",
51
+ "@happy-dom/global-registrator": "^20.11.2",
52
+ "@types/node": "^26.2.0",
46
53
  "@types/react": "^19.2.18",
47
54
  "@types/react-dom": "^19.2.4",
55
+ "ajv": "8.20.0",
48
56
  "oxfmt": "0.62.0",
49
57
  "oxlint": "1.77.0",
50
58
  "oxlint-tsgolint": "^7.0.2001",
51
59
  "react": "^19.2.8",
52
60
  "react-dom": "^19.2.8",
53
- "tsx": "^4.23.7",
61
+ "tsx": "^4.23.12",
54
62
  "typescript": "^7.0.2"
55
63
  },
56
64
  "peerDependencies": {
57
- "@types/react": ">=19",
58
- "react": ">=19"
65
+ "@types/react": ">=19.2.0",
66
+ "react": ">=19.2.0"
59
67
  },
60
68
  "peerDependenciesMeta": {
61
69
  "@types/react": {
@@ -69,17 +77,21 @@
69
77
  "node": ">=24.19.0"
70
78
  },
71
79
  "scripts": {
72
- "build": "tsc -p tsconfig.build.json && pnpm run api:surface",
80
+ "build:ts": "tsc -p tsconfig.build.json",
81
+ "build": "pnpm run build:ts && pnpm run api:surface && pnpm run conformance",
73
82
  "api:surface": "tsx scripts/extract-api-surface.ts",
83
+ "api:surface:check": "tsx scripts/extract-api-surface.ts --check",
74
84
  "check-types": "tsc --noEmit -p tsconfig.json",
75
- "test": "pnpm run build && node --test --import tsx",
85
+ "test": "pnpm run build:ts && node --test --import tsx",
76
86
  "validate": "pnpm run format:check && pnpm run lint && pnpm run check-types && pnpm run test && pnpm run pack:dry-run",
77
- "pack:dry-run": "npm pack --dry-run",
87
+ "pack:dry-run": "pnpm pack --dry-run",
78
88
  "format": "oxfmt --write .",
79
89
  "format:check": "oxfmt --check .",
80
90
  "lint": "oxlint --import-plugin --type-aware --type-check --vitest-plugin .",
81
91
  "lint:fix": "oxlint --import-plugin --type-aware --type-check --vitest-plugin --fix . && oxfmt --write .",
82
92
  "lint:fix-unsafe": "oxlint --import-plugin --type-aware --type-check --vitest-plugin --fix --fix-suggestions --fix-dangerously . && oxfmt --write .",
83
- "check:fix-suggestions": "oxlint --import-plugin --type-aware --type-check --vitest-plugin --fix --fix-suggestions . && oxfmt --write ."
93
+ "check:fix-suggestions": "oxlint --import-plugin --type-aware --type-check --vitest-plugin --fix --fix-suggestions . && oxfmt --write .",
94
+ "conformance": "TZ=UTC tsx scripts/extract-conformance.ts",
95
+ "conformance:check": "TZ=UTC tsx scripts/extract-conformance.ts --check"
84
96
  }
85
97
  }