kibi-cli 0.8.0 → 0.10.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.
Files changed (70) hide show
  1. package/dist/cli.d.ts.map +1 -1
  2. package/dist/cli.js +11 -0
  3. package/dist/commands/check.d.ts.map +1 -1
  4. package/dist/commands/check.js +229 -4
  5. package/dist/commands/init-helpers.d.ts.map +1 -1
  6. package/dist/commands/init-helpers.js +11 -14
  7. package/dist/commands/migrate.d.ts +9 -0
  8. package/dist/commands/migrate.d.ts.map +1 -0
  9. package/dist/commands/migrate.js +183 -0
  10. package/dist/commands/sync/manifest.d.ts +8 -2
  11. package/dist/commands/sync/manifest.d.ts.map +1 -1
  12. package/dist/commands/sync/manifest.js +56 -11
  13. package/dist/commands/sync.d.ts +1 -0
  14. package/dist/commands/sync.d.ts.map +1 -1
  15. package/dist/commands/sync.js +9 -7
  16. package/dist/extractors/manifest.d.ts +30 -0
  17. package/dist/extractors/manifest.d.ts.map +1 -1
  18. package/dist/extractors/manifest.js +60 -7
  19. package/dist/extractors/symbol-coordinates.d.ts +15 -0
  20. package/dist/extractors/symbol-coordinates.d.ts.map +1 -0
  21. package/dist/extractors/symbol-coordinates.js +83 -0
  22. package/dist/public/check-types.d.ts +3 -1
  23. package/dist/public/check-types.d.ts.map +1 -1
  24. package/dist/public/check-types.js +1 -0
  25. package/dist/public/extractors/manifest.d.ts +1 -1
  26. package/dist/public/extractors/manifest.d.ts.map +1 -1
  27. package/dist/public/extractors/manifest.js +1 -1
  28. package/dist/public/ignore-policy.d.ts +10 -0
  29. package/dist/public/ignore-policy.d.ts.map +1 -0
  30. package/dist/public/ignore-policy.js +219 -0
  31. package/dist/public/schema-version.d.ts +3 -0
  32. package/dist/public/schema-version.d.ts.map +1 -0
  33. package/dist/public/schema-version.js +1 -0
  34. package/dist/traceability/evidence-model.d.ts +142 -0
  35. package/dist/traceability/evidence-model.d.ts.map +1 -0
  36. package/dist/traceability/evidence-model.js +70 -0
  37. package/dist/traceability/git-staged.d.ts +1 -0
  38. package/dist/traceability/git-staged.d.ts.map +1 -1
  39. package/dist/traceability/git-staged.js +28 -3
  40. package/dist/traceability/staged-diagnostics.d.ts +25 -0
  41. package/dist/traceability/staged-diagnostics.d.ts.map +1 -0
  42. package/dist/traceability/staged-diagnostics.js +67 -0
  43. package/dist/traceability/staged-impact-contract.d.ts +57 -0
  44. package/dist/traceability/staged-impact-contract.d.ts.map +1 -0
  45. package/dist/traceability/staged-impact-contract.js +202 -0
  46. package/dist/traceability/staged-symbols-manifest.d.ts +23 -0
  47. package/dist/traceability/staged-symbols-manifest.d.ts.map +1 -0
  48. package/dist/traceability/staged-symbols-manifest.js +269 -0
  49. package/dist/traceability/symbol-extract.d.ts.map +1 -1
  50. package/dist/traceability/symbol-extract.js +33 -9
  51. package/dist/utils/config.d.ts +1 -0
  52. package/dist/utils/config.d.ts.map +1 -1
  53. package/dist/utils/config.js +35 -22
  54. package/dist/utils/manifest-paths.d.ts +8 -0
  55. package/dist/utils/manifest-paths.d.ts.map +1 -0
  56. package/dist/utils/manifest-paths.js +62 -0
  57. package/dist/utils/rule-registry.d.ts.map +1 -1
  58. package/dist/utils/rule-registry.js +6 -0
  59. package/dist/utils/schema-version.d.ts +14 -0
  60. package/dist/utils/schema-version.d.ts.map +1 -0
  61. package/dist/utils/schema-version.js +59 -0
  62. package/dist/utils/strict-modeling.d.ts +64 -0
  63. package/dist/utils/strict-modeling.d.ts.map +1 -0
  64. package/dist/utils/strict-modeling.js +371 -0
  65. package/package.json +13 -3
  66. package/schema/config.json +8 -1
  67. package/src/public/check-types.ts +15 -1
  68. package/src/public/extractors/manifest.ts +2 -0
  69. package/src/public/ignore-policy.ts +229 -0
  70. package/src/public/schema-version.ts +6 -0
@@ -14,11 +14,13 @@
14
14
 
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
18
  import { existsSync, readFileSync, writeFileSync } from "node:fs";
19
19
  import * as path from "node:path";
20
20
  import { dump as dumpYAML, load as parseYAML } from "js-yaml";
21
21
  import { enrichSymbolCoordinates, } from "../../extractors/symbols-coordinator.js";
22
+ import { writeCoordinateArtifact } from "../../extractors/symbol-coordinates.js";
23
+ import { resolveSymbolsManifestPaths } from "../../utils/manifest-paths.js";
22
24
  function resolveDeps(overrides) {
23
25
  return {
24
26
  dumpYAML,
@@ -27,6 +29,8 @@ function resolveDeps(overrides) {
27
29
  parseYAML,
28
30
  readFileSync,
29
31
  writeFileSync,
32
+ writeCoordinateArtifact,
33
+ resolveSymbolsManifestPaths,
30
34
  ...overrides,
31
35
  };
32
36
  }
@@ -34,7 +38,7 @@ export const SYMBOLS_MANIFEST_COMMENT_BLOCK = `# symbols.yaml
34
38
  # AUTHORED fields (edit freely):
35
39
  # id, title, sourceFile, links, status, tags, owner, priority
36
40
  # GENERATED fields (never edit manually — overwritten by kibi sync and kb.symbols.refresh):
37
- # sourceLine, sourceColumn, sourceEndLine, sourceEndColumn, coordinatesGeneratedAt
41
+ # sourceLine, sourceColumn, sourceEndLine, sourceEndColumn
38
42
  # Run \`kibi sync\` or call the \`kb.symbols.refresh\` MCP tool to refresh coordinates.
39
43
  `;
40
44
  const SYMBOL_COORD_EXTENSIONS = new Set([
@@ -52,12 +56,12 @@ const GENERATED_COORD_FIELDS = [
52
56
  "sourceColumn",
53
57
  "sourceEndLine",
54
58
  "sourceEndColumn",
55
- "coordinatesGeneratedAt",
56
59
  ];
57
60
  export async function refreshManifestCoordinates(
58
61
  // implements REQ-003
59
62
  manifestPath, workspaceRoot, deps) {
60
63
  const resolved = resolveDeps(deps);
64
+ const shouldRefreshCoordinates = deps?.refreshSymbolCoordinates ?? false;
61
65
  const rawContent = resolved.readFileSync(manifestPath, "utf8");
62
66
  const parsed = resolved.parseYAML(rawContent);
63
67
  if (!isRecord(parsed)) {
@@ -69,11 +73,54 @@ manifestPath, workspaceRoot, deps) {
69
73
  console.warn(`Warning: symbols manifest ${manifestPath} has no symbols array; skipping coordinate refresh`);
70
74
  return;
71
75
  }
72
- const before = rawSymbols.map((entry) => isRecord(entry)
73
- ? { ...entry }
74
- : {});
76
+ const before = rawSymbols.map((entry) => isRecord(entry) ? { ...entry } : {});
75
77
  const enriched = await resolved.enrichSymbolCoordinates(before, workspaceRoot);
76
- parsed.symbols = enriched;
78
+ // Build coordinates map keyed by symbol id
79
+ const coordinatesMap = {};
80
+ for (const entry of enriched) {
81
+ const id = typeof entry?.id === "string" ? entry.id : undefined;
82
+ if (!id)
83
+ continue;
84
+ if (typeof entry.sourceFile === "string" &&
85
+ typeof entry.sourceLine === "number" &&
86
+ typeof entry.sourceColumn === "number" &&
87
+ typeof entry.sourceEndLine === "number" &&
88
+ typeof entry.sourceEndColumn === "number") {
89
+ coordinatesMap[id] = {
90
+ sourceFile: entry.sourceFile,
91
+ sourceLine: entry.sourceLine,
92
+ sourceColumn: entry.sourceColumn,
93
+ sourceEndLine: entry.sourceEndLine,
94
+ sourceEndColumn: entry.sourceEndColumn,
95
+ };
96
+ }
97
+ }
98
+ // Optionally write the coordinate artifact to the coordinates path when explicitly requested
99
+ if (shouldRefreshCoordinates) {
100
+ try {
101
+ const coordinatesPath = resolved.resolveSymbolsManifestPaths(workspaceRoot).coordinatesPath;
102
+ const artifactContent = resolved.writeCoordinateArtifact(coordinatesMap);
103
+ resolved.writeFileSync(coordinatesPath, artifactContent, "utf8");
104
+ }
105
+ catch (err) {
106
+ console.warn(`Warning: Failed to write symbol-coordinates artifact: ${String(err)}`);
107
+ }
108
+ }
109
+ // Strip generated fields from symbols.yaml entries only if original had them
110
+ const strippedEnriched = enriched.map((current, idx) => {
111
+ const prev = before[idx] ?? {};
112
+ const out = { ...current };
113
+ const originalHadGenerated = GENERATED_COORD_FIELDS.some((f) => prev[f] !== undefined);
114
+ if (originalHadGenerated) {
115
+ for (const field of GENERATED_COORD_FIELDS) {
116
+ delete out[field];
117
+ }
118
+ }
119
+ // Ensure we never write coordinatesGeneratedAt
120
+ delete out["coordinatesGeneratedAt"];
121
+ return out;
122
+ });
123
+ parsed.symbols = strippedEnriched;
77
124
  let refreshed = 0;
78
125
  let failed = 0;
79
126
  let unchanged = 0;
@@ -106,7 +153,7 @@ manifestPath, workspaceRoot, deps) {
106
153
  if (rawContent !== nextContent) {
107
154
  resolved.writeFileSync(manifestPath, nextContent, "utf8");
108
155
  }
109
- console.log(`✓ Refreshed symbol coordinates in ${path.relative(workspaceRoot, manifestPath)} (refreshed=${refreshed}, unchanged=${unchanged}, failed=${failed})`);
156
+ console.log(`\u2713 Refreshed symbol coordinates in ${path.relative(workspaceRoot, manifestPath)} (refreshed=${refreshed}, unchanged=${unchanged}, failed=${failed})`);
110
157
  }
111
158
  export function hasAllGeneratedCoordinates(
112
159
  // implements REQ-003
@@ -114,9 +161,7 @@ entry) {
114
161
  return (typeof entry.sourceLine === "number" &&
115
162
  typeof entry.sourceColumn === "number" &&
116
163
  typeof entry.sourceEndLine === "number" &&
117
- typeof entry.sourceEndColumn === "number" &&
118
- typeof entry.coordinatesGeneratedAt === "string" &&
119
- entry.coordinatesGeneratedAt.length > 0);
164
+ typeof entry.sourceEndColumn === "number");
120
165
  }
121
166
  export function isEligibleForCoordinateRefresh(
122
167
  // implements REQ-003
@@ -25,6 +25,7 @@ interface SyncCommandRuntime {
25
25
  export declare function syncCommand(options?: {
26
26
  validateOnly?: boolean;
27
27
  rebuild?: boolean;
28
+ refreshSymbolCoordinates?: boolean;
28
29
  }, runtime?: SyncCommandRuntime): Promise<SyncResult>;
29
30
  export { normalizeMarkdownPath } from "./sync/discovery.js";
30
31
  //# sourceMappingURL=sync.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAc,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAejE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AA4B7C,qBAAa,SAAU,SAAQ,KAAK;gBACtB,OAAO,EAAE,MAAM;CAI5B;AAGD,MAAM,WAAW,UAAW,SAAQ,WAAW;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,yBAAyB;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,UAAU,kBAAkB;IAC1B,WAAW,CAAC,EAAE,CACZ,OAAO,EAAE,yBAAyB,KAC/B,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1B,UAAU,CAAC,EAAE,CACX,OAAO,EAAE,yBAAyB,GAAG;QAAE,UAAU,EAAE,OAAO,CAAA;KAAE,KACzD,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,KAAK,aAAa,CAAC;CAChE;AAGD,wBAAsB,WAAW,CAC/B,OAAO,GAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,EAC3D,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,UAAU,CAAC,CAmbrB;AAED,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAc,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAejE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AA4B7C,qBAAa,SAAU,SAAQ,KAAK;gBACtB,OAAO,EAAE,MAAM;CAI5B;AAGD,MAAM,WAAW,UAAW,SAAQ,WAAW;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,yBAAyB;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,UAAU,kBAAkB;IAC1B,WAAW,CAAC,EAAE,CACZ,OAAO,EAAE,yBAAyB,KAC/B,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1B,UAAU,CAAC,EAAE,CACX,OAAO,EAAE,yBAAyB,GAAG;QAAE,UAAU,EAAE,OAAO,CAAA;KAAE,KACzD,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,KAAK,aAAa,CAAC;CAChE;AAGD,wBAAsB,WAAW,CAC/B,OAAO,GAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,wBAAwB,CAAC,EAAE,OAAO,CAAA;CAAO,EAC/F,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,UAAU,CAAC,CAkbrB;AAED,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -140,13 +140,15 @@ export async function syncCommand(options = {}, runtime = {}) {
140
140
  }
141
141
  }
142
142
  if (!validateOnly) {
143
- for (const file of manifestFiles) {
144
- try {
145
- await refreshManifestCoordinates(file, process.cwd());
146
- }
147
- catch (error) {
148
- const message = error instanceof Error ? error.message : String(error);
149
- console.warn(`Warning: Failed to refresh symbol coordinates in ${file}: ${message}`);
143
+ if (options.refreshSymbolCoordinates) {
144
+ for (const file of manifestFiles) {
145
+ try {
146
+ await refreshManifestCoordinates(file, process.cwd(), { refreshSymbolCoordinates: options.refreshSymbolCoordinates });
147
+ }
148
+ catch (error) {
149
+ const message = error instanceof Error ? error.message : String(error);
150
+ console.warn(`Warning: Failed to refresh symbol coordinates in ${file}: ${message}`);
151
+ }
150
152
  }
151
153
  }
152
154
  }
@@ -27,6 +27,36 @@ export declare class ManifestError extends Error {
27
27
  filePath: string;
28
28
  constructor(message: string, filePath: string);
29
29
  }
30
+ export interface ManifestSymbolRecord {
31
+ id?: string;
32
+ title?: string;
33
+ source?: string;
34
+ sourceFile?: string;
35
+ status?: string;
36
+ tags?: string[];
37
+ owner?: string;
38
+ priority?: string;
39
+ severity?: string;
40
+ text_ref?: string;
41
+ created_at?: string;
42
+ updated_at?: string;
43
+ links?: Array<string | {
44
+ type: string;
45
+ target: string;
46
+ }>;
47
+ relationships?: Array<{
48
+ type: string;
49
+ target: string;
50
+ }>;
51
+ sourceLine?: number;
52
+ sourceColumn?: number;
53
+ sourceEndLine?: number;
54
+ sourceEndColumn?: number;
55
+ coordinatesGeneratedAt?: string;
56
+ [key: string]: unknown;
57
+ }
30
58
  export declare function extractFromManifestString(content: string, filePath: string): ExtractionResult[];
59
+ export declare function extractManifestSymbolRecordsString(content: string, filePath: string): ManifestSymbolRecord[];
31
60
  export declare function extractFromManifest(filePath: string): ExtractionResult[];
61
+ export declare function readManifestWithCoordinateOverlay(manifestPath: string, coordinatesPath?: string): ManifestSymbolRecord[];
32
62
  //# sourceMappingURL=manifest.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/extractors/manifest.ts"],"names":[],"mappings":"AAsBA,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;AA+GD,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,gBAAgB,EAAE,CAmBpB;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAGxE"}
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;AAmHD,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"}
@@ -16,8 +16,11 @@
16
16
  along with this program. If not, see <https://www.gnu.org/licenses/>.
17
17
  */
18
18
  import { createHash } from "node:crypto";
19
- import { readFileSync } from "node:fs";
19
+ import { existsSync, readFileSync } from "node:fs";
20
+ import * as path from "node:path";
20
21
  import { load as parseYAML } from "js-yaml";
22
+ import { DEFAULT_COORDINATES_PATH } from "../utils/manifest-paths.js";
23
+ import { mergeCoordinatesWithManifest, readCoordinateArtifact, } from "./symbol-coordinates.js";
21
24
  export class ManifestError extends Error {
22
25
  filePath;
23
26
  constructor(message, filePath) {
@@ -26,6 +29,12 @@ export class ManifestError extends Error {
26
29
  this.name = "ManifestError";
27
30
  }
28
31
  }
32
+ function getManifestSymbols(manifest, filePath) {
33
+ if (!manifest.symbols || !Array.isArray(manifest.symbols)) {
34
+ throw new ManifestError("No symbols array found in manifest", filePath);
35
+ }
36
+ return manifest.symbols;
37
+ }
29
38
  function extractRelationships(id, symbol) {
30
39
  const relationships = [];
31
40
  if (Array.isArray(symbol.links)) {
@@ -66,10 +75,10 @@ function extractRelationships(id, symbol) {
66
75
  return relationships;
67
76
  }
68
77
  function extractFromParsedManifest(manifest, filePath) {
69
- if (!manifest.symbols || !Array.isArray(manifest.symbols)) {
70
- throw new ManifestError("No symbols array found in manifest", filePath);
71
- }
72
- return manifest.symbols.map((symbol) => {
78
+ return extractFromManifestSymbolRecords(getManifestSymbols(manifest, filePath), filePath);
79
+ }
80
+ function extractFromManifestSymbolRecords(manifestSymbols, filePath) {
81
+ return manifestSymbols.map((symbol) => {
73
82
  if (!symbol.title) {
74
83
  throw new ManifestError("Missing required field: title", filePath);
75
84
  }
@@ -96,6 +105,9 @@ function extractFromParsedManifest(manifest, filePath) {
96
105
  };
97
106
  });
98
107
  }
108
+ function cloneManifestSymbols(manifest, filePath) {
109
+ return getManifestSymbols(manifest, filePath).map((symbol) => ({ ...symbol }));
110
+ }
99
111
  // implements REQ-007
100
112
  export function extractFromManifestString(content, filePath) {
101
113
  try {
@@ -112,9 +124,50 @@ export function extractFromManifestString(content, filePath) {
112
124
  throw error;
113
125
  }
114
126
  }
127
+ export function extractManifestSymbolRecordsString(content, filePath) {
128
+ try {
129
+ const manifest = parseYAML(content);
130
+ return cloneManifestSymbols(manifest, filePath);
131
+ }
132
+ catch (error) {
133
+ if (error instanceof ManifestError) {
134
+ throw error;
135
+ }
136
+ if (error instanceof Error) {
137
+ throw new ManifestError(`Failed to parse manifest: ${error.message}`, filePath);
138
+ }
139
+ throw error;
140
+ }
141
+ }
115
142
  export function extractFromManifest(filePath) {
116
- const content = readFileSync(filePath, "utf8");
117
- return extractFromManifestString(content, filePath);
143
+ return extractFromManifestSymbolRecords(readManifestWithCoordinateOverlay(filePath), filePath);
144
+ }
145
+ function resolveCoordinatesPath(manifestPath, coordinatesPath) {
146
+ if (coordinatesPath) {
147
+ return coordinatesPath;
148
+ }
149
+ return path.join(path.dirname(manifestPath), path.basename(DEFAULT_COORDINATES_PATH));
150
+ }
151
+ function readCoordinateArtifactFromFile(coordinatesPath) {
152
+ if (!existsSync(coordinatesPath)) {
153
+ return null;
154
+ }
155
+ try {
156
+ return readCoordinateArtifact(readFileSync(coordinatesPath, "utf8"));
157
+ }
158
+ catch (error) {
159
+ if (error instanceof Error) {
160
+ throw new ManifestError(`Failed to parse coordinate artifact: ${error.message}`, coordinatesPath);
161
+ }
162
+ throw error;
163
+ }
164
+ }
165
+ // implements REQ-core-extractors
166
+ export function readManifestWithCoordinateOverlay(manifestPath, coordinatesPath) {
167
+ const manifestContent = readFileSync(manifestPath, "utf8");
168
+ const manifestRecords = extractManifestSymbolRecordsString(manifestContent, manifestPath);
169
+ const coordinateArtifact = readCoordinateArtifactFromFile(resolveCoordinatesPath(manifestPath, coordinatesPath));
170
+ return mergeCoordinatesWithManifest(manifestRecords, coordinateArtifact);
118
171
  }
119
172
  function generateId(filePath, title) {
120
173
  const hash = createHash("sha256");
@@ -0,0 +1,15 @@
1
+ import type { ManifestSymbolRecord } from "./manifest.js";
2
+ export interface SymbolCoordinatesRecord {
3
+ sourceFile: string;
4
+ sourceLine: number;
5
+ sourceColumn: number;
6
+ sourceEndLine: number;
7
+ sourceEndColumn: number;
8
+ }
9
+ export interface SymbolCoordinatesArtifact {
10
+ coordinates: Record<string, SymbolCoordinatesRecord>;
11
+ }
12
+ export declare function readCoordinateArtifact(content: string): SymbolCoordinatesArtifact;
13
+ export declare function writeCoordinateArtifact(coordinates: Record<string, SymbolCoordinatesRecord>): string;
14
+ export declare function mergeCoordinatesWithManifest(symbolRecords: ManifestSymbolRecord[], coordinateArtifact: SymbolCoordinatesArtifact | null): ManifestSymbolRecord[];
15
+ //# sourceMappingURL=symbol-coordinates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"symbol-coordinates.d.ts","sourceRoot":"","sources":["../../src/extractors/symbol-coordinates.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAE1D,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,yBAAyB;IACxC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAC;CACtD;AA0DD,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,GACd,yBAAyB,CAkB3B;AAGD,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,uBAAuB,CAAC,GACnD,MAAM,CAUR;AAGD,wBAAgB,4BAA4B,CAC1C,aAAa,EAAE,oBAAoB,EAAE,EACrC,kBAAkB,EAAE,yBAAyB,GAAG,IAAI,GACnD,oBAAoB,EAAE,CAoBxB"}
@@ -0,0 +1,83 @@
1
+ import { dump as dumpYAML, load as parseYAML } from "js-yaml";
2
+ const SYMBOL_COORDINATES_COMMENT_BLOCK = `# symbol-coordinates.yaml
3
+ # GENERATED coordinate artifact — do not edit manually.
4
+ # Run \`kibi sync --refresh-symbol-coordinates\` to refresh.
5
+ `;
6
+ function isRecord(value) {
7
+ return typeof value === "object" && value !== null && !Array.isArray(value);
8
+ }
9
+ function normalizeCoordinateRecord(value) {
10
+ if (!isRecord(value)) {
11
+ return null;
12
+ }
13
+ const { sourceColumn, sourceEndColumn, sourceEndLine, sourceFile, sourceLine } = value;
14
+ if (typeof sourceFile !== "string" ||
15
+ typeof sourceLine !== "number" ||
16
+ typeof sourceColumn !== "number" ||
17
+ typeof sourceEndLine !== "number" ||
18
+ typeof sourceEndColumn !== "number") {
19
+ return null;
20
+ }
21
+ return {
22
+ sourceFile,
23
+ sourceLine,
24
+ sourceColumn,
25
+ sourceEndLine,
26
+ sourceEndColumn,
27
+ };
28
+ }
29
+ function sortCoordinates(coordinates) {
30
+ const sortedCoordinates = {};
31
+ for (const symbolId of Object.keys(coordinates).sort((left, right) => left.localeCompare(right))) {
32
+ const record = normalizeCoordinateRecord(coordinates[symbolId]);
33
+ if (!record) {
34
+ continue;
35
+ }
36
+ sortedCoordinates[symbolId] = record;
37
+ }
38
+ return sortedCoordinates;
39
+ }
40
+ // implements REQ-core-extractors
41
+ export function readCoordinateArtifact(content) {
42
+ const parsed = parseYAML(content);
43
+ if (!isRecord(parsed) || !isRecord(parsed.coordinates)) {
44
+ return { coordinates: {} };
45
+ }
46
+ const coordinates = {};
47
+ for (const [symbolId, record] of Object.entries(parsed.coordinates)) {
48
+ const normalizedRecord = normalizeCoordinateRecord(record);
49
+ if (!normalizedRecord) {
50
+ continue;
51
+ }
52
+ coordinates[symbolId] = normalizedRecord;
53
+ }
54
+ return { coordinates };
55
+ }
56
+ // implements REQ-core-extractors
57
+ export function writeCoordinateArtifact(coordinates) {
58
+ const artifact = {
59
+ coordinates: sortCoordinates(coordinates),
60
+ };
61
+ return `${SYMBOL_COORDINATES_COMMENT_BLOCK}${dumpYAML(artifact, {
62
+ lineWidth: -1,
63
+ noRefs: true,
64
+ sortKeys: true,
65
+ })}`;
66
+ }
67
+ // implements REQ-core-extractors
68
+ export function mergeCoordinatesWithManifest(symbolRecords, coordinateArtifact) {
69
+ const coordinates = coordinateArtifact?.coordinates ?? {};
70
+ return symbolRecords.map((symbolRecord) => {
71
+ const legacyRecord = { ...symbolRecord };
72
+ const symbolId = typeof symbolRecord.id === "string" ? symbolRecord.id : undefined;
73
+ const coordinateRecord = symbolId ? coordinates[symbolId] : undefined;
74
+ if (!coordinateRecord) {
75
+ return legacyRecord;
76
+ }
77
+ const { coordinatesGeneratedAt: _coordinatesGeneratedAt, ...mergedRecord } = legacyRecord;
78
+ return {
79
+ ...mergedRecord,
80
+ ...coordinateRecord,
81
+ };
82
+ });
83
+ }
@@ -1,7 +1,9 @@
1
1
  /**
2
- * Public re-export barrel for shared check types.
2
+ * Public re-export barrel for shared check types and MCP-consumed modeling helpers.
3
3
  * Import from "kibi-cli/public/check-types" in MCP or external consumers.
4
4
  */
5
5
  export type { ChecksConfig, RuleDefinition, SymbolTraceabilityOptions, Violation, } from "../utils/rule-registry.js";
6
+ export type { SemanticClaim, StableRequirementIds, StrictModelInput, StrictWriteSet, } from "../utils/strict-modeling.js";
6
7
  export { DEFAULT_CHECKS_CONFIG, RULE_NAMES, RULES, getEffectiveRules, mergeChecksConfig, validateRuleName, } from "../utils/rule-registry.js";
8
+ export { buildStableRequirementIds, buildStrictWriteSet, modelRequirementClaims, normalizePropertyKey, normalizeSubjectKey, } from "../utils/strict-modeling.js";
7
9
  //# sourceMappingURL=check-types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"check-types.d.ts","sourceRoot":"","sources":["../../src/public/check-types.ts"],"names":[],"mappings":"AAkBA;;;GAGG;AACH,YAAY,EACV,YAAY,EACZ,cAAc,EACd,yBAAyB,EACzB,SAAS,GACV,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,qBAAqB,EACrB,UAAU,EACV,KAAK,EACL,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,2BAA2B,CAAC"}
1
+ {"version":3,"file":"check-types.d.ts","sourceRoot":"","sources":["../../src/public/check-types.ts"],"names":[],"mappings":"AAkBA;;;GAGG;AACH,YAAY,EACV,YAAY,EACZ,cAAc,EACd,yBAAyB,EACzB,SAAS,GACV,MAAM,2BAA2B,CAAC;AACnC,YAAY,EACV,aAAa,EACb,oBAAoB,EACpB,gBAAgB,EAChB,cAAc,GACf,MAAM,6BAA6B,CAAC;AAErC,OAAO,EACL,qBAAqB,EACrB,UAAU,EACV,KAAK,EACL,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,yBAAyB,EACzB,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,6BAA6B,CAAC"}
@@ -16,3 +16,4 @@
16
16
  along with this program. If not, see <https://www.gnu.org/licenses/>.
17
17
  */
18
18
  export { DEFAULT_CHECKS_CONFIG, RULE_NAMES, RULES, getEffectiveRules, mergeChecksConfig, validateRuleName, } from "../utils/rule-registry.js";
19
+ export { buildStableRequirementIds, buildStrictWriteSet, modelRequirementClaims, normalizePropertyKey, normalizeSubjectKey, } from "../utils/strict-modeling.js";
@@ -1,2 +1,2 @@
1
- export { extractFromManifest, extractFromManifestString, type ExtractionResult, type ManifestError, } from "../../extractors/manifest.js";
1
+ export { extractFromManifest, extractFromManifestString, readManifestWithCoordinateOverlay, type ExtractionResult, type ManifestError, type ManifestSymbolRecord, } from "../../extractors/manifest.js";
2
2
  //# sourceMappingURL=manifest.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../../src/public/extractors/manifest.ts"],"names":[],"mappings":"AAkBA,OAAO,EACL,mBAAmB,EACnB,yBAAyB,EACzB,KAAK,gBAAgB,EACrB,KAAK,aAAa,GACnB,MAAM,8BAA8B,CAAC"}
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../../src/public/extractors/manifest.ts"],"names":[],"mappings":"AAkBA,OAAO,EACL,mBAAmB,EACnB,yBAAyB,EACzB,iCAAiC,EACjC,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,KAAK,oBAAoB,GAC1B,MAAM,8BAA8B,CAAC"}
@@ -15,4 +15,4 @@
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
- export { extractFromManifest, extractFromManifestString, } from "../../extractors/manifest.js";
18
+ export { extractFromManifest, extractFromManifestString, readManifestWithCoordinateOverlay, } from "../../extractors/manifest.js";
@@ -0,0 +1,10 @@
1
+ export interface IgnorePolicy {
2
+ isIgnored(inputPath: string): boolean;
3
+ getFastGlobIgnoreGlobs(): string[];
4
+ explain(inputPath: string): {
5
+ ignored: boolean;
6
+ reason?: string;
7
+ };
8
+ }
9
+ export declare function createRepoIgnorePolicy(workspaceRoot: string): IgnorePolicy;
10
+ //# sourceMappingURL=ignore-policy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ignore-policy.d.ts","sourceRoot":"","sources":["../../src/public/ignore-policy.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,YAAY;IAC3B,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IACtC,sBAAsB,IAAI,MAAM,EAAE,CAAC;IACnC,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACnE;AAoBD,wBAAgB,sBAAsB,CAAC,aAAa,EAAE,MAAM,GAAG,YAAY,CA8L1E"}