fix(.vapi-ignore): honor patterns on push and apply, not just pull#26
Merged
Conversation
`.vapi-ignore` is now bidirectional. Four wired pieces:
1. **Load-filter** — `src/resources.ts:loadResources` accepts
`{ ignorePatterns }`; matched ids emit `🚫 <id> (matched .vapi-ignore: <pattern>)`
and are filtered out before duplicate detection, validation, or any API call.
2. **Push wire** — `src/push.ts` reads
`const ignorePatterns = FORCE_DELETE ? [] : loadIgnorePatterns()` once and
passes it into every `loadResources` call. `--force` bypasses the
load-filter for deliberate overrides.
3. **Orphan-protect (CRITICAL DATA SAFETY)** — `src/delete.ts`
`findOrphanedResources` accepts `ignoredIds: Set<string>`; ids matched by
`.vapi-ignore` are excluded from the orphan list, and
`deleteOrphanedResources` emits a
`🚫 <type>/<id> retained (matched .vapi-ignore — orphan-protected)` line
for each retained id. **Orphan-protect ALWAYS honors the ignore list,
even under `--force`** — this prevents a `--force` push from silently
DELETE'ing a dashboard resource the repo has explicitly opted out of
managing.
4. **Ref-validate** — `src/validate.ts:validateNoIgnoredReferences` walks
each loaded resource's referenced ids and emits an `error`-severity
finding for any ref pointing at an ignored id; `--strict` push aborts
before any API call.
Docs updated (`AGENTS.md`, `docs/learnings/yaml-conventions.md`,
`docs/learnings/simulations.md`, `resources/.vapi-ignore.example`) to
describe the bidirectional semantics, the `--force` bypass and the
ref-validate rule. `improvements.md` gets a `[RESOLVED 2026-05-11]` entry
under #21.
Tests: `tests/vapi-ignore-push.test.ts` pins T1–T5 spawn-fixture
integration tests + in-process unit tests for each helper. All 128 tests
pass; biome + tsc clean.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Describe your changes
Makes
.vapi-ignoresymmetric across pull, push, and apply. Previously the file was pull-only —push.tsandapply.tsignored it entirely, which meant a single broken YAML asset (referenced credentials, missing tools, dead refs) could halt every customer'snpm run pushuntil the file was physically deleted. With this PR, four things change:src/resources.ts):loadResources()andloadSingleResource()accept{ ignorePatterns }and skip matching files with a🚫log line, mirroringpull.ts:700.src/push.ts): readsFORCE_DELETE ? [] : loadIgnorePatterns()and threads it into all 9loadResourcescall sites.--forcebypasses the filter, matching pull's force-flag semantics atpull.ts:907.src/delete.ts):findOrphanedResourcesacceptsignoredIds;deleteOrphanedResourcescallsloadIgnorePatterns()directly (not theFORCE_DELETE-shadowed shorthand) so protection stays on even under--force. This is the critical data-safety piece — without it, the first--forcepush after someone.vapi-ignores a previously-tracked resource would DELETE it from the dashboard.src/validate.ts): newvalidateNoIgnoredReferencespromotes the silent-drop inresolver.ts:103-110(squad referencing a now-ignored assistant) to a validation error. In default mode it surfaces as a warning;--strictaborts the push.Plus a new test file
tests/vapi-ignore-push.test.tscovering T1–T5 spawn-fixture integration tests + 9 unit tests (128/128 total tests pass). Most of the non-test file changes are biome import-reorder noise frombiome check --write— no behavior changes outside the four files listed above.Relevant Context (linear ticket, slack link, etc)
Surfaced live during a
gitops-amazon3pfull-fleet sync. Two pre-existing stale assets (my-voice-f1751ee7.mdreferencing a nonexistent PlayHT voice,recording-consent-7230a9c8.mdreferencing three tools that were never imported during theprod → youssaf-orgrename) haltednpm run push -- youssaf-orgmid-stream. Adding both paths to.vapi-ignorehad no effect because push didn't read the file. The customer fork resolved by deleting the YAML directly, but the underlying engine gap remained — this PR closes it.No Linear ticket; tracked in
improvements.mdentry #21.API Changes
Is this changing the public API?
If yes, is it backward‐compatible?
Internal API surface change only:
loadResourcesandloadSingleResourcenow accept an optional{ ignorePatterns?: string[] }second argument. Default behavior (no arg / empty array) is identical to prior behavior — backward-compatible for any internal caller. No public REST API, SDK, or CLI flag contract changes.How did you test this?
tests/vapi-ignore-push.test.ts— 5 spawn-fixture integration tests (T1: dry-run honors ignore; T2:--forcebypasses; T3: orphan-delete protection under--force; T4: squad-references-ignored is hard error under--strict; T5: explicit-file push honors ignore) + 9 in-process unit tests coveringloadResources,findOrphanedResources, andvalidateNoIgnoredReferences.npm test→ 128/128 pass, no regressions in existing suites (push-dry-run,cleanup-safety,path-matching,validate,drift,dep-dedup, etc.).npx @biomejs/biome check src/ tests/→ clean.npm run build(tsc --noEmit) → clean.npm run push -- youssaf-orgingitops-amazon3pis the validation case — the engine would now silently skip ignored assets without halting the fleet sync. (Manual verification deferred to first downstream consumer; the integration tests pin the same contract end-to-end via spawn-fixture.)Known non-blocking follow-ups (from code-reviewer)
validateNoIgnoredReferencesfalse-positives under--force(no abort in default mode, but--strict --forceis noisy). One-line fix.extractReferencedIdsdoesn't walksquadsorevalsrefs — forward-looking gap; no existing config uses them today..vapi-ignore-matched YAMLs to disk (no apply-time damage; load-filter drops them on next push).config.tsmodule-load assertions require dynamic-import shim in tests — architecture nit, follow-up to defer asserts to agetConfig()accessor.delete.ts:228-242O(n³) hot path — hoistloadedIdsto aSet(perf nit).tests/vapi-ignore-push.test.ts:179-186safety timeout not cleared on graceful exit —.unref()follow-up.