kibi-cli 2.11.0 → 2.13.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/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +76 -1
- package/dist/engine.d.ts +27 -4
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +85 -28
- package/dist/operations/bootstrap/generate.d.ts.map +1 -1
- package/dist/operations/bootstrap/generate.js +5 -2
- package/dist/operations/bootstrap/requirement-claims.d.ts +15 -0
- package/dist/operations/bootstrap/requirement-claims.d.ts.map +1 -1
- package/dist/operations/bootstrap/requirement-claims.js +100 -1
- package/dist/operations/modeling/predicate-applyplan.d.ts +13 -0
- package/dist/operations/modeling/predicate-applyplan.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-applyplan.js +72 -20
- package/dist/operations/modeling/predicate-binding-hints.d.ts +1 -1
- package/dist/operations/modeling/predicate-binding-hints.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-binding-hints.js +41 -5
- package/dist/operations/modeling/predicate-bindings.d.ts +13 -0
- package/dist/operations/modeling/predicate-bindings.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-bindings.js +56 -2
- package/dist/operations/modeling/predicate-catalog-1.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-catalog-1.js +3 -0
- package/dist/operations/modeling/predicate-catalog-2.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-catalog-2.js +3 -0
- package/dist/operations/modeling/predicate-catalog-3.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-catalog-3.js +7 -0
- package/dist/operations/modeling/predicate-catalog-4.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-catalog-4.js +2 -0
- package/dist/operations/modeling/predicate-closed-vocabularies.d.ts +104 -0
- package/dist/operations/modeling/predicate-closed-vocabularies.d.ts.map +1 -0
- package/dist/operations/modeling/predicate-closed-vocabularies.js +104 -0
- package/dist/operations/modeling/predicate-types.d.ts +13 -1
- package/dist/operations/modeling/predicate-types.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-utils.d.ts +11 -1
- package/dist/operations/modeling/predicate-utils.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-utils.js +19 -3
- package/dist/operations/modeling/suggest-predicates.d.ts.map +1 -1
- package/dist/operations/modeling/suggest-predicates.js +57 -3
- package/dist/package-versions.d.ts +10 -0
- package/dist/package-versions.d.ts.map +1 -0
- package/dist/package-versions.js +68 -0
- package/dist/prolog.d.ts.map +1 -1
- package/dist/prolog.js +4 -19
- package/dist/public/skills/kibi-bootstrap/SKILL.md +2 -2
- package/dist/public/skills/kibi-usage/SKILL.md +12 -3
- package/dist/utils/strict-modeling.d.ts +1 -0
- package/dist/utils/strict-modeling.d.ts.map +1 -1
- package/dist/utils/strict-modeling.js +1 -1
- package/package.json +2 -2
- package/src/public/skills/kibi-bootstrap/SKILL.md +2 -2
- package/src/public/skills/kibi-usage/SKILL.md +12 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAiFA,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAC3B;AAGD,wBAAsB,aAAa,CACjC,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAoG/B;AAED,wBAAsB,4BAA4B,CAChD,IAAI,GAAE,MAAM,OAAO,CAAC;IAAE,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAAE,CACT,GACxC,OAAO,CAAC,OAAO,CAAC,CAOlB;AAED,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;;;;;;;;;;;;;;;;MAkE3C;AAkGD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGzE;AAED,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,MAAM,GAAG,SAAS,CAepB"}
|
package/dist/commands/doctor.js
CHANGED
|
@@ -21,9 +21,11 @@ import { createRequire } from "node:module";
|
|
|
21
21
|
import * as path from "node:path";
|
|
22
22
|
import { fileURLToPath } from "node:url";
|
|
23
23
|
import { bootstrapKibiEnvironment, secretSourceFromBootstrap, } from "../env/bootstrap.js";
|
|
24
|
+
import { kibiPackageVersions } from "../package-versions.js";
|
|
24
25
|
import { describeConfiguredCapabilityPlugins, readProjectKibiConfig, } from "../plugins/project-config.js";
|
|
25
26
|
import { SwiplResolutionError, inspectSwiplBundle, probeRequiredLibraries, resolveSwipl, } from "../prolog/swipl-resolver.js";
|
|
26
27
|
import { buildMigrationPlan, migrationAction, } from "../public/operations/migration-plan.js";
|
|
28
|
+
import { resolveReadBranchAttachment } from "../utils/branch-resolver.js";
|
|
27
29
|
import { resolveGitRepository, } from "../utils/git-repository-context.js";
|
|
28
30
|
import { readKbManifestStatus } from "../utils/kb-manifest.js";
|
|
29
31
|
import { hasManagedHooks, outdatedManagedHooks } from "./init-helpers.js";
|
|
@@ -86,6 +88,10 @@ export async function doctorCommand(options = {}) {
|
|
|
86
88
|
name: "Capability plugins",
|
|
87
89
|
check: checkCapabilityPlugins,
|
|
88
90
|
},
|
|
91
|
+
{
|
|
92
|
+
name: "Engine daemon",
|
|
93
|
+
check: checkEngineDaemon,
|
|
94
|
+
},
|
|
89
95
|
];
|
|
90
96
|
const results = [];
|
|
91
97
|
for (const { name, check } of checks) {
|
|
@@ -227,7 +233,7 @@ async function runtimeProvenance() {
|
|
|
227
233
|
mcpCliRange: mcp.dependencies?.["kibi-cli"] ?? "unknown",
|
|
228
234
|
executeApplyPlanExported,
|
|
229
235
|
entrypoint: process.argv[1] ?? "unknown",
|
|
230
|
-
packageVersions:
|
|
236
|
+
packageVersions: kibiPackageVersions(),
|
|
231
237
|
locations: {
|
|
232
238
|
cli: packagePath,
|
|
233
239
|
cliEntrypoint: process.argv[1] ?? "unknown",
|
|
@@ -494,6 +500,75 @@ function formatJevStaticConfigParts(env = process.env) {
|
|
|
494
500
|
}
|
|
495
501
|
return [`jev.model=${model}`, `jev.timeoutMs=${String(timeoutMs)}`];
|
|
496
502
|
}
|
|
503
|
+
/**
|
|
504
|
+
* The package versions and SWI-Prolog of the engine daemon serving this
|
|
505
|
+
* workspace and branch, read through its handshake without starting one. A
|
|
506
|
+
* daemon with other versions is replaced by the next Kibi command, so it is
|
|
507
|
+
* reported, not failed.
|
|
508
|
+
*/
|
|
509
|
+
// implements REQ-engine-daemon-package-versions
|
|
510
|
+
async function checkEngineDaemon() {
|
|
511
|
+
const workspaceRoot = path.resolve(process.env.KIBI_WORKSPACE ??
|
|
512
|
+
process.env.KIBI_PROJECT_ROOT ??
|
|
513
|
+
process.env.KIBI_ROOT ??
|
|
514
|
+
process.cwd());
|
|
515
|
+
const expected = kibiPackageVersions();
|
|
516
|
+
const attachment = resolveReadBranchAttachment(workspaceRoot);
|
|
517
|
+
if ("error" in attachment) {
|
|
518
|
+
return {
|
|
519
|
+
passed: true,
|
|
520
|
+
message: "Not checked: no branch to address the engine daemon",
|
|
521
|
+
details: { running: false, expectedPackageVersions: expected },
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
const { EngineClient } = await import("../engine.js");
|
|
525
|
+
const client = new EngineClient({
|
|
526
|
+
workspaceRoot,
|
|
527
|
+
branch: attachment.kbBranch,
|
|
528
|
+
});
|
|
529
|
+
let daemon = null;
|
|
530
|
+
try {
|
|
531
|
+
daemon = await client.inspectLiveDaemon();
|
|
532
|
+
}
|
|
533
|
+
catch (error) {
|
|
534
|
+
return {
|
|
535
|
+
passed: true,
|
|
536
|
+
message: `Not reachable: ${error instanceof Error ? error.message : String(error)}`,
|
|
537
|
+
details: { running: false, expectedPackageVersions: expected },
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
finally {
|
|
541
|
+
await client.terminate();
|
|
542
|
+
}
|
|
543
|
+
if (daemon === null) {
|
|
544
|
+
return {
|
|
545
|
+
passed: true,
|
|
546
|
+
message: "Not running",
|
|
547
|
+
details: { running: false, expectedPackageVersions: expected },
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
const details = {
|
|
551
|
+
running: true,
|
|
552
|
+
pid: client.getPid(),
|
|
553
|
+
branch: attachment.kbBranch,
|
|
554
|
+
packageVersions: daemon.packageVersions,
|
|
555
|
+
prologIdentity: daemon.prologIdentity,
|
|
556
|
+
expectedPackageVersions: expected,
|
|
557
|
+
};
|
|
558
|
+
if (daemon.packageVersions === expected) {
|
|
559
|
+
return {
|
|
560
|
+
passed: true,
|
|
561
|
+
message: `Running ${daemon.packageVersions}`,
|
|
562
|
+
details,
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
return {
|
|
566
|
+
passed: true,
|
|
567
|
+
message: `Running ${daemon.packageVersions ?? "a daemon that reports no package versions"}, not this CLI's ${expected}; the next Kibi command replaces it`,
|
|
568
|
+
remediation: "Run: kibi engine stop",
|
|
569
|
+
details,
|
|
570
|
+
};
|
|
571
|
+
}
|
|
497
572
|
function checkKbDirectory() {
|
|
498
573
|
const kbDir = path.join(process.cwd(), ".kb");
|
|
499
574
|
if (!existsSync(kbDir)) {
|
package/dist/engine.d.ts
CHANGED
|
@@ -8,6 +8,14 @@ export { EngineQueryLimitError, QUERY_LIMIT_EXCEEDED_CODE, queryLimitExceededOf,
|
|
|
8
8
|
export type { EngineLimitExceeded, EngineQueryLimits, } from "./engine-limits.js";
|
|
9
9
|
export declare const ENGINE_PROTOCOL_VERSION = 1;
|
|
10
10
|
export declare const ENGINE_IDLE_TIMEOUT_MS: number;
|
|
11
|
+
/**
|
|
12
|
+
* Package versions this engine build carries (KIBI_PACKAGE_VERSIONS when
|
|
13
|
+
* set). The client sends them on every request and the daemon reports its
|
|
14
|
+
* own in the handshake; a daemon with other versions is replaced, never
|
|
15
|
+
* reused.
|
|
16
|
+
*/
|
|
17
|
+
export declare function enginePackageVersions(): string;
|
|
18
|
+
/** @deprecated The versions at module load; call enginePackageVersions(). */
|
|
11
19
|
export declare const ENGINE_PACKAGE_VERSIONS: string;
|
|
12
20
|
/**
|
|
13
21
|
* Identity of the SWI-Prolog this process would launch (`<bin>@<version>`).
|
|
@@ -43,6 +51,11 @@ export type EnginePublicationLease = Readonly<{
|
|
|
43
51
|
readonly release: () => void;
|
|
44
52
|
}>;
|
|
45
53
|
export declare function acquireEnginePublicationLease(workspaceRoot: string, branch: string): EnginePublicationLease;
|
|
54
|
+
/** What a live daemon reports in its handshake. */
|
|
55
|
+
export type EngineDaemonIdentity = Readonly<{
|
|
56
|
+
prologIdentity: string | null;
|
|
57
|
+
packageVersions: string | null;
|
|
58
|
+
}>;
|
|
46
59
|
export type EngineClientOptions = {
|
|
47
60
|
readonly workspaceRoot: string;
|
|
48
61
|
readonly branch: string;
|
|
@@ -99,11 +112,21 @@ export declare class EngineClient {
|
|
|
99
112
|
invalidateCache(): void;
|
|
100
113
|
isRunning(): boolean;
|
|
101
114
|
private readAttachedIdentity;
|
|
102
|
-
|
|
115
|
+
/** The live daemon's handshake: its SWI-Prolog and package versions. */
|
|
116
|
+
private daemonHandshake;
|
|
117
|
+
/**
|
|
118
|
+
* The identity a live daemon reports, without starting one; null when no
|
|
119
|
+
* daemon serves this workspace and branch. The connection is closed again.
|
|
120
|
+
*/
|
|
121
|
+
inspectLiveDaemon(): Promise<EngineDaemonIdentity | null>;
|
|
122
|
+
/** Why the live daemon may not serve this client, or null when it may. */
|
|
123
|
+
private daemonRuntimeMismatch;
|
|
103
124
|
/**
|
|
104
|
-
* A live daemon keeps the SWI-Prolog
|
|
105
|
-
* resolves a different executable or
|
|
106
|
-
* bundled package was upgraded, a
|
|
125
|
+
* A live daemon keeps the SWI-Prolog and the package versions it was
|
|
126
|
+
* started with. When this client resolves a different executable or
|
|
127
|
+
* version (KIBI_SWIPL changed, the bundled package was upgraded, a
|
|
128
|
+
* pre-handshake daemon) or carries other package versions (a daemon left
|
|
129
|
+
* by another install, for example one a git hook started), the daemon is
|
|
107
130
|
* stopped and replaced; it is never reused.
|
|
108
131
|
*/
|
|
109
132
|
private reconcileRuntime;
|
package/dist/engine.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAgCA,OAAO,EAEL,KAAK,iBAAiB,EAMvB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EACV,wBAAwB,EACxB,eAAe,EAEhB,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
|
package/dist/engine.js
CHANGED
|
@@ -14,6 +14,7 @@ import * as path from "node:path";
|
|
|
14
14
|
import { performance } from "node:perf_hooks";
|
|
15
15
|
import { fileURLToPath } from "node:url";
|
|
16
16
|
import { BOUNDED_READ_HELPER_DEFINITION, assertWithinQueryLimits, boundedReadGoal, normalizeQueryLimits, queryLimitsFromEnv, settleBoundedRead, } from "./engine-limits.js";
|
|
17
|
+
import { kibiPackageVersions } from "./package-versions.js";
|
|
17
18
|
import { writePerformanceTraceEvent } from "./performance-trace.js";
|
|
18
19
|
import { PrologProcess, resolveKbPlPath } from "./prolog.js";
|
|
19
20
|
import { parseEntityFromList, parseListOfLists } from "./prolog/codec.js";
|
|
@@ -33,7 +34,18 @@ const READ_LIMITED_METHODS = new Set([
|
|
|
33
34
|
]);
|
|
34
35
|
export const ENGINE_PROTOCOL_VERSION = 1;
|
|
35
36
|
export const ENGINE_IDLE_TIMEOUT_MS = 10 * 60 * 1000;
|
|
36
|
-
|
|
37
|
+
/**
|
|
38
|
+
* Package versions this engine build carries (KIBI_PACKAGE_VERSIONS when
|
|
39
|
+
* set). The client sends them on every request and the daemon reports its
|
|
40
|
+
* own in the handshake; a daemon with other versions is replaced, never
|
|
41
|
+
* reused.
|
|
42
|
+
*/
|
|
43
|
+
// implements REQ-engine-daemon-package-versions
|
|
44
|
+
export function enginePackageVersions() {
|
|
45
|
+
return kibiPackageVersions();
|
|
46
|
+
}
|
|
47
|
+
/** @deprecated The versions at module load; call enginePackageVersions(). */
|
|
48
|
+
export const ENGINE_PACKAGE_VERSIONS = kibiPackageVersions();
|
|
37
49
|
/**
|
|
38
50
|
* Identity of the SWI-Prolog this process would launch (`<bin>@<version>`).
|
|
39
51
|
* The daemon and every client compare it; a daemon running a different
|
|
@@ -864,6 +876,10 @@ export class EngineClient {
|
|
|
864
876
|
env: {
|
|
865
877
|
...process.env,
|
|
866
878
|
KIBI_ENGINE_PROTOCOL: String(ENGINE_PROTOCOL_VERSION),
|
|
879
|
+
// The daemon reports the versions of the client that
|
|
880
|
+
// started it, so this client and its own daemon agree even
|
|
881
|
+
// when the daemon entry is resolved from a bundled host.
|
|
882
|
+
KIBI_PACKAGE_VERSIONS: enginePackageVersions(),
|
|
867
883
|
},
|
|
868
884
|
});
|
|
869
885
|
await new Promise((resolve, reject) => {
|
|
@@ -978,7 +994,7 @@ export class EngineClient {
|
|
|
978
994
|
...limits,
|
|
979
995
|
id,
|
|
980
996
|
protocolVersion: ENGINE_PROTOCOL_VERSION,
|
|
981
|
-
packageVersions:
|
|
997
|
+
packageVersions: enginePackageVersions(),
|
|
982
998
|
prologIdentity: engineSwiplIdentity(),
|
|
983
999
|
workspaceRoot: this.workspaceRoot,
|
|
984
1000
|
branch: this.branch,
|
|
@@ -1092,7 +1108,7 @@ export class EngineClient {
|
|
|
1092
1108
|
method: "cancel",
|
|
1093
1109
|
cancelOf: requestId,
|
|
1094
1110
|
protocolVersion: ENGINE_PROTOCOL_VERSION,
|
|
1095
|
-
packageVersions:
|
|
1111
|
+
packageVersions: enginePackageVersions(),
|
|
1096
1112
|
prologIdentity: engineSwiplIdentity(),
|
|
1097
1113
|
workspaceRoot: this.workspaceRoot,
|
|
1098
1114
|
branch: this.branch,
|
|
@@ -1136,30 +1152,68 @@ export class EngineClient {
|
|
|
1136
1152
|
return null;
|
|
1137
1153
|
return parseEngineAttachmentIdentity(status.bindings.JsonString);
|
|
1138
1154
|
}
|
|
1139
|
-
|
|
1155
|
+
/** The live daemon's handshake: its SWI-Prolog and package versions. */
|
|
1156
|
+
async daemonHandshake() {
|
|
1140
1157
|
const reply = await this.request({
|
|
1141
1158
|
method: "handshake",
|
|
1142
1159
|
});
|
|
1143
|
-
return
|
|
1160
|
+
return {
|
|
1161
|
+
prologIdentity: typeof reply?.prologIdentity === "string" ? reply.prologIdentity : null,
|
|
1162
|
+
packageVersions: typeof reply?.packageVersions === "string"
|
|
1163
|
+
? reply.packageVersions
|
|
1164
|
+
: null,
|
|
1165
|
+
};
|
|
1166
|
+
}
|
|
1167
|
+
/**
|
|
1168
|
+
* The identity a live daemon reports, without starting one; null when no
|
|
1169
|
+
* daemon serves this workspace and branch. The connection is closed again.
|
|
1170
|
+
*/
|
|
1171
|
+
// implements REQ-engine-daemon-package-versions
|
|
1172
|
+
async inspectLiveDaemon() {
|
|
1173
|
+
const wasConnected = this.isRunning();
|
|
1174
|
+
if (!wasConnected)
|
|
1175
|
+
await this.connect(false);
|
|
1176
|
+
if (!this.isRunning())
|
|
1177
|
+
return null;
|
|
1178
|
+
try {
|
|
1179
|
+
return await this.daemonHandshake();
|
|
1180
|
+
}
|
|
1181
|
+
finally {
|
|
1182
|
+
if (!wasConnected)
|
|
1183
|
+
await this.terminate();
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
/** Why the live daemon may not serve this client, or null when it may. */
|
|
1187
|
+
async daemonRuntimeMismatch() {
|
|
1188
|
+
const daemon = await this.daemonHandshake();
|
|
1189
|
+
const packageVersions = enginePackageVersions();
|
|
1190
|
+
if (daemon.packageVersions !== packageVersions)
|
|
1191
|
+
return `Kibi engine is running other package versions (${daemon.packageVersions ?? "not reported"}) than this client (${packageVersions})`;
|
|
1192
|
+
if (daemon.prologIdentity !== engineSwiplIdentity())
|
|
1193
|
+
return `Kibi engine is running a different SWI-Prolog than this client resolved (${engineSwiplIdentity()})`;
|
|
1194
|
+
return null;
|
|
1144
1195
|
}
|
|
1145
1196
|
/**
|
|
1146
|
-
* A live daemon keeps the SWI-Prolog
|
|
1147
|
-
* resolves a different executable or
|
|
1148
|
-
* bundled package was upgraded, a
|
|
1197
|
+
* A live daemon keeps the SWI-Prolog and the package versions it was
|
|
1198
|
+
* started with. When this client resolves a different executable or
|
|
1199
|
+
* version (KIBI_SWIPL changed, the bundled package was upgraded, a
|
|
1200
|
+
* pre-handshake daemon) or carries other package versions (a daemon left
|
|
1201
|
+
* by another install, for example one a git hook started), the daemon is
|
|
1149
1202
|
* stopped and replaced; it is never reused.
|
|
1150
1203
|
*/
|
|
1151
|
-
// implements REQ-prolog-daemon-runtime-identity
|
|
1204
|
+
// implements REQ-prolog-daemon-runtime-identity, REQ-engine-daemon-package-versions
|
|
1152
1205
|
async reconcileRuntime() {
|
|
1153
1206
|
if (this.replacingStaleDaemon || this.socket === null)
|
|
1154
1207
|
return;
|
|
1155
|
-
if (await this.
|
|
1208
|
+
if ((await this.daemonRuntimeMismatch()) === null)
|
|
1156
1209
|
return;
|
|
1157
1210
|
this.replacingStaleDaemon = true;
|
|
1158
1211
|
try {
|
|
1159
1212
|
await this.shutdownConnectedDaemon();
|
|
1160
1213
|
await this.connect(true);
|
|
1161
|
-
|
|
1162
|
-
|
|
1214
|
+
const mismatch = await this.daemonRuntimeMismatch();
|
|
1215
|
+
if (mismatch !== null) {
|
|
1216
|
+
throw new Error(`${mismatch} after replacing it; run 'kibi engine stop' and retry`);
|
|
1163
1217
|
}
|
|
1164
1218
|
}
|
|
1165
1219
|
finally {
|
|
@@ -1577,6 +1631,7 @@ export async function runEngineDaemon(requestedOptions) {
|
|
|
1577
1631
|
await session.boot();
|
|
1578
1632
|
let attachedIdentity = readEngineAttachmentIdentity(branchPath);
|
|
1579
1633
|
const serverPrologIdentity = engineSwiplIdentity();
|
|
1634
|
+
const serverPackageVersions = enginePackageVersions();
|
|
1580
1635
|
mkdirSync(path.dirname(options.socketPath), { recursive: true, mode: 0o700 });
|
|
1581
1636
|
if (existsSync(options.socketPath)) {
|
|
1582
1637
|
const isLivePeerSignal = (error) => {
|
|
@@ -1739,23 +1794,22 @@ export async function runEngineDaemon(requestedOptions) {
|
|
|
1739
1794
|
if (request.protocolVersion !== ENGINE_PROTOCOL_VERSION) {
|
|
1740
1795
|
throw new Error(`Kibi engine protocol mismatch: client=${request.protocolVersion ?? "missing"}, server=${ENGINE_PROTOCOL_VERSION}`);
|
|
1741
1796
|
}
|
|
1742
|
-
const expectedPackages = process.env.KIBI_PACKAGE_VERSIONS;
|
|
1743
|
-
if (expectedPackages !== undefined &&
|
|
1744
|
-
request.packageVersions !== expectedPackages) {
|
|
1745
|
-
throw new Error(`Kibi engine package-version mismatch: client=${request.packageVersions ?? "missing"}, server=${expectedPackages}`);
|
|
1746
|
-
}
|
|
1747
1797
|
if (canonicalFilesystemPath(request.workspaceRoot ?? "") !==
|
|
1748
1798
|
options.workspaceRoot ||
|
|
1749
1799
|
request.branch !== options.branch) {
|
|
1750
1800
|
throw new Error("Kibi engine workspace identity mismatch");
|
|
1751
1801
|
}
|
|
1752
|
-
// A client
|
|
1753
|
-
//
|
|
1802
|
+
// A client from another install (other package versions) or one that
|
|
1803
|
+
// resolved a different Prolog must not be served by this daemon.
|
|
1804
|
+
// Handshake reports both identities and stop must still work so the
|
|
1754
1805
|
// client can replace the daemon.
|
|
1755
|
-
if (request.method !== "handshake" &&
|
|
1756
|
-
request.
|
|
1757
|
-
|
|
1758
|
-
|
|
1806
|
+
if (request.method !== "handshake" && request.method !== "stop") {
|
|
1807
|
+
if (request.packageVersions !== serverPackageVersions) {
|
|
1808
|
+
throw new Error(`Kibi engine package-version mismatch: client=${request.packageVersions ?? "missing"}, server=${serverPackageVersions}`);
|
|
1809
|
+
}
|
|
1810
|
+
if (request.prologIdentity !== serverPrologIdentity) {
|
|
1811
|
+
throw new Error(`Kibi engine SWI-Prolog mismatch: client=${request.prologIdentity ?? "missing"}, server=${serverPrologIdentity}`);
|
|
1812
|
+
}
|
|
1759
1813
|
}
|
|
1760
1814
|
if (!isEngineLifecycleRequest(request) && (await session.ensureLive())) {
|
|
1761
1815
|
// A recycled session re-read the store; nothing cached from the lost
|
|
@@ -2037,7 +2091,10 @@ export async function runEngineDaemon(requestedOptions) {
|
|
|
2037
2091
|
throw new Error("export.targetDirectory is required");
|
|
2038
2092
|
return prolog.query(`kb_storage_export('${quoteProlog(request.targetDirectory)}')`);
|
|
2039
2093
|
case "handshake":
|
|
2040
|
-
return {
|
|
2094
|
+
return {
|
|
2095
|
+
prologIdentity: serverPrologIdentity,
|
|
2096
|
+
packageVersions: serverPackageVersions,
|
|
2097
|
+
};
|
|
2041
2098
|
case "stop":
|
|
2042
2099
|
setImmediate(() => void shutdown());
|
|
2043
2100
|
return { stopped: true };
|
|
@@ -2134,7 +2191,7 @@ export async function runEngineDaemon(requestedOptions) {
|
|
|
2134
2191
|
id: request.id,
|
|
2135
2192
|
ok: false,
|
|
2136
2193
|
error: "Kibi engine is shutting down; request was not executed",
|
|
2137
|
-
serverPackageVersions
|
|
2194
|
+
serverPackageVersions,
|
|
2138
2195
|
});
|
|
2139
2196
|
return;
|
|
2140
2197
|
}
|
|
@@ -2149,7 +2206,7 @@ export async function runEngineDaemon(requestedOptions) {
|
|
|
2149
2206
|
id: request.id,
|
|
2150
2207
|
ok: false,
|
|
2151
2208
|
error: "Kibi engine request cancelled",
|
|
2152
|
-
serverPackageVersions
|
|
2209
|
+
serverPackageVersions,
|
|
2153
2210
|
});
|
|
2154
2211
|
return;
|
|
2155
2212
|
}
|
|
@@ -2159,7 +2216,7 @@ export async function runEngineDaemon(requestedOptions) {
|
|
|
2159
2216
|
id: request.id,
|
|
2160
2217
|
ok: true,
|
|
2161
2218
|
result,
|
|
2162
|
-
serverPackageVersions
|
|
2219
|
+
serverPackageVersions,
|
|
2163
2220
|
});
|
|
2164
2221
|
}
|
|
2165
2222
|
catch (error) {
|
|
@@ -2167,7 +2224,7 @@ export async function runEngineDaemon(requestedOptions) {
|
|
|
2167
2224
|
id: request.id,
|
|
2168
2225
|
ok: false,
|
|
2169
2226
|
error: error instanceof Error ? error.message : String(error),
|
|
2170
|
-
serverPackageVersions
|
|
2227
|
+
serverPackageVersions,
|
|
2171
2228
|
});
|
|
2172
2229
|
}
|
|
2173
2230
|
finally {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../../src/operations/bootstrap/generate.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AAWjF,OAAO,KAAK,EACV,SAAS,EACT,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAGpB,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,SAAS,gBAAgB,EAAE,EACpC,WAAW,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,GACzC,SAAS,gBAAgB,EAAE,CAI7B;AA+BD,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,SAAS,SAAS,EAAE,EAC3B,WAAW,EAAE,WAAW,CAAC,MAAM,CAAC,EAChC,WAAW,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,EAC1C,OAAO,EAAE,MAAM,GACd;IACD,QAAQ,CAAC,UAAU,EAAE,SAAS,SAAS,EAAE,CAAC;IAC1C,QAAQ,CAAC,UAAU,EAAE,SAAS,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC;IAClE,QAAQ,CAAC,iBAAiB,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACxD,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;CACzC,CA6IA;AA+JD,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,iBAAiB,EACvB,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,mBAAmB,CAAC,
|
|
1
|
+
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../../src/operations/bootstrap/generate.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AAWjF,OAAO,KAAK,EACV,SAAS,EACT,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAGpB,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,SAAS,gBAAgB,EAAE,EACpC,WAAW,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,GACzC,SAAS,gBAAgB,EAAE,CAI7B;AA+BD,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,SAAS,SAAS,EAAE,EAC3B,WAAW,EAAE,WAAW,CAAC,MAAM,CAAC,EAChC,WAAW,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,EAC1C,OAAO,EAAE,MAAM,GACd;IACD,QAAQ,CAAC,UAAU,EAAE,SAAS,SAAS,EAAE,CAAC;IAC1C,QAAQ,CAAC,UAAU,EAAE,SAAS,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC;IAClE,QAAQ,CAAC,iBAAiB,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACxD,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;CACzC,CA6IA;AA+JD,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,iBAAiB,EACvB,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,mBAAmB,CAAC,CAiH9B"}
|
|
@@ -8,7 +8,7 @@ import { buildBootstrapCandidates } from "./candidates.js";
|
|
|
8
8
|
import { discoverBootstrap } from "./discovery.js";
|
|
9
9
|
import { buildIntentClaimCandidates } from "./intent-claims.js";
|
|
10
10
|
import { normalizeBootstrapContext, presentBootstrap } from "./presentation.js";
|
|
11
|
-
import { SubjectKeyRegistry } from "./requirement-claims.js";
|
|
11
|
+
import { SubjectKeyRegistry, shareSubjectFacts } from "./requirement-claims.js";
|
|
12
12
|
import { validateBootstrapPayload } from "./validation.js";
|
|
13
13
|
export function filterSourceOnlySignals(signals, entityTypes) {
|
|
14
14
|
return entityTypes && entityTypes.length > 0
|
|
@@ -340,6 +340,8 @@ export async function executePlanBootstrap(args, context) {
|
|
|
340
340
|
};
|
|
341
341
|
const filteredSignals = filterSourceOnlySignals([...built.sourceOnlySignals, ...claimed.sourceOnlySignals], args.entityTypes);
|
|
342
342
|
const selected = selectBootstrapCandidates([...built.candidates, ...claimed.candidates].filter((candidate) => candidate.confidence >= minConfidence), existingIds, args.entityTypes, maxCandidates);
|
|
343
|
+
// Claims about the same subject share one subject fact.
|
|
344
|
+
const shared = shareSubjectFacts(selected.candidates);
|
|
343
345
|
const ignored = discovery.ignoredSources.map((sourcePath) => ({
|
|
344
346
|
candidateId: "",
|
|
345
347
|
reason: "ignored_source",
|
|
@@ -355,7 +357,7 @@ export async function executePlanBootstrap(args, context) {
|
|
|
355
357
|
...(args.bootstrapContext
|
|
356
358
|
? { bootstrapContext: args.bootstrapContext }
|
|
357
359
|
: {}),
|
|
358
|
-
candidates:
|
|
360
|
+
candidates: shared.candidates,
|
|
359
361
|
sourceOnlySignals: [
|
|
360
362
|
...filteredSignals,
|
|
361
363
|
...filterSourceOnlySignals(selected.sourceOnlySignals, args.entityTypes),
|
|
@@ -377,6 +379,7 @@ export async function executePlanBootstrap(args, context) {
|
|
|
377
379
|
...claimed.diagnostics,
|
|
378
380
|
...built.diagnostics,
|
|
379
381
|
...selected.diagnostics,
|
|
382
|
+
...shared.diagnostics,
|
|
380
383
|
],
|
|
381
384
|
});
|
|
382
385
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type SemanticClaim } from "../../utils/strict-modeling.js";
|
|
2
|
+
import type { Candidate } from "./types.js";
|
|
2
3
|
export declare function normalizeClaimStatement(statement: string): string;
|
|
3
4
|
export declare function claimFor(statement: string, source: string, confidence: number, provenance: string): SemanticClaim | null;
|
|
4
5
|
export type SubjectKeyResolution = {
|
|
@@ -61,4 +62,18 @@ export declare function planSubjectKey(subject: string, propertyKey: string, com
|
|
|
61
62
|
readonly resolution: SubjectKeyResolution;
|
|
62
63
|
readonly diagnostics: string[];
|
|
63
64
|
};
|
|
65
|
+
/**
|
|
66
|
+
* One subject fact per subject_key in a bootstrap plan. The registry keeps
|
|
67
|
+
* different subjects on different keys, so claims that share a key name the
|
|
68
|
+
* same subject: the first selected claim's subject fact is kept, every later
|
|
69
|
+
* requirement links to it through constrains instead of minting another
|
|
70
|
+
* subject fact (which subject-key-identity would report), and the later
|
|
71
|
+
* sources' provenance is added to the kept fact's tags and body. Each shared
|
|
72
|
+
* key is reported as a subject-key-shared diagnostic. The result depends only
|
|
73
|
+
* on the candidate order, so the plan hash stays deterministic.
|
|
74
|
+
*/
|
|
75
|
+
export declare function shareSubjectFacts(candidates: readonly Candidate[]): {
|
|
76
|
+
readonly candidates: Candidate[];
|
|
77
|
+
readonly diagnostics: string[];
|
|
78
|
+
};
|
|
64
79
|
//# sourceMappingURL=requirement-claims.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"requirement-claims.d.ts","sourceRoot":"","sources":["../../../src/operations/bootstrap/requirement-claims.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,aAAa,
|
|
1
|
+
{"version":3,"file":"requirement-claims.d.ts","sourceRoot":"","sources":["../../../src/operations/bootstrap/requirement-claims.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,aAAa,EAInB,MAAM,gCAAgC,CAAC;AACxC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAG5C,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAKjE;AAED,wBAAgB,QAAQ,CACtB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,aAAa,GAAG,IAAI,CA0DtB;AAED,MAAM,MAAM,oBAAoB,GAC5B;IACE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAClB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,4DAA4D;IAC5D,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC,GACD;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAWpD,2DAA2D;AAC3D,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAClC,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAsGnC;;;;;;;;GAQG;AAEH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CA4B3D;AAmBD;;;;;;;;;;GAUG;AAEH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,MAAM,GACjB,oBAAoB,CA2BtB;AAED;;;;;GAKG;AAEH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA6B;IACpD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA6B;IAEtD,gFAAgF;IAChF,MAAM,CAAC,UAAU,EAAE;QACjB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;QAC5B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;KACjC,GAAG;QAAE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE;CAyBpE;AAMD;;;GAGG;AAEH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,QAAQ,EAAE,kBAAkB,GAAG,SAAS,EACxC,QAAQ,EAAE,MAAM,GACf;IACD,QAAQ,CAAC,UAAU,EAAE,oBAAoB,CAAC;IAC1C,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC;CAChC,CAyBA;AAuCD;;;;;;;;;GASG;AAEH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,SAAS,SAAS,EAAE,GAAG;IACnE,QAAQ,CAAC,UAAU,EAAE,SAAS,EAAE,CAAC;IACjC,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC;CAChC,CAwEA"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import { isConventionalSubjectKey, normalizeSubjectKey, } from "../../utils/strict-modeling.js";
|
|
2
|
+
import { isConventionalSubjectKey, normalizeSourceKey, normalizeSubjectKey, } from "../../utils/strict-modeling.js";
|
|
3
3
|
// implements REQ-KIBI-BOOTSTRAP-PLAN
|
|
4
4
|
export function normalizeClaimStatement(statement) {
|
|
5
5
|
return statement
|
|
@@ -321,3 +321,102 @@ export function planSubjectKey(subject, propertyKey, component, registry, locati
|
|
|
321
321
|
diagnostics,
|
|
322
322
|
};
|
|
323
323
|
}
|
|
324
|
+
function stepProperties(step) {
|
|
325
|
+
return step.properties !== null && typeof step.properties === "object"
|
|
326
|
+
? step.properties
|
|
327
|
+
: {};
|
|
328
|
+
}
|
|
329
|
+
function subjectStepKey(step) {
|
|
330
|
+
const properties = stepProperties(step);
|
|
331
|
+
return step.type === "fact" &&
|
|
332
|
+
properties.fact_kind === "subject" &&
|
|
333
|
+
typeof properties.subject_key === "string" &&
|
|
334
|
+
typeof step.id === "string"
|
|
335
|
+
? properties.subject_key
|
|
336
|
+
: null;
|
|
337
|
+
}
|
|
338
|
+
function retarget(relationships, renamed) {
|
|
339
|
+
return relationships.map((relationship) => {
|
|
340
|
+
const to = renamed.get(relationship.to);
|
|
341
|
+
return to === undefined ? relationship : { ...relationship, to };
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
function retargetStep(step, renamed) {
|
|
345
|
+
if (!Array.isArray(step.relationships))
|
|
346
|
+
return step;
|
|
347
|
+
const relationships = step.relationships;
|
|
348
|
+
return { ...step, relationships: retarget(relationships, renamed) };
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* One subject fact per subject_key in a bootstrap plan. The registry keeps
|
|
352
|
+
* different subjects on different keys, so claims that share a key name the
|
|
353
|
+
* same subject: the first selected claim's subject fact is kept, every later
|
|
354
|
+
* requirement links to it through constrains instead of minting another
|
|
355
|
+
* subject fact (which subject-key-identity would report), and the later
|
|
356
|
+
* sources' provenance is added to the kept fact's tags and body. Each shared
|
|
357
|
+
* key is reported as a subject-key-shared diagnostic. The result depends only
|
|
358
|
+
* on the candidate order, so the plan hash stays deterministic.
|
|
359
|
+
*/
|
|
360
|
+
// implements REQ-bootstrap-subject-fact-shared
|
|
361
|
+
export function shareSubjectFacts(candidates) {
|
|
362
|
+
const owners = new Map();
|
|
363
|
+
const renamed = new Map();
|
|
364
|
+
candidates.forEach((candidate, candidateIndex) => {
|
|
365
|
+
for (const step of candidate.applyPlan) {
|
|
366
|
+
const key = subjectStepKey(step);
|
|
367
|
+
if (key === null)
|
|
368
|
+
continue;
|
|
369
|
+
const factId = String(step.id);
|
|
370
|
+
const source = String(stepProperties(step).text_ref ?? candidate.sourcePath);
|
|
371
|
+
const owner = owners.get(key);
|
|
372
|
+
if (owner === undefined) {
|
|
373
|
+
owners.set(key, { factId, candidateIndex, sources: [source] });
|
|
374
|
+
continue;
|
|
375
|
+
}
|
|
376
|
+
if (owner.factId === factId)
|
|
377
|
+
continue;
|
|
378
|
+
renamed.set(factId, owner.factId);
|
|
379
|
+
if (!owner.sources.includes(source))
|
|
380
|
+
owner.sources.push(source);
|
|
381
|
+
}
|
|
382
|
+
});
|
|
383
|
+
if (renamed.size === 0)
|
|
384
|
+
return { candidates: [...candidates], diagnostics: [] };
|
|
385
|
+
const shared = [...owners.entries()].filter(([, owner]) => owner.sources.length > 1);
|
|
386
|
+
const sharedFacts = new Map(shared.map(([key, owner]) => [owner.factId, { key, owner }]));
|
|
387
|
+
const result = candidates.map((candidate) => ({
|
|
388
|
+
...candidate,
|
|
389
|
+
relationships: retarget(candidate.relationships, renamed),
|
|
390
|
+
applyPlan: candidate.applyPlan
|
|
391
|
+
.filter((step) => !renamed.has(String(step.id)))
|
|
392
|
+
.map((step) => {
|
|
393
|
+
const sharing = sharedFacts.get(String(step.id));
|
|
394
|
+
const retargeted = retargetStep(step, renamed);
|
|
395
|
+
if (sharing === undefined || subjectStepKey(step) === null)
|
|
396
|
+
return retargeted;
|
|
397
|
+
const properties = stepProperties(step);
|
|
398
|
+
const tags = Array.isArray(properties.tags)
|
|
399
|
+
? properties.tags.map(String)
|
|
400
|
+
: [];
|
|
401
|
+
return {
|
|
402
|
+
...retargeted,
|
|
403
|
+
properties: {
|
|
404
|
+
...properties,
|
|
405
|
+
tags: [
|
|
406
|
+
...new Set([
|
|
407
|
+
...tags,
|
|
408
|
+
...sharing.owner.sources.map((source) => `provenance:${normalizeSourceKey(source)}`),
|
|
409
|
+
]),
|
|
410
|
+
],
|
|
411
|
+
},
|
|
412
|
+
document: {
|
|
413
|
+
body: `Subject ${sharing.key}, shared by the requirements bootstrap planned from ${sharing.owner.sources.join(", ")}. Each of them links to this fact through constrains.\n`,
|
|
414
|
+
},
|
|
415
|
+
};
|
|
416
|
+
}),
|
|
417
|
+
}));
|
|
418
|
+
return {
|
|
419
|
+
candidates: result,
|
|
420
|
+
diagnostics: shared.map(([key, owner]) => `subject-key-shared: claims at ${owner.sources.join(", ")} name the same subject ${key}, so the plan writes one subject fact ${owner.factId} and links every requirement to it through constrains.`),
|
|
421
|
+
};
|
|
422
|
+
}
|
|
@@ -5,6 +5,19 @@ export declare function buildSuggestion(schema: PredicateSchemaCandidate, text:
|
|
|
5
5
|
applicabilityScore?: number;
|
|
6
6
|
scoreComponents?: PredicateScoreComponents;
|
|
7
7
|
explicitSubject?: boolean;
|
|
8
|
+
/**
|
|
9
|
+
* The subject_key of the subject fact the requirement constrains. It
|
|
10
|
+
* binds the schema's `subject` argument (provenance `requirement`) unless
|
|
11
|
+
* the caller bound that argument or passed subjectHint.
|
|
12
|
+
*/
|
|
13
|
+
requirementSubject?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Every subject_key the requirement constrains. When there are any, the
|
|
16
|
+
* predicate must be about one of them (its `subject` argument or, for a
|
|
17
|
+
* schema without one, its subject_key) or kb_check reports
|
|
18
|
+
* strict-req-fact-pairing; an unpaired candidate stays incomplete.
|
|
19
|
+
*/
|
|
20
|
+
constrainedSubjects?: readonly string[];
|
|
8
21
|
}): PredicateSuggestion;
|
|
9
22
|
export declare function buildPredicateApplyPlan(suggestion: PredicateSuggestion, args: SuggestPredicatesArgs): Array<Record<string, unknown>>;
|
|
10
23
|
export declare function buildRelationshipPlan(factId: string | undefined, requirementId: string | undefined, claimText?: string, existingLogicClaims?: readonly string[]): Record<string, unknown> | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"predicate-applyplan.d.ts","sourceRoot":"","sources":["../../../src/operations/modeling/predicate-applyplan.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAEV,wBAAwB,EACxB,wBAAwB,EACxB,mBAAmB,EACnB,0BAA0B,EAC1B,qBAAqB,EACtB,MAAM,sBAAsB,CAAC;AAQ9B,wBAAgB,eAAe,CAC7B,MAAM,EAAE,wBAAwB,EAChC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,gBAAgB,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM,EACvD,YAAY,CAAC,EAAE,QAAQ,GAAG,MAAM,EAChC,WAAW,CAAC,EAAE;IACZ,WAAW,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;IACtC,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,eAAe,CAAC,EAAE,wBAAwB,CAAC;IAC3C,eAAe,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"predicate-applyplan.d.ts","sourceRoot":"","sources":["../../../src/operations/modeling/predicate-applyplan.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAEV,wBAAwB,EACxB,wBAAwB,EACxB,mBAAmB,EACnB,0BAA0B,EAC1B,qBAAqB,EACtB,MAAM,sBAAsB,CAAC;AAQ9B,wBAAgB,eAAe,CAC7B,MAAM,EAAE,wBAAwB,EAChC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,gBAAgB,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM,EACvD,YAAY,CAAC,EAAE,QAAQ,GAAG,MAAM,EAChC,WAAW,CAAC,EAAE;IACZ,WAAW,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;IACtC,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,eAAe,CAAC,EAAE,wBAAwB,CAAC;IAC3C,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACzC,GACA,mBAAmB,CA4JrB;AAGD,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,mBAAmB,EAC/B,IAAI,EAAE,qBAAqB,GAC1B,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CA0ChC;AAGD,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,SAAS,CAAC,EAAE,MAAM,EAClB,mBAAmB,GAAE,SAAS,MAAM,EAAO,GAC1C,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAuBhC;AAoBD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,qBAAqB,GAC1B,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAwBhC;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GACd,0BAA0B,CAoE5B"}
|