@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.
- package/CHANGELOG.md +172 -0
- package/README.md +105 -3
- package/SPEC.md +439 -0
- package/api-surface.json +3 -1
- package/conformance.json +3176 -0
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +21 -43
- package/dist/engine.js.map +1 -1
- package/dist/gate.d.ts.map +1 -1
- package/dist/gate.js +94 -30
- package/dist/gate.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/levels.d.ts +16 -0
- package/dist/levels.d.ts.map +1 -1
- package/dist/levels.js +54 -1
- package/dist/levels.js.map +1 -1
- package/dist/persistence.d.ts.map +1 -1
- package/dist/persistence.js +16 -23
- package/dist/persistence.js.map +1 -1
- package/dist/reconcile.d.ts +26 -0
- package/dist/reconcile.d.ts.map +1 -0
- package/dist/reconcile.js +75 -0
- package/dist/reconcile.js.map +1 -0
- package/package.json +23 -11
- package/spec/conformance.schema.json +395 -0
- package/spec/energy-state.schema.json +53 -0
- package/src/energy.css +77 -0
package/dist/persistence.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
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
|
-
|
|
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
|
-
//
|
|
37
|
-
//
|
|
38
|
-
console.error(`[energy-system] Discarding
|
|
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
|
|
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(
|
|
97
|
+
listener(next);
|
|
105
98
|
}
|
|
106
99
|
},
|
|
107
100
|
observe(onState) {
|
package/dist/persistence.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"persistence.js","sourceRoot":"","sources":["../src/persistence.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
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.
|
|
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.
|
|
45
|
-
"@types/node": "^26.
|
|
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.
|
|
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
|
|
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": "
|
|
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
|
}
|