kibi-cli 2.21.2 → 2.22.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-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 +96 -6
- package/dist/commands/init-helpers.d.ts +14 -1
- package/dist/commands/init-helpers.d.ts.map +1 -1
- package/dist/commands/init-helpers.js +49 -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.map +1 -1
- package/dist/commands/migrate.js +48 -182
- 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/planning/apply-plan.d.ts.map +1 -1
- package/dist/operations/planning/apply-plan.js +18 -3
- 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/discovery-executors.d.ts +2 -0
- package/dist/public/operations/discovery-executors.d.ts.map +1 -1
- package/dist/public/operations/discovery-executors.js +9 -2
- package/dist/public/operations/migration-plan.d.ts +2 -0
- package/dist/public/operations/migration-plan.d.ts.map +1 -1
- package/dist/public/operations/migration-plan.js +101 -16
- 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/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/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/discovery-executors.ts +12 -2
- package/src/public/operations/migration-plan.ts +100 -19
- 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/symbol-granularity-check.ts +233 -0
- package/src/public/symbol-granularity.ts +37 -0
|
@@ -261,14 +261,80 @@ function predicateSchemaAlignmentAction(diagnostic) {
|
|
|
261
261
|
}
|
|
262
262
|
/** Migration code for mechanical predicate namespace/alias repairs. */
|
|
263
263
|
export const PREDICATE_SCHEMA_ALIGNMENT_CODE = "predicate_schema_alignment";
|
|
264
|
+
/** Migration code of the grouped untracked-source parity findings. */
|
|
265
|
+
export const UNTRACKED_KNOWLEDGE_SOURCES_CODE = "untracked_knowledge_sources";
|
|
266
|
+
/**
|
|
267
|
+
* Every source-relationship-parity finding explained by untracked files
|
|
268
|
+
* (evidence `untrackedSources`) has one cause and one fix: the files Git
|
|
269
|
+
* does not track and no pending-source receipt covers. After a storage move
|
|
270
|
+
* that can be thousands of relationships, so they become one review action
|
|
271
|
+
* naming the files instead of one per relationship.
|
|
272
|
+
*/
|
|
273
|
+
// implements REQ-agent-guided-migration-orchestration, REQ-kibi-source-relationship-parity
|
|
274
|
+
function untrackedSourceActionFromViolations(violations) {
|
|
275
|
+
const consumed = new Set();
|
|
276
|
+
const files = new Set();
|
|
277
|
+
const entityIds = new Set();
|
|
278
|
+
const relationships = [];
|
|
279
|
+
for (const [index, violation] of violations.entries()) {
|
|
280
|
+
if (violation.rule !== "source-relationship-parity")
|
|
281
|
+
continue;
|
|
282
|
+
const evidence = isRecord(violation.evidence) ? violation.evidence : {};
|
|
283
|
+
const sources = Array.isArray(evidence.untrackedSources)
|
|
284
|
+
? evidence.untrackedSources.filter(isRecord)
|
|
285
|
+
: [];
|
|
286
|
+
if (sources.length === 0)
|
|
287
|
+
continue;
|
|
288
|
+
consumed.add(index);
|
|
289
|
+
for (const source of sources) {
|
|
290
|
+
if (typeof source.file === "string")
|
|
291
|
+
files.add(source.file);
|
|
292
|
+
if (typeof source.entityId === "string")
|
|
293
|
+
entityIds.add(source.entityId);
|
|
294
|
+
}
|
|
295
|
+
if (evidence.relationship !== undefined)
|
|
296
|
+
relationships.push(evidence.relationship);
|
|
297
|
+
}
|
|
298
|
+
if (consumed.size === 0)
|
|
299
|
+
return null;
|
|
300
|
+
const listed = [...files].sort();
|
|
301
|
+
return {
|
|
302
|
+
consumed,
|
|
303
|
+
action: migrationAction({
|
|
304
|
+
id: "untracked-knowledge-sources",
|
|
305
|
+
code: UNTRACKED_KNOWLEDGE_SOURCES_CODE,
|
|
306
|
+
category: "relationship",
|
|
307
|
+
safety: "review",
|
|
308
|
+
invocation: {
|
|
309
|
+
kind: "review",
|
|
310
|
+
instruction: `${consumed.size} authored relationship(s) are missing from the compiled KB because ${listed.length} file(s) declaring their endpoints are not tracked by Git and no pending-source receipt covers them: ${listed.join(", ")}. Stage them (git add; staging is enough, Kibi never stages files itself) or rewrite the entities with kb_upsert, then run kibi sync and rerun kibi migrate.`,
|
|
311
|
+
},
|
|
312
|
+
affectedEntityIds: [...entityIds],
|
|
313
|
+
affectedFiles: listed,
|
|
314
|
+
postconditions: [{ rule: "source-relationship-parity", findings: 0 }],
|
|
315
|
+
evidence: {
|
|
316
|
+
relationshipCount: consumed.size,
|
|
317
|
+
files: listed,
|
|
318
|
+
// A sample; the count above is the full number.
|
|
319
|
+
relationships: relationships.slice(0, 20),
|
|
320
|
+
},
|
|
321
|
+
dispositionRequired: true,
|
|
322
|
+
}),
|
|
323
|
+
};
|
|
324
|
+
}
|
|
264
325
|
// implements REQ-agent-guided-migration-orchestration, REQ-kibi-predicate-vocabulary-migration, REQ-cli-schema-migration
|
|
265
326
|
export function buildActionsFromCheck(input) {
|
|
266
327
|
const actions = [];
|
|
267
328
|
const lifecycle = lifecycleActionsFromViolations(input.violations ?? []);
|
|
268
329
|
actions.push(...lifecycle.actions.map(migrationAction));
|
|
330
|
+
const untracked = untrackedSourceActionFromViolations(input.violations ?? []);
|
|
331
|
+
if (untracked !== null)
|
|
332
|
+
actions.push(untracked.action);
|
|
269
333
|
for (const [index, violation] of (input.violations ?? []).entries()) {
|
|
270
334
|
if (lifecycle.consumed.has(index))
|
|
271
335
|
continue;
|
|
336
|
+
if (untracked?.consumed.has(index))
|
|
337
|
+
continue;
|
|
272
338
|
const rule = typeof violation.rule === "string" ? violation.rule : "check";
|
|
273
339
|
const entityId = typeof violation.entityId === "string" ? violation.entityId : "";
|
|
274
340
|
const suggestion = typeof violation.suggestion === "string"
|
|
@@ -442,6 +508,17 @@ function readLegacySchemaVersion(workspaceRoot) {
|
|
|
442
508
|
// implements REQ-agent-guided-migration-orchestration
|
|
443
509
|
/** Migration action code of the automatic recompile of changed sources. */
|
|
444
510
|
export const FRESHNESS_RESYNC = "freshness_resync";
|
|
511
|
+
// implements REQ-cli-status-pre-first-sync
|
|
512
|
+
/**
|
|
513
|
+
* Stale reasons one `kibi sync` clears: sources whose content changed since
|
|
514
|
+
* the last compilation, and a store compiled under another compiler contract
|
|
515
|
+
* (the sync discards that cache, re-imports every source and stamps the
|
|
516
|
+
* current contract).
|
|
517
|
+
*/
|
|
518
|
+
const RESYNC_REASON_CODES = new Set([
|
|
519
|
+
...MTIME_SOURCE_REASON_CODES,
|
|
520
|
+
"compiler_changed",
|
|
521
|
+
]);
|
|
445
522
|
export function buildActionsFromStatus(input) {
|
|
446
523
|
const actions = [];
|
|
447
524
|
const attachment = input.branchAttachment;
|
|
@@ -488,14 +565,19 @@ export function buildActionsFromStatus(input) {
|
|
|
488
565
|
}));
|
|
489
566
|
}
|
|
490
567
|
const storeState = typeof store?.state === "string" ? store.state : null;
|
|
491
|
-
|
|
568
|
+
// Legacy storage is evaluated whether or not the legacy config survives:
|
|
569
|
+
// legacy copies left beside a migrated .kb/ (moved, identical or stale)
|
|
570
|
+
// are the same finding 'kibi doctor' and 'kibi migrate' report.
|
|
571
|
+
// implements REQ-cli-schema-migration
|
|
572
|
+
const legacyStorage = planLegacyStorageMigration(input.workspaceRoot);
|
|
573
|
+
const legacyStorageMigrationRequired = legacyConfigExists(input.workspaceRoot) ||
|
|
574
|
+
legacyStorage.moves.length > 0 ||
|
|
575
|
+
legacyStorage.removals.length > 0 ||
|
|
576
|
+
legacyStorage.blockers.length > 0;
|
|
492
577
|
// A legacy cutover that cannot move its files (a destination already
|
|
493
578
|
// exists, a malformed config) is an operator decision, not an automatic
|
|
494
579
|
// step that fails when applied and takes the compile with it.
|
|
495
|
-
const
|
|
496
|
-
? planLegacyStorageMigration(input.workspaceRoot)
|
|
497
|
-
: null;
|
|
498
|
-
const legacyStorageBlocked = legacyStorage !== null && legacyStorage.blockers.length > 0;
|
|
580
|
+
const legacyStorageBlocked = legacyStorage.blockers.length > 0;
|
|
499
581
|
if (storeState === "missing") {
|
|
500
582
|
actions.push(migrationAction({
|
|
501
583
|
id: "branch-store-ensure",
|
|
@@ -542,26 +624,29 @@ export function buildActionsFromStatus(input) {
|
|
|
542
624
|
invocation: legacyStorageBlocked
|
|
543
625
|
? {
|
|
544
626
|
kind: "review",
|
|
545
|
-
instruction: `
|
|
627
|
+
instruction: `Legacy knowledge files outside .kb/ cannot be migrated automatically: ${legacyStorage.blockers.join(" ")} Then run 'kibi migrate --yes'.`,
|
|
546
628
|
}
|
|
547
629
|
: { kind: "cli", command_argv: ["kibi", "migrate", "--yes"] },
|
|
548
630
|
affectedFiles: [
|
|
549
631
|
".kb/manifest.json",
|
|
550
632
|
".kb/migrations",
|
|
551
633
|
".kb/config.json",
|
|
552
|
-
...
|
|
634
|
+
...legacyStorage.moves.map((move) => move.from),
|
|
635
|
+
...legacyStorage.removals.map((removal) => removal.path),
|
|
553
636
|
],
|
|
554
637
|
evidence: {
|
|
555
638
|
configStatus,
|
|
556
|
-
...(
|
|
557
|
-
? {
|
|
558
|
-
: {
|
|
639
|
+
...(legacyStorageMigrationRequired
|
|
640
|
+
? {
|
|
559
641
|
legacyStorage: {
|
|
560
642
|
moves: legacyStorage.moves,
|
|
643
|
+
removals: legacyStorage.removals,
|
|
644
|
+
conflicts: legacyStorage.conflicts,
|
|
561
645
|
blockers: legacyStorage.blockers,
|
|
562
646
|
legacyConfig: legacyStorage.legacyConfig,
|
|
563
647
|
},
|
|
564
|
-
}
|
|
648
|
+
}
|
|
649
|
+
: {}),
|
|
565
650
|
},
|
|
566
651
|
dependsOn: storeState === "missing" ? ["branch-store-ensure"] : [],
|
|
567
652
|
autoApplicable: !operatorOnly,
|
|
@@ -598,10 +683,10 @@ export function buildActionsFromStatus(input) {
|
|
|
598
683
|
// implements REQ-cli-status-pre-first-sync
|
|
599
684
|
// Sources whose content changed since the last compilation (kb_status has
|
|
600
685
|
// already dropped mtime-only reasons) are fixed by recompiling them: one
|
|
601
|
-
// automatic `kibi sync`, not a review per file.
|
|
602
|
-
//
|
|
603
|
-
|
|
604
|
-
|
|
686
|
+
// automatic `kibi sync`, not a review per file. A store compiled under
|
|
687
|
+
// another compiler contract is fixed by the same sync. An uncompiled store
|
|
688
|
+
// is compiled by the step above, which also covers these reasons.
|
|
689
|
+
const resyncReasons = (input.staleReasons ?? []).filter((reason) => typeof reason.code === "string" && RESYNC_REASON_CODES.has(reason.code));
|
|
605
690
|
if (resyncReasons.length > 0 && uncompiled === undefined) {
|
|
606
691
|
actions.push(migrationAction({
|
|
607
692
|
id: "freshness-resync",
|
|
@@ -626,7 +711,7 @@ export function buildActionsFromStatus(input) {
|
|
|
626
711
|
if (code === BRANCH_STORE_NOT_COMPILED)
|
|
627
712
|
continue;
|
|
628
713
|
// Planned above as one automatic resync (or covered by the compile).
|
|
629
|
-
if (
|
|
714
|
+
if (RESYNC_REASON_CODES.has(code))
|
|
630
715
|
continue;
|
|
631
716
|
const file = typeof reason.path === "string" ? reason.path : "";
|
|
632
717
|
actions.push(migrationAction({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"result-envelope.d.ts","sourceRoot":"","sources":["../../../src/public/operations/result-envelope.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE7E,eAAO,MAAM,qBAAqB,EAAG,CAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"result-envelope.d.ts","sourceRoot":"","sources":["../../../src/public/operations/result-envelope.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE7E,eAAO,MAAM,qBAAqB,EAAG,CAAU,CAAC;AAkEhD,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,UAAU,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAS/B;AAoFD,wBAAgB,aAAa,CAAC,IAAI,EAAE;IAClC,QAAQ,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,CAAC;IACtC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC,GAAG,MAAM,CAET;AAYD,wBAAgB,YAAY,CAAC,CAAC,EAC5B,IAAI,EAAE;IACJ,QAAQ,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,CAAC;IACtC,QAAQ,CAAC,OAAO,EAAE,SAAS,eAAe,EAAE,CAAC;IAC7C,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC,EACD,IAAI,EAAE,CAAC,EACP,OAAO,GAAE,OAAO,CACd,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,QAAQ,GAAG,aAAa,GAAG,aAAa,GAAG,OAAO,CAAC,CACxE,GAAG;IACF;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;CACzB,GACL,UAAU,CAAC,CAAC,CAAC,CAsDf;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAKrD;AAGD,MAAM,WAAW,uBAAuB;IACtC,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C,2EAA2E;IAC3E,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACzC;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,OAAO,GACd,uBAAuB,CAYzB;AAaD;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAC3C,IAAI,CAKN"}
|
|
@@ -14,6 +14,29 @@ function diagnostics(value) {
|
|
|
14
14
|
return [entry];
|
|
15
15
|
});
|
|
16
16
|
}
|
|
17
|
+
// Discovery operations whose empty answer may come from an uncompiled store.
|
|
18
|
+
const STORE_READ_OPERATIONS = new Set(["kb_search", "kb_query"]);
|
|
19
|
+
/**
|
|
20
|
+
* A search or query answered from a branch store that was never compiled
|
|
21
|
+
* reads an empty KB. The payload already names the store state; the envelope
|
|
22
|
+
* also raises it as a warning, so a caller that reads only `status` and
|
|
23
|
+
* `diagnostics` does not take the empty answer as "nothing governs this".
|
|
24
|
+
*/
|
|
25
|
+
// implements REQ-cli-status-pre-first-sync, REQ-mcp-search-discovery
|
|
26
|
+
function uncompiledStoreDiagnostics(operation, row) {
|
|
27
|
+
const store = row?.branchStore;
|
|
28
|
+
if (!STORE_READ_OPERATIONS.has(operation) ||
|
|
29
|
+
!record(store) ||
|
|
30
|
+
store.state !== "not_compiled")
|
|
31
|
+
return [];
|
|
32
|
+
return [
|
|
33
|
+
{
|
|
34
|
+
...(typeof store.code === "string" ? { code: store.code } : {}),
|
|
35
|
+
severity: "warning",
|
|
36
|
+
message: `${typeof store.detail === "string" ? `${store.detail} ` : ""}An empty answer here does not mean no requirement governs this; run \`kibi sync\` and ask again.`,
|
|
37
|
+
},
|
|
38
|
+
];
|
|
39
|
+
}
|
|
17
40
|
function nextActions(value) {
|
|
18
41
|
if (!Array.isArray(value))
|
|
19
42
|
return [];
|
|
@@ -152,7 +175,10 @@ export function toKibiResult(spec, data, options = {}) {
|
|
|
152
175
|
...spec.effects.map((effect) => effectStatus(effect, row, outcome)),
|
|
153
176
|
...extraFailedEffects(spec.effects, row),
|
|
154
177
|
],
|
|
155
|
-
diagnostics: options.diagnostics ??
|
|
178
|
+
diagnostics: options.diagnostics ?? [
|
|
179
|
+
...diagnostics(row?.diagnostics),
|
|
180
|
+
...uncompiledStoreDiagnostics(String(spec.name), row),
|
|
181
|
+
],
|
|
156
182
|
nextActions: options.nextActions ?? nextActions(row?.nextActions),
|
|
157
183
|
...(resultError ? { error: resultError } : {}),
|
|
158
184
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Every selectable kb_check rule name, registry order. */
|
|
2
2
|
export declare const SELECTABLE_RULE_NAMES: readonly string[];
|
|
3
3
|
/** Comma-separated "Allowed:" fragment for the kb_check rules description. */
|
|
4
|
-
export declare 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";
|
|
4
|
+
export declare 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";
|
|
5
5
|
//# sourceMappingURL=check-rules.generated.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check-rules.generated.d.ts","sourceRoot":"","sources":["../../../../src/public/operations/specs/check-rules.generated.ts"],"names":[],"mappings":"AAUA,2DAA2D;AAC3D,eAAO,MAAM,qBAAqB,EAAE,SAAS,MAAM,
|
|
1
|
+
{"version":3,"file":"check-rules.generated.d.ts","sourceRoot":"","sources":["../../../../src/public/operations/specs/check-rules.generated.ts"],"names":[],"mappings":"AAUA,2DAA2D;AAC3D,eAAO,MAAM,qBAAqB,EAAE,SAAS,MAAM,EAqDlD,CAAC;AAGF,8EAA8E;AAC9E,eAAO,MAAM,wBAAwB,gqCAC0nC,CAAC"}
|
|
@@ -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",
|
|
@@ -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
|
+
}
|
|
@@ -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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"}
|