agentsys 5.13.4 → 6.0.0

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 (39) hide show
  1. package/.claude-plugin/marketplace.json +28 -28
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.codex-plugin/plugin.json +2 -3
  4. package/AGENTS.md +8 -8
  5. package/CHANGELOG.md +34 -0
  6. package/README.md +11 -116
  7. package/lib/binary/index.js +8 -2
  8. package/lib/binary/shared-helpers.js +160 -0
  9. package/lib/collectors/codebase.js +7 -2
  10. package/lib/collectors/documentation.js +8 -2
  11. package/lib/enhance/agent-patterns.js +17 -4
  12. package/lib/enhance/auto-suppression.js +19 -7
  13. package/lib/enhance/cross-file-analyzer.js +11 -4
  14. package/lib/enhance/docs-patterns.js +6 -2
  15. package/lib/enhance/fixer.js +22 -5
  16. package/lib/enhance/skill-patterns.js +5 -5
  17. package/lib/index.js +2 -0
  18. package/lib/repo-intel/cache.js +171 -0
  19. package/lib/repo-intel/converter.js +130 -0
  20. package/lib/repo-intel/embed/binary.js +242 -0
  21. package/lib/repo-intel/embed/index.js +26 -0
  22. package/lib/repo-intel/embed/orchestrator.js +239 -0
  23. package/lib/repo-intel/embed/preference.js +136 -0
  24. package/lib/repo-intel/enrich.js +198 -0
  25. package/lib/repo-intel/index.js +370 -0
  26. package/lib/repo-intel/installer.js +78 -0
  27. package/lib/repo-intel/queries.js +213 -13
  28. package/lib/repo-intel/updater.js +104 -0
  29. package/lib/repo-map/index.js +19 -254
  30. package/package.json +1 -1
  31. package/scripts/generate-docs.js +13 -18
  32. package/scripts/plugins.txt +2 -2
  33. package/site/assets/js/main.js +5 -13
  34. package/site/content.json +6 -23
  35. package/site/index.html +29 -77
  36. package/site/ux-spec.md +7 -7
  37. package/.kiro/agents/web-session.json +0 -12
  38. package/.kiro/skills/web-auth/SKILL.md +0 -177
  39. package/.kiro/skills/web-browse/SKILL.md +0 -516
@@ -99,6 +99,19 @@ function runQuery(queryName, extraArgs, cwd) {
99
99
  return parsed;
100
100
  }
101
101
 
102
+ /**
103
+ * Assert a query argument is a non-empty string. Centralizes the validation
104
+ * that file/symbol/concept-taking queries share, so a wrong-typed arg fails
105
+ * with a clear message instead of being stringified into a bogus CLI argument.
106
+ * @param {*} val - the value to check
107
+ * @param {string} label - "<fn>: <arg>" for the error message
108
+ */
109
+ function assertString(val, label) {
110
+ if (typeof val !== 'string' || val.length === 0) {
111
+ throw new TypeError(`${label} must be a non-empty string`);
112
+ }
113
+ }
114
+
102
115
  // ---------------------------------------------------------------------------
103
116
  // Query functions
104
117
  // ---------------------------------------------------------------------------
@@ -123,6 +136,7 @@ function hotspots(cwd, opts = {}) {
123
136
  * @returns {Array}
124
137
  */
125
138
  function coupling(cwd, file, opts = {}) {
139
+ assertString(file, 'coupling: file');
126
140
  const extra = [file];
127
141
  if (opts.limit != null) extra.push('--top', String(opts.limit));
128
142
  return runQuery('coupling', extra, cwd);
@@ -154,17 +168,6 @@ function testGaps(cwd, opts = {}) {
154
168
  return runQuery('test-gaps', extra, cwd);
155
169
  }
156
170
 
157
- /**
158
- * AI-authored ratio per file or project.
159
- * @param {string} cwd
160
- * @param {{ pathFilter?: string }} [opts]
161
- * @returns {Object}
162
- */
163
- function aiRatio(cwd, opts = {}) {
164
- const extra = [];
165
- if (opts.pathFilter != null) extra.push('--path-filter', opts.pathFilter);
166
- return runQuery('ai-ratio', extra, cwd);
167
- }
168
171
 
169
172
  /**
170
173
  * Risk score for a diff (set of changed files).
@@ -197,8 +200,12 @@ function diffRisk(cwd, files) {
197
200
  * @returns {Object}
198
201
  */
199
202
  function dependents(cwd, symbol, file) {
203
+ assertString(symbol, 'dependents: symbol');
200
204
  const extra = [symbol];
201
- if (file != null) extra.push('--file', file);
205
+ if (file != null) {
206
+ assertString(file, 'dependents: file');
207
+ extra.push('--file', file);
208
+ }
202
209
  return runQuery('dependents', extra, cwd);
203
210
  }
204
211
 
@@ -255,6 +262,7 @@ function boundaries(cwd, opts = {}) {
255
262
  * @returns {Object}
256
263
  */
257
264
  function areaOf(cwd, file) {
265
+ assertString(file, 'areaOf: file');
258
266
  return runQuery('area-of', [file], cwd);
259
267
  }
260
268
 
@@ -273,6 +281,171 @@ function communityHealth(cwd, id) {
273
281
  return runQuery('community-health', [String(id)], cwd);
274
282
  }
275
283
 
284
+ // ---------------------------------------------------------------------------
285
+ // Activity / git queries
286
+ // ---------------------------------------------------------------------------
287
+
288
+ /** Least-changed files (no recent activity). @param {string} cwd @param {{limit?:number}} [opts] */
289
+ function coldspots(cwd, opts = {}) {
290
+ const extra = [];
291
+ if (opts.limit != null) extra.push('--top', String(opts.limit));
292
+ return runQuery('coldspots', extra, cwd);
293
+ }
294
+
295
+ /** Ownership for a file or directory. @param {string} cwd @param {string} file */
296
+ function ownership(cwd, file) {
297
+ assertString(file, 'ownership: file');
298
+ return runQuery('ownership', [file], cwd);
299
+ }
300
+
301
+ /** Project norms detected from git history. @param {string} cwd */
302
+ function norms(cwd) {
303
+ return runQuery('norms', [], cwd);
304
+ }
305
+
306
+ /** Area-level health overview. @param {string} cwd */
307
+ function areas(cwd) {
308
+ return runQuery('areas', [], cwd);
309
+ }
310
+
311
+ /** Contributors sorted by commit count. @param {string} cwd @param {{limit?:number}} [opts] */
312
+ function contributors(cwd, opts = {}) {
313
+ const extra = [];
314
+ if (opts.limit != null) extra.push('--top', String(opts.limit));
315
+ return runQuery('contributors', extra, cwd);
316
+ }
317
+
318
+ /** Release cadence and tag info. @param {string} cwd */
319
+ function releaseInfo(cwd) {
320
+ return runQuery('release-info', [], cwd);
321
+ }
322
+
323
+ /** History for a specific file. @param {string} cwd @param {string} file */
324
+ function fileHistory(cwd, file) {
325
+ assertString(file, 'fileHistory: file');
326
+ return runQuery('file-history', [file], cwd);
327
+ }
328
+
329
+ /** Commit message conventions. @param {string} cwd */
330
+ function conventions(cwd) {
331
+ return runQuery('conventions', [], cwd);
332
+ }
333
+
334
+ /** Doc files with low code coupling (likely stale). @param {string} cwd @param {{limit?:number}} [opts] */
335
+ function docDrift(cwd, opts = {}) {
336
+ const extra = [];
337
+ if (opts.limit != null) extra.push('--top', String(opts.limit));
338
+ return runQuery('doc-drift', extra, cwd);
339
+ }
340
+
341
+ // ---------------------------------------------------------------------------
342
+ // Narrative / guidance queries
343
+ // ---------------------------------------------------------------------------
344
+
345
+ /** Newcomer-oriented repo summary. @param {string} cwd */
346
+ function onboard(cwd) {
347
+ return runQuery('onboard', [], cwd);
348
+ }
349
+
350
+ /** Contributor guidance matching skills to areas needing work. @param {string} cwd */
351
+ function canIHelp(cwd) {
352
+ return runQuery('can-i-help', [], cwd);
353
+ }
354
+
355
+ /** Files ranked by pain score (hotspot x complexity x bug density). @param {string} cwd @param {{limit?:number}} [opts] */
356
+ function painspots(cwd, opts = {}) {
357
+ const extra = [];
358
+ if (opts.limit != null) extra.push('--top', String(opts.limit));
359
+ return runQuery('painspots', extra, cwd);
360
+ }
361
+
362
+ /** Every place execution can start (binaries, main fns, npm scripts). @param {string} cwd @param {{files?:string[]|string}} [opts] */
363
+ function entryPoints(cwd, opts = {}) {
364
+ const extra = [];
365
+ if (opts.files) {
366
+ const list = Array.isArray(opts.files) ? opts.files.join(',') : String(opts.files);
367
+ extra.push('--files', list);
368
+ }
369
+ return runQuery('entry-points', extra, cwd);
370
+ }
371
+
372
+ /** Project metadata: languages, CI, license, README. @param {string} cwd */
373
+ function projectInfo(cwd) {
374
+ return runQuery('project-info', [], cwd);
375
+ }
376
+
377
+ // ---------------------------------------------------------------------------
378
+ // AST / symbol queries
379
+ // ---------------------------------------------------------------------------
380
+
381
+ /** AST symbols (exports/imports/definitions) for a file. @param {string} cwd @param {string} file */
382
+ function symbols(cwd, file) {
383
+ assertString(file, 'symbols: file');
384
+ return runQuery('symbols', [file], cwd);
385
+ }
386
+
387
+ /** Doc files with stale references to source symbols. @param {string} cwd @param {{limit?:number}} [opts] */
388
+ function staleDocs(cwd, opts = {}) {
389
+ const extra = [];
390
+ if (opts.limit != null) extra.push('--top', String(opts.limit));
391
+ return runQuery('stale-docs', extra, cwd);
392
+ }
393
+
394
+ /** Concept-to-file search (ranked, replaces grep -r). @param {string} cwd @param {string} query @param {{limit?:number}} [opts] */
395
+ function find(cwd, query, opts = {}) {
396
+ assertString(query, 'find: query');
397
+ const extra = [query];
398
+ if (opts.limit != null) extra.push('--top', String(opts.limit));
399
+ return runQuery('find', extra, cwd);
400
+ }
401
+
402
+ // ---------------------------------------------------------------------------
403
+ // Deslop-agent queries
404
+ // ---------------------------------------------------------------------------
405
+
406
+ /** Structured slop fix actions for the deslop agent. @param {string} cwd */
407
+ function slopFixes(cwd) {
408
+ return runQuery('slop-fixes', [], cwd);
409
+ }
410
+
411
+ /** Ranked slop targets (Sonnet/Opus tiers). @param {string} cwd @param {{top?:number}} [opts] */
412
+ function slopTargets(cwd, opts = {}) {
413
+ const extra = [];
414
+ if (opts.top != null) extra.push('--top', String(opts.top));
415
+ return runQuery('slop-targets', extra, cwd);
416
+ }
417
+
418
+ /**
419
+ * Cached 3-depth narrative summary. Returns null when not yet generated;
420
+ * with opts.depth returns that single depth as plain text. Bypasses the
421
+ * JSON-parse path because the binary emits the literal 'null' or raw text.
422
+ * @param {string} cwd @param {{depth?:1|3|10}} [opts]
423
+ */
424
+ function summary(cwd, opts = {}) {
425
+ const mapFile = requireMapFile(cwd);
426
+ const extra = [];
427
+ if (opts.depth != null) extra.push('--depth', String(opts.depth));
428
+ const args = ['repo-intel', 'query', 'summary', ...extra, '--map-file', mapFile, cwd];
429
+ // summary bypasses runQuery (a single --depth returns plain text, not JSON),
430
+ // so it must wrap the analyzer call + parse itself to match runQuery's error
431
+ // contract instead of leaking a raw spawn / SyntaxError.
432
+ let raw;
433
+ try {
434
+ raw = binary.runAnalyzer(args).trim();
435
+ } catch (err) {
436
+ throw new Error(`repo-intel query failed [summary]: ${err.message}`, { cause: err });
437
+ }
438
+ if (raw === 'null') return null;
439
+ if (opts.depth != null) return raw; // plain-text single depth
440
+ try {
441
+ return JSON.parse(raw);
442
+ } catch (_parseErr) {
443
+ throw new Error(
444
+ `repo-intel query [summary] returned non-JSON output: ${raw.slice(0, 200)}`
445
+ );
446
+ }
447
+ }
448
+
276
449
  // ---------------------------------------------------------------------------
277
450
  // Exports
278
451
  // ---------------------------------------------------------------------------
@@ -286,7 +459,6 @@ module.exports = {
286
459
  coupling,
287
460
  busFactor,
288
461
  testGaps,
289
- aiRatio,
290
462
  diffRisk,
291
463
  dependents,
292
464
  bugspots,
@@ -297,4 +469,32 @@ module.exports = {
297
469
  boundaries,
298
470
  areaOf,
299
471
  communityHealth,
472
+
473
+ // Activity / git queries
474
+ coldspots,
475
+ ownership,
476
+ norms,
477
+ areas,
478
+ contributors,
479
+ releaseInfo,
480
+ fileHistory,
481
+ conventions,
482
+ docDrift,
483
+
484
+ // Narrative / guidance queries
485
+ onboard,
486
+ canIHelp,
487
+ painspots,
488
+ entryPoints,
489
+ projectInfo,
490
+
491
+ // AST / symbol queries
492
+ symbols,
493
+ staleDocs,
494
+ find,
495
+
496
+ // Deslop-agent queries
497
+ slopFixes,
498
+ slopTargets,
499
+ summary,
300
500
  };
@@ -0,0 +1,104 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Repo map staleness checker.
5
+ *
6
+ * Determines whether a cached repo-map is stale relative to the current git HEAD.
7
+ * The incremental update path is handled by agent-analyzer (repo-intel update).
8
+ *
9
+ * @module lib/repo-intel/updater
10
+ */
11
+
12
+ const { execFileSync } = require('child_process');
13
+
14
+ const cache = require('./cache');
15
+
16
+ /**
17
+ * Check whether the cached map is stale
18
+ * @param {string} basePath - Repository root path
19
+ * @param {Object} map - Cached repo map
20
+ * @returns {{isStale: boolean, reason: string|null, commitsBehind: number, suggestFullRebuild: boolean}}
21
+ */
22
+ function checkStaleness(basePath, map) {
23
+ const result = {
24
+ isStale: false,
25
+ reason: null,
26
+ commitsBehind: 0,
27
+ suggestFullRebuild: false
28
+ };
29
+
30
+ if (!map?.git?.commit) {
31
+ result.isStale = true;
32
+ result.reason = 'Missing base commit in repo-map';
33
+ result.suggestFullRebuild = true;
34
+ return result;
35
+ }
36
+
37
+ if (cache.isMarkedStale(basePath)) {
38
+ result.isStale = true;
39
+ result.reason = 'Marked stale by hook';
40
+ }
41
+
42
+ if (!commitExists(basePath, map.git.commit)) {
43
+ result.isStale = true;
44
+ result.reason = 'Base commit no longer exists (rebased?)';
45
+ result.suggestFullRebuild = true;
46
+ return result;
47
+ }
48
+
49
+ const currentBranch = getCurrentBranch(basePath);
50
+ if (currentBranch && map.git.branch && currentBranch !== map.git.branch) {
51
+ result.isStale = true;
52
+ result.reason = `Branch changed from ${map.git.branch} to ${currentBranch}`;
53
+ result.suggestFullRebuild = true;
54
+ }
55
+
56
+ const commitsBehind = getCommitsBehind(basePath, map.git.commit);
57
+ if (commitsBehind > 0) {
58
+ result.isStale = true;
59
+ result.commitsBehind = commitsBehind;
60
+ if (!result.reason) {
61
+ result.reason = `${commitsBehind} commits behind HEAD`;
62
+ }
63
+ }
64
+
65
+ return result;
66
+ }
67
+
68
+ function isValidCommitHash(commit) {
69
+ return typeof commit === 'string' && /^[0-9a-fA-F]{4,40}$/.test(commit);
70
+ }
71
+
72
+ function commitExists(basePath, commit) {
73
+ if (!isValidCommitHash(commit)) return false;
74
+ try {
75
+ execFileSync('git', ['cat-file', '-e', commit], { cwd: basePath, stdio: ['pipe', 'pipe', 'pipe'] });
76
+ return true;
77
+ } catch {
78
+ return false;
79
+ }
80
+ }
81
+
82
+ function getCurrentBranch(basePath) {
83
+ try {
84
+ return execFileSync('git', ['rev-parse', '--abbrev-ref', 'HEAD'], {
85
+ cwd: basePath, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe']
86
+ }).trim();
87
+ } catch {
88
+ return null;
89
+ }
90
+ }
91
+
92
+ function getCommitsBehind(basePath, commit) {
93
+ if (!isValidCommitHash(commit)) return 0;
94
+ try {
95
+ const out = execFileSync('git', ['rev-list', `${commit}..HEAD`, '--count'], {
96
+ cwd: basePath, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe']
97
+ }).trim();
98
+ return Number(out) || 0;
99
+ } catch {
100
+ return 0;
101
+ }
102
+ }
103
+
104
+ module.exports = { checkStaleness };
@@ -1,265 +1,30 @@
1
1
  'use strict';
2
2
 
3
3
  /**
4
- * Repo Map - repository symbol mapping via agent-analyzer
4
+ * DEPRECATED COMPAT SHIM repo-map folded into lib/repo-intel.
5
5
  *
6
- * Uses agent-analyzer for symbol extraction. The binary is auto-downloaded
7
- * on first use - no external tool installation required.
6
+ * repo-map was a leftover split: it produced/converted the artifact while
7
+ * lib/repo-intel/ only queried it. They are one pipeline over one binary, now
8
+ * unified under lib/repo-intel. This shim re-exports the lifecycle surface so
9
+ * existing `require('.../repo-map')` consumers keep working unchanged.
10
+ *
11
+ * Migrate callers to `require('.../repo-intel')` and remove this shim.
8
12
  *
9
13
  * @module lib/repo-map
14
+ * @deprecated use lib/repo-intel
10
15
  */
11
16
 
12
- const fs = require('fs');
13
- const path = require('path');
14
- const { execFileSync } = require('child_process');
15
-
16
- const installer = require('./installer');
17
- const cache = require('./cache');
18
- const updater = require('./updater');
19
- const converter = require('./converter');
20
- const binary = require('../binary');
21
- const { getStateDirPath } = require('../platform/state-dir');
22
- const { writeJsonAtomic } = require('../utils/atomic-write');
23
-
24
- const REPO_INTEL_FILENAME = 'repo-intel.json';
25
-
26
- function getIntelMapPath(basePath) {
27
- return path.join(getStateDirPath(basePath), REPO_INTEL_FILENAME);
28
- }
29
-
30
- /**
31
- * Initialize a new repo map (full scan)
32
- * @param {string} basePath - Repository root path
33
- * @param {Object} options - Options
34
- * @param {boolean} options.force - Force rebuild even if map exists
35
- * @returns {Promise<{success: boolean, map?: Object, error?: string}>}
36
- */
37
- async function init(basePath, options = {}) {
38
- const installed = await installer.checkInstalled();
39
- if (!installed.found) {
40
- return {
41
- success: false,
42
- error: 'agent-analyzer binary unavailable: ' + (installed.error || 'unknown error'),
43
- installSuggestion: installer.getInstallInstructions()
44
- };
45
- }
46
-
47
- const existing = cache.load(basePath);
48
- if (existing && !options.force) {
49
- return {
50
- success: false,
51
- error: 'Repo map already exists. Use --force to rebuild or /repo-map update to refresh.',
52
- existing: cache.getStatus(basePath)
53
- };
54
- }
55
-
56
- const startTime = Date.now();
57
-
58
- let intelJson;
59
- try {
60
- intelJson = await binary.runAnalyzerAsync(['repo-intel', 'init', basePath]);
61
- } catch (e) {
62
- return {
63
- success: false,
64
- error: 'agent-analyzer repo-intel init failed: ' + e.message
65
- };
66
- }
67
-
68
- let intel;
69
- try {
70
- intel = JSON.parse(intelJson);
71
- } catch (e) {
72
- return {
73
- success: false,
74
- error: 'Failed to parse repo-intel output: ' + e.message
75
- };
76
- }
77
-
78
- // Persist repo-intel.json for future incremental updates
79
- const intelPath = getIntelMapPath(basePath);
80
- try {
81
- writeJsonAtomic(intelPath, intel);
82
- } catch {
83
- // Non-fatal: update() will fall back to full init
84
- }
85
-
86
- const map = converter.convertIntelToRepoMap(intel);
87
- map.stats.scanDurationMs = Date.now() - startTime;
88
- cache.save(basePath, map);
89
-
90
- return {
91
- success: true,
92
- map,
93
- summary: {
94
- files: Object.keys(map.files).length,
95
- symbols: map.stats.totalSymbols,
96
- languages: map.project.languages,
97
- duration: map.stats.scanDurationMs
98
- }
99
- };
100
- }
101
-
102
- /**
103
- * Update an existing repo map (incremental via agent-analyzer)
104
- * @param {string} basePath - Repository root path
105
- * @param {Object} options - Options
106
- * @param {boolean} options.full - Force full rebuild instead of incremental
107
- * @returns {Promise<{success: boolean, summary?: Object, error?: string}>}
108
- */
109
- async function update(basePath, options = {}) {
110
- const installed = await installer.checkInstalled();
111
- if (!installed.found) {
112
- return {
113
- success: false,
114
- error: 'agent-analyzer binary unavailable: ' + (installed.error || 'unknown error'),
115
- installSuggestion: installer.getInstallInstructions()
116
- };
117
- }
118
-
119
- if (!cache.exists(basePath)) {
120
- return {
121
- success: false,
122
- error: 'No repo map found. Run /repo-map init first.'
123
- };
124
- }
125
-
126
- if (options.full) {
127
- return init(basePath, { force: true });
128
- }
129
-
130
- const intelPath = getIntelMapPath(basePath);
131
- if (!fs.existsSync(intelPath)) {
132
- return init(basePath, { force: true });
133
- }
134
-
135
- const startTime = Date.now();
136
-
137
- let intelJson;
138
- try {
139
- intelJson = await binary.runAnalyzerAsync([
140
- 'repo-intel', 'update',
141
- '--map-file', intelPath,
142
- basePath
143
- ]);
144
- } catch (e) {
145
- return {
146
- success: false,
147
- error: 'agent-analyzer repo-intel update failed: ' + e.message
148
- };
149
- }
150
-
151
- let intel;
152
- try {
153
- intel = JSON.parse(intelJson);
154
- } catch (e) {
155
- return {
156
- success: false,
157
- error: 'Failed to parse repo-intel update output: ' + e.message
158
- };
159
- }
160
-
161
- try {
162
- writeJsonAtomic(intelPath, intel);
163
- } catch {
164
- // Non-fatal
165
- }
166
-
167
- const map = converter.convertIntelToRepoMap(intel);
168
- map.stats.scanDurationMs = Date.now() - startTime;
169
- cache.save(basePath, map);
170
-
171
- return {
172
- success: true,
173
- map,
174
- summary: {
175
- files: Object.keys(map.files).length,
176
- symbols: map.stats.totalSymbols,
177
- duration: map.stats.scanDurationMs
178
- }
179
- };
180
- }
181
-
182
- /**
183
- * Get repo map status
184
- * @param {string} basePath - Repository root path
185
- * @returns {{exists: boolean, status?: Object}}
186
- */
187
- function status(basePath) {
188
- const map = cache.load(basePath);
189
- if (!map) {
190
- return { exists: false };
191
- }
192
-
193
- const staleness = updater.checkStaleness(basePath, map);
194
-
195
- let branch;
196
- try {
197
- branch = execFileSync('git', ['rev-parse', '--abbrev-ref', 'HEAD'], { cwd: basePath, encoding: 'utf8' }).trim();
198
- } catch {
199
- // Non-fatal
200
- }
201
-
202
- return {
203
- exists: true,
204
- status: {
205
- generated: map.generated,
206
- updated: map.updated,
207
- commit: map.git?.commit,
208
- branch,
209
- files: Object.keys(map.files).length,
210
- symbols: map.stats?.totalSymbols || 0,
211
- languages: map.project?.languages || [],
212
- staleness
213
- }
214
- };
215
- }
216
-
217
- /**
218
- * Load repo map (if exists)
219
- * @param {string} basePath - Repository root path
220
- * @returns {Object|null}
221
- */
222
- function load(basePath) {
223
- return cache.load(basePath);
224
- }
225
-
226
- /**
227
- * Check if repo map exists
228
- * @param {string} basePath - Repository root path
229
- * @returns {boolean}
230
- */
231
- function exists(basePath) {
232
- return cache.exists(basePath);
233
- }
234
-
235
- /**
236
- * Check if agent-analyzer is available (compat alias for checkInstalled).
237
- * Previously checked ast-grep; now checks agent-analyzer.
238
- * @returns {Promise<{found: boolean, version?: string, tool: string}>}
239
- */
240
- async function checkAstGrepInstalled() {
241
- return installer.checkInstalled();
242
- }
243
-
244
- /**
245
- * Get install instructions (compat alias).
246
- * @returns {string}
247
- */
248
- function getInstallInstructions() {
249
- return installer.getInstallInstructions();
250
- }
17
+ const repoIntel = require('../repo-intel');
251
18
 
252
19
  module.exports = {
253
- init,
254
- update,
255
- status,
256
- load,
257
- exists,
258
- checkAstGrepInstalled,
259
- getInstallInstructions,
260
-
261
- // Re-export submodules for advanced usage
262
- installer,
263
- cache,
264
- updater
20
+ init: repoIntel.init,
21
+ update: repoIntel.update,
22
+ status: repoIntel.status,
23
+ load: repoIntel.load,
24
+ exists: repoIntel.exists,
25
+ checkAstGrepInstalled: repoIntel.checkAstGrepInstalled,
26
+ getInstallInstructions: repoIntel.getInstallInstructions,
27
+ installer: repoIntel.installer,
28
+ cache: repoIntel.cache,
29
+ updater: repoIntel.updater
265
30
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentsys",
3
- "version": "5.13.4",
3
+ "version": "6.0.0",
4
4
  "description": "A modular runtime and orchestration system for AI agents - works with Claude Code, OpenCode, and Codex CLI",
5
5
  "main": "lib/platform/detect-platform.js",
6
6
  "type": "commonjs",