@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 +7 -7
- package/package.json +1 -1
- package/src/index.ts +9 -12
- package/src/init.ts +17 -61
- package/src/run.ts +2 -2
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
|
|
39
|
+
vdx audit [project-path] [--format=ansi|markdown|json] [--rubric <path>] [--stack <id>] # default: cwd
|
|
40
40
|
|
|
41
|
-
# Generate mise.toml
|
|
42
|
-
vdx init
|
|
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
|
|
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
|
|
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.
|
|
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
|
|
40
|
-
vdx init
|
|
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
|
-
|
|
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 (
|
|
152
|
-
process.stderr.write('\n[dry-run] mise.toml
|
|
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
|
|
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
|
|
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
|
|
53
|
+
`hint: run \`vdx init --force\` to re-detect, or add the task manually.\n`
|
|
54
54
|
);
|
|
55
55
|
}
|
|
56
56
|
}
|