kibi-cli 0.2.3 → 0.2.6

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 (96) 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 +55 -45
  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 +41 -49
  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 +28 -50
  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 +10 -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 +6 -2
  91. package/schema/config.json +161 -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 +10 -27
  95. package/src/public/schemas/relationship.ts +0 -27
  96. package/src/schemas/entity.schema.json +11 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/query/service.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAQlD,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACzC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,kBAAkB,UAS9B,CAAC;AAEF;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAqClE;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,WAAW,CAAC,CAmCtB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAExD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,YAAY,GACpB,MAAM,CAkBR"}
@@ -0,0 +1,149 @@
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
+ import { escapeAtom, parseEntityFromBinding, parseEntityFromList, parseListOfLists, } from "../prolog/codec.js";
11
+ export const VALID_ENTITY_TYPES = [
12
+ "req",
13
+ "scenario",
14
+ "test",
15
+ "adr",
16
+ "flag",
17
+ "event",
18
+ "symbol",
19
+ "fact",
20
+ ];
21
+ /**
22
+ * Build a Prolog query goal from filters.
23
+ */
24
+ export function buildEntityQueryGoal(filters) {
25
+ const { type, id, sourceFile, tags } = filters;
26
+ if (sourceFile) {
27
+ const safeSource = escapeAtom(sourceFile);
28
+ if (type) {
29
+ const safeType = escapeAtom(type);
30
+ return `findall([Id,'${safeType}',Props], (kb_entities_by_source('${safeSource}', SourceIds), member(Id, SourceIds), kb_entity(Id, '${safeType}', Props)), Results)`;
31
+ }
32
+ return `findall([Id,Type,Props], (kb_entities_by_source('${safeSource}', SourceIds), member(Id, SourceIds), kb_entity(Id, Type, Props)), Results)`;
33
+ }
34
+ if (id && type) {
35
+ const safeId = escapeAtom(id);
36
+ const safeType = escapeAtom(type);
37
+ return `findall(['${safeId}','${safeType}',Props], kb_entity('${safeId}', '${safeType}', Props), Results)`;
38
+ }
39
+ if (id) {
40
+ const safeId = escapeAtom(id);
41
+ return `findall(['${safeId}',Type,Props], kb_entity('${safeId}', Type, Props), Results)`;
42
+ }
43
+ if (tags && tags.length > 0) {
44
+ if (type) {
45
+ const safeType = escapeAtom(type);
46
+ return `findall([Id,'${safeType}',Props], kb_entity(Id, '${safeType}', Props), Results)`;
47
+ }
48
+ return "findall([Id,Type,Props], kb_entity(Id, Type, Props), Results)";
49
+ }
50
+ if (type) {
51
+ const safeType = escapeAtom(type);
52
+ return `findall([Id,'${safeType}',Props], kb_entity(Id, '${safeType}', Props), Results)`;
53
+ }
54
+ return "findall([Id,Type,Props], kb_entity(Id, Type, Props), Results)";
55
+ }
56
+ /**
57
+ * Execute a filtered entity query against the KB.
58
+ */
59
+ export async function queryEntities(prolog, filters) {
60
+ const { tags, limit = 100, offset = 0 } = filters;
61
+ const goal = buildEntityQueryGoal(filters);
62
+ const queryResult = await prolog.query(goal);
63
+ let entities = [];
64
+ if (queryResult.success) {
65
+ if (queryResult.bindings.Results) {
66
+ const entitiesData = parseListOfLists(queryResult.bindings.Results);
67
+ for (const data of entitiesData) {
68
+ const entity = parseEntityFromList(data);
69
+ entities.push(entity);
70
+ }
71
+ }
72
+ else if (queryResult.bindings.Result) {
73
+ const entity = parseEntityFromBinding(queryResult.bindings.Result);
74
+ entities = [entity];
75
+ }
76
+ }
77
+ else {
78
+ throw new Error(queryResult.error || "Query failed with unknown error");
79
+ }
80
+ // Apply tag filtering client-side if specified
81
+ if (tags && tags.length > 0) {
82
+ entities = dedupeEntities(entities.filter((entity) => hasAnyTag(entity, tags)));
83
+ }
84
+ const totalCount = entities.length;
85
+ const paginated = entities.slice(offset, offset + limit);
86
+ return { entities: paginated, totalCount };
87
+ }
88
+ /**
89
+ * Validate entity type.
90
+ */
91
+ export function validateEntityType(type) {
92
+ return VALID_ENTITY_TYPES.includes(type);
93
+ }
94
+ /**
95
+ * Get validation error message for invalid type.
96
+ */
97
+ export function getInvalidTypeError(type) {
98
+ return `Invalid type '${type}'. Valid types: ${VALID_ENTITY_TYPES.join(", ")}. Use a single type value, or omit this parameter to query all entities.`;
99
+ }
100
+ /**
101
+ * Build human-readable summary text for query results.
102
+ */
103
+ export function buildQuerySummaryText(result, filters) {
104
+ const { entities, totalCount } = result;
105
+ const { type, offset, limit } = filters;
106
+ if (totalCount === 0) {
107
+ return `No entities found${type ? ` of type '${type}'` : ""}.`;
108
+ }
109
+ const details = entities
110
+ .map((e) => {
111
+ const id = String(e.id || "").replace(/^file:\/\/.*\//, "");
112
+ const title = String(e.title || "");
113
+ const status = String(e.status || "");
114
+ return `${id} (${title}, status=${status})`;
115
+ })
116
+ .join(", ");
117
+ return `Found ${totalCount} entities${type ? ` of type '${type}'` : ""}. Showing ${entities.length} (offset ${offset}, limit ${limit}): ${details}`;
118
+ }
119
+ function hasAnyTag(entity, requestedTags) {
120
+ const expected = new Set(requestedTags.map(normalizeTagValue));
121
+ const rawTags = entity.tags;
122
+ if (!Array.isArray(rawTags) || rawTags.length === 0) {
123
+ return false;
124
+ }
125
+ for (const tag of rawTags) {
126
+ if (expected.has(normalizeTagValue(tag))) {
127
+ return true;
128
+ }
129
+ }
130
+ return false;
131
+ }
132
+ function normalizeTagValue(tag) {
133
+ return String(tag).trim();
134
+ }
135
+ function dedupeEntities(entities) {
136
+ const seen = new Set();
137
+ const deduped = [];
138
+ for (const entity of entities) {
139
+ const id = String(entity.id ?? "");
140
+ const type = String(entity.type ?? "");
141
+ const key = `${type}::${id}`;
142
+ if (seen.has(key)) {
143
+ continue;
144
+ }
145
+ seen.add(key);
146
+ deduped.push(entity);
147
+ }
148
+ return deduped;
149
+ }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Represents a relationship record stored in shard files.
3
+ */
4
+ export interface RelationshipRecord {
5
+ id: string;
6
+ type: string;
7
+ from: string;
8
+ to: string;
9
+ created_at: string;
10
+ created_by: string;
11
+ source: string;
12
+ confidence?: number;
13
+ }
14
+ /**
15
+ * Gets the path to the relationships directory for a given KB root.
16
+ */
17
+ export declare function getRelationshipsDir(kbRoot: string): string;
18
+ /**
19
+ * Computes the shard name (first 2 chars of SHA256) for a given entity ID.
20
+ */
21
+ export declare function shardForFromId(fromId: string): string;
22
+ /**
23
+ * Computes the shard path for a given entity ID.
24
+ * Uses first 2 chars of SHA256(entityId) as shard name.
25
+ */
26
+ export declare function computeShardPath(kbRoot: string, entityId: string): string;
27
+ /**
28
+ * Reads a relationship shard file.
29
+ * Returns empty array if file doesn't exist.
30
+ * Throws on parse errors.
31
+ */
32
+ export declare function readShard(shardPath: string): RelationshipRecord[];
33
+ /**
34
+ * Writes a relationship shard file.
35
+ * Creates parent directories if needed.
36
+ */
37
+ export declare function writeShard(shardPath: string, records: RelationshipRecord[]): void;
38
+ /**
39
+ * Appends a relationship to the appropriate shard.
40
+ * Returns the shard path and record ID.
41
+ */
42
+ export declare function appendRelationship(kbRoot: string, relationship: Omit<RelationshipRecord, "id">): {
43
+ shardPath: string;
44
+ recordId: string;
45
+ };
46
+ /**
47
+ * Lists all shard files in the relationships directory.
48
+ */
49
+ export declare function listShards(kbRoot: string): string[];
50
+ /**
51
+ * Reads all relationships from all shards.
52
+ */
53
+ export declare function readAllShards(kbRoot: string): RelationshipRecord[];
54
+ /**
55
+ * Removes dangling relationships that reference non-existent entities.
56
+ */
57
+ export declare function pruneDangling(records: RelationshipRecord[], validEntityIds: Set<string>): RelationshipRecord[];
58
+ /**
59
+ * Generates a deterministic relationship ID.
60
+ */
61
+ export declare function relationshipIdFor(type: string, from: string, to: string): string;
62
+ /**
63
+ * Merges existing and incoming relationship records.
64
+ * Deduplicates by (type, from, to) tuple.
65
+ * On conflict, keeps the record with newer created_at timestamp.
66
+ */
67
+ export declare function mergeRecords(existing: RelationshipRecord[], incoming: RelationshipRecord[]): RelationshipRecord[];
68
+ //# sourceMappingURL=shards.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shards.d.ts","sourceRoot":"","sources":["../../src/relationships/shards.ts"],"names":[],"mappings":"AAuBA;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAGrD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGzE;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,kBAAkB,EAAE,CAqFjE;AAED;;;GAGG;AACH,wBAAgB,UAAU,CACxB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,kBAAkB,EAAE,GAC5B,IAAI,CAoBN;AAqCD;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,IAAI,CAAC,kBAAkB,EAAE,IAAI,CAAC,GAC3C;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CA4BzC;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAUnD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,kBAAkB,EAAE,CAUlE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,kBAAkB,EAAE,EAC7B,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,GAC1B,kBAAkB,EAAE,CAKtB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,GACT,MAAM,CAMR;AAID;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,kBAAkB,EAAE,EAC9B,QAAQ,EAAE,kBAAkB,EAAE,GAC7B,kBAAkB,EAAE,CAgCtB"}
@@ -0,0 +1,263 @@
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 crypto from "node:crypto";
19
+ import * as fs from "node:fs";
20
+ import * as path from "node:path";
21
+ import { load as parseYAML } from "js-yaml";
22
+ /**
23
+ * Gets the path to the relationships directory for a given KB root.
24
+ */
25
+ export function getRelationshipsDir(kbRoot) {
26
+ return path.join(kbRoot, "relationships");
27
+ }
28
+ /**
29
+ * Computes the shard name (first 2 chars of SHA256) for a given entity ID.
30
+ */
31
+ export function shardForFromId(fromId) {
32
+ const hash = crypto.createHash("sha256").update(fromId).digest("hex");
33
+ return hash.slice(0, 2);
34
+ }
35
+ /**
36
+ * Computes the shard path for a given entity ID.
37
+ * Uses first 2 chars of SHA256(entityId) as shard name.
38
+ */
39
+ export function computeShardPath(kbRoot, entityId) {
40
+ const shardName = shardForFromId(entityId);
41
+ return path.join(getRelationshipsDir(kbRoot), `${shardName}.yaml`);
42
+ }
43
+ /**
44
+ * Reads a relationship shard file.
45
+ * Returns empty array if file doesn't exist.
46
+ * Throws on parse errors.
47
+ */
48
+ export function readShard(shardPath) {
49
+ if (!fs.existsSync(shardPath)) {
50
+ return [];
51
+ }
52
+ const content = fs.readFileSync(shardPath, "utf8");
53
+ if (!content.trim()) {
54
+ return [];
55
+ }
56
+ const parsed = parseYAML(content);
57
+ if (!parsed || !Array.isArray(parsed.relationships)) {
58
+ throw new Error(`Invalid shard file: missing 'relationships' array at ${shardPath}`);
59
+ }
60
+ return parsed.relationships.map((record, index) => {
61
+ if (typeof record !== "object" || record === null) {
62
+ throw new Error(`Invalid record at ${shardPath}[${index}]: expected object`);
63
+ }
64
+ const rec = record;
65
+ // Validate required fields
66
+ if (typeof rec.id !== "string" || !rec.id) {
67
+ throw new Error(`Missing or invalid 'id' at ${shardPath}[${index}]`);
68
+ }
69
+ if (typeof rec.type !== "string" || !rec.type) {
70
+ throw new Error(`Missing or invalid 'type' at ${shardPath}[${index}]`);
71
+ }
72
+ if (typeof rec.from !== "string" || !rec.from) {
73
+ throw new Error(`Missing or invalid 'from' at ${shardPath}[${index}]`);
74
+ }
75
+ if (typeof rec.to !== "string" || !rec.to) {
76
+ throw new Error(`Missing or invalid 'to' at ${shardPath}[${index}]`);
77
+ }
78
+ // Handle created_at - YAML may auto-convert ISO dates to Date objects
79
+ let createdAt;
80
+ if (rec.created_at instanceof Date) {
81
+ createdAt = rec.created_at.toISOString().replace(/\.000Z$/, 'Z');
82
+ }
83
+ else if (typeof rec.created_at === "string" && rec.created_at) {
84
+ createdAt = rec.created_at;
85
+ }
86
+ else {
87
+ throw new Error(`Missing or invalid 'created_at' at ${shardPath}[${index}]`);
88
+ }
89
+ if (typeof rec.created_by !== "string" || !rec.created_by) {
90
+ throw new Error(`Missing or invalid 'created_by' at ${shardPath}[${index}]`);
91
+ }
92
+ if (typeof rec.source !== "string" || !rec.source) {
93
+ throw new Error(`Missing or invalid 'source' at ${shardPath}[${index}]`);
94
+ }
95
+ const result = {
96
+ id: rec.id,
97
+ type: rec.type,
98
+ from: rec.from,
99
+ to: rec.to,
100
+ created_at: createdAt,
101
+ created_by: rec.created_by,
102
+ source: rec.source,
103
+ };
104
+ if (rec.confidence !== undefined) {
105
+ if (typeof rec.confidence !== "number") {
106
+ throw new Error(`Invalid 'confidence' at ${shardPath}[${index}]: expected number`);
107
+ }
108
+ result.confidence = rec.confidence;
109
+ }
110
+ return result;
111
+ });
112
+ }
113
+ /**
114
+ * Writes a relationship shard file.
115
+ * Creates parent directories if needed.
116
+ */
117
+ export function writeShard(shardPath, records) {
118
+ const dir = path.dirname(shardPath);
119
+ if (!fs.existsSync(dir)) {
120
+ fs.mkdirSync(dir, { recursive: true });
121
+ }
122
+ // Sort and dedupe records
123
+ const sorted = sortRecords(records);
124
+ const seen = new Set();
125
+ const unique = [];
126
+ for (const record of sorted) {
127
+ const key = `${record.type}|${record.from}|${record.to}`;
128
+ if (seen.has(key))
129
+ continue;
130
+ seen.add(key);
131
+ unique.push(record);
132
+ }
133
+ const yamlContent = serializeToYAML(unique);
134
+ fs.writeFileSync(shardPath, yamlContent, "utf8");
135
+ }
136
+ /**
137
+ * Serializes records to YAML format.
138
+ */
139
+ function serializeToYAML(records) {
140
+ const lines = ["relationships:"];
141
+ for (const record of records) {
142
+ lines.push(` - id: ${record.id}`);
143
+ lines.push(` type: ${record.type}`);
144
+ lines.push(` from: ${record.from}`);
145
+ lines.push(` to: ${record.to}`);
146
+ lines.push(` created_at: "${record.created_at}"`);
147
+ lines.push(` created_by: ${record.created_by}`);
148
+ lines.push(` source: ${record.source}`);
149
+ if (record.confidence !== undefined) {
150
+ lines.push(` confidence: ${record.confidence}`);
151
+ }
152
+ }
153
+ return lines.join("\n") + "\n";
154
+ }
155
+ /**
156
+ * Sorts records deterministically by from, then type, then to.
157
+ */
158
+ function sortRecords(records) {
159
+ return [...records].sort((a, b) => {
160
+ const fromCompare = a.from.localeCompare(b.from);
161
+ if (fromCompare !== 0)
162
+ return fromCompare;
163
+ const typeCompare = a.type.localeCompare(b.type);
164
+ if (typeCompare !== 0)
165
+ return typeCompare;
166
+ return a.to.localeCompare(b.to);
167
+ });
168
+ }
169
+ /**
170
+ * Appends a relationship to the appropriate shard.
171
+ * Returns the shard path and record ID.
172
+ */
173
+ export function appendRelationship(kbRoot, relationship) {
174
+ const shardPath = computeShardPath(kbRoot, relationship.from);
175
+ const existing = readShard(shardPath);
176
+ // Generate deterministic ID
177
+ const recordId = relationshipIdFor(relationship.type, relationship.from, relationship.to);
178
+ // Check if relationship already exists
179
+ const exists = existing.some((r) => r.type === relationship.type &&
180
+ r.from === relationship.from &&
181
+ r.to === relationship.to);
182
+ if (!exists) {
183
+ const newRecord = {
184
+ ...relationship,
185
+ id: recordId,
186
+ };
187
+ writeShard(shardPath, [...existing, newRecord]);
188
+ }
189
+ return { shardPath, recordId };
190
+ }
191
+ /**
192
+ * Lists all shard files in the relationships directory.
193
+ */
194
+ export function listShards(kbRoot) {
195
+ const relationshipsDir = getRelationshipsDir(kbRoot);
196
+ if (!fs.existsSync(relationshipsDir)) {
197
+ return [];
198
+ }
199
+ return fs
200
+ .readdirSync(relationshipsDir)
201
+ .filter((f) => f.endsWith(".yaml"))
202
+ .map((f) => path.join(relationshipsDir, f));
203
+ }
204
+ /**
205
+ * Reads all relationships from all shards.
206
+ */
207
+ export function readAllShards(kbRoot) {
208
+ const shards = listShards(kbRoot);
209
+ const allRecords = [];
210
+ for (const shardPath of shards) {
211
+ const records = readShard(shardPath);
212
+ allRecords.push(...records);
213
+ }
214
+ return allRecords;
215
+ }
216
+ /**
217
+ * Removes dangling relationships that reference non-existent entities.
218
+ */
219
+ export function pruneDangling(records, validEntityIds) {
220
+ return records.filter((record) => validEntityIds.has(record.from) && validEntityIds.has(record.to));
221
+ }
222
+ /**
223
+ * Generates a deterministic relationship ID.
224
+ */
225
+ export function relationshipIdFor(type, from, to) {
226
+ const hash = crypto
227
+ .createHash("sha256")
228
+ .update(`${type}|${from}|${to}`)
229
+ .digest("hex");
230
+ return `rel-${hash.slice(0, 12)}`;
231
+ }
232
+ /**
233
+ * Merges existing and incoming relationship records.
234
+ * Deduplicates by (type, from, to) tuple.
235
+ * On conflict, keeps the record with newer created_at timestamp.
236
+ */
237
+ export function mergeRecords(existing, incoming) {
238
+ const recordMap = new Map();
239
+ // Helper to create key from record
240
+ const makeKey = (r) => `${r.type}|${r.from}|${r.to}`;
241
+ // Add existing records
242
+ for (const record of existing) {
243
+ recordMap.set(makeKey(record), record);
244
+ }
245
+ // Merge incoming records
246
+ for (const record of incoming) {
247
+ const key = makeKey(record);
248
+ const existingRecord = recordMap.get(key);
249
+ if (!existingRecord) {
250
+ // New record
251
+ recordMap.set(key, record);
252
+ }
253
+ else {
254
+ // Conflict - keep newer based on created_at
255
+ const existingTime = new Date(existingRecord.created_at).getTime();
256
+ const incomingTime = new Date(record.created_at).getTime();
257
+ if (incomingTime >= existingTime) {
258
+ recordMap.set(key, record);
259
+ }
260
+ }
261
+ }
262
+ return Array.from(recordMap.values());
263
+ }
@@ -10,6 +10,9 @@ export interface StagedFile {
10
10
  hunkRanges: HunkRange[];
11
11
  content?: string;
12
12
  }
13
+ type ExecFn = (cmd: string, opts: {
14
+ encoding: "utf8";
15
+ }) => string;
13
16
  /**
14
17
  * Parse null-separated name-status output from git
15
18
  */
@@ -24,6 +27,6 @@ export declare function parseHunksFromDiff(diffText: string, isNewFile?: boolean
24
27
  /**
25
28
  * Get staged files with statuses, hunks and content.
26
29
  */
27
- export declare function getStagedFiles(): StagedFile[];
30
+ export declare function getStagedFiles(exec?: ExecFn): StagedFile[];
28
31
  export default getStagedFiles;
29
32
  //# sourceMappingURL=git-staged.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"git-staged.d.ts","sourceRoot":"","sources":["../../src/traceability/git-staged.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,MAAM,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAE3C,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAaD;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,GACZ,KAAK,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAS5C;AA8BD;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,SAAS,UAAQ,GAChB,SAAS,EAAE,CAoBb;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,UAAU,EAAE,CAmF7C;AAED,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"git-staged.d.ts","sourceRoot":"","sources":["../../src/traceability/git-staged.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,MAAM,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAE3C,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,KAAK,MAAM,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,KAAK,MAAM,CAAC;AAalE;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,GACZ,KAAK,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAS5C;AAsCD;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,SAAS,UAAQ,GAChB,SAAS,EAAE,CAoBb;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,GAAE,MAAiB,GAAG,UAAU,EAAE,CA4FpE;AAED,eAAe,cAAc,CAAC"}
@@ -1,7 +1,7 @@
1
1
  import { execSync } from "node:child_process";
2
- function runGit(cmd) {
2
+ function runGit(cmd, exec) {
3
3
  try {
4
- return execSync(cmd, { encoding: "utf8" });
4
+ return exec(cmd, { encoding: "utf8" });
5
5
  }
6
6
  catch (err) {
7
7
  // wrap common errors
@@ -35,6 +35,12 @@ const SUPPORTED_EXT = new Set([
35
35
  ".cjs",
36
36
  ]);
37
37
  const ENTITY_MARKDOWN_DIRS = ["/requirements/", "/scenarios/", "/tests/"];
38
+ function shouldLogTraceDebug() {
39
+ return Boolean(process.env.KIBI_TRACE || process.env.KIBI_DEBUG);
40
+ }
41
+ function escapePath(p) {
42
+ return p.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
43
+ }
38
44
  function hasSupportedExt(p) {
39
45
  for (const ext of SUPPORTED_EXT) {
40
46
  if (p.endsWith(ext))
@@ -80,11 +86,11 @@ export function parseHunksFromDiff(diffText, isNewFile = false) {
80
86
  /**
81
87
  * Get staged files with statuses, hunks and content.
82
88
  */
83
- export function getStagedFiles() {
89
+ export function getStagedFiles(exec = execSync) {
84
90
  // 1. get staged name-status -z
85
91
  let nameStatus;
86
92
  try {
87
- nameStatus = runGit("git diff --cached --name-status -z --diff-filter=ACMRD");
93
+ nameStatus = runGit("git diff --cached --name-status -z --diff-filter=ACMRD", exec);
88
94
  }
89
95
  catch (err) {
90
96
  throw new Error(`failed to list staged files: ${String(err)}`);
@@ -95,8 +101,9 @@ export function getStagedFiles() {
95
101
  const statusRaw = entry.status;
96
102
  const status = statusRaw[0] || "M";
97
103
  if (status === "D") {
98
- // deleted files: skip but log via console.debug
99
- console.debug(`Skipping deleted file (staged): ${entry.parts.join(" -> ")}`);
104
+ if (shouldLogTraceDebug()) {
105
+ console.debug(`Skipping deleted file (staged): ${entry.parts.join(" -> ")}`);
106
+ }
100
107
  continue;
101
108
  }
102
109
  // handle renames: parts = [old, new]
@@ -109,17 +116,21 @@ export function getStagedFiles() {
109
116
  }
110
117
  }
111
118
  if (!hasSupportedExt(path) && !isEntityMarkdown(path)) {
112
- console.debug(`Skipping unsupported extension: ${path}`);
119
+ if (shouldLogTraceDebug()) {
120
+ console.debug(`Skipping unsupported extension: ${path}`);
121
+ }
113
122
  continue;
114
123
  }
115
124
  // 4. compute hunks using git diff --cached -U0 -- <path>
116
125
  let diffText = "";
117
126
  try {
118
127
  // use new path for diff; quote the path to handle spaces
119
- diffText = runGit(`git diff --cached -U0 -- "${path.replace(/"/g, '\\"')}"`);
128
+ diffText = runGit(`git diff --cached -U0 -- "${escapePath(path)}"`, exec);
120
129
  }
121
130
  catch (err) {
122
- console.debug(`Failed to get diff for ${path}: ${String(err)}`);
131
+ if (shouldLogTraceDebug()) {
132
+ console.debug(`Failed to get diff for ${path}: ${String(err)}`);
133
+ }
123
134
  diffText = "";
124
135
  }
125
136
  // determine if new file: status 'A' or diff contains /dev/null in old file path
@@ -128,13 +139,15 @@ export function getStagedFiles() {
128
139
  // 5. read staged content using git show :<path>
129
140
  let content;
130
141
  try {
131
- content = runGit(`git show :"${path.replace(/"/g, '\\"')}"`);
142
+ content = runGit(`git show :"${escapePath(path)}"`, exec);
132
143
  }
133
144
  catch (err) {
134
145
  // binary or deleted in index
135
146
  const e = err;
136
147
  const em = e?.message ? String(e.message) : String(err);
137
- console.debug(`Skipping binary/deleted or unreadable staged file ${path}: ${em}`);
148
+ if (shouldLogTraceDebug()) {
149
+ console.debug(`Skipping binary/deleted or unreadable staged file ${path}: ${em}`);
150
+ }
138
151
  continue;
139
152
  }
140
153
  // If we had a new-file sentinel (end = MAX_SAFE_INTEGER) set a realistic end as content lines
@@ -1 +1 @@
1
- {"version":3,"file":"changeset.d.ts","sourceRoot":"","sources":["../../src/types/changeset.ts"],"names":[],"mappings":"AA6CA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,KAAK,gBAAgB,MAAM,iBAAiB,CAAC;AAEpD,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,QAAQ,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,gBAAgB,EAAE,CAAC;CACpC;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,QAAQ,CAAC;IACpB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,MAAM,kBAAkB,GAAG,eAAe,GAAG,eAAe,CAAC;AAEnE,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,kBAAkB,EAAE,CAAC;IACjC,QAAQ,CAAC,EAAE;QACT,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AAED,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"changeset.d.ts","sourceRoot":"","sources":["../../src/types/changeset.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,KAAK,gBAAgB,MAAM,iBAAiB,CAAC;AAEpD,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,QAAQ,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,gBAAgB,EAAE,CAAC;CACpC;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,QAAQ,CAAC;IACpB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,MAAM,kBAAkB,GAAG,eAAe,GAAG,eAAe,CAAC;AAEnE,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,kBAAkB,EAAE,CAAC;IACjC,QAAQ,CAAC,EAAE;QACT,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AAED,eAAe,SAAS,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"entities.d.ts","sourceRoot":"","sources":["../../src/types/entities.ts"],"names":[],"mappings":"AA6CA,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,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,MAAM,EAAE,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC;AACvD,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC;AACzD,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AACvD,MAAM,MAAM,GAAG,GAAG,UAAU,GAAG;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC;AAC/C,MAAM,MAAM,IAAI,GAAG,UAAU,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AACjD,MAAM,MAAM,KAAK,GAAG,UAAU,GAAG;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AACnD,MAAM,MAAM,MAAM,GAAG,UAAU,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC;AACrD,MAAM,MAAM,IAAI,GAAG,UAAU,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjD,MAAM,MAAM,MAAM,GACd,WAAW,GACX,QAAQ,GACR,UAAU,GACV,GAAG,GACH,IAAI,GACJ,KAAK,GACL,MAAM,GACN,IAAI,CAAC"}
1
+ {"version":3,"file":"entities.d.ts","sourceRoot":"","sources":["../../src/types/entities.ts"],"names":[],"mappings":"AAkBA,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,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,MAAM,EAAE,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC;AACvD,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC;AACzD,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AACvD,MAAM,MAAM,GAAG,GAAG,UAAU,GAAG;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC;AAC/C,MAAM,MAAM,IAAI,GAAG,UAAU,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AACjD,MAAM,MAAM,KAAK,GAAG,UAAU,GAAG;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AACnD,MAAM,MAAM,MAAM,GAAG,UAAU,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC;AACrD,MAAM,MAAM,IAAI,GAAG,UAAU,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjD,MAAM,MAAM,MAAM,GACd,WAAW,GACX,QAAQ,GACR,UAAU,GACV,GAAG,GACH,IAAI,GACJ,KAAK,GACL,MAAM,GACN,IAAI,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"relationships.d.ts","sourceRoot":"","sources":["../../src/types/relationships.ts"],"names":[],"mappings":"AA6CA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EACA,YAAY,GACZ,cAAc,GACd,aAAa,GACb,YAAY,GACZ,YAAY,GACZ,gBAAgB,GAChB,YAAY,GACZ,mBAAmB,GACnB,QAAQ,GACR,WAAW,GACX,UAAU,GACV,YAAY,GACZ,YAAY,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,eAAe,gBAAgB,CAAC"}
1
+ {"version":3,"file":"relationships.d.ts","sourceRoot":"","sources":["../../src/types/relationships.ts"],"names":[],"mappings":"AAkBA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EACA,YAAY,GACZ,cAAc,GACd,aAAa,GACb,YAAY,GACZ,YAAY,GACZ,gBAAgB,GAChB,YAAY,GACZ,mBAAmB,GACnB,QAAQ,GACR,WAAW,GACX,UAAU,GACV,YAAY,GACZ,YAAY,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,eAAe,gBAAgB,CAAC"}
@@ -56,6 +56,10 @@ export declare function copyCleanSnapshot(sourcePath: string, targetPath: string
56
56
  */
57
57
  export declare function getVolatileArtifactPatterns(): string[];
58
58
  /**
59
+ * @deprecated defaultBranch is deprecated. Branch lifecycle now follows git naturally
60
+ * without requiring a configured default. This function is kept for backward compatibility
61
+ * but should not be used for new code.
62
+ *
59
63
  * Resolve the default branch using the following precedence:
60
64
  * 1. Configured defaultBranch from config (if set and valid)
61
65
  * 2. Git remote HEAD (refs/remotes/origin/HEAD)
@@ -1 +1 @@
1
- {"version":3,"file":"branch-resolver.d.ts","sourceRoot":"","sources":["../../src/utils/branch-resolver.ts"],"names":[],"mappings":"AA4BA,MAAM,MAAM,uBAAuB,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AACzD,MAAM,MAAM,qBAAqB,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,eAAe,CAAA;CAAE,CAAC;AAC7E,MAAM,MAAM,sBAAsB,GAC9B,uBAAuB,GACvB,qBAAqB,CAAC;AAE1B,MAAM,MAAM,eAAe,GACvB,cAAc,GACd,eAAe,GACf,eAAe,GACf,mBAAmB,GACnB,gBAAgB,GAChB,eAAe,CAAC;AA8BpB;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,aAAa,GAAE,MAAsB,GACpC,sBAAsB,CAmHxB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,aAAa,GAAE,MAAsB,GAAG,OAAO,CAa7E;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,KAAK,EAAE,MAAM,GACZ,MAAM,CAuBR;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAuBvD;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,IAAI,CAUN;AA6BD;;;;;GAKG;AACH,wBAAgB,2BAA2B,IAAI,MAAM,EAAE,CAMtD;AAED;;;;;;;;;;;;GAYG;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,CAqCtD"}
1
+ {"version":3,"file":"branch-resolver.d.ts","sourceRoot":"","sources":["../../src/utils/branch-resolver.ts"],"names":[],"mappings":"AA4BA,MAAM,MAAM,uBAAuB,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AACzD,MAAM,MAAM,qBAAqB,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,eAAe,CAAA;CAAE,CAAC;AAC7E,MAAM,MAAM,sBAAsB,GAC9B,uBAAuB,GACvB,qBAAqB,CAAC;AAE1B,MAAM,MAAM,eAAe,GACvB,cAAc,GACd,eAAe,GACf,eAAe,GACf,mBAAmB,GACnB,gBAAgB,GAChB,eAAe,CAAC;AA8BpB;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,aAAa,GAAE,MAAsB,GACpC,sBAAsB,CAmHxB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,aAAa,GAAE,MAAsB,GAAG,OAAO,CAa7E;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,KAAK,EAAE,MAAM,GACZ,MAAM,CAuBR;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAuBvD;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,IAAI,CAUN;AA6BD;;;;;GAKG;AACH,wBAAgB,2BAA2B,IAAI,MAAM,EAAE,CAMtD;AAED;;;;;;;;;;;;;;;;GAgBG;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,CAqCtD"}
@@ -261,6 +261,10 @@ export function getVolatileArtifactPatterns() {
261
261
  ];
262
262
  }
263
263
  /**
264
+ * @deprecated defaultBranch is deprecated. Branch lifecycle now follows git naturally
265
+ * without requiring a configured default. This function is kept for backward compatibility
266
+ * but should not be used for new code.
267
+ *
264
268
  * Resolve the default branch using the following precedence:
265
269
  * 1. Configured defaultBranch from config (if set and valid)
266
270
  * 2. Git remote HEAD (refs/remotes/origin/HEAD)