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.
- package/dist/cli-json-command.d.ts.map +1 -1
- package/dist/cli-json-command.js +87 -11
- package/dist/cli-register-maintenance.d.ts.map +1 -1
- package/dist/cli-register-maintenance.js +8 -0
- package/dist/cli-register-reporting.d.ts.map +1 -1
- package/dist/cli-register-reporting.js +5 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +2 -1
- package/dist/commands/aggregated-checks.d.ts.map +1 -1
- package/dist/commands/aggregated-checks.js +1 -0
- package/dist/commands/check.d.ts.map +1 -1
- package/dist/commands/check.js +1 -1
- package/dist/commands/coverage.d.ts +5 -0
- package/dist/commands/coverage.d.ts.map +1 -1
- package/dist/commands/coverage.js +5 -0
- package/dist/commands/discovery-table.d.ts.map +1 -1
- package/dist/commands/discovery-table.js +96 -5
- package/dist/commands/sync/cache.d.ts +2 -0
- package/dist/commands/sync/cache.d.ts.map +1 -1
- package/dist/commands/sync/cache.js +8 -0
- package/dist/commands/sync/manifest.d.ts +12 -1
- package/dist/commands/sync/manifest.d.ts.map +1 -1
- package/dist/commands/sync/manifest.js +22 -5
- package/dist/commands/sync/persistence.d.ts.map +1 -1
- package/dist/commands/sync/persistence.js +76 -2
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +72 -15
- package/dist/commands/usage-metrics.d.ts +66 -2
- package/dist/commands/usage-metrics.d.ts.map +1 -1
- package/dist/commands/usage-metrics.js +34 -24
- package/dist/commands/usage-remediation.d.ts +9 -0
- package/dist/commands/usage-remediation.d.ts.map +1 -0
- package/dist/commands/usage-remediation.js +52 -0
- package/dist/extractors/markdown.d.ts +17 -1
- package/dist/extractors/markdown.d.ts.map +1 -1
- package/dist/extractors/markdown.js +81 -2
- package/dist/logic/ir.d.ts +112 -0
- package/dist/logic/ir.d.ts.map +1 -0
- package/dist/logic/ir.js +729 -0
- package/dist/operations/modeling/logic-modeling.d.ts +22 -0
- package/dist/operations/modeling/logic-modeling.d.ts.map +1 -0
- package/dist/operations/modeling/logic-modeling.js +120 -0
- package/dist/operations/modeling/model-requirement.d.ts.map +1 -1
- package/dist/operations/modeling/model-requirement.js +83 -2
- package/dist/operations/modeling/predicate-applyplan.d.ts +1 -1
- package/dist/operations/modeling/predicate-applyplan.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-applyplan.js +29 -4
- package/dist/operations/modeling/predicate-inference.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-inference.js +3 -0
- package/dist/operations/modeling/predicate-loader.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-loader.js +7 -1
- package/dist/operations/modeling/predicate-ranker.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-ranker.js +40 -2
- package/dist/operations/modeling/predicate-types.d.ts +12 -1
- package/dist/operations/modeling/predicate-types.d.ts.map +1 -1
- package/dist/operations/modeling/requirement-types.d.ts +12 -0
- package/dist/operations/modeling/requirement-types.d.ts.map +1 -1
- package/dist/operations/modeling/suggest-predicates.d.ts.map +1 -1
- package/dist/operations/modeling/suggest-predicates.js +35 -11
- package/dist/operations/mutation/audit.js +1 -1
- package/dist/operations/mutation/contradictions.d.ts +1 -1
- package/dist/operations/mutation/contradictions.d.ts.map +1 -1
- package/dist/operations/mutation/contradictions.js +23 -18
- package/dist/operations/mutation/relationships.d.ts.map +1 -1
- package/dist/operations/mutation/relationships.js +8 -0
- package/dist/operations/mutation/serialization.d.ts.map +1 -1
- package/dist/operations/mutation/serialization.js +6 -0
- package/dist/operations/mutation/strict-fact.d.ts.map +1 -1
- package/dist/operations/mutation/strict-fact.js +68 -3
- package/dist/operations/mutation/upsert.d.ts +3 -1
- package/dist/operations/mutation/upsert.d.ts.map +1 -1
- package/dist/operations/mutation/upsert.js +51 -12
- package/dist/operations/mutation/validate-upsert.d.ts.map +1 -1
- package/dist/operations/mutation/validate-upsert.js +18 -2
- package/dist/operations/mutation/validation.d.ts.map +1 -1
- package/dist/operations/mutation/validation.js +8 -0
- package/dist/operations/semantic-advisor/analysis-receipt.d.ts +2 -2
- package/dist/operations/semantic-advisor/analysis-receipt.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/analysis-receipt.js +30 -16
- package/dist/operations/semantic-advisor/analyze-prose.d.ts +1 -1
- package/dist/operations/semantic-advisor/analyze-prose.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/analyze-prose.js +464 -27
- package/dist/operations/semantic-advisor/clauses.d.ts +1 -0
- package/dist/operations/semantic-advisor/clauses.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/clauses.js +7 -7
- package/dist/operations/semantic-advisor/ingestion-boundary.d.ts +18 -0
- package/dist/operations/semantic-advisor/ingestion-boundary.d.ts.map +1 -0
- package/dist/operations/semantic-advisor/ingestion-boundary.js +167 -0
- package/dist/operations/semantic-advisor/observation-plan.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/observation-plan.js +15 -3
- package/dist/operations/semantic-advisor/shared.d.ts +9 -0
- package/dist/operations/semantic-advisor/shared.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/shared.js +38 -4
- package/dist/operations/semantic-advisor/types.d.ts +66 -1
- package/dist/operations/semantic-advisor/types.d.ts.map +1 -1
- package/dist/prolog/codec.d.ts.map +1 -1
- package/dist/prolog/codec.js +19 -2
- package/dist/prolog.d.ts +6 -0
- package/dist/prolog.d.ts.map +1 -1
- package/dist/prolog.js +247 -63
- package/dist/public/diagnostic-usage.d.ts +17 -0
- package/dist/public/diagnostic-usage.d.ts.map +1 -0
- package/dist/public/diagnostic-usage.js +152 -0
- package/dist/public/distribution-parity.d.ts +90 -0
- package/dist/public/distribution-parity.d.ts.map +1 -0
- package/dist/public/distribution-parity.js +367 -0
- package/dist/public/impact/full-kb-quality.d.ts +2 -0
- package/dist/public/impact/full-kb-quality.d.ts.map +1 -1
- package/dist/public/impact/full-kb-quality.js +53 -1
- package/dist/public/impact-diagnostics.d.ts +2 -0
- package/dist/public/impact-diagnostics.d.ts.map +1 -1
- package/dist/public/impact-diagnostics.js +1 -0
- package/dist/public/operations/catalog.d.ts +235 -11
- package/dist/public/operations/catalog.d.ts.map +1 -1
- package/dist/public/operations/check-executor.d.ts.map +1 -1
- package/dist/public/operations/check-executor.js +4 -0
- package/dist/public/operations/discovery-executors.d.ts +6 -0
- package/dist/public/operations/discovery-executors.d.ts.map +1 -1
- package/dist/public/operations/discovery-executors.js +18 -2
- package/dist/public/operations/index.d.ts +5 -0
- package/dist/public/operations/index.d.ts.map +1 -1
- package/dist/public/operations/index.js +5 -0
- package/dist/public/operations/legacy-migration-plan.d.ts +113 -0
- package/dist/public/operations/legacy-migration-plan.d.ts.map +1 -0
- package/dist/public/operations/legacy-migration-plan.js +409 -0
- package/dist/public/operations/node-ports.d.ts.map +1 -1
- package/dist/public/operations/node-ports.js +90 -0
- package/dist/public/operations/repair-plan.d.ts +184 -0
- package/dist/public/operations/repair-plan.d.ts.map +1 -0
- package/dist/public/operations/repair-plan.js +397 -0
- package/dist/public/operations/runtime-types.d.ts +7 -0
- package/dist/public/operations/runtime-types.d.ts.map +1 -1
- package/dist/public/operations/specs/check.d.ts +3 -3
- package/dist/public/operations/specs/check.d.ts.map +1 -1
- package/dist/public/operations/specs/check.js +5 -2
- package/dist/public/operations/specs/discovery.d.ts +1 -1
- package/dist/public/operations/specs/discovery.js +1 -1
- package/dist/public/operations/specs/modeling.d.ts +35 -1
- package/dist/public/operations/specs/modeling.d.ts.map +1 -1
- package/dist/public/operations/specs/modeling.js +32 -1
- package/dist/public/operations/specs/mutation-schemas.d.ts +133 -3
- package/dist/public/operations/specs/mutation-schemas.d.ts.map +1 -1
- package/dist/public/operations/specs/mutation-schemas.js +67 -1
- package/dist/public/operations/specs/reporting.d.ts +42 -1
- package/dist/public/operations/specs/reporting.d.ts.map +1 -1
- package/dist/public/operations/specs/reporting.js +70 -6
- package/dist/public/operations/specs/semantic.d.ts +30 -2
- package/dist/public/operations/specs/semantic.d.ts.map +1 -1
- package/dist/public/operations/specs/semantic.js +35 -3
- package/dist/public/operations/specs/upsert.d.ts +133 -3
- package/dist/public/operations/specs/upsert.d.ts.map +1 -1
- package/dist/public/operations/workspace-snapshot.d.ts +10 -0
- package/dist/public/operations/workspace-snapshot.d.ts.map +1 -0
- package/dist/public/operations/workspace-snapshot.js +20 -0
- package/dist/public/schemas/entity.d.ts.map +1 -1
- package/dist/public/schemas/entity.js +332 -0
- package/dist/public/schemas/relationship.d.ts.map +1 -1
- package/dist/public/schemas/relationship.js +1 -0
- package/dist/public/skills/kibi-traceability/SKILL.md +7 -1
- package/dist/public/skills/kibi-usage/SKILL.md +44 -12
- package/dist/public/skills/kibi-usage/resources/fact-lanes.md +12 -2
- package/dist/public/skills/kibi-usage/resources/logic-ir.md +43 -0
- package/dist/public/skills/kibi-usage/resources/operation-access.md +19 -19
- package/dist/public/skills/kibi-usage/resources/ui-requirements.md +96 -0
- package/dist/public/skills/kibi-usage/resources/workflows.md +40 -8
- package/dist/public/symbol-granularity.d.ts +9 -0
- package/dist/public/symbol-granularity.d.ts.map +1 -1
- package/dist/public/symbol-granularity.js +16 -0
- package/dist/public/telemetry-acceptance.d.ts +89 -0
- package/dist/public/telemetry-acceptance.d.ts.map +1 -0
- package/dist/public/telemetry-acceptance.js +597 -0
- package/dist/public/telemetry-remediation.d.ts +33 -0
- package/dist/public/telemetry-remediation.d.ts.map +1 -0
- package/dist/public/telemetry-remediation.js +257 -0
- package/dist/public/verification-receipt.d.ts +75 -0
- package/dist/public/verification-receipt.d.ts.map +1 -0
- package/dist/public/verification-receipt.js +129 -0
- package/dist/schemas/entity.schema.json +401 -4
- package/dist/traceability/staged-diagnostics.d.ts +1 -1
- package/dist/traceability/staged-diagnostics.d.ts.map +1 -1
- package/dist/traceability/staged-diagnostics.js +17 -10
- package/dist/traceability/staged-impact-contract.js +1 -1
- package/dist/traceability/staged-symbols-manifest.d.ts.map +1 -1
- package/dist/traceability/staged-symbols-manifest.js +28 -10
- package/dist/traceability/temp-kb.d.ts.map +1 -1
- package/dist/traceability/temp-kb.js +49 -3
- package/dist/types/entities.d.ts +1 -0
- package/dist/types/entities.d.ts.map +1 -1
- package/dist/types/relationships.d.ts +1 -1
- package/dist/types/relationships.d.ts.map +1 -1
- package/dist/utils/rule-registry.d.ts +2 -0
- package/dist/utils/rule-registry.d.ts.map +1 -1
- package/dist/utils/rule-registry.js +18 -0
- package/dist/utils/schema-version.d.ts +1 -1
- package/dist/utils/schema-version.js +1 -1
- package/package.json +34 -2
- package/src/public/diagnostic-usage.ts +206 -0
- package/src/public/distribution-parity.ts +580 -0
- package/src/public/impact/full-kb-quality.ts +74 -1
- package/src/public/impact-diagnostics.ts +16 -0
- package/src/public/operations/check-executor.ts +4 -0
- package/src/public/operations/discovery-executors.ts +24 -2
- package/src/public/operations/index.ts +5 -0
- package/src/public/operations/legacy-migration-plan.ts +688 -0
- package/src/public/operations/node-ports.ts +109 -0
- package/src/public/operations/repair-plan.ts +562 -0
- package/src/public/operations/runtime-types.ts +8 -0
- package/src/public/operations/specs/check.ts +5 -2
- package/src/public/operations/specs/discovery.ts +1 -1
- package/src/public/operations/specs/modeling.ts +39 -1
- package/src/public/operations/specs/mutation-schemas.ts +77 -1
- package/src/public/operations/specs/reporting.ts +91 -6
- package/src/public/operations/specs/semantic.ts +42 -3
- package/src/public/operations/workspace-snapshot.ts +28 -0
- package/src/public/schemas/entity.ts +340 -1
- package/src/public/schemas/relationship.ts +1 -0
- package/src/public/skills/kibi-traceability/SKILL.md +7 -1
- package/src/public/skills/kibi-usage/SKILL.md +44 -12
- package/src/public/skills/kibi-usage/resources/fact-lanes.md +12 -2
- package/src/public/skills/kibi-usage/resources/logic-ir.md +43 -0
- package/src/public/skills/kibi-usage/resources/operation-access.md +19 -19
- package/src/public/skills/kibi-usage/resources/ui-requirements.md +96 -0
- package/src/public/skills/kibi-usage/resources/workflows.md +40 -8
- package/src/public/symbol-granularity.ts +25 -0
- package/src/public/telemetry-acceptance.ts +859 -0
- package/src/public/telemetry-remediation.ts +462 -0
- package/src/public/verification-receipt.ts +170 -0
- package/src/schemas/entity.schema.json +401 -4
- 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-
|
|
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 [
|
|
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,
|
|
71
|
-
if (
|
|
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
|
-
|
|
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
|
|
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,
|
|
257
|
+
? withClauseProvenance(rawSuggestion, clause, clauses, expectedClaimKeys, statementOf(payload), semanticSourceOf(payload).field)
|
|
173
258
|
: clause.normative
|
|
174
|
-
? unmatchedClauseSuggestion(payload, clause,
|
|
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 =
|
|
256
|
-
? extractSemanticClauses(
|
|
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
|
|
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
|
-
|
|
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;
|
|
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
|
|
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 =
|
|
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(
|
|
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
|
|
33
|
-
if (suppliedClauses !== undefined &&
|
|
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
|
|
36
|
+
return normalized.map((clause, index) => ({
|
|
37
37
|
claim_key: semanticClaimKey(clause),
|
|
38
38
|
text: clause,
|
|
39
39
|
index,
|
|
40
|
-
normative:
|
|
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
|