kibi-cli 2.18.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 +2 -2
- package/dist/cli-operation-metadata.js +2 -2
- package/dist/cli-register-maintenance.js +1 -1
- package/dist/commands/doctor.js +11 -5
- 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/commands/sync/manifest.d.ts +10 -0
- package/dist/commands/sync/manifest.d.ts.map +1 -1
- package/dist/commands/sync/manifest.js +27 -0
- package/dist/commands/sync/untracked-targets.d.ts +17 -0
- package/dist/commands/sync/untracked-targets.d.ts.map +1 -1
- package/dist/commands/sync/untracked-targets.js +43 -1
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +51 -2
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +33 -22
- 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/source-authoring.d.ts.map +1 -1
- package/dist/operations/mutation/source-authoring.js +5 -12
- 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 +47 -3
- package/dist/prolog/store-lock.d.ts.map +1 -1
- package/dist/prolog/store-lock.js +148 -11
- package/dist/proof/inspect.d.ts +1 -1
- package/dist/proof/inspect.d.ts.map +1 -1
- package/dist/proof/inspect.js +9 -2
- package/dist/public/operations/catalog.d.ts +97 -4
- 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 +11 -4
- package/dist/public/operations/discovery-executors.d.ts +39 -0
- package/dist/public/operations/discovery-executors.d.ts.map +1 -1
- package/dist/public/operations/discovery-executors.js +368 -3
- 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 +52 -3
- package/dist/public/operations/specs/discovery.d.ts.map +1 -1
- package/dist/public/operations/specs/discovery.js +58 -3
- 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 +44 -1
- package/dist/public/skills/kibi-usage/resources/fact-lanes.md +4 -2
- package/dist/runtime/cli-runtime.d.ts.map +1 -1
- package/dist/runtime/cli-runtime.js +7 -2
- package/dist/search-answer.d.ts +25 -3
- package/dist/search-answer.d.ts.map +1 -1
- package/dist/search-answer.js +96 -8
- package/dist/utils/branch-store.d.ts.map +1 -1
- package/dist/utils/branch-store.js +4 -2
- package/dist/utils/content-freshness.d.ts.map +1 -1
- package/dist/utils/content-freshness.js +12 -2
- package/dist/utils/symbol-manifest-layout.d.ts +9 -0
- package/dist/utils/symbol-manifest-layout.d.ts.map +1 -0
- package/dist/utils/symbol-manifest-layout.js +18 -0
- 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 +15 -4
- package/src/public/operations/discovery-executors.ts +484 -2
- package/src/public/operations/specs/composite.ts +1 -1
- package/src/public/operations/specs/discovery.ts +70 -3
- package/src/public/operations/specs/upsert.ts +15 -0
- package/src/public/skills/kibi-usage/SKILL.md +44 -1
- package/src/public/skills/kibi-usage/resources/fact-lanes.md +4 -2
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
|
}
|
|
@@ -43,16 +43,60 @@ export type StoreLockTakeoverRecord = Readonly<{
|
|
|
43
43
|
export declare function recordStoreLockTakeover(storePath: string, brokenPid: number | null, reason: string, at?: Date): void;
|
|
44
44
|
/** The last takeover record of a branch store, or null when none is readable. */
|
|
45
45
|
export declare function readStoreLockTakeover(storePath: string): StoreLockTakeoverRecord | null;
|
|
46
|
+
/** The holder pid an rdf_persistency `lock` file records, or null. */
|
|
47
|
+
export declare function readRdfLockPid(lockPath: string): number | null;
|
|
48
|
+
/**
|
|
49
|
+
* Note, before `kb_attach`, whether a dead holder left this branch store
|
|
50
|
+
* locked, and return the step that records the takeover once the attach has
|
|
51
|
+
* succeeded.
|
|
52
|
+
*
|
|
53
|
+
* rdf_persistency locks the store with an OS advisory lock that the kernel
|
|
54
|
+
* releases when its holder dies, so a killed engine never makes the next
|
|
55
|
+
* attach fail with `store_locked`: the attach simply takes the store over.
|
|
56
|
+
* The only trace is the `rdf/lock` file, which SWI deletes on every detach
|
|
57
|
+
* and halt; one that is still present was left by a holder that crashed or
|
|
58
|
+
* was killed. Its holder (the ownership journal when it names the same
|
|
59
|
+
* process, which adds the boot id, else the lock file's pid) is classified
|
|
60
|
+
* the same way a `store_locked` failure is. The returned step is a no-op
|
|
61
|
+
* unless that holder is provably dead; callers run it only after a
|
|
62
|
+
* successful attach, which proves the holder no longer held the lock.
|
|
63
|
+
*/
|
|
64
|
+
export declare function noteDeadHolderBeforeAttach(kbPath: string): () => void;
|
|
46
65
|
export interface StoreLockTakeoverDecision {
|
|
47
66
|
readonly action: "break" | "surface";
|
|
48
67
|
readonly reason: string;
|
|
49
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;
|
|
50
90
|
/**
|
|
51
91
|
* Decide whether a store-locked failure may be auto-healed. Only a provably
|
|
52
|
-
* dead holder (or a holder from a previous boot) is broken
|
|
53
|
-
*
|
|
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.
|
|
54
96
|
*/
|
|
55
|
-
export declare function decideStoreLockTakeover(owner: PrologStoreLockOwner | null
|
|
97
|
+
export declare function decideStoreLockTakeover(owner: PrologStoreLockOwner | null, options?: {
|
|
98
|
+
readonly storePath?: string;
|
|
99
|
+
}): StoreLockTakeoverDecision;
|
|
56
100
|
export interface StoreLockRetryContext {
|
|
57
101
|
readonly query: (goal: string) => Promise<QueryResult>;
|
|
58
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.
|
|
@@ -176,19 +176,154 @@ export function readStoreLockTakeover(storePath) {
|
|
|
176
176
|
return null;
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
|
+
/** The holder pid an rdf_persistency `lock` file records, or null. */
|
|
180
|
+
// implements REQ-core-journaled-engine-persistence
|
|
181
|
+
export function readRdfLockPid(lockPath) {
|
|
182
|
+
try {
|
|
183
|
+
const match = /pid\((\d+)\)/.exec(readFileSync(lockPath, "utf8"));
|
|
184
|
+
const pid = Number.parseInt(match?.[1] ?? "", 10);
|
|
185
|
+
return Number.isInteger(pid) && pid > 0 ? pid : null;
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Note, before `kb_attach`, whether a dead holder left this branch store
|
|
193
|
+
* locked, and return the step that records the takeover once the attach has
|
|
194
|
+
* succeeded.
|
|
195
|
+
*
|
|
196
|
+
* rdf_persistency locks the store with an OS advisory lock that the kernel
|
|
197
|
+
* releases when its holder dies, so a killed engine never makes the next
|
|
198
|
+
* attach fail with `store_locked`: the attach simply takes the store over.
|
|
199
|
+
* The only trace is the `rdf/lock` file, which SWI deletes on every detach
|
|
200
|
+
* and halt; one that is still present was left by a holder that crashed or
|
|
201
|
+
* was killed. Its holder (the ownership journal when it names the same
|
|
202
|
+
* process, which adds the boot id, else the lock file's pid) is classified
|
|
203
|
+
* the same way a `store_locked` failure is. The returned step is a no-op
|
|
204
|
+
* unless that holder is provably dead; callers run it only after a
|
|
205
|
+
* successful attach, which proves the holder no longer held the lock.
|
|
206
|
+
*/
|
|
207
|
+
// implements REQ-core-journaled-engine-persistence
|
|
208
|
+
export function noteDeadHolderBeforeAttach(kbPath) {
|
|
209
|
+
const lockPath = join(kbPath, "rdf", "lock");
|
|
210
|
+
if (!existsSync(lockPath))
|
|
211
|
+
return () => undefined;
|
|
212
|
+
const lockPid = readRdfLockPid(lockPath);
|
|
213
|
+
const journal = readStoreLockOwner(kbPath)?.owner ?? null;
|
|
214
|
+
const owner = journal !== null && (lockPid === null || journal.pid === lockPid)
|
|
215
|
+
? journal
|
|
216
|
+
: lockPid !== null
|
|
217
|
+
? { pid: lockPid }
|
|
218
|
+
: null;
|
|
219
|
+
const decision = decideStoreLockTakeover(owner, { storePath: kbPath });
|
|
220
|
+
if (decision.action !== "break")
|
|
221
|
+
return () => undefined;
|
|
222
|
+
const brokenPid = owner?.pid ?? null;
|
|
223
|
+
return () => recordStoreLockTakeover(kbPath, brokenPid, decision.reason);
|
|
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
|
+
}
|
|
179
301
|
/**
|
|
180
302
|
* Decide whether a store-locked failure may be auto-healed. Only a provably
|
|
181
|
-
* dead holder (or a holder from a previous boot) is broken
|
|
182
|
-
*
|
|
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.
|
|
183
307
|
*/
|
|
184
|
-
|
|
308
|
+
// implements REQ-core-journaled-engine-persistence
|
|
309
|
+
export function decideStoreLockTakeover(owner, options = {}) {
|
|
185
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
|
+
}
|
|
186
326
|
switch (state) {
|
|
187
|
-
case "dead":
|
|
188
|
-
return {
|
|
189
|
-
action: "break",
|
|
190
|
-
reason: `recorded holder pid ${owner?.pid ?? "?"} is no longer running`,
|
|
191
|
-
};
|
|
192
327
|
case "unknown":
|
|
193
328
|
return {
|
|
194
329
|
action: "surface",
|
|
@@ -215,7 +350,9 @@ export async function retryAttachAfterBreakingStaleLock(prolog, kbPath, failed)
|
|
|
215
350
|
const storeLocked = record?.storeLocked;
|
|
216
351
|
if (storeLocked === undefined)
|
|
217
352
|
return failed;
|
|
218
|
-
const decision = decideStoreLockTakeover(storeLocked.owner
|
|
353
|
+
const decision = decideStoreLockTakeover(storeLocked.owner, {
|
|
354
|
+
storePath: kbPath,
|
|
355
|
+
});
|
|
219
356
|
if (decision.action !== "break") {
|
|
220
357
|
const holderSummary = storeLocked.owner === null
|
|
221
358
|
? decision.reason
|
package/dist/proof/inspect.d.ts
CHANGED
|
@@ -28,7 +28,7 @@ export type ProofInspection = Readonly<{
|
|
|
28
28
|
integrationPlanReason: string;
|
|
29
29
|
}>;
|
|
30
30
|
export type ProofInspectionOptions = Readonly<{
|
|
31
|
-
/** Plan
|
|
31
|
+
/** Plan adding this integration id, or replacing it when it exists. */
|
|
32
32
|
update?: string;
|
|
33
33
|
/** Command (argv) the proposed integration runs instead of the detected one. */
|
|
34
34
|
command?: readonly string[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inspect.d.ts","sourceRoot":"","sources":["../../src/proof/inspect.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;AAC5E,OAAO,EACL,KAAK,mBAAmB,EAEzB,MAAM,uBAAuB,CAAC;AAM/B,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC;IACrC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,gFAAgF;IAChF,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,yEAAyE;IACzE,mBAAmB,EAAE,SAAS,QAAQ,CAAC;QACrC,EAAE,EAAE,MAAM,CAAC;QACX,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;KAC5B,CAAC,EAAE,CAAC;IACL,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,qEAAqE;IACrE,mBAAmB,EAAE,mBAAmB,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC;IAC/D,6EAA6E;IAC7E,gBAAgB,EAAE,mBAAmB,CAAC,kBAAkB,CAAC,GAAG,IAAI,CAAC;IACjE;;;OAGG;IACH,eAAe,EAAE,aAAa,GAAG,IAAI,CAAC;IACtC,sDAAsD;IACtD,qBAAqB,EAAE,MAAM,CAAC;CAC/B,CAAC,CAAC;AAEH,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAAC;IAC5C,
|
|
1
|
+
{"version":3,"file":"inspect.d.ts","sourceRoot":"","sources":["../../src/proof/inspect.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;AAC5E,OAAO,EACL,KAAK,mBAAmB,EAEzB,MAAM,uBAAuB,CAAC;AAM/B,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC;IACrC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,gFAAgF;IAChF,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,yEAAyE;IACzE,mBAAmB,EAAE,SAAS,QAAQ,CAAC;QACrC,EAAE,EAAE,MAAM,CAAC;QACX,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;KAC5B,CAAC,EAAE,CAAC;IACL,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,qEAAqE;IACrE,mBAAmB,EAAE,mBAAmB,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC;IAC/D,6EAA6E;IAC7E,gBAAgB,EAAE,mBAAmB,CAAC,kBAAkB,CAAC,GAAG,IAAI,CAAC;IACjE;;;OAGG;IACH,eAAe,EAAE,aAAa,GAAG,IAAI,CAAC;IACtC,sDAAsD;IACtD,qBAAqB,EAAE,MAAM,CAAC;CAC/B,CAAC,CAAC;AAEH,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAAC;IAC5C,uEAAuE;IACvE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7B,CAAC,CAAC;AAwIH,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,GACZ,OAAO,CAMT;AA2BD,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,sBAA2B,GACnC,eAAe,CAiHjB"}
|
package/dist/proof/inspect.js
CHANGED
|
@@ -219,9 +219,16 @@ export function inspectProofEnvironment(root, options = {}) {
|
|
|
219
219
|
: [];
|
|
220
220
|
const planned = buildProofIntegrationPlan(root, options);
|
|
221
221
|
const applyHint = "review integrationPlan, then apply it with kb_apply_plan (or `kibi apply-plan --input -`) passing plan, approvedPlanHash = plan.planHash and approvedActionIds";
|
|
222
|
+
const updateId = options.update?.trim() || undefined;
|
|
222
223
|
let recommendation;
|
|
223
|
-
if (planned.plan !== null &&
|
|
224
|
-
|
|
224
|
+
if (planned.plan !== null && updateId !== undefined) {
|
|
225
|
+
// implements REQ-kibi-verification-evidence-contract
|
|
226
|
+
// The plan adds an id the file does not have yet; only an existing one is
|
|
227
|
+
// replaced.
|
|
228
|
+
const verb = currentIntegrations.some((entry) => entry.id === updateId)
|
|
229
|
+
? "replace"
|
|
230
|
+
: "add";
|
|
231
|
+
recommendation = `To ${verb} integration '${updateId}', ${applyHint}.`;
|
|
225
232
|
}
|
|
226
233
|
else if (!integrations.available) {
|
|
227
234
|
if (planned.plan === null) {
|
|
@@ -79,7 +79,7 @@ export declare const OPERATION_CATALOG: readonly [{
|
|
|
79
79
|
}, {
|
|
80
80
|
readonly name: "kb_query";
|
|
81
81
|
readonly cliName: "query";
|
|
82
|
-
readonly description: "Read entities from the KB with filters. Use for
|
|
82
|
+
readonly description: "Read entities from the KB with exact filters, or ask typed fact questions. Use for lookup by id, type, tags or sourceFile, and for precise questions about modeled facts: predicate facts by name with named arguments (predicate + where), property facts of a subject (subjectKey + propertyKey), or the catalog of facts of one kind (factKind; 'predicate_schema' lists the predicates you can ask about with their argument names and constants). Typed answers return matching fact rows plus factQuery: the schema used, distinct counts, values that do exist when nothing matched, warnings about the question and the next call to make. Read-only. Tags filter by metadata tags only, not entity IDs.";
|
|
83
83
|
readonly businessInputSchema: {
|
|
84
84
|
readonly type: "object";
|
|
85
85
|
readonly properties: {
|
|
@@ -103,6 +103,55 @@ export declare const OPERATION_CATALOG: readonly [{
|
|
|
103
103
|
readonly type: "string";
|
|
104
104
|
readonly description: "Optional source-file substring filter. Example: 'src/auth/login.ts'. Uses KB source linkage, not file-system scanning.";
|
|
105
105
|
};
|
|
106
|
+
readonly factKind: {
|
|
107
|
+
readonly type: "string";
|
|
108
|
+
readonly enum: readonly ["subject", "property_value", "predicate", "predicate_schema", "observation", "meta", "rule", "rule_schema"];
|
|
109
|
+
readonly description: "Typed fact filter: list facts of one kind with their typed fields. 'predicate_schema' returns the catalog of askable predicates (argument names, constants, fact counts). Example: 'predicate_schema'.";
|
|
110
|
+
};
|
|
111
|
+
readonly predicate: {
|
|
112
|
+
readonly type: "string";
|
|
113
|
+
readonly description: "Typed fact filter: predicate name to ask about, e.g. 'has_role' or 'permission_rule'. Combine with where for named arguments. Returns every stored fact of that predicate with its arguments, polarity and allow/deny effect.";
|
|
114
|
+
};
|
|
115
|
+
readonly namespace: {
|
|
116
|
+
readonly type: "string";
|
|
117
|
+
readonly description: "Optional predicate namespace when the same name exists in several. Default: any namespace.";
|
|
118
|
+
};
|
|
119
|
+
readonly where: {
|
|
120
|
+
readonly type: "object";
|
|
121
|
+
readonly additionalProperties: {
|
|
122
|
+
readonly type: "string";
|
|
123
|
+
};
|
|
124
|
+
readonly description: "Named argument values for predicate, order-free, using the argument names from the predicate's schema. Example: {actor: 'admin', decision: 'allow'}. An unknown name returns a warning with the declared names; no match returns the values that do exist.";
|
|
125
|
+
};
|
|
126
|
+
readonly args: {
|
|
127
|
+
readonly type: "array";
|
|
128
|
+
readonly items: {
|
|
129
|
+
readonly type: readonly ["string", "null"];
|
|
130
|
+
};
|
|
131
|
+
readonly description: "Positional argument values for predicate when it has no schema; null matches any value. Example: ['admin', null, null, 'allow']. Prefer where.";
|
|
132
|
+
};
|
|
133
|
+
readonly polarity: {
|
|
134
|
+
readonly type: "string";
|
|
135
|
+
readonly enum: readonly ["assert", "deny"];
|
|
136
|
+
readonly description: "Optional polarity filter for predicate facts. Default: both.";
|
|
137
|
+
};
|
|
138
|
+
readonly scope: {
|
|
139
|
+
readonly type: "string";
|
|
140
|
+
readonly enum: readonly ["all", "current_requirements"];
|
|
141
|
+
readonly description: "Optional: 'current_requirements' keeps only facts a current (not superseded or retired) requirement requires.";
|
|
142
|
+
};
|
|
143
|
+
readonly distinct: {
|
|
144
|
+
readonly type: "string";
|
|
145
|
+
readonly description: "Optional argument name to count distinct values of across the matching predicate facts, e.g. distinct: 'role' with predicate 'has_role' and where {user: 'alice'} answers how many roles alice has.";
|
|
146
|
+
};
|
|
147
|
+
readonly subjectKey: {
|
|
148
|
+
readonly type: "string";
|
|
149
|
+
readonly description: "Typed fact filter: dotted subject key whose property facts to list, e.g. 'user.role_assignment'. Combine with propertyKey for one property.";
|
|
150
|
+
};
|
|
151
|
+
readonly propertyKey: {
|
|
152
|
+
readonly type: "string";
|
|
153
|
+
readonly description: "Optional property key under subjectKey, e.g. 'max_roles'. Returns operator, value and unit of each fact.";
|
|
154
|
+
};
|
|
106
155
|
readonly limit: {
|
|
107
156
|
readonly type: "number";
|
|
108
157
|
readonly default: 100;
|
|
@@ -141,8 +190,8 @@ export declare const OPERATION_CATALOG: readonly [{
|
|
|
141
190
|
readonly limit: {
|
|
142
191
|
readonly type: "integer";
|
|
143
192
|
readonly minimum: 0;
|
|
144
|
-
readonly default:
|
|
145
|
-
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.";
|
|
146
195
|
};
|
|
147
196
|
readonly offset: {
|
|
148
197
|
readonly type: "integer";
|
|
@@ -669,7 +718,7 @@ export declare const OPERATION_CATALOG: readonly [{
|
|
|
669
718
|
}, {
|
|
670
719
|
readonly name: "kb_model";
|
|
671
720
|
readonly cliName: "model";
|
|
672
|
-
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.";
|
|
673
722
|
readonly businessInputSchema: {
|
|
674
723
|
readonly type: "object";
|
|
675
724
|
readonly required: readonly ["mode", "text"];
|
|
@@ -1640,6 +1689,50 @@ export declare const OPERATION_CATALOG: readonly [{
|
|
|
1640
1689
|
readonly default: false;
|
|
1641
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.";
|
|
1642
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
|
+
};
|
|
1643
1736
|
readonly document: {
|
|
1644
1737
|
readonly type: "object";
|
|
1645
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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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Violation } from "../check-types.js";
|
|
2
|
-
import { type CheckDiagnostic, type CheckStructuredContent, buildStructuredContent, buildSummary } from "./check-format-shared.js";
|
|
2
|
+
import { type CheckDiagnostic, type CheckEvaluated, type CheckStructuredContent, buildStructuredContent, buildSummary } from "./check-format-shared.js";
|
|
3
3
|
import { getEffectiveRules, resolveCheckRules } from "./check-helpers.js";
|
|
4
4
|
import type { OperationContext } from "./runtime-types.js";
|
|
5
5
|
import type { OperationResult } from "./types.js";
|
|
@@ -13,7 +13,7 @@ export type CheckInput = {
|
|
|
13
13
|
readonly maxDiagnostics?: number;
|
|
14
14
|
};
|
|
15
15
|
export type CheckPayload = CheckStructuredContent;
|
|
16
|
-
export type { CheckDiagnostic, CheckStructuredContent };
|
|
16
|
+
export type { CheckDiagnostic, CheckEvaluated, CheckStructuredContent };
|
|
17
17
|
export { buildStructuredContent, buildSummary, getEffectiveRules, resolveCheckRules, };
|
|
18
18
|
export type CheckExecutionOptions = {
|
|
19
19
|
readonly collectFullQualityDiagnosticsForExplicitRules?: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check-executor.d.ts","sourceRoot":"","sources":["../../../src/public/operations/check-executor.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnD,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC3B,sBAAsB,EACtB,YAAY,EACb,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAGL,iBAAiB,EAGjB,iBAAiB,EAElB,MAAM,oBAAoB,CAAC;AAW5B,OAAO,KAAK,EAAE,gBAAgB,EAAc,MAAM,oBAAoB,CAAC;AAMvE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAIlD,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAC1C,QAAQ,CAAC,wBAAwB,CAAC,EAAE,OAAO,CAAC;IAC5C,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,sBAAsB,CAAC;AAClD,YAAY,EAAE,eAAe,EAAE,sBAAsB,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"check-executor.d.ts","sourceRoot":"","sources":["../../../src/public/operations/check-executor.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnD,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,sBAAsB,EAC3B,sBAAsB,EACtB,YAAY,EACb,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAGL,iBAAiB,EAGjB,iBAAiB,EAElB,MAAM,oBAAoB,CAAC;AAW5B,OAAO,KAAK,EAAE,gBAAgB,EAAc,MAAM,oBAAoB,CAAC;AAMvE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAIlD,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAC1C,QAAQ,CAAC,wBAAwB,CAAC,EAAE,OAAO,CAAC;IAC5C,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,sBAAsB,CAAC;AAClD,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,sBAAsB,EAAE,CAAC;AACxE,OAAO,EACL,sBAAsB,EACtB,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,GAClB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,CAAC,6CAA6C,CAAC,EAAE,OAAO,CAAC;IACjE;;;;;;OAMG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAC;CACxC,CAAC;AAoFF;;;;;GAKG;AAEH,wBAAgB,8BAA8B,CAC5C,OAAO,EAAE,gBAAgB,EACzB,aAAa,EAAE,MAAM,GACpB,SAAS,GAAG,IAAI,CAgClB;AAGD,wBAAsB,YAAY,CAChC,IAAI,EAAE,UAAU,EAChB,OAAO,EAAE,gBAAgB,EACzB,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CA0OxC"}
|