kibi-cli 0.17.0 → 0.19.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 (241) hide show
  1. package/dist/cli-json-command.d.ts +1 -2
  2. package/dist/cli-json-command.d.ts.map +1 -1
  3. package/dist/cli-json-command.js +88 -44
  4. package/dist/cli-operation-loader.d.ts +3 -0
  5. package/dist/cli-operation-loader.d.ts.map +1 -0
  6. package/dist/cli-operation-loader.js +58 -0
  7. package/dist/cli-operation-metadata.d.ts +82 -0
  8. package/dist/cli-operation-metadata.d.ts.map +1 -0
  9. package/dist/cli-operation-metadata.js +106 -0
  10. package/dist/cli-protocol.d.ts +1 -1
  11. package/dist/cli-protocol.d.ts.map +1 -1
  12. package/dist/cli-protocol.js +4 -3
  13. package/dist/cli-register-foundation.d.ts.map +1 -1
  14. package/dist/cli-register-foundation.js +14 -17
  15. package/dist/cli-register-json.d.ts +3 -0
  16. package/dist/cli-register-json.d.ts.map +1 -0
  17. package/dist/cli-register-json.js +35 -0
  18. package/dist/cli-register-maintenance.d.ts.map +1 -1
  19. package/dist/cli-register-maintenance.js +41 -8
  20. package/dist/cli-register-reporting.d.ts.map +1 -1
  21. package/dist/cli-register-reporting.js +18 -14
  22. package/dist/cli-register-skills.d.ts.map +1 -1
  23. package/dist/cli-register-skills.js +8 -6
  24. package/dist/cli.d.ts.map +1 -1
  25. package/dist/cli.js +3 -2
  26. package/dist/commands/aggregated-checks.d.ts.map +1 -1
  27. package/dist/commands/aggregated-checks.js +1 -0
  28. package/dist/commands/check.d.ts.map +1 -1
  29. package/dist/commands/check.js +30 -12
  30. package/dist/commands/coverage.d.ts +5 -0
  31. package/dist/commands/coverage.d.ts.map +1 -1
  32. package/dist/commands/coverage.js +6 -1
  33. package/dist/commands/discovery-shared.d.ts +2 -1
  34. package/dist/commands/discovery-shared.d.ts.map +1 -1
  35. package/dist/commands/discovery-shared.js +35 -13
  36. package/dist/commands/discovery-table.d.ts.map +1 -1
  37. package/dist/commands/discovery-table.js +96 -5
  38. package/dist/commands/engine.d.ts +8 -0
  39. package/dist/commands/engine.d.ts.map +1 -0
  40. package/dist/commands/engine.js +100 -0
  41. package/dist/commands/gaps.js +1 -1
  42. package/dist/commands/graph.js +1 -1
  43. package/dist/commands/query.d.ts.map +1 -1
  44. package/dist/commands/query.js +3 -1
  45. package/dist/commands/search.d.ts.map +1 -1
  46. package/dist/commands/search.js +3 -1
  47. package/dist/commands/status.d.ts.map +1 -1
  48. package/dist/commands/status.js +2 -1
  49. package/dist/commands/sync/cache.d.ts +12 -0
  50. package/dist/commands/sync/cache.d.ts.map +1 -1
  51. package/dist/commands/sync/cache.js +38 -1
  52. package/dist/commands/sync/persistence.d.ts +10 -1
  53. package/dist/commands/sync/persistence.d.ts.map +1 -1
  54. package/dist/commands/sync/persistence.js +276 -43
  55. package/dist/commands/sync/staging.d.ts +10 -1
  56. package/dist/commands/sync/staging.d.ts.map +1 -1
  57. package/dist/commands/sync/staging.js +84 -1
  58. package/dist/commands/sync.d.ts.map +1 -1
  59. package/dist/commands/sync.js +521 -27
  60. package/dist/commands/usage-metrics.d.ts +66 -2
  61. package/dist/commands/usage-metrics.d.ts.map +1 -1
  62. package/dist/commands/usage-metrics.js +34 -24
  63. package/dist/commands/usage-remediation.d.ts +9 -0
  64. package/dist/commands/usage-remediation.d.ts.map +1 -0
  65. package/dist/commands/usage-remediation.js +52 -0
  66. package/dist/engine-daemon.d.ts +3 -0
  67. package/dist/engine-daemon.d.ts.map +1 -0
  68. package/dist/engine-daemon.js +34 -0
  69. package/dist/engine.d.ts +63 -0
  70. package/dist/engine.d.ts.map +1 -0
  71. package/dist/engine.js +1256 -0
  72. package/dist/extractors/markdown.d.ts +8 -0
  73. package/dist/extractors/markdown.d.ts.map +1 -1
  74. package/dist/extractors/markdown.js +69 -2
  75. package/dist/extractors/relationships.d.ts +2 -0
  76. package/dist/extractors/relationships.d.ts.map +1 -1
  77. package/dist/extractors/relationships.js +15 -17
  78. package/dist/operations/modeling/logic-modeling.d.ts.map +1 -1
  79. package/dist/operations/modeling/logic-modeling.js +14 -5
  80. package/dist/operations/modeling/model-requirement.d.ts.map +1 -1
  81. package/dist/operations/modeling/model-requirement.js +27 -2
  82. package/dist/operations/modeling/predicate-applyplan.d.ts +1 -1
  83. package/dist/operations/modeling/predicate-applyplan.d.ts.map +1 -1
  84. package/dist/operations/modeling/predicate-applyplan.js +18 -6
  85. package/dist/operations/modeling/predicate-inference.d.ts.map +1 -1
  86. package/dist/operations/modeling/predicate-inference.js +5 -17
  87. package/dist/operations/modeling/predicate-loader.js +1 -1
  88. package/dist/operations/modeling/predicate-types.d.ts +9 -1
  89. package/dist/operations/modeling/predicate-types.d.ts.map +1 -1
  90. package/dist/operations/modeling/suggest-predicates.d.ts.map +1 -1
  91. package/dist/operations/modeling/suggest-predicates.js +35 -11
  92. package/dist/operations/mutation/audit.js +1 -1
  93. package/dist/operations/mutation/contradictions.d.ts +1 -1
  94. package/dist/operations/mutation/contradictions.d.ts.map +1 -1
  95. package/dist/operations/mutation/contradictions.js +23 -18
  96. package/dist/operations/mutation/serialization.d.ts.map +1 -1
  97. package/dist/operations/mutation/serialization.js +6 -3
  98. package/dist/operations/mutation/upsert.d.ts +3 -1
  99. package/dist/operations/mutation/upsert.d.ts.map +1 -1
  100. package/dist/operations/mutation/upsert.js +51 -12
  101. package/dist/operations/mutation/validate-upsert.d.ts.map +1 -1
  102. package/dist/operations/mutation/validate-upsert.js +18 -2
  103. package/dist/operations/mutation/validation.d.ts.map +1 -1
  104. package/dist/operations/mutation/validation.js +8 -0
  105. package/dist/operations/semantic-advisor/analysis-receipt.d.ts.map +1 -1
  106. package/dist/operations/semantic-advisor/analysis-receipt.js +7 -1
  107. package/dist/operations/semantic-advisor/analyze-prose.d.ts.map +1 -1
  108. package/dist/operations/semantic-advisor/analyze-prose.js +76 -61
  109. package/dist/operations/semantic-advisor/clauses.d.ts +1 -0
  110. package/dist/operations/semantic-advisor/clauses.d.ts.map +1 -1
  111. package/dist/operations/semantic-advisor/clauses.js +7 -7
  112. package/dist/operations/semantic-advisor/ingestion-boundary.d.ts +18 -0
  113. package/dist/operations/semantic-advisor/ingestion-boundary.d.ts.map +1 -0
  114. package/dist/operations/semantic-advisor/ingestion-boundary.js +167 -0
  115. package/dist/operations/semantic-advisor/shared.d.ts +8 -0
  116. package/dist/operations/semantic-advisor/shared.d.ts.map +1 -1
  117. package/dist/operations/semantic-advisor/shared.js +37 -3
  118. package/dist/operations/semantic-advisor/types.d.ts +5 -0
  119. package/dist/operations/semantic-advisor/types.d.ts.map +1 -1
  120. package/dist/prolog/codec.d.ts.map +1 -1
  121. package/dist/prolog/codec.js +9 -2
  122. package/dist/prolog.d.ts +14 -0
  123. package/dist/prolog.d.ts.map +1 -1
  124. package/dist/prolog.js +279 -69
  125. package/dist/public/diagnostic-usage.d.ts +17 -0
  126. package/dist/public/diagnostic-usage.d.ts.map +1 -0
  127. package/dist/public/diagnostic-usage.js +152 -0
  128. package/dist/public/distribution-parity.d.ts +90 -0
  129. package/dist/public/distribution-parity.d.ts.map +1 -0
  130. package/dist/public/distribution-parity.js +367 -0
  131. package/dist/public/impact/full-kb-quality.d.ts +2 -0
  132. package/dist/public/impact/full-kb-quality.d.ts.map +1 -1
  133. package/dist/public/impact/full-kb-quality.js +53 -1
  134. package/dist/public/impact-diagnostics.d.ts +2 -0
  135. package/dist/public/impact-diagnostics.d.ts.map +1 -1
  136. package/dist/public/impact-diagnostics.js +1 -0
  137. package/dist/public/operations/catalog.d.ts +151 -6
  138. package/dist/public/operations/catalog.d.ts.map +1 -1
  139. package/dist/public/operations/check-executor.d.ts.map +1 -1
  140. package/dist/public/operations/check-executor.js +4 -0
  141. package/dist/public/operations/discovery-entities.d.ts.map +1 -1
  142. package/dist/public/operations/discovery-entities.js +3 -2
  143. package/dist/public/operations/discovery-executors.d.ts +6 -0
  144. package/dist/public/operations/discovery-executors.d.ts.map +1 -1
  145. package/dist/public/operations/discovery-executors.js +58 -5
  146. package/dist/public/operations/index.d.ts +4 -0
  147. package/dist/public/operations/index.d.ts.map +1 -1
  148. package/dist/public/operations/index.js +4 -0
  149. package/dist/public/operations/legacy-migration-plan.d.ts +113 -0
  150. package/dist/public/operations/legacy-migration-plan.d.ts.map +1 -0
  151. package/dist/public/operations/legacy-migration-plan.js +409 -0
  152. package/dist/public/operations/node-ports.d.ts.map +1 -1
  153. package/dist/public/operations/node-ports.js +90 -0
  154. package/dist/public/operations/prolog-json.d.ts.map +1 -1
  155. package/dist/public/operations/prolog-json.js +14 -4
  156. package/dist/public/operations/repair-plan.d.ts +184 -0
  157. package/dist/public/operations/repair-plan.d.ts.map +1 -0
  158. package/dist/public/operations/repair-plan.js +397 -0
  159. package/dist/public/operations/runtime-types.d.ts +38 -0
  160. package/dist/public/operations/runtime-types.d.ts.map +1 -1
  161. package/dist/public/operations/specs/check.d.ts +2 -2
  162. package/dist/public/operations/specs/check.js +2 -2
  163. package/dist/public/operations/specs/discovery.d.ts +1 -1
  164. package/dist/public/operations/specs/discovery.js +1 -1
  165. package/dist/public/operations/specs/modeling.d.ts +19 -1
  166. package/dist/public/operations/specs/modeling.d.ts.map +1 -1
  167. package/dist/public/operations/specs/modeling.js +16 -1
  168. package/dist/public/operations/specs/mutation-schemas.d.ts +96 -1
  169. package/dist/public/operations/specs/mutation-schemas.d.ts.map +1 -1
  170. package/dist/public/operations/specs/mutation-schemas.js +40 -1
  171. package/dist/public/operations/specs/reporting.d.ts +42 -1
  172. package/dist/public/operations/specs/reporting.d.ts.map +1 -1
  173. package/dist/public/operations/specs/reporting.js +70 -6
  174. package/dist/public/operations/specs/semantic.js +1 -1
  175. package/dist/public/operations/specs/upsert.d.ts +96 -1
  176. package/dist/public/operations/specs/upsert.d.ts.map +1 -1
  177. package/dist/public/operations/workspace-snapshot.d.ts +10 -0
  178. package/dist/public/operations/workspace-snapshot.d.ts.map +1 -0
  179. package/dist/public/operations/workspace-snapshot.js +20 -0
  180. package/dist/public/schemas/entity.d.ts.map +1 -1
  181. package/dist/public/schemas/entity.js +43 -1
  182. package/dist/public/skills/init-kibi/SKILL.md +2 -2
  183. package/dist/public/skills/kibi-freshness/SKILL.md +2 -2
  184. package/dist/public/skills/kibi-traceability/SKILL.md +8 -2
  185. package/dist/public/skills/kibi-usage/SKILL.md +12 -6
  186. package/dist/public/skills/kibi-usage/resources/fact-lanes.md +1 -1
  187. package/dist/public/skills/kibi-usage/resources/logic-ir.md +1 -1
  188. package/dist/public/skills/kibi-usage/resources/operation-access.md +1 -1
  189. package/dist/public/skills/kibi-usage/resources/workflows.md +19 -2
  190. package/dist/public/telemetry-acceptance.d.ts +89 -0
  191. package/dist/public/telemetry-acceptance.d.ts.map +1 -0
  192. package/dist/public/telemetry-acceptance.js +597 -0
  193. package/dist/public/telemetry-remediation.d.ts +33 -0
  194. package/dist/public/telemetry-remediation.d.ts.map +1 -0
  195. package/dist/public/telemetry-remediation.js +257 -0
  196. package/dist/public/verification-receipt.d.ts +75 -0
  197. package/dist/public/verification-receipt.d.ts.map +1 -0
  198. package/dist/public/verification-receipt.js +129 -0
  199. package/dist/runtime/cli-runtime.d.ts.map +1 -1
  200. package/dist/runtime/cli-runtime.js +33 -37
  201. package/dist/schemas/entity.schema.json +96 -2
  202. package/dist/traceability/temp-kb.d.ts.map +1 -1
  203. package/dist/traceability/temp-kb.js +36 -3
  204. package/dist/types/entities.d.ts +1 -0
  205. package/dist/types/entities.d.ts.map +1 -1
  206. package/dist/utils/rule-registry.d.ts +2 -0
  207. package/dist/utils/rule-registry.d.ts.map +1 -1
  208. package/package.json +36 -4
  209. package/src/public/diagnostic-usage.ts +206 -0
  210. package/src/public/distribution-parity.ts +580 -0
  211. package/src/public/impact/full-kb-quality.ts +74 -1
  212. package/src/public/impact-diagnostics.ts +16 -0
  213. package/src/public/operations/check-executor.ts +4 -0
  214. package/src/public/operations/discovery-entities.ts +3 -2
  215. package/src/public/operations/discovery-executors.ts +68 -5
  216. package/src/public/operations/index.ts +4 -0
  217. package/src/public/operations/legacy-migration-plan.ts +688 -0
  218. package/src/public/operations/node-ports.ts +109 -0
  219. package/src/public/operations/prolog-json.ts +15 -3
  220. package/src/public/operations/repair-plan.ts +562 -0
  221. package/src/public/operations/runtime-types.ts +47 -0
  222. package/src/public/operations/specs/check.ts +2 -2
  223. package/src/public/operations/specs/discovery.ts +1 -1
  224. package/src/public/operations/specs/modeling.ts +19 -1
  225. package/src/public/operations/specs/mutation-schemas.ts +47 -1
  226. package/src/public/operations/specs/reporting.ts +91 -6
  227. package/src/public/operations/specs/semantic.ts +1 -1
  228. package/src/public/operations/workspace-snapshot.ts +28 -0
  229. package/src/public/schemas/entity.ts +44 -1
  230. package/src/public/skills/init-kibi/SKILL.md +2 -2
  231. package/src/public/skills/kibi-freshness/SKILL.md +2 -2
  232. package/src/public/skills/kibi-traceability/SKILL.md +8 -2
  233. package/src/public/skills/kibi-usage/SKILL.md +12 -6
  234. package/src/public/skills/kibi-usage/resources/fact-lanes.md +1 -1
  235. package/src/public/skills/kibi-usage/resources/logic-ir.md +1 -1
  236. package/src/public/skills/kibi-usage/resources/operation-access.md +1 -1
  237. package/src/public/skills/kibi-usage/resources/workflows.md +19 -2
  238. package/src/public/telemetry-acceptance.ts +859 -0
  239. package/src/public/telemetry-remediation.ts +462 -0
  240. package/src/public/verification-receipt.ts +170 -0
  241. package/src/schemas/entity.schema.json +96 -2
@@ -2,39 +2,44 @@ import { escapeAtom } from "../../prolog/codec.js";
2
2
  import { formatInvalidRelationshipError } from "./relationships.js";
3
3
  import { buildPropertyList, buildRelationshipMetadata, } from "./serialization.js";
4
4
  // implements REQ-kibi-operation-interface-parity
5
- export function buildUpsertTransaction(input) {
6
- const id = String(input.entity.id);
5
+ export function buildUpsertCommitGoal(input) {
7
6
  const type = String(input.entity.type);
8
- const goals = [
9
- `kb_assert_entity_no_audit(${type}, ${buildPropertyList(input.entity)})`,
10
- ...input.relationships.map((relationship) => `kb_assert_relationship_no_audit(${String(relationship.type)}, '${escapeAtom(String(relationship.from))}', '${escapeAtom(String(relationship.to))}', ${buildRelationshipMetadata(relationship)})`),
11
- ];
12
- if (type === "req" && !input.skipContradictionCheck) {
13
- goals.push(`check_req_contradiction('${escapeAtom(id)}')`);
14
- }
15
- return `rdf_transaction((${goals.join(", ")}))`;
7
+ const relationships = input.relationships.map((relationship) => `rel(${String(relationship.type)}, '${escapeAtom(String(relationship.from))}', '${escapeAtom(String(relationship.to))}', ${buildRelationshipMetadata(relationship)})`);
8
+ return `kb_commit_upsert(${type}, ${buildPropertyList(input.entity)}, [${relationships.join(", ")}], ${input.skipContradictionCheck ? "true" : "false"}, ChangeKind)`;
16
9
  }
17
10
  // implements REQ-kibi-operation-interface-parity
18
11
  export function formatUpsertError(entityId, raw) {
19
12
  if (!raw)
20
13
  return `Failed to upsert entity ${entityId}: Unknown error`;
21
- const invalidRelationship = formatInvalidRelationshipError(raw);
14
+ const stage = raw.match(/\(stage=([^)]+)\)/)?.[1];
15
+ const stageSuffix = stage === undefined ? "" : ` (stage=${stage})`;
16
+ const diagnosticFree = raw.replace(/^__KIBI_(?:STAGE|RUNTIME)__:[^\r\n]*\r?\n?/gm, "");
17
+ if (diagnosticFree.includes("stale_snapshot")) {
18
+ return `Failed to upsert entity ${entityId}: KB snapshot is stale; reattach or refresh the runtime before retrying (stale_snapshot)${stageSuffix}`;
19
+ }
20
+ if (diagnosticFree.includes("Audit journal is locked") ||
21
+ diagnosticFree.includes("audit_log") ||
22
+ diagnosticFree.includes("audit.log") ||
23
+ diagnosticFree.includes("Resource temporarily unavailable")) {
24
+ return `Failed to upsert entity ${entityId}: Audit journal is locked by another Kibi runtime; restart the stale MCP/CLI session before retrying${stageSuffix}`;
25
+ }
26
+ const invalidRelationship = formatInvalidRelationshipError(diagnosticFree);
22
27
  if (invalidRelationship !== null) {
23
- return `Failed to upsert entity ${entityId}: ${invalidRelationship}`;
28
+ return `Failed to upsert entity ${entityId}: ${invalidRelationship}${stageSuffix}`;
24
29
  }
25
- const contradiction = raw.match(/kb_contradiction\(\s*\[([^\]]+)\]\s*\)/);
30
+ const contradiction = diagnosticFree.match(/kb_contradiction\(\s*\[([^\]]+)\]\s*\)/);
26
31
  if (contradiction) {
27
32
  const details = contradiction[1] ?? "";
28
33
  const conflicts = [
29
34
  ...details.matchAll(/(?:'([^']+)'|"([^"\\]*(?:\\.[^"\\]*)*)")-'([^']+)'/g),
30
35
  ].map((match) => ` - Conflicts with ${String(match[3])}: ${String(match[1] ?? match[2])}`);
31
36
  if (conflicts.length > 0) {
32
- return `Contradiction detected for requirement ${entityId}:\n${[...new Set(conflicts)].join("\n")}\n\nTo resolve:\n 1. Add a supersedes relationship from the new requirement to the conflicting one, OR\n 2. Deprecate the conflicting requirement before creating the new one.`;
37
+ return `Contradiction detected for requirement ${entityId}:\n${[...new Set(conflicts)].join("\n")}\n\nTo resolve:\n 1. Add a supersedes relationship from the new requirement to the conflicting one, OR\n 2. Deprecate the conflicting requirement before creating the new one.${stageSuffix}`;
33
38
  }
34
- return `Contradiction detected for entity ${entityId}: This requirement conflicts with existing requirements. Add a supersedes relationship to the conflicting requirement, or deprecate the old requirement before creating the new one.`;
39
+ return `Contradiction detected for entity ${entityId}: This requirement conflicts with existing requirements. Add a supersedes relationship to the conflicting requirement, or deprecate the old requirement before creating the new one.${stageSuffix}`;
35
40
  }
36
- if (raw.includes("rdf_transaction")) {
37
- return `Failed to upsert entity ${entityId}: Transaction failed`;
41
+ if (diagnosticFree.includes("rdf_transaction")) {
42
+ return `Failed to upsert entity ${entityId}: Transaction failed${stageSuffix}`;
38
43
  }
39
- return `Failed to upsert entity ${entityId}: ${raw}`;
44
+ return `Failed to upsert entity ${entityId}: ${diagnosticFree || raw}`;
40
45
  }
@@ -1 +1 @@
1
- {"version":3,"file":"serialization.d.ts","sourceRoot":"","sources":["../../../src/operations/mutation/serialization.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AA6CpD,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACxC,MAAM,CAMR;AAGD,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,iBAAiB,GAAG,MAAM,CAOxE;AAGD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAkBtD"}
1
+ {"version":3,"file":"serialization.d.ts","sourceRoot":"","sources":["../../../src/operations/mutation/serialization.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAkDpD,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACxC,MAAM,CAMR;AAGD,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,iBAAiB,GAAG,MAAM,CAOxE;AAGD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAkBtD"}
@@ -20,16 +20,19 @@ const STRING_FIELDS = [
20
20
  "updated_at",
21
21
  "source",
22
22
  "text_ref",
23
+ "semantic_text",
23
24
  ];
24
25
  function serializeValue(key, value) {
25
26
  if (key === "id" && typeof value === "string") {
26
27
  return `'${value.replaceAll("'", "''")}'`;
27
28
  }
28
- if (Array.isArray(value))
29
- return JSON.stringify(value);
30
- if (key === "rule_ir" || key === "semantic_inventory") {
29
+ if (key === "rule_ir" ||
30
+ key === "semantic_inventory" ||
31
+ key === "verification_receipts") {
31
32
  return toPrologString(JSON.stringify(value));
32
33
  }
34
+ if (Array.isArray(value))
35
+ return JSON.stringify(value);
33
36
  if (typeof value === "string") {
34
37
  return ATOM_FIELDS.includes(key)
35
38
  ? toPrologAtom(value)
@@ -1,5 +1,7 @@
1
1
  import type { OperationContext } from "../../public/operations/runtime-types.js";
2
2
  import type { OperationResult } from "../../public/operations/types.js";
3
- import type { UpsertInput, UpsertPayload } from "./types.js";
3
+ import type { RelationshipInput, UpsertInput, UpsertPayload } from "./types.js";
4
+ export declare function validateAppendOnlyVerificationReceipts(entity: Readonly<Record<string, unknown>>, context: OperationContext): Promise<void>;
5
+ export declare function effectiveRelationships(input: UpsertInput, entity: Readonly<Record<string, unknown>>, relationships: readonly RelationshipInput[], context: OperationContext): Promise<readonly RelationshipInput[]>;
4
6
  export declare function executeUpsert(input: UpsertInput, context: OperationContext): Promise<OperationResult<UpsertPayload>>;
5
7
  //# sourceMappingURL=upsert.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"upsert.d.ts","sourceRoot":"","sources":["../../../src/operations/mutation/upsert.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AACjF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAaxE,OAAO,KAAK,EAAqB,WAAW,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAkChF,wBAAsB,aAAa,CACjC,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC,CA0FzC"}
1
+ {"version":3,"file":"upsert.d.ts","sourceRoot":"","sources":["../../../src/operations/mutation/upsert.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AACjF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAgBxE,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AA8BhF,wBAAsB,sCAAsC,CAC1D,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACzC,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,IAAI,CAAC,CAaf;AAED,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,WAAW,EAClB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACzC,aAAa,EAAE,SAAS,iBAAiB,EAAE,EAC3C,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,SAAS,iBAAiB,EAAE,CAAC,CAgBvC;AAED,wBAAsB,aAAa,CACjC,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC,CAuGzC"}
@@ -1,9 +1,10 @@
1
1
  import { escapeAtom } from "../../prolog/codec.js";
2
+ import { loadEntities } from "../../public/operations/discovery-entities.js";
3
+ import { appendOnlyVerificationReceiptHistoryErrors } from "../../public/verification-receipt.js";
2
4
  import { analyzeSemanticAdvisorInput } from "../semantic-advisor/analyze-prose.js";
3
- import { recordEntityAudit, recordRelationshipAudits } from "./audit.js";
4
- import { buildUpsertTransaction, formatUpsertError } from "./contradictions.js";
5
+ import { assertLogicalGroundingClaimKeys, assertSemanticInventoryBoundary, } from "../semantic-advisor/ingestion-boundary.js";
6
+ import { buildUpsertCommitGoal, formatUpsertError } from "./contradictions.js";
5
7
  import { existingRelationships, validateLiveRelationshipTargets, validateRelationshipSources, validateStrictLanePairing, } from "./relationships.js";
6
- import { saveMutation } from "./save.js";
7
8
  import { validateSymbolGranularity } from "./symbol-granularity.js";
8
9
  import { refreshSymbolCoordinates } from "./symbol-refresh.js";
9
10
  import { validateUpsertInput } from "./validation.js";
@@ -14,7 +15,36 @@ function requireProlog(context) {
14
15
  }
15
16
  return context.prolog;
16
17
  }
17
- async function effectiveRelationships(input, entity, relationships, context) {
18
+ function receiptRecords(value) {
19
+ if (!Array.isArray(value))
20
+ return undefined;
21
+ return value.filter((receipt) => receipt !== null &&
22
+ typeof receipt === "object" &&
23
+ !Array.isArray(receipt));
24
+ }
25
+ function parseChangeKind(value) {
26
+ const normalized = value?.trim().replace(/^['"]|['"]$/g, "");
27
+ return normalized === "created" || normalized === "updated"
28
+ ? normalized
29
+ : null;
30
+ }
31
+ export async function validateAppendOnlyVerificationReceipts(entity, context) {
32
+ if (entity.type !== "test")
33
+ return;
34
+ const existing = await loadEntities(requireProlog(context), {
35
+ id: String(entity.id),
36
+ type: "test",
37
+ });
38
+ const previous = receiptRecords(existing[0]?.verification_receipts);
39
+ if (!previous || previous.length === 0)
40
+ return;
41
+ const next = receiptRecords(entity.verification_receipts);
42
+ const errors = appendOnlyVerificationReceiptHistoryErrors(previous, next);
43
+ if (errors.length > 0) {
44
+ throw new Error(`Entity validation failed: ${errors.join("; ")}`);
45
+ }
46
+ }
47
+ export async function effectiveRelationships(input, entity, relationships, context) {
18
48
  if (input.relationships !== undefined && input.relationships.length > 0) {
19
49
  return relationships;
20
50
  }
@@ -36,13 +66,18 @@ export async function executeUpsert(input, context) {
36
66
  const prolog = requireProlog(context);
37
67
  try {
38
68
  const validated = validateUpsertInput(input, context.clock());
69
+ await validateAppendOnlyVerificationReceipts(validated.entity, context);
39
70
  validateRelationshipSources(input.id, validated.relationships);
40
71
  await validateSymbolGranularity(validated.entity, validated.relationships, context);
41
72
  const relationships = await effectiveRelationships(input, validated.entity, validated.relationships, context);
42
73
  await validateStrictLanePairing(prolog, relationships);
43
74
  await validateLiveRelationshipTargets(prolog, validated.entity, relationships);
44
- const exists = await prolog.query(`once(kb_entity('${escapeAtom(input.id)}', _, _))`);
45
- const transaction = buildUpsertTransaction({
75
+ const semantic = analyzeSemanticAdvisorInput({
76
+ payload: { ...input, relationships },
77
+ });
78
+ assertSemanticInventoryBoundary({ ...input, relationships }, relationships, semantic.receipt);
79
+ await assertLogicalGroundingClaimKeys(prolog, { ...input, relationships }, relationships);
80
+ const transaction = buildUpsertCommitGoal({
46
81
  entity: validated.entity,
47
82
  relationships,
48
83
  skipContradictionCheck: input._skipContradictionCheck === true,
@@ -51,9 +86,14 @@ export async function executeUpsert(input, context) {
51
86
  if (!written.success) {
52
87
  throw new Error(formatUpsertError(input.id, written.error));
53
88
  }
54
- await recordEntityAudit(prolog, exists.success ? "updated" : "created", validated.entity);
55
- await recordRelationshipAudits(prolog, relationships);
56
- await saveMutation(prolog);
89
+ // The combined commit is the sole mutation boundary. Invalidate reads only
90
+ // after Prolog reports success so a failed/rolled-back commit does not
91
+ // disturb callers' view of the current snapshot.
92
+ prolog.invalidateCache?.();
93
+ const changeKind = parseChangeKind(written.bindings.ChangeKind);
94
+ if (changeKind === null) {
95
+ throw new Error(`Upsert commit completed without a created/updated result for ${input.id}`);
96
+ }
57
97
  if (input.type === "symbol") {
58
98
  try {
59
99
  await refreshSymbolCoordinates(input.id, context);
@@ -63,12 +103,11 @@ export async function executeUpsert(input, context) {
63
103
  throw error;
64
104
  }
65
105
  }
66
- const semantic = analyzeSemanticAdvisorInput({ payload: { ...input } });
67
106
  const coverage = await scenarioCoverageWarnings(prolog, validated.relationships, input.type, input.id);
68
- const created = exists.success ? 0 : 1;
107
+ const created = changeKind === "created" ? 1 : 0;
69
108
  const payload = {
70
109
  created,
71
- updated: exists.success ? 1 : 0,
110
+ updated: changeKind === "updated" ? 1 : 0,
72
111
  relationships_created: relationships.length,
73
112
  warnings: [...semantic.warnings, ...coverage],
74
113
  semanticAdvisor: semantic.receipt,
@@ -1 +1 @@
1
- {"version":3,"file":"validate-upsert.d.ts","sourceRoot":"","sources":["../../../src/operations/mutation/validate-upsert.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AACjF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAOxE,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAGrE,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,eAAe,CAAC,qBAAqB,CAAC,CAAC,CAoDjD"}
1
+ {"version":3,"file":"validate-upsert.d.ts","sourceRoot":"","sources":["../../../src/operations/mutation/validate-upsert.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AACjF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAYxE,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAOrE,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,eAAe,CAAC,qBAAqB,CAAC,CAAC,CAoFjD"}
@@ -1,16 +1,32 @@
1
1
  import { analyzeSemanticAdvisorInput } from "../semantic-advisor/analyze-prose.js";
2
+ import { assertLogicalGroundingClaimKeys, assertSemanticInventoryBoundary, validateSemanticInventoryBoundary, } from "../semantic-advisor/ingestion-boundary.js";
2
3
  import { validateLiveRelationshipTargets, validateRelationshipSources, } from "./relationships.js";
3
4
  import { validateSymbolGranularity } from "./symbol-granularity.js";
5
+ import { effectiveRelationships, validateAppendOnlyVerificationReceipts, } from "./upsert.js";
4
6
  import { validateUpsertInput } from "./validation.js";
5
7
  export async function executeValidateUpsert(input, context) {
6
8
  try {
7
9
  const validated = validateUpsertInput(input, context.clock());
10
+ await validateAppendOnlyVerificationReceipts(validated.entity, context);
8
11
  validateRelationshipSources(input.id, validated.relationships);
9
12
  await validateSymbolGranularity(validated.entity, validated.relationships, context);
13
+ const previewSemantic = analyzeSemanticAdvisorInput({
14
+ payload: { ...input, relationships: validated.relationships },
15
+ });
16
+ const previewBoundary = validateSemanticInventoryBoundary({ ...input, relationships: validated.relationships }, validated.relationships, previewSemantic.receipt);
17
+ const relationships = context.prolog === undefined || !previewBoundary.applicable
18
+ ? validated.relationships
19
+ : await effectiveRelationships(input, validated.entity, validated.relationships, context);
10
20
  if (context.prolog !== undefined) {
11
- await validateLiveRelationshipTargets(context.prolog, validated.entity, validated.relationships);
21
+ await validateLiveRelationshipTargets(context.prolog, validated.entity, relationships);
22
+ }
23
+ const semantic = analyzeSemanticAdvisorInput({
24
+ payload: { ...input, relationships },
25
+ });
26
+ assertSemanticInventoryBoundary({ ...input, relationships }, relationships, semantic.receipt);
27
+ if (context.prolog !== undefined) {
28
+ await assertLogicalGroundingClaimKeys(context.prolog, { ...input, relationships }, relationships);
12
29
  }
13
- const semantic = analyzeSemanticAdvisorInput({ payload: { ...input } });
14
30
  const payload = {
15
31
  valid: true,
16
32
  errors: [],
@@ -1 +1 @@
1
- {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../../src/operations/mutation/validation.ts"],"names":[],"mappings":"AAIA,OAAO,EAEL,0BAA0B,EAC3B,MAAM,oCAAoC,CAAC;AAO5C,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAiF/D,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,WAAW,EAClB,GAAG,EAAE,IAAI,GACR,eAAe,CA0CjB;AAED,OAAO,EAAE,0BAA0B,EAAE,CAAC"}
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../../src/operations/mutation/validation.ts"],"names":[],"mappings":"AAIA,OAAO,EAEL,0BAA0B,EAC3B,MAAM,oCAAoC,CAAC;AAQ5C,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAiF/D,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,WAAW,EAClB,GAAG,EAAE,IAAI,GACR,eAAe,CAwDjB;AAED,OAAO,EAAE,0BAA0B,EAAE,CAAC"}
@@ -3,6 +3,7 @@ import entitySchema from "../../public/schemas/entity.js";
3
3
  import relationshipSchema from "../../public/schemas/relationship.js";
4
4
  // implements REQ-kibi-operation-interface-parity
5
5
  import { SYMBOL_ROLES, isAllowedGranularityReason, } from "../../public/symbol-granularity.js";
6
+ import { verificationReceiptHistoryErrors } from "../../public/verification-receipt.js";
6
7
  import { semanticClaimKey } from "../semantic-advisor/clauses.js";
7
8
  import { factKindShapeHints, validateFactModelingShape, valueFieldHint, } from "./strict-fact.js";
8
9
  const ajv = new Ajv({ strict: false });
@@ -84,6 +85,13 @@ export function validateUpsertInput(input, now) {
84
85
  if (!validateEntity(entity)) {
85
86
  throw new Error(`Entity validation failed: ${formatEntityErrors(entity, validateEntity.errors ?? [])}`);
86
87
  }
88
+ if (entity.type === "test" && Array.isArray(entity.verification_receipts)) {
89
+ const receipts = entity.verification_receipts.filter((value) => typeof value === "object" && value !== null && !Array.isArray(value));
90
+ const receiptErrors = verificationReceiptHistoryErrors(input.id, entity.verification_scope, receipts);
91
+ if (receiptErrors.length > 0) {
92
+ throw new Error(`Entity validation failed: ${receiptErrors.join("; ")}`);
93
+ }
94
+ }
87
95
  validateFactModelingShape(entity);
88
96
  if (entity.type === "fact" &&
89
97
  typeof entity.claim_key === "string" &&
@@ -1 +1 @@
1
- {"version":3,"file":"analysis-receipt.d.ts","sourceRoot":"","sources":["../../../src/operations/semantic-advisor/analysis-receipt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,KAAK,OAAO,EAA6B,MAAM,aAAa,CAAC;AACtE,OAAO,KAAK,EACV,6BAA6B,EAI7B,4BAA4B,EAC5B,0BAA0B,EAC1B,mBAAmB,EACnB,iBAAiB,EACjB,cAAc,EACf,MAAM,YAAY,CAAC;AA0CpB,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,SAAS,cAAc,EAAE,EAClC,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,SAAS,0BAA0B,EAAE,EAClD,OAAO,EAAE,SAAS,cAAc,EAAE,EAClC,YAAY,EAAE,SAAS,mBAAmB,EAAE,EAC5C,eAAe,EAAE,SAAS,4BAA4B,EAAE,EACxD,cAAc,EAAE,SAAS,iBAAiB,EAAE,GAC3C,6BAA6B,CA4G/B"}
1
+ {"version":3,"file":"analysis-receipt.d.ts","sourceRoot":"","sources":["../../../src/operations/semantic-advisor/analysis-receipt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EACL,KAAK,OAAO,EAMb,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EACV,6BAA6B,EAI7B,4BAA4B,EAC5B,0BAA0B,EAC1B,mBAAmB,EACnB,iBAAiB,EACjB,cAAc,EACf,MAAM,YAAY,CAAC;AA0CpB,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,SAAS,cAAc,EAAE,EAClC,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,SAAS,0BAA0B,EAAE,EAClD,OAAO,EAAE,SAAS,cAAc,EAAE,EAClC,YAAY,EAAE,SAAS,mBAAmB,EAAE,EAC5C,eAAe,EAAE,SAAS,4BAA4B,EAAE,EACxD,cAAc,EAAE,SAAS,iBAAiB,EAAE,GAC3C,6BAA6B,CAkH/B"}
@@ -1,4 +1,4 @@
1
- import { payloadHash, propertiesOf } from "./shared.js";
1
+ import { SEMANTIC_INVENTORY_VERSION, payloadHash, propertiesOf, semanticSourceHash, semanticSourceOf, } from "./shared.js";
2
2
  function chooseLane(signals) {
3
3
  if (signals.some(({ kind }) => kind === "numeric_cardinality" || kind === "numeric_threshold"))
4
4
  return "strict_property";
@@ -25,6 +25,7 @@ function summary(readiness, lane) {
25
25
  }
26
26
  // implements REQ-mcp-semantic-advisor-preflight
27
27
  export function buildAdvisorResult(payload, signals, modeled, suggestions, clauses, propositions, interpretations, shadowAnalysis) {
28
+ const semanticSource = semanticSourceOf(payload);
28
29
  const suggestionLane = suggestions.some(({ kind }) => kind === "strict_property")
29
30
  ? "strict_property"
30
31
  : suggestions.some(({ kind }) => kind === "rule")
@@ -72,6 +73,11 @@ export function buildAdvisorResult(payload, signals, modeled, suggestions, claus
72
73
  const receipt = {
73
74
  version: "semantic-advisor-v2",
74
75
  payload_hash: payloadHash(payload),
76
+ inventory_contract: {
77
+ version: SEMANTIC_INVENTORY_VERSION,
78
+ source_field: semanticSource.field,
79
+ source_hash: semanticSourceHash(semanticSource.text),
80
+ },
75
81
  logic_readiness: readiness,
76
82
  candidate_lane: candidateLane,
77
83
  signals,
@@ -1 +1 @@
1
- {"version":3,"file":"analyze-prose.d.ts","sourceRoot":"","sources":["../../../src/operations/semantic-advisor/analyze-prose.ts"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EACV,6BAA6B,EAC7B,oBAAoB,EAWrB,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,wBAAwB,wBAAwB,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AA6zBhD,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,oBAAoB,GAC1B,6BAA6B,CAuD/B"}
1
+ {"version":3,"file":"analyze-prose.d.ts","sourceRoot":"","sources":["../../../src/operations/semantic-advisor/analyze-prose.ts"],"names":[],"mappings":"AAkCA,OAAO,KAAK,EACV,6BAA6B,EAC7B,oBAAoB,EAWrB,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,wBAAwB,wBAAwB,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AA01BhD,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,oBAAoB,GAC1B,6BAA6B,CA+D/B"}
@@ -8,7 +8,7 @@ import { CORE_PREDICATE_RULES } from "./predicate-rules-core.js";
8
8
  import { POLICY_PREDICATE_RULES } from "./predicate-rules-policy.js";
9
9
  import { PRODUCT_TAIL_PREDICATE_RULES } from "./predicate-rules-product-tail.js";
10
10
  import { PRODUCT_PREDICATE_RULES } from "./predicate-rules-product.js";
11
- import { isRecord, payloadHash, propertiesOf, relationship, sourceOf, statementOf, stringValue, } from "./shared.js";
11
+ import { isRecord, payloadHash, propertiesOf, relationship, semanticClausesOf, semanticSourceHash, semanticSourceOf, sourceOf, statementOf, stringValue, } from "./shared.js";
12
12
  import { detectStrictSuggestion } from "./strict-rules.js";
13
13
  export const SEMANTIC_ADVISOR_VERSION = "semantic-advisor-v2";
14
14
  export { semanticClaimKey } from "./clauses.js";
@@ -52,7 +52,12 @@ const SIGNAL_PATTERNS = [
52
52
  ];
53
53
  function proseOf(payload) {
54
54
  const properties = propertiesOf(payload);
55
- 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
+ ]
56
61
  .map(stringValue)
57
62
  .filter(Boolean)
58
63
  .join("\n");
@@ -69,8 +74,8 @@ function logicalGroundingSlots(payload) {
69
74
  return relationships.filter((relationship) => isRecord(relationship) &&
70
75
  ["requires_property", "requires_predicate", "requires_rule"].includes(stringValue(relationship.type))).length;
71
76
  }
72
- function isModeled(payload, expectedClaimCount) {
73
- if (expectedClaimCount === 0)
77
+ function isModeled(payload, expectedClaimKeys) {
78
+ if (expectedClaimKeys.length === 0)
74
79
  return false;
75
80
  const relationships = Array.isArray(payload.relationships)
76
81
  ? payload.relationships
@@ -79,7 +84,16 @@ function isModeled(payload, expectedClaimCount) {
79
84
  .filter(isRecord)
80
85
  .map((relationship) => stringValue(relationship.type))
81
86
  .filter(Boolean));
82
- 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)) &&
83
97
  ((types.has("constrains") && types.has("requires_property")) ||
84
98
  types.has("requires_predicate") ||
85
99
  types.has("requires_rule")));
@@ -231,13 +245,8 @@ function modelingSuggestions(payload, modeled, clauses, interpretations) {
231
245
  const suggestions = [];
232
246
  const seen = new Set();
233
247
  const expectedClaimKeys = clauses
234
- .filter((clause) => clause.normative)
248
+ .filter((clause) => !["rationale", "example", "subjective"].includes(propositionRole(clause.text, clause.normative)))
235
249
  .map((clause) => clause.claim_key);
236
- const rawDeclaredClaimKeys = propertiesOf(payload).logic_claims;
237
- const declaredClaimKeys = Array.isArray(rawDeclaredClaimKeys)
238
- ? rawDeclaredClaimKeys.filter((value) => typeof value === "string")
239
- : [];
240
- const mergedClaimKeys = Array.from(new Set([...declaredClaimKeys, ...expectedClaimKeys]));
241
250
  for (const clause of clauses) {
242
251
  const candidate = clause.text;
243
252
  const rawSuggestion = predicateSuggestion(payload, candidate) ??
@@ -245,9 +254,9 @@ function modelingSuggestions(payload, modeled, clauses, interpretations) {
245
254
  ambiguitySuggestion(payload, candidate) ??
246
255
  detectStrictSuggestion(payload, candidate);
247
256
  const suggestion = rawSuggestion
248
- ? withClauseProvenance(rawSuggestion, clause, mergedClaimKeys, statementOf(payload))
257
+ ? withClauseProvenance(rawSuggestion, clause, clauses, expectedClaimKeys, statementOf(payload), semanticSourceOf(payload).field)
249
258
  : clause.normative
250
- ? unmatchedClauseSuggestion(payload, clause, mergedClaimKeys)
259
+ ? unmatchedClauseSuggestion(payload, clause, clauses, expectedClaimKeys)
251
260
  : null;
252
261
  if (!suggestion)
253
262
  continue;
@@ -264,7 +273,7 @@ function modelingSuggestions(payload, modeled, clauses, interpretations) {
264
273
  const suggestion = ruleSuggestion(payload, interpretation);
265
274
  if (!suggestion)
266
275
  continue;
267
- const withProvenance = withClauseProvenance(suggestion, clause, mergedClaimKeys, statementOf(payload));
276
+ const withProvenance = withClauseProvenance(suggestion, clause, clauses, expectedClaimKeys, statementOf(payload), semanticSourceOf(payload).field);
268
277
  const key = withProvenance.kind === "rule"
269
278
  ? `${withProvenance.claim_key}:rule:${withProvenance.semantic_key}`
270
279
  : `${withProvenance.claim_key}:${withProvenance.kind}`;
@@ -275,9 +284,45 @@ function modelingSuggestions(payload, modeled, clauses, interpretations) {
275
284
  }
276
285
  return suggestions;
277
286
  }
278
- function withClauseProvenance(suggestion, clause, expectedClaimKeys, statement) {
287
+ function withClauseProvenance(suggestion, clause, clauses, expectedClaimKeys, statement, sourceField) {
279
288
  const clauseOffset = statement.indexOf(clause.text);
280
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
+ };
281
326
  const applyPlan = suggestion.applyPlan.map((step) => {
282
327
  if (!isRecord(step))
283
328
  return step;
@@ -288,32 +333,16 @@ function withClauseProvenance(suggestion, clause, expectedClaimKeys, statement)
288
333
  const existing = Array.isArray(properties.logic_claims)
289
334
  ? properties.logic_claims.filter((value) => typeof value === "string")
290
335
  : [];
291
- const inventory = Array.isArray(properties.semantic_inventory)
292
- ? properties.semantic_inventory.filter(isRecord)
293
- : [];
294
- const status = suggestion.kind === "ambiguity_observation"
295
- ? "ambiguous"
296
- : suggestion.kind === "ontology_gap"
297
- ? "ontology_gap"
298
- : "modeled";
299
336
  return {
300
337
  ...step,
301
338
  properties: {
302
339
  ...properties,
303
340
  logic_claims: Array.from(new Set([...existing, ...expectedClaimKeys])),
304
- semantic_inventory: [
305
- ...inventory.filter((entry) => entry.claim_key !== clause.claim_key),
306
- {
307
- claim_key: clause.claim_key,
308
- claim_text: clause.text,
309
- role: clause.normative ? "normative" : "descriptive",
310
- status,
311
- span: clauseSpan,
312
- reason: status === "modeled"
313
- ? "Draft apply plan contains a typed grounding for this proposition."
314
- : suggestion.rationale,
315
- },
316
- ],
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,
317
346
  },
318
347
  };
319
348
  }
@@ -342,16 +371,9 @@ function withClauseProvenance(suggestion, clause, expectedClaimKeys, statement)
342
371
  claimKey: clause.claim_key,
343
372
  claimText: clause.text,
344
373
  logicClaims: expectedClaimKeys,
345
- semanticInventory: [
346
- {
347
- claim_key: clause.claim_key,
348
- claim_text: clause.text,
349
- role: clause.normative ? "normative" : "descriptive",
350
- status: "modeled",
351
- span: clauseSpan,
352
- reason: "The returned typed fact grounds this proposition.",
353
- },
354
- ],
374
+ semanticClauses: clauses.map(({ text }) => text),
375
+ semanticInventory,
376
+ inventoryContract,
355
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.",
356
378
  },
357
379
  }
@@ -363,23 +385,16 @@ function withClauseProvenance(suggestion, clause, expectedClaimKeys, statement)
363
385
  claimKey: clause.claim_key,
364
386
  claimText: clause.text,
365
387
  logicClaims: expectedClaimKeys,
366
- semanticInventory: [
367
- {
368
- claim_key: clause.claim_key,
369
- claim_text: clause.text,
370
- role: clause.normative ? "normative" : "descriptive",
371
- status: "modeled",
372
- span: clauseSpan,
373
- reason: "The returned typed rule grounds this proposition.",
374
- },
375
- ],
388
+ semanticClauses: clauses.map(({ text }) => text),
389
+ semanticInventory,
390
+ inventoryContract,
376
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.",
377
392
  },
378
393
  }
379
394
  : {}),
380
395
  };
381
396
  }
382
- function unmatchedClauseSuggestion(payload, clause, expectedClaimKeys) {
397
+ function unmatchedClauseSuggestion(payload, clause, clauses, expectedClaimKeys) {
383
398
  return withClauseProvenance({
384
399
  kind: "ontology_gap",
385
400
  claim_key: clause.claim_key,
@@ -394,7 +409,7 @@ function unmatchedClauseSuggestion(payload, clause, expectedClaimKeys) {
394
409
  "review:ontology-gap",
395
410
  "needs_schema_extension",
396
411
  ]),
397
- }, clause, expectedClaimKeys, statementOf(payload));
412
+ }, clause, clauses, expectedClaimKeys, statementOf(payload), semanticSourceOf(payload).field);
398
413
  }
399
414
  function propositionRole(statement, normative) {
400
415
  if (/\b(?:for example|e\.g\.|such as|illustrative)\b/i.test(statement))
@@ -668,17 +683,17 @@ export function analyzeSemanticAdvisorInput(input) {
668
683
  const statement = statementOf(payload) || proseOf(payload);
669
684
  const signals = requirement ? detectSignals(proseOf(payload)) : [];
670
685
  const clauses = statement
671
- ? extractSemanticClauses(statement, input.clauses)
686
+ ? extractSemanticClauses(statement, input.clauses ?? semanticClausesOf(payload))
672
687
  : [];
673
688
  const rawDeclaredClaims = propertiesOf(payload).logic_claims;
674
689
  const declaredClaims = Array.isArray(rawDeclaredClaims)
675
690
  ? rawDeclaredClaims.filter((value) => typeof value === "string")
676
691
  : [];
677
692
  const expectedClaims = clauses
678
- .filter((clause) => clause.normative)
693
+ .filter((clause) => !["rationale", "example", "subjective"].includes(propositionRole(clause.text, clause.normative)))
679
694
  .map((clause) => clause.claim_key);
680
695
  const modeled = requirement &&
681
- isModeled(payload, expectedClaims.length) &&
696
+ isModeled(payload, expectedClaims) &&
682
697
  expectedClaims.length > 0 &&
683
698
  expectedClaims.every((claimKey) => declaredClaims.includes(claimKey));
684
699
  const suggestions = modelingSuggestions(payload, modeled, clauses, input.interpretations);
@@ -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
  }