VIP-34: compiler and tooling requirements
Status: accepted, 2026-10-29, under Will's standing approval of recommendations ("assume I accept now. I will interrupt you if I need to").
Decision
-
Diagnostics. Every VibeLang diagnostic has a code (
EKxxxx) and a message in the user's words that says what is wrong and how to fix it, with a quick fix wherever the fix is mechanical. TypeScript's own lexical, syntax and static errors on ordinary native syntax keep theirTScodes, including independent errors in embedded expressions and types. A rejection that depends on a VibeLang production, placement rule, proposal-specific early error or explicitly adopted reconciliation uses its owning VIP'sEKcode, even when a TypeScript parser helper implements it. Use an already assigned specific diagnostic for the same rejection; preserve independent native errors. -
Codemods. Every breaking change ships a
vibelang --fixcodemod, so code that compiled under the previous release migrates mechanically. -
One formatter. VibeLang's formatter is the only formatter. Prettier, dprint and Oxfmt reach it through plugins, so a repo's existing formatter command covers
.vibefiles. Under the same compiler/options, formatting preserves parsed program meaning: bindings and scopes, operator and control-flow targets, evaluation order, receivers and call syntax, ordinary runtime values and effects, coldness, failures, interruption and finalizers. It preserves inferred and declared public types, declarations and throws contracts, and diagnostic codes, categories and occurrences; diagnostic locations and quoted source follow the formatted file. Comments and their code associations survive, including JSDoc, compiler/linter/tool directives and directive-prologue meaning. An unparsable file is reported and left unchanged; formatting is idempotent. Semantic migrations and diagnostic repairs belong tovibelang --fixor editor actions.Ordinary layout and lexical-spelling normalization may change emitted JavaScript bytes.
Function.prototype.toString, generated source text, source offsets, line/column and stack presentation may reflect the formatted text. This source-text boundary never permits changes to ordinary strings/data, tagged-template raw or cooked values, regex meaning, function names or lengths, property names or directive semantics. For example, changing an escaped string into an actualuse strictdirective changes meaning. Regenerate compiler-generated source-map and declaration-map provenance, includingsourcesContent, for the formatted file; never retain stale maps. Preservation tests compare parsed source/emit structure, runtime behavior, types/declarations, diagnostics, comments/directives and maps; arbitrary regex stripping is unsound, and a finite structural oracle is not a proof of all program equivalence. Exact-byte tests remain useful where equality is expected, without restricting advertised native formatter style settings. -
Existing tools work. Type checkers work through
.d.vibe.ts(VIP-27), and linters, Knip, bundlers and test runners each read.vibe. Every tool is tested against the dogfood repositories. -
Severities. Warning severities can be adjusted in the config's
"vibe"section (VIP-30). Errors can't be turned off.
-
Amended 2026-10-29: code numbering. Each VIP's rules take one fresh hundred-block of diagnostic codes,
EKvvxxfor VIP-vv; an older code is kept only where its rule is unchanged. The specification's Appendix B lists every code. Decided by the agent on 2026-10-29 under Will's rule "when I state a principle, the agent derives the concrete rule and acts; I can override later" (decided detail 60). -
Amended 2026-10-30: warnings never change the exit status.
vibelangandvibelang lintexit non-zero only on errors, astscand ESLint do by default; a repository that wants a warning to fail CI sets its code to"error"invibe.severities. Decided by the agent on 2026-10-30 under Will's rule "when I state a principle, the agent derives the concrete rule and acts; I can override later" (decided detail 71). -
Amended 2026-11-03: imported Effect diagnostics keep the pinned compiler's exit policy. VibeLang's own warnings do not change compiler exit status unless configured as errors. Compiler diagnostics imported under VIP-38 retain the pinned native Effect TypeScript compiler's exit and
noEmitOnErrorpolicy under the same effective rule, category, inclusion and ignore options; imported warnings affect both by default. The standalonevibelang lintcommand fails only on errors; warnings or suggestions alone exit 0. This narrows the unqualified 2026-10-30 warning rule in VIP-34 (decided detail 71); it does not restate that old rule as already limited to VibeLang diagnostics. The agent's R3 decision (decide-live-r3-warning-scope.md) applies Will's standing direction, "It is already implied we match typescript" (WILL-ANSWERS.md, 2026-11-03), to the measured pinned compiler. It is an agent derivation from that direction, not a new personal answer from Will. -
Amended 2026-10-30, clarified 2026-11-03: emit names mirror TypeScript.
x.vibecompiles tox.jsbesidex.d.tsinoutDir. WithrewriteRelativeImportExtensions, relative specifiers./x.vibein emitted JavaScript are rewritten to./x.js, as for.ts; source-extension admission follows the same tsconfig checks as the native twin (chapter 7). Bundler plugins follow the same names. Decided by the agent on 2026-10-30 under Will's rule "when I state a principle, the agent derives the concrete rule and acts; I can override later" (decided detail 72). -
Amended 2026-10-30: imported-lint capacity. VIP-38 is the exception to the hundred-code capacity: imported codes use
EK38followed by a decimal ordinal padded to at least two digits, so ordinal100follows ordinal99in VIP-38's generated table.EKxxxxis a minimum display width for these codes, andEK39xxremains available to VIP-39. Existing assignments remain stable; configuration matches whole codes against the generated table (decided detail 142). -
Amended 2026-10-31:
--fixreaches a fixed point, and a missing runtime is one error. Onevibelang --fixrun applies fixes until none applies; running it again changes nothing, and a run that has not converged within its pass limit reports the remaining fixes as an error. A compilation that needsvibelang-runtimeand cannot resolve it fails with one error naming the package (TS2307), as a missing dependency does in TypeScript, not with an unresolved name per compiler-generated helper. -
Amended 2026-10-31:
--fixscope flags. Two flags scope avibelang --fixinvocation.--fix-migration-onlyselects migration fixes, excluding TypeScript-form teaching rewrites and prelude/import cleanup.--fix-vip-onlyselects the VIP migration passes, including the VIP-1/VIP-2 function-kind andtrymigration, excluding prelude/import cleanup. Either flag requires--fixsomewhere in the argument list, before or after it; alone, each is an unknown compiler option (TS5023). This records existing CLI behavior and changes no language rule. Decided by the agent under Will's rule "when I state a principle, the agent derives the concrete rule and acts; I can override later" (decided detail 186). -
Amended 2026-11-02: the native-resource warning belongs to VIP-34.
usingin effect code has the default warningEK0801: a failure or interruption can abandon the generator before JavaScript disposal. Its context-safe quick fix usesacquireDisposableinsidescoped. The warning never changes TypeScript disposal or starts cleanup by itself. This is VibeLang's TypeScript-form teaching warning, not an imported Effect lint rule. The existing code is retained under the unchanged-code exception. VIP-8's denial authorizes no language rule; its historical warning amendment points here.
Will's words
"make sure we have good compile error messages too"
"They should not only compile and tests pass but we should be able to actually suggest migrating via having everything work including all their existing tooling"
-
Amended 2026-11-01: migration preserves run phase. The explicitly selected
--fix-vip-onlypass removes a known legacy wrapper'stry, even when its success data is an error, a schema error, another Effect or an object with anasEffectmember. An originally Effect-returning written or native contract keeps its intentional run. Decide from the original resolved callable and migration provenance; refuse when unknown. Ordinary--fixand--fix-migration-onlynever reinterpret a valid currenttrybased on its final result type or lack of annotation. -
Amended 2026-11-01, extended 2026-11-03 for VIP-38’s config migration: which files
--fixwrites. A run writes only its selected project's owned.vibe/.vibexprogram sources, including imported owned sources excluded from root discovery, and owned configs for the named legacy-severity, retired-declarationSidecarsand VIP-38EK3012plugin-entry codemods and VIP-1's--fix-vip-onlyEK4802severity override. Config traversal stops at the repository boundary andnode_modules; external configs are reported, never edited. Dependencies,typeRoots, bundled libs, foreign TypeScript/JavaScript, declarations, emitted output, build info, lock files and other referenced projects are excluded. In-b, each project fixes its own files in build order. VIP-33's platform repair alone may create a fresh absent sibling.tsfile after proving the same run phase, captures, receiver and public types, never overwrite one. Any forbidden write is refused with the not-fixed explanation. -
Amended 2026-11-01: legacy Effect alias migration. VIP-3 allocates migration warning
EK4856to uses resolving to the retired preludeEffect<A, E, R>alias. Its identity-safe shorthand or qualified-type rewrite precedes coordinated alias removal; user-defined and imported types are unchanged. -
Amended 2026-11-03: declaration import spelling follows TypeScript. Ordinary package declarations use the native twin’s relative specifiers:
./user.vibeis declared as./user.tsand./App.vibexas./App.tsx; written./user.js,./App.jsx,./userand native./plain.tskeep their spelling. Synthesized import types use TypeScript’s spelling for the twin under the same imports and tsconfig. Compatibility sidecars instead keep VibeLang source references such as./user.vibeand./App.vibex, relocated to the selected compatibility declaration when necessary, to preserve source identity. NeitherallowImportingTsExtensionsnorrewriteRelativeImportExtensionsrewrites declaration specifiers; JavaScript output rewriting is separate. The retireddeclarationImportStylepaths are ignored with nonfatal deprecation warningEK3011for every value (VIP-30). This corrects the earlier substitution of VibeLang source extensions into ordinary package declarations, under Will’s standing TypeScript rule: a package ships.d.tsfiles, not compatibility sidecars.
Amendment: selected ordinary fixes. --fix --only <files> limits repair writes to the listed project modules under the selection contract. Lists may be comma-separated, repeated or read from @list.txt. Validate the full selection before any write. Configs and unlisted files are never repair targets; post-fix compilation retains ordinary outputs and diagnostics. Only selected-file errors refuse repairs, so the report identifies this as partial checking. The option requires --fix and excludes project-wide migration flags.