kibi-cli 2.15.0 → 2.16.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-register-proof.d.ts.map +1 -1
- package/dist/cli-register-proof.js +16 -2
- package/dist/commands/check.d.ts.map +1 -1
- package/dist/commands/check.js +5 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +83 -4
- package/dist/commands/prove.js +1 -1
- package/dist/operations/modeling/model-requirement.d.ts +5 -0
- package/dist/operations/modeling/model-requirement.d.ts.map +1 -1
- package/dist/operations/modeling/model-requirement.js +17 -5
- package/dist/operations/modeling/predicate-applyplan.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-applyplan.js +16 -6
- package/dist/operations/planning/apply-plan.d.ts.map +1 -1
- package/dist/operations/planning/apply-plan.js +15 -0
- package/dist/proof/inspect.d.ts +18 -1
- package/dist/proof/inspect.d.ts.map +1 -1
- package/dist/proof/inspect.js +17 -8
- package/dist/proof/integration-plan.d.ts +57 -0
- package/dist/proof/integration-plan.d.ts.map +1 -0
- package/dist/proof/integration-plan.js +331 -0
- package/dist/proof/integrations.js +1 -1
- package/dist/public/operations/catalog.d.ts +2 -2
- package/dist/public/operations/check-executor.d.ts +16 -0
- package/dist/public/operations/check-executor.d.ts.map +1 -1
- package/dist/public/operations/check-executor.js +80 -0
- package/dist/public/operations/discovery-executors.d.ts.map +1 -1
- package/dist/public/operations/discovery-executors.js +13 -3
- package/dist/public/operations/migration-plan.d.ts.map +1 -1
- package/dist/public/operations/migration-plan.js +28 -0
- package/dist/public/operations/specs/check-rules.generated.d.ts +1 -1
- package/dist/public/operations/specs/check-rules.generated.d.ts.map +1 -1
- package/dist/public/operations/specs/check-rules.generated.js +2 -1
- package/dist/public/operations/specs/check.d.ts +1 -1
- package/dist/public/operations/specs/composite.d.ts +16 -3
- package/dist/public/operations/specs/composite.d.ts.map +1 -1
- package/dist/public/operations/specs/composite.js +79 -2
- package/dist/public/operations/specs/modeling.d.ts +1 -1
- package/dist/public/operations/specs/modeling.js +1 -1
- package/dist/public/skills/kibi-bootstrap/SKILL.md +2 -1
- package/dist/public/skills/kibi-usage/SKILL.md +14 -6
- package/dist/public/skills/kibi-usage/resources/proof.md +15 -3
- package/dist/utils/branch-store.d.ts +32 -0
- package/dist/utils/branch-store.d.ts.map +1 -1
- package/dist/utils/branch-store.js +122 -1
- package/dist/utils/rule-registry.generated.d.ts +5 -0
- package/dist/utils/rule-registry.generated.d.ts.map +1 -1
- package/dist/utils/rule-registry.generated.js +6 -0
- package/dist/utils/strict-modeling.d.ts +12 -0
- package/dist/utils/strict-modeling.d.ts.map +1 -1
- package/dist/utils/strict-modeling.js +12 -1
- package/package.json +2 -2
- package/src/public/operations/check-executor.ts +105 -0
- package/src/public/operations/discovery-executors.ts +19 -2
- package/src/public/operations/migration-plan.ts +35 -0
- package/src/public/operations/specs/check-rules.generated.ts +2 -1
- package/src/public/operations/specs/composite.ts +110 -11
- package/src/public/operations/specs/modeling.ts +1 -1
- package/src/public/skills/kibi-bootstrap/SKILL.md +2 -1
- package/src/public/skills/kibi-usage/SKILL.md +14 -6
- package/src/public/skills/kibi-usage/resources/proof.md +15 -3
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import { runAggregatedChecks } from "../../commands/aggregated-checks.js";
|
|
2
|
+
import { resolveBranchAttachment } from "../../utils/branch-resolver.js";
|
|
3
|
+
import {
|
|
4
|
+
BRANCH_STORE_NOT_COMPILED_RULE,
|
|
5
|
+
inspectBranchStore,
|
|
6
|
+
uncompiledBranchStoreReason,
|
|
7
|
+
} from "../../utils/branch-store.js";
|
|
2
8
|
/*
|
|
3
9
|
Kibi — repo-local, per-branch, queryable long-term memory for software projects
|
|
4
10
|
Copyright (C) 2026 Piotr Franczyk
|
|
@@ -74,6 +80,14 @@ export {
|
|
|
74
80
|
|
|
75
81
|
export type CheckExecutionOptions = {
|
|
76
82
|
readonly collectFullQualityDiagnosticsForExplicitRules?: boolean;
|
|
83
|
+
/**
|
|
84
|
+
* The engine reads the current branch's store although the context carries
|
|
85
|
+
* no branch attachment (the `kibi check` engine path). A context with a
|
|
86
|
+
* branch attachment (the CLI and MCP runtimes) implies it; without either,
|
|
87
|
+
* the attached store is unknown (an explicit --kb-path store or an injected
|
|
88
|
+
* test store) and the branch-store compilation check is skipped.
|
|
89
|
+
*/
|
|
90
|
+
readonly branchStoreAttached?: boolean;
|
|
77
91
|
};
|
|
78
92
|
|
|
79
93
|
function requireProlog(context: OperationContext): PrologPort {
|
|
@@ -126,6 +140,50 @@ async function readStatusMigrationPlan(
|
|
|
126
140
|
}
|
|
127
141
|
}
|
|
128
142
|
|
|
143
|
+
/**
|
|
144
|
+
* The one finding for a branch whose store was never compiled while .kb/
|
|
145
|
+
* holds authored sources. Every store-backed rule would read an empty KB
|
|
146
|
+
* (source-relationship-parity alone reports each authored relationship as
|
|
147
|
+
* missing), so kb_check reports this instead of any of them.
|
|
148
|
+
*/
|
|
149
|
+
// implements REQ-cli-status-pre-first-sync
|
|
150
|
+
export function uncompiledBranchStoreViolation(
|
|
151
|
+
context: OperationContext,
|
|
152
|
+
workspaceRoot: string,
|
|
153
|
+
): Violation | null {
|
|
154
|
+
let attachment: ReturnType<typeof resolveBranchAttachment>;
|
|
155
|
+
try {
|
|
156
|
+
attachment =
|
|
157
|
+
context.branchAttachment ?? resolveBranchAttachment(workspaceRoot);
|
|
158
|
+
} catch {
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
if ("error" in attachment) return null;
|
|
162
|
+
const store = inspectBranchStore(workspaceRoot, attachment.kbBranch);
|
|
163
|
+
const reason = uncompiledBranchStoreReason(
|
|
164
|
+
workspaceRoot,
|
|
165
|
+
store,
|
|
166
|
+
attachment.kbBranch,
|
|
167
|
+
);
|
|
168
|
+
if (reason === null) return null;
|
|
169
|
+
return {
|
|
170
|
+
rule: BRANCH_STORE_NOT_COMPILED_RULE,
|
|
171
|
+
entityId: attachment.kbBranch,
|
|
172
|
+
description: String(reason.detail),
|
|
173
|
+
suggestion:
|
|
174
|
+
"Run kibi sync to compile this branch's store from the authored .kb/ sources (or apply the branch-store-compile action of the returned migrationPlan with kb_apply_plan), then rerun kb_check. Run kibi init once to install the git hooks that compile a new branch on checkout.",
|
|
175
|
+
source: store.path,
|
|
176
|
+
evidence: {
|
|
177
|
+
store: { state: store.state, path: store.path },
|
|
178
|
+
authoredSources: reason.authoredSources,
|
|
179
|
+
...(reason.generation !== undefined
|
|
180
|
+
? { generation: reason.generation }
|
|
181
|
+
: {}),
|
|
182
|
+
remediation: reason.remediation,
|
|
183
|
+
},
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
129
187
|
// implements REQ-kibi-operation-interface-parity, REQ-002
|
|
130
188
|
export async function executeCheck(
|
|
131
189
|
args: CheckInput,
|
|
@@ -154,6 +212,53 @@ export async function executeCheck(
|
|
|
154
212
|
? { maxDiagnostics: args.maxDiagnostics }
|
|
155
213
|
: {};
|
|
156
214
|
|
|
215
|
+
const uncompiled =
|
|
216
|
+
context.branchAttachment !== undefined ||
|
|
217
|
+
options.branchStoreAttached === true
|
|
218
|
+
? uncompiledBranchStoreViolation(context, workspaceRoot)
|
|
219
|
+
: null;
|
|
220
|
+
if (uncompiled !== null) {
|
|
221
|
+
const violations = [uncompiled];
|
|
222
|
+
const statusPlan = await readStatusMigrationPlan(context);
|
|
223
|
+
const migrationPlan = await migrationPlanForCheck(
|
|
224
|
+
context,
|
|
225
|
+
violations,
|
|
226
|
+
[],
|
|
227
|
+
statusPlan,
|
|
228
|
+
);
|
|
229
|
+
return {
|
|
230
|
+
content: [
|
|
231
|
+
{
|
|
232
|
+
type: "text",
|
|
233
|
+
text: buildSummary({
|
|
234
|
+
violations,
|
|
235
|
+
impactResult,
|
|
236
|
+
qualityDiagnostics: [],
|
|
237
|
+
}),
|
|
238
|
+
},
|
|
239
|
+
],
|
|
240
|
+
structuredContent: buildStructuredContent({
|
|
241
|
+
violations,
|
|
242
|
+
diagnostics: [
|
|
243
|
+
{
|
|
244
|
+
category: "SYNC_ERROR",
|
|
245
|
+
severity: "error",
|
|
246
|
+
message: uncompiled.description,
|
|
247
|
+
...(uncompiled.source !== undefined
|
|
248
|
+
? { file: uncompiled.source }
|
|
249
|
+
: {}),
|
|
250
|
+
...(uncompiled.suggestion !== undefined
|
|
251
|
+
? { suggestion: uncompiled.suggestion }
|
|
252
|
+
: {}),
|
|
253
|
+
},
|
|
254
|
+
],
|
|
255
|
+
qualityDiagnostics: [],
|
|
256
|
+
impactResult,
|
|
257
|
+
migrationPlan,
|
|
258
|
+
}),
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
|
|
157
262
|
if (rulesAllowlist.size === 0) {
|
|
158
263
|
const qualityDiagnostics =
|
|
159
264
|
hasExplicitRules &&
|
|
@@ -16,10 +16,12 @@ import { rankEntities } from "../../search-ranking.js";
|
|
|
16
16
|
import type { SearchMatch } from "../../search-ranking.js";
|
|
17
17
|
import { resolveBranchAttachment } from "../../utils/branch-resolver.js";
|
|
18
18
|
import {
|
|
19
|
+
BRANCH_STORE_NOT_COMPILED,
|
|
19
20
|
type BranchStoreInspection,
|
|
20
21
|
branchStoreReason,
|
|
21
22
|
inspectBranchStore,
|
|
22
23
|
storeLockJournalReason,
|
|
24
|
+
uncompiledBranchStoreReason,
|
|
23
25
|
} from "../../utils/branch-store.js";
|
|
24
26
|
import {
|
|
25
27
|
loadEntities,
|
|
@@ -459,7 +461,17 @@ export async function executeStatus(
|
|
|
459
461
|
}
|
|
460
462
|
const snapshotEvidence = await readWorkspaceSnapshot(context);
|
|
461
463
|
const existingReasons = payload.staleReasons ?? [];
|
|
462
|
-
|
|
464
|
+
// implements REQ-cli-status-pre-first-sync
|
|
465
|
+
// A missing or empty store beside authored sources gets the one reason
|
|
466
|
+
// whose remediation works (kibi sync); `kibi branch ensure` alone would
|
|
467
|
+
// leave the store empty.
|
|
468
|
+
const storeReason =
|
|
469
|
+
uncompiledBranchStoreReason(
|
|
470
|
+
context.workspaceRoot,
|
|
471
|
+
store,
|
|
472
|
+
attachment.kbBranch,
|
|
473
|
+
) ?? branchStoreReason(store);
|
|
474
|
+
const storeUncompiled = storeReason?.code === BRANCH_STORE_NOT_COMPILED;
|
|
463
475
|
const lockReason = storeLockJournalReason(store.path);
|
|
464
476
|
const compilerReason = compilerFingerprintReason(store.path);
|
|
465
477
|
const engineReason = engineStatus
|
|
@@ -495,6 +507,11 @@ export async function executeStatus(
|
|
|
495
507
|
// Source hashes can all match while the compilation itself is lossy, so
|
|
496
508
|
// a compiler contract change alone makes the store stale.
|
|
497
509
|
...(compilerReason ? { syncState: "stale", dirty: true } : {}),
|
|
510
|
+
// An empty store has no stale file to report, yet nothing in it is
|
|
511
|
+
// current: the authored sources were never compiled.
|
|
512
|
+
...(storeUncompiled && store.state === "healthy"
|
|
513
|
+
? { syncState: "stale", dirty: true }
|
|
514
|
+
: {}),
|
|
498
515
|
branchAttachment: attachment,
|
|
499
516
|
branchStore: store,
|
|
500
517
|
...(engineStatus ? { engineStatus } : {}),
|
|
@@ -644,7 +661,7 @@ export async function executeStatus(
|
|
|
644
661
|
content: [
|
|
645
662
|
{
|
|
646
663
|
type: "text",
|
|
647
|
-
text: `Branch ${payload.branch} is ${
|
|
664
|
+
text: `Branch ${payload.branch} is ${enrichedPayload.syncState} (snapshot ${payload.snapshotId}, dirty=${enrichedPayload.dirty}, proofSnapshot=${enrichedPayload.proofSnapshot})${storeUncompiled ? `. Blocking: ${String(storeReason?.detail)} Run kibi sync.` : ""}`,
|
|
648
665
|
},
|
|
649
666
|
],
|
|
650
667
|
structuredContent: statusWithPlan,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { existsSync, readFileSync } from "node:fs";
|
|
3
3
|
import * as path from "node:path";
|
|
4
|
+
import { BRANCH_STORE_NOT_COMPILED } from "../../utils/branch-store.js";
|
|
4
5
|
import { legacyConfigExists } from "../../utils/config.js";
|
|
5
6
|
import { readKbManifestStatus } from "../../utils/kb-manifest.js";
|
|
6
7
|
import {
|
|
@@ -744,8 +745,42 @@ export function buildActionsFromStatus(input: {
|
|
|
744
745
|
);
|
|
745
746
|
}
|
|
746
747
|
|
|
748
|
+
// implements REQ-cli-status-pre-first-sync
|
|
749
|
+
// A branch store that was never compiled while .kb/ holds authored sources
|
|
750
|
+
// is fixed only by compiling it: `kibi branch ensure` alone leaves an empty
|
|
751
|
+
// manifest. The compile step runs after the store exists and after any
|
|
752
|
+
// schema migration, so it compiles the migrated sources.
|
|
753
|
+
const uncompiled = (input.staleReasons ?? []).find(
|
|
754
|
+
(reason) => reason.code === BRANCH_STORE_NOT_COMPILED,
|
|
755
|
+
);
|
|
756
|
+
if (uncompiled !== undefined) {
|
|
757
|
+
actions.push(
|
|
758
|
+
migrationAction({
|
|
759
|
+
id: "branch-store-compile",
|
|
760
|
+
code: BRANCH_STORE_NOT_COMPILED,
|
|
761
|
+
category: "storage",
|
|
762
|
+
safety: "automatic",
|
|
763
|
+
invocation: { kind: "cli", command_argv: ["kibi", "sync"] },
|
|
764
|
+
affectedFiles: [
|
|
765
|
+
typeof store?.path === "string" ? store.path : ".kb/branches",
|
|
766
|
+
],
|
|
767
|
+
evidence: { reason: uncompiled },
|
|
768
|
+
dependsOn: actions
|
|
769
|
+
.map((action) => action.id)
|
|
770
|
+
.filter(
|
|
771
|
+
(id) =>
|
|
772
|
+
id === "branch-store-ensure" || id === "schema-config-upgrade",
|
|
773
|
+
),
|
|
774
|
+
postconditions: [{ branchStore: "compiled" }],
|
|
775
|
+
autoApplicable: true,
|
|
776
|
+
}),
|
|
777
|
+
);
|
|
778
|
+
}
|
|
779
|
+
|
|
747
780
|
for (const reason of input.staleReasons ?? []) {
|
|
748
781
|
const code = typeof reason.code === "string" ? reason.code : "stale_source";
|
|
782
|
+
// Planned above as an automatic compile step, not a review.
|
|
783
|
+
if (code === BRANCH_STORE_NOT_COMPILED) continue;
|
|
749
784
|
const file = typeof reason.path === "string" ? reason.path : "";
|
|
750
785
|
actions.push(
|
|
751
786
|
migrationAction({
|
|
@@ -15,6 +15,7 @@ export const SELECTABLE_RULE_NAMES: readonly string[] = [
|
|
|
15
15
|
"symbol-traceability",
|
|
16
16
|
"no-dangling-refs",
|
|
17
17
|
"source-relationship-parity",
|
|
18
|
+
"branch-store-not-compiled",
|
|
18
19
|
"source-path-dangling",
|
|
19
20
|
"no-cycles",
|
|
20
21
|
"required-fields",
|
|
@@ -61,4 +62,4 @@ export const SELECTABLE_RULE_NAMES: readonly string[] = [
|
|
|
61
62
|
// implements REQ-006
|
|
62
63
|
/** Comma-separated "Allowed:" fragment for the kb_check rules description. */
|
|
63
64
|
export const SELECTABLE_RULES_ALLOWED =
|
|
64
|
-
"must-priority-coverage, symbol-coverage, symbol-traceability, no-dangling-refs, source-relationship-parity, source-path-dangling, no-cycles, required-fields, deprecated-adr-no-successor, superseded-requirement-open, scenario-feasibility, scenario-feasibility-unknown, exception-claim-keys, numeric-string-value, rule-key-arguments-missing, domain-contradictions, logic-coverage, rule-safety, rule-verifiability, query-plan-safety, req-status-vocabulary, strict-fact-shape, strict-req-fact-pairing, predicate-verifiability, strict-readiness, semantic-completeness, related-requirement-unmodeled, proof-contract-symbols, entity-id-style, domain-redundancy, domain-implication, subject-key-identity, subject-key-shape, ontology-quality, exception-unapproved, exception-approval-self-attested, agent-requirement-unapproved, requirement-rationale-missing, symbol-owner-superseded, adr-unlinked, adr-proposed, predicate-schema-conformance, entity-context-missing, entity-context-acknowledged, policy-ownership, policy-markers";
|
|
65
|
+
"must-priority-coverage, symbol-coverage, symbol-traceability, no-dangling-refs, source-relationship-parity, branch-store-not-compiled, source-path-dangling, no-cycles, required-fields, deprecated-adr-no-successor, superseded-requirement-open, scenario-feasibility, scenario-feasibility-unknown, exception-claim-keys, numeric-string-value, rule-key-arguments-missing, domain-contradictions, logic-coverage, rule-safety, rule-verifiability, query-plan-safety, req-status-vocabulary, strict-fact-shape, strict-req-fact-pairing, predicate-verifiability, strict-readiness, semantic-completeness, related-requirement-unmodeled, proof-contract-symbols, entity-id-style, domain-redundancy, domain-implication, subject-key-identity, subject-key-shape, ontology-quality, exception-unapproved, exception-approval-self-attested, agent-requirement-unapproved, requirement-rationale-missing, symbol-owner-superseded, adr-unlinked, adr-proposed, predicate-schema-conformance, entity-context-missing, entity-context-acknowledged, policy-ownership, policy-markers";
|
|
@@ -29,17 +29,76 @@ function requiredFields(spec: {
|
|
|
29
29
|
return Array.isArray(required) ? (required as string[]) : [];
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
type CompositeRoute = {
|
|
33
|
+
readonly name?: string;
|
|
34
|
+
readonly execute: Executor;
|
|
35
|
+
readonly businessInputSchema: Readonly<Record<string, unknown>>;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Per route, the parameters another route of the same composite owns that
|
|
40
|
+
* mean the same thing here under another name. kb_model mode requirement
|
|
41
|
+
* takes the claim's subject as subjectKey; mode predicates takes it as
|
|
42
|
+
* subjectHint.
|
|
43
|
+
*/
|
|
44
|
+
const EQUIVALENT_PARAMETERS: Readonly<
|
|
45
|
+
Record<string, Readonly<Record<string, string>>>
|
|
46
|
+
> = {
|
|
47
|
+
kb_suggest_predicates: { subjectKey: "subjectHint" },
|
|
48
|
+
kb_model_requirement: { subjectHint: "subjectKey" },
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/** Routed operations whose `warnings` are `{ kind, message, nextAction }`. */
|
|
52
|
+
const RECORD_WARNING_OPERATIONS = new Set(["kb_model_requirement"]);
|
|
53
|
+
|
|
54
|
+
// implements REQ-kibi-mcp-tool-consolidation
|
|
55
|
+
/**
|
|
56
|
+
* A composite accepts every route's parameters, so a parameter of another
|
|
57
|
+
* route passes schema validation and the chosen route silently ignores it.
|
|
58
|
+
* Name each one instead, with the parameter this route uses for the same
|
|
59
|
+
* thing when there is one.
|
|
60
|
+
*/
|
|
61
|
+
export function foreignParameterWarnings(
|
|
62
|
+
selector: "action" | "mode",
|
|
63
|
+
choice: string,
|
|
64
|
+
routes: Readonly<Record<string, CompositeRoute>>,
|
|
65
|
+
rest: Readonly<Record<string, unknown>>,
|
|
66
|
+
): Array<{ parameter: string; message: string; nextAction: string }> {
|
|
67
|
+
const route = routes[choice];
|
|
68
|
+
if (route === undefined) return [];
|
|
69
|
+
const own = new Set(Object.keys(properties(route)));
|
|
70
|
+
const equivalents =
|
|
71
|
+
route.name === undefined ? {} : (EQUIVALENT_PARAMETERS[route.name] ?? {});
|
|
72
|
+
const warnings: Array<{
|
|
73
|
+
parameter: string;
|
|
74
|
+
message: string;
|
|
75
|
+
nextAction: string;
|
|
76
|
+
}> = [];
|
|
77
|
+
for (const parameter of Object.keys(rest)) {
|
|
78
|
+
if (own.has(parameter) || rest[parameter] === undefined) continue;
|
|
79
|
+
const owners = Object.entries(routes)
|
|
80
|
+
.filter(
|
|
81
|
+
([other, otherRoute]) =>
|
|
82
|
+
other !== choice && parameter in properties(otherRoute),
|
|
83
|
+
)
|
|
84
|
+
.map(([other]) => `${selector}: ${other}`);
|
|
85
|
+
if (owners.length === 0) continue;
|
|
86
|
+
const equivalent = equivalents[parameter];
|
|
87
|
+
warnings.push({
|
|
88
|
+
parameter,
|
|
89
|
+
message: `${parameter} is a ${owners.join(" / ")} argument; ${selector}: ${choice} ignored it.`,
|
|
90
|
+
nextAction:
|
|
91
|
+
equivalent !== undefined
|
|
92
|
+
? `Use ${equivalent} in ${selector}: ${choice}.`
|
|
93
|
+
: `Drop ${parameter}, or switch to ${owners.join(" / ")} if that is what you meant.`,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
return warnings;
|
|
97
|
+
}
|
|
98
|
+
|
|
32
99
|
export async function dispatchComposite(
|
|
33
100
|
selector: "action" | "mode",
|
|
34
|
-
routes: Readonly<
|
|
35
|
-
Record<
|
|
36
|
-
string,
|
|
37
|
-
{
|
|
38
|
-
readonly execute: Executor;
|
|
39
|
-
readonly businessInputSchema: Readonly<Record<string, unknown>>;
|
|
40
|
-
}
|
|
41
|
-
>
|
|
42
|
-
>,
|
|
101
|
+
routes: Readonly<Record<string, CompositeRoute>>,
|
|
43
102
|
input: Readonly<Record<string, unknown>>,
|
|
44
103
|
context: OperationContext,
|
|
45
104
|
): Promise<OperationResult<Record<string, unknown>>> {
|
|
@@ -69,9 +128,49 @@ export async function dispatchComposite(
|
|
|
69
128
|
wrapped && Array.isArray(result.content)
|
|
70
129
|
? (result.content as OperationResult["content"])
|
|
71
130
|
: [{ type: "text", text: `${selector} ${String(choice)} completed` }];
|
|
131
|
+
const ignored = foreignParameterWarnings(
|
|
132
|
+
selector,
|
|
133
|
+
String(choice),
|
|
134
|
+
routes,
|
|
135
|
+
rest,
|
|
136
|
+
);
|
|
137
|
+
if (ignored.length === 0) {
|
|
138
|
+
return {
|
|
139
|
+
content,
|
|
140
|
+
structuredContent: { [selector]: choice, ...payload },
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
// The routed payload's own warnings list carries them, in its own shape;
|
|
144
|
+
// a payload without one gets them in the text content only.
|
|
145
|
+
const asRecords =
|
|
146
|
+
route.name !== undefined && RECORD_WARNING_OPERATIONS.has(route.name);
|
|
147
|
+
const routedWarnings = Array.isArray(payload.warnings)
|
|
148
|
+
? {
|
|
149
|
+
warnings: [
|
|
150
|
+
...payload.warnings,
|
|
151
|
+
...ignored.map((warning) =>
|
|
152
|
+
asRecords
|
|
153
|
+
? {
|
|
154
|
+
kind: "parameter_ignored",
|
|
155
|
+
message: warning.message,
|
|
156
|
+
nextAction: warning.nextAction,
|
|
157
|
+
}
|
|
158
|
+
: `${warning.message} ${warning.nextAction}`,
|
|
159
|
+
),
|
|
160
|
+
],
|
|
161
|
+
}
|
|
162
|
+
: {};
|
|
72
163
|
return {
|
|
73
|
-
content
|
|
74
|
-
|
|
164
|
+
content: [
|
|
165
|
+
...content,
|
|
166
|
+
{
|
|
167
|
+
type: "text",
|
|
168
|
+
text: ignored
|
|
169
|
+
.map((warning) => `${warning.message} ${warning.nextAction}`)
|
|
170
|
+
.join("\n"),
|
|
171
|
+
},
|
|
172
|
+
],
|
|
173
|
+
structuredContent: { [selector]: choice, ...payload, ...routedWarnings },
|
|
75
174
|
};
|
|
76
175
|
}
|
|
77
176
|
|
|
@@ -78,7 +78,7 @@ export const modelRequirementSpec = {
|
|
|
78
78
|
requirementId: {
|
|
79
79
|
type: "string",
|
|
80
80
|
description:
|
|
81
|
-
"Optional
|
|
81
|
+
"Optional requirement ID. The strict write set updates this requirement instead of minting a REQ-AUTO id, and a typed logic rule attaches its requires_rule relationship to it.",
|
|
82
82
|
},
|
|
83
83
|
claimKey: {
|
|
84
84
|
type: "string",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
id: kibi-bootstrap
|
|
3
3
|
name: kibi-bootstrap
|
|
4
4
|
description: "Use for any Kibi bootstrap or onboarding task: seeding a new or thin knowledge base; reviewing a bootstrap or onboarding plan, preview, or evidence; judging approval readiness or coverage; diagnosing a blocked, partial, or failed bootstrap or its repair; applying an approved bootstrap plan; or asking the human which knowledge sources hold intent. Covers kb_status first, source interview, cited intent claims, read-only kb_plan_bootstrap preview, explicit approval, exact-plan kb_apply_plan, and repair-safe close-out."
|
|
5
|
-
version: 3.
|
|
5
|
+
version: 3.11.0
|
|
6
6
|
kibiCompatibility: ">=1.0.0"
|
|
7
7
|
tags:
|
|
8
8
|
- kibi
|
|
@@ -46,6 +46,7 @@ Seed branch-local Kibi knowledge from cited product intent, without creating a p
|
|
|
46
46
|
- **Scenarios.** Write scenarios from the cited ticket's acceptance criteria, one scenario per criterion, not bulk drafts from the requirement title; ask the human when the source states none. Give each a plain title, the scenario prose in `document.body` (never in `properties`), and `assumes` links to the `property_value` facts whose values the scenario relies on. Set `expects` only when the scenario links `assumes` facts (or its criterion names concrete values that become them); `expects` without `assumes` only yields a feasibility-unknown warning, so a draft tagged `needs-human-review` omits `expects`. Then link the requirement with `specified_by` (upsert the `req` with its stored `title`, a `status` and that relationship only). Example: criterion "Given an annotation in draft state, when the user deletes it, the draft is cleared" becomes `{"type":"scenario","id":"SCEN-annotation-delete-clears-draft","properties":{"title":"Deleting a draft annotation clears the draft","status":"active","expects":"success"},"document":{"body":"Given an annotation in draft state, when the user deletes it, then the draft is cleared and nothing is published.\n\nThe acceptance criterion comes from the cited ticket; reviewers asked for it so a deleted draft never reappears after reload.\n"},"relationships":[{"type":"assumes","from":"SCEN-annotation-delete-clears-draft","to":"FACT-annotation-state-draft"}]}`, where the assumed fact is a `property_value` (`annotation.state` `eq` `draft`). Link existing tests that exercise it; never invent test evidence.
|
|
47
47
|
- **Predicates.** Run `kb_model` with `mode: "predicates"` and `requirementId` on each persisted requirement and apply a returned plan with `requires_predicate` to its `relationshipTarget` (the planned `FACT-PRED-…` id, never a `SUGGEST-…` candidate id), or record the `review:ontology-gap` observation it returns, with its prose in `document.body`. A non-empty `existingGrounding` means the bootstrap already grounded that claim: on `replace_grounding` leave it unless the human wants the `replacementPlan` swap; on `provide_argument_bindings` retry with the listed arguments bound; on `record_ontology_gap` still write the returned gap observation, which is not a grounding link. Count what `kb_query` shows afterwards, not the calls you made.
|
|
48
48
|
- **Unrecorded ambiguity.** Record any conflict or open question you found but did not declare in step 3 as a cited `fact_kind: observation` tagged `review:conflict` or `review:open-question`.
|
|
49
|
+
- **Proof integration.** Run `kibi proof inspect --json`. When it returns an `integrationPlan` (a `command` integration for the detected test runner), show the human the proposed command and `contractDefaults`, and on approval apply that exact plan with `kb_apply_plan` (`plan`, `approvedPlanHash` = its `planHash`, `approvedActionIds`); it writes `.kb/proof/integrations.json`, which you never hand-write. With no runner detected, report that proof stays deferred. Proof-bearing tests then name the integration in `proof_contract.integration`, and `kibi prove` records their evidence.
|
|
49
50
|
Finish with `kb_check` and `kb_status`.
|
|
50
51
|
12. **Report** calls made, result statuses, applied scope, what step 11 authored, gaps, and follow-ups. Classify as complete, partial, awaiting approval, or blocked.
|
|
51
52
|
|
|
@@ -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.12.0
|
|
6
6
|
kibiCompatibility: ">=1.0.0"
|
|
7
7
|
tags:
|
|
8
8
|
- kibi
|
|
@@ -219,11 +219,19 @@ authored. Each one is the order the write path accepts.
|
|
|
219
219
|
`semantic_inventory_version`, `semantic_source_field` and
|
|
220
220
|
`semantic_source_hash`, the prose into `semantic_text`, `propositions`
|
|
221
221
|
into `semantic_inventory` and the assertive `claim_key`s into
|
|
222
|
-
`logic_claims`.
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
222
|
+
`logic_claims`. Reuse (or `kb_upsert`) the subject fact, then call
|
|
223
|
+
`kb_model` mode `predicates` per clause with `subjectHint` set to that
|
|
224
|
+
subject fact's `subject_key`: the requirement constrains nothing yet, so
|
|
225
|
+
the hint is the planned subject and the planned fact gets its
|
|
226
|
+
`subject_key` (`subjectKey` is a mode `requirement` parameter; mode
|
|
227
|
+
`predicates` ignores it and warns). `kb_upsert` the returned `applyPlan`
|
|
228
|
+
fact first (it carries the clause's `claim_key`). Then write the
|
|
229
|
+
requirement in one `kb_upsert` with the ledger (that clause `status:
|
|
230
|
+
modeled`), a sectioned `document.body`, `constrains` to the subject
|
|
231
|
+
fact, `requires_predicate` to `relationshipTarget` and `specified_by` to
|
|
232
|
+
its scenario: `specified_by` (req → scenario) is sent in the
|
|
233
|
+
requirement's write, never in the scenario's, so create the scenario
|
|
234
|
+
first. A
|
|
227
235
|
`modeled` entry and its grounding link must arrive in the same write
|
|
228
236
|
(`modeled semantic_inventory entries (n) must equal logical grounding
|
|
229
237
|
relationships (m)`); a clause not grounded yet stays `status: missing`
|
|
@@ -54,7 +54,16 @@ Provenance lives in `proof_bindings`; the contract stays semantic.
|
|
|
54
54
|
## Integration configuration
|
|
55
55
|
|
|
56
56
|
`.kb/proof/integrations.json` (`kibi.proof-integration.v1`) is tracked,
|
|
57
|
-
Kibi-managed configuration describing evidence production only
|
|
57
|
+
Kibi-managed configuration describing evidence production only. Never
|
|
58
|
+
hand-write it: `kibi proof inspect --json` proposes a `command` integration
|
|
59
|
+
for the detected test runner (the `package.json` `test` script first) and
|
|
60
|
+
returns `integrationPlan`, a hash-bound `kibi.migration-plan.v2`, plus the
|
|
61
|
+
`contractDefaults` a proof-bearing test's `proof_contract` uses. Show the
|
|
62
|
+
proposal to the human, then apply the plan with `kb_apply_plan` (or
|
|
63
|
+
`kibi apply-plan --input -`) passing `plan`, `approvedPlanHash` (the plan's
|
|
64
|
+
`planHash`) and `approvedActionIds`. Once the file exists, a create plan is
|
|
65
|
+
refused; `kibi proof inspect --update <id> --json` plans adding or replacing
|
|
66
|
+
one named integration.
|
|
58
67
|
|
|
59
68
|
- `producer: command` — Kibi synthesizes the envelope from the process
|
|
60
69
|
outcome; obligations are bound with `aggregate_run` provenance and the
|
|
@@ -82,8 +91,11 @@ effective fingerprint and do.
|
|
|
82
91
|
|
|
83
92
|
## Common rejections
|
|
84
93
|
|
|
85
|
-
- `No proof integration configuration` —
|
|
86
|
-
|
|
94
|
+
- `No proof integration configuration` — proof is not configured for this
|
|
95
|
+
repository yet; run `kibi proof inspect --json`, review its
|
|
96
|
+
`integrationPlan` and apply it with `kb_apply_plan`.
|
|
97
|
+
- `integration '<id>' ... is not configured` — the test names an integration
|
|
98
|
+
the file lacks; plan it with `kibi proof inspect --update <id> --json`.
|
|
87
99
|
- `captured snapshot is not the live workspace snapshot` — the tree changed
|
|
88
100
|
between capture and ingest; re-run `kibi prove`.
|
|
89
101
|
- `artifact command_argv does not match the configured command` — the
|