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.
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +11 -0
- package/dist/commands/check.d.ts.map +1 -1
- package/dist/commands/check.js +229 -4
- package/dist/commands/init-helpers.d.ts.map +1 -1
- package/dist/commands/init-helpers.js +11 -14
- package/dist/commands/migrate.d.ts +9 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +183 -0
- package/dist/commands/sync/manifest.d.ts +8 -2
- package/dist/commands/sync/manifest.d.ts.map +1 -1
- package/dist/commands/sync/manifest.js +56 -11
- package/dist/commands/sync.d.ts +1 -0
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +9 -7
- package/dist/extractors/manifest.d.ts +30 -0
- package/dist/extractors/manifest.d.ts.map +1 -1
- package/dist/extractors/manifest.js +60 -7
- package/dist/extractors/symbol-coordinates.d.ts +15 -0
- package/dist/extractors/symbol-coordinates.d.ts.map +1 -0
- package/dist/extractors/symbol-coordinates.js +83 -0
- package/dist/public/check-types.d.ts +3 -1
- package/dist/public/check-types.d.ts.map +1 -1
- package/dist/public/check-types.js +1 -0
- package/dist/public/extractors/manifest.d.ts +1 -1
- package/dist/public/extractors/manifest.d.ts.map +1 -1
- package/dist/public/extractors/manifest.js +1 -1
- package/dist/public/ignore-policy.d.ts +10 -0
- package/dist/public/ignore-policy.d.ts.map +1 -0
- package/dist/public/ignore-policy.js +219 -0
- package/dist/public/schema-version.d.ts +3 -0
- package/dist/public/schema-version.d.ts.map +1 -0
- package/dist/public/schema-version.js +1 -0
- package/dist/traceability/evidence-model.d.ts +142 -0
- package/dist/traceability/evidence-model.d.ts.map +1 -0
- package/dist/traceability/evidence-model.js +70 -0
- package/dist/traceability/git-staged.d.ts +1 -0
- package/dist/traceability/git-staged.d.ts.map +1 -1
- package/dist/traceability/git-staged.js +28 -3
- package/dist/traceability/staged-diagnostics.d.ts +25 -0
- package/dist/traceability/staged-diagnostics.d.ts.map +1 -0
- package/dist/traceability/staged-diagnostics.js +67 -0
- package/dist/traceability/staged-impact-contract.d.ts +57 -0
- package/dist/traceability/staged-impact-contract.d.ts.map +1 -0
- package/dist/traceability/staged-impact-contract.js +202 -0
- package/dist/traceability/staged-symbols-manifest.d.ts +23 -0
- package/dist/traceability/staged-symbols-manifest.d.ts.map +1 -0
- package/dist/traceability/staged-symbols-manifest.js +269 -0
- package/dist/traceability/symbol-extract.d.ts.map +1 -1
- package/dist/traceability/symbol-extract.js +33 -9
- package/dist/utils/config.d.ts +1 -0
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +35 -22
- package/dist/utils/manifest-paths.d.ts +8 -0
- package/dist/utils/manifest-paths.d.ts.map +1 -0
- package/dist/utils/manifest-paths.js +62 -0
- package/dist/utils/rule-registry.d.ts.map +1 -1
- package/dist/utils/rule-registry.js +6 -0
- package/dist/utils/schema-version.d.ts +14 -0
- package/dist/utils/schema-version.d.ts.map +1 -0
- package/dist/utils/schema-version.js +59 -0
- package/dist/utils/strict-modeling.d.ts +64 -0
- package/dist/utils/strict-modeling.d.ts.map +1 -0
- package/dist/utils/strict-modeling.js +371 -0
- package/package.json +13 -3
- package/schema/config.json +8 -1
- package/src/public/check-types.ts +15 -1
- package/src/public/extractors/manifest.ts +2 -0
- package/src/public/ignore-policy.ts +229 -0
- 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
|
|
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
|
-
|
|
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(
|
|
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
|
package/dist/commands/sync.d.ts
CHANGED
|
@@ -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,
|
|
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"}
|
package/dist/commands/sync.js
CHANGED
|
@@ -140,13 +140,15 @@ export async function syncCommand(options = {}, runtime = {}) {
|
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
142
|
if (!validateOnly) {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
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":"
|
|
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
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
return
|
|
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
|
-
|
|
117
|
-
|
|
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;
|
|
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,
|
|
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"}
|