@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.
Files changed (2) hide show
  1. package/dist/cli.js +110 -32
  2. 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 rawMdFiles = walkMdFiles(targetDir);
153
- const mdFiles = rawMdFiles.map(({ relPath, name, fullContent }) => ({
154
- path: relPath,
155
- name,
156
- preview: fullContent.slice(0, 200),
157
- fullContent
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 files with short previews,
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 triageFiles(mdFiles, provider) {
241
- const fileList = mdFiles.map((f) => `- path: ${f.path}
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
- const relevantPaths = await triageFiles(mdFiles, provider);
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
- if (!files.agentsMd) {
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 AGENTS.md to extract commands from"
376
+ detail: "No agent harness file found to extract commands from"
305
377
  }
306
378
  ];
307
379
  }
308
- const commands = extractNpmRunCommands(files.agentsMd);
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 AGENTS.md bash blocks"
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 AGENTS.md found in package.json scripts`
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 AGENTS.md not found in package.json scripts`
405
+ detail: `\`npm run ${cmd}\` in harness not found in package.json scripts`
334
406
  }));
335
407
  }
336
- function checkModules(files) {
337
- if (!files.architectureMd) {
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 ARCHITECTURE.md to extract documented modules from"
418
+ detail: "No architecture file found to extract documented modules from"
342
419
  };
343
420
  }
344
- const documented = extractDocumentedModules(files.architectureMd);
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 ARCHITECTURE.md"
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 ARCHITECTURE.md not found in src/: ${missing.join(", ")}`
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 });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sicilianwildcat/aiready",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "Audit repositories for AI agent readiness",
5
5
  "license": "MIT",
6
6
  "author": "harikrishn4a",