feat(validate): catch broken references and show findings on the PR - #77
Open
scott-lowe-vapi wants to merge 1 commit into
Open
scott-lowe-vapi wants to merge 1 commit into
scott-lowe-vapi wants to merge 1 commit into
Conversation
A reference that names no file and no state entry failed three different ways depending on the field: silently dropped (toolIds, structuredOutputIds), sent raw and rejected mid-push (squad members, hook tools, personalityId, scenarioId), or deferred (improvements.md #31). validate never checked it, so the new CI check couldn't either. - src/validate-refs.ts, run by validate (so by apply and CI) and by push: - dangling-reference (error): a name with no local file and no state entry, across the shared reference walk plus scenario judges' evaluations[].structuredOutputId; - override-tool-by-name (error): toolIds names inside assistantOverrides, membersOverrides or targetOverrides, which push never resolves; - unresolved-credential (warning): a credential name not in state, naming the org's bootstrap pull; - reference-by-uuid (warning): breaks promotion; stock personalities exempt. - validate now also runs reference-to-ignored, as push already did, and reads the committed state file offline. - On GitHub Actions, validate prints each finding as an annotation, so it shows on the file in the PR, warnings included. - The validate header no longer prints an API URL for an offline command. - Docs: a rule table in troubleshooting, the commands row, AGENTS.md (never edit state to make a reference resolve), improvements.md #31 resolved. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This was referenced Oct 3, 2026
scott-lowe-vapi
marked this pull request as ready for review
October 3, 2026 07:44
Contributor
Author
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.

Value
V.A.L.U.E. tier: small — a behavior change:
validate, and soapplyand the Validate resources check, now fail on configs they used to pass.Problem: a reference that names no file fails in one of three ways, depending on the field (
improvements.mddocs: document orphan-YAML gate + --allow-new-files in README and AGENTS #31):model.toolIds,artifactPlan.structuredOutputIds;personalityId,scenarioId;validatenever checked references, so the Validate resources check from ci: validate every org's resources on every pull request #76 couldn't catch a typo'd tool name either. Warnings were also invisible in CI: they don't fail the check, and nobody reads the job log.Who it affects: everyone who edits resource files by hand or with a coding agent, and reviewers of their PRs.
What changes:
New
src/validate-refs.ts, run byvalidate(so byapplyand CI) and bypush:dangling-referenceevaluations[].structuredOutputId.override-tool-by-nametoolIdsinsideassistantOverrides,membersOverridesortargetOverrides, where push never resolves names.unresolved-credentialreference-by-uuidvalidatenow also runsreference-to-ignored, aspushalready did. It reads the committed state file and stays offline.On GitHub Actions, every finding becomes an annotation, so it shows on the file in the PR, warnings included.
pushreports the new rules alongside its existing validators: warnings by default, blocking under--strict.Docs:
validaterow in the commands guide;AGENTS.md: never edit the state file to make a reference resolve;improvements.mddocs: document orphan-YAML gate + --allow-new-files in README and AGENTS #31 marked resolved by validation.Evidence of value
The starter example with two typos,
scheduler→schedularin the squad andbooking-confirmed→booking-confirmdin a judge:npm run validate0 error(s)— ✅ Validation passed2 error(s), onedangling-referenceper typo, naming the file and the missing nametests/validate-refs.test.tscovers:%, newlines,:and,is tested intests/validate.test.ts.tests/ci-validate-workflow.test.tsruns the CI step withGITHUB_ACTIONS=trueon the typo'd squad. The step fails, and the::errorpoints atresources/clinic/squads/front-desk.yml.unresolved-credentialwarning, which is accurate.Testing plan
npm test(523 tests) andnpx tsc --noEmitpass.applyvalidates before it pulls. So a reference to a resource created in the dashboard and never pulled now stopsapply; the message says to pull first. Before,applywent on to pull and push, and the reference resolved only if the pull happened to produce that exact name.applyorpush. Neither code path changed except for the added findings.Refs TEST-141
🤖 Generated with Claude Code