VibeVM
Contents
On this page
en
Publisher
org.vibevm.core
Version
1.0.0latest
Audiences
author
Reading time
7 min
Rendered
Read aloud
never

PROP-051: vibe refactor — the source-refactoring umbrella

1. Mandate

01The owner's mandate, verbatim (2026-08-23, chat, three clauses in one sitting): «я хочу все наши спецификации в проекте (всё внутри spec и packages, итп) сконвертировать в XML как язык исходников. … Это гораздо более продвинутый формат для нас, потому что нейросеть понимает сложные спецификации в нем проще.» — «у тебя уже где-то должна быть система бесшовного переписывания форматов спецификаций. Я предлагаю сделать команду "vibe refactor" которая будет зонтиком для разных команд рефакторинга. Дальше сделать команду vibe refactor convert-source для конвертирования форматов исходников между Markdown и XML. Если в ходе конвертирования будут происходить какие-то деструктивные операции - выдается ошибка с описанием что потеряется и потребуется подтверждение (либо интерактивное, либо флаг --force снимает проверку). Проверку стоит делать честно, обратным переконвертированием.» — «и дальше уже ты просто применишь этот инструмент к своим же файлам.» The seamless-rewrite system the owner names already exists: it is PROP-045's pivot (vibe-specdoc, parse → IR → emit, all four edges); this PROP adds the user-facing verb over AUTHORED sources and the honesty contract that verb must carry.

02The owner's fourth clause, verbatim (2026-08-23): «файлы внутри vibedeps нигде не нужно переконвертировать вручную, нужно вместо этого сконвертировать исходники и выполнить материализацию». The law: convert-source operates on AUTHORED sources only; materialised state (vibedeps/, the machine cache, generated boot artifacts) is never converted in place — sources convert, then vibe install re-materialises the slots under the standing PROP-045 machinery (the derived-manifest law re-transforms them honestly).

2. The umbrella

03vibe refactor <verb> is the command family for meaning-preserving rewrites of authored source trees. Charter: a refactoring changes the FORM of sources, never their meaning, and every verb under the umbrella must carry its own machine-checked honesty proof (for convert-source: the reverse-reconversion check of §3). First citizen: convert-source; future verbs (anchor renames with tombstones, renumbering) join under the same charter, each with its own PROP-level fact before it ships.

3. convert-source

04vibe refactor convert-source --to xml|markdown [PATH…] converts spec sources between the two PROP-045 serialisations (md accepted as an alias of markdown). Each PATH is a file or a directory; a directory walks recursively and selects spec sources (is_spec_source) currently in the OPPOSITE form; a file in the target form already is reported already and skipped. The walk always skips: vibedeps/ (##VIBEDEPS-NEVER-CONVERTED), dot-directories, target/, and any file whose leading lines carry the generated by vibe marker (generated artifacts regenerate; they are not authored sources) — an EXPLICIT file argument overrides only the marker skip, never the vibedeps/ skip.

05A conversion writes the sibling serialisation and deletes the original in the same act, so the one-document-one-form law (PROP-045 ##TARGET-MIXED, the pair-collision check) holds at every instant — the tree never holds X.md and X.xml together, not even transiently between files. The verb assumes version control underneath it and keeps no backups of its own.

06The destructiveness check is the owner's law, implemented by reverse reconversion through the pivot: for a source S, parse to IR, emit the target form, read the target form back, and project it into the SOURCE form again; compare. Three classes: (1) byte-stable — the back-projection equals S byte-for-byte: converts silently. (2) IR-stable loss — the back-projection re-parses to the SAME IR but differs in bytes (dropped MD/XML comments, normalised layout): the verb REFUSES with a per-file description of what is lost, and proceeds only on interactive confirmation or --force. (3) IR-divergent — the back-projection re-parses to a DIFFERENT IR: always refused, --force does not apply; that class is a vibe-specdoc defect to file (the pivot broke its own round-trip law), never a corpus to damage.

07The class-2 description is honest and concrete: it names the file and shows the lost or changed lines (a unified diff of the source against its back-projection), with dropped comments called out as CONTENT loss (PROP-045 ##REVIEW-COMMENTS-LAW: the pivot drops comments by design — REVIEW: markers and prose comments do not survive conversion) rather than folded into formatting noise.

08On a TTY, class-2 files prompt per file (yes / no / all); off a TTY, class-2 without --force is an error listing every lossy file and what each loses. --force waives class 2 only. --dry-run classifies and reports every file, writes nothing, and always exits 0 (an inventory, not an attempt); a real run exits 0 iff every requested conversion landed, non-zero when any file was refused or declined.

09The classification core — (source text, direction) → class + emitted target + loss diff — lives in vibe-specdoc, the crate that owns the IR and all four edges (PROP-045 ##PIVOT-MODEL), so the honesty check is a library property with its own unit tests; the CLI verb is a thin walker / prompter / writer over it, in the house thin-command genre.

10Two skip classes the K2 inventory proved (2026-08-24), amending ##CONVERT-SOURCE-SURFACE: the walk also skips node_modules/ directories — foreign vendored trees are the same genre as vibedeps/, never authored here (the inventory found 129 third-party .md under package tool dirs, including files only the foreign author may reshape) — and harness-contract basenames (CLAUDE.md, AGENTS.md, GEMINI.md, MEMORY.md, SKILL.md, README.md, LICENSE.md — the last two by the owner's 2026-08-24 ruling, verbatim: «это же зарезервированные имена, это не спецификации… чтобы на сайтах типа Гитхаба они отображались нормально»; the K3/K4 flip converted 100 READMEs and 72 LICENSEs before the ruling and they were converted back the same sitting): their FILENAME and format are an external harness's contract (a SKILL.md carries YAML frontmatter the pivot does not model — the inventory showed conversion would strip it and break the skill), so they stay Markdown by law, reported as their own skip class rather than silently converted. An explicit file argument does NOT override either skip — unlike the generated-marker skip, these are not heuristics.

11Both directions are first-class on every converting verb (owner, 2026-08-24, verbatim: «В настройках у обеих должно быть из какого формата в какой (я так понял что ты запланировал только MD->XML, а хочется чтобы была и XML->MD. Параметры --from и --to)»). The surface is --from <markdown|xml> + --to <markdown|xml> (md an alias of markdown on both): --to is required, --from defaults to the counterpart of --to, and --from equal to --to is a loud error — never a silent no-op. --from is a FILTER: only sources currently in that form are selected; everything else reports already/skips unchanged.

12vibe refactor convert-package-src [--from …] --to … <package-root>… converts WHOLE PACKAGES, not individual files (owner, 2026-08-24, verbatim: «Она будет конвертировать целиком пакеты, в отличие от предыдущей команды, которая конвертирует конкретные классы»). Each argument is a package root — a directory carrying vibe.toml (anything else is a loud error; that validation is what distinguishes this verb from pointing convert-source at a bare directory) — and the conversion walks the package's SPEC HOMES with the same core, the same skips and the same honesty contract as convert-source (##HONESTY-BY-REVERSE applies file by file). The perimeter ruling (owner, 2026-08-24, verbatim: «нужно переводить спецификации из директории спецификаций (spec, packages, всякие зарезервированные имена в корне если они есть), а не все подряд файлы» — «тут дело не столько в том, что README.md это зарезервированное имя, сколько что ты конвертировал всё подряд»): the spec homes are spec/ and a nested packages/ — and NOTHING else: root-level working docs (one house's WAL/checkpoint family) are NOT presumed, because the verb serves every project and such names may mean anything elsewhere (owner correction, 2026-08-24, near-verbatim: «не у всех проектов есть эти файлы… это конкретно особенность vibevm. А утилита рефакторинга работает на все проекты»); a house converts its own root extras with explicit convert-source paths. Everything else at a package root — code, tooling, reserved-name docs — is outside the verb's perimeter, with the reserved-name skips of ##FOREIGN-AND-HARNESS-SKIPS as the second, independent guard. A root carrying neither spec home is a loud refusal.

13vibe refactor convert-spec-src [--from …] --to … [<package-root>] converts the spec/ directory of the chosen package; with no argument it targets the CURRENT ROOT PROJECT's spec/ tree (owner, 2026-08-24, verbatim: «она конвертирует директорию spec для выбранного пакета (если не сказано что - конвертирует текущий корневой проект)»), resolved the same way the other project-rooted verbs resolve it.

14The two package-shaped verbs are thin wrappers: they resolve WHICH directories to convert and then run the very same walker and classification core convert-source runs (owner, 2026-08-24, verbatim: «Внутри они используют тот же код что convert-src, вызываемый для разных директорий по смыслу») — no second conversion path, no second honesty check to drift. Canonical names follow the owner's own spellings (convert-package-src, convert-spec-src), and convert-src rides as an alias of convert-source, so both spelling families the owner used in chat resolve.

4. Applying it to our own tree

15The mandate's third clause is a build of its own: the host spec/ tree and every packages/ member convert Markdown → XML with this verb, vibedeps/ re-materialises (never hand-converted), and the by-name references to .md spec paths in prose and contracts (inline links, CLAUDE.md's boot pointers, hooks, tooling docs) are swept to the new names — no-legacy, by the standing F5 precedent (PROP-050 ##MIGRATION-NO-LEGACY genre: one form, no dual reading of retired shapes). Slices, perimeter and the dry-run inventory live in the application plan: vibevm/vibespecs/terraforms/ CONVERT-SOURCE-APPLICATION-v0.1.xml. CLAUDE.md / AGENTS.md / GEMINI.md themselves stay Markdown — their names are harness contracts, not spec sources.

5. History

162026-08-23: mandated, designed and ratified in one owner sitting, immediately after the PROP-050 visibility landing; authored against the already-BUILT PROP-045 pivot (recipe specdoc/4, host lane already STATIC.xml, host spec_format = "xml"), which is why the whole feature is one verb and one application wave rather than a format migration.

For an agent

This page has a machine mirror. The citation carries the version rather than latest, so what an agent quotes does not move under it.

spec://org.vibevm.core/vibevm@1.0.0/common/PROP-051-refactor-umbrella

.md.xmlllms.txt