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.
- package/dist/cli-json-command.d.ts +1 -2
- package/dist/cli-json-command.d.ts.map +1 -1
- package/dist/cli-json-command.js +88 -44
- package/dist/cli-operation-loader.d.ts +3 -0
- package/dist/cli-operation-loader.d.ts.map +1 -0
- package/dist/cli-operation-loader.js +58 -0
- package/dist/cli-operation-metadata.d.ts +82 -0
- package/dist/cli-operation-metadata.d.ts.map +1 -0
- package/dist/cli-operation-metadata.js +106 -0
- package/dist/cli-protocol.d.ts +1 -1
- package/dist/cli-protocol.d.ts.map +1 -1
- package/dist/cli-protocol.js +4 -3
- package/dist/cli-register-foundation.d.ts.map +1 -1
- package/dist/cli-register-foundation.js +14 -17
- package/dist/cli-register-json.d.ts +3 -0
- package/dist/cli-register-json.d.ts.map +1 -0
- package/dist/cli-register-json.js +35 -0
- package/dist/cli-register-maintenance.d.ts.map +1 -1
- package/dist/cli-register-maintenance.js +41 -8
- package/dist/cli-register-reporting.d.ts.map +1 -1
- package/dist/cli-register-reporting.js +18 -14
- package/dist/cli-register-skills.d.ts.map +1 -1
- package/dist/cli-register-skills.js +8 -6
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +3 -2
- 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 +30 -12
- package/dist/commands/coverage.d.ts +5 -0
- package/dist/commands/coverage.d.ts.map +1 -1
- package/dist/commands/coverage.js +6 -1
- package/dist/commands/discovery-shared.d.ts +2 -1
- package/dist/commands/discovery-shared.d.ts.map +1 -1
- package/dist/commands/discovery-shared.js +35 -13
- package/dist/commands/discovery-table.d.ts.map +1 -1
- package/dist/commands/discovery-table.js +96 -5
- package/dist/commands/engine.d.ts +8 -0
- package/dist/commands/engine.d.ts.map +1 -0
- package/dist/commands/engine.js +100 -0
- package/dist/commands/gaps.js +1 -1
- package/dist/commands/graph.js +1 -1
- package/dist/commands/query.d.ts.map +1 -1
- package/dist/commands/query.js +3 -1
- package/dist/commands/search.d.ts.map +1 -1
- package/dist/commands/search.js +3 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +2 -1
- package/dist/commands/sync/cache.d.ts +12 -0
- package/dist/commands/sync/cache.d.ts.map +1 -1
- package/dist/commands/sync/cache.js +38 -1
- package/dist/commands/sync/persistence.d.ts +10 -1
- package/dist/commands/sync/persistence.d.ts.map +1 -1
- package/dist/commands/sync/persistence.js +276 -43
- package/dist/commands/sync/staging.d.ts +10 -1
- package/dist/commands/sync/staging.d.ts.map +1 -1
- package/dist/commands/sync/staging.js +84 -1
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +521 -27
- 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/engine-daemon.d.ts +3 -0
- package/dist/engine-daemon.d.ts.map +1 -0
- package/dist/engine-daemon.js +34 -0
- package/dist/engine.d.ts +63 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +1256 -0
- package/dist/extractors/markdown.d.ts +8 -0
- package/dist/extractors/markdown.d.ts.map +1 -1
- package/dist/extractors/markdown.js +69 -2
- package/dist/extractors/relationships.d.ts +2 -0
- package/dist/extractors/relationships.d.ts.map +1 -1
- package/dist/extractors/relationships.js +15 -17
- package/dist/operations/modeling/logic-modeling.d.ts.map +1 -1
- package/dist/operations/modeling/logic-modeling.js +14 -5
- package/dist/operations/modeling/model-requirement.d.ts.map +1 -1
- package/dist/operations/modeling/model-requirement.js +27 -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 +18 -6
- package/dist/operations/modeling/predicate-inference.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-inference.js +5 -17
- package/dist/operations/modeling/predicate-loader.js +1 -1
- package/dist/operations/modeling/predicate-types.d.ts +9 -1
- package/dist/operations/modeling/predicate-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/serialization.d.ts.map +1 -1
- package/dist/operations/mutation/serialization.js +6 -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.map +1 -1
- package/dist/operations/semantic-advisor/analysis-receipt.js +7 -1
- package/dist/operations/semantic-advisor/analyze-prose.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/analyze-prose.js +76 -61
- 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/shared.d.ts +8 -0
- package/dist/operations/semantic-advisor/shared.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/shared.js +37 -3
- package/dist/operations/semantic-advisor/types.d.ts +5 -0
- 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 +9 -2
- package/dist/prolog.d.ts +14 -0
- package/dist/prolog.d.ts.map +1 -1
- package/dist/prolog.js +279 -69
- 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 +151 -6
- 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-entities.d.ts.map +1 -1
- package/dist/public/operations/discovery-entities.js +3 -2
- 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 +58 -5
- package/dist/public/operations/index.d.ts +4 -0
- package/dist/public/operations/index.d.ts.map +1 -1
- package/dist/public/operations/index.js +4 -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/prolog-json.d.ts.map +1 -1
- package/dist/public/operations/prolog-json.js +14 -4
- 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 +38 -0
- package/dist/public/operations/runtime-types.d.ts.map +1 -1
- package/dist/public/operations/specs/check.d.ts +2 -2
- package/dist/public/operations/specs/check.js +2 -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 +19 -1
- package/dist/public/operations/specs/modeling.d.ts.map +1 -1
- package/dist/public/operations/specs/modeling.js +16 -1
- package/dist/public/operations/specs/mutation-schemas.d.ts +96 -1
- package/dist/public/operations/specs/mutation-schemas.d.ts.map +1 -1
- package/dist/public/operations/specs/mutation-schemas.js +40 -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.js +1 -1
- package/dist/public/operations/specs/upsert.d.ts +96 -1
- 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 +43 -1
- package/dist/public/skills/init-kibi/SKILL.md +2 -2
- package/dist/public/skills/kibi-freshness/SKILL.md +2 -2
- package/dist/public/skills/kibi-traceability/SKILL.md +8 -2
- package/dist/public/skills/kibi-usage/SKILL.md +12 -6
- package/dist/public/skills/kibi-usage/resources/fact-lanes.md +1 -1
- package/dist/public/skills/kibi-usage/resources/logic-ir.md +1 -1
- package/dist/public/skills/kibi-usage/resources/operation-access.md +1 -1
- package/dist/public/skills/kibi-usage/resources/workflows.md +19 -2
- 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/runtime/cli-runtime.d.ts.map +1 -1
- package/dist/runtime/cli-runtime.js +33 -37
- package/dist/schemas/entity.schema.json +96 -2
- package/dist/traceability/temp-kb.d.ts.map +1 -1
- package/dist/traceability/temp-kb.js +36 -3
- package/dist/types/entities.d.ts +1 -0
- package/dist/types/entities.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/package.json +36 -4
- 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-entities.ts +3 -2
- package/src/public/operations/discovery-executors.ts +68 -5
- package/src/public/operations/index.ts +4 -0
- package/src/public/operations/legacy-migration-plan.ts +688 -0
- package/src/public/operations/node-ports.ts +109 -0
- package/src/public/operations/prolog-json.ts +15 -3
- package/src/public/operations/repair-plan.ts +562 -0
- package/src/public/operations/runtime-types.ts +47 -0
- package/src/public/operations/specs/check.ts +2 -2
- package/src/public/operations/specs/discovery.ts +1 -1
- package/src/public/operations/specs/modeling.ts +19 -1
- package/src/public/operations/specs/mutation-schemas.ts +47 -1
- package/src/public/operations/specs/reporting.ts +91 -6
- package/src/public/operations/specs/semantic.ts +1 -1
- package/src/public/operations/workspace-snapshot.ts +28 -0
- package/src/public/schemas/entity.ts +44 -1
- package/src/public/skills/init-kibi/SKILL.md +2 -2
- package/src/public/skills/kibi-freshness/SKILL.md +2 -2
- package/src/public/skills/kibi-traceability/SKILL.md +8 -2
- package/src/public/skills/kibi-usage/SKILL.md +12 -6
- package/src/public/skills/kibi-usage/resources/fact-lanes.md +1 -1
- package/src/public/skills/kibi-usage/resources/logic-ir.md +1 -1
- package/src/public/skills/kibi-usage/resources/operation-access.md +1 -1
- package/src/public/skills/kibi-usage/resources/workflows.md +19 -2
- 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 +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
|
|
6
|
-
const id = String(input.entity.id);
|
|
5
|
+
export function buildUpsertCommitGoal(input) {
|
|
7
6
|
const type = String(input.entity.type);
|
|
8
|
-
const
|
|
9
|
-
|
|
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
|
|
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 =
|
|
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 (
|
|
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;
|
|
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 (
|
|
29
|
-
|
|
30
|
-
|
|
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":"
|
|
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 {
|
|
4
|
-
import {
|
|
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
|
-
|
|
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
|
|
45
|
-
|
|
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
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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 =
|
|
107
|
+
const created = changeKind === "created" ? 1 : 0;
|
|
69
108
|
const payload = {
|
|
70
109
|
created,
|
|
71
|
-
updated:
|
|
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;
|
|
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,
|
|
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;
|
|
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,
|
|
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":"
|
|
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 [
|
|
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,
|
|
73
|
-
if (
|
|
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
|
-
|
|
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,
|
|
257
|
+
? withClauseProvenance(rawSuggestion, clause, clauses, expectedClaimKeys, statementOf(payload), semanticSourceOf(payload).field)
|
|
249
258
|
: clause.normative
|
|
250
|
-
? unmatchedClauseSuggestion(payload, clause,
|
|
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,
|
|
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
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
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
|
-
|
|
346
|
-
|
|
347
|
-
|
|
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
|
-
|
|
367
|
-
|
|
368
|
-
|
|
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
|
|
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;
|
|
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
|
}
|