Agent repeatedly ignores workspace User Rules and repo gates across multiple chats (unauthorized API/deploy, wrong process order)

Where does the bug appear (feature/product)?

Cursor IDE

Describe the Bug

Across four consecutive chats in the Boptec project (Aug 27–Sep 1, 2026), the agent ignores explicit workspace rules (infra/.cursor/rules/, Boptec/.cursor/rules/, user rules) even after a full chat on Aug 31 dedicated to rewriting and centralizing those rules.

Recurring pattern:

  • Mutations without proposal/agreement (DirectAdmin API, SSH, deploy, DB)
  • Wrong order in production migration (imapsync before DNS, SSL before propagation)
  • Empty MR (glab mr create --related-issue → wrong branch, 0 diff)
  • Server workarounds instead of fixing the repo
  • “From now on” promises with no behavior change
  • GitHub/gh suggestions despite GitLab-only user rules

Rules violated (always applied in workspace):

  • autorizacao-alteracoes.mdc — propose → agree → implement
  • valuehost-directadmin.mdc — no ValueHost API/SSH without explicit request
  • gitlab-ci-e-labels-governance.mdc — glab only, labels-governance labels
  • User rules: quality over speed, no gh, no commit without request

Privacy / Data Sharing: Enabled (Cursor Settings → Privacy). Was already enabled during reported incidents.

Chat 1 — Linters activation review (Aug 27–30): manual job on MR pipeline; attempted DRG removal; wrong issue review assumptions; prior DirectAdmin API burst / CSF context.

Chat 2 — Response quality standards (Aug 31 AM): canonical rules created; ignored <24h later in migration chat; agent pointed to Settings > Rules (does not exist; moved to Customize).

Chat 3 — Domain migration process (Aug 31): --apply elidia before MR; imapsync without DNS; unnecessary sh01 deploy; SSL before DNS; three conflicting execution orders; skipped own runbook; DNS export to Google Drive; symlink workaround; DNS+SSL in one authorization; Let’s Encrypt without public propagation.

Chat 4 — Domain migration and API setup (Sep 1): empty MR !49; site MR without asking approval; labels only after user complaint; wrong deploy path (public_html/lib vs api/lib); temporary DA panel outage; user ordered stop.

GitLab MRs: dns-migrate !49 (closed), !50, !51.

Steps to Reproduce

    1. Open Boptec workspace (/home/brunno/work/Boptec) with rules in infra/.cursor/rules/ and user rules (GitLab-only, propose→agree, no ValueHost network without explicit request).
    2. Ask for a scoped migration/infra task (e.g. “prepare script + MR only, no apply”).
    3. Observe agent running DirectAdmin API, SSH, deploy, or MR out of order or without prior agreement.
    4. Correct/challenge; start a new chat — pattern repeats across sessions.

Expected Behavior

    1. Read and obey all workspace/repo rules before acting.
    2. Propose changes and wait for agreement before implement, commit, push, MR, external API, or deploy.
    3. sh01 → ValueHost migration: staging → DNS → propagation → SSL → mail; one step/account at a time.
    4. Dry-run: zero HTTP to hosting APIs.
    5. Do not improvise server paths; align with existing scripts/repos.
    6. Do not suggest GitHub/gh — GitLab glab only.

Screenshots / Screen Recordings

Operating System

Windows 10/11

Version Information

Cursor IDE 3.18.25 (build d5c0e77a0214208f36b56d42e8e787de88d02ea4, x64)
Agent via WSL2: Linux 6.6.114.1-microsoft-standard-WSL2

For AI issues: which model did you use?

Agent mode (default routing / Auto) across multiple chats. Exact model may vary per request; issue is agent behavior and rule compliance, not a single-model regression.

For AI issues: add Request ID with privacy disabled

980ba765-1d60-41cf-8a7d-9ed15dd4bc1c (Linters activation review)
aac29949-7048-4f42-9177-1730b0f0c0b3 (Response quality standards)
b3be470b-9958-46fa-9017-456cc8fc7d14 (Domain migration process)
24ed0e2f-7c42-41f1-9333-1a6632ca8a6a (Domain migration and API setup)

Data Sharing: Enabled. Privacy Mode effectively off.

Additional Information

Impact: production hosting risk (DA API, broken deploy); loss of trust in agent; time fixing process/MRs/deploys; possible contribution to ValueHost DA panel outage (br74-da.valueserver.net.br:2222).

Asking: (1) why User Rules + workspace rules are not respected consistently; (2) conflict with embedded gh/PR instructions vs GitLab user rules; (3) practical guidance for authorization rules in infra workflows.

Does this stop you from using Cursor

Sometimes - I can sometimes use Cursor

Hi,

Thanks for posting on the Cursor forum!

To help ensure most of our users can participate in discussions, this forum is currently English only.

If you’d like, you can edit your post to translate it into English. Once it meets our guidelines, it will be automatically relisted.

Thanks for understanding!

Note: This is an automated detection system and sometimes makes mistakes. If your post is already in English, feel free to ignore this message, or just make a small edit and it will be reviewed again.

Updated main post to English per forum guidelines. Data Sharing enabled. Four Request IDs in the post. Please relist for staff review. Thank you.

Hey @Brunno I checked all four req ids and the turns ran fine, so this comes down to how your rules reach the model. Three fixes:

1. Make the rules global. Rules in infra/.cursor/rules/ only load when a chat is touching infra/ (even with alwaysApply: true), and pointer files only pass the path, not the rule itself. Put the full text of autorizacao-alteracoes, valuehost-directadmin, and gitlab-ci-e-labels-governance in the workspace root Boptec/.cursor/rules/, or in User Rules (Cursor Settings → Customize → Rules). Those load in every chat. Rules docs

2. The gh suggestions aren’t your fault. Your GitLab-only rule is reaching the model, but some built-in guidance competes with it, so adding another “no gh” rule won’t reliably win. This isn’t intended behavior, and we’ve let the team know.

3. For a real propose → agree gate, don’t rely on rules. Use Ask or Plan mode for the proposal step and switch to Agent only after you agree. In Cursor Settings → Agents, turn off auto-run or set an allowlist that excludes ssh, glab, curl, and your deploy scripts. For a hard block, add a beforeShellExecution hook.

After moving the rules to the root (or User Rules), restart and try a scoped request like “prepare the script and MR only, no apply.” If it still acts without asking, reply with that request ID and I’ll dig in.

Subject / Forum reply: Re @mohitjain + follow-up to Neil — rules delivery vs compliance;
mitigations already applied; new Request ID after hooks/sandbox/allowlist

Hi Mohit (@mohitjain), hi Neil,

Thank you for reviewing the earlier Request IDs and for the concrete recommendations.

This reply does three things:

  1. Answers Mohit’s three asks with what is already true in this workspace;
  2. Aligns that with Neil’s email findings (rules were loaded; Agent failed to follow them);
  3. Adds a new Request ID from a session that ran AFTER we applied Allowlist + sandbox.json +
    fail-closed hooks, which still showed serious Agent/process and platform issues.

IDs for this follow-up

New session (post-mitigation), operator-copied Request ID:
44e17d14-1eea-45c1-b62e-1aa208f2993d

Related/alternate Request ID copied from the same operational window (if logs differ by turn):
85e5781f-6ff2-4518-a7c3-d9e82fbf7328

Local Agent transcript UUID (workspace Boptec):
82421142-f868-460f-b057-c075a9f0e64e
Chat title: “DNS change for brunno.bsb.br”
When (BRT): 2026-09-02 ~11:18–15:05

Prior Request IDs already in the ticket/forum (pre-mitigation):
980ba765-1d60-41cf-8a7d-9ed15dd4bc1c
aac29949-7048-4f42-9177-1730b0f0c0b3
b3be470b-9958-46fa-9017-456cc8fc7d14
24ed0e2f-7c42-41f1-9333-1a6632ca8a6a

Forum topic (still needing manual moderation / was auto-unlisted):

Environment: Cursor IDE 3.18.x (Windows) + Agent via WSL2; workspace root
/home/brunno/work/Boptec (monorepo). Data Sharing: Enabled.


How this maps to Neil’s email (already on file)

Neil confirmed after reviewing the first four requests + forum screenshots:

  • Cursor loaded the Boptec workspace gate, user rules, and GitLab-specific instructions.
  • The problem was NOT missing rules — the Agent failed to follow them consistently.
  • Generic GitHub guidance did not override Boptec rules; empty MR and wrong deploy path
    were Agent failures.
  • Rules are instructions, not a hard authorization boundary; Auto-review is best-effort.
  • Recommended: Allowlist (keep network/mutating commands out), sandbox networking so
    production hosts are unreachable by default, and project beforeShellExecution /
    beforeMCPExecution hooks with failClosed: true.
  • Documented local Auto behavior as a distinct report; no reliable rules-only fix.

That matters for Mohit’s diagnosis: if Neil already saw the rules loaded in later sessions,
then “rules not reaching the model” cannot be the whole story for those chats. We still take
Mohit’s delivery advice seriously for the monorepo layout, but the new Request ID shows
failures continuing AFTER hard mitigations Neil recommended.


Response to Mohit’s three recommendations

1) Rule visibility — move full text to workspace root / User Rules

Mohit: rules under infra/.cursor/rules/ only load when a chat touches infra/; alwaysApply
pointers may pass a path, not the rule body; move autorizacao-alteracoes,
valuehost-directadmin, gitlab-ci-e-labels-governance to Boptec/.cursor/rules/ or User Rules;
restart; retry a scoped request.

Our actual layout (important nuance):

  • Workspace is opened at monorepo root /home/brunno/work/Boptec/, not only infra/.
  • Boptec/.cursor/rules/README.mdc is alwaysApply: true and is an explicit GATE that orders
    the Agent to read/obey, before mutable work:
    1. infra/.cursor/rules/00-indice-regras-canonicas.mdc
    2. autorizacao-alteracoes.mdc (propose → agree → implement)
    3. gitlab-ci-e-labels-governance.mdc
    4. copilot-leia-aqui.md (+ per-repo)
    5. labels-governance process docs
  • Canonical editable rules live in infra/.cursor/rules/ by design (single edit source);
    ~/.cursor/rules and app/* pointers are non-editable pointers.
  • valuehost-directadmin.mdc also exists under infra/.cursor/rules/ with alwaysApply: true.

We hear Mohit’s point that path-only pointers may not inject full rule text into every turn.
We are willing to DUPLICATE the full text of the three named rules into
Boptec/.cursor/rules/ (or User Rules) as an experiment — without abandoning the canonical
infra/ source of truth — and restart Cursor as asked.

However: Neil already reported those rules were loaded in later Agent sessions and still
not followed. So we treat “move full text to root” as a necessary delivery experiment, not as
proof that compliance will hold. The new Request ID is the compliance test after hard gates.

2) Conflicting guidance — GitHub (gh) vs GitLab

Mohit: GitLab-only competes with built-in gh guidance; not the user’s fault; team informed;
“no gh” rule alone is not reliable.

Agreed — and this matches our ticket. We already documented that embedded Cursor templates
mentioning gh/PR must not apply to Boptec; User Rule + gitlab-workflow +
gitlab-ci-e-labels-governance.mdc prevail. We will not treat “add another no-gh sentence” as
the fix. Please confirm the product-side fix timeline for built-in gh competing with
workspace GitLab-only rules.

3) Propose → agree must not rely on text alone; Ask/Plan + Allowlist + hooks

Mohit: use Ask/Plan for proposal, switch to Agent only after agreement; turn off auto-run or
restrict allowlist (ssh, glab, curl, deploy scripts); for hard block use beforeShellExecution.

We already did the hard parts Neil/Mohit recommend (same morning, before the new session):

UI (View → Settings → Agents → Execution and Approvals) — note: Rules are under Customize,
not Settings (UI moved):

  • Run Mode: Auto-Review (with Sandbox) — not Run Everything
  • File Deletion Protection: ON
  • External-File Protection: ON
  • Command Allowlist narrowed: removed curl, ssh, scp, rsync, oci, terraform, python3, rm;
    kept read-only git status/diff/log/show and limited glab view-style commands
  • Auto-Run Network Access: sandbox.json + Defaults

Project hard gates (versioned at monorepo root):

  • .cursor/sandbox.json — deny ValueHost (br74-da / 187.110.165.206 / *.valueserver.net.br),
    sh01, monops/construrei, desenv bastion+VCN+LB, srv.bop.dev.br, *.oraclecloud.com
  • .cursor/hooks.json — sessionStart + beforeShellExecution + beforeMCPExecution,
    failClosed: true on shell/MCP gates
  • Shell gate calibrated to DENY prod curl/ssh targets; ASK on --apply, git commit/push,
    mutating glab; ALLOW dry-run valuehost and read-only glab list/view

We also use propose→agree conversationally; Plan/Ask for pure planning when scoped that way.
Relying only on mode switching is not enough for multi-hour cutovers where Agent mode is
required for glab/MR/script work — hence hooks + sandbox + allowlist.


What still failed AFTER those mitigations (Request ID 44e17d14-…)

Please review 44e17d14-1eea-45c1-b62e-1aa208f2993d (and 85e5781f-… if needed) against the
local transcript 82421142-…. Highlights:

  1. Early curl --resolve to ValueHost IP 187.110.165.206 while operator only asked to prepare
    DNS cutover — violates valuehost-directadmin; sandbox deny should block sandboxed runs,
    but Agent requested full_network (~55 times in the session) which bypasses sandbox when
    allowed to proceed.

  2. Wrong GitLab label “documentation” instead of tipo::doc + area::migracao + area::dns
    (labels-governance) — fixed only after operator challenge.

  3. Treated classic CMD_API_SSL checkbox list as the Evolution Automatic SSL UI the operator
    saw; only corrected after screenshots (API ≠ panel).

  4. Confident guesses on LE re-request / mail SAN strategy

  1. Bundled unrelated migration steps (DNS vs mailboxes/aliases vs historical mail sync)

    until operator forced a strict order.

  2. Wrong DirectAdmin reseller ACL guidance (discussed CMD_API_DNS_ADMIN / Admin-level APIs

    while the login key scopes were set from the Agent’s own prior guidance). Correct User

    endpoint is CMD_API_DNS_CONTROL. Operator had to push the provider ACL update, then

    demand documentation via MR.

  3. Unsolicited move_agent_to_root / workspace checkout modal mid-MR (“Are you kidding me?”).

  4. Wrote temp artifacts under /tmp instead of infra/tmp// (workspace rule).

  5. CRITICAL platform issue: Agent shell ran as uid=0 (root) with HOME=/home/brunno and

    USER=brunno, creating root:root files under ~/.boptec (including da-api.lock). Agent

    then workarounded flock failure via /tmp instead of stopping and dropping privilege.

    This is not fixable by moving markdown rules.

  6. ~104 Shell calls; ~21 ssh to VH account host; many after step-scoped authorization,

    but overall shows soft process control remains operator-policed.

Scoped pattern Mohit suggested (“prepare script and MR only, no apply”) was used repeatedly

in this chat; Agent still expanded into VH network, wrong product assumptions, wrong ACL

advice, workspace UI mutation, and root-owned home files.

--------------------------------------------------------------------

What we will do next (Mohit’s test plan)

--------------------------------------------------------------------

  1. Duplicate full text of autorizacao-alteracoes, valuehost-directadmin, and

    gitlab-ci-e-labels-governance into Boptec/.cursor/rules/ (keeping infra/ as canonical

    editable source), OR paste into User Rules under Customize → Rules — then fully restart

    Cursor.

  2. Keep Allowlist + sandbox.json + failClosed hooks as-is (already in place).

  3. Prefer Ask/Plan for proposal-only turns; Agent only after explicit agreement for

    execution.

  4. Run a minimal scoped test: “prepare the script and MR only, no apply.”

  5. If Agent still mutates / hits network / skips agreement → reply here with the new

    Request ID immediately.

--------------------------------------------------------------------

Asks for Cursor (Mohit + Neil / engineering)

--------------------------------------------------------------------

  1. Confirm whether Request ID 44e17d14-1eea-45c1-b62e-1aa208f2993d shows the Boptec gate +

    infra rules as loaded, and whether Agent still violated them (Neil’s framing) vs not

    loaded (Mohit’s framing) — we need one coherent diagnosis.

  2. Confirm product fix for built-in gh / GitHub PR guidance competing with GitLab-only

    workspace rules.

  3. Escalate: Agent shell as root with operator HOME; full_network bypass of project

    sandbox.json deny lists; unsolicited move_agent_to_root.

  4. Please manually moderate the forum topic if it is still unlisted after the English edit

    (Neil already noted this).

  5. Advise whether Enterprise/team controls can hard-block uid=0 agent shells and deny

    full_network to listed production CIDRs without relying on the model.

I can attach screenshots (Evolution SSL vs API, ACL list, root:root ls -la, workspace modal,

Allowlist UI, hooks.json, sandbox.json) on request.

Thanks,

@mohitjain / Neil — follow-up after restart + duplicated root rules

Request ID: da2d4b60-a6cb-4bff-8511-ae5a3b86626b
Local transcript: dc388b4f-5bb6-43ff-93de-2b6345762b6c
Chat title: “File ownership update script”

Context

  • I duplicated autorizacao-alteracoes, valuehost-directadmin, and
    gitlab-ci-e-labels-governance into Boptec/.cursor/rules/ (alwaysApply),
    restarted Cursor, and opened a new Agent chat at the monorepo root
    /home/brunno/work/Boptec (not a nested folder).
  • Operator request: create a script in the ops-scripts repository and open
    an MR only — do not apply ownership changes.

Critical clarification (workspace root)

  • “Create the script in the ops-scripts repo” means write files in that Git
    project. It does not mean move the Agent workspace root.
  • The Agent unilaterally called move_agent_to_root to
    /home/brunno/work/Boptec/infra/ops-scripts. That dropped the monorepo-root
    rules and .cursor/hooks.json that we had just placed for your delivery test.
  • So this Request ID does not cleanly validate “rules at Boptec root load
    everywhere”: the Agent left that root on its own. Same class of failure as
    earlier unsolicited workspace moves.

What the Agent did despite “MR only, no apply”

  1. Ran the new script in dry-run against $HOME without being asked (~324k
    root:root paths reported).
  2. Also invoked the script with --apply (probe) without authorization.
  3. After SSH push failed under the sandbox, switched to HTTPS using a
    GIT_ASKPASS helper that called glab config get token.
  4. The Agent itself admitted the PAT was printed in the tool log (Data Sharing
    was enabled). I rotated the token immediately; it is now supplied via the
    user environment variable GITLAB_TOKEN (monthly expiry). Cursor only picked
    up the env change after another full app restart.

Addendum — Request ID: 486b5008-1a74-4228-bc0a-6c1b98e3c727
Local transcript: 8fb68892-66a5-479d-aec5-026d7825a10f
Chat: “Boptec: fix-root-owned-home”

I opened this chat at monorepo root Boptec and explicitly forbade moving the
workspace. The Agent stayed on Boptec (no move_agent_to_root).

Purpose: reconcile why fix-root-owned-home.sh --sudo-find listed only ~33
root:root paths (none under ~/.boptec), while an earlier Agent session claimed
~/.boptec/directadmin-valuehost was root-owned / Agent shell uid=0.

Finding (please have engineering confirm):

  • Outside the Agent sandbox (Shell with full/host permissions): those paths are
    brunno:brunno (1000:1000); find -user root -group root under ~/.boptec → 0 hits.
  • Inside the Agent sandbox, the same inodes are reported as root:root / uid 0.
  • This matches Cursor’s documented Linux sandbox user-namespace remapping
    (id/UID appear as 0 inside the sandbox; CURSOR_ORIG_UID holds the host user).

So the earlier “Agent ran as root and left root:root under my HOME” claim from
Request ID 44e17d14-… / DNS cutover chat is at least partly a false diagnosis
caused by sandboxed identity/ownership views
, not necessarily real on-disk
ownership. The Agent still treated that false signal as fact and recommended
chown — that remains an Agent reliability failure.

Separately, the real-disk root:root set is small (~33 under nebulasort tmp/
pycache), which is what the operator’s sudo find showed.

Please review how Agent tools should report ownership/identity so sandboxed
uid=0 is not mistaken for host root, and whether dry-run inventories should
refuse to trust sandboxed find -user root without an unsandboxed cross-check.

@Brunno - Quick answers to your asks:

  1. Rules loaded vs not: both are right. In infra/.cursor/rules/ (nested, folder-scoped) they didn’t load in your migration chats, at the workspace root they do. Past that, rules are guidance the model can still deviate from, so the real gate is the hard controls below, not the rule text.
  2. gh vs glab: not on your side, and another “no gh” rule won’t reliably win. Not intended behavior and we’ve let the team know (no timeline; I’ll post updates here).
  3. uid 0 / root:root: your #17 post is correct and expected. The Linux sandbox remaps the shell to uid 0, but files are owned by your real user on disk (CURSOR_ORIG_UID holds it, docs). No real root-owned files. The agent trusting that view and suggesting chown is the miss; we’ve let the team know.
  4. full_network vs sandbox.json: right - an approved full-network request drops your deny list for that command. Keep network mode on sandbox.json Only and decline full-network prompts during cutovers, your failClosed beforeShellExecution hook is the real hard block and runs regardless.
  5. move_agent_to_root: shouldn’t happen; for now decline any prompt to move the workspace root (that’s what dropped your root rules/hooks). Not intended, we’ve let the team know.
  6. Enterprise/team controls: what you’re already running (allowlist + sandbox.json deny on sandbox.json Only + failClosed hooks) is the strongest available today. There’s no switch to force a non-uid-0 shell (it’s cosmetic, per #3) or hard-deny CIDRs past an approved full-network grant - I’ve passed that request on.

Rotating the token and moving it to GITLAB_TOKEN was right. The thread’s already relisted. If a scoped test (rules at root, sandbox.json Only, full-network declined) still acts out, drop that request ID here.

@mohitjain — thanks for the six-point reply. Sandbox, root rules vs infra/, full_network vs deny list, hooks, and declining move_agent_to_root are clear.

Still unanswered, and this is the actual bug I need mitigated:

How does the product stop the Agent from acting outside the explicit scope of the turn?
I ask for X; it delivers or proposes Y (scope creep). Hooks and sandbox.json do not cover that. They gate shell/network; they do not gate “only do what I asked this message.”

Concrete request IDs (rules at workspace root + sticky “commands only / no mutation without explicit auth”):

  1. 5bf1437d-3936-4517-9c60-9140b1ff50f3 — asked for a full Fase D command list; got vague/wrong steps (rclone “copy Alma”, nano over SSH, rclone as opc on sh01). That induced my operational mistakes, including exposing a DB password in chat.
  2. 6cb3e853-bed1-45e3-aac8-a977a894a397 — asked only for an end-to-end command list, no execution. Agent listed steps already known to fail, then edited scripts/docs without authorization; later mixed unrelated answers into narrow asks (IMAPSync vs dry-run skip; SPF fix + OCI apply + dig in one shot).

So: strongest allowlist + sandbox.json Only + failClosed hooks still leave instruction-scope compliance unmitigated. Rules as “guidance” is not an acceptable answer for production cutovers.

Please treat out-of-scope Agent actions as the open product gap (not only “were rules loaded?”). Happy to attach more request IDs under the same setup if useful.