kibi-cli 0.16.1 → 0.18.1

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 (229) hide show
  1. package/dist/cli-json-command.d.ts.map +1 -1
  2. package/dist/cli-json-command.js +87 -11
  3. package/dist/cli-register-maintenance.d.ts.map +1 -1
  4. package/dist/cli-register-maintenance.js +8 -0
  5. package/dist/cli-register-reporting.d.ts.map +1 -1
  6. package/dist/cli-register-reporting.js +5 -0
  7. package/dist/cli.d.ts.map +1 -1
  8. package/dist/cli.js +2 -1
  9. package/dist/commands/aggregated-checks.d.ts.map +1 -1
  10. package/dist/commands/aggregated-checks.js +1 -0
  11. package/dist/commands/check.d.ts.map +1 -1
  12. package/dist/commands/check.js +1 -1
  13. package/dist/commands/coverage.d.ts +5 -0
  14. package/dist/commands/coverage.d.ts.map +1 -1
  15. package/dist/commands/coverage.js +5 -0
  16. package/dist/commands/discovery-table.d.ts.map +1 -1
  17. package/dist/commands/discovery-table.js +96 -5
  18. package/dist/commands/sync/cache.d.ts +2 -0
  19. package/dist/commands/sync/cache.d.ts.map +1 -1
  20. package/dist/commands/sync/cache.js +8 -0
  21. package/dist/commands/sync/manifest.d.ts +12 -1
  22. package/dist/commands/sync/manifest.d.ts.map +1 -1
  23. package/dist/commands/sync/manifest.js +22 -5
  24. package/dist/commands/sync/persistence.d.ts.map +1 -1
  25. package/dist/commands/sync/persistence.js +76 -2
  26. package/dist/commands/sync.d.ts.map +1 -1
  27. package/dist/commands/sync.js +72 -15
  28. package/dist/commands/usage-metrics.d.ts +66 -2
  29. package/dist/commands/usage-metrics.d.ts.map +1 -1
  30. package/dist/commands/usage-metrics.js +34 -24
  31. package/dist/commands/usage-remediation.d.ts +9 -0
  32. package/dist/commands/usage-remediation.d.ts.map +1 -0
  33. package/dist/commands/usage-remediation.js +52 -0
  34. package/dist/extractors/markdown.d.ts +17 -1
  35. package/dist/extractors/markdown.d.ts.map +1 -1
  36. package/dist/extractors/markdown.js +81 -2
  37. package/dist/logic/ir.d.ts +112 -0
  38. package/dist/logic/ir.d.ts.map +1 -0
  39. package/dist/logic/ir.js +729 -0
  40. package/dist/operations/modeling/logic-modeling.d.ts +22 -0
  41. package/dist/operations/modeling/logic-modeling.d.ts.map +1 -0
  42. package/dist/operations/modeling/logic-modeling.js +120 -0
  43. package/dist/operations/modeling/model-requirement.d.ts.map +1 -1
  44. package/dist/operations/modeling/model-requirement.js +83 -2
  45. package/dist/operations/modeling/predicate-applyplan.d.ts +1 -1
  46. package/dist/operations/modeling/predicate-applyplan.d.ts.map +1 -1
  47. package/dist/operations/modeling/predicate-applyplan.js +29 -4
  48. package/dist/operations/modeling/predicate-inference.d.ts.map +1 -1
  49. package/dist/operations/modeling/predicate-inference.js +3 -0
  50. package/dist/operations/modeling/predicate-loader.d.ts.map +1 -1
  51. package/dist/operations/modeling/predicate-loader.js +7 -1
  52. package/dist/operations/modeling/predicate-ranker.d.ts.map +1 -1
  53. package/dist/operations/modeling/predicate-ranker.js +40 -2
  54. package/dist/operations/modeling/predicate-types.d.ts +12 -1
  55. package/dist/operations/modeling/predicate-types.d.ts.map +1 -1
  56. package/dist/operations/modeling/requirement-types.d.ts +12 -0
  57. package/dist/operations/modeling/requirement-types.d.ts.map +1 -1
  58. package/dist/operations/modeling/suggest-predicates.d.ts.map +1 -1
  59. package/dist/operations/modeling/suggest-predicates.js +35 -11
  60. package/dist/operations/mutation/audit.js +1 -1
  61. package/dist/operations/mutation/contradictions.d.ts +1 -1
  62. package/dist/operations/mutation/contradictions.d.ts.map +1 -1
  63. package/dist/operations/mutation/contradictions.js +23 -18
  64. package/dist/operations/mutation/relationships.d.ts.map +1 -1
  65. package/dist/operations/mutation/relationships.js +8 -0
  66. package/dist/operations/mutation/serialization.d.ts.map +1 -1
  67. package/dist/operations/mutation/serialization.js +6 -0
  68. package/dist/operations/mutation/strict-fact.d.ts.map +1 -1
  69. package/dist/operations/mutation/strict-fact.js +68 -3
  70. package/dist/operations/mutation/upsert.d.ts +3 -1
  71. package/dist/operations/mutation/upsert.d.ts.map +1 -1
  72. package/dist/operations/mutation/upsert.js +51 -12
  73. package/dist/operations/mutation/validate-upsert.d.ts.map +1 -1
  74. package/dist/operations/mutation/validate-upsert.js +18 -2
  75. package/dist/operations/mutation/validation.d.ts.map +1 -1
  76. package/dist/operations/mutation/validation.js +8 -0
  77. package/dist/operations/semantic-advisor/analysis-receipt.d.ts +2 -2
  78. package/dist/operations/semantic-advisor/analysis-receipt.d.ts.map +1 -1
  79. package/dist/operations/semantic-advisor/analysis-receipt.js +30 -16
  80. package/dist/operations/semantic-advisor/analyze-prose.d.ts +1 -1
  81. package/dist/operations/semantic-advisor/analyze-prose.d.ts.map +1 -1
  82. package/dist/operations/semantic-advisor/analyze-prose.js +464 -27
  83. package/dist/operations/semantic-advisor/clauses.d.ts +1 -0
  84. package/dist/operations/semantic-advisor/clauses.d.ts.map +1 -1
  85. package/dist/operations/semantic-advisor/clauses.js +7 -7
  86. package/dist/operations/semantic-advisor/ingestion-boundary.d.ts +18 -0
  87. package/dist/operations/semantic-advisor/ingestion-boundary.d.ts.map +1 -0
  88. package/dist/operations/semantic-advisor/ingestion-boundary.js +167 -0
  89. package/dist/operations/semantic-advisor/observation-plan.d.ts.map +1 -1
  90. package/dist/operations/semantic-advisor/observation-plan.js +15 -3
  91. package/dist/operations/semantic-advisor/shared.d.ts +9 -0
  92. package/dist/operations/semantic-advisor/shared.d.ts.map +1 -1
  93. package/dist/operations/semantic-advisor/shared.js +38 -4
  94. package/dist/operations/semantic-advisor/types.d.ts +66 -1
  95. package/dist/operations/semantic-advisor/types.d.ts.map +1 -1
  96. package/dist/prolog/codec.d.ts.map +1 -1
  97. package/dist/prolog/codec.js +19 -2
  98. package/dist/prolog.d.ts +6 -0
  99. package/dist/prolog.d.ts.map +1 -1
  100. package/dist/prolog.js +247 -63
  101. package/dist/public/diagnostic-usage.d.ts +17 -0
  102. package/dist/public/diagnostic-usage.d.ts.map +1 -0
  103. package/dist/public/diagnostic-usage.js +152 -0
  104. package/dist/public/distribution-parity.d.ts +90 -0
  105. package/dist/public/distribution-parity.d.ts.map +1 -0
  106. package/dist/public/distribution-parity.js +367 -0
  107. package/dist/public/impact/full-kb-quality.d.ts +2 -0
  108. package/dist/public/impact/full-kb-quality.d.ts.map +1 -1
  109. package/dist/public/impact/full-kb-quality.js +53 -1
  110. package/dist/public/impact-diagnostics.d.ts +2 -0
  111. package/dist/public/impact-diagnostics.d.ts.map +1 -1
  112. package/dist/public/impact-diagnostics.js +1 -0
  113. package/dist/public/operations/catalog.d.ts +235 -11
  114. package/dist/public/operations/catalog.d.ts.map +1 -1
  115. package/dist/public/operations/check-executor.d.ts.map +1 -1
  116. package/dist/public/operations/check-executor.js +4 -0
  117. package/dist/public/operations/discovery-executors.d.ts +6 -0
  118. package/dist/public/operations/discovery-executors.d.ts.map +1 -1
  119. package/dist/public/operations/discovery-executors.js +18 -2
  120. package/dist/public/operations/index.d.ts +5 -0
  121. package/dist/public/operations/index.d.ts.map +1 -1
  122. package/dist/public/operations/index.js +5 -0
  123. package/dist/public/operations/legacy-migration-plan.d.ts +113 -0
  124. package/dist/public/operations/legacy-migration-plan.d.ts.map +1 -0
  125. package/dist/public/operations/legacy-migration-plan.js +409 -0
  126. package/dist/public/operations/node-ports.d.ts.map +1 -1
  127. package/dist/public/operations/node-ports.js +90 -0
  128. package/dist/public/operations/repair-plan.d.ts +184 -0
  129. package/dist/public/operations/repair-plan.d.ts.map +1 -0
  130. package/dist/public/operations/repair-plan.js +397 -0
  131. package/dist/public/operations/runtime-types.d.ts +7 -0
  132. package/dist/public/operations/runtime-types.d.ts.map +1 -1
  133. package/dist/public/operations/specs/check.d.ts +3 -3
  134. package/dist/public/operations/specs/check.d.ts.map +1 -1
  135. package/dist/public/operations/specs/check.js +5 -2
  136. package/dist/public/operations/specs/discovery.d.ts +1 -1
  137. package/dist/public/operations/specs/discovery.js +1 -1
  138. package/dist/public/operations/specs/modeling.d.ts +35 -1
  139. package/dist/public/operations/specs/modeling.d.ts.map +1 -1
  140. package/dist/public/operations/specs/modeling.js +32 -1
  141. package/dist/public/operations/specs/mutation-schemas.d.ts +133 -3
  142. package/dist/public/operations/specs/mutation-schemas.d.ts.map +1 -1
  143. package/dist/public/operations/specs/mutation-schemas.js +67 -1
  144. package/dist/public/operations/specs/reporting.d.ts +42 -1
  145. package/dist/public/operations/specs/reporting.d.ts.map +1 -1
  146. package/dist/public/operations/specs/reporting.js +70 -6
  147. package/dist/public/operations/specs/semantic.d.ts +30 -2
  148. package/dist/public/operations/specs/semantic.d.ts.map +1 -1
  149. package/dist/public/operations/specs/semantic.js +35 -3
  150. package/dist/public/operations/specs/upsert.d.ts +133 -3
  151. package/dist/public/operations/specs/upsert.d.ts.map +1 -1
  152. package/dist/public/operations/workspace-snapshot.d.ts +10 -0
  153. package/dist/public/operations/workspace-snapshot.d.ts.map +1 -0
  154. package/dist/public/operations/workspace-snapshot.js +20 -0
  155. package/dist/public/schemas/entity.d.ts.map +1 -1
  156. package/dist/public/schemas/entity.js +332 -0
  157. package/dist/public/schemas/relationship.d.ts.map +1 -1
  158. package/dist/public/schemas/relationship.js +1 -0
  159. package/dist/public/skills/kibi-traceability/SKILL.md +7 -1
  160. package/dist/public/skills/kibi-usage/SKILL.md +44 -12
  161. package/dist/public/skills/kibi-usage/resources/fact-lanes.md +12 -2
  162. package/dist/public/skills/kibi-usage/resources/logic-ir.md +43 -0
  163. package/dist/public/skills/kibi-usage/resources/operation-access.md +19 -19
  164. package/dist/public/skills/kibi-usage/resources/ui-requirements.md +96 -0
  165. package/dist/public/skills/kibi-usage/resources/workflows.md +40 -8
  166. package/dist/public/symbol-granularity.d.ts +9 -0
  167. package/dist/public/symbol-granularity.d.ts.map +1 -1
  168. package/dist/public/symbol-granularity.js +16 -0
  169. package/dist/public/telemetry-acceptance.d.ts +89 -0
  170. package/dist/public/telemetry-acceptance.d.ts.map +1 -0
  171. package/dist/public/telemetry-acceptance.js +597 -0
  172. package/dist/public/telemetry-remediation.d.ts +33 -0
  173. package/dist/public/telemetry-remediation.d.ts.map +1 -0
  174. package/dist/public/telemetry-remediation.js +257 -0
  175. package/dist/public/verification-receipt.d.ts +75 -0
  176. package/dist/public/verification-receipt.d.ts.map +1 -0
  177. package/dist/public/verification-receipt.js +129 -0
  178. package/dist/schemas/entity.schema.json +401 -4
  179. package/dist/traceability/staged-diagnostics.d.ts +1 -1
  180. package/dist/traceability/staged-diagnostics.d.ts.map +1 -1
  181. package/dist/traceability/staged-diagnostics.js +17 -10
  182. package/dist/traceability/staged-impact-contract.js +1 -1
  183. package/dist/traceability/staged-symbols-manifest.d.ts.map +1 -1
  184. package/dist/traceability/staged-symbols-manifest.js +28 -10
  185. package/dist/traceability/temp-kb.d.ts.map +1 -1
  186. package/dist/traceability/temp-kb.js +49 -3
  187. package/dist/types/entities.d.ts +1 -0
  188. package/dist/types/entities.d.ts.map +1 -1
  189. package/dist/types/relationships.d.ts +1 -1
  190. package/dist/types/relationships.d.ts.map +1 -1
  191. package/dist/utils/rule-registry.d.ts +2 -0
  192. package/dist/utils/rule-registry.d.ts.map +1 -1
  193. package/dist/utils/rule-registry.js +18 -0
  194. package/dist/utils/schema-version.d.ts +1 -1
  195. package/dist/utils/schema-version.js +1 -1
  196. package/package.json +34 -2
  197. package/src/public/diagnostic-usage.ts +206 -0
  198. package/src/public/distribution-parity.ts +580 -0
  199. package/src/public/impact/full-kb-quality.ts +74 -1
  200. package/src/public/impact-diagnostics.ts +16 -0
  201. package/src/public/operations/check-executor.ts +4 -0
  202. package/src/public/operations/discovery-executors.ts +24 -2
  203. package/src/public/operations/index.ts +5 -0
  204. package/src/public/operations/legacy-migration-plan.ts +688 -0
  205. package/src/public/operations/node-ports.ts +109 -0
  206. package/src/public/operations/repair-plan.ts +562 -0
  207. package/src/public/operations/runtime-types.ts +8 -0
  208. package/src/public/operations/specs/check.ts +5 -2
  209. package/src/public/operations/specs/discovery.ts +1 -1
  210. package/src/public/operations/specs/modeling.ts +39 -1
  211. package/src/public/operations/specs/mutation-schemas.ts +77 -1
  212. package/src/public/operations/specs/reporting.ts +91 -6
  213. package/src/public/operations/specs/semantic.ts +42 -3
  214. package/src/public/operations/workspace-snapshot.ts +28 -0
  215. package/src/public/schemas/entity.ts +340 -1
  216. package/src/public/schemas/relationship.ts +1 -0
  217. package/src/public/skills/kibi-traceability/SKILL.md +7 -1
  218. package/src/public/skills/kibi-usage/SKILL.md +44 -12
  219. package/src/public/skills/kibi-usage/resources/fact-lanes.md +12 -2
  220. package/src/public/skills/kibi-usage/resources/logic-ir.md +43 -0
  221. package/src/public/skills/kibi-usage/resources/operation-access.md +19 -19
  222. package/src/public/skills/kibi-usage/resources/ui-requirements.md +96 -0
  223. package/src/public/skills/kibi-usage/resources/workflows.md +40 -8
  224. package/src/public/symbol-granularity.ts +25 -0
  225. package/src/public/telemetry-acceptance.ts +859 -0
  226. package/src/public/telemetry-remediation.ts +462 -0
  227. package/src/public/verification-receipt.ts +170 -0
  228. package/src/schemas/entity.schema.json +401 -4
  229. package/src/schemas/relationship.schema.json +1 -0
@@ -1,14 +1,16 @@
1
+ import { utf8Span, validateLogicIr, } from "../../logic/ir.js";
2
+ import { logicRuleFactId } from "../modeling/logic-modeling.js";
1
3
  import { buildAdvisorResult } from "./analysis-receipt.js";
2
- import { extractSemanticClauses } from "./clauses.js";
4
+ import { extractSemanticClauses, semanticClaimKey, } from "./clauses.js";
3
5
  import { observationPlan } from "./observation-plan.js";
4
6
  import { detectPredicateRules } from "./predicate-rule.js";
5
7
  import { CORE_PREDICATE_RULES } from "./predicate-rules-core.js";
6
8
  import { POLICY_PREDICATE_RULES } from "./predicate-rules-policy.js";
7
9
  import { PRODUCT_TAIL_PREDICATE_RULES } from "./predicate-rules-product-tail.js";
8
10
  import { PRODUCT_PREDICATE_RULES } from "./predicate-rules-product.js";
9
- import { isRecord, propertiesOf, statementOf, stringValue, } from "./shared.js";
11
+ import { isRecord, payloadHash, propertiesOf, relationship, semanticClausesOf, semanticSourceHash, semanticSourceOf, sourceOf, statementOf, stringValue, } from "./shared.js";
10
12
  import { detectStrictSuggestion } from "./strict-rules.js";
11
- export const SEMANTIC_ADVISOR_VERSION = "semantic-advisor-v1";
13
+ export const SEMANTIC_ADVISOR_VERSION = "semantic-advisor-v2";
12
14
  export { semanticClaimKey } from "./clauses.js";
13
15
  const SIGNAL_PATTERNS = [
14
16
  {
@@ -50,7 +52,12 @@ const SIGNAL_PATTERNS = [
50
52
  ];
51
53
  function proseOf(payload) {
52
54
  const properties = propertiesOf(payload);
53
- return [properties.title, properties.text_ref, properties.description]
55
+ return [
56
+ properties.title,
57
+ properties.semantic_text,
58
+ properties.text_ref,
59
+ properties.description,
60
+ ]
54
61
  .map(stringValue)
55
62
  .filter(Boolean)
56
63
  .join("\n");
@@ -65,10 +72,10 @@ function logicalGroundingSlots(payload) {
65
72
  ? payload.relationships
66
73
  : [];
67
74
  return relationships.filter((relationship) => isRecord(relationship) &&
68
- ["requires_property", "requires_predicate"].includes(stringValue(relationship.type))).length;
75
+ ["requires_property", "requires_predicate", "requires_rule"].includes(stringValue(relationship.type))).length;
69
76
  }
70
- function isModeled(payload, expectedClaimCount) {
71
- if (expectedClaimCount === 0)
77
+ function isModeled(payload, expectedClaimKeys) {
78
+ if (expectedClaimKeys.length === 0)
72
79
  return false;
73
80
  const relationships = Array.isArray(payload.relationships)
74
81
  ? payload.relationships
@@ -77,9 +84,19 @@ function isModeled(payload, expectedClaimCount) {
77
84
  .filter(isRecord)
78
85
  .map((relationship) => stringValue(relationship.type))
79
86
  .filter(Boolean));
80
- return (logicalGroundingSlots(payload) >= expectedClaimCount &&
87
+ const rawInventory = propertiesOf(payload).semantic_inventory;
88
+ const inventory = Array.isArray(rawInventory)
89
+ ? rawInventory.filter(isRecord)
90
+ : [];
91
+ const modeledClaimKeys = inventory
92
+ .filter(({ status }) => status === "modeled")
93
+ .map(({ claim_key }) => stringValue(claim_key));
94
+ return (logicalGroundingSlots(payload) === expectedClaimKeys.length &&
95
+ modeledClaimKeys.length === expectedClaimKeys.length &&
96
+ expectedClaimKeys.every((claimKey) => modeledClaimKeys.includes(claimKey)) &&
81
97
  ((types.has("constrains") && types.has("requires_property")) ||
82
- types.has("requires_predicate")));
98
+ types.has("requires_predicate") ||
99
+ types.has("requires_rule")));
83
100
  }
84
101
  function detectSignals(prose) {
85
102
  const seen = new Set();
@@ -149,19 +166,87 @@ function predicateSuggestion(payload, statement) {
149
166
  detectPredicateRules(payload, statement, PRODUCT_PREDICATE_RULES) ??
150
167
  detectPredicateRules(payload, statement, PRODUCT_TAIL_PREDICATE_RULES));
151
168
  }
152
- function modelingSuggestions(payload, modeled, clauses) {
169
+ function ruleSuggestion(payload, candidate) {
170
+ const validation = validateLogicIr(candidate.ir);
171
+ if (!validation.valid ||
172
+ !validation.normalized ||
173
+ !validation.semanticKey ||
174
+ !validation.renderedProlog)
175
+ return null;
176
+ const reqId = stringValue(payload.id);
177
+ const semanticKey = validation.semanticKey;
178
+ const schemaId = candidate.ir.ruleSchemaId ?? "FACT-RULE-SCHEMA-LOGIC-V1";
179
+ const factId = logicRuleFactId(semanticKey);
180
+ const schemaPlan = candidate.ir.ruleSchemaId
181
+ ? []
182
+ : [
183
+ {
184
+ type: "fact",
185
+ id: schemaId,
186
+ properties: {
187
+ title: "kibi.logic.v1 rule schema",
188
+ status: "active",
189
+ source: sourceOf(payload),
190
+ fact_kind: "rule_schema",
191
+ rule_name: "kibi.logic.v1",
192
+ argument_names: ["rule_ir"],
193
+ argument_types: ["logic_ir"],
194
+ aliases: ["conditional rule", "constraint", "policy rule"],
195
+ examples: [validation.renderedProlog],
196
+ },
197
+ relationships: [],
198
+ },
199
+ ];
200
+ return {
201
+ kind: "rule",
202
+ claim_key: candidate.claim_key,
203
+ claim_text: candidate.claim_text,
204
+ confidence: candidate.confidence ?? 0.75,
205
+ evidence: candidate.claim_text,
206
+ rationale: "The host supplied a typed kibi.logic.v1 interpretation. Kibi validated its safety, canonicalized it, and will persist it as data-backed rule evidence.",
207
+ suggested_next_tool: "kb_model_requirement",
208
+ rule: validation.normalized,
209
+ semantic_key: semanticKey,
210
+ rendered_prolog: validation.renderedProlog,
211
+ rejected_alternatives: ["raw_prolog", "observation_review"],
212
+ applyPlan: [
213
+ ...schemaPlan,
214
+ {
215
+ type: "fact",
216
+ id: factId,
217
+ properties: {
218
+ title: `${candidate.ir.kind} rule ${semanticKey}`,
219
+ status: "active",
220
+ source: sourceOf(payload),
221
+ fact_kind: "rule",
222
+ rule_ir: validation.normalized,
223
+ rule_hash: validation.ruleHash,
224
+ semantic_key: semanticKey,
225
+ rule_schema_id: schemaId,
226
+ rule_name: validation.normalized.ruleSchemaId ?? "kibi.logic.v1",
227
+ canonical_key: semanticKey,
228
+ tags: ["lane:logic", "semantic-advisor-suggestion"],
229
+ },
230
+ relationships: [],
231
+ },
232
+ ],
233
+ relationshipPlan: reqId
234
+ ? {
235
+ applyAfter: factId,
236
+ requiresExistingReq: reqId,
237
+ relationship: relationship(reqId, factId, "requires_rule"),
238
+ }
239
+ : null,
240
+ };
241
+ }
242
+ function modelingSuggestions(payload, modeled, clauses, interpretations) {
153
243
  if (!isRequirement(payload) || modeled)
154
244
  return [];
155
245
  const suggestions = [];
156
246
  const seen = new Set();
157
247
  const expectedClaimKeys = clauses
158
- .filter((clause) => clause.normative)
248
+ .filter((clause) => !["rationale", "example", "subjective"].includes(propositionRole(clause.text, clause.normative)))
159
249
  .map((clause) => clause.claim_key);
160
- const rawDeclaredClaimKeys = propertiesOf(payload).logic_claims;
161
- const declaredClaimKeys = Array.isArray(rawDeclaredClaimKeys)
162
- ? rawDeclaredClaimKeys.filter((value) => typeof value === "string")
163
- : [];
164
- const mergedClaimKeys = Array.from(new Set([...declaredClaimKeys, ...expectedClaimKeys]));
165
250
  for (const clause of clauses) {
166
251
  const candidate = clause.text;
167
252
  const rawSuggestion = predicateSuggestion(payload, candidate) ??
@@ -169,9 +254,9 @@ function modelingSuggestions(payload, modeled, clauses) {
169
254
  ambiguitySuggestion(payload, candidate) ??
170
255
  detectStrictSuggestion(payload, candidate);
171
256
  const suggestion = rawSuggestion
172
- ? withClauseProvenance(rawSuggestion, clause, mergedClaimKeys)
257
+ ? withClauseProvenance(rawSuggestion, clause, clauses, expectedClaimKeys, statementOf(payload), semanticSourceOf(payload).field)
173
258
  : clause.normative
174
- ? unmatchedClauseSuggestion(payload, clause, mergedClaimKeys)
259
+ ? unmatchedClauseSuggestion(payload, clause, clauses, expectedClaimKeys)
175
260
  : null;
176
261
  if (!suggestion)
177
262
  continue;
@@ -181,9 +266,63 @@ function modelingSuggestions(payload, modeled, clauses) {
181
266
  suggestions.push(suggestion);
182
267
  }
183
268
  }
269
+ for (const interpretation of interpretations ?? []) {
270
+ const clause = clauses.find((entry) => entry.claim_key === interpretation.claim_key);
271
+ if (!clause)
272
+ continue;
273
+ const suggestion = ruleSuggestion(payload, interpretation);
274
+ if (!suggestion)
275
+ continue;
276
+ const withProvenance = withClauseProvenance(suggestion, clause, clauses, expectedClaimKeys, statementOf(payload), semanticSourceOf(payload).field);
277
+ const key = withProvenance.kind === "rule"
278
+ ? `${withProvenance.claim_key}:rule:${withProvenance.semantic_key}`
279
+ : `${withProvenance.claim_key}:${withProvenance.kind}`;
280
+ if (!seen.has(key)) {
281
+ seen.add(key);
282
+ suggestions.push(withProvenance);
283
+ }
284
+ }
184
285
  return suggestions;
185
286
  }
186
- function withClauseProvenance(suggestion, clause, expectedClaimKeys) {
287
+ function withClauseProvenance(suggestion, clause, clauses, expectedClaimKeys, statement, sourceField) {
288
+ const clauseOffset = statement.indexOf(clause.text);
289
+ const clauseSpan = utf8Span(statement || clause.text, clauseOffset >= 0 ? clauseOffset : 0, clauseOffset >= 0 ? clauseOffset + clause.text.length : clause.text.length);
290
+ const status = suggestion.kind === "ambiguity_observation"
291
+ ? "ambiguous"
292
+ : suggestion.kind === "ontology_gap"
293
+ ? "ontology_gap"
294
+ : "modeled";
295
+ let inventoryCursor = 0;
296
+ const semanticInventory = clauses.map((entry) => {
297
+ const located = propositionSpan(statement, entry, inventoryCursor);
298
+ inventoryCursor = located.next;
299
+ const role = propositionRole(entry.text, entry.normative);
300
+ const context = ["rationale", "example", "subjective"].includes(role);
301
+ const entryStatus = entry.index === clause.index
302
+ ? status
303
+ : context
304
+ ? "nonlogical"
305
+ : "missing";
306
+ return {
307
+ claim_key: entry.claim_key,
308
+ claim_text: entry.text,
309
+ role,
310
+ status: entryStatus,
311
+ span: located.span,
312
+ reason: entry.index === clause.index
313
+ ? status === "modeled"
314
+ ? "Draft apply plan contains a typed grounding for this proposition."
315
+ : suggestion.rationale
316
+ : context
317
+ ? "Prose is retained for human context and is not a verifiable domain proposition."
318
+ : "No typed grounding is included for this proposition in the current draft plan.",
319
+ };
320
+ });
321
+ const inventoryContract = {
322
+ version: "kibi.semantic-inventory.v1",
323
+ source_field: sourceField,
324
+ source_hash: semanticSourceHash(statement),
325
+ };
187
326
  const applyPlan = suggestion.applyPlan.map((step) => {
188
327
  if (!isRecord(step))
189
328
  return step;
@@ -199,6 +338,11 @@ function withClauseProvenance(suggestion, clause, expectedClaimKeys) {
199
338
  properties: {
200
339
  ...properties,
201
340
  logic_claims: Array.from(new Set([...existing, ...expectedClaimKeys])),
341
+ semantic_clauses: clauses.map(({ text }) => text),
342
+ semantic_inventory_version: inventoryContract.version,
343
+ semantic_source_field: inventoryContract.source_field,
344
+ semantic_source_hash: inventoryContract.source_hash,
345
+ semantic_inventory: semanticInventory,
202
346
  },
203
347
  };
204
348
  }
@@ -210,6 +354,8 @@ function withClauseProvenance(suggestion, clause, expectedClaimKeys) {
210
354
  ...properties,
211
355
  claim_key: clause.claim_key,
212
356
  claim_text: clause.text,
357
+ claim_span_start: clauseSpan.start,
358
+ claim_span_end: clauseSpan.end,
213
359
  },
214
360
  };
215
361
  });
@@ -225,13 +371,30 @@ function withClauseProvenance(suggestion, clause, expectedClaimKeys) {
225
371
  claimKey: clause.claim_key,
226
372
  claimText: clause.text,
227
373
  logicClaims: expectedClaimKeys,
374
+ semanticClauses: clauses.map(({ text }) => text),
375
+ semanticInventory,
376
+ inventoryContract,
228
377
  instructions: "Create the predicate fact, merge the returned logicClaims into the requirement logic_claims manifest, then add requires_predicate without overwriting other requirement metadata.",
229
378
  },
230
379
  }
231
380
  : {}),
381
+ ...(suggestion.kind === "rule" && suggestion.relationshipPlan !== null
382
+ ? {
383
+ relationshipPlan: {
384
+ ...suggestion.relationshipPlan,
385
+ claimKey: clause.claim_key,
386
+ claimText: clause.text,
387
+ logicClaims: expectedClaimKeys,
388
+ semanticClauses: clauses.map(({ text }) => text),
389
+ semanticInventory,
390
+ inventoryContract,
391
+ instructions: "Create the rule_schema and rule facts, merge the returned logicClaims into the requirement logic_claims manifest, then add requires_rule without overwriting other requirement metadata.",
392
+ },
393
+ }
394
+ : {}),
232
395
  };
233
396
  }
234
- function unmatchedClauseSuggestion(payload, clause, expectedClaimKeys) {
397
+ function unmatchedClauseSuggestion(payload, clause, clauses, expectedClaimKeys) {
235
398
  return withClauseProvenance({
236
399
  kind: "ontology_gap",
237
400
  claim_key: clause.claim_key,
@@ -246,26 +409,300 @@ function unmatchedClauseSuggestion(payload, clause, expectedClaimKeys) {
246
409
  "review:ontology-gap",
247
410
  "needs_schema_extension",
248
411
  ]),
249
- }, clause, expectedClaimKeys);
412
+ }, clause, clauses, expectedClaimKeys, statementOf(payload), semanticSourceOf(payload).field);
413
+ }
414
+ function propositionRole(statement, normative) {
415
+ if (/\b(?:for example|e\.g\.|such as|illustrative)\b/i.test(statement))
416
+ return "example";
417
+ if (/\b(?:because|so that|in order to| rationale|therefore)\b/i.test(statement))
418
+ return "rationale";
419
+ if (/\b(?:feel|comfortable|looks complete|seems complete|subjective|prefer)\b/i.test(statement))
420
+ return "subjective";
421
+ if (/\b(?:means|defined as|refers to|is called)\b/i.test(statement))
422
+ return "definition";
423
+ if (/^\s*(?:if|when|whenever|provided that|only if)\b/i.test(statement))
424
+ return "condition";
425
+ if (/\b(?:unless|except|exempt|apart from)\b/i.test(statement))
426
+ return "exception";
427
+ if (normative)
428
+ return "normative";
429
+ return "descriptive";
430
+ }
431
+ function shadowAnalysis(text, interpretations) {
432
+ const valid = interpretations.filter((interpretation) => interpretation.valid);
433
+ const models = valid.flatMap(({ normalized_ir: ir }) => (ir ? [ir] : []));
434
+ const containsExpressionKind = (kind) => {
435
+ const visit = (value) => {
436
+ if (!isRecord(value))
437
+ return false;
438
+ if (value.kind === kind)
439
+ return true;
440
+ return Object.values(value).some((child) => Array.isArray(child) ? child.some(visit) : visit(child));
441
+ };
442
+ return models.some((model) => visit(model));
443
+ };
444
+ const hasModality = (modalities) => models.some((model) => modalities.includes(model.modality));
445
+ const hasNegativeAtom = (() => {
446
+ const visit = (value) => {
447
+ if (!isRecord(value))
448
+ return false;
449
+ if (value.kind === "not" || value.polarity === "negative")
450
+ return true;
451
+ return Object.values(value).some((child) => Array.isArray(child) ? child.some(visit) : visit(child));
452
+ };
453
+ return models.some((model) => visit(model));
454
+ })();
455
+ const cues = [
456
+ {
457
+ kind: "modal",
458
+ pattern: /\b(?:must|shall|should|may|can)\b/i,
459
+ evidence: "deontic modal",
460
+ represented: models.length > 0,
461
+ },
462
+ {
463
+ kind: "polarity",
464
+ pattern: /\b(?:assert|deny|forbid|allowed|permitted|prohibited)\b/i,
465
+ evidence: "polarity cue",
466
+ represented: hasModality(["deny", "forbid", "permit"]) || hasNegativeAtom,
467
+ },
468
+ {
469
+ kind: "passive_voice",
470
+ pattern: /\b(?:is|are|be|was|were)\s+[a-z]+ed\b/i,
471
+ evidence: "passive construction",
472
+ represented: false,
473
+ },
474
+ {
475
+ kind: "nominalization",
476
+ pattern: /\b[a-z]+(?:tion|ment|ity|ance|ence)\b/i,
477
+ evidence: "nominalized domain term",
478
+ represented: false,
479
+ },
480
+ {
481
+ kind: "conditional",
482
+ pattern: /\b(?:if|when|whenever|provided that)\b/i,
483
+ evidence: "conditional",
484
+ represented: models.some(({ kind, body }) => kind === "rule" && body !== undefined),
485
+ },
486
+ {
487
+ kind: "causal",
488
+ pattern: /\b(?:because|so that|therefore|as a result)\b/i,
489
+ evidence: "causal relation",
490
+ represented: false,
491
+ },
492
+ {
493
+ kind: "prerequisite",
494
+ pattern: /\b(?:before|only after|requires?\s+.+?\s+before)\b/i,
495
+ evidence: "prerequisite/order relation",
496
+ represented: containsExpressionKind("temporal"),
497
+ },
498
+ {
499
+ kind: "exception",
500
+ pattern: /\b(?:unless|except|exempt|apart from)\b/i,
501
+ evidence: "exception",
502
+ represented: models.some(({ exceptions }) => (exceptions?.length ?? 0) > 0) ||
503
+ containsExpressionKind("not"),
504
+ },
505
+ {
506
+ kind: "temporal",
507
+ pattern: /\b(?:before|after|during|until|within|expires?|retained for)\b/i,
508
+ evidence: "temporal qualifier",
509
+ represented: containsExpressionKind("temporal") ||
510
+ models.some(({ validFrom, validTo }) => validFrom !== undefined || validTo !== undefined) ||
511
+ containsExpressionKind("duration"),
512
+ },
513
+ {
514
+ kind: "quantifier",
515
+ pattern: /\b(?:each|every|all|any|some|only|at least|at most|exactly|no more than)\b/i,
516
+ evidence: "quantifier/cardinality",
517
+ represented: models.some(({ variables }) => (variables?.length ?? 0) > 0) ||
518
+ containsExpressionKind("count") ||
519
+ containsExpressionKind("compare") ||
520
+ containsExpressionKind("all") ||
521
+ containsExpressionKind("any"),
522
+ },
523
+ {
524
+ kind: "numeric",
525
+ pattern: /\b\d+(?:\.\d+)?\b|\b(?:zero|one|two|three|four|five|six|seven|eight|nine|ten)\b/i,
526
+ evidence: "numeric or cardinality value",
527
+ represented: containsExpressionKind("number") ||
528
+ containsExpressionKind("count") ||
529
+ containsExpressionKind("compare"),
530
+ },
531
+ {
532
+ kind: "negation_scope",
533
+ pattern: /\b(?:not|never|no|without|cannot|can't|must not)\b/i,
534
+ evidence: "negation scope",
535
+ represented: hasModality(["deny", "forbid"]) || hasNegativeAtom,
536
+ },
537
+ {
538
+ kind: "directionality",
539
+ pattern: /\b(?:only if|if and only if|unless|when)\b/i,
540
+ evidence: "condition direction",
541
+ represented: models.some(({ kind, body }) => kind === "rule" && body !== undefined),
542
+ },
543
+ ];
544
+ return cues
545
+ .filter((cue) => cue.pattern.test(text))
546
+ .map(({ kind, evidence, represented }) => ({
547
+ kind,
548
+ evidence,
549
+ represented,
550
+ }));
551
+ }
552
+ function propositionSpan(text, clause, cursor) {
553
+ const exact = text.indexOf(clause.text, cursor);
554
+ const start = exact >= 0 ? exact : cursor;
555
+ const end = exact >= 0
556
+ ? exact + clause.text.length
557
+ : Math.min(text.length, start + clause.text.length);
558
+ return { span: utf8Span(text, start, end), next: Math.max(cursor, end) };
559
+ }
560
+ function interpretationResults(interpretations, clauses, statement) {
561
+ if (interpretations === undefined)
562
+ return { results: [], warnings: [] };
563
+ const known = new Set(clauses.map((clause) => clause.claim_key));
564
+ const semanticKeys = new Map();
565
+ const warnings = [];
566
+ const results = interpretations.slice(0, 3).map((candidate) => {
567
+ const confidence = Math.max(0, Math.min(1, candidate.confidence ?? 0.5));
568
+ const validation = validateLogicIr(candidate.ir);
569
+ const errors = [...validation.errors];
570
+ const clause = clauses.find((entry) => entry.claim_key === candidate.claim_key);
571
+ if (!known.has(candidate.claim_key))
572
+ errors.push(`claim_key ${candidate.claim_key} is not present in the advisor proposition inventory`);
573
+ if (clause &&
574
+ candidate.claim_text !== clause.text &&
575
+ semanticClaimKey(candidate.claim_text) !== clause.claim_key)
576
+ errors.push(`claim_text for ${candidate.claim_key} must match the proposition text (apart from normalized punctuation)`);
577
+ if (candidate.span &&
578
+ (candidate.span.start < 0 || candidate.span.end < candidate.span.start))
579
+ errors.push("interpretation span is invalid");
580
+ if (clause && candidate.span) {
581
+ const candidateStart = statement.indexOf(candidate.claim_text);
582
+ const clauseStart = statement.indexOf(clause.text);
583
+ const sourceStart = candidateStart >= 0 ? candidateStart : clauseStart;
584
+ const sourceEnd = sourceStart >= 0
585
+ ? sourceStart +
586
+ (candidateStart >= 0
587
+ ? candidate.claim_text.length
588
+ : clause.text.length)
589
+ : 0;
590
+ const expectedSpan = utf8Span(statement, Math.max(0, sourceStart), Math.max(0, sourceEnd));
591
+ if (candidate.span.start !== expectedSpan.start ||
592
+ candidate.span.end !== expectedSpan.end)
593
+ errors.push(`interpretation span for ${candidate.claim_key} does not match the exact UTF-8 proposition span`);
594
+ }
595
+ const semanticKey = validation.semanticKey;
596
+ if (semanticKey !== undefined) {
597
+ const prior = semanticKeys.get(candidate.claim_key);
598
+ if (prior !== undefined && prior !== semanticKey)
599
+ warnings.push(`Claim ${candidate.claim_key} has materially different interpretations; it remains unresolved until one is selected.`);
600
+ semanticKeys.set(candidate.claim_key, semanticKey);
601
+ }
602
+ return {
603
+ claim_key: candidate.claim_key,
604
+ ...(semanticKey ? { semantic_key: semanticKey } : {}),
605
+ ...(validation.normalized
606
+ ? { normalized_ir: validation.normalized }
607
+ : {}),
608
+ valid: errors.length === 0 && validation.valid,
609
+ confidence,
610
+ errors,
611
+ warnings: validation.warnings,
612
+ ...(validation.renderedProlog
613
+ ? { rendered_prolog: validation.renderedProlog }
614
+ : {}),
615
+ };
616
+ });
617
+ if (interpretations.length > 3)
618
+ warnings.push("Only the first three interpretations are considered; submit materially distinct alternatives explicitly and resolve them before writing.");
619
+ return { results, warnings };
620
+ }
621
+ function propositionInventory(statement, clauses, suggestions, interpretations, inputPayloadHash) {
622
+ const interpretationKeys = new Map();
623
+ for (const interpretation of interpretations) {
624
+ if (!interpretation.valid || !interpretation.semantic_key)
625
+ continue;
626
+ const keys = interpretationKeys.get(interpretation.claim_key) ?? new Set();
627
+ keys.add(interpretation.semantic_key);
628
+ interpretationKeys.set(interpretation.claim_key, keys);
629
+ }
630
+ let cursor = 0;
631
+ return clauses.map((clause) => {
632
+ const located = propositionSpan(statement, clause, cursor);
633
+ cursor = located.next;
634
+ const role = propositionRole(clause.text, clause.normative);
635
+ const suggestion = suggestions.find((candidate) => candidate.claim_key === clause.claim_key);
636
+ let status;
637
+ let reason;
638
+ const keys = interpretationKeys.get(clause.claim_key);
639
+ const semanticKey = keys?.size === 1 ? [...keys][0] : undefined;
640
+ if (keys && keys.size > 1) {
641
+ status = "ambiguous";
642
+ reason =
643
+ "Materially different valid interpretations were submitted; confidence cannot choose between them.";
644
+ }
645
+ else if (semanticKey) {
646
+ status = "modeled";
647
+ }
648
+ else if (role === "rationale" ||
649
+ role === "example" ||
650
+ role === "subjective") {
651
+ status = "nonlogical";
652
+ reason =
653
+ "Prose is retained for human context but does not assert a verifiable domain proposition.";
654
+ }
655
+ else if (suggestion?.kind === "ambiguity_observation") {
656
+ status = "ambiguous";
657
+ reason = suggestion.rationale;
658
+ }
659
+ else if (suggestion?.kind === "ontology_gap") {
660
+ status = "ontology_gap";
661
+ reason = suggestion.rationale;
662
+ }
663
+ else {
664
+ status = "missing";
665
+ reason =
666
+ "No accepted typed interpretation grounds this assertive proposition.";
667
+ }
668
+ return {
669
+ claim_key: clause.claim_key,
670
+ claim_text: clause.text,
671
+ role,
672
+ status,
673
+ span: located.span,
674
+ payload_hash: inputPayloadHash,
675
+ ...(semanticKey ? { semantic_key: semanticKey } : {}),
676
+ ...(reason ? { reason } : {}),
677
+ };
678
+ });
250
679
  }
251
680
  export function analyzeSemanticAdvisorInput(input) {
252
681
  const payload = input.payload;
253
682
  const requirement = isRequirement(payload);
683
+ const statement = statementOf(payload) || proseOf(payload);
254
684
  const signals = requirement ? detectSignals(proseOf(payload)) : [];
255
- const clauses = requirement
256
- ? extractSemanticClauses(statementOf(payload), input.clauses)
685
+ const clauses = statement
686
+ ? extractSemanticClauses(statement, input.clauses ?? semanticClausesOf(payload))
257
687
  : [];
258
688
  const rawDeclaredClaims = propertiesOf(payload).logic_claims;
259
689
  const declaredClaims = Array.isArray(rawDeclaredClaims)
260
690
  ? rawDeclaredClaims.filter((value) => typeof value === "string")
261
691
  : [];
262
692
  const expectedClaims = clauses
263
- .filter((clause) => clause.normative)
693
+ .filter((clause) => !["rationale", "example", "subjective"].includes(propositionRole(clause.text, clause.normative)))
264
694
  .map((clause) => clause.claim_key);
265
695
  const modeled = requirement &&
266
- isModeled(payload, expectedClaims.length) &&
696
+ isModeled(payload, expectedClaims) &&
267
697
  expectedClaims.length > 0 &&
268
698
  expectedClaims.every((claimKey) => declaredClaims.includes(claimKey));
269
- const suggestions = modelingSuggestions(payload, modeled, clauses);
270
- return buildAdvisorResult(payload, signals, modeled, suggestions, clauses);
699
+ const suggestions = modelingSuggestions(payload, modeled, clauses, input.interpretations);
700
+ const interpreted = interpretationResults(input.interpretations, clauses, statement);
701
+ const propositions = propositionInventory(statement, clauses, suggestions, interpreted.results, payloadHash(payload));
702
+ const shadow = shadowAnalysis(statement, interpreted.results);
703
+ const result = buildAdvisorResult(payload, signals, modeled, suggestions, clauses, propositions, interpreted.results, shadow);
704
+ return {
705
+ receipt: result.receipt,
706
+ warnings: [...result.warnings, ...interpreted.warnings],
707
+ };
271
708
  }
@@ -5,6 +5,7 @@ export type SemanticClause = Readonly<{
5
5
  normative: boolean;
6
6
  source: "detected" | "supplied";
7
7
  }>;
8
+ export declare function normalizeSemanticClause(value: string): string;
8
9
  export declare function semanticClaimKey(text: string): string;
9
10
  export declare function extractSemanticClauses(text: string, suppliedClauses?: readonly string[]): readonly SemanticClause[];
10
11
  //# sourceMappingURL=clauses.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"clauses.d.ts","sourceRoot":"","sources":["../../../src/operations/semantic-advisor/clauses.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,UAAU,GAAG,UAAU,CAAC;CACjC,CAAC,CAAC;AAkBH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIrD;AAeD,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,EACZ,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,GAClC,SAAS,cAAc,EAAE,CAgB3B"}
1
+ {"version":3,"file":"clauses.d.ts","sourceRoot":"","sources":["../../../src/operations/semantic-advisor/clauses.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,UAAU,GAAG,UAAU,CAAC;CACjC,CAAC,CAAC;AAKH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAW7D;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIrD;AAeD,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,EACZ,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,GAClC,SAAS,cAAc,EAAE,CAgB3B"}
@@ -1,6 +1,6 @@
1
1
  import { createHash } from "node:crypto";
2
2
  const NORMATIVE_PATTERN = /\b(?:must|shall|should|required|requires?|may\s+only|only\s+.+?\s+(?:may|can)|must\s+not|shall\s+not|cannot|can't|forbidden|denied|defaults?\s+to|before|unless|when|if)\b/i;
3
- function normalizeClause(value) {
3
+ export function normalizeSemanticClause(value) {
4
4
  return (value
5
5
  .replace(/^\s*(?:[-*+]\s+|\d+[.)]\s+)/, "")
6
6
  .replace(/\s+/g, " ")
@@ -11,7 +11,7 @@ function normalizeClause(value) {
11
11
  .trim());
12
12
  }
13
13
  export function semanticClaimKey(text) {
14
- const normalized = normalizeClause(text).toLowerCase();
14
+ const normalized = normalizeSemanticClause(text).toLowerCase();
15
15
  const digest = createHash("sha256").update(normalized).digest("hex");
16
16
  return `CLAIM-${digest.slice(0, 16).toUpperCase()}`;
17
17
  }
@@ -23,21 +23,21 @@ function detectedClauses(text) {
23
23
  return [sentence];
24
24
  return sentence.split(/\s+(?:,\s*)?and\s+(?=(?:the\s+)?[a-z][^.!?]{0,100}\b(?:must|shall|should|requires?|cannot|can't|expire|default|transition|states?\s+are)\b)/i);
25
25
  })
26
- .map(normalizeClause)
26
+ .map(normalizeSemanticClause)
27
27
  .filter(Boolean);
28
28
  }
29
29
  export function extractSemanticClauses(text, suppliedClauses) {
30
30
  const source = suppliedClauses === undefined ? "detected" : "supplied";
31
31
  const raw = suppliedClauses ?? detectedClauses(text);
32
- const unique = Array.from(new Set(raw.map(normalizeClause).filter(Boolean)));
33
- if (suppliedClauses !== undefined && unique.length === 0) {
32
+ const normalized = raw.map(normalizeSemanticClause).filter(Boolean);
33
+ if (suppliedClauses !== undefined && normalized.length === 0) {
34
34
  throw new Error("Semantic advisor clauses must contain at least one non-empty atomic claim");
35
35
  }
36
- return unique.map((clause, index) => ({
36
+ return normalized.map((clause, index) => ({
37
37
  claim_key: semanticClaimKey(clause),
38
38
  text: clause,
39
39
  index,
40
- normative: source === "supplied" || NORMATIVE_PATTERN.test(clause),
40
+ normative: NORMATIVE_PATTERN.test(clause),
41
41
  source,
42
42
  }));
43
43
  }
@@ -0,0 +1,18 @@
1
+ import type { PrologPort } from "../../public/operations/runtime-types.js";
2
+ import { type Payload } from "./shared.js";
3
+ import type { SemanticAdvisorReceipt } from "./types.js";
4
+ export interface SemanticInventoryBoundaryResult {
5
+ readonly applicable: boolean;
6
+ readonly errors: readonly string[];
7
+ readonly sourceHash: string;
8
+ }
9
+ type SemanticRelationship = Readonly<{
10
+ type?: unknown;
11
+ from?: unknown;
12
+ to?: unknown;
13
+ }>;
14
+ export declare function validateSemanticInventoryBoundary(payload: Payload, relationships: readonly SemanticRelationship[], receipt: SemanticAdvisorReceipt): SemanticInventoryBoundaryResult;
15
+ export declare function assertSemanticInventoryBoundary(payload: Payload, relationships: readonly SemanticRelationship[], receipt: SemanticAdvisorReceipt): void;
16
+ export declare function assertLogicalGroundingClaimKeys(prolog: PrologPort, payload: Payload, relationships: readonly SemanticRelationship[]): Promise<void>;
17
+ export {};
18
+ //# sourceMappingURL=ingestion-boundary.d.ts.map