diff --git a/.aiox-core/core/code-intel/registry-syncer.js b/.aiox-core/core/code-intel/registry-syncer.js index 450e378233..876ac1a5a2 100644 --- a/.aiox-core/core/code-intel/registry-syncer.js +++ b/.aiox-core/core/code-intel/registry-syncer.js @@ -74,6 +74,9 @@ class RegistrySyncer { async sync(options = {}) { const isFull = options.full === true; + // Bootstrap the lazy singleton before checking module-level provider availability. + this._getClient(); + // AC5: Fallback — check provider availability first if (!this._isProviderAvailable()) { this._logger('[registry-syncer] No code intelligence provider available, skipping enrichment'); diff --git a/.aiox-core/data/entity-registry.yaml b/.aiox-core/data/entity-registry.yaml index 1cdcfd85c6..2989de3361 100644 --- a/.aiox-core/data/entity-registry.yaml +++ b/.aiox-core/data/entity-registry.yaml @@ -1,6 +1,6 @@ metadata: version: 1.0.0 - lastUpdated: '2026-05-09T07:56:57.030Z' + lastUpdated: '2026-05-10T16:26:31.587Z' entityCount: 757 checksumAlgorithm: sha256 resolutionRate: 100 @@ -8319,17 +8319,17 @@ entities: usedBy: - sync-registry-intel dependencies: - - code-intel - registry-loader externalDeps: [] - plannedDeps: [] + plannedDeps: + - code-intel-index lifecycle: production adaptability: score: 0.4 constraints: [] extensionPoints: [] - checksum: sha256:701102a519457938d5b9187b75a1f97d85cb5466cef23bce5edfb48b34c69ab8 - lastVerified: '2026-03-11T00:48:55.875Z' + checksum: sha256:0fc20a7f90fc1ac2078878267db64517fd2ae75d8d2a81101d0cac77d1bf6458 + lastVerified: '2026-05-10T16:26:31.572Z' config-cache: path: .aiox-core/core/config/config-cache.js layer: L1 @@ -10673,7 +10673,6 @@ entities: - github-devops-pre-push-quality-gate - plan-create-context - plan-create-implementation - - registry-syncer - code-intel-source - metrics-source dependencies: [] diff --git a/.aiox-core/install-manifest.yaml b/.aiox-core/install-manifest.yaml index b9fbed98b5..23ea8a6124 100644 --- a/.aiox-core/install-manifest.yaml +++ b/.aiox-core/install-manifest.yaml @@ -8,7 +8,7 @@ # - File types for categorization # version: 5.1.17 -generated_at: "2026-05-10T01:14:38.554Z" +generated_at: "2026-05-10T16:27:34.757Z" generator: scripts/generate-install-manifest.js file_count: 1128 files: @@ -237,9 +237,9 @@ files: type: core size: 15619 - path: core/code-intel/registry-syncer.js - hash: sha256:701102a519457938d5b9187b75a1f97d85cb5466cef23bce5edfb48b34c69ab8 + hash: sha256:0fc20a7f90fc1ac2078878267db64517fd2ae75d8d2a81101d0cac77d1bf6458 type: core - size: 10891 + size: 11003 - path: core/config/config-cache.js hash: sha256:9f3c3f90f574d5f49dd94592ab28109465d025b3a740d8639ab781c2560c12ab type: core @@ -1297,9 +1297,9 @@ files: type: data size: 9590 - path: data/entity-registry.yaml - hash: sha256:4b701001f233800095b8830d8406209d1074bb2847fd5c279261b52452a2d71d + hash: sha256:84acf809f112cb726710a9878904db6b9d5c0eb487a2e578de25ede0c2177c5e type: data - size: 529270 + size: 529247 - path: data/learned-patterns.yaml hash: sha256:24ac0b160615583a0ff783d3da8af80b7f94191575d6db2054ec8e10a3f945dc type: data @@ -3697,9 +3697,9 @@ files: type: monitor size: 818 - path: package.json - hash: sha256:9fdf0dcee2dcec6c0643634ee384ba181ad077dcff1267d8807434d4cb4809c7 + hash: sha256:049326a853153ea930a49c1d083d5fa9a5eb5d05c3198f0322dbd831fe151b2e type: other - size: 2495 + size: 2529 - path: product/checklists/accessibility-wcag-checklist.md hash: sha256:56126182b25e9b7bdde43f75315e33167eb49b1f9a9cb0e9a37bc068af40aeab type: checklist diff --git a/.aiox-core/package.json b/.aiox-core/package.json index f6c9b4cba0..ea49119f36 100644 --- a/.aiox-core/package.json +++ b/.aiox-core/package.json @@ -42,6 +42,7 @@ "highlight.js": "^11.9.0", "inquirer": "^8.2.6", "js-yaml": "^4.1.0", + "proper-lockfile": "^4.1.2", "semver": "^7.7.2", "tar": "^7.5.7", "validator": "^13.15.15" @@ -104,4 +105,4 @@ "./docs": "./docs/", "./elicitation": "./elicitation/" } -} \ No newline at end of file +} diff --git a/tests/code-intel/registry-syncer.test.js b/tests/code-intel/registry-syncer.test.js index 45fe96774a..baffee1b82 100644 --- a/tests/code-intel/registry-syncer.test.js +++ b/tests/code-intel/registry-syncer.test.js @@ -3,6 +3,7 @@ const fs = require('fs'); const path = require('path'); const yaml = require('js-yaml'); +const codeIntel = require('../../.aiox-core/core/code-intel'); const { RegistrySyncer, inferRole, ROLE_MAP } = require('../../.aiox-core/core/code-intel/registry-syncer'); // Mock fs module for controlled testing @@ -87,6 +88,8 @@ function createSyncer(options = {}) { describe('RegistrySyncer', () => { beforeEach(() => { jest.clearAllMocks(); + codeIntel.getClient.mockReset(); + codeIntel.isCodeIntelAvailable.mockReset().mockReturnValue(false); // Default fs mocks fs.existsSync.mockReturnValue(true); fs.writeFileSync.mockImplementation(() => {}); @@ -304,6 +307,30 @@ describe('RegistrySyncer', () => { // T5: Fallback sem provider (AC5) describe('Fallback without provider (T5 — AC5)', () => { + it('should bootstrap default client before checking module-level provider availability', async () => { + const logger = jest.fn(); + const mockClient = createMockClient(); + + codeIntel.getClient.mockReturnValue(mockClient); + codeIntel.isCodeIntelAvailable.mockImplementation( + () => codeIntel.getClient.mock.calls.length > 0, + ); + + const syncer = new RegistrySyncer({ + registryPath: '/mock/entity-registry.yaml', + repoRoot: '/mock/repo', + client: null, + logger, + }); + + const stats = await syncer.sync({ full: true }); + + expect(codeIntel.getClient).toHaveBeenCalled(); + expect(stats.aborted).toBeUndefined(); + expect(stats.processed).toBe(3); + expect(fs.writeFileSync).toHaveBeenCalled(); + }); + it('should skip enrichment and log message when no provider available', async () => { const logger = jest.fn(); const syncer = new RegistrySyncer({ diff --git a/tests/unit/validate-aiox-core-deps.test.js b/tests/unit/validate-aiox-core-deps.test.js index 5ec751961d..ad179ea0f5 100644 --- a/tests/unit/validate-aiox-core-deps.test.js +++ b/tests/unit/validate-aiox-core-deps.test.js @@ -52,6 +52,12 @@ describe('validate-aiox-core-deps.js (INS-4.12)', () => { expect(pkg.dependencies).toHaveProperty('tar'); }); + test('.aiox-core/package.json includes proper-lockfile for IDS registry updater', () => { + const pkgPath = path.join(PROJECT_ROOT, '.aiox-core', 'package.json'); + const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8')); + expect(pkg.dependencies).toHaveProperty('proper-lockfile'); + }); + test('allowlisted packages (eslint, @babel/*) are not in deps', () => { const pkgPath = path.join(PROJECT_ROOT, '.aiox-core', 'package.json'); const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));