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.
@@ -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(cwd, parsed.pack);
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, cwd, sensor.assets);
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.0",
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": "^10.4.1",
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",