Skip to content

fix(review): fail auto-maintain guardrail safe on unknown changed paths - #1062

Merged
3 commits merged into
JSONbored:mainfrom
galuis116:fix/auto-maintain-guardrail-failsafe
Jun 23, 2026
Merged

fix(review): fail auto-maintain guardrail safe on unknown changed paths#1062
3 commits merged into
JSONbored:mainfrom
galuis116:fix/auto-maintain-guardrail-failsafe

Conversation

@galuis116

Copy link
Copy Markdown
Contributor

Summary

The autonomous auto-maintain planner (#1050, the "rollout-blocker for autonomy" guardrail) suppresses the irreversible dispositions (auto-merge / auto-close / auto-approve) only when a PR's changed path hits a hard-guardrail glob (.github/workflows/**, scripts/**, scoring/auth). But the changed paths are read from the pull_request_files DB cache with no freshness guarantee, and maybeRunAgentMaintenance never refreshes them:

// src/queue/processors.ts:488 — reads the cache, never refreshes
const [changedFiles] = await Promise.all([listPullRequestFiles(env, repoFullName, pr.number), ...]);
const changedPaths = changedFiles.map((f) => f.path).filter((p) => p.length > 0); // can be []

The file refresh runs only under the slop/manifest gate condition (processors.ts:1010), which is off by default and independent of auto-maintain. So when the cache is empty (a fresh PR processed before the async backfill) or stale (a synchronize added a guarded file after the cache was populated), changedPaths = []changedPathsHittingGuardrail([], globs) returns []guardrailHit = false → the automation may auto-merge or auto-close a PR that actually touches a guarded path. The guardrail fails open — exactly the irreversible mis-action on a CI/policy/auth PR that #1050 exists to block.

Fix

The guardrail's real contract is "never auto-merge/close a PR that touches a guarded path." If the changed paths are unknown (empty) while guardrails are configured, the automation cannot prove the PR is safe, so it must fall through to a human. Make the planner fail SAFE:

// src/settings/agent-actions.ts
const guardrailHit =
  input.hardGuardrailGlobs.length > 0 &&
  (input.changedPaths.length === 0 || changedPathsHittingGuardrail(input.changedPaths, input.hardGuardrailGlobs).length > 0);

Repos with no guardrails configured stay permissive (unchanged); an empty-diff PR is not a real merge/close target, so suppressing it is harmless. (A complementary refresh-before-read in maybeRunAgentMaintenance would avoid merely delaying a legitimate auto-merge on the fresh-PR race; the planner fail-safe alone closes the hole.)

Tests

There was no test exercising the empty-paths guardrail case (the existing planner tests pass changedPaths explicitly and default it to [], which silently blessed the fail-open). Added regression tests: with guardrails configured and changedPaths: [], the planner emits no merge/close/approve (label still runs); and with no guardrails configured, empty paths stay permissive. Planner suite 27/27; broader unit suite green (3363 passed); tsc clean.

Closes #1061

The auto-maintain planner (JSONbored#1050) suppressed auto-merge/close/approve only when a
changed path hit a hard-guardrail glob. But maybeRunAgentMaintenance reads the
changed paths from the pull_request_files cache without refreshing, so an empty
(fresh PR pre-backfill) or stale (post-synchronize) cache yields changedPaths=[],
making guardrailHit=false — letting the automation auto-merge/close a PR that
actually touches a guarded path (.github/workflows, scripts, scoring/auth).

When guardrails are configured but the changed-file set is unknown (empty), treat
it as a hit: we cannot prove the PR is safe, so it must fall through to a human.
Repos with no guardrails configured stay permissive.

Closes JSONbored#1061
@galuis116
galuis116 requested a review from JSONbored as a code owner June 22, 2026 19:56
@dosubot dosubot Bot added the size:XS label Jun 22, 2026
@ghost

ghost commented Jun 22, 2026

Copy link
Copy Markdown

Note

🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦🟦

💡 Gittensory review — advisory only

0 files · no blockers · readiness 0/100

💡 Advisory only — PR closed before full evaluation. No late first comment was created.

Signal Result Evidence
Code review ✅ No blockers synthesized
Gate result ⚠️ Skipped #1062 is no longer open.

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed


💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.

@ghost ghost left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gittensory approves — the gate is satisfied.

@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@codecov

codecov Bot commented Jun 22, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.89%. Comparing base (1cc690f) to head (914c5e5).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1062   +/-   ##
=======================================
  Coverage   94.89%   94.89%           
=======================================
  Files         151      151           
  Lines       18249    18249           
  Branches     6610     6611    +1     
=======================================
  Hits        17317    17317           
  Misses        419      419           
  Partials      513      513           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@JSONbored JSONbored assigned JSONbored and galuis116 and unassigned JSONbored Jun 22, 2026

@ghost ghost left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gittensory approves — the gate is satisfied.

@ghost ghost left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gittensory approves — the gate is satisfied and CI is green.

@ghost ghost left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gittensory approves — the gate is satisfied and CI is green.

@ghost ghost left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gittensory approves — the gate is satisfied and CI is green.

@ghost ghost left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gittensory approves — the gate is satisfied and CI is green.

@ghost ghost left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gittensory approves — the gate is satisfied and CI is green.

@ghost ghost left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gittensory approves — the gate is satisfied and CI is green.

@ghost ghost left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gittensory approves — the gate is satisfied and CI is green.

@ghost ghost left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gittensory approves — the gate is satisfied and CI is green.

@ghost ghost left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gittensory approves — the gate is satisfied and CI is green.

@ghost ghost left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gittensory approves — the gate is satisfied and CI is green.

@ghost ghost left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gittensory approves — the gate is satisfied and CI is green.

@ghost ghost left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gittensory approves — the gate is satisfied and CI is green.

@ghost ghost left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gittensory approves — the gate is satisfied and CI is green.

@ghost ghost left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gittensory approves — the gate is satisfied and CI is green.

@ghost ghost left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gittensory approves — the gate is satisfied and CI is green.

@ghost ghost left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gittensory approves — the gate is satisfied and CI is green.

@ghost ghost added the gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. label Jun 23, 2026
ghost
ghost previously approved these changes Jun 23, 2026

@ghost ghost left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gittensory approves — the gate is satisfied and CI is green.

…uardrail-failsafe

# Conflicts:
#	src/settings/agent-actions.ts

@ghost ghost left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gittensory approves — the gate is satisfied and CI is green.

@ghost
ghost merged commit 72387df into JSONbored:main Jun 23, 2026
16 checks passed
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: auto-maintain guardrail fails open on empty/stale changed-files cache

2 participants