structured-context 0.12.0 → 0.13.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.
Files changed (94) hide show
  1. package/README.md +29 -216
  2. package/dist/api.d.ts +17 -17
  3. package/dist/api.js +12 -12
  4. package/dist/commands/docs.js +1 -0
  5. package/dist/commands/providers.d.ts +4 -0
  6. package/dist/commands/providers.js +52 -0
  7. package/dist/commands/schemas.js +21 -2
  8. package/dist/commands/validate-file.d.ts +3 -0
  9. package/dist/commands/validate-file.js +17 -2
  10. package/dist/commands/validate.d.ts +4 -0
  11. package/dist/commands/validate.js +42 -3
  12. package/dist/config.d.ts +7 -0
  13. package/dist/config.js +26 -3
  14. package/dist/index.d.ts +1 -1
  15. package/dist/index.js +59 -18
  16. package/dist/judge/context.d.ts +20 -0
  17. package/dist/judge/context.js +105 -0
  18. package/dist/judge/factory.d.ts +44 -0
  19. package/dist/judge/factory.js +148 -0
  20. package/dist/judge/index.d.ts +13 -0
  21. package/dist/judge/index.js +8 -0
  22. package/dist/judge/judge-node.d.ts +27 -0
  23. package/dist/judge/judge-node.js +122 -0
  24. package/dist/judge/prompt.d.ts +10 -0
  25. package/dist/judge/prompt.js +92 -0
  26. package/dist/judge/provider/anthropic.d.ts +17 -0
  27. package/dist/judge/provider/anthropic.js +43 -0
  28. package/dist/judge/provider/fake.d.ts +26 -0
  29. package/dist/judge/provider/fake.js +56 -0
  30. package/dist/judge/provider/jev.d.ts +37 -0
  31. package/dist/judge/provider/jev.js +169 -0
  32. package/dist/judge/provider/openai-decisions.d.ts +21 -0
  33. package/dist/judge/provider/openai-decisions.js +84 -0
  34. package/dist/judge/provider/openai.d.ts +20 -0
  35. package/dist/judge/provider/openai.js +53 -0
  36. package/dist/judge/provider/per-rule.d.ts +10 -0
  37. package/dist/judge/provider/per-rule.js +18 -0
  38. package/dist/judge/trim.d.ts +27 -0
  39. package/dist/judge/trim.js +62 -0
  40. package/dist/judge/types.d.ts +92 -0
  41. package/dist/judge/types.js +9 -0
  42. package/dist/judge/verdicts.d.ts +24 -0
  43. package/dist/judge/verdicts.js +82 -0
  44. package/dist/load-space-graph.d.ts +3 -3
  45. package/dist/load-space-graph.js +4 -4
  46. package/dist/plugins/loader.js +1 -1
  47. package/dist/plugins/markdown/parse-embedded.d.ts +2 -0
  48. package/dist/plugins/markdown/parse-embedded.js +161 -24
  49. package/dist/plugins/markdown/read-space.js +4 -9
  50. package/dist/plugins/markdown/render-directory.js +5 -5
  51. package/dist/plugins/markdown/template-sync.js +3 -4
  52. package/dist/plugins/markdown/util.d.ts +26 -5
  53. package/dist/plugins/markdown/util.js +56 -15
  54. package/dist/render/render.d.ts +1 -1
  55. package/dist/render/render.js +1 -1
  56. package/dist/schema/evaluate-rule.d.ts +33 -2
  57. package/dist/schema/evaluate-rule.js +58 -4
  58. package/dist/schema/gating.d.ts +69 -0
  59. package/dist/schema/gating.js +253 -0
  60. package/dist/schema/metadata-contract.d.ts +625 -12
  61. package/dist/schema/metadata-contract.js +110 -4
  62. package/dist/schema/rule-filter.d.ts +12 -0
  63. package/dist/schema/rule-filter.js +46 -0
  64. package/dist/schema/rule-severity.d.ts +13 -0
  65. package/dist/schema/rule-severity.js +33 -0
  66. package/dist/schema/schema.js +31 -1
  67. package/dist/schema/validate-rules.d.ts +17 -8
  68. package/dist/schema/validate-rules.js +91 -48
  69. package/dist/schemas/_knowledge_wiki.json +4 -4
  70. package/dist/schemas/_okf.json +172 -0
  71. package/dist/schemas/_ost_strict.json +15 -6
  72. package/dist/schemas/_sctx_base.json +1 -1
  73. package/dist/schemas/generated/0.13.0/_structured_context_schema_meta.json +400 -0
  74. package/dist/schemas/generated/latest/_structured_context_schema_meta.json +177 -6
  75. package/dist/schemas/okf.json +8 -0
  76. package/dist/space-context.d.ts +2 -2
  77. package/dist/space-context.js +3 -3
  78. package/dist/space-graph.d.ts +1 -1
  79. package/dist/testing.d.ts +1 -1
  80. package/dist/types.d.ts +11 -4
  81. package/dist/validate.d.ts +59 -9
  82. package/dist/validate.js +225 -120
  83. package/docs/concepts.md +52 -6
  84. package/docs/config.md +70 -1
  85. package/docs/rules.md +140 -49
  86. package/docs/schemas.md +43 -18
  87. package/package.json +6 -5
  88. package/schemas/_knowledge_wiki.json +4 -4
  89. package/schemas/_okf.json +172 -0
  90. package/schemas/_ost_strict.json +15 -6
  91. package/schemas/_sctx_base.json +1 -1
  92. package/schemas/generated/0.13.0/_structured_context_schema_meta.json +400 -0
  93. package/schemas/generated/latest/_structured_context_schema_meta.json +177 -6
  94. package/schemas/okf.json +8 -0
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://raw.githubusercontent.com/mindsocket/structured-context/main/schemas/generated/0.12.0/_structured_context_schema_meta.json",
3
+ "$id": "https://raw.githubusercontent.com/mindsocket/structured-context/main/schemas/generated/0.13.0/_structured_context_schema_meta.json",
4
4
  "title": "structured-context schema dialect",
5
5
  "description": "Extends JSON Schema 2020-12 with top-level $metadata for imports, hierarchy, relationships, aliases and rules.",
6
6
  "type": "object",
@@ -203,23 +203,194 @@
203
203
  "type": "string",
204
204
  "minLength": 1
205
205
  },
206
- "check": {
206
+ "expression": {
207
207
  "type": "string",
208
208
  "minLength": 1
209
209
  },
210
+ "when": {
211
+ "type": "string",
212
+ "minLength": 1
213
+ },
214
+ "semantic": {
215
+ "oneOf": [
216
+ {
217
+ "const": true
218
+ },
219
+ {
220
+ "type": "object",
221
+ "properties": {
222
+ "rubric": {
223
+ "type": "string",
224
+ "minLength": 1
225
+ },
226
+ "verdicts": {
227
+ "type": "object",
228
+ "additionalProperties": {
229
+ "oneOf": [
230
+ {
231
+ "type": "string",
232
+ "minLength": 1
233
+ },
234
+ {
235
+ "type": "object",
236
+ "properties": {
237
+ "description": {
238
+ "type": "string",
239
+ "minLength": 1
240
+ },
241
+ "guidance": {
242
+ "type": "string",
243
+ "minLength": 1
244
+ }
245
+ },
246
+ "required": ["description"],
247
+ "additionalProperties": false
248
+ }
249
+ ]
250
+ },
251
+ "minProperties": 2
252
+ },
253
+ "severity": {
254
+ "type": "object",
255
+ "additionalProperties": {
256
+ "enum": ["error", "warning", "info", "ignore"]
257
+ },
258
+ "minProperties": 1
259
+ },
260
+ "scope": {
261
+ "type": "array",
262
+ "items": {
263
+ "enum": ["parent", "siblings", "children", "ancestors", "descendants", "branch"]
264
+ },
265
+ "uniqueItems": true
266
+ },
267
+ "includeContent": {
268
+ "enum": ["nodeOnly", "fullScope", true]
269
+ }
270
+ },
271
+ "additionalProperties": false
272
+ }
273
+ ]
274
+ },
210
275
  "type": {
211
276
  "type": "string",
212
277
  "minLength": 1
213
278
  },
214
- "scope": {
215
- "enum": ["global"]
279
+ "global": {
280
+ "type": "boolean"
216
281
  },
217
282
  "override": {
218
283
  "type": "boolean"
284
+ },
285
+ "gatesDescendants": {
286
+ "type": "boolean"
219
287
  }
220
288
  },
221
- "required": ["id", "category", "description", "check"],
222
- "additionalProperties": false
289
+ "required": ["id", "category", "description"],
290
+ "additionalProperties": false,
291
+ "allOf": [
292
+ {
293
+ "anyOf": [
294
+ {
295
+ "required": ["expression"]
296
+ },
297
+ {
298
+ "required": ["semantic"]
299
+ }
300
+ ]
301
+ },
302
+ {
303
+ "if": {
304
+ "required": ["global"],
305
+ "properties": {
306
+ "global": {
307
+ "const": true
308
+ }
309
+ }
310
+ },
311
+ "then": {
312
+ "not": {
313
+ "anyOf": [
314
+ {
315
+ "required": ["when"]
316
+ },
317
+ {
318
+ "required": ["type"]
319
+ },
320
+ {
321
+ "required": ["semantic"]
322
+ }
323
+ ]
324
+ }
325
+ }
326
+ },
327
+ {
328
+ "if": {
329
+ "required": ["semantic"],
330
+ "properties": {
331
+ "semantic": {
332
+ "type": "object",
333
+ "required": ["verdicts"]
334
+ }
335
+ }
336
+ },
337
+ "then": {
338
+ "properties": {
339
+ "semantic": {
340
+ "type": "object",
341
+ "required": ["severity"]
342
+ }
343
+ }
344
+ }
345
+ },
346
+ {
347
+ "if": {
348
+ "required": ["semantic"],
349
+ "properties": {
350
+ "semantic": {
351
+ "type": "object",
352
+ "not": {
353
+ "required": ["verdicts"]
354
+ }
355
+ }
356
+ }
357
+ },
358
+ "then": {
359
+ "properties": {
360
+ "semantic": {
361
+ "type": "object",
362
+ "properties": {
363
+ "severity": {
364
+ "type": "object",
365
+ "not": {
366
+ "required": ["fail"]
367
+ }
368
+ }
369
+ }
370
+ }
371
+ }
372
+ }
373
+ },
374
+ {
375
+ "if": {
376
+ "required": ["semantic"],
377
+ "properties": {
378
+ "semantic": {
379
+ "type": "object",
380
+ "required": ["verdicts"]
381
+ }
382
+ },
383
+ "not": {
384
+ "required": ["expression"]
385
+ }
386
+ },
387
+ "then": {
388
+ "not": {
389
+ "required": ["severity"]
390
+ }
391
+ }
392
+ }
393
+ ]
223
394
  }
224
395
  }
225
396
  },
@@ -0,0 +1,8 @@
1
+ {
2
+ "$schema": "https://raw.githubusercontent.com/mindsocket/structured-context/main/schemas/generated/latest/_structured_context_schema_meta.json",
3
+ "$id": "sctx://core/okf",
4
+ "title": "Open Knowledge Format",
5
+ "description": "Validates the frontmatter of Open Knowledge Format (OKF v0.2) concept documents in a bundle. Any `type` is accepted and unknown fields are tolerated; `Attested Computation` concepts additionally carry the computation contract.\n\nSpecification: https://github.com/GoogleCloudPlatform/open-knowledge-format",
6
+ "$metadata": { "imports": ["sctx://core/_okf"] },
7
+ "allOf": [{ "$ref": "sctx://core/_okf" }, { "$ref": "sctx://core/_okf#/$defs/concept" }]
8
+ }
@@ -1,5 +1,5 @@
1
- import { type Config } from './config';
2
- import type { SpaceContext } from './types';
1
+ import { type Config } from './config.js';
2
+ import type { SpaceContext } from './types.js';
3
3
  /** Thrown by createSpaceContext when no space matches the given name. */
4
4
  export declare class SpaceNotFoundError extends Error {
5
5
  readonly spaceName: string;
@@ -1,6 +1,6 @@
1
- import { resolveSchema } from './config';
2
- import { resolveSpacePluginSchemas } from './plugins/util';
3
- import { loadSchema } from './schema/schema';
1
+ import { resolveSchema } from './config.js';
2
+ import { resolveSpacePluginSchemas } from './plugins/util.js';
3
+ import { loadSchema } from './schema/schema.js';
4
4
  /** Thrown by createSpaceContext when no space matches the given name. */
5
5
  export class SpaceNotFoundError extends Error {
6
6
  spaceName;
@@ -1,4 +1,4 @@
1
- import type { Hierarchy, SpaceNode } from './types';
1
+ import type { Hierarchy, SpaceNode } from './types.js';
2
2
  /**
3
3
  * A navigable graph over a set of SpaceNodes.
4
4
  *
package/dist/testing.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { BaseNode, Hierarchy, HierarchyLevel, Relationship, ResolvedParentRef, SpaceNode } from './types';
1
+ import type { BaseNode, Hierarchy, HierarchyLevel, Relationship, ResolvedParentRef, SpaceNode } from './types.js';
2
2
  /**
3
3
  * Creates a ResolvedParentRef with sensible defaults for use in tests.
4
4
  * Override any field to represent specific edge contexts.
package/dist/types.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { AnySchemaObject, SchemaObject, ValidateFunction } from 'ajv';
2
- import type { Config, SpaceConfig } from './config';
3
- import type { MetadataContractHierarchyLevel, MetadataContractRelationship, Rule, SharedEdgeFields } from './schema/metadata-contract';
2
+ import type { Config, SpaceConfig } from './config.js';
3
+ import type { MetadataContractHierarchyLevel, MetadataContractRelationship, Rule, SharedEdgeFields } from './schema/metadata-contract.js';
4
4
  /**
5
5
  * Minimal normalized edge for graph resolution.
6
6
  * Derives routing fields from SharedEdgeFields to stay in sync with the schema.
@@ -119,7 +119,7 @@ export type BaseNode = {
119
119
  linkTargets: string[];
120
120
  /** Raw type string from content, as written by the user. */
121
121
  type: string;
122
- /** Body content of the node, if any. First-class accessor mirroring schemaData.content. */
122
+ /** Markdown source of the node's body, if any. First-class accessor mirroring schemaData.content. */
123
123
  content?: string;
124
124
  /**
125
125
  * Links extracted from content body and non-edge string fields at parse time.
@@ -171,7 +171,8 @@ export type RuleCategory = 'validation' | 'coherence' | 'workflow' | 'best-pract
171
171
  * A rule's severity defaults from its category and may be overridden per rule.
172
172
  */
173
173
  export type RuleSeverity = 'error' | 'warning' | 'info';
174
- export type { Rule } from './schema/metadata-contract';
174
+ export type { CoverageGate, GatingSeed } from './schema/gating.js';
175
+ export type { Rule } from './schema/metadata-contract.js';
175
176
  export type RuleViolation = {
176
177
  /** Node label, or empty string for global-scope rules. */
177
178
  file: string;
@@ -179,6 +180,12 @@ export type RuleViolation = {
179
180
  category: RuleCategory;
180
181
  severity: RuleSeverity;
181
182
  description: string;
183
+ /** Cited evidence or reasoning from evaluation (for semantic judge rules). */
184
+ evidence?: string;
185
+ /** The verdict that failed the rule (semantic rules). */
186
+ verdict?: string;
187
+ /** User-facing guidance declared for that verdict (semantic rules). */
188
+ guidance?: string;
182
189
  };
183
190
  export type GraphViolation = {
184
191
  file: string;
@@ -1,7 +1,9 @@
1
1
  import type { ErrorObject } from 'ajv';
2
- import type { Config } from './config';
3
- import { extractEntityInfo } from './schema/schema';
4
- import type { GraphViolation, ParseIssue, ReadSpaceResult, RuleViolation, SchemaWithMetadata, SpaceContext, SpaceNode, ValidateFileOutput } from './types';
2
+ import type { Config, SpaceConfig } from './config.js';
3
+ import type { SemanticJudgeProvider } from './judge/types.js';
4
+ import { type RuleFilter } from './schema/rule-filter.js';
5
+ import { extractEntityInfo } from './schema/schema.js';
6
+ import type { CoverageGate, FileNotInSpaceResult, FileValidationResult, GraphViolation, ParseIssue, ReadSpaceResult, RuleViolation, SchemaWithMetadata, SpaceContext, SpaceNode, ValidateFileOutput } from './types.js';
5
7
  export interface FormattedError {
6
8
  message: string;
7
9
  dedupeKey: string;
@@ -35,19 +37,69 @@ export interface ValidationResult {
35
37
  file: string;
36
38
  target: string;
37
39
  }>;
40
+ /**
41
+ * Cascade gates: nodes whose schema/hierarchy failure or blocking rule violation
42
+ * suppressed rule evaluation for themselves and/or their hierarchy subtree.
43
+ * See docs/rules.md for gating semantics.
44
+ */
45
+ coverageGates: CoverageGate[];
46
+ /** Semantic rule input that had content trimmed to fit the per-node input cap: the node count and the rule ids. */
47
+ contextTrimmed: {
48
+ nodeCount: number;
49
+ ruleIds: string[];
50
+ };
51
+ /** Nodes excluded from validation entirely by a `depth` limit (breadth-first from hierarchy roots). */
52
+ skippedByDepth: Array<{
53
+ file: string;
54
+ title: string;
55
+ }>;
56
+ /** The depth limit applied, if any (undefined means the full space was validated). */
57
+ depthLimit?: number;
38
58
  }
39
59
  /**
40
60
  * Format AJV errors for better readability.
41
61
  * Groups related errors and extracts helpful context like allowed values.
42
62
  */
43
63
  export declare function formatErrors(errors: ErrorObject[], schema: SchemaWithMetadata, schemaRefRegistry: Parameters<typeof extractEntityInfo>[1], nodeData: Record<string, unknown>): FormattedError[];
64
+ export interface ValidateSpaceOptions {
65
+ readResult?: ReadSpaceResult;
66
+ /** Limit validation to hierarchy nodes within N breadth-first levels from the top. */
67
+ depth?: number;
68
+ /** Evaluate rules on gated nodes anyway (gates are still reported). */
69
+ includeGated?: boolean;
70
+ /** Evaluate only rules matching this filter (see `parseRuleFilter`). */
71
+ ruleFilter?: RuleFilter;
72
+ /** Evaluates `semantic` rules. Without one, a rule runs only its `expression`, and a semantic-only rule is skipped. */
73
+ judge?: SemanticJudgeProvider;
74
+ }
75
+ /** One-line text for a rule violation: rule, description, and any evidence and verdict guidance. */
76
+ export declare function ruleViolationMessage(v: RuleViolation): string;
44
77
  /**
45
78
  * Run full validation on a space and return a structured result.
46
79
  * Does not output to console or call process.exit.
47
80
  */
48
- export declare function validateSpace(context: SpaceContext, options?: {
49
- readResult?: ReadSpaceResult;
50
- }): Promise<ValidationResult>;
81
+ export declare function validateSpace(context: SpaceContext, options?: ValidateSpaceOptions): Promise<ValidationResult>;
82
+ /** Find which space a file belongs to by checking directory containment. */
83
+ export declare function resolveFileSpace(filePath: string, config: Config): {
84
+ space: SpaceConfig;
85
+ label: string;
86
+ } | null;
87
+ export interface ValidateFileOptions {
88
+ configDir?: string;
89
+ /** Evaluate rules on gated nodes anyway (gates are still reported). */
90
+ includeGated?: boolean;
91
+ /** Evaluate only rules matching this filter (see `parseRuleFilter`). */
92
+ ruleFilter?: RuleFilter;
93
+ /** Evaluates `semantic` rules. Without one, a rule runs only its `expression`, and a semantic-only rule is skipped. */
94
+ judge?: SemanticJudgeProvider;
95
+ }
96
+ /** The result for a file that belongs to no configured space. */
97
+ export declare function fileNotInSpace(filePath: string): FileNotInSpaceResult;
98
+ /**
99
+ * Validate a file in an already-resolved space. Checks the whole space (required for graph
100
+ * correctness), judging only the file, then selects the file's issues from the result.
101
+ */
102
+ export declare function validateResolvedFile(filePath: string, label: string, context: SpaceContext, options?: Omit<ValidateFileOptions, 'configDir'>): Promise<FileValidationResult>;
51
103
  /**
52
104
  * Validate a single file within its space.
53
105
  *
@@ -57,6 +109,4 @@ export declare function validateSpace(context: SpaceContext, options?: {
57
109
  * Returns a result object — does not output to console or call process.exit.
58
110
  * If the file is not in any configured space, returns a result with `inSpace: false`.
59
111
  */
60
- export declare function validateFile(filePath: string, config: Config, options?: {
61
- configDir?: string;
62
- }): Promise<ValidateFileOutput>;
112
+ export declare function validateFile(filePath: string, config: Config, options?: ValidateFileOptions): Promise<ValidateFileOutput>;