kibi-cli 0.12.0 → 0.12.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.
@@ -1 +1 @@
1
- {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"AA2EA,OAAO,EAGL,KAAK,SAAS,EAEf,MAAM,2BAA2B,CAAC;AAEnC,YAAY,EAAE,SAAS,EAAE,CAAC;AAI1B,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAiVD,wBAAsB,YAAY,CAChC,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAmU/B"}
1
+ {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"AA2EA,OAAO,EAGL,KAAK,SAAS,EAEf,MAAM,2BAA2B,CAAC;AAEnC,YAAY,EAAE,SAAS,EAAE,CAAC;AAI1B,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AA8bD,wBAAsB,YAAY,CAChC,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CA0V/B"}
@@ -15,7 +15,7 @@
15
15
  You should have received a copy of the GNU Affero General Public License
16
16
  along with this program. If not, see <https://www.gnu.org/licenses/>.
17
17
  */
18
- import { existsSync } from "node:fs";
18
+ import { existsSync, readFileSync } from "node:fs";
19
19
  import * as path from "node:path";
20
20
  import { getBranchOverride, isCliTraceOrDebugEnabled } from "../env.js";
21
21
  import { extractFromManifest, extractFromManifestString, } from "../extractors/manifest.js";
@@ -43,6 +43,8 @@ function getMatchGroup(match, index = 1) {
43
43
  function buildManifestLookup(stagedFiles) {
44
44
  const manifestLookup = new Map();
45
45
  const manifestResults = [];
46
+ const authoredSymbolResults = [];
47
+ const stagedAuthoredSymbolResults = [];
46
48
  // Pre-populate lookup from working-tree manifests so that code-only changes
47
49
  // (where symbols.yaml is not staged) still resolve to the correct symbol IDs
48
50
  // and relationships already defined on disk.
@@ -54,6 +56,7 @@ function buildManifestLookup(stagedFiles) {
54
56
  try {
55
57
  const entries = extractFromManifest(absSymbolsPath);
56
58
  for (const entry of entries) {
59
+ authoredSymbolResults.push(entry);
57
60
  const sourceFile = entry.sourceFile || entry.entity.source || absSymbolsPath;
58
61
  const key = `${sourceFile}:${entry.entity.title}`;
59
62
  manifestLookup.set(key, {
@@ -95,6 +98,13 @@ function buildManifestLookup(stagedFiles) {
95
98
  entity: entry.entity,
96
99
  relationships: entry.relationships,
97
100
  });
101
+ const authoredSymbolResult = {
102
+ entity: entry.entity,
103
+ relationships: entry.relationships,
104
+ ...(entry.sourceFile !== undefined ? { sourceFile: entry.sourceFile } : {}),
105
+ };
106
+ authoredSymbolResults.push(authoredSymbolResult);
107
+ stagedAuthoredSymbolResults.push(authoredSymbolResult);
98
108
  const sourceFile = entry.sourceFile || entry.entity.source || manifestFile.path;
99
109
  const key = `${sourceFile}:${entry.entity.title}`;
100
110
  manifestLookup.set(key, {
@@ -114,7 +124,79 @@ function buildManifestLookup(stagedFiles) {
114
124
  // Ignore manifest parsing errors
115
125
  }
116
126
  }
117
- return { manifestLookup, manifestResults };
127
+ return {
128
+ manifestLookup,
129
+ manifestResults,
130
+ authoredSymbolResults,
131
+ stagedAuthoredSymbolResults,
132
+ };
133
+ }
134
+ const GRANULARITY_RELATIONSHIP_TYPES = new Set([
135
+ "implements",
136
+ "covered_by",
137
+ "executable_for",
138
+ ]);
139
+ const ALLOWED_GRANULARITY_REASONS = new Set([
140
+ "config-artifact",
141
+ "module-level-behavior",
142
+ "extractor-miss",
143
+ "legacy-link",
144
+ ]);
145
+ function hasTraceabilityRelationship(result) {
146
+ return result.relationships.some((relationship) => GRANULARITY_RELATIONSHIP_TYPES.has(relationship.type));
147
+ }
148
+ function hasValidGranularityReason(result) {
149
+ const reason = result.entity.granularity_reason;
150
+ return (typeof reason === "string" && ALLOWED_GRANULARITY_REASONS.has(reason));
151
+ }
152
+ function createSymbolGranularityDiagnostics(options) {
153
+ const diagnostics = [];
154
+ for (const result of options.manifestResults) {
155
+ if (!result.sourceFile)
156
+ continue;
157
+ if (!hasTraceabilityRelationship(result))
158
+ continue;
159
+ if (hasValidGranularityReason(result))
160
+ continue;
161
+ const granularSymbols = getGranularSymbolsForSourceFile(result.sourceFile, options.symbolsByFile, options.sourceContentByFile);
162
+ if (granularSymbols.length === 0)
163
+ continue;
164
+ const granularNames = [...new Set(granularSymbols.map((s) => s.name))].sort();
165
+ if (granularNames.includes(result.entity.title))
166
+ continue;
167
+ diagnostics.push({
168
+ id: "symbol_granularity_violation",
169
+ severity: "error",
170
+ files: [result.entity.source, result.sourceFile],
171
+ docs: ["docs/symbol-traceability-taxonomy.md"],
172
+ message: `Symbol ${result.entity.id} links ${result.sourceFile} coarsely while granular symbols are available: ${granularNames.join(", ")}`,
173
+ suggestion: "Move ownership/coverage/test relationships to the narrow function/class/type symbol, or add granularity_reason with config-artifact, module-level-behavior, extractor-miss, or legacy-link when the coarse symbol is intentional.",
174
+ });
175
+ }
176
+ return diagnostics;
177
+ }
178
+ function getGranularSymbolsForSourceFile(sourceFile, symbolsByFile, sourceContentByFile) {
179
+ const stagedContent = sourceContentByFile.get(sourceFile);
180
+ if (stagedContent !== undefined) {
181
+ return extractSymbolsFromStagedFile({
182
+ path: sourceFile,
183
+ status: "M",
184
+ hunkRanges: [{ start: 1, end: Number.MAX_SAFE_INTEGER }],
185
+ content: stagedContent,
186
+ });
187
+ }
188
+ const absolutePath = path.isAbsolute(sourceFile)
189
+ ? sourceFile
190
+ : path.resolve(process.cwd(), sourceFile);
191
+ if (!existsSync(absolutePath)) {
192
+ return [];
193
+ }
194
+ return extractSymbolsFromStagedFile({
195
+ path: sourceFile,
196
+ status: "M",
197
+ hunkRanges: [{ start: 1, end: Number.MAX_SAFE_INTEGER }],
198
+ content: readFileSync(absolutePath, "utf8"),
199
+ });
118
200
  }
119
201
  const KIBI_ENTITY_TYPES = new Set([
120
202
  "req",
@@ -317,7 +399,7 @@ export async function checkCommand(options) {
317
399
  console.log("No staged files found.");
318
400
  return { exitCode: 0 };
319
401
  }
320
- const { manifestLookup, manifestResults } = buildManifestLookup(stagedFiles);
402
+ const { manifestLookup, manifestResults, authoredSymbolResults, stagedAuthoredSymbolResults, } = buildManifestLookup(stagedFiles);
321
403
  const symbolsManifestPath = loadConfig(process.cwd()).paths.symbols ?? KIBI_SYMBOLS_MANIFEST_PATH;
322
404
  const sourceFiles = stagedFiles.filter((file) => !file.path.endsWith(".md") && !isStagedManifestPath(file.path));
323
405
  const markdownFiles = stagedFiles.filter((f) => f.path.endsWith(".md"));
@@ -341,8 +423,12 @@ export async function checkCommand(options) {
341
423
  }
342
424
  const allSymbols = [];
343
425
  const symbolsByFile = new Map();
426
+ const sourceContentByFile = new Map();
344
427
  for (const f of sourceFiles) {
345
428
  try {
429
+ if (f.content !== undefined) {
430
+ sourceContentByFile.set(f.path, f.content);
431
+ }
346
432
  const symbols = extractSymbolsFromStagedFile(f, manifestLookup);
347
433
  symbolsByFile.set(f.path, symbols);
348
434
  if (symbols?.length) {
@@ -367,6 +453,16 @@ export async function checkCommand(options) {
367
453
  symbolsManifestPath,
368
454
  });
369
455
  const stagedKibiDiagnostics = collectStagedKibiDiagnostics(stagedKibiEvidence);
456
+ const stagedAuthoredSymbolSet = new Set(stagedAuthoredSymbolResults);
457
+ const stagedSourcePaths = new Set(sourceFiles.map((file) => file.path));
458
+ const activeGranularityResults = authoredSymbolResults.filter((result) => stagedAuthoredSymbolSet.has(result) ||
459
+ (result.sourceFile !== undefined &&
460
+ stagedSourcePaths.has(result.sourceFile)));
461
+ stagedKibiDiagnostics.push(...createSymbolGranularityDiagnostics({
462
+ manifestResults: activeGranularityResults,
463
+ symbolsByFile,
464
+ sourceContentByFile,
465
+ }));
370
466
  if (allSymbols.length === 0 && stagedEntityResults.length === 0) {
371
467
  console.log("No exported symbols or staged entities found in staged files.");
372
468
  return { exitCode: 0 };
@@ -1 +1 @@
1
- {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../src/commands/migrate.ts"],"names":[],"mappings":"AAkCA,UAAU,cAAc;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAsJD,wBAAsB,cAAc,CAClC,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAgH/B"}
1
+ {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../src/commands/migrate.ts"],"names":[],"mappings":"AAqCA,UAAU,cAAc;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AA2VD,wBAAsB,cAAc,CAClC,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAgI/B"}
@@ -17,7 +17,10 @@
17
17
  */
18
18
  import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync, } from "node:fs";
19
19
  import * as path from "node:path";
20
+ import { load as parseYAML } from "js-yaml";
21
+ import { extractSymbolsFromStagedFile } from "../traceability/symbol-extract.js";
20
22
  import { resolveActiveBranch } from "../utils/branch-resolver.js";
23
+ import { DEFAULT_CONFIG } from "../utils/config.js";
21
24
  import { LATEST_KB_SCHEMA_VERSION, getSchemaVersionStatus, normalizeSchemaVersion, } from "../utils/schema-version.js";
22
25
  const MIGRATION_AUDIT_VERSION = 1;
23
26
  function printWarning(message) {
@@ -83,9 +86,12 @@ function loadRawConfigDocument(cwd) {
83
86
  }
84
87
  }
85
88
  function writeJsonAtomically(filePath, value) {
89
+ writeTextAtomically(filePath, `${JSON.stringify(value, null, 2)}\n`);
90
+ }
91
+ function writeTextAtomically(filePath, content) {
86
92
  mkdirSync(path.dirname(filePath), { recursive: true });
87
93
  const tempPath = `${filePath}.tmp-${process.pid}-${Date.now()}`;
88
- writeFileSync(tempPath, `${JSON.stringify(value, null, 2)}\n`, "utf8");
94
+ writeFileSync(tempPath, content, "utf8");
89
95
  renameSync(tempPath, filePath);
90
96
  }
91
97
  function formatSchemaVersion(rawSchemaVersion, normalized) {
@@ -105,10 +111,146 @@ function buildMigrationAuditRecord(args) {
105
111
  fromVersion: args.fromVersion,
106
112
  migratedAt: args.migratedAt,
107
113
  status: "applied",
114
+ symbolGranularityLegacyLinks: args.symbolGranularityLegacyLinks,
108
115
  toVersion: LATEST_KB_SCHEMA_VERSION,
109
116
  warning: args.warning,
110
117
  };
111
118
  }
119
+ const TRACEABILITY_RELATIONSHIP_TYPES = new Set([
120
+ "implements",
121
+ "covered_by",
122
+ "executable_for",
123
+ ]);
124
+ function hasTraceabilityRelationship(symbol) {
125
+ if (Array.isArray(symbol.links) && symbol.links.length > 0) {
126
+ return true;
127
+ }
128
+ if (!Array.isArray(symbol.relationships)) {
129
+ return false;
130
+ }
131
+ return symbol.relationships.some((relationship) => {
132
+ if (relationship === null ||
133
+ typeof relationship !== "object" ||
134
+ Array.isArray(relationship)) {
135
+ return false;
136
+ }
137
+ const type = relationship.type;
138
+ return typeof type === "string" && TRACEABILITY_RELATIONSHIP_TYPES.has(type);
139
+ });
140
+ }
141
+ function getGranularNames(cwd, sourceFile) {
142
+ const absolutePath = path.isAbsolute(sourceFile)
143
+ ? sourceFile
144
+ : path.join(cwd, sourceFile);
145
+ if (!existsSync(absolutePath)) {
146
+ return new Set();
147
+ }
148
+ const symbols = extractSymbolsFromStagedFile({
149
+ path: sourceFile,
150
+ status: "M",
151
+ hunkRanges: [{ start: 1, end: Number.MAX_SAFE_INTEGER }],
152
+ content: readFileSync(absolutePath, "utf8"),
153
+ });
154
+ return new Set(symbols.map((symbol) => symbol.name));
155
+ }
156
+ function addLegacyReasonsToManifestText(content, symbolIds) {
157
+ if (symbolIds.size === 0)
158
+ return content;
159
+ const lines = content.split("\n");
160
+ const output = [];
161
+ let activeId = null;
162
+ let activeHasReason = false;
163
+ let activePropertyIndent = "";
164
+ const flushLegacyReason = () => {
165
+ if (activeId !== null &&
166
+ symbolIds.has(activeId) &&
167
+ !activeHasReason &&
168
+ activePropertyIndent.length > 0) {
169
+ output.push(`${activePropertyIndent}granularity_reason: legacy-link`);
170
+ activeHasReason = true;
171
+ }
172
+ };
173
+ for (const line of lines) {
174
+ const idMatch = line.match(/^(\s*)-\s+id:\s+(.+)\s*$/);
175
+ if (idMatch) {
176
+ flushLegacyReason();
177
+ activeId = idMatch[2]?.trim() ?? null;
178
+ activeHasReason = false;
179
+ activePropertyIndent = `${idMatch[1] ?? ""} `;
180
+ }
181
+ if (activeId !== null && /^\s+granularity_reason:\s+/.test(line)) {
182
+ activeHasReason = true;
183
+ }
184
+ if (activeId !== null &&
185
+ symbolIds.has(activeId) &&
186
+ !activeHasReason &&
187
+ /^\s+status:\s+/.test(line)) {
188
+ const indent = line.match(/^\s*/)?.[0] ?? "";
189
+ output.push(`${indent}granularity_reason: legacy-link`);
190
+ activeHasReason = true;
191
+ }
192
+ output.push(line);
193
+ }
194
+ flushLegacyReason();
195
+ return output.join("\n");
196
+ }
197
+ function migrateSymbolGranularity(options) {
198
+ const configuredSymbolsPath = options.config.paths?.symbols ?? DEFAULT_CONFIG.paths.symbols;
199
+ if (typeof configuredSymbolsPath !== "string") {
200
+ return { count: 0, manifestPath: null };
201
+ }
202
+ const manifestPath = path.isAbsolute(configuredSymbolsPath)
203
+ ? configuredSymbolsPath
204
+ : path.join(options.cwd, configuredSymbolsPath);
205
+ if (!existsSync(manifestPath)) {
206
+ return { count: 0, manifestPath };
207
+ }
208
+ const manifestContent = readFileSync(manifestPath, "utf8");
209
+ const parsed = parseYAML(manifestContent);
210
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
211
+ return { count: 0, manifestPath };
212
+ }
213
+ const manifest = parsed;
214
+ if (!Array.isArray(manifest.symbols)) {
215
+ return { count: 0, manifestPath };
216
+ }
217
+ let count = 0;
218
+ const migratedSymbolIds = new Set();
219
+ const granularNamesByFile = new Map();
220
+ for (const symbol of manifest.symbols) {
221
+ if (symbol === null || typeof symbol !== "object" || Array.isArray(symbol)) {
222
+ continue;
223
+ }
224
+ const record = symbol;
225
+ if (typeof record.sourceFile !== "string")
226
+ continue;
227
+ if (typeof record.title !== "string")
228
+ continue;
229
+ if (typeof record.id !== "string")
230
+ continue;
231
+ if (record.granularity_reason !== undefined)
232
+ continue;
233
+ if (!hasTraceabilityRelationship(record))
234
+ continue;
235
+ let granularNames = granularNamesByFile.get(record.sourceFile);
236
+ if (granularNames === undefined) {
237
+ granularNames = getGranularNames(options.cwd, record.sourceFile);
238
+ granularNamesByFile.set(record.sourceFile, granularNames);
239
+ }
240
+ if (granularNames.size === 0 || granularNames.has(record.title)) {
241
+ continue;
242
+ }
243
+ count += 1;
244
+ if (!options.dryRun) {
245
+ record.granularity_reason = "legacy-link";
246
+ migratedSymbolIds.add(record.id);
247
+ }
248
+ }
249
+ if (count > 0 && !options.dryRun) {
250
+ writeTextAtomically(manifestPath, addLegacyReasonsToManifestText(manifestContent, migratedSymbolIds));
251
+ }
252
+ return { count, manifestPath };
253
+ }
112
254
  // implements REQ-003
113
255
  export async function migrateCommand(options = {}) {
114
256
  const cwd = process.cwd();
@@ -156,9 +298,17 @@ export async function migrateCommand(options = {}) {
156
298
  return { exitCode: 0 };
157
299
  }
158
300
  const fromVersionLabel = formatSchemaVersion(rawSchemaVersion, normalizedVersion);
301
+ const symbolGranularityMigration = migrateSymbolGranularity({
302
+ cwd,
303
+ config,
304
+ dryRun: options.dryRun || !options.yes,
305
+ });
159
306
  if (options.dryRun) {
160
307
  console.log(`dry run: would migrate ${configPathRelative} schemaVersion from ${fromVersionLabel} to ${LATEST_KB_SCHEMA_VERSION}.`);
161
308
  console.log(`dry run: would write migration audit metadata to ${auditPathRelative}.`);
309
+ if (symbolGranularityMigration.count > 0) {
310
+ console.log(`dry run: would mark ${symbolGranularityMigration.count} legacy coarse symbol link(s) in ${toRelativePath(cwd, symbolGranularityMigration.manifestPath ?? "symbols.yaml")}.`);
311
+ }
162
312
  console.log("Re-run with --yes to apply these changes.");
163
313
  return { exitCode: 0 };
164
314
  }
@@ -179,9 +329,13 @@ export async function migrateCommand(options = {}) {
179
329
  configPath: configPathRelative,
180
330
  fromVersion: configStatus.currentVersion,
181
331
  migratedAt,
332
+ symbolGranularityLegacyLinks: symbolGranularityMigration.count,
182
333
  warning: migrationWarning,
183
334
  }));
184
335
  console.log(`Migrated ${configPathRelative} schemaVersion from ${fromVersionLabel} to ${LATEST_KB_SCHEMA_VERSION}.`);
336
+ if (symbolGranularityMigration.count > 0) {
337
+ console.log(`Marked ${symbolGranularityMigration.count} existing coarse symbol link(s) as legacy-link.`);
338
+ }
185
339
  console.log(`Wrote migration audit metadata to ${auditPathRelative}.`);
186
340
  console.log("Migration complete. Future 'kibi migrate' runs will be a no-op.");
187
341
  return { exitCode: 0 };
@@ -11,6 +11,7 @@ export interface ExtractedEntity {
11
11
  priority?: string;
12
12
  severity?: string;
13
13
  text_ref?: string;
14
+ granularity_reason?: string;
14
15
  }
15
16
  export interface ExtractedRelationship {
16
17
  type: string;
@@ -20,7 +21,6 @@ export interface ExtractedRelationship {
20
21
  export interface ExtractionResult {
21
22
  entity: ExtractedEntity;
22
23
  relationships: ExtractedRelationship[];
23
- /** The per-symbol source code file, distinct from the manifest file path. */
24
24
  sourceFile?: string;
25
25
  }
26
26
  export declare class ManifestError extends Error {
@@ -38,6 +38,7 @@ export interface ManifestSymbolRecord {
38
38
  priority?: string;
39
39
  severity?: string;
40
40
  text_ref?: string;
41
+ granularity_reason?: string;
41
42
  created_at?: string;
42
43
  updated_at?: string;
43
44
  links?: Array<string | {
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/extractors/manifest.ts"],"names":[],"mappings":"AA6BA,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,eAAe,CAAC;IACxB,aAAa,EAAE,qBAAqB,EAAE,CAAC;IACvC,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,aAAc,SAAQ,KAAK;IAG7B,QAAQ,EAAE,MAAM;gBADvB,OAAO,EAAE,MAAM,EACR,QAAQ,EAAE,MAAM;CAK1B;AAED,MAAM,WAAW,oBAAoB;IACnC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACzD,aAAa,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAwHD,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,gBAAgB,EAAE,CAmBpB;AAED,wBAAgB,kCAAkC,CAChD,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,oBAAoB,EAAE,CAmBxB;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAKxE;AAsCD,wBAAgB,iCAAiC,CAC/C,YAAY,EAAE,MAAM,EACpB,eAAe,CAAC,EAAE,MAAM,GACvB,oBAAoB,EAAE,CAWxB"}
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/extractors/manifest.ts"],"names":[],"mappings":"AA6BA,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,eAAe,CAAC;IACxB,aAAa,EAAE,qBAAqB,EAAE,CAAC;IACvC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,aAAc,SAAQ,KAAK;IAG7B,QAAQ,EAAE,MAAM;gBADvB,OAAO,EAAE,MAAM,EACR,QAAQ,EAAE,MAAM;CAK1B;AAED,MAAM,WAAW,oBAAoB;IACnC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACzD,aAAa,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AA2HD,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,gBAAgB,EAAE,CAmBpB;AAED,wBAAgB,kCAAkC,CAChD,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,oBAAoB,EAAE,CAmBxB;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAKxE;AAsCD,wBAAgB,iCAAiC,CAC/C,YAAY,EAAE,MAAM,EACpB,eAAe,CAAC,EAAE,MAAM,GACvB,oBAAoB,EAAE,CAWxB"}
@@ -96,6 +96,9 @@ function extractFromManifestSymbolRecords(manifestSymbols, filePath) {
96
96
  ...(symbol.priority !== undefined ? { priority: symbol.priority } : {}),
97
97
  ...(symbol.severity !== undefined ? { severity: symbol.severity } : {}),
98
98
  ...(symbol.text_ref !== undefined ? { text_ref: symbol.text_ref } : {}),
99
+ ...(symbol.granularity_reason !== undefined
100
+ ? { granularity_reason: symbol.granularity_reason }
101
+ : {}),
99
102
  };
100
103
  const sourceFile = symbol.sourceFile ?? symbol.source;
101
104
  return {
@@ -11,6 +11,7 @@ export interface ExtractedEntity {
11
11
  priority?: string;
12
12
  severity?: string;
13
13
  text_ref?: string;
14
+ granularity_reason?: string;
14
15
  verification_scope?: "unit" | "integration" | "end_to_end";
15
16
  verification_perspective?: "internal" | "consumer";
16
17
  fact_kind?: "subject" | "property_value" | "observation" | "meta";
@@ -38,7 +39,6 @@ export interface ExtractedRelationship {
38
39
  export interface ExtractionResult {
39
40
  entity: ExtractedEntity;
40
41
  relationships: ExtractedRelationship[];
41
- /** The per-symbol source code file, distinct from the manifest file path. */
42
42
  sourceFile?: string;
43
43
  }
44
44
  export declare class FrontmatterError extends Error {
@@ -1 +1 @@
1
- {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/extractors/markdown.ts"],"names":[],"mappings":"AAwDA,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kBAAkB,CAAC,EAAE,MAAM,GAAG,aAAa,GAAG,YAAY,CAAC;IAC3D,wBAAwB,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;IAEnD,SAAS,CAAC,EAAE,SAAS,GAAG,gBAAgB,GAAG,aAAa,GAAG,MAAM,CAAC;IAClE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,IAAI,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,CAAC;IACtD,UAAU,CAAC,EAAE,QAAQ,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IAClD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAChC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,eAAe,CAAC;IACxB,aAAa,EAAE,qBAAqB,EAAE,CAAC;IACvC,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AA2BD,qBAAa,gBAAiB,SAAQ,KAAK;IAOhC,QAAQ,EAAE,MAAM;IANlB,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,MAAM,CAAC;gBAG5B,OAAO,EAAE,MAAM,EACR,QAAQ,EAAE,MAAM,EACvB,OAAO,CAAC,EAAE;QACR,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB;IAYM,QAAQ;CAUlB;AA8DD,wBAAgB,sBAAsB,CAEpC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,UAAU,EAAE,MAAM,GACjB,MAAM,EAAE,CAkDV;AAmRD,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,gBAAgB,CAElB;AAGD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CAatE;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CASjE;AASD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAQpE"}
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/extractors/markdown.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"entity.d.ts","sourceRoot":"","sources":["../../../src/public/schemas/entity.ts"],"names":[],"mappings":"AA+EA,QAAA,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAkJzC,CAAC;AAEF,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"entity.d.ts","sourceRoot":"","sources":["../../../src/public/schemas/entity.ts"],"names":[],"mappings":"AA+EA,QAAA,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CA2JzC,CAAC;AAEF,eAAe,YAAY,CAAC"}
@@ -104,6 +104,15 @@ const entitySchema = {
104
104
  links: { type: "array", items: { type: "string" } },
105
105
  text_ref: { type: "string" },
106
106
  sourceFile: { type: "string" },
107
+ granularity_reason: {
108
+ type: "string",
109
+ enum: [
110
+ "config-artifact",
111
+ "module-level-behavior",
112
+ "extractor-miss",
113
+ "legacy-link",
114
+ ],
115
+ },
107
116
  type: {
108
117
  type: "string",
109
118
  enum: [
@@ -39,6 +39,15 @@
39
39
  "links": { "type": "array", "items": { "type": "string" } },
40
40
  "text_ref": { "type": "string" },
41
41
  "sourceFile": { "type": "string" },
42
+ "granularity_reason": {
43
+ "type": "string",
44
+ "enum": [
45
+ "config-artifact",
46
+ "module-level-behavior",
47
+ "extractor-miss",
48
+ "legacy-link"
49
+ ]
50
+ },
42
51
  "verification_scope": {
43
52
  "type": "string",
44
53
  "enum": ["unit", "integration", "end_to_end"]
@@ -1,5 +1,5 @@
1
1
  import { type KibiImpactEvidence } from "./evidence-model.js";
2
- export type KibiImpactDiagnosticId = "kibi_impact_evidence_missing" | "symbols_manifest_stale" | "kibi_impact_override_missing_rationale";
2
+ export type KibiImpactDiagnosticId = "kibi_impact_evidence_missing" | "symbols_manifest_stale" | "symbol_granularity_violation" | "kibi_impact_override_missing_rationale";
3
3
  export interface KibiImpactDiagnostic {
4
4
  /** Stable staged-enforcement diagnostic identifier. */
5
5
  id: KibiImpactDiagnosticId;
@@ -1 +1 @@
1
- {"version":3,"file":"staged-diagnostics.d.ts","sourceRoot":"","sources":["../../src/traceability/staged-diagnostics.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,kBAAkB,EAIxB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,MAAM,sBAAsB,GAC9B,8BAA8B,GAC9B,wBAAwB,GACxB,wCAAwC,CAAC;AAE7C,MAAM,WAAW,oBAAoB;IACnC,uDAAuD;IACvD,EAAE,EAAE,sBAAsB,CAAC;IAC3B,iDAAiD;IACjD,QAAQ,EAAE,OAAO,CAAC;IAClB,iEAAiE;IACjE,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,gDAAgD;IAChD,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,0CAA0C;IAC1C,UAAU,EAAE,MAAM,CAAC;CACpB;AAsDD;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,kBAAkB,GAC3B,oBAAoB,EAAE,CAoCxB"}
1
+ {"version":3,"file":"staged-diagnostics.d.ts","sourceRoot":"","sources":["../../src/traceability/staged-diagnostics.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,kBAAkB,EAIxB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,MAAM,sBAAsB,GAC9B,8BAA8B,GAC9B,wBAAwB,GACxB,8BAA8B,GAC9B,wCAAwC,CAAC;AAE7C,MAAM,WAAW,oBAAoB;IACnC,uDAAuD;IACvD,EAAE,EAAE,sBAAsB,CAAC;IAC3B,iDAAiD;IACjD,QAAQ,EAAE,OAAO,CAAC;IAClB,iEAAiE;IACjE,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,gDAAgD;IAChD,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,0CAA0C;IAC1C,UAAU,EAAE,MAAM,CAAC;CACpB;AAsDD;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,kBAAkB,GAC3B,oBAAoB,EAAE,CAoCxB"}
@@ -6,7 +6,7 @@ type TraceabilityRelationship = {
6
6
  export interface ExtractedSymbol {
7
7
  id: string;
8
8
  name: string;
9
- kind: "function" | "class" | "variable" | "enum" | "unknown";
9
+ kind: "function" | "class" | "interface" | "type" | "variable" | "enum" | "unknown";
10
10
  location: {
11
11
  file: string;
12
12
  startLine: number;
@@ -1 +1 @@
1
- {"version":3,"file":"symbol-extract.d.ts","sourceRoot":"","sources":["../../src/traceability/symbol-extract.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7D,KAAK,wBAAwB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAU7D,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,UAAU,GAAG,OAAO,GAAG,UAAU,GAAG,MAAM,GAAG,SAAS,CAAC;IAC7D,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,aAAa,CAAC,EAAE,wBAAwB,EAAE,CAAC;CAC5C;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,CAAC,EAAE,wBAAwB,EAAE,CAAC;CAC5C;AAED,MAAM,MAAM,cAAc,GAAG,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;AAE9D,wBAAgB,+BAA+B,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAG5E;AAkOD,wBAAgB,4BAA4B,CAE1C,UAAU,EAAE,UAAU,EACtB,cAAc,CAAC,EAAE,cAAc,GAC9B,eAAe,EAAE,CA+JnB"}
1
+ {"version":3,"file":"symbol-extract.d.ts","sourceRoot":"","sources":["../../src/traceability/symbol-extract.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7D,KAAK,wBAAwB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAU7D,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EACA,UAAU,GACV,OAAO,GACP,WAAW,GACX,MAAM,GACN,UAAU,GACV,MAAM,GACN,SAAS,CAAC;IACd,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,aAAa,CAAC,EAAE,wBAAwB,EAAE,CAAC;CAC5C;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,CAAC,EAAE,wBAAwB,EAAE,CAAC;CAC5C;AAED,MAAM,MAAM,cAAc,GAAG,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;AAE9D,wBAAgB,+BAA+B,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAG5E;AAkOD,wBAAgB,4BAA4B,CAE1C,UAAU,EAAE,UAAU,EACtB,cAAc,CAAC,EAAE,cAAc,GAC9B,eAAe,EAAE,CA+MnB"}
@@ -217,7 +217,7 @@ stagedFile, manifestLookup) {
217
217
  results.push(buildSymbolResult(stagedFile, name, "function", span, reqLinks, manifestLookup));
218
218
  }
219
219
  catch {
220
- // skip: individual declaration extraction may fail on malformed AST nodes
220
+ void stagedFile.path;
221
221
  }
222
222
  }
223
223
  // Classes
@@ -236,7 +236,7 @@ stagedFile, manifestLookup) {
236
236
  results.push(buildSymbolResult(stagedFile, name, "class", span, reqLinks, manifestLookup));
237
237
  }
238
238
  catch {
239
- // skip: individual declaration extraction may fail on malformed AST nodes
239
+ void stagedFile.path;
240
240
  }
241
241
  }
242
242
  // Enums
@@ -252,7 +252,37 @@ stagedFile, manifestLookup) {
252
252
  results.push(buildSymbolResult(stagedFile, name, "enum", span, reqLinks, manifestLookup));
253
253
  }
254
254
  catch {
255
- // skip: individual declaration extraction may fail on malformed AST nodes
255
+ void stagedFile.path;
256
+ }
257
+ }
258
+ for (const iface of typeof sf.getInterfaces === "function" ? sf.getInterfaces() : []) {
259
+ if (!iface.isExported())
260
+ continue;
261
+ try {
262
+ const name = iface.getName();
263
+ const start = iface.getNameNode().getStart();
264
+ const end = iface.getEnd();
265
+ const span = getSpan(start, end);
266
+ const reqLinks = parseReqDirectives(iface.getText());
267
+ results.push(buildSymbolResult(stagedFile, name, "interface", span, reqLinks, manifestLookup));
268
+ }
269
+ catch {
270
+ void stagedFile.path;
271
+ }
272
+ }
273
+ for (const alias of typeof sf.getTypeAliases === "function" ? sf.getTypeAliases() : []) {
274
+ if (!alias.isExported())
275
+ continue;
276
+ try {
277
+ const name = alias.getName();
278
+ const start = alias.getNameNode().getStart();
279
+ const end = alias.getEnd();
280
+ const span = getSpan(start, end);
281
+ const reqLinks = parseReqDirectives(alias.getText());
282
+ results.push(buildSymbolResult(stagedFile, name, "type", span, reqLinks, manifestLookup));
283
+ }
284
+ catch {
285
+ void stagedFile.path;
256
286
  }
257
287
  }
258
288
  // Variable statements (exported)
@@ -269,7 +299,7 @@ stagedFile, manifestLookup) {
269
299
  results.push(buildSymbolResult(stagedFile, name, "variable", span, reqLinks, manifestLookup));
270
300
  }
271
301
  catch {
272
- // skip: individual declaration extraction may fail on malformed AST nodes
302
+ void stagedFile.path;
273
303
  }
274
304
  }
275
305
  }
@@ -1 +1 @@
1
- {"version":3,"file":"temp-kb.d.ts","sourceRoot":"","sources":["../../src/traceability/temp-kb.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAGV,gBAAgB,EACjB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,aAAa,CAAC;CACvB;AAMD;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CASvC;AAOD;;;GAGG;AACH,wBAAgB,iBAAiB,CAE/B,OAAO,EAAE,CAAC,IAAI,EAAE;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,KAAK,aAAa,GACpD,IAAI,CAEN;AA4ID,iBAAe,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAgB/D;AAED,OAAO,EAAE,cAAc,EAAE,CAAC;AAG1B,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,gBAAgB,EAAE,GAC1B,OAAO,CAAC,IAAI,CAAC,CAiCf;AAED,wBAAsB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CA6C7E;AAGD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,MAAM,CAkBrE;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA2BlE"}
1
+ {"version":3,"file":"temp-kb.d.ts","sourceRoot":"","sources":["../../src/traceability/temp-kb.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAGV,gBAAgB,EACjB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,aAAa,CAAC;CACvB;AAMD;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CASvC;AAOD;;;GAGG;AACH,wBAAgB,iBAAiB,CAE/B,OAAO,EAAE,CAAC,IAAI,EAAE;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,KAAK,aAAa,GACpD,IAAI,CAEN;AA4ID,iBAAe,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAgB/D;AAED,OAAO,EAAE,cAAc,EAAE,CAAC;AAG1B,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,gBAAgB,EAAE,GAC1B,OAAO,CAAC,IAAI,CAAC,CAwBf;AAED,wBAAsB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CA6C7E;AAGD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,MAAM,CAkBrE;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA2BlE"}
@@ -124,10 +124,10 @@ function buildEntityAssertionGoal(entity) {
124
124
  if (entity.type === "fact") {
125
125
  props.push(...serializeTypedFactFields(entity));
126
126
  }
127
- return `kb_assert_entity(${entity.type}, [${props.join(", ")}])`;
127
+ return `kb_assert_entity_no_audit(${entity.type}, [${props.join(", ")}])`;
128
128
  }
129
129
  function buildRelationshipAssertionGoal(relationship) {
130
- return `kb_assert_relationship(${toPrologAtom(relationship.type)}, ${toPrologAtom(relationship.from)}, ${toPrologAtom(relationship.to)}, [])`;
130
+ return `kb_assert_relationship_no_audit(${toPrologAtom(relationship.type)}, ${toPrologAtom(relationship.from)}, ${toPrologAtom(relationship.to)}, [])`;
131
131
  }
132
132
  function createCleanupHandler(tempDir) {
133
133
  let inProgress = false;
@@ -170,10 +170,6 @@ export { consultOverlay };
170
170
  // implements REQ-014
171
171
  export async function projectStagedEntities(prolog, results) {
172
172
  for (const { entity } of results) {
173
- const retractResult = await prolog.query(`kb_retract_entity(${toPrologAtom(entity.id)})`);
174
- if (!retractResult.success) {
175
- throw new Error(`Failed to retract staged entity ${entity.id}: ${retractResult.error || "unknown error"}`);
176
- }
177
173
  const assertEntityResult = await prolog.query(buildEntityAssertionGoal(entity));
178
174
  if (!assertEntityResult.success) {
179
175
  throw new Error(`Failed to assert staged entity ${entity.id}: ${assertEntityResult.error || "unknown error"}`);
@@ -1,5 +1,5 @@
1
1
  import type { KbConfig } from "./config.js";
2
- export declare const LATEST_KB_SCHEMA_VERSION = 1;
2
+ export declare const LATEST_KB_SCHEMA_VERSION = 2;
3
3
  export interface SchemaVersionStatus {
4
4
  status: "missing" | "invalid" | "older" | "current" | "newer";
5
5
  currentVersion: number | null;
@@ -1,5 +1,5 @@
1
1
  // implements REQ-003
2
- export const LATEST_KB_SCHEMA_VERSION = 1;
2
+ export const LATEST_KB_SCHEMA_VERSION = 2;
3
3
  // implements REQ-003
4
4
  export function normalizeSchemaVersion(schemaVersion) {
5
5
  if (schemaVersion === undefined || schemaVersion === null) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kibi-cli",
3
- "version": "0.12.0",
3
+ "version": "0.12.1",
4
4
  "type": "module",
5
5
  "description": "Kibi CLI for knowledge base management",
6
6
  "engines": {
@@ -11,7 +11,13 @@
11
11
  "bin": {
12
12
  "kibi": "bin/kibi"
13
13
  },
14
- "files": ["dist", "bin", "schema", "src/schemas", "src/public"],
14
+ "files": [
15
+ "dist",
16
+ "bin",
17
+ "schema",
18
+ "src/schemas",
19
+ "src/public"
20
+ ],
15
21
  "scripts": {
16
22
  "build": "tsc -p tsconfig.json && mkdir -p dist/public/skills && cp -r src/public/skills/. dist/public/skills/",
17
23
  "prepack": "npm run build"
@@ -118,6 +118,15 @@ const entitySchema: Record<string, unknown> = {
118
118
  links: { type: "array", items: { type: "string" } },
119
119
  text_ref: { type: "string" },
120
120
  sourceFile: { type: "string" },
121
+ granularity_reason: {
122
+ type: "string",
123
+ enum: [
124
+ "config-artifact",
125
+ "module-level-behavior",
126
+ "extractor-miss",
127
+ "legacy-link",
128
+ ],
129
+ },
121
130
  type: {
122
131
  type: "string",
123
132
  enum: [
@@ -39,6 +39,15 @@
39
39
  "links": { "type": "array", "items": { "type": "string" } },
40
40
  "text_ref": { "type": "string" },
41
41
  "sourceFile": { "type": "string" },
42
+ "granularity_reason": {
43
+ "type": "string",
44
+ "enum": [
45
+ "config-artifact",
46
+ "module-level-behavior",
47
+ "extractor-miss",
48
+ "legacy-link"
49
+ ]
50
+ },
42
51
  "verification_scope": {
43
52
  "type": "string",
44
53
  "enum": ["unit", "integration", "end_to_end"]