aios-core 4.3.0 → 4.4.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.
- package/.aios-core/core/code-intel/code-intel-client.js +19 -5
- package/.aios-core/core/code-intel/hook-runtime.js +186 -0
- package/.aios-core/core/code-intel/index.js +2 -0
- package/.aios-core/core/code-intel/providers/code-graph-provider.js +8 -0
- package/.aios-core/core/code-intel/providers/provider-interface.js +9 -0
- package/.aios-core/core/code-intel/providers/registry-provider.js +515 -0
- package/.aios-core/core/doctor/checks/code-intel.js +95 -21
- package/.aios-core/core/doctor/checks/hooks-claude-count.js +15 -4
- package/.aios-core/core/doctor/checks/ide-sync.js +24 -7
- package/.aios-core/core/synapse/memory/memory-bridge.js +17 -43
- package/.aios-core/core/synapse/memory/synapse-memory-provider.js +201 -0
- package/.aios-core/data/entity-registry.yaml +836 -812
- package/.aios-core/data/workflow-chains.yaml +156 -0
- package/.aios-core/development/agents/aios-master.md +17 -10
- package/.aios-core/development/agents/analyst.md +17 -10
- package/.aios-core/development/agents/architect.md +17 -10
- package/.aios-core/development/agents/data-engineer.md +17 -10
- package/.aios-core/development/agents/dev.md +17 -10
- package/.aios-core/development/agents/devops.md +22 -10
- package/.aios-core/development/agents/pm.md +17 -10
- package/.aios-core/development/agents/po.md +17 -10
- package/.aios-core/development/agents/qa.md +17 -10
- package/.aios-core/development/agents/sm.md +17 -10
- package/.aios-core/development/agents/squad-creator.md +18 -9
- package/.aios-core/development/agents/ux-design-expert.md +16 -9
- package/.aios-core/development/tasks/apply-qa-fixes.md +7 -0
- package/.aios-core/development/tasks/architect-analyze-impact.md +8 -1
- package/.aios-core/development/tasks/brownfield-create-story.md +7 -0
- package/.aios-core/development/tasks/build-autonomous.md +7 -0
- package/.aios-core/development/tasks/create-deep-research-prompt.md +7 -0
- package/.aios-core/development/tasks/create-next-story.md +7 -0
- package/.aios-core/development/tasks/create-suite.md +7 -0
- package/.aios-core/development/tasks/dev-develop-story.md +8 -0
- package/.aios-core/development/tasks/execute-checklist.md +7 -0
- package/.aios-core/development/tasks/github-devops-github-pr-automation.md +7 -0
- package/.aios-core/development/tasks/github-devops-pre-push-quality-gate.md +7 -0
- package/.aios-core/development/tasks/po-close-story.md +7 -0
- package/.aios-core/development/tasks/qa-create-fix-request.md +7 -0
- package/.aios-core/development/tasks/qa-fix-issues.md +7 -0
- package/.aios-core/development/tasks/qa-gate.md +8 -0
- package/.aios-core/development/tasks/qa-review-story.md +8 -0
- package/.aios-core/development/tasks/release-management.md +7 -0
- package/.aios-core/development/tasks/spec-critique.md +8 -0
- package/.aios-core/development/tasks/spec-gather-requirements.md +7 -0
- package/.aios-core/development/tasks/spec-write-spec.md +5 -0
- package/.aios-core/development/tasks/validate-next-story.md +7 -0
- package/.aios-core/install-manifest.yaml +105 -89
- package/.aios-core/product/templates/ide-rules/claude-rules.md +48 -0
- package/package.json +1 -1
- package/packages/installer/src/config/templates/core-config-template.js +25 -0
- package/packages/installer/src/wizard/ide-config-generator.js +24 -3
- package/packages/installer/tests/unit/artifact-copy-pipeline/artifact-copy-pipeline.test.js +15 -5
- package/packages/installer/tests/unit/claude-md-template-v5/claude-md-template-v5.test.js +3 -3
- package/packages/installer/tests/unit/doctor/doctor-checks.test.js +68 -9
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const { CodeGraphProvider } = require('./providers/code-graph-provider');
|
|
4
|
+
const { RegistryProvider } = require('./providers/registry-provider');
|
|
4
5
|
|
|
5
6
|
// --- Constants (adjustable, not hardcoded magic numbers) ---
|
|
6
7
|
const CIRCUIT_BREAKER_THRESHOLD = 3;
|
|
@@ -51,10 +52,19 @@ class CodeIntelClient {
|
|
|
51
52
|
|
|
52
53
|
/**
|
|
53
54
|
* Register default providers based on configuration.
|
|
55
|
+
* Provider priority: RegistryProvider FIRST (native, T1), then CodeGraphProvider (MCP, T3).
|
|
56
|
+
* First provider with isAvailable() === true wins.
|
|
54
57
|
* @private
|
|
55
58
|
*/
|
|
56
59
|
_registerDefaultProviders(options) {
|
|
57
|
-
//
|
|
60
|
+
// RegistryProvider — native, T1, always available when registry exists
|
|
61
|
+
const registryProvider = new RegistryProvider({
|
|
62
|
+
registryPath: options.registryPath || null,
|
|
63
|
+
projectRoot: options.projectRoot || null,
|
|
64
|
+
});
|
|
65
|
+
this._providers.push(registryProvider);
|
|
66
|
+
|
|
67
|
+
// Code Graph MCP — T3, available when mcpCallFn is configured
|
|
58
68
|
const codeGraphProvider = new CodeGraphProvider({
|
|
59
69
|
mcpServerName: options.mcpServerName || 'code-graph',
|
|
60
70
|
mcpCallFn: options.mcpCallFn || null,
|
|
@@ -74,6 +84,7 @@ class CodeIntelClient {
|
|
|
74
84
|
|
|
75
85
|
/**
|
|
76
86
|
* Detect and return the first available provider.
|
|
87
|
+
* Uses polymorphic isAvailable() — first provider that returns true wins.
|
|
77
88
|
* @returns {import('./providers/provider-interface').CodeIntelProvider|null}
|
|
78
89
|
* @private
|
|
79
90
|
*/
|
|
@@ -81,10 +92,13 @@ class CodeIntelClient {
|
|
|
81
92
|
if (this._activeProvider) return this._activeProvider;
|
|
82
93
|
|
|
83
94
|
for (const provider of this._providers) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
95
|
+
try {
|
|
96
|
+
if (typeof provider.isAvailable === 'function' && provider.isAvailable()) {
|
|
97
|
+
this._activeProvider = provider;
|
|
98
|
+
return provider;
|
|
99
|
+
}
|
|
100
|
+
} catch (_err) {
|
|
101
|
+
// Provider threw during availability check — treat as unavailable
|
|
88
102
|
}
|
|
89
103
|
}
|
|
90
104
|
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const { RegistryProvider } = require('./providers/registry-provider');
|
|
5
|
+
|
|
6
|
+
/** Cached provider instance (survives across hook invocations in same process). */
|
|
7
|
+
let _provider = null;
|
|
8
|
+
let _providerRoot = null;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Get or create a RegistryProvider singleton.
|
|
12
|
+
* Resets if projectRoot changes between calls.
|
|
13
|
+
* @param {string} projectRoot - Project root directory
|
|
14
|
+
* @returns {RegistryProvider}
|
|
15
|
+
*/
|
|
16
|
+
function getProvider(projectRoot) {
|
|
17
|
+
if (!_provider || _providerRoot !== projectRoot) {
|
|
18
|
+
_provider = new RegistryProvider({ projectRoot });
|
|
19
|
+
_providerRoot = projectRoot;
|
|
20
|
+
}
|
|
21
|
+
return _provider;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Resolve code intelligence context for a file being written/edited.
|
|
26
|
+
*
|
|
27
|
+
* Queries RegistryProvider for:
|
|
28
|
+
* - Entity definition (path, layer, purpose, type)
|
|
29
|
+
* - References (files that use this entity)
|
|
30
|
+
* - Dependencies (entities this file depends on)
|
|
31
|
+
*
|
|
32
|
+
* @param {string} filePath - Absolute or relative path to the target file
|
|
33
|
+
* @param {string} cwd - Project root / working directory
|
|
34
|
+
* @returns {{ entity: Object|null, references: Array|null, dependencies: Object|null }|null}
|
|
35
|
+
*/
|
|
36
|
+
async function resolveCodeIntel(filePath, cwd) {
|
|
37
|
+
if (!filePath || !cwd) return null;
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
const provider = getProvider(cwd);
|
|
41
|
+
if (!provider.isAvailable()) return null;
|
|
42
|
+
|
|
43
|
+
// Normalize to relative path (registry uses relative paths)
|
|
44
|
+
let relativePath = filePath;
|
|
45
|
+
if (path.isAbsolute(filePath)) {
|
|
46
|
+
relativePath = path.relative(cwd, filePath).replace(/\\/g, '/');
|
|
47
|
+
} else {
|
|
48
|
+
relativePath = filePath.replace(/\\/g, '/');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Run all three queries in parallel
|
|
52
|
+
const [definition, references, dependencies] = await Promise.all([
|
|
53
|
+
provider.findDefinition(relativePath),
|
|
54
|
+
provider.findReferences(relativePath),
|
|
55
|
+
provider.analyzeDependencies(relativePath),
|
|
56
|
+
]);
|
|
57
|
+
|
|
58
|
+
// Treat empty dependency graph as no data
|
|
59
|
+
const hasUsefulDeps = dependencies && dependencies.nodes && dependencies.nodes.length > 0;
|
|
60
|
+
|
|
61
|
+
// If nothing found at all, try searching by the file basename
|
|
62
|
+
if (!definition && !references && !hasUsefulDeps) {
|
|
63
|
+
const basename = path.basename(relativePath, path.extname(relativePath));
|
|
64
|
+
const fallbackDef = await provider.findDefinition(basename);
|
|
65
|
+
if (!fallbackDef) return null;
|
|
66
|
+
|
|
67
|
+
const [fallbackRefs, fallbackDeps] = await Promise.all([
|
|
68
|
+
provider.findReferences(basename),
|
|
69
|
+
provider.analyzeDependencies(basename),
|
|
70
|
+
]);
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
entity: fallbackDef,
|
|
74
|
+
references: fallbackRefs,
|
|
75
|
+
dependencies: fallbackDeps,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
entity: definition,
|
|
81
|
+
references,
|
|
82
|
+
dependencies,
|
|
83
|
+
};
|
|
84
|
+
} catch (_err) {
|
|
85
|
+
// Guard against provider exceptions to avoid unhandled rejections in hook runtime
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Format code intelligence data as XML for injection into Claude context.
|
|
92
|
+
*
|
|
93
|
+
* @param {Object|null} intel - Result from resolveCodeIntel()
|
|
94
|
+
* @param {string} filePath - Target file path (for display)
|
|
95
|
+
* @returns {string|null} XML string or null if no data
|
|
96
|
+
*/
|
|
97
|
+
function formatAsXml(intel, filePath) {
|
|
98
|
+
if (!intel) return null;
|
|
99
|
+
|
|
100
|
+
const { entity, references, dependencies } = intel;
|
|
101
|
+
|
|
102
|
+
// At least one piece of data must exist
|
|
103
|
+
if (!entity && !references && !dependencies) return null;
|
|
104
|
+
|
|
105
|
+
const lines = ['<code-intel-context>'];
|
|
106
|
+
lines.push(` <target-file>${escapeXml(filePath)}</target-file>`);
|
|
107
|
+
|
|
108
|
+
// Entity definition
|
|
109
|
+
if (entity) {
|
|
110
|
+
lines.push(' <existing-entity>');
|
|
111
|
+
if (entity.file) lines.push(` <path>${escapeXml(entity.file)}</path>`);
|
|
112
|
+
if (entity.context) lines.push(` <purpose>${escapeXml(entity.context)}</purpose>`);
|
|
113
|
+
lines.push(' </existing-entity>');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// References
|
|
117
|
+
if (references && references.length > 0) {
|
|
118
|
+
// Deduplicate by file path
|
|
119
|
+
const uniqueRefs = [];
|
|
120
|
+
const seen = new Set();
|
|
121
|
+
for (const ref of references) {
|
|
122
|
+
if (ref.file && !seen.has(ref.file)) {
|
|
123
|
+
seen.add(ref.file);
|
|
124
|
+
uniqueRefs.push(ref);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
lines.push(` <referenced-by count="${uniqueRefs.length}">`);
|
|
129
|
+
for (const ref of uniqueRefs.slice(0, 15)) {
|
|
130
|
+
const ctx = ref.context ? ` context="${escapeXml(ref.context)}"` : '';
|
|
131
|
+
lines.push(` <ref file="${escapeXml(ref.file)}"${ctx} />`);
|
|
132
|
+
}
|
|
133
|
+
if (uniqueRefs.length > 15) {
|
|
134
|
+
lines.push(` <!-- ...and ${uniqueRefs.length - 15} more -->`);
|
|
135
|
+
}
|
|
136
|
+
lines.push(' </referenced-by>');
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Dependencies
|
|
140
|
+
if (dependencies && dependencies.nodes && dependencies.nodes.length > 1) {
|
|
141
|
+
// First node is the target itself, rest are dependencies
|
|
142
|
+
const depNodes = dependencies.nodes.slice(1);
|
|
143
|
+
lines.push(` <dependencies count="${depNodes.length}">`);
|
|
144
|
+
for (const dep of depNodes.slice(0, 10)) {
|
|
145
|
+
const layer = dep.layer ? ` layer="${dep.layer}"` : '';
|
|
146
|
+
lines.push(` <dep name="${escapeXml(dep.name)}"${layer} />`);
|
|
147
|
+
}
|
|
148
|
+
if (depNodes.length > 10) {
|
|
149
|
+
lines.push(` <!-- ...and ${depNodes.length - 10} more -->`);
|
|
150
|
+
}
|
|
151
|
+
lines.push(' </dependencies>');
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
lines.push('</code-intel-context>');
|
|
155
|
+
return lines.join('\n');
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Escape special XML characters.
|
|
160
|
+
* @param {string} str
|
|
161
|
+
* @returns {string}
|
|
162
|
+
*/
|
|
163
|
+
function escapeXml(str) {
|
|
164
|
+
if (!str) return '';
|
|
165
|
+
return String(str)
|
|
166
|
+
.replace(/&/g, '&')
|
|
167
|
+
.replace(/</g, '<')
|
|
168
|
+
.replace(/>/g, '>')
|
|
169
|
+
.replace(/"/g, '"');
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Reset cached provider (for testing).
|
|
174
|
+
*/
|
|
175
|
+
function _resetForTesting() {
|
|
176
|
+
_provider = null;
|
|
177
|
+
_providerRoot = null;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
module.exports = {
|
|
181
|
+
resolveCodeIntel,
|
|
182
|
+
formatAsXml,
|
|
183
|
+
escapeXml,
|
|
184
|
+
getProvider,
|
|
185
|
+
_resetForTesting,
|
|
186
|
+
};
|
|
@@ -4,6 +4,7 @@ const { CodeIntelClient } = require('./code-intel-client');
|
|
|
4
4
|
const { CodeIntelEnricher } = require('./code-intel-enricher');
|
|
5
5
|
const { CodeIntelProvider, CAPABILITIES } = require('./providers/provider-interface');
|
|
6
6
|
const { CodeGraphProvider, TOOL_MAP } = require('./providers/code-graph-provider');
|
|
7
|
+
const { RegistryProvider } = require('./providers/registry-provider');
|
|
7
8
|
|
|
8
9
|
// Singleton client instance (lazily initialized)
|
|
9
10
|
let _defaultClient = null;
|
|
@@ -127,6 +128,7 @@ module.exports = {
|
|
|
127
128
|
CodeIntelEnricher,
|
|
128
129
|
CodeIntelProvider,
|
|
129
130
|
CodeGraphProvider,
|
|
131
|
+
RegistryProvider,
|
|
130
132
|
|
|
131
133
|
// Constants
|
|
132
134
|
CAPABILITIES,
|
|
@@ -29,6 +29,14 @@ class CodeGraphProvider extends CodeIntelProvider {
|
|
|
29
29
|
this._mcpServerName = options.mcpServerName || 'code-graph';
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
/**
|
|
33
|
+
* Code Graph provider is available when mcpCallFn is configured.
|
|
34
|
+
* @returns {boolean}
|
|
35
|
+
*/
|
|
36
|
+
isAvailable() {
|
|
37
|
+
return typeof this.options.mcpCallFn === 'function';
|
|
38
|
+
}
|
|
39
|
+
|
|
32
40
|
/**
|
|
33
41
|
* Execute an MCP tool call via the configured server.
|
|
34
42
|
* This method is the single point of MCP communication — all capabilities route through here.
|
|
@@ -14,6 +14,15 @@ class CodeIntelProvider {
|
|
|
14
14
|
this.options = options;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Check if this provider is available and can serve requests.
|
|
19
|
+
* Subclasses MUST override this to indicate availability.
|
|
20
|
+
* @returns {boolean}
|
|
21
|
+
*/
|
|
22
|
+
isAvailable() {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
|
|
17
26
|
/**
|
|
18
27
|
* Locate the definition of a symbol.
|
|
19
28
|
* @param {string} symbol - Symbol name to find
|