@mikeargento/bitgraph-player 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 +98 -0
- package/SPEC.md +234 -0
- package/dist/__tests__/cast-order.test.d.ts +2 -0
- package/dist/__tests__/cast-order.test.d.ts.map +1 -0
- package/dist/__tests__/cast-order.test.js +434 -0
- package/dist/__tests__/cast-order.test.js.map +1 -0
- package/dist/__tests__/evaluate-verdict.test.d.ts +2 -0
- package/dist/__tests__/evaluate-verdict.test.d.ts.map +1 -0
- package/dist/__tests__/evaluate-verdict.test.js +228 -0
- package/dist/__tests__/evaluate-verdict.test.js.map +1 -0
- package/dist/__tests__/fixtures.d.ts +63 -0
- package/dist/__tests__/fixtures.d.ts.map +1 -0
- package/dist/__tests__/fixtures.js +150 -0
- package/dist/__tests__/fixtures.js.map +1 -0
- package/dist/__tests__/logic-rule.test.d.ts +2 -0
- package/dist/__tests__/logic-rule.test.d.ts.map +1 -0
- package/dist/__tests__/logic-rule.test.js +190 -0
- package/dist/__tests__/logic-rule.test.js.map +1 -0
- package/dist/cast.d.ts +29 -0
- package/dist/cast.d.ts.map +1 -0
- package/dist/cast.js +85 -0
- package/dist/cast.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +130 -0
- package/dist/cli.js.map +1 -0
- package/dist/evaluate.d.ts +30 -0
- package/dist/evaluate.d.ts.map +1 -0
- package/dist/evaluate.js +177 -0
- package/dist/evaluate.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/logic.d.ts +16 -0
- package/dist/logic.d.ts.map +1 -0
- package/dist/logic.js +29 -0
- package/dist/logic.js.map +1 -0
- package/dist/order.d.ts +50 -0
- package/dist/order.d.ts.map +1 -0
- package/dist/order.js +290 -0
- package/dist/order.js.map +1 -0
- package/dist/rule.d.ts +40 -0
- package/dist/rule.d.ts.map +1 -0
- package/dist/rule.js +324 -0
- package/dist/rule.js.map +1 -0
- package/dist/types.d.ts +205 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +16 -0
- package/dist/types.js.map +1 -0
- package/dist/verdict.d.ts +14 -0
- package/dist/verdict.d.ts.map +1 -0
- package/dist/verdict.js +146 -0
- package/dist/verdict.js.map +1 -0
- package/package.json +42 -0
- package/src/__tests__/cast-order.test.ts +473 -0
- package/src/__tests__/evaluate-verdict.test.ts +266 -0
- package/src/__tests__/fixtures.ts +206 -0
- package/src/__tests__/logic-rule.test.ts +221 -0
- package/src/cast.ts +120 -0
- package/src/cli.ts +143 -0
- package/src/evaluate.ts +238 -0
- package/src/index.ts +38 -0
- package/src/logic.ts +39 -0
- package/src/order.ts +380 -0
- package/src/rule.ts +340 -0
- package/src/types.ts +224 -0
- package/src/verdict.ts +159 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024-2026 Mike Argento
|
|
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,98 @@
|
|
|
1
|
+
# @mikeargento/bitgraph-player
|
|
2
|
+
|
|
3
|
+
Deterministic evaluation of causal rules over BitGraph proof bundles.
|
|
4
|
+
|
|
5
|
+
BitGraph records. Player executes.
|
|
6
|
+
|
|
7
|
+
A BitGraph proof bundle establishes facts: these bits were recorded at
|
|
8
|
+
these causal positions, bracketed by these Ethereum anchors. Player
|
|
9
|
+
evaluates a rule over those facts and produces a verdict anyone can
|
|
10
|
+
reproduce from the bundle alone — no network, no clock, no account, no
|
|
11
|
+
trust in the machine that ran it first.
|
|
12
|
+
|
|
13
|
+
evidence + rule = conclusion
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
npm install @mikeargento/bitgraph-player
|
|
18
|
+
|
|
19
|
+
## Use
|
|
20
|
+
|
|
21
|
+
bitgraph-play rule.json bundle/ > verdict.json
|
|
22
|
+
|
|
23
|
+
The bundle is a directory, `.tar`, or `.tar.gz` of BitGraph exports (the
|
|
24
|
+
folders the BitGraph Folder writes). Exit codes: `0` TRUE, `1` FALSE,
|
|
25
|
+
`2` UNDETERMINED, `3` error. `--out file` writes the verdict to a file;
|
|
26
|
+
`--summary` prints a bundle reconnaissance to stderr.
|
|
27
|
+
|
|
28
|
+
## A rule
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"rule": "bitgraph-player/1",
|
|
33
|
+
"id": "po-release-payment",
|
|
34
|
+
"cast": {
|
|
35
|
+
"purchase_order": { "digest": "sha256:…", "means": "PO-4471" },
|
|
36
|
+
"delivery": { "digest": "sha256:…" },
|
|
37
|
+
"approval": { "digest": "sha256:…" },
|
|
38
|
+
"cancellation": { "digest": "sha256:…", "optional": true }
|
|
39
|
+
},
|
|
40
|
+
"world": "closed",
|
|
41
|
+
"requires": { "ordering": "assumption-dependent" },
|
|
42
|
+
"claim": { "all": [
|
|
43
|
+
{ "exists": "purchase_order" },
|
|
44
|
+
{ "after": ["delivery", "purchase_order"] },
|
|
45
|
+
{ "after": ["approval", "delivery"] },
|
|
46
|
+
{ "not": { "before": ["cancellation", "approval"] } }
|
|
47
|
+
]},
|
|
48
|
+
"then": { "label": "release_payment" }
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
`cast` is everything taken on the rule author's word: which digest means
|
|
53
|
+
what, which occurrence is meant, who is said to have signed it. `claim`
|
|
54
|
+
is only what BitGraph derives. `then` is a label — no field of a rule can
|
|
55
|
+
cause an action. Player decides; whatever stakes money on a TRUE sits
|
|
56
|
+
above it.
|
|
57
|
+
|
|
58
|
+
## Three answers, not two
|
|
59
|
+
|
|
60
|
+
A claim evaluates to `TRUE`, `FALSE`, or `UNDETERMINED`. Undetermined is
|
|
61
|
+
the honest answer wherever the evidence does not decide: recordings whose
|
|
62
|
+
order the ledger does not establish, a digest recorded more than once
|
|
63
|
+
with no pin selecting the occurrence, evidence below the rule's declared
|
|
64
|
+
trust floor (`requires.ordering`). An evaluator that always answers is
|
|
65
|
+
wrong on some input.
|
|
66
|
+
|
|
67
|
+
The verdict splits `derived` (BitGraph established this) from `declared`
|
|
68
|
+
(a named party asserted this), and its last declared entry is always the
|
|
69
|
+
closed world itself — absence is asserted only among the roles the author
|
|
70
|
+
declared, and nothing establishes that the cast is complete.
|
|
71
|
+
|
|
72
|
+
## Determinism
|
|
73
|
+
|
|
74
|
+
Same rule bytes, same bundle contents, byte-identical verdict, on any
|
|
75
|
+
machine, years later. No timestamps, no paths, no randomness. The
|
|
76
|
+
normative semantics are in [SPEC.md](./SPEC.md); this package is the
|
|
77
|
+
reference implementation, and a conforming Player in any language must
|
|
78
|
+
agree with it.
|
|
79
|
+
|
|
80
|
+
## API
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
import { runAudit } from "@mikeargento/bitgraph-audit";
|
|
84
|
+
import {
|
|
85
|
+
parseRule, resolveCast, evaluate, buildVerdict, serializeVerdict,
|
|
86
|
+
} from "@mikeargento/bitgraph-player";
|
|
87
|
+
|
|
88
|
+
const rule = parseRule(ruleText);
|
|
89
|
+
const audit = await runAudit(bundlePath);
|
|
90
|
+
const resolutions = resolveCast(rule.cast, audit);
|
|
91
|
+
const evaluation = evaluate(rule, resolutions, audit);
|
|
92
|
+
const verdict = buildVerdict(rule, ruleSha256Hex, resolutions, evaluation, audit);
|
|
93
|
+
process.stdout.write(serializeVerdict(verdict));
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## License
|
|
97
|
+
|
|
98
|
+
MIT. Verification and evaluation are permissionless by design.
|
package/SPEC.md
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
# BitGraph Player specification, version 1
|
|
2
|
+
|
|
3
|
+
This document is the normative semantics of `bitgraph-player/1` rules and
|
|
4
|
+
`bitgraph-player-verdict/1` verdicts. The TypeScript package in this
|
|
5
|
+
directory is the reference implementation; a conforming Player in any
|
|
6
|
+
language MUST reach the same result and, for the serialization defined in
|
|
7
|
+
section 7, the same bytes.
|
|
8
|
+
|
|
9
|
+
BitGraph records. Player executes. Player is a pure function:
|
|
10
|
+
|
|
11
|
+
evaluate(rule, verified evidence) -> verdict
|
|
12
|
+
|
|
13
|
+
The evidence is a BitGraph proof bundle as interpreted by the audit
|
|
14
|
+
pipeline (`bitgraph-audit`), which is the canonical interpretation of
|
|
15
|
+
bundle contents. Player makes no network requests, reads no clock, and
|
|
16
|
+
uses no randomness. Same rule bytes, same bundle contents, same verdict
|
|
17
|
+
bytes, on any machine, at any later time.
|
|
18
|
+
|
|
19
|
+
## 1. Three-valued results
|
|
20
|
+
|
|
21
|
+
Every claim evaluates to `TRUE`, `FALSE`, or `UNDETERMINED`.
|
|
22
|
+
|
|
23
|
+
`UNDETERMINED` is the required answer wherever the evidence does not
|
|
24
|
+
decide. A conforming Player MUST NOT collapse it into `FALSE` or `TRUE`.
|
|
25
|
+
Composition uses strong Kleene connectives (the grammar in section 5
|
|
26
|
+
requires `all` and `any` to be non-empty, so the empty case never
|
|
27
|
+
arises):
|
|
28
|
+
|
|
29
|
+
all: FALSE if any operand is FALSE; else UNDETERMINED if any is
|
|
30
|
+
UNDETERMINED; else TRUE.
|
|
31
|
+
any: TRUE if any operand is TRUE; else UNDETERMINED if any is
|
|
32
|
+
UNDETERMINED; else FALSE.
|
|
33
|
+
not: swaps TRUE and FALSE; UNDETERMINED is unchanged.
|
|
34
|
+
|
|
35
|
+
Evaluation is a FULL WALK: every sub-claim is evaluated and recorded even
|
|
36
|
+
when an outcome is already forced, so the verdict is a complete trace.
|
|
37
|
+
|
|
38
|
+
## 2. The rule file
|
|
39
|
+
|
|
40
|
+
A rule is a JSON object with exactly these top-level fields:
|
|
41
|
+
|
|
42
|
+
| field | required | value |
|
|
43
|
+
|---|---|---|
|
|
44
|
+
| `rule` | yes | the string `"bitgraph-player/1"` |
|
|
45
|
+
| `id` | yes | non-empty string naming the rule |
|
|
46
|
+
| `cast` | yes | object of at least one role (section 3) |
|
|
47
|
+
| `world` | yes | the string `"closed"` (the only defined value) |
|
|
48
|
+
| `requires` | yes | `{ "ordering": "hash-linked" \| "assumption-dependent" }` |
|
|
49
|
+
| `claim` | yes | a claim (section 5) |
|
|
50
|
+
| `then` | no | `{ "label": <non-empty string> }` |
|
|
51
|
+
|
|
52
|
+
Unknown fields anywhere in the file are errors. `requires.ordering` has
|
|
53
|
+
no default: a rule that does not declare its trust floor does not parse.
|
|
54
|
+
`then` is a label and nothing else; no field of a rule is capable of
|
|
55
|
+
causing an action. Player decides; it does not enforce.
|
|
56
|
+
|
|
57
|
+
Role names match `[A-Za-z0-9_.-]+` and MUST contain at least one
|
|
58
|
+
non-digit character: pure-integer names do not survive JSON object key
|
|
59
|
+
ordering identically across languages, and the verdict depends on
|
|
60
|
+
declaration order. Claim nesting is bounded at depth 32; deeper rules do
|
|
61
|
+
not parse. A claim MAY reference a role the cast does not declare; that
|
|
62
|
+
is not a parse error and evaluates per section 5.
|
|
63
|
+
|
|
64
|
+
## 3. Cast
|
|
65
|
+
|
|
66
|
+
The cast is the trust boundary. Everything in it is DECLARED — taken on
|
|
67
|
+
the rule author's word and surfaced in the verdict — never derived.
|
|
68
|
+
|
|
69
|
+
Each role is an object:
|
|
70
|
+
|
|
71
|
+
| field | required | meaning |
|
|
72
|
+
|---|---|---|
|
|
73
|
+
| `digest` | yes | SHA-256 of the bits, as `sha256:<hex>`, bare hex, base64, or base64url; all normalize to one canonical form. Base64 forms MUST be canonical spellings (round-trip byte-exactly); spellings with nonzero trailing padding bits are parse errors, never silently reinterpreted |
|
|
74
|
+
| `means` | no | what the digest means as a business object; echoed, never interpreted |
|
|
75
|
+
| `at` | no | occurrence pin: `{ "proofHash": s }` or `{ "epochId": s, "counter": decimal-string }` |
|
|
76
|
+
| `signedBy` | no | external identity evidence; echoed verbatim, `verifiedHere: false`. SIGNED_BY is not a BitGraph primitive |
|
|
77
|
+
| `optional` | no | boolean, default false |
|
|
78
|
+
|
|
79
|
+
### 3.1 Resolution
|
|
80
|
+
|
|
81
|
+
A digest identifies bits; a recording identifies an occurrence of those
|
|
82
|
+
bits at a causal position. A role resolves against the bundle's verified
|
|
83
|
+
recordings of its digest — proofs whose canonical verification PASSED:
|
|
84
|
+
audit status `"verified"` (the full-tier pass, artifact bytes present and
|
|
85
|
+
matching) or `"artifact-unavailable"` (the integrity-tier pass, verified
|
|
86
|
+
bytes-free; the digest is inside the signed body either way). Recordings
|
|
87
|
+
whose verification failed are not evidence. Digest matching is by decoded
|
|
88
|
+
BYTES, not string equality: a bundle proof may spell its digest in any
|
|
89
|
+
accepted form, and "only broken recordings exist" must not masquerade as
|
|
90
|
+
"no recordings exist".
|
|
91
|
+
|
|
92
|
+
| verified matches | pin | resolution |
|
|
93
|
+
|---|---|---|
|
|
94
|
+
| exactly 1 | — | resolved |
|
|
95
|
+
| 0, and matches exist unverified | — | invalid (evaluates UNDETERMINED): "only broken recordings" does not support an absence claim |
|
|
96
|
+
| 0, none at all, `optional: true` | — | definitely absent (a fact under the closed world) |
|
|
97
|
+
| 0, none at all, required | — | absent-required (evaluates UNDETERMINED) |
|
|
98
|
+
| 2 or more | none | ambiguous (evaluates UNDETERMINED; never a silent pick) |
|
|
99
|
+
| 2 or more | selects exactly 1 | resolved |
|
|
100
|
+
| any | selects 0 | invalid (evaluates UNDETERMINED) |
|
|
101
|
+
| any | selects 2+ | ambiguous |
|
|
102
|
+
|
|
103
|
+
## 4. Ordering
|
|
104
|
+
|
|
105
|
+
An artifact's causal position is its COMMIT position. The slot is
|
|
106
|
+
evidence about creation, never an alternative position.
|
|
107
|
+
|
|
108
|
+
Commit counters obey the canonical strict-decimal grammar `[0-9]+` (no
|
|
109
|
+
sign, no whitespace, no base prefix, non-empty). Any other counter string
|
|
110
|
+
is NO counter evidence, exactly as the audit pipeline treats it — never
|
|
111
|
+
parsed leniently, never a crash.
|
|
112
|
+
|
|
113
|
+
Given two resolved recordings A and B, precedence is decided by the first
|
|
114
|
+
applicable row and no other source:
|
|
115
|
+
|
|
116
|
+
| situation | answer | basis | tier |
|
|
117
|
+
|---|---|---|---|
|
|
118
|
+
| same recording | not-before (contributes FALSE to `before`) | — | — |
|
|
119
|
+
| either recording holds no causal position (unchained) | unordered | — | — |
|
|
120
|
+
| same partition (signer key, epochId, chainId), a DIRECTED prevB64 path through observed proofs connects the two, in both directions (cycle) | unordered (anomaly) | — | — |
|
|
121
|
+
| same partition, a directed prevB64 path connects the two, and both counters parse with an order CONTRADICTING the path | unordered (anomaly) | — | — |
|
|
122
|
+
| same partition, a directed prevB64 path connects the two | the path decides the direction (ancestor precedes descendant) | `chain-link` | hash-linked |
|
|
123
|
+
| same partition, no path, both counters parse, distinct | strict order of commit counters as integers | `counter-order` | assumption-dependent |
|
|
124
|
+
| same partition, no path, counters missing/unparseable or equal | unordered | — | — |
|
|
125
|
+
| different partitions, same epochId string | unordered (a self-declared epochId is not epoch membership) | — | — |
|
|
126
|
+
| different epochs, a chain of hard epochLink edges COVERS the pair (section 4.2) | A before B along the chain | `epoch-lineage` | hash-linked, or assumption-dependent when predecessor-side coverage rests on counters |
|
|
127
|
+
| different epochs, lineage coverage holds in both directions | unordered (contradictory) | — | — |
|
|
128
|
+
| different epochs, a not-after anchor bound on A's segment strictly precedes a not-before anchor bound on B's segment, and NOT also the reverse | A before B | `anchor-bounds` | assumption-dependent |
|
|
129
|
+
| different epochs, strict anchor separation in both directions | unordered (contradictory) | — | — |
|
|
130
|
+
| otherwise | unordered | — | — |
|
|
131
|
+
|
|
132
|
+
Undirected co-membership in a prevB64 component is NOT chain-link
|
|
133
|
+
evidence: two fork branches share a component with no path between them,
|
|
134
|
+
and their relative order rests only on counter discipline — which the
|
|
135
|
+
fork itself demonstrates is broken.
|
|
136
|
+
|
|
137
|
+
Strict anchor precedence means strictly smaller block number (or, when a
|
|
138
|
+
block number is absent, strictly smaller verified witness timestamp).
|
|
139
|
+
Equality proves nothing: A precedes the anchor COMMIT that consumed block
|
|
140
|
+
N while B follows the MINING of block N, and the gap between mining and
|
|
141
|
+
commit is exactly where they could swap. The not-after side always rests
|
|
142
|
+
on the anchor-freshness assumption, which is why every `anchor-bounds`
|
|
143
|
+
answer is assumption-dependent. A `weaker` flag is carried when the
|
|
144
|
+
evidence additionally rests on counter-order rather than a chain-link
|
|
145
|
+
path (on either side of an anchor comparison, or for `counter-order`
|
|
146
|
+
itself).
|
|
147
|
+
|
|
148
|
+
### 4.2 Lineage coverage
|
|
149
|
+
|
|
150
|
+
A hard epochLink edge proves one thing: the successor epoch's key was
|
|
151
|
+
created (at init) after the referenced predecessor proof existed. It is
|
|
152
|
+
applied at recording granularity, never as whole-epoch ordering by
|
|
153
|
+
epochId string — epochId is self-declared, and recordings the evidence
|
|
154
|
+
does not cover get nothing from it.
|
|
155
|
+
|
|
156
|
+
A chain of hard edges proves A-before-B when:
|
|
157
|
+
|
|
158
|
+
- the first edge's observed predecessor proof P is in A's partition,
|
|
159
|
+
and A is P itself or a directed prevB64 ancestor of P (hash-linked),
|
|
160
|
+
or A's parseable counter is strictly smaller than P's (downgrades the
|
|
161
|
+
whole answer to the assumption-dependent tier);
|
|
162
|
+
- each subsequent edge's observed predecessor proof is in the partition
|
|
163
|
+
the previous edge's via proof belongs to (free of assumptions: a
|
|
164
|
+
proof signed by that key postdates the key's creation);
|
|
165
|
+
- the last edge's via proof is in B's partition (B is covered by key:
|
|
166
|
+
it cannot predate its own key's creation).
|
|
167
|
+
|
|
168
|
+
### 4.1 The evidence floor
|
|
169
|
+
|
|
170
|
+
`requires.ordering` is a floor on the tier of ordering evidence the rule
|
|
171
|
+
accepts. An ordering answer whose tier is below the floor makes the
|
|
172
|
+
predicate `UNDETERMINED` — in BOTH directions. The floor gates evidence,
|
|
173
|
+
not polarity: distrusted evidence may neither prove nor refute.
|
|
174
|
+
|
|
175
|
+
## 5. Claims
|
|
176
|
+
|
|
177
|
+
| claim | semantics |
|
|
178
|
+
|---|---|
|
|
179
|
+
| `{ "exists": r }` | TRUE if r resolved; FALSE if r definitely absent; else UNDETERMINED |
|
|
180
|
+
| `{ "before": [x, y] }` | TRUE/FALSE from precedence of x's and y's recordings, gated by the floor; FALSE when either is definitely absent; UNDETERMINED when either is undeclared, absent-required, ambiguous, invalid, or the pair is unordered |
|
|
181
|
+
| `{ "after": [x, y] }` | exactly `before(y, x)` |
|
|
182
|
+
| `{ "between": [s, a, b] }` | `all(after(s, a), before(s, b))`, recorded as its two halves |
|
|
183
|
+
| `{ "all": [...] }`, `{ "any": [...] }`, `{ "not": c }` | strong Kleene (section 1) |
|
|
184
|
+
|
|
185
|
+
The closed world is scoped to the cast: definite absence exists only for
|
|
186
|
+
declared optional roles whose digest has no verified recording in the
|
|
187
|
+
bundle. Positive claims over a definitely absent role are FALSE, which is
|
|
188
|
+
what makes negatives over it hold. A role the cast never declared is
|
|
189
|
+
UNDETERMINED wherever it appears; the closed-world declaration cannot
|
|
190
|
+
speak about bits the author never named.
|
|
191
|
+
|
|
192
|
+
## 6. The verdict
|
|
193
|
+
|
|
194
|
+
A verdict is a JSON object with fields in exactly this order:
|
|
195
|
+
|
|
196
|
+
verdict "bitgraph-player-verdict/1"
|
|
197
|
+
result TRUE | FALSE | UNDETERMINED
|
|
198
|
+
rule { id, sha256 } (sha256: lowercase hex of the rule file bytes)
|
|
199
|
+
then? echoed from the rule
|
|
200
|
+
weakestEvidence? weakest tier among ordering answers that decided a
|
|
201
|
+
step ("assumption-dependent" if any, else
|
|
202
|
+
"hash-linked"); absent when no ordering decided
|
|
203
|
+
anything
|
|
204
|
+
cast per role, in declaration order: digestB64,
|
|
205
|
+
resolution label, and when resolved: proofHash,
|
|
206
|
+
epochId?, chainId, counter?, slotCounter?
|
|
207
|
+
derived every evaluated step, in evaluation order — what
|
|
208
|
+
BitGraph established
|
|
209
|
+
declared what was taken on somebody's word — every `means`,
|
|
210
|
+
every `at` pin, every `signedBy`, each with
|
|
211
|
+
verifiedHere: false, and LAST the closed-world
|
|
212
|
+
entry: { assertion: "closed-world", verifiedHere:
|
|
213
|
+
false, castSize, recordingsInBundle, claim }
|
|
214
|
+
evaluator { name, version }
|
|
215
|
+
network "none"
|
|
216
|
+
|
|
217
|
+
The closed-world entry is mandatory. Nothing in BitGraph establishes that
|
|
218
|
+
a declared cast is complete; without this entry a verdict would pass
|
|
219
|
+
"there is no X before Y" off as established when what was established is
|
|
220
|
+
"among the recordings the author declared, no X precedes Y".
|
|
221
|
+
|
|
222
|
+
## 7. Determinism
|
|
223
|
+
|
|
224
|
+
Serialization: UTF-8 JSON, two-space indent, key order as constructed
|
|
225
|
+
per section 6, one trailing newline. A verdict MUST NOT contain a run
|
|
226
|
+
timestamp, a filesystem path, a hostname, or any other machine- or
|
|
227
|
+
run-local value. Two evaluations of the same rule bytes over the same
|
|
228
|
+
bundle contents MUST be byte-identical.
|
|
229
|
+
|
|
230
|
+
## 8. Exit codes (command-line Players)
|
|
231
|
+
|
|
232
|
+
0 TRUE 1 FALSE 2 UNDETERMINED 3 error
|
|
233
|
+
|
|
234
|
+
Diagnostics go to stderr. Stdout carries verdict bytes only.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cast-order.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/cast-order.test.ts"],"names":[],"mappings":""}
|