kibi-cli 0.16.1 → 0.17.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 (117) hide show
  1. package/dist/commands/check.d.ts.map +1 -1
  2. package/dist/commands/check.js +1 -1
  3. package/dist/commands/sync/manifest.d.ts +12 -1
  4. package/dist/commands/sync/manifest.d.ts.map +1 -1
  5. package/dist/commands/sync/manifest.js +22 -5
  6. package/dist/commands/sync/persistence.d.ts.map +1 -1
  7. package/dist/commands/sync/persistence.js +18 -1
  8. package/dist/extractors/markdown.d.ts +9 -1
  9. package/dist/extractors/markdown.d.ts.map +1 -1
  10. package/dist/extractors/markdown.js +12 -0
  11. package/dist/logic/ir.d.ts +112 -0
  12. package/dist/logic/ir.d.ts.map +1 -0
  13. package/dist/logic/ir.js +729 -0
  14. package/dist/operations/modeling/logic-modeling.d.ts +22 -0
  15. package/dist/operations/modeling/logic-modeling.d.ts.map +1 -0
  16. package/dist/operations/modeling/logic-modeling.js +111 -0
  17. package/dist/operations/modeling/model-requirement.d.ts.map +1 -1
  18. package/dist/operations/modeling/model-requirement.js +56 -0
  19. package/dist/operations/modeling/predicate-applyplan.d.ts.map +1 -1
  20. package/dist/operations/modeling/predicate-applyplan.js +15 -2
  21. package/dist/operations/modeling/predicate-inference.d.ts.map +1 -1
  22. package/dist/operations/modeling/predicate-inference.js +17 -2
  23. package/dist/operations/modeling/predicate-loader.d.ts.map +1 -1
  24. package/dist/operations/modeling/predicate-loader.js +6 -0
  25. package/dist/operations/modeling/predicate-ranker.d.ts.map +1 -1
  26. package/dist/operations/modeling/predicate-ranker.js +40 -2
  27. package/dist/operations/modeling/predicate-types.d.ts +3 -0
  28. package/dist/operations/modeling/predicate-types.d.ts.map +1 -1
  29. package/dist/operations/modeling/requirement-types.d.ts +12 -0
  30. package/dist/operations/modeling/requirement-types.d.ts.map +1 -1
  31. package/dist/operations/mutation/relationships.d.ts.map +1 -1
  32. package/dist/operations/mutation/relationships.js +8 -0
  33. package/dist/operations/mutation/serialization.d.ts.map +1 -1
  34. package/dist/operations/mutation/serialization.js +3 -0
  35. package/dist/operations/mutation/strict-fact.d.ts.map +1 -1
  36. package/dist/operations/mutation/strict-fact.js +68 -3
  37. package/dist/operations/semantic-advisor/analysis-receipt.d.ts +2 -2
  38. package/dist/operations/semantic-advisor/analysis-receipt.d.ts.map +1 -1
  39. package/dist/operations/semantic-advisor/analysis-receipt.js +23 -15
  40. package/dist/operations/semantic-advisor/analyze-prose.d.ts +1 -1
  41. package/dist/operations/semantic-advisor/analyze-prose.d.ts.map +1 -1
  42. package/dist/operations/semantic-advisor/analyze-prose.js +435 -13
  43. package/dist/operations/semantic-advisor/observation-plan.d.ts.map +1 -1
  44. package/dist/operations/semantic-advisor/observation-plan.js +15 -3
  45. package/dist/operations/semantic-advisor/shared.d.ts +1 -0
  46. package/dist/operations/semantic-advisor/shared.d.ts.map +1 -1
  47. package/dist/operations/semantic-advisor/shared.js +1 -1
  48. package/dist/operations/semantic-advisor/types.d.ts +61 -1
  49. package/dist/operations/semantic-advisor/types.d.ts.map +1 -1
  50. package/dist/prolog/codec.d.ts.map +1 -1
  51. package/dist/prolog/codec.js +11 -1
  52. package/dist/prolog.d.ts.map +1 -1
  53. package/dist/prolog.js +7 -2
  54. package/dist/public/operations/catalog.d.ts +85 -6
  55. package/dist/public/operations/catalog.d.ts.map +1 -1
  56. package/dist/public/operations/index.d.ts +1 -0
  57. package/dist/public/operations/index.d.ts.map +1 -1
  58. package/dist/public/operations/index.js +1 -0
  59. package/dist/public/operations/specs/check.d.ts +2 -2
  60. package/dist/public/operations/specs/check.d.ts.map +1 -1
  61. package/dist/public/operations/specs/check.js +4 -1
  62. package/dist/public/operations/specs/modeling.d.ts +16 -0
  63. package/dist/public/operations/specs/modeling.d.ts.map +1 -1
  64. package/dist/public/operations/specs/modeling.js +16 -0
  65. package/dist/public/operations/specs/mutation-schemas.d.ts +37 -2
  66. package/dist/public/operations/specs/mutation-schemas.d.ts.map +1 -1
  67. package/dist/public/operations/specs/mutation-schemas.js +27 -0
  68. package/dist/public/operations/specs/semantic.d.ts +30 -2
  69. package/dist/public/operations/specs/semantic.d.ts.map +1 -1
  70. package/dist/public/operations/specs/semantic.js +34 -2
  71. package/dist/public/operations/specs/upsert.d.ts +37 -2
  72. package/dist/public/operations/specs/upsert.d.ts.map +1 -1
  73. package/dist/public/schemas/entity.d.ts.map +1 -1
  74. package/dist/public/schemas/entity.js +290 -0
  75. package/dist/public/schemas/relationship.d.ts.map +1 -1
  76. package/dist/public/schemas/relationship.js +1 -0
  77. package/dist/public/skills/kibi-usage/SKILL.md +35 -9
  78. package/dist/public/skills/kibi-usage/resources/fact-lanes.md +11 -1
  79. package/dist/public/skills/kibi-usage/resources/logic-ir.md +43 -0
  80. package/dist/public/skills/kibi-usage/resources/operation-access.md +19 -19
  81. package/dist/public/skills/kibi-usage/resources/ui-requirements.md +96 -0
  82. package/dist/public/skills/kibi-usage/resources/workflows.md +21 -6
  83. package/dist/public/symbol-granularity.d.ts +9 -0
  84. package/dist/public/symbol-granularity.d.ts.map +1 -1
  85. package/dist/public/symbol-granularity.js +16 -0
  86. package/dist/schemas/entity.schema.json +306 -3
  87. package/dist/traceability/staged-diagnostics.d.ts +1 -1
  88. package/dist/traceability/staged-diagnostics.d.ts.map +1 -1
  89. package/dist/traceability/staged-diagnostics.js +17 -10
  90. package/dist/traceability/staged-impact-contract.js +1 -1
  91. package/dist/traceability/staged-symbols-manifest.d.ts.map +1 -1
  92. package/dist/traceability/staged-symbols-manifest.js +28 -10
  93. package/dist/traceability/temp-kb.d.ts.map +1 -1
  94. package/dist/traceability/temp-kb.js +13 -0
  95. package/dist/types/relationships.d.ts +1 -1
  96. package/dist/types/relationships.d.ts.map +1 -1
  97. package/dist/utils/rule-registry.d.ts.map +1 -1
  98. package/dist/utils/rule-registry.js +18 -0
  99. package/dist/utils/schema-version.d.ts +1 -1
  100. package/dist/utils/schema-version.js +1 -1
  101. package/package.json +6 -2
  102. package/src/public/operations/index.ts +1 -0
  103. package/src/public/operations/specs/check.ts +4 -1
  104. package/src/public/operations/specs/modeling.ts +20 -0
  105. package/src/public/operations/specs/mutation-schemas.ts +30 -0
  106. package/src/public/operations/specs/semantic.ts +41 -2
  107. package/src/public/schemas/entity.ts +297 -1
  108. package/src/public/schemas/relationship.ts +1 -0
  109. package/src/public/skills/kibi-usage/SKILL.md +35 -9
  110. package/src/public/skills/kibi-usage/resources/fact-lanes.md +11 -1
  111. package/src/public/skills/kibi-usage/resources/logic-ir.md +43 -0
  112. package/src/public/skills/kibi-usage/resources/operation-access.md +19 -19
  113. package/src/public/skills/kibi-usage/resources/ui-requirements.md +96 -0
  114. package/src/public/skills/kibi-usage/resources/workflows.md +21 -6
  115. package/src/public/symbol-granularity.ts +25 -0
  116. package/src/schemas/entity.schema.json +306 -3
  117. package/src/schemas/relationship.schema.json +1 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kibi-cli",
3
- "version": "0.16.1",
3
+ "version": "0.17.0",
4
4
  "type": "module",
5
5
  "description": "Kibi CLI for knowledge base management",
6
6
  "engines": {
@@ -107,6 +107,10 @@
107
107
  "default": "./dist/public/skills.js"
108
108
  },
109
109
  "./operations": "./dist/public/operations/index.js",
110
+ "./logic/ir": {
111
+ "types": "./dist/logic/ir.d.ts",
112
+ "default": "./dist/logic/ir.js"
113
+ },
110
114
  "./operations/mutation/relationships": {
111
115
  "types": "./dist/operations/mutation/relationships.d.ts",
112
116
  "default": "./dist/operations/mutation/relationships.js"
@@ -157,7 +161,7 @@
157
161
  "fast-glob": "^3.2.12",
158
162
  "gray-matter": "^4.0.3",
159
163
  "js-yaml": "^4.1.0",
160
- "kibi-core": "^0.7.1",
164
+ "kibi-core": "^0.8.0",
161
165
  "ts-morph": "^23.0.0",
162
166
  "ignore": "^5.3.0"
163
167
  },
@@ -17,3 +17,4 @@ export * from "./types.js";
17
17
  export * from "../../operations/autopilot/generate.js";
18
18
  export * from "../../operations/autopilot/presentation.js";
19
19
  export type * from "../../operations/autopilot/types.js";
20
+ export * from "../../logic/ir.js";
@@ -26,11 +26,14 @@ export const checkSpec = {
26
26
  "strict-req-fact-pairing",
27
27
  "predicate-verifiability",
28
28
  "logic-coverage",
29
+ "rule-safety",
30
+ "rule-verifiability",
31
+ "semantic-completeness",
29
32
  "query-plan-safety",
30
33
  ],
31
34
  },
32
35
  description:
33
- "Optional rule subset. Allowed: must-priority-coverage, symbol-coverage, symbol-traceability, no-dangling-refs, no-cycles, required-fields, deprecated-adr-no-successor, domain-contradictions, strict-fact-shape, strict-req-fact-pairing, predicate-verifiability, logic-coverage, query-plan-safety. If omitted, server runs all rules plus the full-KB qualityDiagnostics audit scan; if supplied, server preserves scoped validation and skips the full-KB advisory scan.",
36
+ "Optional rule subset. Allowed: must-priority-coverage, symbol-coverage, symbol-traceability, no-dangling-refs, no-cycles, required-fields, deprecated-adr-no-successor, domain-contradictions, strict-fact-shape, strict-req-fact-pairing, predicate-verifiability, logic-coverage, rule-safety, rule-verifiability, semantic-completeness, query-plan-safety. If omitted, server runs all rules plus the full-KB qualityDiagnostics audit scan; if supplied, server preserves scoped validation and skips the full-KB advisory scan.",
34
37
  },
35
38
  sourceFiles: {
36
39
  type: "array",
@@ -75,6 +75,26 @@ export const modelRequirementSpec = {
75
75
  description:
76
76
  "Existing requirement logic_claims values. The returned requirement update merges the new atomic claim key into this manifest instead of replacing prior claims.",
77
77
  },
78
+ requirementId: {
79
+ type: "string",
80
+ description:
81
+ "Optional existing requirement ID to receive the requires_rule relationship.",
82
+ },
83
+ claimKey: {
84
+ type: "string",
85
+ description:
86
+ "Optional advisor-issued claim key for the exact proposition represented by logic.",
87
+ },
88
+ claimText: {
89
+ type: "string",
90
+ description:
91
+ "Optional exact proposition text represented by logic; defaults to text.",
92
+ },
93
+ logic: {
94
+ type: "object",
95
+ description:
96
+ "Optional typed kibi.logic.v1 IR. Kibi validates and canonicalizes it into a rule fact; raw Prolog is rejected.",
97
+ },
78
98
  },
79
99
  },
80
100
  requiresProlog: true,
@@ -125,6 +125,8 @@ export const ENTITY_PROPERTIES_SCHEMA = {
125
125
  "meta",
126
126
  "predicate_schema",
127
127
  "predicate",
128
+ "rule_schema",
129
+ "rule",
128
130
  ],
129
131
  description:
130
132
  "Optional fact lane kind for fact entities. Strict lane uses 'subject' and 'property_value'; context lane uses 'observation' or 'meta'; ontology lane uses 'predicate_schema' or 'predicate'. Use kb_model_requirement or kb_suggest_predicates when starting from prose.",
@@ -246,6 +248,33 @@ export const ENTITY_PROPERTIES_SCHEMA = {
246
248
  items: { type: "string" },
247
249
  description: "Optional ground-term examples for a predicate schema.",
248
250
  },
251
+ semantic_inventory: {
252
+ type: "array",
253
+ description:
254
+ "Requirement proposition ledger returned by kb_semantic_advisor; preserve entries while modeling each assertive span.",
255
+ items: { type: "object" },
256
+ },
257
+ rule_ir: {
258
+ type: "object",
259
+ description:
260
+ "Schema-validated kibi.logic.v1 rule IR. It is persisted as data and never executed as caller-supplied Prolog.",
261
+ },
262
+ rule_hash: {
263
+ type: "string",
264
+ description: "Deterministic hash of canonical rule_ir.",
265
+ },
266
+ rule_schema_id: {
267
+ type: "string",
268
+ description: "Rule schema fact ID used to validate this rule.",
269
+ },
270
+ rule_name: { type: "string", description: "Stable rule schema name." },
271
+ semantic_key: {
272
+ type: "string",
273
+ description:
274
+ "Canonical semantic identity of the normalized logical model.",
275
+ },
276
+ claim_span_start: { type: "integer", minimum: 0 },
277
+ claim_span_end: { type: "integer", minimum: 0 },
249
278
  },
250
279
  allOf: [CLAIM_PROVENANCE_CONDITIONAL],
251
280
  required: ["title", "status"],
@@ -273,6 +302,7 @@ export const RELATIONSHIPS_SCHEMA = {
273
302
  "constrains",
274
303
  "requires_property",
275
304
  "requires_predicate",
305
+ "requires_rule",
276
306
  "guards",
277
307
  "publishes",
278
308
  "consumes",
@@ -43,6 +43,9 @@ export async function executeSemanticAdvisor(
43
43
  },
44
44
  },
45
45
  ...(args.clauses !== undefined ? { clauses: args.clauses } : {}),
46
+ ...(args.interpretations !== undefined
47
+ ? { interpretations: args.interpretations }
48
+ : {}),
46
49
  });
47
50
  return {
48
51
  content: [
@@ -69,6 +72,15 @@ async function executeSemanticAdvisorInput(
69
72
  (value): value is string => typeof value === "string",
70
73
  )
71
74
  : undefined;
75
+ const interpretations = Array.isArray(input.interpretations)
76
+ ? input.interpretations.filter(
77
+ (
78
+ value,
79
+ ): value is NonNullable<
80
+ SemanticAdvisorArgs["interpretations"]
81
+ >[number] => typeof value === "object" && value !== null,
82
+ )
83
+ : undefined;
72
84
  return executeSemanticAdvisor(
73
85
  {
74
86
  text: requiredText(input.text),
@@ -78,6 +90,7 @@ async function executeSemanticAdvisorInput(
78
90
  ...(source ? { source } : {}),
79
91
  ...(status ? { status } : {}),
80
92
  ...(clauses !== undefined ? { clauses } : {}),
93
+ ...(interpretations !== undefined ? { interpretations } : {}),
81
94
  },
82
95
  context,
83
96
  );
@@ -103,12 +116,38 @@ export const semanticAdvisorSpec = {
103
116
  description:
104
117
  "Optional complete list of atomic requirement clauses supplied by the caller. Use this for compound prose so every normative clause receives a stable claim key and independent grounding review.",
105
118
  },
119
+ interpretations: {
120
+ type: "array",
121
+ maxItems: 3,
122
+ description:
123
+ "Optional host-LLM typed kibi.logic.v1 interpretations. Kibi validates and canonicalizes them; raw Prolog is not accepted.",
124
+ items: {
125
+ type: "object",
126
+ required: ["claim_key", "claim_text", "ir"],
127
+ properties: {
128
+ claim_key: { type: "string" },
129
+ claim_text: { type: "string" },
130
+ confidence: { type: "number", minimum: 0, maximum: 1 },
131
+ span: { type: "object" },
132
+ ir: { type: "object" },
133
+ },
134
+ },
135
+ },
106
136
  type: {
107
137
  type: "string",
108
- enum: ["req"],
138
+ enum: [
139
+ "req",
140
+ "scenario",
141
+ "test",
142
+ "adr",
143
+ "flag",
144
+ "event",
145
+ "symbol",
146
+ "fact",
147
+ ],
109
148
  default: "req",
110
149
  description:
111
- "Entity type context for analysis. Currently requirement prose is supported.",
150
+ "Entity type context for analysis. Requirement, domain-fact, and supporting prose all receive a proposition ledger; only requirements receive deterministic modeling suggestions.",
112
151
  },
113
152
  id: {
114
153
  type: "string",
@@ -25,7 +25,9 @@ type FactKind =
25
25
  | "observation"
26
26
  | "meta"
27
27
  | "predicate_schema"
28
- | "predicate";
28
+ | "predicate"
29
+ | "rule_schema"
30
+ | "rule";
29
31
  type Operator = "eq" | "neq" | "lt" | "lte" | "gt" | "gte";
30
32
  type ValueType = "string" | "int" | "number" | "bool";
31
33
  type Polarity = "require" | "forbid" | "assert" | "deny";
@@ -74,6 +76,30 @@ const factConditionals = JSON.parse(`[
74
76
  }
75
77
  }
76
78
  },
79
+ {
80
+ "if": {
81
+ "properties": {
82
+ "type": { "const": "fact" },
83
+ "fact_kind": { "const": "rule_schema" }
84
+ },
85
+ "required": ["type", "fact_kind"]
86
+ },
87
+ "then": {
88
+ "required": ["rule_name", "argument_names", "argument_types"]
89
+ }
90
+ },
91
+ {
92
+ "if": {
93
+ "properties": {
94
+ "type": { "const": "fact" },
95
+ "fact_kind": { "const": "rule" }
96
+ },
97
+ "required": ["type", "fact_kind"]
98
+ },
99
+ "then": {
100
+ "required": ["rule_ir", "rule_hash", "rule_schema_id", "rule_name", "semantic_key"]
101
+ }
102
+ },
77
103
  {
78
104
  "if": {
79
105
  "properties": {
@@ -90,10 +116,209 @@ const factConditionals = JSON.parse(`[
90
116
  }
91
117
  ]`) as Array<Record<string, unknown>>;
92
118
 
119
+ // The persisted rule payload is still data, but its shape is constrained at
120
+ // the JSON boundary as well as by validateLogicIr. Keeping this vocabulary
121
+ // closed prevents a raw_goal/raw Prolog field from entering an upsert payload.
122
+ const logicTermSchema = {
123
+ oneOf: [
124
+ {
125
+ type: "object",
126
+ required: ["kind", "name", "type"],
127
+ properties: {
128
+ kind: { const: "var" },
129
+ name: { type: "string", pattern: "^[A-Z][A-Za-z0-9_]*$" },
130
+ type: { type: "string", pattern: "^[a-z][a-z0-9_:.\\/-]*$" },
131
+ },
132
+ additionalProperties: false,
133
+ },
134
+ {
135
+ type: "object",
136
+ required: ["kind", "value"],
137
+ properties: {
138
+ kind: { const: "const" },
139
+ value: { type: "string", minLength: 1 },
140
+ type: { type: "string", pattern: "^[a-z][a-z0-9_:.\\/-]*$" },
141
+ },
142
+ additionalProperties: false,
143
+ },
144
+ {
145
+ type: "object",
146
+ required: ["kind", "value"],
147
+ properties: {
148
+ kind: { const: "number" },
149
+ value: { type: "number" },
150
+ unit: { type: "string", pattern: "^[a-z][a-z0-9_:.\\/-]*$" },
151
+ },
152
+ additionalProperties: false,
153
+ },
154
+ {
155
+ type: "object",
156
+ required: ["kind", "value", "unit"],
157
+ properties: {
158
+ kind: { const: "duration" },
159
+ value: { type: "number", minimum: 0 },
160
+ unit: { type: "string", enum: ["ms", "s", "m", "h", "d", "w"] },
161
+ },
162
+ additionalProperties: false,
163
+ },
164
+ {
165
+ type: "object",
166
+ required: ["kind", "value"],
167
+ properties: {
168
+ kind: { const: "timestamp" },
169
+ value: { type: "string" },
170
+ },
171
+ additionalProperties: false,
172
+ },
173
+ {
174
+ type: "object",
175
+ required: ["kind", "start", "end"],
176
+ properties: {
177
+ kind: { const: "interval" },
178
+ start: { type: "string" },
179
+ end: { type: "string" },
180
+ },
181
+ additionalProperties: false,
182
+ },
183
+ ],
184
+ };
185
+
186
+ const logicAtomSchema = {
187
+ type: "object",
188
+ required: ["kind", "name", "args"],
189
+ properties: {
190
+ kind: { const: "atom" },
191
+ namespace: { type: "string", pattern: "^[a-z][a-z0-9_:.\\/-]*$" },
192
+ name: { type: "string", pattern: "^[a-z][a-z0-9_:.\\/-]*$" },
193
+ args: {
194
+ type: "array",
195
+ maxItems: 8,
196
+ items: { $ref: "#/$defs/logicTerm" },
197
+ },
198
+ polarity: { enum: ["positive", "negative"] },
199
+ closedWorld: { type: "boolean" },
200
+ },
201
+ additionalProperties: false,
202
+ };
203
+
204
+ const logicExpressionSchema = {
205
+ oneOf: [
206
+ { $ref: "#/$defs/logicAtom" },
207
+ {
208
+ type: "object",
209
+ required: ["kind", "items"],
210
+ properties: {
211
+ kind: { enum: ["all", "any"] },
212
+ items: {
213
+ type: "array",
214
+ minItems: 1,
215
+ maxItems: 32,
216
+ items: { $ref: "#/$defs/logicExpression" },
217
+ },
218
+ },
219
+ additionalProperties: false,
220
+ },
221
+ {
222
+ type: "object",
223
+ required: ["kind", "item"],
224
+ properties: {
225
+ kind: { const: "not" },
226
+ item: { $ref: "#/$defs/logicAtom" },
227
+ },
228
+ additionalProperties: false,
229
+ },
230
+ {
231
+ type: "object",
232
+ required: ["kind", "operator", "left", "right"],
233
+ properties: {
234
+ kind: { const: "compare" },
235
+ operator: { enum: ["eq", "neq", "lt", "lte", "gt", "gte"] },
236
+ left: { $ref: "#/$defs/logicTerm" },
237
+ right: { $ref: "#/$defs/logicTerm" },
238
+ },
239
+ additionalProperties: false,
240
+ },
241
+ {
242
+ type: "object",
243
+ required: ["kind", "atom", "operator", "value"],
244
+ properties: {
245
+ kind: { const: "count" },
246
+ atom: { $ref: "#/$defs/logicAtom" },
247
+ operator: { enum: ["eq", "neq", "lt", "lte", "gt", "gte"] },
248
+ value: { type: "integer", minimum: 0 },
249
+ },
250
+ additionalProperties: false,
251
+ },
252
+ {
253
+ type: "object",
254
+ required: ["kind", "relation", "left", "right"],
255
+ properties: {
256
+ kind: { const: "temporal" },
257
+ relation: {
258
+ enum: ["before", "after", "during", "overlaps", "starts", "finishes"],
259
+ },
260
+ left: { $ref: "#/$defs/logicTerm" },
261
+ right: { $ref: "#/$defs/logicTerm" },
262
+ },
263
+ additionalProperties: false,
264
+ },
265
+ ],
266
+ };
267
+
268
+ const logicRuleSchema = {
269
+ type: "object",
270
+ required: ["version", "kind", "modality"],
271
+ properties: {
272
+ version: { const: "kibi.logic.v1" },
273
+ kind: { enum: ["atom", "rule", "constraint"] },
274
+ modality: { enum: ["assert", "deny", "oblige", "permit", "forbid"] },
275
+ head: { $ref: "#/$defs/logicAtom" },
276
+ body: { $ref: "#/$defs/logicExpression" },
277
+ variables: {
278
+ type: "array",
279
+ maxItems: 32,
280
+ items: {
281
+ type: "object",
282
+ required: ["name", "type"],
283
+ properties: {
284
+ name: { type: "string", pattern: "^[A-Z][A-Za-z0-9_]*$" },
285
+ type: { type: "string", pattern: "^[a-z][a-z0-9_:.\\/-]*$" },
286
+ quantifier: { enum: ["forall", "exists"] },
287
+ },
288
+ additionalProperties: false,
289
+ },
290
+ },
291
+ exceptions: {
292
+ type: "array",
293
+ maxItems: 16,
294
+ items: { $ref: "#/$defs/logicExpression" },
295
+ },
296
+ scope: {
297
+ type: "object",
298
+ properties: {
299
+ authority: { type: "string" },
300
+ name: { type: "string" },
301
+ tags: { type: "array", items: { type: "string" } },
302
+ },
303
+ additionalProperties: false,
304
+ },
305
+ validFrom: { type: "string" },
306
+ validTo: { type: "string" },
307
+ ruleSchemaId: { type: "string", minLength: 1 },
308
+ },
309
+ additionalProperties: false,
310
+ };
311
+
93
312
  const entitySchema: Record<string, unknown> = {
94
313
  $id: "entity.schema.json",
95
314
  title: "Entity",
96
315
  type: "object",
316
+ $defs: {
317
+ logicTerm: logicTermSchema,
318
+ logicAtom: logicAtomSchema,
319
+ logicExpression: logicExpressionSchema,
320
+ logicRule: logicRuleSchema,
321
+ },
97
322
  properties: {
98
323
  id: { type: "string" },
99
324
  title: { type: "string" },
@@ -136,6 +361,53 @@ const entitySchema: Record<string, unknown> = {
136
361
  uniqueItems: true,
137
362
  items: { type: "string", pattern: "^CLAIM-[A-F0-9]{16}$" },
138
363
  },
364
+ semantic_inventory: {
365
+ type: "array",
366
+ items: {
367
+ type: "object",
368
+ required: ["claim_key", "claim_text", "role", "status", "span"],
369
+ properties: {
370
+ claim_key: { type: "string", pattern: "^CLAIM-[A-F0-9]{16}$" },
371
+ claim_text: { type: "string", minLength: 1 },
372
+ role: {
373
+ type: "string",
374
+ enum: [
375
+ "normative",
376
+ "definition",
377
+ "descriptive",
378
+ "condition",
379
+ "exception",
380
+ "rationale",
381
+ "example",
382
+ "subjective",
383
+ ],
384
+ },
385
+ status: {
386
+ type: "string",
387
+ enum: [
388
+ "modeled",
389
+ "ambiguous",
390
+ "ontology_gap",
391
+ "nonlogical",
392
+ "missing",
393
+ ],
394
+ },
395
+ span: {
396
+ type: "object",
397
+ required: ["start", "end"],
398
+ properties: {
399
+ start: { type: "integer", minimum: 0 },
400
+ end: { type: "integer", minimum: 0 },
401
+ },
402
+ additionalProperties: false,
403
+ },
404
+ semantic_key: { type: "string" },
405
+ payload_hash: { type: "string" },
406
+ reason: { type: "string" },
407
+ },
408
+ additionalProperties: false,
409
+ },
410
+ },
139
411
  sourceFile: { type: "string" },
140
412
  granularity_reason: {
141
413
  type: "string",
@@ -181,6 +453,8 @@ const entitySchema: Record<string, unknown> = {
181
453
  "meta",
182
454
  "predicate_schema",
183
455
  "predicate",
456
+ "rule_schema",
457
+ "rule",
184
458
  ] satisfies FactKind[],
185
459
  },
186
460
  subject_key: { type: "string" },
@@ -212,6 +486,13 @@ const entitySchema: Record<string, unknown> = {
212
486
  aliases: { type: "array", items: { type: "string" } },
213
487
  examples: { type: "array", items: { type: "string" } },
214
488
  predicate_args: { type: "array", items: { type: "string" } },
489
+ rule_ir: { $ref: "#/$defs/logicRule" },
490
+ rule_hash: { type: "string", pattern: "^[a-f0-9]{64}$" },
491
+ rule_schema_id: { type: "string", minLength: 1 },
492
+ rule_name: { type: "string", minLength: 1 },
493
+ semantic_key: { type: "string", pattern: "^SEM-[A-F0-9]{24}$" },
494
+ claim_span_start: { type: "integer", minimum: 0 },
495
+ claim_span_end: { type: "integer", minimum: 0 },
215
496
  },
216
497
  required: [
217
498
  "id",
@@ -268,6 +549,13 @@ const entitySchema: Record<string, unknown> = {
268
549
  { required: ["aliases"] },
269
550
  { required: ["examples"] },
270
551
  { required: ["predicate_args"] },
552
+ { required: ["rule_ir"] },
553
+ { required: ["rule_hash"] },
554
+ { required: ["rule_schema_id"] },
555
+ { required: ["rule_name"] },
556
+ { required: ["semantic_key"] },
557
+ { required: ["claim_span_start"] },
558
+ { required: ["claim_span_end"] },
271
559
  ],
272
560
  },
273
561
  },
@@ -285,6 +573,14 @@ const entitySchema: Record<string, unknown> = {
285
573
  },
286
574
  },
287
575
  },
576
+ {
577
+ if: {
578
+ properties: { type: { const: "req" } },
579
+ },
580
+ else: {
581
+ not: { required: ["semantic_inventory"] },
582
+ },
583
+ },
288
584
  ...factConditionals,
289
585
  ],
290
586
  additionalProperties: false,
@@ -35,6 +35,7 @@ const relationshipSchema = {
35
35
  "constrains",
36
36
  "requires_property",
37
37
  "requires_predicate",
38
+ "requires_rule",
38
39
  "guards",
39
40
  "publishes",
40
41
  "consumes",