kibi-cli 2.17.0 → 2.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli-operation-metadata.d.ts +1 -1
- package/dist/cli-operation-metadata.js +1 -1
- package/dist/cli-register-proof.js +9 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +18 -6
- 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 +81 -9
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +76 -6
- package/dist/engine.d.ts +4 -0
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +56 -33
- package/dist/operations/modeling/predicate-applicability.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-applicability.js +5 -2
- package/dist/operations/modeling/predicate-catalog-4.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-catalog-4.js +4 -0
- package/dist/operations/modeling/predicate-loader.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-loader.js +3 -0
- package/dist/operations/modeling/predicate-score-3.js +1 -1
- package/dist/operations/modeling/predicate-types.d.ts +5 -0
- package/dist/operations/modeling/predicate-types.d.ts.map +1 -1
- package/dist/operations/mutation/source-authoring.d.ts +9 -0
- package/dist/operations/mutation/source-authoring.d.ts.map +1 -1
- package/dist/operations/mutation/source-authoring.js +30 -1
- package/dist/operations/planning/apply-plan.d.ts.map +1 -1
- package/dist/operations/planning/apply-plan.js +10 -1
- package/dist/operations/semantic-advisor/clauses.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/clauses.js +7 -1
- package/dist/prolog/store-lock.d.ts +41 -0
- package/dist/prolog/store-lock.d.ts.map +1 -1
- package/dist/prolog/store-lock.js +91 -1
- package/dist/prolog.d.ts +7 -1
- package/dist/prolog.d.ts.map +1 -1
- package/dist/prolog.js +21 -3
- package/dist/proof/inspect.d.ts +8 -1
- package/dist/proof/inspect.d.ts.map +1 -1
- package/dist/proof/inspect.js +19 -2
- package/dist/public/operations/catalog.d.ts +50 -1
- package/dist/public/operations/catalog.d.ts.map +1 -1
- package/dist/public/operations/contracts.d.ts.map +1 -1
- package/dist/public/operations/contracts.js +4 -4
- package/dist/public/operations/discovery-executors.d.ts +50 -1
- package/dist/public/operations/discovery-executors.d.ts.map +1 -1
- package/dist/public/operations/discovery-executors.js +418 -8
- package/dist/public/operations/migration-plan.d.ts +2 -0
- package/dist/public/operations/migration-plan.d.ts.map +1 -1
- package/dist/public/operations/migration-plan.js +31 -0
- package/dist/public/operations/source-relationship-parity.d.ts.map +1 -1
- package/dist/public/operations/source-relationship-parity.js +55 -1
- package/dist/public/operations/specs/discovery.d.ts +50 -1
- package/dist/public/operations/specs/discovery.d.ts.map +1 -1
- package/dist/public/operations/specs/discovery.js +56 -1
- package/dist/public/skills/kibi-usage/SKILL.md +20 -3
- package/dist/public/skills/kibi-usage/resources/proof.md +23 -0
- package/dist/runtime/cli-runtime.d.ts.map +1 -1
- package/dist/runtime/cli-runtime.js +7 -2
- package/dist/search-answer.d.ts +12 -3
- package/dist/search-answer.d.ts.map +1 -1
- package/dist/search-answer.js +51 -4
- package/dist/utils/branch-store.d.ts +8 -0
- package/dist/utils/branch-store.d.ts.map +1 -1
- package/dist/utils/branch-store.js +27 -1
- package/dist/utils/content-freshness.d.ts +13 -0
- package/dist/utils/content-freshness.d.ts.map +1 -0
- package/dist/utils/content-freshness.js +171 -0
- 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 +2 -2
- package/src/public/operations/contracts.ts +7 -4
- package/src/public/operations/discovery-executors.ts +556 -6
- package/src/public/operations/migration-plan.ts +44 -0
- package/src/public/operations/source-relationship-parity.ts +60 -3
- package/src/public/operations/specs/discovery.ts +67 -1
- package/src/public/skills/kibi-usage/SKILL.md +20 -3
- package/src/public/skills/kibi-usage/resources/proof.md +23 -0
|
@@ -2,6 +2,7 @@ import { execFileSync } from "node:child_process";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { discoverSourceFiles } from "../../commands/sync/discovery.js";
|
|
4
4
|
import { processExtractions } from "../../commands/sync/extraction.js";
|
|
5
|
+
import { findUntrackedDocumentMatches } from "../../commands/sync/untracked-targets.js";
|
|
5
6
|
import { RELATIONSHIP_TYPES } from "../../operations/mutation/relationships.js";
|
|
6
7
|
import { parseListOfLists, parsePrologValue } from "../../prolog/codec.js";
|
|
7
8
|
import { readAllShards } from "../../relationships/shards.js";
|
|
@@ -173,5 +174,58 @@ export async function collectSourceRelationshipParityViolations(workspaceRoot, p
|
|
|
173
174
|
source: ".kb/relationships",
|
|
174
175
|
});
|
|
175
176
|
}
|
|
176
|
-
return compareRelationshipParity(authored, await compiledRelationships(prolog));
|
|
177
|
+
return explainUntrackedEndpoints(workspaceRoot, compareRelationshipParity(authored, await compiledRelationships(prolog)));
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* An authored relationship is missing from the compiled KB most often
|
|
181
|
+
* because an endpoint is declared in a file sync cannot see: one Git does not
|
|
182
|
+
* track and no pending-source receipt covers (for example a `.kb/symbols.yaml`
|
|
183
|
+
* that `kibi init` created and kb_upsert appended to before receipts covered
|
|
184
|
+
* existing untracked files). Name that file and the fix.
|
|
185
|
+
*/
|
|
186
|
+
// implements REQ-kibi-source-relationship-parity
|
|
187
|
+
function explainUntrackedEndpoints(workspaceRoot, violations) {
|
|
188
|
+
const endpoints = new Set();
|
|
189
|
+
for (const violation of violations) {
|
|
190
|
+
const relationship = authoredToCompiledRelationship(violation);
|
|
191
|
+
if (relationship === null)
|
|
192
|
+
continue;
|
|
193
|
+
endpoints.add(relationship.from);
|
|
194
|
+
endpoints.add(relationship.to);
|
|
195
|
+
}
|
|
196
|
+
if (endpoints.size === 0)
|
|
197
|
+
return violations;
|
|
198
|
+
const untracked = findUntrackedDocumentMatches(workspaceRoot, [...endpoints]);
|
|
199
|
+
if (untracked.size === 0)
|
|
200
|
+
return violations;
|
|
201
|
+
return violations.map((violation) => {
|
|
202
|
+
const relationship = authoredToCompiledRelationship(violation);
|
|
203
|
+
if (relationship === null)
|
|
204
|
+
return violation;
|
|
205
|
+
const sources = [relationship.from, relationship.to].flatMap((id) => {
|
|
206
|
+
const file = untracked.get(id);
|
|
207
|
+
return file === undefined ? [] : [{ entityId: id, file }];
|
|
208
|
+
});
|
|
209
|
+
if (sources.length === 0)
|
|
210
|
+
return violation;
|
|
211
|
+
const files = [...new Set(sources.map((source) => source.file))];
|
|
212
|
+
return {
|
|
213
|
+
...violation,
|
|
214
|
+
suggestion: `${sources.map((source) => source.entityId).join(" and ")} ${sources.length === 1 ? "is" : "are"} declared in ${files.join(", ")}, which Git does not track and no pending-source receipt covers, so sync never compiles it. Run 'git add ${files.join(" ")}' (staging is enough) or rewrite the entity with kb_upsert, then run kibi sync and rerun kb_check.`,
|
|
215
|
+
evidence: {
|
|
216
|
+
...(violation.evidence ?? {}),
|
|
217
|
+
untrackedSources: sources,
|
|
218
|
+
},
|
|
219
|
+
};
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
function authoredToCompiledRelationship(violation) {
|
|
223
|
+
const evidence = violation.evidence;
|
|
224
|
+
if (evidence?.direction !== "authored_to_compiled")
|
|
225
|
+
return null;
|
|
226
|
+
const from = evidence.relationship?.from;
|
|
227
|
+
const to = evidence.relationship?.to;
|
|
228
|
+
return typeof from === "string" && typeof to === "string"
|
|
229
|
+
? { from, to }
|
|
230
|
+
: null;
|
|
177
231
|
}
|
|
@@ -2,7 +2,7 @@ import { executeQuery, executeSearch, executeStatus } from "../discovery-executo
|
|
|
2
2
|
export declare const querySpec: {
|
|
3
3
|
readonly name: "kb_query";
|
|
4
4
|
readonly cliName: "query";
|
|
5
|
-
readonly description: "Read entities from the KB with filters. Use for
|
|
5
|
+
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.";
|
|
6
6
|
readonly businessInputSchema: {
|
|
7
7
|
readonly type: "object";
|
|
8
8
|
readonly properties: {
|
|
@@ -26,6 +26,55 @@ export declare const querySpec: {
|
|
|
26
26
|
readonly type: "string";
|
|
27
27
|
readonly description: "Optional source-file substring filter. Example: 'src/auth/login.ts'. Uses KB source linkage, not file-system scanning.";
|
|
28
28
|
};
|
|
29
|
+
readonly factKind: {
|
|
30
|
+
readonly type: "string";
|
|
31
|
+
readonly enum: readonly ["subject", "property_value", "predicate", "predicate_schema", "observation", "meta", "rule", "rule_schema"];
|
|
32
|
+
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'.";
|
|
33
|
+
};
|
|
34
|
+
readonly predicate: {
|
|
35
|
+
readonly type: "string";
|
|
36
|
+
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.";
|
|
37
|
+
};
|
|
38
|
+
readonly namespace: {
|
|
39
|
+
readonly type: "string";
|
|
40
|
+
readonly description: "Optional predicate namespace when the same name exists in several. Default: any namespace.";
|
|
41
|
+
};
|
|
42
|
+
readonly where: {
|
|
43
|
+
readonly type: "object";
|
|
44
|
+
readonly additionalProperties: {
|
|
45
|
+
readonly type: "string";
|
|
46
|
+
};
|
|
47
|
+
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.";
|
|
48
|
+
};
|
|
49
|
+
readonly args: {
|
|
50
|
+
readonly type: "array";
|
|
51
|
+
readonly items: {
|
|
52
|
+
readonly type: readonly ["string", "null"];
|
|
53
|
+
};
|
|
54
|
+
readonly description: "Positional argument values for predicate when it has no schema; null matches any value. Example: ['admin', null, null, 'allow']. Prefer where.";
|
|
55
|
+
};
|
|
56
|
+
readonly polarity: {
|
|
57
|
+
readonly type: "string";
|
|
58
|
+
readonly enum: readonly ["assert", "deny"];
|
|
59
|
+
readonly description: "Optional polarity filter for predicate facts. Default: both.";
|
|
60
|
+
};
|
|
61
|
+
readonly scope: {
|
|
62
|
+
readonly type: "string";
|
|
63
|
+
readonly enum: readonly ["all", "current_requirements"];
|
|
64
|
+
readonly description: "Optional: 'current_requirements' keeps only facts a current (not superseded or retired) requirement requires.";
|
|
65
|
+
};
|
|
66
|
+
readonly distinct: {
|
|
67
|
+
readonly type: "string";
|
|
68
|
+
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.";
|
|
69
|
+
};
|
|
70
|
+
readonly subjectKey: {
|
|
71
|
+
readonly type: "string";
|
|
72
|
+
readonly description: "Typed fact filter: dotted subject key whose property facts to list, e.g. 'user.role_assignment'. Combine with propertyKey for one property.";
|
|
73
|
+
};
|
|
74
|
+
readonly propertyKey: {
|
|
75
|
+
readonly type: "string";
|
|
76
|
+
readonly description: "Optional property key under subjectKey, e.g. 'max_roles'. Returns operator, value and unit of each fact.";
|
|
77
|
+
};
|
|
29
78
|
readonly limit: {
|
|
30
79
|
readonly type: "number";
|
|
31
80
|
readonly default: 100;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../../../src/public/operations/specs/discovery.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,aAAa,EACb,aAAa,EACd,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../../../src/public/operations/specs/discovery.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,aAAa,EACb,aAAa,EACd,MAAM,2BAA2B,CAAC;AAiCnC,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuGsC,CAAC;AAE7D,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0GuC,CAAC;AAE/D,eAAO,MAAM,UAAU;;;;;;;;;;;;CAWuC,CAAC"}
|
|
@@ -9,10 +9,20 @@ const ENTITY_TYPES = [
|
|
|
9
9
|
"symbol",
|
|
10
10
|
"fact",
|
|
11
11
|
];
|
|
12
|
+
const FACT_KINDS = [
|
|
13
|
+
"subject",
|
|
14
|
+
"property_value",
|
|
15
|
+
"predicate",
|
|
16
|
+
"predicate_schema",
|
|
17
|
+
"observation",
|
|
18
|
+
"meta",
|
|
19
|
+
"rule",
|
|
20
|
+
"rule_schema",
|
|
21
|
+
];
|
|
12
22
|
export const querySpec = {
|
|
13
23
|
name: "kb_query",
|
|
14
24
|
cliName: "query",
|
|
15
|
-
description: "Read entities from the KB with filters. Use for
|
|
25
|
+
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.",
|
|
16
26
|
businessInputSchema: {
|
|
17
27
|
type: "object",
|
|
18
28
|
properties: {
|
|
@@ -34,6 +44,51 @@ export const querySpec = {
|
|
|
34
44
|
type: "string",
|
|
35
45
|
description: "Optional source-file substring filter. Example: 'src/auth/login.ts'. Uses KB source linkage, not file-system scanning.",
|
|
36
46
|
},
|
|
47
|
+
factKind: {
|
|
48
|
+
type: "string",
|
|
49
|
+
enum: FACT_KINDS,
|
|
50
|
+
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'.",
|
|
51
|
+
},
|
|
52
|
+
predicate: {
|
|
53
|
+
type: "string",
|
|
54
|
+
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.",
|
|
55
|
+
},
|
|
56
|
+
namespace: {
|
|
57
|
+
type: "string",
|
|
58
|
+
description: "Optional predicate namespace when the same name exists in several. Default: any namespace.",
|
|
59
|
+
},
|
|
60
|
+
where: {
|
|
61
|
+
type: "object",
|
|
62
|
+
additionalProperties: { type: "string" },
|
|
63
|
+
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.",
|
|
64
|
+
},
|
|
65
|
+
args: {
|
|
66
|
+
type: "array",
|
|
67
|
+
items: { type: ["string", "null"] },
|
|
68
|
+
description: "Positional argument values for predicate when it has no schema; null matches any value. Example: ['admin', null, null, 'allow']. Prefer where.",
|
|
69
|
+
},
|
|
70
|
+
polarity: {
|
|
71
|
+
type: "string",
|
|
72
|
+
enum: ["assert", "deny"],
|
|
73
|
+
description: "Optional polarity filter for predicate facts. Default: both.",
|
|
74
|
+
},
|
|
75
|
+
scope: {
|
|
76
|
+
type: "string",
|
|
77
|
+
enum: ["all", "current_requirements"],
|
|
78
|
+
description: "Optional: 'current_requirements' keeps only facts a current (not superseded or retired) requirement requires.",
|
|
79
|
+
},
|
|
80
|
+
distinct: {
|
|
81
|
+
type: "string",
|
|
82
|
+
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.",
|
|
83
|
+
},
|
|
84
|
+
subjectKey: {
|
|
85
|
+
type: "string",
|
|
86
|
+
description: "Typed fact filter: dotted subject key whose property facts to list, e.g. 'user.role_assignment'. Combine with propertyKey for one property.",
|
|
87
|
+
},
|
|
88
|
+
propertyKey: {
|
|
89
|
+
type: "string",
|
|
90
|
+
description: "Optional property key under subjectKey, e.g. 'max_roles'. Returns operator, value and unit of each fact.",
|
|
91
|
+
},
|
|
37
92
|
limit: {
|
|
38
93
|
type: "number",
|
|
39
94
|
default: 100,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
id: kibi-usage
|
|
3
3
|
name: Kibi Usage
|
|
4
4
|
description: Use Kibi's source-first, exact-Git, migration-aware, proof-aware operations safely across MCP or the trusted local CLI, including partial completion repair.
|
|
5
|
-
version: 2.
|
|
5
|
+
version: 2.15.0
|
|
6
6
|
kibiCompatibility: ">=1.0.0"
|
|
7
7
|
tags:
|
|
8
8
|
- kibi
|
|
@@ -237,7 +237,11 @@ authored. Each one is the order the write path accepts.
|
|
|
237
237
|
fact, `requires_predicate` to `relationshipTarget` and `specified_by` to
|
|
238
238
|
its scenario: `specified_by` (req → scenario) is sent in the
|
|
239
239
|
requirement's write, never in the scenario's, so create the scenario
|
|
240
|
-
first
|
|
240
|
+
first, with `assumes` links (scenario → `property_value` fact, sent in
|
|
241
|
+
the scenario's own write) to the values its outcome relies on. Set
|
|
242
|
+
`expects` only on a scenario that has `assumes` links; `expects: success`
|
|
243
|
+
without them only yields `scenario-feasibility-unknown` ("assumes
|
|
244
|
+
nothing"). A
|
|
241
245
|
`modeled` entry and its grounding link must arrive in the same write
|
|
242
246
|
(`modeled semantic_inventory entries (n) must equal logical grounding
|
|
243
247
|
relationships (m)`); a clause not grounded yet stays `status: missing`
|
|
@@ -249,7 +253,12 @@ authored. Each one is the order the write path accepts.
|
|
|
249
253
|
claim_keys must match logical grounding target claim_keys exactly`.
|
|
250
254
|
Prefer supersession for a change of meaning: analyze the new prose,
|
|
251
255
|
write its facts, write the new requirement (`-v2`) with `supersedes` to
|
|
252
|
-
the old one, then set the old one to `status: closed`.
|
|
256
|
+
the old one, then set the old one to `status: closed`. Its scenario
|
|
257
|
+
follows the same rule as in recipe 1: create the new scenario (with
|
|
258
|
+
`assumes` to the `property_value` facts it relies on, and `expects` only
|
|
259
|
+
when it has them) before the `-v2` write that sends `specified_by`, then
|
|
260
|
+
re-point the old scenario (its `assumes` go in its own write) or close
|
|
261
|
+
it. For a wording fix
|
|
253
262
|
that keeps the meaning, re-ground in place: analyze the new prose,
|
|
254
263
|
`kb_upsert` each grounding fact with the new `claim_key`/`claim_text`
|
|
255
264
|
(same fact id), then `kb_upsert` the requirement with the new ledger,
|
|
@@ -400,6 +409,14 @@ Prolog `symbol-coverage` also requires the test to `validates` the requirement
|
|
|
400
409
|
enough. Do not rely on legacy `// implements REQ-<area>-<behavior>` comments as the
|
|
401
410
|
traceability record.
|
|
402
411
|
|
|
412
|
+
Set the symbol's `title` to the behavioral member the extractor can locate in
|
|
413
|
+
`sourceFile`: `ClassName.methodName`, an exported function, or a class, not a
|
|
414
|
+
file or module name. A traceability link (`implements`, `covered_by`, …) from
|
|
415
|
+
a symbol whose `title` names no such member is refused by the granularity gate
|
|
416
|
+
when the file already has granular behavioral symbols, unless the symbol sets
|
|
417
|
+
`granularity_reason` to `config-artifact`, `module-level-behavior`,
|
|
418
|
+
`extractor-miss`, `legacy-link` or `test-suite`.
|
|
419
|
+
|
|
403
420
|
## Complete Logical Coverage
|
|
404
421
|
|
|
405
422
|
Decompose all atomic normative clauses into `claim_key`/`claim_text` entries in
|
|
@@ -97,6 +97,29 @@ Cosmetic edits (descriptions, labels) never stale proof. Execution-relevant
|
|
|
97
97
|
edits (command, artifact, targets, options, bindings, contract) change the
|
|
98
98
|
effective fingerprint and do.
|
|
99
99
|
|
|
100
|
+
## What counts toward proofProven
|
|
101
|
+
|
|
102
|
+
A requirement is proven only by its scenarios' tests, and a scenario test
|
|
103
|
+
counts only when it is an **end-to-end** test with a valid, fresh, passing
|
|
104
|
+
receipt for the current snapshot.
|
|
105
|
+
|
|
106
|
+
- The scope comes from the test entity's `verification_scope`
|
|
107
|
+
(`end_to_end`, `integration`, `unit`), never from the integration id or the
|
|
108
|
+
producer. Without `verification_scope`, a test tagged `e2e` (or whose
|
|
109
|
+
`source` path contains `e2e`) counts as end-to-end; anything else is
|
|
110
|
+
`unknown` scope.
|
|
111
|
+
- A `unit` or `integration` receipt is still recorded on the test entity, but
|
|
112
|
+
it does not move `proofProven` for a behavioural requirement: the
|
|
113
|
+
requirement keeps the `missing_passing_e2e` gap in `proofGaps`. The one
|
|
114
|
+
exception is a scenario whose specifying requirements are all grounded only
|
|
115
|
+
in component-scope UI predicates (`ui_pattern`, `same_pattern`,
|
|
116
|
+
`pattern_marker`); a unit or integration test that renders the component
|
|
117
|
+
may prove it.
|
|
118
|
+
- `coverage_depth` (`kb_coverage`, `kb_find_gaps`) follows the test's
|
|
119
|
+
authored `status` (`passing`) and scope, not its receipts: a passing
|
|
120
|
+
receipt does not change it, and a `passing` status without a fresh receipt
|
|
121
|
+
proves nothing.
|
|
122
|
+
|
|
100
123
|
## Attempt semantics (factual, never optimistic)
|
|
101
124
|
|
|
102
125
|
- `attempts: {status: "complete", entries: [...]}` — known history; the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-runtime.d.ts","sourceRoot":"","sources":["../../src/runtime/cli-runtime.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cli-runtime.d.ts","sourceRoot":"","sources":["../../src/runtime/cli-runtime.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAKV,gBAAgB,EAEhB,cAAc,EACf,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAEL,KAAK,qBAAqB,EAE3B,MAAM,6BAA6B,CAAC;AAOrC,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,qBAAqB,GAChC,MAAM,CAOR;AA2GD,wBAAgB,gBAAgB,CAC9B,OAAO,GAAE,cAAmB,GAC3B,gBAAgB,CAgJlB"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
-
import { retryAttachAfterBreakingStaleLock } from "../prolog/store-lock.js";
|
|
2
|
+
import { noteDeadHolderBeforeAttach, retryAttachAfterBreakingStaleLock, } from "../prolog/store-lock.js";
|
|
3
3
|
import { EngineClient } from "../engine.js";
|
|
4
4
|
import { CapabilityRegistryCache, ensureCapabilityRegistry, } from "../plugins/registry.js";
|
|
5
5
|
import { nodeFilesystem, nodeGit, nodeNetwork, } from "../public/operations/node-ports.js";
|
|
@@ -186,8 +186,13 @@ export function createCliRuntime(options = {}) {
|
|
|
186
186
|
await prolog.start?.();
|
|
187
187
|
const kbPath = attachment.storePath;
|
|
188
188
|
if (!usesEngine) {
|
|
189
|
+
// implements REQ-core-journaled-engine-persistence
|
|
190
|
+
// A killed holder never makes kb_attach fail, so note it first.
|
|
191
|
+
const recordTakeover = noteDeadHolderBeforeAttach(kbPath);
|
|
189
192
|
let attached = await prolog.query(`kb_attach('${quoteProlog(kbPath)}')`);
|
|
190
|
-
if (
|
|
193
|
+
if (attached.success)
|
|
194
|
+
recordTakeover();
|
|
195
|
+
else {
|
|
191
196
|
attached = await retryAttachAfterBreakingStaleLock(prolog, kbPath, attached);
|
|
192
197
|
}
|
|
193
198
|
if (!attached.success) {
|
package/dist/search-answer.d.ts
CHANGED
|
@@ -66,12 +66,21 @@ export type SearchAnswerVerdict = Readonly<{
|
|
|
66
66
|
export type SearchAnswerException = SearchAnswerEntity & Readonly<{
|
|
67
67
|
approvedBy?: string;
|
|
68
68
|
}>;
|
|
69
|
+
/**
|
|
70
|
+
* A linked fact says what it states in its typed form, so an agent can read
|
|
71
|
+
* `has_role(alice, admin)` or `user.role_assignment max_roles lte 2` without
|
|
72
|
+
* opening the entity, and `ask` is the exact kb_query that answers precise
|
|
73
|
+
* questions about the same predicate or subject.
|
|
74
|
+
*/
|
|
75
|
+
export type SearchAnswerFact = SearchAnswerEntity & Readonly<{
|
|
76
|
+
factKind?: string;
|
|
77
|
+
claim?: string;
|
|
78
|
+
ask?: string;
|
|
79
|
+
}>;
|
|
69
80
|
export type SearchAnswerRequirement = SearchAnswerEntity & Readonly<{
|
|
70
81
|
score: number;
|
|
71
82
|
via: string;
|
|
72
|
-
facts: readonly
|
|
73
|
-
factKind?: string;
|
|
74
|
-
})[];
|
|
83
|
+
facts: readonly SearchAnswerFact[];
|
|
75
84
|
scenarios: readonly SearchAnswerEntity[];
|
|
76
85
|
tests: readonly SearchAnswerTest[];
|
|
77
86
|
adrs: readonly SearchAnswerEntity[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search-answer.d.ts","sourceRoot":"","sources":["../src/search-answer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAW5D,OAAO,KAAK,EACV,UAAU,EAEX,MAAM,sCAAsC,CAAC;AAI9C;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,kBAAkB,GAAG,QAAQ,CAAC;IACxC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC,CAAC;AAEH;;;GAGG;AAEH,MAAM,MAAM,gBAAgB,GAAG,kBAAkB,GAAG,QAAQ,CAAC;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE9E,sEAAsE;AAEtE,MAAM,MAAM,qBAAqB,GAAG,kBAAkB,GACpD,QAAQ,CAAC;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAElD,0EAA0E;AAE1E,MAAM,MAAM,mBAAmB,GAAG,QAAQ,CAAC;IACzC,KAAK,EAAE,uBAAuB,GAAG,sBAAsB,CAAC;IACxD,MAAM,EAAE,eAAe,GAAG,YAAY,CAAC;IACvC,uEAAuE;IACvE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC,CAAC;AAEH;;;;;GAKG;AAEH,MAAM,MAAM,mBAAmB,GAAG,QAAQ,CAAC;IACzC,IAAI,EACA,0BAA0B,GAC1B,qBAAqB,GACrB,wBAAwB,GACxB,qBAAqB,GACrB,qBAAqB,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7B,CAAC,CAAC;AAGH,MAAM,MAAM,mBAAmB,GAAG,QAAQ,CAAC;IACzC;;;;OAIG;IACH,MAAM,EAAE,eAAe,GAAG,YAAY,GAAG,SAAS,GAAG,MAAM,CAAC;IAC5D,SAAS,EAAE,SAAS,mBAAmB,EAAE,CAAC;CAC3C,CAAC,CAAC;AAEH,sDAAsD;AAEtD,MAAM,MAAM,qBAAqB,GAAG,kBAAkB,GACpD,QAAQ,CAAC;IAAE,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"search-answer.d.ts","sourceRoot":"","sources":["../src/search-answer.ts"],"names":[],"mappings":"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"}
|
package/dist/search-answer.js
CHANGED
|
@@ -43,6 +43,19 @@ const ROW_KEYS = [
|
|
|
43
43
|
"approved_by",
|
|
44
44
|
"source",
|
|
45
45
|
"sourceFile",
|
|
46
|
+
"predicate_namespace",
|
|
47
|
+
"predicate_name",
|
|
48
|
+
"predicate_args",
|
|
49
|
+
"polarity",
|
|
50
|
+
"subject_key",
|
|
51
|
+
"property_key",
|
|
52
|
+
"operator",
|
|
53
|
+
"value_type",
|
|
54
|
+
"value_string",
|
|
55
|
+
"value_int",
|
|
56
|
+
"value_number",
|
|
57
|
+
"value_bool",
|
|
58
|
+
"unit",
|
|
46
59
|
];
|
|
47
60
|
// implements REQ-kibi-search-answer-layer-v2
|
|
48
61
|
export const SEARCH_ANSWER_LIMITS = {
|
|
@@ -76,6 +89,40 @@ function brief(entity) {
|
|
|
76
89
|
...(status ? { status } : {}),
|
|
77
90
|
};
|
|
78
91
|
}
|
|
92
|
+
function queryCall(args) {
|
|
93
|
+
return `kb_query(${JSON.stringify(args)})`;
|
|
94
|
+
}
|
|
95
|
+
/** Typed statement and follow-up query of a linked fact, by fact kind. */
|
|
96
|
+
// implements REQ-kibi-query-fact-filters
|
|
97
|
+
function factDetail(fact) {
|
|
98
|
+
const factKind = text(fact.fact_kind);
|
|
99
|
+
const base = factKind ? { factKind } : {};
|
|
100
|
+
const predicate = text(fact.predicate_name);
|
|
101
|
+
if (factKind === "predicate" && predicate) {
|
|
102
|
+
const args = Array.isArray(fact.predicate_args)
|
|
103
|
+
? fact.predicate_args.map(text).join(", ")
|
|
104
|
+
: text(fact.predicate_args);
|
|
105
|
+
const polarity = text(fact.polarity) === "deny" ? " [deny]" : "";
|
|
106
|
+
return {
|
|
107
|
+
...base,
|
|
108
|
+
claim: `${predicate}(${args})${polarity}`,
|
|
109
|
+
ask: queryCall({ predicate }),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
const subjectKey = text(fact.subject_key);
|
|
113
|
+
const propertyKey = text(fact.property_key);
|
|
114
|
+
if (factKind === "property_value" && subjectKey && propertyKey) {
|
|
115
|
+
const unit = text(fact.unit);
|
|
116
|
+
const valueType = text(fact.value_type) || "string";
|
|
117
|
+
const value = text(fact[`value_${valueType}`]);
|
|
118
|
+
const claim = `${subjectKey} ${propertyKey} ${text(fact.operator) || "eq"} ${value}${unit ? ` ${unit}` : ""}`;
|
|
119
|
+
return { ...base, claim, ask: queryCall({ subjectKey, propertyKey }) };
|
|
120
|
+
}
|
|
121
|
+
if (factKind === "subject" && subjectKey) {
|
|
122
|
+
return { ...base, claim: subjectKey, ask: queryCall({ subjectKey }) };
|
|
123
|
+
}
|
|
124
|
+
return base;
|
|
125
|
+
}
|
|
79
126
|
function edgesGoal(ids) {
|
|
80
127
|
const idList = ids.map((id) => `'${escapeAtom(id)}'`).join(",");
|
|
81
128
|
return `findall([Rel,From,To], (member(Rel, [${ANSWER_RELATIONSHIPS.join(",")}]), kb_relationship(Rel, From, To), (member(From, [${idList}]); member(To, [${idList}]))), Edges)`;
|
|
@@ -666,10 +713,10 @@ export async function buildSearchAnswer(prolog, matches, options = {}) {
|
|
|
666
713
|
...brief(req.entity),
|
|
667
714
|
score: req.score,
|
|
668
715
|
via: req.via,
|
|
669
|
-
facts: rowsOf(plan.facts).map((fact) => {
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
}),
|
|
716
|
+
facts: rowsOf(plan.facts).map((fact) => ({
|
|
717
|
+
...brief(fact),
|
|
718
|
+
...factDetail(fact),
|
|
719
|
+
})),
|
|
673
720
|
scenarios: rowsOf(plan.scenarios).map(brief),
|
|
674
721
|
tests: rowsOf(testIds[index] ?? []).map((row) => ({
|
|
675
722
|
...brief(row),
|
|
@@ -21,6 +21,14 @@ export declare function inspectBranchStore(workspaceRoot: string, branch: string
|
|
|
21
21
|
* auto-heal; the reason exists so operators see the state before it bites.
|
|
22
22
|
*/
|
|
23
23
|
export declare function storeLockJournalReason(storePath: string): Record<string, unknown> | null;
|
|
24
|
+
/**
|
|
25
|
+
* An informational notice that this branch store's lock was taken over from
|
|
26
|
+
* a dead holder. The takeover itself is safe and automatic; it is reported
|
|
27
|
+
* because it means an engine or prove run crashed or was killed while it
|
|
28
|
+
* held the store, which nothing else shows once the new holder rewrites the
|
|
29
|
+
* ownership journal. Visible for STORE_LOCK_TAKEOVER_VISIBLE_MS.
|
|
30
|
+
*/
|
|
31
|
+
export declare function storeLockTakeoverReason(storePath: string, now?: Date): Record<string, unknown> | null;
|
|
24
32
|
export declare function branchStoreReason(inspection: BranchStoreInspection): Record<string, unknown> | null;
|
|
25
33
|
/**
|
|
26
34
|
* The number of authored source files under `.kb/`: entity Markdown in the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"branch-store.d.ts","sourceRoot":"","sources":["../../src/utils/branch-store.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"branch-store.d.ts","sourceRoot":"","sources":["../../src/utils/branch-store.ts"],"names":[],"mappings":"AA0BA,mEAAmE;AACnE,eAAO,MAAM,yBAAyB,8BAA8B,CAAC;AACrE,yCAAyC;AACzC,eAAO,MAAM,8BAA8B,8BAA8B,CAAC;AAE1E,MAAM,MAAM,gBAAgB,GACxB,SAAS,GACT,SAAS,GACT,YAAY,GACZ,YAAY,CAAC;AAEjB,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC;IAC3C,KAAK,EAAE,gBAAgB,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,OAAO,CAAC;CAC3B,CAAC,CAAC;AAEH;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,MAAM,GACb,qBAAqB,CA0GvB;AAED;;;;GAIG;AAEH,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,MAAM,GAChB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAiBhC;AAED;;;;;;GAMG;AAEH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,EACjB,GAAG,GAAE,IAAiB,GACrB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAehC;AAED,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,qBAAqB,GAChC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAWhC;AA6BD;;;;GAIG;AAEH,wBAAgB,sBAAsB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAOpE;AAED,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAAC;IAC5C,oEAAoE;IACpE,QAAQ,EAAE,OAAO,CAAC;IAClB,0EAA0E;IAC1E,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,CAAC,CAAC;AAEH;;;;;;GAMG;AAEH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,qBAAqB,GAChC,sBAAsB,CAwBxB;AAkBD;;;;;;GAMG;AAEH,wBAAgB,2BAA2B,CACzC,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,qBAAqB,EACjC,MAAM,EAAE,MAAM,GACb,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAwBhC"}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { existsSync, readFileSync, readdirSync, statSync, } from "node:fs";
|
|
6
6
|
import * as path from "node:path";
|
|
7
|
-
import { classifyStoreLockHolder, readStoreLockOwner, } from "../prolog/store-lock.js";
|
|
7
|
+
import { STORE_LOCK_TAKEOVER_VISIBLE_MS, classifyStoreLockHolder, readStoreLockOwner, readStoreLockTakeover, } from "../prolog/store-lock.js";
|
|
8
8
|
import { branchStoreManifestMatches, branchStorePath, legacyBranchStorePath, } from "./branch-store-locator.js";
|
|
9
9
|
import { ENTITY_LANES, KB_ROOT } from "./kb-paths.js";
|
|
10
10
|
/** Stale-reason code of a branch store that was never compiled. */
|
|
@@ -147,6 +147,32 @@ export function storeLockJournalReason(storePath) {
|
|
|
147
147
|
},
|
|
148
148
|
};
|
|
149
149
|
}
|
|
150
|
+
/**
|
|
151
|
+
* An informational notice that this branch store's lock was taken over from
|
|
152
|
+
* a dead holder. The takeover itself is safe and automatic; it is reported
|
|
153
|
+
* because it means an engine or prove run crashed or was killed while it
|
|
154
|
+
* held the store, which nothing else shows once the new holder rewrites the
|
|
155
|
+
* ownership journal. Visible for STORE_LOCK_TAKEOVER_VISIBLE_MS.
|
|
156
|
+
*/
|
|
157
|
+
// implements REQ-core-journaled-engine-persistence
|
|
158
|
+
export function storeLockTakeoverReason(storePath, now = new Date()) {
|
|
159
|
+
const record = readStoreLockTakeover(storePath);
|
|
160
|
+
if (record === null)
|
|
161
|
+
return null;
|
|
162
|
+
const age = now.getTime() - Date.parse(record.at);
|
|
163
|
+
if (age < 0 || age > STORE_LOCK_TAKEOVER_VISIBLE_MS)
|
|
164
|
+
return null;
|
|
165
|
+
return {
|
|
166
|
+
code: "store_lock_taken_over",
|
|
167
|
+
path: record.path,
|
|
168
|
+
entityIds: [],
|
|
169
|
+
blocking: false,
|
|
170
|
+
brokenPid: record.brokenPid,
|
|
171
|
+
reason: record.reason,
|
|
172
|
+
at: record.at,
|
|
173
|
+
detail: `Kibi broke a stale branch-store lock at ${record.at} (${record.reason || "holder no longer running"}) and reattached. Nothing needs repair; a holder that died while it held the store usually means an engine or kibi prove run crashed or was killed.`,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
150
176
|
export function branchStoreReason(inspection) {
|
|
151
177
|
if (inspection.state === "healthy")
|
|
152
178
|
return null;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Stale-reason codes that compare file times only. */
|
|
2
|
+
export declare const MTIME_SOURCE_REASON_CODES: ReadonlySet<string>;
|
|
3
|
+
type Reason = Readonly<Record<string, unknown>>;
|
|
4
|
+
/**
|
|
5
|
+
* Drop mtime-only stale reasons whose file content provably matches what the
|
|
6
|
+
* store compiled. Reasons without such evidence are kept.
|
|
7
|
+
*/
|
|
8
|
+
export declare function confirmSourceNewerReasons(workspaceRoot: string, storePath: string, reasons: readonly Reason[]): {
|
|
9
|
+
kept: Reason[];
|
|
10
|
+
dropped: Reason[];
|
|
11
|
+
};
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=content-freshness.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-freshness.d.ts","sourceRoot":"","sources":["../../src/utils/content-freshness.ts"],"names":[],"mappings":"AAYA,uDAAuD;AACvD,eAAO,MAAM,yBAAyB,EAAE,WAAW,CAAC,MAAM,CAIxD,CAAC;AAEH,KAAK,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAyJhD;;;GAGG;AAEH,wBAAgB,yBAAyB,CACvC,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,SAAS,MAAM,EAAE,GACzB;IAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAkBvC"}
|