kibi-cli 2.38.0 → 2.40.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-json-command.d.ts.map +1 -1
- package/dist/cli-json-command.js +4 -0
- package/dist/cli-register-foundation.js +2 -2
- package/dist/cli-register-reporting.d.ts.map +1 -1
- package/dist/cli-register-reporting.js +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +3 -0
- package/dist/commands/check.d.ts.map +1 -1
- package/dist/commands/check.js +33 -9
- package/dist/commands/coverage.d.ts +1 -0
- package/dist/commands/coverage.d.ts.map +1 -1
- package/dist/commands/coverage.js +40 -0
- package/dist/commands/doctor.d.ts +5 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +29 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +4 -0
- package/dist/commands/migrate-plan-record.d.ts +18 -0
- package/dist/commands/migrate-plan-record.d.ts.map +1 -0
- package/dist/commands/migrate-plan-record.js +112 -0
- package/dist/commands/migrate.d.ts +11 -2
- package/dist/commands/migrate.d.ts.map +1 -1
- package/dist/commands/migrate.js +60 -8
- package/dist/commands/prove.d.ts.map +1 -1
- package/dist/commands/prove.js +18 -3
- package/dist/commands/sync/manifest.d.ts.map +1 -1
- package/dist/commands/sync/manifest.js +17 -4
- package/dist/commands/sync/persistence.d.ts.map +1 -1
- package/dist/commands/sync/persistence.js +6 -0
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +8 -0
- package/dist/commands/telemetry.d.ts.map +1 -1
- package/dist/commands/telemetry.js +12 -2
- package/dist/extractors/markdown.d.ts +6 -0
- package/dist/extractors/markdown.d.ts.map +1 -1
- package/dist/extractors/markdown.js +21 -0
- package/dist/extractors/symbol-title-match.d.ts +31 -0
- package/dist/extractors/symbol-title-match.d.ts.map +1 -0
- package/dist/extractors/symbol-title-match.js +133 -0
- package/dist/extractors/symbols-coordinator.d.ts.map +1 -1
- package/dist/extractors/symbols-coordinator.js +81 -12
- package/dist/operations/bootstrap/discovery-evidence.d.ts.map +1 -1
- package/dist/operations/bootstrap/discovery-evidence.js +44 -2
- package/dist/operations/bootstrap/discovery.d.ts.map +1 -1
- package/dist/operations/bootstrap/discovery.js +1 -0
- package/dist/operations/bootstrap/guidance-actions.d.ts.map +1 -1
- package/dist/operations/bootstrap/guidance-actions.js +12 -1
- package/dist/operations/bootstrap/plugin-offers.d.ts +7 -1
- package/dist/operations/bootstrap/plugin-offers.d.ts.map +1 -1
- package/dist/operations/bootstrap/plugin-offers.js +73 -3
- package/dist/operations/modeling/logic-modeling.d.ts.map +1 -1
- package/dist/operations/modeling/logic-modeling.js +2 -1
- package/dist/operations/modeling/model-requirement.d.ts.map +1 -1
- package/dist/operations/modeling/model-requirement.js +2 -1
- package/dist/operations/mutation/symbol-refresh.d.ts +2 -0
- package/dist/operations/mutation/symbol-refresh.d.ts.map +1 -1
- package/dist/operations/mutation/symbol-refresh.js +6 -1
- package/dist/operations/mutation/upsert.d.ts.map +1 -1
- package/dist/operations/mutation/upsert.js +7 -0
- package/dist/operations/planning/compile-intent.d.ts.map +1 -1
- package/dist/operations/planning/compile-intent.js +2 -1
- package/dist/operations/proof/claim-bindings.d.ts +11 -0
- package/dist/operations/proof/claim-bindings.d.ts.map +1 -1
- package/dist/operations/proof/claim-bindings.js +144 -1
- package/dist/operations/proof/code-certificates.d.ts +10 -3
- package/dist/operations/proof/code-certificates.d.ts.map +1 -1
- package/dist/operations/proof/code-certificates.js +65 -13
- package/dist/operations/proof/code-languages.d.ts +104 -0
- package/dist/operations/proof/code-languages.d.ts.map +1 -0
- package/dist/operations/proof/code-languages.js +119 -0
- package/dist/operations/proof/code-models.d.ts +2 -0
- package/dist/operations/proof/code-models.d.ts.map +1 -1
- package/dist/operations/proof/code-models.js +11 -5
- package/dist/operations/proof/code-runner.d.ts +12 -9
- package/dist/operations/proof/code-runner.d.ts.map +1 -1
- package/dist/operations/proof/code-runner.js +81 -38
- package/dist/operations/proof/code-scope.d.ts +8 -0
- package/dist/operations/proof/code-scope.d.ts.map +1 -1
- package/dist/operations/proof/code-scope.js +30 -1
- package/dist/operations/proof/explain.d.ts +76 -0
- package/dist/operations/proof/explain.d.ts.map +1 -1
- package/dist/operations/proof/explain.js +228 -0
- package/dist/operations/proof/ingest-proof.d.ts +2 -0
- package/dist/operations/proof/ingest-proof.d.ts.map +1 -1
- package/dist/operations/proof/ingest-proof.js +1 -0
- package/dist/operations/proof/java-package-shadow.d.ts +14 -0
- package/dist/operations/proof/java-package-shadow.d.ts.map +1 -0
- package/dist/operations/proof/java-package-shadow.js +389 -0
- package/dist/operations/proof/prolog-evaluator.d.ts +14 -0
- package/dist/operations/proof/prolog-evaluator.d.ts.map +1 -0
- package/dist/operations/proof/prolog-evaluator.js +247 -0
- package/dist/operations/proof/prolog-source-reader.d.ts +20 -0
- package/dist/operations/proof/prolog-source-reader.d.ts.map +1 -0
- package/dist/operations/proof/prolog-source-reader.js +1123 -0
- package/dist/operations/proof/source-code-readers.d.ts +6 -0
- package/dist/operations/proof/source-code-readers.d.ts.map +1 -1
- package/dist/operations/proof/source-code-readers.js +879 -75
- package/dist/operations/semantic-advisor/analyze-prose.d.ts +9 -1
- package/dist/operations/semantic-advisor/analyze-prose.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/analyze-prose.js +21 -0
- package/dist/operations/semantic-advisor/case-preview.d.ts +24 -0
- package/dist/operations/semantic-advisor/case-preview.d.ts.map +1 -0
- package/dist/operations/semantic-advisor/case-preview.js +216 -0
- package/dist/operations/semantic-advisor/shared.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/shared.js +3 -0
- package/dist/operations/semantic-advisor/types.d.ts +23 -0
- package/dist/operations/semantic-advisor/types.d.ts.map +1 -1
- package/dist/plugins/approved-source-analyzers.generated.d.ts +15 -34
- package/dist/plugins/approved-source-analyzers.generated.d.ts.map +1 -1
- package/dist/plugins/approved-source-analyzers.generated.js +15 -34
- package/dist/plugins/plugin-install-check.d.ts +21 -0
- package/dist/plugins/plugin-install-check.d.ts.map +1 -0
- package/dist/plugins/plugin-install-check.js +62 -0
- package/dist/plugins/proof-reference-extractors.d.ts +20 -0
- package/dist/plugins/proof-reference-extractors.d.ts.map +1 -0
- package/dist/plugins/proof-reference-extractors.js +104 -0
- package/dist/plugins/reference-language-suggestion.d.ts +51 -0
- package/dist/plugins/reference-language-suggestion.d.ts.map +1 -0
- package/dist/plugins/reference-language-suggestion.js +277 -0
- package/dist/plugins/registry.d.ts.map +1 -1
- package/dist/plugins/registry.js +3 -1
- package/dist/plugins/source-analysis-service.d.ts.map +1 -1
- package/dist/plugins/source-analysis-service.js +4 -0
- package/dist/plugins/source-change-analysis.d.ts +26 -1
- package/dist/plugins/source-change-analysis.d.ts.map +1 -1
- package/dist/plugins/source-change-analysis.js +77 -5
- package/dist/plugins/source-classification.d.ts +2 -2
- package/dist/plugins/source-classification.d.ts.map +1 -1
- package/dist/plugins/source-classification.js +45 -1
- package/dist/public/operations/catalog.d.ts +62 -7
- package/dist/public/operations/catalog.d.ts.map +1 -1
- package/dist/public/operations/check-executor.d.ts.map +1 -1
- package/dist/public/operations/check-executor.js +3 -0
- package/dist/public/operations/evidence-floor.d.ts +8 -0
- package/dist/public/operations/evidence-floor.d.ts.map +1 -1
- package/dist/public/operations/evidence-floor.js +19 -1
- package/dist/public/operations/repair-plan.d.ts +46 -0
- package/dist/public/operations/repair-plan.d.ts.map +1 -1
- package/dist/public/operations/repair-plan.js +110 -1
- package/dist/public/operations/schema6-check-actions.js +1 -1
- 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 +3 -1
- package/dist/public/operations/specs/check.d.ts +1 -1
- package/dist/public/operations/specs/mutation-schemas.d.ts +61 -6
- package/dist/public/operations/specs/mutation-schemas.d.ts.map +1 -1
- package/dist/public/operations/specs/mutation-schemas.js +30 -0
- package/dist/public/operations/specs/reporting.d.ts +8 -0
- package/dist/public/operations/specs/reporting.d.ts.map +1 -1
- package/dist/public/operations/specs/reporting.js +26 -3
- package/dist/public/operations/specs/semantic.d.ts.map +1 -1
- package/dist/public/operations/specs/semantic.js +2 -1
- package/dist/public/operations/specs/upsert.d.ts +61 -6
- package/dist/public/operations/specs/upsert.d.ts.map +1 -1
- package/dist/public/operations/symbol-coordinates-check.d.ts +11 -0
- package/dist/public/operations/symbol-coordinates-check.d.ts.map +1 -0
- package/dist/public/operations/symbol-coordinates-check.js +66 -0
- package/dist/public/proof-protocol.d.ts +31 -6
- package/dist/public/proof-protocol.d.ts.map +1 -1
- package/dist/public/proof-protocol.js +45 -15
- package/dist/public/proof-sources.d.ts +4 -2
- package/dist/public/proof-sources.d.ts.map +1 -1
- package/dist/public/proof-sources.js +43 -4
- package/dist/public/schemas/entity.d.ts.map +1 -1
- package/dist/public/schemas/entity.js +59 -0
- package/dist/public/skills/kibi-commit-review/SKILL.md +6 -2
- package/dist/public/skills/kibi-decisions/SKILL.md +7 -2
- package/dist/public/skills/kibi-decisions/resources/signoff-views.md +3 -1
- package/dist/public/skills/kibi-usage/SKILL.md +14 -3
- package/dist/public/skills/kibi-usage/resources/prolog-proofs.md +207 -0
- package/dist/public/skills/kibi-usage/resources/proof.md +44 -3
- package/dist/schemas/entity.schema.json +126 -6
- package/dist/search-answer.d.ts +3 -2
- package/dist/search-answer.d.ts.map +1 -1
- package/dist/search-answer.js +56 -3
- package/dist/traceability/analysis-gate.d.ts +3 -1
- package/dist/traceability/analysis-gate.d.ts.map +1 -1
- package/dist/traceability/analysis-gate.js +9 -1
- package/dist/traceability/impact-knowledge.d.ts.map +1 -1
- package/dist/traceability/impact-knowledge.js +2 -0
- package/dist/traceability/staged-file-coverage.d.ts.map +1 -1
- package/dist/traceability/staged-file-coverage.js +7 -2
- package/dist/traceability/symbol-extract.d.ts +17 -0
- package/dist/traceability/symbol-extract.d.ts.map +1 -1
- package/dist/traceability/symbol-extract.js +69 -15
- package/dist/traceability/temp-kb.d.ts.map +1 -1
- package/dist/traceability/temp-kb.js +11 -1
- package/dist/traceability/validate.d.ts.map +1 -1
- package/dist/traceability/validate.js +5 -7
- package/dist/types/entities.d.ts +12 -0
- package/dist/types/entities.d.ts.map +1 -1
- package/dist/usage-telemetry.d.ts +9 -0
- package/dist/usage-telemetry.d.ts.map +1 -1
- package/dist/usage-telemetry.js +50 -4
- package/dist/utils/first-sentence.d.ts +9 -0
- package/dist/utils/first-sentence.d.ts.map +1 -0
- package/dist/utils/first-sentence.js +52 -0
- package/dist/utils/rule-registry.generated.d.ts +11 -0
- package/dist/utils/rule-registry.generated.d.ts.map +1 -1
- package/dist/utils/rule-registry.generated.js +13 -0
- package/package.json +5 -5
- package/schema/entities.pl +12 -0
- package/src/public/operations/check-executor.ts +8 -0
- package/src/public/operations/evidence-floor.ts +29 -1
- package/src/public/operations/repair-plan.ts +152 -1
- package/src/public/operations/schema6-check-actions.ts +1 -1
- package/src/public/operations/specs/check-rules.generated.ts +3 -1
- package/src/public/operations/specs/mutation-schemas.ts +34 -0
- package/src/public/operations/specs/reporting.ts +38 -3
- package/src/public/operations/specs/semantic.ts +2 -1
- package/src/public/operations/symbol-coordinates-check.ts +79 -0
- package/src/public/proof-protocol-types.d.ts +22 -5
- package/src/public/proof-protocol.ts +78 -19
- package/src/public/proof-sources.ts +51 -3
- package/src/public/schemas/entity.ts +65 -0
- package/src/public/skills/kibi-commit-review/SKILL.md +6 -2
- package/src/public/skills/kibi-decisions/SKILL.md +7 -2
- package/src/public/skills/kibi-decisions/resources/signoff-views.md +3 -1
- package/src/public/skills/kibi-usage/SKILL.md +14 -3
- package/src/public/skills/kibi-usage/resources/prolog-proofs.md +207 -0
- package/src/public/skills/kibi-usage/resources/proof.md +44 -3
- package/src/schemas/entity.schema.json +126 -6
|
@@ -110,6 +110,40 @@ const REPAIR_PHASES = {
|
|
|
110
110
|
validationRules: ["must-priority-coverage", "no-dangling-refs"],
|
|
111
111
|
writePolicy: "sequential_upsert",
|
|
112
112
|
},
|
|
113
|
+
dimension_grounding: {
|
|
114
|
+
order: 64,
|
|
115
|
+
objective:
|
|
116
|
+
"Ground each quantified claim (each, every, all, or a cardinality bound) on what varies: an integer count or bound, a set of members, a rule over a variable, or a state machine. If the quantifier ranges over nothing, record a dimension_waiver on the grounding fact for a person to approve, and record their approval in the same pull request.",
|
|
117
|
+
workflowSteps: [
|
|
118
|
+
"kb_model_requirement",
|
|
119
|
+
"kb_validate_upsert",
|
|
120
|
+
"kb_upsert",
|
|
121
|
+
"kb_check",
|
|
122
|
+
],
|
|
123
|
+
validationRules: ["no-dangling-refs"],
|
|
124
|
+
writePolicy: "sequential_upsert",
|
|
125
|
+
},
|
|
126
|
+
case_scenarios: {
|
|
127
|
+
order: 66,
|
|
128
|
+
objective:
|
|
129
|
+
"Cover each uncovered rejection case: add a scenario whose assumes fact states the case's assumption (a value past the bound, a value outside the set), expects rejection or error, is linked with specified_by and is verified by a passing end-to-end test. Each repair lists caseSkeletons, upsert-ready draft scenarios and their assumed facts: fill in the placeholders, verify the scenario by a test, then set its status to active (a draft never covers a case). If a person accepts the cases as covered another way, record a case_waiver on the grounding fact for them to approve, and record their approval in the same pull request.",
|
|
130
|
+
workflowSteps: [
|
|
131
|
+
"kb_coverage",
|
|
132
|
+
"kb_validate_upsert",
|
|
133
|
+
"kb_upsert",
|
|
134
|
+
"kb_check",
|
|
135
|
+
],
|
|
136
|
+
validationRules: ["scenario-outcome-mismatch", "no-dangling-refs"],
|
|
137
|
+
writePolicy: "sequential_upsert",
|
|
138
|
+
},
|
|
139
|
+
negative_scenarios: {
|
|
140
|
+
order: 65,
|
|
141
|
+
objective:
|
|
142
|
+
"Add a scenario that expects rejection or error and assumes a value the requirement forbids (see suggestedNegatives), link it with specified_by and verify it with a passing end-to-end test.",
|
|
143
|
+
workflowSteps: ["kb_query", "kb_validate_upsert", "kb_upsert", "kb_check"],
|
|
144
|
+
validationRules: ["scenario-outcome-mismatch", "no-dangling-refs"],
|
|
145
|
+
writePolicy: "sequential_upsert",
|
|
146
|
+
},
|
|
113
147
|
scenario_tests: {
|
|
114
148
|
order: 70,
|
|
115
149
|
objective:
|
|
@@ -206,6 +240,9 @@ const GAP_PHASE: Readonly<Record<string, RepairPhase>> = {
|
|
|
206
240
|
missing_scenario: "scenario_endpoints",
|
|
207
241
|
infeasible_scenario: "scenario_endpoints",
|
|
208
242
|
unknown_scenario_feasibility: "scenario_endpoints",
|
|
243
|
+
dimension_unrepresented: "dimension_grounding",
|
|
244
|
+
happy_path_only: "negative_scenarios",
|
|
245
|
+
uncovered_case: "case_scenarios",
|
|
209
246
|
missing_scenario_test: "scenario_tests",
|
|
210
247
|
proof_snapshot_unavailable: "snapshot_runtime",
|
|
211
248
|
missing_passing_e2e: "proof_evidence",
|
|
@@ -235,6 +272,9 @@ const GAP_STAGE: Readonly<Record<string, string>> = {
|
|
|
235
272
|
missing_scenario: "scenarios",
|
|
236
273
|
infeasible_scenario: "scenarios",
|
|
237
274
|
unknown_scenario_feasibility: "scenarios",
|
|
275
|
+
dimension_unrepresented: "dimension",
|
|
276
|
+
happy_path_only: "negative_path",
|
|
277
|
+
uncovered_case: "cases",
|
|
238
278
|
missing_scenario_test: "scenario_tests",
|
|
239
279
|
missing_passing_e2e: "passing_e2e",
|
|
240
280
|
missing_proof_receipt: "passing_e2e",
|
|
@@ -255,6 +295,9 @@ const PROOF_STAGE_KEY: Readonly<Record<string, string>> = {
|
|
|
255
295
|
contradictions: "contradictions",
|
|
256
296
|
scenarios: "scenarios",
|
|
257
297
|
scenario_tests: "scenarioTests",
|
|
298
|
+
negative_path: "negativePath",
|
|
299
|
+
dimension: "dimension",
|
|
300
|
+
cases: "cases",
|
|
258
301
|
passing_e2e: "passingE2e",
|
|
259
302
|
executable_symbols: "executableSymbols",
|
|
260
303
|
production_symbols: "productionSymbols",
|
|
@@ -268,6 +311,34 @@ export type RepairPlanRepair = {
|
|
|
268
311
|
readonly proofStage: string;
|
|
269
312
|
readonly action: string;
|
|
270
313
|
readonly evidence: Readonly<Record<string, unknown>>;
|
|
314
|
+
/** Draft scenarios for an uncovered_case repair, one per uncovered case. */
|
|
315
|
+
readonly caseSkeletons?: readonly CaseSkeleton[];
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
type SkeletonEntity = {
|
|
319
|
+
readonly type: "fact" | "scenario";
|
|
320
|
+
readonly id: string;
|
|
321
|
+
readonly properties: Readonly<Record<string, unknown>>;
|
|
322
|
+
readonly relationships: readonly {
|
|
323
|
+
readonly type: string;
|
|
324
|
+
readonly from: string;
|
|
325
|
+
readonly to: string;
|
|
326
|
+
}[];
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
// implements REQ-kibi-case-coverage
|
|
330
|
+
/**
|
|
331
|
+
* An upsert-ready draft scenario for one uncovered case: the fact it assumes
|
|
332
|
+
* (the case's value class) and the scenario that expects the predicted
|
|
333
|
+
* outcome. Drafts never count as coverage, so writing one changes no gap
|
|
334
|
+
* until it is verified and made active. placeholder is true when the value
|
|
335
|
+
* must be chosen by the author (a value outside a set).
|
|
336
|
+
*/
|
|
337
|
+
export type CaseSkeleton = {
|
|
338
|
+
readonly caseId: string;
|
|
339
|
+
readonly constraint: string;
|
|
340
|
+
readonly placeholder: boolean;
|
|
341
|
+
readonly entities: readonly [SkeletonEntity, SkeletonEntity];
|
|
271
342
|
};
|
|
272
343
|
|
|
273
344
|
export type RepairPlanBatch = {
|
|
@@ -379,6 +450,82 @@ function stageEvidence(
|
|
|
379
450
|
return isRecord(stable) ? stable : {};
|
|
380
451
|
}
|
|
381
452
|
|
|
453
|
+
const VALUE_FIELD: Readonly<Record<string, string>> = {
|
|
454
|
+
int: "value_int",
|
|
455
|
+
number: "value_number",
|
|
456
|
+
set: "value_set",
|
|
457
|
+
string: "value_string",
|
|
458
|
+
};
|
|
459
|
+
|
|
460
|
+
function caseSkeleton(
|
|
461
|
+
requirementId: string,
|
|
462
|
+
row: Readonly<Record<string, unknown>>,
|
|
463
|
+
): CaseSkeleton | undefined {
|
|
464
|
+
const caseId = typeof row.caseId === "string" ? row.caseId : undefined;
|
|
465
|
+
const assumption = isRecord(row.assumption) ? row.assumption : undefined;
|
|
466
|
+
const valueType =
|
|
467
|
+
typeof assumption?.value_type === "string" ? assumption.value_type : "";
|
|
468
|
+
const valueField = VALUE_FIELD[valueType];
|
|
469
|
+
if (caseId === undefined || assumption === undefined || !valueField)
|
|
470
|
+
return undefined;
|
|
471
|
+
const constraint = typeof row.constraint === "string" ? row.constraint : "";
|
|
472
|
+
const property =
|
|
473
|
+
typeof assumption.property_key === "string" ? assumption.property_key : "";
|
|
474
|
+
const expects = row.predicted === "rejection" ? "rejection" : "success";
|
|
475
|
+
const placeholder = JSON.stringify(assumption.value).includes("<");
|
|
476
|
+
const suffix = caseId.replace(/^CASE-/, "");
|
|
477
|
+
const factId = `FACT-CASE-${suffix}`;
|
|
478
|
+
const scenarioId = `SCEN-CASE-${suffix}`;
|
|
479
|
+
return {
|
|
480
|
+
caseId,
|
|
481
|
+
constraint,
|
|
482
|
+
placeholder,
|
|
483
|
+
entities: [
|
|
484
|
+
{
|
|
485
|
+
type: "fact",
|
|
486
|
+
id: factId,
|
|
487
|
+
properties: {
|
|
488
|
+
title: `${property} ${constraint}`,
|
|
489
|
+
status: "active",
|
|
490
|
+
fact_kind: "property_value",
|
|
491
|
+
subject_key: assumption.subject_key,
|
|
492
|
+
property_key: property,
|
|
493
|
+
operator: assumption.operator,
|
|
494
|
+
value_type: valueType,
|
|
495
|
+
[valueField]: assumption.value,
|
|
496
|
+
},
|
|
497
|
+
relationships: [],
|
|
498
|
+
},
|
|
499
|
+
{
|
|
500
|
+
type: "scenario",
|
|
501
|
+
id: scenarioId,
|
|
502
|
+
properties: {
|
|
503
|
+
title: `${property} ${constraint} is ${expects === "rejection" ? "refused" : "accepted"}`,
|
|
504
|
+
status: "draft",
|
|
505
|
+
expects,
|
|
506
|
+
},
|
|
507
|
+
relationships: [
|
|
508
|
+
{ type: "assumes", from: scenarioId, to: factId },
|
|
509
|
+
{ type: "specified_by", from: requirementId, to: scenarioId },
|
|
510
|
+
],
|
|
511
|
+
},
|
|
512
|
+
],
|
|
513
|
+
};
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
function caseSkeletons(
|
|
517
|
+
requirementId: string,
|
|
518
|
+
evidence: Readonly<Record<string, unknown>>,
|
|
519
|
+
): CaseSkeleton[] {
|
|
520
|
+
const rows = Array.isArray(evidence.uncoveredCases)
|
|
521
|
+
? evidence.uncoveredCases.filter(isRecord)
|
|
522
|
+
: [];
|
|
523
|
+
return rows.flatMap((row) => {
|
|
524
|
+
const skeleton = caseSkeleton(requirementId, row);
|
|
525
|
+
return skeleton === undefined ? [] : [skeleton];
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
|
|
382
529
|
function batchId(requirementId: string, phase: RepairPhase): string {
|
|
383
530
|
const order = String(REPAIR_PHASES[phase].order).padStart(3, "0");
|
|
384
531
|
const safeRequirementId = requirementId.replace(/[^A-Za-z0-9_-]/g, "-");
|
|
@@ -408,6 +555,7 @@ function buildRequirementBatches(
|
|
|
408
555
|
typeof sourceRepair?.stage === "string"
|
|
409
556
|
? sourceRepair.stage
|
|
410
557
|
: (GAP_STAGE[gap] ?? "manual_review");
|
|
558
|
+
const evidence = stageEvidence(row, proofStage);
|
|
411
559
|
const repair: RepairPlanRepair = {
|
|
412
560
|
requirementId,
|
|
413
561
|
gap,
|
|
@@ -417,7 +565,10 @@ function buildRequirementBatches(
|
|
|
417
565
|
),
|
|
418
566
|
proofStage,
|
|
419
567
|
action: actionForRepair(sourceRepair, phase),
|
|
420
|
-
evidence
|
|
568
|
+
evidence,
|
|
569
|
+
...(gap === "uncovered_case"
|
|
570
|
+
? { caseSkeletons: caseSkeletons(requirementId, evidence) }
|
|
571
|
+
: {}),
|
|
421
572
|
};
|
|
422
573
|
const phaseRepairs = byPhase.get(phase) ?? [];
|
|
423
574
|
phaseRepairs.push(repair);
|
|
@@ -728,7 +728,7 @@ export function schema6ReviewActionsFromCheck(
|
|
|
728
728
|
safety: "review",
|
|
729
729
|
invocation: {
|
|
730
730
|
kind: "review",
|
|
731
|
-
instruction: `${total} agent-authored requirement(s) have no human approval${total > listed.length ? `; these ${listed.length} come first` : ""}: ${listed.join(", ")}. Have a person read each one; when it states the intended behavior, kb_upsert it with origin.approved_by set to the reviewer (keep kind: agent and the rest of origin). Rerun kb_check for the next page.`,
|
|
731
|
+
instruction: `${total} agent-authored requirement(s) have no human approval${total > listed.length ? `; these ${listed.length} come first` : ""}: ${listed.join(", ")}. Have a person read each one; when it states the intended behavior, kb_upsert it with origin.approved_by set to the reviewer (keep kind: agent and the rest of origin), in the same change and pull request as the requirement, not a separate one. Rerun kb_check for the next page.`,
|
|
732
732
|
},
|
|
733
733
|
affectedEntityIds: listed,
|
|
734
734
|
affectedFiles: [...new Set(agentRequirementFiles)].sort(),
|
|
@@ -14,6 +14,7 @@ export const SELECTABLE_RULE_NAMES: readonly string[] = [
|
|
|
14
14
|
"symbol-coverage",
|
|
15
15
|
"symbol-traceability",
|
|
16
16
|
"symbol-granularity",
|
|
17
|
+
"symbol-coordinates-missing",
|
|
17
18
|
"no-dangling-refs",
|
|
18
19
|
"source-relationship-parity",
|
|
19
20
|
"branch-store-not-compiled",
|
|
@@ -24,6 +25,7 @@ export const SELECTABLE_RULE_NAMES: readonly string[] = [
|
|
|
24
25
|
"superseded-requirement-open",
|
|
25
26
|
"scenario-feasibility",
|
|
26
27
|
"scenario-feasibility-unknown",
|
|
28
|
+
"scenario-outcome-mismatch",
|
|
27
29
|
"exception-claim-keys",
|
|
28
30
|
"numeric-string-value",
|
|
29
31
|
"rule-key-arguments-missing",
|
|
@@ -72,4 +74,4 @@ export const SELECTABLE_RULE_NAMES: readonly string[] = [
|
|
|
72
74
|
// implements REQ-006
|
|
73
75
|
/** Comma-separated "Allowed:" fragment for the kb_check rules description. */
|
|
74
76
|
export const SELECTABLE_RULES_ALLOWED =
|
|
75
|
-
"must-priority-coverage, symbol-coverage, symbol-traceability, symbol-granularity, 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, decision-firm-unreferenced, decision-firm-superseded, decision-firm-edited, supersedes-reason-missing, supersedes-reason-acknowledged, policy-ownership, policy-markers, kb-consistency, kb-consistency-unresolved, evidence-floor, proof-contract-claims";
|
|
77
|
+
"must-priority-coverage, symbol-coverage, symbol-traceability, symbol-granularity, symbol-coordinates-missing, 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, scenario-outcome-mismatch, 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, decision-firm-unreferenced, decision-firm-superseded, decision-firm-edited, supersedes-reason-missing, supersedes-reason-acknowledged, policy-ownership, policy-markers, kb-consistency, kb-consistency-unresolved, evidence-floor, proof-contract-claims";
|
|
@@ -126,6 +126,18 @@ export const ENTITY_PROPERTIES_SCHEMA = {
|
|
|
126
126
|
description:
|
|
127
127
|
"Requirement-only. Optional reference to the exception's approval decision record.",
|
|
128
128
|
},
|
|
129
|
+
failure_side_waiver: {
|
|
130
|
+
type: "string",
|
|
131
|
+
minLength: 1,
|
|
132
|
+
description:
|
|
133
|
+
"Requirement-only. Why the requirement has no failure side to test (its claims state a capability or output shape). Waives happy_path_only once failure_side_waiver_approved_by is set.",
|
|
134
|
+
},
|
|
135
|
+
failure_side_waiver_approved_by: {
|
|
136
|
+
type: "string",
|
|
137
|
+
minLength: 1,
|
|
138
|
+
description:
|
|
139
|
+
"Requirement-only. The person who accepted failure_side_waiver.",
|
|
140
|
+
},
|
|
129
141
|
firmness: {
|
|
130
142
|
type: "string",
|
|
131
143
|
enum: ["firm", "default", "exploratory"],
|
|
@@ -323,6 +335,28 @@ export const ENTITY_PROPERTIES_SCHEMA = {
|
|
|
323
335
|
description:
|
|
324
336
|
"Exact atomic requirement clause represented by this fact, retained for human audit. On a grounding fact Kibi derives claim_key from it; an observation or meta fact quotes the clause it is about without a key.",
|
|
325
337
|
},
|
|
338
|
+
dimension_waiver: {
|
|
339
|
+
type: "string",
|
|
340
|
+
minLength: 1,
|
|
341
|
+
description:
|
|
342
|
+
"Fact-only. Why the quantifier word in claim_text ranges over nothing, so the claim needs no count, set or rule. Waives dimension_unrepresented once dimension_waiver_approved_by is set.",
|
|
343
|
+
},
|
|
344
|
+
dimension_waiver_approved_by: {
|
|
345
|
+
type: "string",
|
|
346
|
+
minLength: 1,
|
|
347
|
+
description: "Fact-only. The person who accepted dimension_waiver.",
|
|
348
|
+
},
|
|
349
|
+
case_waiver: {
|
|
350
|
+
type: "string",
|
|
351
|
+
minLength: 1,
|
|
352
|
+
description:
|
|
353
|
+
"Fact-only. Why the edge cases derived from this fact are covered some other way or cannot occur. Waives uncovered_case once case_waiver_approved_by is set.",
|
|
354
|
+
},
|
|
355
|
+
case_waiver_approved_by: {
|
|
356
|
+
type: "string",
|
|
357
|
+
minLength: 1,
|
|
358
|
+
description: "Fact-only. The person who accepted case_waiver.",
|
|
359
|
+
},
|
|
326
360
|
predicate_name: {
|
|
327
361
|
type: "string",
|
|
328
362
|
description:
|
|
@@ -37,6 +37,32 @@ const ENTITY_TYPES = [
|
|
|
37
37
|
] as const;
|
|
38
38
|
const ENTITY_TYPE_SET: ReadonlySet<string> = new Set(ENTITY_TYPES);
|
|
39
39
|
|
|
40
|
+
/**
|
|
41
|
+
* The engine names the attached store by its directory key (a SHA-256 of the
|
|
42
|
+
* branch name); meta.branch carries the branch name, as kb_status does, and
|
|
43
|
+
* the key moves to meta.branchStoreKey.
|
|
44
|
+
*/
|
|
45
|
+
// implements REQ-kibi-verification-evidence-contract
|
|
46
|
+
export function withBranchName<
|
|
47
|
+
T extends { readonly meta?: Readonly<Record<string, unknown>> },
|
|
48
|
+
>(payload: T, context: Pick<OperationContext, "branchAttachment">): T {
|
|
49
|
+
const meta = payload.meta;
|
|
50
|
+
const name = context.branchAttachment?.kbBranch;
|
|
51
|
+
if (meta === undefined || name === undefined || meta.branch === name)
|
|
52
|
+
return payload;
|
|
53
|
+
const key = typeof meta.branch === "string" ? meta.branch : undefined;
|
|
54
|
+
return {
|
|
55
|
+
...payload,
|
|
56
|
+
meta: {
|
|
57
|
+
...meta,
|
|
58
|
+
branch: name,
|
|
59
|
+
...(key !== undefined && key !== "unknown"
|
|
60
|
+
? { branchStoreKey: key }
|
|
61
|
+
: {}),
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
40
66
|
export type FindGapsInput = {
|
|
41
67
|
readonly type?: string;
|
|
42
68
|
readonly missingRelationships?: readonly string[];
|
|
@@ -161,7 +187,10 @@ export async function executeFindGaps(
|
|
|
161
187
|
: `Found ${payload.count ?? rows.length} gap rows. Showing ${rows.length}: ${rows.map((row) => row.id).join(", ")}.${stubNote}`,
|
|
162
188
|
},
|
|
163
189
|
],
|
|
164
|
-
structuredContent:
|
|
190
|
+
structuredContent: withBranchName(
|
|
191
|
+
confirmMetaFreshness(payload, context.workspaceRoot),
|
|
192
|
+
context,
|
|
193
|
+
),
|
|
165
194
|
};
|
|
166
195
|
} catch (error) {
|
|
167
196
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -418,7 +447,10 @@ export async function executeCoverage(
|
|
|
418
447
|
const migrationPlan = statusPlan
|
|
419
448
|
? mergeMigrationPlans([statusPlan, coveragePlan])
|
|
420
449
|
: coveragePlan;
|
|
421
|
-
const confirmed =
|
|
450
|
+
const confirmed = withBranchName(
|
|
451
|
+
confirmMetaFreshness(payload, context.workspaceRoot),
|
|
452
|
+
context,
|
|
453
|
+
);
|
|
422
454
|
const enrichedPayload = {
|
|
423
455
|
...confirmed,
|
|
424
456
|
rows,
|
|
@@ -581,7 +613,10 @@ export async function executeGraph(
|
|
|
581
613
|
: `Graph traversal returned ${nodes.length} nodes and ${edges.length} edges from ${input.seedIds.join(", ")}.`,
|
|
582
614
|
},
|
|
583
615
|
],
|
|
584
|
-
structuredContent:
|
|
616
|
+
structuredContent: withBranchName(
|
|
617
|
+
confirmMetaFreshness(payload, context.workspaceRoot),
|
|
618
|
+
context,
|
|
619
|
+
),
|
|
585
620
|
};
|
|
586
621
|
} catch (error) {
|
|
587
622
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -7,6 +7,7 @@ import type {
|
|
|
7
7
|
SemanticAdvisorReceipt,
|
|
8
8
|
} from "../../../operations/semantic-advisor/types.js";
|
|
9
9
|
import { publicCapabilityStamp } from "../../../plugins/compose-semantic-classifier.js";
|
|
10
|
+
import { firstSentence } from "../../../utils/first-sentence.js";
|
|
10
11
|
import type { OperationContext, PrologPort } from "../runtime-types.js";
|
|
11
12
|
import type { OperationSpec } from "../types.js";
|
|
12
13
|
|
|
@@ -59,7 +60,7 @@ export async function executeSemanticAdvisor(
|
|
|
59
60
|
): Promise<SemanticAdvisorOperationResult> {
|
|
60
61
|
const text = requiredText(args.text);
|
|
61
62
|
const id = optionalString(args.id) ?? "REQ-SEMANTIC-ADVISOR-PREVIEW";
|
|
62
|
-
const title = optionalString(args.title) ?? text
|
|
63
|
+
const title = optionalString(args.title) ?? (firstSentence(text) || text);
|
|
63
64
|
const source = optionalString(args.source) ?? "mcp://kibi/semantic-advisor";
|
|
64
65
|
const orchestrated = await analyzeSemanticAdvisorInputWithPlugins(
|
|
65
66
|
{
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Kibi — repo-local, per-branch, queryable long-term memory for software projects
|
|
3
|
+
Copyright (C) 2026 Piotr Franczyk
|
|
4
|
+
|
|
5
|
+
This program is free software: you can redistribute it and/or modify
|
|
6
|
+
it under the terms of the GNU Affero General Public License as published by
|
|
7
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
(at your option) any later version.
|
|
9
|
+
|
|
10
|
+
This program is distributed in the hope that it will be useful,
|
|
11
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
GNU Affero General Public License for more details.
|
|
14
|
+
|
|
15
|
+
You should have received a copy of the GNU Affero General Public License
|
|
16
|
+
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { existsSync, statSync } from "node:fs";
|
|
20
|
+
import * as path from "node:path";
|
|
21
|
+
import { parseEntityFromList, parseListOfLists } from "../../prolog/codec.js";
|
|
22
|
+
import type { Violation } from "../../utils/rule-registry.js";
|
|
23
|
+
import type { PrologPort } from "./runtime-types.js";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* A symbol whose source file exists but which Kibi could not place in it is
|
|
27
|
+
* linked to no code: impact review, coverage and proofs never see it there.
|
|
28
|
+
* kibi sync names it in its refresh output only, so the check reports every
|
|
29
|
+
* such symbol as a warning (advisory, non-blocking).
|
|
30
|
+
*/
|
|
31
|
+
// implements REQ-cli-check, REQ-generated-coordinate-persistence
|
|
32
|
+
export const SYMBOL_COORDINATES_MISSING_RULE = "symbol-coordinates-missing";
|
|
33
|
+
|
|
34
|
+
const SYMBOL_PLACEMENT_QUERY =
|
|
35
|
+
"findall([Id,symbol,Fields], (kb_entity(Id, symbol, Props), include([Key=_]>>memberchk(Key, [title,status,sourceFile,sourceLine]), Props, Fields)), Rows)";
|
|
36
|
+
|
|
37
|
+
const INACTIVE_STATUSES = new Set([
|
|
38
|
+
"deprecated",
|
|
39
|
+
"removed",
|
|
40
|
+
"retired",
|
|
41
|
+
"superseded",
|
|
42
|
+
]);
|
|
43
|
+
|
|
44
|
+
// implements REQ-cli-check
|
|
45
|
+
export async function collectSymbolCoordinatesMissingViolations(
|
|
46
|
+
prolog: Pick<PrologPort, "query">,
|
|
47
|
+
workspaceRoot: string,
|
|
48
|
+
rules: ReadonlySet<string>,
|
|
49
|
+
): Promise<Violation[]> {
|
|
50
|
+
if (!rules.has(SYMBOL_COORDINATES_MISSING_RULE)) return [];
|
|
51
|
+
const rows = await prolog.query(SYMBOL_PLACEMENT_QUERY);
|
|
52
|
+
if (!rows.success)
|
|
53
|
+
throw new Error(
|
|
54
|
+
`symbol-coordinates-missing symbol projection failed: ${rows.error ?? "unknown error"}`,
|
|
55
|
+
);
|
|
56
|
+
const violations: Violation[] = [];
|
|
57
|
+
for (const row of parseListOfLists(rows.bindings.Rows ?? "[]")) {
|
|
58
|
+
const entity = parseEntityFromList(row);
|
|
59
|
+
const id = typeof entity.id === "string" ? entity.id : "";
|
|
60
|
+
const sourceFile =
|
|
61
|
+
typeof entity.sourceFile === "string" ? entity.sourceFile : "";
|
|
62
|
+
const status = typeof entity.status === "string" ? entity.status : "";
|
|
63
|
+
if (id === "" || sourceFile === "" || INACTIVE_STATUSES.has(status))
|
|
64
|
+
continue;
|
|
65
|
+
if (entity.sourceLine !== undefined && entity.sourceLine !== null) continue;
|
|
66
|
+
const absolute = path.resolve(workspaceRoot, sourceFile);
|
|
67
|
+
if (!existsSync(absolute) || !statSync(absolute).isFile()) continue;
|
|
68
|
+
const title = typeof entity.title === "string" ? entity.title : id;
|
|
69
|
+
violations.push({
|
|
70
|
+
rule: SYMBOL_COORDINATES_MISSING_RULE,
|
|
71
|
+
entityId: id,
|
|
72
|
+
source: sourceFile,
|
|
73
|
+
description: `${id} (${title}) has no symbol coordinates in ${sourceFile}: Kibi could not place it, so its links are checked against no code`,
|
|
74
|
+
suggestion:
|
|
75
|
+
"Run kibi sync --refresh-symbol-coordinates and read its failed lines; use the name the extractor gives the declaration, install the plugins and grammar packs kibi doctor names, or add symbol_role and granularity_reason for a file-level link.",
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
return violations;
|
|
79
|
+
}
|
|
@@ -99,13 +99,21 @@ export type ProofContract = Readonly<{
|
|
|
99
99
|
| "state_machine"
|
|
100
100
|
| "regex"
|
|
101
101
|
| "source";
|
|
102
|
-
domain_source?: Readonly<{
|
|
102
|
+
domain_source?: Readonly<{
|
|
103
|
+
symbol_id: string;
|
|
104
|
+
export?: string;
|
|
105
|
+
field?: string;
|
|
106
|
+
/** A SWI-Prolog predicate's argument (1-based) that names each member. */
|
|
107
|
+
arg?: number;
|
|
108
|
+
}>;
|
|
103
109
|
witness?: Readonly<{ path: string }>;
|
|
104
110
|
constraint_source?: Readonly<{ fact_ids: readonly string[] }>;
|
|
105
111
|
value_source?: readonly (
|
|
106
112
|
| Readonly<{
|
|
107
113
|
symbol_id: string;
|
|
108
114
|
export?: string;
|
|
115
|
+
/** A SWI-Prolog predicate's argument (1-based) that holds the value. */
|
|
116
|
+
arg?: number;
|
|
109
117
|
/** value (default): the export is a number; count: the size of a list, set, map or object. */
|
|
110
118
|
measure?: "value" | "count";
|
|
111
119
|
}>
|
|
@@ -130,12 +138,20 @@ export type ProofContract = Readonly<{
|
|
|
130
138
|
domains?: Readonly<
|
|
131
139
|
Record<
|
|
132
140
|
string,
|
|
133
|
-
| Readonly<{ symbol_id: string; export?: string }>
|
|
141
|
+
| Readonly<{ symbol_id: string; export?: string; arg?: number }>
|
|
134
142
|
| Readonly<{ source: ProofSourceSpec }>
|
|
135
143
|
>
|
|
136
144
|
>;
|
|
137
|
-
initial_source?: Readonly<{
|
|
138
|
-
|
|
145
|
+
initial_source?: Readonly<{
|
|
146
|
+
symbol_id: string;
|
|
147
|
+
export?: string;
|
|
148
|
+
arg?: number;
|
|
149
|
+
}>;
|
|
150
|
+
pattern_source?: Readonly<{
|
|
151
|
+
symbol_id: string;
|
|
152
|
+
export?: string;
|
|
153
|
+
arg?: number;
|
|
154
|
+
}>;
|
|
139
155
|
/** kind source: the project source Kibi reads. */
|
|
140
156
|
source?: ProofSourceSpec;
|
|
141
157
|
}>;
|
|
@@ -151,7 +167,8 @@ export type ProofSourceSpec = Readonly<Record<string, unknown>> &
|
|
|
151
167
|
| "references"
|
|
152
168
|
| "schema"
|
|
153
169
|
| "routes"
|
|
154
|
-
| "validator"
|
|
170
|
+
| "validator"
|
|
171
|
+
| "prolog";
|
|
155
172
|
}>;
|
|
156
173
|
|
|
157
174
|
export type ProofBinding = Readonly<{
|