Skip to content

Add looper lint: rubric anti-pattern checks as a static command#16

Merged
ksimback merged 2 commits into
mainfrom
looper-lint
Jul 7, 2026
Merged

Add looper lint: rubric anti-pattern checks as a static command#16
ksimback merged 2 commits into
mainfrom
looper-lint

Conversation

@ksimback

@ksimback ksimback commented Jul 7, 2026

Copy link
Copy Markdown
Owner

What

looper lint <loop.yaml> — ROADMAP Part 3 #2. The design rubrics become a static checker that runs against any compilable loop.yaml, no wizard interview required.

Severity contract

  • error — the spec will not behave the way it reads at runtime:
    • judge-criterion-unreachable: judge criteria listed on a fixed_passes gate (the runner only consults judges under revise_until_clean, so those rubrics are dead)
    • unscoped-egress: a non-local, cross-vendor council member with no privacy.egress declaration
    • egress-unknown-member: an egress entry whose to matches no council member (its redactions/consent never apply)
  • warning — rubric coaching: 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-placeholders

Exit 0 clean/warnings-only, 1 on errors (or any finding with --strict), 2 if the spec does not compile. --json for tooling. Compile validation runs first, so everything normalize_spec already rejects stays a hard looper: 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/--json behavior, 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

ksimback and others added 2 commits July 7, 2026 13:46
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>
@ksimback ksimback merged commit 19f30e9 into main Jul 7, 2026
9 checks passed
@ksimback ksimback deleted the looper-lint branch July 7, 2026 21:07
@ksimback ksimback mentioned this pull request Jul 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant