fix(preflight): inline named-agent model without flows.json (#263) - #266
Conversation
…ows.json is present (#263) A self-contained flow that declares agents inline (`agents: { drafter: { cli, model } }`) should validate and run without a mandatory external flows.json. Today `check.ts` sends `models: []` with `modelRegistryPath: undefined` when no flows.json is found, and `unknownModelDiagnostics` refuses every inline model with `model_unknown` — forcing every single-file example to ship a second file. model_unknown is a governance refusal about a *registry-declared* allowlist. No registry means no policy to enforce. Distinguish the two signals: relax the check when modelRegistryPath is undefined; keep it strict when it is set (including for an empty allowlist, which is a real project decision). The CLI+model auth probe still runs. Model authority is not "any model works" — it is "we prove the model works via the adapter probe below, not via a policy file". Scope kept narrow to match the issue: inline `agents:` map only. Step-level `model:` on an individual step is a different affordance and is not touched here. Tests - Two existing tests conflated `models` with registry presence (passed `models` without `modelRegistryPath`); updated them to pass both, reflecting the actual production shape that `check.ts` emits when a flows.json IS found. - New test: exact issue repro (inline named agent, no registry) → preflight ok, probe ran once (proves auth verification still happens). - New test: registry present + disallowed inline model → still refused, so governance semantics are preserved. Session-Id: efeda5df-9b7c-48d4-b2ce-957f5bef0a82
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Advanced Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Review swarm: maintainabilityMaintainability Review: PR #266fix(preflight): inline named-agent model without flows.json (#263) Reviewer: maintainability-agent SummaryThis PR introduces a governance check relaxation: inline named-agent model declarations now pass preflight when no FindingsF1: Asymmetric enforcement with no documented boundary contract [CRITICAL]Location: The change introduces a three-state distinction where the code expresses only two:
The problem: States 2 and 3 diverge at line 212 inside the step-level loop, but the named-agent path (lines 197-208) does not check
Wait — I misread. Line 212 is inside Actually, re-reading: The step-level block unconditionally pushes a refusal diagnostic when the model is unknown. The named-agent block has the guard. This means:
This is a latent defect: the same governance policy applies inconsistently depending on where the model is declared. A stranger changing this code in six months will not see this boundary and will unify the logic incorrectly. What the code should say but doesn't:
Missing contract documentation:
Stranger-in-six-months test: FAIL. A developer refactoring this function will see two parallel loops checking models and will factor out the F2: Implicit contract between
|
Review swarm: historyPR #266 — history reviewReviewed head: Finding H1 — P1: preserve explicitly supplied SDK allowlists without a pathLocation: A caller can supply This repeats the named-declaration validation hole rejected in The captured parent/head comparison below uses actual preflight source, with Repair: represent absent policy separately from an explicitly supplied model Story, constitution, and commit-message assessment
Input recovery and limitsThe advertised The initial Git command failed with: I recovered the real repository objects with This follows the drive log's 2026-09-10 10:57Z correction: missing /tmp input This is a history review with a focused deterministic before/after reproduction, Literal commands and captured evidenceExit annotations below are captured process exit statuses. Empty command output It releases the reservation and returns from The lens made this immediate to confirm by capturing a literal Also correct, and also mine:
REVIEW_FAILED |
Review swarm: structureNo fresh transcript was produced for run |
Review swarm: FAILED
Cloud run: |
maintainability lens — FAILMaintainability review — PR #266Context read: BlockerAsymmetric enforcement between the two authoring surfaces. Concerns
Notes
REVIEW_FAILED |
history lens — PASSBlockers: none. PR #266 passes the three HISTORY criteria. The change in The relevant historical mistake is recorded in Concerns: The new test at Also, direct SDK callers supplying Notes: Commit I inspected the requested recent history, repository guidance, relevant drive-log entries, NEXT, DIRECTIVES, and commit metadata. I did not execute tests; the PR body’s numerical test results are not independently verified by this review. REVIEW_PASSED |
structure lens — MISSING |
|
🎯 review-swarm: FAILED (M:fail H:pass S:missing) Lens transcripts posted as sibling comments above. |
Closes #263.
The change
unknownModelDiagnosticsinpreflight.tscurrently refuses every inline named-agent model unless it appears inoptions.models. When noflows.jsonis found,check.tssendsmodels: []withmodelRegistryPath: undefined, so every inline declaration refuses with:That forces every single-file example flow to ship a second file.
model_unknownis a governance refusal about a registry-declared allowlist. No registry = no policy to enforce. This PR distinguishes the two signals: relax the check whenmodelRegistryPath === undefined; keep it strict when it is set (including empty allowlist, which is a real project decision).Scope kept narrow to match the issue exactly: inline
agents:map only. Step-levelmodel:on an individual step is a different affordance and is not touched here.Safety
probeCalls === 1for the relaxed path.modelRegistryPathpresence) already exists and is already the honest indicator of registry state.Tests
Two existing tests conflated
modelswith registry presence (passedmodelswithoutmodelRegistryPath). Updated them to pass both, reflecting the actual production shapecheck.tsemits when a flows.json IS found.preflight.test.ts27/27 pass,cli.test.ts63/63 pass,model-selection.test.ts10/10 pass,tsc --noEmitclean.Two new tests:
result.ok === true, probe ran once.Not in this PR
The step-level analogue (
type: llm/type: agentwith inlinemodel:on the step itself) shows the same conflation and could be relaxed under the same reasoning. Kept out of scope because the issue and its acceptance criteria are explicit about named agents, and I want the review surface small. Happy to open a follow-up if you want the same treatment there.Note
Low Risk
Narrow SDK validation change for named agents only when no registry is configured; governance with flows.json and CLI probes are unchanged.
Overview
Preflight no longer treats an empty
modelslist as a hard deny when no project model registry exists. Named-agent entries inagents:were incorrectly gettingmodel_unknownbecausecheck.tspassesmodels: []and omitsmodelRegistryPathwhen noflows.jsonis found; that empty list meant “no policy,” not “forbid everything.”unknownModelDiagnosticsnow enforces the registry allowlist only whenoptions.modelRegistryPathis set. Inline named-agent models can pass preflight in the no-registry case; CLI/model probes still run. If a registry path is present (including an empty allowlist from a realflows.json), disallowed named-agent models still refuse.Tests align existing cases with
modelRegistryPathwhen a registry is intended, and add coverage for the relaxed no-registry path and preserved governance when a registry disallows the model. Step-levelmodel:validation is unchanged.Reviewed by Cursor Bugbot for commit 0a8f01a. Bugbot is set up for automated code reviews on this repo. Configure here.