kibi-cli 0.2.3 → 0.2.5

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 (95) hide show
  1. package/dist/cli.js +3 -28
  2. package/dist/commands/aggregated-checks.d.ts +4 -1
  3. package/dist/commands/aggregated-checks.d.ts.map +1 -1
  4. package/dist/commands/aggregated-checks.js +13 -3
  5. package/dist/commands/branch.d.ts.map +1 -1
  6. package/dist/commands/branch.js +3 -41
  7. package/dist/commands/check.d.ts.map +1 -1
  8. package/dist/commands/check.js +54 -44
  9. package/dist/commands/doctor.d.ts.map +1 -1
  10. package/dist/commands/doctor.js +0 -27
  11. package/dist/commands/gc.d.ts.map +1 -1
  12. package/dist/commands/gc.js +2 -51
  13. package/dist/commands/init-helpers.d.ts.map +1 -1
  14. package/dist/commands/init-helpers.js +23 -36
  15. package/dist/commands/init.d.ts.map +1 -1
  16. package/dist/commands/init.js +0 -27
  17. package/dist/commands/query.d.ts.map +1 -1
  18. package/dist/commands/query.js +7 -288
  19. package/dist/commands/sync/cache.d.ts +13 -0
  20. package/dist/commands/sync/cache.d.ts.map +1 -0
  21. package/dist/commands/sync/cache.js +76 -0
  22. package/dist/commands/sync/discovery.d.ts +8 -0
  23. package/dist/commands/sync/discovery.d.ts.map +1 -0
  24. package/dist/commands/sync/discovery.js +50 -0
  25. package/dist/commands/sync/extraction.d.ts +11 -0
  26. package/dist/commands/sync/extraction.d.ts.map +1 -0
  27. package/dist/commands/sync/extraction.js +69 -0
  28. package/dist/commands/sync/manifest.d.ts +5 -0
  29. package/dist/commands/sync/manifest.d.ts.map +1 -0
  30. package/dist/commands/sync/manifest.js +118 -0
  31. package/dist/commands/sync/persistence.d.ts +16 -0
  32. package/dist/commands/sync/persistence.d.ts.map +1 -0
  33. package/dist/commands/sync/persistence.js +188 -0
  34. package/dist/commands/sync/staging.d.ts +4 -0
  35. package/dist/commands/sync/staging.d.ts.map +1 -0
  36. package/dist/commands/sync/staging.js +86 -0
  37. package/dist/commands/sync.d.ts +2 -1
  38. package/dist/commands/sync.d.ts.map +1 -1
  39. package/dist/commands/sync.js +69 -501
  40. package/dist/extractors/manifest.d.ts +0 -1
  41. package/dist/extractors/manifest.d.ts.map +1 -1
  42. package/dist/extractors/manifest.js +39 -48
  43. package/dist/extractors/markdown.d.ts +0 -1
  44. package/dist/extractors/markdown.d.ts.map +1 -1
  45. package/dist/extractors/markdown.js +16 -49
  46. package/dist/extractors/relationships.d.ts +39 -0
  47. package/dist/extractors/relationships.d.ts.map +1 -0
  48. package/dist/extractors/relationships.js +137 -0
  49. package/dist/extractors/symbols-coordinator.d.ts.map +1 -1
  50. package/dist/extractors/symbols-coordinator.js +0 -27
  51. package/dist/extractors/symbols-ts.d.ts.map +1 -1
  52. package/dist/extractors/symbols-ts.js +0 -27
  53. package/dist/kb/target-resolver.d.ts +80 -0
  54. package/dist/kb/target-resolver.d.ts.map +1 -0
  55. package/dist/kb/target-resolver.js +313 -0
  56. package/dist/prolog/codec.d.ts +63 -0
  57. package/dist/prolog/codec.d.ts.map +1 -0
  58. package/dist/prolog/codec.js +434 -0
  59. package/dist/prolog.d.ts.map +1 -1
  60. package/dist/prolog.js +0 -27
  61. package/dist/public/extractors/symbols-coordinator.d.ts.map +1 -1
  62. package/dist/public/extractors/symbols-coordinator.js +0 -27
  63. package/dist/public/prolog/index.d.ts.map +1 -1
  64. package/dist/public/prolog/index.js +0 -27
  65. package/dist/public/schemas/entity.d.ts.map +1 -1
  66. package/dist/public/schemas/entity.js +0 -27
  67. package/dist/public/schemas/relationship.d.ts.map +1 -1
  68. package/dist/public/schemas/relationship.js +0 -27
  69. package/dist/query/service.d.ts +35 -0
  70. package/dist/query/service.d.ts.map +1 -0
  71. package/dist/query/service.js +149 -0
  72. package/dist/relationships/shards.d.ts +68 -0
  73. package/dist/relationships/shards.d.ts.map +1 -0
  74. package/dist/relationships/shards.js +263 -0
  75. package/dist/traceability/git-staged.d.ts +4 -1
  76. package/dist/traceability/git-staged.d.ts.map +1 -1
  77. package/dist/traceability/git-staged.js +24 -11
  78. package/dist/types/changeset.d.ts.map +1 -1
  79. package/dist/types/entities.d.ts.map +1 -1
  80. package/dist/types/relationships.d.ts.map +1 -1
  81. package/dist/utils/branch-resolver.d.ts +4 -0
  82. package/dist/utils/branch-resolver.d.ts.map +1 -1
  83. package/dist/utils/branch-resolver.js +4 -0
  84. package/dist/utils/config.d.ts +10 -1
  85. package/dist/utils/config.d.ts.map +1 -1
  86. package/dist/utils/config.js +27 -1
  87. package/dist/utils/rule-registry.d.ts +47 -0
  88. package/dist/utils/rule-registry.d.ts.map +1 -0
  89. package/dist/utils/rule-registry.js +139 -0
  90. package/package.json +5 -1
  91. package/schema/config.json +156 -0
  92. package/src/public/extractors/symbols-coordinator.ts +0 -27
  93. package/src/public/prolog/index.ts +0 -27
  94. package/src/public/schemas/entity.ts +0 -27
  95. package/src/public/schemas/relationship.ts +0 -27
@@ -10,7 +10,6 @@ export interface ExtractedEntity {
10
10
  owner?: string;
11
11
  priority?: string;
12
12
  severity?: string;
13
- links?: unknown[];
14
13
  text_ref?: string;
15
14
  }
16
15
  export interface ExtractedRelationship {
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/extractors/manifest.ts"],"names":[],"mappings":"AAiDA,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,KAAK,CAAC,EAAE,OAAO,EAAE,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;CACxC;AAED,qBAAa,aAAc,SAAQ,KAAK;IAG7B,QAAQ,EAAE,MAAM;gBADvB,OAAO,EAAE,MAAM,EACR,QAAQ,EAAE,MAAM;CAK1B;AA2BD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAqDxE"}
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;CACxC;AAED,qBAAa,aAAc,SAAQ,KAAK;IAG7B,QAAQ,EAAE,MAAM;gBADvB,OAAO,EAAE,MAAM,EACR,QAAQ,EAAE,MAAM;CAK1B;AAsBD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,EAAE,CA4FxE"}
@@ -15,33 +15,6 @@
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
- /*
19
- How to apply this header to source files (examples)
20
-
21
- 1) Prepend header to a single file (POSIX shells):
22
-
23
- cat LICENSE_HEADER.txt "$FILE" > "$FILE".with-header && mv "$FILE".with-header "$FILE"
24
-
25
- 2) Apply to multiple files (example: the project's main entry files):
26
-
27
- for f in packages/cli/bin/kibi packages/mcp/bin/kibi-mcp packages/cli/src/*.ts packages/mcp/src/*.ts; do
28
- if [ -f "$f" ]; then
29
- cp "$f" "$f".bak
30
- (cat LICENSE_HEADER.txt; echo; cat "$f" ) > "$f".new && mv "$f".new "$f"
31
- fi
32
- done
33
-
34
- 3) Avoid duplicating the header: run a quick guard to only add if missing
35
-
36
- for f in packages/cli/bin/kibi packages/mcp/bin/kibi-mcp; do
37
- if [ -f "$f" ]; then
38
- if ! head -n 5 "$f" | grep -q "Copyright (C) 2026 Piotr Franczyk"; then
39
- cp "$f" "$f".bak
40
- (cat LICENSE_HEADER.txt; echo; cat "$f" ) > "$f".new && mv "$f".new "$f"
41
- fi
42
- fi
43
- done
44
- */
45
18
  import { createHash } from "node:crypto";
46
19
  import { readFileSync } from "node:fs";
47
20
  import { load as parseYAML } from "js-yaml";
@@ -65,7 +38,45 @@ export function extractFromManifest(filePath) {
65
38
  throw new ManifestError("Missing required field: title", filePath);
66
39
  }
67
40
  const id = symbol.id || generateId(filePath, symbol.title);
68
- const relationships = extractRelationships(symbol.relationships || symbol.links || [], id);
41
+ const relationships = [];
42
+ // Extract relationships from links field
43
+ // Supports both simple strings (treated as implements) and typed objects
44
+ if (Array.isArray(symbol.links)) {
45
+ for (const link of symbol.links) {
46
+ if (typeof link === "string") {
47
+ relationships.push({
48
+ type: "implements",
49
+ from: id,
50
+ to: link,
51
+ });
52
+ }
53
+ else if (link !== null && typeof link === "object") {
54
+ const typedLink = link;
55
+ if (typeof typedLink.type === "string" &&
56
+ typeof typedLink.target === "string") {
57
+ relationships.push({
58
+ type: typedLink.type,
59
+ from: id,
60
+ to: typedLink.target,
61
+ });
62
+ }
63
+ }
64
+ }
65
+ }
66
+ // Extract relationships from relationships field
67
+ if (Array.isArray(symbol.relationships)) {
68
+ for (const rel of symbol.relationships) {
69
+ if (rel &&
70
+ typeof rel.type === "string" &&
71
+ typeof rel.target === "string") {
72
+ relationships.push({
73
+ type: rel.type,
74
+ from: id,
75
+ to: rel.target,
76
+ });
77
+ }
78
+ }
79
+ }
69
80
  return {
70
81
  entity: {
71
82
  id,
@@ -79,7 +90,6 @@ export function extractFromManifest(filePath) {
79
90
  owner: symbol.owner,
80
91
  priority: symbol.priority,
81
92
  severity: symbol.severity,
82
- links: symbol.links,
83
93
  text_ref: symbol.text_ref,
84
94
  },
85
95
  relationships,
@@ -101,22 +111,3 @@ function generateId(filePath, title) {
101
111
  hash.update(`${filePath}:${title}`);
102
112
  return hash.digest("hex").substring(0, 16);
103
113
  }
104
- function extractRelationships(links, fromId) {
105
- if (!Array.isArray(links))
106
- return [];
107
- return links.map((link) => {
108
- if (typeof link === "string") {
109
- return {
110
- type: "relates_to",
111
- from: fromId,
112
- to: link,
113
- };
114
- }
115
- const linkObj = link;
116
- return {
117
- type: linkObj.type || "relates_to",
118
- from: fromId,
119
- to: linkObj.target || linkObj.id || linkObj.to || "",
120
- };
121
- });
122
- }
@@ -10,7 +10,6 @@ export interface ExtractedEntity {
10
10
  owner?: string;
11
11
  priority?: string;
12
12
  severity?: string;
13
- links?: unknown[];
14
13
  text_ref?: string;
15
14
  }
16
15
  export interface ExtractedRelationship {
@@ -1 +1 @@
1
- {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/extractors/markdown.ts"],"names":[],"mappings":"AAiDA,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,KAAK,CAAC,EAAE,OAAO,EAAE,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;CACxC;AAED,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;IASM,QAAQ;CAUlB;AAED,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,UAAU,EAAE,MAAM,GACjB,MAAM,EAAE,CA8CV;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CAkItE;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CASjE"}
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/extractors/markdown.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;CACxC;AAED,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;IASM,QAAQ;CAUlB;AAED,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,UAAU,EAAE,MAAM,GACjB,MAAM,EAAE,CA8CV;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CAmJtE;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CASjE"}
@@ -15,33 +15,6 @@
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
- /*
19
- How to apply this header to source files (examples)
20
-
21
- 1) Prepend header to a single file (POSIX shells):
22
-
23
- cat LICENSE_HEADER.txt "$FILE" > "$FILE".with-header && mv "$FILE".with-header "$FILE"
24
-
25
- 2) Apply to multiple files (example: the project's main entry files):
26
-
27
- for f in packages/cli/bin/kibi packages/mcp/bin/kibi-mcp packages/cli/src/*.ts packages/mcp/src/*.ts; do
28
- if [ -f "$f" ]; then
29
- cp "$f" "$f".bak
30
- (cat LICENSE_HEADER.txt; echo; cat "$f" ) > "$f".new && mv "$f".new "$f"
31
- fi
32
- done
33
-
34
- 3) Avoid duplicating the header: run a quick guard to only add if missing
35
-
36
- for f in packages/cli/bin/kibi packages/mcp/bin/kibi-mcp; do
37
- if [ -f "$f" ]; then
38
- if ! head -n 5 "$f" | grep -q "Copyright (C) 2026 Piotr Franczyk"; then
39
- cp "$f" "$f".bak
40
- (cat LICENSE_HEADER.txt; echo; cat "$f" ) > "$f".new && mv "$f".new "$f"
41
- fi
42
- fi
43
- done
44
- */
45
18
  import { createHash } from "node:crypto";
46
19
  import { readFileSync } from "node:fs";
47
20
  import matter from "gray-matter";
@@ -145,11 +118,25 @@ export function extractFromMarkdown(filePath) {
145
118
  const entityTypes = embeddedEntities.join(" and ");
146
119
  throw new FrontmatterError(`Invalid embedded entity: requirement contains ${entityTypes} fields`, filePath, {
147
120
  classification: "Embedded Entity Violation",
148
- hint: `Move ${entityTypes} to separate entity files and link them using 'links' with relationship types like 'specified_by' or 'verified_by'.`,
121
+ hint: `Move ${entityTypes} to separate entity files and link them via relationship shards in .kb/relationships/.`,
149
122
  });
150
123
  }
151
124
  const id = data.id || generateId(filePath, data.title);
152
- const relationships = extractRelationships(data.links || [], id);
125
+ const relationships = [];
126
+ if (Array.isArray(data.links)) {
127
+ for (const link of data.links) {
128
+ if (link &&
129
+ typeof link === "object" &&
130
+ typeof link.type === "string" &&
131
+ typeof link.target === "string") {
132
+ relationships.push({
133
+ type: link.type,
134
+ from: id,
135
+ to: link.target,
136
+ });
137
+ }
138
+ }
139
+ }
153
140
  return {
154
141
  entity: {
155
142
  id,
@@ -163,7 +150,6 @@ export function extractFromMarkdown(filePath) {
163
150
  owner: data.owner,
164
151
  priority: data.priority,
165
152
  severity: data.severity,
166
- links: data.links,
167
153
  text_ref: data.text_ref,
168
154
  },
169
155
  relationships,
@@ -229,22 +215,3 @@ function generateId(filePath, title) {
229
215
  hash.update(`${filePath}:${title}`);
230
216
  return hash.digest("hex").substring(0, 16);
231
217
  }
232
- function extractRelationships(links, fromId) {
233
- if (!Array.isArray(links))
234
- return [];
235
- return links.map((link) => {
236
- if (typeof link === "string") {
237
- return {
238
- type: "relates_to",
239
- from: fromId,
240
- to: link,
241
- };
242
- }
243
- const linkObj = link;
244
- return {
245
- type: linkObj.type || "relates_to",
246
- from: fromId,
247
- to: linkObj.target || linkObj.id || linkObj.to || "",
248
- };
249
- });
250
- }
@@ -0,0 +1,39 @@
1
+ export interface ExtractedRelationship {
2
+ type: string;
3
+ from: string;
4
+ to: string;
5
+ metadata?: {
6
+ created_at?: string;
7
+ created_by?: string;
8
+ source?: string;
9
+ confidence?: number;
10
+ };
11
+ }
12
+ export interface ShardExtractionResult {
13
+ shardPath: string;
14
+ relationships: ExtractedRelationship[];
15
+ }
16
+ /**
17
+ * Extracts all relationships from relationship shard files in the given directory.
18
+ *
19
+ * @param relationshipsDir - Path to .kb/relationships directory
20
+ * @returns Array of extraction results, one per shard file
21
+ */
22
+ export declare function extractFromRelationshipShards(relationshipsDir: string): ShardExtractionResult[];
23
+ /**
24
+ * Gets the path to the relationships directory for a given KB root.
25
+ */
26
+ export declare function getRelationshipsDir(kbRoot: string): string;
27
+ /**
28
+ * Flattens multiple shard extraction results into a single array of relationships.
29
+ */
30
+ export declare function flattenRelationships(results: ShardExtractionResult[]): ExtractedRelationship[];
31
+ /**
32
+ * Validates that all relationships reference valid entity IDs.
33
+ * Returns validation errors for dangling references.
34
+ */
35
+ export declare function validateRelationships(relationships: ExtractedRelationship[], validEntityIds: Set<string>): Array<{
36
+ relationship: ExtractedRelationship;
37
+ error: "missing_from" | "missing_to";
38
+ }>;
39
+ //# sourceMappingURL=relationships.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relationships.d.ts","sourceRoot":"","sources":["../../src/extractors/relationships.ts"],"names":[],"mappings":"AAsBA,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,CAAC,EAAE;QACT,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;CACH;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,qBAAqB,EAAE,CAAC;CACxC;AAsBD;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAC3C,gBAAgB,EAAE,MAAM,GACvB,qBAAqB,EAAE,CAyCzB;AA6CD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,qBAAqB,EAAE,GAC/B,qBAAqB,EAAE,CAEzB;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,qBAAqB,EAAE,EACtC,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,GAC1B,KAAK,CAAC;IACP,YAAY,EAAE,qBAAqB,CAAC;IACpC,KAAK,EAAE,cAAc,GAAG,YAAY,CAAC;CACtC,CAAC,CAgBD"}
@@ -0,0 +1,137 @@
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 * as fs from "node:fs";
19
+ import * as path from "node:path";
20
+ import { readShard } from "../relationships/shards.js";
21
+ /**
22
+ * Valid relationship types per the Kibi schema.
23
+ */
24
+ const VALID_RELATIONSHIP_TYPES = new Set([
25
+ "depends_on",
26
+ "specified_by",
27
+ "verified_by",
28
+ "validates",
29
+ "implements",
30
+ "covered_by",
31
+ "constrained_by",
32
+ "constrains",
33
+ "requires_property",
34
+ "guards",
35
+ "publishes",
36
+ "consumes",
37
+ "supersedes",
38
+ "relates_to",
39
+ ]);
40
+ /**
41
+ * Extracts all relationships from relationship shard files in the given directory.
42
+ *
43
+ * @param relationshipsDir - Path to .kb/relationships directory
44
+ * @returns Array of extraction results, one per shard file
45
+ */
46
+ export function extractFromRelationshipShards(relationshipsDir) {
47
+ if (!fs.existsSync(relationshipsDir)) {
48
+ return [];
49
+ }
50
+ const results = [];
51
+ const files = fs.readdirSync(relationshipsDir);
52
+ for (const file of files) {
53
+ if (!file.endsWith(".yaml") && !file.endsWith(".yml")) {
54
+ continue;
55
+ }
56
+ const shardPath = path.join(relationshipsDir, file);
57
+ const stats = fs.statSync(shardPath);
58
+ if (!stats.isFile()) {
59
+ continue;
60
+ }
61
+ try {
62
+ const records = readShard(shardPath);
63
+ const relationships = records
64
+ .map(convertRecordToRelationship)
65
+ .filter((r) => r !== null);
66
+ results.push({
67
+ shardPath,
68
+ relationships,
69
+ });
70
+ }
71
+ catch (error) {
72
+ // Re-throw with shard path context
73
+ throw new Error(`Failed to extract relationships from ${shardPath}: ${error instanceof Error ? error.message : String(error)}`);
74
+ }
75
+ }
76
+ return results;
77
+ }
78
+ /**
79
+ * Converts a RelationshipRecord to an ExtractedRelationship.
80
+ * Returns null if the record is invalid.
81
+ */
82
+ function convertRecordToRelationship(record) {
83
+ // Validate type
84
+ if (!VALID_RELATIONSHIP_TYPES.has(record.type)) {
85
+ throw new Error(`Invalid relationship type "${record.type}" in record ${record.id}`);
86
+ }
87
+ // Validate from/to are not empty
88
+ if (!record.from || !record.to) {
89
+ throw new Error(`Missing from or to in relationship record ${record.id}`);
90
+ }
91
+ const relationship = {
92
+ type: record.type,
93
+ from: record.from,
94
+ to: record.to,
95
+ };
96
+ // Include metadata if present
97
+ if (record.created_at ||
98
+ record.created_by ||
99
+ record.source ||
100
+ record.confidence !== undefined) {
101
+ relationship.metadata = {
102
+ created_at: record.created_at,
103
+ created_by: record.created_by,
104
+ source: record.source,
105
+ confidence: record.confidence,
106
+ };
107
+ }
108
+ return relationship;
109
+ }
110
+ /**
111
+ * Gets the path to the relationships directory for a given KB root.
112
+ */
113
+ export function getRelationshipsDir(kbRoot) {
114
+ return path.join(kbRoot, "relationships");
115
+ }
116
+ /**
117
+ * Flattens multiple shard extraction results into a single array of relationships.
118
+ */
119
+ export function flattenRelationships(results) {
120
+ return results.flatMap((r) => r.relationships);
121
+ }
122
+ /**
123
+ * Validates that all relationships reference valid entity IDs.
124
+ * Returns validation errors for dangling references.
125
+ */
126
+ export function validateRelationships(relationships, validEntityIds) {
127
+ const errors = [];
128
+ for (const rel of relationships) {
129
+ if (!validEntityIds.has(rel.from)) {
130
+ errors.push({ relationship: rel, error: "missing_from" });
131
+ }
132
+ if (!validEntityIds.has(rel.to)) {
133
+ errors.push({ relationship: rel, error: "missing_to" });
134
+ }
135
+ }
136
+ return errors;
137
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"symbols-coordinator.d.ts","sourceRoot":"","sources":["../../src/extractors/symbols-coordinator.ts"],"names":[],"mappings":"AA+CA,OAAO,EACL,KAAK,mBAAmB,EAEzB,MAAM,iBAAiB,CAAC;AAazB,YAAY,EAAE,mBAAmB,EAAE,CAAC;AAEpC,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,mBAAmB,EAAE,EAC9B,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAmChC"}
1
+ {"version":3,"file":"symbols-coordinator.d.ts","sourceRoot":"","sources":["../../src/extractors/symbols-coordinator.ts"],"names":[],"mappings":"AAoBA,OAAO,EACL,KAAK,mBAAmB,EAEzB,MAAM,iBAAiB,CAAC;AAazB,YAAY,EAAE,mBAAmB,EAAE,CAAC;AAEpC,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,mBAAmB,EAAE,EAC9B,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAmChC"}
@@ -15,33 +15,6 @@
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
- /*
19
- How to apply this header to source files (examples)
20
-
21
- 1) Prepend header to a single file (POSIX shells):
22
-
23
- cat LICENSE_HEADER.txt "$FILE" > "$FILE".with-header && mv "$FILE".with-header "$FILE"
24
-
25
- 2) Apply to multiple files (example: the project's main entry files):
26
-
27
- for f in packages/cli/bin/kibi packages/mcp/bin/kibi-mcp packages/cli/src/*.ts packages/mcp/src/*.ts; do
28
- if [ -f "$f" ]; then
29
- cp "$f" "$f".bak
30
- (cat LICENSE_HEADER.txt; echo; cat "$f" ) > "$f".new && mv "$f".new "$f"
31
- fi
32
- done
33
-
34
- 3) Avoid duplicating the header: run a quick guard to only add if missing
35
-
36
- for f in packages/cli/bin/kibi packages/mcp/bin/kibi-mcp; do
37
- if [ -f "$f" ]; then
38
- if ! head -n 5 "$f" | grep -q "Copyright (C) 2026 Piotr Franczyk"; then
39
- cp "$f" "$f".bak
40
- (cat LICENSE_HEADER.txt; echo; cat "$f" ) > "$f".new && mv "$f".new "$f"
41
- fi
42
- fi
43
- done
44
- */
45
18
  import * as fs from "node:fs";
46
19
  import * as path from "node:path";
47
20
  import { enrichSymbolCoordinatesWithTsMorph, } from "./symbols-ts.js";
@@ -1 +1 @@
1
- {"version":3,"file":"symbols-ts.d.ts","sourceRoot":"","sources":["../../src/extractors/symbols-ts.ts"],"names":[],"mappings":"AAuDA,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,sBAAsB,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,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,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAaD,wBAAsB,kCAAkC,CACtD,OAAO,EAAE,mBAAmB,EAAE,EAC9B,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAwDhC"}
1
+ {"version":3,"file":"symbols-ts.d.ts","sourceRoot":"","sources":["../../src/extractors/symbols-ts.ts"],"names":[],"mappings":"AA4BA,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,sBAAsB,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,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,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAaD,wBAAsB,kCAAkC,CACtD,OAAO,EAAE,mBAAmB,EAAE,EAC9B,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAwDhC"}
@@ -15,33 +15,6 @@
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
- /*
19
- How to apply this header to source files (examples)
20
-
21
- 1) Prepend header to a single file (POSIX shells):
22
-
23
- cat LICENSE_HEADER.txt "$FILE" > "$FILE".with-header && mv "$FILE".with-header "$FILE"
24
-
25
- 2) Apply to multiple files (example: the project's main entry files):
26
-
27
- for f in packages/cli/bin/kibi packages/mcp/bin/kibi-mcp packages/cli/src/*.ts packages/mcp/src/*.ts; do
28
- if [ -f "$f" ]; then
29
- cp "$f" "$f".bak
30
- (cat LICENSE_HEADER.txt; echo; cat "$f" ) > "$f".new && mv "$f".new "$f"
31
- fi
32
- done
33
-
34
- 3) Avoid duplicating the header: run a quick guard to only add if missing
35
-
36
- for f in packages/cli/bin/kibi packages/mcp/bin/kibi-mcp; do
37
- if [ -f "$f" ]; then
38
- if ! head -n 5 "$f" | grep -q "Copyright (C) 2026 Piotr Franczyk"; then
39
- cp "$f" "$f".bak
40
- (cat LICENSE_HEADER.txt; echo; cat "$f" ) > "$f".new && mv "$f".new "$f"
41
- fi
42
- fi
43
- done
44
- */
45
18
  import * as fs from "node:fs";
46
19
  import * as path from "node:path";
47
20
  import { Project, } from "ts-morph";
@@ -0,0 +1,80 @@
1
+ export type ResolutionReason = "env" | "kb" | "git" | "cwd";
2
+ export interface WorkspaceInfo {
3
+ root: string;
4
+ reason: ResolutionReason;
5
+ }
6
+ export interface KbTarget {
7
+ workspaceRoot: string;
8
+ branch: string;
9
+ kbPath: string;
10
+ reason: ResolutionReason;
11
+ }
12
+ export type BranchErrorCode = "ENV_OVERRIDE" | "DETACHED_HEAD" | "UNBORN_BRANCH" | "GIT_NOT_AVAILABLE" | "NOT_A_GIT_REPO" | "UNKNOWN_ERROR";
13
+ export interface BranchResolutionSuccess {
14
+ branch: string;
15
+ }
16
+ export interface BranchResolutionError {
17
+ error: string;
18
+ code: BranchErrorCode;
19
+ }
20
+ export type BranchResolutionResult = BranchResolutionSuccess | BranchResolutionError;
21
+ /**
22
+ * Resolve workspace root directory.
23
+ * Priority: env vars > .kb directory > .git directory > cwd
24
+ */
25
+ export declare function resolveWorkspaceRoot(startDir?: string): string;
26
+ /**
27
+ * Resolve workspace root with reason for resolution.
28
+ */
29
+ export declare function resolveWorkspaceRootInfo(startDir?: string): WorkspaceInfo;
30
+ /**
31
+ * Resolve KB path for a given workspace and branch.
32
+ */
33
+ export declare function resolveKbPath(workspaceRoot: string, branch: string): string;
34
+ /**
35
+ * Resolve the active branch according to precedence:
36
+ * 1. KIBI_BRANCH env var (if set)
37
+ * 2. Git active branch (from git branch --show-current)
38
+ * 3. Diagnostic failure (no silent fallback)
39
+ */
40
+ export declare function resolveActiveBranch(workspaceRoot?: string): BranchResolutionResult;
41
+ /**
42
+ * @deprecated defaultBranch is deprecated. Branch lifecycle now follows git naturally.
43
+ * This function is kept for backward compatibility but should not be used for new code.
44
+ *
45
+ * Resolve the default branch using precedence:
46
+ * 1. Configured defaultBranch from config (if set and valid)
47
+ * 2. Git remote HEAD (refs/remotes/origin/HEAD)
48
+ * 3. Fallback to "main"
49
+ */
50
+ export declare function resolveDefaultBranch(cwd?: string, config?: {
51
+ defaultBranch?: string;
52
+ }): {
53
+ branch: string;
54
+ } | {
55
+ error: string;
56
+ code: string;
57
+ };
58
+ /**
59
+ * Resolve complete KB target with all components.
60
+ */
61
+ export declare function resolveKbTarget(options?: {
62
+ workspaceRoot?: string;
63
+ branch?: string;
64
+ config?: {
65
+ defaultBranch?: string;
66
+ };
67
+ }): KbTarget;
68
+ /**
69
+ * Check if repository is in detached HEAD state.
70
+ */
71
+ export declare function isDetachedHead(workspaceRoot?: string): boolean;
72
+ /**
73
+ * Validate a branch name for safety.
74
+ */
75
+ export declare function isValidBranchName(name: string): boolean;
76
+ /**
77
+ * Get a detailed diagnostic message for branch resolution failures.
78
+ */
79
+ export declare function getBranchDiagnostic(branch: string | undefined, error: string): string;
80
+ //# sourceMappingURL=target-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"target-resolver.d.ts","sourceRoot":"","sources":["../../src/kb/target-resolver.ts"],"names":[],"mappings":"AAqBA,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,GAAG,KAAK,CAAC;AAE5D,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,gBAAgB,CAAC;CAC1B;AAED,MAAM,WAAW,QAAQ;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,gBAAgB,CAAC;CAC1B;AAED,MAAM,MAAM,eAAe,GACvB,cAAc,GACd,eAAe,GACf,eAAe,GACf,mBAAmB,GACnB,gBAAgB,GAChB,eAAe,CAAC;AAEpB,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,eAAe,CAAC;CACvB;AAED,MAAM,MAAM,sBAAsB,GAC9B,uBAAuB,GACvB,qBAAqB,CAAC;AAE1B;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,GAAE,MAAsB,GAAG,MAAM,CAiB7E;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,GAAE,MAAsB,GAC/B,aAAa,CAiBf;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAW3E;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,aAAa,GAAE,MAAsB,GACpC,sBAAsB,CA4GxB;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,GAAE,MAAsB,EAC3B,MAAM,CAAC,EAAE;IAAE,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAmCtD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,CAAC,EAAE;IACxC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACrC,GAAG,QAAQ,CAwBX;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,aAAa,GAAE,MAAsB,GAAG,OAAO,CAa7E;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAuBvD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,KAAK,EAAE,MAAM,GACZ,MAAM,CAuBR"}