@vodmal/vdx-cli 0.2.0 → 0.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/README.md CHANGED
@@ -1,51 +1,63 @@
1
- # vdx-cli — Native predicate evaluator (v0.1)
1
+ # @vodmal/vdx-cli — vdx evaluator + MCP server
2
2
 
3
- Минимальный аудит-движок для рубрики `vdx-rubric-vodmal`. Шаг C плана
4
- реализации (см. `../docs/decisions.md` D10 — нативный оценщик, не OPA).
3
+ Native predicate evaluator for `vdx-rubric-vodmal` + MCP stdio server for the
4
+ Claude Code `vdx` plugin. Decision basis: [docs/decisions.md](../docs/decisions.md)
5
+ D10 (native evaluator, not OPA).
5
6
 
6
- ## Установка
7
+ Published on npm as **[@vodmal/vdx-cli](https://www.npmjs.com/package/@vodmal/vdx-cli)**.
8
+
9
+ ## Install
7
10
 
8
11
  ```bash
9
- cd "$(realpath .)"
10
- npm install
12
+ # global install
13
+ npm install -g @vodmal/vdx-cli
14
+
15
+ # or one-shot via npx (no install)
16
+ npx -y -p @vodmal/vdx-cli vdx audit /path/to/project
11
17
  ```
12
18
 
13
- ## Запуск
19
+ ## Use
14
20
 
15
21
  ```bash
16
- npx tsx src/index.ts audit /path/to/project
17
- # или
18
- npm run audit -- /path/to/project --json
22
+ vdx audit <project-path> [--json] [--rubric <path>] [--stack <id>]
23
+ vdx init <project-path> [--baseline github.com/org/repo@vX.Y] [--dry-run] [--force]
24
+ vdx-mcp --project <path> # MCP stdio server (used by the plugin)
19
25
  ```
20
26
 
21
- По умолчанию рубрика читается из
22
- `/Users/vdm/AI Projects/vdx-rubric-vodmal/vdx-rubric.yaml`. Override:
23
- `--rubric /alt/path.yaml`.
27
+ By default the bundled `rubric/vdx-rubric.yaml` is used (a mirror of canonical
28
+ [vdx-rubric-vodmal](https://github.com/VoDmAl/vdx-rubric-vodmal) at the time of
29
+ each CLI release). Override via `--rubric <path>` or the env var `VDX_RUBRIC`.
24
30
 
25
- ## Smoke-тест
31
+ ## Dev
26
32
 
27
33
  ```bash
28
- npm run smoke
34
+ git clone https://github.com/VoDmAl/vdx
35
+ cd vdx/cli
36
+ npm install
37
+ npm run audit -- /path/to/project --json
38
+ npm run smoke # gauge against 3 calibration references
39
+ npm run typecheck
29
40
  ```
30
41
 
31
- Прогоняет аудит на трёх калибровочных референсах
32
- (telegram / t23b / bookmap). Ожидаемо все capped at L2 на оси `ci`.
33
-
34
- ## Структура
42
+ ## Structure
35
43
 
36
- - `src/rubric.ts` — типы + YAML-загрузчик
37
- - `src/manifest.ts` — парсинг `[vdx]` блока в `mise.toml` + `.vdx-overrides.yml`
38
- - `src/facts.ts` — fact source loaders (tasks, packages, configs)
39
- - `src/predicates.ts` — registry предикатов (v0.1: 11 функций)
40
- - `src/evaluator.ts` — рекурсивный evaluator + сахарная нотация
41
- - `src/scoring.ts` — delta-style для уровней, flags для гибкой оси
42
- - `src/audit.ts` — оркестратор: применяет overrides + считает уровень (D7)
43
- - `src/report.ts` — markdown / JSON формат отчёта
44
+ - `src/rubric.ts` — types + YAML loader
45
+ - `src/manifest.ts` — parser for `[vdx]` block in `mise.toml` + `.vdx-overrides.yml`
46
+ - `src/facts.ts` — fact source loaders (tasks, packages, configs, sub-package detection)
47
+ - `src/predicates.ts` — predicate registry (11 functions)
48
+ - `src/evaluator.ts` — recursive evaluator + sugar notation
49
+ - `src/scoring.ts` — delta-style levels, flags for orthogonal axes
50
+ - `src/audit.ts` — orchestrator: overrides + applies_to filter + subpackage-ctx
51
+ - `src/report.ts` — markdown / JSON output
44
52
  - `src/index.ts` — CLI entry
53
+ - `src/mcp-server.ts` — MCP stdio server (9 tools)
54
+ - `src/defaults.ts` — bundled rubric resolution
55
+ - `bin/vdx.cjs`, `bin/vdx-mcp.cjs` — Node wrappers (tsx ESM loader in-process)
45
56
 
46
- ## Что НЕ реализовано в v0.1
57
+ ## Not implemented yet
47
58
 
48
- - `config_value`, `command_succeeds` предикаты — заглушки с warning.
49
- - Загрузка baseline из git-репо по `baseline:` ссылке — пока только local file.
50
- - Watermark drift (фаза 2 из drift-algorithm.md).
51
- - MCP-server обёртка (D6 — следующий шаг).
59
+ - `config_value`/`command_succeeds` predicates are stubs (warning at evaluation).
60
+ - Baseline loading from a git ref is documented but evaluator still reads file
61
+ paths only — `baseline:` in `mise.toml` is recorded but does not auto-fetch.
62
+ - Watermark drift (phase 2 of `drift-algorithm.md`).
63
+ - O25/O26/O27/O33/O34 — see [docs/decisions.md](../docs/decisions.md).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vodmal/vdx-cli",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "vdx — unified lifecycle interface (up/down/build/test/check/fix) + versioned maturity audit with drift detection. Pairs with the vdx Claude Code plugin.",
5
5
  "keywords": [
6
6
  "vdx",
@@ -23,8 +23,8 @@
23
23
  },
24
24
  "type": "module",
25
25
  "bin": {
26
- "vdx": "./bin/vdx.cjs",
27
- "vdx-mcp": "./bin/vdx-mcp.cjs"
26
+ "vdx": "bin/vdx.cjs",
27
+ "vdx-mcp": "bin/vdx-mcp.cjs"
28
28
  },
29
29
  "files": [
30
30
  "src",
package/src/audit.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as fs from 'node:fs';
2
2
  import * as path from 'node:path';
3
3
  import type { Rubric, LevelName } from './rubric.ts';
4
- import { findSubPackages, type Ctx } from './facts.ts';
4
+ import { findSubPackages, stackForDir, type Ctx } from './facts.ts';
5
5
  import type { Override, VdxManifest } from './manifest.ts';
6
6
  import { evalAxis, projectLevel, type AxisResult } from './scoring.ts';
7
7
 
@@ -33,12 +33,14 @@ function resolveSubpackageCtx(
33
33
  manifest: VdxManifest | null,
34
34
  ): { ctx: Ctx; relPath: string | null } {
35
35
  let relPath: string | null = null;
36
+ let subpackageStack: string | null = null;
36
37
 
37
38
  if (manifest?.primary_subpackage) {
38
39
  const p = manifest.primary_subpackage;
39
40
  const abs = path.join(ctx.projectRoot, p);
40
41
  if (fs.existsSync(abs)) {
41
42
  relPath = p;
43
+ subpackageStack = stackForDir(abs);
42
44
  } else {
43
45
  process.stderr.write(
44
46
  `warning: primary_subpackage "${p}" does not exist — falling back to root\n`,
@@ -49,6 +51,12 @@ function resolveSubpackageCtx(
49
51
  const matching = subs.filter((s) => s.stack === ctx.stack);
50
52
  if (matching.length === 1) {
51
53
  relPath = matching[0]!.relPath;
54
+ subpackageStack = matching[0]!.stack;
55
+ } else if (matching.length === 0 && subs.length === 1) {
56
+ // O33: single sub-package with a stack different from ctx.stack —
57
+ // adopt it so applies_to-axes for that stack can evaluate.
58
+ relPath = subs[0]!.relPath;
59
+ subpackageStack = subs[0]!.stack;
52
60
  }
53
61
  }
54
62
 
@@ -56,7 +64,7 @@ function resolveSubpackageCtx(
56
64
  return {
57
65
  ctx: {
58
66
  projectRoot: path.join(ctx.projectRoot, relPath),
59
- stack: ctx.stack,
67
+ stack: subpackageStack ?? ctx.stack,
60
68
  cache: new Map(),
61
69
  },
62
70
  relPath,
@@ -96,7 +104,8 @@ export function audit(
96
104
  });
97
105
  continue;
98
106
  }
99
- if (axis.applies_to && !axis.applies_to.includes(ctx.stack)) {
107
+ const evalCtx = axis.applies_to ? subpackageCtx : ctx;
108
+ if (axis.applies_to && !axis.applies_to.includes(evalCtx.stack)) {
100
109
  perAxis.push({
101
110
  axis_id: axis.id,
102
111
  class: axis.class,
@@ -106,7 +115,6 @@ export function audit(
106
115
  });
107
116
  continue;
108
117
  }
109
- const evalCtx = axis.applies_to ? subpackageCtx : ctx;
110
118
  const achieved = evalAxis(axis, evalCtx);
111
119
  const ov = overrideByAxis.get(axis.id);
112
120
  const target = (ov?.target as LevelName) ?? axis.default_target;
package/src/facts.ts CHANGED
@@ -216,7 +216,7 @@ const MANIFEST_TO_STACK: Array<[string, string]> = [
216
216
  ['requirements.txt', 'python'],
217
217
  ];
218
218
 
219
- function stackForDir(dir: string): string | null {
219
+ export function stackForDir(dir: string): string | null {
220
220
  for (const [manifest, stack] of MANIFEST_TO_STACK) {
221
221
  if (fs.existsSync(path.join(dir, manifest))) return stack;
222
222
  }