@vodmal/vdx-cli 0.9.1 → 0.11.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/README.md CHANGED
@@ -36,10 +36,10 @@ sub-optimal.
36
36
  vdx up | down | build | test | check | fix
37
37
 
38
38
  # Maturity audit against the owner baseline rubric
39
- vdx audit <project-path> [--format=ansi|markdown|json] [--rubric <path>] [--stack <id>]
39
+ vdx audit [project-path] [--format=ansi|markdown|json] [--rubric <path>] [--stack <id>] # default: cwd
40
40
 
41
- # Generate mise.toml + AGENTS.md for a project
42
- vdx init <project-path> [--baseline github.com/org/repo@vX.Y] [--stack <id>] [--dry-run] [--force]
41
+ # Generate mise.toml for a project (no AGENTS.md — vdx-discover skill covers Claude Code; pick your own format for other agents)
42
+ vdx init [project-path] [--baseline github.com/org/repo@vX.Y] [--stack <id>] [--dry-run] [--force] # default: cwd
43
43
 
44
44
  # Publish a library (Node MVP; PHP/Python coming in Y.3)
45
45
  vdx publish <patch|minor|major> [--dry-run] [--force]
@@ -54,11 +54,11 @@ vdx-mcp --project <path>
54
54
  **Three quick examples**
55
55
 
56
56
  ```bash
57
- # 1. Score the project I'm standing in
58
- vdx audit .
57
+ # 1. Score the project I'm standing in (no arg → cwd)
58
+ vdx audit
59
59
 
60
60
  # 2. Wire native scripts into the 6 lifecycle verbs, then run one
61
- vdx init . --stack node
61
+ vdx init --stack node
62
62
  vdx test # → mise run test (which calls `vitest run` or whatever was detected)
63
63
 
64
64
  # 3. Ship a new minor release of a Node lib
@@ -89,7 +89,7 @@ npm run typecheck
89
89
  - `src/evaluator.ts` — recursive evaluator + sugar notation
90
90
  - `src/scoring.ts` — delta-style levels, flags for orthogonal axes
91
91
  - `src/audit.ts` — orchestrator: overrides + applies_to filter + subpackage-ctx
92
- - `src/init.ts` — `vdx init` planner (`selectVerbTask` + mise.toml/AGENTS.md renderers)
92
+ - `src/init.ts` — `vdx init` planner (`selectVerbTask` + mise.toml renderer)
93
93
  - `src/run.ts` — `resolveLifecycleVerb` + error renderer (pure logic for `vdx <verb>`)
94
94
  - `src/publish.ts` — `planPublish` (pre-flight) + `executePublish` (bump → npm → git)
95
95
  - `src/report.ts` — markdown / JSON output
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vodmal/vdx-cli",
3
- "version": "0.9.1",
3
+ "version": "0.11.0",
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",
package/src/index.ts CHANGED
@@ -36,8 +36,8 @@ function usage(): never {
36
36
  process.stderr.write(
37
37
  `Usage:
38
38
  vdx <up|down|build|test|check|fix> run lifecycle verb (via mise run <verb>)
39
- vdx audit <project_path> [--rubric <path>] [--stack <stack>] [--format=ansi|markdown|json] [--json]
40
- vdx init <project_path> [--stack <id>] [--baseline <ref>] [--dry-run] [--force]
39
+ vdx audit [project_path] [--rubric <path>] [--stack <stack>] [--format=ansi|markdown|json] [--json] (default: cwd)
40
+ vdx init [project_path] [--stack <id>] [--baseline <ref>] [--dry-run] [--force] (default: cwd)
41
41
  vdx publish <patch|minor|major> [--dry-run] [--force]
42
42
  vdx doctor [--format=ansi|markdown|json] [--json]
43
43
  `,
@@ -80,8 +80,7 @@ function parseArgs(argv: string[]): ParsedArgs {
80
80
  }
81
81
 
82
82
  function cmdAudit(opts: ParsedArgs): void {
83
- const projectArg = opts.positionals[0];
84
- if (!projectArg) usage();
83
+ const projectArg = opts.positionals[0] ?? '.';
85
84
  const projectRoot = path.resolve(projectArg);
86
85
 
87
86
  if (!looksLikeProject(projectRoot)) {
@@ -129,8 +128,7 @@ function cmdAudit(opts: ParsedArgs): void {
129
128
  }
130
129
 
131
130
  function cmdInit(opts: ParsedArgs): void {
132
- const projectArg = opts.positionals[0];
133
- if (!projectArg) usage();
131
+ const projectArg = opts.positionals[0] ?? '.';
134
132
  const projectRoot = path.resolve(projectArg);
135
133
 
136
134
  const baselineFlag = opts.flags.baseline;
@@ -142,21 +140,20 @@ function cmdInit(opts: ParsedArgs): void {
142
140
  ...(stackOverride ? { stack: stackOverride } : {}),
143
141
  });
144
142
 
145
- process.stdout.write(renderPlanSummary(plan));
143
+ const dryRun = Boolean(opts.flags['dry-run']);
144
+ process.stdout.write(renderPlanSummary(plan, { verbose: dryRun }));
146
145
 
147
146
  for (const w of plan.warnings) {
148
147
  process.stderr.write(`\n⚠ ${w}\n`);
149
148
  }
150
149
 
151
- if (opts.flags['dry-run']) {
152
- process.stderr.write('\n[dry-run] mise.toml / AGENTS.md не записаны.\n');
150
+ if (dryRun) {
151
+ process.stderr.write('\n[dry-run] mise.toml не записан.\n');
153
152
  return;
154
153
  }
155
154
  try {
156
155
  writeInit(plan, { force: Boolean(opts.flags.force) });
157
- process.stderr.write(
158
- `\n✓ Записаны:\n ${plan.miseTomlPath}\n ${plan.agentsMdPath}\n`,
159
- );
156
+ process.stderr.write(`\n✓ wrote ${plan.miseTomlPath}\n`);
160
157
  } catch (e: any) {
161
158
  process.stderr.write(`\nerror: ${e?.message ?? String(e)}\n`);
162
159
  process.exit(2);
package/src/init.ts CHANGED
@@ -2,9 +2,7 @@ import * as fs from 'node:fs';
2
2
  import * as path from 'node:path';
3
3
  import {
4
4
  Ctx,
5
- fileExists,
6
5
  readJson,
7
- readText,
8
6
  listAllTasks,
9
7
  autoDetectStack,
10
8
  findSubPackages,
@@ -124,8 +122,6 @@ export interface InitPlan {
124
122
  mappings: VerbMapping[];
125
123
  miseTomlPath: string;
126
124
  miseTomlContent: string;
127
- agentsMdPath: string;
128
- agentsMdContent: string;
129
125
  baseline: string;
130
126
  /** Human-readable advisories for the user — printed to stderr by the CLI. */
131
127
  warnings: string[];
@@ -299,7 +295,7 @@ export function renderMiseToml(
299
295
  stack +
300
296
  '". Замени на php/node/go/python/meta',
301
297
  );
302
- out.push('# и заполни [tasks.*] блоки руками, либо перегенери: vdx init . --stack <id>.');
298
+ out.push('# и заполни [tasks.*] блоки руками, либо перегенери: vdx init --stack <id>.');
303
299
  out.push('');
304
300
  }
305
301
 
@@ -340,52 +336,6 @@ export function renderMiseToml(
340
336
  return out.join('\n');
341
337
  }
342
338
 
343
- const AGENTS_MARKER_OPEN = '<!-- vdx:commands -->';
344
- const AGENTS_MARKER_CLOSE = '<!-- /vdx:commands -->';
345
-
346
- export function renderAgentsCommandsSection(
347
- mappings: VerbMapping[],
348
- baseline: string,
349
- ): string {
350
- const lines: string[] = [];
351
- lines.push(AGENTS_MARKER_OPEN);
352
- lines.push('## Commands');
353
- lines.push('');
354
- lines.push(
355
- `This project follows the vdx lifecycle interface (baseline: ${baseline}).`,
356
- );
357
- lines.push('');
358
- lines.push('| Verb | What it does | Native command |');
359
- lines.push('|------|--------------|----------------|');
360
- for (const m of mappings) {
361
- if (!m.runCommand) {
362
- lines.push(`| \`mise run ${m.verb}\` | ${VERB_DESCRIPTIONS[m.verb]} | _(not mapped)_ |`);
363
- } else {
364
- lines.push(
365
- `| \`mise run ${m.verb}\` | ${VERB_DESCRIPTIONS[m.verb]} | \`${m.runCommand}\` |`,
366
- );
367
- }
368
- }
369
- lines.push(AGENTS_MARKER_CLOSE);
370
- return lines.join('\n');
371
- }
372
-
373
- export function buildAgentsMd(existing: string | null, section: string): string {
374
- if (existing === null) {
375
- return `# AGENTS\n\nProject agent guide.\n\n${section}\n`;
376
- }
377
- const openIdx = existing.indexOf(AGENTS_MARKER_OPEN);
378
- const closeIdx = existing.indexOf(AGENTS_MARKER_CLOSE);
379
- if (openIdx !== -1 && closeIdx !== -1 && closeIdx > openIdx) {
380
- const before = existing.slice(0, openIdx);
381
- const after = existing.slice(closeIdx + AGENTS_MARKER_CLOSE.length);
382
- return before + section + after;
383
- }
384
- // No markers — append.
385
- const sep = existing.endsWith('\n') ? '\n' : '\n\n';
386
- return existing + sep + section + '\n';
387
- }
388
-
389
339
  export function planInit(
390
340
  projectRoot: string,
391
341
  opts: { baseline?: string; stack?: string } = {},
@@ -463,11 +413,6 @@ export function planInit(
463
413
  const baseline = opts.baseline ?? DEFAULT_BASELINE;
464
414
  const miseTomlContent = renderMiseToml(tools, mappings, stack, baseline, primarySubpackage);
465
415
 
466
- const agentsMdPath = path.join(projectRoot, 'AGENTS.md');
467
- const existingAgents = fileExists(rootCtx, 'AGENTS.md') ? readText(rootCtx, 'AGENTS.md') : null;
468
- const section = renderAgentsCommandsSection(mappings, baseline);
469
- const agentsMdContent = buildAgentsMd(existingAgents, section);
470
-
471
416
  let pkgManager: InitPlan['pkgManager'] = null;
472
417
  const pmStack = primarySubpackage ? scanStack : stack;
473
418
  const pmRoot = primarySubpackage ? scanRoot : projectRoot;
@@ -484,8 +429,6 @@ export function planInit(
484
429
  mappings,
485
430
  miseTomlPath: path.join(projectRoot, 'mise.toml'),
486
431
  miseTomlContent,
487
- agentsMdPath,
488
- agentsMdContent,
489
432
  baseline,
490
433
  warnings,
491
434
  };
@@ -498,10 +441,24 @@ export function writeInit(plan: InitPlan, opts: { force: boolean }): void {
498
441
  );
499
442
  }
500
443
  fs.writeFileSync(plan.miseTomlPath, plan.miseTomlContent, 'utf8');
501
- fs.writeFileSync(plan.agentsMdPath, plan.agentsMdContent, 'utf8');
502
444
  }
503
445
 
504
- export function renderPlanSummary(plan: InitPlan): string {
446
+ export function renderPlanSummary(plan: InitPlan, opts: { verbose?: boolean } = {}): string {
447
+ const verbose = opts.verbose === true;
448
+ const mapped = plan.mappings.filter((m) => m.runCommand).length;
449
+ const total = plan.mappings.length;
450
+ const unmatched = plan.mappings.filter((m) => !m.runCommand).map((m) => m.verb);
451
+
452
+ if (!verbose) {
453
+ const lines: string[] = [];
454
+ lines.push(`vdx init: stack=${plan.stack}${plan.stackOverridden ? ' (via --stack)' : ''}, ${mapped}/${total} verbs mapped`);
455
+ if (plan.primarySubpackage) lines.push(` primary subpackage: ${plan.primarySubpackage}`);
456
+ if (unmatched.length > 0) {
457
+ lines.push(` not mapped: ${unmatched.join(', ')} (add [tasks.X] in mise.toml manually)`);
458
+ }
459
+ return lines.join('\n') + '\n';
460
+ }
461
+
505
462
  const lines: string[] = [];
506
463
  lines.push(`# vdx init plan`);
507
464
  lines.push('');
@@ -555,7 +512,6 @@ export function renderPlanSummary(plan: InitPlan): string {
555
512
  }
556
513
  lines.push('');
557
514
  }
558
- const unmatched = plan.mappings.filter((m) => !m.runCommand).map((m) => m.verb);
559
515
  if (unmatched.length > 0) {
560
516
  lines.push(`> Not mapped: ${unmatched.join(', ')}. Добавь тиски в \`mise.toml\` вручную.`);
561
517
  lines.push('');
package/src/run.ts CHANGED
@@ -43,14 +43,14 @@ export function renderResolveError(
43
43
  case 'no-mise-toml':
44
44
  return (
45
45
  `vdx: no mise.toml in ${projectRoot}\n` +
46
- `hint: run \`vdx init .\` to generate one, or define it manually.\n`
46
+ `hint: run \`vdx init\` to generate one, or define it manually.\n`
47
47
  );
48
48
  case 'parse-error':
49
49
  return `vdx: failed to parse mise.toml: ${res.detail ?? 'unknown error'}\n`;
50
50
  case 'no-task':
51
51
  return (
52
52
  `vdx: no \`[tasks.${verb}]\` in mise.toml\n` +
53
- `hint: run \`vdx init . --force\` to re-detect, or add the task manually.\n`
53
+ `hint: run \`vdx init --force\` to re-detect, or add the task manually.\n`
54
54
  );
55
55
  }
56
56
  }