Skip to content

Screenshot gate auto-closed non-visual PRs via apps/loopover-ui/public/** (openapi.json); verify sibling repos #9434

Description

@JSONbored

Summary

The screenshot-table gate auto-closed contributor PRs that made no visual change, because whenPaths included apps/loopover-ui/public/** — a directory that is overwhelmingly non-visual.

Mitigated in the ORB private config for JSONbored/loopover. Filing to track (a) verifying the sibling repos and (b) deciding whether the matcher should support exclusions.

Root cause

apps/loopover-ui/public/ contains openapi.json (generated, 536KB), robots.txt, sitemap.xml, sw.js, manifest.webmanifest, .nojekyll, plus favicons.

CLAUDE.md requires contributors to run npm run ui:openapi on any API/schema change, which regenerates apps/loopover-ui/public/openapi.json. Following the documented contribution steps therefore tripped a gate demanding Desktop/Tablet/Mobile × Dark before/after screenshots of a JSON spec file. With action: close and the gate being one-shot, those PRs were auto-closed with no recovery path.

Note src/settings/agent-actions.ts observes that screenshot_table is "our single top close reason all-time" — consistent with systemic over-firing.

Confirmed damage

Of the last 40 closed loopover PRs, 11 touched openapi.json with zero real visual changes; 5 were auto-closed by this gate: #9414, #9411, #9410, #9409, #9405. All five were reopened and re-gated after the fix.

Fix applied (ORB private config, jsonbored__loopover/.loopover.yml)

whenPaths narrowed to the actually-rendered UI:

whenPaths:
  - "apps/loopover-ui/src/components/**"
  - "apps/loopover-ui/src/routes/**"
  - "apps/loopover-ui/src/styles.css"

Dropped apps/loopover-ui/public/** and apps/loopover-ui/components.json (shadcn tooling config, not a rendered change).

Why the glob had to be narrowed rather than excluded

matchesAny (packages/loopover-engine/src/signals/change-guardrail.ts) is positive-only: no ! negation, and {a,b} braces are regex-escaped to literals. There is no way to express "public/** except openapi.json" in the current matcher.

Follow-up

  1. Check the sibling reposJSONbored/metagraphed and JSONbored/awesome-claude private configs may carry the same over-broad globs. Not yet verified.
  2. Consider whether matchesAny should support exclusion patterns, so a gate can say "this directory except these generated artifacts" without enumerating every visual extension.
  3. Consider whether a gate whose action: close is one-shot should require a positive visual signal (an image diff in the changed files) rather than a path prefix alone.

Metadata

Metadata

Assignees

Labels

gittensor:bugGittensor-scored bug fix — scores a 0.05x multiplier.maintainer-onlyOwner-only work — yields no Gittensor points.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions