kibi-cli 2.19.0 → 2.20.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-operation-metadata.d.ts +1 -1
- package/dist/cli-operation-metadata.js +1 -1
- package/dist/cli-register-maintenance.js +1 -1
- package/dist/commands/engine.d.ts +2 -1
- package/dist/commands/engine.d.ts.map +1 -1
- package/dist/commands/engine.js +6 -1
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +24 -6
- package/dist/intent-search.d.ts +7 -0
- package/dist/intent-search.d.ts.map +1 -1
- package/dist/intent-search.js +66 -4
- package/dist/operations/modeling/predicate-applicability.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-applicability.js +10 -4
- package/dist/operations/modeling/predicate-applyplan.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-applyplan.js +16 -5
- package/dist/operations/modeling/predicate-catalog-4.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-catalog-4.js +3 -0
- package/dist/operations/modeling/predicate-inference-1.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-inference-1.js +34 -7
- package/dist/operations/modeling/predicate-score-3.js +1 -1
- package/dist/operations/modeling/predicate-types.d.ts +6 -0
- 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 +111 -0
- package/dist/operations/mutation/types.d.ts +26 -0
- package/dist/operations/mutation/types.d.ts.map +1 -1
- package/dist/operations/mutation/upsert.d.ts.map +1 -1
- package/dist/operations/mutation/upsert.js +8 -2
- package/dist/operations/mutation/validate-upsert.d.ts.map +1 -1
- package/dist/operations/mutation/validate-upsert.js +116 -4
- package/dist/operations/mutation/warnings.d.ts +10 -0
- package/dist/operations/mutation/warnings.d.ts.map +1 -1
- package/dist/operations/mutation/warnings.js +26 -0
- package/dist/operations/mutation/what-if.d.ts +25 -0
- package/dist/operations/mutation/what-if.d.ts.map +1 -0
- package/dist/operations/mutation/what-if.js +59 -0
- package/dist/operations/planning/compile-intent.d.ts +15 -20
- package/dist/operations/planning/compile-intent.d.ts.map +1 -1
- package/dist/operations/planning/compile-intent.js +64 -53
- package/dist/operations/semantic-advisor/clauses.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/clauses.js +8 -7
- package/dist/prolog/janitor.d.ts +26 -2
- package/dist/prolog/janitor.d.ts.map +1 -1
- package/dist/prolog/janitor.js +55 -3
- package/dist/prolog/store-lock.d.ts +28 -3
- package/dist/prolog/store-lock.d.ts.map +1 -1
- package/dist/prolog/store-lock.js +103 -12
- package/dist/public/operations/catalog.d.ts +47 -3
- package/dist/public/operations/catalog.d.ts.map +1 -1
- package/dist/public/operations/check-executor.d.ts +2 -2
- package/dist/public/operations/check-executor.d.ts.map +1 -1
- package/dist/public/operations/check-executor.js +35 -0
- package/dist/public/operations/check-format-shared.d.ts +16 -0
- package/dist/public/operations/check-format-shared.d.ts.map +1 -1
- package/dist/public/operations/check-format-shared.js +19 -0
- package/dist/public/operations/contracts.d.ts.map +1 -1
- package/dist/public/operations/contracts.js +10 -0
- package/dist/public/operations/discovery-executors.d.ts +3 -0
- package/dist/public/operations/discovery-executors.d.ts.map +1 -1
- package/dist/public/operations/discovery-executors.js +7 -2
- package/dist/public/operations/specs/composite.d.ts +1 -1
- package/dist/public/operations/specs/composite.js +1 -1
- package/dist/public/operations/specs/discovery.d.ts +2 -2
- package/dist/public/operations/specs/discovery.d.ts.map +1 -1
- package/dist/public/operations/specs/discovery.js +2 -2
- package/dist/public/operations/specs/upsert.d.ts +44 -0
- package/dist/public/operations/specs/upsert.d.ts.map +1 -1
- package/dist/public/operations/specs/upsert.js +14 -0
- package/dist/public/skills/kibi-usage/SKILL.md +36 -1
- package/dist/public/skills/kibi-usage/resources/fact-lanes.md +4 -2
- package/dist/search-answer.d.ts +13 -0
- package/dist/search-answer.d.ts.map +1 -1
- package/dist/search-answer.js +45 -4
- package/dist/utils/branch-store.d.ts.map +1 -1
- package/dist/utils/branch-store.js +4 -2
- package/package.json +3 -3
- package/src/public/operations/check-executor.ts +44 -1
- package/src/public/operations/check-format-shared.ts +35 -1
- package/src/public/operations/contracts.ts +11 -0
- package/src/public/operations/discovery-executors.ts +12 -2
- package/src/public/operations/specs/composite.ts +1 -1
- package/src/public/operations/specs/discovery.ts +3 -2
- package/src/public/operations/specs/upsert.ts +15 -0
- package/src/public/skills/kibi-usage/SKILL.md +36 -1
- package/src/public/skills/kibi-usage/resources/fact-lanes.md +4 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compile-intent.d.ts","sourceRoot":"","sources":["../../../src/operations/planning/compile-intent.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EAEpB,MAAM,wBAAwB,CAAC;AAMhC,OAAO,KAAK,EACV,gBAAgB,EAEjB,MAAM,0CAA0C,CAAC;
|
|
1
|
+
{"version":3,"file":"compile-intent.d.ts","sourceRoot":"","sources":["../../../src/operations/planning/compile-intent.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,17 +3,18 @@ import path from "node:path";
|
|
|
3
3
|
import { renderRequirementBody, reviseRequirementBody, } from "../../entity-body-context.js";
|
|
4
4
|
import { executeIntentSearch, } from "../../intent-search.js";
|
|
5
5
|
import { publicCapabilityStamp } from "../../plugins/compose-semantic-classifier.js";
|
|
6
|
-
import { normalizeEntityId } from "../../prolog/codec.js";
|
|
7
6
|
import { loadEntities } from "../../public/operations/discovery-entities.js";
|
|
8
7
|
import { executeStatus } from "../../public/operations/discovery-executors.js";
|
|
9
8
|
import { readAuthoredEntity } from "../../public/operations/entity-context.js";
|
|
10
9
|
import { buildWhatIfAnalysisGoal } from "../mutation/contradictions.js";
|
|
11
10
|
import { canonicalSourcePath } from "../mutation/source-authoring.js";
|
|
12
11
|
import { validateUpsertInput } from "../mutation/validation.js";
|
|
12
|
+
import { isBlockingWitness, parseWhatIfAnalysis, } from "../mutation/what-if.js";
|
|
13
13
|
import { analyzeSemanticAdvisorInputWithPlugins } from "../semantic-advisor/plugin-orchestration.js";
|
|
14
14
|
import { canonicalize } from "../semantic-advisor/shared.js";
|
|
15
15
|
// implements REQ-kibi-change-to-proof-plan-compiler-v2
|
|
16
16
|
export const COMPILE_PLAN_VERSION = "kibi.compile-plan.v1";
|
|
17
|
+
export { isBlockingWitness, parseWhatIfAnalysis } from "../mutation/what-if.js";
|
|
17
18
|
// implements REQ-kibi-change-to-proof-plan-compiler-v2
|
|
18
19
|
export function compilePlanHash(plan) {
|
|
19
20
|
const { planHash: _ignored, ...body } = plan;
|
|
@@ -342,58 +343,6 @@ export function planWhatIfGoal(steps, now) {
|
|
|
342
343
|
};
|
|
343
344
|
}));
|
|
344
345
|
}
|
|
345
|
-
function whatIfWitness(witness) {
|
|
346
|
-
return {
|
|
347
|
-
...witness,
|
|
348
|
-
requirements: Array.isArray(witness.requirements)
|
|
349
|
-
? witness.requirements.map((id) => normalizeEntityId(String(id)))
|
|
350
|
-
: [],
|
|
351
|
-
reason: text(witness.reason),
|
|
352
|
-
status: text(witness.status) || "contradiction",
|
|
353
|
-
...(typeof witness.kind === "string" ? { kind: witness.kind } : {}),
|
|
354
|
-
};
|
|
355
|
-
}
|
|
356
|
-
function whatIfWitnesses(value) {
|
|
357
|
-
return (Array.isArray(value) ? value.filter(isRecord) : []).map(whatIfWitness);
|
|
358
|
-
}
|
|
359
|
-
// implements REQ-kibi-truthful-consistency
|
|
360
|
-
/**
|
|
361
|
-
* Parse checks:what_if_analysis_json/2 output. The binding is a quoted Prolog
|
|
362
|
-
* string, so the JSON may arrive encoded once more as a JSON string. A bare
|
|
363
|
-
* witness array (the what_if_contradiction_witnesses_json/2 shape) carries no
|
|
364
|
-
* current-KB baseline, so every witness in it is treated as introduced.
|
|
365
|
-
* Returns null when the output cannot be read.
|
|
366
|
-
*/
|
|
367
|
-
export function parseWhatIfAnalysis(raw) {
|
|
368
|
-
if (typeof raw !== "string")
|
|
369
|
-
return null;
|
|
370
|
-
let parsed;
|
|
371
|
-
try {
|
|
372
|
-
parsed = JSON.parse(raw);
|
|
373
|
-
if (typeof parsed === "string")
|
|
374
|
-
parsed = JSON.parse(parsed);
|
|
375
|
-
}
|
|
376
|
-
catch {
|
|
377
|
-
return null;
|
|
378
|
-
}
|
|
379
|
-
if (Array.isArray(parsed)) {
|
|
380
|
-
const after = whatIfWitnesses(parsed);
|
|
381
|
-
return { after, introduced: after, removed: [], unchanged: [] };
|
|
382
|
-
}
|
|
383
|
-
if (!isRecord(parsed))
|
|
384
|
-
return null;
|
|
385
|
-
return {
|
|
386
|
-
after: whatIfWitnesses(parsed.after),
|
|
387
|
-
introduced: whatIfWitnesses(parsed.introduced),
|
|
388
|
-
removed: whatIfWitnesses(parsed.removed),
|
|
389
|
-
unchanged: whatIfWitnesses(parsed.unchanged),
|
|
390
|
-
};
|
|
391
|
-
}
|
|
392
|
-
// implements REQ-kibi-truthful-consistency
|
|
393
|
-
/** Blocking: a proven contradiction or an infeasible success scenario. */
|
|
394
|
-
export function isBlockingWitness(witness) {
|
|
395
|
-
return witness.status === "contradiction" || witness.status === "infeasible";
|
|
396
|
-
}
|
|
397
346
|
// implements REQ-kibi-truthful-consistency
|
|
398
347
|
// Check the KB as it would be after this plan, not the KB as it is: stage every
|
|
399
348
|
// planned step in a rolled-back transaction and compare its contradiction and
|
|
@@ -608,6 +557,68 @@ function draftSteps(requirementId, scenarios, tests) {
|
|
|
608
557
|
}
|
|
609
558
|
return { steps, diagnostics };
|
|
610
559
|
}
|
|
560
|
+
// implements REQ-model-what-if-planned-facts
|
|
561
|
+
/**
|
|
562
|
+
* A hash-bound compile plan for a grounding kb_model planned: the predicate
|
|
563
|
+
* fact and the requirement upsert that links it, validated and applied
|
|
564
|
+
* together by kb_apply_plan. Its contradiction analysis is the what-if over
|
|
565
|
+
* the current KB plus these steps, so a decision conflict with a fact that is
|
|
566
|
+
* already stored is reported here, before any write, and blocks the plan.
|
|
567
|
+
*/
|
|
568
|
+
export async function compileGroundingPlan(context, prolog, input) {
|
|
569
|
+
const now = context.clock();
|
|
570
|
+
const statusResult = await executeStatus({}, context);
|
|
571
|
+
const status = statusResult.structuredContent;
|
|
572
|
+
if (!status)
|
|
573
|
+
throw new Error("Grounding plan failed: status query returned no payload");
|
|
574
|
+
const contradictions = await contradictionAnalysis(prolog, input.requirementId, input.steps, now);
|
|
575
|
+
const diagnostics = [];
|
|
576
|
+
let statusValue = contradictions.outcome === "conflict" ? "blocked" : "ready";
|
|
577
|
+
let planSteps = [...input.steps];
|
|
578
|
+
if (statusValue === "ready") {
|
|
579
|
+
try {
|
|
580
|
+
planSteps = await withDocumentTargets(context, prolog, input.steps, { id: input.requirementId }, now);
|
|
581
|
+
}
|
|
582
|
+
catch (error) {
|
|
583
|
+
statusValue = "needs_resolution";
|
|
584
|
+
diagnostics.push(`A plan step cannot be applied as written: ${error instanceof Error ? error.message : String(error)}`);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
// The hash binds the plan as it travels: a step field left undefined
|
|
588
|
+
// (kb_model's optional source) is absent on the wire, so it is absent here.
|
|
589
|
+
const planBody = JSON.parse(JSON.stringify({
|
|
590
|
+
version: COMPILE_PLAN_VERSION,
|
|
591
|
+
status: statusValue,
|
|
592
|
+
expected: {
|
|
593
|
+
branch: status.branch,
|
|
594
|
+
kbSnapshotId: status.snapshotId,
|
|
595
|
+
workspaceSnapshot: status.proofSnapshot ?? "unknown",
|
|
596
|
+
sourceHashes: {},
|
|
597
|
+
},
|
|
598
|
+
target: {
|
|
599
|
+
mode: "update",
|
|
600
|
+
requirementId: input.requirementId,
|
|
601
|
+
selectionReason: `kb_model mode predicates grounds claim ${input.claimKey} of the supplied requirementId.`,
|
|
602
|
+
},
|
|
603
|
+
discovery: { candidates: [], abstained: true },
|
|
604
|
+
propositions: [
|
|
605
|
+
{
|
|
606
|
+
claimKey: input.claimKey,
|
|
607
|
+
text: input.text,
|
|
608
|
+
span: { start: 0, end: Buffer.byteLength(input.text, "utf8") },
|
|
609
|
+
disposition: "predicate",
|
|
610
|
+
status: "modeled",
|
|
611
|
+
origin: "deterministic",
|
|
612
|
+
},
|
|
613
|
+
],
|
|
614
|
+
contradictionAnalysis: contradictions,
|
|
615
|
+
proposals: [],
|
|
616
|
+
steps: planSteps,
|
|
617
|
+
sourceWrites: [],
|
|
618
|
+
diagnostics,
|
|
619
|
+
}));
|
|
620
|
+
return { ...planBody, planHash: compilePlanHash(planBody) };
|
|
621
|
+
}
|
|
611
622
|
// implements REQ-kibi-change-to-proof-plan-compiler-v2
|
|
612
623
|
export async function executeCompileIntent(args, context) {
|
|
613
624
|
const intent = requiredIntent(args);
|
|
@@ -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;AAmBH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE3D;AAQD,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,QAAQ,CAAC,EAAE,MAAM,GAChB,WAAW,GAAG,aAAa,CAG7B;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAW7D;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIrD;AA4BD,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,EACZ,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,GAClC,SAAS,cAAc,EAAE,CA4B3B"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
// An explicit grant ("are allowed to", "is permitted to"
|
|
3
|
-
// permission just as "denied"/"forbidden"
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
// unmodeled normative
|
|
8
|
-
|
|
2
|
+
// An explicit grant ("are allowed to", "is permitted to", "have permission
|
|
3
|
+
// to", "are entitled to") asserts a permission just as "denied"/"forbidden"
|
|
4
|
+
// assert a prohibition. Bare "can", "may" and "are able to" are accepted by
|
|
5
|
+
// the predicate applicability gate but not here: stored clause roles are
|
|
6
|
+
// derived from this pattern, and "it can be restricted to …" style capability
|
|
7
|
+
// prose would turn existing descriptive inventories into unmodeled normative
|
|
8
|
+
// clauses ("must be able to" is already normative through "must").
|
|
9
|
+
const NORMATIVE_ASSERTION_PATTERN = /\b(?:must|shall|should|required|requires?|may\s+only|(?:is|are)\s+(?:not\s+)?(?:allowed|permitted|entitled)\s+to|ha(?:s|ve)\s+(?:no\s+)?permission\s+to|permitted|may\s+(?:not\s+)?(?:be\s+)?\w+\s+only\b|may\s+(?:have\s+)?(?:at\s+most|at\s+least|exactly|no\s+more\s+than|up\s+to)|only\s+.+?\s+(?:may|can)|must\s+not|shall\s+not|cannot|can't|denied|forbidden|prohibited|(?:is|are|be|become|becomes|remain|remains)\s+(?:invalid|rejected|prohibited|forbidden)|(?:reject|rejects|rejected|rejection)\s+(?:invalid|unresolved|ambiguous)|fail(?:s|ed)?\s+(?:clearly|explicitly|with)|expires?\s+(?:after|within|in)|failure\s+(?:behavior|policy|outcome)|error\s+(?:handling|behavior|policy|outcome)|required\s+outcome|defaults?\s+to)\b/i;
|
|
9
10
|
// Conditional/temporal cues help discover clauses but do not by themselves
|
|
10
11
|
// turn explanatory or subjective context into an asserted obligation.
|
|
11
12
|
const NORMATIVE_PATTERN = new RegExp(`${NORMATIVE_ASSERTION_PATTERN.source}|\\b(?:before|unless|when|if)\\b`, "i");
|
package/dist/prolog/janitor.d.ts
CHANGED
|
@@ -25,7 +25,20 @@ export interface SocketFinding {
|
|
|
25
25
|
readonly holderState: StoreLockHolderState;
|
|
26
26
|
readonly action: "clean" | "keep";
|
|
27
27
|
}
|
|
28
|
-
|
|
28
|
+
/**
|
|
29
|
+
* A stale-lock takeover record past its visibility window: kb_status no
|
|
30
|
+
* longer reports it, so it is only clutter in the branch store.
|
|
31
|
+
*/
|
|
32
|
+
export interface TakeoverRecordFinding {
|
|
33
|
+
readonly kind: "takeover-record";
|
|
34
|
+
readonly storePath: string;
|
|
35
|
+
readonly recordPath: string;
|
|
36
|
+
/** When the takeover happened (the file's mtime for an unreadable record). */
|
|
37
|
+
readonly at: string;
|
|
38
|
+
readonly brokenPid?: number;
|
|
39
|
+
readonly action: "clean";
|
|
40
|
+
}
|
|
41
|
+
export type JanitorFinding = StoreLockFinding | SocketFinding | TakeoverRecordFinding;
|
|
29
42
|
export interface JanitorOptions {
|
|
30
43
|
/** Branch stores live under <workspaceRoot>/.kb/branches. */
|
|
31
44
|
readonly workspaceRoot: string;
|
|
@@ -35,16 +48,27 @@ export interface JanitorOptions {
|
|
|
35
48
|
readonly all?: boolean;
|
|
36
49
|
/** Execute cleanups; when false the scan only reports (dry run). */
|
|
37
50
|
readonly apply?: boolean;
|
|
51
|
+
/** Clock for the takeover-record age; defaults to the current time. */
|
|
52
|
+
readonly now?: Date;
|
|
38
53
|
}
|
|
39
54
|
/** Scan one branch store's ownership journal and clean stale artifacts. */
|
|
40
55
|
export declare function sweepStoreLock(storePath: string, apply: boolean): StoreLockFinding | null;
|
|
41
56
|
/** Scan all branch stores under <workspaceRoot>/.kb/branches. */
|
|
42
57
|
export declare function sweepWorkspaceStoreLocks(options: JanitorOptions): StoreLockFinding[];
|
|
58
|
+
/**
|
|
59
|
+
* Report, and with apply delete, the stale-lock takeover records under
|
|
60
|
+
* <workspaceRoot>/.kb/branches that are older than the window kb_status
|
|
61
|
+
* shows them for. Fresh records are kept and not reported.
|
|
62
|
+
*/
|
|
63
|
+
export declare function sweepStoreLockTakeoverRecords(options: JanitorOptions): TakeoverRecordFinding[];
|
|
43
64
|
/**
|
|
44
65
|
* Sweep runtime-directory daemon sockets. A socket is stale when its pid
|
|
45
66
|
* file records a dead process or a connect attempt is refused.
|
|
46
67
|
*/
|
|
47
68
|
export declare function sweepRuntimeSockets(options: JanitorOptions): SocketFinding[];
|
|
48
|
-
/**
|
|
69
|
+
/**
|
|
70
|
+
* Full janitor sweep across branch stores, expired takeover records and
|
|
71
|
+
* (optionally) runtime sockets.
|
|
72
|
+
*/
|
|
49
73
|
export declare function runJanitor(options: JanitorOptions): JanitorFinding[];
|
|
50
74
|
//# sourceMappingURL=janitor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"janitor.d.ts","sourceRoot":"","sources":["../../src/prolog/janitor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"janitor.d.ts","sourceRoot":"","sources":["../../src/prolog/janitor.ts"],"names":[],"mappings":"AA0BA,OAAO,EAGL,KAAK,oBAAoB,EAM1B,MAAM,iBAAiB,CAAC;AAEzB;;;;;;;;GAQG;AAGH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,oBAAoB,CAAC;IAC3C,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,gBAAgB,GAAG,MAAM,CAAC;CACtD;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,oBAAoB,CAAC;IAC3C,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC;CACnC;AAED;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,MAAM,cAAc,GACtB,gBAAgB,GAChB,aAAa,GACb,qBAAqB,CAAC;AAE1B,MAAM,WAAW,cAAc;IAC7B,6DAA6D;IAC7D,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,8DAA8D;IAC9D,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,kEAAkE;IAClE,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;IACvB,oEAAoE;IACpE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,uEAAuE;IACvE,QAAQ,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC;CACrB;AAED,2EAA2E;AAE3E,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,OAAO,GACb,gBAAgB,GAAG,IAAI,CA+CzB;AAED,iEAAiE;AAEjE,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,cAAc,GACtB,gBAAgB,EAAE,CAepB;AAED;;;;GAIG;AAEH,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,cAAc,GACtB,qBAAqB,EAAE,CAmCzB;AAED;;;GAGG;AAEH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,cAAc,GAAG,aAAa,EAAE,CA8C5E;AAED;;;GAGG;AAEH,wBAAgB,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,cAAc,EAAE,CAMpE"}
|
package/dist/prolog/janitor.js
CHANGED
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
You should have received a copy of the GNU Affero General Public License
|
|
16
16
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
17
|
*/
|
|
18
|
-
import { existsSync, readFileSync, readdirSync, rmSync } from "node:fs";
|
|
18
|
+
import { existsSync, readFileSync, readdirSync, rmSync, statSync, } from "node:fs";
|
|
19
19
|
import { join } from "node:path";
|
|
20
|
-
import { breakStoreLock, classifyStoreLockHolder, isProcessAlive, readStoreLockOwner, } from "./store-lock.js";
|
|
20
|
+
import { STORE_LOCK_TAKEOVER_FILE, STORE_LOCK_TAKEOVER_VISIBLE_MS, breakStoreLock, classifyStoreLockHolder, isProcessAlive, readStoreLockOwner, readStoreLockTakeover, } from "./store-lock.js";
|
|
21
21
|
/** Scan one branch store's ownership journal and clean stale artifacts. */
|
|
22
22
|
// implements REQ-core-journaled-engine-persistence
|
|
23
23
|
export function sweepStoreLock(storePath, apply) {
|
|
@@ -90,6 +90,54 @@ export function sweepWorkspaceStoreLocks(options) {
|
|
|
90
90
|
}
|
|
91
91
|
return findings;
|
|
92
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* Report, and with apply delete, the stale-lock takeover records under
|
|
95
|
+
* <workspaceRoot>/.kb/branches that are older than the window kb_status
|
|
96
|
+
* shows them for. Fresh records are kept and not reported.
|
|
97
|
+
*/
|
|
98
|
+
// implements REQ-core-journaled-engine-persistence
|
|
99
|
+
export function sweepStoreLockTakeoverRecords(options) {
|
|
100
|
+
const branchesDir = join(options.workspaceRoot, ".kb", "branches");
|
|
101
|
+
if (!existsSync(branchesDir))
|
|
102
|
+
return [];
|
|
103
|
+
const now = (options.now ?? new Date()).getTime();
|
|
104
|
+
const findings = [];
|
|
105
|
+
for (const entry of readdirSync(branchesDir)) {
|
|
106
|
+
const storePath = join(branchesDir, entry);
|
|
107
|
+
const recordPath = join(storePath, STORE_LOCK_TAKEOVER_FILE);
|
|
108
|
+
let at;
|
|
109
|
+
let brokenPid = null;
|
|
110
|
+
try {
|
|
111
|
+
const record = readStoreLockTakeover(storePath);
|
|
112
|
+
if (record !== null) {
|
|
113
|
+
at = record.at;
|
|
114
|
+
brokenPid = record.brokenPid;
|
|
115
|
+
}
|
|
116
|
+
else if (existsSync(recordPath)) {
|
|
117
|
+
at = statSync(recordPath).mtime.toISOString();
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
if (now - Date.parse(at) <= STORE_LOCK_TAKEOVER_VISIBLE_MS)
|
|
127
|
+
continue;
|
|
128
|
+
if (options.apply === true)
|
|
129
|
+
rmSync(recordPath, { force: true });
|
|
130
|
+
findings.push({
|
|
131
|
+
kind: "takeover-record",
|
|
132
|
+
storePath,
|
|
133
|
+
recordPath,
|
|
134
|
+
at,
|
|
135
|
+
...(brokenPid !== null ? { brokenPid } : {}),
|
|
136
|
+
action: "clean",
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
return findings;
|
|
140
|
+
}
|
|
93
141
|
/**
|
|
94
142
|
* Sweep runtime-directory daemon sockets. A socket is stale when its pid
|
|
95
143
|
* file records a dead process or a connect attempt is refused.
|
|
@@ -144,11 +192,15 @@ export function sweepRuntimeSockets(options) {
|
|
|
144
192
|
}
|
|
145
193
|
return findings;
|
|
146
194
|
}
|
|
147
|
-
/**
|
|
195
|
+
/**
|
|
196
|
+
* Full janitor sweep across branch stores, expired takeover records and
|
|
197
|
+
* (optionally) runtime sockets.
|
|
198
|
+
*/
|
|
148
199
|
// implements REQ-core-journaled-engine-persistence
|
|
149
200
|
export function runJanitor(options) {
|
|
150
201
|
return [
|
|
151
202
|
...sweepWorkspaceStoreLocks(options),
|
|
203
|
+
...sweepStoreLockTakeoverRecords(options),
|
|
152
204
|
...sweepRuntimeSockets(options),
|
|
153
205
|
];
|
|
154
206
|
}
|
|
@@ -66,12 +66,37 @@ export interface StoreLockTakeoverDecision {
|
|
|
66
66
|
readonly action: "break" | "surface";
|
|
67
67
|
readonly reason: string;
|
|
68
68
|
}
|
|
69
|
+
/** Reason prefix of a takeover that removed lock artifacts copied in. */
|
|
70
|
+
export declare const FOREIGN_STORE_LOCK_REASON_PREFIX = "journal belongs to another workspace";
|
|
71
|
+
/**
|
|
72
|
+
* The recorded root of an ownership journal that another workspace wrote,
|
|
73
|
+
* or null when the journal belongs to this store (or cannot be judged).
|
|
74
|
+
*
|
|
75
|
+
* kb.pl records the attached store directory as `workspaceRoot`; a journal
|
|
76
|
+
* may also name a workspace root. Either way it is foreign only when the
|
|
77
|
+
* workspace it names differs from the one that owns `storePath`, which
|
|
78
|
+
* happens when a `.kb` was copied (`cp -a`, a backup restore) while another
|
|
79
|
+
* workspace's engine held its store. An advisory lock is never inherited by
|
|
80
|
+
* a copied file, so nobody holds this store on the journal's behalf.
|
|
81
|
+
*
|
|
82
|
+
* The journal is judged only when that is safe: when the store's `rdf/lock`
|
|
83
|
+
* names a different pid than the journal, a process of this workspace has
|
|
84
|
+
* locked the store since the copy; when the recorded path no longer exists,
|
|
85
|
+
* the store may have been moved here while its holder still runs; and a
|
|
86
|
+
* recorded path that is this very directory (a bind mount) is not another
|
|
87
|
+
* workspace. Each of those returns null.
|
|
88
|
+
*/
|
|
89
|
+
export declare function foreignStoreLockJournalRoot(owner: PrologStoreLockOwner | null, storePath: string): string | null;
|
|
69
90
|
/**
|
|
70
91
|
* Decide whether a store-locked failure may be auto-healed. Only a provably
|
|
71
|
-
* dead holder (or a holder from a previous boot) is broken
|
|
72
|
-
*
|
|
92
|
+
* dead holder (or a holder from a previous boot) is broken, and, when the
|
|
93
|
+
* caller names the store being attached, a journal copied in from another
|
|
94
|
+
* workspace; live or unknown holders are surfaced so the operator can close
|
|
95
|
+
* the real session.
|
|
73
96
|
*/
|
|
74
|
-
export declare function decideStoreLockTakeover(owner: PrologStoreLockOwner | null
|
|
97
|
+
export declare function decideStoreLockTakeover(owner: PrologStoreLockOwner | null, options?: {
|
|
98
|
+
readonly storePath?: string;
|
|
99
|
+
}): StoreLockTakeoverDecision;
|
|
75
100
|
export interface StoreLockRetryContext {
|
|
76
101
|
readonly query: (goal: string) => Promise<QueryResult>;
|
|
77
102
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store-lock.d.ts","sourceRoot":"","sources":["../../src/prolog/store-lock.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"store-lock.d.ts","sourceRoot":"","sources":["../../src/prolog/store-lock.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,KAAK,EAAqB,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAgBhF,8EAA8E;AAC9E,wBAAgB,aAAa,IAAI,MAAM,GAAG,IAAI,CAa7C;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAUnD;AAED,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;AAEzE,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,oBAAoB,GAAG,IAAI,GACjC,oBAAoB,CAYtB;AAED;;;;;GAKG;AAEH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,GAChB;IAAE,KAAK,EAAE,oBAAoB,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CA4B7D;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAWzD;AAED,qEAAqE;AACrE,eAAO,MAAM,wBAAwB,6BAA6B,CAAC;AAEnE;;;;;GAKG;AACH,eAAO,MAAM,8BAA8B,QAAsB,CAAC;AAElE,MAAM,MAAM,uBAAuB,GAAG,QAAQ,CAAC;IAC7C,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd,CAAC,CAAC;AAEH;;;GAGG;AAEH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,MAAM,EAAE,MAAM,EACd,EAAE,GAAE,IAAiB,GACpB,IAAI,CAUN;AAED,iFAAiF;AAEjF,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,MAAM,GAChB,uBAAuB,GAAG,IAAI,CAmBhC;AAED,sEAAsE;AAEtE,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQ9D;AAED;;;;;;;;;;;;;;;GAeG;AAEH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,IAAI,CAerE;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,yEAAyE;AACzE,eAAO,MAAM,gCAAgC,yCACL,CAAC;AAoCzC;;;;;;;;;;;;;;;;;GAiBG;AAEH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,oBAAoB,GAAG,IAAI,EAClC,SAAS,EAAE,MAAM,GAChB,MAAM,GAAG,IAAI,CAcf;AAED;;;;;;GAMG;AAEH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,oBAAoB,GAAG,IAAI,EAClC,OAAO,GAAE;IAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GAC5C,yBAAyB,CA+B3B;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;CACxD;AAED;;;;;;GAMG;AAEH,wBAAsB,iCAAiC,CACrD,MAAM,EAAE,qBAAqB,EAC7B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,WAAW,CAAC,CAmCtB"}
|
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
You should have received a copy of the GNU Affero General Public License
|
|
16
16
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
17
|
*/
|
|
18
|
-
import { existsSync, rmSync, writeFileSync } from "node:fs";
|
|
18
|
+
import { existsSync, realpathSync, rmSync, statSync, writeFileSync, } from "node:fs";
|
|
19
19
|
import { readFileSync } from "node:fs";
|
|
20
|
-
import { dirname, join } from "node:path";
|
|
20
|
+
import { basename, dirname, join } from "node:path";
|
|
21
21
|
import { escapeAtom } from "./codec.js";
|
|
22
22
|
/**
|
|
23
23
|
* Stewardship for the branch-store lock.
|
|
@@ -216,25 +216,114 @@ export function noteDeadHolderBeforeAttach(kbPath) {
|
|
|
216
216
|
: lockPid !== null
|
|
217
217
|
? { pid: lockPid }
|
|
218
218
|
: null;
|
|
219
|
-
const decision = decideStoreLockTakeover(owner);
|
|
219
|
+
const decision = decideStoreLockTakeover(owner, { storePath: kbPath });
|
|
220
220
|
if (decision.action !== "break")
|
|
221
221
|
return () => undefined;
|
|
222
222
|
const brokenPid = owner?.pid ?? null;
|
|
223
223
|
return () => recordStoreLockTakeover(kbPath, brokenPid, decision.reason);
|
|
224
224
|
}
|
|
225
|
+
/** Reason prefix of a takeover that removed lock artifacts copied in. */
|
|
226
|
+
export const FOREIGN_STORE_LOCK_REASON_PREFIX = "journal belongs to another workspace";
|
|
227
|
+
function existingRealPath(pathname) {
|
|
228
|
+
try {
|
|
229
|
+
return realpathSync(pathname);
|
|
230
|
+
}
|
|
231
|
+
catch {
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
function sameDirectory(left, right) {
|
|
236
|
+
try {
|
|
237
|
+
const a = statSync(left);
|
|
238
|
+
const b = statSync(right);
|
|
239
|
+
return a.dev === b.dev && a.ino === b.ino;
|
|
240
|
+
}
|
|
241
|
+
catch {
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* The workspace that owns a branch store: `<root>/.kb/branches/<key>` (a
|
|
247
|
+
* legacy key may span several segments) is owned by `<root>`. Null for a
|
|
248
|
+
* path outside that layout.
|
|
249
|
+
*/
|
|
250
|
+
function owningWorkspaceRoot(storePath) {
|
|
251
|
+
let current = storePath;
|
|
252
|
+
for (;;) {
|
|
253
|
+
const parent = dirname(current);
|
|
254
|
+
if (parent === current)
|
|
255
|
+
return null;
|
|
256
|
+
if (basename(parent) === "branches" && basename(dirname(parent)) === ".kb")
|
|
257
|
+
return dirname(dirname(parent));
|
|
258
|
+
current = parent;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* The recorded root of an ownership journal that another workspace wrote,
|
|
263
|
+
* or null when the journal belongs to this store (or cannot be judged).
|
|
264
|
+
*
|
|
265
|
+
* kb.pl records the attached store directory as `workspaceRoot`; a journal
|
|
266
|
+
* may also name a workspace root. Either way it is foreign only when the
|
|
267
|
+
* workspace it names differs from the one that owns `storePath`, which
|
|
268
|
+
* happens when a `.kb` was copied (`cp -a`, a backup restore) while another
|
|
269
|
+
* workspace's engine held its store. An advisory lock is never inherited by
|
|
270
|
+
* a copied file, so nobody holds this store on the journal's behalf.
|
|
271
|
+
*
|
|
272
|
+
* The journal is judged only when that is safe: when the store's `rdf/lock`
|
|
273
|
+
* names a different pid than the journal, a process of this workspace has
|
|
274
|
+
* locked the store since the copy; when the recorded path no longer exists,
|
|
275
|
+
* the store may have been moved here while its holder still runs; and a
|
|
276
|
+
* recorded path that is this very directory (a bind mount) is not another
|
|
277
|
+
* workspace. Each of those returns null.
|
|
278
|
+
*/
|
|
279
|
+
// implements REQ-core-journaled-engine-persistence
|
|
280
|
+
export function foreignStoreLockJournalRoot(owner, storePath) {
|
|
281
|
+
const recorded = owner?.workspaceRoot;
|
|
282
|
+
if (recorded === undefined || recorded === "")
|
|
283
|
+
return null;
|
|
284
|
+
const store = existingRealPath(storePath);
|
|
285
|
+
if (store === null)
|
|
286
|
+
return null;
|
|
287
|
+
const ownWorkspace = owningWorkspaceRoot(store);
|
|
288
|
+
if (ownWorkspace === null)
|
|
289
|
+
return null;
|
|
290
|
+
const lockPid = readRdfLockPid(join(storePath, "rdf", "lock"));
|
|
291
|
+
if (lockPid !== null && lockPid !== owner?.pid)
|
|
292
|
+
return null;
|
|
293
|
+
const recordedPath = existingRealPath(recorded);
|
|
294
|
+
if (recordedPath === null || recordedPath === store)
|
|
295
|
+
return null;
|
|
296
|
+
if (sameDirectory(recordedPath, store))
|
|
297
|
+
return null;
|
|
298
|
+
const recordedWorkspace = owningWorkspaceRoot(recordedPath) ?? recordedPath;
|
|
299
|
+
return recordedWorkspace === ownWorkspace ? null : recorded;
|
|
300
|
+
}
|
|
225
301
|
/**
|
|
226
302
|
* Decide whether a store-locked failure may be auto-healed. Only a provably
|
|
227
|
-
* dead holder (or a holder from a previous boot) is broken
|
|
228
|
-
*
|
|
303
|
+
* dead holder (or a holder from a previous boot) is broken, and, when the
|
|
304
|
+
* caller names the store being attached, a journal copied in from another
|
|
305
|
+
* workspace; live or unknown holders are surfaced so the operator can close
|
|
306
|
+
* the real session.
|
|
229
307
|
*/
|
|
230
|
-
|
|
308
|
+
// implements REQ-core-journaled-engine-persistence
|
|
309
|
+
export function decideStoreLockTakeover(owner, options = {}) {
|
|
231
310
|
const state = classifyStoreLockHolder(owner);
|
|
311
|
+
if (state === "dead") {
|
|
312
|
+
return {
|
|
313
|
+
action: "break",
|
|
314
|
+
reason: `recorded holder pid ${owner?.pid ?? "?"} is no longer running`,
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
const foreignRoot = options.storePath === undefined
|
|
318
|
+
? null
|
|
319
|
+
: foreignStoreLockJournalRoot(owner, options.storePath);
|
|
320
|
+
if (foreignRoot !== null) {
|
|
321
|
+
return {
|
|
322
|
+
action: "break",
|
|
323
|
+
reason: `${FOREIGN_STORE_LOCK_REASON_PREFIX} ${foreignRoot}`,
|
|
324
|
+
};
|
|
325
|
+
}
|
|
232
326
|
switch (state) {
|
|
233
|
-
case "dead":
|
|
234
|
-
return {
|
|
235
|
-
action: "break",
|
|
236
|
-
reason: `recorded holder pid ${owner?.pid ?? "?"} is no longer running`,
|
|
237
|
-
};
|
|
238
327
|
case "unknown":
|
|
239
328
|
return {
|
|
240
329
|
action: "surface",
|
|
@@ -261,7 +350,9 @@ export async function retryAttachAfterBreakingStaleLock(prolog, kbPath, failed)
|
|
|
261
350
|
const storeLocked = record?.storeLocked;
|
|
262
351
|
if (storeLocked === undefined)
|
|
263
352
|
return failed;
|
|
264
|
-
const decision = decideStoreLockTakeover(storeLocked.owner
|
|
353
|
+
const decision = decideStoreLockTakeover(storeLocked.owner, {
|
|
354
|
+
storePath: kbPath,
|
|
355
|
+
});
|
|
265
356
|
if (decision.action !== "break") {
|
|
266
357
|
const holderSummary = storeLocked.owner === null
|
|
267
358
|
? decision.reason
|
|
@@ -190,8 +190,8 @@ export declare const OPERATION_CATALOG: readonly [{
|
|
|
190
190
|
readonly limit: {
|
|
191
191
|
readonly type: "integer";
|
|
192
192
|
readonly minimum: 0;
|
|
193
|
-
readonly default:
|
|
194
|
-
readonly description: "Optional max rows to return after ranking. Default:
|
|
193
|
+
readonly default: 10;
|
|
194
|
+
readonly description: "Optional max rows to return after ranking. Default: 10; raise it or page with offset when the answer layer is not enough.";
|
|
195
195
|
};
|
|
196
196
|
readonly offset: {
|
|
197
197
|
readonly type: "integer";
|
|
@@ -718,7 +718,7 @@ export declare const OPERATION_CATALOG: readonly [{
|
|
|
718
718
|
}, {
|
|
719
719
|
readonly name: "kb_model";
|
|
720
720
|
readonly cliName: "model";
|
|
721
|
-
readonly description: "Turn requirement prose into checkable structure without writing the KB. mode:analyze returns the semantic advisor receipt: the clause ledger, what is grounded, what is ambiguous and suggested modeling (pass clauses for compound prose and optional typed kibi.logic.v1 interpretations). mode:requirement converts one claim (subjectKey, propertyKey, operator, value, or typed logic) into a strict-lane write set and applyPlan. mode:predicates ranks ontology predicate schemas and returns an applicable predicate-fact plan only for reviewed bindings, otherwise an ontology-gap observation.
|
|
721
|
+
readonly description: "Turn requirement prose into checkable structure without writing the KB. mode:analyze returns the semantic advisor receipt: the clause ledger, what is grounded, what is ambiguous and suggested modeling (pass clauses for compound prose and optional typed kibi.logic.v1 interpretations). mode:requirement converts one claim (subjectKey, propertyKey, operator, value, or typed logic) into a strict-lane write set and applyPlan. mode:predicates ranks ontology predicate schemas and returns an applicable predicate-fact plan only for reviewed bindings, otherwise an ontology-gap observation. With requirementId, mode:predicates also returns a hash-bound plan (fact write plus requires_predicate link) for kb_apply_plan, whose contradictionAnalysis is the what-if over the current KB; other returned plans apply with kb_upsert, and kb_upsert dryRun with plannedFacts previews a requirement before its facts exist.";
|
|
722
722
|
readonly businessInputSchema: {
|
|
723
723
|
readonly type: "object";
|
|
724
724
|
readonly required: readonly ["mode", "text"];
|
|
@@ -1689,6 +1689,50 @@ export declare const OPERATION_CATALOG: readonly [{
|
|
|
1689
1689
|
readonly default: false;
|
|
1690
1690
|
readonly description: "Validate the payload and return schema/modeling errors, a normalized preview and the semantic advisor receipt without writing the KB or workspace. Use it as the preflight before the real write.";
|
|
1691
1691
|
};
|
|
1692
|
+
readonly plannedFacts: {
|
|
1693
|
+
readonly type: "array";
|
|
1694
|
+
readonly description: "dryRun only. Fact upsert payloads (type, id, properties, optional relationships) that will be written before this payload, typically the applyPlan entries kb_model returned. They are validated in order and staged with the payload, so a requires_predicate or requires_property target that does not exist yet resolves, its claim_key is read from the plan, and the contradiction preview runs against the KB as it would be after the whole batch (result: stagedFacts, whatIf). A conflict the batch would introduce, such as an allow and a deny permission_rule on the same key, is refused as the commit would refuse it. Rejected without dryRun: write the facts first.";
|
|
1695
|
+
readonly items: {
|
|
1696
|
+
readonly type: "object";
|
|
1697
|
+
readonly required: readonly ["type", "id", "properties"];
|
|
1698
|
+
readonly properties: {
|
|
1699
|
+
readonly type: {
|
|
1700
|
+
readonly type: "string";
|
|
1701
|
+
readonly const: "fact";
|
|
1702
|
+
};
|
|
1703
|
+
readonly id: {
|
|
1704
|
+
readonly type: "string";
|
|
1705
|
+
readonly minLength: 1;
|
|
1706
|
+
};
|
|
1707
|
+
readonly properties: {
|
|
1708
|
+
readonly type: "object";
|
|
1709
|
+
};
|
|
1710
|
+
readonly relationships: {
|
|
1711
|
+
readonly type: "array";
|
|
1712
|
+
readonly description: "Optional relationship rows to create in the same call. For requirement encoding, prefer `constrains` + `requires_property` for strict property facts or `requires_predicate` for ontology predicate facts. Side effect: asserts edges in KB.";
|
|
1713
|
+
readonly items: {
|
|
1714
|
+
readonly type: "object";
|
|
1715
|
+
readonly required: readonly ["type", "from", "to"];
|
|
1716
|
+
readonly properties: {
|
|
1717
|
+
readonly type: {
|
|
1718
|
+
readonly type: "string";
|
|
1719
|
+
readonly enum: readonly ["depends_on", "specified_by", "verified_by", "validates", "implements", "covered_by", "executable_for", "constrained_by", "constrains", "requires_property", "requires_predicate", "requires_rule", "guards", "publishes", "consumes", "supersedes", "restates", "assumes", "exempts", "relates_to"];
|
|
1720
|
+
readonly description: "Relationship type enum. Use only supported values. Direction semantics follow KB model (e.g., implements symbol->req, verified_by req/scenario->test, executable_for symbol->test).";
|
|
1721
|
+
};
|
|
1722
|
+
readonly from: {
|
|
1723
|
+
readonly type: "string";
|
|
1724
|
+
readonly description: "Source entity ID (must exist). Example: 'SYM-login-handler'.";
|
|
1725
|
+
};
|
|
1726
|
+
readonly to: {
|
|
1727
|
+
readonly type: "string";
|
|
1728
|
+
readonly description: "Target entity ID (must exist). Example: 'REQ-cli-gc'.";
|
|
1729
|
+
};
|
|
1730
|
+
};
|
|
1731
|
+
};
|
|
1732
|
+
};
|
|
1733
|
+
};
|
|
1734
|
+
};
|
|
1735
|
+
};
|
|
1692
1736
|
readonly document: {
|
|
1693
1737
|
readonly type: "object";
|
|
1694
1738
|
readonly additionalProperties: false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../../src/public/operations/catalog.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EACV,aAAa,EACb,aAAa,EACb,qBAAqB,EACtB,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,iBAAiB
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../../src/public/operations/catalog.ts"],"names":[],"mappings":"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"}
|