VibeFlow CLI flag reference
Contents
vf init --ai --autopilot- How It is Enforced
- What to Do When You Add a New File and Coverage Drops
- bun:coverage Quirks
- Anti-Patterns Suite
- When You Have a Real Coverage Blocker
This document tracks every non-trivial flag in the VibeFlow CLI that the release notes, marketing copy, or new contributors need to know about. It is maintained alongside the source: when a flag is added or its behavior changes, update the entry here in the same commit.
vf init --ai --autopilot
Added in: feat(ai-init): add --autopilot flag for engine auto-fallback
Summary: When the chosen engine is unavailable or returns a permission/unauthorized error, automatically fall back to the next-best ready engine instead of failing hard.
Default: false (preserves pre-existing single-shot behavior; a
failure is the user’s problem to debug).
Scope: The flag is on vf init --ai, NOT a global flag. Only the
AI-powered enrichment phase (Phase 2 of vf init) is affected. The
deterministic baseline (Phase 1) is unchanged.
Behavior:
- If
forceEngine(from--engine) is set and the engine is not ready, autopilot clearsforceEngineand falls through toselectBestEngine(readiness), which picks the next-best engine in priority order:claude > copilot > codex. - If the engine invocation reports the CLI as unavailable (e.g.
copilotbinary missing), autopilot retries with the next-best engine. - If the engine spawner returns a permission-denied or unauthorized
response (e.g. copilot missing
--allow-allflags), autopilot retries with the next-best engine. - Timeouts and unknown non-zero status codes are NOT retried — those indicate an engine-side issue, not a fallback opportunity.
- Retries are capped at 3 (4 total attempts). The fallback engine must be DIFFERENT from the one that just failed (the loop never retries the same engine twice).
- The
AiInitResultincludes afallback: { original, used }field when the chosen engine differs from the original request. The CLI surfaces this as✔ AI analysis complete (used; fell back from original via --autopilot).
Result on total failure: If every engine fails (or the only
candidate is unavailable), the result reason is wrapped with
— exhausted 3 autopilot fallbacks; original request was <engine> so
the caller knows fallback was attempted and gave up.
Non-retryable failures (preserved single-shot): When autopilot is off, the loop is bypassed entirely. A failure on the first attempt returns immediately — no fallback is attempted. The original error message is preserved verbatim.
Tests: the behavior has focused coverage in test/ai-init.test.ts
and test/commands-coverage.test.ts. Do not infer a repository-wide
coverage percentage from those focused tests; only a fresh
bun run coverage:check result is coverage evidence.
Coverage policy: fresh lcov evidence, no invented percentage
VibeFlow targets 100% executable line coverage per src/ file unless
the coverage gate carries an explicit issue-bound waiver. A normal test
pass, a stale coverage/lcov.info, or the Bun version is not proof that
the target was met. Report the exact live numerator/denominator from
bun run coverage:check.
How it’s enforced
scripts/coverage-gate.cjsparses freshly generatedcoverage/lcov.info. It enforces per-file executable-line coverage forsrc/, except entries in its explicitCOVERAGE_WAIVERSmap.bun run coverage:checkremoves old coverage, builds the UI, runs Bun 1.4 with the lcov reporter, then runs that gate.bun run check— runs typecheck + lint + test + coverage:check..github/workflows/ci.ymlruns the same coverage command. Its result is authoritative only after the current commit’s job is green.
What to do when you add a new file and coverage drops
Option A: Cover the new code with a test (always preferred)
- Add the new src/ file.
- Add
test/foo.test.tswith at least oneexpect()per public function. - Run
bun run coverage:checkto confirm.
Option B: Extract and test a real seam
If the code path depends on a network, filesystem, clock, process, or platform boundary, inject that dependency and drive both success and failure branches. Do not reshape production control flow merely to make the reporter count fewer lines.
Option C: Use an issue-bound waiver (last resort)
When a platform-only path cannot run in the current job, add the narrow
file waiver required by scripts/coverage-gate.cjs, with an owner,
issue, expiry, and a dedicated platform test job.
bun:coverage quirks
- Bun 1.4 can generate the lcov file used by this repository, including
executable
DAline records. That fixes neither missing tests nor a stale report. - The current Bun 1.4 lcov path emits no BRDA records in this suite,
so branch coverage reports
0/0. The::notice::line incoverage-gate.cjsmakes that blind spot explicit; do not call it 100% branch coverage. setInterval(() => {...}, 25000)callback body never hits in tests because tests complete in <25s. Either exercise the callback in a test, or use aninject.timerseam.
Anti-patterns suite
test/coverage-anti-patterns.test.ts rejects structural patterns that
make coverage or test isolation unreliable, including top-level spawn,
empty catches, and raw Bun.spawn in tests. It is a hygiene gate, not a
substitute for the lcov result.
When you have a real coverage blocker
Open an issue with the file, uncovered executable line, runtime condition, and an expiry/owner for any temporary waiver. Prefer an injected seam and a real test. Do not hide a gap with a type cast, formatting trick, stale lcov file, or an untracked ignore.
Related: Master Spec · Generated Files Edit this page on GitHub