@sentropic/focus 0.3.0 → 0.5.0-rc.3
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 +9 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/model.d.ts +73 -1
- package/dist/model.d.ts.map +1 -1
- package/dist/registry/definitions.d.ts +159 -0
- package/dist/registry/definitions.d.ts.map +1 -0
- package/dist/registry/definitions.js +501 -0
- package/dist/registry/definitions.js.map +1 -0
- package/dist/render/html.d.ts.map +1 -1
- package/dist/render/html.js +12 -1
- package/dist/render/html.js.map +1 -1
- package/dist/render/md.d.ts.map +1 -1
- package/dist/render/md.js +12 -1
- package/dist/render/md.js.map +1 -1
- package/dist/render/presentation.d.ts +4 -0
- package/dist/render/presentation.d.ts.map +1 -0
- package/dist/render/presentation.js +25 -0
- package/dist/render/presentation.js.map +1 -0
- package/dist/render/terminal.d.ts.map +1 -1
- package/dist/render/terminal.js +12 -1
- package/dist/render/terminal.js.map +1 -1
- package/dist/track/index.d.ts.map +1 -1
- package/dist/track/index.js +24 -10
- package/dist/track/index.js.map +1 -1
- package/dist/validation/index.d.ts +59 -0
- package/dist/validation/index.d.ts.map +1 -0
- package/dist/validation/index.js +490 -0
- package/dist/validation/index.js.map +1 -0
- package/dist/validation/readability.d.ts +28 -0
- package/dist/validation/readability.d.ts.map +1 -0
- package/dist/validation/readability.js +244 -0
- package/dist/validation/readability.js.map +1 -0
- package/package.json +25 -8
- package/registry/entries.v1.json +127 -0
- package/schemas/decision-dossier-document.v1.schema.json +193 -0
- package/skills/focus/SKILL.md +132 -0
|
@@ -0,0 +1,490 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@sentropic/focus/validate` — the typed runtime validator for the
|
|
3
|
+
* `DecisionDossierDocument` (contract §4.2, R4).
|
|
4
|
+
*
|
|
5
|
+
* Two layers, matching the published JSON Schema asset
|
|
6
|
+
* (`schemas/decision-dossier-document.v1.schema.json`,
|
|
7
|
+
* `urn:sentropic:focus:DecisionDossierDocument:1.0.0`):
|
|
8
|
+
*
|
|
9
|
+
* 1. structure — closed shape check (unknown fields, wrong types, bad enums,
|
|
10
|
+
* an enabled snapshot interaction all refuse);
|
|
11
|
+
* 2. semantics — unique node IDs, interaction targets resolvable to the
|
|
12
|
+
* dossier ref, a section id/targetRef or a nested option id/targetRef,
|
|
13
|
+
* an opaque provenance source binding (any string, per the published
|
|
14
|
+
* schema), and comprehension evidence whose dossier hash still matches
|
|
15
|
+
* the snapshot hash.
|
|
16
|
+
*
|
|
17
|
+
* Pure and dependency-free: no I/O, no clock, no mutation of the input.
|
|
18
|
+
* Every recorded issue is a refusal — the schema is closed.
|
|
19
|
+
*/
|
|
20
|
+
import { validateDecisionDossierReadability } from "./readability.js";
|
|
21
|
+
export { READABILITY_LIMITS, READABILITY_BUDGETS, validateDecisionDossierReadability } from "./readability.js";
|
|
22
|
+
/** Stable schema ID of the published DecisionDossierDocument asset. */
|
|
23
|
+
export const DOSSIER_SCHEMA_ID = "urn:sentropic:focus:DecisionDossierDocument:1.0.0";
|
|
24
|
+
/** Version of the dossier schema, independent of the package version. */
|
|
25
|
+
export const DOSSIER_SCHEMA_VERSION = "1.0.0";
|
|
26
|
+
/** Thrown by {@link assertDecisionDossierDocument} on an invalid dossier. */
|
|
27
|
+
export class DecisionDossierValidationError extends Error {
|
|
28
|
+
issues;
|
|
29
|
+
constructor(issues) {
|
|
30
|
+
super(`invalid DecisionDossierDocument: ${issues
|
|
31
|
+
.map((issue) => `${issue.path} ${issue.code}: ${issue.message}`)
|
|
32
|
+
.join("; ")}`);
|
|
33
|
+
this.name = "DecisionDossierValidationError";
|
|
34
|
+
this.issues = issues;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
38
|
+
const issue = (path, code, message) => ({
|
|
39
|
+
path,
|
|
40
|
+
code,
|
|
41
|
+
message,
|
|
42
|
+
});
|
|
43
|
+
/**
|
|
44
|
+
* Closed-object check: unknown keys refuse, required keys must be present,
|
|
45
|
+
* and `stringKeys` members must be strings when present (a missing required
|
|
46
|
+
* string key therefore yields exactly one `missing_field`).
|
|
47
|
+
*/
|
|
48
|
+
const checkClosedObject = (value, path, allowed, required, stringKeys, issues) => {
|
|
49
|
+
if (!isRecord(value)) {
|
|
50
|
+
issues.push(issue(path, "invalid_type", "expected an object"));
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
const allowedSet = new Set(allowed);
|
|
54
|
+
for (const key of Object.keys(value)) {
|
|
55
|
+
if (!allowedSet.has(key)) {
|
|
56
|
+
issues.push(issue(`${path}.${key}`, "unknown_field", "field not in the closed schema"));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
for (const key of required) {
|
|
60
|
+
if (value[key] === undefined) {
|
|
61
|
+
issues.push(issue(`${path}.${key}`, "missing_field", "required field is missing"));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
for (const key of stringKeys) {
|
|
65
|
+
if (value[key] !== undefined && typeof value[key] !== "string") {
|
|
66
|
+
issues.push(issue(`${path}.${key}`, "invalid_type", "expected a string"));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return value;
|
|
70
|
+
};
|
|
71
|
+
const checkEnum = (value, path, allowed, issues) => {
|
|
72
|
+
if (typeof value !== "string" || !allowed.includes(value)) {
|
|
73
|
+
issues.push(issue(path, "invalid_enum", `expected one of: ${allowed.join(" | ")}`));
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
const TOP_REQUIRED = [
|
|
77
|
+
"ref",
|
|
78
|
+
"subject",
|
|
79
|
+
"title",
|
|
80
|
+
"hash",
|
|
81
|
+
"cursor",
|
|
82
|
+
"sections",
|
|
83
|
+
"interactions",
|
|
84
|
+
"provenance",
|
|
85
|
+
"amendmentTrace",
|
|
86
|
+
];
|
|
87
|
+
const TOP_STRINGS = ["ref", "subject", "title", "hash", "cursor"];
|
|
88
|
+
/** Backward-compatible readability fields: optional at schema level, enforced by the gate. */
|
|
89
|
+
const TOP_ALLOWED = [...TOP_REQUIRED, "readability"];
|
|
90
|
+
const checkOptionNode = (value, path, issues) => {
|
|
91
|
+
const start = issues.length;
|
|
92
|
+
const node = checkClosedObject(value, path, ["kind", "id", "targetRef", "label", "body", "annotation", "annotationComment", "consequence"], ["kind", "id", "targetRef", "label", "annotation"], ["id", "targetRef", "label", "body", "annotationComment", "consequence"], issues);
|
|
93
|
+
if (node === undefined)
|
|
94
|
+
return undefined;
|
|
95
|
+
if (node["kind"] !== "option") {
|
|
96
|
+
issues.push(issue(`${path}.kind`, "invalid_discriminator", 'expected "option"'));
|
|
97
|
+
}
|
|
98
|
+
checkEnum(node["annotation"], `${path}.annotation`, ["none", "accept", "reject", "comment"], issues);
|
|
99
|
+
if (issues.length !== start)
|
|
100
|
+
return undefined;
|
|
101
|
+
return {
|
|
102
|
+
kind: "option",
|
|
103
|
+
id: node["id"],
|
|
104
|
+
targetRef: node["targetRef"],
|
|
105
|
+
label: node["label"],
|
|
106
|
+
...(typeof node["body"] === "string" ? { body: node["body"] } : {}),
|
|
107
|
+
annotation: node["annotation"],
|
|
108
|
+
...(typeof node["annotationComment"] === "string"
|
|
109
|
+
? { annotationComment: node["annotationComment"] }
|
|
110
|
+
: {}),
|
|
111
|
+
...(typeof node["consequence"] === "string" ? { consequence: node["consequence"] } : {}),
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
const checkAmendmentStep = (value, path, issues) => {
|
|
115
|
+
const start = issues.length;
|
|
116
|
+
const step = checkClosedObject(value, path, ["at", "author", "summary"], ["at", "author", "summary"], ["at", "author", "summary"], issues);
|
|
117
|
+
if (step === undefined || issues.length !== start)
|
|
118
|
+
return undefined;
|
|
119
|
+
return { at: step["at"], author: step["author"], summary: step["summary"] };
|
|
120
|
+
};
|
|
121
|
+
const checkSectionNode = (value, path, issues) => {
|
|
122
|
+
if (!isRecord(value)) {
|
|
123
|
+
issues.push(issue(path, "invalid_type", "expected an object"));
|
|
124
|
+
return undefined;
|
|
125
|
+
}
|
|
126
|
+
const kind = value["kind"];
|
|
127
|
+
if (kind !== "prose" && kind !== "question" && kind !== "optionSet" && kind !== "outcome" && kind !== "amendmentTrace" && kind !== "diagram") {
|
|
128
|
+
issues.push(issue(`${path}.kind`, typeof kind === "undefined" ? "missing_field" : "unknown_node_kind", `unknown section kind ${typeof kind === "string" ? `"${kind}"` : " discriminant"}`));
|
|
129
|
+
return undefined;
|
|
130
|
+
}
|
|
131
|
+
const start = issues.length;
|
|
132
|
+
switch (kind) {
|
|
133
|
+
case "prose": {
|
|
134
|
+
const node = checkClosedObject(value, path, ["kind", "id", "targetRef", "markdown", "questionId"], ["kind", "id", "targetRef", "markdown"], ["id", "targetRef", "markdown", "questionId"], issues);
|
|
135
|
+
if (node === undefined || issues.length !== start)
|
|
136
|
+
return undefined;
|
|
137
|
+
return { kind: "prose", id: node["id"], targetRef: node["targetRef"], markdown: node["markdown"], ...(typeof node["questionId"] === "string" ? { questionId: node["questionId"] } : {}) };
|
|
138
|
+
}
|
|
139
|
+
case "question": {
|
|
140
|
+
const node = checkClosedObject(value, path, ["kind", "id", "targetRef", "question", "recommendedAnswer", "answer", "state", "context", "readingTimeMinutes", "recommendedOptionId"], ["kind", "id", "targetRef", "question", "state"], ["id", "targetRef", "question", "recommendedAnswer", "answer", "context", "recommendedOptionId"], issues);
|
|
141
|
+
if (node === undefined)
|
|
142
|
+
return undefined;
|
|
143
|
+
checkEnum(node["state"], `${path}.state`, ["open", "answered", "validated"], issues);
|
|
144
|
+
if (node["readingTimeMinutes"] !== undefined && (typeof node["readingTimeMinutes"] !== "number" || !Number.isFinite(node["readingTimeMinutes"]))) {
|
|
145
|
+
issues.push(issue(`${path}.readingTimeMinutes`, "invalid_type", "expected a finite number"));
|
|
146
|
+
}
|
|
147
|
+
if (issues.length !== start)
|
|
148
|
+
return undefined;
|
|
149
|
+
return {
|
|
150
|
+
kind: "question",
|
|
151
|
+
id: node["id"],
|
|
152
|
+
targetRef: node["targetRef"],
|
|
153
|
+
question: node["question"],
|
|
154
|
+
...(typeof node["recommendedAnswer"] === "string" ? { recommendedAnswer: node["recommendedAnswer"] } : {}),
|
|
155
|
+
...(typeof node["answer"] === "string" ? { answer: node["answer"] } : {}),
|
|
156
|
+
state: node["state"],
|
|
157
|
+
...(typeof node["context"] === "string" ? { context: node["context"] } : {}),
|
|
158
|
+
...(typeof node["recommendedOptionId"] === "string" ? { recommendedOptionId: node["recommendedOptionId"] } : {}),
|
|
159
|
+
...(typeof node["readingTimeMinutes"] === "number" ? { readingTimeMinutes: node["readingTimeMinutes"] } : {}),
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
case "optionSet": {
|
|
163
|
+
const node = checkClosedObject(value, path, ["kind", "id", "targetRef", "title", "options", "questionId"], ["kind", "id", "targetRef", "options"], ["id", "targetRef", "title", "questionId"], issues);
|
|
164
|
+
if (node === undefined)
|
|
165
|
+
return undefined;
|
|
166
|
+
const options = [];
|
|
167
|
+
if (!Array.isArray(node["options"])) {
|
|
168
|
+
issues.push(issue(`${path}.options`, "invalid_type", "expected an array"));
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
node["options"].forEach((option, index) => {
|
|
172
|
+
const checked = checkOptionNode(option, `${path}.options[${index}]`, issues);
|
|
173
|
+
if (checked !== undefined)
|
|
174
|
+
options.push(checked);
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
if (issues.length !== start)
|
|
178
|
+
return undefined;
|
|
179
|
+
return {
|
|
180
|
+
kind: "optionSet",
|
|
181
|
+
id: node["id"],
|
|
182
|
+
targetRef: node["targetRef"],
|
|
183
|
+
...(typeof node["title"] === "string" ? { title: node["title"] } : {}),
|
|
184
|
+
options,
|
|
185
|
+
...(typeof node["questionId"] === "string" ? { questionId: node["questionId"] } : {}),
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
case "outcome": {
|
|
189
|
+
const node = checkClosedObject(value, path, ["kind", "id", "targetRef", "modality", "statement", "questionId"], ["kind", "id", "targetRef", "modality", "statement"], ["id", "targetRef", "statement", "questionId"], issues);
|
|
190
|
+
if (node === undefined)
|
|
191
|
+
return undefined;
|
|
192
|
+
checkEnum(node["modality"], `${path}.modality`, ["decision", "orientation", "amendment", "comment"], issues);
|
|
193
|
+
if (issues.length !== start)
|
|
194
|
+
return undefined;
|
|
195
|
+
return {
|
|
196
|
+
kind: "outcome",
|
|
197
|
+
id: node["id"],
|
|
198
|
+
targetRef: node["targetRef"],
|
|
199
|
+
modality: node["modality"],
|
|
200
|
+
statement: node["statement"],
|
|
201
|
+
...(typeof node["questionId"] === "string" ? { questionId: node["questionId"] } : {}),
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
case "amendmentTrace": {
|
|
205
|
+
const node = checkClosedObject(value, path, ["kind", "id", "targetRef", "steps"], ["kind", "id", "targetRef", "steps"], ["id", "targetRef"], issues);
|
|
206
|
+
if (node === undefined)
|
|
207
|
+
return undefined;
|
|
208
|
+
const steps = [];
|
|
209
|
+
if (!Array.isArray(node["steps"])) {
|
|
210
|
+
issues.push(issue(`${path}.steps`, "invalid_type", "expected an array"));
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
node["steps"].forEach((step, index) => {
|
|
214
|
+
const checked = checkAmendmentStep(step, `${path}.steps[${index}]`, issues);
|
|
215
|
+
if (checked !== undefined)
|
|
216
|
+
steps.push(checked);
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
if (issues.length !== start)
|
|
220
|
+
return undefined;
|
|
221
|
+
return {
|
|
222
|
+
kind: "amendmentTrace",
|
|
223
|
+
id: node["id"],
|
|
224
|
+
targetRef: node["targetRef"],
|
|
225
|
+
steps,
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
case "diagram": {
|
|
229
|
+
const node = checkClosedObject(value, path, ["kind", "id", "targetRef", "syntax", "source", "alt", "scene"], ["kind", "id", "targetRef", "syntax", "source", "alt"], ["id", "targetRef", "source", "alt"], issues);
|
|
230
|
+
if (node === undefined)
|
|
231
|
+
return undefined;
|
|
232
|
+
checkEnum(node["syntax"], `${path}.syntax`, ["mermaid", "plantuml"], issues);
|
|
233
|
+
// Opaque diagram-core JSON; its authoritative schema will be pinned when published.
|
|
234
|
+
if (node["scene"] !== undefined && !isRecord(node["scene"])) {
|
|
235
|
+
issues.push(issue(`${path}.scene`, "invalid_type", "expected a diagram-core SemanticDocument object"));
|
|
236
|
+
}
|
|
237
|
+
if (issues.length !== start)
|
|
238
|
+
return undefined;
|
|
239
|
+
return {
|
|
240
|
+
kind: "diagram",
|
|
241
|
+
id: node["id"],
|
|
242
|
+
targetRef: node["targetRef"],
|
|
243
|
+
syntax: node["syntax"],
|
|
244
|
+
source: node["source"],
|
|
245
|
+
alt: node["alt"],
|
|
246
|
+
...(node["scene"] === undefined ? {} : { scene: node["scene"] }),
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
const checkInteraction = (value, path, issues) => {
|
|
252
|
+
const start = issues.length;
|
|
253
|
+
const affordance = checkClosedObject(value, path, ["name", "targetRef", "label", "enabled"], ["name", "targetRef", "label", "enabled"], ["name", "targetRef", "label"], issues);
|
|
254
|
+
if (affordance === undefined)
|
|
255
|
+
return undefined;
|
|
256
|
+
// The snapshot profile is read-only: an enabled affordance is never valid here.
|
|
257
|
+
if (affordance["enabled"] !== false) {
|
|
258
|
+
issues.push(issue(`${path}.enabled`, "enabled_action", "snapshot interactions must stay disabled (enabled:false)"));
|
|
259
|
+
}
|
|
260
|
+
if (issues.length !== start)
|
|
261
|
+
return undefined;
|
|
262
|
+
return {
|
|
263
|
+
name: affordance["name"],
|
|
264
|
+
targetRef: affordance["targetRef"],
|
|
265
|
+
label: affordance["label"],
|
|
266
|
+
enabled: false,
|
|
267
|
+
};
|
|
268
|
+
};
|
|
269
|
+
const checkGlossaryEntry = (value, path, issues) => {
|
|
270
|
+
const start = issues.length;
|
|
271
|
+
const entry = checkClosedObject(value, path, ["term", "definition"], ["term", "definition"], ["term", "definition"], issues);
|
|
272
|
+
if (entry === undefined || issues.length !== start)
|
|
273
|
+
return undefined;
|
|
274
|
+
return { term: entry["term"], definition: entry["definition"] };
|
|
275
|
+
};
|
|
276
|
+
/** Closed-object check for the optional dossier-level readability statement. */
|
|
277
|
+
const checkReadability = (value, path, issues) => {
|
|
278
|
+
const start = issues.length;
|
|
279
|
+
const block = checkClosedObject(value, path, ["ownerRequestQuote", "noOwnerRequest", "stakes", "stakesLevel", "readingBudgetMinutes", "glossary"], [], ["ownerRequestQuote", "stakes"], issues);
|
|
280
|
+
if (block === undefined)
|
|
281
|
+
return undefined;
|
|
282
|
+
if (block["stakesLevel"] !== undefined) {
|
|
283
|
+
checkEnum(block["stakesLevel"], `${path}.stakesLevel`, ["low", "medium", "high"], issues);
|
|
284
|
+
}
|
|
285
|
+
if (block["noOwnerRequest"] !== undefined && typeof block["noOwnerRequest"] !== "boolean") {
|
|
286
|
+
issues.push(issue(`${path}.noOwnerRequest`, "invalid_type", "expected a boolean"));
|
|
287
|
+
}
|
|
288
|
+
if (block["readingBudgetMinutes"] !== undefined && (typeof block["readingBudgetMinutes"] !== "number" || !Number.isFinite(block["readingBudgetMinutes"]))) {
|
|
289
|
+
issues.push(issue(`${path}.readingBudgetMinutes`, "invalid_type", "expected a finite number"));
|
|
290
|
+
}
|
|
291
|
+
let glossary;
|
|
292
|
+
if (block["glossary"] !== undefined) {
|
|
293
|
+
glossary = [];
|
|
294
|
+
if (!Array.isArray(block["glossary"])) {
|
|
295
|
+
issues.push(issue(`${path}.glossary`, "invalid_type", "expected an array"));
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
block["glossary"].forEach((entry, index) => {
|
|
299
|
+
const checked = checkGlossaryEntry(entry, `${path}.glossary[${index}]`, issues);
|
|
300
|
+
if (checked !== undefined)
|
|
301
|
+
glossary.push(checked);
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
if (issues.length !== start)
|
|
306
|
+
return undefined;
|
|
307
|
+
return {
|
|
308
|
+
...(typeof block["ownerRequestQuote"] === "string" ? { ownerRequestQuote: block["ownerRequestQuote"] } : {}),
|
|
309
|
+
...(typeof block["noOwnerRequest"] === "boolean" ? { noOwnerRequest: block["noOwnerRequest"] } : {}),
|
|
310
|
+
...(typeof block["stakes"] === "string" ? { stakes: block["stakes"] } : {}),
|
|
311
|
+
...(block["stakesLevel"] !== undefined ? { stakesLevel: block["stakesLevel"] } : {}),
|
|
312
|
+
...(typeof block["readingBudgetMinutes"] === "number" ? { readingBudgetMinutes: block["readingBudgetMinutes"] } : {}),
|
|
313
|
+
...(glossary !== undefined ? { glossary } : {}),
|
|
314
|
+
};
|
|
315
|
+
};
|
|
316
|
+
/** Structural layer: closed shape check against the published schema. */
|
|
317
|
+
export const validateDecisionDossierStructure = (value) => {
|
|
318
|
+
const issues = [];
|
|
319
|
+
const doc = checkClosedObject(value, "$", [...TOP_ALLOWED], [...TOP_REQUIRED], [...TOP_STRINGS], issues);
|
|
320
|
+
if (doc === undefined)
|
|
321
|
+
return { ok: false, issues };
|
|
322
|
+
const sections = [];
|
|
323
|
+
if (!Array.isArray(doc["sections"])) {
|
|
324
|
+
issues.push(issue("$.sections", "invalid_type", "expected an array"));
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
doc["sections"].forEach((section, index) => {
|
|
328
|
+
const checked = checkSectionNode(section, `$.sections[${index}]`, issues);
|
|
329
|
+
if (checked !== undefined)
|
|
330
|
+
sections.push(checked);
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
const interactions = [];
|
|
334
|
+
if (!Array.isArray(doc["interactions"])) {
|
|
335
|
+
issues.push(issue("$.interactions", "invalid_type", "expected an array"));
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
doc["interactions"].forEach((interaction, index) => {
|
|
339
|
+
const checked = checkInteraction(interaction, `$.interactions[${index}]`, issues);
|
|
340
|
+
if (checked !== undefined)
|
|
341
|
+
interactions.push(checked);
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
let provenance;
|
|
345
|
+
const rawProvenance = checkClosedObject(doc["provenance"], "$.provenance", ["source", "readAt", "comprehensionEvidence"], ["source", "readAt"], ["source", "readAt"], issues);
|
|
346
|
+
if (rawProvenance !== undefined) {
|
|
347
|
+
let evidence;
|
|
348
|
+
if (rawProvenance["comprehensionEvidence"] !== undefined) {
|
|
349
|
+
const evidenceStart = issues.length;
|
|
350
|
+
const rawEvidence = checkClosedObject(rawProvenance["comprehensionEvidence"], "$.provenance.comprehensionEvidence", ["subject", "dossierHash", "signature"], ["subject", "dossierHash"], ["subject", "dossierHash", "signature"], issues);
|
|
351
|
+
if (rawEvidence !== undefined && issues.length === evidenceStart) {
|
|
352
|
+
evidence = {
|
|
353
|
+
subject: rawEvidence["subject"],
|
|
354
|
+
dossierHash: rawEvidence["dossierHash"],
|
|
355
|
+
...(typeof rawEvidence["signature"] === "string" ? { signature: rawEvidence["signature"] } : {}),
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
provenance = {
|
|
360
|
+
source: rawProvenance["source"],
|
|
361
|
+
readAt: rawProvenance["readAt"],
|
|
362
|
+
...(evidence !== undefined ? { comprehensionEvidence: evidence } : {}),
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
const amendmentTrace = [];
|
|
366
|
+
if (!Array.isArray(doc["amendmentTrace"])) {
|
|
367
|
+
issues.push(issue("$.amendmentTrace", "invalid_type", "expected an array"));
|
|
368
|
+
}
|
|
369
|
+
else {
|
|
370
|
+
doc["amendmentTrace"].forEach((step, index) => {
|
|
371
|
+
const checked = checkAmendmentStep(step, `$.amendmentTrace[${index}]`, issues);
|
|
372
|
+
if (checked !== undefined)
|
|
373
|
+
amendmentTrace.push(checked);
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
let readability;
|
|
377
|
+
if (doc["readability"] !== undefined) {
|
|
378
|
+
readability = checkReadability(doc["readability"], "$.readability", issues);
|
|
379
|
+
}
|
|
380
|
+
// Every recorded issue is a refusal: the schema is closed.
|
|
381
|
+
if (issues.length > 0 || provenance === undefined || (doc["readability"] !== undefined && readability === undefined)) {
|
|
382
|
+
return { ok: false, issues };
|
|
383
|
+
}
|
|
384
|
+
if (typeof doc["ref"] !== "string" ||
|
|
385
|
+
typeof doc["subject"] !== "string" ||
|
|
386
|
+
typeof doc["title"] !== "string" ||
|
|
387
|
+
typeof doc["hash"] !== "string" ||
|
|
388
|
+
typeof doc["cursor"] !== "string") {
|
|
389
|
+
return { ok: false, issues };
|
|
390
|
+
}
|
|
391
|
+
return {
|
|
392
|
+
ok: true,
|
|
393
|
+
value: {
|
|
394
|
+
ref: doc["ref"],
|
|
395
|
+
subject: doc["subject"],
|
|
396
|
+
title: doc["title"],
|
|
397
|
+
hash: doc["hash"],
|
|
398
|
+
cursor: doc["cursor"],
|
|
399
|
+
sections,
|
|
400
|
+
interactions,
|
|
401
|
+
provenance,
|
|
402
|
+
amendmentTrace,
|
|
403
|
+
...(readability !== undefined ? { readability } : {}),
|
|
404
|
+
},
|
|
405
|
+
};
|
|
406
|
+
};
|
|
407
|
+
/** Semantic layer on a structurally valid dossier. Empty means valid. */
|
|
408
|
+
export const validateDecisionDossierSemantics = (doc) => {
|
|
409
|
+
const issues = [];
|
|
410
|
+
const seen = new Map();
|
|
411
|
+
const registerId = (id, path) => {
|
|
412
|
+
const first = seen.get(id);
|
|
413
|
+
if (first !== undefined) {
|
|
414
|
+
issues.push(issue(path, "duplicate_id", `node id "${id}" already used at ${first}`));
|
|
415
|
+
}
|
|
416
|
+
else {
|
|
417
|
+
seen.set(id, path);
|
|
418
|
+
}
|
|
419
|
+
};
|
|
420
|
+
doc.sections.forEach((section, index) => {
|
|
421
|
+
const path = `$.sections[${index}]`;
|
|
422
|
+
registerId(section.id, `${path}.id`);
|
|
423
|
+
if (section.kind === "optionSet") {
|
|
424
|
+
section.options.forEach((option, optionIndex) => {
|
|
425
|
+
registerId(option.id, `${path}.options[${optionIndex}].id`);
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
});
|
|
429
|
+
// Every interaction target must resolve: the dossier ref, a section
|
|
430
|
+
// id/targetRef, or a nested option id/targetRef.
|
|
431
|
+
const resolvable = new Set([doc.ref]);
|
|
432
|
+
for (const section of doc.sections) {
|
|
433
|
+
resolvable.add(section.id);
|
|
434
|
+
resolvable.add(section.targetRef);
|
|
435
|
+
if (section.kind === "optionSet") {
|
|
436
|
+
for (const option of section.options) {
|
|
437
|
+
resolvable.add(option.id);
|
|
438
|
+
resolvable.add(option.targetRef);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
doc.interactions.forEach((interaction, index) => {
|
|
443
|
+
if (!resolvable.has(interaction.targetRef)) {
|
|
444
|
+
issues.push(issue(`$.interactions[${index}].targetRef`, "unresolved_target", `interaction target "${interaction.targetRef}" resolves to no node`));
|
|
445
|
+
}
|
|
446
|
+
});
|
|
447
|
+
// The source binding selects the read backend. It is opaque (e.g. a
|
|
448
|
+
// `track:<events-path>` binding): the published schema accepts any string,
|
|
449
|
+
// so the validator does too — no stricter refusal without a versioned change.
|
|
450
|
+
// Comprehension evidence is carried verbatim: its dossier hash must still be
|
|
451
|
+
// the hash the snapshot was taken over. A mismatch is forged evidence.
|
|
452
|
+
const evidence = doc.provenance.comprehensionEvidence;
|
|
453
|
+
if (evidence !== undefined && evidence.dossierHash !== doc.hash) {
|
|
454
|
+
issues.push(issue("$.provenance.comprehensionEvidence.dossierHash", "evidence_mismatch", "comprehension evidence does not match the snapshot hash"));
|
|
455
|
+
}
|
|
456
|
+
return issues;
|
|
457
|
+
};
|
|
458
|
+
/** Full validation: structure first, then semantics. */
|
|
459
|
+
export const validateDecisionDossierDocument = (value) => {
|
|
460
|
+
const structural = validateDecisionDossierStructure(value);
|
|
461
|
+
if (!structural.ok)
|
|
462
|
+
return structural;
|
|
463
|
+
const semantic = validateDecisionDossierSemantics(structural.value);
|
|
464
|
+
if (semantic.length > 0)
|
|
465
|
+
return { ok: false, issues: semantic };
|
|
466
|
+
return structural;
|
|
467
|
+
};
|
|
468
|
+
/** Parse or throw {@link DecisionDossierValidationError}. */
|
|
469
|
+
export const assertDecisionDossierDocument = (value) => {
|
|
470
|
+
const result = validateDecisionDossierDocument(value);
|
|
471
|
+
if (!result.ok)
|
|
472
|
+
throw new DecisionDossierValidationError(result.issues);
|
|
473
|
+
return result.value;
|
|
474
|
+
};
|
|
475
|
+
/** Presentation requires the backward-compatible structure AND the readability gate. */
|
|
476
|
+
export const validateDecisionDossierForPresentation = (value) => {
|
|
477
|
+
const result = validateDecisionDossierDocument(value);
|
|
478
|
+
if (!result.ok)
|
|
479
|
+
return result;
|
|
480
|
+
const issues = validateDecisionDossierReadability(result.value);
|
|
481
|
+
return issues.length > 0 ? { ok: false, issues } : result;
|
|
482
|
+
};
|
|
483
|
+
/** Refuse before any presentation or host rendering hook runs. */
|
|
484
|
+
export const assertDecisionDossierForPresentation = (value) => {
|
|
485
|
+
const result = validateDecisionDossierForPresentation(value);
|
|
486
|
+
if (!result.ok)
|
|
487
|
+
throw new DecisionDossierValidationError(result.issues);
|
|
488
|
+
return result.value;
|
|
489
|
+
};
|
|
490
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/validation/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** Pure presentation gate. Schema validity alone does not make a dossier readable.
|
|
2
|
+
* Semantic intent, quotation authenticity and proportional stakes still need review.
|
|
3
|
+
*/
|
|
4
|
+
import type { DecisionDossierDocument } from "../model.js";
|
|
5
|
+
import type { ValidationIssue } from "./index.js";
|
|
6
|
+
export declare const READABILITY_BUDGETS: {
|
|
7
|
+
readonly low: 2;
|
|
8
|
+
readonly medium: 8;
|
|
9
|
+
readonly high: 30;
|
|
10
|
+
};
|
|
11
|
+
export declare const READABILITY_LIMITS: {
|
|
12
|
+
readonly minOwnerRequestQuoteLength: 8;
|
|
13
|
+
readonly minStakesLength: 20;
|
|
14
|
+
readonly minQuestionContextLength: 20;
|
|
15
|
+
readonly minOptionsPerQuestion: 2;
|
|
16
|
+
readonly maxOptionsPerQuestion: 4;
|
|
17
|
+
readonly maxQuestionReadingMinutes: 2;
|
|
18
|
+
readonly maxDossierBudgetMinutes: 30;
|
|
19
|
+
readonly wordsPerMinute: 180;
|
|
20
|
+
readonly maxHeadingLength: 100;
|
|
21
|
+
readonly maxDecisionLineLength: 300;
|
|
22
|
+
readonly maxOptionLabelLength: 100;
|
|
23
|
+
readonly maxConsequenceLength: 160;
|
|
24
|
+
readonly maxOptionBodyLength: 300;
|
|
25
|
+
};
|
|
26
|
+
/** Check a structurally valid document; use ForPresentation for untrusted input. */
|
|
27
|
+
export declare const validateDecisionDossierReadability: (doc: DecisionDossierDocument) => ValidationIssue[];
|
|
28
|
+
//# sourceMappingURL=readability.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readability.d.ts","sourceRoot":"","sources":["../../src/validation/readability.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAiB,uBAAuB,EAAc,MAAM,aAAa,CAAC;AACtF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,eAAO,MAAM,mBAAmB;;;;CAA2C,CAAC;AAC5E,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;CAcrB,CAAC;AAeX,oFAAoF;AACpF,eAAO,MAAM,kCAAkC,GAAI,KAAK,uBAAuB,KAAG,eAAe,EAoMhG,CAAC"}
|