agentic-workflow-manager 8.2.0 → 8.2.1
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/src/commands/sensors/compatibility/live.js +1 -0
- package/dist/src/commands/sensors/compatibility/probe.js +15 -3
- package/dist/src/commands/sensors/status.js +6 -2
- package/dist/tests/commands/sensors/compatibility/probe.test.js +27 -0
- package/dist/tests/commands/sensors/status.test.js +58 -0
- package/package.json +2 -2
|
@@ -85,6 +85,7 @@ async function resolveParsedPackCompatibility(cwd, pack, options = {}) {
|
|
|
85
85
|
environment: variant.command.environment,
|
|
86
86
|
configFiles: evidence.configFiles,
|
|
87
87
|
scripts: evidence.scripts,
|
|
88
|
+
variantArgs: variant.command.args,
|
|
88
89
|
})
|
|
89
90
|
: null;
|
|
90
91
|
sensors[name] = (0, resolve_1.resolveProjectCompatibility)({ ...executionPack, sensors: { [name]: sensor } }, { ...resolutionEvidence, probe: probe ?? undefined }).sensors[name];
|
|
@@ -24,11 +24,23 @@ function commandFor(kind, evidence) {
|
|
|
24
24
|
};
|
|
25
25
|
if (kind === 'version')
|
|
26
26
|
return { ...command, args: ['--version'] };
|
|
27
|
+
// A pack asset is never named the tool's default config filename (e.g.
|
|
28
|
+
// `eslint.config.awm.mjs`, not `eslint.config.js`), so the real command always
|
|
29
|
+
// pins it via an explicit `--config <file>`. Mirroring that same pair here — rather
|
|
30
|
+
// than probing with a bare invocation — is what lets the probe find the config the
|
|
31
|
+
// real run will actually use, for whatever name or tool version is in play.
|
|
27
32
|
if (kind === 'eslint-print-config')
|
|
28
|
-
return { ...command, args: ['--print-config', evidence.configFiles?.[0] ?? 'package.json'] };
|
|
33
|
+
return { ...command, args: [...configFlag(evidence.variantArgs), '--print-config', evidence.configFiles?.[0] ?? 'package.json'] };
|
|
29
34
|
if (kind === 'typescript-show-config')
|
|
30
|
-
return { ...command, args: ['--showConfig'] };
|
|
31
|
-
return { ...command, args: ['--validate'] };
|
|
35
|
+
return { ...command, args: [...configFlag(evidence.variantArgs), '--showConfig'] };
|
|
36
|
+
return { ...command, args: [...configFlag(evidence.variantArgs), '--validate'] };
|
|
37
|
+
}
|
|
38
|
+
/** The `--config <file>` pair from a variant's real command args, if it declares one. */
|
|
39
|
+
function configFlag(variantArgs) {
|
|
40
|
+
if (!variantArgs)
|
|
41
|
+
return [];
|
|
42
|
+
const i = variantArgs.indexOf('--config');
|
|
43
|
+
return i !== -1 && variantArgs[i + 1] !== undefined ? ['--config', variantArgs[i + 1]] : [];
|
|
32
44
|
}
|
|
33
45
|
/** Executes only the closed probe enum. Raw output is intentionally discarded. */
|
|
34
46
|
async function runCompatibilityProbe(probe, evidence, executor = exec_1.runStructuredCommand) {
|
|
@@ -145,10 +145,14 @@ async function computeSensorStatus(cwd = process.cwd()) {
|
|
|
145
145
|
const raw = JSON.parse(fs_1.default.readFileSync(manifestPath, 'utf-8'));
|
|
146
146
|
const parsed = (0, manifest_1.parseSensorManifest)(raw, manifestPath);
|
|
147
147
|
if (parsed.kind === 'v2') {
|
|
148
|
+
// Monorepo support (mirrors run.ts/init.ts): detection and structured-command
|
|
149
|
+
// asset resolution both need to see the real package, not the (possibly
|
|
150
|
+
// unrelated) directory the manifest lives in.
|
|
151
|
+
const projectCwd = parsed.pack.packageRoot ? path_1.default.resolve(cwd, parsed.pack.packageRoot) : cwd;
|
|
148
152
|
const checks = {};
|
|
149
153
|
let compatibility;
|
|
150
154
|
try {
|
|
151
|
-
compatibility = resolveStaticV2Compatibility(
|
|
155
|
+
compatibility = resolveStaticV2Compatibility(projectCwd, parsed.pack);
|
|
152
156
|
}
|
|
153
157
|
catch (error) {
|
|
154
158
|
const detail = error instanceof Error ? error.message : 'live compatibility unavailable';
|
|
@@ -163,7 +167,7 @@ async function computeSensorStatus(cwd = process.cwd()) {
|
|
|
163
167
|
continue;
|
|
164
168
|
}
|
|
165
169
|
checks[name] = staticCompatibilityCheck(sensor, compatibility[name])
|
|
166
|
-
?? checkStructuredCommand(sensor.command,
|
|
170
|
+
?? checkStructuredCommand(sensor.command, projectCwd, sensor.assets);
|
|
167
171
|
}
|
|
168
172
|
return { overall: Object.keys(checks).length > 0 && Object.values(checks).every(check => check.ok) ? 'READY' : 'DEGRADED', pack: parsed.pack.pack, checks };
|
|
169
173
|
}
|
|
@@ -53,4 +53,31 @@ describe('runCompatibilityProbe', () => {
|
|
|
53
53
|
await (0, probe_1.runCompatibilityProbe)({ kind: 'version' }, { ...evidence, toolExecutable, toolResolution: 'python-environment' }, fakeExecutor);
|
|
54
54
|
expect(fakeExecutor).toHaveBeenCalledWith(expect.objectContaining({ executable: toolExecutable, resolution: 'python-environment', args: ['--version'] }), expect.any(Object));
|
|
55
55
|
});
|
|
56
|
+
// A pack asset is never named the tool's own default (e.g. `eslint.config.awm.mjs`,
|
|
57
|
+
// not `eslint.config.js`) so the real command always pins it via `--config`. A probe
|
|
58
|
+
// that omits the same flag never finds a config to load and always reports
|
|
59
|
+
// not-matched — a false negative on every AWM-configured project. The probe must
|
|
60
|
+
// mirror the variant's own `--config` argument, not guess a bare invocation.
|
|
61
|
+
it('carries the variant\'s --config argument into an eslint-print-config probe', async () => {
|
|
62
|
+
await (0, probe_1.runCompatibilityProbe)({ kind: 'eslint-print-config' }, {
|
|
63
|
+
...evidence, variantArgs: ['.', '--config', 'eslint.config.awm.mjs', '--cache', '--format', 'json'],
|
|
64
|
+
}, fakeExecutor);
|
|
65
|
+
expect(fakeExecutor).toHaveBeenCalledWith(expect.objectContaining({ args: ['--config', 'eslint.config.awm.mjs', '--print-config', 'eslint.config.js'] }), expect.any(Object));
|
|
66
|
+
});
|
|
67
|
+
it('carries the variant\'s --config argument into a typescript-show-config probe', async () => {
|
|
68
|
+
await (0, probe_1.runCompatibilityProbe)({ kind: 'typescript-show-config' }, {
|
|
69
|
+
...evidence, variantArgs: ['--config', 'tsconfig.awm.json', '--noEmit'],
|
|
70
|
+
}, fakeExecutor);
|
|
71
|
+
expect(fakeExecutor).toHaveBeenCalledWith(expect.objectContaining({ args: ['--config', 'tsconfig.awm.json', '--showConfig'] }), expect.any(Object));
|
|
72
|
+
});
|
|
73
|
+
it('carries the variant\'s --config argument into a semgrep-validate probe', async () => {
|
|
74
|
+
await (0, probe_1.runCompatibilityProbe)({ kind: 'semgrep-validate' }, {
|
|
75
|
+
...evidence, variantArgs: ['--config', '.semgrep.awm.yml', '--json', '.'],
|
|
76
|
+
}, fakeExecutor);
|
|
77
|
+
expect(fakeExecutor).toHaveBeenCalledWith(expect.objectContaining({ args: ['--config', '.semgrep.awm.yml', '--validate'] }), expect.any(Object));
|
|
78
|
+
});
|
|
79
|
+
it('omits --config from the probe when the variant command declares none', async () => {
|
|
80
|
+
await (0, probe_1.runCompatibilityProbe)({ kind: 'eslint-print-config' }, { ...evidence, variantArgs: ['.', '--cache'] }, fakeExecutor);
|
|
81
|
+
expect(fakeExecutor).toHaveBeenCalledWith(expect.objectContaining({ args: ['--print-config', 'eslint.config.js'] }), expect.any(Object));
|
|
82
|
+
});
|
|
56
83
|
});
|
|
@@ -182,6 +182,64 @@ describe('computeSensorStatus', () => {
|
|
|
182
182
|
expect(result.pack).toBe('python');
|
|
183
183
|
expect(result.checks).toEqual({});
|
|
184
184
|
});
|
|
185
|
+
it('resolves v2 compatibility and structured-command assets against packageRoot in a monorepo', async () => {
|
|
186
|
+
// Monorepo support (mirrors run.ts/init.ts): the manifest lives at the repo
|
|
187
|
+
// root, but package.json/node_modules/the config asset all live under the
|
|
188
|
+
// declared packageRoot subdirectory. Without threading packageRoot through,
|
|
189
|
+
// detection finds no package.json at the manifest's own directory and every
|
|
190
|
+
// sensor reads back "not-applicable" — a false compatibility drift on every
|
|
191
|
+
// check, even immediately after a correct `awm sensors init --package-root`.
|
|
192
|
+
const previousHome = process.env.AWM_HOME;
|
|
193
|
+
const home = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'awm-status-home-'));
|
|
194
|
+
try {
|
|
195
|
+
process.env.AWM_HOME = home;
|
|
196
|
+
const registry = path_1.default.join(home, 'registries', 'baseline');
|
|
197
|
+
fs_1.default.mkdirSync(path_1.default.join(registry, 'sensor-packs', 'js-ts'), { recursive: true });
|
|
198
|
+
fs_1.default.writeFileSync(path_1.default.join(home, 'registries.json'), JSON.stringify([{ name: 'baseline', remote: 'https://example.test/baseline.git' }]));
|
|
199
|
+
fs_1.default.writeFileSync(path_1.default.join(registry, 'sensor-packs', 'js-ts', 'pack.json'), JSON.stringify({
|
|
200
|
+
schemaVersion: 2, name: 'js-ts', description: 'test', detects: ['package.json'],
|
|
201
|
+
coverage: { schemaVersion: 1, classes: { lint: { description: 'lint', detectors: [{ sensor: 'lint' }], remedy: { summary: 'fix lint', command: 'awm sensors init --pack js-ts' } } } },
|
|
202
|
+
sensors: { lint: {
|
|
203
|
+
applicability: { allFiles: ['package.json'] },
|
|
204
|
+
variants: [{
|
|
205
|
+
id: 'eslint-10', priority: 10, certifiedRange: '>=10.0.0 <11.0.0',
|
|
206
|
+
requirements: { tool: 'eslint', toolRange: '>=10.0.0 <11.0.0', runtime: 'node', runtimeRange: '>=0.0.0' },
|
|
207
|
+
assets: ['eslint.config.awm.mjs'], formatter: 'eslint-llm', probe: { kind: 'package-script-present' },
|
|
208
|
+
command: { executable: 'eslint', resolution: 'node-modules-bin', args: ['.', '--config', 'eslint.config.awm.mjs'] },
|
|
209
|
+
}],
|
|
210
|
+
} },
|
|
211
|
+
}));
|
|
212
|
+
const packageDir = path_1.default.join(tmpDir, 'cli');
|
|
213
|
+
fs_1.default.mkdirSync(packageDir, { recursive: true });
|
|
214
|
+
fs_1.default.writeFileSync(path_1.default.join(packageDir, 'package.json'), JSON.stringify({ devDependencies: { eslint: '^10.0.0' }, scripts: { lint: 'eslint .' } }));
|
|
215
|
+
fs_1.default.mkdirSync(path_1.default.join(packageDir, 'node_modules', 'eslint'), { recursive: true });
|
|
216
|
+
fs_1.default.writeFileSync(path_1.default.join(packageDir, 'node_modules', 'eslint', 'package.json'), JSON.stringify({ version: '10.4.1' }));
|
|
217
|
+
fs_1.default.mkdirSync(path_1.default.join(packageDir, 'node_modules', '.bin'), { recursive: true });
|
|
218
|
+
fs_1.default.writeFileSync(path_1.default.join(packageDir, 'node_modules', '.bin', 'eslint'), '');
|
|
219
|
+
fs_1.default.writeFileSync(path_1.default.join(packageDir, 'eslint.config.awm.mjs'), 'export default []');
|
|
220
|
+
fs_1.default.mkdirSync(path_1.default.join(tmpDir, '.awm'), { recursive: true });
|
|
221
|
+
fs_1.default.writeFileSync(path_1.default.join(tmpDir, '.awm', 'sensors.json'), JSON.stringify({
|
|
222
|
+
schemaVersion: 2, pack: 'js-ts', packageRoot: 'cli', registryRoot: registry,
|
|
223
|
+
sensors: { lint: {
|
|
224
|
+
enabled: true, variantId: 'eslint-10', command: { executable: 'eslint', resolution: 'node-modules-bin', args: ['.', '--config', 'eslint.config.awm.mjs'] },
|
|
225
|
+
assets: ['eslint.config.awm.mjs'],
|
|
226
|
+
initializedCompatibility: { state: 'certified', reason: 'range-and-probe', variantId: 'eslint-10', toolVersion: '10.4.1', runtimeVersion: process.versions.node, certifiedRange: '>=10.0.0 <11.0.0', evidence: [] },
|
|
227
|
+
} },
|
|
228
|
+
}));
|
|
229
|
+
const result = await (0, status_1.computeSensorStatus)(tmpDir);
|
|
230
|
+
expect(result.checks.lint).toMatchObject({ ok: true });
|
|
231
|
+
expect(result.overall).toBe('READY');
|
|
232
|
+
expect(runCommand).not.toHaveBeenCalled();
|
|
233
|
+
expect(runStructuredCommand).not.toHaveBeenCalled();
|
|
234
|
+
}
|
|
235
|
+
finally {
|
|
236
|
+
if (previousHome === undefined)
|
|
237
|
+
delete process.env.AWM_HOME;
|
|
238
|
+
else
|
|
239
|
+
process.env.AWM_HOME = previousHome;
|
|
240
|
+
fs_1.default.rmSync(home, { recursive: true, force: true });
|
|
241
|
+
}
|
|
242
|
+
});
|
|
185
243
|
it('marks disabled sensors as ok', async () => {
|
|
186
244
|
fs_1.default.mkdirSync(path_1.default.join(tmpDir, '.awm'), { recursive: true });
|
|
187
245
|
fs_1.default.writeFileSync(path_1.default.join(tmpDir, '.awm', 'sensors.json'), JSON.stringify({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentic-workflow-manager",
|
|
3
|
-
"version": "8.2.
|
|
3
|
+
"version": "8.2.1",
|
|
4
4
|
"main": "dist/src/index.js",
|
|
5
5
|
"bin": {
|
|
6
6
|
"awm": "./dist/src/index.js"
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"@types/node": "^25.3.0",
|
|
57
57
|
"@types/semver": "^7.7.1",
|
|
58
58
|
"dependency-cruiser": "^17.4.3",
|
|
59
|
-
"eslint": "
|
|
59
|
+
"eslint": "10.8.1",
|
|
60
60
|
"jest": "^30.2.0",
|
|
61
61
|
"js-yaml": "4.1.0",
|
|
62
62
|
"ts-jest": "^29.4.6",
|