@sicilianwildcat/aiready 0.1.3 → 0.1.4
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.js +110 -32
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -133,6 +133,59 @@ function loadAgentEntry(targetDir) {
|
|
|
133
133
|
}
|
|
134
134
|
return null;
|
|
135
135
|
}
|
|
136
|
+
var GRAPHIFY_DIRECT_PATHS = ["graphify-out/graph.json", ".graphify/graph.json"];
|
|
137
|
+
function findGraphifyOutput(target) {
|
|
138
|
+
for (const p of GRAPHIFY_DIRECT_PATHS) {
|
|
139
|
+
const full = (0, import_path2.join)(target, p);
|
|
140
|
+
if (exists(full)) return full;
|
|
141
|
+
}
|
|
142
|
+
const datedBase = (0, import_path2.join)(target, "graphify-out");
|
|
143
|
+
if (exists(datedBase)) {
|
|
144
|
+
const subdirs = listDirs(datedBase).sort().reverse();
|
|
145
|
+
for (const subdir of subdirs) {
|
|
146
|
+
const candidate = (0, import_path2.join)(datedBase, subdir, "graph.json");
|
|
147
|
+
if (exists(candidate)) return candidate;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
function loadFromGraph(target, graphPath) {
|
|
153
|
+
const raw = readFile(graphPath);
|
|
154
|
+
if (!raw) return [];
|
|
155
|
+
let graph;
|
|
156
|
+
try {
|
|
157
|
+
graph = JSON.parse(raw);
|
|
158
|
+
} catch {
|
|
159
|
+
return [];
|
|
160
|
+
}
|
|
161
|
+
const nodeDegree = /* @__PURE__ */ new Map();
|
|
162
|
+
for (const link of graph.links ?? []) {
|
|
163
|
+
nodeDegree.set(link.source, (nodeDegree.get(link.source) ?? 0) + 1);
|
|
164
|
+
nodeDegree.set(link.target, (nodeDegree.get(link.target) ?? 0) + 1);
|
|
165
|
+
}
|
|
166
|
+
const fileDegree = /* @__PURE__ */ new Map();
|
|
167
|
+
for (const node of graph.nodes ?? []) {
|
|
168
|
+
if (node.file_type !== "document") continue;
|
|
169
|
+
if (!node.source_file?.endsWith(".md")) continue;
|
|
170
|
+
const current = fileDegree.get(node.source_file) ?? 0;
|
|
171
|
+
fileDegree.set(node.source_file, current + (nodeDegree.get(node.id) ?? 0));
|
|
172
|
+
}
|
|
173
|
+
const topFiles = [...fileDegree.entries()].sort((a, b) => b[1] - a[1]).slice(0, 10).map(([filePath]) => filePath);
|
|
174
|
+
const repoFiles = [];
|
|
175
|
+
for (const filePath of topFiles) {
|
|
176
|
+
const full = (0, import_path2.join)(target, filePath);
|
|
177
|
+
if (!exists(full)) continue;
|
|
178
|
+
const content = readFile(full);
|
|
179
|
+
if (content === null) continue;
|
|
180
|
+
repoFiles.push({
|
|
181
|
+
path: filePath,
|
|
182
|
+
name: filePath.split("/").pop() ?? filePath,
|
|
183
|
+
preview: content.slice(0, 200),
|
|
184
|
+
fullContent: content
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
return repoFiles;
|
|
188
|
+
}
|
|
136
189
|
function loadRepo(targetDir) {
|
|
137
190
|
const read = (name) => readFile((0, import_path2.join)(targetDir, name));
|
|
138
191
|
const packageJsonRaw = read("package.json");
|
|
@@ -149,15 +202,27 @@ function loadRepo(targetDir) {
|
|
|
149
202
|
const progressMd = read("PROGRESS.md") ?? read("progress.md");
|
|
150
203
|
const sessionHandoffMd = read("SESSION-HANDOFF.md") ?? read("session-handoff.md");
|
|
151
204
|
const progressMdModifiedAt = statMtime((0, import_path2.join)(targetDir, "PROGRESS.md")) ?? statMtime((0, import_path2.join)(targetDir, "progress.md"));
|
|
152
|
-
const
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
205
|
+
const graphPath = findGraphifyOutput(targetDir);
|
|
206
|
+
let mdFiles;
|
|
207
|
+
let usedGraphify = false;
|
|
208
|
+
if (graphPath) {
|
|
209
|
+
mdFiles = loadFromGraph(targetDir, graphPath);
|
|
210
|
+
usedGraphify = true;
|
|
211
|
+
const rel = graphPath.startsWith(targetDir) ? graphPath.slice(targetDir.length + 1) : graphPath;
|
|
212
|
+
console.log(` Using Graphify knowledge graph (${rel})`);
|
|
213
|
+
console.log(` Top ${mdFiles.length} files by centrality selected`);
|
|
214
|
+
} else {
|
|
215
|
+
const rawMdFiles = walkMdFiles(targetDir);
|
|
216
|
+
mdFiles = rawMdFiles.map(({ relPath, name, fullContent }) => ({
|
|
217
|
+
path: relPath,
|
|
218
|
+
name,
|
|
219
|
+
preview: fullContent.slice(0, 200),
|
|
220
|
+
fullContent
|
|
221
|
+
}));
|
|
222
|
+
}
|
|
159
223
|
return {
|
|
160
224
|
mdFiles,
|
|
225
|
+
usedGraphify,
|
|
161
226
|
agentsMd,
|
|
162
227
|
architectureMd,
|
|
163
228
|
constraintsMd,
|
|
@@ -173,7 +238,7 @@ function loadRepo(targetDir) {
|
|
|
173
238
|
}
|
|
174
239
|
|
|
175
240
|
// src/audit/mapper.ts
|
|
176
|
-
var TRIAGE_SYSTEM = `You are a repository analyst. Given a list of
|
|
241
|
+
var TRIAGE_SYSTEM = `You are a repository analyst. Given a list of file paths,
|
|
177
242
|
identify which files could plausibly serve as harness artifacts for AI
|
|
178
243
|
coding agents.
|
|
179
244
|
|
|
@@ -237,12 +302,11 @@ function parseMapperResponse(text) {
|
|
|
237
302
|
return [];
|
|
238
303
|
}
|
|
239
304
|
}
|
|
240
|
-
async function
|
|
241
|
-
const fileList = mdFiles.map((f) => `-
|
|
242
|
-
preview: ${JSON.stringify(firstLines(f.fullContent, 5))}`).join("\n");
|
|
305
|
+
async function triageByFilename(mdFiles, provider) {
|
|
306
|
+
const fileList = mdFiles.map((f) => `- ${f.path}`).join("\n");
|
|
243
307
|
const text = await provider.chat(
|
|
244
308
|
TRIAGE_SYSTEM,
|
|
245
|
-
`Identify harness-relevant files:
|
|
309
|
+
`Identify harness-relevant files from these paths:
|
|
246
310
|
|
|
247
311
|
${fileList}`,
|
|
248
312
|
{ fast: true }
|
|
@@ -261,9 +325,12 @@ ${fileList}`,
|
|
|
261
325
|
);
|
|
262
326
|
return parseMapperResponse(text);
|
|
263
327
|
}
|
|
264
|
-
async function mapFiles(mdFiles, provider) {
|
|
328
|
+
async function mapFiles(mdFiles, provider, usedGraphify = false) {
|
|
265
329
|
if (mdFiles.length === 0) return [];
|
|
266
|
-
|
|
330
|
+
if (usedGraphify) {
|
|
331
|
+
return classifyFiles(mdFiles, provider);
|
|
332
|
+
}
|
|
333
|
+
const relevantPaths = await triageByFilename(mdFiles, provider);
|
|
267
334
|
if (relevantPaths.length === 0) return [];
|
|
268
335
|
const pathSet = new Set(relevantPaths);
|
|
269
336
|
const relevantFiles = mdFiles.filter((f) => pathSet.has(f.path));
|
|
@@ -295,23 +362,28 @@ function extractDocumentedModules(content) {
|
|
|
295
362
|
}
|
|
296
363
|
return [...new Set(modules)];
|
|
297
364
|
}
|
|
298
|
-
function checkCommands(files) {
|
|
299
|
-
|
|
365
|
+
function checkCommands(files, mappings, mdFileMap) {
|
|
366
|
+
let contentToCheck = files.agentsMd;
|
|
367
|
+
if (!contentToCheck && mappings.length > 0) {
|
|
368
|
+
const mapped = mappings.filter((m) => m.subsystems.includes("identity") || m.subsystems.includes("verification")).map((m) => mdFileMap.get(m.path)).filter((c) => c !== void 0).join("\n\n");
|
|
369
|
+
if (mapped) contentToCheck = mapped;
|
|
370
|
+
}
|
|
371
|
+
if (!contentToCheck) {
|
|
300
372
|
return [
|
|
301
373
|
{
|
|
302
374
|
name: "commands-in-agents-exist-in-package",
|
|
303
375
|
passed: false,
|
|
304
|
-
detail: "No
|
|
376
|
+
detail: "No agent harness file found to extract commands from"
|
|
305
377
|
}
|
|
306
378
|
];
|
|
307
379
|
}
|
|
308
|
-
const commands = extractNpmRunCommands(
|
|
380
|
+
const commands = extractNpmRunCommands(contentToCheck);
|
|
309
381
|
if (commands.length === 0) {
|
|
310
382
|
return [
|
|
311
383
|
{
|
|
312
384
|
name: "commands-in-agents-exist-in-package",
|
|
313
385
|
passed: true,
|
|
314
|
-
detail: "No npm run commands found in
|
|
386
|
+
detail: "No npm run commands found in harness bash blocks"
|
|
315
387
|
}
|
|
316
388
|
];
|
|
317
389
|
}
|
|
@@ -323,30 +395,35 @@ function checkCommands(files) {
|
|
|
323
395
|
{
|
|
324
396
|
name: "commands-in-agents-exist-in-package",
|
|
325
397
|
passed: true,
|
|
326
|
-
detail: `All ${commands.length} npm run command(s) in
|
|
398
|
+
detail: `All ${commands.length} npm run command(s) in harness found in package.json scripts`
|
|
327
399
|
}
|
|
328
400
|
];
|
|
329
401
|
}
|
|
330
402
|
return missing.map((cmd) => ({
|
|
331
403
|
name: "commands-in-agents-exist-in-package",
|
|
332
404
|
passed: false,
|
|
333
|
-
detail: `\`npm run ${cmd}\` in
|
|
405
|
+
detail: `\`npm run ${cmd}\` in harness not found in package.json scripts`
|
|
334
406
|
}));
|
|
335
407
|
}
|
|
336
|
-
function checkModules(files) {
|
|
337
|
-
|
|
408
|
+
function checkModules(files, mappings, mdFileMap) {
|
|
409
|
+
let contentToCheck = files.architectureMd;
|
|
410
|
+
if (!contentToCheck && mappings.length > 0) {
|
|
411
|
+
const mapped = mappings.filter((m) => m.subsystems.includes("memory")).map((m) => mdFileMap.get(m.path)).filter((c) => c !== void 0).join("\n\n");
|
|
412
|
+
if (mapped) contentToCheck = mapped;
|
|
413
|
+
}
|
|
414
|
+
if (!contentToCheck) {
|
|
338
415
|
return {
|
|
339
416
|
name: "architecture-modules-match-src",
|
|
340
417
|
passed: false,
|
|
341
|
-
detail: "No
|
|
418
|
+
detail: "No architecture file found to extract documented modules from"
|
|
342
419
|
};
|
|
343
420
|
}
|
|
344
|
-
const documented = extractDocumentedModules(
|
|
421
|
+
const documented = extractDocumentedModules(contentToCheck);
|
|
345
422
|
if (documented.length === 0) {
|
|
346
423
|
return {
|
|
347
424
|
name: "architecture-modules-match-src",
|
|
348
425
|
passed: true,
|
|
349
|
-
detail: "No annotated module directories found in
|
|
426
|
+
detail: "No annotated module directories found in architecture file"
|
|
350
427
|
};
|
|
351
428
|
}
|
|
352
429
|
const missing = documented.filter((mod) => !files.srcDirs.includes(mod));
|
|
@@ -360,7 +437,7 @@ function checkModules(files) {
|
|
|
360
437
|
return {
|
|
361
438
|
name: "architecture-modules-match-src",
|
|
362
439
|
passed: false,
|
|
363
|
-
detail: `Module(s) in
|
|
440
|
+
detail: `Module(s) in architecture file not found in src/: ${missing.join(", ")}`
|
|
364
441
|
};
|
|
365
442
|
}
|
|
366
443
|
function checkProgressFreshness(files) {
|
|
@@ -385,11 +462,12 @@ function checkProgressFreshness(files) {
|
|
|
385
462
|
detail: `PROGRESS.md last updated ${Math.round(ageDays)} days ago (threshold: 7)`
|
|
386
463
|
};
|
|
387
464
|
}
|
|
388
|
-
function crossRef(files) {
|
|
465
|
+
function crossRef(files, mappings = []) {
|
|
466
|
+
const mdFileMap = new Map(files.mdFiles.map((f) => [f.path, f.fullContent]));
|
|
389
467
|
return {
|
|
390
468
|
checks: [
|
|
391
|
-
...checkCommands(files),
|
|
392
|
-
checkModules(files),
|
|
469
|
+
...checkCommands(files, mappings, mdFileMap),
|
|
470
|
+
checkModules(files, mappings, mdFileMap),
|
|
393
471
|
checkProgressFreshness(files)
|
|
394
472
|
]
|
|
395
473
|
};
|
|
@@ -475,7 +553,7 @@ ${contentSections}`,
|
|
|
475
553
|
const overall = Math.round(
|
|
476
554
|
(identity.score + verification.score + state.score + memory.score + constraints.score) / 5
|
|
477
555
|
);
|
|
478
|
-
const xref = crossRef(files);
|
|
556
|
+
const xref = crossRef(files, mappings);
|
|
479
557
|
return { identity, verification, state, memory, constraints, overall, crossRef: xref };
|
|
480
558
|
}
|
|
481
559
|
|
|
@@ -825,7 +903,7 @@ async function runAudit(target, opts) {
|
|
|
825
903
|
const provider = createProvider(config.provider, config.apiKey, config.modelId);
|
|
826
904
|
const targetDir = (0, import_path3.resolve)(target);
|
|
827
905
|
const files = loadRepo(targetDir);
|
|
828
|
-
const mappings = await mapFiles(files.mdFiles, provider);
|
|
906
|
+
const mappings = await mapFiles(files.mdFiles, provider, files.usedGraphify);
|
|
829
907
|
const scored = await scoreRepo(files, mappings, provider);
|
|
830
908
|
const totalTokens = provider.getTotalTokens();
|
|
831
909
|
report(scored, { json: opts.json, tokenUsage: totalTokens });
|