@rubric-protocol/jev 1.0.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.
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Stub Jev client (tasks/P3.md). Emits Jev's documented decision shape, standing
3
+ * in for the real external Jev service in tests and local dev. Deterministic
4
+ * given its inputs. It only constructs values of the `JevDecision` type owned by
5
+ * the mapping file — it does not itself map to DAR inputs.
6
+ */
7
+ import { type JevDecision } from "./mapping.js";
8
+ export interface StubJevOptions {
9
+ agentId?: string;
10
+ policyId?: string;
11
+ policyRevision?: number;
12
+ /** Approve when `subject.amountUsd` is at or below this limit. */
13
+ limitUsd?: number;
14
+ }
15
+ export declare class StubJevClient {
16
+ private readonly agentId;
17
+ private readonly policyId;
18
+ private readonly policyRevision;
19
+ private readonly limitUsd;
20
+ constructor(opts?: StubJevOptions);
21
+ /** Emit a Jev decision for a subject. `atMs` sets Jev's emitted time. */
22
+ decide(subject: Record<string, unknown>, atMs?: number): JevDecision;
23
+ }
24
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAmB,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAEjE,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;gBAEtB,IAAI,GAAE,cAAmB;IAOrC,yEAAyE;IACzE,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,GAAE,MAAmB,GAAG,WAAW;CAcjF"}
package/dist/client.js ADDED
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Stub Jev client (tasks/P3.md). Emits Jev's documented decision shape, standing
3
+ * in for the real external Jev service in tests and local dev. Deterministic
4
+ * given its inputs. It only constructs values of the `JevDecision` type owned by
5
+ * the mapping file — it does not itself map to DAR inputs.
6
+ */
7
+ import { makeJevDecision } from "./mapping.js";
8
+ export class StubJevClient {
9
+ agentId;
10
+ policyId;
11
+ policyRevision;
12
+ limitUsd;
13
+ constructor(opts = {}) {
14
+ this.agentId = opts.agentId ?? "agent://jev/stub";
15
+ this.policyId = opts.policyId ?? "policy/default";
16
+ this.policyRevision = opts.policyRevision ?? 1;
17
+ this.limitUsd = opts.limitUsd ?? 1000;
18
+ }
19
+ /** Emit a Jev decision for a subject. `atMs` sets Jev's emitted time. */
20
+ decide(subject, atMs = Date.now()) {
21
+ const amount = typeof subject.amountUsd === "number" ? subject.amountUsd : 0;
22
+ const approved = amount <= this.limitUsd;
23
+ return makeJevDecision({
24
+ agentId: this.agentId,
25
+ policyId: this.policyId,
26
+ policyRevision: this.policyRevision,
27
+ action: approved ? "approve" : "deny",
28
+ score: approved ? 90 : 20,
29
+ reasons: approved ? undefined : ["amount_over_limit"],
30
+ subject,
31
+ emittedAtMs: atMs,
32
+ });
33
+ }
34
+ }
35
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,eAAe,EAAoB,MAAM,cAAc,CAAC;AAUjE,MAAM,OAAO,aAAa;IACP,OAAO,CAAS;IAChB,QAAQ,CAAS;IACjB,cAAc,CAAS;IACvB,QAAQ,CAAS;IAElC,YAAY,OAAuB,EAAE;QACnC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,kBAAkB,CAAC;QAClD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,gBAAgB,CAAC;QAClD,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,cAAc,IAAI,CAAC,CAAC;QAC/C,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC;IACxC,CAAC;IAED,yEAAyE;IACzE,MAAM,CAAC,OAAgC,EAAE,OAAe,IAAI,CAAC,GAAG,EAAE;QAChE,MAAM,MAAM,GAAG,OAAO,OAAO,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7E,MAAM,QAAQ,GAAG,MAAM,IAAI,IAAI,CAAC,QAAQ,CAAC;QACzC,OAAO,eAAe,CAAC;YACrB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,cAAc,EAAE,IAAI,CAAC,cAAc;YACnC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM;YACrC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE;YACzB,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC;YACrD,OAAO;YACP,WAAW,EAAE,IAAI;SAClB,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @rubric-protocol/jev — Jev decision-shape adapter (tasks/P3.md).
3
+ *
4
+ * All knowledge of Jev's documented decision shape is confined to ./mapping.ts;
5
+ * `toDecision()` there produces DAR builder inputs for @rubric-protocol/attest-decision.
6
+ */
7
+ export { toDecision, type JevDecision } from "./mapping.js";
8
+ export { StubJevClient, type StubJevOptions } from "./client.js";
9
+ export declare const JEV_ADAPTER_VERSION: "0.1.0";
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,UAAU,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAEjE,eAAO,MAAM,mBAAmB,EAAG,OAAgB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @rubric-protocol/jev — Jev decision-shape adapter (tasks/P3.md).
3
+ *
4
+ * All knowledge of Jev's documented decision shape is confined to ./mapping.ts;
5
+ * `toDecision()` there produces DAR builder inputs for @rubric-protocol/attest-decision.
6
+ */
7
+ export { toDecision } from "./mapping.js";
8
+ export { StubJevClient } from "./client.js";
9
+ export const JEV_ADAPTER_VERSION = "0.1.0";
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,UAAU,EAAoB,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAuB,MAAM,aAAa,CAAC;AAEjE,MAAM,CAAC,MAAM,mBAAmB,GAAG,OAAgB,CAAC"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Jev decision-shape mapping (tasks/P3.md).
3
+ *
4
+ * This file is the ONLY place that knows Jev's documented decision shape — its
5
+ * field names never appear anywhere else in the pipeline. Everything downstream
6
+ * consumes the DAR builder inputs produced by `toDecision()`.
7
+ */
8
+ import type { DarBuildInput } from "@rubric-protocol/attest-decision";
9
+ /** Jev's documented decision shape (schema tag "jev.decision/1"). */
10
+ export interface JevDecision {
11
+ jevSchema: "jev.decision/1";
12
+ agent: {
13
+ id: string;
14
+ label?: string;
15
+ };
16
+ policy: {
17
+ id: string;
18
+ revision: number;
19
+ };
20
+ outcome: {
21
+ action: string;
22
+ score?: number;
23
+ reasons?: string[];
24
+ };
25
+ subject: Record<string, unknown>;
26
+ emittedAt: string;
27
+ }
28
+ /** Semantic parameters for constructing a Jev decision, free of Jev field names. */
29
+ export interface JevDecisionParams {
30
+ agentId: string;
31
+ policyId: string;
32
+ policyRevision: number;
33
+ action: string;
34
+ score?: number;
35
+ reasons?: string[];
36
+ subject: Record<string, unknown>;
37
+ emittedAtMs: number;
38
+ }
39
+ /** Build a Jev-shaped decision from semantic parameters (the shape lives here). */
40
+ export declare function makeJevDecision(p: JevDecisionParams): JevDecision;
41
+ /**
42
+ * Map a Jev decision to hashes-only DAR builder inputs: the subject is the
43
+ * `input`, the outcome is the `output`, and the policy descriptor is the
44
+ * `schema`. Absent optional fields are omitted (not `undefined`) so each stays
45
+ * strict-JCS clean. No raw content reaches the DAR core — only its hashes.
46
+ */
47
+ export declare function toDecision(jev: JevDecision): DarBuildInput;
48
+ //# sourceMappingURL=mapping.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapping.d.ts","sourceRoot":"","sources":["../src/mapping.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AAItE,qEAAqE;AACrE,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,gBAAgB,CAAC;IAC5B,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACtC,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACzC,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAChE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,oFAAoF;AACpF,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,mFAAmF;AACnF,wBAAgB,eAAe,CAAC,CAAC,EAAE,iBAAiB,GAAG,WAAW,CAYjE;AAYD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,WAAW,GAAG,aAAa,CAgB1D"}
@@ -0,0 +1,51 @@
1
+ const JEV_ADAPTER = { name: "jev", version: "1.0.0" };
2
+ /** Build a Jev-shaped decision from semantic parameters (the shape lives here). */
3
+ export function makeJevDecision(p) {
4
+ const outcome = { action: p.action };
5
+ if (p.score !== undefined)
6
+ outcome.score = p.score;
7
+ if (p.reasons !== undefined)
8
+ outcome.reasons = p.reasons;
9
+ return {
10
+ jevSchema: "jev.decision/1",
11
+ agent: { id: p.agentId },
12
+ policy: { id: p.policyId, revision: p.policyRevision },
13
+ outcome,
14
+ subject: p.subject,
15
+ emittedAt: new Date(p.emittedAtMs).toISOString(),
16
+ };
17
+ }
18
+ /** The schema descriptor a Jev decision is attested under (derived from its policy). */
19
+ function jevSchemaDescriptor(jev) {
20
+ return {
21
+ source: "jev",
22
+ schema: jev.jevSchema,
23
+ policyId: jev.policy.id,
24
+ policyRevision: jev.policy.revision,
25
+ };
26
+ }
27
+ /**
28
+ * Map a Jev decision to hashes-only DAR builder inputs: the subject is the
29
+ * `input`, the outcome is the `output`, and the policy descriptor is the
30
+ * `schema`. Absent optional fields are omitted (not `undefined`) so each stays
31
+ * strict-JCS clean. No raw content reaches the DAR core — only its hashes.
32
+ */
33
+ export function toDecision(jev) {
34
+ const output = { action: jev.outcome.action };
35
+ if (jev.outcome.score !== undefined)
36
+ output.score = jev.outcome.score;
37
+ if (jev.outcome.reasons !== undefined)
38
+ output.reasons = jev.outcome.reasons;
39
+ return {
40
+ agentId: jev.agent.id,
41
+ schema: jevSchemaDescriptor(jev),
42
+ input: jev.subject,
43
+ output,
44
+ meta: {
45
+ schemaRef: `${jev.policy.id}@${jev.policy.revision}`,
46
+ adapter: { ...JEV_ADAPTER },
47
+ leafType: "decision",
48
+ },
49
+ };
50
+ }
51
+ //# sourceMappingURL=mapping.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapping.js","sourceRoot":"","sources":["../src/mapping.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAW,CAAC;AAwB/D,mFAAmF;AACnF,MAAM,UAAU,eAAe,CAAC,CAAoB;IAClD,MAAM,OAAO,GAA2B,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;IAC7D,IAAI,CAAC,CAAC,KAAK,KAAK,SAAS;QAAE,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;IACnD,IAAI,CAAC,CAAC,OAAO,KAAK,SAAS;QAAE,OAAO,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC;IACzD,OAAO;QACL,SAAS,EAAE,gBAAgB;QAC3B,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE;QACxB,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC,cAAc,EAAE;QACtD,OAAO;QACP,OAAO,EAAE,CAAC,CAAC,OAAO;QAClB,SAAS,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,WAAW,EAAE;KACjD,CAAC;AACJ,CAAC;AAED,wFAAwF;AACxF,SAAS,mBAAmB,CAAC,GAAgB;IAC3C,OAAO;QACL,MAAM,EAAE,KAAK;QACb,MAAM,EAAE,GAAG,CAAC,SAAS;QACrB,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE;QACvB,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,QAAQ;KACpC,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,GAAgB;IACzC,MAAM,MAAM,GAA4B,EAAE,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;IACvE,IAAI,GAAG,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS;QAAE,MAAM,CAAC,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC;IACtE,IAAI,GAAG,CAAC,OAAO,CAAC,OAAO,KAAK,SAAS;QAAE,MAAM,CAAC,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC;IAE5E,OAAO;QACL,OAAO,EAAE,GAAG,CAAC,KAAK,CAAC,EAAE;QACrB,MAAM,EAAE,mBAAmB,CAAC,GAAG,CAAC;QAChC,KAAK,EAAE,GAAG,CAAC,OAAO;QAClB,MAAM;QACN,IAAI,EAAE;YACJ,SAAS,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,EAAE;YACpD,OAAO,EAAE,EAAE,GAAG,WAAW,EAAE;YAC3B,QAAQ,EAAE,UAAU;SACrB;KACF,CAAC;AACJ,CAAC"}
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@rubric-protocol/jev",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "description": "Rubric adapter: Jev decision shape -> DAR inputs (mapping confined here)",
6
+ "license": "Apache-2.0",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/0xsims/rubric-attest.git",
10
+ "directory": "packages/jev"
11
+ },
12
+ "main": "./dist/index.js",
13
+ "types": "./dist/index.d.ts",
14
+ "exports": {
15
+ ".": {
16
+ "development": "./src/index.ts",
17
+ "types": "./dist/index.d.ts",
18
+ "default": "./dist/index.js"
19
+ }
20
+ },
21
+ "files": ["dist", "src"],
22
+ "publishConfig": { "access": "public" },
23
+ "scripts": {
24
+ "prepublishOnly": "npm run build",
25
+ "build": "tsc -p tsconfig.build.json",
26
+ "test": "vitest run"
27
+ },
28
+ "dependencies": {
29
+ "@rubric-protocol/attest-decision": "^1.0.0"
30
+ }
31
+ }
package/src/client.ts ADDED
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Stub Jev client (tasks/P3.md). Emits Jev's documented decision shape, standing
3
+ * in for the real external Jev service in tests and local dev. Deterministic
4
+ * given its inputs. It only constructs values of the `JevDecision` type owned by
5
+ * the mapping file — it does not itself map to DAR inputs.
6
+ */
7
+ import { makeJevDecision, type JevDecision } from "./mapping.js";
8
+
9
+ export interface StubJevOptions {
10
+ agentId?: string;
11
+ policyId?: string;
12
+ policyRevision?: number;
13
+ /** Approve when `subject.amountUsd` is at or below this limit. */
14
+ limitUsd?: number;
15
+ }
16
+
17
+ export class StubJevClient {
18
+ private readonly agentId: string;
19
+ private readonly policyId: string;
20
+ private readonly policyRevision: number;
21
+ private readonly limitUsd: number;
22
+
23
+ constructor(opts: StubJevOptions = {}) {
24
+ this.agentId = opts.agentId ?? "agent://jev/stub";
25
+ this.policyId = opts.policyId ?? "policy/default";
26
+ this.policyRevision = opts.policyRevision ?? 1;
27
+ this.limitUsd = opts.limitUsd ?? 1000;
28
+ }
29
+
30
+ /** Emit a Jev decision for a subject. `atMs` sets Jev's emitted time. */
31
+ decide(subject: Record<string, unknown>, atMs: number = Date.now()): JevDecision {
32
+ const amount = typeof subject.amountUsd === "number" ? subject.amountUsd : 0;
33
+ const approved = amount <= this.limitUsd;
34
+ return makeJevDecision({
35
+ agentId: this.agentId,
36
+ policyId: this.policyId,
37
+ policyRevision: this.policyRevision,
38
+ action: approved ? "approve" : "deny",
39
+ score: approved ? 90 : 20,
40
+ reasons: approved ? undefined : ["amount_over_limit"],
41
+ subject,
42
+ emittedAtMs: atMs,
43
+ });
44
+ }
45
+ }
package/src/index.ts ADDED
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @rubric-protocol/jev — Jev decision-shape adapter (tasks/P3.md).
3
+ *
4
+ * All knowledge of Jev's documented decision shape is confined to ./mapping.ts;
5
+ * `toDecision()` there produces DAR builder inputs for @rubric-protocol/attest-decision.
6
+ */
7
+ export { toDecision, type JevDecision } from "./mapping.js";
8
+ export { StubJevClient, type StubJevOptions } from "./client.js";
9
+
10
+ export const JEV_ADAPTER_VERSION = "0.1.0" as const;
package/src/mapping.ts ADDED
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Jev decision-shape mapping (tasks/P3.md).
3
+ *
4
+ * This file is the ONLY place that knows Jev's documented decision shape — its
5
+ * field names never appear anywhere else in the pipeline. Everything downstream
6
+ * consumes the DAR builder inputs produced by `toDecision()`.
7
+ */
8
+ import type { DarBuildInput } from "@rubric-protocol/attest-decision";
9
+
10
+ const JEV_ADAPTER = { name: "jev", version: "1.0.0" } as const;
11
+
12
+ /** Jev's documented decision shape (schema tag "jev.decision/1"). */
13
+ export interface JevDecision {
14
+ jevSchema: "jev.decision/1";
15
+ agent: { id: string; label?: string };
16
+ policy: { id: string; revision: number };
17
+ outcome: { action: string; score?: number; reasons?: string[] };
18
+ subject: Record<string, unknown>;
19
+ emittedAt: string; // RFC 3339 UTC
20
+ }
21
+
22
+ /** Semantic parameters for constructing a Jev decision, free of Jev field names. */
23
+ export interface JevDecisionParams {
24
+ agentId: string;
25
+ policyId: string;
26
+ policyRevision: number;
27
+ action: string;
28
+ score?: number;
29
+ reasons?: string[];
30
+ subject: Record<string, unknown>;
31
+ emittedAtMs: number;
32
+ }
33
+
34
+ /** Build a Jev-shaped decision from semantic parameters (the shape lives here). */
35
+ export function makeJevDecision(p: JevDecisionParams): JevDecision {
36
+ const outcome: JevDecision["outcome"] = { action: p.action };
37
+ if (p.score !== undefined) outcome.score = p.score;
38
+ if (p.reasons !== undefined) outcome.reasons = p.reasons;
39
+ return {
40
+ jevSchema: "jev.decision/1",
41
+ agent: { id: p.agentId },
42
+ policy: { id: p.policyId, revision: p.policyRevision },
43
+ outcome,
44
+ subject: p.subject,
45
+ emittedAt: new Date(p.emittedAtMs).toISOString(),
46
+ };
47
+ }
48
+
49
+ /** The schema descriptor a Jev decision is attested under (derived from its policy). */
50
+ function jevSchemaDescriptor(jev: JevDecision): Record<string, unknown> {
51
+ return {
52
+ source: "jev",
53
+ schema: jev.jevSchema,
54
+ policyId: jev.policy.id,
55
+ policyRevision: jev.policy.revision,
56
+ };
57
+ }
58
+
59
+ /**
60
+ * Map a Jev decision to hashes-only DAR builder inputs: the subject is the
61
+ * `input`, the outcome is the `output`, and the policy descriptor is the
62
+ * `schema`. Absent optional fields are omitted (not `undefined`) so each stays
63
+ * strict-JCS clean. No raw content reaches the DAR core — only its hashes.
64
+ */
65
+ export function toDecision(jev: JevDecision): DarBuildInput {
66
+ const output: Record<string, unknown> = { action: jev.outcome.action };
67
+ if (jev.outcome.score !== undefined) output.score = jev.outcome.score;
68
+ if (jev.outcome.reasons !== undefined) output.reasons = jev.outcome.reasons;
69
+
70
+ return {
71
+ agentId: jev.agent.id,
72
+ schema: jevSchemaDescriptor(jev),
73
+ input: jev.subject,
74
+ output,
75
+ meta: {
76
+ schemaRef: `${jev.policy.id}@${jev.policy.revision}`,
77
+ adapter: { ...JEV_ADAPTER },
78
+ leafType: "decision",
79
+ },
80
+ };
81
+ }