kibi-cli 2.21.2 → 2.22.1
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-foundation.d.ts.map +1 -1
- package/dist/cli-register-foundation.js +1 -0
- package/dist/commands/check.d.ts +0 -1
- package/dist/commands/check.d.ts.map +1 -1
- package/dist/commands/check.js +47 -111
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +108 -6
- package/dist/commands/init-helpers.d.ts +16 -2
- package/dist/commands/init-helpers.d.ts.map +1 -1
- package/dist/commands/init-helpers.js +52 -10
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +12 -1
- package/dist/commands/legacy-storage-migration.d.ts +46 -1
- package/dist/commands/legacy-storage-migration.d.ts.map +1 -1
- package/dist/commands/legacy-storage-migration.js +219 -9
- package/dist/commands/migrate.d.ts +37 -0
- package/dist/commands/migrate.d.ts.map +1 -1
- package/dist/commands/migrate.js +72 -188
- package/dist/commands/sync/manifest.d.ts.map +1 -1
- package/dist/commands/sync/manifest.js +9 -0
- package/dist/extractors/symbols-coordinator.js +1 -0
- package/dist/intent-search.d.ts.map +1 -1
- package/dist/intent-search.js +28 -6
- package/dist/operations/migration/inventory-rederive.d.ts +40 -1
- package/dist/operations/migration/inventory-rederive.d.ts.map +1 -1
- package/dist/operations/migration/inventory-rederive.js +99 -8
- package/dist/operations/migration/requirement-status.d.ts +25 -0
- package/dist/operations/migration/requirement-status.d.ts.map +1 -0
- package/dist/operations/migration/requirement-status.js +105 -0
- package/dist/operations/migration/schema6.d.ts +25 -0
- package/dist/operations/migration/schema6.d.ts.map +1 -1
- package/dist/operations/migration/schema6.js +265 -7
- package/dist/operations/migration/symbol-legacy-links.d.ts +51 -0
- package/dist/operations/migration/symbol-legacy-links.d.ts.map +1 -0
- package/dist/operations/migration/symbol-legacy-links.js +319 -0
- package/dist/operations/mutation/context-warning.d.ts +12 -2
- package/dist/operations/mutation/context-warning.d.ts.map +1 -1
- package/dist/operations/mutation/context-warning.js +6 -6
- package/dist/operations/mutation/source-authoring.d.ts.map +1 -1
- package/dist/operations/mutation/source-authoring.js +130 -35
- package/dist/operations/mutation/types.d.ts +2 -1
- package/dist/operations/mutation/types.d.ts.map +1 -1
- package/dist/operations/mutation/upsert.d.ts +17 -2
- package/dist/operations/mutation/upsert.d.ts.map +1 -1
- package/dist/operations/mutation/upsert.js +28 -11
- package/dist/operations/mutation/validate-upsert.d.ts.map +1 -1
- package/dist/operations/mutation/validate-upsert.js +40 -8
- package/dist/operations/mutation/validation.d.ts.map +1 -1
- package/dist/operations/mutation/validation.js +43 -1
- package/dist/operations/planning/apply-plan.d.ts.map +1 -1
- package/dist/operations/planning/apply-plan.js +34 -10
- package/dist/operations/semantic-advisor/ingestion-boundary.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/ingestion-boundary.js +25 -1
- package/dist/operations/semantic-advisor/stored-ledger-drift.d.ts +19 -0
- package/dist/operations/semantic-advisor/stored-ledger-drift.d.ts.map +1 -0
- package/dist/operations/semantic-advisor/stored-ledger-drift.js +78 -0
- package/dist/public/impact/diagnostics.d.ts.map +1 -1
- package/dist/public/impact/diagnostics.js +24 -14
- package/dist/public/operations/catalog.d.ts +3 -3
- package/dist/public/operations/check-executor.d.ts.map +1 -1
- package/dist/public/operations/check-executor.js +3 -0
- package/dist/public/operations/contracts.d.ts.map +1 -1
- package/dist/public/operations/contracts.js +6 -1
- package/dist/public/operations/decision-firmness.d.ts +3 -1
- package/dist/public/operations/decision-firmness.d.ts.map +1 -1
- package/dist/public/operations/decision-firmness.js +13 -3
- package/dist/public/operations/discovery-executors.d.ts +2 -0
- package/dist/public/operations/discovery-executors.d.ts.map +1 -1
- package/dist/public/operations/discovery-executors.js +24 -2
- package/dist/public/operations/migration-plan.d.ts +15 -0
- package/dist/public/operations/migration-plan.d.ts.map +1 -1
- package/dist/public/operations/migration-plan.js +130 -17
- package/dist/public/operations/result-envelope.d.ts.map +1 -1
- package/dist/public/operations/result-envelope.js +27 -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 +2 -1
- package/dist/public/operations/specs/check.d.ts +1 -1
- package/dist/public/operations/specs/planning.d.ts +2 -2
- package/dist/public/operations/specs/planning.js +2 -2
- package/dist/public/operations/specs/semantic.d.ts.map +1 -1
- package/dist/public/operations/specs/semantic.js +26 -1
- package/dist/public/operations/symbol-granularity-check.d.ts +18 -0
- package/dist/public/operations/symbol-granularity-check.d.ts.map +1 -0
- package/dist/public/operations/symbol-granularity-check.js +175 -0
- package/dist/public/skills/kibi-usage/SKILL.md +8 -3
- package/dist/public/symbol-granularity.d.ts +17 -0
- package/dist/public/symbol-granularity.d.ts.map +1 -1
- package/dist/public/symbol-granularity.js +21 -0
- package/dist/traceability/evidence-model.d.ts +7 -3
- package/dist/traceability/evidence-model.d.ts.map +1 -1
- package/dist/traceability/staged-symbols-manifest.js +6 -5
- package/dist/traceability/validate.d.ts +14 -1
- package/dist/traceability/validate.d.ts.map +1 -1
- package/dist/traceability/validate.js +41 -0
- 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/package.json +3 -3
- package/src/public/impact/diagnostics.ts +29 -17
- package/src/public/operations/check-executor.ts +7 -0
- package/src/public/operations/contracts.ts +6 -1
- package/src/public/operations/decision-firmness.ts +18 -2
- package/src/public/operations/discovery-executors.ts +28 -2
- package/src/public/operations/migration-plan.ts +147 -20
- package/src/public/operations/result-envelope.ts +34 -1
- package/src/public/operations/specs/check-rules.generated.ts +2 -1
- package/src/public/operations/specs/planning.ts +2 -2
- package/src/public/operations/specs/semantic.ts +37 -2
- package/src/public/operations/symbol-granularity-check.ts +233 -0
- package/src/public/skills/kibi-usage/SKILL.md +8 -3
- package/src/public/symbol-granularity.ts +37 -0
|
@@ -12,6 +12,7 @@ export const SELECTABLE_RULE_NAMES = [
|
|
|
12
12
|
"must-priority-coverage",
|
|
13
13
|
"symbol-coverage",
|
|
14
14
|
"symbol-traceability",
|
|
15
|
+
"symbol-granularity",
|
|
15
16
|
"no-dangling-refs",
|
|
16
17
|
"source-relationship-parity",
|
|
17
18
|
"branch-store-not-compiled",
|
|
@@ -63,4 +64,4 @@ export const SELECTABLE_RULE_NAMES = [
|
|
|
63
64
|
];
|
|
64
65
|
// implements REQ-006
|
|
65
66
|
/** Comma-separated "Allowed:" fragment for the kb_check rules description. */
|
|
66
|
-
export const SELECTABLE_RULES_ALLOWED = "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, decision-firm-unreferenced, decision-firm-superseded, supersedes-reason-missing, supersedes-reason-acknowledged, policy-ownership, policy-markers";
|
|
67
|
+
export const SELECTABLE_RULES_ALLOWED = "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, supersedes-reason-missing, supersedes-reason-acknowledged, policy-ownership, policy-markers";
|
|
@@ -12,7 +12,7 @@ export declare const checkSpec: {
|
|
|
12
12
|
readonly type: "string";
|
|
13
13
|
readonly enum: readonly string[];
|
|
14
14
|
};
|
|
15
|
-
readonly description: "Optional rule subset. Allowed: 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, decision-firm-unreferenced, decision-firm-superseded, supersedes-reason-missing, supersedes-reason-acknowledged, policy-ownership, policy-markers. If omitted, server runs canonical and advisory rules plus the full-KB qualityDiagnostics audit scan, including usage telemetry acceptance when evidence exists; migration rules run only when explicitly selected. Advisory and migration findings are non-blocking qualityDiagnostics. If supplied, server preserves scoped validation and skips the full-KB advisory scan.";
|
|
15
|
+
readonly description: "Optional rule subset. Allowed: 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, supersedes-reason-missing, supersedes-reason-acknowledged, policy-ownership, policy-markers. If omitted, server runs canonical and advisory rules plus the full-KB qualityDiagnostics audit scan, including usage telemetry acceptance when evidence exists; migration rules run only when explicitly selected. Advisory and migration findings are non-blocking qualityDiagnostics. If supplied, server preserves scoped validation and skips the full-KB advisory scan.";
|
|
16
16
|
};
|
|
17
17
|
readonly sourceFiles: {
|
|
18
18
|
readonly type: "array";
|
|
@@ -270,7 +270,7 @@ export declare const applyPlanSpec: {
|
|
|
270
270
|
readonly plan: {
|
|
271
271
|
readonly type: "object";
|
|
272
272
|
readonly required: readonly ["version", "planHash"];
|
|
273
|
-
readonly description: "The complete kibi.bootstrap-plan.v1, kibi.compile-plan.v1, kibi.migration-plan.v2, or hash-bound kibi.entity-deletion-plan.v1 object. Migration plans require approvedActionIds and reject blocked
|
|
273
|
+
readonly description: "The complete kibi.bootstrap-plan.v1, kibi.compile-plan.v1, kibi.migration-plan.v2, or hash-bound kibi.entity-deletion-plan.v1 object. Migration plans require approvedActionIds and reject blocked actions and review actions Kibi cannot execute.";
|
|
274
274
|
};
|
|
275
275
|
readonly approvedActionIds: {
|
|
276
276
|
readonly type: "array";
|
|
@@ -278,7 +278,7 @@ export declare const applyPlanSpec: {
|
|
|
278
278
|
readonly type: "string";
|
|
279
279
|
readonly minLength: 1;
|
|
280
280
|
};
|
|
281
|
-
readonly description: "Required for migration-plan.v2. Exact
|
|
281
|
+
readonly description: "Required for migration-plan.v2. Exact action IDs explicitly approved for this application: automatic actions, or review actions with a cli invocation that Kibi executes only when approved by id (for example semantic_inventory_rederive_drop_grounding).";
|
|
282
282
|
};
|
|
283
283
|
readonly recoveryJournalId: {
|
|
284
284
|
readonly type: "string";
|
|
@@ -188,12 +188,12 @@ export const applyPlanSpec = {
|
|
|
188
188
|
plan: {
|
|
189
189
|
type: "object",
|
|
190
190
|
required: ["version", "planHash"],
|
|
191
|
-
description: "The complete kibi.bootstrap-plan.v1, kibi.compile-plan.v1, kibi.migration-plan.v2, or hash-bound kibi.entity-deletion-plan.v1 object. Migration plans require approvedActionIds and reject blocked
|
|
191
|
+
description: "The complete kibi.bootstrap-plan.v1, kibi.compile-plan.v1, kibi.migration-plan.v2, or hash-bound kibi.entity-deletion-plan.v1 object. Migration plans require approvedActionIds and reject blocked actions and review actions Kibi cannot execute.",
|
|
192
192
|
},
|
|
193
193
|
approvedActionIds: {
|
|
194
194
|
type: "array",
|
|
195
195
|
items: { type: "string", minLength: 1 },
|
|
196
|
-
description: "Required for migration-plan.v2. Exact
|
|
196
|
+
description: "Required for migration-plan.v2. Exact action IDs explicitly approved for this application: automatic actions, or review actions with a cli invocation that Kibi executes only when approved by id (for example semantic_inventory_rederive_drop_grounding).",
|
|
197
197
|
},
|
|
198
198
|
recoveryJournalId: {
|
|
199
199
|
type: "string",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"semantic.d.ts","sourceRoot":"","sources":["../../../../src/public/operations/specs/semantic.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"semantic.d.ts","sourceRoot":"","sources":["../../../../src/public/operations/specs/semantic.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,mBAAmB,EACnB,8BAA8B,EAE/B,MAAM,+CAA+C,CAAC;AAEvD,OAAO,KAAK,EAAE,gBAAgB,EAAc,MAAM,qBAAqB,CAAC;AA8CxE,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,mBAAmB,EACzB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,8BAA8B,CAAC,CAiGzC;AAED,iBAAe,2BAA2B,CACxC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACxC,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,8BAA8B,CAAC,CAiCzC;AAED,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2EE,CAAC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { InputError } from "../../../cli-errors.js";
|
|
2
2
|
import { analyzeSemanticAdvisorInputWithPlugins } from "../../../operations/semantic-advisor/plugin-orchestration.js";
|
|
3
|
+
import { storedLedgerDriftWarning } from "../../../operations/semantic-advisor/stored-ledger-drift.js";
|
|
3
4
|
import { publicCapabilityStamp } from "../../../plugins/compose-semantic-classifier.js";
|
|
4
5
|
function requiredText(value) {
|
|
5
6
|
const text = typeof value === "string" ? value.trim() : "";
|
|
@@ -12,6 +13,29 @@ function optionalString(value) {
|
|
|
12
13
|
const text = typeof value === "string" ? value.trim() : "";
|
|
13
14
|
return text || undefined;
|
|
14
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* The stored-ledger comparison runs only for a requirement the caller named
|
|
18
|
+
* and only when the host can open the branch engine; analysis without a KB
|
|
19
|
+
* (a preview, a unit test, a workspace before `kibi sync`) stays as it was.
|
|
20
|
+
* A store that cannot be read is not an analysis failure, so the warning is
|
|
21
|
+
* simply absent then.
|
|
22
|
+
*/
|
|
23
|
+
// implements REQ-kibi-proposition-complete-ingestion
|
|
24
|
+
async function storedLedgerWarnings(args, text, receipt, context) {
|
|
25
|
+
const id = optionalString(args.id);
|
|
26
|
+
if (!id || (optionalString(args.type) ?? "req") !== "req")
|
|
27
|
+
return [];
|
|
28
|
+
try {
|
|
29
|
+
const prolog = context?.prolog ?? (await context?.ensureProlog?.());
|
|
30
|
+
if (!prolog)
|
|
31
|
+
return [];
|
|
32
|
+
const warning = await storedLedgerDriftWarning(prolog, id, text, receipt);
|
|
33
|
+
return warning ? [warning] : [];
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
15
39
|
export async function executeSemanticAdvisor(args, context) {
|
|
16
40
|
const text = requiredText(args.text);
|
|
17
41
|
const id = optionalString(args.id) ?? "REQ-SEMANTIC-ADVISOR-PREVIEW";
|
|
@@ -39,6 +63,7 @@ export async function executeSemanticAdvisor(args, context) {
|
|
|
39
63
|
: {}),
|
|
40
64
|
});
|
|
41
65
|
const result = orchestrated.analysis;
|
|
66
|
+
const ledgerWarnings = await storedLedgerWarnings(args, text, result.receipt, context);
|
|
42
67
|
const pluginWarnings = orchestrated.stamps.length > 0
|
|
43
68
|
? [
|
|
44
69
|
`Capability plugins consulted: ${orchestrated.stamps
|
|
@@ -87,7 +112,7 @@ export async function executeSemanticAdvisor(args, context) {
|
|
|
87
112
|
],
|
|
88
113
|
structuredContent: {
|
|
89
114
|
receipt: result.receipt,
|
|
90
|
-
warnings: [...result.warnings, ...pluginWarnings],
|
|
115
|
+
warnings: [...result.warnings, ...ledgerWarnings, ...pluginWarnings],
|
|
91
116
|
...(capabilityPlugins ? { capabilityPlugins } : {}),
|
|
92
117
|
},
|
|
93
118
|
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Violation } from "../../utils/rule-registry.js";
|
|
2
|
+
import type { PrologPort } from "./runtime-types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Full-check form of the staged gate's `symbol_granularity_violation`: a
|
|
5
|
+
* symbol with traceability relationships must not link its source file
|
|
6
|
+
* coarsely while narrower behavioral symbols are available, unless it carries
|
|
7
|
+
* an allowed granularity_reason.
|
|
8
|
+
*/
|
|
9
|
+
export declare const SYMBOL_GRANULARITY_RULE = "symbol-granularity";
|
|
10
|
+
/**
|
|
11
|
+
* `symbol-granularity`: the staged gate's granularity predicate, evaluated
|
|
12
|
+
* for every symbol against its whole working-tree file, every declaration a
|
|
13
|
+
* candidate as if the file were fully staged. Only files of symbols the gate
|
|
14
|
+
* would judge are analyzed; a file the source analyzers cannot fully analyze
|
|
15
|
+
* is skipped.
|
|
16
|
+
*/
|
|
17
|
+
export declare function collectSymbolGranularityViolations(prolog: Pick<PrologPort, "query">, workspaceRoot: string, rules: ReadonlySet<string>): Promise<Violation[]>;
|
|
18
|
+
//# sourceMappingURL=symbol-granularity-check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"symbol-granularity-check.d.ts","sourceRoot":"","sources":["../../../src/public/operations/symbol-granularity-check.ts"],"names":[],"mappings":"AAgCA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAQ9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD;;;;;GAKG;AAEH,eAAO,MAAM,uBAAuB,uBAAuB,CAAC;AA+J5D;;;;;;GAMG;AAEH,wBAAsB,kCAAkC,CACtD,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,EACjC,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,GACzB,OAAO,CAAC,SAAS,EAAE,CAAC,CAYtB"}
|
|
@@ -0,0 +1,175 @@
|
|
|
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
|
+
import { readFileSync, statSync } from "node:fs";
|
|
19
|
+
import * as path from "node:path";
|
|
20
|
+
import { createMaintenanceSourceAnalysisService } from "../../plugins/maintenance-source-analysis.js";
|
|
21
|
+
import { normalizeEntityId, parseEntityFromList, parseListOfLists, parseTriples, } from "../../prolog/codec.js";
|
|
22
|
+
import { extractSymbolsFromStagedFileAsync, } from "../../traceability/symbol-extract.js";
|
|
23
|
+
import { createSymbolGranularityDiagnostics } from "../impact/diagnostics.js";
|
|
24
|
+
import { createImpactManifestLookup } from "../impact/manifest.js";
|
|
25
|
+
import { normalizeSourceFile } from "../impact/source-changes.js";
|
|
26
|
+
import { isAllowedGranularityReason, isTraceabilityRelationshipType, } from "../symbol-granularity.js";
|
|
27
|
+
/**
|
|
28
|
+
* Full-check form of the staged gate's `symbol_granularity_violation`: a
|
|
29
|
+
* symbol with traceability relationships must not link its source file
|
|
30
|
+
* coarsely while narrower behavioral symbols are available, unless it carries
|
|
31
|
+
* an allowed granularity_reason.
|
|
32
|
+
*/
|
|
33
|
+
// implements REQ-cli-check, REQ-cli-staged-impact-enforcement
|
|
34
|
+
export const SYMBOL_GRANULARITY_RULE = "symbol-granularity";
|
|
35
|
+
const SYMBOL_ROWS_QUERY = "findall([Id,symbol,Fields], (kb_entity(Id, symbol, Props), include([Key=_]>>memberchk(Key, [title,status,source,sourceFile,granularity_reason]), Props, Fields)), Rows)";
|
|
36
|
+
const SYMBOL_RELATIONSHIPS_QUERY = "findall([From,To,Type], (member(Type, [implements,covered_by,executable_for]), kb_relationship(Type, From, To), kb_entity(From, symbol, _)), Rels)";
|
|
37
|
+
function stringField(entity, key) {
|
|
38
|
+
const value = entity[key];
|
|
39
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
40
|
+
}
|
|
41
|
+
// implements REQ-cli-check
|
|
42
|
+
async function loadSymbolResults(prolog, workspaceRoot) {
|
|
43
|
+
const rows = await prolog.query(SYMBOL_ROWS_QUERY);
|
|
44
|
+
if (!rows.success) {
|
|
45
|
+
throw new Error(`symbol-granularity symbol projection failed: ${rows.error ?? "unknown error"}`);
|
|
46
|
+
}
|
|
47
|
+
const rels = await prolog.query(SYMBOL_RELATIONSHIPS_QUERY);
|
|
48
|
+
if (!rels.success) {
|
|
49
|
+
throw new Error(`symbol-granularity relationship projection failed: ${rels.error ?? "unknown error"}`);
|
|
50
|
+
}
|
|
51
|
+
const relationships = new Map();
|
|
52
|
+
for (const [rawFrom, rawTo, type] of parseTriples(rels.bindings.Rels ?? "[]")) {
|
|
53
|
+
const from = normalizeEntityId(rawFrom);
|
|
54
|
+
const current = relationships.get(from) ?? [];
|
|
55
|
+
current.push({ from, to: normalizeEntityId(rawTo), type });
|
|
56
|
+
relationships.set(from, current);
|
|
57
|
+
}
|
|
58
|
+
const results = [];
|
|
59
|
+
for (const row of parseListOfLists(rows.bindings.Rows ?? "[]")) {
|
|
60
|
+
const entity = parseEntityFromList(row);
|
|
61
|
+
const id = stringField(entity, "id");
|
|
62
|
+
const sourceFile = stringField(entity, "sourceFile");
|
|
63
|
+
if (id === undefined || sourceFile === undefined)
|
|
64
|
+
continue;
|
|
65
|
+
const granularityReason = stringField(entity, "granularity_reason");
|
|
66
|
+
results.push({
|
|
67
|
+
entity: {
|
|
68
|
+
id,
|
|
69
|
+
type: "symbol",
|
|
70
|
+
title: stringField(entity, "title") ?? "",
|
|
71
|
+
status: stringField(entity, "status") ?? "",
|
|
72
|
+
created_at: "",
|
|
73
|
+
updated_at: "",
|
|
74
|
+
source: stringField(entity, "source") ?? "",
|
|
75
|
+
...(granularityReason !== undefined
|
|
76
|
+
? { granularity_reason: granularityReason }
|
|
77
|
+
: {}),
|
|
78
|
+
},
|
|
79
|
+
relationships: relationships.get(id) ?? [],
|
|
80
|
+
sourceFile: normalizeSourceFile(workspaceRoot, sourceFile),
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
return results;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* The symbols the staged gate would judge: they carry a traceability
|
|
87
|
+
* relationship and no allowed granularity_reason. Other symbols are exempt,
|
|
88
|
+
* so their source files need no analysis.
|
|
89
|
+
*/
|
|
90
|
+
// implements REQ-cli-check
|
|
91
|
+
function granularityCandidates(results) {
|
|
92
|
+
return results.filter((result) => result.relationships.some((relationship) => isTraceabilityRelationshipType(relationship.type)) && !isAllowedGranularityReason(result.entity.granularity_reason));
|
|
93
|
+
}
|
|
94
|
+
function readRegularFile(absolutePath) {
|
|
95
|
+
try {
|
|
96
|
+
if (!statSync(absolutePath).isFile())
|
|
97
|
+
return null;
|
|
98
|
+
return readFileSync(absolutePath, "utf8");
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
// implements REQ-cli-check
|
|
105
|
+
async function analyzeFiles(files, results, workspaceRoot) {
|
|
106
|
+
const manifestLookup = createImpactManifestLookup(results);
|
|
107
|
+
const service = createMaintenanceSourceAnalysisService(workspaceRoot);
|
|
108
|
+
const analyses = new Map();
|
|
109
|
+
for (const file of files) {
|
|
110
|
+
const content = readRegularFile(path.resolve(workspaceRoot, file));
|
|
111
|
+
if (content === null)
|
|
112
|
+
continue;
|
|
113
|
+
try {
|
|
114
|
+
const analysis = await service.analyzeTextV2(file, content);
|
|
115
|
+
// Only a complete parser-backed analysis decides; the staged gate
|
|
116
|
+
// reports an incomplete one itself when the file is touched.
|
|
117
|
+
if (analysis.status !== "ok")
|
|
118
|
+
continue;
|
|
119
|
+
const symbols = await extractSymbolsFromStagedFileAsync({
|
|
120
|
+
path: file,
|
|
121
|
+
status: "M",
|
|
122
|
+
content,
|
|
123
|
+
hunkRanges: [{ start: 1, end: Number.MAX_SAFE_INTEGER }],
|
|
124
|
+
}, manifestLookup, { analyzeText: async () => analysis });
|
|
125
|
+
analyses.set(file, symbols);
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
// An analysis failure cannot decide anything for this file.
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return analyses;
|
|
132
|
+
}
|
|
133
|
+
// implements REQ-cli-check
|
|
134
|
+
function granularityViolations(candidates, sourceSymbolsByFile, workspaceRoot) {
|
|
135
|
+
return createSymbolGranularityDiagnostics({
|
|
136
|
+
manifestResults: candidates.filter((result) => result.sourceFile !== undefined &&
|
|
137
|
+
sourceSymbolsByFile.has(result.sourceFile)),
|
|
138
|
+
symbolsByFile: new Map(),
|
|
139
|
+
sourceSymbolsByFile,
|
|
140
|
+
workspaceRoot,
|
|
141
|
+
}).map((diagnostic) => ({
|
|
142
|
+
rule: SYMBOL_GRANULARITY_RULE,
|
|
143
|
+
entityId: diagnostic.entityId ?? "",
|
|
144
|
+
description: diagnostic.message,
|
|
145
|
+
suggestion: diagnostic.suggestion,
|
|
146
|
+
...(diagnostic.source !== undefined ? { source: diagnostic.source } : {}),
|
|
147
|
+
evidence: {
|
|
148
|
+
diagnosticId: diagnostic.id,
|
|
149
|
+
...(diagnostic.evidence ?? {}),
|
|
150
|
+
},
|
|
151
|
+
}));
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* `symbol-granularity`: the staged gate's granularity predicate, evaluated
|
|
155
|
+
* for every symbol against its whole working-tree file, every declaration a
|
|
156
|
+
* candidate as if the file were fully staged. Only files of symbols the gate
|
|
157
|
+
* would judge are analyzed; a file the source analyzers cannot fully analyze
|
|
158
|
+
* is skipped.
|
|
159
|
+
*/
|
|
160
|
+
// implements REQ-cli-check, REQ-cli-staged-impact-enforcement
|
|
161
|
+
export async function collectSymbolGranularityViolations(prolog, workspaceRoot, rules) {
|
|
162
|
+
if (!rules.has(SYMBOL_GRANULARITY_RULE))
|
|
163
|
+
return [];
|
|
164
|
+
const results = await loadSymbolResults(prolog, workspaceRoot);
|
|
165
|
+
const candidates = granularityCandidates(results);
|
|
166
|
+
const files = [
|
|
167
|
+
...new Set(candidates.map((result) => result.sourceFile ?? "")),
|
|
168
|
+
]
|
|
169
|
+
.filter((file) => file.length > 0)
|
|
170
|
+
.sort();
|
|
171
|
+
if (files.length === 0)
|
|
172
|
+
return [];
|
|
173
|
+
const analyses = await analyzeFiles(files, results, workspaceRoot);
|
|
174
|
+
return granularityViolations(candidates, analyses, workspaceRoot);
|
|
175
|
+
}
|
|
@@ -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.16.
|
|
5
|
+
version: 2.16.1
|
|
6
6
|
kibiCompatibility: ">=1.0.0"
|
|
7
7
|
tags:
|
|
8
8
|
- kibi
|
|
@@ -286,8 +286,13 @@ authored. Each one is the order the write path accepts.
|
|
|
286
286
|
existing entity, whose stored ledger Kibi keeps.
|
|
287
287
|
2. **Changing the text of a grounded requirement.** New prose means new
|
|
288
288
|
claim keys, so a bare rewrite is refused with `modeled proposition
|
|
289
|
-
claim_keys must match logical grounding target claim_keys exactly
|
|
290
|
-
|
|
289
|
+
claim_keys must match logical grounding target claim_keys exactly`; the
|
|
290
|
+
error names the modeled keys no fact declares and the facts whose keys
|
|
291
|
+
the ledger dropped. Analyze the new prose with the requirement's `id`
|
|
292
|
+
first: the receipt warns `Claim-key drift against the stored ledger`
|
|
293
|
+
and names the grounded clauses the new wording drops (the title worded
|
|
294
|
+
differently from the stored `semantic_text` is the usual cause), before
|
|
295
|
+
any write. Prefer supersession for a change of meaning: analyze the new prose,
|
|
291
296
|
write its facts, write the new requirement (`-v2`) with `supersedes` to
|
|
292
297
|
the old one, then set the old one to `status: closed`. Its scenario
|
|
293
298
|
follows the same rule as in recipe 1: create the new scenario (with
|
|
@@ -17,5 +17,22 @@ export declare function isCoarseGranularityReason(value: unknown): value is Coar
|
|
|
17
17
|
export declare function getSymbolRole(candidate: GranularSymbolCandidate): SymbolRole;
|
|
18
18
|
export declare function isBehavioralSymbol(candidate: GranularSymbolCandidate): boolean;
|
|
19
19
|
export declare function getBehavioralSymbolNames(candidates: GranularSymbolCandidate[]): string[];
|
|
20
|
+
/**
|
|
21
|
+
* The candidates that are narrower than a manifest symbol: members of it
|
|
22
|
+
* (`Title.member`), or, when the source declares no symbol named like it,
|
|
23
|
+
* every other declaration in the file.
|
|
24
|
+
*/
|
|
25
|
+
export declare function narrowerSymbols<T extends {
|
|
26
|
+
name: string;
|
|
27
|
+
}>(manifestSymbolName: string, candidates: readonly T[], sourceSymbols: readonly {
|
|
28
|
+
name: string;
|
|
29
|
+
}[]): T[];
|
|
30
|
+
/**
|
|
31
|
+
* The behavioral symbols that make a traceability link on
|
|
32
|
+
* `manifestSymbolName` coarse: the staged granularity gate blocks such a
|
|
33
|
+
* link unless it carries a granularity_reason, and `kibi migrate` marks
|
|
34
|
+
* exactly these links legacy-link. Empty when the link is narrow enough.
|
|
35
|
+
*/
|
|
36
|
+
export declare function coarseLinkBehavioralNames(manifestSymbolName: string, sourceSymbols: readonly GranularSymbolCandidate[]): string[];
|
|
20
37
|
export declare function getNonBehavioralSymbolNames(candidates: GranularSymbolCandidate[]): string[];
|
|
21
38
|
//# sourceMappingURL=symbol-granularity.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"symbol-granularity.d.ts","sourceRoot":"","sources":["../../src/public/symbol-granularity.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,2BAA2B,EAC3B,iCAAiC,EACjC,0BAA0B,EAC1B,wCAAwC,EACxC,gCAAgC,EAChC,KAAK,uBAAuB,EAC5B,KAAK,iBAAiB,EACtB,cAAc,EACd,YAAY,EACZ,KAAK,UAAU,EACf,+BAA+B,EAC/B,KAAK,4BAA4B,EAClC,MAAM,mCAAmC,CAAC;AAK3C,OAAO,EACL,2BAA2B,EAC3B,iCAAiC,EACjC,0BAA0B,EAC1B,wCAAwC,EACxC,gCAAgC,EAChC,cAAc,EACd,YAAY,EACZ,+BAA+B,GAChC,CAAC;AACF,YAAY,EACV,uBAAuB,EACvB,iBAAiB,EACjB,UAAU,EACV,4BAA4B,GAC7B,MAAM,mCAAmC,CAAC;AAE3C,MAAM,MAAM,UAAU,GAClB,UAAU,GACV,OAAO,GACP,QAAQ,GACR,UAAU,GACV,UAAU,GACV,WAAW,GACX,MAAM,GACN,UAAU,GACV,MAAM,GACN,SAAS,CAAC;AAEd,MAAM,MAAM,gBAAgB,GAAG,UAAU,CAAC;AAE1C,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAYD,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU,CAE5D;AAED,eAAO,MAAM,uBAAuB,wBAAkB,CAAC;AAEvD,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,UAAU,CAIhE;AAED,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,4BAA4B,CAIvC;AAED,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,iBAAiB,CAE5B;AAED,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,uBAAuB,CAElC;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,uBAAuB,GAAG,UAAU,CAI5E;AAED,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,uBAAuB,GACjC,OAAO,CAET;AAED,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,uBAAuB,EAAE,GACpC,MAAM,EAAE,CAMV;AAED,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,uBAAuB,EAAE,GACpC,MAAM,EAAE,CAQV"}
|
|
1
|
+
{"version":3,"file":"symbol-granularity.d.ts","sourceRoot":"","sources":["../../src/public/symbol-granularity.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,2BAA2B,EAC3B,iCAAiC,EACjC,0BAA0B,EAC1B,wCAAwC,EACxC,gCAAgC,EAChC,KAAK,uBAAuB,EAC5B,KAAK,iBAAiB,EACtB,cAAc,EACd,YAAY,EACZ,KAAK,UAAU,EACf,+BAA+B,EAC/B,KAAK,4BAA4B,EAClC,MAAM,mCAAmC,CAAC;AAK3C,OAAO,EACL,2BAA2B,EAC3B,iCAAiC,EACjC,0BAA0B,EAC1B,wCAAwC,EACxC,gCAAgC,EAChC,cAAc,EACd,YAAY,EACZ,+BAA+B,GAChC,CAAC;AACF,YAAY,EACV,uBAAuB,EACvB,iBAAiB,EACjB,UAAU,EACV,4BAA4B,GAC7B,MAAM,mCAAmC,CAAC;AAE3C,MAAM,MAAM,UAAU,GAClB,UAAU,GACV,OAAO,GACP,QAAQ,GACR,UAAU,GACV,UAAU,GACV,WAAW,GACX,MAAM,GACN,UAAU,GACV,MAAM,GACN,SAAS,CAAC;AAEd,MAAM,MAAM,gBAAgB,GAAG,UAAU,CAAC;AAE1C,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAYD,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU,CAE5D;AAED,eAAO,MAAM,uBAAuB,wBAAkB,CAAC;AAEvD,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,UAAU,CAIhE;AAED,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,4BAA4B,CAIvC;AAED,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,iBAAiB,CAE5B;AAED,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,uBAAuB,CAElC;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,uBAAuB,GAAG,UAAU,CAI5E;AAED,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,uBAAuB,GACjC,OAAO,CAET;AAED,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,uBAAuB,EAAE,GACpC,MAAM,EAAE,CAMV;AAED;;;;GAIG;AAEH,wBAAgB,eAAe,CAAC,CAAC,SAAS;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,EACxD,kBAAkB,EAAE,MAAM,EAC1B,UAAU,EAAE,SAAS,CAAC,EAAE,EACxB,aAAa,EAAE,SAAS;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,GACzC,CAAC,EAAE,CASL;AAED;;;;;GAKG;AAEH,wBAAgB,yBAAyB,CACvC,kBAAkB,EAAE,MAAM,EAC1B,aAAa,EAAE,SAAS,uBAAuB,EAAE,GAChD,MAAM,EAAE,CAIV;AAED,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,uBAAuB,EAAE,GACpC,MAAM,EAAE,CAQV"}
|
|
@@ -37,6 +37,27 @@ export function getBehavioralSymbolNames(candidates) {
|
|
|
37
37
|
...new Set(candidates.filter(isBehavioralSymbol).map((candidate) => candidate.name)),
|
|
38
38
|
].sort();
|
|
39
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* The candidates that are narrower than a manifest symbol: members of it
|
|
42
|
+
* (`Title.member`), or, when the source declares no symbol named like it,
|
|
43
|
+
* every other declaration in the file.
|
|
44
|
+
*/
|
|
45
|
+
// implements REQ-symbol-behavioral-anchors, REQ-cli-schema-migration
|
|
46
|
+
export function narrowerSymbols(manifestSymbolName, candidates, sourceSymbols) {
|
|
47
|
+
const declared = sourceSymbols.some((symbol) => symbol.name === manifestSymbolName);
|
|
48
|
+
return candidates.filter((candidate) => candidate.name !== manifestSymbolName &&
|
|
49
|
+
(candidate.name.startsWith(`${manifestSymbolName}.`) || !declared));
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The behavioral symbols that make a traceability link on
|
|
53
|
+
* `manifestSymbolName` coarse: the staged granularity gate blocks such a
|
|
54
|
+
* link unless it carries a granularity_reason, and `kibi migrate` marks
|
|
55
|
+
* exactly these links legacy-link. Empty when the link is narrow enough.
|
|
56
|
+
*/
|
|
57
|
+
// implements REQ-symbol-behavioral-anchors, REQ-cli-schema-migration
|
|
58
|
+
export function coarseLinkBehavioralNames(manifestSymbolName, sourceSymbols) {
|
|
59
|
+
return getBehavioralSymbolNames(narrowerSymbols(manifestSymbolName, sourceSymbols, sourceSymbols));
|
|
60
|
+
}
|
|
40
61
|
export function getNonBehavioralSymbolNames(candidates) {
|
|
41
62
|
return [
|
|
42
63
|
...new Set(candidates
|
|
@@ -61,14 +61,18 @@ export interface KibiImpactSymbolsManifestFileDetail {
|
|
|
61
61
|
path: string;
|
|
62
62
|
/** Symbol count extraction finds in the staged source content. */
|
|
63
63
|
expectedCount: number;
|
|
64
|
-
/**
|
|
64
|
+
/**
|
|
65
|
+
* Extracted symbols that have a matching staged manifest+coordinates entry
|
|
66
|
+
* (`expectedCount - missing.length`); evidence-only entries in `extra` are
|
|
67
|
+
* not counted.
|
|
68
|
+
*/
|
|
65
69
|
coveredCount: number;
|
|
66
|
-
/**
|
|
70
|
+
/** Every extracted symbol with no evidence entry (title + definition line). */
|
|
67
71
|
missing: Array<{
|
|
68
72
|
title: string;
|
|
69
73
|
line: number;
|
|
70
74
|
}>;
|
|
71
|
-
/**
|
|
75
|
+
/** Every evidence entry the extractor no longer finds at the recorded shape. */
|
|
72
76
|
extra: string[];
|
|
73
77
|
}
|
|
74
78
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"evidence-model.d.ts","sourceRoot":"","sources":["../../src/traceability/evidence-model.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,eAAO,MAAM,+BAA+B,iDACI,CAAC;AAEjD,eAAO,MAAM,sBAAsB,0BAA0B,CAAC;AAE9D,+EAA+E;AAC/E,eAAO,MAAM,0BAA0B,qBAAqB,CAAC;AAE7D,qFAAqF;AACrF,eAAO,MAAM,4BAA4B,gCAAgC,CAAC;AAE1E,mEAAmE;AACnE,eAAO,MAAM,0BAA0B,sBAAsB,CAAC;AAE9D,oEAAoE;AACpE,MAAM,MAAM,cAAc,GACtB,KAAK,GACL,UAAU,GACV,MAAM,GACN,KAAK,GACL,MAAM,GACN,OAAO,GACP,QAAQ,GACR,MAAM,CAAC;AAEX;;;;;;;GAOG;AACH,MAAM,MAAM,gBAAgB,GACxB,sBAAsB,GACtB,0BAA0B,CAAC;AAE/B,sEAAsE;AACtE,MAAM,WAAW,sBAAsB;IACrC,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,IAAI,EAAE,gBAAgB,CAAC;CACxB;AAED;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC,wEAAwE;IACxE,IAAI,EAAE,iBAAiB,GAAG,kBAAkB,CAAC;IAC7C,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,kEAAkE;IAClE,WAAW,EAAE,cAAc,EAAE,CAAC;IAC9B,2DAA2D;IAC3D,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,sEAAsE;IACtE,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,mCAAmC;IAClD,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,kEAAkE;IAClE,aAAa,EAAE,MAAM,CAAC;IACtB
|
|
1
|
+
{"version":3,"file":"evidence-model.d.ts","sourceRoot":"","sources":["../../src/traceability/evidence-model.ts"],"names":[],"mappings":"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"}
|
|
@@ -264,8 +264,7 @@ function getEffectiveManifestRecords(options) {
|
|
|
264
264
|
stagedCoordinateArtifact,
|
|
265
265
|
};
|
|
266
266
|
}
|
|
267
|
-
|
|
268
|
-
const MAX_DETAIL_ITEMS = 6;
|
|
267
|
+
// implements REQ-cli-staged-impact-enforcement
|
|
269
268
|
function diffSymbolEvidence(sourcePath, expectedSymbols, stagedSymbols) {
|
|
270
269
|
const stagedTitles = new Set(stagedSymbols.map((symbol) => symbol.title));
|
|
271
270
|
const expectedTitles = new Set(expectedSymbols.map((symbol) => symbol.title));
|
|
@@ -282,12 +281,14 @@ function diffSymbolEvidence(sourcePath, expectedSymbols, stagedSymbols) {
|
|
|
282
281
|
if (missing.length === 0 && extra.length === 0) {
|
|
283
282
|
return null;
|
|
284
283
|
}
|
|
284
|
+
// Keep the complete lists: human-facing renderers truncate (with an
|
|
285
|
+
// accurate "… and N more"), while JSON evidence carries every name.
|
|
285
286
|
return {
|
|
286
287
|
path: sourcePath,
|
|
287
288
|
expectedCount: expectedSymbols.length,
|
|
288
|
-
coveredCount:
|
|
289
|
-
missing
|
|
290
|
-
extra
|
|
289
|
+
coveredCount: expectedSymbols.length - missing.length,
|
|
290
|
+
missing,
|
|
291
|
+
extra,
|
|
291
292
|
};
|
|
292
293
|
}
|
|
293
294
|
export function assessStagedSymbolsManifest(options) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type PrologProcess } from "../prolog.js";
|
|
2
|
+
import { type ParsedViolation } from "../prolog/codec.js";
|
|
2
3
|
export interface ValidationOptions {
|
|
3
4
|
minLinks: number;
|
|
4
5
|
prolog: PrologProcess;
|
|
@@ -17,6 +18,18 @@ declare function splitTopLevelComma(s: string): string[];
|
|
|
17
18
|
declare function splitTopLevelLists(value: string): string[];
|
|
18
19
|
declare function parsePrologListOfLists(value: string): string[][];
|
|
19
20
|
export declare function validateStagedSymbols(options: ValidationOptions): Promise<Violation[]>;
|
|
21
|
+
/**
|
|
22
|
+
* Full-check `symbol-coverage` for the staged change set: the changed source
|
|
23
|
+
* symbols in the consulted overlay plus `extraSymbolIds` (symbols whose staged
|
|
24
|
+
* manifest entry changed). The Prolog rule is the one `kibi check` runs, so a
|
|
25
|
+
* commit cannot pass the staged gate with coverage the full check rejects.
|
|
26
|
+
*/
|
|
27
|
+
export declare function validateStagedSymbolCoverage(options: {
|
|
28
|
+
prolog: PrologProcess;
|
|
29
|
+
extraSymbolIds?: readonly string[];
|
|
30
|
+
}): Promise<ParsedViolation[]>;
|
|
31
|
+
/** Text lines for staged symbol-coverage violations, in `kibi check` form. */
|
|
32
|
+
export declare function formatCoverageViolations(violations: readonly ParsedViolation[]): string;
|
|
20
33
|
export declare function formatViolations(violations: Violation[]): string;
|
|
21
34
|
export declare const __test__: {
|
|
22
35
|
unquoteAtom: typeof unquoteAtom;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/traceability/validate.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/traceability/validate.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,aAAa,EAAmB,MAAM,cAAc,CAAC;AACnE,OAAO,EACL,KAAK,eAAe,EAIrB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,aAAa,CAAC;CACvB;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,iBAAS,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAO1C;AAED,iBAAS,kBAAkB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CA0B/C;AAED,iBAAS,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CA8CnD;AAED,iBAAS,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,CAuBzD;AAGD,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,SAAS,EAAE,CAAC,CAgDtB;AAED;;;;;GAKG;AAEH,wBAAsB,4BAA4B,CAAC,OAAO,EAAE;IAC1D,MAAM,EAAE,aAAa,CAAC;IACtB,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAgB7B;AAED,8EAA8E;AAE9E,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,SAAS,eAAe,EAAE,GACrC,MAAM,CAaR;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,MAAM,CAkBhE;AAGD,eAAO,MAAM,QAAQ;;;;;CAKpB,CAAC"}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { resolveKbPlPath } from "../prolog.js";
|
|
3
|
+
import { escapeAtom, parseViolationRows, toPrologAtom, } from "../prolog/codec.js";
|
|
1
4
|
function unquoteAtom(value) {
|
|
2
5
|
// remove surrounding single quotes and unescape doubled quotes
|
|
3
6
|
const trimmed = value.trim();
|
|
@@ -141,6 +144,44 @@ export async function validateStagedSymbols(options) {
|
|
|
141
144
|
}
|
|
142
145
|
return violations;
|
|
143
146
|
}
|
|
147
|
+
/**
|
|
148
|
+
* Full-check `symbol-coverage` for the staged change set: the changed source
|
|
149
|
+
* symbols in the consulted overlay plus `extraSymbolIds` (symbols whose staged
|
|
150
|
+
* manifest entry changed). The Prolog rule is the one `kibi check` runs, so a
|
|
151
|
+
* commit cannot pass the staged gate with coverage the full check rejects.
|
|
152
|
+
*/
|
|
153
|
+
// implements REQ-014
|
|
154
|
+
export async function validateStagedSymbolCoverage(options) {
|
|
155
|
+
const extra = `[${[...new Set(options.extraSymbolIds ?? [])]
|
|
156
|
+
.sort()
|
|
157
|
+
.map(toPrologAtom)
|
|
158
|
+
.join(",")}]`;
|
|
159
|
+
const checksPl = escapeAtom(path.join(path.dirname(resolveKbPlPath()), "checks.pl"));
|
|
160
|
+
const goal = `(use_module('${checksPl}'), call(checks:check_changed_symbol_coverage(${extra}, Violations)))`;
|
|
161
|
+
const res = await options.prolog.query(goal);
|
|
162
|
+
if (!res.success) {
|
|
163
|
+
throw new Error(`Prolog symbol-coverage query failed: ${res.error || "unknown error"}`);
|
|
164
|
+
}
|
|
165
|
+
return parseViolationRows(res.bindings.Violations ?? "[]");
|
|
166
|
+
}
|
|
167
|
+
/** Text lines for staged symbol-coverage violations, in `kibi check` form. */
|
|
168
|
+
// implements REQ-014
|
|
169
|
+
export function formatCoverageViolations(violations) {
|
|
170
|
+
if (violations.length === 0)
|
|
171
|
+
return "";
|
|
172
|
+
const lines = [
|
|
173
|
+
`Found ${violations.length} symbol-coverage violation(s) in staged symbols (the same rule kibi check runs):`,
|
|
174
|
+
];
|
|
175
|
+
for (const violation of violations) {
|
|
176
|
+
lines.push("", `[${violation.rule}] ${violation.entityId}`);
|
|
177
|
+
if (violation.source)
|
|
178
|
+
lines.push(` Source: ${violation.source}`);
|
|
179
|
+
lines.push(` ${violation.description}`);
|
|
180
|
+
if (violation.suggestion)
|
|
181
|
+
lines.push(` Suggestion: ${violation.suggestion}`);
|
|
182
|
+
}
|
|
183
|
+
return lines.join("\n");
|
|
184
|
+
}
|
|
144
185
|
export function formatViolations(violations) {
|
|
145
186
|
// implements REQ-014
|
|
146
187
|
if (!violations || violations.length === 0)
|
|
@@ -13,6 +13,11 @@ export declare const GENERATED_RULES: readonly [{
|
|
|
13
13
|
readonly description: "Production symbols must directly implement requirements for ownership; covered_by is coverage only and executable_for is test identity only";
|
|
14
14
|
readonly enforcementClass: "canonical";
|
|
15
15
|
readonly category: "traceability";
|
|
16
|
+
}, {
|
|
17
|
+
readonly name: "symbol-granularity";
|
|
18
|
+
readonly description: "A symbol with traceability relationships must not link its source file coarsely while narrower behavioral symbols are available, unless it carries an allowed granularity_reason; the staged gate's symbol_granularity_violation evaluated KB-wide";
|
|
19
|
+
readonly enforcementClass: "canonical";
|
|
20
|
+
readonly category: "traceability";
|
|
16
21
|
}, {
|
|
17
22
|
readonly name: "no-dangling-refs";
|
|
18
23
|
readonly description: "All relationship targets must exist in the KB";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rule-registry.generated.d.ts","sourceRoot":"","sources":["../../src/utils/rule-registry.generated.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,eAAe
|
|
1
|
+
{"version":3,"file":"rule-registry.generated.d.ts","sourceRoot":"","sources":["../../src/utils/rule-registry.generated.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgXlB,CAAC"}
|
|
@@ -26,6 +26,12 @@ export const GENERATED_RULES = [
|
|
|
26
26
|
enforcementClass: "canonical",
|
|
27
27
|
category: "traceability",
|
|
28
28
|
},
|
|
29
|
+
{
|
|
30
|
+
name: "symbol-granularity",
|
|
31
|
+
description: "A symbol with traceability relationships must not link its source file coarsely while narrower behavioral symbols are available, unless it carries an allowed granularity_reason; the staged gate's symbol_granularity_violation evaluated KB-wide",
|
|
32
|
+
enforcementClass: "canonical",
|
|
33
|
+
category: "traceability",
|
|
34
|
+
},
|
|
29
35
|
{
|
|
30
36
|
name: "no-dangling-refs",
|
|
31
37
|
description: "All relationship targets must exist in the KB",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kibi-cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.22.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Kibi CLI for knowledge base management",
|
|
6
6
|
"engines": {
|
|
@@ -235,8 +235,8 @@
|
|
|
235
235
|
"fast-glob": "^3.2.12",
|
|
236
236
|
"gray-matter": "^4.0.3",
|
|
237
237
|
"js-yaml": "^4.1.0",
|
|
238
|
-
"kibi-core": "^0.
|
|
239
|
-
"kibi-plugin-builtin": "^0.5.
|
|
238
|
+
"kibi-core": "^0.22.0",
|
|
239
|
+
"kibi-plugin-builtin": "^0.5.2",
|
|
240
240
|
"kibi-plugin-sdk": "^0.5.0",
|
|
241
241
|
"kibi-swipl": "^1.0.1",
|
|
242
242
|
"saxes": "^6.0.0",
|