Skip to content

feat(settings): per-repo override of the global agent-freeze kill-switch - #4375

Merged
JSONbored merged 2 commits into
mainfrom
claude/repo-scoped-agent-freeze-override
Jul 9, 2026
Merged

feat(settings): per-repo override of the global agent-freeze kill-switch#4375
JSONbored merged 2 commits into
mainfrom
claude/repo-scoped-agent-freeze-override

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Summary

  • global_agent_controls.frozen (the DB-backed operator kill-switch) has no per-repo scoping today — flipping it affects every repo at once. That caused a real multi-repo incident tonight: a global unfreeze meant for one repo let live merge/close actions fire against repos meant to stay paused.
  • Adds agentGlobalFreezeOverride (new RepositorySettings field + .gittensory.yml settings: block entry): a repo can opt in to bypass the DB-backed freeze while every other repo stays frozen — the same global-default + per-repo-override shape every other gate/settings field already uses.
  • AGENT_ACTIONS_PAUSED (the env-var hard stop) is never overridable by any per-repo setting. A repo's own agentPaused: true still always wins over its own override.
  • Threaded through every real enforcement path: AgentActionExecutionContext/IssueActionExecutionContext (the executor), the shared resolveRepoActionMode helper, and all direct resolveAgentActionMode call sites across processors.ts, agent-approval-queue.ts, contributor-issue-draft.ts, and the MCP automation-state tool.
  • New isDbFrozenForRepo(env, override) helper in db/repositories.ts centralizes the bypass logic.

Scope

  • Migration 0127_agent_global_freeze_override.sql
  • Drizzle schema, RepositorySettings type, OpenAPI schemas + routes
  • Engine package (packages/gittensory-engine) yml resolver + type mirror
  • .gittensory.yml.example + config/examples/gittensory.full.yml documentation (kept byte-synced)
  • Deliberately NOT exposed in the maintainer-facing dashboard UI (maintainer-settings.tsx) — this is an emergency operator-only lever set via the private per-repo .gittensory.yml, not something a repo maintainer should self-serve during an active incident freeze.

Validation

  • npx tsc --noEmit -p . — clean
  • npm run db:migrations:check / npm run db:schema-drift:check / npm run manifest:drift-check — clean
  • npm run ui:openapi (regenerated) / npm run ui:openapi:settings-parity — clean
  • npm run test:engine-parity / npm run test --workspace @jsonbored/gittensory-engine — all pass
  • npm run test:coverage (full unsharded) — 625 files / 12377 tests pass, 0 failed, exit 0, all thresholds (90% floor) exceeded
  • Targeted regression tests added: isDbFrozenForRepo both branches, the executor bypasses-freeze-but-not-env-var-or-own-pause matrix (4 new tests in agent-action-executor.test.ts), resolveRepoActionMode override matrix, DB round-trip (insert/update/default) in data-spine.test.ts, and the yml settings: parse + resolveEffectiveSettings override in focus-manifest.test.ts

Safety

  • No secrets/wallets/hotkeys/trust-scores/reward values touched
  • Env-var hard stop (AGENT_ACTIONS_PAUSED) verified non-overridable by a dedicated regression test
  • A repo's own agentPaused verified to still win over its own override (dedicated regression test)

global_agent_controls.frozen has no per-repo scoping today -- flipping it
affects every repo at once, which caused a real multi-repo incident where
live merge/close actions fired for repos meant to stay paused. Adds
agentGlobalFreezeOverride (RepositorySettings + .gittensory.yml settings:
block, global-default + per-repo-override like every other gate setting):
when a repo opts in, it bypasses the DB-backed freeze while every other
repo stays frozen. The AGENT_ACTIONS_PAUSED env var and a repo's own
agentPaused still always win over the override.

Threaded through every real enforcement path: the executor's
AgentActionExecutionContext/IssueActionExecutionContext, the shared
resolveRepoActionMode helper, and all direct resolveAgentActionMode call
sites in processors.ts, agent-approval-queue.ts, contributor-issue-draft.ts,
and the MCP automation-state tool.
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
gittensory-ui f49ea74 Commit Preview URL

Branch Preview URL
Jul 09 2026, 05:36 AM

Comment thread src/api/routes.ts Outdated
@superagent-security superagent-security Bot added the pr:flagged PR flagged for review by security analysis. label Jul 9, 2026
@codecov

codecov Bot commented Jul 9, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.95%. Comparing base (084cb38) to head (b324dad).
⚠️ Report is 1 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #4375   +/-   ##
=======================================
  Coverage   93.95%   93.95%           
=======================================
  Files         400      400           
  Lines       36820    36823    +3     
  Branches    13452    13454    +2     
=======================================
+ Hits        34595    34598    +3     
  Misses       1569     1569           
  Partials      656      656           
Files with missing lines Coverage Δ
packages/gittensory-engine/src/focus-manifest.ts 99.16% <100.00%> (ø)
src/db/repositories.ts 96.71% <100.00%> (+<0.01%) ⬆️
src/db/schema.ts 72.13% <ø> (ø)
src/github/client.ts 100.00% <100.00%> (ø)
src/mcp/server.ts 95.40% <100.00%> (ø)
src/openapi/schemas.ts 100.00% <ø> (ø)
src/queue/processors.ts 95.39% <100.00%> (ø)
src/services/agent-action-executor.ts 96.95% <100.00%> (ø)
src/services/agent-approval-queue.ts 99.17% <ø> (ø)
src/services/contributor-issue-draft.ts 97.48% <100.00%> (ø)
... and 1 more
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

…gs API

agentGlobalFreezeOverride is an operator-only emergency lever (set via
the private .gittensory.yml, never a repo maintainer) but had landed
in maintainerSettingsSchema, whose PUT /v1/repos/:owner/:repo/settings
endpoint only requires repo write access -- any maintainer could set
it directly, bypassing the operator-only restriction the field exists
for. Drop it from that schema; the yml-only config-as-code path is the
sole intended write mechanism.
@superagent-security

Copy link
Copy Markdown
Contributor

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

@superagent-security superagent-security Bot removed the pr:flagged PR flagged for review by security analysis. label Jul 9, 2026
@JSONbored JSONbored added the gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. label Jul 9, 2026
@JSONbored
JSONbored merged commit 1b6fa8c into main Jul 9, 2026
12 checks passed
@JSONbored
JSONbored deleted the claude/repo-scoped-agent-freeze-override branch July 9, 2026 06:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier.

Development

Successfully merging this pull request may close these issues.

1 participant