Add looper lint: rubric anti-pattern checks as a static command#16
Merged
Conversation
New subcommand checks any compilable loop.yaml for the rubric anti-patterns without running the wizard. Two severities: errors for specs that will not behave as written (judge criteria on a fixed_passes gate are never evaluated by the runner; a cross-vendor council member with no privacy.egress declaration; an egress entry naming an unknown member) and warnings for design coaching (all-vibe verification, same-family judge+host, judgment-only delivery gate, undeclared non-local sends, pre-granted consent, no checkpoint before cross-vendor sends, missing revision caps, null wall-clock budget, empty stop conditions, shell-string checks, unresolved placeholders). Exit contract: 0 clean or warnings-only, 1 on errors (or any finding with --strict), 2 when the spec does not compile. --json for CI. The wizard now runs lint after compile (errors block, warnings are relayed as coaching). 10 new tests (37 total) including a sweep asserting the five shipped templates and the example lint error-free. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Correctness: - judge-criterion-unreachable now also fires for revise_until_clean gates with verdict_source: human (the runner asks for a bare pass/revise and never surfaces judge rubrics there either). - unscoped-egress only applies to members actually referenced by a gate''s members or verdict_source; unreferenced members get a new unreferenced-council-member warning instead of a false-positive error. - egress-consent-pregranted groups entries per member and fires only when a non-local member''s entries are ALL consent: granted, matching the runner''s all() check; local members never prompt so never warn. - egress-unknown-member message no longer claims the entry''s redact globs are inert (all_redaction_globs folds them into context redaction regardless of target). - Removed cross-vendor-send-without-checkpoint: it was satisfied by checkpoint names the runner never fires, and consent is already the fail-closed before-first-send human gate. Replaced with unhonored-human-checkpoint, which warns when human_checkpoints entries other than after_plan will only bind in-session. Cleanup: - Empty goal.verification gets a dedicated no-verification-criteria message instead of a factually wrong all-vibe diagnostic. - missing-max-revisions reads the resolved gate (normalize_spec never writes the default back), dropping the redundant raw-gates plumbing. - Shared placeholder_warning_text() so compile and lint cannot drift. - Load-bearing deepcopy in cmd_lint is now explained. - README documents exit 2 and that --json emits nothing on it. 4 new tests (41 total). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
What
looper lint <loop.yaml>— ROADMAP Part 3 #2. The design rubrics become a static checker that runs against any compilableloop.yaml, no wizard interview required.Severity contract
judge-criterion-unreachable: judge criteria listed on afixed_passesgate (the runner only consults judges underrevise_until_clean, so those rubrics are dead)unscoped-egress: a non-local, cross-vendor council member with noprivacy.egressdeclarationegress-unknown-member: an egress entry whosetomatches no council member (its redactions/consent never apply)all-vibe-verification,same-family-judge,delivery-gate-no-programmatic,non-local-member-without-egress,egress-consent-pregranted,cross-vendor-send-without-checkpoint,missing-max-revisions,no-wall-clock-cap,no-stop-conditions,shell-string-check,unresolved-placeholdersExit 0 clean/warnings-only, 1 on errors (or any finding with
--strict), 2 if the spec does not compile.--jsonfor tooling. Compile validation runs first, so everythingnormalize_specalready rejects stays a hardlooper: error:.Wizard integration
SKILL.md step 10 now runs lint after compile: errors are emit blockers, warnings are relayed to the user as coaching.
Tests
10 new tests (37 total): one per check family,
--strict/--jsonbehavior, exit-2 on uncompilable specs, and a sweep asserting all five shipped templates plus the example lint with zero errors (they intentionally carry warnings: same-family judges with in-file rationale,{{PLACEHOLDER}}tokens, bug-hunt's shlex-split string checks).🤖 Generated with Claude Code